checkLogin(); $user = $this->getCurrentUser(); if ($user['role'] === self::ROLE_SUPER_ADMIN) { return $user; } if ($user['role'] === self::ROLE_ADMIN && ($user['category'] ?? '') === self::CATEGORY_INVENTORY) { return $user; } header('Location: ' . BASE_URL . '/Front/index'); exit; } public function index() { $user = $this->checkCategoryAccess(); $supplier = new Supplier(); $purchaseOrder = new PurchaseOrder(); $inventory = new Inventory(); $salesOrder = new SalesOrder(); $this->assign('title', '进销存概览'); $this->assign('user', $user); $this->assign('activeMenu', 'inventory_dashboard'); $this->assign('supplierCount', count($supplier->getAll())); $this->assign('purchaseCount', $purchaseOrder->getCount()); $this->assign('stockCount', $inventory->getCount()); $this->assign('salesCount', $salesOrder->getCount()); $this->assign('lowStockItems', $inventory->getLowStock()); $this->render(); } // ========== 供应商管理 ========== public function supplier() { $user = $this->checkCategoryAccess(); $supplier = new Supplier(); $suppliers = $supplier->getAll(); $this->assign('title', '供应商管理'); $this->assign('user', $user); $this->assign('activeMenu', 'supplier'); $this->assign('suppliers', $suppliers); $this->render(); } public function supplierAdd() { $user = $this->checkCategoryAccess(); if ($user['role'] !== self::ROLE_SUPER_ADMIN && $user['role'] !== self::ROLE_ADMIN) { exit('无权限访问'); } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $this->csrfVerify(); $data = [ 'name' => trim($_POST['name'] ?? ''), 'contact_person' => trim($_POST['contact_person'] ?? ''), 'phone' => trim($_POST['phone'] ?? ''), 'address' => trim($_POST['address'] ?? ''), 'remark' => trim($_POST['remark'] ?? ''), 'status' => (int)($_POST['status'] ?? 1), ]; if (empty($data['name'])) { $this->assign('error', '供应商名称不能为空'); $this->assign('title', '添加供应商'); $this->assign('user', $user); $this->assign('activeMenu', 'supplier'); $this->assign('csrfToken', $this->csrfToken()); $this->render(); return; } try { $supplier = new Supplier(); $supplier->add($data); header('Location: ' . BASE_URL . '/Inventory/supplier'); exit; } catch (\Throwable $e) { error_log('[supplierAdd] ' . $e->getMessage()); $this->assign('error', '添加失败:' . $e->getMessage()); $this->assign('title', '添加供应商'); $this->assign('user', $user); $this->assign('activeMenu', 'supplier'); $this->assign('csrfToken', $this->csrfToken()); $this->render(); return; } } $this->assign('title', '添加供应商'); $this->assign('user', $user); $this->assign('activeMenu', 'supplier'); $this->assign('csrfToken', $this->csrfToken()); $this->render(); } public function supplierEdit() { $user = $this->checkCategoryAccess(); $id = (int)($_GET['id'] ?? 0); $supplier = new Supplier(); $record = $supplier->getById($id); if (!$record) exit('供应商不存在'); if ($_SERVER['REQUEST_METHOD'] === 'POST') { $this->csrfVerify(); $data = [ 'name' => trim($_POST['name'] ?? ''), 'contact_person' => trim($_POST['contact_person'] ?? ''), 'phone' => trim($_POST['phone'] ?? ''), 'address' => trim($_POST['address'] ?? ''), 'remark' => trim($_POST['remark'] ?? ''), 'status' => (int)($_POST['status'] ?? 1), ]; if (empty($data['name'])) { $this->assign('error', '供应商名称不能为空'); $this->assign('title', '编辑供应商'); $this->assign('user', $user); $this->assign('activeMenu', 'supplier'); $this->assign('record', $record); $this->assign('csrfToken', $this->csrfToken()); $this->render(); return; } try { $supplier->where(['id = :id'], [':id' => $id])->update($data); header('Location: ' . BASE_URL . '/Inventory/supplier'); exit; } catch (\Throwable $e) { error_log('[supplierEdit] ' . $e->getMessage()); $this->assign('error', '更新失败:' . $e->getMessage()); $this->assign('title', '编辑供应商'); $this->assign('user', $user); $this->assign('activeMenu', 'supplier'); $this->assign('record', $record); $this->assign('csrfToken', $this->csrfToken()); $this->render(); return; } } $this->assign('title', '编辑供应商'); $this->assign('user', $user); $this->assign('activeMenu', 'supplier'); $this->assign('record', $record); $this->assign('csrfToken', $this->csrfToken()); $this->render(); } public function supplierDelete() { $this->checkLogin(); $this->requireMethod('post'); $this->csrfVerify(); $id = (int)($_POST['id'] ?? 0); $supplier = new Supplier(); $supplier->delete($id); header('Location: ' . BASE_URL . '/Inventory/supplier'); exit; } // ========== 采购管理 ========== public function purchase() { $user = $this->checkCategoryAccess(); $purchaseOrder = new PurchaseOrder(); $orders = $purchaseOrder->getAll(); $this->assign('title', '采购管理'); $this->assign('user', $user); $this->assign('activeMenu', 'purchase'); $this->assign('orders', $orders); $this->render(); } public function purchaseAdd() { $user = $this->checkCategoryAccess(); if ($user['role'] !== self::ROLE_SUPER_ADMIN && $user['role'] !== self::ROLE_ADMIN) { exit('无权限访问'); } $supplierModel = new Supplier(); $suppliers = $supplierModel->getActiveList(); if ($_SERVER['REQUEST_METHOD'] === 'POST') { $this->csrfVerify(); $supplierId = (int)($_POST['supplier_id'] ?? 0); $supplierInfo = $supplierModel->getById($supplierId); $orderData = [ 'order_no' => trim($_POST['order_no'] ?? ''), 'supplier_id' => $supplierId, 'supplier_name' => $supplierInfo['name'] ?? '', 'order_date' => trim($_POST['order_date'] ?? date('Y-m-d')), 'total_amount' => 0, 'status' => trim($_POST['status'] ?? 'pending'), 'remark' => trim($_POST['remark'] ?? ''), 'operator' => $user['emp_name'], ]; if (empty($orderData['order_no'])) { $this->assign('error', '采购单号不能为空'); $this->assign('title', '添加采购订单'); $this->assign('user', $user); $this->assign('activeMenu', 'purchase'); $this->assign('suppliers', $suppliers); $this->assign('csrfToken', $this->csrfToken()); $this->render(); return; } try { $purchaseOrder = new PurchaseOrder(); $purchaseOrder->add($orderData); $orderId = $this->pdo->lastInsertId(); $productNames = $_POST['product_name'] ?? []; $productModels = $_POST['product_model'] ?? []; $quantities = $_POST['quantity'] ?? []; $units = $_POST['unit'] ?? []; $unitPrices = $_POST['unit_price'] ?? []; $totalAmount = 0; $purchaseItem = new PurchaseItem(); foreach ($productNames as $i => $pname) { if (empty(trim($pname))) continue; $qty = (int)($quantities[$i] ?? 0); $price = (float)($unitPrices[$i] ?? 0); $amount = $qty * $price; $totalAmount += $amount; $purchaseItem->add([ 'order_id' => $orderId, 'product_name' => trim($pname), 'product_model' => trim($productModels[$i] ?? ''), 'quantity' => $qty, 'unit' => trim($units[$i] ?? '个'), 'unit_price' => $price, 'amount' => $amount, ]); } $purchaseOrder->where(['id = :id'], [':id' => $orderId])->update(['total_amount' => $totalAmount]); header('Location: ' . BASE_URL . '/Inventory/purchase'); exit; } catch (\Throwable $e) { error_log('[purchaseAdd] ' . $e->getMessage()); $this->assign('error', '添加失败:' . $e->getMessage()); $this->assign('title', '添加采购订单'); $this->assign('user', $user); $this->assign('activeMenu', 'purchase'); $this->assign('suppliers', $suppliers); $this->assign('csrfToken', $this->csrfToken()); $this->render(); return; } } $this->assign('title', '添加采购订单'); $this->assign('user', $user); $this->assign('activeMenu', 'purchase'); $this->assign('suppliers', $suppliers); $this->assign('csrfToken', $this->csrfToken()); $this->render(); } public function purchaseDetail() { $user = $this->checkCategoryAccess(); $id = (int)($_GET['id'] ?? 0); $purchaseOrder = new PurchaseOrder(); $order = $purchaseOrder->getById($id); if (!$order) exit('订单不存在'); $purchaseItem = new PurchaseItem(); $items = $purchaseItem->getByOrder($id); $this->assign('title', '采购订单详情'); $this->assign('user', $user); $this->assign('activeMenu', 'purchase'); $this->assign('order', $order); $this->assign('items', $items); $this->render(); } public function purchaseEdit() { $user = $this->checkCategoryAccess(); $id = (int)($_GET['id'] ?? 0); $purchaseOrder = new PurchaseOrder(); $order = $purchaseOrder->getById($id); if (!$order) exit('订单不存在'); $supplierModel = new Supplier(); $suppliers = $supplierModel->getActiveList(); $purchaseItem = new PurchaseItem(); $items = $purchaseItem->getByOrder($id); if ($_SERVER['REQUEST_METHOD'] === 'POST') { $this->csrfVerify(); $supplierId = (int)($_POST['supplier_id'] ?? 0); $supplierInfo = $supplierModel->getById($supplierId); $orderData = [ 'order_no' => trim($_POST['order_no'] ?? ''), 'supplier_id' => $supplierId, 'supplier_name' => $supplierInfo['name'] ?? '', 'order_date' => trim($_POST['order_date'] ?? ''), 'status' => trim($_POST['status'] ?? 'pending'), 'remark' => trim($_POST['remark'] ?? ''), ]; try { $purchaseOrder->where(['id = :id'], [':id' => $id])->update($orderData); $purchaseItem->deleteByOrder($id); $productNames = $_POST['product_name'] ?? []; $productModels = $_POST['product_model'] ?? []; $quantities = $_POST['quantity'] ?? []; $units = $_POST['unit'] ?? []; $unitPrices = $_POST['unit_price'] ?? []; $totalAmount = 0; foreach ($productNames as $i => $pname) { if (empty(trim($pname))) continue; $qty = (int)($quantities[$i] ?? 0); $price = (float)($unitPrices[$i] ?? 0); $amount = $qty * $price; $totalAmount += $amount; $purchaseItem->add([ 'order_id' => $id, 'product_name' => trim($pname), 'product_model' => trim($productModels[$i] ?? ''), 'quantity' => $qty, 'unit' => trim($units[$i] ?? '个'), 'unit_price' => $price, 'amount' => $amount, ]); } $purchaseOrder->where(['id = :id'], [':id' => $id])->update(['total_amount' => $totalAmount]); header('Location: ' . BASE_URL . '/Inventory/purchase'); exit; } catch (\Throwable $e) { error_log('[purchaseEdit] ' . $e->getMessage()); $this->assign('error', '更新失败:' . $e->getMessage()); $this->assign('title', '编辑采购订单'); $this->assign('user', $user); $this->assign('activeMenu', 'purchase'); $this->assign('order', $order); $this->assign('items', $items); $this->assign('suppliers', $suppliers); $this->assign('csrfToken', $this->csrfToken()); $this->render(); return; } } $this->assign('title', '编辑采购订单'); $this->assign('user', $user); $this->assign('activeMenu', 'purchase'); $this->assign('order', $order); $this->assign('items', $items); $this->assign('suppliers', $suppliers); $this->assign('csrfToken', $this->csrfToken()); $this->render(); } public function purchaseDelete() { $this->checkLogin(); $this->requireMethod('post'); $this->csrfVerify(); $id = (int)($_POST['id'] ?? 0); $purchaseItem = new PurchaseItem(); $purchaseItem->deleteByOrder($id); $purchaseOrder = new PurchaseOrder(); $purchaseOrder->delete($id); header('Location: ' . BASE_URL . '/Inventory/purchase'); exit; } // ========== 库存管理 ========== public function stock() { $user = $this->checkCategoryAccess(); $inventory = new Inventory(); $stocks = $inventory->getAll(); $this->assign('title', '库存管理'); $this->assign('user', $user); $this->assign('activeMenu', 'stock'); $this->assign('stocks', $stocks); $this->render(); } public function stockAdd() { $user = $this->checkCategoryAccess(); if ($_SERVER['REQUEST_METHOD'] === 'POST') { $this->csrfVerify(); $data = [ 'product_name' => trim($_POST['product_name'] ?? ''), 'product_model' => trim($_POST['product_model'] ?? ''), 'category' => trim($_POST['category'] ?? ''), 'quantity' => (int)($_POST['quantity'] ?? 0), 'unit' => trim($_POST['unit'] ?? '个'), 'unit_price' => (float)($_POST['unit_price'] ?? 0), 'min_stock' => (int)($_POST['min_stock'] ?? 0), 'max_stock' => (int)($_POST['max_stock'] ?? 0), 'warehouse' => trim($_POST['warehouse'] ?? ''), 'location' => trim($_POST['location'] ?? ''), 'remark' => trim($_POST['remark'] ?? ''), ]; if (empty($data['product_name'])) { $this->assign('error', '产品名称不能为空'); $this->assign('title', '添加库存'); $this->assign('user', $user); $this->assign('activeMenu', 'stock'); $this->assign('csrfToken', $this->csrfToken()); $this->render(); return; } try { $inventory = new Inventory(); $inventory->add($data); header('Location: ' . BASE_URL . '/Inventory/stock'); exit; } catch (\Throwable $e) { error_log('[stockAdd] ' . $e->getMessage()); $this->assign('error', '添加失败:' . $e->getMessage()); $this->assign('title', '添加库存'); $this->assign('user', $user); $this->assign('activeMenu', 'stock'); $this->assign('csrfToken', $this->csrfToken()); $this->render(); return; } } $this->assign('title', '添加库存'); $this->assign('user', $user); $this->assign('activeMenu', 'stock'); $this->assign('csrfToken', $this->csrfToken()); $this->render(); } public function stockEdit() { $user = $this->checkCategoryAccess(); $id = (int)($_GET['id'] ?? 0); $inventory = new Inventory(); $record = $inventory->getById($id); if (!$record) exit('库存记录不存在'); if ($_SERVER['REQUEST_METHOD'] === 'POST') { $this->csrfVerify(); $data = [ 'product_name' => trim($_POST['product_name'] ?? ''), 'product_model' => trim($_POST['product_model'] ?? ''), 'category' => trim($_POST['category'] ?? ''), 'quantity' => (int)($_POST['quantity'] ?? 0), 'unit' => trim($_POST['unit'] ?? '个'), 'unit_price' => (float)($_POST['unit_price'] ?? 0), 'min_stock' => (int)($_POST['min_stock'] ?? 0), 'max_stock' => (int)($_POST['max_stock'] ?? 0), 'warehouse' => trim($_POST['warehouse'] ?? ''), 'location' => trim($_POST['location'] ?? ''), 'remark' => trim($_POST['remark'] ?? ''), ]; try { $inventory->where(['id = :id'], [':id' => $id])->update($data); header('Location: ' . BASE_URL . '/Inventory/stock'); exit; } catch (\Throwable $e) { error_log('[stockEdit] ' . $e->getMessage()); $this->assign('error', '更新失败:' . $e->getMessage()); $this->assign('title', '编辑库存'); $this->assign('user', $user); $this->assign('activeMenu', 'stock'); $this->assign('record', $record); $this->assign('csrfToken', $this->csrfToken()); $this->render(); return; } } $this->assign('title', '编辑库存'); $this->assign('user', $user); $this->assign('activeMenu', 'stock'); $this->assign('record', $record); $this->assign('csrfToken', $this->csrfToken()); $this->render(); } public function stockDelete() { $this->checkLogin(); $this->requireMethod('post'); $this->csrfVerify(); $id = (int)($_POST['id'] ?? 0); $inventory = new Inventory(); $inventory->delete($id); header('Location: ' . BASE_URL . '/Inventory/stock'); exit; } // ========== 销售管理 ========== public function sales() { $user = $this->checkCategoryAccess(); $salesOrder = new SalesOrder(); $orders = $salesOrder->getAll(); $this->assign('title', '销售管理'); $this->assign('user', $user); $this->assign('activeMenu', 'sales'); $this->assign('orders', $orders); $this->render(); } public function salesAdd() { $user = $this->checkCategoryAccess(); if ($_SERVER['REQUEST_METHOD'] === 'POST') { $this->csrfVerify(); $orderData = [ 'order_no' => trim($_POST['order_no'] ?? ''), 'customer_name' => trim($_POST['customer_name'] ?? ''), 'order_date' => trim($_POST['order_date'] ?? date('Y-m-d')), 'total_amount' => 0, 'status' => trim($_POST['status'] ?? 'pending'), 'remark' => trim($_POST['remark'] ?? ''), 'operator' => $user['emp_name'], ]; if (empty($orderData['order_no'])) { $this->assign('error', '销售单号不能为空'); $this->assign('title', '添加销售订单'); $this->assign('user', $user); $this->assign('activeMenu', 'sales'); $this->assign('csrfToken', $this->csrfToken()); $this->render(); return; } try { $salesOrder = new SalesOrder(); $salesOrder->add($orderData); $orderId = $this->pdo->lastInsertId(); $productNames = $_POST['product_name'] ?? []; $productModels = $_POST['product_model'] ?? []; $quantities = $_POST['quantity'] ?? []; $units = $_POST['unit'] ?? []; $unitPrices = $_POST['unit_price'] ?? []; $totalAmount = 0; $salesItem = new SalesItem(); foreach ($productNames as $i => $pname) { if (empty(trim($pname))) continue; $qty = (int)($quantities[$i] ?? 0); $price = (float)($unitPrices[$i] ?? 0); $amount = $qty * $price; $totalAmount += $amount; $salesItem->add([ 'order_id' => $orderId, 'product_name' => trim($pname), 'product_model' => trim($productModels[$i] ?? ''), 'quantity' => $qty, 'unit' => trim($units[$i] ?? '个'), 'unit_price' => $price, 'amount' => $amount, ]); } $salesOrder->where(['id = :id'], [':id' => $orderId])->update(['total_amount' => $totalAmount]); header('Location: ' . BASE_URL . '/Inventory/sales'); exit; } catch (\Throwable $e) { error_log('[salesAdd] ' . $e->getMessage()); $this->assign('error', '添加失败:' . $e->getMessage()); $this->assign('title', '添加销售订单'); $this->assign('user', $user); $this->assign('activeMenu', 'sales'); $this->assign('csrfToken', $this->csrfToken()); $this->render(); return; } } $this->assign('title', '添加销售订单'); $this->assign('user', $user); $this->assign('activeMenu', 'sales'); $this->assign('csrfToken', $this->csrfToken()); $this->render(); } public function salesDetail() { $user = $this->checkCategoryAccess(); $id = (int)($_GET['id'] ?? 0); $salesOrder = new SalesOrder(); $order = $salesOrder->getById($id); if (!$order) exit('订单不存在'); $salesItem = new SalesItem(); $items = $salesItem->getByOrder($id); $this->assign('title', '销售订单详情'); $this->assign('user', $user); $this->assign('activeMenu', 'sales'); $this->assign('order', $order); $this->assign('items', $items); $this->render(); } public function salesEdit() { $user = $this->checkCategoryAccess(); $id = (int)($_GET['id'] ?? 0); $salesOrder = new SalesOrder(); $order = $salesOrder->getById($id); if (!$order) exit('订单不存在'); $salesItem = new SalesItem(); $items = $salesItem->getByOrder($id); if ($_SERVER['REQUEST_METHOD'] === 'POST') { $this->csrfVerify(); $orderData = [ 'order_no' => trim($_POST['order_no'] ?? ''), 'customer_name' => trim($_POST['customer_name'] ?? ''), 'order_date' => trim($_POST['order_date'] ?? ''), 'status' => trim($_POST['status'] ?? 'pending'), 'remark' => trim($_POST['remark'] ?? ''), ]; try { $salesOrder->where(['id = :id'], [':id' => $id])->update($orderData); $salesItem->deleteByOrder($id); $productNames = $_POST['product_name'] ?? []; $productModels = $_POST['product_model'] ?? []; $quantities = $_POST['quantity'] ?? []; $units = $_POST['unit'] ?? []; $unitPrices = $_POST['unit_price'] ?? []; $totalAmount = 0; foreach ($productNames as $i => $pname) { if (empty(trim($pname))) continue; $qty = (int)($quantities[$i] ?? 0); $price = (float)($unitPrices[$i] ?? 0); $amount = $qty * $price; $totalAmount += $amount; $salesItem->add([ 'order_id' => $id, 'product_name' => trim($pname), 'product_model' => trim($productModels[$i] ?? ''), 'quantity' => $qty, 'unit' => trim($units[$i] ?? '个'), 'unit_price' => $price, 'amount' => $amount, ]); } $salesOrder->where(['id = :id'], [':id' => $id])->update(['total_amount' => $totalAmount]); header('Location: ' . BASE_URL . '/Inventory/sales'); exit; } catch (\Throwable $e) { error_log('[salesEdit] ' . $e->getMessage()); $this->assign('error', '更新失败:' . $e->getMessage()); $this->assign('title', '编辑销售订单'); $this->assign('user', $user); $this->assign('activeMenu', 'sales'); $this->assign('order', $order); $this->assign('items', $items); $this->assign('csrfToken', $this->csrfToken()); $this->render(); return; } } $this->assign('title', '编辑销售订单'); $this->assign('user', $user); $this->assign('activeMenu', 'sales'); $this->assign('order', $order); $this->assign('items', $items); $this->assign('csrfToken', $this->csrfToken()); $this->render(); } public function salesDelete() { $this->checkLogin(); $this->requireMethod('post'); $this->csrfVerify(); $id = (int)($_POST['id'] ?? 0); $salesItem = new SalesItem(); $salesItem->deleteByOrder($id); $salesOrder = new SalesOrder(); $salesOrder->delete($id); header('Location: ' . BASE_URL . '/Inventory/sales'); exit; } }