StockInOrderClass.php 18 KB

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