111 lines
4.5 KiB
PHP
111 lines
4.5 KiB
PHP
<?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');
|
||
}
|
||
}
|