feat: [barobill] React 연동용 바로빌 카드/은행/홈택스 REST API 구현
- 바로빌 카드 거래 API (16 엔드포인트): 조회, 분할, 수동입력, 숨김/복원, 금액수정, 분개 - 바로빌 은행 거래 API (13 엔드포인트): 조회, 분할, 오버라이드, 수동입력, 잔액요약, 분개 - 홈택스 세금계산서 API (13 엔드포인트): 매출/매입 조회, 수동입력, 자체분개, 통합분개 - JournalEntry 소스 타입 상수 추가 (barobill_card, barobill_bank, hometax_invoice)
This commit is contained in:
308
app/Services/BarobillCardTransactionService.php
Normal file
308
app/Services/BarobillCardTransactionService.php
Normal file
@@ -0,0 +1,308 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Barobill\BarobillCardTransaction;
|
||||
use App\Models\Barobill\BarobillCardTransactionAmountLog;
|
||||
use App\Models\Barobill\BarobillCardTransactionHide;
|
||||
use App\Models\Barobill\BarobillCardTransactionSplit;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* 바로빌 카드 거래 서비스 (React 연동용)
|
||||
*
|
||||
* MNG에서 동기화된 barobill_card_transactions 데이터를
|
||||
* React 프론트엔드에서 조회/분개/숨김 등 처리
|
||||
*/
|
||||
class BarobillCardTransactionService extends Service
|
||||
{
|
||||
/**
|
||||
* 카드 거래 목록 조회 (기간별, 카드번호별)
|
||||
*/
|
||||
public function index(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');
|
||||
$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];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user