diff --git a/app/Http/Controllers/Barobill/EcardController.php b/app/Http/Controllers/Barobill/EcardController.php index 1a410f5f..93acede8 100644 --- a/app/Http/Controllers/Barobill/EcardController.php +++ b/app/Http/Controllers/Barobill/EcardController.php @@ -7,6 +7,7 @@ use App\Models\Barobill\BarobillConfig; use App\Models\Barobill\BarobillMember; use App\Models\Barobill\CardTransaction; +use App\Models\Barobill\CardTransactionAmountLog; use App\Models\Barobill\CardTransactionSplit; use App\Models\Tenants\Tenant; use Illuminate\Http\JsonResponse; @@ -654,6 +655,16 @@ private function parseTransactionLogs($resultData, $savedData = null): array 'evidenceName' => $savedItem?->evidence_name ?? ($log->UseStoreName ?? ''), 'description' => $savedItem?->description ?? ($log->UseStoreBizType ?? $log->Memo ?? ''), 'isSaved' => $savedItem !== null, + // 금액 수정 관련 필드 + 'modifiedSupplyAmount' => $savedItem?->modified_supply_amount !== null ? (float) $savedItem->modified_supply_amount : null, + 'modifiedTax' => $savedItem?->modified_tax !== null ? (float) $savedItem->modified_tax : null, + 'effectiveSupplyAmount' => $savedItem?->modified_supply_amount !== null + ? (float) $savedItem->modified_supply_amount + : ($amount - floatval($log->Tax ?? 0)), + 'effectiveTax' => $savedItem?->modified_tax !== null + ? (float) $savedItem->modified_tax + : floatval($log->Tax ?? 0), + 'isAmountModified' => $savedItem?->modified_supply_amount !== null || $savedItem?->modified_tax !== null, ]; // 공제/불공제 통계 집계 @@ -851,7 +862,54 @@ public function save(Request $request): JsonResponse ->where('approval_amount', $data['approval_amount']) ->first(); + // 수정 금액 처리 + $modifiedSupplyAmount = isset($trans['modifiedSupplyAmount']) && $trans['modifiedSupplyAmount'] !== null + ? floatval($trans['modifiedSupplyAmount']) : null; + $modifiedTax = isset($trans['modifiedTax']) && $trans['modifiedTax'] !== null + ? floatval($trans['modifiedTax']) : null; + + $data['modified_supply_amount'] = $modifiedSupplyAmount; + $data['modified_tax'] = $modifiedTax; + if ($existing) { + // 금액 변경 감지 및 이력 기록 + $oldSupply = $existing->modified_supply_amount !== null + ? (float) $existing->modified_supply_amount + : ((float) $existing->approval_amount - (float) $existing->tax); + $oldTax = $existing->modified_tax !== null + ? (float) $existing->modified_tax + : (float) $existing->tax; + + $newSupply = $modifiedSupplyAmount !== null + ? $modifiedSupplyAmount + : ((float) $existing->approval_amount - (float) $existing->tax); + $newTax = $modifiedTax !== null + ? $modifiedTax + : (float) $existing->tax; + + $amountChanged = abs($oldSupply - $newSupply) > 0.01 || abs($oldTax - $newTax) > 0.01; + + if ($amountChanged) { + $uniqueKey = implode('|', [ + $existing->card_num, + $existing->use_dt, + $existing->approval_num, + (int) $existing->approval_amount, + ]); + + CardTransactionAmountLog::create([ + 'card_transaction_id' => $existing->id, + 'original_unique_key' => $uniqueKey, + 'before_supply_amount' => $oldSupply, + 'before_tax' => $oldTax, + 'after_supply_amount' => $newSupply, + 'after_tax' => $newTax, + 'modified_by' => auth()->id(), + 'modified_by_name' => auth()->user()?->name ?? '', + 'ip_address' => $request->ip(), + ]); + } + // 계정과목 및 수정 가능한 필드들 업데이트 $existing->update([ 'account_code' => $data['account_code'], @@ -859,6 +917,8 @@ public function save(Request $request): JsonResponse 'deduction_type' => $data['deduction_type'], 'evidence_name' => $data['evidence_name'], 'description' => $data['description'], + 'modified_supply_amount' => $data['modified_supply_amount'], + 'modified_tax' => $data['modified_tax'], ]); $updated++; } else { diff --git a/app/Models/Barobill/CardTransaction.php b/app/Models/Barobill/CardTransaction.php index 369b45c5..1b213dd3 100644 --- a/app/Models/Barobill/CardTransaction.php +++ b/app/Models/Barobill/CardTransaction.php @@ -41,12 +41,16 @@ class CardTransaction extends Model 'deduction_type', 'evidence_name', 'description', + 'modified_supply_amount', + 'modified_tax', ]; protected $casts = [ 'approval_amount' => 'decimal:2', 'tax' => 'decimal:2', 'service_charge' => 'decimal:2', + 'modified_supply_amount' => 'decimal:2', + 'modified_tax' => 'decimal:2', ]; /** diff --git a/app/Models/Barobill/CardTransactionAmountLog.php b/app/Models/Barobill/CardTransactionAmountLog.php new file mode 100644 index 00000000..82395fcb --- /dev/null +++ b/app/Models/Barobill/CardTransactionAmountLog.php @@ -0,0 +1,44 @@ + 'decimal:2', + 'before_tax' => 'decimal:2', + 'after_supply_amount' => 'decimal:2', + 'after_tax' => 'decimal:2', + 'created_at' => 'datetime', + ]; + + /** + * 카드 거래 관계 + */ + public function cardTransaction(): BelongsTo + { + return $this->belongsTo(CardTransaction::class, 'card_transaction_id'); + } +} diff --git a/resources/views/barobill/ecard/index.blade.php b/resources/views/barobill/ecard/index.blade.php index 01be5524..7b187092 100644 --- a/resources/views/barobill/ecard/index.blade.php +++ b/resources/views/barobill/ecard/index.blade.php @@ -826,18 +826,84 @@ className="w-full px-2 py-1 text-sm border border-stone-200 rounded focus:outlin /> - - {log.approvalAmountFormatted}원 - + {(() => { + const effectiveSupply = log.effectiveSupplyAmount ?? ((log.approvalAmount || 0) - (log.tax || 0)); + const effectiveTax = log.effectiveTax ?? (log.tax || 0); + const totalAmount = effectiveSupply + effectiveTax; + return ( +
+ + {new Intl.NumberFormat('ko-KR').format(totalAmount)}원 + + {log.isAmountModified && totalAmount !== log.approvalAmount && ( +
{log.approvalAmountFormatted}원
+ )} +
+ ); + })()} {hasSplits && (
분개됨 ({logSplits.length}건)
)} - - {new Intl.NumberFormat('ko-KR').format((log.approvalAmount || 0) - (log.tax || 0))}원 + + {hasSplits ? ( + + {new Intl.NumberFormat('ko-KR').format(log.effectiveSupplyAmount ?? ((log.approvalAmount || 0) - (log.tax || 0)))}원 + + ) : ( +
+ { + const val = parseFloat(String(e.target.value).replace(/[^0-9.-]/g, '')) || 0; + const originalSupply = (log.approvalAmount || 0) - (log.tax || 0); + const isModified = Math.abs(val - originalSupply) > 0.01; + onFieldChange(index, 'effectiveSupplyAmount', val); + onFieldChange(index, 'modifiedSupplyAmount', isModified ? val : null); + onFieldChange(index, 'isAmountModified', isModified || log.modifiedTax !== null); + }} + className={`w-full px-2 py-1 text-sm text-right border rounded focus:outline-none focus:ring-1 focus:ring-purple-500 focus:border-purple-500 ${ + log.modifiedSupplyAmount !== null ? 'border-orange-300 bg-orange-50' : 'border-stone-200' + }`} + /> + {log.modifiedSupplyAmount !== null && ( +
+ {new Intl.NumberFormat('ko-KR').format((log.approvalAmount || 0) - (log.tax || 0))}원 +
+ )} +
+ )} - - {log.taxFormatted}원 + + {hasSplits ? ( + + {new Intl.NumberFormat('ko-KR').format(log.effectiveTax ?? (log.tax || 0))}원 + + ) : ( +
+ { + const val = parseFloat(String(e.target.value).replace(/[^0-9.-]/g, '')) || 0; + const originalTax = log.tax || 0; + const isModified = Math.abs(val - originalTax) > 0.01; + onFieldChange(index, 'effectiveTax', val); + onFieldChange(index, 'modifiedTax', isModified ? val : null); + onFieldChange(index, 'isAmountModified', isModified || log.modifiedSupplyAmount !== null); + }} + className={`w-full px-2 py-1 text-sm text-right border rounded focus:outline-none focus:ring-1 focus:ring-purple-500 focus:border-purple-500 ${ + log.modifiedTax !== null ? 'border-orange-300 bg-orange-50' : 'border-stone-200' + }`} + /> + {log.modifiedTax !== null && ( +
+ {new Intl.NumberFormat('ko-KR').format(log.tax || 0)}원 +
+ )} +
+ )} {log.approvalNum || '-'}