This commit is contained in:
mzl
2025-12-09 07:33:04 +00:00
parent 399eaa2b5c
commit 725710abcb
14 changed files with 4213 additions and 1964 deletions
@@ -2,6 +2,7 @@
namespace app\common\service;
use app\common\model\InvRequisition;
use app\common\model\InvRequisitionItem;
use app\common\validate\InvRequisitionItemReturnValidate;
use app\common\traits\crud\CrudServiceTrait;
@@ -268,30 +269,181 @@ class InvRequisitionItemReturnService
InvRequisitionItemReturnAttachment::where('return_id', $returnId)->delete();
}
public function returnConfirm(Request $request, array $data, string $scene = '')
/**
* 物品领用归还确认
*
* @param Request $request
* @param array $data
* @param string $scene
* @return array|bool
* @throws BusinessException
*/
public function serviceReturnConfirm(Request $request, array $data, string $scene = 'returnConfirm')
{
try {
// 关联表增加事务处理
return Db::transaction(function () use ($request, $data) {
$data = $this->preProcess('Update', $data, $request);
$config = $this->buildQueryConfig($request, 'update');
// 归还确认是业务顶层方法,这里统一使用事务
return Db::transaction(function () use ($request, $data, $scene) {
$attachment = $data['attachment'];
unset($data['attachment']);
// 1. 当前操作人信息
$userInfo = (new UserService())->getUserInfo($request->user->uid, '');
if (empty($userInfo['user']['id']) || empty($userInfo['user']['name'])) {
throw new BusinessException('无法获取当前用户信息');
}
$this->logicUpdateBy($config, $data);
// 获取更新后的完整记录
$updated = $this->logicShow($config);
// 处理附件更新
$this->processRequisitionItemReturnAttachment($updated, $attachment, true);
return $this->postProcess('Update', $updated);
$handlerId = (int)$userInfo['user']['id'];
$handlerName = (string)$userInfo['user']['name'];
$data['handler_id'] = $handlerId;
$data['handler_name'] = $handlerName;
// 确认状态:1=通过,2=拒绝 (按你现在用法)
$status = isset($data['status']) ? (int)$data['status'] : null;
if (!in_array($status, [1, 2], true)) {
throw new BusinessException('非法的归还处理状态');
}
// 2. 构建查询配置,定位到这条归还记录
$config = $this->buildQueryConfig($request, $scene);
// 更新时不允许前端覆盖主键
unset($data['requisition_item_return_id']);
// 3. 获取现有记录
/** @var \app\model\InvRequisitionItemReturn|null $existingRecord */
$existingRecord = $this->logicShow($config);
if (!$existingRecord) {
throw new BusinessException('未找到对应的归还申请记录');
}
// 已处理校验:只要归还记录的 status 已经是「通过或拒绝」,就不能再处理
$existingStatus = (int)($existingRecord->status ?? 0);
if (in_array($existingStatus, [1, 2], true) || !empty($existingRecord->handler_id)) {
throw new BusinessException('该归还申请已经被处理过了');
}
// 4. 更新归还记录(状态 + 审核人 + 备注等)
$updateResult = $this->logicUpdateBy($config, $data);
if ($updateResult === 0) {
throw new BusinessException('更新归还申请失败,可能记录不存在或已被处理');
}
// 5. 若是拒绝,直接返回(不改库存、不改已归还数量)
if ($status === 2) {
// 拒绝:这里你返回 true 或者返回更新后的记录都可以
return true;
}
// 6. 审核通过:继续处理领用明细 & 库存 & 领用单状态
// 注意:requisition_item_id、item_id、return_qty 等字段在本次确认流程中不会被修改,
// 所以可以直接使用 $existingRecord 中的值(都是只读字段)
$requisitionItemId = (int)$existingRecord->requisition_item_id;
$itemId = (int)$existingRecord->item_id;
$returnQty = (int)$existingRecord->return_qty;
$requisitionId = (int)$existingRecord->requisition_id;
if ($requisitionItemId <= 0 || $itemId <= 0 || $returnQty <= 0 || $requisitionId <= 0) {
throw new BusinessException('归还申请记录缺少必要字段,无法处理');
}
// 6.1 处理领用明细
/** @var \app\model\InvRequisitionItem|null $item */
$item = InvRequisitionItem::find($requisitionItemId);
if (!$item) {
throw new BusinessException('未找到对应的领用明细记录');
}
$approvedQty = (int)($item->approved_qty ?? 0);
$returnedQty = (int)($item->returned_qty ?? 0);
if ($approvedQty <= 0) {
throw new BusinessException('该物品尚未审批出库,无法归还');
}
if ($returnedQty + $returnQty > $approvedQty) {
throw new BusinessException('归还数量超过已借数量,无法确认');
}
$item->returned_qty = $returnedQty + $returnQty;
if ($item->returned_qty >= $approvedQty) {
$item->is_finished = 1;
}
$item->updated_at = time();
if ($item->save() === false) {
throw new BusinessException('更新领用明细失败');
}
// 6.2 处理库存(入库)
(new InvItemService())->stockIn($itemId, $returnQty);
// 6.3 检查整张单是否已全部归还(只看非耗材)
$notFinishedCount = InvRequisitionItem::query()
->where('requisition_id', $requisitionId)
->where('is_consumable_snap', 0)
->where('is_finished', 0)
->count();
if ($notFinishedCount === 0) {
// 全部非耗材都已归还
$affected = InvRequisition::where('id', $requisitionId)->update([
'is_returned' => 1,
'updated_at' => time(),
]);
// Eloquent::update 返回的是影响行数,0 表示未更新到任何行
if ($affected === 0) {
throw new BusinessException('更新领用单状态失败,可能记录不存在');
}
}
// 7. 返回处理结果(保持你原来的 postProcess 习惯)
return $this->postProcess(ucfirst($scene), $existingRecord);
});
} catch (BusinessException $e) {
throw $e;
} catch (\Throwable $e) {
throw new BusinessException("确认归还物品失败:" . $e->getMessage());
}
}
/**
* 构建查询配置
*
* @param Request $request
* @param string $scene
* @return array
*/
protected function buildQueryConfig(Request $request, string $scene = 'default'): array
{
$p = $request->all();
$config = [];
$config['model'] = $this->modelClass;
switch ($scene) {
case 'returnConfirm':
$config['where']['id'] = $p['requisition_item_return_id'];
break;
case 'index':
$config['where']['status'] = 1;
$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;
}
}