Mahdee Rajon
File "CashFlowService.php"
Full Path: /var/www/html/back/app/Services/CashFlowService.php
File size: 58.28 KB
MIME-type: text/x-php
Charset: utf-8
<?php
declare(strict_types=1);
namespace App\Services;
use App\Domain\Article\Enums\ArticleTypeEnum;
use App\Domain\Payment\Enums\PaymentStatusEnum;
use App\Domain\Payment\Enums\PaymentTypeEnum;
use App\Exports\PaymentsExport;
use App\Http\Resources\CashFlowCreditResource;
use App\Http\Resources\CashFlowDebitResource;
use App\Http\Resources\CashFlowProjectCreditResource;
use App\Http\Resources\ShowUndistributedPaymentsByCounterpartyResource;
use App\Models\Article;
use App\Models\ArticleGroup;
use App\Models\Counterparty;
use App\Models\Payment;
use App\Models\PaymentDistribution;
use App\Repositories\CashFlowIndex\Interfaces\PaymentDistributionsRepositoryInterface;
use App\Repositories\CashFlowIndex\Interfaces\TotalAmountRepositoryInterface;
use App\Responses\ResponseDto;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Facades\Excel;
class CashFlowService
{
private $distributionsRepository;
private $paymentRepository;
public function __construct(PaymentDistributionsRepositoryInterface $paymentDistributionsRepository, TotalAmountRepositoryInterface $paymentRepository)
{
$this->distributionsRepository = $paymentDistributionsRepository;
$this->paymentRepository = $paymentRepository;
}
public function getIncomeAndExpensesShow($modelId, $type, $filters)
{
$query = PaymentDistribution::query();
$filters = array_filter($filters, function ($value) {
return $value !== null;
});
$query->where('cashbox', null);
if (!empty($filters)) {
if (!empty($filters['date_from'])) {
$dateFrom = $filters['date_from'];
$dateTo = empty($filters['date_to']) ? Carbon::now() : $filters['date_to'];
$query->whereHas('payment', function ($paymentFilterQuery) use ($dateFrom, $dateTo) {
$paymentFilterQuery->whereBetween('payment_date', [$dateFrom, $dateTo]);
});
}
if (!empty($filters['projects'])) {
$query->whereIn('project_id', $filters['projects']);
}
$query->whereHas('payment', function ($paymentFilterQuery) use ($filters) {
if (!empty($filters['accounts'])) {
$paymentFilterQuery->whereIn('account_id', $filters['accounts']);
}
if (!empty($filters['payments_made'])) {
$paymentFilterQuery->whereIn('status', $filters['payments_made']);
}
if (!empty($filters['cash'])) {
$paymentFilterQuery->whereIn('payment_type', $filters['cash']);
}
$paymentFilterQuery->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value)
->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value);
});
}
$query->with(['payment' => function ($paymentQuery) use ($filters) {
if (!empty($filters['date_from'])) {
$dateFrom = $filters['date_from'];
$dateTo = empty($filters['date_to']) ? Carbon::now() : $filters['date_to'];
$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']);
}
$paymentQuery->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value)
->with('contragent');
}]);
switch ($type) {
case 'credit':
$query->with(['article' => function ($query) use ($modelId) {
$query->where('id', '!=', 1)
->where([
'article_type' => ArticleTypeEnum::ARTICLE_TYPE_CREDIT->value,
'model_id' => $modelId
]);
}])->whereHas('article', function ($query) use ($modelId) {
$query->where('id', '!=', 1)
->where([
'article_type' => ArticleTypeEnum::ARTICLE_TYPE_CREDIT->value,
'model_id' => $modelId
]);
});
break;
case 'debit':
$query->with(['article' => function ($query) use ($modelId) {
$query->where('id', '!=', 1)
->where([
'article_type' => ArticleTypeEnum::ARTICLE_TYPE_DEBIT->value,
'model_id' => $modelId
]);
}])->whereHas('article', function ($query) use ($modelId) {
$query->where('id', '!=', 1)
->where([
'article_type' => ArticleTypeEnum::ARTICLE_TYPE_DEBIT->value,
'model_id' => $modelId
]);
});
break;
default:
break;
}
return $query->get();
}
public function getCashIncomeShow($modelId)
{
$query = PaymentDistribution::query()
->whereHas('payment', function ($query) use ($modelId) {
$query
->where('model_id', $modelId)
->where('status', PaymentStatusEnum::STATUS_RECEIVED->value)
->whereIn('payment_type', [
PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value,
PaymentTypeEnum::PAYMENT_TYPE_MOVING->value,
]);
})
->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 getReceptionIncomeShow($modelId, $statuses)
{
$query = PaymentDistribution::query()
->whereHas('payment', function ($query) use ($modelId, $statuses) {
$query
->where('model_id', $modelId)
->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value);
if (!empty($statuses)) {
$query->whereIn('status', $statuses);
}
})
->with([
'payment.contragent',
'article',
]);
$collection = $query->get();
$collection->each(function ($distribution) {
$distribution->amount = $distribution->cashbox ?? $distribution->amount;
});
return $collection;
}
public function getUndistributedIncomeShow($modelId, $paymentsMade)
{
$query = PaymentDistribution::query()
->whereHas('payment', function ($query) use ($modelId, $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);
}
})
->with([
'payment.contragent',
'article',
]);
$collection = $query->get();
return $collection;
}
public function getIssueanceShow($modelId)
{
$query = PaymentDistribution::query()
->whereHas('payment', function ($query) use ($modelId) {
$query
->where('model_id', $modelId)
->where('status', PaymentStatusEnum::STATUS_RECEIVED->value)
->whereIn('payment_type', [
PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value,
PaymentTypeEnum::PAYMENT_TYPE_PAYMENT->value,
]);
})
->with([
'payment.contragent',
'article',
]);
$collection = $query->get();
$collection->each(function ($distribution) {
if (
in_array(
$distribution->payment->payment_type,
[
PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value,
PaymentTypeEnum::PAYMENT_TYPE_PAYMENT->value,
],
true
)
) {
$distribution->amount = $distribution->cashbox ?? $distribution->amount;
}
});
return $collection;
}
public function getTotalCash($filters, $modelId)
{
$query = PaymentDistribution::query();
if (!empty($filters['projects'])) {
$query->whereIn('project_id', $filters['projects']);
}
$query->whereHas('payment', function ($paymentQuery) use ($filters, $modelId) {
$paymentQuery->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value)
->where('model_id', $modelId);
if (!empty($filters['date_from'])) {
$dateFrom = $filters['date_from'];
$dateTo = !empty($filters['date_to']) ? $filters['date_to'] : Carbon::now()->toDateString();
$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']);
}
});
$query->with(['payment' => function ($q) use ($modelId) {
$q->where('model_id', $modelId)
->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value);
}]);
$distributions = $query->get();
$totalCash = $distributions->sum(function ($distribution) use ($modelId) {
return (float)($distribution->amount ?? 0);
});
$totalCash += $this->getTotalCashFromMoving($filters, $modelId);
return $totalCash;
}
public function getTotalCashFromMoving($filters, $modelId)
{
$query = PaymentDistribution::query();
$query->whereNotNull('cashbox');
$query->whereHas('payment', function ($paymentQuery) use ($modelId, $filters) {
$paymentQuery->where('model_id', $modelId)
->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value)
->where('status', PaymentStatusEnum::STATUS_RECEIVED->value)
->whereNotNull('actual_date');
if (!empty($filters['date_from'])) {
$dateFrom = $filters['date_from'];
$dateTo = $filters['date_to'] ?? Carbon::now()->toDateString();
$paymentQuery->whereBetween('actual_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']);
}
});
if (!empty($filters['projects'])) {
$query->whereIn('project_id', $filters['projects']);
}
$query->with(['payment' => function ($q) use ($modelId) {
$q->where('model_id', $modelId)
->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value)
->where('status', PaymentStatusEnum::STATUS_RECEIVED->value)
->whereNotNull('actual_date');
}]);
$distributions = $query->get();
return $distributions->sum(function ($distribution) {
return (float)($distribution->cashbox ?? 0);
});
}
public function getOtherDataShow($modelId, $type, $filters)
{
$baseQuery = function ($query) {
$query->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 ($baseQuery, $modelId, $filters) {
$query->where(['payment_type' => PaymentTypeEnum::PAYMENT_TYPE_MOVING->value, 'model_id' => $modelId]);
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, $filters) {
$query->where(['payment_type' => PaymentTypeEnum::PAYMENT_TYPE_MOVING->value, 'model_id' => $modelId]);
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;
case 'commission':
$query->where('comission', '!=', null)
->with(['payment' => function ($query) use ($baseQuery, $modelId, $filters) {
$query->where('model_id', $modelId);
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 ($qMoving) use ($dateFrom, $dateTo) {
$qMoving->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value)
->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]);
});
})->orWhere(function ($qOther) use ($dateFrom, $dateTo) {
$qOther->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value)
->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, $filters) {
$query->where('model_id', $modelId);
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 ($qMoving) use ($dateFrom, $dateTo) {
$qMoving->where('payment_type', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value)
->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]);
});
})->orWhere(function ($qOther) use ($dateFrom, $dateTo) {
$qOther->where('payment_type', '!=', PaymentTypeEnum::PAYMENT_TYPE_MOVING->value)
->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;
case 'cash':
$query->where('cashbox', '!=', null)
->with(['payment' => function ($query) use ($baseQuery, $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->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, $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->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;
case 'cash-credit':
$query->with(['payment' => function ($query) use ($baseQuery, $modelId, $filters) {
$query->where(function ($q) use ($modelId, $filters) {
$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');
});
});
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, $filters) {
$query->where(function ($q) use ($modelId) {
$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');
});
});
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 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->sumTotalAmount($paymentDistributionsCredit);
$totalDebit = $this->sumTotalAmount($paymentDistributionsDebit);
$formattedToProjectCredit = $this->sortToProject($paymentDistributionsCredit, $credit = true);
$formattedToProjectDebit = $this->sortToProject($paymentDistributionsDebit, $credit = false);
$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->getTotalCash($filters, $modelID);
return new ResponseDto(
data: [
'credit' => [
'static' => [
'total_amount' => $totalCredit + $totalAmountCreditPayment,
'articles' => CashFlowCreditResource::collection($paymentDistributionsCredit),
'not_distribution_payments_total_amount' => $totalAmountCreditPayment,
'other_data' => [
'total_cash' => $totalCash,
],
],
'dynamic' => [
'projects' => $formattedToProjectCredit,
],
],
'debit' => [
'static' => [
'total_amount' => $totalDebit + $totalAmountDebitPayment,
'articles' => CashFlowDebitResource::collection($paymentDistributionsDebit),
'not_distribution_payments_total_amount' => $totalAmountDebitPayment,
'other_data' => [
'moving' => $totalMoving,
'commission' => $totalAmountCashDebitCommissionPayment,
'cash' => $totalAmountDebitCashPayment,
],
],
'dynamic' => [
'projects' => $formattedToProjectDebit,
],
],
],
status: true
);
}
public function getShowArticlesGroup($modelId, $articleGroupId, $filters)
{
$query = ArticleGroup::query()
->where('model_id', $modelId)
->where('id', $articleGroupId);
$articlesCallback = function ($query) use ($filters) {
$query->has('paymentDistributions')->with([
'paymentDistributions' => function ($query) use ($filters) {
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 ($filters) {
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 sortToProject($paymentDistributionsCredit, $type)
{
if ($type) {
return CashFlowProjectCreditResource::collection($paymentDistributionsCredit);
} else {
return CashFlowProjectCreditResource::collection($paymentDistributionsCredit);
}
}
public function getArticleShow($modelId, $articleId, $filters)
{
$query = Article::query()
->where('model_id', $modelId)
->where('id', $articleId);
$applyPaymentFilters = function ($query) use ($filters) {
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->with('contragent');
}
]);
$article = $query->first();
$counterparties = $this->getUniqueCounterparties($article);
$article->counterparties = $counterparties;
return $article;
}
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 getProjectCounterparties($project)
{
return $project->paymentDistributions
->filter(fn ($pd) => $pd->payment && $pd->payment->contragent)
->groupBy(fn ($pd) => $pd->payment->contragent->id)
->map(function ($distributions) {
$counterparty = $distributions->first()->payment->contragent;
$counterparty->payments = $distributions->map(fn ($pd) => $pd->payment);
$counterparty->total_amount = $distributions->sum('amount');
return $counterparty;
})
->values();
}
public function getUniqueCounterpariesToPayment($data)
{
$counterpartyIds = collect();
$paymentsIds = collect();
$data->each(function ($item) use (&$counterpartyIds, &$paymentsIds) {
if ($item->payment) {
$counterpartyIds->push($item->payment->counterparty_id);
$paymentsIds->push($item->payment->id);
}
});
$counterpartyIds = $counterpartyIds->unique();
$paymentsIds = $paymentsIds->unique();
$counterparties = Counterparty::query()
->whereIn('id', $counterpartyIds)
->with(['payments' => function ($query) use ($paymentsIds) {
$query->whereIn('id', $paymentsIds);
}])
->get();
return $counterparties;
}
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 getPaymentsMade($paymentsMadeInput)
{
$mapping = [
'draft' => [
PaymentStatusEnum::STATUS_DRAFT->value,
PaymentStatusEnum::STATUS_FINALIZE->value,
PaymentStatusEnum::STATUS_FINALIZE_ONE_TWO->value,
PaymentStatusEnum::STATUS_FINALIZE_TWO_TWO->value,
],
'approve' => [
PaymentStatusEnum::STATUS_APPROVE->value,
PaymentStatusEnum::STATUS_AGREE_ONE_TWO->value,
PaymentStatusEnum::STATUS_AGREE_TWO_TWO->value,
],
'awaiting_payment' => [
PaymentStatusEnum::STATUS_PAY->value,
PaymentStatusEnum::STATUS_ISSUE->value,
],
'paid' => [
PaymentStatusEnum::STATUS_PAID->value,
],
'verified' => [
PaymentStatusEnum::STATUS_RECEIVED->value,
PaymentStatusEnum::STATUS_ISSUED->value,
],
'awaiting_deposit' => [
PaymentStatusEnum::STATUS_SENT->value,
PaymentStatusEnum::STATUS_MOVING->value,
],
];
$paymentsMade = [];
if (isset($paymentsMadeInput)) {
if (is_array($paymentsMadeInput)) {
foreach ($paymentsMadeInput as $input) {
if (isset($mapping[$input])) {
$paymentsMade = array_merge($paymentsMade, $mapping[$input]);
}
}
$paymentsMade = array_unique($paymentsMade);
} elseif (isset($mapping[$paymentsMadeInput])) {
$paymentsMade = $mapping[$paymentsMadeInput];
}
}
return array_values($paymentsMade);
}
public function getPaymentsMadeForApi(array $input): array
{
return array_values(array_unique($input));
}
public function getScoreAndCashFilter($scoreAndCashInput)
{
$paymentTypes = [];
if (isset($scoreAndCashInput)) {
if ($scoreAndCashInput == 'cash') {
$paymentTypes = [
PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value
];
} elseif ($scoreAndCashInput == 'score') {
$paymentTypes = [
PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value,
PaymentTypeEnum::PAYMENT_TYPE_PAYMENT->value,
PaymentTypeEnum::PAYMENT_TYPE_MOVING->value,
];
} elseif ($scoreAndCashInput == 'score_and_cash') {
$paymentTypes = [
PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value,
PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value,
PaymentTypeEnum::PAYMENT_TYPE_PAYMENT->value,
PaymentTypeEnum::PAYMENT_TYPE_MOVING->value
];
}
}
return $paymentTypes;
}
public function getFilter($projectsInput)
{
if (is_array($projectsInput)) {
$flattened = array_reduce($projectsInput, function ($carry, $item) {
if (is_string($item)) {
$carry = array_merge($carry, explode(',', $item));
} elseif (is_array($item)) {
$carry = array_merge($carry, $item);
} elseif ($item !== null) {
$carry[] = $item;
}
return $carry;
}, []);
return array_filter(array_map('trim', $flattened), 'is_numeric');
} elseif (is_string($projectsInput)) {
return array_filter(array_map('trim', explode(',', $projectsInput)), 'is_numeric');
} elseif ($projectsInput !== null) {
return [(string)$projectsInput];
}
}
public function excelExport($ids)
{
$export = new PaymentsExport(Payment::whereHas('distributions', function ($query) use ($ids): void {
$query->whereIn('article_id', $ids);
}), $ids);
$filename = 'payments-' . date('Y-m-d-H-i-s') . '.xlsx';
Excel::store($export, $filename, 'public');
return $filename;
}
public function moveArticleOrArticleGroupInCashFlow($articleId, $newLine, $articleGroupId): void
{
if (isset($articleId) && isset($newLine)) {
$article = Article::find($articleId);
if (!$article) {
return;
}
DB::transaction(function () use ($article, $newLine, $articleGroupId) {
$oldGroupId = $article->article_group_id;
$oldSort = $article->sort;
if ($oldGroupId == (int)$articleGroupId) {
if ($oldSort == $newLine) {
$this->sortArticleAfterCreated($article->article_type, $articleGroupId, $newLine, $article);
}
if ($oldSort < $newLine) {
$this->decrementSortArticleInGroup($article->article_type, $articleGroupId, $oldSort, $newLine);
} else {
$this->incrementSortArticleInGroup($article->article_type, $articleGroupId, $oldSort, $newLine);
}
} else {
$query = Article::where('article_type', $article->article_type);
if ($articleGroupId === null) {
$query->whereNull('article_group_id');
} else {
$query->where('article_group_id', $articleGroupId);
}
$query->where('sort', '>=', $newLine)
->increment('sort');
$this->sortArticleInGroupAfterDelete($oldGroupId, $oldSort);
}
$article->update([
'article_group_id' => $articleGroupId,
'sort' => $newLine
]);
});
}
if (isset($articleGroupId) && isset($newLine)) {
$articleGroup = ArticleGroup::find($articleGroupId);
if (!$articleGroup) {
return;
}
DB::transaction(function () use ($articleGroup, $newLine) {
$where = [
'article_type' => $articleGroup->article_type,
'sort' => $newLine,
];
$prevArticle = Article::where('article_group_id', $articleGroup->article_group_id)
->where($where)
->first();
if ($prevArticle) {
$prevArticle->update(['sort' => $articleGroup->sort]);
$articleGroup->update(['sort' => $newLine]);
} else {
$articleGroup->update(['sort' => $newLine]);
}
});
}
}
public function sumTotalExtradition($articleDebit)
{
$totalExtradition = 0.0;
foreach ($articleDebit as $item) {
foreach ($item->paymentDistributions as $distribution) {
$amount = (float)$distribution->amount;
if ($distribution->payment->payment_type == PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value) {
$totalExtradition += $amount;
}
}
}
return $totalExtradition;
}
public function sortArticleAfterCreated($articleType, $articleGroupId, $newLine, $article)
{
Article::where('article_type', $articleType)
->where('article_group_id', $articleGroupId)
->where('sort', '>=', $newLine)
->where('id', '!=', $article->id)
->increment('sort');
}
public function decrementSortArticleInGroup($articleType, $articleGroupId, $oldSort, $newLine)
{
return Article::where('article_type', $articleType)
->where('article_group_id', $articleGroupId)
->where('sort', '>', $oldSort)
->where('sort', '<=', $newLine)
->decrement('sort');
}
public function incrementSortArticleInGroup($articleType, $articleGroupId, $oldSort, $newLine)
{
return Article::where('article_type', $articleType)
->where('article_group_id', $articleGroupId)
->where('sort', '<', $oldSort)
->where('sort', '>=', $newLine)
->increment('sort');
}
public function sortArticleInGroupAfterDelete($oldGroupId, $oldSort)
{
return Article::where('article_group_id', $oldGroupId)
->where('sort', '>', $oldSort)
->decrement('sort');
}
public function sortArticleWithoutGroupAfterDelete($oldSort)
{
return Article::where('article_group_id', null)
->where('sort', '>', $oldSort)
->decrement('sort');
}
public function getUndistributedPayments($modelId, $type, $filters = [])
{
$query = Payment::query();
$query->where('model_id', $modelId);
switch ($type) {
case 'income':
$query->whereIn('payment_type', [
PaymentTypeEnum::PAYMENT_TYPE_RECEPTION_FROM_1C->value]);
if (!empty($filters['payments_made'])) {
$query->whereIn('status', $filters['payments_made']);
}
break;
case 'expenses':
$query->whereIn('payment_type', [
PaymentTypeEnum::PAYMENT_TYPE_PAYMENT->value,
PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value
]);
if (!empty($filters['payments_made'])) {
$query->whereIn('status', $filters['payments_made']);
}
break;
default :
break;
}
$this->applyPaymentDateFilter($query, $filters);
$query->with(['organization', 'contragent', 'creator', 'account']);
$query->whereHas('distributions', function ($subQuery) {
$subQuery->whereNull('article_id');
});
$payments = $query->get();
$counterparties = Counterparty::whereHas(
'payments',
function ($paymentQuery) use ($modelId, $type, $filters) {
$paymentQuery->where('model_id', $modelId);
switch ($type) {
case 'income':
$paymentQuery->whereIn('payment_type', [
PaymentTypeEnum::PAYMENT_TYPE_RECEPTION_FROM_1C->value
]);
break;
case 'expenses':
$paymentQuery->whereIn('payment_type', [
PaymentTypeEnum::PAYMENT_TYPE_PAYMENT->value,
PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value
]);
break;
default:
break;
}
if (!empty($filters['payments_made'])) {
$paymentQuery->whereIn('status', $filters['payments_made']);
}
$this->applyPaymentDateFilter($paymentQuery, $filters);
}
)->whereHas(
'payments.distributions',
function ($distributionQuery) {
$distributionQuery->whereNull('article_id');
}
)->with('payments.distributions')->get();
return [
'count' => $query->count(),
'total_amount' => $query->sum('amount'),
'data' => $payments,
'by_counterparty' => ShowUndistributedPaymentsByCounterpartyResource::make($counterparties),
];
}
public function applyPaymentDateFilter($query, $filters)
{
if (empty($filters['year'])) {
return;
}
$year = (int) $filters['year'];
$month = !empty($filters['month']) ? (int) $filters['month'] : null;
$day = !empty($filters['day']) ? (int) $filters['day'] : null;
$quarter = !empty($filters['quarter']) ? (int) $filters['quarter'] : null;
$query->whereYear('payment_date', $year);
if ($month && $day) {
$query->whereMonth('payment_date', $month)
->whereDay('payment_date', $day);
return;
}
if ($month) {
$query->whereMonth('payment_date', $month);
return;
}
if ($quarter) {
$quarters = [
1 => [1, 2, 3],
2 => [4, 5, 6],
3 => [7, 8, 9],
4 => [10, 11, 12],
];
if (isset($quarters[$quarter])) {
$query->whereIn(
DB::raw('EXTRACT(MONTH FROM payment_date)'),
$quarters[$quarter]
);
}
}
}
}