<?php namespace App\Services\CashFlow; use App\Domain\Article\Enums\ArticleTypeEnum; use App\Domain\Payment\Enums\PaymentStatusEnum; use App\Domain\Payment\Enums\PaymentTypeEnum; use App\Http\Resources\CashFlowCreditResource; use App\Http\Resources\CashFlowCreditToMonthResource; use App\Http\Resources\CashFlowDebitResource; use App\Http\Resources\CashFlowDebitToMonthResource; use App\Http\Resources\NotDistributedPaymentResource; use App\Models\Article; use App\Models\ArticleGroup; use App\Models\Counterparty; use App\Models\PaymentDistribution; use App\Repositories\CashFlowIndex\Interfaces\PaymentDistributionsRepositoryInterface; use App\Repositories\CashFlowIndex\Interfaces\TotalAmountRepositoryInterface; use App\Responses\ResponseDto; use App\Services\CashFlowService; use Carbon\Carbon; use Illuminate\Support\Facades\DB; class ActiveTabQuarterService { private $distributionsRepository; private $paymentRepository; public function __construct(PaymentDistributionsRepositoryInterface $paymentDistributionsRepository, TotalAmountRepositoryInterface $paymentRepository, protected CashFlowService $cashFlowService) { $this->distributionsRepository = $paymentDistributionsRepository; $this->paymentRepository = $paymentRepository; } public function getIndex(int $modelID, $filters) { $paymentDistributionsCredit = $this->distributionsRepository->getPaymentDistributions($modelID, $filters, ArticleTypeEnum::ARTICLE_TYPE_CREDIT->value); $paymentDistributionsDebit = $this->distributionsRepository->getPaymentDistributions($modelID, $filters, ArticleTypeEnum::ARTICLE_TYPE_DEBIT->value); $totalAmountCreditPayment = $this->paymentRepository->getTotalAmountPayment($modelID, $filters, $credit = true); $totalAmountDebitPayment = $this->paymentRepository->getTotalAmountPayment($modelID, $filters, $credit = false); $totalAmountCashCreditPayment = $this->paymentRepository->getTotalAmountCashPayment($modelID, $filters, $credit = true, $debitType = null); $totalAmountCashDebitMovingPayment = $this->paymentRepository->getTotalAmountCashPayment($modelID, $filters, $credit = false, $debitType = 'cash'); $totalAmountCashDebitCommissionPayment = $this->paymentRepository->getTotalCommissionPaymentDistribution($modelID, $filters, $debitType); $totalMoving = $this->paymentRepository->getTotalAmountCashPayment($modelID, $filters, $credit = false, $debitType = 'moving'); $groupsWithoutArticlesCredit = ArticleGroup::where(['article_type' => 'credit', 'model_id' => $modelID])->doesntHave('articles')->get(); $groupsWithoutArticlesDebit = ArticleGroup::where(['article_type' => 'debit', 'model_id' => $modelID])->doesntHave('articles')->get(); $paymentNotDistributionCredit = $this->distributionsRepository->getNotDistributionsPayment($modelID, $filters, $credit = true); $paymentNotDistributionDebit = $this->distributionsRepository->getNotDistributionsPayment($modelID, $filters, $credit = false); $totalCash = $this->cashFlowService->getTotalCash($filters, $modelID); $check = array_filter($filters, function ($value) { return $value !== null; }); if ($check) { $formattedDataCredit = $this->sortToQuarter($paymentDistributionsCredit, true, $check); $formattedDataDebit = $this->sortToQuarter($paymentDistributionsDebit, false, $check); $formattedCommission = $this->sortToQuarterOtherDataDebit($filters, $check, $modelID); $formattedTotalCash = $this->sortToQuarterTotalCash($filters, $check, $modelID); $formattedNotDistributionCredit = $this->sortNotDistributedPaymentsToQuarter($paymentNotDistributionCredit, true, $check); $formattedNotDistributionDebit = $this->sortNotDistributedPaymentsToQuarter($paymentNotDistributionDebit, false, $check); } else { $formattedDataCredit = $this->sortToQuarter($paymentDistributionsCredit, true, $check); $formattedDataDebit = $this->sortToQuarter($paymentDistributionsDebit, false, $check); $formattedCommission = $this->sortToQuarterOtherDataDebit($filters, $check, $modelID); $formattedTotalCash = $this->sortToQuarterTotalCash($filters, $check, $modelID); $formattedNotDistributionCredit = $this->sortNotDistributedPaymentsToQuarter($paymentNotDistributionCredit, true, $check); $formattedNotDistributionDebit = $this->sortNotDistributedPaymentsToQuarter($paymentNotDistributionDebit, false, $check); } $totalAmountToQuarter = $this->totalAmountToQuarter($formattedDataCredit, $formattedTotalCash, 'credit'); $totalAmountToQuarter = $this->mergeDistributedAndNotDistributedByQuarter($totalAmountToQuarter, $formattedNotDistributionCredit); $totalAmountToQuarterDebit = $this->totalAmountToQuarter($formattedDataDebit, $formattedCommission, 'debit'); $totalAmountToQuarterDebit = $this->mergeDistributedAndNotDistributedByQuarter($totalAmountToQuarterDebit, $formattedNotDistributionDebit); $totalCredit = $this->sumTotalAmount($paymentDistributionsCredit); $totalDebit = $this->sumTotalAmount($paymentDistributionsDebit); $totalCashDetailes = $this->totalCasCreditToQuarter($formattedTotalCash); $ttlCash = $this->totalCashDetails($formattedDataDebit); $newFormat = $this->newFormat($filters, $check); $startPeriod = $this->startPeriod($formattedDataCredit, $formattedDataDebit, $formattedTotalCash, $newFormat, $formattedCommission); $totalCashDebit = $this->getTotalCashDebit($paymentDistributionsDebit); $startCash = $this->startCash($formattedTotalCash, $formattedDataDebit); $toQuarter = $this->sortToQuarterAmount($formattedDataCredit, $formattedDataDebit); return new ResponseDto( data: [ 'header' => [ 'start_period' => [ 'amount' => $startPeriod, 'cash' => $startCash, ] ], 'credit' => [ 'static' => [ 'groups_without_articles' => $groupsWithoutArticlesCredit, 'total_amount' => $totalCredit + $totalAmountCreditPayment, 'total_cash' => $totalCash, 'articles' => CashFlowCreditResource::collection($paymentDistributionsCredit), 'not_distribution_payments_total_amount' => $totalAmountCreditPayment, 'cash' => $totalAmountCashCreditPayment, 'other_data' => [ 'total_cash' => $totalCash, ], ], 'dynamic' => [ 'total_amount' => $totalAmountToQuarter, 'total_cash' => $totalCashDetailes, 'articles' => $formattedDataCredit, 'other_data' => $formattedTotalCash, 'not_distribution_payments' => $formattedNotDistributionCredit, ], ], 'debit' => [ 'static' => [ 'groups_without_articles' => $groupsWithoutArticlesDebit, 'total_amount' => $totalDebit + $totalAmountDebitPayment, 'total_cash_debit' => $totalCashDebit, 'articles' => CashFlowDebitResource::collection($paymentDistributionsDebit), 'not_distribution_payments_total_amount' => $totalAmountDebitPayment, 'other_data' => [ 'moving' => $totalMoving, 'commission' => $totalAmountCashDebitCommissionPayment, 'cash' => $totalAmountCashDebitMovingPayment, ], ], 'dynamic' => [ 'total_amount' => $totalAmountToQuarterDebit, 'total_cash' => $ttlCash, 'articles' => $formattedDataDebit, 'other_data' => $formattedCommission, 'not_distribution_payments' => $formattedNotDistributionDebit, ], ], 'footer' => [ 'end_period' => [ 'amount' => $startPeriod, 'cash' => $startCash, ] ], ], status: true ); } public function startCash($formattedTotalCash, $formattedDataDebit) { $newCollection = []; foreach ($formattedTotalCash as $year => $quarters) { foreach ($quarters as $quarterIndex => $quarterData) { if (isset($newCollection[$year][$quarterIndex])) { $newCollection[$year][$quarterIndex] = array_merge($newCollection[$year][$quarterIndex], $quarterData); } else { $newCollection[$year][$quarterIndex] = $quarterData; } } } foreach ($formattedDataDebit as $year => $quarters) { foreach ($quarters as $quarterIndex => $quarterData) { if (isset($newCollection[$year][$quarterIndex])) { $newCollection[$year][$quarterIndex] = array_merge($newCollection[$year][$quarterIndex], $quarterData); } else { $newCollection[$year][$quarterIndex] = $quarterData; } } } foreach ($newCollection as $year => &$quarters) { ksort($quarters); } unset($quarters); $collection = []; $previousBalance = 0; foreach ($newCollection as $year => $quarters) { foreach ($quarters as $quarter => $records) { $income = 0; $expense = 0; foreach ($records as $key => $record) { if ((!is_object($record) && ($key == 'total_cash'))) { $income += $record; } if (is_object($record)) { $item = $record->resolve(); if ($item['type'] == ArticleTypeEnum::ARTICLE_TYPE_DEBIT->value) { $expense += (float)$item['total_extradition']; } } } $startBalance = $previousBalance; $endBalance = $startBalance + $income - $expense; if (!isset($collection[$year])) { $collection[$year] = []; } $collection[$year][$quarter] = [ 'start_balance' => $startBalance, 'end_balance' => $endBalance ]; $previousBalance = $endBalance; } } return $collection; } public function getTotalCashDebit($paymentDistributions) { $totalExtradition = 0; foreach ($paymentDistributions as $article) { foreach ($article->paymentDistributions as $distribution) { if ($distribution->payment != null) { if ($distribution->payment->payment_type == PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value) { $amount = (float)$distribution->amount; $totalExtradition += $amount; } } } } return $totalExtradition; } public function newFormat($filters, $check) { $query = PaymentDistribution::query(); if ($check) { if (!empty($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = !empty($filters['date_to']) ? $filters['date_to'] : Carbon::now(); $query->with(['payment' => function ($query) use ($dateFrom, $dateTo) { $query->whereBetween('payment_date', [$dateFrom, $dateTo]); }]); } if (!empty($filters['projects'])) { $query->whereIn('project_id', $filters['projects']); } if (!empty($filters['accounts'])) { $query->whereHas('payment', function ($query) use ($filters) { $query->whereIn('account_id', $filters['accounts']); }); } if (!empty($filters['cash'])) { $query->whereHas('payment', function ($query) use ($filters) { $query->whereIn('payment_type', $filters['cash']); }); } } else { $query->with('payment'); } $paymentDistributions = $query->get(); $quarterlyCollection = []; foreach ($paymentDistributions as $distribution) { if (isset($distribution->payment->payment_date)) { $paymentDate = $distribution->payment->payment_date; $year = date('Y', strtotime($paymentDate)); $quarter = $this->getQuarter($paymentDate); if (!isset($quarterlyCollection[$year])) { $quarterlyCollection[$year] = [ 1 => [ 'total_debit_cash' => 0, ], 2 => [ 'total_debit_cash' => 0, ], 3 => [ 'total_debit_cash' => 0, ], 4 => [ 'total_debit_cash' => 0, ] ]; } if ($distribution->payment->payment_type == PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) { $quarterlyCollection[$year][$quarter]['total_debit_cash'] += $distribution->amount; } } } if ($check) { foreach ($quarterlyCollection as $year => $quarters) { foreach ($quarters as $quarter => $items) { if ($items['total_debit_cash'] == 0) { unset($quarterlyCollection[$year][$quarter]); } } if (empty($quarterlyCollection[$year])) { unset($quarterlyCollection[$year]); } } } return $quarterlyCollection; } public function startPeriod($formattedDataCredit, $formattedDataDebit, $formattedTotalCash, $formattedOtherData, $formattedCommission) { $newCollection = []; foreach ($formattedDataCredit as $year => $quarters) { foreach ($quarters as $quarterIndex => $quarterData) { if (isset($newCollection[$year][$quarterIndex])) { $newCollection[$year][$quarterIndex] = array_merge($newCollection[$year][$quarterIndex], $quarterData); } else { $newCollection[$year][$quarterIndex] = $quarterData; } } } foreach ($formattedDataDebit as $year => $quarters) { foreach ($quarters as $quarterIndex => $quarterData) { if (isset($newCollection[$year][$quarterIndex])) { $newCollection[$year][$quarterIndex] = array_merge($newCollection[$year][$quarterIndex], $quarterData); } else { $newCollection[$year][$quarterIndex] = $quarterData; } } } foreach ($formattedTotalCash as $year => $quarters) { foreach ($quarters as $quarterIndex => $quarterData) { if (isset($newCollection[$year][$quarterIndex])) { $newCollection[$year][$quarterIndex] = array_merge($newCollection[$year][$quarterIndex], $quarterData); } else { $newCollection[$year][$quarterIndex] = $quarterData; } } } foreach ($formattedOtherData as $year => $quarters) { foreach ($quarters as $quarterIndex => $quarterData) { if (isset($newCollection[$year][$quarterIndex])) { $newCollection[$year][$quarterIndex] = array_merge($newCollection[$year][$quarterIndex], $quarterData); } else { $newCollection[$year][$quarterIndex] = $quarterData; } } } foreach ($formattedCommission as $year => $quarters) { foreach ($quarters as $quarterIndex => $quarterData) { $value = is_array($quarterData) ? ($quarterData['total_cash'] ?? null) : ($quarterData->total_cash ?? null); if (!isset($newCollection[$year][$quarterIndex])) { $newCollection[$year][$quarterIndex] = []; } $newCollection[$year][$quarterIndex]['total_moving'] = $value; } } foreach ($newCollection as $year => &$quarters) { ksort($quarters); } unset($quarters); $collection = []; $previousBalance = 0; foreach ($newCollection as $year => $quarters) { foreach ($quarters as $quarter => $values) { $income = 0; $expense = 0; foreach ($values as $key => $item) { if ((!is_object($item) && ($key == 'total_cash'))) { $income += $item; } if ((!is_object($item) && ($key == 'total_moving'))) { $expense += $item; } if (is_object($item)) { if ($item->article->article_type == "credit") { $income += (float)$item->total_amount; } else { $expense += (float)$item->total_amount; } } } $startBalance = $previousBalance; $endBalance = $startBalance + $income - $expense; if (!isset($collection[$year])) { $collection[$year] = []; } $collection[$year][$quarter] = [ 'start_balance' => $startBalance, 'end_balance' => $endBalance ]; $previousBalance = $endBalance; } } return $collection; } public function totalCashDetails($formattedDataDebit) { $quarterExtradition = []; foreach ($formattedDataDebit as $year => $quarters) { if (!isset($quarterExtradition[$year])) { $quarterExtradition[$year] = []; } foreach ($quarters as $quarter => $items) { $totalExtradition = 0; foreach ($items as $item) { $arr = $item->toArray(request()); $totalExtradition += $arr['total_extradition'] ?? 0; } $quarterExtradition[$year][$quarter] = $totalExtradition; } } return $quarterExtradition; } public function totalCasCreditToQuarter($formattedTotalCash) { $result = []; foreach ($formattedTotalCash as $year => $quarters) { foreach ($quarters as $quarter => $items) { if (isset($items['total_cash'])) { $cashValue = (float)$items['total_cash']; if (isset($result[$year][$quarter])) { $result[$year][$quarter] += $cashValue; } else { $result[$year][$quarter] = $cashValue; } } } } return $result; } public function totalAmountToQuarter($formattedDataCredit, $formattedTotalCash, $type) { $result = []; foreach ($formattedDataCredit as $year => $quarters) { $yearTotalAmount = 0; foreach ($quarters as $quarter => $items) { $quarterTotalAmount = 0; foreach ($items as $item) { $quarterTotalAmount += (float)$item->total_amount; } $yearTotalAmount += $quarterTotalAmount; if (!isset($result[$year])) { $result[$year] = []; } $result[$year][$quarter] = $quarterTotalAmount; } $result[$year]['total'] = $yearTotalAmount; } // foreach ($formattedTotalCash as $year => $quarters) { // foreach ($quarters as $quarter => $items) { // if (isset($items['total_cash'])) { // $cashValue = intval($items['total_cash']); // if (isset($result[$year][$quarter])) { // $result[$year][$quarter] += $cashValue; // } else { // $result[$year][$quarter] = $cashValue; // } //// $result[$year]['total'] += $cashValue; // } // } // } return $result; } public function sortToQuarterAmount($formattedDataCredit, $formattedDataDebit) { $combinedData = [ 'credit_by_quarter' => [], 'debit_by_quarter' => [] ]; return $combinedData; } public function getArticleShow($modelId, $articleId, $year, $quarter, $filters) { $query = Article::query() ->where('model_id', $modelId) ->where('id', $articleId); $startMonth = ($quarter - 1) * 3 + 1; $endMonth = $quarter * 3; $applyPaymentFilters = function ($query) use ($year, $startMonth, $endMonth, $filters) { $query->whereYear('payment_date', $year) ->whereMonth('payment_date', '>=', $startMonth) ->whereMonth('payment_date', '<=', $endMonth) ->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value) ->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value); if (!empty($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = empty($filters['date_to']) ? Carbon::now() : $filters['date_to']; $query->whereBetween('payment_date', [$dateFrom, $dateTo]); } if (!empty($filters['accounts'])) { $query->whereIn('account_id', $filters['accounts']); } if (!empty($filters['payments_made'])) { $query->whereIn('status', $filters['payments_made']); } if (!empty($filters['cash'])) { $query->whereIn('payment_type', $filters['cash']); } }; $query->whereHas('paymentDistributions.payment', $applyPaymentFilters); if (!empty($filters['projects'])) { $query->whereHas('paymentDistributions', function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); }); } $query->with([ 'paymentDistributions.project', 'paymentDistributions' => function ($query) use ($filters, $applyPaymentFilters) { if (!empty($filters['projects'])) { $query->whereIn('project_id', $filters['projects']); } $query->whereHas('payment', $applyPaymentFilters); }, 'paymentDistributions.payment' => function ($query) use ($applyPaymentFilters) { $applyPaymentFilters($query); $query->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value) ->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value) ->with('contragent'); } ]); $article = $query->first(); $counterparties = $this->getUniqueCounterparties($article); $article->counterparties = $counterparties; return $article; } public function getArticlesGroupShow($modelId, $articleGroupId, $year, $quarter, $filters) { $query = ArticleGroup::query() ->where('model_id', $modelId) ->where('id', $articleGroupId); $articlesCallback = function ($query) use ($year, $quarter, $filters) { $startMonth = ($quarter - 1) * 3 + 1; $endMonth = $quarter * 3; $query->has('paymentDistributions')->with([ 'paymentDistributions' => function ($query) use ($year, $startMonth, $endMonth, $filters) { $query->whereHas('payment', function ($query) use ($year, $startMonth, $endMonth) { $query->whereYear('payment_date', $year) ->whereMonth('payment_date', '>=', $startMonth) ->whereMonth('payment_date', '<=', $endMonth) ->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value) ->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value); }); if (!empty($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = empty($filters['date_to']) ? Carbon::now() : $filters['date_to']; $query->whereHas('payment', function ($q) use ($filters, $dateFrom, $dateTo) { $q->whereBetween('payment_date', [$dateFrom, $dateTo]); }); } if (!empty($filters['projects'])) { $query->whereIn('project_id', $filters['projects']); } if (!empty($filters['accounts'])) { $query->whereHas('payment', function ($q) use ($filters) { $q->whereIn('account_id', $filters['accounts']); }); } if (!empty($filters['payments_made'])) { $query->whereHas('payment', function ($q) use ($filters) { $q->whereIn('status', $filters['payments_made']); }); } if (!empty($filters['cash'])) { $query->whereHas('payment', function ($q) use ($filters) { $q->whereIn('payment_type', $filters['cash']); }); } }, 'paymentDistributions.payment' => function ($query) use ($year, $startMonth, $endMonth, $filters) { $query->whereYear('payment_date', $year) ->whereMonth('payment_date', '>=', $startMonth) ->whereMonth('payment_date', '<=', $endMonth) ->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value) ->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value) ->with('contragent'); if (!empty($filters['accounts'])) { $query->whereIn('account_id', $filters['accounts']); } if (!empty($filters['payments_made'])) { $query->whereIn('status', $filters['payments_made']); } if (!empty($filters['cash'])) { $query->whereIn('payment_type', $filters['cash']); } }, 'paymentDistributions.project', ]); if (!empty($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = empty($filters['date_to']) ? Carbon::now() : $filters['date_to']; $query->whereHas('paymentDistributions.payment', function ($q) use ($filters, $dateFrom, $dateTo) { $q->whereBetween('payment_date', [$dateFrom, $dateTo]); }); } if (!empty($filters['projects'])) { $query->whereHas('paymentDistributions', function ($q) use ($filters) { $q->whereIn('project_id', $filters['projects']); }); } if (!empty($filters['accounts'])) { $query->whereHas('paymentDistributions.payment', function ($q) use ($filters) { $q->whereIn('account_id', $filters['accounts']); }); } if (!empty($filters['payments_made'])) { $query->whereHas('paymentDistributions.payment', function ($q) use ($filters) { $q->whereIn('status', $filters['payments_made']); }); } if (!empty($filters['cash'])) { $query->whereHas('paymentDistributions.payment', function ($q) use ($filters) { $q->whereIn('payment_type', $filters['cash']); }); } }; $query->with(['articles' => $articlesCallback]); $counterpartyIds = collect(); $paymentsIds = collect(); $articleGroups = $query->first(); $articleGroups->articles->each(function ($article) use (&$counterpartyIds, &$paymentsIds) { $uniqueCounterparties = $article->paymentDistributions ->pluck('payment.contragent') ->unique('id') ->values(); $counterpartyIds = $counterpartyIds->concat($uniqueCounterparties->pluck('id')); $paymentsIds = $paymentsIds->concat($article->paymentDistributions->pluck('payment_id')); }); $counterparties = Counterparty::query() ->whereIn('id', $counterpartyIds) ->with(['payments' => function ($query) use ($paymentsIds) { $query->whereIn('id', $paymentsIds) ->with('distributions.project'); }]) ->get(); $articleGroups->setRelation('counterparties', $counterparties); return $articleGroups; } public function getOtherDataShow($modelId, $year, $quarter, $type, $filters) { $quarters = [ 1 => [1, 2, 3], 2 => [4, 5, 6], 3 => [7, 8, 9], 4 => [10, 11, 12], ]; $months = $quarters[$quarter]; $baseQuery = function ($query, bool $forcePaymentDate = false) use ($year, $months) { $query->where(function ($q) use ($year, $months, $forcePaymentDate) { if ($forcePaymentDate) { $q->whereYear('payment_date', $year) ->whereRaw( 'EXTRACT(MONTH FROM payment_date) IN (' . implode(',', array_map('intval', $months)) . ')' ); return; } $q->where(function ($q) use ($year, $months) { $q->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->whereNotNull('actual_date') ->whereYear('actual_date', $year) ->whereRaw('EXTRACT(MONTH FROM actual_date) IN (' . implode(',', array_map('intval', $months)) . ')'); }) ->orWhere(function ($q) use ($year, $months) { $q->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->whereYear('payment_date', $year) ->whereRaw('EXTRACT(MONTH FROM payment_date) IN (' . implode(',', array_map('intval', $months)) . ')'); }); }) ->with('contragent'); }; $query = PaymentDistribution::query(); $query->whereHas('payment', function ($query) use ($modelId) { $query->where('model_id', $modelId); }); switch ($type) { case 'moving': $query ->with(['payment' => function ($query) use ($year, $months, $modelId, $filters) { if (!empty($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = !empty($filters['date_to']) ? $filters['date_to'] : Carbon::now(); $query->where(function ($q) use ($dateFrom, $dateTo) { $q->whereBetween('payment_date', [$dateFrom, $dateTo]); }); } if (!empty($filters['projects'])) { $query->whereHas('distributions', function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); })->with(['distributions' => function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); }]); } if (!empty($filters['accounts'])) { $query->whereIn('account_id', $filters['accounts']); } if (!empty($filters['payments_made'])) { $query->whereIn('status', $filters['payments_made']); } if (!empty($filters['cash'])) { $query->whereIn('payment_type', $filters['cash']); } $query->where(['payment_type' => PaymentTypeEnum::PAYMENT_TYPE_MOVING->value, 'model_id' => $modelId]) ->where(function ($q) use ($year, $months) { $q->whereYear('payment_date', $year) ->whereRaw('EXTRACT(MONTH FROM payment_date) IN (' . implode(',', array_map('intval', $months)) . ')'); }) ->with('contragent'); }]) ->whereHas('payment', function ($query) use ($year, $months, $modelId, $filters) { if (!empty($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = !empty($filters['date_to']) ? $filters['date_to'] : Carbon::now(); $query->where(function ($q) use ($dateFrom, $dateTo) { $q->whereBetween('payment_date', [$dateFrom, $dateTo]); }); } if (!empty($filters['projects'])) { $query->whereHas('distributions', function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); })->with(['distributions' => function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); }]); } if (!empty($filters['accounts'])) { $query->whereIn('account_id', $filters['accounts']); } if (!empty($filters['payments_made'])) { $query->whereIn('status', $filters['payments_made']); } if (!empty($filters['cash'])) { $query->whereIn('payment_type', $filters['cash']); } $query->where(['payment_type' => PaymentTypeEnum::PAYMENT_TYPE_MOVING->value, 'model_id' => $modelId]) ->where(function ($q) use ($year, $months) { $q->whereYear('payment_date', $year) ->whereRaw('EXTRACT(MONTH FROM payment_date) IN (' . implode(',', array_map('intval', $months)) . ')'); }); }); break; case 'commission': $query->where('comission', '!=', null) ->with(['payment' => function ($query) use ($baseQuery, $year, $months, $modelId, $filters) { $query->where('model_id', $modelId) ->where(function ($q) use ($year, $months) { $q->where(function ($qMoving) use ($year, $months) { $qMoving->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->where(function ($qPayment) use ($year, $months) { $qPayment->whereYear('payment_date', $year) ->whereRaw('EXTRACT(MONTH FROM payment_date) IN (' . implode(',', array_map('intval', $months)) . ')'); }); })->orWhere(function ($qOther) use ($year, $months) { $qOther->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->whereYear('payment_date', $year) ->whereRaw('EXTRACT(MONTH FROM payment_date) IN (' . implode(',', array_map('intval', $months)) . ')'); }); }) ->with('contragent'); if (!empty($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = !empty($filters['date_to']) ? $filters['date_to'] : Carbon::now(); $query->where(function ($q) use ($dateFrom, $dateTo) { $q->where(function ($qActual) use ($dateFrom, $dateTo) { $qActual->whereNotNull('actual_date') ->whereBetween('actual_date', [$dateFrom, $dateTo]); })->orWhere(function ($qPayment) use ($dateFrom, $dateTo) { $qPayment->whereNull('actual_date') ->whereBetween('payment_date', [$dateFrom, $dateTo]); }); }); } if (!empty($filters['projects'])) { $query->whereHas('distributions', function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); })->with(['distributions' => function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); }]); } if (!empty($filters['accounts'])) { $query->whereIn('account_id', $filters['accounts']); } if (!empty($filters['payments_made'])) { $query->whereIn('status', $filters['payments_made']); } if (!empty($filters['cash'])) { $query->whereIn('payment_type', $filters['cash']); } $baseQuery($query, true); }]) ->whereHas('payment', function ($query) use ($baseQuery, $year, $months, $modelId, $filters) { $query->where('model_id', $modelId) ->where(function ($q) use ($year, $months) { $q->where(function ($qMoving) use ($year, $months) { $qMoving->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->where(function ($qPayment) use ($year, $months) { $qPayment->whereYear('payment_date', $year) ->whereRaw('EXTRACT(MONTH FROM payment_date) IN (' . implode(',', array_map('intval', $months)) . ')'); }); })->orWhere(function ($qOther) use ($year, $months) { $qOther->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->whereYear('payment_date', $year) ->whereRaw('EXTRACT(MONTH FROM payment_date) IN (' . implode(',', array_map('intval', $months)) . ')'); }); }); if (!empty($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = !empty($filters['date_to']) ? $filters['date_to'] : Carbon::now(); $query->where(function ($q) use ($dateFrom, $dateTo) { $q->where(function ($qActual) use ($dateFrom, $dateTo) { $qActual->whereNotNull('actual_date') ->whereBetween('actual_date', [$dateFrom, $dateTo]); })->orWhere(function ($qPayment) use ($dateFrom, $dateTo) { $qPayment->whereNull('actual_date') ->whereBetween('payment_date', [$dateFrom, $dateTo]); }); }); } if (!empty($filters['projects'])) { $query->whereHas('distributions', function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); })->with(['distributions' => function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); }]); } if (!empty($filters['accounts'])) { $query->whereIn('account_id', $filters['accounts']); } if (!empty($filters['payments_made'])) { $query->whereIn('status', $filters['payments_made']); } if (!empty($filters['cash'])) { $query->whereIn('payment_type', $filters['cash']); } $baseQuery($query, true); }); break; case 'cash': $query->where('cashbox', '!=', null) ->with(['payment' => function ($query) use ($baseQuery, $modelId, $year, $months, $filters) { if (!empty($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = !empty($filters['date_to']) ? $filters['date_to'] : Carbon::now(); $query->where(function ($q) use ($dateFrom, $dateTo) { $q->whereBetween('payment_date', [$dateFrom, $dateTo]); }); } if (!empty($filters['projects'])) { $query->whereHas('distributions', function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); })->with(['distributions' => function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); }]); } if (!empty($filters['accounts'])) { $query->whereIn('account_id', $filters['accounts']); } if (!empty($filters['payments_made'])) { $query->whereIn('status', $filters['payments_made']); } if (!empty($filters['cash'])) { $query->whereIn('payment_type', $filters['cash']); } $baseQuery($query, true); }]) ->whereHas('payment', function ($query) use ($baseQuery, $modelId, $year, $months, $filters) { if (!empty($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = !empty($filters['date_to']) ? $filters['date_to'] : Carbon::now(); $query->where(function ($q) use ($dateFrom, $dateTo) { $q->whereBetween('payment_date', [$dateFrom, $dateTo]); }); } if (!empty($filters['projects'])) { $query->whereHas('distributions', function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); })->with(['distributions' => function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); }]); } if (!empty($filters['accounts'])) { $query->whereIn('account_id', $filters['accounts']); } if (!empty($filters['payments_made'])) { $query->whereIn('status', $filters['payments_made']); } if (!empty($filters['cash'])) { $query->whereIn('payment_type', $filters['cash']); } $baseQuery($query, true); }); break; case 'cash-credit': $query->with(['payment' => function ($query) use ($baseQuery, $modelId, $year, $months, $filters) { $query->where(function ($q) use ($modelId, $year, $months) { $q->where([ 'payment_type' => PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value, 'model_id' => $modelId ])->orWhere(function ($q2) use ($modelId) { $q2->where([ 'payment_type' => PaymentTypeEnum::PAYMENT_TYPE_MOVING->value, 'model_id' => $modelId, 'status' => PaymentStatusEnum::STATUS_RECEIVED->value]); })->whereNotNull('actual_date') ->whereYear('actual_date', $year) ->whereRaw('EXTRACT(MONTH FROM actual_date) IN (' . implode(',', array_map('intval', $months)) . ')'); }); if (!empty($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = !empty($filters['date_to']) ? $filters['date_to'] : Carbon::now(); $query->where(function ($q) use ($dateFrom, $dateTo) { $q->where(function ($qActual) use ($dateFrom, $dateTo) { $qActual->whereNotNull('actual_date') ->whereBetween('actual_date', [$dateFrom, $dateTo]); })->orWhere(function ($qPayment) use ($dateFrom, $dateTo) { $qPayment->whereNull('actual_date') ->whereBetween('payment_date', [$dateFrom, $dateTo]); }); }); } if (!empty($filters['projects'])) { $query->whereHas('distributions', function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); })->with(['distributions' => function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); }]); } if (!empty($filters['accounts'])) { $query->whereIn('account_id', $filters['accounts']); } if (!empty($filters['payments_made'])) { $query->whereIn('status', $filters['payments_made']); } if (!empty($filters['cash'])) { $query->whereIn('payment_type', $filters['cash']); } $baseQuery($query); }]) ->whereHas('payment', function ($query) use ($baseQuery, $modelId, $year, $months, $filters) { $query->where(function ($q) use ($modelId, $year, $months) { $q->where([ 'payment_type' => PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value, 'model_id' => $modelId ]) ->orWhere(function ($q2) use ($modelId, $year, $months) { $q2->where([ 'payment_type' => PaymentTypeEnum::PAYMENT_TYPE_MOVING->value, 'model_id' => $modelId, 'status' => PaymentStatusEnum::STATUS_RECEIVED->value]) ->whereNotNull('actual_date') ->whereYear('actual_date', $year) ->whereRaw('EXTRACT(MONTH FROM actual_date) IN (' . implode(',', array_map('intval', $months)) . ')'); }); }); if (!empty($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = !empty($filters['date_to']) ? $filters['date_to'] : Carbon::now(); $query->where(function ($q) use ($dateFrom, $dateTo) { $q->where(function ($qActual) use ($dateFrom, $dateTo) { $qActual->whereNotNull('actual_date') ->whereBetween('actual_date', [$dateFrom, $dateTo]); })->orWhere(function ($qPayment) use ($dateFrom, $dateTo) { $qPayment->whereNull('actual_date') ->whereBetween('payment_date', [$dateFrom, $dateTo]); }); }); } if (!empty($filters['projects'])) { $query->whereHas('distributions', function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); })->with(['distributions' => function ($query) use ($filters) { $query->whereIn('project_id', $filters['projects']); }]); } if (!empty($filters['accounts'])) { $query->whereIn('account_id', $filters['accounts']); } if (!empty($filters['payments_made'])) { $query->whereIn('status', $filters['payments_made']); } if (!empty($filters['cash'])) { $query->whereIn('payment_type', $filters['cash']); } $baseQuery($query); }); break; default: break; } if (!empty($filters['accounts'])) { $query->whereHas('payment', function ($query) use ($filters) { $query->whereIn('account_id', $filters['accounts']); }); } return $query->get(); } public function getUniqueCounterparties($article) { $uniqueCounterparties = $article->paymentDistributions ->pluck('payment.contragent') ->unique('id') ->values(); $counterpartyIds = $uniqueCounterparties->pluck('id')->toArray(); $paymentsIds = PaymentDistribution::query()->where('article_id', $article->id)->get('payment_id')->toArray(); return Counterparty::query() ->whereIn('id', $counterpartyIds) ->with(['payments' => function ($query) use ($paymentsIds) { $query->whereIn('id', $paymentsIds) ->with('distributions'); }]) ->get(); } public function sortToQuarterOtherDataDebit($filters, $check, $modelId) { $query = PaymentDistribution::query(); if ($check) { $query->whereHas('payment', function ($q) use ($filters, $modelId) { $q->where('model_id', $modelId); if (!empty($filters['date_from'])) { $q->whereBetween('payment_date', [ $filters['date_from'], $filters['date_to'] ?? Carbon::now() ]); } if (!empty($filters['accounts'])) { $q->whereIn('account_id', $filters['accounts']); } if (!empty($filters['payments_made'])) { $q->whereIn('status', $filters['payments_made']); } if (!empty($filters['cash'])) { $q->whereIn('payment_type', $filters['cash']); } }); if (!empty($filters['projects'])) { $query->whereIn('project_id', $filters['projects']); } $query->with('payment'); } else { $query->with('payment'); } $paymentDistributions = $query->get(); $quarterlyCollection = []; foreach ($paymentDistributions as $distribution) { if (isset($distribution->payment->payment_date)) { if ($distribution->payment->model_id == $modelId) { $paymentDate = $distribution->payment->payment_date; $year = date('Y', strtotime($paymentDate)); $quarter = $this->getQuarter($paymentDate); if (!isset($quarterlyCollection[$year])) { $quarterlyCollection[$year] = [ 1 => [ 'total_cash' => 0, 'total_commission' => 0, 'total_moving' => 0 ], 2 => [ 'total_cash' => 0, 'total_commission' => 0, 'total_moving' => 0 ], 3 => [ 'total_cash' => 0, 'total_commission' => 0, 'total_moving' => 0 ], 4 => [ 'total_cash' => 0, 'total_commission' => 0, 'total_moving' => 0 ] ]; } $quarterlyCollection[$year][$quarter]['total_commission']+= $distribution->comission; if ($distribution->payment->payment_type === PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) { $quarterlyCollection[$year][$quarter]['total_cash']+= $distribution->amount; if (!is_null($distribution->cashbox)) { $quarterlyCollection[$year][$quarter]['total_moving']+= $distribution->cashbox; } } } } } if ($check) { foreach ($quarterlyCollection as $year => $quarters) { foreach ($quarters as $quarter => $items) { if (($items['total_cash'] == 0) && ($items['total_commission'] == 0) && ($items['total_moving'] == 0)) { unset($quarterlyCollection[$year][$quarter]); } } if (empty($quarterlyCollection[$year])) { unset($quarterlyCollection[$year]); } } } return $quarterlyCollection; } public function sortToQuarterTotalCash($filters, $check, $modelID) { $query = PaymentDistribution::query() ->whereHas('payment', function ($q) use ($modelID) { $q->where('model_id', $modelID); }); if ($check) { if (!empty($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = $filters['date_to'] ?? Carbon::now(); // Добавляем приемы по payment_date и перемещения по actual_date $query->whereHas('payment', function ($query) use ($dateFrom, $dateTo) { $query->where(function ($q) use ($dateFrom, $dateTo) { // Приемы по payment_date $q->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value) ->whereBetween('payment_date', [$dateFrom, $dateTo]); })->orWhere(function ($q2) use ($dateFrom, $dateTo) { // Перемещения по actual_date $q2->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->where('status', PaymentStatusEnum::STATUS_RECEIVED->value) ->whereNotNull('actual_date') ->whereBetween('actual_date', [$dateFrom, $dateTo]); }); }); } if (!empty($filters['payments_made'])) { $query->whereHas('payment', function ($query) use ($filters) { $query->whereIn('status', $filters['payments_made']); }); } if (!empty($filters['cash'])) { $query->whereHas('payment', function ($query) use ($filters) { $query->whereIn('payment_type', $filters['cash']); }); } } else { $query->whereHas('payment', function ($query) { $query->where(function ($q) { $q->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value); })->orWhere(function ($q2) { $q2->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->where('status', PaymentStatusEnum::STATUS_RECEIVED->value) ->whereNotNull('actual_date'); }); }); } $paymentDistributions = $query->get(); $quarterlyCollection = []; foreach ($paymentDistributions as $distribution) { $payment = $distribution->payment; if (!$payment) continue; // Для приемов используем payment_date и amount if ($payment->payment_type == PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value && isset($payment->payment_date)) { $paymentDate = $payment->payment_date; $year = date('Y', strtotime($paymentDate)); $quarter = $this->getQuarter($paymentDate); if (!isset($quarterlyCollection[$year])) { $quarterlyCollection[$year] = [ 1 => [ 'total_cash' => 0, ], 2 => [ 'total_cash' => 0, ], 3 => [ 'total_cash' => 0, ], 4 => [ 'total_cash' => 0, ] ]; } $quarterlyCollection[$year][$quarter]['total_cash'] += $distribution->amount; } // Для перемещений используем actual_date и cashbox elseif ($payment->payment_type == PaymentTypeEnum::PAYMENT_TYPE_MOVING->value && $payment->status == PaymentStatusEnum::STATUS_RECEIVED->value && isset($payment->actual_date)) { $paymentDate = $payment->actual_date; $year = date('Y', strtotime($paymentDate)); $quarter = $this->getQuarter($paymentDate); if (!isset($quarterlyCollection[$year])) { $quarterlyCollection[$year] = [ 1 => [ 'total_cash' => 0, ], 2 => [ 'total_cash' => 0, ], 3 => [ 'total_cash' => 0, ], 4 => [ 'total_cash' => 0, ] ]; } // Используем cashbox для перемещений if (isset($distribution->cashbox)) { $quarterlyCollection[$year][$quarter]['total_cash'] += $distribution->cashbox; } } } if ($check) { foreach ($quarterlyCollection as $year => $quarters) { foreach ($quarters as $quarter => $items) { if ($items['total_cash'] == 0) { unset($quarterlyCollection[$year][$quarter]); } } if (empty($quarterlyCollection[$year])) { unset($quarterlyCollection[$year]); } } } return $quarterlyCollection; } protected function sortToQuarter($paymentDistributions, $credit, $filter) { $quarterlyCollection = []; foreach ($paymentDistributions as $payment) { if (isset($payment->paymentDistributions)) { foreach ($payment->paymentDistributions as $distribution) { if (isset($distribution->payment->payment_date)) { $paymentDate = $distribution->payment->payment_date; $year = date('Y', strtotime($paymentDate)); $quarter = $this->getQuarter($paymentDate); if (!isset($quarterlyCollection[$year])) { $quarterlyCollection[$year] = [ 1 => [], 2 => [], 3 => [], 4 => [] ]; } $articleId = $distribution->article_id; $found = false; if (($distribution->payment->payment_type != PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value) && ($distribution->payment->payment_type != PaymentTypeEnum::PAYMENT_TYPE_MOVING->value)) { $distribution->total_amount = $distribution->amount; } if ($distribution->payment->payment_type == PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value) { $distribution->total_extradition = $distribution->amount; } else { $distribution->total_extradition = 0; } foreach ($quarterlyCollection[$year][$quarter] as &$item) { if ($item->article_id == $articleId) { if (($distribution->payment->payment_type != PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value) && ($distribution->payment->payment_type != PaymentTypeEnum::PAYMENT_TYPE_MOVING->value)) { $item->total_amount += $distribution->total_amount; } $item->total_extradition += $distribution->total_extradition; $found = true; break; } } if (!$found) { if ($credit) { $quarterlyCollection[$year][$quarter][] = new CashFlowCreditToMonthResource($distribution); } else { $quarterlyCollection[$year][$quarter][] = new CashFlowDebitToMonthResource($distribution); } } } } } } if ($filter) { foreach ($quarterlyCollection as $year => $quarters) { foreach ($quarters as $quarter => $items) { if (empty($items)) { unset($quarterlyCollection[$year][$quarter]); } } if (empty($quarterlyCollection[$year])) { unset($quarterlyCollection[$year]); } } } return $quarterlyCollection; } private function getQuarter($date) { $month = date('n', strtotime($date)); return ceil($month / 3); } public function sumTotalAmount($paymentDistributions) { $total = 0; foreach ($paymentDistributions as $article) { foreach ($article->paymentDistributions as $distribution) { if ($distribution->payment == null) { continue; } if (($distribution->payment->payment_type != PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) && ($distribution->payment->payment_type != PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value)) { $amount = (float)$distribution->amount; $total += $amount; } } } return $total; } public function getIncomeAndExpensesToQuarterShow($modelId, $type, $year, $quarter, array $filters = []) { $query = PaymentDistribution::query(); $quarters = [ 1 => [1, 2, 3], 2 => [4, 5, 6], 3 => [7, 8, 9], 4 => [10, 11, 12], ]; $months = $quarters[$quarter]; $statuses = $filters['payments_made'] ?? [PaymentStatusEnum::STATUS_RECEIVED->value]; $query->whereHas('payment', function ($query) use ($year, $months, $statuses) { $query->whereYear('payment_date', $year) ->whereIn(DB::raw('EXTRACT(MONTH FROM payment_date)'), $months) ->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value) ->where(function ($q) use ($statuses) { $q->whereIn('status', $statuses) ->orWhere(function ($q) { $q->where('status', PaymentStatusEnum::STATUS_SENT->value) ->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION_FROM_1C->value); }); }); }); switch ($type) { case 'credit': $query->with(['article' => function ($query) use ($modelId) { $query->where([ 'article_type' => ArticleTypeEnum::ARTICLE_TYPE_CREDIT->value, 'model_id' => $modelId ]); }, 'payment' => function ($paymentQuery) { $paymentQuery->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value) ->where(function ($q) { $q->where('status', PaymentStatusEnum::STATUS_RECEIVED->value) ->orWhere(function ($q) { $q->where('status', PaymentStatusEnum::STATUS_SENT->value) ->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION_FROM_1C->value); }); }) ->with('contragent'); }]) ->whereHas('article', function ($query) use ($modelId) { $query->where([ 'article_type' => ArticleTypeEnum::ARTICLE_TYPE_CREDIT->value, 'model_id' => $modelId ]); }); break; case 'debit': $query->with(['article' => function ($query) use ($modelId) { $query ->where([ 'article_type' => ArticleTypeEnum::ARTICLE_TYPE_DEBIT->value, 'model_id' => $modelId ]); }, 'payment.contragent']) ->whereHas('article', function ($query) use ($modelId) { $query->where([ 'article_type' => ArticleTypeEnum::ARTICLE_TYPE_DEBIT->value, 'model_id' => $modelId ]); }); break; default: break; } return $query->get(); } public function getCashIncomeToQuarterShow($modelId, $year, $quarter) { $quarters = [ 1 => [1, 2, 3], 2 => [4, 5, 6], 3 => [7, 8, 9], 4 => [10, 11, 12], ]; $months = $quarters[$quarter]; $query = PaymentDistribution::query() ->whereHas('payment', function ($query) use ($modelId, $year, $months) { $query ->where('model_id', $modelId) ->where('status', PaymentStatusEnum::STATUS_RECEIVED->value) ->whereIn('payment_type', [ PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value, PaymentTypeEnum::PAYMENT_TYPE_MOVING->value, ]) ->where(function ($q) use ($year, $months) { $q->where(function ($q) use ($year, $months) { $q->whereNotNull('actual_date') ->whereYear('actual_date', $year) ->whereIn(DB::raw('EXTRACT(MONTH FROM actual_date)'), $months); }); $q->orWhere(function ($q) use ($year, $months) { $q->whereNull('actual_date') ->whereYear('payment_date', $year) ->whereIn(DB::raw('EXTRACT(MONTH FROM payment_date)'), $months); }); }); }) ->with([ 'payment.contragent', 'article', ]); $collection = $query->get(); $collection->each(function ($distribution) { if ( in_array( $distribution->payment->payment_type, [ PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value, PaymentTypeEnum::PAYMENT_TYPE_MOVING->value, ], true ) ) { $distribution->amount = $distribution->cashbox ?? $distribution->amount; } }); return $collection; } public function getReceptionIncomeToQuarterShow($modelId, $year, $quarter, $statuses = []) { $quarters = [ 1 => [1, 2, 3], 2 => [4, 5, 6], 3 => [7, 8, 9], 4 => [10, 11, 12], ]; $months = $quarters[$quarter]; $query = PaymentDistribution::query() ->whereHas('payment', function ($query) use ($modelId, $year, $months, $statuses) { $query->where('model_id', $modelId) ->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value); if (!empty($statuses)) { $query->whereIn('status', $statuses); } $query->where(function ($q) use ($year, $months) { $q->where(function ($q) use ($year, $months) { $q->whereNotNull('actual_date') ->whereYear('actual_date', $year) ->whereIn(DB::raw('EXTRACT(MONTH FROM actual_date)'), $months); }); $q->orWhere(function ($q) use ($year, $months) { $q->whereNull('actual_date') ->whereYear('payment_date', $year) ->whereIn(DB::raw('EXTRACT(MONTH FROM payment_date)'), $months); }); }); }) ->with([ 'payment.contragent', 'article', ]); $collection = $query->get(); $collection->each(function ($distribution) { $distribution->amount = $distribution->cashbox ?? $distribution->amount; }); return $collection; } public function getUndistributedIncomeShowByQuarter($modelId, $year, $quarter, $paymentsMade) { $quarters = [ 1 => [1, 2, 3], 2 => [4, 5, 6], 3 => [7, 8, 9], 4 => [10, 11, 12], ]; $months = $quarters[$quarter]; $query = PaymentDistribution::query() ->whereHas('payment', function ($query) use ($modelId, $year, $months, $paymentsMade) { $query->where('model_id', $modelId) ->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION_FROM_1C->value) ->whereNull('article_id'); if (!empty($paymentsMade)) { $query->whereIn('status', $paymentsMade); } $query->where(function ($q) use ($year, $months) { $q->whereYear('payment_date', $year) ->whereIn(DB::raw('EXTRACT(MONTH FROM payment_date)'), $months); }); }) ->with([ 'payment.contragent', 'article', ]); return $query->get(); } protected function sortNotDistributedPaymentsToQuarter($paymentDistributions, $credit, $filter) { $quarterlyCollection = []; foreach ($paymentDistributions as $distribution) { if (!isset($distribution->payment->payment_date)) { continue; } $paymentDate = $distribution->payment->payment_date; $year = date('Y', strtotime($paymentDate)); $quarter = $this->getQuarter($paymentDate); if (!isset($quarterlyCollection[$year])) { $quarterlyCollection[$year] = [ 1 => [], 2 => [], 3 => [], 4 => [] ]; } $amount = $credit ? $distribution->amount : $distribution->amount; $quarterlyCollection[$year][$quarter]['total_amount'] = ($quarterlyCollection[$year][$quarter]['total_amount'] ?? 0) + $amount; } if ($filter) { foreach ($quarterlyCollection as $year => $quarters) { foreach ($quarters as $quarter => $items) { if (empty($items)) { unset($quarterlyCollection[$year][$quarter]); } } if (empty($quarterlyCollection[$year])) { unset($quarterlyCollection[$year]); } } } return $quarterlyCollection; } private function mergeDistributedAndNotDistributedByQuarter(array $totalAmount, array $notDistributedPayments): array { foreach ($notDistributedPayments as $year => $quarters) { foreach ($quarters as $quarter => $data) { if ($quarter === 'total') continue; $amount = $data['total_amount'] ?? 0; if (!isset($totalAmount[$year][$quarter])) { $totalAmount[$year][$quarter] = 0; } $totalAmount[$year][$quarter] += $amount; } } // пересчёт total по годам foreach ($totalAmount as $year => $quarters) { $totalAmount[$year]['total'] = array_sum(array_filter($quarters, fn($k) => $k !== 'total', ARRAY_FILTER_USE_KEY)); } return $totalAmount; } }