Inventory.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <?php
  2. /**
  3. * Niushop商城系统 - 团队十年电商经验汇集巨献!
  4. * =========================================================
  5. * Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
  6. * ----------------------------------------------
  7. * 官方网址: https://www.niushop.com
  8. * =========================================================
  9. */
  10. namespace addon\stock\model\stock;
  11. use app\model\store\Store;
  12. use app\model\BaseModel;
  13. use app\model\storegoods\StoreGoods;
  14. /**
  15. * 盘点
  16. *
  17. * @author Administrator
  18. *
  19. */
  20. class Inventory extends BaseModel
  21. {
  22. /**
  23. * 添加盘点单
  24. * @param array $inventory_data
  25. * @param array $inventory_goods_data (sku_id:盘点数量,sku_id:盘点数量)
  26. */
  27. public function addInventory($params)
  28. {
  29. //同商品同时只能存在一个盘点单据
  30. model('stock_inventory')->startTrans();
  31. try {
  32. $site_id = $params[ 'site_id' ];
  33. $store_id = $params[ 'store_id' ];
  34. $sku_list = $params[ 'sku_list' ];
  35. $user_info = $params[ 'user_info' ];
  36. $inventory_no = 'PD' . date('ymdhis', time()) . rand(1111, 9999);
  37. //查询门店名称信息
  38. $store_model = new Store();
  39. $store_condition = array (
  40. [ 'store_id', '=', $store_id ]
  41. );
  42. $store_info = $store_model->getStoreInfo($store_condition, 'store_name')[ 'data' ] ?? [];
  43. if (empty($store_info)) {
  44. model('stock_inventory')->rollback();
  45. return $this->success([], '找不到所选的门店');
  46. }
  47. $store_name = $store_info[ 'store_name' ];
  48. $common_data = array (
  49. 'site_id' => $site_id,
  50. 'create_time' => time(),
  51. 'store_id' => $store_id
  52. );
  53. $data = array (
  54. 'operater' => $user_info[ 'uid' ] ?? 0,
  55. 'operater_name' => $user_info[ 'username' ] ?? '',
  56. 'create_time' => time(),
  57. 'inventory_no' => $inventory_no,
  58. 'store_name' => $store_name,
  59. 'remark' => $params[ 'remark' ] ?? ''
  60. );
  61. //盘点单据
  62. $inventory_data = array_merge($data, $common_data);
  63. $inventory_id = model('stock_inventory')->add($inventory_data);
  64. $common_data[ 'inventory_id' ] = $inventory_id;
  65. foreach ($sku_list as $k => $goods_sku) {
  66. $goods_sku_id = $goods_sku[ 'goods_sku_id' ];
  67. $goods_num = numberFormat($goods_sku[ 'goods_num' ]);
  68. $goods_remark = '';
  69. //具体业务尚未调试,表结构不一致
  70. $goods_sku_info = model('goods_sku')->getInfo([ [ 'sku_id', '=', $goods_sku_id ] ], 'sku_id,goods_id,sku_name,sku_no,sku_image,spec_name');
  71. $goods_sku_data_info = model('store_goods_sku')->getInfo([ [ 'sku_id', '=', $goods_sku_id ], [ 'store_id', '=', $store_id ] ], '*');
  72. $goods_stock = $goods_sku_data_info[ 'real_stock' ] ?? 0;
  73. $goods_sku_data = [];
  74. $goods_sku_data[ 'inventory_num' ] = $goods_num;
  75. $goods_sku_data[ 'inventory_remark' ] = $goods_remark;
  76. $goods_sku_data[ 'goods_id' ] = $goods_sku_info[ 'goods_id' ];
  77. $goods_sku_data[ 'goods_sku_id' ] = $goods_sku_id;
  78. $goods_sku_data[ 'goods_sku_name' ] = $goods_sku_info[ 'sku_name' ];
  79. $goods_sku_data[ 'goods_sku_no' ] = $goods_sku_info[ 'sku_no' ];
  80. $goods_sku_data[ 'goods_sku_spec' ] = $goods_sku_info[ 'spec_name' ];
  81. $goods_sku_data[ 'goods_img' ] = $goods_sku_info[ 'sku_image' ];
  82. $goods_sku_data[ 'stock' ] = numberFormat($goods_stock);
  83. model('stock_inventory_goods')->add(array_merge($goods_sku_data, $common_data));
  84. }
  85. //主动调用审核
  86. $inventory_params = array (
  87. 'inventory_id' => $inventory_id,
  88. 'site_id' => $site_id,
  89. 'user_info' => $user_info
  90. );
  91. $audit_result = $this->audit($inventory_params);
  92. if ($audit_result[ 'code' ] < 0) {
  93. model('stock_inventory')->rollback();
  94. return $audit_result;
  95. }
  96. model('stock_inventory')->commit();
  97. return $this->success();
  98. } catch (\Exception $e) {
  99. model('stock_inventory')->rollback();
  100. return $this->error($e->getMessage() . $e->getFile() . $e->getLine());
  101. }
  102. }
  103. /**
  104. * 通过审核
  105. * @param $params
  106. */
  107. public function audit($params)
  108. {
  109. $inventory_id = $params[ 'inventory_id' ];
  110. $site_id = $params[ 'site_id' ];
  111. $user_info = $params[ 'user_info' ];
  112. $condition = array (
  113. [ 'inventory_id', '=', $inventory_id ],
  114. [ 'site_id', '=', $site_id ]
  115. );
  116. $info = model('stock_inventory')->getInfo($condition);
  117. if (empty($info))
  118. return $this->error([], '找不到可审核的单据');
  119. $data = array (
  120. 'status' => 1
  121. );
  122. model('stock_inventory')->update($data, $condition);
  123. $store_id = $info[ 'store_id' ];
  124. $result = $this->complete([ 'inventory_id' => $inventory_id, 'site_id' => $site_id, 'store_id' => $store_id, 'user_info' => $user_info ]);
  125. return $result;
  126. }
  127. /**
  128. * 单据通过审核
  129. * @param $params
  130. */
  131. public function complete($params)
  132. {
  133. $inventory_id = $params[ 'inventory_id' ];
  134. $user_info = $params[ 'user_info' ] ?? [];
  135. $site_id = $params[ 'site_id' ];
  136. $condition = array (
  137. [ 'inventory_id', '=', $inventory_id ],
  138. [ 'site_id', '=', $site_id ]
  139. );
  140. $info = model('stock_inventory')->getInfo($condition);
  141. if (empty($info))
  142. return $this->error([], '找不到可审核的单据');
  143. $stock_inventory_goods_list = model('stock_inventory_goods')->getList($condition, '*');
  144. if (empty($stock_inventory_goods_list))
  145. return $this->error([], '找不到可审核的单据');
  146. $store_id = $info[ 'store_id' ];
  147. $stat_data = $this->stat([ 'inventory_id' => $inventory_id, 'store_id' => $store_id ])[ 'data' ] ?? [];
  148. $data = array (
  149. 'kinds_num' => $stat_data[ 'kinds_num' ],
  150. 'kinds_profit_num' => $stat_data[ 'kinds_profit_num' ],
  151. 'kinds_loss_num' => $stat_data[ 'kinds_loss_num' ],
  152. 'kinds_even_num' => $stat_data[ 'kinds_even_num' ],
  153. 'num' => $stat_data[ 'num' ],
  154. 'profit_num' => $stat_data[ 'profit_num' ],
  155. 'loss_num' => $stat_data[ 'loss_num' ],
  156. 'even_num' => $stat_data[ 'even_num' ],
  157. 'profitloss_num' => $stat_data[ 'profitloss_num' ],
  158. 'inventory_cost_money' => $stat_data[ 'inventory_cost_money' ],
  159. 'profitloss_sale_money' => $stat_data[ 'profitloss_sale_money' ],
  160. );
  161. model('stock_inventory')->update($data, $condition);
  162. $inventory_goods_list = $stat_data[ 'inventory_goods_list' ] ?? [];
  163. $goods_model = new \app\model\goods\Goods();
  164. $store_goods_model = new StoreGoods();
  165. foreach ($inventory_goods_list as $k => $v) {
  166. $item_sku_id = $v[ 'goods_sku_id' ];
  167. $item_goods_id = $v[ 'goods_id' ];
  168. $input_array = [];
  169. $output_array = [];
  170. $item_condition = array (
  171. [ 'inventory_id', '=', $inventory_id ],
  172. [ 'goods_sku_id', '=', $item_sku_id ]
  173. );
  174. $item_data = array (
  175. 'inventory_id' => $inventory_id,
  176. 'goods_id' => $v[ 'goods_id' ],
  177. 'goods_sku_id' => $v[ 'goods_sku_id' ],
  178. 'stock' => $v[ 'stock' ],
  179. 'inventory_num' => $v[ 'inventory_num' ],
  180. 'inventory_remark' => $v[ 'inventory_remark' ] ?? '',
  181. 'profitloss_num' => $v[ 'profitloss_num' ],
  182. 'inventory_cost_money' => $v[ 'inventory_cost_money' ],
  183. 'profitloss_sale_money' => $v[ 'profitloss_sale_money' ],
  184. );
  185. model('stock_inventory_goods')->update($item_data, $item_condition);
  186. $store_goods_sku_condition = array (
  187. [ 'sku_id', '=', $item_sku_id ],
  188. [ 'store_id', '=', $store_id ]
  189. );
  190. $store_sku_info = $store_goods_model->getStoreGoodsSkuInfo($store_goods_sku_condition)[ 'data' ] ?? [];
  191. $store_sku_stock = $store_sku_info[ 'real_stock' ] ?? 0;
  192. $inventory_num = $v[ 'inventory_num' ];
  193. $goods_sku_condition = array (
  194. [ 'sku_id', '=', $item_sku_id ],
  195. );
  196. $sku_info = $goods_model->getGoodsSkuInfo($goods_sku_condition, 'sku_name, unit')[ 'data' ] ?? [];
  197. $item_price = $store_sku_info[ 'cost_price' ] ?? 0;
  198. $item_unit = $store_sku_info[ 'unit' ] ?? '件';
  199. $diff = abs($inventory_num - $store_sku_stock);
  200. if ($diff != 0) {
  201. if ($inventory_num > $store_sku_stock) {
  202. $input_array[] = [
  203. 'goods_id' => $item_goods_id,
  204. 'goods_sku_id' => $item_sku_id,
  205. 'goods_sku_name' => $sku_info[ 'sku_name' ],
  206. 'goods_unit' => $item_unit,
  207. 'goods_num' => $diff,
  208. 'goods_price' => $item_price,
  209. ];
  210. } else if ($inventory_num < $store_sku_stock) {
  211. $output_array[] = [
  212. 'goods_id' => $item_goods_id,
  213. 'goods_sku_id' => $item_sku_id,
  214. 'goods_sku_name' => $sku_info[ 'sku_name' ],
  215. 'goods_unit' => $item_unit,
  216. 'goods_num' => $diff,
  217. 'goods_price' => $item_price,
  218. ];
  219. }
  220. $document = new Document();
  221. $document_params = array (
  222. 'inventory_id' => $inventory_id,
  223. 'store_id' => $store_id,
  224. 'user_info' => $user_info,
  225. 'site_id' => $site_id
  226. );
  227. if (!empty($input_array)) {
  228. $document_params[ 'document_type' ] = 'PANYING';
  229. $document_params[ 'goods_sku_list' ] = $input_array;
  230. $result = $document->addDocument($document_params);
  231. }
  232. if (!empty($output_array)) {
  233. $document_params[ 'document_type' ] = 'PANKUI';
  234. $document_params[ 'goods_sku_list' ] = $output_array;
  235. $document_params[ 'is_out_stock' ] = 1;
  236. $result = $document->addDocument($document_params);
  237. }
  238. if ($result[ 'code' ] < 0) {
  239. return $result;
  240. }
  241. }
  242. }
  243. return $this->success();
  244. }
  245. /**
  246. * 数据统计以及整理
  247. * @param $params
  248. * @return array
  249. */
  250. public function stat($params)
  251. {
  252. $inventory_id = $params[ 'inventory_id' ];
  253. $condition = array (
  254. [ 'inventory_id', '=', $inventory_id ]
  255. );
  256. $info = model('stock_inventory')->getInfo($condition);
  257. $store_id = $info[ 'store_id' ];
  258. $kinds_num = $kinds_profit_num = $kinds_loss_num = $kinds_even_num = $num = $profit_num = $loss_num = $even_num = $profitloss_num = $inventory_cost_money = $profitloss_sale_money = 0;
  259. $stock_inventory_goods_list = model('stock_inventory_goods')->getList($condition, '*');
  260. $store_goods_model = new StoreGoods();
  261. $inventory_goods_list = [];
  262. foreach ($stock_inventory_goods_list as $k => $v) {
  263. $kinds_num++;
  264. $sku_id = $v[ 'goods_sku_id' ];
  265. $goods_id = $v[ 'goods_id' ];
  266. $store_sku_condition = array (
  267. [ 'store_id', '=', $store_id ],
  268. [ 'sku_id', '=', $sku_id ]
  269. );
  270. $v[ 'stock' ] = numberFormat($v[ 'stock' ]);
  271. $v[ 'inventory_num' ] = numberFormat($v[ 'inventory_num' ]);
  272. $v[ 'profitloss_num' ] = numberFormat($v[ 'profitloss_num' ]);
  273. $sku_info = model('goods_sku')->getInfo([ [ 'sku_id', '=', $sku_id ] ]);
  274. $item_info = $store_goods_model->getStoreGoodsSkuInfo($store_sku_condition)[ 'data' ] ?? [];
  275. $item_price = $item_info[ 'price' ] ?? 0;//销售价
  276. $item_cost_price = $item_info[ 'cost_price' ] ?? 0;// 成本价
  277. $item_stock = $item_info[ 'real_stock' ] ?? 0;//实物库存
  278. // $item_sale_stock = $item_info['stock'] ?? 0;//销售库存
  279. // $item_total_cost_money = $item_cost_price * $item_stock;//总成本价
  280. $item_total_sale_money = $item_price * $item_stock;//总销售价
  281. $inventory_num = $v[ 'inventory_num' ];//盘点数量
  282. $item_inventory_cost_money = $inventory_num * $item_cost_price;
  283. $inventory_cost_money += $item_inventory_cost_money;//盘点总成本价
  284. $ing_total_sale_money = $inventory_num * $item_price;//盘点总销售价
  285. $num += $inventory_num;//盘点总数
  286. $item_profitloss_num = $inventory_num - $item_stock;
  287. $item_profitloss_sale_money = 0;
  288. if ($item_profitloss_num == 0) {//持平
  289. $kinds_even_num++;
  290. $even_num += abs($item_profitloss_num);
  291. } else if ($item_profitloss_num > 0) {//盘盈数
  292. $kinds_profit_num++;
  293. $profit_num += abs($item_profitloss_num);
  294. $item_profitloss_sale_money = $ing_total_sale_money - $item_total_sale_money;
  295. } else {//盘亏数
  296. $kinds_loss_num++;
  297. $loss_num += abs($item_profitloss_num);
  298. }
  299. $profitloss_num += $item_profitloss_num;
  300. $profitloss_sale_money += $item_profitloss_sale_money;
  301. $inventory_goods_list[ $sku_id ] = [
  302. 'goods_id' => $goods_id,
  303. 'goods_sku_id' => $sku_id,
  304. 'goods_sku_name' => $sku_info[ 'sku_name' ],
  305. 'goods_sku_no' => $sku_info[ 'sku_no' ],
  306. 'goods_unit' => $sku_info[ 'unit' ],
  307. 'stock' => numberFormat($item_stock),
  308. 'inventory_num' => numberFormat($inventory_num),
  309. // 'goods_price' => $item_info['cost_price'],
  310. 'profitloss_num' => numberFormat($item_profitloss_num),
  311. 'inventory_cost_money' => $item_inventory_cost_money,
  312. 'profitloss_sale_money' => $item_profitloss_sale_money,
  313. ];
  314. }
  315. $data = array (
  316. 'kinds_num' => $kinds_num,
  317. 'kinds_profit_num' => $kinds_profit_num,
  318. 'kinds_loss_num' => $kinds_loss_num,
  319. 'kinds_even_num' => $kinds_even_num,
  320. 'num' => $num,
  321. 'profit_num' => $profit_num,
  322. 'loss_num' => $loss_num,
  323. 'even_num' => $even_num,
  324. 'profitloss_num' => $profitloss_num,
  325. 'inventory_cost_money' => $inventory_cost_money,
  326. 'profitloss_sale_money' => $profitloss_sale_money,
  327. 'inventory_goods_list' => $inventory_goods_list
  328. );
  329. return $this->success($data);
  330. }
  331. /**
  332. * 库存盘点单列表
  333. * @param array $conditionstock_document
  334. * @param number $page
  335. * @param string $page_size
  336. * @param string $order
  337. * @param string $field
  338. */
  339. public function getInventoryPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '*')
  340. {
  341. $list = model('stock_inventory')->pageList($condition, $field, $order, $page, $page_size);
  342. foreach ($list as $k => $v) {
  343. if (isset($v[ 'num' ])) {
  344. $list[ $k ][ 'num' ] = numberFormat($list[ $k ][ 'num' ]);
  345. }
  346. if (isset($v[ 'profit_num' ])) {
  347. $list[ $k ][ 'profit_num' ] = numberFormat($list[ $k ][ 'profit_num' ]);
  348. }
  349. if (isset($v[ 'loss_num' ])) {
  350. $list[ $k ][ 'loss_num' ] = numberFormat($list[ $k ][ 'loss_num' ]);
  351. }
  352. if (isset($v[ 'even_num' ])) {
  353. $list[ $k ][ 'even_num' ] = numberFormat($list[ $k ][ 'even_num' ]);
  354. }
  355. if (isset($v[ 'profitloss_num' ])) {
  356. $list[ $k ][ 'profitloss_num' ] = numberFormat($list[ $k ][ 'profitloss_num' ]);
  357. }
  358. }
  359. return $this->success($list);
  360. }
  361. /**
  362. * 单据详情
  363. * @param array $condition
  364. * @param string $field
  365. */
  366. public function getInventoryInfo($condition = [], $field = '*')
  367. {
  368. $inventory_info = model('stock_inventory')->getInfo($condition, $field);
  369. if (!empty($inventory_info)) {
  370. if (isset($inventory_info[ 'num' ])) {
  371. $inventory_info[ 'num' ] = numberFormat($inventory_info[ 'num' ]);
  372. }
  373. if (isset($inventory_info[ 'profit_num' ])) {
  374. $inventory_info[ 'profit_num' ] = numberFormat($inventory_info[ 'profit_num' ]);
  375. }
  376. if (isset($inventory_info[ 'loss_num' ])) {
  377. $inventory_info[ 'loss_num' ] = numberFormat($inventory_info[ 'loss_num' ]);
  378. }
  379. if (isset($inventory_info[ 'even_num' ])) {
  380. $inventory_info[ 'even_num' ] = numberFormat($inventory_info[ 'even_num' ]);
  381. }
  382. if (isset($inventory_info[ 'profitloss_num' ])) {
  383. $inventory_info[ 'profitloss_num' ] = numberFormat($inventory_info[ 'profitloss_num' ]);
  384. }
  385. //单据产品项
  386. $inventory_goods_list = model('stock_inventory_goods')->getList([
  387. [ 'inventory_id', '=', $inventory_info[ 'inventory_id' ] ]
  388. ]);
  389. foreach ($inventory_goods_list as $k => $v) {
  390. $inventory_goods_list[ $k ][ 'stock' ] = numberFormat($inventory_goods_list[ $k ][ 'stock' ]);
  391. $inventory_goods_list[ $k ][ 'inventory_num' ] = numberFormat($inventory_goods_list[ $k ][ 'inventory_num' ]);
  392. $inventory_goods_list[ $k ][ 'profitloss_num' ] = numberFormat($inventory_goods_list[ $k ][ 'profitloss_num' ]);
  393. }
  394. $inventory_info[ 'goods_sku_list_array' ] = $inventory_goods_list;
  395. $inventory_info[ 'goods_count' ] = count($inventory_info[ 'goods_sku_list_array' ]);
  396. $inventory_info[ 'create_time' ] = date('Y-m-d H:i:s', $inventory_info[ 'create_time' ]);
  397. }
  398. return $this->success($inventory_info);
  399. }
  400. }