From 90e6c80a61c4317672dba3e677d765941903f6cf Mon Sep 17 00:00:00 2001 From: Mark Gregory Date: Tue, 22 Sep 2026 13:03:06 +0100 Subject: [PATCH] M3 Integration fixes pass 20 --- .../M3/Http/Controllers/API/M3Controller.php | 637 ++++-------- .../M3/Http/Controllers/API/TransferAPI.php | 979 ++++++------------ 2 files changed, 520 insertions(+), 1096 deletions(-) mode change 100755 => 100644 Modules/M3/Http/Controllers/API/M3Controller.php diff --git a/Modules/M3/Http/Controllers/API/M3Controller.php b/Modules/M3/Http/Controllers/API/M3Controller.php old mode 100755 new mode 100644 index 54720910..7027795e --- a/Modules/M3/Http/Controllers/API/M3Controller.php +++ b/Modules/M3/Http/Controllers/API/M3Controller.php @@ -13,53 +13,220 @@ use Str; class M3Controller extends Controller { private const FIELD_PREFIX = 'Field: '; - private const M3_LIST_SUFFIX = ' M3-Lis-JSN'; - // Split Data and Write to ICM666M2 public function insertToICM666M2($dataSplit, $commentData) { - - $commentDataSS = explode("\n", $dataSplit); - $aXLINENO = 1; - foreach ($commentDataSS as $substring) { - // Process each substring - $fullData = $commentData; - $fullData['AXCOMMENT'] = $substring; - $fullData['AXLINENO'] = $aXLINENO; - DB::connection(config('m3.connection', 'pgsql'))->table('icm666m2')->insert($fullData); - - $aXLINENO++; - - // AXCO ICM666M2 CHARACTER 3 - // AXWHS ICM666M2 CHARACTER 3 - // AXPLANT ICM666M2 CHARACTER 3 - // AXDOCUMENT ICM666M2 CHARACTER 15 - // AXCOMMENT ICM666M2 CHARACTER 60 - // AXLINENO DECIMAL(3,0) + $line = 1; + foreach (explode("\n", $dataSplit) as $substring) { + $data = $commentData; + $data['AXCOMMENT'] = $substring; + $data['AXLINENO'] = $line++; + DB::connection(config('m3.connection', 'pgsql'))->table('icm666m2')->insert($data); } } - public function index() - { - dd('Index'); - } - - public function create() - { - // This API controller does not expose a create form. - } + public function index() { dd('Index'); } + public function create() {} public function store(Request $request) + { + $this->configureTimeouts(); + $user = m3User() !== '' ? Str::upper(m3User()) : 'WEBUSER'; + $json = $request->json()->all(); + $context = $this->rootContext($json, $user); + + try { + $response = $json === [] ? $this->emptyPayloadResponse($context) : $this->processPayload($json, $context); + } catch (\Throwable $throwable) { + $response = $this->exceptionResponse($context, $json, $throwable); + } + + return $response; + } + + private function configureTimeouts(): void { ini_set('max_execution_time', Config::get('arrays.PHPTimeOut')); ini_set('max_input_time', Config::get('arrays.PHPTimeOut')); ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut')); + } - $rEQKPKUS = m3User() !== '' ? Str::upper(m3User()) : 'WEBUSER'; - $sHSOURCE = 'M3ReceiverAPI'; + private function rootContext(array $json, string $user): array + { + $carrier = $json['CarrierCode'] ?? ''; + if (($carrier === '' || $carrier === null) && ($json['Warehouse'] ?? '') === '111' && ($json['Company'] ?? '') === '410' && ($json['Plant'] ?? '') === '410') { + $carrier = 'BWAY'; + } + return [ + 'user' => $user, 'source' => 'M3ReceiverAPI', 'company' => $json['Company'] ?? '', 'plant' => $json['Plant'] ?? '', + 'warehouse' => $json['Warehouse'] ?? '', 'order' => $json['OrderNumber'] ?? '', 'picker' => $json['PickerNumber'] ?? '', + 'prom_date' => $json['PromDate'] ?? '', 'route' => $json['RouteCode'] ?? '', 'category' => $json['OrderCategory'] ?? '', + 'release' => $json['ReleaseNumber'] ?? '', 'shipment' => $json['ShipmentNumber'] ?? '', 'currency' => $json['Currency'] ?? '', + 'carrier' => $carrier, 'po' => $json['ShipmentPONumber'] ?? '', 'terms' => $json['ShipTerms'] ?? '', + 'order_class' => $json['OrderClass'] ?? '', 'gs1' => $json['GS1-128Label'] ?? '0', 'exchange' => $json['CurrencyExchangeRate'] ?? '', + 'macpkr' => ($json['PickerNumber'] ?? '') !== '' ? $json['PickerNumber'] : '000000', + ]; + } - $iCM666MFields = [ + private function processPayload(array $json, array $context) + { + $recipient = $this->recipient($json['Recipient'] ?? []); + $this->storeComments($json['Comments'] ?? [], $context); + $validation = $this->storeProducts($json['Contents']['Commodities'] ?? [], $context, $recipient, $json); + if ($validation !== null) { + return $validation; + } + $this->callUpdateProgram($context, $json); + $this->log($context, json_encode($json), '', 'M3-Lis-in'); + return response()->json(['code' => '200', 'status' => 'success', 'message' => 'File Received, DB Updated']); + } + + private function recipient(array $recipient): array + { + return [ + 'CompanyName' => $recipient['CompanyName'] ?? '', 'Address1' => $recipient['Address1'] ?? '', 'Address2' => $recipient['Address2'] ?? '', + 'Address3' => $recipient['Address3'] ?? '', 'Address4' => $recipient['Address4'] ?? '', 'City' => $recipient['City'] ?? '', + 'State' => $recipient['State'] ?? '', 'PostalCode' => $recipient['PostalCode'] ?? '', 'Country' => $recipient['Country'] ?? '', + 'CountryName' => $recipient['CountryName'] ?? '', 'BillToId' => $recipient['BillToId'] ?? '', 'ShipToId' => $recipient['ShipToId'] ?? '', + 'PersonName' => $recipient['PersonName'] ?? '', 'AccountNo' => $recipient['AccountNo'] ?? '', 'Email' => $recipient['Email'] ?? '', + ]; + } + + private function storeComments(array $comments, array $c): void + { + foreach ($comments as $document => $comment) { + $document = Helper::sanityzeString($document); + if (! in_array($document, ['Picker', 'Packer', 'Carrier', 'Other'], true)) { + continue; + } + $text = Helper::sanityzeString($comment ?? 'null'); + if ($text === 'null') { + continue; + } + $this->insertToICM666M2($text, [ + 'AXCO' => $c['company'], 'AXPLANT' => $c['plant'], 'AXWHS' => $c['warehouse'], 'AXDELNO' => $c['picker'], + 'AXONO' => $c['order'], 'AXRLNO' => $c['release'], 'AXSHNO' => $c['shipment'], 'AXDOCUMENT' => $document, + ]); + } + } + + private function storeProducts(array $products, array $c, array $recipient, array $json) + { + foreach ($products as $product) { + $values = $this->productValues($product, $c, $recipient, $json); + [$insert, $messages] = $this->validatedInsert($values); + if ($messages !== []) { + $this->log($c, json_encode($messages) . self::M3_LIST_SUFFIX . json_encode($json), 'X', 'M3-Lis-spl'); + return response()->json($messages); + } + $this->enrichProduct($insert, $c, (string) ($product['PartNumber'] ?? '')); + DB::connection(config('m3.connection', 'pgsql'))->table('icm666m')->insert($insert); + } + return null; + } + + private function productValues(array $p, array $c, array $r, array $json): array + { + return array_merge($r, [ + 'Company' => $c['company'], 'Warehouse' => $c['warehouse'], 'Plant' => $c['plant'], 'PickerNumber' => $c['picker'], + 'OrderNumber' => $c['order'], 'ReleaseNumber' => $c['release'], 'ShipmentNumber' => $c['shipment'], + 'OrderLine' => $p['OrderLine'] ?? '', 'PartNumber' => $p['PartNumber'] ?? '', + 'Description' => isset($p['Description']) ? Str::limit($p['Description'], 25, '') : '', 'Quantity' => $p['Quantity'] ?? '', + 'BaseUnitPrice' => $p['BaseUnitPrice'] ?? '', 'Currency' => $c['currency'], 'Zone' => $p['Zone'] ?? '', 'PromDate' => $c['prom_date'], + 'RouteCode' => $c['route'], 'PartWeight' => $p['PartWeight'] ?? '', 'SellUOM' => $p['SellUOM'] ?? '', 'PartConv' => $p['PartConv'] ?? '', + 'CarrierCode' => $c['carrier'], 'ShipVia' => $json['ShipVia'] ?? '', 'PrimaryLocation' => $p['PrimaryLocation'] ?? '', + 'Allocation' => $p['Allocation'] ?? '', 'AllocatedTo' => $p['AllocatedTo'] ?? '', 'LocationSeq' => $p['LocationSeq'] ?? '', + 'UOM' => $p['UOM'] ?? '', 'HazMat' => $p['HazMat'] ?? '', 'PartUPC' => $p['PartUPC'] ?? '', 'PartEAN' => $p['PartEAN'] ?? '', + 'LotFlag' => $p['LotFlag'] ?? '', 'ManOrd' => $p['ManOrd'] ?? '', 'LotNumber' => $p['LotNumber'] ?? '', 'ProductArea' => $p['ProductArea'] ?? '', + 'FreightClass' => $p['FreightClass'] ?? '', 'ShipmentPONumber' => $c['po'], 'ShipmentPOLine' => $p['ShipmentPOLine'] ?? '', + 'ShipTerms' => $c['terms'], 'OrderClass' => $c['order_class'], 'LocationType' => $p['LocationType'] ?? '', 'PallSize' => $p['PallSize'] ?? '', + 'MasterCarton' => $p['MasterCarton'] ?? '', 'MasterQty' => $p['MasterQty'] ?? '', 'InnerQty' => $p['InnerQty'] ?? '', + 'PalletQty' => $p['PalletQty'] ?? '', 'CartonQty' => $p['CartonQty'] ?? '', 'OrderCategory' => $c['category'], + 'A1DATEADD' => date('Ymd'), 'A1TIMEADD' => date('His'), 'KitPartNumber' => $p['KitPartNumber'] ?? '', + 'OrderLineSuffix' => $p['OrderLineSuffix'] ?? '', 'CustomerPartNumber' => isset($p['CustomerPartNumber']) ? substr($p['CustomerPartNumber'], 0, 20) : '', + 'GS1Label' => $c['gs1'], 'CurrencyExchangeRate' => $c['exchange'], + ]); + } + + private function validatedInsert(array $values): array + { + $insert = []; $messages = []; + foreach ($this->fieldDefinitions() as $key => $definition) { + $value = Helper::sanityzeString($values[$key] ?? ''); + $test = Helper::checkLength($value, $definition[1], $definition[2]); + $this->appendValidationMessages($messages, $key, $definition[2], $test); + if ($value !== '') { + $insert[$definition[0]] = $value; + } + } + return [$insert, $messages]; + } + + private function appendValidationMessages(array &$messages, string $key, string $type, array $test): void + { + if (! ($test[413] ?? false)) $messages[] = ['code' => '413', 'status' => 'error', 'message' => self::FIELD_PREFIX . $key . ' is larger then expected']; + if (! ($test[411] ?? false)) $messages[] = ['code' => '411', 'status' => 'error', 'message' => self::FIELD_PREFIX . $key . ' is empty']; + if (! ($test[417] ?? false)) $messages[] = ['code' => '417', 'status' => 'error', 'message' => self::FIELD_PREFIX . $key . 'type is different then Expected type: ' . $type]; + } + + private function enrichProduct(array &$insert, array $c, string $part): void + { + $row = DB::connection(config('m3.connection', 'pgsql'))->table('icm709m')->select() + ->where('AT9CO', $c['company'])->where('AT9PLT', $c['plant'])->where('AT9WHS', $c['warehouse'])->where('AT9PART', $part)->first(); + $insert['A1USRN01'] = $row->AT9QTY ?? 0; + $insert['A1MATWRN'] = $row->AT9WRN ?? ''; + } + + private function callUpdateProgram(array $c, array $json): void + { + if ($c['warehouse'] === '' || $c['picker'] === '' || $c['company'] === '') return; + $error = ''; + try { + $conn = app(PostgresProgramBridge::class); + $conn->setOptions(['persistent' => false, 'stateless' => true, 'debug' => true, 'debugLogFile' => env('TOOLKIT_DEBUG_LOG')]); + $params = [$conn->addParameterChar('in', 3, 'Company', '', $c['company']), $conn->addParameterChar('in', 3, 'Warehouse', '', $c['warehouse'])]; + $params[] = $conn->addParameterChar('in', 11, 'PickerNumber', '', ltrim(strval($c['picker']), '0')); + if (! $conn->pgmCall('ICM700CSBM', env('OBJLIB'), $params, [], [])) $error = 'Error calling program. Code: ' . $conn->getErrorCode() . ' - Msg: ' . $conn->getErrorMsg(); + } catch (\Throwable $e) { + $error = $this->programConnectionError($e); + } + if ($error !== '') $this->log($c, $error . self::M3_LIST_SUFFIX . json_encode($json), 'X', 'M3-Lis-spl'); + } + + private function programConnectionError(\Throwable $e): string + { + return match ((int) $e->getCode()) { + 8001 => 'Could not connect due to wrong user or password.', + 42705 => 'Database not found. Try WRKRDBDIRE to check.', + default => 'Could not connect. Error: ' . $e->getCode() . ' ' . $e->getMessage(), + }; + } + + private function emptyPayloadResponse(array $c) + { + $data = 'No Json File Found...'; + Helper::logToICM699M(['SHMACPKR' => $c['macpkr'], 'SHDT' => date('Y-m-d'), 'SHTIME' => date('H:i:s'), 'SHERROR' => 'Z', 'SHINTBOX' => '', + 'SHTYPE' => 'M3-Lis-in', 'SHDATA' => $data, 'SHUSER' => $c['user'], 'SHSOURCE' => $c['source'], 'SHCO' => $c['company'], 'SHWHS' => $c['warehouse'], + 'SHACKNOTE' => 'Sentinel automatically closed the error related to this empty data set sent by M3']); + return response()->json(['code' => '415', 'status' => 'error', 'message' => 'No Json File Found']); + } + + private function exceptionResponse(array $c, array $json, \Throwable $th) + { + $this->log($c, 'General Catchable Error - ' . substr((string) $th, 0, 300) . self::M3_LIST_SUFFIX . json_encode($json), 'X', 'M3-Lis-in'); + return response()->json(['code' => '405', 'status' => 'error', 'message' => 'An Error Occured...']); + } + + private function log(array $c, string $message, string $error, string $type): void + { + Helper::logToICM699M(['SHMACPKR' => $c['macpkr'], 'SHDT' => date('Y-m-d'), 'SHTIME' => date('H:i:s'), 'SHERROR' => $error, 'SHINTBOX' => '', + 'SHTYPE' => $type, 'SHDATA' => $message, 'SHUSER' => $c['user'], 'SHSOURCE' => $c['source'], 'SHCO' => $c['company'], 'SHWHS' => $c['warehouse']]); + } + + private function fieldDefinitions(): array + { + return [ 'Company' => ['A1CO', 3, 'string'], 'Warehouse' => ['A1WHS', 3, 'string'], 'Plant' => ['A1PLANT', 3, 'string'], @@ -130,406 +297,10 @@ class M3Controller extends Controller 'GS1Label' => ['A1SPR1A01', 1, 'string'], 'CurrencyExchangeRate' => ['A1EXGRATE', 18, 'DEC'], - ]; + ]; } - try { - $jsonFile = count($request->json()->all()) > 0 ? $request->json()->all() : ''; - - // Root - $company = isset($jsonFile['Company']) ? $jsonFile['Company'] : ''; - $plant = isset($jsonFile['Plant']) ? $jsonFile['Plant'] : ''; - $warehouse = isset($jsonFile['Warehouse']) ? $jsonFile['Warehouse'] : ''; - $orderNumber = isset($jsonFile['OrderNumber']) ? $jsonFile['OrderNumber'] : ''; - $pickerNumber = isset($jsonFile['PickerNumber']) ? $jsonFile['PickerNumber'] : ''; - $promDate = isset($jsonFile['PromDate']) ? $jsonFile['PromDate'] : ''; - $routeCode = isset($jsonFile['RouteCode']) ? $jsonFile['RouteCode'] : ''; - $orderCategory = isset($jsonFile['OrderCategory']) ? $jsonFile['OrderCategory'] : ''; - $releaseNumber = isset($jsonFile['ReleaseNumber']) ? $jsonFile['ReleaseNumber'] : ''; - $shipmentNumber = isset($jsonFile['ShipmentNumber']) ? $jsonFile['ShipmentNumber'] : ''; - $currency = isset($jsonFile['Currency']) ? $jsonFile['Currency'] : ''; - $carrierCode = isset($jsonFile['CarrierCode']) ? $jsonFile['CarrierCode'] : ''; - $shipmentPONumber = isset($jsonFile['ShipmentPONumber']) ? $jsonFile['ShipmentPONumber'] : ''; // CustPo - $shipTerms = isset($jsonFile['ShipTerms']) ? $jsonFile['ShipTerms'] : ''; - $orderClass = isset($jsonFile['OrderClass']) ? $jsonFile['OrderClass'] : ''; - $gS1Label = isset($jsonFile['GS1-128Label']) ? $jsonFile['GS1-128Label'] : '0'; - $currencyExchangeRate = isset($jsonFile['CurrencyExchangeRate']) ? $jsonFile['CurrencyExchangeRate'] : ''; - - // Set Carrier BWAY if it's empty for Tilburg only - if (($carrierCode == '' || $carrierCode == null) && $warehouse == '111' && $company == '410' && $plant == '410') { - $carrierCode = 'BWAY'; - } - - $sHMACPKR = $pickerNumber != '' ? $pickerNumber : '000000'; - - if ($jsonFile != '') { - // Order Category - /* - 1 = Material to manufacturing order - 3 = Customer Order - 4 = Requisition Order - 5 = Distribution Order - 9 = Move order / Replenishment - */ - - // Recipient - $recipient = $jsonFile['Recipient']; - $companyName = isset($recipient['CompanyName']) ? $recipient['CompanyName'] : ''; - $address1 = isset($recipient['Address1']) ? $recipient['Address1'] : ''; - $address2 = isset($recipient['Address2']) ? $recipient['Address2'] : ''; - $city = isset($recipient['City']) ? $recipient['City'] : ''; - $state = isset($recipient['State']) ? $recipient['State'] : ''; - $postalCode = isset($recipient['PostalCode']) ? $recipient['PostalCode'] : ''; - $country = isset($recipient['Country']) ? $recipient['Country'] : ''; - $postalCode = isset($recipient['PostalCode']) ? $recipient['PostalCode'] : ''; - $billToId = isset($recipient['BillToId']) ? $recipient['BillToId'] : ''; - $shipToId = isset($recipient['ShipToId']) ? $recipient['ShipToId'] : ''; - $address3 = isset($recipient['Address3']) ? $recipient['Address3'] : ''; - $address4 = isset($recipient['Address4']) ? $recipient['Address4'] : ''; - $countryName = isset($recipient['CountryName']) ? $recipient['CountryName'] : ''; - $personName = isset($recipient['PersonName']) ? $recipient['PersonName'] : ''; - $accountNo = isset($recipient['AccountNo']) ? $recipient['AccountNo'] : ''; - $email = isset($recipient['Email']) ? $recipient['Email'] : ''; - $a1DATEADD = date('Ymd'); - $a1TIMEADD = date('His'); - - // MycarrierDetails - $shipVia = isset($jsonFile['ShipVia']) ? $jsonFile['ShipVia'] : ''; - - // Comments - $picker = $packer = $carrier = $other = ''; - $aXCO = $company; - $aXPLANT = $plant; - $aXWHS = $warehouse; - $aXDELNO = $pickerNumber; - $aXONO = $orderNumber; - $aXRLNO = $releaseNumber; - $aXSHNO = $shipmentNumber; - - $comments = isset($jsonFile['Comments']) ? $jsonFile['Comments'] : ''; - - if ($comments != '') { - foreach ($comments as $key => $comment) { - $commentData = []; - $aXDOCUMENT = Helper::sanityzeString($key); - - $commentData = ['AXCO' => $aXCO, 'AXPLANT' => $aXPLANT, 'AXWHS' => $aXWHS, 'AXDELNO' => $aXDELNO, 'AXONO' => $aXONO, - 'AXRLNO' => $aXRLNO, 'AXSHNO' => $aXSHNO, 'AXDOCUMENT' => $aXDOCUMENT]; - - switch ($aXDOCUMENT) { - case 'Picker': - $picker = isset($comment) ? Helper::sanityzeString($comment) : 'null'; - if ($picker != 'null') { - $this->insertToICM666M2($picker, $commentData); - } - break; - - case 'Packer': - $packer = isset($comment) ? Helper::sanityzeString($comment) : 'null'; - if ($packer != 'null') { - $this->insertToICM666M2($packer, $commentData); - } - break; - - case 'Carrier': - $carrier = isset($comment) ? Helper::sanityzeString($comment) : 'null'; - if ($carrier != 'null') { - $this->insertToICM666M2($carrier, $commentData); - } - break; - - case 'Other': - $other = isset($comment) ? Helper::sanityzeString($comment) : 'null'; - if ($other != 'null') { - $this->insertToICM666M2($other, $commentData); - } - break; - - default: - break; - } - } - } - - // Get Products : commodities And Write ICM666M - $products = $jsonFile['Contents']['Commodities']; - foreach ($products as $key => $product) { - $quantity = isset($product['Quantity']) ? $product['Quantity'] : ''; - $description = isset($product['Description']) ? Str::limit($product['Description'], 25, '') : ''; - $partNumber = isset($product['PartNumber']) ? $product['PartNumber'] : ''; - $orderLine = isset($product['OrderLine']) ? $product['OrderLine'] : ''; - $partWeight = isset($product['PartWeight']) ? $product['PartWeight'] : ''; - $primaryLocation = isset($product['PrimaryLocation']) ? $product['PrimaryLocation'] : ''; - $allocation = isset($product['Allocation']) ? $product['Allocation'] : ''; - $allocatedTo = isset($product['AllocatedTo']) ? $product['AllocatedTo'] : ''; - $locationSeq = isset($product['LocationSeq']) ? $product['LocationSeq'] : ''; - $zone = isset($product['Zone']) ? $product['Zone'] : ''; - $baseUnitPrice = isset($product['BaseUnitPrice']) ? $product['BaseUnitPrice'] : ''; - $sellUOM = isset($product['SellUOM']) ? $product['SellUOM'] : ''; - $partConv = isset($product['PartConv']) ? $product['PartConv'] : ''; - $uOM = isset($product['UOM']) ? $product['UOM'] : ''; - $hazMat = isset($product['HazMat']) ? $product['HazMat'] : ''; - $partUPC = isset($product['PartUPC']) ? $product['PartUPC'] : ''; - $partEAN = isset($product['PartEAN']) ? $product['PartEAN'] : ''; - $lotFlag = isset($product['LotFlag']) ? $product['LotFlag'] : ''; - $manOrd = isset($product['ManOrd']) ? $product['ManOrd'] : ''; - $lotNumber = isset($product['LotNumber']) ? $product['LotNumber'] : ''; - $productArea = isset($product['ProductArea']) ? $product['ProductArea'] : ''; - $freightClass = isset($product['FreightClass']) ? $product['FreightClass'] : ''; - $shipmentPOLine = isset($product['ShipmentPOLine']) ? $product['ShipmentPOLine'] : ''; - $locationType = isset($product['LocationType']) ? $product['LocationType'] : ''; - $pallSize = isset($product['PallSize']) ? $product['PallSize'] : ''; - $masterCarton = isset($product['MasterCarton']) ? $product['MasterCarton'] : ''; - $masterQty = isset($product['MasterQty']) ? $product['MasterQty'] : ''; - $innerQty = isset($product['InnerQty']) ? $product['InnerQty'] : ''; - $sonar_pallet_qty = isset($product['PalletQty']) ? $product['PalletQty'] : ''; - $cartonQty = isset($product['CartonQty']) ? $product['CartonQty'] : ''; - $kitPartNumber = isset($product['KitPartNumber']) ? $product['KitPartNumber'] : ''; - $orderLineSuffix = isset($product['OrderLineSuffix']) ? $product['OrderLineSuffix'] : ''; - $customerPartNumber = isset($product['CustomerPartNumber']) ? substr($product['CustomerPartNumber'], 0, 20) : ''; // Limit to 20 Chars - - // Initialise Table Fields to be filled - $insertArray = []; - $fieldValues = [ - 'Company' => $company, - 'Warehouse' => $warehouse, - 'Plant' => $plant, - 'PickerNumber' => $pickerNumber, - 'OrderNumber' => $orderNumber, - 'ReleaseNumber' => $releaseNumber, - 'ShipmentNumber' => $shipmentNumber, - 'OrderLine' => $orderLine, - 'PartNumber' => $partNumber, - 'Description' => $description, - 'Quantity' => $quantity, - 'BaseUnitPrice' => $baseUnitPrice, - 'Currency' => $currency, - 'Zone' => $zone, - 'PromDate' => $promDate, - 'RouteCode' => $routeCode, - 'BillToId' => $billToId, - 'ShipToId' => $shipToId, - 'CompanyName' => $companyName, - 'Address1' => $address1, - 'Address2' => $address2, - 'Address3' => $address3, - 'Address4' => $address4, - 'City' => $city, - 'State' => $state, - 'PostalCode' => $postalCode, - 'Country' => $country, - 'CountryName' => $countryName, - 'PartWeight' => $partWeight, - 'SellUOM' => $sellUOM, - 'PartConv' => $partConv, - 'CarrierCode' => $carrierCode, - 'ShipVia' => $shipVia, - 'PrimaryLocation' => $primaryLocation, - 'Allocation' => $allocation, - 'AllocatedTo' => $allocatedTo, - 'LocationSeq' => $locationSeq, - 'UOM' => $uOM, - 'HazMat' => $hazMat, - 'PartUPC' => $partUPC, - 'PartEAN' => $partEAN, - 'LotFlag' => $lotFlag, - 'ManOrd' => $manOrd, - 'LotNumber' => $lotNumber, - 'ProductArea' => $productArea, - 'FreightClass' => $freightClass, - 'ShipmentPONumber' => $shipmentPONumber, - 'ShipmentPOLine' => $shipmentPOLine, - 'ShipTerms' => $shipTerms, - 'OrderClass' => $orderClass, - 'LocationType' => $locationType, - 'PallSize' => $pallSize, - 'MasterCarton' => $masterCarton, - 'MasterQty' => $masterQty, - 'InnerQty' => $innerQty, - 'PalletQty' => $sonar_pallet_qty, - 'CartonQty' => $cartonQty, - 'PersonName' => $personName, - 'AccountNo' => $accountNo, - 'Email' => $email, - 'OrderCategory' => $orderCategory, - 'A1DATEADD' => $a1DATEADD, - 'A1TIMEADD' => $a1TIMEADD, - 'KitPartNumber' => $kitPartNumber, - 'OrderLineSuffix' => $orderLineSuffix, - 'CustomerPartNumber' => $customerPartNumber, - 'GS1Label' => $gS1Label, - 'CurrencyExchangeRate' => $currencyExchangeRate, - ]; - - // Check JSON fields if empty or > DB Fields - foreach ($iCM666MFields as $key => $value) { - // Sanitize String - $fieldValue = Helper::sanityzeString($fieldValues[$key] ?? ''); - // Check Var Types & Length - $lengthTest = Helper::checkLength($fieldValue, $value[1], $value[2]); - - if (! $lengthTest[413] || ! $lengthTest[411] || ! $lengthTest[417]) { - if (! $lengthTest[413]) { - $message[] = ['code' => '413', 'status' => 'error', 'message' => self::FIELD_PREFIX . $key . ' is larger then expected']; - } - if (! $lengthTest[411]) { - $message[] = ['code' => '411', 'status' => 'error', 'message' => self::FIELD_PREFIX . $key . ' is empty']; - } - if (! $lengthTest[417]) { - $message[] = ['code' => '417', 'status' => 'error', 'message' => self::FIELD_PREFIX . $key . 'type is different then Expected type: ' . $value[2]]; - } - - // Write to Logs Out : Error & JSON - $data = ['SHMACPKR' => $sHMACPKR, 'SHDT' => date('Y-m-d'), 'SHTIME' => date('H:i:s'), 'SHERROR' => 'X', 'SHINTBOX' => '', 'SHTYPE' => 'M3-Lis-spl', - 'SHDATA' => json_encode($message) . self::M3_LIST_SUFFIX . json_encode($jsonFile), 'SHUSER' => $rEQKPKUS, 'SHSOURCE' => $sHSOURCE, 'SHCO' => $company, 'SHWHS' => $warehouse]; - Helper::logToICM699M($data); - - return response()->json($message); - } elseif ($fieldValue != '') { - $insertArray[$value[0]] = $fieldValue; - } - } - - // Check ICM709M - $iCM709MSEL = DB::connection(config('m3.connection', 'pgsql'))->table('icm709m') - ->select() - ->where('AT9CO', $aXCO) - ->where('AT9PLT', $aXPLANT) - ->where('AT9WHS', $aXWHS) - ->where('AT9PART', $partNumber) - ->first(); - $palletQty = isset($iCM709MSEL->AT9QTY) ? $iCM709MSEL->AT9QTY : 0; - // dd($palletQty); - // Get Pallet Qty - $insertArray['A1USRN01'] = $palletQty; - - // Hazard Material - $hazMat = isset($iCM709MSEL->AT9WRN) ? $iCM709MSEL->AT9WRN : ''; - $insertArray['A1MATWRN'] = $hazMat; - - // } - - // SQL Insert to ICM666M - DB::connection(config('m3.connection', 'pgsql'))->table('icm666m')->insert($insertArray); - } - - // Call PGM ICM700CSBM - if ($warehouse != '' && $pickerNumber != '' && $company != '') { - $pGMERRORS = ''; - - // connect to toolkit using DB2 credentials (can also leave blank for default authority) - try { - $conn = app(PostgresProgramBridge::class); - } catch (\Throwable $e) { - // Determine reason for failure. - // Probably database authentication error or invalid or unreachable database. - $code = $e->getCode(); - $msg = $e->getMessage(); - - switch ($code) { - case 8001: - // "Authorization failure on distributed database connection attempt" - // Usually means a wrong DB2 user or password - $pGMERRORS = 'Could not connect due to wrong user or password.'; - break; - case 42705: - $pGMERRORS = 'Database not found. Try WRKRDBDIRE to check.'; - break; - default: - $pGMERRORS = 'Could not connect. Error: ' . $code . ' ' . $msg; - break; - } - } - $conn->setOptions(['persistent' => false, 'stateless' => true, 'debug' => true, 'debugLogFile' => env('TOOLKIT_DEBUG_LOG')]); - - // Add LIB - // $result = $conn->clCommand('ADDLIBLE LIB(MPDAT10)'); - - // define several input/output params - $params = []; - - // AddParameterChar($io, $size, $comment, $varName, $value, $varying, $dimension) - // Add Warehouse Param - $params[] = $conn->addParameterChar('in', 3, 'Company', '', $company); - - $params[] = $conn->addParameterChar('in', 3, 'Warehouse', '', $warehouse); - - // AddParameterPackDec($io, $length, $scale, $comment, $varName, $value,$dimension) - // Add Delivery Note Param - $pickerNumberNoZero = ltrim(strval($pickerNumber), '0'); - $params[] = $conn->addParameterChar('in', 11, 'PickerNumber', '', $pickerNumberNoZero); - - // Start Time Tracking - - // ICM700C EWOBJTST ICM700C ICM700CSBM - $result = $conn->pgmCall('ICM700CSBM', env('OBJLIB'), $params, [], []); - - if (! $result) { - $pGMERRORS = 'Error calling program. Code: ' . $conn->getErrorCode() . ' - Msg: ' . $conn->getErrorMsg(); - } - - if ($pGMERRORS != '') { - // Write to Logs Out : Error & JSON - $data = ['SHMACPKR' => $sHMACPKR, 'SHDT' => date('Y-m-d'), 'SHTIME' => date('H:i:s'), 'SHERROR' => 'X', 'SHINTBOX' => '', 'SHTYPE' => 'M3-Lis-spl', - 'SHDATA' => $pGMERRORS . self::M3_LIST_SUFFIX . json_encode($jsonFile), 'SHUSER' => $rEQKPKUS, 'SHSOURCE' => $sHSOURCE, 'SHCO' => $company, 'SHWHS' => $warehouse]; - Helper::logToICM699M($data); - } - } - - // Write to Logs Out : Success - $data = ['SHMACPKR' => $sHMACPKR, 'SHDT' => date('Y-m-d'), 'SHTIME' => date('H:i:s'), 'SHERROR' => '', 'SHINTBOX' => '', 'SHTYPE' => 'M3-Lis-in', - 'SHDATA' => json_encode($jsonFile), 'SHUSER' => $rEQKPKUS, 'SHSOURCE' => $sHSOURCE, 'SHCO' => $company, 'SHWHS' => $warehouse]; - Helper::logToICM699M($data); - - return response()->json([ - 'code' => '200', - 'status' => 'success', - 'message' => 'File Received, DB Updated', - ]); - } else { - // Write to Logs Out : Error & JSON - $sHACKNOTE = 'Sentinel automatically closed the error related to this empty data set sent by M3'; - - $data = ['SHMACPKR' => $sHMACPKR, 'SHDT' => date('Y-m-d'), 'SHTIME' => date('H:i:s'), 'SHERROR' => 'Z', 'SHINTBOX' => '', 'SHTYPE' => 'M3-Lis-in', - 'SHDATA' => 'No Json File Found...', 'SHUSER' => $rEQKPKUS, 'SHSOURCE' => $sHSOURCE, 'SHCO' => $company, 'SHWHS' => $warehouse, 'SHACKNOTE' => $sHACKNOTE]; - Helper::logToICM699M($data); - - return response()->json([ - 'code' => '415', - 'status' => 'error', - 'message' => 'No Json File Found', - ]); - } - } catch (\Throwable $th) { - // Write to Logs Out : Error & JSON - $data = ['SHMACPKR' => $sHMACPKR, 'SHDT' => date('Y-m-d'), 'SHTIME' => date('H:i:s'), 'SHERROR' => 'X', 'SHINTBOX' => '', 'SHTYPE' => 'M3-Lis-in', - 'SHDATA' => 'General Catchable Error - ' . substr($th, 0, 300) . self::M3_LIST_SUFFIX . json_encode($jsonFile), 'SHUSER' => $rEQKPKUS, 'SHSOURCE' => $sHSOURCE, 'SHCO' => $company, 'SHWHS' => $warehouse]; - Helper::logToICM699M($data); - - return response()->json([ - 'code' => '405', - 'status' => 'error', - 'message' => 'An Error Occured...', - ]); - } - } - - public function show($id) - { - // This resource endpoint is intentionally unsupported. - } - - public function edit($id) - { - // This resource endpoint is intentionally unsupported. - } - - public function update(Request $request, $id) - { - // This resource endpoint is intentionally unsupported. - } - - public function destroy($id) - { - // This resource endpoint is intentionally unsupported. - } + public function show($id) {} + public function edit($id) {} + public function update(Request $request, $id) {} + public function destroy($id) {} } diff --git a/Modules/M3/Http/Controllers/API/TransferAPI.php b/Modules/M3/Http/Controllers/API/TransferAPI.php index 78d16ee6..7c69825b 100755 --- a/Modules/M3/Http/Controllers/API/TransferAPI.php +++ b/Modules/M3/Http/Controllers/API/TransferAPI.php @@ -7,7 +7,6 @@ use DateTime; use DB; use Http; use Illuminate\Http\Request; -use Illuminate\Http\Response; use Log; use Modules\M3\Helpers\Helper; use Modules\M3\Http\Controllers\Controller; @@ -16,683 +15,337 @@ use Str; class TransferAPI extends Controller { private const ZERO_PAD = '000000'; - private const JSON_CONTENT_TYPE = 'application/json'; - private const ORDER_CATEGORY_LABEL = ' Order Category: '; - private const NO_URL_PARAMETERS = 'No URL Parameters Sent'; - // TransferAPIURL : with URL PARAMS public function TransferAPIURL(Request $request) { - ini_set('max_execution_time', Config::get('arrays.PHPTimeOut')); - ini_set('max_input_time', Config::get('arrays.PHPTimeOut')); - ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut')); - - // Get the Calling User - $sHUSER = m3User() !== '' ? Str::upper(m3User()) : 'WebUser'; - // Set SHSOURCE - $sHSOURCE = 'TransferAPIURL'; - $m3Errors = ''; - - // Get URL PARAMS - $urlParams = count($request->all()) > 0 ? $request->all() : ''; - $dIVI = isset($urlParams['COMPANY']) ? $urlParams['COMPANY'] : ''; - $wHS = isset($urlParams['WHS']) ? $urlParams['WHS'] : ''; + $this->configureTimeouts(); + $context = $this->transferContext($request); try { - if ($urlParams != '') { - $pART = isset($urlParams['PART']) ? $urlParams['PART'] : ''; - $lOCATIONFROM = isset($urlParams['LOCATIONFROM']) ? $urlParams['LOCATIONFROM'] : ''; - $lOCATIONTO = isset($urlParams['LOCATIONTO']) ? $urlParams['LOCATIONTO'] : ''; - $qUANTITY = isset($urlParams['QUANTITY']) ? $urlParams['QUANTITY'] : ''; - $oRDERCATEGORY = isset($urlParams['ORDERCATEGORY']) ? $urlParams['ORDERCATEGORY'] : ''; - $lOTNUMBER = isset($urlParams['LOTNUMBER']) ? $urlParams['LOTNUMBER'] : ''; - $cONUMBER = isset($urlParams['CONUMBER']) ? $urlParams['CONUMBER'] : ''; - $cOLINENO = isset($urlParams['COLINENO']) ? $urlParams['COLINENO'] : ''; - $dELIVERYNO = isset($urlParams['DELIVERYNO']) ? $urlParams['DELIVERYNO'] : self::ZERO_PAD; - $pICKLISTSUFFIX = isset($urlParams['PICKLISTSUFFIX']) ? $urlParams['PICKLISTSUFFIX'] : ''; - $eNDFLAG = isset($urlParams['ENDFLAG']) ? $urlParams['ENDFLAG'] : ''; - $tYPE = isset($urlParams['TYPE']) ? $urlParams['TYPE'] : ''; - $cOLINESUFFIX = isset($urlParams['COLINESUFFIX']) ? $urlParams['COLINESUFFIX'] : ''; - - // TYPE : - // DeliveryNote - // S15 - // CloseShipment - // COCharge - // Replenishment - // Move - - // ORDERCATEGORY : Order Category - // 1 = Material to manufacturing order - // 3 = Customer Order - // 4 = Requisition Order - // 5 = Distribution Order - // 9 = Move order - - $dELIVERYNO = isset($dELIVERYNO) ? $dELIVERYNO : self::ZERO_PAD; - - $tRANSTYPE = isset($urlParams['TRANSTYPE']) ? $urlParams['TRANSTYPE'] : ''; // R for Retry - $sHDT = isset($urlParams['SHDT']) ? $urlParams['SHDT'] : ''; - $sHTIME = isset($urlParams['SHTIME']) ? $urlParams['SHTIME'] : ''; - $sHTYPE = isset($urlParams['SHTYPE']) ? $urlParams['SHTYPE'] : ''; - - // Retry Transfer - if ($tRANSTYPE == 'R') { - // $t = strtotime($sHTIME); - // $SHTIMEHM = date('H:i',$t); - // dd($SHTIMEHM); - // Get the record that contain the payload - $iCM699MS = DB::connection(config('m3.connection', 'pgsql'))->table('icm699m') - ->select('SHDATA') - ->where('SHMACPKR', $dELIVERYNO) - ->where('SHDT', $sHDT) - ->where('SHTIME', $sHTIME) - // ->whereRaw("VARCHAR_FORMAT (TIMESTAMP (CURRENT DATE) + MIDNIGHT_SECONDS (SHTIME) SECONDS, 'HH24:MI') = ?", [$SHTIMEHM]) - ->where('SHCO', $dIVI) - ->where('SHWHS', $wHS) - ->where('SHSOURCE', $sHSOURCE) - ->where('SHERROR', 'X') - ->where('SHTYPE', $sHTYPE) - ->first(); - - // Read The substring from SHDATA after M3-JSN-out - $word = 'M3-JSN-out'; - $sHDATA = isset($iCM699MS->SHDATA) ? $iCM699MS->SHDATA : ''; - $sHDATAJSON = ''; - $position = strpos($sHDATA, $word); - // Also Read CommTCP_read - $word2 = 'url:http://127.0.0.1:10005/api/TransferAPIURL?'; - $sHDATA2 = isset($iCM699MS->SHDATA) ? $iCM699MS->SHDATA : ''; - $position2 = strpos($sHDATA2, $word2); - - if ($position !== false) { - $sHDATAJSON = substr($sHDATA, $position + strlen($word)); - } elseif ($position2 !== false) { - $sHDATAJSONS = substr($sHDATA2, $position2 + strlen($word2)); - $sHDATAJSONA = []; - parse_str($sHDATAJSONS, $sHDATAJSONA); - $sHDATAJSON = json_encode($sHDATAJSONA); - } - // Find the position of the opening and closing curly braces - $startPos = strpos($sHDATAJSON, '{'); - $endPos = strrpos($sHDATAJSON, '}'); - // Extract the substring within the curly braces - $sHDATAJSON = substr($sHDATAJSON, $startPos, $endPos - $startPos + 1); - - $jSONTR = $sHDATAJSON != '' ? json_decode($sHDATAJSON) : ''; - - if ($jSONTR != '') { - $pART = isset($jSONTR->PART) ? $jSONTR->PART : ''; - $lOCATIONFROM = isset($jSONTR->LOCATIONFROM) ? $jSONTR->LOCATIONFROM : ''; - $lOCATIONTO = isset($jSONTR->LOCATIONTO) ? $jSONTR->LOCATIONTO : ''; - $qUANTITY = isset($jSONTR->QUANTITY) ? $jSONTR->QUANTITY : ''; - $oRDERCATEGORY = isset($jSONTR->ORDERCATEGORY) ? $jSONTR->ORDERCATEGORY : ''; - $lOTNUMBER = isset($jSONTR->LOTNUMBER) ? $jSONTR->LOTNUMBER : ''; - $cONUMBER = isset($jSONTR->CONUMBER) ? $jSONTR->CONUMBER : ''; - $cOLINENO = isset($jSONTR->COLINENO) ? $jSONTR->COLINENO : ''; - $dELIVERYNO = isset($jSONTR->DELIVERYNO) ? $jSONTR->DELIVERYNO : self::ZERO_PAD; - $pICKLISTSUFFIX = isset($jSONTR->PICKLISTSUFFIX) ? $jSONTR->PICKLISTSUFFIX : ''; - $eNDFLAG = isset($jSONTR->ENDFLAG) ? $jSONTR->ENDFLAG : ''; - $tYPE = isset($jSONTR->TYPE) ? $jSONTR->TYPE : ''; - $cOLINESUFFIX = isset($jSONTR->COLINESUFFIX) ? $jSONTR->COLINESUFFIX : ''; - } - - // Set SHERROR to Z in ICM699M - DB::connection(config('m3.connection', 'pgsql'))->table('icm699m') - ->where('SHMACPKR', $dELIVERYNO) - ->where('SHDT', $sHDT) - ->where('SHTIME', $sHTIME) - ->where('SHCO', $dIVI) - ->where('SHWHS', $wHS) - ->where('SHSOURCE', $sHSOURCE) - ->where('SHERROR', 'X') - ->where('SHTYPE', $sHTYPE) - ->update(['SHERROR' => 'Z', 'SHACKUSER' => $sHUSER, 'SHACKDATE' => date('Y-m-d'), 'SHACKTIME' => date('H:i:s')]); - } - - // Part Exists : proceed - if ($pART != '') { - // Read from ICM688M2 - // Get Parts And Lots from ICM688M2 - $iCM688M2SLTMP = DB::connection(config('m3.connection', 'pgsql'))->table('icm688m2') - ->select('A5BRADLN', 'A5PKSFX', 'A5PLANT', 'A5SENTPKR') - ->distinct() - ->where('A5CO', $dIVI) - ->where('A5WHS', $wHS) - ->where('A5MACPKR', $dELIVERYNO); - - // Get Pack Lines - if ($cOLINENO != '') { - $iCM688M2SLTMP->where('A5PKLN', $cOLINENO); - } - $iCM688M2SL = $iCM688M2SLTMP->first(); - - $a5BRADLINE = isset($iCM688M2SL->A5BRADLN) ? $iCM688M2SL->A5BRADLN : ''; - $cOLINESUFFIX = isset($iCM688M2SL->A5PKSFX) ? $iCM688M2SL->A5PKSFX : ''; // Case 551 : $cOLINESUFFIX - $a5PLANT = isset($iCM688M2SL->A5PLANT) ? $iCM688M2SL->A5PLANT : ''; - $a5SENTPKR = isset($iCM688M2SL->A5SENTPKR) ? $iCM688M2SL->A5SENTPKR : ''; - - $jSONIN = json_encode([ - 'DIVI' => $dIVI, - 'WHS' => $wHS, - 'PART' => $pART, - 'LOCATIONFROM' => $lOCATIONFROM, - 'LOCATIONTO' => $lOCATIONTO, - 'QUANTITY' => $qUANTITY, - 'ORDERCATEGORY' => $oRDERCATEGORY, - 'LOTNUMBER' => $lOTNUMBER, - 'CONUMBER' => $cONUMBER, - 'COLINENO' => $cOLINENO, - 'DELIVERYNO' => $dELIVERYNO, - 'PICKLISTSUFFIX' => $pICKLISTSUFFIX, - 'ENDFLAG' => $eNDFLAG, - 'TYPE' => $tYPE, - 'COLINESUFFIX' => $cOLINESUFFIX, - ], JSON_UNESCAPED_SLASHES); - - $jSON = json_encode([ - 'DIVI' => $dIVI, - 'WHS' => $wHS, - 'PART' => $pART, - 'LOCATIONFROM' => $lOCATIONFROM, - 'LOCATIONTO' => $lOCATIONTO, - 'QUANTITY' => $qUANTITY, - 'ORDERCATEGORY' => $oRDERCATEGORY, - 'LOTNUMBER' => $lOTNUMBER, - 'CONUMBER' => $cONUMBER, - 'COLINENO' => $a5BRADLINE, - 'DELIVERYNO' => $dELIVERYNO, - 'PICKLISTSUFFIX' => $pICKLISTSUFFIX, - 'ENDFLAG' => $eNDFLAG, - 'TYPE' => $tYPE, - 'COLINESUFFIX' => $cOLINESUFFIX, - ], JSON_UNESCAPED_SLASHES); - - // Write JSON Params to Logs Out - $data = ['SHMACPKR' => $dELIVERYNO, - 'SHDT' => date('Y-m-d'), - 'SHTIME' => date('H:i:s'), - 'SHERROR' => '', - 'SHINTBOX' => '', - 'SHTYPE' => 'M3-Req-out', - 'SHDATA' => $jSON, - 'SHUSER' => $sHUSER, - 'SHSOURCE' => $sHSOURCE, - 'SHCO' => $dIVI, - 'SHWHS' => $wHS, - ]; - Helper::logToICM699M($data); - - // Get Token - $tokenResponse = Helper::checkReceiveTokenV2(); - $tokenData = $tokenResponse->getData(); - if ($tokenData->code == '200') { - $ionToken = isset($tokenData->token) ? $tokenData->token : ''; - } else { - $sHDATA = isset($tokenData->message) ? $tokenData->message : ''; - // Write to Logs : Error - $data = ['SHMACPKR' => $dELIVERYNO, - 'SHDT' => date('Y-m-d'), - 'SHTIME' => date('H:i:s'), - 'SHERROR' => '', - 'SHINTBOX' => '', - 'SHTYPE' => 'M3-Res-out', - 'SHDATA' => $sHDATA, - 'SHUSER' => $sHUSER, - 'SHSOURCE' => $sHSOURCE, - 'SHCO' => $dIVI, - 'SHWHS' => $wHS, - ]; - Helper::logToICM699M($data); - - return $tokenResponse; - } - - // Call ionapi with Params - $endPointURL = env('ENDPOINTURL') . 'APIFLOWS/Sentinel/TransferAPI?ionapiRespStyle=sync'; - $token = $ionToken; - - $response = Http::withHeaders([ - 'accept' => self::JSON_CONTENT_TYPE, - 'Content-Type' => self::JSON_CONTENT_TYPE, - ]) - ->withToken($token) - ->withBody($jSON, self::JSON_CONTENT_TYPE) - ->timeout(Config::get('arrays.curlTimeOut')) - ->post($endPointURL); - $responseStatusCode = $response->getStatusCode(); - $m3SessionId = $response->hasHeader('x-transaction-id') ? '-sessionID:' . $response->header('x-transaction-id') : '-sessionID'; - $m3ResponseTimeTmp = $response->hasHeader('x-response-time') ? ltrim($response->header('x-response-time'), '-') : '0'; - $m3ResponseTimeTmp2 = floatval($m3ResponseTimeTmp) / 1000; - $dateTime = new DateTime; - $dateTime->setTimestamp($m3ResponseTimeTmp2); - $m3ResponseTime = $m3ResponseTimeTmp != '' ? '-M3ResponseTime:' . $dateTime->format('d/m/Y H:i:s.v') : '-M3ResponseTime'; - $transferStats = $response->transferStats; - $m3transferTime = $transferStats->getTransferTime() != null ? '-M3transferTime:' . $transferStats->getTransferTime() : '-M3transferTime'; - - if ($responseStatusCode == '200') { - $responseContents = json_decode($response->getBody()->getContents()); - $responseResult = $responseContents->result; - $m3JSONResponse = json_encode($responseContents); - // Check M3 Response for Errors - $m3Errors = Helper::checkM3Errors($responseResult); - } else { - $m3JSONResponse = ''; - $m3Errors = 'Error: No Response from M3'; - } - - if ($m3Errors == '') { - // Write to Logs Out : Success - $data = ['SHMACPKR' => $dELIVERYNO, - 'SHDT' => date('Y-m-d'), - 'SHTIME' => date('H:i:s'), - 'SHERROR' => '', - 'SHINTBOX' => '', - 'SHTYPE' => 'M3-Res-out', - 'SHDATA' => $responseStatusCode . 'TYPE :' . $tYPE . self::ORDER_CATEGORY_LABEL . $oRDERCATEGORY . '-' . $m3JSONResponse . $m3SessionId . $m3ResponseTime . $m3transferTime, - 'SHUSER' => $sHUSER, - 'SHSOURCE' => $sHSOURCE, - 'SHCO' => $dIVI, - 'SHWHS' => $wHS, - ]; - Helper::logToICM699M($data); - - // Log to ICM799M - DB::connection(config('m3.connection', 'pgsql'))->table('icm799m') - ->insert(['IMDIV' => $dIVI, - 'IMPLANT' => $a5PLANT, - 'IMWHS' => $wHS, - 'IMSENTPKR' => $a5SENTPKR, - 'IMDELNO' => $dELIVERYNO, - 'IMORDER' => $cONUMBER, - 'IMLINE' => $cOLINENO, - 'IMBRADLN' => $a5BRADLINE, - 'IMSUFFIX' => $pICKLISTSUFFIX, - 'IMPART' => $pART, - 'IMLOT' => $lOTNUMBER, - 'IMQTY' => $qUANTITY, - 'IMFRLOC' => $lOCATIONFROM, - 'IMTOLOC' => $lOCATIONTO, - 'IMDATE' => date('Ymd'), - 'IMTIME' => date('His'), - ]); - - return response()->json([ - 'code' => $responseStatusCode, - 'status' => 'Success', - ]); - } else { - // Write to Logs Out : Failed - $data = ['SHMACPKR' => $dELIVERYNO, - 'SHDT' => date('Y-m-d'), - 'SHTIME' => date('H:i:s'), - 'SHERROR' => 'X', - 'SHINTBOX' => '', - 'SHTYPE' => 'M3-Res-out', - 'SHDATA' => $responseStatusCode . '-' . $m3Errors . '-TYPE:' . $tYPE . self::ORDER_CATEGORY_LABEL . $oRDERCATEGORY . '-' . $m3JSONResponse . - 'M3-JSN-out' . $jSONIN . $m3SessionId . $m3ResponseTime . $m3transferTime, - 'SHUSER' => $sHUSER, - 'SHSOURCE' => $sHSOURCE, - 'SHCO' => $dIVI, - 'SHWHS' => $wHS, - ]; - Helper::logToICM699M($data); - - return response()->json([ - 'code' => '206', - 'status' => 'Error', - 'message' => $responseStatusCode . '-' . $m3Errors . '- TYPE :' . $tYPE . self::ORDER_CATEGORY_LABEL . $oRDERCATEGORY . '-' . $m3JSONResponse, - ]); - } - } - // Part Does not Exist : Failure - else { - // Return Error - return response()->json([ - 'code' => '405', - 'status' => 'Error', - 'message' => 'Json Payload Not Valid, possible cause: Retry butto was clicked by another user.', - ]); - } - } else { - // Write to Logs Out : Error - $dELIVERYNO = isset($dELIVERYNO) ? $dELIVERYNO : self::ZERO_PAD; - $data = ['SHMACPKR' => $dELIVERYNO, - 'SHDT' => date('Y-m-d'), - 'SHTIME' => date('H:i:s'), - 'SHERROR' => 'X', - 'SHINTBOX' => '', - 'SHTYPE' => 'M3-Res-out', - 'SHDATA' => self::NO_URL_PARAMETERS, - 'SHUSER' => $sHUSER, - 'SHSOURCE' => $sHSOURCE, - 'SHCO' => $dIVI, - 'SHWHS' => $wHS, - ]; - Helper::logToICM699M($data); - - // Return Error - return response()->json([ - 'code' => '405', - 'status' => 'Error', - 'message' => self::NO_URL_PARAMETERS, - ]); - } - } catch (\Throwable $th) { - $getCurlErrors = str_contains($th->getMessage(), 'cURL error'); - if ($getCurlErrors) { - // Write to Logs Out : Failed - $data = ['SHMACPKR' => $dELIVERYNO, - 'SHDT' => date('Y-m-d'), - 'SHTIME' => date('H:i:s'), - 'SHERROR' => 'X', - 'SHINTBOX' => '', - 'SHTYPE' => 'M3-Res-out', - 'SHDATA' => 'Curl Error: Communication with M3 Timed Out' . ' M3-JSN-out' . $jSONIN, - 'SHUSER' => $sHUSER, - 'SHSOURCE' => $sHSOURCE, - 'SHCO' => $dIVI, - 'SHWHS' => $wHS, - ]; - Helper::logToICM699M($data); - - return response()->json([ - 'code' => '405', - 'status' => 'error', - 'message' => 'Curl Error: Communication with M3 Timed Out.', - ]); - } else { - // Write to Logs Out : Error - $dELIVERYNO = isset($dELIVERYNO) ? $dELIVERYNO : self::ZERO_PAD; - $data = ['SHMACPKR' => $dELIVERYNO, - 'SHDT' => date('Y-m-d'), - 'SHTIME' => date('H:i:s'), - 'SHERROR' => 'X', - 'SHINTBOX' => '', - 'SHTYPE' => 'M3-Err-out', - 'SHDATA' => 'An Error Occured - ' . substr($th, 0, 300), - 'SHUSER' => $sHUSER, - 'SHSOURCE' => $sHSOURCE, - 'SHCO' => $dIVI, - 'SHWHS' => $wHS, - ]; - Helper::logToICM699M($data); - Log::error($th); - - return response()->json([ - 'code' => '405', - 'status' => 'error', - 'message' => 'Uncaught Error', - ]); - } - + $response = $this->processTransfer($context); + } catch (\Throwable $throwable) { + $response = $this->exceptionResponse($context, $throwable, $context['json_in'] ?? ''); } - } - // End TransferAPIURL - // UpdateShipmentNumber : with URL PARAMS + return $response; + } + public function UpdateShipmentNumber(Request $request) + { + $this->configureTimeouts(); + $context = $this->shipmentContext($request); + + try { + $response = $this->processShipmentUpdate($context); + } catch (\Throwable $throwable) { + $response = $this->exceptionResponse($context, $throwable, $context['json'] ?? ''); + } + + return $response; + } + + private function configureTimeouts(): void { ini_set('max_execution_time', Config::get('arrays.PHPTimeOut')); ini_set('max_input_time', Config::get('arrays.PHPTimeOut')); ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut')); - - // Get the Calling User - $sHUSER = m3User() !== '' ? Str::upper(m3User()) : 'WebUser'; - // Set SHSOURCE - $sHSOURCE = 'UpdateShipmentNumber'; - $m3Errors = ''; - - // Get URL PARAMS - $urlParams = count($request->all()) > 0 ? $request->all() : ''; - $dIVI = isset($urlParams['COMPANY']) ? $urlParams['COMPANY'] : ''; - $wHS = isset($urlParams['WHS']) ? $urlParams['WHS'] : ''; - $pLANT = isset($urlParams['PLANT']) ? $urlParams['PLANT'] : ''; - - try { - if ($urlParams != '') { - $a4SPR15A01 = isset($urlParams['A4SPR15A01']) ? $urlParams['A4SPR15A01'] : ''; - $dELIVERYNO = isset($urlParams['DELIVERYNO']) ? $urlParams['DELIVERYNO'] : ''; - $tYPE = 'UpdateShipmentNumber'; - $allMacpkrs = []; - - if ($a4SPR15A01 != '') { - // Read from ICM688M1 - $iCM688M1SLTMP = DB::connection(config('m3.connection', 'pgsql'))->table('icm688m1') - ->select('A4MACPKR') - ->where('A4CO', $dIVI) - ->where('A4WHS', $wHS) - ->where('A4PLANT', $pLANT) - ->where('A4SPR15A01', $a4SPR15A01); - - // Get Macpikers also if sent as Parameter - if ($dELIVERYNO != '') { - $iCM688M1SLTMP->where('A4MACPKR', $dELIVERYNO); - } - $iCM688M1SL = $iCM688M1SLTMP->get(); - // Loop ICM688M1 to get all A4MACPKR - foreach ($iCM688M1SL as $ICM688M1) { - $allMacpkrs[] = $ICM688M1->A4MACPKR; - } - } - - // A4SPR15A01 Exists : proceed - if ($a4SPR15A01 != '' && ! empty($allMacpkrs)) { - $jSON = json_encode([ - 'DIVI' => $dIVI, - 'WHS' => $wHS, - 'ShipmentNumber' => [ - 'Number' => $a4SPR15A01, - 'DeliveryNumbers' => $allMacpkrs, - ], - 'TYPE' => $tYPE, - 'ENDFLAG' => '', - - ], JSON_UNESCAPED_SLASHES); - - // Write JSON Params to Logs Out - $data = ['SHMACPKR' => $dELIVERYNO, - 'SHDT' => date('Y-m-d'), - 'SHTIME' => date('H:i:s'), - 'SHERROR' => '', - 'SHINTBOX' => '', - 'SHTYPE' => 'M3-Req-out', - 'SHDATA' => $jSON, - 'SHUSER' => $sHUSER, - 'SHSOURCE' => $sHSOURCE, - 'SHCO' => $dIVI, - 'SHWHS' => $wHS, - ]; - Helper::logToICM699M($data); - - // Get Token - $tokenResponse = Helper::checkReceiveTokenV2(); - $tokenData = $tokenResponse->getData(); - if ($tokenData->code == '200') { - $ionToken = isset($tokenData->token) ? $tokenData->token : ''; - } else { - $sHDATA = isset($tokenData->message) ? $tokenData->message : ''; - // Write to Logs : Error - $data = ['SHMACPKR' => $dELIVERYNO, - 'SHDT' => date('Y-m-d'), - 'SHTIME' => date('H:i:s'), - 'SHERROR' => '', - 'SHINTBOX' => '', - 'SHTYPE' => 'M3-Res-out', - 'SHDATA' => $sHDATA, - 'SHUSER' => $sHUSER, - 'SHSOURCE' => $sHSOURCE, - 'SHCO' => $dIVI, - 'SHWHS' => $wHS, - ]; - Helper::logToICM699M($data); - - return $tokenResponse; - } - - // Call ionapi with Params - $endPointURL = env('ENDPOINTURL') . 'APIFLOWS/Sentinel/TransferAPI?ionapiRespStyle=sync'; - $token = $ionToken; - - $response = Http::withHeaders([ - 'accept' => self::JSON_CONTENT_TYPE, - 'Content-Type' => self::JSON_CONTENT_TYPE, - ]) - ->withToken($token) - ->withBody($jSON, self::JSON_CONTENT_TYPE) - ->timeout(Config::get('arrays.curlTimeOut')) - ->post($endPointURL); - $responseStatusCode = $response->getStatusCode(); - $m3SessionId = $response->hasHeader('x-transaction-id') ? '-sessionID:' . $response->header('x-transaction-id') : '-sessionID'; - $m3ResponseTimeTmp = $response->hasHeader('x-response-time') ? ltrim($response->header('x-response-time'), '-') : '0'; - $m3ResponseTimeTmp2 = floatval($m3ResponseTimeTmp) / 1000; - $dateTime = new DateTime; - $dateTime->setTimestamp($m3ResponseTimeTmp2); - $m3ResponseTime = $m3ResponseTimeTmp != '' ? '-M3ResponseTime:' . $dateTime->format('d/m/Y H:i:s.v') : '-M3ResponseTime'; - $transferStats = $response->transferStats; - $m3transferTime = $transferStats->getTransferTime() != null ? '-M3transferTime:' . $transferStats->getTransferTime() : '-M3transferTime'; - - if ($responseStatusCode == '200') { - $responseContents = json_decode($response->getBody()->getContents()); - $responseResult = $responseContents->result; - $m3JSONResponse = json_encode($responseContents); - // Check M3 Response for Errors - $m3Errors = Helper::checkM3Errors($responseResult); - } else { - $m3JSONResponse = ''; - $m3Errors = 'Error: No Response from M3'; - } - - if ($m3Errors == '') { - // Write to Logs Out : Success - $data = ['SHMACPKR' => $dELIVERYNO, - 'SHDT' => date('Y-m-d'), - 'SHTIME' => date('H:i:s'), - 'SHERROR' => '', - 'SHINTBOX' => '', - 'SHTYPE' => 'M3-Res-out', - 'SHDATA' => $responseStatusCode . 'TYPE :' . $tYPE . '-' . $m3JSONResponse . $m3SessionId . $m3ResponseTime . $m3transferTime, - 'SHUSER' => $sHUSER, - 'SHSOURCE' => $sHSOURCE, - 'SHCO' => $dIVI, - 'SHWHS' => $wHS, - ]; - Helper::logToICM699M($data); - - return response()->json([ - 'code' => $responseStatusCode, - 'status' => 'Success', - ]); - } else { - // Write to Logs Out : Failed - $data = ['SHMACPKR' => $dELIVERYNO, - 'SHDT' => date('Y-m-d'), - 'SHTIME' => date('H:i:s'), - 'SHERROR' => 'X', - 'SHINTBOX' => '', - 'SHTYPE' => 'M3-Res-out', - 'SHDATA' => $responseStatusCode . '-' . $m3Errors . '-TYPE:' . $tYPE . '-' . $m3JSONResponse . - 'M3-JSN-out' . $jSON . $m3SessionId . $m3ResponseTime . $m3transferTime, - 'SHUSER' => $sHUSER, - 'SHSOURCE' => $sHSOURCE, - 'SHCO' => $dIVI, - 'SHWHS' => $wHS, - ]; - Helper::logToICM699M($data); - - return response()->json([ - 'code' => '206', - 'status' => 'Error', - 'message' => $responseStatusCode . '-' . $m3Errors . '- TYPE :' . $tYPE . '-' . $m3JSONResponse, - ]); - } - } - // A4SPR15A01 Does not Exist : Failure - else { - // Return Error - return response()->json([ - 'code' => '405', - 'status' => 'Error', - 'message' => 'Json Payload Not Valid, missing Parameter or no Macpicker # found.', - ]); - } - } else { - // Write to Logs Out : Error - $dELIVERYNO = isset($dELIVERYNO) ? $dELIVERYNO : self::ZERO_PAD; - $data = ['SHMACPKR' => $dELIVERYNO, - 'SHDT' => date('Y-m-d'), - 'SHTIME' => date('H:i:s'), - 'SHERROR' => 'X', - 'SHINTBOX' => '', - 'SHTYPE' => 'M3-Res-out', - 'SHDATA' => self::NO_URL_PARAMETERS, - 'SHUSER' => $sHUSER, - 'SHSOURCE' => $sHSOURCE, - 'SHCO' => $dIVI, - 'SHWHS' => $wHS, - ]; - Helper::logToICM699M($data); - - // Return Error - return response()->json([ - 'code' => '405', - 'status' => 'Error', - 'message' => self::NO_URL_PARAMETERS, - ]); - } - } catch (\Throwable $th) { - $getCurlErrors = str_contains($th->getMessage(), 'cURL error'); - if ($getCurlErrors) { - // Write to Logs Out : Failed - $data = ['SHMACPKR' => $dELIVERYNO, - 'SHDT' => date('Y-m-d'), - 'SHTIME' => date('H:i:s'), - 'SHERROR' => 'X', - 'SHINTBOX' => '', - 'SHTYPE' => 'M3-Res-out', - 'SHDATA' => 'Curl Error: Communication with M3 Timed Out' . ' M3-JSN-out' . $jSON, - 'SHUSER' => $sHUSER, - 'SHSOURCE' => $sHSOURCE, - 'SHCO' => $dIVI, - 'SHWHS' => $wHS, - ]; - Helper::logToICM699M($data); - - return response()->json([ - 'code' => '405', - 'status' => 'error', - 'message' => 'Curl Error: Communication with M3 Timed Out.', - ]); - } else { - // Write to Logs Out : Error - $dELIVERYNO = isset($dELIVERYNO) ? $dELIVERYNO : self::ZERO_PAD; - $data = ['SHMACPKR' => $dELIVERYNO, - 'SHDT' => date('Y-m-d'), - 'SHTIME' => date('H:i:s'), - 'SHERROR' => 'X', - 'SHINTBOX' => '', - 'SHTYPE' => 'M3-Err-out', - 'SHDATA' => 'An Error Occured - ' . substr($th, 0, 300), - 'SHUSER' => $sHUSER, - 'SHSOURCE' => $sHSOURCE, - 'SHCO' => $dIVI, - 'SHWHS' => $wHS, - ]; - Helper::logToICM699M($data); - Log::error($th); - - return response()->json([ - 'code' => '405', - 'status' => 'error', - 'message' => 'Uncaught Error', - ]); - } - - } } - // End UpdateShipmentNumber + private function transferContext(Request $request): array + { + $params = $request->all(); + + return [ + 'params' => $params, + 'user' => m3User() !== '' ? Str::upper(m3User()) : 'WebUser', + 'source' => 'TransferAPIURL', + 'company' => $params['COMPANY'] ?? '', + 'warehouse' => $params['WHS'] ?? '', + 'delivery' => $params['DELIVERYNO'] ?? self::ZERO_PAD, + ]; + } + + private function shipmentContext(Request $request): array + { + $params = $request->all(); + + return [ + 'params' => $params, + 'user' => m3User() !== '' ? Str::upper(m3User()) : 'WebUser', + 'source' => 'UpdateShipmentNumber', + 'company' => $params['COMPANY'] ?? '', + 'warehouse' => $params['WHS'] ?? '', + 'plant' => $params['PLANT'] ?? '', + 'delivery' => $params['DELIVERYNO'] ?? '', + ]; + } + + private function processTransfer(array &$context) + { + if ($context['params'] === []) { + $this->log($context, self::NO_URL_PARAMETERS, 'X', 'M3-Res-out'); + return $this->errorResponse('405', self::NO_URL_PARAMETERS); + } + + $context = array_merge($context, $this->transferFields($context['params'])); + $this->restoreRetryPayload($context); + + if ($context['part'] === '') { + return $this->errorResponse('405', 'Json Payload Not Valid, possible cause: Retry butto was clicked by another user.'); + } + + return $this->executeTransfer($context); + } + + private function transferFields(array $params): array + { + return [ + 'part' => $params['PART'] ?? '', 'from' => $params['LOCATIONFROM'] ?? '', + 'to' => $params['LOCATIONTO'] ?? '', 'quantity' => $params['QUANTITY'] ?? '', + 'order_category' => $params['ORDERCATEGORY'] ?? '', 'lot' => $params['LOTNUMBER'] ?? '', + 'co_number' => $params['CONUMBER'] ?? '', 'co_line' => $params['COLINENO'] ?? '', + 'delivery' => $params['DELIVERYNO'] ?? self::ZERO_PAD, 'pick_suffix' => $params['PICKLISTSUFFIX'] ?? '', + 'end_flag' => $params['ENDFLAG'] ?? '', 'type' => $params['TYPE'] ?? '', + 'co_line_suffix' => $params['COLINESUFFIX'] ?? '', 'trans_type' => $params['TRANSTYPE'] ?? '', + 'shdt' => $params['SHDT'] ?? '', 'shtime' => $params['SHTIME'] ?? '', 'shtype' => $params['SHTYPE'] ?? '', + ]; + } + + private function restoreRetryPayload(array &$context): void + { + if ($context['trans_type'] !== 'R') { + return; + } + + $record = DB::connection(config('m3.connection', 'pgsql'))->table('icm699m') + ->select('SHDATA')->where('SHMACPKR', $context['delivery'])->where('SHDT', $context['shdt']) + ->where('SHTIME', $context['shtime'])->where('SHCO', $context['company'])->where('SHWHS', $context['warehouse']) + ->where('SHSOURCE', $context['source'])->where('SHERROR', 'X')->where('SHTYPE', $context['shtype'])->first(); + + $payload = $this->retryPayload($record->SHDATA ?? ''); + if ($payload !== []) { + $context = array_merge($context, $this->transferFields($payload)); + } + + DB::connection(config('m3.connection', 'pgsql'))->table('icm699m') + ->where('SHMACPKR', $context['delivery'])->where('SHDT', $context['shdt'])->where('SHTIME', $context['shtime']) + ->where('SHCO', $context['company'])->where('SHWHS', $context['warehouse'])->where('SHSOURCE', $context['source']) + ->where('SHERROR', 'X')->where('SHTYPE', $context['shtype']) + ->update(['SHERROR' => 'Z', 'SHACKUSER' => $context['user'], 'SHACKDATE' => date('Y-m-d'), 'SHACKTIME' => date('H:i:s')]); + } + + private function retryPayload(string $data): array + { + $json = ''; + $marker = 'M3-JSN-out'; + $urlMarker = 'url:http://127.0.0.1:10005/api/TransferAPIURL?'; + $position = strpos($data, $marker); + $urlPosition = strpos($data, $urlMarker); + + if ($position !== false) { + $json = substr($data, $position + strlen($marker)); + } elseif ($urlPosition !== false) { + parse_str(substr($data, $urlPosition + strlen($urlMarker)), $payload); + return is_array($payload) ? $payload : []; + } + + $start = strpos($json, '{'); + $end = strrpos($json, '}'); + if ($start === false || $end === false || $end < $start) { + return []; + } + + $decoded = json_decode(substr($json, $start, $end - $start + 1), true); + return is_array($decoded) ? $decoded : []; + } + + private function executeTransfer(array &$context) + { + $line = $this->transferLine($context); + $context['brad_line'] = $line->A5BRADLN ?? ''; + $context['co_line_suffix'] = $line->A5PKSFX ?? ''; + $context['plant'] = $line->A5PLANT ?? ''; + $context['sent_picker'] = $line->A5SENTPKR ?? ''; + $context['json_in'] = $this->transferJson($context, false); + $json = $this->transferJson($context, true); + $this->log($context, $json, '', 'M3-Req-out'); + + $token = $this->token($context); + if (! is_string($token)) { + return $token; + } + + $result = $this->callM3($token, $json); + return $this->transferResult($context, $result); + } + + private function transferLine(array $context): ?object + { + $query = DB::connection(config('m3.connection', 'pgsql'))->table('icm688m2') + ->select('A5BRADLN', 'A5PKSFX', 'A5PLANT', 'A5SENTPKR')->distinct() + ->where('A5CO', $context['company'])->where('A5WHS', $context['warehouse'])->where('A5MACPKR', $context['delivery']); + if ($context['co_line'] !== '') { + $query->where('A5PKLN', $context['co_line']); + } + return $query->first(); + } + + private function transferJson(array $c, bool $useBradLine): string + { + return (string) json_encode([ + 'DIVI' => $c['company'], 'WHS' => $c['warehouse'], 'PART' => $c['part'], 'LOCATIONFROM' => $c['from'], + 'LOCATIONTO' => $c['to'], 'QUANTITY' => $c['quantity'], 'ORDERCATEGORY' => $c['order_category'], 'LOTNUMBER' => $c['lot'], + 'CONUMBER' => $c['co_number'], 'COLINENO' => $useBradLine ? $c['brad_line'] : $c['co_line'], 'DELIVERYNO' => $c['delivery'], + 'PICKLISTSUFFIX' => $c['pick_suffix'], 'ENDFLAG' => $c['end_flag'], 'TYPE' => $c['type'], 'COLINESUFFIX' => $c['co_line_suffix'], + ], JSON_UNESCAPED_SLASHES); + } + + private function processShipmentUpdate(array &$context) + { + $shipment = $context['params']['A4SPR15A01'] ?? ''; + $pickers = $this->shipmentPickers($context, $shipment); + $invalid = $this->shipmentValidationResponse($context, $shipment, $pickers); + if ($invalid !== null) { + return $invalid; + } + + $context['type'] = 'UpdateShipmentNumber'; + $context['json'] = (string) json_encode([ + 'DIVI' => $context['company'], 'WHS' => $context['warehouse'], + 'ShipmentNumber' => ['Number' => $shipment, 'DeliveryNumbers' => $pickers], + 'TYPE' => $context['type'], 'ENDFLAG' => '', + ], JSON_UNESCAPED_SLASHES); + $this->log($context, $context['json'], '', 'M3-Req-out'); + + $token = $this->token($context); + if (! is_string($token)) { + return $token; + } + + return $this->shipmentResult($context, $this->callM3($token, $context['json'])); + } + + private function shipmentValidationResponse(array $context, string $shipment, array $pickers) + { + if ($context['params'] === []) { + $this->log($context, self::NO_URL_PARAMETERS, 'X', 'M3-Res-out'); + return $this->errorResponse('405', self::NO_URL_PARAMETERS); + } + if ($shipment === '' || $pickers === []) { + return $this->errorResponse('405', 'Json Payload Not Valid, missing Parameter or no Macpicker # found.'); + } + return null; + } + + private function shipmentPickers(array $context, string $shipment): array + { + if ($shipment === '') { + return []; + } + $query = DB::connection(config('m3.connection', 'pgsql'))->table('icm688m1')->select('A4MACPKR') + ->where('A4CO', $context['company'])->where('A4WHS', $context['warehouse'])->where('A4PLANT', $context['plant']) + ->where('A4SPR15A01', $shipment); + if ($context['delivery'] !== '') { + $query->where('A4MACPKR', $context['delivery']); + } + return $query->get()->pluck('A4MACPKR')->all(); + } + + private function token(array $context) + { + $response = Helper::checkReceiveTokenV2(); + $data = $response->getData(); + if ((string) ($data->code ?? '') === '200') { + return (string) ($data->token ?? ''); + } + $this->log($context, (string) ($data->message ?? ''), '', 'M3-Res-out'); + return $response; + } + + private function callM3(string $token, string $json): array + { + $response = Http::withHeaders(['accept' => self::JSON_CONTENT_TYPE, 'Content-Type' => self::JSON_CONTENT_TYPE]) + ->withToken($token)->withBody($json, self::JSON_CONTENT_TYPE)->timeout(Config::get('arrays.curlTimeOut')) + ->post(env('ENDPOINTURL') . 'APIFLOWS/Sentinel/TransferAPI?ionapiRespStyle=sync'); + $status = $response->getStatusCode(); + $jsonResponse = ''; + $errors = 'Error: No Response from M3'; + if ((string) $status === '200') { + $contents = json_decode($response->getBody()->getContents()); + $jsonResponse = json_encode($contents); + $errors = Helper::checkM3Errors($contents->result ?? null); + } + return ['status' => $status, 'json' => $jsonResponse, 'errors' => $errors, 'metrics' => $this->responseMetrics($response)]; + } + + private function responseMetrics($response): string + { + $session = $response->hasHeader('x-transaction-id') ? '-sessionID:' . $response->header('x-transaction-id') : '-sessionID'; + $raw = $response->hasHeader('x-response-time') ? ltrim($response->header('x-response-time'), '-') : '0'; + $dateTime = new DateTime; + $dateTime->setTimestamp(floatval($raw) / 1000); + $responseTime = $raw !== '' ? '-M3ResponseTime:' . $dateTime->format('d/m/Y H:i:s.v') : '-M3ResponseTime'; + $transfer = $response->transferStats->getTransferTime(); + return $session . $responseTime . ($transfer !== null ? '-M3transferTime:' . $transfer : '-M3transferTime'); + } + + private function transferResult(array $c, array $result) + { + $prefix = $result['status'] . 'TYPE :' . $c['type'] . self::ORDER_CATEGORY_LABEL . $c['order_category'] . '-'; + if ($result['errors'] !== '') { + $this->log($c, $result['status'] . '-' . $result['errors'] . '-TYPE:' . $c['type'] . self::ORDER_CATEGORY_LABEL . $c['order_category'] . '-' . $result['json'] . 'M3-JSN-out' . $c['json_in'] . $result['metrics'], 'X', 'M3-Res-out'); + return $this->errorResponse('206', $result['status'] . '-' . $result['errors'] . '- TYPE :' . $c['type'] . self::ORDER_CATEGORY_LABEL . $c['order_category'] . '-' . $result['json']); + } + $this->log($c, $prefix . $result['json'] . $result['metrics'], '', 'M3-Res-out'); + $this->insertTransferAudit($c); + return response()->json(['code' => $result['status'], 'status' => 'Success']); + } + + private function shipmentResult(array $c, array $result) + { + if ($result['errors'] !== '') { + $this->log($c, $result['status'] . '-' . $result['errors'] . '-TYPE:' . $c['type'] . '-' . $result['json'] . 'M3-JSN-out' . $c['json'] . $result['metrics'], 'X', 'M3-Res-out'); + return $this->errorResponse('206', $result['status'] . '-' . $result['errors'] . '- TYPE :' . $c['type'] . '-' . $result['json']); + } + $this->log($c, $result['status'] . 'TYPE :' . $c['type'] . '-' . $result['json'] . $result['metrics'], '', 'M3-Res-out'); + return response()->json(['code' => $result['status'], 'status' => 'Success']); + } + + private function insertTransferAudit(array $c): void + { + DB::connection(config('m3.connection', 'pgsql'))->table('icm799m')->insert([ + 'IMDIV' => $c['company'], 'IMPLANT' => $c['plant'], 'IMWHS' => $c['warehouse'], 'IMSENTPKR' => $c['sent_picker'], + 'IMDELNO' => $c['delivery'], 'IMORDER' => $c['co_number'], 'IMLINE' => $c['co_line'], 'IMBRADLN' => $c['brad_line'], + 'IMSUFFIX' => $c['pick_suffix'], 'IMPART' => $c['part'], 'IMLOT' => $c['lot'], 'IMQTY' => $c['quantity'], + 'IMFRLOC' => $c['from'], 'IMTOLOC' => $c['to'], 'IMDATE' => date('Ymd'), 'IMTIME' => date('His'), + ]); + } + + private function log(array $c, string $message, string $error, string $type): void + { + Helper::logToICM699M([ + 'SHMACPKR' => $c['delivery'] ?: self::ZERO_PAD, 'SHDT' => date('Y-m-d'), 'SHTIME' => date('H:i:s'), + 'SHERROR' => $error, 'SHINTBOX' => '', 'SHTYPE' => $type, 'SHDATA' => $message, + 'SHUSER' => $c['user'], 'SHSOURCE' => $c['source'], 'SHCO' => $c['company'], 'SHWHS' => $c['warehouse'], + ]); + } + + private function exceptionResponse(array $context, \Throwable $throwable, string $json) + { + if (str_contains($throwable->getMessage(), 'cURL error')) { + $this->log($context, 'Curl Error: Communication with M3 Timed Out M3-JSN-out' . $json, 'X', 'M3-Res-out'); + return response()->json(['code' => '405', 'status' => 'error', 'message' => 'Curl Error: Communication with M3 Timed Out.']); + } + $this->log($context, 'An Error Occured - ' . substr((string) $throwable, 0, 300), 'X', 'M3-Err-out'); + Log::error($throwable); + return response()->json(['code' => '405', 'status' => 'error', 'message' => 'Uncaught Error']); + } + + private function errorResponse(string $code, string $message) + { + return response()->json(['code' => $code, 'status' => 'Error', 'message' => $message]); + } }