'草稿', self::STATUS_COMPLETE => '已盘点', ]; public static function bookToDelStock($productId, $num, $shop, $staff) { $sjId = $shop->sjId ?? 0; $shopId = $shop->id ?? 0; $mainId = $shop->mainId ?? 0; $product = ProductClass::getById($productId, true); if (empty($product) || $product->mainId != $mainId) { util::fail('没有找到花材。'); } $stock = $out->stock ?? 0; $bookSn = $shop->bookSn ?? 0; $couldDelNum = 0; if (empty($bookSn)) { util::fail('没有在预订活动中'); } $bookItem = BookItemClass::getByCondition(['bookSn' => $bookSn, 'itemId' => $productId], true); if (!empty($bookItem)) { //借出的人预订控制在不受影响范围 $bookNum = $bookItem->bookNum ?? 0; if ($bookNum > 0) { $roadNum = $bookItem->roadNum ?? 0; $needCgNum = $bookItem->needCgNum ?? 0; $unReachNum = bcadd($roadNum, $needCgNum, 2); $useStock = bcsub($bookNum, $unReachNum, 2); if ($stock > $useStock) { $couldDelNum = bcsub($stock, $useStock, 2); } } else { $couldDelNum = $stock; } } else { $couldDelNum = $stock; } if ($couldDelNum <= 0) { util::fail('不能减库存'); } if ($num > $couldDelNum) { util::fail("最多只能删{$couldDelNum}份"); } $newStock = bcsub($stock, $num, 2); $adminId = $staff->adminId ?? 0; $staffName = $staff->name ?? ''; $staffId = $staff->id ?? 0; $ghsItemInfo = [['productId' => $couldDelNum, 'bigNum' => $newStock, 'smallNum' => 0,]]; $pdData = []; $pdData['itemInfo'] = $ghsItemInfo; $pdData['sjId'] = $sjId; $pdData['shopId'] = $shopId; $pdData['adminId'] = $adminId; $pdData['mainId'] = $mainId; $pdData['staffName'] = $data['staffName'] ?? ''; $pdData['remark'] = "在预订中删除库存"; $pdData['staffName'] = $staffName; $pdData['staffId'] = $staffId; self::opOrder($pdData, false, false, false); return true; } public static function bookToAddStock($productId, $num, $shop, $staff, $bookItemCustomRes) { $cacheKey = 'change_book_item_num_' . $productId; $noLock = util::lock($cacheKey); if (!$noLock) { util::fail("系统繁忙,1秒后再提交"); } $mainId = $shop->mainId ?? 0; $product = ProductClass::getById($productId, true); if (empty($product) || $product->mainId != $mainId) { util::fail('没有找到花材...'); } $bookSn = $shop->bookSn ?? 0; $stock = $product->stock ?? 0; $newStock = bcadd($stock, $num); $adminId = $staff->adminId ?? 0; $staffName = $staff->name ?? ''; $staffId = $staff->id ?? 0; $sjId = $shop->sjId ?? 0; $shopId = $shop->id ?? 0; $mainId = $shop->mainId ?? 0; $ghsItemInfo = [['productId' => $productId, 'bigNum' => $newStock, 'smallNum' => 0,]]; $pdData = []; $pdData['itemInfo'] = $ghsItemInfo; $pdData['sjId'] = $sjId; $pdData['shopId'] = $shopId; $pdData['adminId'] = $adminId; $pdData['mainId'] = $mainId; $pdData['staffName'] = $staffName; $pdData['staffId'] = $staffId; $pdData['remark'] = "预定盘点增加{$num}个库存"; $inOrder = self::opOrder($pdData, false, false, false); $needCgNum = $bookItemCustomRes->needCgNum ?? 0; if ($num > $needCgNum) { util::fail('增加库存不能超过待采数量'); } $delNeedCgNum = $num; $params = ['staffId' => $staffId, 'staffName' => $staffName]; $params['currentChangeType'] = 'pdAddStock'; $bookItemCustomRes = BookItemCustomClass::delNeedCgNum($bookItemCustomRes, $delNeedCgNum, 0, $inOrder, $shop, $product, $params); $bookItemRes = BookItemClass::getByCondition(['bookSn' => $bookSn, 'itemId' => $productId], true); if (empty($bookItemRes)) { util::fail('借库存没有找到bookItem'); } $bookItemRes = BookItemClass::delNeedCgNum($bookItemRes, $delNeedCgNum, 0, $inOrder, $shop, $product, $params); $customId = $bookItemCustomRes->customId ?? 0; $bookCustomRes = BookCustomClass::getByCondition(['bookSn' => $bookSn, 'customId' => $customId], true); if (empty($bookCustomRes)) { util::fail('盘点加库存没有找到bookCustom'); } $bookCustomRes = BookCustomClass::delNeedCgNum($bookCustomRes, $delNeedCgNum, 0, $inOrder, $shop, $product, $params); util::unlock($cacheKey); return true; } public static function loanStock($inId, $outId, $num, $shop, $staff, $bookItemCustomRes) { $cacheKey = 'change_book_item_num_' . $inId; $noLock = util::lock($cacheKey); if (!$noLock) { util::fail("系统繁忙,1秒后再提交"); } $sjId = $shop->sjId ?? 0; $shopId = $shop->id ?? 0; $mainId = $shop->mainId ?? 0; $in = ProductClass::getById($inId, true); if (empty($in) || $in->mainId != $mainId) { util::fail('没有找到花材...'); } $inName = $in->name ?? ''; $out = ProductClass::getById($outId, true); if (empty($out) || $out->mainId != $mainId) { util::fail('没有找到花材。'); } $outName = $out->name ?? ''; $stock = $out->stock ?? 0; $bookSn = $shop->bookSn ?? 0; $couldLoan = 0; if (!empty($bookSn)) { $bookItem = BookItemClass::getByCondition(['bookSn' => $bookSn, 'itemId' => $outId], true); if (!empty($bookItem)) { //借出的人预订控制在不受影响范围 $bookNum = $bookItem->bookNum ?? 0; if ($bookNum > 0) { $roadNum = $bookItem->roadNum ?? 0; $needCgNum = $bookItem->needCgNum ?? 0; $unReachNum = bcadd($roadNum, $needCgNum, 2); $useStock = bcsub($bookNum, $unReachNum, 2); if ($stock > $useStock) { $couldLoan = bcsub($stock, $useStock, 2); } } else { $couldLoan = $stock; } } else { $couldLoan = $stock; } } if ($num > $couldLoan) { util::fail("只能借{$couldLoan}"); } if ($inId == $outId) { util::fail('同个花材呢'); } $newOutStock = bcsub($stock, $num, 2); $inStock = $in->stock ?? 0; $newInStock = bcadd($inStock, $num); $adminId = $staff->adminId ?? 0; $staffName = $staff->name ?? ''; $staffId = $staff->id ?? 0; $ghsItemInfo = [['productId' => $outId, 'bigNum' => $newOutStock, 'smallNum' => 0,]]; $pdData = []; $pdData['itemInfo'] = $ghsItemInfo; $pdData['sjId'] = $sjId; $pdData['shopId'] = $shopId; $pdData['adminId'] = $adminId; $pdData['mainId'] = $mainId; $pdData['staffName'] = $data['staffName'] ?? ''; $pdData['remark'] = "借{$num}个库存给{$inName}"; $pdData['staffName'] = $staffName; $pdData['staffId'] = $staffId; self::opOrder($pdData, false, false, false); $sjId = $shop->sjId ?? 0; $shopId = $shop->id ?? 0; $mainId = $shop->mainId ?? 0; $ghsItemInfo = [['productId' => $inId, 'bigNum' => $newInStock, 'smallNum' => 0,]]; $pdData = []; $pdData['itemInfo'] = $ghsItemInfo; $pdData['sjId'] = $sjId; $pdData['shopId'] = $shopId; $pdData['adminId'] = $adminId; $pdData['mainId'] = $mainId; $pdData['staffName'] = $staffName; $pdData['staffId'] = $staffId; $pdData['remark'] = "向{$outName}借{$num}个库存"; $inOrder = self::opOrder($pdData, false, false, false); //借入的人待采会被影响 $needCgNum = $bookItemCustomRes->needCgNum ?? 0; if ($num > $needCgNum) { $delNeedCgNum = $needCgNum; } else { $delNeedCgNum = $num; } $params = ['staffId' => $staffId, 'staffName' => $staffName]; $params['currentChangeType'] = 'loanStock'; $params['outName'] = $outName; $bookItemCustomRes = BookItemCustomClass::delNeedCgNum($bookItemCustomRes, $delNeedCgNum, 0, $inOrder, $shop, $in, $params); $bookItemRes = BookItemClass::getByCondition(['bookSn' => $bookSn, 'itemId' => $inId], true); if (empty($bookItemRes)) { util::fail('借库存没有找到bookItem'); } $bookItemRes = BookItemClass::delNeedCgNum($bookItemRes, $delNeedCgNum, 0, $inOrder, $shop, $in, $params); $customId = $bookItemCustomRes->customId ?? 0; $bookCustomRes = BookCustomClass::getByCondition(['bookSn' => $bookSn, 'customId' => $customId], true); if (empty($bookCustomRes)) { util::fail('借库存没有找到bookCustom'); } $bookCustomRes = BookCustomClass::delNeedCgNum($bookCustomRes, $delNeedCgNum, 0, $inOrder, $shop, $in, $params); util::unlock($cacheKey); return true; } //2021.1.22 lqh 操作订单 添加/保存草稿/草稿编辑保存: 区别在添加是立即改库存和记录流水记录,而保存草稿是只保存订单信息 public static function opOrder($data, $draft = false, $update = false, $check = true, $params = []) { $sjId = $data['sjId']; $shopId = $data['shopId']; $adminId = $data['adminId'] ?? 0; $pdType = $data['pdType'] ?? ''; $mainId = $data['mainId'] ?? 0; $remark = $data['remark'] ?? ''; if (!empty($remark)) { $remark = stringUtil::subStringUtf8($remark, 100, '...'); } //控制修改库存的权限,在这里控制 ssh 20250313 if (getenv('YII_ENV') == 'production') { //花大苪只有三个人可以修改库存 if ($mainId == 8164) { if (!in_array($adminId, [9273, 9303, 47576])) { util::fail('不能修改库存哦'); } } } if ($draft) { //保存草稿 $data['status'] = self::STATUS_DRAFT; } else { //确定保存 $data['status'] = self::STATUS_COMPLETE; } if ($update) { $orderSn = $data['orderSn']; } else { $orderSn = orderSn::getGhsCheckSn(); } $data['orderSn'] = $orderSn; //数据格式 [{bigNum:0,smallNum:0,productId:1}] $ghsItemInfo = $data['itemInfo']; //之前出现过同个花材在不现分类下出现,这里进行组合 $ghsItemInfo = self::mergeItemInfo($ghsItemInfo); $sumNum = self::sumNumByItemInfo($ghsItemInfo); $data['bigNum'] = $sumNum['bigNum'];// 总的大单位数量 总共多少扎 $data['smallNum'] = $sumNum['smallNum']; //总的小单位数量 总共多少支 $connection = Yii::$app->db; $transaction = $connection->beginTransaction(); try { if ($update) { //更新先删除数据 self::deleteByCondition(['orderSn' => $orderSn]); CheckOrderItemClass::deleteByCondition(['orderSn' => $orderSn]); } $order = self::add($data, true); //写入详情表 $batchData = self::groupOrderItem($ghsItemInfo, $orderSn); CheckOrderItemClass::batchAddOrderItem($batchData); $avCost = 0; $changeCost = 0; $unitCost = 0; $remainCost = 0; $remainStock = 0; if (isset($params['motherId']) && $params['motherId'] > 0) { $motherInfo = ProductClass::getById($params['motherId'], true); $unitCost = $motherInfo->avCost ?? 0; } $addAmount = 0; $subAmount = 0; $ids = []; if ($draft === false) { //盘点完成完成,直接将库存中的数量改为当时盘点的数量 foreach ($batchData as $v) { $productId = $v['productId']; $ids[] = $productId; //修改库存数量:盘点同样需要锁住花材行,避免与开单/调拨并发覆盖库存 $productData = ProductClass::getLockById($productId); if (empty($productData)) { util::fail("花材不存在"); } //当 limitBuy=0 时,则清空限购记录缓存 if ($productData->limitBuy == 0) { ProductClass::clearLimitBuyCache($productId); \bizHd\product\classes\ProductClass::clearLimitBuyCache($productId); } //涉及平均成本计算的,多处要修改,搜索关键词 calc_av_cost if (isset($params['motherId']) && $params['motherId'] > 0) { //变动库存和变动成本 $changeNum = bcsub($productData->stock, $v['itemNum'], 2); $changeNum = abs($changeNum); $changeCost = bcmul($unitCost, $changeNum, 2); //原库存和原成本,也叫剩余成本和剩余库存 $oldItemStock = $productData->stock ?? 0; $oldAvCost = $productData->avCost ?? 0; $oldItemCost = bcmul($oldItemStock, $oldAvCost, 2); if ($productId == $params['motherId']) { //新库存和新成本 $remainCost = bcsub($oldItemCost, $changeCost, 2); $remainCost = $remainCost > 0 ? $remainCost : 0; $remainStock = bcsub($oldItemStock, $changeNum, 2); $remainStock = $remainStock > 0 ? $remainStock : 0; $avCost = $unitCost; $productData->avCost = $avCost; $productData->totalCost = $remainCost; $productData->totalStock = $remainStock; $productData->save(); } else { //新库存和新成本 $remainStock = bcadd($changeNum, $oldItemStock, 2); $remainCost = bcadd($changeCost, $oldItemCost, 2); if ($remainStock > 0) { $avCost = bcdiv($remainCost, $remainStock, 2); } else { $avCost = 0; $remainStock = 0; $remainCost = 0; } $productData->avCost = $avCost; $productData->totalCost = $remainCost; $productData->totalStock = $remainStock; $productData->save(); } } //上架 if ($v['itemNum'] > 0 && $productData->status == 2) { ProductClass::changeStatusAndReset($productData, 1); } //下架 if ($v['itemNum'] <= 0 && $productData->status == 1) { ProductClass::changeStatusAndReset($productData, 2, true); } $oldStockVal = $productData->stock ?? 0; $productData->stock = $v['itemNum']; if ($adminId) { $productData->adminId = $adminId; } //流水记录 $record = []; $record['sjId'] = $sjId; $record['shopId'] = $shopId; $record['mainId'] = $productData->mainId ?? 0; $record['orderSn'] = $orderSn; $record['ptStyle'] = 2; $record['relateName'] = $data['staffName'] ?? ''; $record['itemId'] = $v['itemId']; $record['productId'] = $productId; $record['itemNum'] = abs($v['profitLossNum']); $record['oldStock'] = $oldStockVal; $record['newStock'] = $v['itemNum']; $record['targetId'] = $order->id ?? 0; $record['remark'] = $remark; $record['avCost'] = $avCost; $record['changeCost'] = $changeCost; $record['unitCost'] = $unitCost; $record['totalStock'] = $remainStock; $record['totalCost'] = $remainCost; StockRecordClass::addCheckOrderRecord($record); $amount = $v['amount'] ?? 0; if ($amount > 0) { $addAmount = bcadd($addAmount, $amount, 2); } else { $subAmount = bcadd($subAmount, $amount, 2); } //如果花材是自动补充库存类型的花材,则库存低于900时,自动补充到98520,多处要同步修改,关键词 auto_add_stock if ($productData->virtualStock == 1 && $v['itemNum'] < 9900) { $productData->stock = 98520; $productData->status = 1; } $productData->save(); } $shop = ShopClass::getById($shopId, true); $bookSn = $shop->bookSn ?? 0; if (!empty($bookSn) && $check == true) { $bookItemRes = BookItemClass::getAllByCondition(['bookSn' => $bookSn, 'itemId' => ['in', $ids]], null, '*', null, true); if (!empty($bookItemRes)) { foreach ($bookItemRes as $bookItem) { $name = $bookItem->name ?? '未命名'; util::fail($name . " 被预订,不能直接改库存"); } } } if ($pdType == 'stockInPd' && !empty($mainId)) { //如果是车销的入库花材盘点,则将记录过的花材清除 StockInDayClass::deleteByCondition(['mainId' => $mainId]); } } $order->addAmount = $addAmount; $order->subAmount = $subAmount; $order->price = bcadd($addAmount, $subAmount, 2); $order->save(); $transaction->commit(); return $order; } catch (\Exception $exception) { $transaction->rollBack(); util::fail('保存失败' . $exception->getMessage()); } } //2021.1.22 lqh 订单列表 public static function getOrderList($where) { $data = self::getList('*', $where, 'addTime DESC'); $list = isset($data['list']) && !empty($data['list']) ? $data['list'] : []; if (empty($list)) { return $data; } $data['list'] = $list; $data['list'] = self::groupAdminList($list); $data['list'] = self::groupStatusName($data['list']); return $data; } //2021.1.22 订单详情 //获取订单详情信息 lqh 2021.1.20 public static function getOrderDetail($orderSn, $shopId) { $orderData = self::orderExist($orderSn, $shopId); $orderInfo = CheckOrderItemClass::getOrderItemDetail($orderSn); $itemData = []; if ($orderInfo) { foreach ($orderInfo as $v) { $info = json_decode($v['itemInfo'], true); $tmp = $info; $tmp['itemCover'] = self::groupImg($info['itemCover']); unset($v['itemInfo']); if (!isset($tmp['rank'])) { $tmp['rank'] = 'B'; } $tmp = array_merge($tmp, $v); $tmp['id'] = $v['productId']; $tmp['classId'] = 0; $itemData[] = $tmp; } } $orderData = self::groupAdmin($orderData); $orderData['itemInfo'] = $itemData; $orderData['statusName'] = self::getStatusName($orderData['status']); return $orderData; } //2021.1.22 lqh 判断订单号是否存在 public static function orderExist($orderSn, $shopId) { $where = [ 'orderSn' => $orderSn, 'shopId' => $shopId, ]; $orderData = self::getByCondition($where); if (!$orderData) { util::fail('订单不存在'); } return $orderData; } // 组装 orderItem lqh 2021.1.25 public static function groupOrderItem($ghsItemInfo, $orderSn) { $productData = self::getProductMapData($ghsItemInfo); //写入详情表 $batchData = []; foreach ($ghsItemInfo as $v) { $tmp = []; $productId = $v['productId']; $itemId = $productData[$productId]['itemId']; $rank = $productData[$productId]['rank'] ?? 'B';// 花材级别 $tmp['orderSn'] = $orderSn; $tmp['itemId'] = $itemId; $tmp['productId'] = $v['productId']; $unitNum = $productData[$productId]['ratio'] ?? 0; $tmp['itemStock'] = $productData[$productId]['stock'] ?? 0;//当时库存 $itemNum = ProductClass::mergeItemNum($v['bigNum'], $v['smallNum'], $unitNum); $tmp['itemNum'] = $itemNum;// 盘点数量 $tmp['itemPrice'] = $productData[$productId]['price'] ?? 0; //当时售卖的价格 $tmp['itemCost'] = $productData[$productId]['cost'] ?? 0; //当时成本的价格 $tmp['profitLossNum'] = bcsub($tmp['itemNum'], $tmp['itemStock'], 2); //盈亏数 = 盘点数-当时库存数 $tmp['amount'] = bcmul($tmp['profitLossNum'], $tmp['itemCost'], 2); $stockFormat = ProductClass::formatStock($tmp['itemStock'], $unitNum); // 库存总单位数量转大小单位的数量 $itemInfo = [ 'itemName' => $productData[$productId]['name'] ?? '',//花材名称 'itemCover' => $productData[$productId]['cover'] ?? '',//花材图片 'bigNum' => $v['bigNum'] ?? 0,//数量(大单位) 'smallNum' => $v['smallNum'] ?? 0,//数量(小单位) 'bigNumStock' => $stockFormat['bigNum'],// 当时库存大单位数 'smallNumStock' => $stockFormat['smallNum'],//当时库存 小单位数 'bigNumProfitLoss' => bcsub($v['bigNum'], $stockFormat['bigNum']),//大单位的盈亏 'smallNumProfitLoss' => bcsub($v['smallNum'], $stockFormat['smallNum']),//小单位的盈亏 'itemUnit' => $unitNum ? 2 : 1,//单位 'ratio' => $unitNum,// 比例 'rank' => $rank,// 花材级别 'bigUnit' => $productData[$productId]['bigUnit'],//大单位名称 扎 'smallUnit' => $productData[$productId]['smallUnit'],//小单位名称 支 ]; $tmp['itemInfo'] = json_encode($itemInfo); $batchData[] = $tmp; } return $batchData; } // 组装状态码 lqh 2021.1.30 public static function groupStatusName($list) { foreach ($list as $k => $val) { $status = $val['status'] ?? 0; $list[$k]['statusName'] = self::getStatusName($status); } return $list; } // 获取状态码名称 public static function getStatusName($status) { return self::$statusMap[$status] ?? ''; } }