231 lines
8.5 KiB
PHP
231 lines
8.5 KiB
PHP
<?php
|
|
|
|
namespace App\Repositories\Mypage;
|
|
|
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
final class UsageRepository
|
|
{
|
|
public function findAttemptWithOrder(int $attemptId): ?object
|
|
{
|
|
return DB::table('gc_payment_attempts as a')
|
|
->leftJoin('gc_pin_order as o', 'o.id', '=', 'a.order_id')
|
|
->select([
|
|
'a.id as attempt_id',
|
|
'a.provider as attempt_provider',
|
|
'a.oid as attempt_oid',
|
|
'a.mem_no as attempt_mem_no',
|
|
'a.order_id as attempt_order_id',
|
|
'a.pay_method as attempt_pay_method',
|
|
'a.status as attempt_status',
|
|
'a.pg_tid as attempt_pg_tid',
|
|
'a.return_code as attempt_return_code',
|
|
'a.return_msg as attempt_return_msg',
|
|
'a.request_payload as attempt_request_payload',
|
|
'a.response_payload as attempt_response_payload',
|
|
'a.return_payload as attempt_return_payload',
|
|
'a.noti_payload as attempt_noti_payload',
|
|
'a.created_at as attempt_created_at',
|
|
'a.updated_at as attempt_updated_at',
|
|
|
|
// 추가: cancel_status 필드들
|
|
'a.cancel_status as attempt_cancel_status',
|
|
'a.cancel_requested_at as attempt_cancel_requested_at',
|
|
'a.cancel_done_at as attempt_cancel_done_at',
|
|
'a.cancel_last_code as attempt_cancel_last_code',
|
|
'a.cancel_last_msg as attempt_cancel_last_msg',
|
|
|
|
'o.id as order_id',
|
|
'o.oid as order_oid',
|
|
'o.mem_no as order_mem_no',
|
|
'o.stat_pay as order_stat_pay',
|
|
'o.products_name as order_product_name',
|
|
'o.provider as order_provider',
|
|
'o.pay_method as order_pay_method',
|
|
'o.pg_tid as order_pg_tid',
|
|
'o.ret_code as order_ret_code',
|
|
'o.ret_msg as order_ret_msg',
|
|
'o.subtotal_amount as order_subtotal_amount',
|
|
'o.fee_amount as order_fee_amount',
|
|
'o.pg_fee_amount as order_pg_fee_amount',
|
|
'o.pay_money as order_pay_money',
|
|
'o.pay_data as order_pay_data',
|
|
'o.ret_data as order_ret_data',
|
|
'o.created_at as order_created_at',
|
|
'o.updated_at as order_updated_at',
|
|
|
|
// 추가: order cancel_status 필드들
|
|
'o.cancel_status as order_cancel_status',
|
|
'o.cancel_requested_at as order_cancel_requested_at',
|
|
'o.cancel_done_at as order_cancel_done_at',
|
|
'o.cancel_last_code as order_cancel_last_code',
|
|
'o.cancel_last_msg as order_cancel_last_msg',
|
|
'o.cancel_reason as order_cancel_reason',
|
|
])
|
|
->where('a.id', $attemptId)
|
|
->first();
|
|
}
|
|
|
|
/**
|
|
* 리스트: 검색/페이징
|
|
*/
|
|
public function paginateAttemptsWithOrder(int $memNo, array $filters, int $perPage = 20): LengthAwarePaginator
|
|
{
|
|
$q = trim((string)($filters['q'] ?? ''));
|
|
$method = trim((string)($filters['method'] ?? ''));
|
|
$status = trim((string)($filters['status'] ?? ''));
|
|
$from = trim((string)($filters['from'] ?? ''));
|
|
$to = trim((string)($filters['to'] ?? ''));
|
|
|
|
// order_items 집계 서브쿼리 (group by를 메인 쿼리에서 피해서 paginate 안정)
|
|
$oiAgg = DB::table('gc_pin_order_items')
|
|
->selectRaw('order_id, SUM(qty) as total_qty, MIN(item_name) as first_item_name')
|
|
->groupBy('order_id');
|
|
|
|
$qb = DB::table('gc_payment_attempts as a')
|
|
->leftJoin('gc_pin_order as o', 'o.id', '=', 'a.order_id')
|
|
->leftJoinSub($oiAgg, 'oi', 'oi.order_id', '=', 'o.id')
|
|
->where('a.mem_no', $memNo)
|
|
|
|
// ✅ 중요: OR 조건 전체를 반드시 하나의 where 그룹으로 묶어야 함
|
|
->where(function ($s) {
|
|
// 1) 취소완료
|
|
$s->where(function ($x) {
|
|
$x->where('a.cancel_status', 'success')
|
|
->orWhere('o.cancel_status', 'success');
|
|
})
|
|
|
|
// 2) 결제완료
|
|
->orWhere(function ($x) {
|
|
$x->where('a.status', 'paid')
|
|
->orWhere('o.stat_pay', 'p');
|
|
})
|
|
|
|
// 3) 입금대기(가상계좌)
|
|
->orWhere(function ($x) {
|
|
$x->where('a.status', 'issued')
|
|
->orWhere('o.stat_pay', 'w');
|
|
});
|
|
})
|
|
|
|
->select([
|
|
'a.id as attempt_id',
|
|
'o.oid as order_oid',
|
|
DB::raw("COALESCE(o.products_name, oi.first_item_name) as product_name"),
|
|
'oi.first_item_name as item_name',
|
|
DB::raw("COALESCE(oi.total_qty, 0) as total_qty"),
|
|
'a.pay_method as pay_method',
|
|
'o.pay_money as pay_money',
|
|
'a.status as attempt_status',
|
|
'o.stat_pay as order_stat_pay',
|
|
'a.cancel_status as attempt_cancel_status',
|
|
'o.cancel_status as order_cancel_status',
|
|
'a.created_at as created_at',
|
|
])
|
|
->orderByDesc('a.id');
|
|
|
|
// ✅ q 검색: 거래번호(o.oid / a.oid) 정확히 일치
|
|
if ($q !== '') {
|
|
$qb->where(function ($w) use ($q) {
|
|
$w->where('o.oid', $q)
|
|
->orWhere('a.oid', $q);
|
|
});
|
|
}
|
|
|
|
// 결제수단
|
|
if ($method !== '') {
|
|
$qb->where('a.pay_method', $method);
|
|
}
|
|
|
|
// ✅ 상태 필터도 화면 의미에 맞게 묶어서 처리
|
|
// (현재 화면 기준: paid / issued / cancel를 의미 상태로 쓰는 경우)
|
|
if ($status !== '') {
|
|
if ($status === 'paid') {
|
|
$qb->where(function ($x) {
|
|
$x->where('a.status', 'paid')
|
|
->orWhere('o.stat_pay', 'p');
|
|
});
|
|
} elseif ($status === 'issued') {
|
|
$qb->where(function ($x) {
|
|
$x->where('a.status', 'issued')
|
|
->orWhere('o.stat_pay', 'w');
|
|
});
|
|
} elseif (in_array($status, ['cancel', 'cancelled', 'canceled'], true)) {
|
|
$qb->where(function ($x) {
|
|
$x->where('a.cancel_status', 'success')
|
|
->orWhere('o.cancel_status', 'success');
|
|
});
|
|
} else {
|
|
// 기타 상태는 attempts 기준으로 그대로
|
|
$qb->where('a.status', $status);
|
|
}
|
|
}
|
|
|
|
// 날짜 필터 (date 기준)
|
|
if ($from !== '') {
|
|
$qb->whereDate('a.created_at', '>=', $from);
|
|
}
|
|
if ($to !== '') {
|
|
$qb->whereDate('a.created_at', '<=', $to);
|
|
}
|
|
|
|
return $qb->paginate($perPage)->appends($filters);
|
|
}
|
|
|
|
public function getOrderItems(int $orderId)
|
|
{
|
|
return DB::table('gc_pin_order_items')
|
|
->where('order_id', $orderId)
|
|
->orderBy('id', 'asc')
|
|
->get();
|
|
}
|
|
|
|
public function countAssignedPins(int $orderId): int
|
|
{
|
|
return (int) DB::table('gc_pins')
|
|
->where('order_id', $orderId)
|
|
->count();
|
|
}
|
|
|
|
public function getAssignedPinsStatusSummary(int $orderId): array
|
|
{
|
|
$rows = DB::table('gc_pins')
|
|
->selectRaw('status, COUNT(*) as cnt')
|
|
->where('order_id', $orderId)
|
|
->groupBy('status')
|
|
->get();
|
|
|
|
$out = [];
|
|
foreach ($rows as $r) $out[(string)$r->status] = (int)$r->cnt;
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* 핀 목록(오픈 전/후 표시용) — 핀 반납(홀드 해제)은 이번 범위 제외
|
|
*/
|
|
public function getPinsForOrder(int $orderId): array
|
|
{
|
|
$rows = DB::table('gc_pins')
|
|
->where('order_id', $orderId)
|
|
->orderBy('id', 'asc')
|
|
->get();
|
|
|
|
return array_map(fn($r) => (array)$r, $rows->all());
|
|
}
|
|
|
|
/**
|
|
* 취소 로그 조회
|
|
*/
|
|
public function getCancelLogsForAttempt(int $attemptId, int $limit = 20): array
|
|
{
|
|
$rows = DB::table('gc_payment_cancel_logs')
|
|
->where('attempt_id', $attemptId)
|
|
->orderByDesc('id')
|
|
->limit($limit)
|
|
->get();
|
|
|
|
return array_map(fn($r) => (array)$r, $rows->all());
|
|
}
|
|
}
|