307 lines
16 KiB
PHP
307 lines
16 KiB
PHP
<?php
|
|
|
|
namespace Modules\M3\Http\Controllers\API;
|
|
|
|
use Config;
|
|
use DB;
|
|
use Illuminate\Http\Request;
|
|
use Modules\M3\Helpers\Helper;
|
|
use Modules\M3\Http\Controllers\Controller;
|
|
use Modules\M3\Services\PostgresProgramBridge;
|
|
use Str;
|
|
|
|
class M3Controller extends Controller
|
|
{
|
|
private const FIELD_PREFIX = 'Field: ';
|
|
private const M3_LIST_SUFFIX = ' M3-Lis-JSN';
|
|
|
|
public function insertToICM666M2($dataSplit, $commentData)
|
|
{
|
|
$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() {}
|
|
|
|
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'));
|
|
}
|
|
|
|
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',
|
|
];
|
|
}
|
|
|
|
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'],
|
|
'PickerNumber' => ['A1DELNO', 11, 'integer'],
|
|
'OrderNumber' => ['A1ONO', 10, 'string'],
|
|
'ReleaseNumber' => ['A1RLNO', 3, 'string'], // Pick list suffix in ICM666M
|
|
'ShipmentNumber' => ['A1SHNO', 7, 'string'],
|
|
'OrderLine' => ['A1PKLN', 6, 'integer'],
|
|
'PartNumber' => ['A1PART', 15, 'string'],
|
|
'Description' => ['A1PARTDES', 120, 'string'],
|
|
'Quantity' => ['A1RSVQTY', 22, 'DEC'],
|
|
'BaseUnitPrice' => ['A1SLUNPR', 22, 'DEC'],
|
|
'Currency' => ['A1SHCURR', 3, 'string'],
|
|
'Zone' => ['A1LVZONE', 2, 'string'],
|
|
'PromDate' => ['A1PROMDTE', 8, 'integer'],
|
|
'RouteCode' => ['A1SHSRT', 6, 'string'],
|
|
'BillToId' => ['A1BILLTO', 10, 'string'],
|
|
'ShipToId' => ['A1SHIPTO', 10, 'string'],
|
|
'CompanyName' => ['A1SHSHNM', 36, 'string'],
|
|
'Address1' => ['A1SHSHA1', 36, 'string'],
|
|
'Address2' => ['A1SHSHA2', 36, 'string'],
|
|
'Address3' => ['A1SHSHA3', 36, 'string'],
|
|
'Address4' => ['A1SHSHA4', 36, 'string'],
|
|
'City' => ['A1SHSHCI', 20, 'string'],
|
|
'State' => ['A1SHSHST', 2, 'string'],
|
|
'PostalCode' => ['A1SHSHZP', 10, 'string'],
|
|
'Country' => ['A1SHSHCT', 3, 'string'],
|
|
'CountryName' => ['A1SHP2CNTY', 40, 'string'],
|
|
'PartWeight' => ['A1PRTWGT', 15, 'integer'],
|
|
'SellUOM' => ['A1SLUOM', 3, 'string'],
|
|
'PartConv' => ['A1PARTCONV', 25, 'DEC'],
|
|
'CarrierCode' => ['A1CARRIER', 6, 'string'],
|
|
'ShipVia' => ['A1SHPVIA', 3, 'string'],
|
|
'PrimaryLocation' => ['A1PRIMLOC', 10, 'string'],
|
|
'Allocation' => ['A1SPR10A01', 10, 'string'],
|
|
'AllocatedTo' => ['A1SPR15A01', 10, 'string'],
|
|
'LocationSeq' => ['A1LOCSEQ', 10, 'string'],
|
|
'UOM' => ['A1UOM', 3, 'string'],
|
|
'HazMat' => ['A1MATWRN', 4, 'string'],
|
|
'PartUPC' => ['A1UPC', 30, 'string'],
|
|
'PartEAN' => ['A1EAN', 30, 'string'],
|
|
'LotFlag' => ['A1IZLCF', 1, 'string'],
|
|
'ManOrd' => ['A1MONUM', 30, 'string'],
|
|
'LotNumber' => ['A1LOTNUM', 30, 'string'],
|
|
'ProductArea' => ['A1LVUSD1', 15, 'string'],
|
|
'FreightClass' => ['A1WBFRCT', 10, 'string'],
|
|
'ShipmentPONumber' => ['A1SOPONO', 20, 'string'],
|
|
'ShipmentPOLine' => ['A1SOPOLN', 7, 'integer'],
|
|
'ShipTerms' => ['A1OFSTRM', 3, 'string'],
|
|
// 'ExchangeRate' =>[ 'A1EXGRATE', 18,'DEC'],
|
|
'OrderClass' => ['A1SHORCL', 3, 'string'],
|
|
'LocationType' => ['A1LVUSD2', 2, 'string'],
|
|
'PallSize' => ['A1LVUSD3', 10, 'string'],
|
|
'MasterCarton' => ['A1USRLD1', 30, 'string'],
|
|
'MasterQty' => ['A1WBSHQY', 25, 'DEC'],
|
|
'InnerQty' => ['A1WBPKQY', 25, 'DEC'],
|
|
'PalletQty' => ['A1USRN01', 24, 'DEC'],
|
|
'CartonQty' => ['A1USRN31', 25, 'DEC'],
|
|
'PersonName' => ['A1PERNAME', 30, 'string'],
|
|
'AccountNo' => ['A1ACCNUM', 20, 'string'],
|
|
'Email' => ['A1EMAIL', 100, 'string'],
|
|
'OrderCategory' => ['A1REFORD', 1, 'string'],
|
|
'A1DATEADD' => ['A1DATEADD', 12, 'string'],
|
|
'A1TIMEADD' => ['A1TIMEADD', 12, 'string'],
|
|
'KitPartNumber' => ['A1KITPART', 15, 'string'],
|
|
'OrderLineSuffix' => ['A1PKSFX', 6, 'DEC'],
|
|
'CustomerPartNumber' => ['A1CUSTPART', 20, 'string'],
|
|
'GS1Label' => ['A1SPR1A01', 1, 'string'],
|
|
'CurrencyExchangeRate' => ['A1EXGRATE', 18, 'DEC'],
|
|
|
|
]; }
|
|
|
|
public function show($id) {}
|
|
public function edit($id) {}
|
|
public function update(Request $request, $id) {}
|
|
public function destroy($id) {}
|
|
}
|