File "ActiveTabProjectService.php"
Full Path: /var/www/html/back/app/Services/CashFlow/ActiveTabProjectService.php
File size: 25.57 KB
MIME-type: text/x-php
Charset: utf-8
<?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();
}
}