diff --git a/app/Http/Controllers/Sales/SalesContractController.php b/app/Http/Controllers/Sales/SalesContractController.php index f1ed494b..c29e0146 100644 --- a/app/Http/Controllers/Sales/SalesContractController.php +++ b/app/Http/Controllers/Sales/SalesContractController.php @@ -16,11 +16,15 @@ class SalesContractController extends Controller { /** * 계약 상품 저장 (전체 교체 방식) + * - tenant_id 또는 prospect_id 중 하나 필수 */ public function saveProducts(Request $request): JsonResponse { $validated = $request->validate([ - 'tenant_id' => 'required|exists:tenants,id', + 'tenant_id' => 'nullable|exists:tenants,id', + 'prospect_id' => 'nullable|exists:tenant_prospects,id', + 'management_id' => 'nullable|exists:sales_tenant_managements,id', + 'category_id' => 'required|exists:sales_product_categories,id', 'products' => 'required|array', 'products.*.product_id' => 'required|exists:sales_products,id', 'products.*.category_id' => 'required|exists:sales_product_categories,id', @@ -28,15 +32,34 @@ public function saveProducts(Request $request): JsonResponse 'products.*.subscription_fee' => 'required|numeric|min:0', ]); + // tenant_id 또는 prospect_id 중 하나는 필수 + if (empty($validated['tenant_id']) && empty($validated['prospect_id'])) { + return response()->json([ + 'success' => false, + 'message' => 'tenant_id 또는 prospect_id가 필요합니다.', + ], 422); + } + try { - DB::transaction(function () use ($validated) { - $tenantId = $validated['tenant_id']; + $managementId = null; + + DB::transaction(function () use ($validated, &$managementId) { + $tenantId = $validated['tenant_id'] ?? null; + $prospectId = $validated['prospect_id'] ?? null; + $categoryId = $validated['category_id']; // 영업관리 레코드 조회 (없으면 생성) - $management = SalesTenantManagement::findOrCreateByTenant($tenantId); + if ($tenantId) { + $management = SalesTenantManagement::findOrCreateByTenant($tenantId); + } else { + $management = SalesTenantManagement::findOrCreateByProspect($prospectId); + } + $managementId = $management->id; - // 기존 상품 삭제 - SalesContractProduct::where('tenant_id', $tenantId)->delete(); + // 해당 카테고리의 기존 상품 삭제 + SalesContractProduct::where('management_id', $management->id) + ->where('category_id', $categoryId) + ->delete(); // 새 상품 저장 foreach ($validated['products'] as $product) { @@ -51,16 +74,22 @@ public function saveProducts(Request $request): JsonResponse 'created_by' => auth()->id(), ]); } + + // 총 가입비 업데이트 + $totalRegistrationFee = SalesContractProduct::where('management_id', $management->id) + ->sum('registration_fee'); + $management->update(['total_registration_fee' => $totalRegistrationFee]); }); return response()->json([ 'success' => true, 'message' => '계약 상품이 저장되었습니다.', + 'management_id' => $managementId, ]); } catch (\Exception $e) { return response()->json([ 'success' => false, - 'message' => '저장 중 오류가 발생했습니다.', + 'message' => '저장 중 오류가 발생했습니다: ' . $e->getMessage(), ], 500); } } diff --git a/resources/views/sales/modals/partials/product-selection.blade.php b/resources/views/sales/modals/partials/product-selection.blade.php index 46a80235..369435d1 100644 --- a/resources/views/sales/modals/partials/product-selection.blade.php +++ b/resources/views/sales/modals/partials/product-selection.blade.php @@ -2,21 +2,36 @@ @php use App\Models\Sales\SalesProductCategory; use App\Models\Sales\SalesContractProduct; + use App\Models\Sales\SalesTenantManagement; + + // 가망고객/테넌트 모드 확인 + $isProspect = $isProspect ?? false; + $entity = $entity ?? $tenant ?? null; $categories = SalesProductCategory::active() ->ordered() ->with(['products' => fn($q) => $q->active()->ordered()]) ->get(); - // 이미 선택된 상품들 조회 - $selectedProducts = SalesContractProduct::where('tenant_id', $tenant->id) - ->pluck('product_id') - ->toArray(); + // Management ID 조회 (가망고객/테넌트 공통) + if ($isProspect) { + $management = SalesTenantManagement::where('tenant_prospect_id', $entity->id)->first(); + } else { + $management = SalesTenantManagement::where('tenant_id', $entity->id)->first(); + } + $managementId = $management?->id; - // 기존 계약 상품 정보 (가격 커스터마이징 포함) - $contractProducts = SalesContractProduct::where('tenant_id', $tenant->id) - ->get() - ->keyBy('product_id'); + // 이미 선택된 상품들 조회 (management_id 기반) + $selectedProducts = []; + $contractProducts = collect(); + if ($managementId) { + $selectedProducts = SalesContractProduct::where('management_id', $managementId) + ->pluck('product_id') + ->toArray(); + $contractProducts = SalesContractProduct::where('management_id', $managementId) + ->get() + ->keyBy('product_id'); + } @endphp
@@ -153,6 +168,9 @@ function productSelection() { totalSubFee: 0, selectedCount: 0, saving: false, + isProspect: {{ $isProspect ? 'true' : 'false' }}, + entityId: {{ $entity->id }}, + managementId: {{ $managementId ?? 'null' }}, init() { // 카테고리 코드 → ID 매핑 @@ -229,6 +247,20 @@ function productSelection() { subscription_fee: this.productData[id].subFee, })); + // 요청 데이터 구성 (가망고객/테넌트 모드에 따라) + const requestData = { + category_id: currentCategoryId, + products: products, + }; + + if (this.isProspect) { + requestData.prospect_id = this.entityId; + requestData.management_id = this.managementId; + } else { + requestData.tenant_id = this.entityId; + requestData.management_id = this.managementId; + } + const response = await fetch('/sales/contracts/products', { method: 'POST', headers: { @@ -236,16 +268,16 @@ function productSelection() { 'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]').content, 'Accept': 'application/json', }, - body: JSON.stringify({ - tenant_id: {{ $tenant->id }}, - category_id: currentCategoryId, - products: products, - }), + body: JSON.stringify(requestData), }); const result = await response.json(); if (result.success) { alert('상품 선택이 저장되었습니다.'); + // management_id 업데이트 (새로 생성된 경우) + if (result.management_id) { + this.managementId = result.management_id; + } } else { alert(result.message || '저장에 실패했습니다.'); } diff --git a/resources/views/sales/modals/scenario-step.blade.php b/resources/views/sales/modals/scenario-step.blade.php index 537cceed..b6cd3794 100644 --- a/resources/views/sales/modals/scenario-step.blade.php +++ b/resources/views/sales/modals/scenario-step.blade.php @@ -172,9 +172,12 @@ class="border-t border-gray-100"> @endforeach
- {{-- 계약 체결 단계 (Step 6)에서만 상품 선택 컴포넌트 표시 (테넌트 전용) --}} - @if($step['id'] === 6 && $scenarioType === 'sales' && !$isProspectMode) - @include('sales.modals.partials.product-selection', ['tenant' => $entity]) + {{-- 계약 체결 단계 (Step 6)에서만 상품 선택 컴포넌트 표시 --}} + @if($step['id'] === 6 && $scenarioType === 'sales') + @include('sales.modals.partials.product-selection', [ + 'entity' => $entity, + 'isProspect' => $isProspectMode, + ]) @endif {{-- 단계 이동 버튼 --}}