199 lines
5.5 KiB
PHP
199 lines
5.5 KiB
PHP
<?php
|
|
|
|
namespace app\common\service;
|
|
|
|
use app\common\logic\InvItemLogic;
|
|
use app\common\validate\InvItemValidate;
|
|
use app\common\traits\crud\CrudServiceTrait;
|
|
use app\common\model\InvItem;
|
|
use support\Request;
|
|
use support\exception\BusinessException;
|
|
|
|
class InvItemService
|
|
{
|
|
|
|
use CrudServiceTrait;
|
|
|
|
/**
|
|
* 指定当前要操作的模型
|
|
*/
|
|
protected string $modelClass = InvItem::class;
|
|
|
|
/**
|
|
* 验证器
|
|
*/
|
|
protected $validator = InvItemValidate::class;
|
|
|
|
protected $logic;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->logic = (new InvItemLogic());
|
|
}
|
|
/**
|
|
* 获取验证器
|
|
*/
|
|
public function getValidator()
|
|
{
|
|
return new $this->validator;
|
|
}
|
|
|
|
/**
|
|
* 构造 CrudUtil 查询配置
|
|
*/
|
|
protected function buildQueryConfig(Request $request, string $scene = 'default'): array
|
|
{
|
|
$p = $request->all();
|
|
|
|
$config = [];
|
|
$config['model'] = $this->modelClass;
|
|
switch ($scene) {
|
|
case 'default':
|
|
$config['where']['status'] = 1;
|
|
$config['order']['sort'] = 'desc';
|
|
$config['order']['id'] = 'desc';
|
|
break;
|
|
case 'index':
|
|
$config['where']['status'] = 1;
|
|
|
|
// 关键字
|
|
if (isset($p['keyword']) && $p['keyword']) {
|
|
$k = '%' . $p['keyword'] . '%';
|
|
foreach (['item_name'] as $col) {
|
|
$config['orWhere'][] = [$col, 'like', $k];
|
|
}
|
|
}
|
|
|
|
$config['order']['sort'] = 'desc';
|
|
$config['order']['id'] = 'desc';
|
|
break;
|
|
case 'show':
|
|
$config['where']['id'] = $p['id'];
|
|
$config['where']['status'] = 1;
|
|
break;
|
|
case 'store':
|
|
break;
|
|
case 'update':
|
|
$config['where']['id'] = $p['id'];
|
|
break;
|
|
case 'destroy':
|
|
$config['where']['id'] = $p['id'];
|
|
break;
|
|
}
|
|
|
|
return $config;
|
|
}
|
|
|
|
/**
|
|
* 生成 8-12 位的物品编码(默认10位)
|
|
*
|
|
* @param int $length 编码长度,默认为10(范围 8-12)
|
|
* @return string 返回大写的字母数字组合编码
|
|
*/
|
|
private function generateItemCode($length = 10)
|
|
{
|
|
// 排除易混淆字符:0, O, o, 1, I, l
|
|
$chars = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
|
|
$code = '';
|
|
$maxIndex = strlen($chars) - 1;
|
|
|
|
for ($i = 0; $i < $length; $i++) {
|
|
$code .= $chars[mt_rand(0, $maxIndex)];
|
|
}
|
|
|
|
return $code;
|
|
}
|
|
|
|
|
|
public function beforeServiceStore($data, Request $request): array
|
|
{
|
|
$data['item_code'] = $this->generateItemCode();
|
|
$data['category_id'] = 0;
|
|
$data['spec_model'] = '';
|
|
$data['unit'] = '件';
|
|
$data['is_consumable'] = 0;
|
|
$data['stock_qty'] = $data['stock_qty']??1;
|
|
$data['location'] = '';
|
|
return $data;
|
|
}
|
|
|
|
|
|
/**
|
|
* 变动物品库存数量
|
|
*
|
|
* @param int $itemId 物品ID
|
|
* @param int $changeQty 变动数量:>0 入库,<0 出库
|
|
* @param bool $allowNegative 是否允许库存变成负数,默认不允许
|
|
*
|
|
* @return InvItem 最新的物品记录
|
|
* @throws BusinessException
|
|
*/
|
|
public function changeStock(int $itemId, int $changeQty, bool $allowNegative = false): InvItem
|
|
{
|
|
if ($changeQty === 0) {
|
|
throw new BusinessException('库存变动数量不能为 0');
|
|
}
|
|
|
|
$now = time();
|
|
|
|
// 构建查询
|
|
$query = InvItem::query()->where('id', $itemId);
|
|
|
|
// 如果不允许负数,并且是出库场景(变动为负)
|
|
if (! $allowNegative && $changeQty < 0) {
|
|
// 要保证:当前 stock_qty >= 出库数量
|
|
$query->where('stock_qty', '>=', -$changeQty);
|
|
}
|
|
|
|
// 使用 increment 实现:UPDATE inv_item SET stock_qty = stock_qty + ?, updated_at = ? WHERE ...
|
|
$affected = $query->increment('stock_qty', $changeQty, [
|
|
'updated_at' => $now,
|
|
]);
|
|
|
|
if ($affected === 0) {
|
|
// 更新不到行:
|
|
// 1) 物品不存在
|
|
// 2) 或者库存不足(不允许负数时)
|
|
$exists = InvItem::query()->where('id', $itemId)->exists();
|
|
if (! $exists) {
|
|
throw new BusinessException('物品不存在');
|
|
}
|
|
throw new BusinessException('库存不足,无法完成库存变动');
|
|
}
|
|
|
|
// 再查一次最新数据返回(在外层事务中也会保持一致)
|
|
/** @var InvItem $item */
|
|
$item = InvItem::query()->find($itemId);
|
|
return $item;
|
|
}
|
|
|
|
/**
|
|
* 出库(减库存,默认不允许负数)
|
|
*/
|
|
public function stockOut(int $itemId, int $qty, bool $allowNegative = false): InvItem
|
|
{
|
|
if ($qty <= 0) {
|
|
throw new BusinessException('出库数量必须大于 0');
|
|
}
|
|
return $this->changeStock($itemId, -$qty, $allowNegative);
|
|
}
|
|
|
|
/**
|
|
* 入库(加库存)
|
|
*/
|
|
public function stockIn(int $itemId, int $qty): InvItem
|
|
{
|
|
if ($qty <= 0) {
|
|
throw new BusinessException('入库数量必须大于 0');
|
|
}
|
|
return $this->changeStock($itemId, $qty, true);
|
|
}
|
|
|
|
/**
|
|
* 获取车型list
|
|
*/
|
|
public function getList()
|
|
{
|
|
return $this->logic->getList();
|
|
}
|
|
} |