<?php
namespace App\Repositories\Integrations;
use App\Domain\Payment\Enums\PaymentStatusEnum;
use App\Domain\Payment\Enums\PaymentTypeEnum;
use App\Domain\Payment\PaymentLogService;
use App\DTO\IntegrationPaymentDTO;
use App\Models\Account;
use App\Models\Counterparty;
use App\Models\Organization;
use App\Models\Payment;
use App\Repositories\Integrations\Interfaces\IntegrationInterface;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
class IntegrationRepository implements IntegrationInterface
{
protected PaymentLogService $paymentLogService;
public function __construct()
{
$this->paymentLogService = app()->make(PaymentLogService::class);
}
public function createDataInAccountDb($modelId, $account)
{
$searchAccount = null;
$organization = Organization::query()->where(['model_id' => $modelId, 'external_id' => $account['organization_id']])->first();
$searchAccount = Account::query()->where([
'model_id' => $modelId,
'external_id' => trim($account['id'])
])->first();
if (!$searchAccount) {
$searchAccount = Account::query()->where([
'model_id' => $modelId,
'number' => trim($account['number'])
])->first();
}
if ($searchAccount) {
$searchAccount->update(['external_id' => $account['id'],
'deposit' => $account['deposit'],
'bank_name' => $account['bank_name'],
'bank_bic' => $account['bank_bic'],
'bank_city' => $account['bank_city'],
// 'balance_of_the_date' => $account['balance_of_the_date'],
'cor_number' => $account['cor_number'],
'name' => $account['name'],
'added' => $account['added'],
'archived' => $account['archived'],
'current_balance' => $account['deposit'],
]);
return $searchAccount;
} else {
return Account::query()->create([
'external_id' => $account['id'],
'organization_id' => $organization->id,
'model_id' => $modelId,
'name' => $account['name'],
'archived' => $account['archived'],
'added' => $account['added'],
'balance_of_the_date' => $account['balance_of_the_date'],
'bank_name' => $account['bank_name'],
'bank_bic' => $account['bank_bic'],
'cor_number' => $account['cor_number'],
'number' => $account['number'],
'bank_city' => $account['bank_city'],
'deposit' => $account['deposit']
]);
}
}
public function createDataInCounterpartyDb($modelId, $counterparty)
{
$searchCounterparty = null;
$searchCounterparty = Counterparty::query()->where([
'model_id' => $modelId,
'external_id' => trim($counterparty['id'])
])->first();
if (!$searchCounterparty) {
$searchCounterparty = Counterparty::query()->where([
'model_id' => $modelId,
'inn' => trim($counterparty['inn'])
])->first();
}
if ($searchCounterparty) {
$searchCounterparty->update(['external_id' => $counterparty['id'],
'name' => $counterparty['name'],
'comment' => $counterparty['comment'],
'kpp' => $counterparty['kpp'],
'archived' => $counterparty['archived'],
]);
return $searchCounterparty;
} else {
return Counterparty::query()->create([
'external_id' => $counterparty['id'],
'model_id' => $modelId,
'name' => $counterparty['name'],
'archived' => $counterparty['archived'],
'inn' => $counterparty['inn'],
'kpp' => $counterparty['kpp'],
'comment' => $counterparty['comment'],
]);
}
}
public function createDataInOrganizationsDb($modelId, $organization)
{
$searchOrganization = null;
$searchOrganization = Organization::query()->where([
'model_id' => $modelId,
'external_id' => trim($organization['id'])
])->first();
if (!$searchOrganization) {
$searchOrganization = Organization::query()->where([
'model_id' => $modelId,
'inn' => trim($organization['inn'])
])->first();
}
if ($searchOrganization) {
$searchOrganization->update(['external_id' => $organization['id'],
'full_name' => $organization['fname'],
'short_name' => $organization['name'],
'kpp' => $organization['kpp'],
'archived' => $organization['archived'],
]);
return $searchOrganization;
} else {
return Organization::query()->create([
'model_id' => $modelId,
'external_id' => $organization['id'],
'full_name' => $organization['fname'],
'short_name' => $organization['name'],
'inn' => $organization['inn'],
'kpp' => $organization['kpp'],
'archived' => $organization['archived'],
]);
}
}
public function createDataInPaymentsDb($modelId, $payment)
{
return DB::transaction(function () use ($modelId, $payment) {
$paymentModel = null;
if (is_numeric($payment['id'])) {
$paymentModel = Payment::query()->find((int)$payment['id']);
}
if (is_string($payment['id'])) {
if (ctype_digit($payment['id'])) {
$paymentModel = Payment::query()
->where('external_id', $payment['id'])
->orWhere('id', (int)$payment['id'])
->first();
} else {
$paymentModel = Payment::query()
->where('external_id', $payment['id'])
->first();
}
}
if ($paymentModel) {
$original = $paymentModel->getOriginal();
$account = Account::query()->find($paymentModel->account_id);
$importAccount = Account::query()
->where([
'model_id' => $modelId,
'external_id' => $payment['account_id']
])
->first();
$status = match ($paymentModel->payment_type) {
PaymentTypeEnum::PAYMENT_TYPE_RECEPTION->value => PaymentStatusEnum::STATUS_RECEIVED->value,
PaymentTypeEnum::PAYMENT_TYPE_MOVING->value => PaymentStatusEnum::STATUS_MOVING->value,
PaymentTypeEnum::PAYMENT_TYPE_ISSUEANCE->value => PaymentStatusEnum::STATUS_ISSUED->value,
PaymentTypeEnum::PAYMENT_TYPE_PAYMENT->value => PaymentStatusEnum::STATUS_PAID->value,
default => PaymentStatusEnum::STATUS_SENT->value,
};
if ((!isset($account)) || (($account->number != $importAccount->number) && ($account->external_id != $importAccount->external_id))) {
$paymentModel->update(['account_id' => $importAccount->id]);
}
$paymentModel->update([
'status' => $status,
'amount' => $payment['amount'],
'payment_date' => $payment['date'],
'actual_date' => $payment['payment_date'],
'purpose_of_payment_1c' => $payment['appointment'] ?? 'Платеж из 1с',
'note_1c' => $payment['comment'] ?? '',
'account_debit_1c' => $importAccount->name ?? $account?->name ?? null,
]);
$distribution = $paymentModel->distributions()->first();
if ($distribution) {
$distribution->update(['amount' => $payment['amount']]);
}
$this->createLogPayment($paymentModel, $original);
} else {
$paymentDTO = IntegrationPaymentDTO::fromArray($modelId, $payment);
$account = $this->getAccountId($modelId, $payment['account_id']);
$counterpartyId = $this->getCounterpartyId($modelId, $payment['counterparty_id']);
$organizationId = $this->getOrganizationId($modelId, $payment['organization_id']);
$paymentData = $paymentDTO->toArray($account, $counterpartyId, $organizationId);
$paymentModel = Payment::query()->create($paymentData);
//КОСТЫЛЬ ))Привет разрабу, который это разгребает, это было сделано до меня
$paymentModel->distributions()->create([
'amount' => 0.00,
'amount_limit' => 0.00,
]);
$this->createLogPayment($paymentModel, null);
}
return $paymentModel;
});
}
public function createLogPayment($payment, $original)
{
if (!$original) {
$original = $payment->getOriginal();
}
$changes = [];
foreach ($payment->getAttributes() as $field => $newValue) {
$oldValue = $original[$field] ?? null;
if (($field == 'status') || ($field == 'amount') || ($field == 'name') || ($field == 'payment_date') || ($field == 'account_id')) {
if ($field == 'payment_date') {
$oldValue = Carbon::parse($oldValue)->toDateString();
$newValue = Carbon::parse($newValue)->toDateString();
}
if ($oldValue != $newValue) {
if ($field == 'account_id') {
if($oldValue != null) {
$oldValue = Account::query()->find($oldValue)->name;
}
$newValue = Account::query()->find($newValue)->name;
}
$changes[$field] = [(string)$oldValue ?? null, (string)$newValue];
}
}
}
if (!empty($changes)) {
$this->paymentLogService->store(
1,
$payment,
$original['status'] instanceof PaymentStatusEnum ? $original['status']->value : $payment['status'],
null,
'',
$changes
);
}
}
public function getOrganizationId($modelId, $organizationExternalId)
{
return Organization::query()->where(['model_id' => $modelId, 'external_id' => $organizationExternalId])->first()?->id;
}
public function getCounterpartyId($modelId, $counterpartyExternalId)
{
return Counterparty::query()->where(['model_id' => $modelId, 'external_id' => $counterpartyExternalId])->first()?->id;
}
public function getAccountId($modelId, $accountExternalId)
{
return Account::query()->where(['model_id' => $modelId, 'external_id' => $accountExternalId])->first();
}
}