changes
This commit is contained in:
parent
f40c3d0f2e
commit
39dd3d4d8f
|
|
@ -182,7 +182,6 @@ public function updateContract(ClientCase $clientCase, string $uuid, UpdateContr
|
|||
$accountData = [];
|
||||
// Track old balance before applying changes
|
||||
$currentAccount = $contract->account; // newest (latestOfMany)
|
||||
$oldBalance = (float) optional($currentAccount)->balance_amount;
|
||||
if (! is_null($initial)) {
|
||||
$accountData['initial_amount'] = $initial;
|
||||
}
|
||||
|
|
@ -213,56 +212,6 @@ public function updateContract(ClientCase $clientCase, string $uuid, UpdateContr
|
|||
$created = $contract->account()->create($accountData);
|
||||
$freshBal = (float) optional($created->fresh())->balance_amount;
|
||||
}
|
||||
// If multiple historical accounts exist, log them and optionally propagate update to all to keep consistent
|
||||
$allAccounts = \DB::table('accounts')->where('contract_id', $contract->id)->orderBy('id')->get(['id','balance_amount','initial_amount']);
|
||||
if ($allAccounts->count() > 1 && array_key_exists('balance_amount', $accountData)) {
|
||||
// Propagate balance to all for consistency (comment out if not desired)
|
||||
\DB::table('accounts')->where('contract_id', $contract->id)->update(['balance_amount' => $accountData['balance_amount'], 'updated_at' => now()]);
|
||||
$freshBal = (float) \DB::table('accounts')->where('contract_id', $contract->id)->latest('id')->value('balance_amount');
|
||||
}
|
||||
try {
|
||||
$accountCount = $allAccounts->count();
|
||||
logger()->info('Contract account upsert', [
|
||||
'contract_id' => $contract->id,
|
||||
'request_initial' => $initial,
|
||||
'request_balance_present' => $balanceFieldPresent,
|
||||
'request_balance' => $balance,
|
||||
'request_account_type_id' => $request->input('account_type_id'),
|
||||
'account_data_applied' => $accountData,
|
||||
'old_balance' => $oldBalance,
|
||||
'new_balance_after_update' => $freshBal,
|
||||
'accounts_for_contract' => $accountCount,
|
||||
'accounts_snapshot' => $allAccounts,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
// ignore logging errors
|
||||
}
|
||||
|
||||
// After update/create, if balance_amount changed (and not through a payment), log an activity with before/after
|
||||
if (array_key_exists('balance_amount', $accountData)) {
|
||||
// Guard against null account (e.g., if creation failed silently earlier)
|
||||
$newAccount = $contract->account; // refreshed latest
|
||||
$newBalance = $newAccount ? (float) optional($newAccount->fresh())->balance_amount : $oldBalance;
|
||||
if ($newAccount && $newBalance !== $oldBalance) {
|
||||
try {
|
||||
$currency = optional(\App\Models\PaymentSetting::query()->first())->default_currency ?? 'EUR';
|
||||
$beforeStr = number_format($oldBalance, 2, ',', '.').' '.$currency;
|
||||
$afterStr = number_format($newBalance, 2, ',', '.').' '.$currency;
|
||||
$note = 'Sprememba stanja (Stanje pred: '.$beforeStr.', Stanje po: '.$afterStr.'; Izvor: sprememba)';
|
||||
\App\Models\Activity::create([
|
||||
'due_date' => null,
|
||||
'amount' => null,
|
||||
'note' => $note,
|
||||
'action_id' => null,
|
||||
'decision_id' => null,
|
||||
'client_case_id' => $contract->client_case_id,
|
||||
'contract_id' => $contract->id,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
// non-fatal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
@ -1376,6 +1325,8 @@ public function archiveContract(ClientCase $clientCase, string $uuid, Request $r
|
|||
$hasReactivateRule = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$executor = app(\App\Services\Archiving\ArchiveExecutor::class);
|
||||
$context = [
|
||||
'contract_id' => $contract->id,
|
||||
|
|
@ -1388,6 +1339,7 @@ public function archiveContract(ClientCase $clientCase, string $uuid, Request $r
|
|||
$overall = [];
|
||||
$hadAnyEffect = false;
|
||||
foreach ($settings as $setting) {
|
||||
dd($setting);
|
||||
$res = $executor->executeSetting($setting, $context, optional($request->user())->id);
|
||||
foreach ($res as $table => $count) {
|
||||
$overall[$table] = ($overall[$table] ?? 0) + $count;
|
||||
|
|
|
|||
|
|
@ -213,6 +213,14 @@ public function process(Import $import, ?Authenticatable $user = null): array
|
|||
$importRow = null;
|
||||
try {
|
||||
$rawAssoc = $this->buildRowAssoc($row, $header);
|
||||
// Skip entirely empty rows (all raw values blank/null after trimming) without creating an ImportRow
|
||||
if ($this->rowIsEffectivelyEmpty($rawAssoc)) {
|
||||
$skipped++;
|
||||
if ($isPg) {
|
||||
// No DB changes were made for this row; nothing to roll back explicitly.
|
||||
}
|
||||
continue; // proceed to next CSV row
|
||||
}
|
||||
[$recordType, $mapped] = $this->applyMappings($rawAssoc, $mappings);
|
||||
|
||||
// Determine row-level reactivation intent: precedence row > import > template
|
||||
|
|
@ -1083,7 +1091,11 @@ private function upsertAccount(Import $import, array $mapped, $mappings): array
|
|||
];
|
||||
foreach (['start_date', 'end_date', 'description', 'type_id'] as $k) {
|
||||
if (array_key_exists($k, $contractFields) && ! is_null($contractFields[$k])) {
|
||||
$newContractData[$k] = $contractFields[$k];
|
||||
$val = $contractFields[$k];
|
||||
if (in_array($k, ['start_date', 'end_date'], true)) {
|
||||
$val = $this->normalizeDate(is_scalar($val) ? (string) $val : null);
|
||||
}
|
||||
$newContractData[$k] = $val;
|
||||
}
|
||||
}
|
||||
$newContractData['start_date'] = $newContractData['start_date'] ?? now()->toDateString();
|
||||
|
|
@ -1422,6 +1434,12 @@ private function upsertContractChain(Import $import, array $mapped, $mappings):
|
|||
return ['action' => 'skipped', 'message' => 'No contract fields marked for insert'];
|
||||
}
|
||||
$data = array_filter($applyInsert, fn ($v) => ! is_null($v));
|
||||
if (array_key_exists('start_date', $data)) {
|
||||
$data['start_date'] = $this->normalizeDate(is_scalar($data['start_date']) ? (string) $data['start_date'] : null) ?? $data['start_date'];
|
||||
}
|
||||
if (array_key_exists('end_date', $data)) {
|
||||
$data['end_date'] = $this->normalizeDate(is_scalar($data['end_date']) ? (string) $data['end_date'] : null) ?? $data['end_date'];
|
||||
}
|
||||
$data['client_case_id'] = $clientCaseId;
|
||||
$data['reference'] = $reference;
|
||||
// ensure required defaults
|
||||
|
|
@ -1441,6 +1459,39 @@ private function sanitizeHeaderName(string $v): string
|
|||
return trim($v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a raw date string coming from import sources to Y-m-d or null.
|
||||
* Accepts common European formats like d.m.Y / d.m.y / d/m/Y / d/m/y and ISO.
|
||||
* Falls back to strtotime parsing; returns null on failure instead of throwing.
|
||||
*/
|
||||
private function normalizeDate(?string $raw): ?string
|
||||
{
|
||||
if ($raw === null) {
|
||||
return null;
|
||||
}
|
||||
$raw = trim($raw);
|
||||
if ($raw === '') {
|
||||
return null;
|
||||
}
|
||||
$candidates = ['d.m.Y', 'd.m.y', 'd/m/Y', 'd/m/y', 'Y-m-d'];
|
||||
foreach ($candidates as $fmt) {
|
||||
$dt = \DateTime::createFromFormat($fmt, $raw);
|
||||
if ($dt instanceof \DateTime) {
|
||||
// Reject invalid (createFromFormat returns false on mismatch; partial matches handled by checking errors)
|
||||
$errors = \DateTime::getLastErrors();
|
||||
if (($errors['warning_count'] ?? 0) === 0 && ($errors['error_count'] ?? 0) === 0) {
|
||||
return $dt->format('Y-m-d');
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fallback: strtotime (very permissive); if fails return null
|
||||
$ts = @strtotime($raw);
|
||||
if ($ts === false) {
|
||||
return null;
|
||||
}
|
||||
return date('Y-m-d', $ts);
|
||||
}
|
||||
|
||||
private function findSourceColumnFor($mappings, string $targetField): ?string
|
||||
{
|
||||
foreach ($mappings as $map) {
|
||||
|
|
@ -1627,6 +1678,29 @@ private function collectPaymentAppliedFields(array $payload, \App\Models\Payment
|
|||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a raw CSV row is "effectively" empty: all scalar values are null or blank after trimming.
|
||||
* Non-scalar values (arrays/objects) will cause the row to be treated as non-empty.
|
||||
*/
|
||||
private function rowIsEffectivelyEmpty(array $rawAssoc): bool
|
||||
{
|
||||
if (empty($rawAssoc)) {
|
||||
return true; // no columns at all
|
||||
}
|
||||
foreach ($rawAssoc as $v) {
|
||||
if (is_array($v) || is_object($v)) {
|
||||
return false; // treat structured data as content
|
||||
}
|
||||
if (! is_null($v)) {
|
||||
$s = trim((string) $v);
|
||||
if ($s !== '') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure mapping roots are recognized; fail fast if unknown roots found.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user