. */ declare(strict_types=1); namespace FireflyIII\Api\V1\Controllers\Insight\Expense; use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Requests\Insight\GenericRequest; use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Support\Facades\Amount; use Illuminate\Http\JsonResponse; use Illuminate\Support\Facades\Log; /** * Class BillController */ class BillController extends Controller { private BillRepositoryInterface $repository; /** * BillController constructor. */ public function __construct() { parent::__construct(); $this->middleware( function ($request, $next) { $user = auth()->user(); $this->repository = app(BillRepositoryInterface::class); $this->repository->setUser($user); return $next($request); } ); } /** * This endpoint is documented at: * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightExpenseBill * * Expenses per bill, possibly filtered by bill and account. */ public function bill(GenericRequest $request): JsonResponse { $accounts = $request->getAssetAccounts(); $bills = $request->getBills(); $start = $request->getStart(); $end = $request->getEnd(); $convertToPrimary = Amount::convertToPrimary(); $primary = Amount::getPrimaryCurrency(); $response = []; // get all bills: if (0 === $bills->count()) { $bills = $this->repository->getBills(); } // collect all expenses in this period (regardless of type) by the given bills and accounts. $collector = app(GroupCollectorInterface::class); $collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setRange($start, $end)->setSourceAccounts($accounts); $collector->setBills($bills); $genericSet = $collector->getExtractedJournals(); foreach ($genericSet as $journal) { $billId = (int) $journal['bill_id']; $currencyId = (int) $journal['currency_id']; $currencyCode = $journal['currency_code']; $field = 'amount'; // use the primary amount if the user wants to convert to primary currency if ($convertToPrimary && $currencyId !== $primary->id) { $currencyId = $primary->id; $currencyCode = $primary->code; $field = 'pc_amount'; } // use foreign amount when the foreign currency IS the default currency. if ($convertToPrimary && $journal['currency_id'] !== $primary->id && $primary->id === $journal['foreign_currency_id']) { $field = 'foreign_amount'; } Log::debug(sprintf('Journal #%d in bill #%d will use %s (%s %s)', $journal['transaction_group_id'], $billId, $field, $currencyCode, $journal[$field] ?? '0')); $key = sprintf('%d-%d', $billId, $currencyId); if (0 !== $currencyId) { $response[$key] ??= [ 'id' => (string) $billId, 'name' => $journal['bill_name'], 'difference' => '0', 'difference_float' => 0, 'currency_id' => (string) $currencyId, 'currency_code' => $currencyCode, ]; $response[$key]['difference'] = bcadd($response[$key]['difference'], (string) ($journal[$field] ?? '0')); $response[$key]['difference_float'] = (float) $response[$key]['difference']; // intentional float } } return response()->json(array_values($response)); } /** * This endpoint is documented at: * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightExpenseNoBill * * Expenses for no bill filtered by account. */ public function noBill(GenericRequest $request): JsonResponse { $accounts = $request->getAssetAccounts(); $start = $request->getStart(); $end = $request->getEnd(); $convertToPrimary = Amount::convertToPrimary(); $primary = Amount::getPrimaryCurrency(); $response = []; // collect all expenses in this period (regardless of type) by the given bills and accounts. $collector = app(GroupCollectorInterface::class); $collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setRange($start, $end)->setSourceAccounts($accounts); $collector->withoutBill(); $genericSet = $collector->getExtractedJournals(); foreach ($genericSet as $journal) { $currencyId = (int) $journal['currency_id']; $currencyCode = $journal['currency_code']; $field = 'amount'; // use the primary amount if the user wants to convert to primary currency if ($convertToPrimary && $currencyId !== $primary->id) { $currencyId = $primary->id; $currencyCode = $primary->code; $field = 'pc_amount'; } // use foreign amount when the foreign currency IS the default currency. if ($convertToPrimary && $journal['currency_id'] !== $primary->id && $primary->id === $journal['foreign_currency_id']) { $field = 'foreign_amount'; } Log::debug(sprintf('Journal #%d will use %s (%s %s)', $journal['transaction_group_id'], $field, $currencyCode, $journal[$field] ?? '0')); if (0 !== $currencyId) { $response[$currencyId] ??= [ 'difference' => '0', 'difference_float' => 0, 'currency_id' => (string) $currencyId, 'currency_code' => $currencyCode, ]; $response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], (string) ($journal[$field] ?? '0')); $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // intentional float } } return response()->json(array_values($response)); } }