208 lines
8.5 KiB
PHP
208 lines
8.5 KiB
PHP
<?php
|
|
|
|
namespace Modules\M3\Http\Controllers\API;
|
|
|
|
use Config;
|
|
use DB;
|
|
use Http;
|
|
use Log;
|
|
use Modules\M3\Helpers\Helper;
|
|
|
|
final class CloseShipmentStandardProcessor
|
|
{
|
|
private const SOURCE = 'CloseShipmentCoChargeAPI';
|
|
private const JSON_CONTENT_TYPE = 'application/json';
|
|
private const NULL_M3_RESPONSE = 'M3 API responded with null value';
|
|
|
|
public function __construct(
|
|
private array $context,
|
|
private readonly string $token,
|
|
private readonly mixed $freightTerms,
|
|
) {
|
|
}
|
|
|
|
public function process($shipments)
|
|
{
|
|
$allErrors = '';
|
|
$lastShipment = null;
|
|
foreach ($shipments as $shipment) {
|
|
$lastShipment = $this->shipmentContext($shipment);
|
|
$allErrors .= $this->processShipment($lastShipment);
|
|
}
|
|
|
|
if ($lastShipment !== null) {
|
|
$this->closeFalsePositiveErrors($lastShipment);
|
|
}
|
|
$this->markManifestProcessed();
|
|
|
|
return $this->resultResponse($allErrors);
|
|
}
|
|
|
|
private function shipmentContext(object $shipment): array
|
|
{
|
|
return [
|
|
'whs' => trim($shipment->AYWHS),
|
|
'company' => trim($shipment->AYCO),
|
|
'delivery' => trim($shipment->AYMACPKR),
|
|
'release' => trim($shipment->AYRLNO),
|
|
'manifest' => trim($shipment->AYAPRF1551),
|
|
];
|
|
}
|
|
|
|
private function processShipment(array $shipment): string
|
|
{
|
|
$endFlag = $this->shortPickEndFlag($shipment);
|
|
$trailer = $this->trailerContext($shipment);
|
|
$builder = new CloseShipmentPackageBuilder($this->context, $this->freightTerms);
|
|
$state = $builder->build($shipment, $trailer);
|
|
|
|
if ($state['packages'] === []) {
|
|
return $state['errors'];
|
|
}
|
|
|
|
$json = $builder->closeShipmentJson($shipment, $trailer, $state, $endFlag);
|
|
if ($state['errors'] !== '') {
|
|
$this->logValidationErrors($shipment, $state['errors']);
|
|
|
|
return $state['errors'];
|
|
}
|
|
|
|
return $this->sendCloseRequest($shipment, $json, $state['coCharge']);
|
|
}
|
|
|
|
private function shortPickEndFlag(array $shipment): int
|
|
{
|
|
$rows = DB::connection(config('m3.connection', 'pgsql'))->table('icm688m2')
|
|
->select('A5PART', 'A5PACKED', 'A5PICKED', 'A5PKLN', 'A5RSVQTY')->distinct()
|
|
->where('A5CO', $shipment['company'])->where('A5WHS', $shipment['whs'])
|
|
->where('A5MACPKR', $shipment['delivery'])->where('A5RLNO', $shipment['release'])
|
|
->orderBy('A5PART')->get();
|
|
|
|
foreach ($rows as $row) {
|
|
if ((int) ($row->A5RSVQTY ?? 0) - (int) ($row->A5PICKED ?? 0) > 0) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
private function trailerContext(array $shipment): array
|
|
{
|
|
$row = DB::connection(config('m3.connection', 'pgsql'))->table('icm705m1')
|
|
->select('APTRUCKID', 'APTRACKNO', 'APMANIFEST')
|
|
->where('APCO', $this->context['company'])->where('APMANIFEST', $shipment['manifest'])
|
|
->where('APWHS', $this->context['whs'])->first();
|
|
|
|
return [
|
|
'trailer' => isset($row->APTRUCKID) ? trim($row->APTRUCKID) : '',
|
|
'pro' => isset($row->APTRACKNO) ? trim($row->APTRACKNO) : '',
|
|
];
|
|
}
|
|
|
|
private function sendCloseRequest(array $shipment, string $json, array $coCharge): string
|
|
{
|
|
Log::channel('dailyCron')->info('1 >>> JSON Sent for Manifest: ' . (string) (int) $shipment['manifest'] . ' ,Macpicker: ' . $shipment['delivery']);
|
|
$this->log($shipment, 'M3-JSN-out', $json);
|
|
$response = Http::withHeaders(['accept' => self::JSON_CONTENT_TYPE, 'Content-Type' => self::JSON_CONTENT_TYPE, 'Connection' => 'close'])
|
|
->withToken($this->token)->withBody($json, self::JSON_CONTENT_TYPE)
|
|
->timeout(Config::get('arrays.curlTimeOut'))->retry(3, 100)
|
|
->post(env('ENDPOINTURL') . 'APIFLOWS/Sentinel/TransferAPI?ionapiRespStyle=sync');
|
|
Log::channel('dailyCron')->info('2 >>> Close API M3 Responded...');
|
|
$result = $this->parseM3Response($response, $shipment, $coCharge !== []);
|
|
|
|
if ($result['success']) {
|
|
$this->log($shipment, 'M3-Res-out', 'Success...' . json_encode($result['responseResult']) . $result['session']);
|
|
|
|
return '';
|
|
}
|
|
|
|
$this->markShipmentFailed($shipment);
|
|
$this->log($shipment, 'M3-Res-out', 'Important-Error: ' . $result['errors'] . json_encode($result['message']) . $result['session'], 'X');
|
|
|
|
return $result['errors'] . ' ';
|
|
}
|
|
|
|
private function parseM3Response($response, array $shipment, bool $hasCoCharge): array
|
|
{
|
|
$status = $response->getStatusCode();
|
|
$session = $response->hasHeader('x-transaction-id') ? '-sessionID:' . $response->header('x-transaction-id') : '-sessionID';
|
|
$contents = json_decode(Helper::sanityzeString($response->getBody()->getContents()));
|
|
if ($contents === null || (string) $status !== '200') {
|
|
return ['success' => false, 'message' => self::NULL_M3_RESPONSE, 'responseResult' => '', 'errors' => $status, 'session' => $session];
|
|
}
|
|
|
|
$message = $contents->result->CloseShipment;
|
|
$apiResult = $message->PickingListClose->Result;
|
|
$responseResult = $contents->result;
|
|
$errors = Helper::checkM3Errors($responseResult);
|
|
if ($apiResult !== 'Error') {
|
|
$this->markShipmentSuccessful($shipment, $hasCoCharge);
|
|
}
|
|
|
|
return ['success' => $apiResult !== 'Error', 'message' => $message, 'responseResult' => $responseResult, 'errors' => $errors, 'session' => $session];
|
|
}
|
|
|
|
private function markShipmentSuccessful(array $shipment, bool $hasCoCharge): void
|
|
{
|
|
$values = $hasCoCharge ? ['A4RATEM3' => 'X', 'A4PICKSTS' => 'A'] : ['A4PICKSTS' => 'A'];
|
|
DB::connection(config('m3.connection', 'pgsql'))->table('icm688m1')
|
|
->where('A4MACPKR', $shipment['delivery'])->where('A4CO', $shipment['company'])
|
|
->where('A4WHS', $shipment['whs'])->update($values);
|
|
}
|
|
|
|
private function markShipmentFailed(array $shipment): void
|
|
{
|
|
DB::connection(config('m3.connection', 'pgsql'))->table('icm688m1')
|
|
->where('A4MACPKR', $shipment['delivery'])->where('A4CO', $shipment['company'])
|
|
->where('A4WHS', $shipment['whs'])->update(['A4PICKSTS' => 'a']);
|
|
}
|
|
|
|
private function logValidationErrors(array $shipment, string $errors): void
|
|
{
|
|
$this->log($shipment, 'M3-Res-out', Helper::removeDuplicateSubstrings($errors), 'X');
|
|
}
|
|
|
|
private function closeFalsePositiveErrors(array $shipment): void
|
|
{
|
|
DB::connection(config('m3.connection', 'pgsql'))->table('icm699m')
|
|
->where('SHMACPKR', $shipment['delivery'])->where('SHCO', $this->context['company'])
|
|
->where('SHWHS', $this->context['whs'])->where('SHSOURCE', self::SOURCE)->where('SHERROR', 'X')
|
|
->where('SHTYPE', 'M3-General')->where('SHDATA', 'like', '%CommTCP_read%')
|
|
->update(['SHERROR' => 'Z', 'SHACKUSER' => $this->context['user'], 'SHACKDATE' => date('Y-m-d'),
|
|
'SHACKTIME' => date('H:i:s'), 'SHACKNOTE' => 'Sentinel automatically closed the error (false positive CommTCP_read)']);
|
|
}
|
|
|
|
private function markManifestProcessed(): void
|
|
{
|
|
if ($this->context['transType'] !== 'M') {
|
|
return;
|
|
}
|
|
DB::connection(config('m3.connection', 'pgsql'))->table('icm705m1')
|
|
->where('APMANIFEST', $this->context['manifest'])->where('APCO', $this->context['company'])
|
|
->where('APWHS', $this->context['whs'])->update(['APSPARE2' => 'X']);
|
|
}
|
|
|
|
private function resultResponse(string $errors)
|
|
{
|
|
if ($errors === '') {
|
|
return response()->json(['code' => '200', 'status' => 'Success', 'message' => 'All Operations Successful']);
|
|
}
|
|
|
|
return response()->json([
|
|
'code' => '206', 'status' => 'Success With Warnings',
|
|
'message' => Helper::removeDuplicateSubstrings($errors) . '; Check Transaction Logs for Errors or Warnings.',
|
|
]);
|
|
}
|
|
|
|
private function log(array $shipment, string $type, string $message, string $error = ''): void
|
|
{
|
|
Helper::logToICM699M([
|
|
'SHMACPKR' => $shipment['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'],
|
|
]);
|
|
}
|
|
}
|