StockInOrderClass.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. <?php
  2. namespace bizGhs\order\classes;
  3. use biz\shop\classes\ShopCapitalClass;
  4. use biz\shop\classes\ShopClass;
  5. use biz\stat\classes\StatOutClass;
  6. use biz\stat\classes\StatStockInClass;
  7. use biz\stat\classes\StatStockOutClass;
  8. use bizGhs\item\classes\CostChangeClass;
  9. use bizGhs\item\classes\PriceChangeClass;
  10. use bizGhs\order\models\StockOutOrderItem;
  11. use bizGhs\order\traits\OrderTrait;
  12. use bizGhs\product\classes\ProductClass;
  13. use bizGhs\shop\classes\MainClass;
  14. use bizGhs\shop\classes\ShopAdminClass;
  15. use bizGhs\stock\classes\StockInDayClass;
  16. use bizGhs\stock\classes\StockRecordClass;
  17. use bizHd\stat\classes\StatIncomeClass;
  18. use common\components\dict;
  19. use common\components\noticeUtil;
  20. use common\components\orderSn;
  21. use common\components\util;
  22. use Yii;
  23. use bizGhs\base\classes\BaseClass;
  24. class StockInOrderClass extends BaseClass
  25. {
  26. use OrderTrait;
  27. const STATUS_WAIT = 1; //待入库
  28. const STATUS_COMPLETE = 2; //已入库
  29. const STATUS_CANCEL = 3; //取消入库
  30. const ACTION_CONFIRM = 'confirm'; //直接入库
  31. public static $baseFile = '\bizGhs\order\models\StockInOrder';
  32. public static $statusMap = [
  33. self::STATUS_WAIT => '待入库',
  34. self::STATUS_COMPLETE => '已入库',
  35. ];
  36. //2021.1.25 lqh 订单列表
  37. public static function getOrderList($where)
  38. {
  39. $data = self::getList('*', $where, 'addTime DESC');
  40. $list = isset($data['list']) && !empty($data['list']) ? $data['list'] : [];
  41. if (empty($list)) {
  42. return $data;
  43. }
  44. $ids = array_column($list, 'outShopId');
  45. $ids = array_filter(array_unique($ids));
  46. $shopInfo = ShopClass::getByIds($ids, null, 'id');
  47. foreach ($list as $key => $val) {
  48. $outShopId = $val['outShopId'] ?? 0;
  49. $list[$key]['outShopName'] = $shopInfo[$outShopId]['shopName'] ?? '';
  50. }
  51. $data['list'] = $list;
  52. $data['list'] = self::groupAdminList($list);
  53. $data['list'] = self::groupStatusName($data['list']);
  54. return $data;
  55. }
  56. //入库 (状态在待入库中 )lqh 2021.1.23
  57. public static function addOrder($outOrderData)
  58. {
  59. $data = [];
  60. $data['status'] = self::STATUS_WAIT;//待入库
  61. $orderSn = orderSn::getGhsStockInSn();
  62. $data['orderSn'] = $orderSn;
  63. $data['sjId'] = $outOrderData['sjId'];
  64. $data['outShopId'] = $outOrderData['outShopId'] ?? 0;
  65. $data['outMainId'] = $outOrderData['outMainId'] ?? 0;
  66. $data['inShopId'] = $outOrderData['inShopId'];
  67. $data['inMainId'] = $outOrderData['inMainId'] ?? 0;
  68. $data['outOrderSn'] = $outOrderData['orderSn'];
  69. $data['adminId'] = $outOrderData['adminId'];
  70. $data['bigNum'] = $outOrderData['bigNum'];
  71. $data['smallNum'] = $outOrderData['smallNum'];
  72. $data['price'] = $outOrderData['price'] ?? 0;
  73. $data['remark'] = $outOrderData['remark'];
  74. $ghsItemInfo = $outOrderData['itemInfo'];
  75. $shopId = $outOrderData['inShopId'] ?? 0;
  76. $mainId = $outOrderData['inMainId'] ?? 0;
  77. //入库: 需要将itemId 转换成对应的productId,若没有对应的productId,则需要新增
  78. ProductClass::complementProduct($data['sjId'], $mainId, $shopId, $ghsItemInfo);
  79. $itemIds = array_column($ghsItemInfo, "itemId");
  80. $productData = ProductClass::getGhsProductDataByItemIds($mainId, $itemIds);
  81. $itemData = array_column($productData, null, 'itemId');
  82. $connection = Yii::$app->db;
  83. $transaction = $connection->beginTransaction();
  84. try {
  85. //写入订单表
  86. $order = self::add($data);
  87. //写入详情表
  88. $batchData = [];
  89. foreach ($ghsItemInfo as $v) {
  90. $tmp = [];
  91. $itemId = $v['itemId'];
  92. $productId = $itemData[$itemId]['id'] ?? 0;
  93. if (!$productId) {
  94. util::fail("入库失败");
  95. }
  96. $tmp['productId'] = $productId;
  97. $tmp['orderSn'] = $orderSn;
  98. $tmp['itemId'] = $itemId;
  99. $tmp['itemStock'] = $itemData[$itemId]['stock'] ?? 0;//当时库存
  100. $tmp['itemNum'] = $v['itemNum'];
  101. $tmp['itemPrice'] = $v['itemPrice'] ?? 0;
  102. $tmp['price'] = $v['price'] ?? 0;
  103. $tmp['skPrice'] = $v['skPrice'] ?? 0;
  104. $tmp['hjPrice'] = $v['hjPrice'] ?? 0;
  105. $tmp['cost'] = $v['cost'] ?? 0;
  106. $ratio = $itemData[$itemId]['ratio'] ?? 0;
  107. $formatStock = ProductClass::formatStock($tmp['itemStock'], $ratio);
  108. $itemInfo = [
  109. 'itemName' => $v['itemName'] ?? '',
  110. 'itemCover' => $v['cover'] ?? '',
  111. 'bigNum' => $v['bigNum'],// 出库的大单位数量
  112. 'smallNum' => $v['smallNum'], //出库的小单位数量
  113. 'bigNumStock' => $formatStock['bigNum'],// 当时库存大单位数
  114. 'smallNumStock' => $formatStock['smallNum'],//当时库存 小单位数
  115. 'itemUnit' => $v['itemUnit'],
  116. 'ratio' => $v['ratio'],// 比例
  117. 'rank' => $v['rank'] ?? 'B',// 花材级别
  118. 'bigUnit' => $v['bigUnit'],
  119. 'smallUnit' => $v['smallUnit'],
  120. ];
  121. $tmp['itemInfo'] = json_encode($itemInfo);
  122. $tmp['shopId'] = $outOrderData['inShopId'] ?? 0;
  123. $tmp['mainId'] = $outOrderData['inMainId'] ?? 0;
  124. $batchData[] = $tmp;
  125. }
  126. StockInOrderItemClass::batchAddOrderItem($batchData);
  127. $transaction->commit();
  128. return $order;
  129. } catch (\Exception $exception) {
  130. $transaction->rollBack();
  131. util::fail("入库失败" . $exception->getMessage());
  132. }
  133. }
  134. //确定入库
  135. //修改状态 1=》2
  136. // 加库存
  137. // 加流水记录
  138. //增加门店收支记录 : 出库的门店加金额,入库的门店减金额(用成本价计算)
  139. public static function confirmOrder($orderSn, $shop, $adminId)
  140. {
  141. $shopId = $shop->id ?? 0;
  142. $mainId = $shop->mainId ?? 0;
  143. $staff = ShopAdminClass::getByCondition(['mainId' => $mainId, 'adminId' => $adminId], true);
  144. $staffId = $staff->id ?? 0;
  145. $staffName = $staff->name ?? '';
  146. $data = ['status' => self::STATUS_COMPLETE, 'adminId' => $adminId];
  147. $orderData = self::getOrderDetail($orderSn, $shopId);
  148. if ($orderData['status'] != self::STATUS_WAIT) {
  149. util::fail("订单已处理");
  150. }
  151. $orderId = $orderData['id'];
  152. self::updateById($orderId, $data);
  153. $outShopId = $orderData['outShopId'] ?? 0;
  154. $outShop = ShopClass::getById($outShopId, true);
  155. $event = '从别的门店调拨过来';
  156. if (!empty($outShop)) {
  157. $event = '从' . $outShop->shopName . '调拨过来';
  158. }
  159. $itemInfo = $orderData['itemInfo'] ?? [];
  160. if (empty($itemInfo)) {
  161. util::fail("订单异常");
  162. }
  163. $totalCost = $orderData['price'] ?? 0;
  164. foreach ($itemInfo as $k => $v) {
  165. $currentItemId = $v['productId'] ?? 0;
  166. $currentCost = $v['itemPrice'] ?? 0;
  167. $currentHdPrice = $v['price'] ?? 0;
  168. $currentSkPrice = $v['skPrice'] ?? 0;
  169. $currentHjPrice = $v['hjPrice'] ?? 0;
  170. //不管加盟还是直营店如果当前花材没有库存,则成本和价格都传导过来。
  171. $currentInfo = ProductClass::getById($currentItemId, true);
  172. if (isset($currentInfo->stock) && floatval($currentInfo->stock) == 0) {
  173. $upData = ['cost' => $currentCost];
  174. if ($currentHdPrice > 0) {
  175. $upData['price'] = $currentHdPrice;
  176. }
  177. if ($currentSkPrice > 0) {
  178. $upData['skPrice'] = $currentSkPrice;
  179. }
  180. if ($currentHjPrice > 0) {
  181. $upData['hjPrice'] = $currentHjPrice;
  182. }
  183. ProductClass::updateById($currentItemId, $upData);
  184. //成本变动记录
  185. $changeData = [
  186. 'ptStyle' => 2,
  187. 'sjId' => $currentInfo->sjId ?? 0,
  188. 'mainId' => $currentInfo->mainId ?? 0,
  189. 'itemId' => $currentInfo->id ?? 0,
  190. 'ptItemId' => $currentInfo->itemId ?? 0,
  191. 'cost' => $currentCost,
  192. 'staffId' => $staffId,
  193. 'staffName' => $staffName,
  194. 'name' => $currentInfo->name ?? '',
  195. 'cover' => $currentInfo->cover ?? '',
  196. 'targetId' => $orderId,
  197. 'type' => 1,
  198. 'event' => $event,
  199. ];
  200. CostChangeClass::addData($changeData);
  201. if ($currentHdPrice > 0) {
  202. $changeData = [
  203. 'ptStyle' => 2,
  204. 'sjId' => $currentInfo->sjId ?? 0,
  205. 'mainId' => $mainId,
  206. 'itemId' => $currentInfo->id ?? 0,
  207. 'ptItemId' => $currentInfo->itemId ?? 0,
  208. 'price' => $currentHdPrice,
  209. 'skPrice' => $currentSkPrice,
  210. 'hjPrice' => $currentHjPrice,
  211. 'staffId' => $staffId,
  212. 'staffName' => $staffName,
  213. 'name' => $currentInfo->name ?? '',
  214. 'cover' => $currentInfo->cover ?? '',
  215. 'event' => $event,
  216. 'targetId' => $orderId,
  217. 'type' => 2,
  218. ];
  219. PriceChangeClass::addData($changeData);
  220. }
  221. }
  222. $stockInfo = ProductClass::addStockByItemNum($currentItemId, $v['itemNum']);
  223. $itemInfo[$k]['oldStock'] = $stockInfo['oldStock'];
  224. $itemInfo[$k]['itemStock'] = $stockInfo['oldStock'];
  225. $itemInfo[$k]['newStock'] = $stockInfo['newStock'];
  226. }
  227. //流水记录
  228. $orderData['shopId'] = $shopId;
  229. $orderData['itemInfo'] = $itemInfo;
  230. $orderData['ptStyle'] = dict::getDict('ptStyle', 'ghs');
  231. StockRecordClass::addRecordByOrder($orderData, StockRecordClass::STOCK_RECORD_TYPE_IN_STOCK);
  232. $outOrderSn = $orderData['outOrderSn'];
  233. $outShopId = $orderData['outShopId'];
  234. $outOrderInfo = StockOutOrderClass::getOrderDetail($outOrderSn, $outShopId);
  235. $payWay = dict::getDict('payWay', 'unknown');
  236. if (empty($outOrderInfo)) {
  237. util::fail('没有找到出库单');
  238. }
  239. $outOrderInfoItem = $outOrderInfo['itemInfo'] ?? '';
  240. if (empty($outOrderInfoItem)) {
  241. util::fail('没有出库单信息');
  242. }
  243. $outEvent = '出库';
  244. $outCapitalType = dict::getDict('capitalType', 'ghsCheckOut', 'id');
  245. $shop = ShopClass::getLockById($outShopId);
  246. if (empty($shop)) {
  247. util::fail('没有找到出库门店');
  248. }
  249. $mainId = $shop->mainId ?? 0;
  250. $main = MainClass::getLockById($mainId);
  251. if (empty($main)) {
  252. util::fail('没有main信息34');
  253. }
  254. $outCurrentTotalIncome = bcadd($main->totalIncome, $totalCost, 2);
  255. $currentTotalStockOut = bcadd($main->totalStockOut, $totalCost, 2);
  256. $main->totalIncome = $outCurrentTotalIncome;
  257. $main->totalStockOut = $currentTotalStockOut;
  258. $main->save();
  259. $capitalData = [
  260. 'capitalType' => $outCapitalType,
  261. 'io' => 1,
  262. 'totalIncome' => $outCurrentTotalIncome,
  263. 'payWay' => $payWay,
  264. 'amount' => $totalCost,
  265. 'sjId' => $outOrderInfo['sjId'] ?? 0,
  266. 'shopId' => $outShopId,
  267. 'event' => $outEvent,
  268. 'mainId' => $mainId,
  269. ];
  270. ShopCapitalClass::addCapital($capitalData);
  271. //每天和每月收入统计,出库也算收入
  272. StatIncomeClass::updateOrInsert($main, $shop, $totalCost);
  273. //出库每日和每月统计
  274. StatStockOutClass::replace($main, $shop, $totalCost);
  275. //入库门店
  276. $inEvent = '入库';
  277. $inCapitalType = dict::getDict('capitalType', 'ghsCheckIn', 'id');
  278. $inShop = ShopClass::getLockById($shopId);
  279. if (empty($inShop)) {
  280. util::fail('没有找到入库门店');
  281. }
  282. $inMainId = $inShop->mainId ?? 0;
  283. $inMain = MainClass::getLockById($inMainId);
  284. if (empty($inMain)) {
  285. util::fail('没有main信息35');
  286. }
  287. $inCurrentTotalExpend = bcadd($inMain->totalExpend, $totalCost, 2);
  288. $inMain->totalExpend = $inCurrentTotalExpend;
  289. $currentTotalStockIn = bcadd($inMain->totalStockIn, $totalCost, 2);
  290. $inMain->totalStockIn = $currentTotalStockIn;
  291. $inMain->save();
  292. $capitalData = [
  293. 'capitalType' => $inCapitalType,
  294. 'io' => 0,
  295. 'totalExpend' => $inCurrentTotalExpend,
  296. 'payWay' => $payWay,
  297. 'amount' => $totalCost,
  298. 'sjId' => $orderData['sjId'] ?? 0,
  299. 'shopId' => $shopId,
  300. 'event' => $inEvent,
  301. 'mainId' => $mainId,
  302. ];
  303. ShopCapitalClass::addCapital($capitalData);
  304. //当天和当月支出统计,调拨入库算支出
  305. StatOutClass::updateOrInsert($main, $shop, $totalCost);
  306. //入库每天和每月统计
  307. StatStockInClass::replace($inMain, $inShop, $totalCost);
  308. }
  309. //2021.1.23 lqh 订单详情
  310. public static function getOrderDetail($orderSn, $shopId)
  311. {
  312. $orderData = self::orderExist(['orderSn' => $orderSn, 'inShopId' => $shopId]);
  313. $orderInfo = StockInOrderItemClass::getOrderItemDetail($orderSn);
  314. $itemData = [];
  315. if ($orderInfo) {
  316. foreach ($orderInfo as $v) {
  317. $info = json_decode($v['itemInfo'], true);
  318. $tmp = $info;
  319. $tmp['itemCover'] = self::groupImg($info['itemCover']);
  320. unset($v['itemInfo']);
  321. if (!isset($tmp['rank'])) {
  322. $tmp['rank'] = 'B';
  323. }
  324. $tmp = array_merge($tmp, $v);
  325. $itemData[] = $tmp;
  326. }
  327. }
  328. $orderData = self::groupAdmin($orderData);
  329. $orderData['itemInfo'] = $itemData;
  330. $orderData['statusName'] = self::getStatusName($orderData['status']);
  331. $outShopId = $orderData['outShopId'] ?? 0;
  332. $outShop = ShopClass::getById($outShopId);
  333. $outShopName = $outShop['shopName'] ?? '';
  334. $orderData['outShopName'] = $outShopName;
  335. return $orderData;
  336. }
  337. //2021.1.25 lqh 判断定时是否存在
  338. public static function orderExist($where)
  339. {
  340. $orderData = self::getByCondition($where);
  341. if (!$orderData) {
  342. util::fail('订单不存在');
  343. }
  344. return $orderData;
  345. }
  346. // 组装状态码 lqh 2021.1.30
  347. public static function groupStatusName($list)
  348. {
  349. foreach ($list as $k => $val) {
  350. $status = $val['status'] ?? 0;
  351. $list[$k]['statusName'] = self::getStatusName($status);
  352. }
  353. return $list;
  354. }
  355. // 获取状态码名称
  356. public static function getStatusName($status)
  357. {
  358. return self::$statusMap[$status] ?? '';
  359. }
  360. //组装出库门店信息
  361. public static function groupOutShopName($list)
  362. {
  363. foreach ($list as $k => $val) {
  364. $list[$k]['shopName'] = "出库门店名称";
  365. }
  366. return $list;
  367. }
  368. //取消入库
  369. public static function cancelOrder($order, $adminId)
  370. {
  371. if ($order->status != self::STATUS_WAIT) {
  372. util::fail('订单不能取消');
  373. }
  374. $order->status = self::STATUS_CANCEL;
  375. $order->adminId = $adminId;
  376. $order->save();
  377. $outOrderSn = $order->outOrderSn ?? '';
  378. $outShopId = $order->outShopId ?? '';
  379. $outOrderData = StockOutOrderClass::getOrderDetail($outOrderSn, $outShopId);
  380. $outOrderData['shopId'] = $outShopId;
  381. //加库存
  382. $itemInfo = $outOrderData['itemInfo'] ?? [];
  383. if (empty($itemInfo)) {
  384. util::fail("订单异常");
  385. }
  386. foreach ($itemInfo as $k => $v) {
  387. $stockInfo = ProductClass::addStockByItemNum($v['productId'], $v['itemNum']);
  388. $itemInfo[$k]['oldStock'] = $stockInfo['oldStock'];
  389. $itemInfo[$k]['itemStock'] = $stockInfo['oldStock'];
  390. $itemInfo[$k]['newStock'] = $stockInfo['newStock'];
  391. }
  392. $outOrderData['itemInfo'] = $itemInfo;
  393. $outOrderData['ptStyle'] = dict::getDict('ptStyle', 'ghs');
  394. StockRecordClass::addRecordByOrder($outOrderData, StockRecordClass::STOCK_RECORD_TYPE_IN_STOCK_CANCEL);
  395. //修改出库订单状态
  396. $whereOut = [
  397. 'orderSn' => $outOrderSn,
  398. 'outShopId' => $outShopId,
  399. ];
  400. StockOutOrderClass::updateByCondition($whereOut, ['status' => StockOutOrderClass::STATUS_CANCEL]);
  401. }
  402. }