feat:카드 사용내역 분개 기능 추가
- CardTransactionSplit 모델 및 마이그레이션 추가 - EcardController에 splits, saveSplits, deleteSplits API 추가 - 분개 라우트 추가 (GET/POST/DELETE /barobill/ecard/splits) - 프론트엔드 SplitModal 컴포넌트 추가 - 각 거래 행에 +/- 버튼으로 분개 추가/삭제 - 분개 행 시각적 구분 (들여쓰기, 배경색) - 분개 금액 합계 검증 - 고유키(cardNum|useDt|approvalNum|amount)로 원본 데이터 연결 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
use App\Models\Barobill\BarobillConfig;
|
||||
use App\Models\Barobill\BarobillMember;
|
||||
use App\Models\Barobill\CardTransaction;
|
||||
use App\Models\Barobill\CardTransactionSplit;
|
||||
use App\Models\Tenants\Tenant;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -855,6 +856,113 @@ public function exportExcel(Request $request): StreamedResponse|JsonResponse
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 분개 내역 조회
|
||||
*/
|
||||
public function splits(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
|
||||
$startDate = $request->input('startDate', date('Ymd'));
|
||||
$endDate = $request->input('endDate', date('Ymd'));
|
||||
|
||||
$splits = CardTransactionSplit::getByDateRange($tenantId, $startDate, $endDate);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $splits
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('분개 내역 조회 오류: ' . $e->getMessage());
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => '조회 오류: ' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 분개 저장
|
||||
*/
|
||||
public function saveSplits(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
|
||||
$uniqueKey = $request->input('uniqueKey');
|
||||
$originalData = $request->input('originalData', []);
|
||||
$splits = $request->input('splits', []);
|
||||
|
||||
if (empty($uniqueKey)) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => '고유키가 없습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
// 분개 금액 합계 검증
|
||||
$originalAmount = floatval($originalData['originalAmount'] ?? 0);
|
||||
$splitTotal = array_sum(array_map(fn($s) => floatval($s['amount'] ?? 0), $splits));
|
||||
|
||||
if (abs($originalAmount - $splitTotal) > 0.01) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => "분개 금액 합계({$splitTotal})가 원본 금액({$originalAmount})과 일치하지 않습니다."
|
||||
]);
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
CardTransactionSplit::saveSplits($tenantId, $uniqueKey, $originalData, $splits);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => '분개가 저장되었습니다.',
|
||||
'splitCount' => count($splits)
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
DB::rollBack();
|
||||
Log::error('분개 저장 오류: ' . $e->getMessage());
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => '저장 오류: ' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 분개 삭제 (원본으로 복원)
|
||||
*/
|
||||
public function deleteSplits(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$tenantId = session('selected_tenant_id', self::HEADQUARTERS_TENANT_ID);
|
||||
$uniqueKey = $request->input('uniqueKey');
|
||||
|
||||
if (empty($uniqueKey)) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => '고유키가 없습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$deleted = CardTransactionSplit::deleteSplits($tenantId, $uniqueKey);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => '분개가 삭제되었습니다.',
|
||||
'deleted' => $deleted
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('분개 삭제 오류: ' . $e->getMessage());
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => '삭제 오류: ' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SOAP 호출
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user