fix: [settlement] 수당지급현황통계 파트너별 결산 개별 건 표시

- 파트너별 GROUP BY 요약 → 개별 commission 레코드 표시로 변경
- 1차/2차수당 계산에 매니저/유치 수당 포함하여 합계 불일치 해소
- 파트너 헤더행 + 개별 건 행 + 합계행 구조로 테이블 재구성
This commit is contained in:
김보곤
2026-02-23 22:42:13 +09:00
parent c9e57b59ce
commit 3a8d28e21d
2 changed files with 133 additions and 95 deletions

View File

@@ -12,7 +12,6 @@
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
class SettlementController extends Controller
@@ -26,7 +25,7 @@ public function __construct(
*/
public function index(Request $request): View|Response
{
if ($request->header('HX-Request') && !$request->header('HX-Boosted')) {
if ($request->header('HX-Request') && ! $request->header('HX-Boosted')) {
return response('', 200)->header('HX-Redirect', route('finance.settlement'));
}
@@ -170,7 +169,7 @@ public function partnerSummary(Request $request): View
// 각 파트너별 수당 집계
$partnerIds = $partners->pluck('id')->toArray();
if (!empty($partnerIds)) {
if (! empty($partnerIds)) {
$commissionStats = SalesCommission::selectRaw('
partner_id,
SUM(CASE WHEN status = "paid" THEN partner_commission ELSE 0 END) as paid_total,
@@ -215,7 +214,7 @@ public function customerTab(Request $request): View
if ($search = $request->input('search')) {
$query->where(function ($q) use ($search) {
$q->whereHas('tenant', fn ($tq) => $tq->where('company_name', 'like', "%{$search}%"))
->orWhereHas('tenantProspect', fn ($pq) => $pq->where('company_name', 'like', "%{$search}%"));
->orWhereHas('tenantProspect', fn ($pq) => $pq->where('company_name', 'like', "%{$search}%"));
});
}
@@ -228,9 +227,9 @@ public function customerTab(Request $request): View
if ($partnerId = $request->input('partner_id')) {
$query->where(function ($q) use ($partnerId) {
$q->where('sales_partner_id', $partnerId)
->orWhereHas('tenantProspect.registeredBy.salesPartner', function ($sq) use ($partnerId) {
$sq->where('id', $partnerId);
});
->orWhereHas('tenantProspect.registeredBy.salesPartner', function ($sq) use ($partnerId) {
$sq->where('id', $partnerId);
});
});
}
@@ -245,10 +244,11 @@ public function customerTab(Request $request): View
$managements->getCollection()->filter(function ($mgmt) use ($paymentStatus) {
$depositPaid = $mgmt->deposit_status === 'paid';
$balancePaid = $mgmt->balance_status === 'paid';
return match ($paymentStatus) {
'fully_paid' => $depositPaid && $balancePaid,
'partial' => ($depositPaid || $balancePaid) && !($depositPaid && $balancePaid),
'unpaid' => !$depositPaid && !$balancePaid,
'partial' => ($depositPaid || $balancePaid) && ! ($depositPaid && $balancePaid),
'unpaid' => ! $depositPaid && ! $balancePaid,
default => true,
};
})
@@ -264,7 +264,7 @@ public function customerTab(Request $request): View
->toArray();
$subscriptionFees = [];
if (!empty($tenantIds)) {
if (! empty($tenantIds)) {
$subscriptionFees = SalesContractProduct::whereIn('tenant_id', $tenantIds)
->selectRaw('tenant_id, SUM(subscription_fee) as total_subscription_fee')
->groupBy('tenant_id')
@@ -305,13 +305,13 @@ public function subscriptionTab(Request $request): View
'tenant', 'tenantProspect', 'salesPartner.user',
'manager', 'contractProducts.product', 'contractProducts.category',
])
->where('hq_status', 'handover');
->where('hq_status', 'handover');
// 검색 필터
if ($search = $request->input('search')) {
$query->where(function ($q) use ($search) {
$q->whereHas('tenant', fn($t) => $t->where('company_name', 'like', "%{$search}%"))
->orWhereHas('tenantProspect', fn($t) => $t->where('company_name', 'like', "%{$search}%"));
$q->whereHas('tenant', fn ($t) => $t->where('company_name', 'like', "%{$search}%"))
->orWhereHas('tenantProspect', fn ($t) => $t->where('company_name', 'like', "%{$search}%"));
});
}
@@ -320,8 +320,8 @@ public function subscriptionTab(Request $request): View
// 통계 계산
$stats = [
'activeCount' => $managements->count(),
'monthlyRecurring' => $managements->sum(fn($m) => $m->contractProducts->sum('subscription_fee')),
'totalProducts' => $managements->sum(fn($m) => $m->contractProducts->where('subscription_fee', '>', 0)->count()),
'monthlyRecurring' => $managements->sum(fn ($m) => $m->contractProducts->sum('subscription_fee')),
'totalProducts' => $managements->sum(fn ($m) => $m->contractProducts->where('subscription_fee', '>', 0)->count()),
];
$stats['yearlyRecurring'] = $stats['monthlyRecurring'] * 12;
@@ -392,7 +392,7 @@ public function paymentPartnerDetail(int $partnerId): View
*/
public function paymentStats(Request $request): View|Response
{
if ($request->header('HX-Request') && !$request->header('HX-Boosted')) {
if ($request->header('HX-Request') && ! $request->header('HX-Boosted')) {
return response('', 200)->header('HX-Redirect', route('finance.settlement.payment-stats'));
}
@@ -445,8 +445,8 @@ public function paymentStats(Request $request): View|Response
if ($search) {
$query->where(function ($q) use ($search) {
$q->whereHas('partner.user', fn ($uq) => $uq->where('name', 'like', "%{$search}%"))
->orWhereHas('partner', fn ($pq) => $pq->where('partner_code', 'like', "%{$search}%"))
->orWhereHas('management.tenant', fn ($tq) => $tq->where('company_name', 'like', "%{$search}%"));
->orWhereHas('partner', fn ($pq) => $pq->where('partner_code', 'like', "%{$search}%"))
->orWhereHas('management.tenant', fn ($tq) => $tq->where('company_name', 'like', "%{$search}%"));
});
}
@@ -538,11 +538,11 @@ private function getMonthlyTrend(\Closure $baseQuery, Carbon $startDate, Carbon
private function getTypeRatio(\Closure $baseQuery): ?object
{
return $baseQuery()
->selectRaw("
->selectRaw('
SUM(partner_commission) as partner_total,
SUM(manager_commission) as manager_total,
SUM(COALESCE(referrer_commission, 0)) as referrer_total
")
')
->first();
}
@@ -575,11 +575,11 @@ private function getTopPartners(\Closure $baseQuery): array
private function getStatusDistribution(\Closure $baseQuery): \Illuminate\Support\Collection
{
return $baseQuery()
->selectRaw("
->selectRaw('
status,
COUNT(*) as count,
SUM(partner_commission + manager_commission + COALESCE(referrer_commission, 0)) as amount
")
')
->groupBy('status')
->get();
}
@@ -602,37 +602,39 @@ private function getMonthlyComparison(\Closure $baseQuery, Carbon $startDate, Ca
}
/**
* 파트너별 결산 테이블
* 파트너별 결산 테이블 (개별 건 포함)
*/
private function getPartnerSettlement(\Closure $baseQuery): \Illuminate\Support\Collection
{
$data = $baseQuery()
->selectRaw("
partner_id,
COUNT(*) as contract_count,
SUM(CASE WHEN payment_type = 'deposit' THEN partner_commission ELSE 0 END) as first_commission,
SUM(CASE WHEN payment_type = 'balance' THEN partner_commission ELSE 0 END) as second_commission,
SUM(partner_commission) as total_partner,
SUM(CASE WHEN status = 'paid' THEN partner_commission + manager_commission + COALESCE(referrer_commission, 0) ELSE 0 END) as paid_amount,
SUM(CASE WHEN status IN ('pending','approved') THEN partner_commission + manager_commission + COALESCE(referrer_commission, 0) ELSE 0 END) as unpaid_amount,
SUM(partner_commission + manager_commission + COALESCE(referrer_commission, 0)) as total_amount
")
->groupBy('partner_id')
->orderByDesc('total_amount')
->with(['partner.user', 'management.tenant'])
->select([
'id', 'partner_id', 'management_id', 'payment_type',
'partner_commission', 'manager_commission', 'referrer_commission',
'status', 'scheduled_payment_date',
])
->orderBy('partner_id')
->orderBy('scheduled_payment_date')
->get();
$partnerInfo = SalesPartner::with('user')
->whereIn('id', $data->pluck('partner_id'))
->get()
->keyBy('id');
$commissionTotal = fn ($item) => $item->partner_commission + $item->manager_commission + ($item->referrer_commission ?? 0);
return $data->map(function ($row) use ($partnerInfo) {
$partner = $partnerInfo->get($row->partner_id);
$row->partner_name = $partner?->user?->name ?? 'N/A';
$row->partner_type = $partner?->partner_type ?? '';
$row->completion_rate = $row->total_amount > 0 ? round(($row->paid_amount / $row->total_amount) * 100, 1) : 0;
return $row;
});
return $data->groupBy('partner_id')->map(function ($items, $partnerId) use ($commissionTotal) {
$partner = $items->first()->partner;
return (object) [
'partner_id' => $partnerId,
'partner_name' => $partner?->user?->name ?? 'N/A',
'partner_type' => $partner?->partner_type ?? '',
'items' => $items,
'contract_count' => $items->count(),
'first_commission' => $items->where('payment_type', 'deposit')->sum($commissionTotal),
'second_commission' => $items->where('payment_type', 'balance')->sum($commissionTotal),
'total_amount' => $items->sum($commissionTotal),
'paid_amount' => $items->where('status', 'paid')->sum($commissionTotal),
'unpaid_amount' => $items->whereIn('status', ['pending', 'approved'])->sum($commissionTotal),
];
})->sortByDesc('total_amount')->values();
}
/**
@@ -661,6 +663,7 @@ private function getManagerSettlement(\Closure $baseQuery): \Illuminate\Support\
$manager = $managerInfo->get($row->manager_user_id);
$row->manager_name = $manager?->name ?? 'N/A';
$row->completion_rate = $row->total_manager > 0 ? round(($row->paid_amount / $row->total_manager) * 100, 1) : 0;
return $row;
});
}
@@ -681,8 +684,8 @@ private function getCustomerStats(): array
->where('deposit_status', 'paid')
->sum('deposit_amount')
+ (clone $baseQuery)
->where('balance_status', 'paid')
->sum('balance_amount');
->where('balance_status', 'paid')
->sum('balance_amount');
// 미수금
$uncollectedAmount = $totalFee - $collectedAmount;