fix: [bank-account] 계좌 관리 API 누락 필드 8개 보강

- account_type, balance, currency, opened_at, branch_name, memo, sort_order, last_transaction_at 추가
- Model: fillable, casts, hidden, scopes, accessors를 MNG 모델 기준으로 통일
- Service: store/update에 누락 필드 반영
- FormRequest: Store/Update에 검증 규칙 추가
This commit is contained in:
김보곤
2026-02-20 23:20:49 +09:00
parent 0692eda282
commit fdea1d0244
4 changed files with 107 additions and 11 deletions

View File

@@ -19,9 +19,16 @@ public function rules(): array
'account_number' => ['required', 'string', 'max:30', 'regex:/^[\d-]+$/'], 'account_number' => ['required', 'string', 'max:30', 'regex:/^[\d-]+$/'],
'account_holder' => ['required', 'string', 'max:50'], 'account_holder' => ['required', 'string', 'max:50'],
'account_name' => ['required', 'string', 'max:100'], 'account_name' => ['required', 'string', 'max:100'],
'account_type' => ['nullable', 'string', 'max:30'],
'balance' => ['nullable', 'numeric', 'min:0'],
'currency' => ['nullable', 'string', 'max:3'],
'opened_at' => ['nullable', 'date'],
'branch_name' => ['nullable', 'string', 'max:100'],
'memo' => ['nullable', 'string', 'max:500'],
'status' => ['nullable', 'string', 'in:active,inactive'], 'status' => ['nullable', 'string', 'in:active,inactive'],
'assigned_user_id' => ['nullable', 'integer', 'exists:users,id'], 'assigned_user_id' => ['nullable', 'integer', 'exists:users,id'],
'is_primary' => ['nullable', 'boolean'], 'is_primary' => ['nullable', 'boolean'],
'sort_order' => ['nullable', 'integer', 'min:0'],
]; ];
} }

View File

@@ -19,8 +19,15 @@ public function rules(): array
'account_number' => ['sometimes', 'string', 'max:30', 'regex:/^[\d-]+$/'], 'account_number' => ['sometimes', 'string', 'max:30', 'regex:/^[\d-]+$/'],
'account_holder' => ['sometimes', 'string', 'max:50'], 'account_holder' => ['sometimes', 'string', 'max:50'],
'account_name' => ['sometimes', 'string', 'max:100'], 'account_name' => ['sometimes', 'string', 'max:100'],
'account_type' => ['sometimes', 'nullable', 'string', 'max:30'],
'balance' => ['sometimes', 'nullable', 'numeric', 'min:0'],
'currency' => ['sometimes', 'nullable', 'string', 'max:3'],
'opened_at' => ['sometimes', 'nullable', 'date'],
'branch_name' => ['sometimes', 'nullable', 'string', 'max:100'],
'memo' => ['sometimes', 'nullable', 'string', 'max:500'],
'status' => ['sometimes', 'string', 'in:active,inactive'], 'status' => ['sometimes', 'string', 'in:active,inactive'],
'assigned_user_id' => ['nullable', 'integer', 'exists:users,id'], 'assigned_user_id' => ['nullable', 'integer', 'exists:users,id'],
'sort_order' => ['sometimes', 'nullable', 'integer', 'min:0'],
]; ];
} }

View File

