StockService.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. <?php
  2. namespace app\common\service;
  3. use app\common\util\Result;
  4. use think\annotation\route\Group;
  5. use think\facade\Db;
  6. use app\common\model\Good;
  7. use app\common\model\Repo;
  8. use app\common\model\Stock;
  9. use app\common\util\WhereBuilder;
  10. use app\common\util\PhpSpreadsheetExportV2;
  11. class StockService extends Service
  12. {
  13. public function page($params = [])
  14. {
  15. $this->autoParams($params);
  16. $keyword = $this->pg('keyword');
  17. $repo_id = $this->pg('repo_id');
  18. $good_id = $this->pg('good_id');
  19. $filter_zero_transit = $this->pgd(false, 'filter_zero_transit');
  20. if ($repo_id && !Repo::find($repo_id)) {
  21. throw $this->exception('仓库不存在');
  22. }
  23. if ($good_id && !Good::find($good_id)) {
  24. throw $this->exception('物品不存在');
  25. }
  26. $where = WhereBuilder::builder()
  27. ->like('g.no|g.name|r.name', $keyword)
  28. ->in('s.repo_id', $repo_id)
  29. ->build();
  30. $transit_filter_symbol = '>=';
  31. if ($filter_zero_transit) {
  32. $transit_filter_symbol = '>';
  33. }
  34. $page = (new Stock)
  35. ->alias('s')
  36. ->field('s.*, g.name as good_name, g.no as good_no, r.name as repo_name, IFNULL(sum(abs(d.num) - d.transit_received), 0) as sum_transit')
  37. ->join('good g', 'g.id = s.good_id', 'LEFT')
  38. ->join('repo r', 'r.id = s.repo_id', 'LEFT')
  39. ->join('io_detail d', 'd.good_id = s.good_id AND d.repo_id = s.repo_id AND d.transit_status = "TRANSIT"', 'LEFT')
  40. ->where($where)
  41. ->whereRaw("IFNULL(abs(d.num) - d.transit_received, 0) $transit_filter_symbol 0")
  42. ->group('s.id')
  43. ->paginate($this->tp6Page(PHP_INT_MAX));
  44. return $page;
  45. }
  46. public function allByRepo($params = [])
  47. {
  48. $this->autoParams($params);
  49. $repo = $this->one(Repo::class);
  50. return (new Stock)->where('repo_id', '=', $repo->id)->select();
  51. }
  52. public function info($params = [])
  53. {
  54. $this->autoParams($params);
  55. $stock = $this->one(Stock::class);
  56. $stock->append(['good']);
  57. return $stock;
  58. }
  59. public function getByGoodAndRepo($params = [])
  60. {
  61. $this->autoParams($params);
  62. $good = $this->one(Good::class, 'good_id');
  63. $repo = $this->one(Repo::class, 'repo_id');
  64. return (new Stock)
  65. ->with(['good'])
  66. ->where('good_id', '=', $good->id)
  67. ->where('repo_id', '=', $repo->id)
  68. ->find()
  69. ?? Result::rest(['repo_id' => $repo->id, 'good_id' => $good->id, 'num' => 0]);
  70. }
  71. /**
  72. * tp6是支持事务嵌套的,为了保证修改库存时数据不出现问题,请无脑使用该事务方法
  73. */
  74. public function chengeStockTrans(Repo $repo, Good $good, $change)
  75. {
  76. // tp6是支持事务嵌套的,所有修改可以直接用事务
  77. return Db::transaction(fn() => $this->changeStock($repo, $good, $change));
  78. }
  79. protected function changeStock(Repo $repo, Good $good, $change)
  80. {
  81. if (!$repo) {
  82. throw $this->exception('致命错误,$repo为空');
  83. }
  84. if (!$good) {
  85. throw $this->exception('致命错误,$good为空');
  86. }
  87. /**
  88. * @var Stock
  89. */
  90. $stock = (new Stock)
  91. ->lock(true)
  92. ->where('good_id', '=', $good->id)
  93. ->where('repo_id', '=', $repo->id)
  94. ->find();
  95. if (!$stock) {
  96. $stock = Stock::create([
  97. 'repo_id' => $repo->id,
  98. 'good_id' => $good->id,
  99. 'num' => 0
  100. ]);
  101. }
  102. if ($change < 0 && $stock->num < abs($change)) {
  103. $info = <<<EOF
  104. 物品{$good->name}库存不足,当前库存为{$stock->num},出库数量为{$change}
  105. 出现这种情况可能有以下原因:
  106. - 在该操作前,该物品已由另一名操作员出库,导致库存不足
  107. - 多个相同商品出库相加库存不足
  108. - 库存不足
  109. - 库存低于0.01,此时系统会认为没有库存,请避免此类情况的发生
  110. - 出库数量/库存数量过高导致溢出,如出现此类情况请联系开发人员解决
  111. EOF;
  112. throw $this->exception($info);
  113. }
  114. $stock->num += $change;
  115. $stock->save();
  116. }
  117. public function export($params = [])
  118. {
  119. $params = $this->autoParams($params);
  120. $params['pageParams']['size'] = PHP_INT_MAX;
  121. $stocks = $this->page($params)->getCollection();
  122. $stocks = $stocks->map(fn(Stock $stock) => $stock->getData());
  123. $header = [
  124. [
  125. 'id',
  126. '仓库id',
  127. '商品id',
  128. '创建时间',
  129. '更新时间',
  130. '删除时间',
  131. '数量',
  132. '商品名',
  133. '编号',
  134. '仓库名',
  135. '在途数量'
  136. ]
  137. ];
  138. $res = PhpSpreadsheetExportV2::outputFile(
  139. $stocks,
  140. $header,
  141. '仓储管理系统' . date('Ymdis'),
  142. []
  143. );
  144. return $res;
  145. }
  146. }