From c97776892ee87985a369005831738697317a0622 Mon Sep 17 00:00:00 2001 From: sky121113 Date: Wed, 8 Apr 2026 17:41:26 +0800 Subject: [PATCH] =?UTF-8?q?[FEAT]=20=E5=84=AA=E5=8C=96=E5=AE=A2=E6=88=B6?= =?UTF-8?q?=E5=90=88=E7=B4=84=E7=AE=A1=E7=90=86=E4=BB=8B=E9=9D=A2=E8=88=87?= =?UTF-8?q?=E4=BF=AE=E5=BE=A9=E6=97=A5=E6=9C=9F=E5=81=8F=E7=A7=BB=E5=95=8F?= =?UTF-8?q?=E9=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 整合「客戶詳情」與「合約歷程」至單一側邊欄,改用分頁 (Tabs) 切換介面。 2. 優化清單「服務期程」顯示:根據客戶模式(租賃/買斷)動態顯示對應期間,並使用完整文字標籤取代縮寫。 3. 修復日期 Bug:在 Company 模型指定日期序列化格式為 Y-m-d,解決時區轉換導致的日期減少一天問題。 4. 新增合約歷程資料表模型、遷移檔以及對應的多語系翻譯(中、英、日)。 5. 移除清單操作列中重複的合約歷程圖示。 --- .../Controllers/Admin/CompanyController.php | 45 ++- app/Models/System/Company.php | 20 +- app/Models/System/CompanyContract.php | 50 +++ ..._add_contract_dates_to_companies_table.php | 36 ++ ..._165000_create_company_contracts_table.php | 39 +++ lang/en.json | 28 +- lang/ja.json | 28 +- lang/zh_TW.json | 30 +- .../views/admin/companies/index.blade.php | 310 +++++++++++++++--- 9 files changed, 530 insertions(+), 56 deletions(-) create mode 100644 app/Models/System/CompanyContract.php create mode 100644 database/migrations/2026_04_08_164500_add_contract_dates_to_companies_table.php create mode 100644 database/migrations/2026_04_08_165000_create_company_contracts_table.php diff --git a/app/Http/Controllers/Admin/CompanyController.php b/app/Http/Controllers/Admin/CompanyController.php index 3db60ed..aba2016 100644 --- a/app/Http/Controllers/Admin/CompanyController.php +++ b/app/Http/Controllers/Admin/CompanyController.php @@ -14,7 +14,8 @@ class CompanyController extends Controller */ public function index(Request $request) { - $query = Company::query()->withCount(['users', 'machines']); + $query = Company::query()->withCount(['users', 'machines']) + ->with(['contracts.creator:id,name']); // 搜尋 if ($search = $request->input('search')) { @@ -55,6 +56,10 @@ class CompanyController extends Controller 'contact_email' => 'nullable|email|max:255', 'start_date' => 'required|date', 'end_date' => 'nullable|date', + 'warranty_start_date' => 'nullable|date', + 'warranty_end_date' => 'nullable|date', + 'software_start_date' => 'nullable|date', + 'software_end_date' => 'nullable|date', 'status' => 'required|boolean', 'note' => 'nullable|string', 'settings' => 'nullable|array', @@ -83,11 +88,28 @@ class CompanyController extends Controller 'contact_email' => $validated['contact_email'] ?? null, 'start_date' => $validated['start_date'] ?? null, 'end_date' => $validated['end_date'] ?? null, + 'warranty_start_date' => $validated['warranty_start_date'] ?? null, + 'warranty_end_date' => $validated['warranty_end_date'] ?? null, + 'software_start_date' => $validated['software_start_date'] ?? null, + 'software_end_date' => $validated['software_end_date'] ?? null, 'status' => $validated['status'], 'note' => $validated['note'] ?? null, 'settings' => $validated['settings'] ?? [], ]); + // 記錄合約歷程 + $company->contracts()->create([ + 'type' => $company->original_type, + 'start_date' => $company->start_date, + 'end_date' => $company->end_date, + 'warranty_start_date' => $company->warranty_start_date, + 'warranty_end_date' => $company->warranty_end_date, + 'software_start_date' => $company->software_start_date, + 'software_end_date' => $company->software_end_date, + 'note' => __('Initial contract registration'), + 'creator_id' => auth()->id(), + ]); + // 如果有填寫帳號資訊,則建立管理員帳號 if (!empty($validated['admin_username']) && !empty($validated['admin_password'])) { $user = \App\Models\System\User::create([ @@ -143,6 +165,10 @@ class CompanyController extends Controller 'contact_email' => 'nullable|email|max:255', 'start_date' => 'required|date', 'end_date' => 'nullable|date', + 'warranty_start_date' => 'nullable|date', + 'warranty_end_date' => 'nullable|date', + 'software_start_date' => 'nullable|date', + 'software_end_date' => 'nullable|date', 'status' => 'required|boolean', 'note' => 'nullable|string', 'settings' => 'nullable|array', @@ -154,7 +180,22 @@ class CompanyController extends Controller $validated['settings']['enable_points'] = filter_var($validated['settings']['enable_points'] ?? false, FILTER_VALIDATE_BOOLEAN); } - $company->update($validated); + DB::transaction(function () use ($validated, $company) { + $company->update($validated); + + // 記錄合約歷程 + $company->contracts()->create([ + 'type' => $company->current_type, + 'start_date' => $company->start_date, + 'end_date' => $company->end_date, + 'warranty_start_date' => $company->warranty_start_date, + 'warranty_end_date' => $company->warranty_end_date, + 'software_start_date' => $company->software_start_date, + 'software_end_date' => $company->software_end_date, + 'note' => $validated['note'] ?? __('Contract information updated'), + 'creator_id' => auth()->id(), + ]); + }); // 分支邏輯:若停用客戶,連帶停用其所有帳號 if ($validated['status'] == 0) { diff --git a/app/Models/System/Company.php b/app/Models/System/Company.php index a7bf51a..f0f9202 100644 --- a/app/Models/System/Company.php +++ b/app/Models/System/Company.php @@ -25,17 +25,33 @@ class Company extends Model 'status', 'start_date', 'end_date', + 'warranty_start_date', + 'warranty_end_date', + 'software_start_date', + 'software_end_date', 'note', 'settings', ]; protected $casts = [ - 'start_date' => 'date', - 'end_date' => 'date', + 'start_date' => 'date:Y-m-d', + 'end_date' => 'date:Y-m-d', + 'warranty_start_date' => 'date:Y-m-d', + 'warranty_end_date' => 'date:Y-m-d', + 'software_start_date' => 'date:Y-m-d', + 'software_end_date' => 'date:Y-m-d', 'status' => 'integer', 'settings' => 'array', ]; + /** + * Get the contract history for the company. + */ + public function contracts(): HasMany + { + return $this->hasMany(CompanyContract::class)->latest(); + } + /** * Get the users for the company. */ diff --git a/app/Models/System/CompanyContract.php b/app/Models/System/CompanyContract.php new file mode 100644 index 0000000..8d1a56e --- /dev/null +++ b/app/Models/System/CompanyContract.php @@ -0,0 +1,50 @@ + 'date:Y-m-d', + 'end_date' => 'date:Y-m-d', + 'warranty_start_date' => 'date:Y-m-d', + 'warranty_end_date' => 'date:Y-m-d', + 'software_start_date' => 'date:Y-m-d', + 'software_end_date' => 'date:Y-m-d', + ]; + + /** + * Get the company that owns the contract. + */ + public function company(): BelongsTo + { + return $this->belongsTo(Company::class); + } + + /** + * Get the user who created the record. + */ + public function creator(): BelongsTo + { + return $this->belongsTo(User::class, 'creator_id'); + } +} diff --git a/database/migrations/2026_04_08_164500_add_contract_dates_to_companies_table.php b/database/migrations/2026_04_08_164500_add_contract_dates_to_companies_table.php new file mode 100644 index 0000000..a5bd48f --- /dev/null +++ b/database/migrations/2026_04_08_164500_add_contract_dates_to_companies_table.php @@ -0,0 +1,36 @@ +date('warranty_start_date')->nullable()->after('end_date')->comment('保固起始日'); + $table->date('warranty_end_date')->nullable()->after('warranty_start_date')->comment('保固結束日'); + $table->date('software_start_date')->nullable()->after('warranty_end_date')->comment('軟體服務起始日'); + $table->date('software_end_date')->nullable()->after('software_start_date')->comment('軟體服務結束日'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('companies', function (Blueprint $table) { + $table->dropColumn([ + 'warranty_start_date', + 'warranty_end_date', + 'software_start_date', + 'software_end_date' + ]); + }); + } +}; diff --git a/database/migrations/2026_04_08_165000_create_company_contracts_table.php b/database/migrations/2026_04_08_165000_create_company_contracts_table.php new file mode 100644 index 0000000..b60ea78 --- /dev/null +++ b/database/migrations/2026_04_08_165000_create_company_contracts_table.php @@ -0,0 +1,39 @@ +id(); + $table->foreignId('company_id')->constrained()->onDelete('cascade'); + $table->string('type')->comment('buyout, lease'); + $table->date('start_date')->nullable(); + $table->date('end_date')->nullable(); + $table->date('warranty_start_date')->nullable(); + $table->date('warranty_end_date')->nullable(); + $table->date('software_start_date')->nullable(); + $table->date('software_end_date')->nullable(); + $table->text('note')->nullable(); + $table->foreignId('creator_id')->nullable()->constrained('users'); + $table->timestamps(); + + $table->index(['company_id', 'created_at']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('company_contracts'); + } +}; diff --git a/lang/en.json b/lang/en.json index 06e11cc..a8bdf4c 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1119,5 +1119,31 @@ "Model changed to :model": "Model changed to :model", "User logged in: :name": "User logged in: :name", "Login failed: :account": "Login failed: :account", - "Unauthorized login attempt: :account": "Unauthorized login attempt: :account" + "Unauthorized login attempt: :account": "Unauthorized login attempt: :account", + "Contract Model": "Contract Model", + "Warranty Service": "Warranty Service", + "Software Service": "Software Service", + "Modification History": "Modification History", + "No history records": "No history records", + "Initial contract registration": "Initial contract registration", + "Contract information updated": "Contract information updated", + "Warranty Start": "Warranty Start", + "Warranty End": "Warranty End", + "Software Start": "Software Start", + "Software End": "Software End", + "Contract History": "Contract History", + "Unlimited": "Unlimited", + "Change Note": "Change Note", + "Log Time": "Log Time", + "Service Periods": "Service Periods", + "Creator": "Creator", + "View Full History": "View Full History", + "Contract Start": "Contract Start", + "Contract End": "Contract End", + "Contract History Detail": "Contract History Detail", + "by": "by", + "Service Terms": "Service Periods", + "Contract": "Contract", + "Warranty": "Warranty", + "Software": "Software" } \ No newline at end of file diff --git a/lang/ja.json b/lang/ja.json index ce6787d..5a97e8b 100644 --- a/lang/ja.json +++ b/lang/ja.json @@ -1118,5 +1118,31 @@ "Model changed to :model": "モデル変更::model", "User logged in: :name": "ユーザーログイン::name", "Login failed: :account": "ログイン失敗::account", - "Unauthorized login attempt: :account": "不許可のログイン試行::account" + "Unauthorized login attempt: :account": "不許可のログイン試行::account", + "Contract Model": "契約モデル", + "Warranty Service": "保証サービス", + "Software Service": "ソフトウェアサービス", + "Modification History": "変更履歴", + "No history records": "履歴なし", + "Initial contract registration": "初期契約登録", + "Contract information updated": "契約情報更新", + "Warranty Start": "保証開始", + "Warranty End": "保証終了", + "Software Start": "ソフト開始", + "Software End": "ソフト終了", + "Contract History": "契約履歴", + "Unlimited": "無期限", + "Change Note": "変更メモ", + "Log Time": "記録時間", + "Service Periods": "サービス期間", + "Creator": "作成者", + "View Full History": "全履歴を表示", + "Contract Start": "契約開始", + "Contract End": "契約終了", + "Contract History Detail": "契約履歴の詳細", + "by": "作成者:", + "Service Terms": "サービス期間", + "Contract": "契約", + "Warranty": "保証", + "Software": "ソフトウェア" } \ No newline at end of file diff --git a/lang/zh_TW.json b/lang/zh_TW.json index e4a1870..c9dbe6e 100644 --- a/lang/zh_TW.json +++ b/lang/zh_TW.json @@ -677,7 +677,7 @@ "Pending": "等待機台領取", "pending": "等待機台領取", "Performance": "效能 (Performance)", - "Permanent": "永久授權", + "Permanent": "永久", "Permanently Delete Account": "永久刪除帳號", "Permission Settings": "權限設定", "Permissions": "權限", @@ -1119,5 +1119,31 @@ "Model changed to :model": "型號變更::model", "User logged in: :name": "使用者登入::name", "Login failed: :account": "登入失敗::account", - "Unauthorized login attempt: :account": "越權登入嘗試::account" + "Unauthorized login attempt: :account": "越權登入嘗試::account", + "Contract Model": "合約模式", + "Warranty Service": "保固服務", + "Software Service": "軟體服務", + "Modification History": "異動歷程", + "No history records": "尚無歷史紀錄", + "Initial contract registration": "初始合約註冊", + "Contract information updated": "合約資訊已更新", + "Warranty Start": "保固起始", + "Warranty End": "保固結束", + "Software Start": "軟體起始", + "Software End": "軟體結束", + "Contract History": "合約歷程", + "Unlimited": "無限期", + "Change Note": "異動備註", + "Log Time": "記錄時間", + "Service Periods": "服務區間", + "Creator": "建立者", + "View Full History": "查看完整歷程", + "Contract Start": "合約起始", + "Contract End": "合約結束", + "Contract History Detail": "合約歷程詳情", + "by": "由", + "Service Terms": "服務期程", + "Contract": "合約", + "Warranty": "保固", + "Software": "軟體" } \ No newline at end of file diff --git a/resources/views/admin/companies/index.blade.php b/resources/views/admin/companies/index.blade.php index f0cb779..3b4b5de 100644 --- a/resources/views/admin/companies/index.blade.php +++ b/resources/views/admin/companies/index.blade.php @@ -2,8 +2,11 @@ @section('content')
@@ -164,7 +207,7 @@ {{ __('Accounts / Machines') }} - {{ __('Contract Period') }} + {{ __('Service Terms') }} {{ __('Actions') }} @@ -235,20 +278,53 @@
- -
-
- {{ __('From:') }} - - {{ $company->start_date ? $company->start_date->format('Y-m-d') : '--' }} + +
+ + @if($company->current_type === 'lease') +
+ + {{ __('Contract') }} +
+ {{ $company->start_date ? $company->start_date->format('Y-m-d') : '--' }} + ~ + + {{ $company->end_date ? $company->end_date->format('Y-m-d') : __('Permanent') }} + +
-
- {{ __('To:') }} - - {{ $company->end_date ? $company->end_date->format('Y-m-d') : __('Permanent') }} + @endif + + @if($company->current_type === 'buyout') + +
+ + {{ __('Warranty') }} +
+ {{ $company->warranty_start_date ? $company->warranty_start_date->format('Y-m-d') : '--' }} + ~ + + {{ $company->warranty_end_date ? $company->warranty_end_date->format('Y-m-d') : '--' }} + +
+ + +
+ + {{ __('Software') }} + +
+ {{ $company->software_start_date ? $company->software_start_date->format('Y-m-d') : '--' }} + ~ + + {{ $company->software_end_date ? $company->software_end_date->format('Y-m-d') : '--' }} + +
+
+ @endif
@@ -447,11 +523,11 @@
-
+
-
@@ -462,6 +538,38 @@
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+ + +
@@ -652,7 +760,7 @@
-

{{ __('Customer Details') }}

+

@@ -666,7 +774,19 @@
-
+
+ +
+ + +
+ + +

{{ __('Account Status') }}

@@ -690,38 +810,56 @@
-
-

{{ __('Business Type') }}

-
-
- {{ __('Original:') }} - -
-
- {{ __('Current:') }} - +
+
+
+

{{ __('Contract Model') }}

+ + +
+ + + + + +
- -
-

{{ __('Contract Period') }}

-
-
- {{ __('From:') }} -
-
-
- {{ __('To:') }} -
-
-
-
@@ -803,6 +941,82 @@

+
+ + +
+ + +
+
+ +
+

{{ __('No history records') }}

+
+
@@ -815,7 +1029,7 @@
- +