Files
sam-api/app/Services/Barobill/HometaxSyncService.php
김보곤 269a17b49c feat: [barobill] SOAP 동기화 서비스 신규 구축
- BarobillSoapService: PHP SoapClient 기반 SOAP 래퍼 (회원/계좌/카드/인증서)
- BarobillBankSyncService: 은행 거래내역 SOAP 조회 → DB 캐시 동기화
- BarobillCardSyncService: 카드 거래내역 SOAP 조회 → DB 캐시 동기화
- HometaxSyncService: 홈택스 세금계산서 upsert 동기화
- BarobillSyncController: 동기화/회원/인증서/잔액 API 11개 엔드포인트
- SyncBarobillDataJob: 매일 06:00/06:30 자동 동기화 스케줄러
- BarobillController.status() 보강: 실제 계좌/카드 수 표시
2026-03-17 13:03:24 +09:00

117 lines
4.0 KiB
PHP

<?php
namespace App\Services\Barobill;
use App\Models\Barobill\HometaxInvoice;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
/**
* 홈택스 세금계산서 동기화 서비스 (API 독립 구현)
*
* MNG의 HometaxSyncService 패턴을 참고하여 독립 작성.
* 바로빌 API 응답 데이터를 로컬 DB에 upsert한다.
*/
class HometaxSyncService extends Service
{
/**
* API 응답 데이터를 로컬 DB에 동기화
*
* @param array $invoices API에서 받은 세금계산서 목록
* @param int $tenantId 테넌트 ID
* @param string $invoiceType 'sales' 또는 'purchase'
* @return array 동기화 결과
*/
public function syncInvoices(array $invoices, int $tenantId, string $invoiceType): array
{
$result = [
'inserted' => 0,
'updated' => 0,
'failed' => 0,
'total' => count($invoices),
];
if (empty($invoices)) {
return $result;
}
DB::beginTransaction();
try {
foreach ($invoices as $apiData) {
if (empty($apiData['ntsConfirmNum'])) {
$result['failed']++;
continue;
}
$modelData = HometaxInvoice::fromApiData($apiData, $tenantId, $invoiceType);
$existing = HometaxInvoice::withoutGlobalScopes()
->where('tenant_id', $tenantId)
->where('nts_confirm_num', $modelData['nts_confirm_num'])
->where('invoice_type', $invoiceType)
->first();
if ($existing) {
$existing->update([
'write_date' => $modelData['write_date'],
'issue_date' => $modelData['issue_date'],
'invoicer_corp_num' => $modelData['invoicer_corp_num'],
'invoicer_corp_name' => $modelData['invoicer_corp_name'],
'invoicer_ceo_name' => $modelData['invoicer_ceo_name'],
'invoicee_corp_num' => $modelData['invoicee_corp_num'],
'invoicee_corp_name' => $modelData['invoicee_corp_name'],
'invoicee_ceo_name' => $modelData['invoicee_ceo_name'],
'supply_amount' => $modelData['supply_amount'],
'tax_amount' => $modelData['tax_amount'],
'total_amount' => $modelData['total_amount'],
'tax_type' => $modelData['tax_type'],
'purpose_type' => $modelData['purpose_type'],
'item_name' => $modelData['item_name'],
'remark' => $modelData['remark'],
'synced_at' => now(),
]);
$result['updated']++;
} else {
HometaxInvoice::create($modelData);
$result['inserted']++;
}
}
DB::commit();
Log::info('[HometaxSync] 동기화 완료', [
'tenant_id' => $tenantId,
'invoice_type' => $invoiceType,
'result' => $result,
]);
} catch (\Throwable $e) {
DB::rollBack();
Log::error('[HometaxSync] 동기화 실패', [
'tenant_id' => $tenantId,
'invoice_type' => $invoiceType,
'error' => $e->getMessage(),
]);
throw $e;
}
return $result;
}
/**
* 마지막 동기화 시간 조회
*/
public function getLastSyncTime(int $tenantId, string $invoiceType): ?string
{
$lastSync = HometaxInvoice::withoutGlobalScopes()
->where('tenant_id', $tenantId)
->where('invoice_type', $invoiceType)
->orderByDesc('synced_at')
->value('synced_at');
return $lastSync?->format('Y-m-d H:i:s');
}
}