/
var
/
www
/
html
/
back
/
app
/
Services
/
CashFlow
/
Upload File
HOME
<?php namespace App\Services\CashFlow; use App\Domain\Article\Enums\ArticleTypeEnum; use App\Domain\Payment\Enums\PaymentTypeEnum; use App\Http\Resources\CashFlowCreditResource; use App\Http\Resources\CashFlowDebitResource; use App\Http\Resources\CashFlowProjectCreditResource; use App\Models\PaymentDistribution; use App\Models\Project; 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\Log; class ActiveTabProjectService { private $distributionsRepository; private $paymentRepository; public function __construct(PaymentDistributionsRepositoryInterface $paymentDistributionsRepository, TotalAmountRepositoryInterface $paymentRepository, protected CashFlowService $cashFlowService) { $this->distributionsRepository = $paymentDistributionsRepository; $this->paymentRepository = $paymentRepository; } public function getActivePageProjectToIndex(int $modelID, $filters) { $paymentDistributionsCredit = $this->distributionsRepository->getPaymentDistributionsProject($modelID, $filters, ArticleTypeEnum::ARTICLE_TYPE_CREDIT->value); $paymentDistributionsDebit = $this->distributionsRepository->getPaymentDistributionsProject($modelID, $filters, ArticleTypeEnum::ARTICLE_TYPE_DEBIT->value); $totalAmountCreditPayment = $this->paymentRepository->getTotalAmountPayment($modelID, $filters, $credit = true); $totalAmountDebitPayment = $this->paymentRepository->getTotalAmountPayment($modelID, $filters, $credit = false); $totalCredit = $this->cashFlowService->sumTotalAmount($paymentDistributionsCredit); $totalDebit = $this->cashFlowService->sumTotalAmount($paymentDistributionsDebit); $check = array_filter($filters, function ($value) { return $value !== null; }); if ($check) { $formattedToProjectCredit = $this->sortToProject($paymentDistributionsCredit, true, $check); $formattedToProjectDebit = $this->sortToProject($paymentDistributionsDebit, false, $check); $formattedOtherData = $this->sortToProjectOtherData($filters, false, $modelID); } else { $formattedToProjectCredit = $this->sortToProject($paymentDistributionsCredit, true, $check); $formattedToProjectDebit = $this->sortToProject($paymentDistributionsDebit, false, $check); $formattedOtherData = $this->sortToProjectOtherData($filters, false, $modelID); } $totalAmountToProject = $this->totalAmountToProject($filters); $totalAmountDebitCashPayment = $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'); $totalCash = $this->cashFlowService->getTotalCash($filters, $modelID); $totalAmountDebit = $this->totalAmountDebitProject($filters); $newFormat = $this->newFormat($filters, false); $startPeriod = $this->startPeriod($formattedToProjectCredit, $formattedToProjectDebit, $newFormat, $formattedOtherData); return new ResponseDto( data: [ 'header' => [ 'start_period' => [ 'amount' => $startPeriod, // 'cash' => $startCash, ] ], 'credit' => [ 'static' => [ 'total_amount' => $totalCredit + $totalAmountCreditPayment, 'total_cash' => $totalCash, 'articles' => CashFlowCreditResource::collection($paymentDistributionsCredit), 'not_distribution_payments_total_amount' => $totalAmountCreditPayment, 'other_data' => [ 'total_cash' => $totalCash, ], ], 'dynamic' => [ 'total_amount' => $totalAmountToProject, 'projects' => $formattedToProjectCredit, ], ], 'debit' => [ 'static' => [ 'total_amount' => $totalDebit + $totalAmountDebitPayment + $totalAmountDebitCashPayment, 'articles' => CashFlowDebitResource::collection($paymentDistributionsDebit), 'not_distribution_payments_total_amount' => $totalAmountDebitPayment, 'other_data' => [ 'moving' => $totalMoving, 'commission' => $totalAmountCashDebitCommissionPayment, 'cash' => $totalAmountDebitCashPayment, ], ], 'dynamic' => [ 'total_amount' => $totalAmountDebit, // 'total_cash' => $ttlCash, 'projects' => $formattedToProjectDebit, 'other_data' => $formattedOtherData, ], ], 'footer' => [ 'end_period' => [ 'total_amount' => (($totalCredit + $totalCash) - ($totalDebit + $totalAmountDebitCashPayment)), 'amount' => $startPeriod, // 'cash' => $startCash, ] ], ], status: true ); } public function totalAmountDebitProject($filters) { $query = PaymentDistribution::query(); $query->with(['payment', 'article']); $filters = array_filter($filters, function ($value) { return $value !== null; }); if (!empty($filters)) { 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['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']); }); } } $paymentDistributions = $query->get(); $result = []; foreach ($paymentDistributions as $item) { if ($item->article && $item->article->article_type == 'debit' && $item->article->id != 1) { $amount = floatval($item->amount); if (!isset($result[$item->project_id])) { $result[$item->project_id] = 0; } $result[$item->project_id] += $amount; } } return $result; } public function newFormat($filters, $check) { $query = PaymentDistribution::query(); if ($check) { if (!empty($filters['date_from'])) { if (empty($filters['date_to'])) { $dateTo = Carbon::now(); } else { $dateTo = $filters['date_to']; } $query->with(['payment' => function ($query) use ($filters, $dateTo) { $query->where(function ($q) use ($filters, $dateTo) { // Для moving учитываем actual_date $q->where(function ($qMoving) use ($filters, $dateTo) { $qMoving->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->where(function ($qActual) use ($filters, $dateTo) { $qActual->whereNotNull('actual_date') ->whereBetween('actual_date', [$filters['date_from'], $dateTo]); })->orWhere(function ($qPayment) use ($filters, $dateTo) { $qPayment->whereNull('actual_date') ->whereBetween('payment_date', [$filters['date_from'], $dateTo]); }); })->orWhere(function ($qOther) use ($filters, $dateTo) { $qOther->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->whereBetween('payment_date', [$filters['date_from'], $dateTo]); }); }); }]); } if (!empty($filters['cash'])) { $query->whereHas('payment', function ($query) use ($filters) { $query->whereIn('payment_type', $filters['cash']); }); } } else { $query->with('payment'); } $paymentDistributions = $query->get(); $projectCollection = []; foreach ($paymentDistributions as $distribution) { if (isset($distribution->payment->payment_date) && isset($distribution->project_id)) { $projectId = $distribution->project_id; if (!isset($projectCollection[$projectId])) { $projectCollection[$projectId] = [ 'total_cash_debit' => 0, ]; } if ($distribution->payment->payment_type == PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) { // Используем cashbox для moving if (isset($distribution->cashbox)) { $projectCollection[$projectId]['total_cash_debit'] += $distribution->cashbox; } } } } if ($check) { foreach ($projectCollection as $projectId => $items) { if ($items['total_cash_debit'] == 0) { unset($projectCollection[$projectId]); } } } return $projectCollection; } public function startPeriod($formattedDataCredit, $formattedDataDebit, $newFormat, $formattedOtherData) { $newCollection = []; foreach ($formattedDataCredit as $item) { $itemArray = $item->resolve(); if (!empty($itemArray['project'])) { foreach ($itemArray['project'] as $project) { $projectId = $project['id']; if (!isset($newCollection[$projectId])) { $newCollection[$projectId] = []; } $newCollection[$projectId][] = [ 'amount' => $project['payment']['amount'], 'total_extradition' => $project['total_extradition'], 'type' => 'credit', ]; } } } foreach ($formattedDataDebit as $item) { $itemArray = $item->resolve(); if (!empty($itemArray['project'])) { foreach ($itemArray['project'] as $project) { $projectId = $project['id']; if (!isset($newCollection[$projectId])) { $newCollection[$projectId] = []; } $newCollection[$projectId][] = [ 'amount' => $project['payment']['amount'], 'total_extradition' => $project['total_extradition'], 'type' => 'debit', ]; } } } Log::info('NewCOllect' . json_encode($newCollection)); $collection = []; $previousBalance = 0; foreach ($newCollection as $projectId => $records) { $income = 0; $expense = 0; foreach ($records as $key => $record) { if ((!is_object($record) && ($key == 'total_cash'))) { $income += $record; } if ((!is_object($record) && ($key == 'total_moving'))) { $expense += $record; } if ($record) { if ($record['type'] == ArticleTypeEnum::ARTICLE_TYPE_CREDIT->value) { $income += intval($record['amount']); } else { $expense += intval($record['amount']); } } } $startBalance = 0; $endBalance = $startBalance + $income - $expense; if (!isset($collection[$projectId])) { $collection[$projectId] = []; } $collection[$projectId] = [ 'start_balance' => $startBalance, 'end_balance' => $endBalance ]; $previousBalance = $endBalance; } return $collection; } public function totalAmountToProject($filters) { $query = PaymentDistribution::query(); $query->with(['payment', 'article']); $filters = array_filter($filters, function ($value) { return $value !== null; }); if (!empty($filters)) { 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['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']); }); } } $paymentDistributions = $query->get(); $result = []; foreach ($paymentDistributions as $item) { if ($item->article && $item->article->article_type == 'credit' && $item->article->id != 1) { $amount = floatval($item->amount); if (!isset($result[$item->project_id])) { $result[$item->project_id] = 0; } $result[$item->project_id] += $amount; } } return $result; } public function sortToProjectOtherData($filters, $check, $modelId) { $query = PaymentDistribution::query(); if ($check) { if (!empty($filters['date_from'])) { if (empty($filters['date_to'])) { $dateTo = Carbon::now(); } else { $dateTo = $filters['date_to']; } // Для moving и commission нужно учитывать actual_date $query->with(['payment' => function ($query) use ($filters, $dateTo) { $query->where(function ($q) use ($filters, $dateTo) { // Для moving: если есть actual_date, фильтруем по нему, иначе по payment_date $q->where(function ($qMoving) use ($filters, $dateTo) { $qMoving->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->where(function ($qActual) use ($filters, $dateTo) { $qActual->whereNotNull('actual_date') ->whereBetween('actual_date', [$filters['date_from'], $dateTo]); })->orWhere(function ($qPayment) use ($filters, $dateTo) { $qPayment->whereNull('actual_date') ->whereBetween('payment_date', [$filters['date_from'], $dateTo]); }); })->orWhere(function ($qOther) use ($filters, $dateTo) { // Для других типов - только payment_date $qOther->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) ->whereBetween('payment_date', [$filters['date_from'], $dateTo]); }); }); }]); } if (!empty($filters['cash'])) { $query->whereHas('payment', function ($query) use ($filters) { $query->whereIn('payment_type', $filters['cash']); }); } } else { $query->with('payment'); } $paymentDistributions = $query->get(); $projectCollection = []; foreach ($paymentDistributions as $distribution) { if ($distribution->payment->model_id == $modelId) { // Определяем дату для фильтрации $paymentDate = null; if ($distribution->payment->payment_type == PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) { // Для moving используем actual_date если есть, иначе payment_date $paymentDate = $distribution->payment->actual_date ?? $distribution->payment->payment_date; } else { $paymentDate = $distribution->payment->payment_date; } if (isset($paymentDate) && isset($distribution->project_id)) { $projectId = $distribution->project_id; if (!isset($projectCollection[$projectId])) { $projectCollection[$projectId] = [ 'total_cash' => 0, 'total_commission' => 0, 'total_moving' => 0 ]; } if (isset($distribution->comission)) { $projectCollection[$projectId]['total_commission'] += $distribution->comission; } if ($distribution->payment->payment_type == PaymentTypeEnum::PAYMENT_TYPE_MOVING->value) { // Используем cashbox для moving вместо amount if (isset($distribution->cashbox)) { $projectCollection[$projectId]['total_cash'] += $distribution->cashbox; } } if ((isset($distribution->cashbox)) && ($distribution->payment->payment_type == PaymentTypeEnum::PAYMENT_TYPE_MOVING->value)) { $projectCollection[$projectId]['total_moving'] += $distribution->cashbox; } } } } if ($check) { foreach ($projectCollection as $projectId => $items) { if (($items['total_cash'] == 0) && ($items['total_commission'] == 0) && ($items['total_moving'] == 0)) { unset($projectCollection[$projectId]); } } } return $projectCollection; } public function getProjectShow($modelId, $projectId, $articleId, $filters) { $query = Project::query() ->where('model_id', $modelId); if (!empty($filters['projects'])) { $query->whereIn('id', $filters['projects']); } $query->with([ 'paymentDistributions' => function ($pdQuery) use ($articleId, $filters) { $pdQuery->where('article_id', $articleId); $pdQuery->whereHas('payment', function ($paymentQuery) use ($filters) { if (isset($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = $filters['date_to'] ?? Carbon::now(); $paymentQuery->whereBetween('payment_date', [$dateFrom, $dateTo]); } if (!empty($filters['accounts'])) { $paymentQuery->whereIn('account_id', $filters['accounts']); } if (!empty($filters['payments_made'])) { $paymentQuery->whereIn('status', $filters['payments_made']); } if (!empty($filters['cash'])) { $paymentQuery->whereIn('payment_type', $filters['cash']); } }); }, 'paymentDistributions.project', 'paymentDistributions.payment.contragent', 'paymentDistributions.article' ]); $project = $query->find($projectId); $counterparties = $this->cashFlowService->getProjectCounterparties($project); $project->counterparties = $counterparties; return $project; } public function getArticleGroupProjectShow($modelId, $projectId, $articleGroupId, $filters) { $query = Project::query() ->where('model_id', $modelId); if (!empty($filters['projects'])) { $query->whereIn('id', $filters['projects']); } $query->with([ 'paymentDistributions' => function ($query) use ($articleGroupId, $filters) { $query->whereHas('article', function ($query) use ($articleGroupId) { $query->where('article_group_id', $articleGroupId); }); if (isset($filters['date_from'])) { $dateFrom = $filters['date_from']; $dateTo = $filters['date_to'] ?? Carbon::now(); $query->whereHas('payment', function ($query) use ($dateFrom, $dateTo) { $query->whereBetween('payment_date', [$dateFrom, $dateTo]); }); } if (!empty($filters['accounts'])) { $query->whereHas('payment', function ($query) use ($filters) { $query->whereIn('account_id', $filters['accounts']); }); } 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']); }); } }, 'paymentDistributions.project', 'paymentDistributions.payment.contragent', 'paymentDistributions.article' => function ($query) use ($articleGroupId) { $query->where('article_group_id', $articleGroupId); } ]); $project = $query->find($projectId); $counterparties = $this->cashFlowService->getProjectCounterparties($project); $project->counterparties = $counterparties; return $project; } public function sortToProject($paymentDistributionsCredit, $type, $check) { if ($type) { return CashFlowProjectCreditResource::collection($paymentDistributionsCredit); } else { return CashFlowProjectCreditResource::collection($paymentDistributionsCredit); } } public function getIncomeAndExpensesToProjectShow($modelId, $type, $projectId) { $query = PaymentDistribution::query(); $query->where('project_id', $projectId); switch ($type) { case 'credit': $query->with(['article' => function ($query) use ($modelId) { $query->where([ 'article_type' => ArticleTypeEnum::ARTICLE_TYPE_CREDIT->value, 'model_id' => $modelId ]); }, 'payment.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(); } }