From 7098f30af284bbc295b2a42f83e730583d69afcc Mon Sep 17 00:00:00 2001 From: "WIN-C27C5MSVTPO\\16961" <1696136552@qq.com> Date: Thu, 12 Feb 2026 15:33:23 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A1=AE=E8=AE=A4=E5=BD=92=E8=BF=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../InvRequisitionItemReturnController.php | 19 +++ .../InvRequisitionItemReturnService.php | 161 +++++++++++++++++- .../InvRequisitionItemReturnController.php | 21 ++- config/route.php | 2 + 4 files changed, 201 insertions(+), 2 deletions(-) diff --git a/app/common/controller/InvRequisitionItemReturnController.php b/app/common/controller/InvRequisitionItemReturnController.php index 6635fa6..f1bda95 100644 --- a/app/common/controller/InvRequisitionItemReturnController.php +++ b/app/common/controller/InvRequisitionItemReturnController.php @@ -138,6 +138,25 @@ class InvRequisitionItemReturnController extends BaseController } } + /** + * 物品归还确认 + * + * @param Request $request + * @return mixed + */ + public function returnItemConfirm(Request $request) + { + try { + // 验证申请数据 + $data = $this->validate($this->service->getValidator(), $request->post(), 'returnConfirm'); + // 处理申请逻辑 + $result = $this->service->serviceReturnItemConfirm($request, $data, 'returnConfirm'); + + return $this->success($result, '申请提交成功'); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } /** * 物品归还确认 diff --git a/app/common/service/InvRequisitionItemReturnService.php b/app/common/service/InvRequisitionItemReturnService.php index 5853eb7..46f7787 100644 --- a/app/common/service/InvRequisitionItemReturnService.php +++ b/app/common/service/InvRequisitionItemReturnService.php @@ -391,7 +391,7 @@ class InvRequisitionItemReturnService * @return array|bool * @throws BusinessException */ - public function serviceReturnConfirm(Request $request, array $data, string $scene = 'returnConfirm') + public function serviceReturnItemConfirm(Request $request, array $data, string $scene = 'returnConfirm') { try { $attachment = $request->post('attachment'); @@ -543,6 +543,165 @@ class InvRequisitionItemReturnService } } + /** + * 物品领用归还确认 + * + * @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 { + $attachment = $request->post('attachment'); + unset($data['attachment']); + // 归还确认是业务顶层方法,这里统一使用事务 + return Db::transaction(function () use ($request, $data, $scene, $attachment) { + + // 1. 当前操作人信息 + $userInfo = (new UserService())->getUserInfo($request->user->uid, ''); + if (empty($userInfo['user']['id']) || empty($userInfo['user']['name'])) { + throw new BusinessException('无法获取当前用户信息'); + } + + $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. 构建查询配置,定位到这条归还记录 + $returnService = new InvRequisitionReturnService(); + $return = InvRequisitionReturn::where('id', $data['return_id'])->first(); + if (!$return) { + throw new BusinessException('未找到对应的领用归还记录'); + } + $requisitionId = (int)$return->requisition_id; + $existingStatus = (int)($return->status ?? 0); + if (in_array($existingStatus, [1, 2], true)) { + throw new BusinessException('该归还申请已经被处理过了'); + } + $return->status = $status; + $return->save(); + + // 保存归还审核附件 + foreach ($attachment as $attac) { + Db::table('inv_requisition_return_approve_attachment')->insertGetId([ + 'requisition_id' => $requisitionId, + 'return_id' => $data['return_id'], + 'file_name' => $attac['original_name'], + 'file_path' => $attac['file_path'], + 'created_at' => time(), + ]); + } + + //查询归还明细 + $itemReturns = InvRequisitionItemReturn::where('return_id', $data['return_id'])->get(); + foreach ($itemReturns as $itemReturn) { + $itemReturn->status = $status; + $itemReturn->handle_remark = $data['handle_remark']; + $itemReturn->save(); + + // 5. 若是拒绝,直接跳出(不改库存、不改已归还数量) + if ($status === 2) { + // 拒绝:这里你返回 true 或者返回更新后的记录都可以 + continue; + } + + // 6. 审核通过:继续处理领用明细 & 库存 & 领用单状态 + // 注意:requisition_item_id、item_id、return_qty 等字段在本次确认流程中不会被修改, + // 所以可以直接使用 $existingRecord 中的值(都是只读字段) + $requisitionItemId = (int)$itemReturn->requisition_item_id; + $itemId = (int)$itemReturn->item_id; + $returnQty = (int)$itemReturn->return_qty; + + if ($requisitionItemId <= 0 || $itemId <= 0 || $returnQty <= 0 || $requisitionId <= 0) { + throw new BusinessException('归还申请记录缺少必要字段,无法处理'); + } + + // 6.2 处理领用明细 + /** @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.3 处理库存(入库) + (new InvItemService())->stockIn($itemId, $returnQty); + } + // 5. 若是拒绝,直接返回(不修改领用申请状态) + if ($status === 2) { + // 拒绝:这里你返回 true 或者返回更新后的记录都可以 + return $return; + } + + // 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, + 'status' => 17, + 'updated_at' => time(), + ]); + + // Eloquent::update 返回的是影响行数,0 表示未更新到任何行 + if ($affected === 0) { + throw new BusinessException('更新领用单状态失败,可能记录不存在'); + } + }else{ + // 非耗材未全部归还 + $affected = InvRequisition::where('id', $requisitionId)->update([ + 'status' => 16, + 'updated_at' => time(), + ]); + } + + // 7. 返回处理结果(保持你原来的 postProcess 习惯) + //return $this->postProcess(ucfirst($scene), $existingRecord); + return $return; + }); + + } catch (BusinessException $e) { + throw $e; + } catch (\Throwable $e) { + throw new BusinessException("确认归还物品失败:" . $e->getMessage()); + } + } + /** * 构建查询配置 * diff --git a/app/mobile/controller/InvRequisitionItemReturnController.php b/app/mobile/controller/InvRequisitionItemReturnController.php index 1657d9f..8d2a478 100644 --- a/app/mobile/controller/InvRequisitionItemReturnController.php +++ b/app/mobile/controller/InvRequisitionItemReturnController.php @@ -138,6 +138,25 @@ class InvRequisitionItemReturnController extends BaseController } } + /** + * 物品归还确认 + * + * @param Request $request + * @return mixed + */ + public function returnItemConfirm(Request $request) + { + try { + // 验证申请数据 + $data = $this->validate($this->service->getValidator(), $request->post(), 'returnConfirm'); + // 处理申请逻辑 + $result = $this->service->serviceReturnItemConfirm($request, $data, 'returnConfirm'); + + return $this->success($result, '申请提交成功'); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + } /** * 物品归还确认 @@ -152,7 +171,7 @@ class InvRequisitionItemReturnController extends BaseController $data = $this->validate($this->service->getValidator(), $request->post(), 'returnConfirm'); // 处理申请逻辑 $result = $this->service->serviceReturnConfirm($request, $data, 'returnConfirm'); - + return $this->success($result, '申请提交成功'); } catch (\Throwable $e) { return $this->error($e->getMessage()); diff --git a/config/route.php b/config/route.php index 50d4480..77904d3 100644 --- a/config/route.php +++ b/config/route.php @@ -528,6 +528,7 @@ Route::group('/admin', function () { Route::any('/list', [app\common\controller\InvRequisitionItemReturnController::class, 'index']); Route::any('/show', [app\common\controller\InvRequisitionItemReturnController::class, 'show']); Route::any('/confirm', [app\common\controller\InvRequisitionItemReturnController::class, 'returnConfirm']); + Route::any('/confirmItem', [app\common\controller\InvRequisitionItemReturnController::class, 'returnItemConfirm']); }); }); }); @@ -680,6 +681,7 @@ Route::group('/mobile', function () { Route::any('/list', [app\mobile\controller\InvRequisitionItemReturnController::class, 'index']); Route::any('/show', [app\mobile\controller\InvRequisitionItemReturnController::class, 'show']); Route::any('/confirm', [app\mobile\controller\InvRequisitionItemReturnController::class, 'returnConfirm']); + Route::any('/confirmItem', [app\mobile\controller\InvRequisitionItemReturnController::class, 'returnItemConfirm']); }); }); }); \ No newline at end of file