feat: 第三阶段业务模块(服务产康/月嫂/进销存)

- 新增3个migration(15张表): service/nanny/inventory
- 新增15个Model + 13个Controller
- 新增55条API路由(总计212条)
- 新增3个前端API模块 + 11个管理页面
- vite build验证通过
This commit is contained in:
li
2026-03-13 20:29:45 +08:00
parent 16bcd9bcf0
commit e7d4d9b414
46 changed files with 2573 additions and 0 deletions
@@ -0,0 +1,17 @@
<?php
namespace App\Http\Controllers\Admin\Inventory;
use App\Http\Controllers\Controller;
use App\Models\Inventory\Inventory;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class InventoryController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = Inventory::query()->with(['warehouse','material']);
$query->when($request->warehouse_id, fn($q, $v) => $q->where('warehouse_id', $v));
$query->when($request->material_id, fn($q, $v) => $q->where('material_id', $v));
return $this->paginate($query->paginate($request->input('per_page', 50)));
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Http\Controllers\Admin\Inventory;
use App\Http\Controllers\Controller;
use App\Models\Inventory\Material;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class MaterialController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = Material::query();
$query->when($request->name, fn($q, $v) => $q->where('name', 'like', "%{$v}%"));
$query->when($request->category, fn($q, $v) => $q->where('category', $v));
$query->when($request->code, fn($q, $v) => $q->where('code', 'like', "%{$v}%"));
return $this->paginate($query->latest()->paginate($request->input('per_page', 15)));
}
public function store(Request $request): JsonResponse
{
$v = $request->validate(['name'=>'required|string|max:100','code'=>'nullable|string|max:50','category'=>'nullable|string|max:50','unit'=>'nullable|string|max:20','spec'=>'nullable|string|max:100','min_stock'=>'sometimes|integer|min:0','shelf_life_days'=>'nullable|integer|min:1','status'=>'sometimes|integer|in:0,1']);
return $this->success(Material::create($v));
}
public function show(Material $material): JsonResponse { return $this->success($material); }
public function update(Request $request, Material $material): JsonResponse { $v = $request->validate(['name'=>'sometimes|string|max:100','code'=>'nullable|string|max:50','category'=>'nullable|string|max:50','unit'=>'nullable|string|max:20','spec'=>'nullable|string|max:100','min_stock'=>'sometimes|integer|min:0','shelf_life_days'=>'nullable|integer|min:1','status'=>'sometimes|integer|in:0,1']); $material->update($v); return $this->success($material); }
public function destroy(Material $material): JsonResponse { $material->delete(); return $this->success(null); }
}
@@ -0,0 +1,44 @@
<?php
namespace App\Http\Controllers\Admin\Inventory;
use App\Http\Controllers\Controller;
use App\Models\Inventory\PurchaseOrder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class PurchaseOrderController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = PurchaseOrder::query()->with(['supplier','auditor']);
$query->when($request->order_no, fn($q, $v) => $q->where('order_no', 'like', "%{$v}%"));
$query->when($request->supplier_id, fn($q, $v) => $q->where('supplier_id', $v));
$query->when($request->has('status'), fn($q) => $q->where('status', $request->status));
return $this->paginate($query->latest()->paginate($request->input('per_page', 15)));
}
public function store(Request $request): JsonResponse
{
$v = $request->validate(['order_no'=>'required|string|max:50|unique:purchase_orders','supplier_id'=>'nullable|exists:suppliers,id','total_amount'=>'nullable|numeric|min:0','items'=>'nullable|array','remark'=>'nullable|string']);
$v['status'] = 0; $v['created_by'] = auth()->id();
return $this->success(PurchaseOrder::create($v));
}
public function show(PurchaseOrder $purchaseOrder): JsonResponse { return $this->success($purchaseOrder->load(['supplier','auditor','creator'])); }
public function update(Request $request, PurchaseOrder $purchaseOrder): JsonResponse
{
if ($purchaseOrder->status >= 2) return $this->error('已审批的采购单不可修改', 40001);
$v = $request->validate(['supplier_id'=>'nullable|exists:suppliers,id','total_amount'=>'nullable|numeric|min:0','items'=>'nullable|array','remark'=>'nullable|string']);
$purchaseOrder->update($v);
return $this->success($purchaseOrder);
}
public function audit(Request $request, PurchaseOrder $purchaseOrder): JsonResponse
{
if ($purchaseOrder->status >= 2) return $this->error('已审批', 40001);
$v = $request->validate(['status'=>'required|integer|in:2,4']);
$purchaseOrder->update(['status'=>$v['status'],'audit_user_id'=>auth()->id(),'audit_at'=>now()]);
return $this->success($purchaseOrder);
}
public function destroy(PurchaseOrder $purchaseOrder): JsonResponse
{
if ($purchaseOrder->status >= 2) return $this->error('已审批不可删除', 40001);
$purchaseOrder->delete(); return $this->success(null);
}
}
@@ -0,0 +1,48 @@
<?php
namespace App\Http\Controllers\Admin\Inventory;
use App\Http\Controllers\Controller;
use App\Models\Inventory\StockMovement;
use App\Models\Inventory\Inventory;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class StockMovementController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = StockMovement::query()->with('warehouse');
$query->when($request->warehouse_id, fn($q, $v) => $q->where('warehouse_id', $v));
$query->when($request->type, fn($q, $v) => $q->where('type', $v));
$query->when($request->has('status'), fn($q) => $q->where('status', $request->status));
return $this->paginate($query->latest()->paginate($request->input('per_page', 15)));
}
public function store(Request $request): JsonResponse
{
$v = $request->validate([
'warehouse_id'=>'required|exists:warehouses,id','movement_no'=>'required|string|max:50|unique:stock_movements',
'type'=>'required|integer|in:1,2,3,4','direction'=>'nullable|integer|in:1,2',
'items'=>'nullable|array','related_order'=>'nullable|string|max:50','remark'=>'nullable|string',
]);
$v['status'] = 0; $v['operator_id'] = auth()->id();
return $this->success(StockMovement::create($v));
}
public function show(StockMovement $stockMovement): JsonResponse { return $this->success($stockMovement->load(['warehouse','operator'])); }
public function confirm(StockMovement $stockMovement): JsonResponse
{
if ($stockMovement->status === 1) return $this->error('已确认', 40001);
$stockMovement->update(['status' => 1]);
// 更新库存
if ($stockMovement->items) {
foreach ($stockMovement->items as $item) {
$inv = Inventory::firstOrCreate(
['warehouse_id'=>$stockMovement->warehouse_id,'material_id'=>$item['material_id'],'batch_no'=>$item['batch_no']??null],
['quantity'=>0]
);
$qty = $item['quantity'] ?? 0;
$inv->quantity = $stockMovement->direction === 1 ? $inv->quantity + $qty : $inv->quantity - $qty;
$inv->save();
}
}
return $this->success($stockMovement);
}
}
@@ -0,0 +1,24 @@
<?php
namespace App\Http\Controllers\Admin\Inventory;
use App\Http\Controllers\Controller;
use App\Models\Inventory\Supplier;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class SupplierController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = Supplier::query();
$query->when($request->name, fn($q, $v) => $q->where('name', 'like', "%{$v}%"));
return $this->paginate($query->latest()->paginate($request->input('per_page', 15)));
}
public function store(Request $request): JsonResponse
{
$v = $request->validate(['name'=>'required|string|max:100','contact'=>'nullable|string|max:50','phone'=>'nullable|string|max:20','address'=>'nullable|string|max:255','bank_info'=>'nullable|string|max:255','status'=>'sometimes|integer|in:0,1']);
return $this->success(Supplier::create($v));
}
public function show(Supplier $supplier): JsonResponse { return $this->success($supplier); }
public function update(Request $request, Supplier $supplier): JsonResponse { $v = $request->validate(['name'=>'sometimes|string|max:100','contact'=>'nullable|string|max:50','phone'=>'nullable|string|max:20','address'=>'nullable|string|max:255','bank_info'=>'nullable|string|max:255','status'=>'sometimes|integer|in:0,1']); $supplier->update($v); return $this->success($supplier); }
public function destroy(Supplier $supplier): JsonResponse { $supplier->delete(); return $this->success(null); }
}
@@ -0,0 +1,24 @@
<?php
namespace App\Http\Controllers\Admin\Inventory;
use App\Http\Controllers\Controller;
use App\Models\Inventory\Warehouse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class WarehouseController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = Warehouse::query()->with('manager');
$query->when($request->name, fn($q, $v) => $q->where('name', 'like', "%{$v}%"));
return $this->paginate($query->latest()->paginate($request->input('per_page', 15)));
}
public function store(Request $request): JsonResponse
{
$v = $request->validate(['name'=>'required|string|max:50','manager_id'=>'nullable|exists:users,id','status'=>'sometimes|integer|in:0,1']);
return $this->success(Warehouse::create($v));
}
public function show(Warehouse $warehouse): JsonResponse { return $this->success($warehouse->load('manager')); }
public function update(Request $request, Warehouse $warehouse): JsonResponse { $v = $request->validate(['name'=>'sometimes|string|max:50','manager_id'=>'nullable|exists:users,id','status'=>'sometimes|integer|in:0,1']); $warehouse->update($v); return $this->success($warehouse); }
public function destroy(Warehouse $warehouse): JsonResponse { $warehouse->delete(); return $this->success(null); }
}
@@ -0,0 +1,50 @@
<?php
namespace App\Http\Controllers\Admin\Nanny;
use App\Http\Controllers\Controller;
use App\Models\Nanny\Nanny;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class NannyController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = Nanny::query();
$query->when($request->name, fn($q, $v) => $q->where('name', 'like', "%{$v}%"));
$query->when($request->level, fn($q, $v) => $q->where('level', $v));
$query->when($request->status, fn($q, $v) => $q->where('status', $v));
$query->when($request->cooperation_type, fn($q, $v) => $q->where('cooperation_type', $v));
return $this->paginate($query->latest()->paginate($request->input('per_page', 15)));
}
public function store(Request $request): JsonResponse
{
$validated = $request->validate([
'name'=>'required|string|max:50','phone'=>'nullable|string|max:20','id_card'=>'nullable|string|max:20',
'level'=>'nullable|integer|in:1,2,3,4','skills'=>'nullable|array','experience_years'=>'nullable|integer|min:0',
'health_cert'=>'nullable|string|max:255','cooperation_type'=>'nullable|integer|in:1,2,3',
'base_salary'=>'nullable|numeric|min:0','introduction'=>'nullable|string','status'=>'sometimes|integer|in:1,2,3,4',
]);
return $this->success(Nanny::create($validated));
}
public function show(Nanny $nanny): JsonResponse { return $this->success($nanny->load(['orders.customer','schedules'])); }
public function update(Request $request, Nanny $nanny): JsonResponse
{
$validated = $request->validate([
'name'=>'sometimes|string|max:50','phone'=>'nullable|string|max:20','level'=>'nullable|integer|in:1,2,3,4',
'skills'=>'nullable|array','experience_years'=>'nullable|integer|min:0','cooperation_type'=>'nullable|integer|in:1,2,3',
'base_salary'=>'nullable|numeric|min:0','introduction'=>'nullable|string','status'=>'sometimes|integer|in:1,2,3,4',
]);
$nanny->update($validated);
return $this->success($nanny);
}
public function destroy(Nanny $nanny): JsonResponse
{
if ($nanny->status === 2) return $this->error('服务中的月嫂无法删除', 40001);
$nanny->delete();
return $this->success(null);
}
}
@@ -0,0 +1,55 @@
<?php
namespace App\Http\Controllers\Admin\Nanny;
use App\Http\Controllers\Controller;
use App\Models\Nanny\NannyOrder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class NannyOrderController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = NannyOrder::query()->with(['customer','nanny']);
$query->when($request->customer_id, fn($q, $v) => $q->where('customer_id', $v));
$query->when($request->nanny_id, fn($q, $v) => $q->where('nanny_id', $v));
$query->when($request->has('status'), fn($q) => $q->where('status', $request->status));
return $this->paginate($query->latest()->paginate($request->input('per_page', 15)));
}
public function store(Request $request): JsonResponse
{
$validated = $request->validate([
'customer_id'=>'required|exists:customers,id','nanny_id'=>'nullable|exists:nannies,id',
'order_no'=>'required|string|max:50|unique:nanny_orders','service_type'=>'nullable|integer|in:1,2',
'start_date'=>'nullable|date','end_date'=>'nullable|date|after_or_equal:start_date',
'days'=>'nullable|integer|min:1','price'=>'nullable|numeric|min:0','remark'=>'nullable|string',
]);
$validated['status'] = 0;
$validated['created_by'] = auth()->id();
return $this->success(NannyOrder::create($validated));
}
public function show(NannyOrder $nannyOrder): JsonResponse { return $this->success($nannyOrder->load(['customer','nanny','reviews'])); }
public function update(Request $request, NannyOrder $nannyOrder): JsonResponse
{
if ($nannyOrder->status >= 4) return $this->error('已完成/取消的订单不可修改', 40001);
$validated = $request->validate([
'nanny_id'=>'nullable|exists:nannies,id','start_date'=>'nullable|date','end_date'=>'nullable|date',
'days'=>'nullable|integer|min:1','price'=>'nullable|numeric|min:0','status'=>'sometimes|integer|in:0,1,2,3,4,5',
'match_candidates'=>'nullable|array','remark'=>'nullable|string',
]);
$nannyOrder->update($validated);
if (isset($validated['nanny_id']) && $validated['nanny_id']) {
$nannyOrder->nanny->update(['status' => 2]);
}
return $this->success($nannyOrder);
}
public function destroy(NannyOrder $nannyOrder): JsonResponse
{
if ($nannyOrder->status >= 2) return $this->error('已签约后不可删除', 40001);
$nannyOrder->delete();
return $this->success(null);
}
}
@@ -0,0 +1,27 @@
<?php
namespace App\Http\Controllers\Admin\Nanny;
use App\Http\Controllers\Controller;
use App\Models\Nanny\NannySchedule;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class NannyScheduleController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = NannySchedule::query()->with(['nanny','order']);
$query->when($request->nanny_id, fn($q, $v) => $q->where('nanny_id', $v));
$query->when($request->start_date, fn($q, $v) => $q->where('schedule_date', '>=', $v));
$query->when($request->end_date, fn($q, $v) => $q->where('schedule_date', '<=', $v));
return $this->paginate($query->orderBy('schedule_date')->paginate($request->input('per_page', 31)));
}
public function store(Request $request): JsonResponse
{
$validated = $request->validate([
'nanny_id'=>'required|exists:nannies,id','nanny_order_id'=>'nullable|exists:nanny_orders,id',
'schedule_date'=>'required|date','type'=>'nullable|integer|in:1,2,3','remark'=>'nullable|string|max:255',
]);
return $this->success(NannySchedule::create($validated));
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Http\Controllers\Admin\Service;
use App\Http\Controllers\Controller;
use App\Models\Service\ServiceExecution;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ServiceExecutionController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = ServiceExecution::query()->with(['order','serviceItem','customer','technician']);
$query->when($request->service_order_id, fn($q, $v) => $q->where('service_order_id', $v));
$query->when($request->technician_id, fn($q, $v) => $q->where('technician_id', $v));
$query->when($request->has('status'), fn($q) => $q->where('status', $request->status));
return $this->paginate($query->latest()->paginate($request->input('per_page', 15)));
}
public function store(Request $request): JsonResponse
{
$validated = $request->validate([
'service_order_id'=>'required|exists:service_orders,id','service_item_id'=>'required|exists:service_items,id',
'customer_id'=>'required|exists:customers,id','technician_id'=>'nullable|exists:users,id',
'scheduled_at'=>'nullable|date','remark'=>'nullable|string',
]);
$validated['status'] = 0;
return $this->success(ServiceExecution::create($validated));
}
public function start(ServiceExecution $serviceExecution): JsonResponse
{
if ($serviceExecution->status !== 0) return $this->error('只有待执行可开始', 40001);
$serviceExecution->update(['status'=>1,'started_at'=>now()]);
return $this->success($serviceExecution);
}
public function finish(ServiceExecution $serviceExecution): JsonResponse
{
if ($serviceExecution->status !== 1) return $this->error('只有执行中可完成', 40001);
$serviceExecution->update(['status'=>2,'ended_at'=>now()]);
return $this->success($serviceExecution);
}
}
@@ -0,0 +1,51 @@
<?php
namespace App\Http\Controllers\Admin\Service;
use App\Http\Controllers\Controller;
use App\Models\Service\ServiceItem;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ServiceItemController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = ServiceItem::query();
$query->when($request->name, fn($q, $v) => $q->where('name', 'like', "%{$v}%"));
$query->when($request->category, fn($q, $v) => $q->where('category', $v));
$query->when($request->has('status'), fn($q) => $q->where('status', $request->status));
return $this->paginate($query->latest()->paginate($request->input('per_page', 15)));
}
public function store(Request $request): JsonResponse
{
$validated = $request->validate([
'name' => 'required|string|max:100',
'category' => 'nullable|integer|in:1,2,3,4',
'price' => 'required|numeric|min:0',
'duration' => 'nullable|integer|min:1',
'description' => 'nullable|string',
'image' => 'nullable|string|max:255',
'status' => 'sometimes|integer|in:0,1',
]);
return $this->success(ServiceItem::create($validated));
}
public function show(ServiceItem $serviceItem): JsonResponse { return $this->success($serviceItem); }
public function update(Request $request, ServiceItem $serviceItem): JsonResponse
{
$validated = $request->validate([
'name' => 'sometimes|string|max:100',
'category' => 'nullable|integer|in:1,2,3,4',
'price' => 'sometimes|numeric|min:0',
'duration' => 'nullable|integer|min:1',
'description' => 'nullable|string',
'image' => 'nullable|string|max:255',
'status' => 'sometimes|integer|in:0,1',
]);
$serviceItem->update($validated);
return $this->success($serviceItem);
}
public function destroy(ServiceItem $serviceItem): JsonResponse { $serviceItem->delete(); return $this->success(null); }
}
@@ -0,0 +1,64 @@
<?php
namespace App\Http\Controllers\Admin\Service;
use App\Http\Controllers\Controller;
use App\Models\Service\ServiceOrder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ServiceOrderController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = ServiceOrder::query()->with(['customer']);
$query->when($request->order_no, fn($q, $v) => $q->where('order_no', 'like', "%{$v}%"));
$query->when($request->customer_id, fn($q, $v) => $q->where('customer_id', $v));
$query->when($request->type, fn($q, $v) => $q->where('type', $v));
$query->when($request->has('status'), fn($q) => $q->where('status', $request->status));
return $this->paginate($query->latest()->paginate($request->input('per_page', 15)));
}
public function store(Request $request): JsonResponse
{
$validated = $request->validate([
'customer_id'=>'required|exists:customers,id','order_no'=>'required|string|max:50|unique:service_orders',
'type'=>'nullable|integer|in:1,2,3,4','items'=>'nullable|array',
'total_amount'=>'required|numeric|min:0','discount_amount'=>'sometimes|numeric|min:0','actual_amount'=>'required|numeric|min:0',
'pay_method'=>'nullable|integer|in:1,2,3,4','remark'=>'nullable|string',
]);
$validated['status'] = 0;
$validated['created_by'] = auth()->id();
return $this->success(ServiceOrder::create($validated));
}
public function show(ServiceOrder $serviceOrder): JsonResponse { return $this->success($serviceOrder->load(['customer','executions.serviceItem','executions.technician'])); }
public function update(Request $request, ServiceOrder $serviceOrder): JsonResponse
{
if ($serviceOrder->status >= 2) return $this->error('已完成/取消的订单不可修改', 40001);
$validated = $request->validate(['items'=>'nullable|array','total_amount'=>'sometimes|numeric|min:0','discount_amount'=>'sometimes|numeric|min:0','actual_amount'=>'sometimes|numeric|min:0','remark'=>'nullable|string']);
$serviceOrder->update($validated);
return $this->success($serviceOrder);
}
public function destroy(ServiceOrder $serviceOrder): JsonResponse
{
if ($serviceOrder->status >= 1) return $this->error('已付款的订单不可删除', 40001);
$serviceOrder->delete();
return $this->success(null);
}
public function pay(Request $request, ServiceOrder $serviceOrder): JsonResponse
{
if ($serviceOrder->status !== 0) return $this->error('该订单不可付款', 40001);
$validated = $request->validate(['pay_method'=>'required|integer|in:1,2,3,4']);
$serviceOrder->update(['status'=>1,'pay_method'=>$validated['pay_method'],'paid_at'=>now()]);
return $this->success($serviceOrder);
}
public function complete(ServiceOrder $serviceOrder): JsonResponse
{
if ($serviceOrder->status !== 1) return $this->error('只有已付款的订单可完成', 40001);
$serviceOrder->update(['status'=>2]);
return $this->success($serviceOrder);
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\Http\Controllers\Admin\Service;
use App\Http\Controllers\Controller;
use App\Models\Service\ServicePackage;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ServicePackageController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = ServicePackage::query();
$query->when($request->name, fn($q, $v) => $q->where('name', 'like', "%{$v}%"));
$query->when($request->has('status'), fn($q) => $q->where('status', $request->status));
return $this->paginate($query->latest()->paginate($request->input('per_page', 15)));
}
public function store(Request $request): JsonResponse
{
$validated = $request->validate(['name'=>'required|string|max:100','items'=>'nullable|array','price'=>'required|numeric|min:0','validity_days'=>'nullable|integer|min:1','status'=>'sometimes|integer|in:0,1']);
return $this->success(ServicePackage::create($validated));
}
public function show(ServicePackage $servicePackage): JsonResponse { return $this->success($servicePackage); }
public function update(Request $request, ServicePackage $servicePackage): JsonResponse
{
$validated = $request->validate(['name'=>'sometimes|string|max:100','items'=>'nullable|array','price'=>'sometimes|numeric|min:0','validity_days'=>'nullable|integer|min:1','status'=>'sometimes|integer|in:0,1']);
$servicePackage->update($validated);
return $this->success($servicePackage);
}
public function destroy(ServicePackage $servicePackage): JsonResponse { $servicePackage->delete(); return $this->success(null); }
}
@@ -0,0 +1,13 @@
<?php
namespace App\Models\Inventory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Inventory extends Model
{
const CREATED_AT = null;
protected $table = 'inventories';
protected $fillable = ['warehouse_id','material_id','quantity','batch_no','expire_date'];
protected function casts(): array { return ['quantity'=>'decimal:2','expire_date'=>'date']; }
public function warehouse(): BelongsTo { return $this->belongsTo(Warehouse::class); }
public function material(): BelongsTo { return $this->belongsTo(Material::class); }
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace App\Models\Inventory;
use App\Traits\BelongsToStore;
use Illuminate\Database\Eloquent\Model;
class Material extends Model
{
use BelongsToStore;
protected $fillable = ['store_id','name','code','category','unit','spec','min_stock','shelf_life_days','status'];
protected function casts(): array { return ['min_stock'=>'integer','shelf_life_days'=>'integer','status'=>'integer']; }
}
@@ -0,0 +1,15 @@
<?php
namespace App\Models\Inventory;
use App\Models\User;
use App\Traits\BelongsToStore;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class PurchaseOrder extends Model
{
use BelongsToStore;
protected $fillable = ['store_id','order_no','supplier_id','total_amount','status','items','audit_user_id','audit_at','remark','created_by'];
protected function casts(): array { return ['total_amount'=>'decimal:2','status'=>'integer','items'=>'array','audit_at'=>'datetime']; }
public function supplier(): BelongsTo { return $this->belongsTo(Supplier::class); }
public function auditor(): BelongsTo { return $this->belongsTo(User::class, 'audit_user_id'); }
public function creator(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); }
}
@@ -0,0 +1,14 @@
<?php
namespace App\Models\Inventory;
use App\Models\User;
use App\Traits\BelongsToStore;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class StockMovement extends Model
{
use BelongsToStore;
protected $fillable = ['store_id','warehouse_id','movement_no','type','direction','items','related_order','status','operator_id','remark'];
protected function casts(): array { return ['type'=>'integer','direction'=>'integer','items'=>'array','status'=>'integer']; }
public function warehouse(): BelongsTo { return $this->belongsTo(Warehouse::class); }
public function operator(): BelongsTo { return $this->belongsTo(User::class, 'operator_id'); }
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace App\Models\Inventory;
use App\Traits\BelongsToStore;
use Illuminate\Database\Eloquent\Model;
class Supplier extends Model
{
use BelongsToStore;
protected $fillable = ['store_id','name','contact','phone','address','bank_info','status'];
protected function casts(): array { return ['status'=>'integer']; }
}
@@ -0,0 +1,13 @@
<?php
namespace App\Models\Inventory;
use App\Models\User;
use App\Traits\BelongsToStore;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Warehouse extends Model
{
use BelongsToStore;
protected $fillable = ['store_id','name','manager_id','status'];
protected function casts(): array { return ['status'=>'integer']; }
public function manager(): BelongsTo { return $this->belongsTo(User::class, 'manager_id'); }
}
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace App\Models\Nanny;
use App\Traits\BelongsToStore;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Nanny extends Model
{
use BelongsToStore;
protected $fillable = ['store_id','name','phone','id_card','avatar','level','skills','experience_years','health_cert','cooperation_type','base_salary','introduction','status'];
protected function casts(): array { return ['level'=>'integer','skills'=>'array','experience_years'=>'integer','cooperation_type'=>'integer','base_salary'=>'decimal:2','status'=>'integer']; }
public function orders(): HasMany { return $this->hasMany(NannyOrder::class); }
public function schedules(): HasMany { return $this->hasMany(NannySchedule::class); }
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace App\Models\Nanny;
use App\Models\Crm\Customer;
use App\Models\User;
use App\Traits\BelongsToStore;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class NannyOrder extends Model
{
use BelongsToStore;
protected $fillable = ['store_id','customer_id','nanny_id','order_no','service_type','start_date','end_date','days','price','status','match_candidates','remark','created_by'];
protected function casts(): array { return ['service_type'=>'integer','start_date'=>'date','end_date'=>'date','days'=>'integer','price'=>'decimal:2','status'=>'integer','match_candidates'=>'array']; }
public function customer(): BelongsTo { return $this->belongsTo(Customer::class); }
public function nanny(): BelongsTo { return $this->belongsTo(Nanny::class); }
public function creator(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); }
public function reviews(): HasMany { return $this->hasMany(NannyReview::class); }
}
+14
View File
@@ -0,0 +1,14 @@
<?php
namespace App\Models\Nanny;
use App\Models\Crm\Customer;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class NannyReview extends Model
{
const UPDATED_AT = null;
protected $fillable = ['nanny_order_id','customer_id','nanny_id','score','content'];
protected function casts(): array { return ['score'=>'integer']; }
public function order(): BelongsTo { return $this->belongsTo(NannyOrder::class, 'nanny_order_id'); }
public function customer(): BelongsTo { return $this->belongsTo(Customer::class); }
public function nanny(): BelongsTo { return $this->belongsTo(Nanny::class); }
}
@@ -0,0 +1,12 @@
<?php
namespace App\Models\Nanny;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class NannySchedule extends Model
{
const UPDATED_AT = null;
protected $fillable = ['nanny_id','nanny_order_id','schedule_date','type','remark'];
protected function casts(): array { return ['schedule_date'=>'date','type'=>'integer']; }
public function nanny(): BelongsTo { return $this->belongsTo(Nanny::class); }
public function order(): BelongsTo { return $this->belongsTo(NannyOrder::class, 'nanny_order_id'); }
}
@@ -0,0 +1,15 @@
<?php
namespace App\Models\Service;
use App\Models\Crm\Customer;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class ServiceExecution extends Model
{
protected $fillable = ['service_order_id','service_item_id','customer_id','technician_id','scheduled_at','started_at','ended_at','status','remark'];
protected function casts(): array { return ['scheduled_at'=>'datetime','started_at'=>'datetime','ended_at'=>'datetime','status'=>'integer']; }
public function order(): BelongsTo { return $this->belongsTo(ServiceOrder::class, 'service_order_id'); }
public function serviceItem(): BelongsTo { return $this->belongsTo(ServiceItem::class); }
public function customer(): BelongsTo { return $this->belongsTo(Customer::class); }
public function technician(): BelongsTo { return $this->belongsTo(User::class, 'technician_id'); }
}
@@ -0,0 +1,10 @@
<?php
namespace App\Models\Service;
use App\Traits\BelongsToStore;
use Illuminate\Database\Eloquent\Model;
class ServiceItem extends Model
{
use BelongsToStore;
protected $fillable = ['store_id','name','category','price','duration','description','image','status'];
protected function casts(): array { return ['category'=>'integer','price'=>'decimal:2','duration'=>'integer','status'=>'integer']; }
}
@@ -0,0 +1,17 @@
<?php
namespace App\Models\Service;
use App\Models\Crm\Customer;
use App\Models\User;
use App\Traits\BelongsToStore;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class ServiceOrder extends Model
{
use BelongsToStore;
protected $fillable = ['store_id','customer_id','order_no','type','items','total_amount','discount_amount','actual_amount','status','pay_method','paid_at','created_by'];
protected function casts(): array { return ['type'=>'integer','items'=>'array','total_amount'=>'decimal:2','discount_amount'=>'decimal:2','actual_amount'=>'decimal:2','status'=>'integer','pay_method'=>'integer','paid_at'=>'datetime']; }
public function customer(): BelongsTo { return $this->belongsTo(Customer::class); }
public function creator(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); }
public function executions(): HasMany { return $this->hasMany(ServiceExecution::class); }
}
@@ -0,0 +1,10 @@
<?php
namespace App\Models\Service;
use App\Traits\BelongsToStore;
use Illuminate\Database\Eloquent\Model;
class ServicePackage extends Model
{
use BelongsToStore;
protected $fillable = ['store_id','name','items','price','validity_days','status'];
protected function casts(): array { return ['items'=>'array','price'=>'decimal:2','validity_days'=>'integer','status'=>'integer']; }
}
@@ -0,0 +1,13 @@
<?php
namespace App\Models\Service;
use App\Models\Crm\Customer;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class ServiceReview extends Model
{
const UPDATED_AT = null;
protected $fillable = ['service_order_id','service_execution_id','customer_id','score','content'];
protected function casts(): array { return ['score'=>'integer']; }
public function order(): BelongsTo { return $this->belongsTo(ServiceOrder::class, 'service_order_id'); }
public function customer(): BelongsTo { return $this->belongsTo(Customer::class); }
}