| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068 |
- <?php
- namespace App\Http\Controllers;
- use Illuminate\Http\Request;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Validator;
- use Illuminate\Support\Carbon;
- use PhpOffice\PhpSpreadsheet\Spreadsheet;
- use PhpOffice\PhpSpreadsheet\IOFactory;
- use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
- class TemplatesManagementController extends Controller {
- private $responseController;
- private $encryptionController;
- private $functionsController;
- private $resourcesController;
- private $documentManagementController;
- private $templatesUbic;
- public function __construct(){
- $this->responseController = new ResponseController();
- $this->encryptionController = new EncryptionController();
- $this->functionsController = new FunctionsController();
- $this->resourcesController = new ResourcesController();
- $this->documentManagementController = new DocumentManagementController();
- $this->templatesUbic = app_path('Http/Controllers');
- }
- /**
- * Validar y procesar plantilla Excel de equipamientos
- * Recibe el ID del archivo temporal ya cargado
- */
- public function validateAndProcessExcelTemplate(Request $request) {
- DB::enableQueryLog();
-
- $validator = Validator::make($request->all(), [
- 'id_user' => 'required|string',
- 'id_file' => 'required|string',
- 'linea' => 'required|integer',
- ]);
- if($validator->fails()){
- return $this->responseController->makeResponse(
- true,
- "Se encontraron uno o más errores.",
- $this->responseController->makeErrors($validator->errors()->messages()),
- 401
- );
- }
- $form = $request->all();
- $idUser = '0000000001';
-
- if(!$idUser){
- return $this->responseController->makeResponse(true, "El id del usuario no fue desencriptado correctamente", [], 400);
- }
- $usr = DB::table('S002V01TUSUA')->where([
- ['USUA_IDUS', '=', $idUser],
- ['USUA_NULI', '=', $form['linea']]
- ])->first();
- if(is_null($usr)){
- return $this->responseController->makeResponse(true, 'El usuario no está registrado', [], 404);
- }
- // Obtener archivo temporal
- $fileIdDecrypted = $this->encryptionController->decrypt($form['id_file']);
- $tempFile = DB::table('S002V01TARTE')->where([
- ['ARTE_IDAR', '=', $fileIdDecrypted],
- ['ARTE_NULI', '=', $form['linea']]
- ])->first();
-
- if(is_null($tempFile)){
- return $this->responseController->makeResponse(true, 'El archivo temporal no fue encontrado', [], 404);
- }
- try {
- // Validar estructura del Excel
- $structureValidation = $this->validateExcelStructure($tempFile->ARTE_UBTE);
- if(!$structureValidation['valid']) {
- return $this->responseController->makeResponse(true, $structureValidation['message'], [], 400);
- }
- // Procesar contenido del Excel
- $spreadsheet = IOFactory::load($tempFile->ARTE_UBTE);
- $config = ExcelTemplateConfig::getTemplateConfigs()['TPCEQ'];
- $acronymMappings = $this->extractAcronymMappings($spreadsheet);
- $cargaMap = $acronymMappings['carga'];
- $lruMap = $acronymMappings['lru'];
- $sheetsToProcess = [
- 'CASO 1', 'CASO 2', 'CASO 3',
- 'CASO 4', 'CASO 5', 'CASO 6'
- ];
- $processedData = [];
- $errors = [];
- $successCount = 0;
-
- DB::beginTransaction();
-
- foreach($sheetsToProcess as $sheetName) {
- // Verificar si la hoja existe en el documento
- if(!in_array($sheetName, $spreadsheet->getSheetNames())) {
- $errors[] = "Hoja requerida no encontrada: $sheetName";
- continue;
- }
-
- // Obtener configuración de la hoja
- $sheetConfig = $config['worksheets'][$sheetName] ?? null;
- if(!$sheetConfig) {
- $errors[] = "Configuración no encontrada para hoja: $sheetName";
- continue;
- }
- $worksheet = $spreadsheet->getSheetByName($sheetName);
- $result = $this->processWorksheet(
- $worksheet,
- $sheetConfig,
- $sheetName,
- $form['linea'],
- $idUser,
- $cargaMap, // Nuevo parámetro
- $lruMap // Nuevo parámetro
- );
-
- $worksheet = $spreadsheet->getSheetByName($sheetName);
- $result = $this->processWorksheet($worksheet, $sheetConfig, $sheetName, $form['linea'], $idUser, $cargaMap, $lruMap);
-
- $processedData = array_merge($processedData, $result['data']);
- $errors = array_merge($errors, $result['errors']);
- $successCount += $result['count'];
- }
-
- if(!empty($errors) && empty($processedData)) {
- DB::rollBack();
- return $this->responseController->makeResponse(true, "Errores en el procesamiento: " . implode('; ', array_slice($errors, 0, 5)), [], 400);
- }
-
- // Insertar datos procesados en la tabla temporal de equipamientos
- foreach($processedData as $data) {
- DB::table('S002V01TPCEQ')->insert($data);
- }
-
- DB::commit();
-
- // Registrar actividad
- $nowStr = Carbon::now('America/Mexico_city')->toDateTimeString();
- $name = $this->functionsController->joinName($usr->USUA_NOMB, $usr->USUA_APPA, $usr->USUA_APMA);
-
- $actions = DB::getQueryLog();
- $idac = $this->functionsController->registerActivity(
- $form['linea'],
- 'S002V01M07GEEQ',
- 'S002V01F01ADEQ',
- 'S002V01P11REEQ',
- 'Procesamiento',
- "El usuario $name (" . $usr->USUA_IDUS . ") procesó $successCount equipos desde el archivo {$tempFile->ARTE_NOAR}.",
- $idUser,
- $nowStr,
- );
-
- $this->functionsController->registerLog($actions, $idUser, $nowStr, $idac, $form['linea']);
-
- $responseData = [
- 'equipos_procesados' => $successCount,
- 'archivo' => $tempFile->ARTE_NOAR,
- 'id_archivo' => $form['id_file']
- ];
-
- if(!empty($errors)) {
- $responseData['advertencias'] = array_slice($errors, 0, 10);
- }
-
- return $this->responseController->makeResponse(false, "Procesamiento exitoso", $responseData);
-
- } catch(Exception $e) {
- DB::rollBack();
- return $this->responseController->makeResponse(true, "Error al procesar el archivo: " . $e->getMessage(), [], 500);
- }
- }
- private function extractAcronymMappings($spreadsheet) {
- $mappings = [
- 'carga' => [
- 'equipos' => [],
- 'modelos' => []
- ],
- 'lru' => [
- 'equipos' => [],
- 'modelos' => []
- ]
- ];
-
- // Normalizar nombres de hojas
- $sheetNames = array_map('strtolower', $spreadsheet->getSheetNames());
-
- // 1. Encontrar hoja CARGA DE EQUIPOS (case-insensitive)
- $cargaSheet = null;
- foreach ($spreadsheet->getAllSheets() as $sheet) {
- if (strtolower(trim($sheet->getTitle())) === 'equipamiento') {
- $cargaSheet = $sheet;
- break;
- }
- }
- // 2. Procesar hoja CARGA DE EQUIPOS si existe
- if ($cargaSheet) {
- $highestRow = $cargaSheet->getHighestRow();
- \Log::debug("Procesando CARGA DE EQUIPOS. Filas: $highestRow");
-
- for ($row = 9; $row <= $highestRow; $row++) {
- // Mapeo de equipos
- $acronym = $this->getCellValue($cargaSheet, 'D', $row);
- $type = $this->getCellValue($cargaSheet, 'C', $row);
-
- if (!empty($acronym) && !empty($type)) {
- $mappings['carga']['equipos'][$acronym] = $type;
- }
-
- // Mapeo de modelos
- $modelAcronym = $this->getCellValue($cargaSheet, 'F', $row);
- $modelFull = $this->getCellValue($cargaSheet, 'E', $row);
-
- if (!empty($modelAcronym) && !empty($modelFull)) {
- $mappings['carga']['modelos'][$modelAcronym] = $modelFull;
- }
- }
- \Log::debug('Mapeos CARGA modelos: ' . json_encode($mappings['carga']['modelos']));
- } else {
- \Log::warning('Hoja CARGA DE EQUIPOS no encontrada en el archivo');
- }
- // 3. Procesar hoja LRU (usando el mismo método robusto)
- $lruSheet = null;
- foreach ($spreadsheet->getAllSheets() as $sheet) {
- if (strtolower(trim($sheet->getTitle())) === 'lru') {
- $lruSheet = $sheet;
- break;
- }
- }
- if ($lruSheet) {
- $highestRow = $lruSheet->getHighestRow();
- for ($row = 9; $row <= $highestRow; $row++) {
- // Mapeo de equipos
- $acronym = $this->getCellValue($lruSheet, 'D', $row);
- $type = $this->getCellValue($lruSheet, 'C', $row);
- if (!empty($acronym) && !empty($type)) {
- $mappings['lru']['equipos'][$acronym] = $type;
- }
-
- // Mapeo de modelos
- $modelAcronym = $this->getCellValue($lruSheet, 'F', $row);
- $modelFull = $this->getCellValue($lruSheet, 'E', $row);
- if (!empty($modelAcronym) && !empty($modelFull)) {
- $mappings['lru']['modelos'][$modelAcronym] = $modelFull;
- }
- }
- }
- return $mappings;
- }
- // Nueva función para obtener valores de celda robusta
- private function getCellValue($worksheet, $column, $row) {
- try {
- $cell = $worksheet->getCell($column . $row);
-
-
- // Manejar cualquier tipo de dato
- return trim($cell->getFormattedValue());
- } catch (\Exception $e) {
- \Log::error("Error leyendo celda $column$row: " . $e->getMessage());
- return '';
- }
- }
- /**
- * Validar solo la estructura del Excel (sin procesar datos)
- */
- public function validateExcelStructureOnly(Request $request) {
- $validator = Validator::make($request->all(), [
- 'id_user' => 'required|string',
- 'id_file' => 'required|string',
- 'linea' => 'required|integer',
- ]);
- if($validator->fails()){
- return $this->responseController->makeResponse(
- true,
- "Se encontraron uno o más errores.",
- $this->responseController->makeErrors($validator->errors()->messages()),
- 401
- );
- }
- $form = $request->all();
- $idUser = $this->encryptionController->decrypt($form['id_user']);
-
- if(!$idUser){
- return $this->responseController->makeResponse(true, "El id del usuario no fue desencriptado correctamente", [], 400);
- }
- // Obtener archivo temporal
- $fileIdDecrypted = $this->encryptionController->decrypt($form['id_file']);
- $tempFile = DB::table('S002V01TARTE')->where([
- ['ARTE_IDAR', '=', $fileIdDecrypted],
- ['ARTE_NULI', '=', $form['linea']]
- ])->first();
-
- if(is_null($tempFile)){
- return $this->responseController->makeResponse(true, 'El archivo temporal no fue encontrado', [], 404);
- }
- // Validar solo la estructura
- $structureValidation = $this->validateExcelStructure($tempFile->ARTE_UBTE);
- if(!$structureValidation['valid']) {
- return $this->responseController->makeResponse(true, $structureValidation['message'], [], 400);
- }
- return $this->responseController->makeResponse(false, "Estructura del archivo válida", [
- 'archivo' => $tempFile->ARTE_NOAR,
- 'validado' => true
- ]);
- }
- private function validateExcelStructure($filePath) {
- try {
- $spreadsheet = IOFactory::load($filePath);
- $config = ExcelTemplateConfig::getTemplateConfigs()['TPCEQ'];
-
- $requiredSheets = array_keys($config['worksheets']);
- $existingSheets = $spreadsheet->getSheetNames();
-
- // Verificar que existan las hojas requeridas
- $missingSheets = array_diff($requiredSheets, $existingSheets);
- if(!empty($missingSheets)) {
- return [
- 'valid' => false,
- 'message' => 'Tu documento no cumple con las hojas requeridas de la plantilla'
- ];
- }
- // Validar headers de cada hoja
- foreach($config['worksheets'] as $sheetName => $sheetConfig) {
- if(!in_array($sheetName, $existingSheets)) continue;
-
- $worksheet = $spreadsheet->getSheetByName($sheetName);
- $headerValidation = $this->validateSheetHeaders($worksheet, $sheetConfig, $sheetName);
-
- if(!$headerValidation['valid']) {
- return [
- 'valid' => false,
- 'message' => 'Tu documento tiene error en los Headers, revísalos e intentalo de nuevo'
- ];
- }
- // Validar que tenga datos (solo para CARGA DE EQUIPOS)
- if($sheetName === 'CARGA DE EQUIPOS') {
- $dataValidation = $this->validateSheetHasData($worksheet, $sheetName, $sheetConfig);
- if(!$dataValidation['valid']) {
- return $dataValidation;
- }
- }
- }
- return ['valid' => true, 'message' => 'Estructura válida'];
-
- } catch(Exception $e) {
- return [
- 'valid' => false,
- 'message' => 'Error al validar la estructura del archivo: ' . $e->getMessage()
- ];
- }
- }
- private function validateSheetHeaders($worksheet, $sheetConfig, $sheetName) {
- // Para CATÁLOGOS usar validación especial
- if($sheetName === 'CATÁLOGOS') {
- return $this->validateCatalogosSheet($worksheet);
- }
-
- $headerRow = $sheetConfig['header_row'] ?? 4;
- $fieldMapping = $sheetConfig['field_mapping'];
-
- // Definir headers esperados según la configuración de Angular
- $expectedHeaders = $this->getExpectedHeaders($sheetName);
-
- if(empty($expectedHeaders)) {
- return ['valid' => true, 'message' => "No hay headers específicos para validar en $sheetName"];
- }
- foreach($expectedHeaders as $column => $expectedHeader) {
- $cellValue = $worksheet->getCell($column . $headerRow)->getCalculatedValue();
- $actualHeader = $cellValue ? trim((string)$cellValue) : '';
-
- if($actualHeader !== $expectedHeader) {
- return [
- 'valid' => false,
- 'message' => "Error en header de $sheetName, columna $column: esperado '$expectedHeader', encontrado '$actualHeader'"
- ];
- }
- }
-
- return ['valid' => true, 'message' => "Headers válidos para $sheetName"];
- }
- private function validateCatalogosSheet($worksheet) {
- $expectedHeaders = [
- 'B' => 'FAMILIA',
- 'C' => 'ACRÓNIMO',
- 'E' => 'SUBFAMILIA',
- 'F' => 'ACRÓNIMO',
- 'G' => 'SUBFAMILY',
- 'I' => 'UBICACIONES (FRENTES)',
- 'J' => 'CÓDIGO',
- 'L' => 'RMS',
- 'M' => 'ELEMENTO',
- 'N' => 'CÓDIGO',
- 'P' => 'OCUPACIÓN',
- 'Q' => 'CÓDIGO',
- 'S' => 'ESTADO',
- 'T' => 'ACRÓNIMO'
- ];
- foreach($expectedHeaders as $column => $expectedHeader) {
- $cellValue = $worksheet->getCell($column . '5')->getCalculatedValue();
- $actualHeader = $cellValue ? trim((string)$cellValue) : '';
-
- if($actualHeader !== $expectedHeader) {
- return [
- 'valid' => false,
- 'message' => "Error en CATÁLOGOS, fila 5, columna $column: esperado '$expectedHeader', encontrado '$actualHeader'"
- ];
- }
- }
- return ['valid' => true, 'message' => 'Headers válidos para CATÁLOGOS'];
- }
- private function validateSheetHasData($worksheet, $sheetName, $sheetConfig) {
- try {
- $range = $worksheet->calculateWorksheetDimension();
- $highestRow = $worksheet->getHighestRow();
-
- $dataStartRow = $sheetConfig['date_start_row'] ?? 9;
-
- if($highestRow < $dataStartRow) {
- return [
- 'valid' => false,
- 'message' => "La hoja '$sheetName' no contiene datos. Se requiere al menos un registro con información."
- ];
- }
- // Verificar que hay al menos una fila con datos
- $hasData = false;
- $mainColumns = ['B', 'D', 'F', 'G']; // Columnas principales para verificar
-
- for($row = $dataStartRow; $row <= $highestRow; $row++) {
- foreach($mainColumns as $col) {
- $cellValue = $worksheet->getCell($col . $row)->getCalculatedValue();
-
- if($cellValue !== null && $cellValue !== '' && trim((string)$cellValue) !== '') {
- $hasData = true;
- break 2;
- }
- }
- }
-
- if(!$hasData) {
- return [
- 'valid' => false,
- 'message' => "La hoja '$sheetName' no contiene datos. Se requiere al menos un registro con información."
- ];
- }
-
- return ['valid' => true, 'message' => 'Datos encontrados'];
-
- } catch(Exception $e) {
- return [
- 'valid' => false,
- 'message' => "Error al validar datos en '$sheetName': " . $e->getMessage()
- ];
- }
- }
- private function getExpectedHeaders($sheetName) {
- $headers = [
- 'CARGA DE EQUIPOS' => [
- 'B' => 'CÓDIGO EQUIVALENTE',
- 'C' => 'TIPO / DESCRIPCIÓN',
- 'D' => 'ACRÓNIMO DEL EQUIPO',
- 'E' => 'MODELO COMPLETO',
- 'F' => 'ACRÓNIMO DEL MODELO',
- 'G' => 'ID',
- 'H' => 'NO.SERIE',
- 'I' => 'NO. CÓDIGO DE BARRAS',
- 'J' => 'CARÁCTER',
- 'K' => 'FECHA DE VENCIMIENTO DEL ARTÍCULO',
- 'L' => 'ETIQUETA FINAL DEL EQUIPO',
- ],
- 'LRU' => [
- 'B' => 'CÓDIGO EQUIVALENTE',
- 'C' => 'TIPO / DESCRIPCIÓN',
- 'D' => 'ACRÓNIMO DEL EQUIPO',
- 'E' => 'MODELO COMPLETO',
- 'F' => 'ACRÓNIMO DEL MODELO',
- 'G' => 'ID',
- 'H' => 'NO.SERIE',
- 'I' => 'NO. CÓDIGO DE BARRAS',
- 'J' => 'CARÁCTER',
- 'K' => 'FECHA DE VENCIMIENTO DEL ARTÍCULO',
- 'L' => 'ETIQUETA FINAL DEL EQUIPO'
- ],
- 'CASO 1'=> [
- 'B'=> 'LÍNEA',
- 'D'=> 'UBICACIÓN',
- 'F'=> 'NIVEL',
- 'H'=> 'OCUPACIÓN',
- 'J'=> 'ELEMENTO',
- 'L'=> 'COORDENADAS PLANO GENERAL',
- 'M'=> 'COORDENADAS DETALLE',
- 'N'=> 'COORDENADAS DE POSICIÓN',
- 'P'=> 'FAMILIA',
- 'R'=> 'SUBFAMILIA',
- 'T'=> 'ESTADO',
- 'V'=> 'TIPO',
- 'X'=> 'MODELO',
- 'Z'=> 'ID',
- 'AB'=> 'TIPO',
- 'AD'=> 'MODELO',
- 'AF'=> 'ID',
- 'AH'=> 'CÓDIGO COMPLETO SAM',
- 'AI'=> 'CÓDIGO EQUIVALENTE',
- ],
- 'CASO 2'=> [
- 'B'=> 'LÍNEA',
- 'D'=> 'UBICACIÓN',
- 'F'=> 'NIVEL',
- 'H'=> 'OCUPACIÓN',
- 'J'=> 'ELEMENTO',
- 'L'=> 'COORDENADAS PLANO GENERAL',
- 'M'=> 'COORDENADAS DE POSICIÓN',
- 'N'=> 'POSICIÓN EN RACK',
- 'P'=> 'FAMILIA',
- 'R'=> 'SUBFAMILIA',
- 'T'=> 'ESTADO',
- 'V'=> 'TIPO',
- 'X'=> 'MODELO',
- 'Z'=> 'ID',
- 'AB'=> 'TIPO',
- 'AD'=> 'MODELO',
- 'AF'=> 'ID',
- 'AH'=> 'CÓDIGO COMPLETO',
- 'AI'=> 'CÓDIGO EQUIVALENTE',
- ],
- 'CASO 3'=> [
- 'B'=> 'LÍNEA',
- 'D'=> 'UBICACIÓN ORIGEN',
- 'F'=> 'NIVEL ORIGEN',
- 'H'=> 'OCUPACIÓN ORIGEN',
- 'J'=> 'ELEMENTO ORIGEN',
- 'L'=> 'PK ORIGEN',
- 'N'=> 'UBICACIÓN DESTINO',
- 'P'=> 'NIVEL DESTINO',
- 'R'=> 'OCUPACIÓN DESTINO',
- 'T'=> 'ELEMENTO DESTINO',
- 'V'=> 'PK DESTINO',
- 'X'=> 'FAMILIA',
- 'Z'=> 'SUBFAMILIA',
- 'AB'=> 'ESTADO',
- 'AD'=> 'TIPO',
- 'AF'=> 'MODELO',
- 'AH'=> 'ID',
- 'AJ'=> 'TIPO',
- 'AL'=> 'MODELO',
- 'AN'=> 'ID',
- 'AP'=> 'CÓDIGO COMPLETO',
- 'AQ'=> 'CÓDIGO EQUIVALENTE'
- ],
- 'CASO 4'=> [
- 'B'=> 'LÍNEA',
- 'D'=> 'UBICACIÓN ORIGEN',
- 'F'=> 'NIVEL ORIGEN',
- 'H'=> 'OCUPACIÓN ORIGEN',
- 'J'=> 'ELEMENTO ORIGEN',
- 'L'=> 'SECUENCIAL ORIGEN',
- 'N'=> 'COORDENADAS PLANO',
- 'O'=> 'COORDENADAS DETALLE',
- 'P'=> 'COORDENADAS DE POSICIÓN',
- 'R'=> 'UBICACIÓN DESTINO',
- 'T'=> 'NIVEL DESTINO',
- 'V'=> 'OCUPACIÓN DESTINO',
- 'X'=> 'ELEMENTO DESTINO',
- 'Z'=> 'SECUENCIAL DESTINO',
- 'AB'=> 'COORDENADAS PLANO',
- 'AC'=> 'COORDENADAS DETALLE',
- 'AD'=> 'COORDENADAS DE POSICIÓN',
- 'AF'=> 'FAMILIA',
- 'AH'=> 'SUBFAMILIA',
- 'AJ'=> 'ESTADO',
- 'AL'=> 'TIPO',
- 'AN'=> 'MODELO',
- 'AP'=> 'ID',
- 'AR'=> 'TIPO',
- 'AT'=> 'MODELO',
- 'AV'=> 'ID',
- 'AX'=> 'CÓDIGO COMPLETO',
- 'AY'=> 'CÓDIGO EQUIVALENTE',
- ],
- 'CASO 5'=> [
- 'B'=> 'LÍNEA',
- 'D'=> 'UBICACIÓN',
- 'F'=> 'NIVEL',
- 'H'=> 'OCUPACIÓN',
- 'J'=> 'ÁREA',
- 'L'=> 'ELEMENTO',
- 'N'=> 'FAMILIA',
- 'P'=> 'SUBFAMILIA',
- 'R'=> 'ESTADO',
- 'T'=> 'TIPO',
- 'V'=> 'MODELO',
- 'X'=> 'ID',
- 'Z'=> 'TIPO',
- 'AB'=> 'MODELO',
- 'AD'=> 'ID',
- 'AF'=> 'CÓDIGO COMPLETO',
- 'AG'=> 'CÓDIGO EQUIVALENTE',
- ],
- 'CASO 6' => [
- 'B'=> 'LÍNEA',
- 'D'=> 'UBICACIÓN',
- 'F'=> 'NIVEL',
- 'H'=> 'OCUPACIÓN',
- 'J'=> 'ELEMENTO',
- 'L'=> 'POSICIÓN',
- 'N'=> 'FAMILIA',
- 'P'=> 'SUBFAMILIA',
- 'R'=> 'ESTADO',
- 'T'=> 'TIPO',
- 'V'=> 'MODELO',
- 'X'=> 'ID',
- 'Z'=> 'TIPO',
- 'AB'=> 'MODELO',
- 'AD'=> 'ID',
- 'AF'=> 'CÓDIGO COMPLETO',
- 'AG'=> 'CÓDIGO EQUIVALENTE'
- ]
- ];
- return $headers[$sheetName] ?? [];
- }
- private function extractRowData($worksheet, $row, $fieldMapping, $sheetName) {
- $rowData = [];
-
- foreach($fieldMapping as $column => $field) {
- $cellValue = $worksheet->getCell($column . $row)->getCalculatedValue();
-
- // Manejar concatenaciones especiales para coordenadas
- if($sheetName === 'CASO 1' || $sheetName === 'CASO 2') {
- if($column === 'L' && isset($fieldMapping['M']) && isset($fieldMapping['N'])) {
- $coordL = $worksheet->getCell('L' . $row)->getCalculatedValue();
- $coordM = $worksheet->getCell('M' . $row)->getCalculatedValue();
- $coordN = $worksheet->getCell('N' . $row)->getCalculatedValue();
- $rowData['PCEQ_COOR'] = $coordL . $coordM . $coordN;
- }
- }
-
- if($sheetName === 'CASO 4') {
- if($column === 'N' && isset($fieldMapping['O']) && isset($fieldMapping['P'])) {
- $coordN = $worksheet->getCell('N' . $row)->getCalculatedValue();
- $coordO = $worksheet->getCell('O' . $row)->getCalculatedValue();
- $coordP = $worksheet->getCell('P' . $row)->getCalculatedValue();
- $rowData['PCEQ_COOR_ORIGEN'] = $coordN . $coordO . $coordP;
- }
- if($column === 'AB' && isset($fieldMapping['AC']) && isset($fieldMapping['AD'])) {
- $coordAB = $worksheet->getCell('AB' . $row)->getCalculatedValue();
- $coordAC = $worksheet->getCell('AC' . $row)->getCalculatedValue();
- $coordAD = $worksheet->getCell('AD' . $row)->getCalculatedValue();
- $rowData['PCEQ_COOR_DESTINO'] = $coordAB . $coordAC . $coordAD;
- }
- }
-
- if(!empty($field) && !in_array($field, ['.', '-', '_', '+', ':', ';'])) {
- $rowData[$field] = $cellValue;
- }
- }
-
- return $rowData;
- }
- private function isEmptyRow($rowData) {
- $requiredFields = ['PCEQ_TIEQ', 'PCEQ_MOEQ']; // Campos mínimos
-
- foreach($requiredFields as $field) {
- if(isset($rowData[$field]) && !empty(trim((string)$rowData[$field]))) {
- return false;
- }
- }
- return true;
- }
- private function validateRowData($rowData, $sheetName, $row) {
- $errors = [];
- $valid = true;
-
- // Para hojas de casos 1-6
- if (in_array($sheetName, ['CASO 1', 'CASO 2', 'CASO 3', 'CASO 4', 'CASO 5', 'CASO 6'])) {
- $tienePrimerConjunto =
- !empty(trim($rowData['PCEQ_TIEQ'] ?? '')) &&
- !empty(trim($rowData['PCEQ_MOEQ'] ?? ''));
-
- $tieneSegundoConjunto =
- !empty(trim($rowData['PCEQ_TIEQ_HIJO'] ?? '')) &&
- !empty(trim($rowData['PCEQ_MOEQ_HIJO'] ?? ''));
-
- if (!$tienePrimerConjunto && !$tieneSegundoConjunto) {
- $errors[] = 'Se requiere al menos un conjunto completo de datos (Tipo/Modelo)';
- $valid = false;
- }
- } else {
- // Validación original para otras hojas
- if(empty($rowData['PCEQ_TIEQ'] ?? '')) {
- $errors[] = 'Tipo de equipo requerido';
- $valid = false;
- }
-
- if(empty($rowData['PCEQ_MOEQ'] ?? '')) {
- $errors[] = 'Modelo requerido';
- $valid = false;
- }
- }
-
- // Validar fechas si existen
- $dateFields = ['PCEQ_FEAD', 'PCEQ_FIGA', 'PCEQ_FTGA'];
- foreach($dateFields as $dateField) {
- if(isset($rowData[$dateField]) && !empty($rowData[$dateField])) {
- try {
- Carbon::parse($rowData[$dateField]);
- } catch(Exception $e) {
- $errors[] = "Fecha inválida en campo $dateField";
- $valid = false;
- }
- }
- }
-
- return ['valid' => $valid, 'errors' => $errors];
- }
- private function noDate($value)
- {
- if (empty($value) ||
- strtoupper(trim($value)) === 'NA' ||
- trim($value) === '.' ||
- trim($value) === '-') {
- return now()->format('Y-m-d');
- }
-
- if (is_numeric($value)) {
- try {
- return \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value)->format('Y-m-d');
- } catch (Exception $e) {
- return null;
- }
- }
-
- if (is_string($value)) {
- try {
- $date = new \DateTime($value);
- return $date->format('Y-m-d');
- } catch (Exception $e) {
- return null;
- }
- }
-
- return null;
- }
- private function prepareEquipmentData($rowData, $linea, $idUser, $sheetName) {
- $nowStr = Carbon::now('America/Mexico_city')->toDateTimeString();
-
- // si se llegan a meter columnas de fechas a la hoja ests variables formatean la fecha de la columna, nada más habría que formatear
- // queda así
- //'PCEQ_FIGA' => $fechaInicioGarantia 'PCEQ_FEAD' => $fechaAdquisicion 'PCEQ_FTGA' => $fechaFinGarantia
- $caracter = $this->normalizeCaracter($rowData['PCEQ_CARA'] ?? null);
- $fechaInicioGarantia = $this->parseDate($rowData['PCEQ_FIGA'] ?? null);
- $fechaFinGarantia = $this->parseDate($rowData['PCEQ_FTGA'] ?? null);
- $fechaAdquisicion = $this->parseDate($rowData['PCEQ_FEAD'] ?? null);
- $fechaVencimiento = $this->noDate($rowData['PCEQ_FVAR'] ?? null);
-
- $equipmentData = [
- 'PCEQ_FIGA' => now()->format('Y-m-d'),
- 'PCEQ_FEAD' => now()->format('Y-m-d'),
- 'PCEQ_FTGA' => now()->format('Y-m-d'),
- 'PCEQ_OTCO' => '[]',
- 'PCEQ_NULI' => $linea,
- 'PCEQ_UBOR' => $rowData['PCEQ_UBOR'] ?? '',
- 'PCEQ_NIOR' => $rowData['PCEQ_NIOR'] ?? '',
- 'PCEQ_OCOR' => $rowData['PCEQ_OCOR'] ?? '',
- 'PCEQ_ELOR' => $rowData['PCEQ_ELOR'] ?? '',
- 'PCEQ_COOR' => $rowData['PCEQ_COOR'] ?? '',
- 'PCEQ_FAMI' => $rowData['PCEQ_FAMI'] ?? '',
- 'PCEQ_SUBF' => $rowData['PCEQ_SUBF'] ?? '',
- 'PCEQ_ESEQ' => $rowData['PCEQ_ESEQ'] ?? 'A',
- 'PCEQ_TIEQ' => $rowData['PCEQ_TIEQ'] ?? '',
- 'PCEQ_MOEQ' => $rowData['PCEQ_MOEQ'] ?? '',
- 'PCEQ_CPGE' => $rowData['PCEQ_CPGE'] ?? '',
- 'PCEQ_TICO' => $this->getCodeTypeFromSheet($sheetName),
- 'PCEQ_JERA' => 'Padre',
- 'PCEQ_EQPA' => null,
- 'PCEQ_NUSE' => $rowData['PCEQ_NUSE'] ?? '',
- 'PCEQ_COBA' => $rowData['PCEQ_COBA'] ?? '',
- 'PCEQ_CARA' => $caracter,
- 'PCEQ_PREQ' => $rowData['PCEQ_PREQ'] ?? 0,
- 'PCEQ_FVAR' => $fechaVencimiento,
- 'PCEQ_GAIM' => json_encode([]),
- 'PCEQ_DORE' => json_encode([]),
- 'PCEQ_ESRE' => 'Revisión',
- 'PCEQ_USRE' => $idUser,
- 'PCEQ_FERE' => $nowStr,
- 'PCEQ_IDPR' => $this->generateNumericUniqueId($linea)
- ];
- $this->handleHierarchy($equipmentData, $rowData, $sheetName);
-
- // Lógica de jerarquía (Padre/Hijo) para casos 1-6
- if (in_array($sheetName, ['CASO 1', 'CASO 2', 'CASO 3', 'CASO 4', 'CASO 5', 'CASO 6'])) {
- // Verificar si los campos del segundo conjunto (AB y AD) tienen datos
- $tieneSegundoConjunto =
- !empty(trim($rowData['PCEQ_TIEQ_HIJO'] ?? '')) &&
- !empty(trim($rowData['PCEQ_MOEQ_HIJO'] ?? ''));
-
- if ($tieneSegundoConjunto) {
- // Usar valores del segundo conjunto (Hijo)
- $equipmentData['PCEQ_TIEQ'] = $rowData['PCEQ_TIEQ_HIJO'];
- $equipmentData['PCEQ_MOEQ'] = $rowData['PCEQ_MOEQ_HIJO'];
- $equipmentData['PCEQ_JERA'] = 'Hijo';
- } else {
- // Usar valores del primer conjunto (Padre)
- $equipmentData['PCEQ_TIEQ'] = $rowData['PCEQ_TIEQ'] ?? '';
- $equipmentData['PCEQ_MOEQ'] = $rowData['PCEQ_MOEQ'] ?? '';
- $equipmentData['PCEQ_JERA'] = 'Padre';
- }
- } else {
- // Para otras hojas (CARGA DE EQUIPOS, LRU) usar valores normales
- $equipmentData['PCEQ_TIEQ'] = $rowData['PCEQ_TIEQ'] ?? '';
- $equipmentData['PCEQ_MOEQ'] = $rowData['PCEQ_MOEQ'] ?? '';
- }
-
- // Agregar campos específicos según el tipo de hoja
- $this->addSheetSpecificFields($equipmentData, $rowData, $sheetName);
-
- // Manejar fechas
- if(isset($rowData['PCEQ_FEAD'])) {
- $equipmentData['PCEQ_FEAD'] = $this->noDate($rowData['PCEQ_FEAD']) ?? now()->format('Y-m-d');
- }
- if(isset($rowData['PCEQ_FIGA'])) {
- $equipmentData['PCEQ_FIGA'] = $this->noDate($rowData['PCEQ_FIGA']) ?? now()->format('Y-m-d');
- }
- if(isset($rowData['PCEQ_FTGA'])) {
- $equipmentData['PCEQ_FTGA'] = $this->noDate($rowData['PCEQ_FTGA']) ?? now()->format('Y-m-d');
- }
- if(isset($rowData['PCEQ_FVAR'])) {
- $equipmentData['PCEQ_FVAR'] = $this->noDate($rowData['PCEQ_FVAR']) ?? now()->format('Y-m-d');
- }
-
- // GENERAR PCEQ_IDPR: Solo un ID numérico único simple
- $equipmentData['PCEQ_IDPR'] = $this->generateNumericUniqueId($linea);
-
- // GENERAR PCEQ_CPGE: El código concatenado completo (solo para CASOS 1-6)
- if(in_array($sheetName, ['CASO 1', 'CASO 2', 'CASO 3', 'CASO 4', 'CASO 5', 'CASO 6'])) {
- $equipmentData['PCEQ_CPGE'] = $this->generateConcatenatedCode($equipmentData, $sheetName);
- } else {
- // Para CARGA DE EQUIPOS y LRU, usar valor por defecto o del Excel
- $equipmentData['PCEQ_CPGE'] = $rowData['PCEQ_CPGE'] ?? 'DEFAULT_CODE_' . $equipmentData['PCEQ_IDPR'];
- }
-
- return $equipmentData;
- }
- private function parseDate($value) {
- if (!$value) return null;
-
- try {
- // Intentar como fecha de Excel
- if (is_numeric($value)) {
- return \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value)
- ->format('Y-m-d');
- }
-
- // Intentar como cadena de fecha
- return Carbon::createFromFormat('d/m/Y', $value)->format('Y-m-d');
- } catch (\Exception $e) {
- return null;
- }
- }
- // Función para manejar jerarquía
- private function handleHierarchy(&$equipmentData, $rowData, $sheetName) {
- if (!in_array($sheetName, ['CASO 1','CASO 2','CASO 3','CASO 4','CASO 5','CASO 6'])) {
- return;
- }
- // Determinar si es hijo
- $isHijo = !empty($rowData['PCEQ_TIEQ_HIJO']) || !empty($rowData['PCEQ_MOEQ_HIJO']);
-
- if ($isHijo) {
- $equipmentData['PCEQ_JERA'] = 'Hijo';
- $equipmentData['PCEQ_TIEQ'] = $rowData['PCEQ_TIEQ_HIJO'] ?? '';
- $equipmentData['PCEQ_MOEQ'] = $rowData['PCEQ_MOEQ_HIJO'] ?? '';
- }
- }
- private function normalizeCaracter($value) {
- if (!$value) return null;
-
- $value = strtoupper(trim($value));
- $mapping = [
- 'REPARABLE' => 'REPARABLE',
- 'REP' => 'REPARABLE',
- 'R' => 'REPARABLE',
- 'CONSUMIBLE' => 'CONSUMIBLE',
- 'CONSUM' => 'CONSUMIBLE',
- 'CONS' => 'CONSUMIBLE',
- 'C' => 'CONSUMIBLE',
- 'DESECHABLE' => 'CONSUMIBLE'
- ];
-
- return $mapping[$value] ?? null;
- }
- // MÉTODO PARA GENERAR PCEQ_IDPR: Solo ID numérico único
- private function generateNumericUniqueId($linea) {
- // Obtener el máximo ID existente para esta línea
- $maxId = DB::table('S002V01TPCEQ')
- ->where('PCEQ_NULI', $linea)
- ->max('PCEQ_IDPR');
-
- // Generar el siguiente ID secuencial
- $nextId = $maxId ? $maxId + 1 : 1;
-
- // Verificar que el ID no exista (por seguridad)
- while(DB::table('S002V01TPCEQ')
- ->where('PCEQ_NULI', $linea)
- ->where('PCEQ_IDPR', $nextId)
- ->exists()) {
- $nextId++;
- }
-
- return $nextId;
- }
- // MÉTODO PARA GENERAR PCEQ_CPGE: El código concatenado complejo (solo CASOS 1-6)
- private function generateConcatenatedCode($equipmentData, $sheetName) {
- // Solo generar concatenación para CASOS 1-6
- switch($sheetName) {
- case 'CASO 1':
- case 'CASO 2':
- return $this->generateCodeCaso1y2($equipmentData);
-
- case 'CASO 3':
- return $this->generateCodeCaso3($equipmentData);
-
- case 'CASO 4':
- return $this->generateCodeCaso4($equipmentData);
-
- case 'CASO 5':
- case 'CASO 6':
- return $this->generateCodeCaso5y6($equipmentData);
-
- default:
- return 'DEFAULT_CODE_' . $equipmentData['PCEQ_IDPR'];
- }
- }
- private function generateCodeCaso1y2($data) {
- // Patrón: LINEA.UBICACION.NIVEL.OCUPACION.ELEMENTO+COORDENADAS_FAMILIA.SUBFAMILIA.ESTADO.TIPO-MODELO-ID.TIPO-MODELO-ID-CODIGO_SAM
- $parts = [
- str_pad($data['PCEQ_NULI'], 2, '0', STR_PAD_LEFT), // Línea con padding
- $data['PCEQ_UBOR'] ?? '', // Ubicación
- $data['PCEQ_NIOR'] ?? '', // Nivel
- $data['PCEQ_OCOR'] ?? '', // Ocupación
- $data['PCEQ_ELOR'] ?? '', // Elemento
- $data['PCEQ_COOR'] ?? '', // Coordenadas
- $data['PCEQ_FAMI'] ?? '', // Familia
- '',
- $data['PCEQ_SUBF'] ?? '', // Subfamilia
- $data['PCEQ_ESEQ'] ?? 'A', // Estado
- $data['PCEQ_TIEQ'] ?? '', // Tipo
- $data['PCEQ_MOEQ'] ?? '', // Modelo
- $data['PCEQ_IDPR'], // ID numérico
- ];
-
- return implode('.', array_filter($parts));
- }
- private function generateCodeCaso3($data) {
- // Patrón para CASO 3: LINEA.UBICACION_ORIGEN.NIVEL_ORIGEN.OCUPACION_ORIGEN.ELEMENTO_ORIGEN:UBICACION_DESTINO.NIVEL_DESTINO.OCUPACION_DESTINO.ELEMENTO_DESTINO-FAMILIA-SUBFAMILIA.ESTADO-TIPO-MODELO-ID
- $parts = [
- str_pad($data['PCEQ_NULI'], 2, '0', STR_PAD_LEFT),
- $data['PCEQ_UBOR'] ?? '', // Ubicación origen
- $data['PCEQ_NIDE'] ?? '', // Nivel origen
- $data['PCEQ_OCDE'] ?? '', // Ocupación origen
- $data['PCEQ_ELDE'] ?? '', // Elemento origen
- $data['PCEQ_UBDE'] ?? '', // Ubicación destino
- $data['PCEQ_FAMI'] ?? '', // Familia
- $data['PCEQ_SUBF'] ?? '', // Subfamilia
- $data['PCEQ_ESEQ'] ?? 'A', // Estado
- $data['PCEQ_TIEQ'] ?? '', // Tipo
- $data['PCEQ_MOEQ'] ?? '', // Modelo
- $data['PCEQ_IDPR'], // ID numérico
- ];
-
- return implode('.', array_filter($parts));
- }
- private function generateCodeCaso4($data) {
- // Patrón para CASO 4: Similar a CASO 3 pero con secuenciales y coordenadas adicionales
- $parts = [
- str_pad($data['PCEQ_NULI'], 2, '0', STR_PAD_LEFT),
- $data['PCEQ_UBOR'] ?? '', // Ubicación origen
- $data['PCEQ_SEOR'] ?? '0', // Secuencial origen
- $data['PCEQ_COOR'] ?? '', // Coordenadas origen
- $data['PCEQ_UBDE'] ?? '', // Ubicación destino
- $data['PCEQ_SEDE'] ?? '0', // Secuencial destino
- $data['PCEQ_CODE'] ?? '', // Coordenadas destino
- $data['PCEQ_FAMI'] ?? '', // Familia
- $data['PCEQ_SUBF'] ?? '', // Subfamilia
- $data['PCEQ_ESEQ'] ?? 'A', // Estado
- $data['PCEQ_TIEQ'] ?? '', // Tipo
- $data['PCEQ_MOEQ'] ?? '', // Modelo
- $data['PCEQ_IDPR'], // ID numérico
- ];
-
- return implode('.', array_filter($parts));
- }
- private function generateCodeCaso5y6($data) {
- // Patrón para CASO 5 y 6: LINEA.UBICACION.NIVEL.OCUPACION.AREA.ELEMENTO_FAMILIA.SUBFAMILIA.ESTADO.TIPO-MODELO-ID.TIPO-MODELO-ID-CODIGO
- $parts = [
- str_pad($data['PCEQ_NULI'], 2, '0', STR_PAD_LEFT),
- $data['PCEQ_UBOR'] ?? '', // Ubicación
- $data['PCEQ_NIOR'] ?? '', // Nivel
- $data['PCEQ_OCOR'] ?? '', // Ocupación
- $data['PCEQ_ARTR'] ?? '', // Área
- $data['PCEQ_ELOR'] ?? '', // Elemento
- $data['PCEQ_FAMI'] ?? '', // Familia
- $data['PCEQ_SUBF'] ?? '', // Subfamilia
- $data['PCEQ_ESEQ'] ?? 'A', // Estado
- $data['PCEQ_TIEQ'] ?? '', // Tipo
- $data['PCEQ_MOEQ'] ?? '', // Modelo
- $data['PCEQ_IDPR'], // ID numérico
- ];
-
- return implode('.', array_filter($parts));
- }
- // MÉTODO ALTERNATIVO: Usar timestamp + hash para garantizar unicidad (para CARGA DE EQUIPOS y LRU)
- private function generateUniqueHashId($linea) {
- // Crear ID único basado en timestamp + random para CARGA DE EQUIPOS y LRU
- return $linea . '_' . date('YmdHis') . '_' . uniqid();
- }
- // MÉTODO DE RESPALDO: Si falla todo, usar este ID de emergencia
- private function generateFallbackId($linea) {
- return 'FALLBACK_' . $linea . '_' . microtime(true) . '_' . rand(10000, 99999);
- }
- // SOLUCIÓN MEJORADA: Verificar duplicados de PCEQ_IDPR antes de insertar
- private function insertEquipmentWithDuplicateHandling($equipmentData) {
- $maxAttempts = 5;
- $attempt = 0;
-
- while($attempt < $maxAttempts) {
- try {
- // Verificar si ya existe este PCEQ_IDPR para esta línea
- $exists = DB::table('S002V01TPCEQ')
- ->where('PCEQ_NULI', $equipmentData['PCEQ_NULI'])
- ->where('PCEQ_IDPR', $equipmentData['PCEQ_IDPR'])
- ->exists();
-
- if($exists) {
- // Regenerar PCEQ_IDPR numérico único
- $equipmentData['PCEQ_IDPR'] = $this->generateNumericUniqueId($equipmentData['PCEQ_NULI']);
-
- // Si es un CASO 1-6, regenerar también el PCEQ_CPGE con el nuevo IDPR
- if(isset($equipmentData['PCEQ_CPGE']) && strpos($equipmentData['PCEQ_CPGE'], '.') !== false) {
- $sheetName = $this->getSheetNameFromCodeType($equipmentData['PCEQ_TICO']);
- if($sheetName) {
- $equipmentData['PCEQ_CPGE'] = $this->generateConcatenatedCode($equipmentData, $sheetName);
- }
- }
-
- $attempt++;
- continue;
- }
-
- // Intentar insertar
- return DB::table('S002V01TPCEQ')->insert($equipmentData);
-
- } catch(\Illuminate\Database\QueryException $e) {
- // Si es error de clave duplicada, regenerar ID
- if($e->getCode() == 23000 || strpos($e->getMessage(), 'Duplicate entry') !== false) {
- $equipmentData['PCEQ_IDPR'] = $this->generateNumericUniqueId($equipmentData['PCEQ_NULI']);
- $attempt++;
- continue;
- }
-
- // Si es otro tipo de error, re-lanzar
- throw $e;
- }
- }
-
- throw new Exception("No se pudo insertar el registro después de $maxAttempts intentos");
- }
- // MÉTODO AUXILIAR: Obtener nombre de hoja basado en tipo de código
- private function getSheetNameFromCodeType($codeType) {
- $codeTypes = [
- '1' => 'CASO 1',
- '2' => 'CASO 2',
- '3' => 'CASO 3',
- '4' => 'CASO 4',
- '5' => 'CASO 5',
- '6' => 'CASO 6'
- ];
-
- return $codeTypes[$codeType] ?? null;
- }
- // SOLUCIÓN 3: Usar upsert (insertar o actualizar)
- private function upsertEquipmentData($equipmentData) {
- return DB::table('S002V01TPCEQ')->updateOrInsert(
- [
- 'PCEQ_NULI' => $equipmentData['PCEQ_NULI'],
- 'PCEQ_TICO' => $equipmentData['PCEQ_TICO'],
- 'PCEQ_IDPR' => $equipmentData['PCEQ_IDPR']
- ],
- $equipmentData
- );
- }
- // MÉTODO MODIFICADO PARA PROCESAR WORKSHEET CON MANEJO DE DUPLICADOS
- private function processWorksheet($worksheet, $sheetConfig, $sheetName, $linea, $idUser, $cargaMap, $lruMap) {
- $processedData = [];
- $errors = [];
- $count = 0;
-
- $highestRow = $worksheet->getHighestRow();
- $startRow = $sheetConfig['date_start_row'];
- $fieldMapping = $sheetConfig['field_mapping'];
-
- // Obtener todos los equipos de CARGA y LRU para búsqueda
- $cargaEquipments = $this->getAllCargaEquipments($worksheet->getParent());
- $lruEquipments = $this->getAllLruEquipments($worksheet->getParent());
-
- for($row = $startRow; $row <= $highestRow; $row++) {
- $rowData = $this->extractRowData($worksheet, $row, $fieldMapping, $sheetName);
-
- if($this->isEmptyRow($rowData)) {
- continue;
- }
-
- $this->replaceAcronyms($rowData, $sheetName, $cargaMap, $lruMap);
- $validation = $this->validateRowData($rowData, $sheetName, $row);
-
- if(!$validation['valid']) {
- $errors[] = "Hoja: $sheetName, Fila: $row - " . implode(', ', $validation['errors']);
- continue;
- }
-
- // Determinar si es equipo padre o hijo
- $isHijo = !empty($rowData['PCEQ_TIEQ_HIJO']) || !empty($rowData['PCEQ_MOEQ_HIJO']);
-
- // Buscar equipo completo en CARGA o LRU
- $fullEquipment = null;
- if($isHijo) {
- // Buscar en LRU por tipo y modelo hijo
- $fullEquipment = $this->findEquipment(
- $lruEquipments,
- $rowData['PCEQ_TIEQ_HIJO'] ?? '',
- $rowData['PCEQ_MOEQ_HIJO'] ?? ''
- );
- } else {
- // Buscar en CARGA por tipo y modelo padre
- $fullEquipment = $this->findEquipment(
- $cargaEquipments,
- $rowData['PCEQ_TIEQ'] ?? '',
- $rowData['PCEQ_MOEQ'] ?? ''
- );
- }
-
- // Combinar datos del caso con datos del equipo completo
- if($fullEquipment) {
- $rowData = array_merge($rowData, $fullEquipment);
- }
-
- $equipmentData = $this->prepareEquipmentData($rowData, $linea, $idUser, $sheetName);
- $processedData[] = $equipmentData;
- $count++;
- }
-
- return [
- 'data' => $processedData,
- 'errors' => $errors,
- 'count' => $count
- ];
- }
- // Obtener todos los equipos de CARGA DE EQUIPOS
- private function getAllCargaEquipments($spreadsheet) {
- $equipments = [];
- $sheet = $spreadsheet->getSheetByName('CARGA DE EQUIPOS');
-
- if(!$sheet) return $equipments;
-
- $highestRow = $sheet->getHighestRow();
- $config = ExcelTemplateConfig::getTemplateConfigs()['TPCEQ']['worksheets']['CARGA DE EQUIPOS'];
- $startRow = $config['date_start_row'];
-
- for($row = $startRow; $row <= $highestRow; $row++) {
- $equipment = $this->extractRowData($sheet, $row, $config['field_mapping'], 'CARGA DE EQUIPOS');
-
- if(!$this->isEmptyRow($equipment)) {
- $equipments[] = $equipment;
- }
- }
-
- return $equipments;
- }
- // Obtener todos los equipos de LRU
- private function getAllLruEquipments($spreadsheet) {
- $equipments = [];
- $sheet = $spreadsheet->getSheetByName('LRU');
-
- if(!$sheet) return $equipments;
-
- $highestRow = $sheet->getHighestRow();
- $config = ExcelTemplateConfig::getTemplateConfigs()['TPCEQ']['worksheets']['LRU'];
- $startRow = $config['date_start_row'];
-
- for($row = $startRow; $row <= $highestRow; $row++) {
- $equipment = $this->extractRowData($sheet, $row, $config['field_mapping'], 'LRU');
-
- if(!$this->isEmptyRow($equipment)) {
- $equipments[] = $equipment;
- }
- }
-
- return $equipments;
- }
- // Buscar equipo por tipo y modelo
- private function findEquipment($equipments, $tipo, $modelo) {
- $normalize = function($value) {
- return trim(strtoupper($value));
- };
-
- $tipo = $normalize($tipo);
- $modelo = $normalize($modelo);
-
- foreach($equipments as $equipment) {
- $eqTipo = $normalize($equipment['PCEQ_TIEQ'] ?? '');
- $eqModelo = $normalize($equipment['PCEQ_MOEQ'] ?? '');
-
- if($eqTipo === $tipo && $eqModelo === $modelo) {
- return $equipment;
- }
- }
-
- return null;
- }
- private function replaceAcronyms(&$rowData, $sheetName, $cargaMap, $lruMap) {
- // Solo aplica para hojas de casos
- if (!in_array($sheetName, ['CASO 1','CASO 2','CASO 3','CASO 4','CASO 5','CASO 6'])) {
- return;
- }
- // Reemplazar acrónimo padre (de CARGA DE EQUIPOS)
- if (isset($rowData['PCEQ_TIEQ'])) {
- $acronym = trim($rowData['PCEQ_TIEQ']);
- if (isset($cargaMap['equipos'][$acronym])) {
- $rowData['PCEQ_TIEQ'] = $cargaMap['equipos'][$acronym];
- }
- }
- // Reemplazar acrónimo hijo (de LRU)
- if (isset($rowData['PCEQ_TIEQ_HIJO'])) {
- $acronym = trim($rowData['PCEQ_TIEQ_HIJO']);
- if (isset($lruMap['equipos'][$acronym])) {
- $rowData['PCEQ_TIEQ_HIJO'] = $lruMap['equipos'][$acronym];
- }
- }
- if (isset($rowData['PCEQ_MOEQ'])) {
- $acronym = trim($rowData['PCEQ_MOEQ']);
- if (isset($cargaMap['modelos'][$acronym])) {
- $rowData['PCEQ_MOEQ'] = $cargaMap['modelos'][$acronym];
- }
- }
- // NUEVO: Reemplazar acrónimo de modelo hijo (de LRU)
- if (isset($rowData['PCEQ_MOEQ_HIJO'])) {
- $acronym = trim($rowData['PCEQ_MOEQ_HIJO']);
- if (isset($lruMap['modelos'][$acronym])) {
- $rowData['PCEQ_MOEQ_HIJO'] = $lruMap['modelos'][$acronym];
- }
- }
-
- }
- // MÉTODO ALTERNATIVO: Limpiar datos duplicados antes del procesamiento
- public function cleanDuplicateRecords(Request $request) {
- $validator = Validator::make($request->all(), [
- 'id_user' => 'required|string',
- 'linea' => 'required|integer',
- ]);
- if($validator->fails()) {
- return $this->responseController->makeResponse(
- true,
- "Se encontraron uno o más errores.",
- $this->responseController->makeErrors($validator->errors()->messages()),
- 401
- );
- }
- $form = $request->all();
- $idUser = $this->encryptionController->decrypt($form['id_user']);
-
- if(!$idUser) {
- return $this->responseController->makeResponse(true, "El id del usuario no fue desencriptado correctamente", [], 400);
- }
- try {
- DB::beginTransaction();
-
- // Eliminar registros duplicados manteniendo solo el más reciente
- $duplicatesDeleted = DB::statement("
- DELETE p1 FROM S002V01TPCEQ p1
- INNER JOIN S002V01TPCEQ p2
- WHERE p1.PCEQ_NULI = p2.PCEQ_NULI
- AND p1.PCEQ_TICO = p2.PCEQ_TICO
- AND p1.PCEQ_IDPR = p2.PCEQ_IDPR
- AND p1.PCEQ_FERE < p2.PCEQ_FERE
- AND p1.PCEQ_NULI = ?
- ", [$form['linea']]);
-
- DB::commit();
-
- return $this->responseController->makeResponse(false, "Duplicados eliminados exitosamente", [
- 'linea' => $form['linea'],
- 'duplicados_eliminados' => $duplicatesDeleted
- ]);
-
- } catch(Exception $e) {
- DB::rollBack();
- return $this->responseController->makeResponse(true, "Error al limpiar duplicados: " . $e->getMessage(), [], 500);
- }
- }
- private function getCodeTypeFromSheet($sheetName) {
- $codeTypes = [
- 'CASO 1' => '1',
- 'CASO 2' => '2',
- 'CASO 3' => '3',
- 'CASO 4' => '4',
- 'CASO 5' => '5',
- 'CASO 6' => '6',
- ];
-
- return $codeTypes[$sheetName] ?? '1';
- }
- private function addSheetSpecificFields(&$equipmentData, $rowData, $sheetName) {
- switch($sheetName) {
- case 'CASO 1':
- case 'CASO 2':
- $equipmentData['PCEQ_UBOR'] = $rowData['PCEQ_UBOR'] ?? '';
- $equipmentData['PCEQ_NIOR'] = $rowData['PCEQ_NIOR'] ?? '';
- $equipmentData['PCEQ_OCOR'] = $rowData['PCEQ_OCOR'] ?? '';
- $equipmentData['PCEQ_ELOR'] = $rowData['PCEQ_ELOR'] ?? '';
- $equipmentData['PCEQ_COOR'] = $rowData['PCEQ_COOR'] ?? '';
- $equipmentData['PCEQ_FAMI'] = $rowData['PCEQ_FAMI'] ?? '';
- $equipmentData['PCEQ_SUBF'] = $rowData['PCEQ_SUBF'] ?? '';
- if(isset($rowData['PCEQ_CPGE'])) {
- $equipmentData['PCEQ_CPGE'] = $rowData['PCEQ_CPGE'];
- }
- break;
-
- case 'CASO 3':
- $equipmentData['PCEQ_UBOR'] = $rowData['PCEQ_UBOR'] ?? '';
- $equipmentData['PCEQ_UBDE'] = $rowData['PCEQ_UBDE'] ?? '';
- if(isset($rowData['PCEQ_IDPR'])) {
- $equipmentData['PCEQ_IDPR'] = $rowData['PCEQ_IDPR'];
- }
- if(isset($rowData['PCEQ_CPGE'])) {
- $equipmentData['PCEQ_CPGE'] = $rowData['PCEQ_CPGE'];
- }
- break;
-
- case 'CASO 4':
- $equipmentData['PCEQ_UBOR'] = $rowData['PCEQ_UBOR'] ?? '';
- $equipmentData['PCEQ_UBDE'] = $rowData['PCEQ_UBDE'] ?? '';
- $equipmentData['PCEQ_SEOR'] = $rowData['PCEQ_SEOR'] ?? 0;
- $equipmentData['PCEQ_SEDE'] = $rowData['PCEQ_SEDE'] ?? 0;
- $equipmentData['PCEQ_COOR'] = $rowData['PCEQ_COOR_ORIGEN'] ?? '';
- $equipmentData['PCEQ_CODE'] = $rowData['PCEQ_COOR_DESTINO'] ?? '';
- if(isset($rowData['PCEQ_IDPR'])) {
- $equipmentData['PCEQ_IDPR'] = $rowData['PCEQ_IDPR'];
- }
- if(isset($rowData['PCEQ_CPGE'])) {
- $equipmentData['PCEQ_CPGE'] = $rowData['PCEQ_CPGE'];
- }
- break;
-
- case 'CASO 5':
- case 'CASO 6':
- $equipmentData['PCEQ_UBOR'] = $rowData['PCEQ_UBOR'] ?? '';
- $equipmentData['PCEQ_NIOR'] = $rowData['PCEQ_NIOR'] ?? '';
- $equipmentData['PCEQ_OCOR'] = $rowData['PCEQ_OCOR'] ?? '';
- $equipmentData['PCEQ_ARTR'] = $rowData['PCEQ_ARTR'] ?? '';
- $equipmentData['PCEQ_ELOR'] = $rowData['PCEQ_ELOR'] ?? '';
- if(isset($rowData['PCEQ_IDPR'])) {
- $equipmentData['PCEQ_IDPR'] = $rowData['PCEQ_IDPR'];
- }
- if(isset($rowData['PCEQ_CPGE'])) {
- $equipmentData['PCEQ_CPGE'] = $rowData['PCEQ_CPGE'];
- }
- break;
- }
- }
- // Método para obtener equipos en revisión
- public function getPendingEquipments(Request $request) {
- $validator = Validator::make($request->all(), [
- 'id_user' => 'required|string',
- 'linea' => 'required|integer',
- ]);
- if($validator->fails()) {
- return $this->responseController->makeResponse(
- true,
- "Se encontraron uno o más errores.",
- $this->responseController->makeErrors($validator->errors()->messages()),
- 401
- );
- }
- $form = $request->all();
- $idUser = $this->encryptionController->decrypt($form['id_user']);
-
- if(!$idUser) {
- return $this->responseController->makeResponse(true, "El id del usuario no fue desencriptado correctamente", [], 400);
- }
- $pendingEquipments = DB::table('S002V01TPCEQ')
- ->where('PCEQ_NULI', $form['linea'])
- ->where('PCEQ_ESRE', 'Revisión')
- ->orderBy('PCEQ_FERE', 'desc')
- ->get();
- $equipmentsArray = [];
- foreach($pendingEquipments as $equipment) {
- $equipmentsArray[] = [
- 'id' => $this->encryptionController->encrypt($equipment->PCEQ_IDPR),
- 'codigo' => $equipment->PCEQ_CPGE,
- 'tipo' => $equipment->PCEQ_TIEQ,
- 'modelo' => $equipment->PCEQ_MOEQ,
- 'familia' => $equipment->PCEQ_FAMI,
- 'subfamilia' => $equipment->PCEQ_SUBF,
- 'estado' => $equipment->PCEQ_ESEQ,
- 'fecha_registro' => $equipment->PCEQ_FERE,
- 'estado_revision' => $equipment->PCEQ_ESRE
- ];
- }
- return $this->responseController->makeResponse(false, 'EXITO.', $equipmentsArray);
- }
- /**
- * Método para aprobar equipamientos desde la tabla temporal hacia la tabla final
- */
- public function approveEquipments(Request $request) {
- DB::enableQueryLog();
-
- $validator = Validator::make($request->all(), [
- 'id_user' => 'required|string',
- 'linea' => 'required|integer',
- 'equipment_ids' => 'required|array',
- 'equipment_ids.*' => 'required|string'
- ]);
- if($validator->fails()) {
- return $this->responseController->makeResponse(
- true,
- "Se encontraron uno o más errores.",
- $this->responseController->makeErrors($validator->errors()->messages()),
- 401
- );
- }
- $form = $request->all();
- $idUser = $this->encryptionController->decrypt($form['id_user']);
-
- if(!$idUser) {
- return $this->responseController->makeResponse(true, "El id del usuario no fue desencriptado correctamente", [], 400);
- }
- $usr = DB::table('S002V01TUSUA')->where([
- ['USUA_IDUS', '=', $idUser],
- ['USUA_NULI', '=', $form['linea']]
- ])->first();
- if(is_null($usr)) {
- return $this->responseController->makeResponse(true, 'El usuario no está registrado', [], 404);
- }
- try {
- DB::beginTransaction();
-
- $approvedCount = 0;
- $errors = [];
-
- foreach($form['equipment_ids'] as $encryptedId) {
- $equipmentId = $this->encryptionController->decrypt($encryptedId);
-
- if(!$equipmentId) {
- $errors[] = "ID de equipamiento inválido: $encryptedId";
- continue;
- }
-
- // Obtener equipamiento temporal
- $tempEquipment = DB::table('S002V01TPCEQ')
- ->where('PCEQ_IDPR', $equipmentId)
- ->where('PCEQ_NULI', $form['linea'])
- ->where('PCEQ_ESRE', 'Revisión')
- ->first();
-
- if(!$tempEquipment) {
- $errors[] = "Equipamiento no encontrado o ya procesado: $equipmentId";
- continue;
- }
-
- // Mover a tabla final de equipamientos
- $finalEquipmentData = $this->prepareFinalEquipmentData($tempEquipment, $idUser);
-
- $finalEquipmentId = DB::table('S002V01TEQUI')->insertGetId($finalEquipmentData);
-
- // Actualizar estado en tabla temporal
- DB::table('S002V01TPCEQ')
- ->where('PCEQ_IDPR', $equipmentId)
- ->update([
- 'PCEQ_ESRE' => 'Aprobado',
- 'PCEQ_USAP' => $idUser,
- 'PCEQ_FEAP' => Carbon::now('America/Mexico_city')->toDateTimeString()
- ]);
-
- $approvedCount++;
- }
-
- if($approvedCount === 0) {
- DB::rollBack();
- return $this->responseController->makeResponse(true, "No se pudo aprobar ningún equipamiento: " . implode('; ', $errors), [], 400);
- }
-
- DB::commit();
-
- // Registrar actividad
- $nowStr = Carbon::now('America/Mexico_city')->toDateTimeString();
- $name = $this->functionsController->joinName($usr->USUA_NOMB, $usr->USUA_APPA, $usr->USUA_APMA);
-
- $actions = DB::getQueryLog();
- $idac = $this->functionsController->registerActivity(
- $form['linea'],
- 'S002V01M07GEEQ',
- 'S002V01F01ADEQ',
- 'S002V01P11REEQ',
- 'Aprobación',
- "El usuario $name (" . $usr->USUA_IDUS . ") aprobó $approvedCount equipamientos.",
- $idUser,
- $nowStr,
- );
-
- $this->functionsController->registerLog($actions, $idUser, $nowStr, $idac, $form['linea']);
-
- $responseData = [
- 'equipos_aprobados' => $approvedCount,
- 'total_procesados' => count($form['equipment_ids'])
- ];
-
- if(!empty($errors)) {
- $responseData['errores'] = $errors;
- }
-
- return $this->responseController->makeResponse(false, "Aprobación exitosa", $responseData);
-
- } catch(Exception $e) {
- DB::rollBack();
- return $this->responseController->makeResponse(true, "Error al aprobar equipamientos: " . $e->getMessage(), [], 500);
- }
- }
- private function prepareFinalEquipmentData($tempEquipment, $approvingUserId) {
- $nowStr = Carbon::now('America/Mexico_city')->toDateTimeString();
-
- return [
- 'EQUI_NULI' => $tempEquipment->PCEQ_NULI,
- 'EQUI_COEQ' => $tempEquipment->PCEQ_CPGE,
- 'EQUI_JERA' => $tempEquipment->PCEQ_JERA,
- 'EQUI_EQPA' => $tempEquipment->PCEQ_EQPA,
- 'EQUI_TICO' => $tempEquipment->PCEQ_TICO,
- 'EQUI_UBOR' => $tempEquipment->PCEQ_UBOR,
- 'EQUI_NIOR' => $tempEquipment->PCEQ_NIOR,
- 'EQUI_OCOR' => $tempEquipment->PCEQ_OCOR,
- 'EQUI_ELOR' => $tempEquipment->PCEQ_ELOR,
- 'EQUI_FAMI' => $tempEquipment->PCEQ_FAMI,
- 'EQUI_SUBF' => $tempEquipment->PCEQ_SUBF,
- 'EQUI_ESEQ' => $tempEquipment->PCEQ_ESEQ,
- 'EQUI_TIEQ' => $tempEquipment->PCEQ_TIEQ,
- 'EQUI_MOEQ' => $tempEquipment->PCEQ_MOEQ,
- 'EQUI_FEAD' => $tempEquipment->PCEQ_FEAD,
- 'EQUI_FIGA' => $tempEquipment->PCEQ_FIGA,
- 'EQUI_FTGA' => $tempEquipment->PCEQ_FTGA,
- 'EQUI_PREQ' => $tempEquipment->PCEQ_PREQ,
- 'EQUI_NUSE' => $tempEquipment->PCEQ_NUSE,
- 'EQUI_GAIM' => $tempEquipment->PCEQ_GAIM,
- 'EQUI_DORE' => $tempEquipment->PCEQ_DORE,
- 'EQUI_USRE' => $approvingUserId,
- 'EQUI_FERE' => $nowStr,
- // Campos adicionales según el tipo de equipamiento
- 'EQUI_UBDE' => $tempEquipment->PCEQ_UBDE ?? null,
- 'EQUI_NIDE' => $tempEquipment->PCEQ_NIDE ?? null,
- 'EQUI_OCDE' => $tempEquipment->PCEQ_OCDE ?? null,
- 'EQUI_ELDE' => $tempEquipment->PCEQ_ELDE ?? null,
- 'EQUI_COOR' => $tempEquipment->PCEQ_COOR ?? null,
- 'EQUI_SEOR' => $tempEquipment->PCEQ_SEOR ?? null,
- 'EQUI_SEDE' => $tempEquipment->PCEQ_SEDE ?? null,
- 'EQUI_ARTR' => $tempEquipment->PCEQ_ARTR ?? null,
- ];
- }
- /**
- * Método para rechazar equipamientos
- */
- public function rejectEquipments(Request $request) {
- $validator = Validator::make($request->all(), [
- 'id_user' => 'required|string',
- 'linea' => 'required|integer',
- 'equipment_ids' => 'required|array',
- 'equipment_ids.*' => 'required|string',
- 'rejection_reason' => 'required|string'
- ]);
- if($validator->fails()) {
- return $this->responseController->makeResponse(
- true,
- "Se encontraron uno o más errores.",
- $this->responseController->makeErrors($validator->errors()->messages()),
- 401
- );
- }
- $form = $request->all();
- $idUser = $this->encryptionController->decrypt($form['id_user']);
-
- if(!$idUser) {
- return $this->responseController->makeResponse(true, "El id del usuario no fue desencriptado correctamente", [], 400);
- }
- try {
- DB::beginTransaction();
-
- $rejectedCount = 0;
-
- foreach($form['equipment_ids'] as $encryptedId) {
- $equipmentId = $this->encryptionController->decrypt($encryptedId);
-
- if($equipmentId) {
- DB::table('S002V01TPCEQ')
- ->where('PCEQ_IDPR', $equipmentId)
- ->where('PCEQ_NULI', $form['linea'])
- ->update([
- 'PCEQ_ESRE' => 'Rechazado',
- 'PCEQ_MORE' => $form['rejection_reason'],
- 'PCEQ_USRE' => $idUser,
- 'PCEQ_FERE' => Carbon::now('America/Mexico_city')->toDateTimeString()
- ]);
-
- $rejectedCount++;
- }
- }
-
- DB::commit();
-
- return $this->responseController->makeResponse(false, "Equipamientos rechazados exitosamente", [
- 'equipos_rechazados' => $rejectedCount
- ]);
-
- } catch(Exception $e) {
- DB::rollBack();
- return $this->responseController->makeResponse(true, "Error al rechazar equipamientos: " . $e->getMessage(), [], 500);
- }
- }
- }
- class ExcelTemplateConfig {
- public static function getTemplateConfigs() {
- return [
- 'TPCEQ' => [
- 'model' => 'S002V01TPCEQ',
- 'worksheets' => [
- 'EQUIPAMIENTO' => [
- 'table_start' => 'B9',
- 'table_end' => 'P9',
- 'header_row' => 7,
- 'date_start_row' => 9,
- 'field_mapping' => [
- 'A' => '',
- 'B' => 'PCEQ_OTCO', // Código Equivalente
- 'C' => 'PCEQ_TIEQ', // Tipo / Descripción
- 'D' => '', // Acrónimo del equipo
- 'E' => 'PCEQ_MOEQ', // Acrónimo del modelo
- 'F' => '', // Acrónimo del modelo
- 'G' => '', // Id
- 'H' => 'PCEQ_NUSE', // No. código de barras
- 'I' => 'PCEQ_COBA', // Carácter
- 'J' => 'PCEQ_CARA', // Proveedor del equipamiento
- 'K' => 'PCEQ_FVAR', // Fecha inicio de garantía
- 'L' => '', // Fecha de vencimiento del artículo
- ]
- ],
- 'LRU' => [
- 'table_start' => 'B9',
- 'table_end' => 'L9',
- 'header_row' => 7,
- 'date_start_row' => 9,
- 'field_mapping' => [
- 'A' => '',
- 'B' => 'PCEQ_TIEQ', // Tipo / Descripción
- 'C' => '', // Acrónimo del equipo
- 'D' => 'PCEQ_MOEQ', // Modelo completo
- 'E' => '', // Acrónimo del modelo
- 'F' => '', // Id
- 'G' => 'PCEQ_NUSE', // No. serie
- 'H' => 'PCEQ_COBA', // No. código de barras
- 'I' => 'PCEQ_CARA', // Carácter
- 'J' => 'PCEQ_FTGA', // Fecha de vencimiento del artículo
- 'K' => '', // Etiqueta final del equipo
- 'L' => '', // Código equivalente
- ]
- ],
- 'CASO 1' => [
- 'table_start' => 'B8',
- 'table_end' => 'AI8',
- 'header_row' => 7,
- 'date_start_row' => 8,
- 'field_mapping' => [
- 'A' => '',
- 'B' => 'PCEQ_NULI', // Línea
- 'C' => '.', // .
- 'D' => 'PCEQ_UBOR', // Ubicación
- 'E' => '.', // .
- 'F' => 'PCEQ_NIOR', // Nivel
- 'G' => '.', // .
- 'H' => 'PCEQ_OCOR', // Ocupación
- 'I' => '.', // .
- 'J' => 'PCEQ_ELOR', // Elemento
- 'K' => '+', // +
- 'L' => '', // Coordenadas plano
- 'M' => '', // Coordenadas detalle
- 'N' => '', // Coordenadas de posición
- 'O' => '_', // _
- 'P' => 'PCEQ_FAMI', // Familia
- 'Q' => '.', // .
- 'R' => 'PCEQ_SUBF', // Subfamilia
- 'S' => '.', // .
- 'T' => 'PCEQ_ESEQ', // Estado
- 'U' => '.', // .
- 'V' => 'PCEQ_TIEQ', // Tipo
- 'W' => '-', // -
- 'X' => 'PCEQ_MOEQ', // Modelo
- 'Y' => '-', // -
- 'Z' => '', // ID
- 'AA' => '.', // .
- 'AB' => 'PCEQ_TIEQ_HIJO', // Tipo
- 'AC' => '-', // -
- 'AD' => 'PCEQ_MOEQ_HIJO', // Modelo
- 'AE' => '-', // -
- 'AF' => '', // ID
- 'AG' => '', // Vacío
- 'AH' => 'PCEQ_CPGE', // Código completo SAM
- 'AI' => 'PCEQ_OTCO', // Código equivalente
- ]
- ],
- 'CASO 2' => [
- 'table_start' => 'B8',
- 'table_end' => 'AI8',
- 'header_row' => 7,
- 'date_start_row' => 8,
- 'field_mapping' => [
- 'A' => '',
- 'B' => 'PCEQ_NULI', // Línea
- 'C' => '.', // .
- 'D' => 'PCEQ_UBOR', // Ubicación
- 'E' => '.', // .
- 'F' => 'PCEQ_NIOR', // Nivel
- 'G' => '.', // .
- 'H' => 'PCEQ_OCOR', // Ocupación
- 'I' => '.', // .
- 'J' => 'PCEQ_ELOR', // Elemento
- 'K' => '+', // +
- 'L' => '', // Coordenadas plano
- 'M' => '', // Coordenadas detalle
- 'N' => '', // Coordenadas de posición
- 'O' => '_', // _
- 'P' => 'PCEQ_FAMI', // Familia
- 'Q' => '.', // .
- 'R' => 'PCEQ_SUBF', // Subfamilia
- 'S' => '.', // .
- 'T' => 'PCEQ_ESEQ', // Estado
- 'U' => '.', // .
- 'V' => 'PCEQ_TIEQ', // Tipo
- 'W' => '-', // -
- 'X' => 'PCEQ_MOEQ', // Modelo
- 'Y' => '-', // -
- 'Z' => '', // ID
- 'AA' => '.', // .
- 'AB' => 'PCEQ_TIEQ_HIJO', // Tipo
- 'AC' => '-', // -
- 'AD' => 'PCEQ_MOEQ_HIJO', // Modelo
- 'AE' => '-', // -
- 'AF' => '', // ID
- 'AG' => '', // Vacío
- 'AH' => 'PCEQ_CPGE', // Código completo SAM
- 'AI' => 'PCEQ_OTCO', // Código equivalente
- ]
- ],
- 'CASO 3' => [
- 'table_start' => 'B8',
- 'table_end' => 'AQ8',
- 'header_row' => 7,
- 'date_start_row' => 8,
- 'field_mapping' => [
- 'A' => '',
- 'B' => 'PCEQ_NULI', // Línea
- 'C' => '.', // .
- 'D' => 'PCEQ_UBOR', // Ubicación origen
- 'E' => '.', // .
- 'F' => 'PCEQ_NIOR', // Nivel origen
- 'G' => '.', // .
- 'H' => 'PCEQ_OCOR', // Ocupación origen
- 'I' => '.', // .
- 'J' => 'PCEQ_ELOR', // Elemento origen
- 'K' => '.', // .
- 'L' => 'PCEQ_KIOR', // PK origen
- 'M' => ':', // :
- 'N' => 'PCEQ_UBDE', // Ubicación destino
- 'O' => '.', // .
- 'P' => 'PCEQ_NIDE', // Nivel destino
- 'Q' => '.', // .
- 'R' => 'PCEQ_OCDE', // Ocupación destino
- 'S' => '.', // .
- 'T' => 'PCEQ_ELDE', // Elemento destino
- 'U' => '.', // .
- 'V' => 'PCEQ_KIDE', // PK destino
- 'W' => '-', // -
- 'X' => 'PCEQ_FAMI', // Familia
- 'Y' => '-', // -
- 'Z' => 'PCEQ_SUBF', // Subfamilia
- 'AA' => '.', // .
- 'AB' => 'PCEQ_ESEQ', // Estado
- 'AC' => '-', // -
- 'AD' => 'PCEQ_TIEQ', // Tipo
- 'AE' => '-', // -
- 'AF' => 'PCEQ_MOEQ', // Modelo
- 'AG' => '-', // -
- 'AH' => '', // ID
- 'AI' => '.', // .
- 'AJ' => 'PCEQ_TIEQ_HIJO', // Tipo
- 'AK' => '-', // -
- 'AL' => 'PCEQ_MOEQ_HIJO', // Modelo
- 'AM' => '-', // -
- 'AN' => 'PCEQ_IDPR', // ID
- 'AO' => '-', // -
- 'AP' => 'PCEQ_CPGE', // Código completo
- 'AQ' => 'PCEQ_OTCO', // Código equivalente
- ]
- ],
- 'CASO 4' => [
- 'table_start' => 'B8',
- 'table_end' => 'AY8',
- 'header_row' => 7,
- 'date_start_row' => 8,
- 'field_mapping' => [
- 'A' => '',
- 'B' => 'PCEQ_NULI', // Línea
- 'C' => '.', // .
- 'D' => 'PCEQ_UBOR', // Ubicación origen
- 'E' => '.', // .
- 'F' => 'PCEQ_NIOR', // Nivel origen
- 'G' => '.', // .
- 'H' => 'PCEQ_OCOR', // Ocupación origen
- 'I' => '.', // .
- 'J' => 'PCEQ_ELOR', // Elemento origen
- 'K' => '.', // .
- 'L' => 'PCEQ_SEOR', // Secuencial origen
- 'M' => '.', // .
- 'N' => '', // Coordenadas plano (concatenar con O,P)
- 'O' => '', // Coordenadas detalle
- 'P' => '', // Coordenadas de posición
- 'Q' => ':', // :
- 'R' => 'PCEQ_UBDE', // Ubicación destino
- 'S' => '.', // .
- 'T' => 'PCEQ_NIDE', // Nivel destino
- 'U' => '.', // .
- 'V' => 'PCEQ_OCDE', // Ocupación destino
- 'W' => '.', // .
- 'X' => 'PCEQ_ELDE', // Elemento destino
- 'Y' => '.', // .
- 'Z' => 'PCEQ_SEDE', // Secuencial destino
- 'AA' => '+', // +
- 'AB' => '', // Coordenadas plano (concatenar con AC,AD)
- 'AC' => '', // Coordenadas detalle
- 'AD' => '', // Coordenadas de posición
- 'AE' => '_', // _
- 'AF' => 'PCEQ_FAMI', // Familia
- 'AG' => '.', // .
- 'AH' => 'PCEQ_SUBF', // Subfamilia
- 'AI' => '.', // .
- 'AJ' => 'PCEQ_ESEQ', // Estado
- 'AK' => '.', // .
- 'AL' => 'PCEQ_TIEQ', // Tipo
- 'AM' => '-', // -
- 'AN' => 'PCEQ_MOEQ', // Modelo
- 'AO' => '-', // -
- 'AP' => '', // ID
- 'AQ' => '.', // .
- 'AR' => 'PCEQ_TIEQ_HIJO', // Tipo
- 'AS' => '-', // -
- 'AT' => 'PCEQ_MOEQ_HIJO', // Modelo
- 'AU' => '-', // -
- 'AV' => '', // ID
- 'AW' => '', // Vacío
- 'AX' => 'PCEQ_CPGE', // Código completo
- 'AY' => 'PCEQ_OTCO', // Código equivalente
- ]
- ],
- 'CASO 5' => [
- 'table_start' => 'B8',
- 'table_end' => 'AG8',
- 'header_row' => 7,
- 'date_start_row' => 8,
- 'field_mapping' => [
- 'A' => '',
- 'B' => 'PCEQ_NULI', // Línea
- 'C' => '.', // .
- 'D' => 'PCEQ_UBOR', // Ubicación
- 'E' => '.', // .
- 'F' => 'PCEQ_NIOR', // Nivel
- 'G' => '.', // .
- 'H' => 'PCEQ_OCOR', // Ocupación
- 'I' => '.', // .
- 'J' => 'PCEQ_ARTR', // Área
- 'K' => '.', // .
- 'L' => 'PCEQ_ELOR', // Elemento
- 'M' => '_', // _
- 'N' => 'PCEQ_FAMI', // Familia
- 'O' => '.', // .
- 'P' => 'PCEQ_SUBF', // Subfamilia
- 'Q' => '.', // .
- 'R' => 'PCEQ_ESEQ', // Estado
- 'S' => '.', // .
- 'T' => 'PCEQ_TIEQ', // Tipo
- 'U' => '-', // -
- 'V' => 'PCEQ_MOEQ', // Modelo
- 'W' => '-', // -
- 'X' => '', // ID
- 'Y' => '.', // .
- 'Z' => 'PCEQ_TIEQ_HIJO', // Tipo LRU
- 'AA' => '-', // -
- 'AB' => 'PCEQ_MOEQ_HIJO', // Modelo LRU
- 'AC' => '-', // -
- 'AD' => '', // ID LRU
- 'AE' => '', // Vacío
- 'AF' => 'PCEQ_CPGE', // Código completo
- 'AG' => 'PCEQ_OTCO', // Código equivalente
- ]
- ],
- 'CASO 6' => [
- 'table_start' => '',
- 'table_end' => '',
- 'header_row' => 7,
- 'date_start_row' => 8,
- 'field_mapping' => [
- 'A' => '', // Vacío
- 'B' => 'PCEQ_NULI', // Linea
- 'C' => '.', // .
- 'D' => 'PCEQ_UBOR', // Ubicación
- 'E' => '.', // .
- 'F' => 'PCEQ_NIOR', // Nivel
- 'G' => '.', // .
- 'H' => 'PCEQ_OCOR', // Ocupación
- 'I' => '.', // .
- 'J' => 'PCEQ_ELOR', // Elemento
- 'K' => '.', // .
- 'L' => 'PCEQ_COOR', // Posición
- 'M' => '_', // _
- 'N' => 'PCEQ_FAMI', // Familia
- 'O' => '.', // .
- 'P' => 'PCEQ_SUBF', // Subfamilia
- 'Q' => '.', // .
- 'R' => 'PCEQ_ESEQ', // Estado
- 'S' => '.', // .
- 'T' => 'PCEQ_TIEQ', // Tipo
- 'U' => '-', // -
- 'V' => 'PCEQ_MOEQ', // Modelo
- 'W' => '-', // -
- 'X' => 'PCEQ_IDPR', // ID
- 'Y' => '.', // .
- 'Z' => 'PCEQ_TIEQ_HIJO', // Tipo
- 'AA' => '-', // -
- 'AB' => 'PCEQ_MOEQ_HIJO', // Modelo
- 'AC' => '-', // -
- 'AD' => 'PCEQ_LRID', // ID
- 'AE' => '', // Vacío
- 'AF' => 'PCEQ_CPGE', // Código completo
- 'AG' => 'PCEQ_OTCO', // Código equivalente
- ]
- ]
- ]
- ],
- ];
- }
- };
|