文件还在测试中

This commit is contained in:
2026-08-08 15:53:53 +08:00
parent 5f1e7adb64
commit 8101177cb5
241 changed files with 18074 additions and 22 deletions
+110
View File
@@ -0,0 +1,110 @@
<?php
namespace App\Controllers\PSI;
use App\Controllers\Controller;
use App\Models\PSI\Sales;
use App\Models\PSI\Product;
use App\Models\PSI\Material;
/** 销售出库:内销 + 外贸出口。出库自动扣减库存并校验库存充足 */
class SalesController extends Controller
{
use StockHelper;
public function index()
{
$sales = (new Sales())->all();
return $this->renderSubsys('psi', 'psi/sales', ['sales' => $sales], \psi_nav(), 'sales');
}
public function create()
{
subsys_admin('psi') or \Core\App::forbidden('需要 PSI 管理员权限');
$materials = (new \App\Models\PSI\Material())->all();
$products = (new \App\Models\PSI\Product())->all();
return $this->renderSubsys('psi', 'psi/sale_form', [
'sale' => null, 'materials' => $materials, 'products' => $products,
], \psi_nav(), 'sales');
}
public function store()
{
subsys_admin('psi') or \Core\App::forbidden('需要 PSI 管理员权限');
if (!csrf_check()) return $this->redirect('PSI/sales');
$itemType = $this->post('item_type') === 'material' ? 'material' : 'product';
$itemId = (int)$this->post('item_id');
$qty = (float)$this->post('qty');
$price = (float)$this->post('price');
if ($itemId <= 0 || $qty <= 0) { $this->flash('请选择有效的成品/物料并填写数量'); return $this->redirect('PSI/sales'); }
$model = $itemType === 'product' ? new Product() : new Material();
$item = $model->find($itemId);
if (!$item || (float)($item['stock'] ?? 0) < $qty) {
$this->flash('库存不足,无法出库(当前库存:' . (isset($item) ? (float)$item['stock'] : 0) . '');
return $this->redirect('PSI/sales');
}
$no = 'SO' . date('Ymd') . '-' . substr(uniqid(), -4);
$saleId = (new Sales())->insert([
'order_no' => $no,
'customer' => trim($this->post('customer')),
'channel' => $this->post('channel') === 'export' ? 'export' : 'domestic',
'region' => trim($this->post('region')),
'item_id' => $itemId,
'item_type' => $itemType,
'qty' => $qty,
'price' => $price,
'amount' => $qty * $price,
'status' => 'shipped',
'batch_no' => trim($this->post('batch_no')),
'remark' => trim($this->post('remark')),
'created_at' => date('Y-m-d'),
]);
$this->adjustStock($itemType, $itemId, $qty, 'out', $no, trim($this->post('batch_no')));
$this->flash('销售出库成功,库存已扣减', 'ok');
if ($this->post('auto_print', '1') !== '0') {
return $this->redirect('PSI/sales/print/' . $saleId);
}
return $this->redirect('PSI/sales');
}
public function show($id)
{
$sale = (new Sales())->find($id);
if (!$sale) { \Core\App::notFound('销售记录不存在'); return; }
$itemInfo = $this->lookupItem($sale['item_id'] ?? 0, $sale['item_type'] ?? '');
return $this->renderSubsys('psi', 'psi/sales_show', [
's' => $sale,
'item' => $itemInfo,
], \psi_nav(), 'sales');
}
public function printDoc($id)
{
$sale = (new Sales())->find($id);
if (!$sale) { \Core\App::notFound('销售记录不存在'); return; }
$itemInfo = $this->lookupItem($sale['item_id'] ?? 0, $sale['item_type'] ?? '');
$body = \Core\View::buffer('psi/sales_print', ['s' => $sale, 'item' => $itemInfo]);
echo \psi_print_shell('销售出库单 - ' . e($sale['order_no']), $body);
}
/** 尝试从成品表或物料表查找物品信息 */
private function lookupItem(int $itemId, string $itemType = ''): array
{
if ($itemId <= 0) return ['name' => '—', 'spec' => '', 'unit' => ''];
if ($itemType === 'material') {
$row = (new Material())->find($itemId);
} else {
$row = (new Product())->find($itemId) ?: (new Material())->find($itemId);
}
if ($row) return ['name' => $row['name'] ?? '—', 'spec' => $row['spec'] ?? '', 'unit' => $row['unit'] ?? ''];
return ['name' => '—', 'spec' => '', 'unit' => ''];
}
public function destroy($id)
{
subsys_admin('psi') or \Core\App::forbidden('需要 PSI 管理员权限');
(new Sales())->delete($id);
return $this->redirect('PSI/sales');
}
}