CaiWuXiTong/modules/EcommerceFinance/Services/FinanceLedgerAccountCreator.php

167 lines
6.9 KiB
PHP

<?php
namespace Modules\EcommerceFinance\Services;
use App\Utilities\FinanceLedgerAccountStatus;
use App\Utilities\FinanceLedgerAccountShouldKeep;
use App\Utilities\FinanceLedgerAccountType;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
/**
* 在账户总表中新增一个财务台账账户,并在公司不存在时同步建立公司台账。
*/
class FinanceLedgerAccountCreator
{
public function create(array $data): array
{
$connection = DB::connection((string) config('upstream_mirrors.connection', 'business_mirror'));
$companyName = $this->text($data['company_name'] ?? '');
$accountShort = $this->text($data['account_short'] ?? '');
$accountNo = $this->text($data['account_no'] ?? '');
$accountType = $this->text($data['account_type'] ?? '');
$companyPlan = $this->text($data['company_plan'] ?? '');
$companyFields = [
'register_place' => $this->nullableText($data['company_register_place'] ?? null),
'business_type' => $this->nullableText($data['company_business_type'] ?? null),
'tax_type' => $this->nullableText($data['company_tax_type'] ?? null),
'status' => $this->nullableText($data['company_status'] ?? null),
'basic_bank' => $this->nullableText($data['company_basic_bank'] ?? null),
'basic_account_last4' => $this->nullableText($data['company_basic_account_last4'] ?? null),
'remark' => $this->nullableText($data['company_remark'] ?? null),
];
$openingDate = (string) ($data['opening_date'] ?? now()->toDateString());
$openingBalance = round((float) ($data['opening_balance'] ?? 0), 2);
$status = FinanceLedgerAccountStatus::normalize((string) ($data['status'] ?? ''));
$accountShouldKeep = FinanceLedgerAccountShouldKeep::normalize(
(string) ($data['account_should_keep'] ?? ''),
);
$accountLast4 = FinanceLedgerAccountType::last4($accountType, $accountNo);
$normal = $status === FinanceLedgerAccountStatus::NORMAL;
$now = now();
return $connection->transaction(function () use (
$connection,
$companyName,
$accountShort,
$accountNo,
$accountType,
$companyPlan,
$companyFields,
$openingDate,
$openingBalance,
$status,
$accountShouldKeep,
$accountLast4,
$normal,
$data,
$now,
): array {
if ($connection->table('fin_accounts')->where('account_short', $accountShort)->exists()) {
throw ValidationException::withMessages([
'account_short' => '账户简称已存在,请改用其他简称或直接编辑现有账户。',
]);
}
$company = $connection->table('fin_companies')->where('name', $companyName)->first(['id']);
$companyCreated = $company === null;
$companyUpdated = false;
if ($companyCreated) {
$connection->table('fin_companies')->insert([
'name' => $companyName,
...$companyFields,
'created_at' => $now,
'updated_at' => $now,
]);
} else {
$providedCompanyFields = array_filter(
$companyFields,
static fn (?string $value): bool => $value !== null,
);
if ($providedCompanyFields !== []) {
$connection->table('fin_companies')
->where('id', $company->id)
->update([
...$providedCompanyFields,
'updated_at' => $now,
]);
$companyUpdated = true;
}
}
$accountId = $connection->table('fin_accounts')->insertGetId([
'company_name' => $companyName,
'account_short' => $accountShort,
'region' => $this->nullableText($data['region'] ?? null),
'account_no' => $accountNo !== '' ? $accountNo : null,
'bank_name' => $this->nullableText($data['bank_name'] ?? null),
'bank_city_branch' => $this->nullableText($data['bank_city_branch'] ?? null),
'account_type' => $accountType !== '' ? $accountType : null,
'company_plan' => $companyPlan !== '' ? $companyPlan : null,
'account_should_keep' => $accountShouldKeep !== '' ? $accountShouldKeep : null,
'account_last4' => $accountLast4,
'current_balance' => $openingBalance,
'blocked_amount' => $normal ? 0 : $openingBalance,
'daily_available' => $normal ? $openingBalance : 0,
'created_at' => $now,
'updated_at' => $now,
]);
$connection->table('fin_account_opening')->insert([
'account_short' => $accountShort,
'opening_date' => $openingDate,
'opening_balance' => $openingBalance,
'remark' => '新增账户期初',
'created_at' => $now,
'updated_at' => $now,
]);
$connection->table('fin_daily_flows')->insert([
'flow_date' => $openingDate,
'company_name' => $companyName,
'account_short' => $accountShort,
'opening_balance' => $openingBalance,
'inflow' => 0,
'outflow' => 0,
'closing_balance' => $openingBalance,
'remark' => '新增账户期初',
'created_at' => $now,
'updated_at' => $now,
]);
if (! $normal) {
$connection->table('fin_account_statuses')->insert([
'account_short' => $accountShort,
'status' => $status,
'updated_by' => (string) user()->name,
'created_at' => $now,
'updated_at' => $now,
]);
}
return [
'id' => (int) $accountId,
'company_name' => $companyName,
'account_short' => $accountShort,
'company_created' => $companyCreated,
'company_updated' => $companyUpdated,
'status' => $status,
'opening_date' => $openingDate,
'opening_balance' => $openingBalance,
];
});
}
private function text(mixed $value): string
{
return preg_replace('/\s+/u', ' ', trim((string) $value)) ?? trim((string) $value);
}
private function nullableText(mixed $value): ?string
{
$text = $this->text($value);
return $text !== '' ? $text : null;
}
}