ultimatepos/Modules/Maintenance/Services/MaintenanceAccountingService.php

133 lines
5.4 KiB
PHP

<?php
namespace Modules\Maintenance\Services;
use App\Business;
use App\Utils\Util;
use Illuminate\Support\Facades\DB;
use Modules\Accounting\Entities\AccountingAccountsTransaction;
use Modules\Accounting\Entities\AccountingAccTransMapping;
use Modules\Maintenance\Exceptions\MaintenanceAccountingException;
use Modules\Maintenance\Models\WorkOrder;
use Modules\Maintenance\Utils\MaintenanceUtil;
class MaintenanceAccountingService
{
public function __construct(
protected MaintenanceUtil $maintenanceUtil,
protected Util $util
) {}
public function postWorkOrderIfCompleted(WorkOrder $workOrder, int $businessId, int $userId): void
{
if ($workOrder->status !== 'completed' || $workOrder->accounting_journal_mapping_id) {
return;
}
if (! class_exists(AccountingAccTransMapping::class)) {
return;
}
if (! $this->maintenanceUtil->isAccountingEnabled($businessId)) {
return;
}
$settings = $this->maintenanceUtil->getMaintenanceSettings($businessId);
if (empty($settings['auto_post_journal'])) {
return;
}
$expenseAccountId = $settings['expense_account_id'] ?? null;
$paymentAccountId = $settings['payment_account_id'] ?? null;
if (empty($expenseAccountId) || empty($paymentAccountId)) {
throw new MaintenanceAccountingException('Maintenance accounting accounts are not configured.');
}
$amount = (float) $workOrder->cost;
if ($amount <= 0) {
return;
}
DB::transaction(function () use ($workOrder, $businessId, $userId, $expenseAccountId, $paymentAccountId, $amount) {
if (class_exists(\Modules\Accounting\Services\FinancialPostingService::class)) {
$postingService = app(\Modules\Accounting\Services\FinancialPostingService::class);
$entityResolution = app(\Modules\Accounting\Services\HoldingEntityResolutionService::class);
$locationId = optional($workOrder->equipment)->branch_id ?? null;
$holdingEntityId = $entityResolution->resolveFromLocation($businessId, $locationId ? (int) $locationId : null);
$request = new \Modules\Accounting\Domain\FinancialPostingRequest(
businessId: $businessId,
userId: $userId,
sourceType: 'maintenance_work_order',
sourceId: $workOrder->id,
note: 'هزینه دستور کار نگهداری: '.$workOrder->work_order_number,
lines: [
['accounting_account_id' => $expenseAccountId, 'amount' => $amount, 'type' => 'debit', 'holding_entity_id' => $holdingEntityId],
['accounting_account_id' => $paymentAccountId, 'amount' => $amount, 'type' => 'credit', 'holding_entity_id' => $holdingEntityId],
],
operationDate: ($workOrder->completed_at ?? now())->toDateTimeString(),
holdingEntityId: $holdingEntityId,
);
$mapping = $postingService->post($request);
if (! $mapping?->id) {
throw new MaintenanceAccountingException('Maintenance journal posting returned no mapping.');
}
$workOrder->update(['accounting_journal_mapping_id' => $mapping->id]);
return;
}
$mapping = new AccountingAccTransMapping();
$mapping->business_id = $businessId;
$mapping->ref_no = $this->generateRefNo($businessId);
$mapping->note = 'هزینه دستور کار نگهداری: '.$workOrder->work_order_number;
$mapping->type = 'journal_entry';
$mapping->created_by = $userId;
$mapping->operation_date = $workOrder->completed_at ?? now();
$mapping->save();
$operationDate = $mapping->operation_date;
AccountingAccountsTransaction::create([
'accounting_account_id' => $expenseAccountId,
'amount' => $amount,
'type' => 'debit',
'sub_type' => 'journal_entry',
'created_by' => $userId,
'operation_date' => $operationDate,
'acc_trans_mapping_id' => $mapping->id,
]);
AccountingAccountsTransaction::create([
'accounting_account_id' => $paymentAccountId,
'amount' => $amount,
'type' => 'credit',
'sub_type' => 'journal_entry',
'created_by' => $userId,
'operation_date' => $operationDate,
'acc_trans_mapping_id' => $mapping->id,
]);
$workOrder->update(['accounting_journal_mapping_id' => $mapping->id]);
});
}
protected function generateRefNo(int $businessId): string
{
$accountingUtil = class_exists(\Modules\Accounting\Utils\AccountingUtil::class)
? app(\Modules\Accounting\Utils\AccountingUtil::class)
: null;
$settings = $accountingUtil
? $accountingUtil->getAccountingSettings($businessId)
: [];
$refCount = $this->util->setAndGetReferenceCount('journal_entry');
$prefix = $settings['journal_entry_prefix'] ?? 'MJ-';
return $this->util->generateReferenceNumber('journal_entry', $refCount, $businessId, $prefix);
}
}