1. 修正客戶管理頁面 H1 標題與麵包屑導覽路徑。 2. 在機台編輯頁面實作分頁功能(基本、營運、機台系統設定)。 3. 實作極簡奢華風的機台系統設定 UI,按功能模組(電子發票、刷卡、支付、購物車等)進行卡片式分組。 4. 將系統設定資料從 Company JSON 遷移至 Machine 資料表獨立欄位,並更新關聯控制器與模型邏輯。 5. 清理 CompanyController 與視圖中的冗餘設定邏輯。 6. 完成現有資料遷移,確保機台正確繼承客戶層級之設定。 7. 優化倉儲管理「現有庫存」矩陣視圖與導覽功能。
265 lines
11 KiB
PHP
265 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\System\Company;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class CompanyController extends Controller
|
|
{
|
|
/**
|
|
* Display a listing of the resource.
|
|
*/
|
|
public function index(Request $request)
|
|
{
|
|
$query = Company::query()->withCount(['users', 'machines'])
|
|
->with(['contracts.creator:id,name']);
|
|
|
|
// 搜尋
|
|
if ($search = $request->input('search')) {
|
|
$query->where(function($q) use ($search) {
|
|
$q->where('name', 'like', "%{$search}%")
|
|
->orWhere('code', 'like', "%{$search}%");
|
|
});
|
|
}
|
|
|
|
// 狀態篩選
|
|
if ($request->filled('status')) {
|
|
$query->where('status', $request->status);
|
|
}
|
|
|
|
$per_page = $request->input('per_page', 10);
|
|
$companies = $query->latest()->paginate($per_page)->withQueryString();
|
|
|
|
// 取得可供選擇的客戶角色範本 (系統層級的角色,排除 super-admin)
|
|
$template_roles = \App\Models\System\Role::whereNull('company_id')
|
|
->where('name', '!=', 'super-admin')
|
|
->get();
|
|
|
|
return view('admin.companies.index', compact('companies', 'template_roles'));
|
|
}
|
|
|
|
/**
|
|
* Store a newly created resource in storage.
|
|
*/
|
|
public function store(Request $request)
|
|
{
|
|
$validated = $request->validate([
|
|
'name' => 'required|string|max:255',
|
|
'code' => 'required|string|max:50|unique:companies,code',
|
|
'original_type' => 'required|string|in:buyout,lease',
|
|
'tax_id' => 'nullable|string|max:50',
|
|
'contact_name' => 'nullable|string|max:255',
|
|
'contact_phone' => 'nullable|string|max:50',
|
|
'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',
|
|
// 帳號相關欄位 (可選)
|
|
'admin_username' => 'nullable|string|max:255|unique:users,username',
|
|
'admin_password' => 'nullable|string|min:8',
|
|
'admin_name' => 'nullable|string|max:255',
|
|
'admin_role' => 'nullable|string|exists:roles,name',
|
|
]);
|
|
|
|
// 確保 settings 中的值為布林值
|
|
if (isset($validated['settings'])) {
|
|
$validated['settings']['enable_material_code'] = filter_var($validated['settings']['enable_material_code'] ?? false, FILTER_VALIDATE_BOOLEAN);
|
|
$validated['settings']['enable_points'] = filter_var($validated['settings']['enable_points'] ?? false, FILTER_VALIDATE_BOOLEAN);
|
|
}
|
|
|
|
DB::transaction(function () use ($validated) {
|
|
$company = Company::create([
|
|
'name' => $validated['name'],
|
|
'code' => $validated['code'],
|
|
'original_type' => $validated['original_type'],
|
|
'current_type' => $validated['original_type'], // 新增時同步
|
|
'tax_id' => $validated['tax_id'] ?? null,
|
|
'contact_name' => $validated['contact_name'] ?? null,
|
|
'contact_phone' => $validated['contact_phone'] ?? null,
|
|
'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([
|
|
'company_id' => $company->id,
|
|
'username' => $validated['admin_username'],
|
|
'password' => \Illuminate\Support\Facades\Hash::make($validated['admin_password']),
|
|
'name' => $validated['admin_name'] ?: ($validated['contact_name'] ?: $validated['name']),
|
|
'status' => 1,
|
|
]);
|
|
|
|
// 角色初始化與克隆邏輯 (優先使用選擇的角色,否則使用預設)
|
|
$selected_role_name = $validated['admin_role'] ?? '客戶管理員角色模板';
|
|
$role_to_assign = null;
|
|
|
|
$template_role = \App\Models\System\Role::where('name', $selected_role_name)
|
|
->whereNull('company_id')
|
|
->where('name', '!=', 'super-admin')
|
|
->first();
|
|
|
|
if ($template_role) {
|
|
// 克隆範本為該公司的「管理員」
|
|
$role_to_assign = \App\Models\System\Role::query()->create([
|
|
'name' => '管理員',
|
|
'guard_name' => 'web',
|
|
'company_id' => $company->id,
|
|
'is_system' => false,
|
|
]);
|
|
$role_to_assign->syncPermissions($template_role->getPermissionNames());
|
|
} else {
|
|
// 如果找不到選定的角色範本,退而求其次嘗試指派現有角色 (通常不應發生)
|
|
$role_to_assign = $selected_role_name;
|
|
}
|
|
|
|
$user->assignRole($role_to_assign);
|
|
}
|
|
});
|
|
|
|
return redirect()->back()->with('success', __('Customer created successfully.'));
|
|
}
|
|
|
|
/**
|
|
* Update the specified resource in storage.
|
|
*/
|
|
public function update(Request $request, Company $company)
|
|
{
|
|
$validated = $request->validate([
|
|
'name' => 'required|string|max:255',
|
|
'code' => 'required|string|max:50|unique:companies,code,' . $company->id,
|
|
'current_type' => 'required|string|in:buyout,lease',
|
|
'tax_id' => 'nullable|string|max:50',
|
|
'contact_name' => 'nullable|string|max:255',
|
|
'contact_phone' => 'nullable|string|max:50',
|
|
'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',
|
|
]);
|
|
|
|
// 確保 settings 中的值為布林值,避免 JSON 存儲為字串導致前端判斷錯誤
|
|
if (isset($validated['settings'])) {
|
|
$validated['settings']['enable_material_code'] = filter_var($validated['settings']['enable_material_code'] ?? false, FILTER_VALIDATE_BOOLEAN);
|
|
$validated['settings']['enable_points'] = filter_var($validated['settings']['enable_points'] ?? false, FILTER_VALIDATE_BOOLEAN);
|
|
}
|
|
|
|
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) {
|
|
$company->users()->update(['status' => 0]);
|
|
}
|
|
|
|
return redirect()->back()->with('success', __('Customer updated successfully.'));
|
|
}
|
|
|
|
/**
|
|
* 更新客戶的系統設定
|
|
*/
|
|
public function updateSettings(Request $request, Company $company)
|
|
{
|
|
\Log::info('updateSettings payload:', $request->all());
|
|
$settings = $request->input('settings', []);
|
|
|
|
$formattedSettings = [
|
|
'enable_material_code' => filter_var($settings['enable_material_code'] ?? false, FILTER_VALIDATE_BOOLEAN),
|
|
'enable_points' => filter_var($settings['enable_points'] ?? false, FILTER_VALIDATE_BOOLEAN),
|
|
];
|
|
|
|
// Ensure we force save the JSON cast properly
|
|
$company->settings = $formattedSettings;
|
|
$company->save();
|
|
|
|
return redirect()->to(route('admin.permission.companies.index') . '?tab=settings')
|
|
->with('success', __('System settings updated successfully.'));
|
|
}
|
|
|
|
/**
|
|
* 切換客戶狀態
|
|
*/
|
|
public function toggleStatus(Company $company)
|
|
{
|
|
$newStatus = $company->status == 1 ? 0 : 1;
|
|
$company->update(['status' => $newStatus]);
|
|
|
|
// 若切換為停用,同步更新所有旗下帳號
|
|
if ($newStatus == 0) {
|
|
$company->users()->update(['status' => 0]);
|
|
return redirect()->back()->with('success', __('Customer and associated accounts disabled successfully.'));
|
|
}
|
|
|
|
return redirect()->back()->with('success', __('Customer enabled successfully.'));
|
|
}
|
|
|
|
/**
|
|
* Remove the specified resource from storage.
|
|
*/
|
|
public function destroy(Company $company)
|
|
{
|
|
if ($company->users()->count() > 0) {
|
|
return redirect()->back()->with('error', __('Cannot delete company with active accounts.'));
|
|
}
|
|
|
|
// 為了解決軟刪除導致的唯一索引佔用問題,刪除前先重新命名唯一欄位
|
|
$timestamp = now()->getTimestamp();
|
|
$company->code = $company->code . '.deleted.' . $timestamp;
|
|
$company->save();
|
|
|
|
$company->delete();
|
|
|
|
return redirect()->back()->with('success', __('Customer deleted successfully.'));
|
|
}
|
|
}
|