@@ -40,16 +40,34 @@ class BankAccount extends Model
'account_number', 'account_number',
'account_holder', 'account_holder',
'account_name', 'account_name',
'account_type',
'balance',
'currency',
'opened_at',
'last_transaction_at',
'branch_name',
'memo',
'status', 'status',
'assigned_user_id', 'assigned_user_id',
'is_primary', 'is_primary',
'sort_order',
'created_by', 'created_by',
'updated_by', 'updated_by',
'deleted_by', 'deleted_by',
]; ];
protected $hidden = [
'created_by',
'updated_by',
'deleted_by',
'deleted_at',
];
protected $casts = [ protected $casts = [
'balance' => 'decimal:2',
'is_primary' => 'boolean', 'is_primary' => 'boolean',
'opened_at' => 'date',
'last_transaction_at' => 'datetime',
]; ];
protected $attributes = [ protected $attributes = [
@@ -89,22 +107,69 @@ public function updater(): BelongsTo
// 헬퍼 메서드 // 헬퍼 메서드
// ========================================================================= // =========================================================================
// =========================================================================
// Accessors
// =========================================================================
/** /**
* 마스킹된 계좌번호 조회 * 포맷된 잔액
*/
public function getFormattedBalanceAttribute(): string
{
$amount = abs($this->balance ?? 0);
if ($amount >= 100000000) {
return number_format($amount / 100000000, 1).'억원';
} elseif ($amount >= 10000000) {
return number_format($amount / 10000000, 0).'천만원';
} elseif ($amount >= 10000) {
return number_format($amount / 10000, 0).'만원';
}
return number_format($amount).'원';
}
/**
* 마스킹된 계좌번호
*/ */
public function getMaskedAccountNumber(): string public function getMaskedAccountNumber(): string
{ {
$length = strlen($this->account_number); $number = $this->account_number;
if ($length <= 4) { if (strlen($number) <= 6) {
return $this->account_number; return $number;
} }
$visibleEnd = substr($this->account_number, -4); return substr($number, 0, 3).'-***-'.substr($number, -4);
$maskedPart = str_repeat('*', $length - 4);
return $maskedPart.$visibleEnd;
} }
// =========================================================================
// Scopes
// =========================================================================
public function scopeActive($query)
{
return $query->where('status', 'active');
}
public function scopePrimary($query)
{
return $query->where('is_primary', true);
}
public function scopeByType($query, string $accountType)
{
return $query->where('account_type', $accountType);
}
public function scopeOrdered($query)
{
return $query->orderBy('sort_order')->orderBy('bank_name');
}
// =========================================================================
// 헬퍼 메서드
// =========================================================================
/** /**
* 활성 상태 여부 * 활성 상태 여부
*/ */
@@ -122,10 +187,13 @@ public function toggleStatus(): void
} }
/** /**
* 대표계좌로 설정 * 잔액 업데이트
*/ */
public function setAsPrimary(): void public function updateBalance(float $newBalance): void
{ {
$this->is_primary = true; $this->update([
'balance' => $newBalance,
'last_transaction_at' => now(),
]);
} }
} }

View File

@@ -94,9 +94,16 @@ public function store(array $data): BankAccount
'account_number' => $data['account_number'], 'account_number' => $data['account_number'],
'account_holder' => $data['account_holder'], 'account_holder' => $data['account_holder'],
'account_name' => $data['account_name'], 'account_name' => $data['account_name'],
'account_type' => $data['account_type'] ?? null,
'balance' => $data['balance'] ?? 0,
'currency' => $data['currency'] ?? 'KRW',
'opened_at' => $data['opened_at'] ?? null,
'branch_name' => $data['branch_name'] ?? null,
'memo' => $data['memo'] ?? null,
'status' => $data['status'] ?? 'active', 'status' => $data['status'] ?? 'active',
'assigned_user_id' => $data['assigned_user_id'] ?? null, 'assigned_user_id' => $data['assigned_user_id'] ?? null,
'is_primary' => $isPrimary, 'is_primary' => $isPrimary,
'sort_order' => $data['sort_order'] ?? 0,
'created_by' => $userId, 'created_by' => $userId,
'updated_by' => $userId, 'updated_by' => $userId,
]); ]);
@@ -124,8 +131,15 @@ public function update(int $id, array $data): BankAccount
'account_number' => $data['account_number'] ?? $account->account_number, 'account_number' => $data['account_number'] ?? $account->account_number,
'account_holder' => $data['account_holder'] ?? $account->account_holder, 'account_holder' => $data['account_holder'] ?? $account->account_holder,
'account_name' => $data['account_name'] ?? $account->account_name, 'account_name' => $data['account_name'] ?? $account->account_name,
'account_type' => $data['account_type'] ?? $account->account_type,
'balance' => $data['balance'] ?? $account->balance,
'currency' => $data['currency'] ?? $account->currency,
'opened_at' => $data['opened_at'] ?? $account->opened_at,
'branch_name' => $data['branch_name'] ?? $account->branch_name,
'memo' => $data['memo'] ?? $account->memo,
'status' => $data['status'] ?? $account->status, 'status' => $data['status'] ?? $account->status,
'assigned_user_id' => $data['assigned_user_id'] ?? $account->assigned_user_id, 'assigned_user_id' => $data['assigned_user_id'] ?? $account->assigned_user_id,
'sort_order' => $data['sort_order'] ?? $account->sort_order,
'updated_by' => $userId, 'updated_by' => $userId,
]); ]);