BizIngest.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. namespace app\common\library\ps;
  3. use app\common\model\ps\Product;
  4. use app\common\model\ps\Workorder;
  5. use think\Exception;
  6. /**
  7. * 产品/工单统一入库(页面、AI 导入、Open API 共用)
  8. */
  9. class BizIngest
  10. {
  11. /**
  12. * @param array $payload
  13. * @param int $userId
  14. * @return Product
  15. * @throws Exception
  16. */
  17. public static function saveProduct(array $payload, $userId = 0)
  18. {
  19. $factoryId = FactoryContext::requireId();
  20. $code = self::str($payload, ['code', 'product_code', 'no'], 64);
  21. $name = self::str($payload, ['name', 'product_name', 'title'], 100);
  22. if ($code === '' && $name === '') {
  23. throw new Exception('产品缺少编码或名称');
  24. }
  25. if ($code === '') {
  26. $code = 'P' . date('ymdHis') . substr((string)mt_rand(100, 999), 0, 3);
  27. }
  28. if ($name === '') {
  29. $name = $code;
  30. }
  31. $processes = self::normalizeProcesses($payload);
  32. $row = (new Product())->where('factory_id', $factoryId)->where('code', $code)->find();
  33. $data = [
  34. 'code' => $code,
  35. 'name' => $name,
  36. 'spec' => self::str($payload, ['spec'], 100),
  37. 'unit' => self::str($payload, ['unit'], 20) ?: '件',
  38. 'remark' => self::str($payload, ['remark'], 255),
  39. 'status' => 'normal',
  40. 'creator_user_id' => $userId,
  41. ];
  42. if ($row) {
  43. unset($data['creator_user_id']);
  44. $row->allowField(true)->save($data);
  45. } else {
  46. $row = new Product();
  47. $row->allowField(true)->save($data);
  48. }
  49. ProcessWriter::save($row->id, $processes, 'product');
  50. return $row;
  51. }
  52. /**
  53. * @param array $payload
  54. * @param int $userId
  55. * @return Workorder
  56. * @throws Exception
  57. */
  58. public static function saveWorkorder(array $payload, $userId = 0)
  59. {
  60. $factoryId = FactoryContext::requireId();
  61. $no = self::str($payload, ['no', 'workorder_no', 'code'], 64);
  62. if ($no === '') {
  63. $no = 'WO' . date('ymdHis') . substr((string)mt_rand(100, 999), 0, 3);
  64. }
  65. $productId = (int)($payload['product_id'] ?? 0);
  66. $productCode = self::str($payload, ['product_code'], 64);
  67. if ($productId <= 0 && $productCode !== '') {
  68. $product = (new Product())->where('factory_id', $factoryId)->where('code', $productCode)->find();
  69. if (!$product) {
  70. $product = self::saveProduct([
  71. 'code' => $productCode,
  72. 'name' => self::str($payload, ['product_name', 'name'], 100) ?: $productCode,
  73. 'spec' => self::str($payload, ['spec'], 100),
  74. 'unit' => self::str($payload, ['unit'], 20),
  75. 'processes' => [],
  76. ], $userId);
  77. }
  78. $productId = (int)$product->id;
  79. }
  80. $processes = self::normalizeProcesses($payload);
  81. if (!$processes && $productId > 0) {
  82. $product = Product::with('processes')->find($productId);
  83. $processes = $product ? $product['processes'] : [];
  84. }
  85. $productName = self::str($payload, ['product_name', 'name'], 100);
  86. if ($productName === '' && $productId > 0) {
  87. $linked = isset($product) ? $product : Product::get($productId);
  88. $productName = $linked ? (string)$linked['name'] : '';
  89. }
  90. if ($productName === '') {
  91. throw new Exception('请选择产品或填写名称');
  92. }
  93. $row = (new Workorder())->where('factory_id', $factoryId)->where('no', $no)->find();
  94. $data = [
  95. 'no' => $no,
  96. 'product_id' => $productId,
  97. 'product_name' => $productName,
  98. 'batch_no' => self::str($payload, ['batch_no', 'batch'], 64),
  99. 'customer' => self::str($payload, ['customer'], 100),
  100. 'plan_date' => self::date($payload, ['plan_date', 'date']),
  101. 'remark' => self::str($payload, ['remark'], 255),
  102. 'status' => self::str($payload, ['status'], 20) ?: 'draft',
  103. 'creator_user_id' => $userId,
  104. ];
  105. if ($row) {
  106. unset($data['creator_user_id']);
  107. $row->allowField(true)->save($data);
  108. } else {
  109. $row = new Workorder();
  110. $row->allowField(true)->save($data);
  111. }
  112. ProcessWriter::save($row->id, $processes, 'workorder');
  113. return $row;
  114. }
  115. /**
  116. * @param array $payload
  117. * @return array
  118. */
  119. public static function normalizeProcesses($payload)
  120. {
  121. $rows = [];
  122. if (isset($payload['processes']) && is_array($payload['processes'])) {
  123. $rows = $payload['processes'];
  124. } elseif (isset($payload['process_list']) && is_array($payload['process_list'])) {
  125. $rows = $payload['process_list'];
  126. }
  127. $out = [];
  128. $seq = 1;
  129. foreach ($rows as $row) {
  130. if (!is_array($row)) {
  131. continue;
  132. }
  133. $name = self::str($row, ['name', 'process_name', 'title'], 100);
  134. $code = self::str($row, ['code', 'process_code', 'no'], 64);
  135. if ($name === '' && $code === '') {
  136. continue;
  137. }
  138. $out[] = [
  139. 'seq' => isset($row['seq']) && $row['seq'] !== '' ? (int)$row['seq'] : $seq,
  140. 'code' => $code,
  141. 'name' => $name !== '' ? $name : $code,
  142. 'workstation' => self::str($row, ['workstation', 'station'], 64),
  143. 'standard_time' => self::str($row, ['standard_time', 'time'], 32),
  144. 'qc_points' => self::str($row, ['qc_points', 'qc'], 255),
  145. 'remark' => self::str($row, ['remark'], 255),
  146. ];
  147. $seq++;
  148. }
  149. return $out;
  150. }
  151. protected static function str(array $data, array $keys, $max = 255)
  152. {
  153. foreach ($keys as $key) {
  154. if (!isset($data[$key])) {
  155. continue;
  156. }
  157. $v = trim((string)$data[$key]);
  158. if ($v !== '') {
  159. return mb_substr($v, 0, $max);
  160. }
  161. }
  162. return '';
  163. }
  164. protected static function num(array $data, array $keys)
  165. {
  166. foreach ($keys as $key) {
  167. if (!isset($data[$key]) || $data[$key] === '') {
  168. continue;
  169. }
  170. return (float)$data[$key];
  171. }
  172. return 0;
  173. }
  174. protected static function date(array $data, array $keys)
  175. {
  176. $v = self::str($data, $keys, 32);
  177. if ($v === '') {
  178. return null;
  179. }
  180. $ts = strtotime($v);
  181. return $ts ? date('Y-m-d', $ts) : null;
  182. }
  183. }