tenantId(); $startDate = $params['start_date'] ?? now()->startOfMonth()->format('Y-m-d'); $endDate = $params['end_date'] ?? now()->format('Y-m-d'); $cardNum = $params['card_num'] ?? null; $search = $params['search'] ?? null; $includeHidden = $params['include_hidden'] ?? false; $perPage = $params['per_page'] ?? 50; $query = BarobillCardTransaction::where('tenant_id', $tenantId) ->whereBetween('use_date', [$startDate, $endDate]); if ($cardNum) { $query->where('card_num', $cardNum); } if ($search) { $query->where(function ($q) use ($search) { $q->where('merchant_name', 'like', "%{$search}%") ->orWhere('memo', 'like', "%{$search}%") ->orWhere('approval_num', 'like', "%{$search}%"); }); } // 숨김 거래 필터링 if (! $includeHidden) { $hiddenKeys = BarobillCardTransactionHide::getHiddenKeys($tenantId, $startDate, $endDate); if (! empty($hiddenKeys)) { $query->whereNotIn( DB::raw("CONCAT(card_num, '|', use_dt, '|', approval_num, '|', approval_amount)"), $hiddenKeys ); } } $query->orderByDesc('use_date')->orderByDesc('use_dt'); $transactions = $query->paginate($perPage); // 분할 거래 정보 로드 $uniqueKeys = $transactions->getCollection()->map->unique_key->toArray(); $splits = BarobillCardTransactionSplit::where('tenant_id', $tenantId) ->whereIn('original_unique_key', $uniqueKeys) ->orderBy('sort_order') ->get() ->groupBy('original_unique_key'); $transactions->getCollection()->transform(function ($tx) use ($splits) { $tx->splits = $splits->get($tx->unique_key, collect()); $tx->has_splits = $tx->splits->isNotEmpty(); return $tx; }); return [ 'data' => $transactions, ]; } /** * 단일 카드 거래 상세 */ public function show(int $id): ?BarobillCardTransaction { return BarobillCardTransaction::where('tenant_id', $this->tenantId()) ->find($id); } /** * 카드 거래 분할 조회 */ public function getSplits(string $uniqueKey): array { $tenantId = $this->tenantId(); $splits = BarobillCardTransactionSplit::getByUniqueKey($tenantId, $uniqueKey); return ['items' => $splits]; } /** * 카드 거래 분할 저장 */ public function saveSplits(string $uniqueKey, array $items): array { $tenantId = $this->tenantId(); return DB::transaction(function () use ($tenantId, $uniqueKey, $items) { // 기존 분할 삭제 BarobillCardTransactionSplit::where('tenant_id', $tenantId) ->where('original_unique_key', $uniqueKey) ->delete(); $created = []; foreach ($items as $index => $item) { $created[] = BarobillCardTransactionSplit::create([ 'tenant_id' => $tenantId, 'original_unique_key' => $uniqueKey, 'split_amount' => $item['split_amount'], 'split_supply_amount' => $item['split_supply_amount'] ?? 0, 'split_tax' => $item['split_tax'] ?? 0, 'account_code' => $item['account_code'] ?? null, 'account_name' => $item['account_name'] ?? null, 'deduction_type' => $item['deduction_type'] ?? null, 'evidence_name' => $item['evidence_name'] ?? null, 'description' => $item['description'] ?? null, 'memo' => $item['memo'] ?? null, 'sort_order' => $index + 1, 'card_num' => $item['card_num'] ?? null, 'use_dt' => $item['use_dt'] ?? null, 'use_date' => $item['use_date'] ?? null, 'approval_num' => $item['approval_num'] ?? null, 'original_amount' => $item['original_amount'] ?? 0, 'merchant_name' => $item['merchant_name'] ?? null, ]); } return ['items' => $created, 'count' => count($created)]; }); } /** * 카드 거래 분할 삭제 */ public function deleteSplits(string $uniqueKey): array { $tenantId = $this->tenantId(); $deleted = BarobillCardTransactionSplit::where('tenant_id', $tenantId) ->where('original_unique_key', $uniqueKey) ->delete(); return ['deleted_count' => $deleted]; } /** * 수동 카드 거래 등록 */ public function storeManual(array $data): BarobillCardTransaction { $tenantId = $this->tenantId(); return BarobillCardTransaction::create([ 'tenant_id' => $tenantId, 'card_num' => $data['card_num'], 'card_company' => $data['card_company'] ?? null, 'card_company_name' => $data['card_company_name'] ?? null, 'use_dt' => $data['use_dt'], 'use_date' => $data['use_date'], 'use_time' => $data['use_time'] ?? null, 'approval_num' => $data['approval_num'] ?? 'MANUAL-'.now()->format('YmdHis'), 'approval_type' => $data['approval_type'] ?? '1', 'approval_amount' => $data['approval_amount'], 'tax' => $data['tax'] ?? 0, 'service_charge' => $data['service_charge'] ?? 0, 'payment_plan' => $data['payment_plan'] ?? null, 'merchant_name' => $data['merchant_name'], 'merchant_biz_num' => $data['merchant_biz_num'] ?? null, 'account_code' => $data['account_code'] ?? null, 'account_name' => $data['account_name'] ?? null, 'deduction_type' => $data['deduction_type'] ?? null, 'evidence_name' => $data['evidence_name'] ?? null, 'description' => $data['description'] ?? null, 'memo' => $data['memo'] ?? null, 'is_manual' => true, ]); } /** * 수동 카드 거래 수정 */ public function updateManual(int $id, array $data): BarobillCardTransaction { $tx = BarobillCardTransaction::where('tenant_id', $this->tenantId()) ->where('is_manual', true) ->findOrFail($id); $tx->update($data); return $tx->fresh(); } /** * 수동 카드 거래 삭제 */ public function destroyManual(int $id): bool { $tx = BarobillCardTransaction::where('tenant_id', $this->tenantId()) ->where('is_manual', true) ->findOrFail($id); return $tx->delete(); } /** * 카드 거래 숨김 */ public function hide(int $id): BarobillCardTransactionHide { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); $tx = BarobillCardTransaction::where('tenant_id', $tenantId)->findOrFail($id); return BarobillCardTransactionHide::hideTransaction($tenantId, $tx->unique_key, [ 'card_num' => $tx->card_num, 'use_date' => $tx->use_date, 'approval_num' => $tx->approval_num, 'approval_amount' => $tx->approval_amount, 'merchant_name' => $tx->merchant_name, ], $userId); } /** * 카드 거래 숨김 복원 */ public function restore(int $id): bool { $tenantId = $this->tenantId(); $tx = BarobillCardTransaction::where('tenant_id', $tenantId)->findOrFail($id); return BarobillCardTransactionHide::restoreTransaction($tenantId, $tx->unique_key); } /** * 숨겨진 거래 목록 */ public function hiddenList(array $params): array { $tenantId = $this->tenantId(); $startDate = $params['start_date'] ?? now()->startOfMonth()->format('Y-m-d'); $endDate = $params['end_date'] ?? now()->format('Y-m-d'); $hiddenItems = BarobillCardTransactionHide::where('tenant_id', $tenantId) ->whereBetween('use_date', [$startDate, $endDate]) ->orderByDesc('created_at') ->get(); return ['items' => $hiddenItems]; } /** * 금액 수정 (공급가액/세액 수정) */ public function updateAmount(int $id, array $data): BarobillCardTransaction { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); $tx = BarobillCardTransaction::where('tenant_id', $tenantId)->findOrFail($id); // 변경 이력 기록 BarobillCardTransactionAmountLog::create([ 'card_transaction_id' => $tx->id, 'original_unique_key' => $tx->unique_key, 'before_supply_amount' => $tx->modified_supply_amount ?? $tx->approval_amount, 'before_tax' => $tx->modified_tax ?? $tx->tax, 'after_supply_amount' => $data['supply_amount'], 'after_tax' => $data['tax'], 'modified_by' => $userId, 'modified_by_name' => $data['modified_by_name'] ?? '', 'ip_address' => request()->ip(), ]); $tx->update([ 'modified_supply_amount' => $data['supply_amount'], 'modified_tax' => $data['tax'], ]); return $tx->fresh(); } /** * 카드 번호 목록 (필터용) */ public function cardNumbers(): array { $tenantId = $this->tenantId(); $cards = BarobillCardTransaction::where('tenant_id', $tenantId) ->select('card_num', 'card_company_name') ->distinct() ->orderBy('card_num') ->get(); return ['items' => $cards]; } }