UpdatePickZone.php 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. namespace App\Imports;
  3. use App\OracleDOCOrderDetail;
  4. use App\Services\LogService;
  5. use Carbon\Carbon;
  6. use Illuminate\Database\Eloquent\Builder;
  7. use Illuminate\Support\Collection;
  8. use Illuminate\Support\Facades\Auth;
  9. use Illuminate\Support\Facades\Cache;
  10. use Illuminate\Support\Facades\DB;
  11. use Maatwebsite\Excel\Concerns\ToCollection;
  12. use Maatwebsite\Excel\Concerns\WithHeadingRow;
  13. use Maatwebsite\Excel\Imports\HeadingRowFormatter;
  14. HeadingRowFormatter::default('none');
  15. class UpdatePickZone implements ToCollection,WithHeadingRow
  16. {
  17. /**
  18. * @param Collection $collection
  19. * @return bool
  20. * @throws
  21. */
  22. public function collection(Collection $collection)
  23. {
  24. $row = $collection->first();
  25. $headers = ["订单编号","商品条码","数量","生产日期","失效日期"];
  26. foreach ($headers as $header){
  27. if (!isset($row[$header])){
  28. Cache::put("commodityAssign",["success"=>false, "data"=>"表头不存在“".$header."”"],86400);
  29. return false;
  30. }
  31. }
  32. $errors = [];
  33. $ids = [];
  34. foreach ($collection as $index=>$item){
  35. if (!$item["订单编号"] && !$item["生产日期"] && !$item["失效日期"] && !$item["商品条码"] && !$item["数量"])continue;
  36. if (!$item["订单编号"]){
  37. $errors[] = "第“" . ($index + 2) . "”行订单编号为空";
  38. continue;
  39. }
  40. if (!$item["商品条码"]){
  41. $errors[] = "“{$item['订单编号']}”商品条码为空";
  42. continue;
  43. }
  44. if ($item["生产日期"]){
  45. if (is_numeric($item["生产日期"]))$item["生产日期"] = formatExcelDate($item["生产日期"]);
  46. else{
  47. try{
  48. $item["生产日期"]=Carbon::parse($item["生产日期"])->format('Y-m-d');
  49. }catch (\Exception $e){
  50. $errors[] = "“{$item["订单编号"]}”生产日期无法识别";
  51. continue;
  52. }
  53. }
  54. }
  55. if ($item["失效日期"]){
  56. if (is_numeric($item["失效日期"]))$item["失效日期"] = formatExcelDate($item["失效日期"]);
  57. else{
  58. try{
  59. $item["失效日期"]=Carbon::parse($item["失效日期"])->format('Y-m-d');
  60. }catch (\Exception $e){
  61. $errors[] = "“{$item['订单编号']}”失效日期无法识别";
  62. continue;
  63. }
  64. }
  65. }
  66. if (!$item["生产日期"] && !$item["失效日期"]){
  67. $errors[] = "“{$item['订单编号']}”不存在日期";
  68. continue;
  69. }
  70. $detail = OracleDOCOrderDetail::query()->select("DOC_ORDER_DETAILS.customerid","DOC_ORDER_DETAILS.sku","DOC_ORDER_DETAILS.orderno","DOC_ORDER_DETAILS.orderlineno","sostatus")
  71. ->where("DOC_ORDER_DETAILS.orderno",$item["订单编号"])
  72. ->whereHas("sku",function ($query)use($item){
  73. /** @var Builder $query */
  74. $query->where("alternate_sku1",$item["商品条码"]);
  75. })->leftJoin("DOC_ORDER_HEADER","DOC_ORDER_DETAILS.ORDERNO","=","DOC_ORDER_HEADER.ORDERNO")->first();
  76. if (!$detail){
  77. $errors[] = "“{$item['订单编号']}”未知订单商品";
  78. continue;
  79. }
  80. if ($detail->sostatus != '00'){
  81. $errors[] = "“{$item['订单编号']}”订单状态不为创建订单";
  82. continue;
  83. }
  84. $sql = "select BAS_ZONE.DESCR,INV_LOT_LOC_ID.LOCATIONID,INV_LOT_LOC_ID.LOTNUM,BAS_LOCATION.PICKZONE,(INV_LOT_LOC_ID.QTY-INV_LOT_LOC_ID.QTYALLOCATED-QTYONHOLD-QTYRPOUT-QTYMVOUT) AS qty from INV_LOT_ATT LEFT JOIN
  85. INV_LOT_LOC_ID ON INV_LOT_ATT.LOTNUM = INV_LOT_LOC_ID.LOTNUM LEFT JOIN BAS_LOCATION ON INV_LOT_LOC_ID.LOCATIONID = BAS_LOCATION.LOCATIONID
  86. LEFT JOIN BAS_ZONE ON BAS_LOCATION.PICKZONE = BAS_ZONE.ZONE
  87. where INV_LOT_ATT.LOTNUM in (select LOTNUM from INV_LOT_LOC_ID where CUSTOMERID = ? AND SKU = ? GROUP BY LOTNUM)";
  88. $bindings = [$detail->customerid,$detail->sku];
  89. if ($item["生产日期"]){
  90. $sql .= " AND LOTATT01 = ?";
  91. $bindings[] = $item["生产日期"];
  92. }else $sql .= " AND LOTATT01 IS NULL";
  93. if ($item["失效日期"]){
  94. $sql .= " AND LOTATT02 = ?";
  95. $bindings[] = $item["失效日期"];
  96. }else $sql .= " AND LOTATT02 IS NULL";
  97. $lots = DB::connection("oracle")->select(DB::raw($sql),$bindings);
  98. if (!$lots){
  99. $errors[] = "“{$item['订单编号']}”未找到库位";
  100. continue;
  101. }
  102. $result = null;
  103. if (count($lots) == 1)$result = $lots[0];
  104. else {
  105. $zone = ["存储","拣货","虚拟"];
  106. $zones = [[],[],[]];
  107. foreach ($lots as $lot){
  108. foreach ($zone as $ind=>$str){
  109. if (mb_strpos($lot->descr,$str) !== false){
  110. $zones[$ind][] = $lot;
  111. break;
  112. }
  113. }
  114. }
  115. foreach ($zones as $zl){
  116. $result = $this->matchingMax($zl,$item["数量"]);
  117. if ($result)break;
  118. }
  119. if (!$result){
  120. foreach ($zones as $zl){
  121. $result = $this->matchingMin($zl,$item["数量"]);
  122. if ($result)break;
  123. }
  124. }
  125. }
  126. if ($result){
  127. try{
  128. $sql = "UPDATE DOC_ORDER_DETAILS SET LOTNUM = ?,PICKZONE = ?,KITREFERENCENO = ?,D_EDI_09 = ?,D_EDI_10 = ? WHERE ORDERNO = ? AND ORDERLINENO = ?";
  129. DB::connection("oracle")->update(DB::raw($sql),[$result->lotnum,$result->pickzone,'0','0','0',$detail->orderno,$detail->orderlineno]);
  130. LogService::log(__METHOD__,"SUCCESS-指定效期分配修改库位",json_encode($detail)." | ".json_encode($result));
  131. $order = app("OrderService")->first(["code"=>$item["订单编号"]]);
  132. if (!$order){
  133. $errors[] = "“{$item['订单编号']}”已成功修改FLUX库位但在本地未找到订单";
  134. continue;
  135. }
  136. $barcode = app("CommodityBarcodeService")->first(["code"=>$item["商品条码"]]);
  137. if (!$barcode){
  138. $errors[] = "“{$item['订单编号']}”已成功修改FLUX库位但在本地未找到条码";
  139. continue;
  140. }
  141. $model = app("OrderCommodityAssignService")->create([
  142. "order_id" => $order->id,
  143. "commodity_id" => $barcode->commodity_id,
  144. "amount" => $item["数量"],
  145. "produced_at" => $item["生产日期"],
  146. "valid_at" => $item["失效日期"],
  147. "batch_number" => $result->lotnum,
  148. "location" => $result->locationid,
  149. "region" => $result->pickzone,
  150. "user_id" => Auth::id(),
  151. ]);
  152. LogService::log(__METHOD__,"SUCCESS-生成配置记录",json_encode($model));
  153. $ids[] = $model->id;
  154. }catch (\Exception $e){
  155. LogService::log(__METHOD__,"ERROR-指定效期分配修改库位",json_encode($detail)." | ".json_encode($result));
  156. }
  157. }else $errors[] = "“{$item['订单编号']}”未找到可分配库位";
  158. }
  159. $models = [];
  160. if ($ids){
  161. $assigns = app("OrderCommodityAssignService")->get(["id"=>$ids]);
  162. foreach ($assigns as $assign){
  163. $models[] = [
  164. "orderNumber" => $assign->order ? $assign->order->code : '',
  165. "barcode" => $assign->commodity ? $assign->commodity->barcode : '',
  166. "amount" => $assign->amount,
  167. "producedAt" => $assign->produced_at,
  168. "validAt" => $assign->valid_at,
  169. "batchNumber" => $assign->batch_number,
  170. "location" => $assign->location,
  171. "region" => $assign->region,
  172. "createdAt" => $assign->created_at,
  173. "userName" => $assign->user ? $assign->user->name : 'system',
  174. ];
  175. }
  176. }
  177. Cache::put("commodityAssign",["success"=>true,"data"=>$models,"errors"=>array_unique($errors)]);
  178. }
  179. private function matchingMax($lots, $amount)
  180. {
  181. if (!$lots) return null;
  182. $max = null;
  183. $map = [];
  184. foreach ($lots as $i => $l){
  185. $qty = (int)$l->qty;
  186. $map[$qty] = $i;
  187. if (($qty >= $amount && $qty<=$max) || $max===null)$max = $qty;
  188. }
  189. if ($max !== null && $max>=$amount)return $lots[$map[$max]];
  190. return null;
  191. }
  192. private function matchingMin($lots, $amount)
  193. {
  194. if (!$lots) return null;
  195. $min = null;
  196. $map = [];
  197. foreach ($lots as $i => $l){
  198. $qty = (int)$l->qty;
  199. $map[$qty] = $i;
  200. if (($qty < $amount && $qty>=$min) || $min===null)$min = $qty;
  201. }
  202. if ($min !== null)return $lots[$map[$min]];
  203. return null;
  204. }
  205. }