request->isGet) { $post = Yii::$app->request->get(); } elseif (Yii::$app->request->isPost) { $post = Yii::$app->request->post(); } $orderSn = $post['orderSn'] ?? ''; $in = StockInOrderClass::getByCondition(['orderSn' => $orderSn], true); if (empty($in)) { util::fail('没有找到入库单'); } if ($in->inMainId != $this->mainId) { util::fail('不是你的入库单'); } $inShopId = $post['inShopId'] ?? 0; if ($inShopId == $this->shopId) { util::fail('出库和入库门店一样'); } $inShop = ShopClass::getById($inShopId, true); if (empty($inShop)) { util::fail('没有找到入库门店'); } $changeList = $post['changeList'] ?? []; $changeData = []; if (!empty($changeList)) { $changeFormatData = json_decode($changeList, true); if (!empty($changeFormatData)) { foreach ($changeFormatData as $k => $v) { $productId = $v['productId']; $actPutNum = $v['actPutNum'] ?? 0; $itemName = $v['itemName'] ?? ''; $changeData[$productId] = ['actPutNum' => $actPutNum, 'itemName' => $itemName]; } } } $inItemList = StockInOrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*'); if (empty($inItemList)) { util::fail('没有找到入库单的花材'); } $itemInfo = []; foreach ($inItemList as $key => $info) { $productId = $info['productId'] ?? 0; $itemNum = $info['itemNum'] ? floatval($info['itemNum']) : 0; if (!empty($changeData)) { if (isset($changeData[$productId])) { $changeResult = $changeData[$productId]; $itemNum = $changeResult['actPutNum']; $itemName = $changeResult['itemName']; if (!is_numeric($itemNum)) { util::fail('请填写【' . $itemName . '】回调数值'); } } } $itemInfo[] = ['productId' => $productId, 'bigNum' => $itemNum, 'smallNum' => 0]; } $arr = [ 'confirmIn' => 1, 'date' => '', 'outTime' => '', 'remark' => '一键再次出库', 'inShopId' => $inShopId, 'inMainId' => $inShop->mainId, 'itemInfo' => $itemInfo, 'action' => 'confirm', 'sjId' => $this->sjId, 'outShopId' => $this->shopId, 'outMainId' => $this->mainId, 'adminId' => $this->adminId, ]; $connection = Yii::$app->db; $transaction = $connection->beginTransaction(); try { StockOutOrderClass::addOrder($arr); //回调次数+1 $in->callbackTime += 1; $in->save(); $transaction->commit(); util::complete('操作成功'); } catch (\Exception $exception) { $transaction->rollBack(); util::fail('操作失败'); } } //结清账单 ssh 20221113 public function actionClear() { $shopAdmin = $this->shopAdmin; if (isset($shopAdmin->super) == false || $shopAdmin->super != 1) { util::fail('超管才能修改'); } $get = Yii::$app->request->get(); $orderSn = $get['orderSn'] ?? ''; $out = StockOutOrderClass::getByCondition(['orderSn' => $orderSn], true); if (empty($out)) { util::fail('没有找到出库单'); } if ($out->outMainId != $this->mainId) { util::fail('没有权限'); } if ($out->status != 2) { util::fail('已出库才能结账单'); } if ($out->debt == 0) { util::fail('已经结过了'); } $inOrderSn = $out->inOrderSn ?? ''; $in = StockInOrderClass::getByCondition(['orderSn' => $inOrderSn], true); if (empty($in)) { util::fail('没有找到入库单'); } if ($in->status != 2) { util::fail('已入库才能结账单'); } if ($in->debt == 0) { util::fail('已经结过了'); } $out->debt = 0; $out->save(); $in->debt = 0; $in->save(); util::complete(); } /** * 全部出库 * 职责:将当前门店下所有有库存且未删除的花材一次性全部出库到指定门店 * 入参:GET 传参 shopId (入库门店ID), confirmIn (是否直接确认入库) * 返回:JSON 格式的成功提示 * 副作用:扣减出库门店库存,记录出库单及明细,写入库存变动日志 * 关键边界: * 1. 校验入库门店有效性,默认门店不允许全部出库,不能出库给自己 * 2. 优化:直接在数据库过滤有库存且未删除的商品,且仅查询必要字段(id, stock, ratio),返回纯数组,避免实例化大量 ActiveRecord 对象,极大节省内存和 CPU 耗时 */ public function actionAllOut() { $get = Yii::$app->request->get(); $inShopId = $get['shopId'] ?? 0; $confirmIn = $get['confirmIn'] ?? 0; $inShop = ShopClass::getById($inShopId, true); if (empty($inShop)) { util::fail('入库门店没有找到'); } $inMainId = $inShop->mainId ?? 0; $shop = $this->shop; if ($shop->default == 1) { util::fail('默认门店不能全部出库'); } $connection = Yii::$app->db; $transaction = $connection->beginTransaction(); try { $shopId = $this->shopId; $mainId = $this->mainId; $sjId = $shop->sjId ?? 0; // 复杂分支/关键逻辑:优化查询。直接在数据库过滤 delStatus=0 且 stock>0 的商品,仅查询 id, stock, ratio 字段,且返回纯数组(不实例化对象) $list = ProductClass::getAllByCondition([ 'mainId' => $mainId, 'delStatus' => 0, 'stock>' => 0, ], null, 'id, stock, ratio', null, false); if (empty($list)) { util::fail('没有花材'); } if ($inShopId == $shopId) { util::fail('不能出给自己'); } $itemInfo = []; foreach ($list as $item) { $stock = $item['stock'] ?? 0; $ratio = $item['ratio'] ?? 0; $bigNum = intval($stock); $small = bcsub((string)$stock, (string)$bigNum, 2); $smallNum = bcmul($small, (string)$ratio); $currentId = $item['id']; $itemInfo[] = ['productId' => $currentId, 'bigNum' => $bigNum, 'smallNum' => (float)$smallNum]; } if (empty($itemInfo)) { util::fail('没有库存'); } $data = [ 'remark' => '全部出库', 'itemInfo' => $itemInfo, 'inShopId' => $inShopId, 'inMainId' => $inMainId, 'outMainId' => $mainId, 'outShopId' => $shopId, 'sjId' => $sjId, 'action' => StockOutOrderClass::ACTION_CONFIRM, 'outTime' => date('Y-m-d H:i:s'), 'adminId' => $this->adminId, 'confirmIn' => $confirmIn, ]; StockOutOrderClass::addOrder($data); $transaction->commit(); util::complete(); } catch (\Exception $exception) { $transaction->rollBack(); util::fail('出库失败' . $exception->getMessage()); } } //出库列表 lqh 2021.1.23 public function actionList() { $get = Yii::$app->request->get(); $orderStatus = isset($get['status']) ? $get['status'] : ''; $where = []; $where['outShopId'] = $this->shopId; if (!empty($orderStatus)) { $where['status'] = $orderStatus; } $list = StockOutOrderClass::getOrderList($where); util::success($list); } //新增出库 lqh 2021.1.23 public function actionCreateOrder() { $post = Yii::$app->request->post(); $post['sjId'] = $this->sjId; $post['outShopId'] = $this->shopId; $post['outMainId'] = $this->mainId; $post['adminId'] = $this->adminId; $inShopId = $post['inShopId'] ?? 0; $now = date('Y-m-d H:i:s'); $date = $post['date'] ?? $now; $post['outTime'] = $date; $action = $post['action'] ?? 'wait'; //confirm(直接出库) wait(待出库中) $post['action'] = $action; $post['inShopId'] = $inShopId; $check = StockOutOrderClass::getByCondition(['outShopId' => $this->shopId, 'inShopId' => $inShopId, 'status' => StockOutOrderClass::STATUS_WAIT]); if ($check) { util::fail('还有待出库的订单'); } $ghsItemInfo = $post['itemInfo'] ?? ''; if (empty($ghsItemInfo)) { util::fail('请选择花材'); } $ghsItemInfo = json_decode($ghsItemInfo, true); // [{productId:0,bigNum:1,smallNum:0}] if (!is_array($ghsItemInfo)) { util::fail('花材格式不正确'); } //避免重复提交 $adminId = $this->adminId; util::checkRepeatCommit($adminId, 5); try { $order = util::runWithDbConcurrencyRetry(function () use ($post, $ghsItemInfo, $inShopId) { $connection = Yii::$app->db; $transaction = $connection->beginTransaction(); try { //入库门店有效性判断 if ($this->shopId == $inShopId) { util::fail('不能出库给当前门店'); } $inShop = ShopClass::getById($inShopId); if (empty($inShop)) { util::fail('没有找到门店68'); } ShopClass::valid($inShop, $this->sjId); $post['inMainId'] = $inShop['mainId'] ?? 0; $staff = $this->shopAdmin; $post['staffName'] = $staff->name ?? ''; $post['staffId'] = $staff->id ?? 0; $post['adminId'] = $this->adminId; ProductClass::valid($ghsItemInfo, $this->mainId); //判断花材里的信息 foreach ($ghsItemInfo as $v) { $bigNum = $v['bigNum'] ?? 0; $smallNum = $v['smallNum'] ?? 0; if ($bigNum <= 0 && $smallNum <= 0) { util::fail('花材数量不能为0'); } } $post['itemInfo'] = $ghsItemInfo; $order = StockOutOrderClass::addOrder($post); $transaction->commit(); return $order; } catch (\Exception $exception) { if ($transaction->isActive) { $transaction->rollBack(); } throw $exception; } }); util::success($order); } catch (\Exception $exception) { if (util::isDbConcurrencyException($exception)) { util::fail('系统繁忙中,请稍后再试'); } else { util::fail('出库失败' . $exception->getMessage()); } } } //出库详情 lqh 2021.1.23 public function actionDetail() { $orderSn = Yii::$app->request->get('orderSn', ''); $orderData = StockOutOrderClass::getOrderDetail($orderSn, $this->shopId); util::success($orderData); } //确认出库 lqh 2021.1.23 public function actionConfirmOrder() { $get = Yii::$app->request->get(); $orderSn = $get['orderSn']; try { util::runWithDbConcurrencyRetry(function () use ($orderSn) { $connection = Yii::$app->db; $transaction = $connection->beginTransaction(); try { StockOutOrderClass::confirmOrder($orderSn, $this->shopId, $this->adminId); $transaction->commit(); } catch (\Exception $exception) { if ($transaction->isActive) { $transaction->rollBack(); } throw $exception; } }); util::complete("出库成功"); } catch (\Exception $exception) { if (util::isDbConcurrencyException($exception)) { util::fail('系统繁忙中,请稍后再试'); } else { util::fail($exception->getMessage()); } } } //取消出库 lqh 2021.1.23 public function actionCancelOrder() { $get = Yii::$app->request->get(); $orderSn = $get['orderSn']; try { util::runWithDbConcurrencyRetry(function () use ($orderSn) { $connection = Yii::$app->db; $transaction = $connection->beginTransaction(); try { StockOutOrderClass::cancelOrder($orderSn, $this->shopId, $this->adminId); $transaction->commit(); } catch (\Exception $exception) { if ($transaction->isActive) { $transaction->rollBack(); } throw $exception; } }); util::complete("取消成功"); } catch (\Exception $exception) { if (util::isDbConcurrencyException($exception)) { util::fail('系统繁忙中,请稍后再试'); } else { util::fail($exception->getMessage()); } } } //打印出库单 ssh 20231026 public function actionPrint() { $get = Yii::$app->request->get(); $id = $get['id']; $out = StockOutOrderClass::getById($id, true); if (empty($out)) { util::fail('没有找到出库记录'); } if ($out->outMainId != $this->mainId) { util::fail('不是你的出库单'); } StockOutOrderClass::printOrder($out, $this->shop); util::complete(); } }