context = $this->makeContext(); } public function handle() { try { return $this->process(); } catch (Throwable $throwable) { return $this->exceptionResponse($throwable); } } private function process() { if ($this->context['params'] === []) { $this->log('M3-Res-out', 'No URL Parameters Sent', 'X'); return response()->json([ 'code' => '405', 'status' => 'Error', 'message' => 'No URL Parameters Sent', ]); } $this->logInitialRequest(); $tokenResult = $this->receiveToken(); if ($tokenResult['response'] !== null) { return $tokenResult['response']; } $shipments = $this->loadShipments(); $shipments = $this->removeAlreadyClosed($shipments); $freightTerms = DB::connection(config('m3.connection', 'pgsql'))->table('icm321m') ->selectRaw('TRIM(ARCODE) as FREIGHTTERMS,ARCHARGE as BILLABLE') ->get(); return $this->dispatchShipments($shipments, $freightTerms, $tokenResult['token']); } private function makeContext(): array { $params = $this->request->all(); $manifest = (string) ($params['MANIFEST'] ?? ''); $transType = (string) ($params['TRANSTYPE'] ?? 'M'); return [ 'params' => $params, 'whs' => (string) ($params['WHS'] ?? ''), 'company' => (string) ($params['COMPANY'] ?? ''), 'manifest' => $manifest, 'transType' => $transType !== '' ? $transType : 'M', 'shdt' => (string) ($params['SHDT'] ?? ''), 'shtime' => (string) ($params['SHTIME'] ?? ''), 'shtype' => (string) ($params['SHTYPE'] ?? ''), 'user' => m3_user() !== '' ? Str::upper(m3_user()) : 'WebUser', 'delivery' => $manifest !== '' ? $manifest : self::ZERO_PAD, 'jsonIn' => '', ]; } private function logInitialRequest(): void { $this->context['jsonIn'] = json_encode([ 'WHS' => $this->context['whs'], 'COMPANY' => $this->context['company'], 'MANIFEST-MACPKR' => $this->context['manifest'], 'TRANSTYPE' => $this->context['transType'], ]); $this->log('M3-Req-out', $this->context['jsonIn']); } private function receiveToken(): array { $response = Helper::checkReceiveTokenV2(); $data = $response->getData(); if ((string) ($data->code ?? '') === '200') { return ['token' => (string) ($data->token ?? ''), 'response' => null]; } $this->log('M3-Res-out', (string) ($data->message ?? ''), 'X'); return ['token' => '', 'response' => $response]; } private function loadShipments() { $type = $this->context['transType']; if (! in_array($type, ['M', 'P', 'Z'], true)) { return collect(); } if ($type === 'P') { $this->acknowledgeRetry(); } $query = $type === 'Z' ? $this->zeroPickQuery() : $this->standardShipmentQuery($type); return $query->get(); } private function standardShipmentQuery(string $type) { $query = DB::connection(config('m3.connection', 'pgsql'))->table('icm695m1') ->select('AYCO', 'AYWHS', 'AYMACPKR', 'AYRLNO', 'AYAPRF1551') ->distinct() ->where('AYCO', $this->context['company']) ->where('AYWHS', $this->context['whs']) ->orderBy('AYMACPKR'); $field = $type === 'P' ? 'AYMACPKR' : 'AYAPRF1551'; return $query->where($field, $this->context['manifest']); } private function zeroPickQuery() { return DB::connection(config('m3.connection', 'pgsql'))->table('icm688m1') ->select()->distinct() ->where('A4CO', $this->context['company']) ->where('A4WHS', $this->context['whs']) ->where('A4MACPKR', $this->context['manifest']) ->orderBy('A4MACPKR'); } private function acknowledgeRetry(): void { if ($this->context['shdt'] !== '' && $this->context['shtime'] !== '' && $this->context['shtype'] !== '') { DB::connection(config('m3.connection', 'pgsql'))->table('icm699m') ->where('SHMACPKR', $this->context['manifest']) ->where('SHDT', $this->context['shdt'])->where('SHTIME', $this->context['shtime']) ->where('SHCO', $this->context['company'])->where('SHWHS', $this->context['whs']) ->where('SHSOURCE', self::SOURCE)->where('SHERROR', 'X') ->where('SHTYPE', $this->context['shtype']) ->update($this->acknowledgementValues()); } $this->context['lineAck'] = $this->acknowledgedLines(); } private function acknowledgedLines(): array { $rows = DB::connection(config('m3.connection', 'pgsql'))->table('icm699m') ->where('SHMACPKR', $this->context['manifest']) ->where('SHCO', $this->context['company'])->where('SHWHS', $this->context['whs']) ->where('SHSOURCE', 'PackSyst4tray')->where('SHERROR', 'Z')->where('SHTYPE', 'M3-QtyChg') ->get(); return $rows->map(fn ($row) => Helper::getSubstringBetween($row->SHDATA, 'PickerLine:', ' -'))->all(); } private function removeAlreadyClosed($shipments) { $field = $this->context['transType'] === 'Z' ? 'A4MACPKR' : 'AYMACPKR'; $deliveryNumbers = $shipments->map(fn ($row) => trim($row->{$field}))->all(); if ($deliveryNumbers === []) { return $shipments; } $closed = DB::connection(config('m3.connection', 'pgsql'))->table('icm699m') ->whereIn('SHMACPKR', $deliveryNumbers) ->where('SHCO', $this->context['company'])->where('SHWHS', $this->context['whs']) ->where('SHSOURCE', self::SOURCE)->where('SHERROR', '') ->where('SHTYPE', 'M3-Res-out')->where('SHDATA', 'like', '%Success%') ->pluck('SHMACPKR')->all(); return $shipments->reject(fn ($row) => in_array($row->{$field}, $closed)); } private function dispatchShipments($shipments, $freightTerms, string $token) { if ($shipments->isEmpty()) { return $this->noRecordsResponse(); } if ($this->context['transType'] === 'Z') { return (new CloseShipmentZeroPickProcessor($this->context, $token))->process($shipments); } return (new CloseShipmentStandardProcessor($this->context, $token, $freightTerms))->process($shipments); } private function noRecordsResponse() { $delivery = $this->context['manifest'] !== '' ? $this->context['manifest'] : self::ZERO_PAD; $this->context['delivery'] = $delivery; $message = 'No records found in ICM695M1,or URL parameters incomplete'; $this->log('M3-Req-out', $message, 'X'); return response()->json([ 'code' => '405', 'status' => 'Error', 'message' => $message . ' For MacPkr/Manifest:' . $delivery, ]); } private function exceptionResponse(Throwable $throwable) { $isCurlError = str_contains($throwable->getMessage(), 'cURL error'); $message = $isCurlError ? 'Curl Error: Communication with M3 Timed Out' : 'An Error Occured - ' . substr((string) $throwable, 0, 300); $this->log('M3-Res-out', $message . ($isCurlError ? ' M3-JSN-out' . $this->context['jsonIn'] : ''), 'X'); if (! $isCurlError) { Log::error($throwable); } return response()->json([ 'code' => '405', 'status' => 'error', 'message' => $isCurlError ? $message . '.' : 'Catched Error: ' . $throwable, ]); } private function log(string $type, string $message, string $error = ''): void { Helper::logToICM699M([ 'SHMACPKR' => $this->context['delivery'], 'SHDT' => date('Y-m-d'), 'SHTIME' => date('H:i:s'), 'SHERROR' => $error, 'SHINTBOX' => '', 'SHTYPE' => $type, 'SHDATA' => $message, 'SHUSER' => $this->context['user'], 'SHSOURCE' => self::SOURCE, 'SHCO' => $this->context['company'], 'SHWHS' => $this->context['whs'], ]); } private function acknowledgementValues(): array { return [ 'SHERROR' => 'Z', 'SHACKUSER' => $this->context['user'], 'SHACKDATE' => date('Y-m-d'), 'SHACKTIME' => date('H:i:s'), ]; } }