R659PALT ?? abort(404, 'Manifest Not Found'); $userWhsCoPlant = self::getUserWhsCoPlant(); $boxes = DB::connection(config('m3.connection', 'pgsql'))->table(self::PALLET_TABLE_ALIAS) ->select( 'p.R659PALT', 'p.R659BOX', 'p.R659LOADED', 'p.R659USER', 'p.R659DATE', 'p.R659TIME', 'c.AYMACPKR', 'c.AYSPR15A01', 'cv.A4APR8N001', 'cv.A4SHSHCT', self::CONVEYOR_SELECT, ) ->leftJoin(self::CARTON_TABLE_ALIAS, 'p.R659BOX', '=', 'c.AYINTBOX') ->leftJoin(self::CONVEYOR_VALUE_ALIAS, 'c.AYMACPKR', '=', 'cv.A4MACPKR') ->leftJoin(self::CONVEYOR_TABLE_ALIAS, 'cv.A4APR8N001', '=', 'cnv.R652SEQ') ->where('p.R659PALT', $r659PALT) ->where('p.R659CO', trim($userWhsCoPlant['USERCO'])) ->where('p.R659WHS', trim($userWhsCoPlant['USERWHS'])) ->where('p.R659PLANT', trim($userWhsCoPlant['USERPL'])) ->orderBy('p.R659DATE', 'desc') ->orderBy('p.R659TIME', 'desc') ->distinct() ->get() ->unique('R659BOX') ->values(); if ($request->ajax()) { return response()->json([ 'success' => true, 'data' => $boxes, ]); } $palletHeader = $boxes->first(); return view('m3::liberty-theme.pages.BoxPackToPalletScan', ['boxes' => $boxes, 'palletHeader' => $palletHeader, 'R659PALT' => $r659PALT]); } // Scan Boxes public static function scanBoxes(Request $request) { $pallet = $request->R659PALT ?? abort(400, 'Pallet Not Found'); $box = trim((string) ($request->R659BOX ?? '')); abort_if($box === '', 400, 'Box Not Found'); $user = m3User() !== '' ? Str::upper(m3User()) : 'WebUser'; $profile = self::getUserWhsCoPlant(); $validation = self::validateScannedBox($pallet, $box, $profile); if ($validation !== '') { return response()->json(['success' => false, 'message' => $validation], 409); } self::insertScannedBox($pallet, $box, $user, $profile); return response()->json([ 'success' => true, 'message' => "• Box {$box} added to Pallet {$pallet}.", 'data' => self::boxesForPallet($pallet, $profile), ]); } private static function validateScannedBox($pallet, string $box, array $profile): string { $messages = []; $existing = self::findExistingBox($pallet, $box, $profile); if ($existing) { $messages[] = "• Box {$box} is already assigned to Pallet {$existing->R659PALT}."; } $boxRecord = self::findCarton($box, $profile); if (! isset($boxRecord->AYINTBOX)) { $messages[] = "• Box {$box} does not exist in ICM695M1 or it belongs to another Company."; } elseif (($boxRecord->AYTYPE ?? '') !== 'BX') { $messages[] = "• Scanned barcode {$box} is not a Box."; } elseif (! $existing) { $messages = array_merge($messages, self::palletCompatibilityMessages($pallet, $box, $boxRecord, $profile)); } return implode('
', $messages); } private static function findExistingBox($pallet, string $box, array $profile): ?object { return DB::connection(config('m3.connection', 'pgsql'))->table('icm659m') ->select('R659PALT')->where('R659PALT', $pallet)->where('R659BOX', $box) ->where('R659CO', trim($profile['USERCO']))->where('R659WHS', trim($profile['USERWHS'])) ->where('R659PLANT', trim($profile['USERPL']))->first(); } private static function findCarton(string $box, array $profile): ?object { return DB::connection(config('m3.connection', 'pgsql'))->table(self::CARTON_TABLE_ALIAS) ->select('c.AYINTBOX', 'c.AYSPR15A01', 'c.AYTYPE', 'c.AYMACPKR', 'cv.A4APR8N001', self::CONVEYOR_SELECT) ->leftJoin(self::CONVEYOR_VALUE_ALIAS, 'c.AYMACPKR', '=', 'cv.A4MACPKR') ->leftJoin(self::CONVEYOR_TABLE_ALIAS, 'cv.A4APR8N001', '=', 'cnv.R652SEQ') ->where('c.AYINTBOX', $box)->where('c.AYCO', trim($profile['USERCO'])) ->where('c.AYWHS', trim($profile['USERWHS']))->where('c.AYPLANT', trim($profile['USERPL']))->first(); } private static function palletCompatibilityMessages($pallet, string $box, object $incoming, array $profile): array { $first = DB::connection(config('m3.connection', 'pgsql'))->table(self::PALLET_TABLE_ALIAS) ->select('c.AYSPR15A01', self::CONVEYOR_SELECT) ->leftJoin(self::CARTON_TABLE_ALIAS, 'p.R659BOX', '=', 'c.AYINTBOX') ->leftJoin(self::CONVEYOR_VALUE_ALIAS, 'c.AYMACPKR', '=', 'cv.A4MACPKR') ->leftJoin(self::CONVEYOR_TABLE_ALIAS, 'cv.A4APR8N001', '=', 'cnv.R652SEQ') ->where('p.R659PALT', $pallet)->where('p.R659CO', trim($profile['USERCO'])) ->where('p.R659WHS', trim($profile['USERWHS']))->where('p.R659PLANT', trim($profile['USERPL']))->first(); if (! $first) { return []; } $messages = []; $incomingCarrier = trim($incoming->AYSPR15A01 ?? ''); $incomingConveyor = trim($incoming->CONVEYOR_NAME ?? ''); $palletCarrier = trim($first->AYSPR15A01 ?? ''); $palletConveyor = trim($first->CONVEYOR_NAME ?? ''); if ($incomingCarrier !== $palletCarrier) { $messages[] = "• Box {$box} has a different Carrier ({$incomingCarrier}) than the boxes already on Pallet {$pallet} ({$palletCarrier})."; } if ($incomingConveyor !== $palletConveyor) { $messages[] = "• Box {$box} has a different Conveyor ({$incomingConveyor}) than the boxes already on Pallet {$pallet} ({$palletConveyor})."; } return $messages; } private static function insertScannedBox($pallet, string $box, string $user, array $profile): void { DB::connection(config('m3.connection', 'pgsql'))->table('icm659m')->insert([ 'R659PALT' => $pallet, 'R659BOX' => $box, 'R659LOADED' => '', 'R659USER' => $user, 'R659DATE' => date('Y-m-d'), 'R659TIME' => date('H:i:s'), 'R659CO' => trim($profile['USERCO']), 'R659WHS' => trim($profile['USERWHS']), 'R659PLANT' => trim($profile['USERPL']), ]); } private static function boxesForPallet($pallet, array $profile) { return DB::connection(config('m3.connection', 'pgsql'))->table(self::PALLET_TABLE_ALIAS) ->select( 'p.R659PALT', 'p.R659BOX', 'p.R659LOADED', 'p.R659USER', 'p.R659DATE', 'p.R659TIME', 'c.AYMACPKR', 'c.AYSPR15A01', 'cv.A4APR8N001', 'cv.A4SHSHCT', self::CONVEYOR_SELECT, ) ->leftJoin(self::CARTON_TABLE_ALIAS, 'p.R659BOX', '=', 'c.AYINTBOX') ->leftJoin(self::CONVEYOR_VALUE_ALIAS, 'c.AYMACPKR', '=', 'cv.A4MACPKR') ->leftJoin(self::CONVEYOR_TABLE_ALIAS, 'cv.A4APR8N001', '=', 'cnv.R652SEQ') ->where('p.R659PALT', $pallet)->where('p.R659CO', trim($profile['USERCO'])) ->where('p.R659WHS', trim($profile['USERWHS']))->where('p.R659PLANT', trim($profile['USERPL'])) ->orderBy('p.R659DATE', 'desc')->orderBy('p.R659TIME', 'desc')->distinct()->get()->unique('R659BOX')->values(); } // Delete Box public static function deleteBox(Request $request) { $r659PALT = $request->R659PALT ?? abort(400, 'Pallet Not Found'); $r659BOX = trim($request->R659BOX) ?? abort(400, 'Box Not Found'); $userWhsCoPlant = self::getUserWhsCoPlant(); // Guard: only allow delete if R659LOADED is empty $record = DB::connection(config('m3.connection', 'pgsql')) ->table('icm659m') ->where('R659PALT', $r659PALT) ->where('R659BOX', $r659BOX) ->first(); if (! $record) { return response()->json([ 'success' => false, 'message' => "Box {$r659BOX} not found on Pallet {$r659PALT}.", ], 404); } if (! empty(trim($record->R659LOADED))) { return response()->json([ 'success' => false, 'message' => "Box {$r659BOX} is already loaded and cannot be removed.", ], 403); } DB::connection(config('m3.connection', 'pgsql')) ->table('icm659m') ->where('R659PALT', $r659PALT) ->where('R659BOX', $r659BOX) ->delete(); // Return refreshed list $boxes = DB::connection(config('m3.connection', 'pgsql'))->table(self::PALLET_TABLE_ALIAS) ->select( 'p.R659PALT', 'p.R659BOX', 'p.R659LOADED', 'p.R659USER', 'p.R659DATE', 'p.R659TIME', 'c.AYMACPKR', 'c.AYSPR15A01', 'cv.A4APR8N001', 'cv.A4SHSHCT', self::CONVEYOR_SELECT, ) ->leftJoin(self::CARTON_TABLE_ALIAS, 'p.R659BOX', '=', 'c.AYINTBOX') ->leftJoin(self::CONVEYOR_VALUE_ALIAS, 'c.AYMACPKR', '=', 'cv.A4MACPKR') ->leftJoin(self::CONVEYOR_TABLE_ALIAS, 'cv.A4APR8N001', '=', 'cnv.R652SEQ') ->where('p.R659PALT', $r659PALT) ->where('p.R659CO', trim($userWhsCoPlant['USERCO'])) ->where('p.R659WHS', trim($userWhsCoPlant['USERWHS'])) ->where('p.R659PLANT', trim($userWhsCoPlant['USERPL'])) ->orderBy('p.R659DATE', 'desc') ->orderBy('p.R659TIME', 'desc') ->distinct() ->get() ->unique('R659BOX') ->values(); return response()->json([ 'success' => true, 'message' => "Box {$r659BOX} removed from Pallet {$r659PALT}.", 'data' => $boxes, ]); } // Get Logged User CO/WHS/PLANT public static function getUserWhsCoPlant() { $sHUSER = m3User() !== '' ? Str::upper(trim(m3User())) : ''; // Get users from ICM428M $iCM428M = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m') ->select('R428US', 'R428CO', 'R428WH', 'R428PL') ->where('R428US', '=', $sHUSER) ->first(); $r428US = isset($iCM428M->R428US) ? $iCM428M->R428US : ''; $uSERCO = isset($iCM428M->R428CO) ? $iCM428M->R428CO : ''; $uSERWH = isset($iCM428M->R428WH) ? $iCM428M->R428WH : ''; $r428PL = isset($iCM428M->R428PL) ? $iCM428M->R428PL : ''; return [ 'R428US' => $r428US, 'USERCO' => $uSERCO, 'USERWHS' => $uSERWH, 'USERPL' => $r428PL, ]; } }