- AI 2단계 분석: 고객 인터뷰 → 요구사항 추출 → 견적 산출 - 모델 확장: AiQuotation(모드/견적번호), AiQuotationItem(규격/단가/금액) - AiQuotePriceTable 모델 신규 생성 - Create 페이지: 모듈/제조 모드 탭, 제품 카테고리, 고객 정보 입력 - Show 페이지: 제조 모드 분기 렌더링 (품목/금액/고객정보) - Edit 페이지: 품목 인라인 편집, 할인/부가세/조건 입력 - Document: 한국 표준 제조업 견적서 양식 템플릿 - Controller/Route: update 엔드포인트, edit 라우트 추가
145 lines
5.8 KiB
PHP
145 lines
5.8 KiB
PHP
@extends('layouts.document')
|
|
|
|
@section('title', '견적서')
|
|
|
|
@push('styles')
|
|
<style>
|
|
/* 템플릿 선택 UI */
|
|
.template-selector { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; padding: 16px 0; }
|
|
.template-card {
|
|
width: 120px; text-decoration: none; color: inherit; border: 2px solid #e5e7eb;
|
|
border-radius: 10px; overflow: hidden; transition: all 0.2s; cursor: pointer;
|
|
}
|
|
.template-card:hover { border-color: #3b82f6; transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
|
|
.template-card.active { border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59,130,246,0.2); }
|
|
.template-card .preview {
|
|
height: 64px; display: flex; align-items: center; justify-content: center;
|
|
font-size: 10px; font-weight: 600; letter-spacing: 0.2em;
|
|
}
|
|
.template-card .label { padding: 6px 0; text-align: center; font-size: 11px; font-weight: 500; background: #f9fafb; }
|
|
.template-card.active .label { background: #eff6ff; color: #1d4ed8; }
|
|
|
|
/* 미리보기 색상 */
|
|
.preview-classic { background: #fff; border-bottom: 2px solid #1f2937; color: #1f2937; }
|
|
.preview-modern { background: #f9fafb; border-bottom: 2px solid #9ca3af; color: #6b7280; }
|
|
.preview-blue { background: linear-gradient(135deg, #1e40af, #3b82f6); color: #fff; }
|
|
.preview-dark { background: #111827; color: #fbbf24; }
|
|
.preview-colorful { background: linear-gradient(135deg, #f59e0b, #ef4444); color: #fff; }
|
|
</style>
|
|
@endpush
|
|
|
|
@section('content')
|
|
@php
|
|
// 한글 금액 변환 함수
|
|
if (!function_exists('numberToKorean')) {
|
|
function numberToKorean(int $number): string {
|
|
return \App\Services\Rd\AiQuotationService::numberToKorean($number);
|
|
}
|
|
}
|
|
|
|
// 견적 모드 판별
|
|
$isManufacture = $quotation->isManufacture();
|
|
|
|
// 템플릿 (기본값: classic)
|
|
$template = $template ?? 'classic';
|
|
|
|
if ($isManufacture) {
|
|
// 제조 견적서 데이터
|
|
$options = $quotation->options ?? [];
|
|
$client = $options['client'] ?? [];
|
|
$project = $options['project'] ?? [];
|
|
$pricing = $options['pricing'] ?? [];
|
|
$terms = $options['terms'] ?? [];
|
|
|
|
$quotationNo = $quotation->quote_number ?? 'AQ-'.$quotation->created_at->format('Y').'-'.str_pad($quotation->id, 3, '0', STR_PAD_LEFT);
|
|
$subtotal = (int) ($pricing['subtotal'] ?? 0);
|
|
$discountRate = (float) ($pricing['discount_rate'] ?? 0);
|
|
$discountAmount = (int) ($pricing['discount_amount'] ?? 0);
|
|
$vatAmount = (int) ($pricing['vat_amount'] ?? 0);
|
|
$finalAmount = (int) ($pricing['final_amount'] ?? 0);
|
|
$subtotalKorean = numberToKorean($subtotal);
|
|
$validUntil = $terms['valid_until'] ?? now()->addDays(30)->format('Y-m-d');
|
|
|
|
$templates = [
|
|
'classic' => '클래식',
|
|
];
|
|
} else {
|
|
// 모듈 추천 견적서 데이터 (기존)
|
|
$quotationNo = 'AQ-' . $quotation->created_at->format('Y') . '-' . str_pad($quotation->id, 3, '0', STR_PAD_LEFT);
|
|
$company = $quotation->analysis_result['company_analysis'] ?? [];
|
|
$plan = $quotation->quotation_result['implementation_plan'] ?? [];
|
|
$estimatedMonths = $plan['estimated_months'] ?? null;
|
|
|
|
$devSubtotal = (int) $quotation->total_dev_cost;
|
|
$monthlySubtotal = (int) $quotation->total_monthly_fee;
|
|
$devVat = (int) round($devSubtotal * 0.1);
|
|
$monthlyVat = (int) round($monthlySubtotal * 0.1);
|
|
$devTotal = $devSubtotal + $devVat;
|
|
$monthlyTotal = $monthlySubtotal + $monthlyVat;
|
|
$devTotalKorean = numberToKorean($devSubtotal);
|
|
$sortedItems = $quotation->items->sortByDesc('is_required')->values();
|
|
|
|
$templates = [
|
|
'classic' => '클래식',
|
|
'modern' => '모던',
|
|
'blue' => '블루',
|
|
'dark' => '다크',
|
|
'colorful' => '컬러풀',
|
|
];
|
|
}
|
|
@endphp
|
|
|
|
{{-- 템플릿 선택 UI (인쇄 시 숨김) --}}
|
|
<div class="no-print" style="max-width: 700px; margin: 24px auto 0;">
|
|
<div class="template-selector">
|
|
@foreach($templates as $key => $label)
|
|
<a href="?template={{ $key }}"
|
|
class="template-card {{ $template === $key ? 'active' : '' }}">
|
|
<div class="preview preview-{{ $key }}">견 적 서</div>
|
|
<div class="label">{{ $label }}</div>
|
|
</a>
|
|
@endforeach
|
|
</div>
|
|
{{-- PDF 다운로드 버튼 --}}
|
|
<div class="text-center mt-3">
|
|
<button onclick="window.print()" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition text-sm">
|
|
<i class="ri-printer-line"></i> 인쇄 / PDF 다운로드
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- 선택된 템플릿 렌더링 --}}
|
|
@if($isManufacture)
|
|
@include('rd.ai-quotation.document-templates.manufacture-classic', [
|
|
'quotation' => $quotation,
|
|
'quotationNo' => $quotationNo,
|
|
'client' => $client,
|
|
'project' => $project,
|
|
'pricing' => $pricing,
|
|
'terms' => $terms,
|
|
'subtotal' => $subtotal,
|
|
'discountRate' => $discountRate,
|
|
'discountAmount' => $discountAmount,
|
|
'vatAmount' => $vatAmount,
|
|
'finalAmount' => $finalAmount,
|
|
'subtotalKorean' => $subtotalKorean,
|
|
'validUntil' => $validUntil,
|
|
])
|
|
@else
|
|
@include('rd.ai-quotation.document-templates.' . $template, [
|
|
'quotation' => $quotation,
|
|
'quotationNo' => $quotationNo,
|
|
'company' => $company,
|
|
'estimatedMonths' => $estimatedMonths,
|
|
'devSubtotal' => $devSubtotal,
|
|
'monthlySubtotal' => $monthlySubtotal,
|
|
'devVat' => $devVat,
|
|
'monthlyVat' => $monthlyVat,
|
|
'devTotal' => $devTotal,
|
|
'monthlyTotal' => $monthlyTotal,
|
|
'devTotalKorean' => $devTotalKorean,
|
|
'sortedItems' => $sortedItems,
|
|
])
|
|
@endif
|
|
@endsection
|