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; } }