ImportReclamationsService.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. <?php
  2. namespace App\Services;
  3. use App\Helpers\DateHelper;
  4. use App\Models\Import;
  5. use App\Models\Order;
  6. use App\Models\Product;
  7. use App\Models\ProductSKU;
  8. use App\Models\Reclamation;
  9. use App\Models\ReclamationType;
  10. use App\Models\Setting;
  11. use Illuminate\Support\Str;
  12. class ImportReclamationsService extends ImportBaseService
  13. {
  14. const HEADERS = [
  15. 'Округ' => 'districts.name',
  16. 'Район' => 'areas.name',
  17. 'Адрес' => 'orders.object_address',
  18. 'Артикул' => 'products.article',
  19. 'Тип' => 'products.nomenclature_number',
  20. 'RFID' => 'products_sku.rfid',
  21. 'Гарантии' => 'reclamations.guarantee',
  22. 'Что сделано' => 'reclamations.whats_done',
  23. 'Дата создания' => 'reclamations.create_date',
  24. 'Дата начала работ' => 'reclamations.start_work_date',
  25. 'Дата завершения работ' => 'reclamations.finish_date',
  26. 'Год поставки МАФ' => 'orders.year',
  27. 'Причина' => 'reclamations.reason',
  28. 'Статус' => 'reclamation_statuses.name',
  29. 'Комментарий' => 'reclamations.comment',
  30. ];
  31. public function __construct(Import $import)
  32. {
  33. parent::__construct($import);
  34. $this->headers = self::HEADERS;
  35. }
  36. public function handle(): bool
  37. {
  38. if(!$this->prepare()) {
  39. return false;
  40. }
  41. $strNumber = 0;
  42. $result = [
  43. 'reclamationsCreated' => 0,
  44. 'mafAttached' => 0,
  45. ];
  46. $defaultMafOrderUserId = Setting::getInt(
  47. Setting::KEY_DEFAULT_MAF_ORDER_USER_ID,
  48. (int) config('app.default_maf_order_user_id')
  49. );
  50. $dkrReclamationTypeId = ReclamationType::idForCode(ReclamationType::CODE_DKR);
  51. $errors = [
  52. 'district_not_found' => [],
  53. 'area_not_found' => [],
  54. 'status_not_found' => [],
  55. 'order_not_found' => [],
  56. 'product_not_found' => [],
  57. 'sku_not_found' => [],
  58. 'exceptions' => [],
  59. ];
  60. foreach ($this->rowIterator as $row) {
  61. $r = $this->rowToArray($row);
  62. $strNumber++;
  63. if(1 === $strNumber) {
  64. echo $this->import->log('Skip headers Row: ' . $strNumber);
  65. continue;
  66. }
  67. try {
  68. $logMessage = "Row $strNumber: " . $r['orders.object_address'] . ". ";
  69. $year = (int)$r['orders.year'];
  70. // округ
  71. // if (!($districtId = $this->findId('districts.shortname', $r['districts.name'] ?? ''))) {
  72. // $errors['district_not_found'][] = $strNumber;
  73. // continue;
  74. // }
  75. // район
  76. // if (!($areaId = $this->findId('areas.name', $r['areas.name']))) {
  77. // $errors['area_not_found'][] = $strNumber;
  78. // continue;
  79. // }
  80. // manager
  81. $userId = $defaultMafOrderUserId;
  82. // status
  83. if (!($statusId = $this->findId('reclamation_statuses.name', $r['reclamation_statuses.name']))) {
  84. $errors['status_not_found'][] = $strNumber;
  85. continue;
  86. }
  87. // order
  88. // $order = Order::query()
  89. // ->withoutGlobalScope(\App\Models\Scopes\YearScope::class)
  90. // ->where('year', $year)
  91. // ->where('object_address', $r['orders.object_address'])
  92. // ->first();
  93. // if (!$order) {
  94. // echo $this->import->log('Order NOT FOUND: ' . $r['orders.object_address'], 'WARNING');
  95. // $errors['order_not_found'][] = $strNumber;
  96. // continue;
  97. // } else {
  98. // $logMessage .= 'Found order: ' . $order->object_address . ". ";
  99. // }
  100. // product
  101. // $product = Product::query()
  102. // ->withoutGlobalScope(\App\Models\Scopes\YearScope::class)
  103. // ->where('year', $year)
  104. // ->where('nomenclature_number', $r['products.nomenclature_number'])
  105. // ->first();
  106. // if (!$product) {
  107. // echo $this->import->log('Product not found: ' . $r['products.nomenclature_number'], 'WARNING');
  108. // $errors['product_not_found'][] = $strNumber;
  109. // continue;
  110. // }
  111. $rfid = Str::replace(' ', '', $r['products_sku.rfid']);
  112. // check maf with this nomenclature number in order
  113. $productSKU = ProductSKU::query()
  114. ->withoutGlobalScope(\App\Models\Scopes\YearScope::class)
  115. // ->where('year', $year)
  116. // ->where('product_id', $product->id)
  117. // ->where('order_id', $order->id)
  118. ->where('rfid', $rfid)
  119. ->first();
  120. if (!$productSKU) {
  121. echo $this->import->log('SKU not found: ' . $r['products.nomenclature_number'] . '(RFID: ' . $r['products_sku.rfid'] . ')', 'WARNING');
  122. $errors['sku_not_found'][] = $strNumber;
  123. continue;
  124. }
  125. $order = Order::query()->withoutGlobalScope(\App\Models\Scopes\YearScope::class)->where('id', $productSKU->order_id)->first();
  126. $createDate = ($r['reclamations.create_date']) ? DateHelper::excelDateToISODate($r['reclamations.create_date']) : null;
  127. $finishDate = ($r['reclamations.finish_date']) ? DateHelper::excelDateToISODate($r['reclamations.finish_date']) : null;
  128. $startWorkDate = ($r['reclamations.start_work_date']) ? DateHelper::excelDateToISODate($r['reclamations.start_work_date']) : null;
  129. // reclamation
  130. $reclamation = Reclamation::query()
  131. ->where('order_id', $order->id)
  132. ->where('status_id', $statusId)
  133. ->where('create_date', $createDate)
  134. ->where('finish_date', $finishDate)
  135. ->where('start_work_date', $startWorkDate)
  136. ->where('reason', $r['reclamations.reason'])
  137. ->where('whats_done', $r['reclamations.whats_done'])
  138. ->where('guarantee', $r['reclamations.guarantee'])
  139. ->first();
  140. if (!$reclamation) {
  141. $reclamation = Reclamation::query()
  142. ->create([
  143. 'order_id' => $order->id,
  144. 'reclamation_type_id' => $dkrReclamationTypeId,
  145. 'user_id' => $userId,
  146. 'status_id' => $statusId,
  147. 'create_date' => $createDate,
  148. 'finish_date' => $finishDate,
  149. 'reason' => $r['reclamations.reason'],
  150. 'guarantee' => $r['reclamations.guarantee'],
  151. 'whats_done' => $r['reclamations.whats_done'],
  152. 'start_work_date' => $startWorkDate,
  153. 'comment' => $r['reclamations.comment'],
  154. ]);
  155. $logMessage .= 'Reclamation created: ' . $r['orders.object_address'] . ". ";
  156. $result['reclamationsCreated']++;
  157. } else {
  158. $logMessage .= 'Reclamation found: ' . $r['orders.object_address']. ". ";
  159. }
  160. if (!$reclamation->skus->contains($productSKU)) {
  161. $reclamation->skus()->syncWithoutDetaching($productSKU->id);
  162. $logMessage .= 'Attached MAF to reclamation, maf_id: ' . $productSKU->id . ". ";
  163. $result['mafAttached']++;
  164. } else {
  165. $logMessage .= 'MAF already attached!';
  166. }
  167. echo $this->import->log($logMessage);
  168. } catch(\Exception $e) {
  169. echo $this->import->log($e->getMessage(), 'WARNING');
  170. $errors['exceptions'][] = $strNumber;
  171. }
  172. }
  173. echo $this->import->log(print_r($result, true));
  174. // Резюме по ошибкам
  175. $totalErrors = array_sum(array_map('count', $errors));
  176. if ($totalErrors > 0) {
  177. echo $this->import->log('--- РЕЗЮМЕ ПО ОШИБКАМ ---');
  178. if (count($errors['district_not_found']) > 0) {
  179. $rows = implode(', ', $errors['district_not_found']);
  180. echo $this->import->log("Округ не найден: " . count($errors['district_not_found']) . " ({$rows})", 'WARNING');
  181. }
  182. if (count($errors['area_not_found']) > 0) {
  183. $rows = implode(', ', $errors['area_not_found']);
  184. echo $this->import->log("Район не найден: " . count($errors['area_not_found']) . " ({$rows})", 'WARNING');
  185. }
  186. if (count($errors['status_not_found']) > 0) {
  187. $rows = implode(', ', $errors['status_not_found']);
  188. echo $this->import->log("Статус не найден: " . count($errors['status_not_found']) . " ({$rows})", 'WARNING');
  189. }
  190. if (count($errors['order_not_found']) > 0) {
  191. $rows = implode(', ', $errors['order_not_found']);
  192. echo $this->import->log("Заказ не найден: " . count($errors['order_not_found']) . " ({$rows})", 'WARNING');
  193. }
  194. if (count($errors['product_not_found']) > 0) {
  195. $rows = implode(', ', $errors['product_not_found']);
  196. echo $this->import->log("Товар не найден: " . count($errors['product_not_found']) . " ({$rows})", 'WARNING');
  197. }
  198. if (count($errors['sku_not_found']) > 0) {
  199. $rows = implode(', ', $errors['sku_not_found']);
  200. echo $this->import->log("МАФ (SKU) не найден: " . count($errors['sku_not_found']) . " ({$rows})", 'WARNING');
  201. }
  202. if (count($errors['exceptions']) > 0) {
  203. $rows = implode(', ', $errors['exceptions']);
  204. echo $this->import->log("Исключения: " . count($errors['exceptions']) . " ({$rows})", 'WARNING');
  205. }
  206. echo $this->import->log("Всего ошибок: {$totalErrors}", 'WARNING');
  207. } else {
  208. echo $this->import->log('Импорт завершён без ошибок');
  209. }
  210. $this->import->status = 'DONE';
  211. $this->import->save();
  212. return true;
  213. }
  214. }