From 3b86212755f41e69182533d6fefcca851cd11378 Mon Sep 17 00:00:00 2001 From: ygbanzato Date: Thu, 18 Jan 2024 08:54:17 +0000 Subject: [PATCH] Updating the creation of projects --- .../CreateProjectController copy.php | 1525 +++++++++++++++++ .../Controllers/CreateProjectController.php | 504 +++--- .../ExecutionProjectController.php | 49 +- .../Controllers/ProjectoDatacontroller.php | 22 +- .../ViewComposers/WorkstationComposer.php | 214 +-- .../SelectElementalTasksInWonkstation.php | 19 +- app/Models/CompanyProject.php | 4 + app/Models/Equipment.php | 11 +- app/Models/EquipmentWorkHistory.php | 15 + public/templateExcel/FinalTemplate1.xlsx | Bin 56044 -> 0 bytes ...TestTemplate.xlsx => Valves_Template.xlsx} | Bin 66213 -> 68452 bytes .../views/Templates/templateAdmin.blade.php | 34 +- .../Templates/templateWorkstations.blade.php | 8 +- .../projectsClients/articulated_2.blade.php | 408 +++-- .../articulated_2_ShowEquipment.blade.php | 16 +- .../projectsClients/workStation_3.blade.php | 2 + routes/web.php | 25 +- 17 files changed, 2316 insertions(+), 540 deletions(-) create mode 100755 app/Http/Controllers/CreateProjectController copy.php delete mode 100755 public/templateExcel/FinalTemplate1.xlsx rename public/templateExcel/{TestTemplate.xlsx => Valves_Template.xlsx} (52%) mode change 100755 => 100644 diff --git a/app/Http/Controllers/CreateProjectController copy.php b/app/Http/Controllers/CreateProjectController copy.php new file mode 100755 index 00000000..ea10f0e0 --- /dev/null +++ b/app/Http/Controllers/CreateProjectController copy.php @@ -0,0 +1,1525 @@ +first(); + + if (!$PlantData) { + return response()->json([]); + } + + $receiveUnits = Unit::where('plant_id', $PlantData->plant_id)->get(); + + // Formatar a resposta para o formato esperado pelo JavaScript + $formattedUnits = $receiveUnits->map(function ($unit) { + return [ + 'id' => $unit->receiveUnits, // Ajuste para o nome da sua coluna correta + 'name' => $unit->unit_name // Ajuste para o nome da sua coluna correta + ]; + }); + + return response()->json($formattedUnits); + } + + + public function deleteFurtherTasks(Request $request) + { + $receiveDataEquipment = Equipment::where('equipment_id', $request->equipmentID)->first(); + // Buscar os registros que correspondem ao equipmentID e que têm further_tasks_id nos selectedTasks + $tasksToDelete = OrderEquipmentTasks::where('equipment_id', $request->equipmentID) + ->whereIn('further_tasks_id', $request->selectedTasks) + ->get(); + + // Excluir esses registros + foreach ($tasksToDelete as $task) { + $task->delete(); + } + + // Se o treatmentFurtherTask for "DeleteFurtherTask", exclua os registros da tabela principal FurtherTasks + if ($request->treatmentFurtherTask == "DeleteFurtherTask") { + FurtherTasks::whereIn('further_tasks_id', $request->selectedTasks)->delete(); + } + + // Reordenar os registros restantes + $remainingTasks = OrderEquipmentTasks::where('equipment_id', $request->equipmentID) + ->orderBy('execution_order', 'asc') + ->get(); + + $executionOrder = 1; + foreach ($remainingTasks as $task) { + $task->execution_order = $executionOrder; + $task->save(); + $executionOrder++; + } + return redirect()->back()->with('success', 'Ordem de execução do equipamento: ' . $receiveDataEquipment->equipment_tag . ' Atulizada!'); + } + + public function addFurtherTasks(Request $request) + { + // Recebe e organiza os dados do equipameto recebido : ($request->equipmentID) e organiza em asc de acordo com a Ordem de execução + $equipmentId = $request->equipmentID; + $tasksToReorder = OrderEquipmentTasks::where('equipment_id', $equipmentId) + ->orderBy('execution_order', 'asc') + ->get(); + + $receiveDataEquipment = Equipment::where('equipment_id', $request->equipmentID)->first(); + + + // *Para Criar uma nova Tarefa complementar deve ser a soma dos dados das 2 tabelas para dar o numero da proxima tarefa e assim o numero da TC + // Obtenha a contagem de registros nas tabelas ElementalTasks e FurtherTasks + $elementalTasksCount = ElementalTasks::count(); + $furtherTasksCount = FurtherTasks::count(); + + // Calcule o valor de further_tasks_id + $newFurtherTaskId = $elementalTasksCount + $furtherTasksCount + 1; + + // Calcule o valor de further_tasks_name + $newFurtherTaskName = 'TC' . ($furtherTasksCount + 1); + + + + $insertPosition = $request->ArrayListElementsTasks + 1; + + // Incrementar a execution_order das tarefas após a posição de inserção + foreach ($tasksToReorder as $task) { + if ($task->execution_order >= $insertPosition) { + $task->execution_order += 1; + $task->save(); + } + } + + // Agora, insira a nova tarefa na posição desejada + $newOrderEquipmentTask = new OrderEquipmentTasks; + $newOrderEquipmentTask->equipment_id = $equipmentId; + $newOrderEquipmentTask->execution_order = $insertPosition; + $newOrderEquipmentTask->elemental_tasks_id = null; + + // Se o selectedFurtherTaskExisting for null quer dizer que e uma TC complementar criada e nova se nao for null quer dizer que vamos criar uma TC existente. + if ($request->selectedFurtherTaskExisting == 'null') { + + // Cria uma nova tarefa Complementar + $newFurtherTask = new FurtherTasks; + $newFurtherTask->further_tasks_id = $newFurtherTaskId; + $newFurtherTask->further_tasks_name = $newFurtherTaskName; + $newFurtherTask->further_tasks_description = $request->furtherTask; + $newFurtherTask->company_projects_id = $receiveDataEquipment->company_projects_id; + $newFurtherTask->save(); + + $newOrderEquipmentTask->further_tasks_id = $newFurtherTask->further_tasks_id; + } else { + $newOrderEquipmentTask->further_tasks_id = $request->selectedFurtherTaskExisting; + } + + $newOrderEquipmentTask->inspection = 2; + $newOrderEquipmentTask->save(); + + return redirect()->back()->with('success', 'Ordem de execução do equipamento: ' . $receiveDataEquipment->equipment_tag . ' Atulizada!'); + } + + + public function receiveEquipmentToAssociateTasks(Request $request) + { + // dd($request); + + foreach ($request->equipment as $equipment) { + $equipmentModel = Equipment::where('equipment_id', $equipment['equipment_id'])->first(); + + if ($equipmentModel) { + $equipmentModel->company_projects_id = $request->receiveNumberProject; + $equipmentModel->save(); + } + } + return redirect()->back()->with('success', 'Equipametos associados a Obra com Sucesso !'); + } + + public function receiveUnitsForExcelTemplate($numberProject) + { + $receveCompanyProject = CompanyProject::where('company_projects_id', $numberProject)->first(); + $recevePlant = Plant::where('plant_id', $receveCompanyProject->plant_id)->first(); + $receveUnits = Unit::where('plant_id', $recevePlant->plant_id)->get(); + $filePath = public_path('templateExcel/TestTemplate.xlsx'); + // Load the spreadsheet + $spreadsheet = IOFactory::load($filePath); + // Get the second sheet + $sheet = $spreadsheet->getSheet(1); // Sheet index starts from 0 + $row = 1; // Row number where you want to start inserting data + foreach ($receveUnits as $unit) { + // Set value for column D + $sheet->setCellValue('D' . $row, $unit->unit_name); + $row++; + } + // Generate and return the download response + return $this->createDownloadResponse($spreadsheet, 'Valves_Template.xlsx'); + } + + protected function createDownloadResponse($spreadsheet, $filename) + { + // Create a writer object + $writer = new Xlsx($spreadsheet); + // Create a StreamedResponse with a callback + $response = new StreamedResponse( + function () use ($writer) { + $writer->save('php://output'); + } + ); + // Set headers to indicate we're sending an Excel file + $response->headers->set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); + $response->headers->set('Content-Disposition', 'attachment;filename="' . $filename . '"'); + $response->headers->set('Cache-Control', 'max-age=0'); + + return $response; + } + + public function finishCreatingProject($numberProject) + { + // recebe atraves de sessao toda a vez quem entra no componente 'SelectElementalTasksInWonkstation' para selecionar as tarefas de cada Workstation + $receiveAllFurtherTasks = session('receiveAllFurtherTasks'); + $receiveElementalTasks = session('receiveElementalTasks'); + + // Inicializar a matriz de IDs faltantes + $missingElementalTasks = []; + $missingFurtherTasksDetails = []; + $missingWorkstations = []; + + // Recebe todos os dados dos postos de Trabalho + $receiveWorkstaions = ConstructionWorkstation::where('company_projects_id', $numberProject)->get(); + + foreach ($receiveWorkstaions as $workstation) { + // Verifica se o ID da workstation está presente na tabela WorkstationsAssociationTasks + $exists = WorkstationsAssociationTasks::where('id_workstations', $workstation->id_workstations)->exists(); + + // Se não existe na tabela, adiciona à lista das workstations onde nao tem tarefas atribuidas ainda. + if (!$exists) { + $missingWorkstations[$workstation->id_workstations] = [ + 'name_workstations' => $workstation->name_workstations, + 'nomenclature_workstation' => $workstation->nomenclature_workstation + ]; + } + } + + // Extrai apena o id_workstations de cada um + $workstationIds = $receiveWorkstaions->pluck('id_workstations')->toArray(); + + // Iterar sobre cada tarefa em $receiveElementalTasks + foreach ($receiveElementalTasks as $taskGroup) { + foreach ($taskGroup as $taskId => $taskDetails) { + // Verificar se a tarefa está associada a algum id_workstations + $exists = WorkstationsAssociationTasks::whereIn('id_workstations', $workstationIds) + ->where('elemental_tasks_id', $taskId) + ->exists(); + + // Se não existe, adicionar à lista de tarefas faltantes + if (!$exists) { + $missingElementalTasks[$taskId] = $taskDetails; + } + } + } + + // Iterar sobre cada tarefa em $receiveAllFurtherTasks + foreach ($receiveAllFurtherTasks as $furtherTask) { + // Obter o ID da tarefa + $taskId = $furtherTask->further_tasks_id; + + // Verificar se a tarefa está associada a algum id_workstations + $exists = WorkstationsAssociationTasks::whereIn('id_workstations', $workstationIds) + ->where('further_tasks_id', $taskId) + ->exists(); + + // Se não existe, adicionar à lista de tarefas faltantes + if (!$exists) { + $missingFurtherTasksDetails[$taskId] = [ + 'name' => $furtherTask->further_tasks_name, + 'description' => $furtherTask->further_tasks_description + ]; + } + } + + // A Partir daqui ja temos as 2 variaveis a receberem array com as tarefas que faltam ser associadas. + $allMissingTasks = [ + 'elemental' => $missingElementalTasks, + 'further' => $missingFurtherTasksDetails, + 'workstation' => $missingWorkstations + ]; + // Verificar se todos os arrays internos estão vazios + $isEmpty = empty($allMissingTasks['elemental']) && empty($allMissingTasks['further']) && empty($allMissingTasks['workstation']); + + if (!$isEmpty) { + return redirect()->back()->with('errors', $allMissingTasks); + } else { + $project = CompanyProject::find($numberProject); + $project->order_project = 2; + $project->save(); + + return redirect()->route('home'); + } + } + + public function deleteWorkstation($name) + { + $workstation = ConstructionWorkstation::where('name_workstations', $name)->first(); + $removeAcountUserWorkstation = User::where('user_name', $workstation->name_workstations)->first(); + + if ($workstation && $removeAcountUserWorkstation) { + $workstation->delete(); + $removeAcountUserWorkstation->delete(); + + // pegar o número da estação de trabalho que está sendo deletada + preg_match('/workstation(\d+)-/', $workstation->name_workstations, $matches); + $deletedWorkstationNumber = $matches[1]; + + // pega o número do projeto da estação de trabalho que está sendo deletada + $projectNumber = explode('-', $workstation->name_workstations)[1]; + + // pegar todas as estações de trabalho e Utilizadors com números maiores que o deletado e renumerá-los + $workstationsToUpdate = ConstructionWorkstation::where('company_projects_id', $projectNumber) + ->whereRaw("SUBSTRING_INDEX(name_workstations, '-', 1) REGEXP '^workstation[0-9]+$'") + ->whereRaw("CAST(SUBSTRING(SUBSTRING_INDEX(name_workstations, '-', 1), 12) AS UNSIGNED) >= ?", [$deletedWorkstationNumber]) + ->orderByRaw("CAST(SUBSTRING(SUBSTRING_INDEX(name_workstations, '-', 1), 12) AS UNSIGNED) DESC") + ->get(); + + foreach ($workstationsToUpdate as $workstationToUpdate) { + // pegar o número da estação de trabalho atual + preg_match('/workstation(\d+)-/', $workstationToUpdate->name_workstations, $matches); + $currentWorkstationNumber = $matches[1]; + + // atualizar nome da estação de trabalho + $workstationToUpdate->name_workstations = 'workstation' . ($currentWorkstationNumber - 1) . '-' . $projectNumber; + $workstationToUpdate->save(); + + // atualizar Utilizador associado + $userToUpdate = User::where('user_name', 'workstation' . $currentWorkstationNumber . '-' . $projectNumber)->first(); + if ($userToUpdate) { + $userToUpdate->user_name = 'workstation' . ($currentWorkstationNumber - 1) . '-' . $projectNumber; + $userToUpdate->save(); + } + } + + return back()->with('success', 'Posto de Trabalho removido com sucesso!'); + } + return back()->with('danger', 'Posto de Trabalho não encontrado!'); + } + + public function removeProjectEquipment(Request $request) + { + + $equipment = Equipment::find($request->EquipmentID); + + if ($request->removalType == 'total') { + $equipment->delete(); + + return back()->with('success', 'Equipamento Excluido com sucesso!'); + } else + $equipment->company_projects_id = null; + $equipment->save(); + + return back()->with('success', 'Equipamento retirado da obra !'); + } + public function EditEquipmentsProjects(Request $request) + { + // dd($request); + // Localiza o equipment pelo numberProject + $equipment = Equipment::find($request->equipmentId); + + // Atualiza os campos + $equipment->equipment_tag = $request->tag; + $equipment->equipment_description = $request->equipmentDescription; + $equipment->equipment_serial_number = $request->serialNumberEquipment; + $equipment->equipment_brand = $request->equipmentBrand; + $equipment->equipment_model = $request->equipmentModel; + + $equipment->save(); + + if ($request->input('attributes')) { + foreach ($request->input('attributes') as $key => $value) { + // Verifica se o valor é null e a chave é um número (correspondendo aos general_attributes_equipment_id) + if ($value == null && is_numeric($key)) { + // Procura o registro relevante em SpecificAttributesEquipmentType + $specificAttributes = SpecificAttributesEquipmentType::where('equipment_id', $request->equipmentId) + ->where('general_attributes_equipment_id', $key) + ->first(); + + // Se o registro existir, o deleta + if ($specificAttributes) { + $specificAttributes->delete(); + } + } + // Se o valor não for null, atualiza ou cria um novo registro + elseif ($value !== null && is_numeric($key)) { + + // Procura o registro relevante em SpecificAttributesEquipmentType + $specificAttributes = SpecificAttributesEquipmentType::where('equipment_id', $request->equipmentId) + ->where('general_attributes_equipment_id', $key) + ->first(); + + // Se o registro existir, atualiza o valor + if ($specificAttributes) { + $specificAttributes->specific_attributes_value = $value; + $specificAttributes->save(); + } + // Se não existir, cria um novo + else { + // Cria um novo registro em SpecificAttributesEquipmentType + $specificAttributes = new SpecificAttributesEquipmentType(); + $specificAttributes->equipment_id = $request->equipmentId; + $specificAttributes->equipment_type_id = $equipment->equipment_type_id; + $specificAttributes->general_attributes_equipment_id = $key; + $specificAttributes->specific_attributes_value = $value; + $specificAttributes->save(); + } + } + } + } + + + // Se não selecionar nenhuma tarefas ele devolve um erro , pois e necessario pelo menos uma + if (!in_array('on', $request->input('ordemTasks'))) { + return redirect()->back()->with('danger', 'É necessário selecionar pelo menos uma tarefa, Para o Equipamento : ' . $equipment->equipment_tag); + } + $executionOrder = 1; + + foreach ($request->input('ordemTasks') as $key => $value) { + $orderEquipmentTask = OrderEquipmentTasks::where('equipment_id', $request->equipmentId) + ->where('elemental_tasks_id', $key) + ->first(); + + if ($value == "on") { + if (!$orderEquipmentTask) { + $orderEquipmentTask = new OrderEquipmentTasks(); + $orderEquipmentTask->equipment_id = $request->equipmentId; + $orderEquipmentTask->elemental_tasks_id = $key; + } + $orderEquipmentTask->execution_order = $executionOrder; + $orderEquipmentTask->save(); + + $executionOrder++; + } elseif ($value == "off" && $orderEquipmentTask) { + $orderEquipmentTask->delete(); + } + } + + + $executionOrder = 1; // Reinicia a contagem de ordem de execução + $remainingOrderEquipmentTasks = OrderEquipmentTasks::where('equipment_id', $request->equipmentId) + ->orderBy('execution_order', 'asc') + ->get(); + + foreach ($remainingOrderEquipmentTasks as $orderEquipmentTask) { + $orderEquipmentTask->execution_order = $executionOrder; + $orderEquipmentTask->save(); + $executionOrder++; + } + + $orderTasks = OrderEquipmentTasks::where('equipment_id', $request->equipmentId) + ->orderBy('execution_order', 'asc') + ->get(); + + $taskExecutionOrders = []; + foreach ($orderTasks as $task) { + $taskExecutionOrders[$task->elemental_tasks_id] = $task->execution_order; + } + + // Retorna uma resposta + return redirect()->route('test2', ['id' => $request->numberProject]) + ->with('success', 'Equipamento ' . $equipment->equipment_tag . ' Editado com Sucesso!!!') + ->with('taskExecutionOrders', $taskExecutionOrders); + } + + public function showJson($id) + { + $attributes = SpecificAttributesEquipmentType::where('equipment_id', $id)->get(); + $OrdemTasks = OrderEquipmentTasks::where('equipment_id', $id)->get(); + $allElementalTasks = ElementalTasks::all(); + + return response()->json([ + 'attributes' => $attributes, + 'OrdemTasks' => $OrdemTasks, + 'allElementalTasks' => $allElementalTasks + ]); + } + + public function receveTasksWorkstationPlanning($WorkstationId) + { + $workstationsAssociationTasks = WorkstationsAssociationTasks::where('id_workstations', $WorkstationId)->get(); + + return response()->json([ + 'workstationsAssociationTasks' => $workstationsAssociationTasks + ]); + } + + + public function createWorkStations(Request $request) + { + // Pega o número de estações de trabalho do request + $numberWorkstations = $request->numberWorkstations; + + // Pega o número do projeto do request + $numberProject = $request->numberProject; + + $listWorkstations = ConstructionWorkstation::where('company_projects_id', $numberProject)->get(); + $receveProjectCompanyNumber = CompanyProject::where('company_projects_id', $numberProject)->first(); + + // Pega o último elemento da lista + $lastWorkstation = $listWorkstations->last(); + + + // Se houver uma estação de trabalho anterior, extrai o número dela + $startNumber = 1; + if ($lastWorkstation) { + $parts = explode('-', $lastWorkstation->name_workstations); + $startNumber = intval(str_replace('workstation', '', $parts[0])) + 1; + } + + // Loop para criar as estações de trabalho e seus logins + for ($i = $startNumber; $i < $startNumber + $numberWorkstations; $i++) { + $workstation = new ConstructionWorkstation(); + $workstation->name_workstations = 'workstation' . $i . '-' . $numberProject; + $workstation->company_projects_id = $numberProject; + $workstation->save(); + + preg_match('/workstation(\d+)-/', $workstation->name_workstations, $matches); + $receiveNumberWorkstation = $matches[1]; + + //Apos criar a Workstation vamos criar um login para pode aceder os postos de trabalho na obra + $loginWorkStation = new User; + $loginWorkStation->user_name = $workstation->name_workstations; + $loginWorkStation->email = $receveProjectCompanyNumber->project_company_number . '-' . $receiveNumberWorkstation . '@isptgroup.com'; + $loginWorkStation->password = bcrypt($receveProjectCompanyNumber->project_company_number . '-' . $receiveNumberWorkstation); + $loginWorkStation->type_users = 5; + $loginWorkStation->user_nif = $receveProjectCompanyNumber->project_company_number . '-' . $receiveNumberWorkstation; + $loginWorkStation->save(); + } + + // Redireciona para onde você quiser após a criação das workstations + return redirect()->route('test3', ['id' => $request->numberProject]) + ->with('success', $numberWorkstations . ' Postos de Trabalho criados !!!') + ->with('listWorkstations', $listWorkstations); + } + + + // Funcao apenas para retornar os dados necessarios para a view criar uma Obra. + public function createProjectForStep1() + { + $companies = User::where('type_users', 3)->get(); + // Apos terminar não vai ficar step 1 + return view('projectsClients/createProject', ['step' => 1], ['companies' => $companies]); + } + + // Progress Bar + //Devolve para a primeira para na Descrição do projecto apenas user com ID 3, quer dizer que apenas as "empresas" + public function showStep1($company_projects_id) + { + // $projects = CompanyProject::find($company_projects_id); + + $projects = CompanyProject::with('user')->find($company_projects_id); + // dd($projects->user); + + $companies = User::where('type_users', 3)->get(); + + return view('projectsClients/projectDetails_1', ['step' => 1], ['companies' => $companies]) + ->with('projects', $projects); + } + + // Se forem alterados dados dos Detalhes da Obra, vai ser alterado + public function EditprocessStep1(Request $request) + { + } + + public function removePendingEquipment($id) + { + $equipment = PendingEquipment::findOrFail($id); + $equipment->delete(); + return back()->with('success', 'Equipamento pendente removido com sucesso!'); + } + + public function CreateNewEquipmentFromPendingEquipment(Request $request, $id) + { + $checkPendingEquipment = PendingEquipment::findOrFail($id); + + $counter = 2; + $baseTag = $checkPendingEquipment->pending_equipment_tag; + $baseDescription = $checkPendingEquipment->pending_equipment_description; + + // Ciclo para verificar se ja existe um equipamento com o mesmo nome se existir vai criando com o contador iniciado a partir de (2) + while (Equipment::where('equipment_tag', $baseTag . "({$counter})")->orWhere('equipment_description', $baseDescription . "({$counter})")->exists()) { + $counter++; + } + + $newEquipment = new Equipment; + $newEquipment->unit_id = $checkPendingEquipment->pending_equipment_unit_id; + $newEquipment->equipment_type_id = $checkPendingEquipment->pending_equipment_type_id; + $newEquipment->equipment_tag = $baseTag . "({$counter})"; + $newEquipment->equipment_description = $baseDescription . "({$counter})"; + $newEquipment->equipment_serial_number = $checkPendingEquipment->pending_equipment_serial_number; + $newEquipment->equipment_brand = $checkPendingEquipment->pending_equipment_brand; + $newEquipment->equipment_model = $checkPendingEquipment->pending_equipment_model; + $newEquipment->company_projects_id = $checkPendingEquipment->pending_company_projects_id; + $newEquipment->save(); + + $receiveEquipmentID = $newEquipment->equipment_id; + + $newEquipmentAssociationAmbits = new EquipmentAssociationAmbit; + $newEquipmentAssociationAmbits->equipment_type_id = $newEquipment->equipment_type_id; + $newEquipmentAssociationAmbits->ambits_id = $request->EquipmentAmbit; + $newEquipmentAssociationAmbits->equipment_id = $receiveEquipmentID; + $newEquipmentAssociationAmbits->save(); + + + + $checkPendingEquipment->delete(); + + return back()->with('success', 'Equipamento ' . $newEquipment->equipment_tag . ' criado com sucesso'); + } + + + public function processStep1(Request $request) + { + // Validação... + $installationId = $request->input('installation_id'); + + if ($installationId == 'new_install') { + + // Criar uma nova instalação... + $newInstallation = new Plant; + + $newInstallation->plant_name = $request->input('new_company_name'); + $newInstallation->plant_address = $request->input('new_company_address'); + $newInstallation->user_id = $request->input('user_id'); + + $newInstallation->save(); + + // Use o id da nova instalação. + $installationId = $newInstallation->plant_id; + } + + $project = new CompanyProject; + + $project->company_project_description = $request->input('description_project'); + $project->project_ispt_number = $request->input('n_project_ispt'); + $project->project_company_number = $request->input('project_company_number'); + $project->project_ispt_responsible = $request->input('responsible_project_ispt'); + $project->project_company_responsible = $request->input('responsible_project_company'); + + // Verifica se e igual a nulo , se for usa a data ja existente + if ($request->date_started === null) { + $project->date_started = $request->input('date_started_present'); + } else + $project->date_started = $request->input('date_started'); + + $project->plant_id = $installationId; + $project->order_project = 1; + + $project->save(); + + session(['form_data.step1' => $request->all()]); + + // // Redirecione o Utilizador para a próxima etapa + // return redirect('/test2') + // ->with('project', $project) + // ->with('success', 'Dados guardados com sucesso'); + return redirect()->route('test2', ['id' => $project->company_projects_id]) + ->with('success', 'Detalhes, Projecto criado com sucesso'); + } + + public function showStep2($company_projects_id) + { + // Verifique se a etapa 1 foi concluída + + // if (!session('form_data.step1')) { + // return redirect('/createProject'); + // } + + //recebe o Id de Plant vai devolver todos os equipamentos relacionados a esta Instalação(plant) + // Carregue o projeto com o id fornecido + $project = CompanyProject::find($company_projects_id); + + $numberProject = $project->company_projects_id; + + $typeEquipments = EquipmentType::all(); + + //Retorna todas as Fabricas Unit, com base na Instalação + $checkUnits = DB::table('units') + ->join('plants', 'units.plant_id', '=', 'plants.plant_id') + ->join('company_projects', 'plants.plant_id', '=', 'company_projects.plant_id') + ->select('units.*') + ->where('company_projects.company_projects_id', '=', $company_projects_id) + ->get(); + + //Retorna todos os Equipamentos, com base na instalcao do projecto + $checkEquipments = DB::table('equipments') + ->join('units', 'equipments.unit_id', '=', 'units.unit_id') + ->join('plants', 'units.plant_id', '=', 'plants.plant_id') + ->select('equipments.*') // Seleciona todas as colunas da tabela 'equipments' + ->where('plants.plant_id', '=', $project['plant_id']) // Filtra baseado no 'plant_id' + ->get(); + + // Para listar os equipamentos vinculados na obra, buscamos suas associações gerais entre suas tabelas , ou seja a : fabrica(unit), tipo de equipamento e o Âmbito para se realizar a tarefas pretendida neste obra. + $listEquipmentsProjects = Equipment::with([ + 'unit', + 'equipmentType', + // 'equipmentAssociationAmbit.ambitsEquipment', + 'specificAttributes' => function ($query) { + $query->orderBy('specific_attributes_value', 'asc'); + } + ]) + ->where('company_projects_id', $company_projects_id) + ->get(); + + dd($listEquipmentsProjects); + + $pendingEquipments = PendingEquipment::where('pending_company_projects_id', $numberProject)->get(); + + if (!$pendingEquipments->isEmpty()) { + // Retornamos para a view 'step' => 2 indicando conclusao da primeira parte, $numberProject para associacao de equipamentos a esta obra, alem de todos os equipamentos e fabricao ja existente com base na Instalação que se iniciou a obra. + return view('projectsClients/articulated_2', ['step' => 2, 'numberProject' => $numberProject]) + ->with('danger', 'Equipamentos Pendentes: ' . count($pendingEquipments)) + ->with('pendingEquipments', $pendingEquipments) + ->with('listEquipmentsProjects', $listEquipmentsProjects) + ->with('typeEquipments', $typeEquipments) + ->with('checkEquipments', $checkEquipments) + ->with('checkUnits', $checkUnits) + ->with('receiveNumberProject', $project); + } + return view('projectsClients/articulated_2', ['step' => 2, 'numberProject' => $numberProject]) + ->with('listEquipmentsProjects', $listEquipmentsProjects) + ->with('typeEquipments', $typeEquipments) + ->with('checkEquipments', $checkEquipments) + ->with('checkUnits', $checkUnits) + ->with('receiveNumberProject', $project); + } + + public function createEquipmentManual(Request $request) + { + // EquipmentAmbit + // *** Recebe a Instalação(Plant), com base no número da Obra Criada + $receivePlant = DB::table('plants') + ->join('company_projects', 'company_projects.plant_id', 'plants.plant_id') + ->select('plants.plant_id') + ->where('company_projects.company_projects_id', '=', $request->numberProject) + ->get(); + + //recebe a lista de todos os equipmentos relacionados a obra que se esta a criar. + $listEquipmentsProjects = DB::table('equipments') + ->select('equipments.*') + ->where('equipments.company_projects_id', '=', $request->numberProject) + ->get(); + + // Verifica se ja existe um equipamento com as as caracteristicas : tag,unit_id, iguais ao que pretendemos criar + $existingEquipment = Equipment::firstWhere([ + 'equipment_tag' => $request->tag, + 'unit_id' => $request->unit_id + ]); + + if ($existingEquipment) { + return redirect()->route('test2', ['id' => $request->numberProject]) + ->with('danger', 'Equipamento ja Existe !!') + ->with('listEquipmentsProjects', $listEquipmentsProjects); + } + + // Se realmente for um equipamento novo, verifica se ira associar a uma fabrica (unit) nova ou ja existente + $newEquipmentProject = new Equipment; + + // Se for uma fabrica(Unit) existente + if ($request->new_unit_name == null) { + $newEquipmentProject->unit_id = $request->unit_id; + } else { + + //ja retorna se for uma fabrica nova (Unit) + $newUnit = new Unit; + $newUnit->unit_name = $request->new_unit_name; + $newUnit->plant_id = $receivePlant[0]->plant_id; + $newUnit->save(); + + $newEquipmentProject->unit_id = $newUnit->unit_id; + } + + $newEquipmentProject->equipment_type_id = $request->equipmentTypeId; + $newEquipmentProject->equipment_tag = $request->tag; + $newEquipmentProject->equipment_description = $request->equipmentDescription; + + // Estes campos a baixo : podem ter valor ou não + $newEquipmentProject->equipment_serial_number = $request->serialNumberEquipment ?? NULL; + $newEquipmentProject->equipment_brand = $request->equipmentBrand ?? NULL; + $newEquipmentProject->equipment_model = $request->equipmentModel ?? NULL; + + $newEquipmentProject->company_projects_id = $request->numberProject; + + $newEquipmentProject->save(); + + // ID do equipamento criado + $equipmentID = $newEquipmentProject->equipment_id; + + $newEquipmentWorkHistorys = new EquipmentWorkHistory; + + $newEquipmentWorkHistorys->equipment_id = $equipmentID; + $newEquipmentWorkHistorys->ispt_number = 0; + $newEquipmentWorkHistorys->company_projects_id = $request->numberProject; + + $newEquipmentWorkHistorys->save(); + + $equipmentWorkHistorysID = $newEquipmentWorkHistorys->equipmentWorkHistorys_id; + + // Verifica os campos do Card_do tipo de valvula selecionado (Ex: psv_card) e de acordo com os campos preenchidos se for de atributos especificos, ele compara o 'name' dos inputs com os 'general_attributes_equipment_description' da tabela : GeneralAttributesEquipment e associa + $checkAtributs = GeneralAttributesEquipment::whereIn('general_attributes_equipment_description', array_keys($request->all())) + ->pluck('general_attributes_equipment_id', 'general_attributes_equipment_description') + ->toArray(); + + // Recebe esta associacao, e cria um array para cada 'name'(inputs) igual ao 'general_attributes_equipment_description', contanto que seu valor(input) seja diferente de *NULL, assim o "$receivesAssociationAttributes" recebe o id de acordo com a tabela , o nome de acordo com a tabela e o valor do $request recebido associado ao campo + $receivesAssociationAttributes = []; + foreach ($checkAtributs as $description => $id) { + if ($request[$description] !== null) { + $receivesAssociationAttributes[] = [ + 'general_attributes_equipment_id' => $id, + 'general_attributes_equipment_description' => $description, + 'value' => $request[$description] + ]; + } + } + // Para cada um dos Arrays criados acima, vai criar os novos dados na tabela 'SpecificAttributesEquipmentType' + foreach ($receivesAssociationAttributes as $receivesAssociationAttribute) { + + $AddAtributsEquipments = new SpecificAttributesEquipmentType; + $AddAtributsEquipments->equipment_id = $equipmentID; + $AddAtributsEquipments->equipment_type_id = $request->equipmentTypeId; + $AddAtributsEquipments->general_attributes_equipment_id = $receivesAssociationAttribute['general_attributes_equipment_id']; + $AddAtributsEquipments->specific_attributes_value = $receivesAssociationAttribute['value']; + + $AddAtributsEquipments->save(); + } + //Criar associacao do equipamento ao Âmbito + $AssociationEquipmentAmbit = new EquipmentAssociationAmbit; + $AssociationEquipmentAmbit->equipment_type_id = $request->equipmentTypeId; + $AssociationEquipmentAmbit->ambits_id = $request->EquipmentAmbit; + $AssociationEquipmentAmbit->equipmentWorkHistorys_id = $equipmentWorkHistorysID; + + $AssociationEquipmentAmbit->save(); + + $execution_order = 1; + + //Recebe a tabela com as associoacoes entre Âmbitos e tarefas Elementares + $TasksAssociationAmbits = TasksAssociationAmbits::all()->where('ambits_equipment_id', $AssociationEquipmentAmbit->ambits_id); + + foreach ($TasksAssociationAmbits as $TasksAssociationAmbit) { + $JoinsEquipmentsWithTasks = new OrderEquipmentTasks; + $JoinsEquipmentsWithTasks->equipmentWorkHistorys_id = $equipmentWorkHistorysID; + $JoinsEquipmentsWithTasks->execution_order = $execution_order++; + $JoinsEquipmentsWithTasks->elemental_tasks_id = $TasksAssociationAmbit->elemental_tasks_id; + $JoinsEquipmentsWithTasks->further_tasks_id = null; + $JoinsEquipmentsWithTasks->inspection = 2; + $JoinsEquipmentsWithTasks->save(); + } + + // O $request->numberProject e sempre necessario retornar para indicar a obra que se esta modificando... + return redirect()->route('test2', ['id' => $request->numberProject]) + ->with('success', 'Equipamento criado com sucesso') + ->with('listEquipmentsProjects', $listEquipmentsProjects); + } + public function receiveIdEquipment(Equipment $equipment) + { + // return response()->json($equipment); + return view('projectsClients/articulated_2', ['equipment' => $equipment]); + } + + public function processStep2(Request $request) + { + // Valide e processe os dados do formulário + $file = $request->file('documento'); + + // Recebe a id do Projecto criado + $company_projects_id = $request->numberProject; + + // Inicializa o contador para ispt_number + $isptNumber = 1; + + // Certifique-se de que um arquivo foi enviado + if ($file) { + // Carregue o arquivo Excel + $spreadsheet = IOFactory::load($file->path()); + + // Obtenha a primeira planilha, onde fica os nomes chaves para associar as tabelas : 'general_attributes_equipaments' ,'equipments' e 'equipmentWorkHistorys' + $worksheet = $spreadsheet->getSheet(0); + + // Transforme os dados da planilha em um array + $data = $worksheet->toArray(); + + + // Retorna um array com todos os names preenchidos na primeira linha do template de Excel + $nomesColunas = $data[0]; + + // dd($data); + + $countPendingEquipments = 0; + $countNewEquipment = 0; + + $linhasIgnoradas = []; + + // Comece a partir da sexta linha do template os dados dos Equipamentos + for ($i = 6; $i < count($data); $i++) { + + $dadosLinha = $data[$i]; + + // Verifica se os 5 primeiros campos essenciais estao preenchidos, um deles não estiver preenchido ele ignora e não cria o equipamento + // $isEmpty = false; + // for ($j = 0; $j < 5; $j++) { + // if (empty($dadosLinha[$j])) { + // $isEmpty = true; + // break; + // } + // } + // if ($isEmpty) { + // continue; + // } + + $dadosLinha = $data[$i]; + + // Verifica se a coluna 'fábrica' (primeiro campo) está vazia + if (empty($dadosLinha[0])) { + // Se a coluna 'fábrica' estiver vazia, pule para a próxima linha + continue; + } + + // Verifica se os 5 primeiros campos essenciais estão preenchidos + for ($j = 0; $j < 5; $j++) { + if (empty($dadosLinha[$j])) { + // Se um campo (exceto 'fábrica') estiver vazio, adicione a linha e o índice do campo vazio às linhas ignoradas + $linhasIgnoradas[] = [ + 'linha' => $i, + 'campoVazio' => $nomesColunas[$j] // ou simplesmente $j se não tiver o nome da coluna + ]; + continue 2; // Pula para a próxima linha + } + } + + + // Em cada um das linhas horizontais do excel, vai se guardar a 'key' vinculada ao valor do campo preenchido ou seja a 'key' vai ter o mesmo nome de um dos dados da tabela 'general_attributes_equipaments' na coluna : general_attributes_equipment_description, assim sendo mais facil implementar na tabela : specific_attributes_equipament_types + $juntarArrays = array_combine($nomesColunas, $dadosLinha); + + // vai guardar todos os campos de possiveis novos equipamentos, cada um em um array para multiplos inserts, na base de dados + $datas = array_filter($juntarArrays, function ($chave) { + return !empty($chave); + }, ARRAY_FILTER_USE_KEY); + + //Indentifica qual o tipo de equipamento selecionado de acordo com a tabela EquipmentType + $equipmentType = EquipmentType::where('equipment_type_name', $datas['equipment_type_name'])->first(); + + $checkFactory = Unit::where('unit_name', $datas['unit'])->first(); + + // Antes de criar o novo equipamento, verifique se já existe um equipamento + // com o mesmo factory_id e tag. + $existingEquipment = Equipment::where('unit_id', $checkFactory->unit_id) + ->where('equipment_tag', $datas['equipment_tag']) + ->first(); + + if ($existingEquipment) { + + // Se o equipamento existir, crie o novo equipamento na tabela pending_equipaments. + $pendingEquipament = new PendingEquipment; + + // Defina os atributos do pendingEquipament conforme necessário. + $pendingEquipament->pending_equipment_unit_id = $checkFactory->unit_id; + $pendingEquipament->pending_equipment_type_id = $equipmentType->equipment_type_id; + $pendingEquipament->pending_equipment_tag = $datas['tag']; + $pendingEquipament->pending_equipment_description = $datas['equipment_Description']; + $pendingEquipament->pending_equipment_serial_number = $datas['n_serie']; + $pendingEquipament->pending_equipment_brand = $datas['modelo']; + $pendingEquipament->pending_company_projects_id = $company_projects_id; + $pendingEquipament->save(); + + // Incremente o contador de PendingEquipments + $countPendingEquipments++; + + // Continue com o próximo loop. + continue; + } + + $newEquipament = new Equipment; + + $newEquipament->unit_id = $checkFactory->unit_id; + $newEquipament->equipment_type_id = $equipmentType->equipment_type_id; + $newEquipament->equipment_Description = $datas['equipment_description']; + $newEquipament->equipment_tag = $datas['equipment_tag']; + $newEquipament->equipment_serial_number = $datas['equipment_serial_number']; + $newEquipament->equipment_brand = $datas['equipment_brand']; + $newEquipament->equipment_model = $datas['equipment_model']; + $newEquipament->ispt_number = $isptNumber; + $newEquipament->company_projects_id = $company_projects_id; + + $newEquipament->save(); + + $countNewEquipment++; + + $isptNumber++; + + // Guardo os valores de 'id' e do 'tipo de equipamento' que nosso novo equipamento acabado de criar + $receveEquipment_ID = $newEquipament->equipment_id; + $receveEquipament_type_ID = $newEquipament->equipment_type_id; + + + $ambit = AmbitsEquipment::where('ambits_description', $datas['ambit'])->first(); + + if ($ambit) { + $ambit_id = $ambit->ambits_id; + } + + //Criar associacao do equipamento ao Âmbito + $AssociationEquipmentAmbit = new EquipmentAssociationAmbit; + $AssociationEquipmentAmbit->equipment_type_id = $receveEquipament_type_ID; + $AssociationEquipmentAmbit->ambits_id = $ambit_id; + $AssociationEquipmentAmbit->equipment_id = $receveEquipment_ID; + $AssociationEquipmentAmbit->save(); + + $execution_order = 1; + + //Recebe a tabela com as associoacoes entre Âmbitos e tarefas Elementares + $TasksAssociationAmbits = TasksAssociationAmbits::all()->where('ambits_equipment_id', $AssociationEquipmentAmbit->ambits_id); + + foreach ($TasksAssociationAmbits as $TasksAssociationAmbit) { + $JoinsEquipmentsWithTasks = new OrderEquipmentTasks; + $JoinsEquipmentsWithTasks->equipment_id = $receveEquipment_ID; + $JoinsEquipmentsWithTasks->execution_order = $execution_order++; + $JoinsEquipmentsWithTasks->elemental_tasks_id = $TasksAssociationAmbit->elemental_tasks_id; + $JoinsEquipmentsWithTasks->further_tasks_id = null; + // 2 vai significar 'nao' e 1 'sim' + $JoinsEquipmentsWithTasks->inspection = 2; + $JoinsEquipmentsWithTasks->save(); + } + + + $generalAttributes = GeneralAttributesEquipment::all(); + + + foreach ($generalAttributes as $generalAttribute) { + // Verifica se a chave existe em $datas, comparando com os dados da tabela : GeneralAttributesEquipment assim adicionando todos diferentes de NULL relacionados com o equipamento acabado de cria + if (isset($datas[$generalAttribute->general_attributes_equipment_description])) { + + $specificAttribute = new SpecificAttributesEquipmentType; + $specificAttribute->equipment_id = $receveEquipment_ID; + $specificAttribute->equipment_type_id = $receveEquipament_type_ID; + $specificAttribute->general_attributes_equipment_id = $generalAttribute->general_attributes_equipment_id; + // Atribui o valor da chave correspondente em $datas + $specificAttribute->specific_attributes_value = $datas[$generalAttribute->general_attributes_equipment_description]; + + $specificAttribute->save(); + } + } + } + dd($linhasIgnoradas); + + + $pendingEquipments = PendingEquipment::where('pending_company_projects_id', $request->numberProject)->get(); + + // $pendingEquipments = session('pendingEquipments'); + if ($countPendingEquipments != 0) { + // return redirect()->route('test2')->with('Danger', 'Equipamentos Pendentes')->with('listValves', $listValves)->with('pendingEquipments', $pendingEquipments); + return redirect()->route('test2', ['id' => $request->numberProject]) + ->with('danger', 'Equipamentos Pendentes criados : ' . $countPendingEquipments) + ->with('pendingEquipments', $pendingEquipments); + // ->with('success', 'Equipamentos Criados :' . count($listValves)) + } + return redirect()->route('test2', ['id' => $request->numberProject]) + ->with('success', 'Equipamentos Criados :' . $countNewEquipment); + } + + //Nao chega aqui ainda pois volta para a pagina com dados ja carregados. + + session(['form_data.step2' => $request->all()]); + + // Redirecione o Utilizador para a próxima etapa + return redirect('/test3'); + } + + public function showStep3($company_projects_id) + { + $equipments = Equipment::where('company_projects_id', $company_projects_id) + ->get(); + + foreach ($equipments as $equipment) { + $tags = []; + if ($equipment->equipment_type_id == 3) { + $tags = ['@Corpo', '@Flange', '@Obturador']; + } elseif ($equipment->equipment_type_id == 1) { + $tags = ['@Corpo', '@Flange']; + } + + foreach ($tags as $tag) { + $associatedEquipment = QrcodesAssociatedEquipment::where('equipment_id', $equipment->equipment_id) + ->where('component_tag', 'LIKE', '%' . $tag) + ->first(); + + if ($associatedEquipment) { + // Atualizar a coluna component_tag para ser igual à equipment_tag, mantendo a parte após o "@" + $newComponentTag = $equipment->equipment_tag . $tag; + $associatedEquipment->component_tag = $newComponentTag; + $associatedEquipment->save(); + } else { + // Criar uma nova entrada + QrcodesAssociatedEquipment::create([ + 'equipment_id' => $equipment->equipment_id, + 'component_tag' => $equipment->equipment_tag . $tag + ]); + } + } + } + + // 3. Verificar se há algum equipment_id em QrcodesAssociatedEquipment que não existe mais em Equipment e, se sim, excluí-lo. + $allEquipmentIds = Equipment::where('company_projects_id', $company_projects_id)->pluck('equipment_id')->toArray(); + $orphanedEntries = QrcodesAssociatedEquipment::whereNotIn('equipment_id', $allEquipmentIds)->get(); + + foreach ($orphanedEntries as $orphanedEntry) { + $orphanedEntry->delete(); + } + + + + //Sempre que entrar na view ja verifica se existe 'Workstations' preparadas para esta obra. + $listWorkstations = ConstructionWorkstation::where('company_projects_id', $company_projects_id)->get(); + + $futherTasks = FurtherTasks::where('company_projects_id', $company_projects_id) + ->get(); + + return view('projectsClients/workStation_3', ['step' => 3, 'numberProject' => $company_projects_id]) + ->with('listWorkstations', $listWorkstations) + ->with('equipments', $equipments) + ->with('futherTasks', $futherTasks); + } + + public function workstationsAssociationTasks(Request $request) + { + // dd($request); + + $workStation = ConstructionWorkstation::where('id_workstations', $request->idWorkStation)->first(); + + // Trocar o nome se for diferente do recebido + if ($workStation) { + $workStation->nomenclature_workstation = $request->nameWorkstation; + $workStation->save(); + } + + // Atualizar a lista de tipos de tarefas para incluir os novos grupos + $taskTypes = ['generalTasks', '1', '2', '3', 'FurtherTasks']; + + foreach ($taskTypes as $groupTasks) { + if (isset($request[$groupTasks])) { // Checar se esse grupo de tarefas existe no request + foreach ($request[$groupTasks] as $taskID => $check) { + + if ($groupTasks == 'FurtherTasks') { + // Encontra a tarefa existente, se houver, para FurtherTasks + $taskAssociation = WorkstationsAssociationTasks::where('id_workstations', $workStation->id_workstations) + ->where('further_tasks_id', $taskID) + ->where('company_projects_id', $workStation->company_projects_id) + ->first(); + } else { + // Encontra a tarefa existente, se houver, para os outros grupos + $taskAssociation = WorkstationsAssociationTasks::where('id_workstations', $workStation->id_workstations) + ->where('elemental_tasks_id', $taskID) + ->where('company_projects_id', $workStation->company_projects_id) + ->first(); + } + + if ($check == 'on') { + if (!$taskAssociation) { + $taskAssociation = new WorkstationsAssociationTasks; + $taskAssociation->id_workstations = $workStation->id_workstations; + if ($groupTasks == 'FurtherTasks') { + $taskAssociation->further_tasks_id = $taskID; // Usando $taskID, que é a key + } else { + $taskAssociation->elemental_tasks_id = $taskID; // Usando $taskID, que é a key + } + $taskAssociation->company_projects_id = $workStation->company_projects_id; + } + $taskAssociation->save(); + } elseif ($check == 'off' && $taskAssociation) { + $taskAssociation->delete(); + } + } + } + } + + + // Redirecionar de volta com uma mensagem de sucesso + return back()->with('success', 'Posto de trabalho : ' . $workStation->name_workstations . ' atualizado com sucesso!'); + } + + public function processStep3(Request $request) + { + // Valide e processe os dados do formulário + // ... + session(['form_data.step3' => $request->all()]); + + // Aqui, todas as etapas foram concluídas + // Você pode redirecionar o Utilizador para uma página de "Obrigado" ou processar os dados do formulário + // ... + } + + public function index() + { + // $results = DB::table('equipaments') + // ->join('specific_attributes_equipament_types', 'equipaments.equipment_ID', '=', 'specific_attributes_equipament_types.tb_equipament_id') + // ->join('general_attributes_equipaments', 'specific_attributes_equipament_types.specific_Attributes_Equipment_Type_ID', '=', 'general_attributes_equipaments.general_Attributes_Equipment_ID') + // ->select('equipaments.tag', 'general_attributes_equipaments.description', 'specific_attributes_equipament_types.value') + // ->get(); + + $results = DB::table('equipments') + ->join('specific_attributes_equipament_types', 'equipments.equipment_id', '=', 'specific_attributes_equipament_types.equipment_id') + ->join('general_attributes_equipaments', 'specific_attributes_equipament_types.specific_attributes_equipment_type_id', '=', 'general_attributes_equipaments.general_attributes_equipment_id') + ->select('equipments.equipment_tag', 'general_attributes_equipaments.general_attributes_equipment_description', 'specific_attributes_equipament_types.specific_attributes_value') + ->get(); + + + // dd($results); + + $groupedEquipments = []; + + foreach ($results as $result) { + if (!isset($groupedEquipments[$result->tag])) { + $groupedEquipments[$result->tag] = []; + } + + $groupedEquipments[$result->tag][] = [ + 'description' => $result->description, + 'value' => $result->value + ]; + } + + $equipments = DB::table('equipments')->get(); + + foreach ($equipments as $equipment) { + if (isset($groupedEquipments[$equipment->tag])) { + $equipment->specific_attributes = $groupedEquipments[$equipment->tag]; + } + } + $allPossibleAttributes = GeneralAttributesEquipment::all()->pluck('description')->toArray(); + + return view('test2', ['equipments' => $equipments, 'allAttributes' => $allPossibleAttributes]); + // Retorne a view com os dados + // return view('test', ['equipments' => $equipments]); + } + + + public function listCompanies() + { + $companies = User::where('type_users', 3)->get(); + return view('projectsClients/createProject', ['companies' => $companies]); + } + + + public function createProject(Request $request) + { + + // Validação... + $installationId = $request->input('installation_id'); + + if ($installationId == 'new_install') { + // Criar uma nova instalação... + $newInstallation = new Unit; + $newInstallation->installation_name = $request->input('new_company_name'); + $newInstallation->address = $request->input('new_company_address'); + $newInstallation->user_id = $request->input('user_id'); + + $newInstallation->save(); + + // Use o id da nova instalação. + $installationId = $newInstallation->id; + // dd($installationId); + } + + $project = new CompanyProject; + + $project->description_project = $request->input('description_project'); + $project->n_project_ispt = $request->input('n_project_ispt'); + $project->responsible_project_ispt = $request->input('responsible_project_ispt'); + $project->responsible_project_company = $request->input('responsible_project_company'); + $project->date_started = $request->input('date_started'); + + $project->installation_id = $installationId; + + $project->save(); + + return redirect()->route('createProject')->with('success', 'Dados guardados com sucesso'); + // return redirect()->route('createProject')->with('success', 'Dados guardados com sucesso'); + + } + + public function storeProject(Request $request) + { + if ($request->input('company_id') == 'new') { + $company = new CompanyProject; // Substitua "Company" pelo nome do seu modelo de empresas + $company->name = $request->input('new_company_name'); + $company->save(); + + $company_id = $company->id; + } else { + $company_id = $request->input('company_id'); + } + + // Agora, você pode usar $company_id ao criar o projeto + } + + public function getByUserNif(Request $request) + { + + // dd(Plant::where('user_id', $request->input('user_id'))->get()); + + $user_id = $request->input('user_id'); //Check + $installations = Plant::where('user_id', $user_id)->get(); + + return response()->json($installations); + } + + public function getAmbits($equipmentType) + { + + $ambits = DB::table('ambits_equipments') + ->select('ambits_equipments.*') + ->where('ambits_equipments.equipment_type_id', $equipmentType) + ->get(); + return response()->json($ambits); + } + + public function getAttributes($id) + { + $equipment = Equipment::with('specificAttributes')->find($id); + return response()->json($equipment->specificAttributes); + } + + // public function createEquipamentProject(Request $request) + // { + // $file = $request->file('documento'); + + // // Certifique-se de que um arquivo foi enviado + // if ($file) { + // // Carregue o arquivo Excel + // $spreadsheet = IOFactory::load($file->path()); + + // // Obtenha a primeira planilha + // $worksheet = $spreadsheet->getSheet(0); + + // // Transforme os dados da planilha em um array + // $data = $worksheet->toArray(); + + // $nomesColunas = $data[0]; + + // $dadosLinha6 = $data[6]; + + // $juntarArrays = array_combine($nomesColunas, $dadosLinha6); + + // $datas = array_filter($juntarArrays, function ($chave) { + // return !empty($chave); + // }, ARRAY_FILTER_USE_KEY); + + // $equipamentType = equipament_type::where('equipment_type_name', $datas['tipo_equipamento'])->first(); + // $checkFactory = factorie::where('factories_name', $datas['fabrica'])->first(); + + + // $newEquipament = new equipament; + // //Primeiro tem de derificar se a fabrica existe, senão cria uma. + // $newEquipament->factory_id = $checkFactory->factories_id; + // $newEquipament->equipament_type_id = $equipamentType->equipament_type_id; + // $newEquipament->equipment_Description = $datas['equipment_Description']; + // $newEquipament->tag = $datas['tag']; + // $newEquipament->serial_number = $datas['n_serie']; + // $newEquipament->model = $datas['modelo']; + + // $newEquipament->save(); + + + // $receveEquipment_ID = $newEquipament->id; + // $receveEquipament_type_ID = $newEquipament->equipament_type_id; + + + // // Atributos que você quer buscar e inserir + // $attributes = ["dimension", "dn_ent", "p&id", "n_sap", "isolation", "scaffolding", "grua", "interlocks"]; + + // // $attributes = array_slice($data[0], 7); + + // foreach ($attributes as $attribute) { + + // // Buscar o atributo na tabela general_attributes_equipament + // $generalAttribute = general_attributes_equipament::where('description', $attribute)->first(); + + + // // Se o atributo foi encontrado + // if (!is_null($generalAttribute)) { + // // Criar um novo registro em specific_attributes_equipament_Types + // $specificAttribute = new specific_attributes_equipament_type; + + // $specificAttribute->tb_equipament_id = $receveEquipment_ID; + // $specificAttribute->equipament_Type_id = $receveEquipament_type_ID; + // $specificAttribute->specific_attributes_equipment_type_id = $generalAttribute->general_attributes_equipment_id; + // $specificAttribute->value = $datas[$attribute]; + + // $specificAttribute->save(); + // } + // } + // $listValves = equipament::all(); + + // return redirect()->route('testExcel')->with('success', 'Dados guardados com sucesso')->with('listValves', $listValves); + // } + // } + + + + + // public function createEquipamentProject(Request $request) + // { + // $file = $request->file('documento'); + + // // Certifique-se de que um arquivo foi enviado + // if ($file) { + // // Carregue o arquivo Excel + // $spreadsheet = IOFactory::load($file->path()); + + // // Obtenha a primeira planilha + // $worksheet = $spreadsheet->getSheet(0); + + // // Transforme os dados da planilha em um array + // $data = $worksheet->toArray(); + + // $nomesColunas = $data[0]; + + // // Atributos que você quer buscar e inserir + // $attributes = ["dimension", "dn_ent", "p&id", "n_sap", "isolation", "scaffolding", "grua", "interlocks"]; + + // // Comece a partir da sexta linha + // for ($i = 6; $i < count($data); $i++) { + + // $dadosLinha = $data[$i]; + + // //Se não preencher o campo $dadosLinha[0], não cria um novo equipamento + // //Trocar pelos 5 primeiros + // if (empty($dadosLinha[0])) { + // continue; + // } + + + // $juntarArrays = array_combine($nomesColunas, $dadosLinha); + + // $datas = array_filter($juntarArrays, function ($chave) { + // return !empty($chave); + // }, ARRAY_FILTER_USE_KEY); + + // $equipmentType = EquipmentType::where('equipment_type_name', $datas['tipo_equipamento'])->first(); + + // $checkFactory = Unit::where('unit_name', $datas['fabrica'])->first(); + + + // // Antes de criar o novo equipamento, verifique se já existe um equipamento + // // com o mesmo factory_id e tag. + // $existingEquipment = Equipment::where('unit_id', $checkFactory->unit_id) + // ->where('equipment_tag', $datas['tag']) + // ->first(); + + // if ($existingEquipment) { + // // Se o equipamento existir, crie o novo equipamento na tabela pending_equipaments. + // $pendingEquipament = new PendingEquipment; + // // Defina os atributos do pendingEquipament conforme necessário. + // $pendingEquipament->pending_equipment_unit_id = $checkFactory->unit_id; + // $pendingEquipament->pending_equipment_type_id = $equipmentType->equipment_type_id; + // $pendingEquipament->pending_equipment_tag = $datas['tag']; + // $pendingEquipament->pending_equipment_description = $datas['equipment_Description']; + // $pendingEquipament->pending_equipment_serial_number = $datas['n_serie']; + // $pendingEquipament->pending_equipment_brand = $datas['modelo']; + + // $pendingEquipament->save(); + + // // Adicione uma variável de sessão para indicar que um equipamento pendente foi criado. + // session(['pendingEquipmentCreated' => true]); + + // // Adicione uma variável de sessão para indicar que um equipamento pendente foi criado. + // session()->push('pendingEquipments', $pendingEquipament); + + // // Continue com o próximo loop. + // continue; + // } + + // $newEquipament = new Equipment; + + // $newEquipament->unit_id = $checkFactory->unit_id; + // $newEquipament->equipment_type_id = $equipmentType->equipment_type_id; + // $newEquipament->equipment_Description = $datas['equipment_Description']; + // $newEquipament->equipment_tag = $datas['tag']; + // $newEquipament->equipment_serial_number = $datas['n_serie']; + // $newEquipament->equipment_model = $datas['modelo']; + + // $newEquipament->save(); + + // $receveEquipment_ID = $newEquipament->equipment_id; + + // $receveEquipament_type_ID = $newEquipament->equipment_type_id; + + + // foreach ($attributes as $attribute) { + + // $generalAttribute = GeneralAttributesEquipment::where('general_attributes_equipment_description', $attribute)->first(); + + // if (!is_null($generalAttribute)) { + + // $specificAttribute = new SpecificAttributesEquipmentType; + + // $specificAttribute->equipment_id = $receveEquipment_ID; + // $specificAttribute->equipment_type_id = $receveEquipament_type_ID; + // $specificAttribute->specific_attributes_equipment_type_id = $generalAttribute->general_attributes_equipment_id; + // $specificAttribute->specific_attributes_value = $datas[$attribute]; + + // // $specificAttribute->save(); + // } + // } + // } + + // $listValves = Equipment::all(); + // $pendingEquipments = PendingEquipment::all(); + + // // return redirect()->route('createProject')->with('success', 'Dados guardados com sucesso')->with('listValves', $listValves); + + // // return redirect()->route('createProject')->with('success', 'Dados guardados com sucesso')->with('listValves', $listValves)->with('pendingEquipments', $pendingEquipments); + + // $listValves = Equipment::all(); + // $pendingEquipments = session('pendingEquipments'); + // if ($pendingEquipments) { + // return redirect()->route('createProject')->with('success', 'Dados guardados com sucesso')->with('listValves', $listValves)->with('pendingEquipments', $pendingEquipments); + // } else { + // return redirect()->route('createProject')->with('success', 'Dados guardados com sucesso')->with('listValves', $listValves); + // } + // } + // } +} diff --git a/app/Http/Controllers/CreateProjectController.php b/app/Http/Controllers/CreateProjectController.php index 85c49cb3..9dfd9d8b 100755 --- a/app/Http/Controllers/CreateProjectController.php +++ b/app/Http/Controllers/CreateProjectController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Models\EquipmentWorkHistory; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use PhpOffice\PhpSpreadsheet\IOFactory; @@ -36,6 +37,106 @@ class CreateProjectController extends Controller { + public function changeAmbitEquipment(Request $request) + { + + $receiveAmbitEquipmentId = $request->receveAmbit; + + $equipmentId = $request->equipmentID; + + // $receiveEquipment = Equipment::where('equipment_id', $equipmentId)->first(); + + // $receiveEquipmentWorkHistorys = EquipmentWorkHistory::where('equipment_id',$receiveEquipment->equipment_id) + // ->where('company_projects_id', $receiveEquipment->company_projects_id ) + // ->first(); + + // $receiveDataEquipmentAssociationAmbit = EquipmentAssociationAmbit::where('equipmentWorkHistorys_id',$receiveEquipmentWorkHistorys->equipmentWorkHistorys_id)->first(); + + // if($receiveDataEquipmentAssociationAmbit->ambits_id == $receiveAmbitEquipmentId){ + + // return back()->with('danger', 'Ambito selecionado, igual ao anterior!'); + // } else { + // $receiveDataEquipmentAssociationAmbit->ambits_id = $receiveAmbitEquipmentId; + // $receiveDataEquipmentAssociationAmbit->save(); + + + // } + + $receiveEquipment = Equipment::where('equipment_id', $equipmentId)->first(); + + $receiveEquipmentWorkHistorys = EquipmentWorkHistory::where('equipment_id', $receiveEquipment->equipment_id) + ->where('company_projects_id', $receiveEquipment->company_projects_id) + ->first(); + + $receiveDataEquipmentAssociationAmbit = EquipmentAssociationAmbit::where('equipmentWorkHistorys_id', $receiveEquipmentWorkHistorys->equipmentWorkHistorys_id)->first(); + + if ($receiveDataEquipmentAssociationAmbit->ambits_id == $receiveAmbitEquipmentId) { + return back()->with('danger', 'Âmbito selecionado é igual ao anterior!'); + } else { + // Deleta as tarefas associadas ao equipamento no âmbito atual + OrderEquipmentTasks::where('equipmentWorkHistorys_id', $receiveEquipmentWorkHistorys->equipmentWorkHistorys_id)->delete(); + + // Atualiza o âmbito do equipamento + $receiveDataEquipmentAssociationAmbit->ambits_id = $receiveAmbitEquipmentId; + $receiveDataEquipmentAssociationAmbit->save(); + + // Insere as novas tarefas para o novo âmbito + $TasksAssociationAmbits = TasksAssociationAmbits::where('ambits_equipment_id', $receiveAmbitEquipmentId)->get(); + $execution_order = 1; + foreach ($TasksAssociationAmbits as $TasksAssociationAmbit) { + $JoinsEquipmentsWithTasks = new OrderEquipmentTasks; + $JoinsEquipmentsWithTasks->equipmentWorkHistorys_id = $receiveEquipmentWorkHistorys->equipmentWorkHistorys_id; + $JoinsEquipmentsWithTasks->execution_order = $execution_order++; + $JoinsEquipmentsWithTasks->elemental_tasks_id = $TasksAssociationAmbit->elemental_tasks_id; + $JoinsEquipmentsWithTasks->further_tasks_id = null; + $JoinsEquipmentsWithTasks->inspection = 2; // ou outro valor conforme necessário + $JoinsEquipmentsWithTasks->save(); + } + + return back()->with('success', 'Equipamento: ' . $receiveEquipment->equipment_id . ' trocado de âmbito com sucesso!'); + } + + } + + public function deleteEquipmentInProject(Request $request) + { + $receiveEquipmentId = $request->equipmentId; + $receiveEquipment = Equipment::where('equipment_id', $receiveEquipmentId)->first(); + $receiveStatus = $request->deleteEquipmentProject; + + if ($receiveStatus == 'complete') { + EquipmentWorkHistory::where('equipment_id', $receiveEquipment->equipment_id) + ->where('company_projects_id', $receiveEquipment->company_projects_id) + ->delete(); + $receiveEquipment->delete(); + + return redirect()->back() + ->with('success', 'Equipamento: ' . $receiveEquipment->equipment_id . ' excluído com sucesso!'); + } else { + $receiveEquipment->company_projects_id = null; + $receiveEquipment->save(); + + return redirect()->back() + ->with('success', 'Equipamento: ' . $receiveEquipment->equipment_id . ' retirado da obra com sucesso!'); + } + } + + + + public function deletePendingEquipments(Request $request) + { + $pendingEquipmentIds = $request->input('pendingEquipmentIds', []); + + // Verifica se o array não está vazio + if (!empty($pendingEquipmentIds)) { + // Deleta todos os registros de PendingEquipment que correspondam aos IDs + PendingEquipment::whereIn('pending_equipment_id', $pendingEquipmentIds)->delete(); + } + + return redirect()->back() + ->with('success', 'Todos os equipamentos pendentes apagados com sucesso!'); + } + public function receiveUnits($numberProject) { @@ -174,7 +275,7 @@ public function receiveUnitsForExcelTemplate($numberProject) $receveCompanyProject = CompanyProject::where('company_projects_id', $numberProject)->first(); $recevePlant = Plant::where('plant_id', $receveCompanyProject->plant_id)->first(); $receveUnits = Unit::where('plant_id', $recevePlant->plant_id)->get(); - $filePath = public_path('templateExcel/TestTemplate.xlsx'); + $filePath = public_path('templateExcel/Valves_Template.xlsx'); // Load the spreadsheet $spreadsheet = IOFactory::load($filePath); // Get the second sheet @@ -185,8 +286,13 @@ public function receiveUnitsForExcelTemplate($numberProject) $sheet->setCellValue('D' . $row, $unit->unit_name); $row++; } + + $formattedDateTime = date('Y-m-d_H-i'); // Formato: Ano-Mês-Dia_Hora-Minuto + $fileName = "Valves_Template_{$numberProject}_{$formattedDateTime}.xlsx"; + // Generate and return the download response - return $this->createDownloadResponse($spreadsheet, 'Valves_Template.xlsx'); + // return $this->createDownloadResponse($spreadsheet, 'Valves_Template.xlsx'); + return $this->createDownloadResponse($spreadsheet, $fileName); } protected function createDownloadResponse($spreadsheet, $filename) @@ -659,6 +765,7 @@ public function processStep1(Request $request) public function showStep2($company_projects_id) { + $groupedArrayForPendingEquipments = session('groupedArrayForPendingEquipments'); // Verifique se a etapa 1 foi concluída // if (!session('form_data.step1')) { @@ -693,10 +800,11 @@ public function showStep2($company_projects_id) // $listEquipmentsProjects = Equipment::with(['unit', 'equipmentType', 'equipmentAssociationAmbit.ambitsEquipment']) // ->where('company_projects_id', $company_projects_id) // ->get(); + $listEquipmentsProjects = Equipment::with([ 'unit', 'equipmentType', - 'equipmentAssociationAmbit.ambitsEquipment', + // 'equipmentAssociationAmbit.ambitsEquipment', 'specificAttributes' => function ($query) { $query->orderBy('specific_attributes_value', 'asc'); } @@ -704,7 +812,6 @@ public function showStep2($company_projects_id) ->where('company_projects_id', $company_projects_id) ->get(); - // dd($checkUnits); $pendingEquipments = PendingEquipment::where('pending_company_projects_id', $numberProject)->get(); if (!$pendingEquipments->isEmpty()) { @@ -716,13 +823,15 @@ public function showStep2($company_projects_id) ->with('typeEquipments', $typeEquipments) ->with('checkEquipments', $checkEquipments) ->with('checkUnits', $checkUnits) - ->with('receiveNumberProject', $project); + ->with('receiveNumberProject', $project) + ->with('groupedArrayForPendingEquipments', $groupedArrayForPendingEquipments); } return view('projectsClients/articulated_2', ['step' => 2, 'numberProject' => $numberProject]) ->with('listEquipmentsProjects', $listEquipmentsProjects) ->with('typeEquipments', $typeEquipments) ->with('checkEquipments', $checkEquipments) ->with('checkUnits', $checkUnits) + ->with('groupedArrayForPendingEquipments', $groupedArrayForPendingEquipments) ->with('receiveNumberProject', $project); } @@ -770,6 +879,7 @@ public function createEquipmentManual(Request $request) $newEquipmentProject->unit_id = $newUnit->unit_id; } + $newEquipmentProject->equipment_type_id = $request->equipmentTypeId; $newEquipmentProject->equipment_tag = $request->tag; $newEquipmentProject->equipment_description = $request->equipmentDescription; @@ -780,12 +890,21 @@ public function createEquipmentManual(Request $request) $newEquipmentProject->equipment_model = $request->equipmentModel ?? NULL; $newEquipmentProject->company_projects_id = $request->numberProject; + $newEquipmentProject->save(); // ID do equipamento criado $equipmentID = $newEquipmentProject->equipment_id; + $newEquipmentWorkHistorys = new EquipmentWorkHistory; + $newEquipmentWorkHistorys->equipment_id = $equipmentID; + $newEquipmentWorkHistorys->ispt_number = 0; + $newEquipmentWorkHistorys->company_projects_id = $request->numberProject; + + $newEquipmentWorkHistorys->save(); + + $equipmentWorkHistorysID = $newEquipmentWorkHistorys->equipmentWorkHistorys_id; // Verifica os campos do Card_do tipo de valvula selecionado (Ex: psv_card) e de acordo com os campos preenchidos se for de atributos especificos, ele compara o 'name' dos inputs com os 'general_attributes_equipment_description' da tabela : GeneralAttributesEquipment e associa $checkAtributs = GeneralAttributesEquipment::whereIn('general_attributes_equipment_description', array_keys($request->all())) @@ -805,20 +924,22 @@ public function createEquipmentManual(Request $request) } // Para cada um dos Arrays criados acima, vai criar os novos dados na tabela 'SpecificAttributesEquipmentType' foreach ($receivesAssociationAttributes as $receivesAssociationAttribute) { + $AddAtributsEquipments = new SpecificAttributesEquipmentType; $AddAtributsEquipments->equipment_id = $equipmentID; $AddAtributsEquipments->equipment_type_id = $request->equipmentTypeId; $AddAtributsEquipments->general_attributes_equipment_id = $receivesAssociationAttribute['general_attributes_equipment_id']; $AddAtributsEquipments->specific_attributes_value = $receivesAssociationAttribute['value']; + $AddAtributsEquipments->save(); } //Criar associacao do equipamento ao Âmbito $AssociationEquipmentAmbit = new EquipmentAssociationAmbit; $AssociationEquipmentAmbit->equipment_type_id = $request->equipmentTypeId; $AssociationEquipmentAmbit->ambits_id = $request->EquipmentAmbit; - $AssociationEquipmentAmbit->equipment_id = $equipmentID; - $AssociationEquipmentAmbit->save(); + $AssociationEquipmentAmbit->equipmentWorkHistorys_id = $equipmentWorkHistorysID; + $AssociationEquipmentAmbit->save(); $execution_order = 1; @@ -827,7 +948,7 @@ public function createEquipmentManual(Request $request) foreach ($TasksAssociationAmbits as $TasksAssociationAmbit) { $JoinsEquipmentsWithTasks = new OrderEquipmentTasks; - $JoinsEquipmentsWithTasks->equipment_id = $equipmentID; + $JoinsEquipmentsWithTasks->equipmentWorkHistorys_id = $equipmentWorkHistorysID; $JoinsEquipmentsWithTasks->execution_order = $execution_order++; $JoinsEquipmentsWithTasks->elemental_tasks_id = $TasksAssociationAmbit->elemental_tasks_id; $JoinsEquipmentsWithTasks->further_tasks_id = null; @@ -835,7 +956,6 @@ public function createEquipmentManual(Request $request) $JoinsEquipmentsWithTasks->save(); } - // O $request->numberProject e sempre necessario retornar para indicar a obra que se esta modificando... return redirect()->route('test2', ['id' => $request->numberProject]) ->with('success', 'Equipamento criado com sucesso') @@ -849,58 +969,70 @@ public function receiveIdEquipment(Equipment $equipment) public function processStep2(Request $request) { - // dd($request); // Valide e processe os dados do formulário $file = $request->file('documento'); - // Recebe a id do Projecto criado $company_projects_id = $request->numberProject; - // Inicializa o contador para ispt_number $isptNumber = 1; // Certifique-se de que um arquivo foi enviado if ($file) { + //Busca o nome do arquivo xslx. + $originalFileName = $file->getClientOriginalName(); // Carregue o arquivo Excel $spreadsheet = IOFactory::load($file->path()); - - // Obtenha a primeira planilha, onde fica os nomes chaves para associar a tabela : general_attributes_equipaments + // Obtenha a primeira planilha, onde fica os nomes chaves para associar as tabelas : 'general_attributes_equipaments' ,'equipments' e 'equipmentWorkHistorys' $worksheet = $spreadsheet->getSheet(0); - - // Transforme os dados da planilha em um array $data = $worksheet->toArray(); // Retorna um array com todos os names preenchidos na primeira linha do template de Excel - $nomesColunas = $data[0]; - - // dd($nomesColunas); - + $columnNames = $data[0]; $countPendingEquipments = 0; $countNewEquipment = 0; - // Comece a partir da sexta linha + // Recebo os nomes das colunas do execel dependendo da linguagem selecionada + $columnRealNames = $data[5]; + + $equipmentPendingLogs = []; + $ignoredLines = []; + + // Comece a partir da sexta linha do template os dados dos Equipamentos for ($i = 6; $i < count($data); $i++) { - $dadosLinha = $data[$i]; + $dataLines = $data[$i]; - // Verifica se os 5 primeiros campos essenciais estao preenchidos, um deles não estiver preenchido ele ignora e não cria o equipamento - $isEmpty = false; - for ($j = 0; $j < 5; $j++) { - if (empty($dadosLinha[$j])) { - $isEmpty = true; - break; - } - } - if ($isEmpty) { + // Verifica se a coluna 'fábrica' (primeiro campo) está vazia + if (empty($dataLines[0])) { + // Se a coluna 'fábrica' estiver vazia, pule para a próxima linha continue; } + $emptyFields = []; + + // Verifica se os 5 primeiros campos essenciais estão preenchidos + for ($j = 0; $j < 5; $j++) { + if (empty($dataLines[$j])) { + // Adiciona o índice do campo vazio ao array $camposVazios + $emptyFields[] = $columnRealNames[$j]; // ou simplesmente $j se não tiver o nome da coluna + } + } + + if (!empty($emptyFields)) { + // Se houver campos vazios, adicione a linha e os campos vazios às linhas ignoradas + $ignoredLines[] = [ + 'line' => $i + 1, + 'emptyFields' => $emptyFields + ]; + continue; // Pula para a próxima linha + } + // Em cada um das linhas horizontais do excel, vai se guardar a 'key' vinculada ao valor do campo preenchido ou seja a 'key' vai ter o mesmo nome de um dos dados da tabela 'general_attributes_equipaments' na coluna : general_attributes_equipment_description, assim sendo mais facil implementar na tabela : specific_attributes_equipament_types - $juntarArrays = array_combine($nomesColunas, $dadosLinha); + $joinArrays = array_combine($columnNames, $dataLines); // vai guardar todos os campos de possiveis novos equipamentos, cada um em um array para multiplos inserts, na base de dados - $datas = array_filter($juntarArrays, function ($chave) { + $datas = array_filter($joinArrays, function ($chave) { return !empty($chave); }, ARRAY_FILTER_USE_KEY); @@ -917,22 +1049,46 @@ public function processStep2(Request $request) if ($existingEquipment) { + $foundInExcel = false; + $rowExcelDuplicated = null; + + // Verificar duplicatas no Excel + for ($j = 6; $j < $i; $j++) { + if ($data[$j][0] === $datas['unit'] && $data[$j][1] === $datas['equipment_tag'] && $data[$j][4] === $datas['equipment_description']) { + $foundInExcel = true; + $rowExcelDuplicated = $j; + break; + } + } + // Se o equipamento existir, crie o novo equipamento na tabela pending_equipaments. $pendingEquipament = new PendingEquipment; // Defina os atributos do pendingEquipament conforme necessário. $pendingEquipament->pending_equipment_unit_id = $checkFactory->unit_id; $pendingEquipament->pending_equipment_type_id = $equipmentType->equipment_type_id; - $pendingEquipament->pending_equipment_tag = $datas['tag']; - $pendingEquipament->pending_equipment_description = $datas['equipment_Description']; - $pendingEquipament->pending_equipment_serial_number = $datas['n_serie']; - $pendingEquipament->pending_equipment_brand = $datas['modelo']; + $pendingEquipament->pending_equipment_tag = $datas['equipment_tag']; + $pendingEquipament->pending_equipment_description = $datas['equipment_description']; + $pendingEquipament->pending_equipment_serial_number = $datas['serial_number']; + $pendingEquipament->pending_equipment_brand = $datas['model']; $pendingEquipament->pending_company_projects_id = $company_projects_id; $pendingEquipament->save(); // Incremente o contador de PendingEquipments $countPendingEquipments++; + // A variavel $pendenteLogs, na 'linhaExcel' vai recebe a linha do execel onde encontrou a duplicata em Array, vinda do primeiro $data, onde transforma toda o execel em array + // 'existingEquipmentId' vai ver qual o id do equipament que esta sendo duplicado. + //'duplicadoNoExcel' vai ser um boolean indicando que este valor duplicado veio da base de dados ou se foi de uma coluna anterior. + // linhaExcelDuplicada se o valor de duplicadoNoExcel for 'true' quer dizer que existe uma linha anterior com o mesmos dados, e essa variavel busco a o numero do array desta linha com base na variavel primeiro $data + $equipmentPendingLogs[] = [ + 'rowExecel' => $i + 1, + 'pendingEquipmentId' => $pendingEquipament->pending_equipment_id, + 'existingEquipmentId' => $existingEquipment->equipment_id, + 'foundInExcel' => $foundInExcel, + 'rowExcelDuplicated' => $rowExcelDuplicated + ]; + // Continue com o próximo loop. continue; } @@ -943,22 +1099,31 @@ public function processStep2(Request $request) $newEquipament->equipment_type_id = $equipmentType->equipment_type_id; $newEquipament->equipment_Description = $datas['equipment_description']; $newEquipament->equipment_tag = $datas['equipment_tag']; - $newEquipament->equipment_serial_number = $datas['equipment_serial_number']; - $newEquipament->equipment_brand = $datas['equipment_brand']; - $newEquipament->equipment_model = $datas['equipment_model']; - $newEquipament->ispt_number = $isptNumber; + $newEquipament->equipment_serial_number = $datas['serial_number']; + $newEquipament->equipment_brand = $datas['brand']; + $newEquipament->equipment_model = $datas['model']; $newEquipament->company_projects_id = $company_projects_id; $newEquipament->save(); $countNewEquipment++; - $isptNumber++; - // Guardo os valores de 'id' e do 'tipo de equipamento' que nosso novo equipamento acabado de criar $receveEquipment_ID = $newEquipament->equipment_id; $receveEquipament_type_ID = $newEquipament->equipment_type_id; + $newEquipmentWorkHistory = new EquipmentWorkHistory; + + $newEquipmentWorkHistory->equipment_id = $receveEquipment_ID; + $newEquipmentWorkHistory->ispt_number = $isptNumber; + $newEquipmentWorkHistory->company_projects_id = $company_projects_id; + + $newEquipmentWorkHistory->save(); + + // Recebe o Id do 'EquipmentWorkHistory' criado. + $recebeNewEquipmentWorkHistoryID = $newEquipmentWorkHistory->equipmentWorkHistorys_id; + + $isptNumber++; $ambit = AmbitsEquipment::where('ambits_description', $datas['ambit'])->first(); @@ -968,9 +1133,10 @@ public function processStep2(Request $request) //Criar associacao do equipamento ao Âmbito $AssociationEquipmentAmbit = new EquipmentAssociationAmbit; + $AssociationEquipmentAmbit->equipment_type_id = $receveEquipament_type_ID; $AssociationEquipmentAmbit->ambits_id = $ambit_id; - $AssociationEquipmentAmbit->equipment_id = $receveEquipment_ID; + $AssociationEquipmentAmbit->equipmentWorkHistorys_id = $recebeNewEquipmentWorkHistoryID; $AssociationEquipmentAmbit->save(); $execution_order = 1; @@ -980,7 +1146,8 @@ public function processStep2(Request $request) foreach ($TasksAssociationAmbits as $TasksAssociationAmbit) { $JoinsEquipmentsWithTasks = new OrderEquipmentTasks; - $JoinsEquipmentsWithTasks->equipment_id = $receveEquipment_ID; + + $JoinsEquipmentsWithTasks->equipmentWorkHistorys_id = $recebeNewEquipmentWorkHistoryID; $JoinsEquipmentsWithTasks->execution_order = $execution_order++; $JoinsEquipmentsWithTasks->elemental_tasks_id = $TasksAssociationAmbit->elemental_tasks_id; $JoinsEquipmentsWithTasks->further_tasks_id = null; @@ -992,7 +1159,6 @@ public function processStep2(Request $request) $generalAttributes = GeneralAttributesEquipment::all(); - foreach ($generalAttributes as $generalAttribute) { // Verifica se a chave existe em $datas, comparando com os dados da tabela : GeneralAttributesEquipment assim adicionando todos diferentes de NULL relacionados com o equipamento acabado de cria if (isset($datas[$generalAttribute->general_attributes_equipment_description])) { @@ -1009,18 +1175,43 @@ public function processStep2(Request $request) } } + // Separa o nome do arquivo para obter o tipo de documento e a data-hora + $parts = explode('_', $originalFileName); + $documentType = $parts[2]; // 98 + $timestamp = $parts[3]; // 2024-01-14_14-33 + + // Cria um array agrupado + $groupedArrayForPendingEquipments = [$documentType, [$timestamp, $equipmentPendingLogs]]; + + // Armazenar $groupedArrayForPendingEquipments na sessão + session(['groupedArrayForPendingEquipments' => $groupedArrayForPendingEquipments]); + $pendingEquipments = PendingEquipment::where('pending_company_projects_id', $request->numberProject)->get(); - // $pendingEquipments = session('pendingEquipments'); - if ($countPendingEquipments != 0) { - // return redirect()->route('test2')->with('Danger', 'Equipamentos Pendentes')->with('listValves', $listValves)->with('pendingEquipments', $pendingEquipments); + // Verifica se foram criados equipamentos pendentes,e se nesses pendentes vieram do execel ou da base de dados, alem de indicar as linha nao preenchidas. + // if ($countPendingEquipments != 0 && !empty($pendenteLogs) && !empty($linhasIgnoradas)) { + // return redirect()->route('test2', ['id' => $request->numberProject]) + // ->with('danger', 'Equipamentos Pendentes criados : ' . $countPendingEquipments) + // ->with('dangerPendenteLogs', ['linhasIgnoradas' => $linhasIgnoradas, 'pendenteLogs' => $pendenteLogs]) + // ->with('pendingEquipments', $pendingEquipments); + // } + // return redirect()->route('test2', ['id' => $request->numberProject]) + // ->with('success', 'Equipamentos Criados :' . $countNewEquipment); + + if ($countPendingEquipments != 0 && !empty($equipmentPendingLogs)) { + // Se houver equipamentos pendentes, redirecione com essa informação e inclua os $linhasIgnoradas se não estiverem vazios return redirect()->route('test2', ['id' => $request->numberProject]) - ->with('danger', 'Equipamentos Pendentes criados : ' . $countPendingEquipments) + ->with('danger', 'Equipamentos Pendentes criados: ' . $countPendingEquipments) + ->with('dangerLogs', $ignoredLines) + ->with('equipmentPendingLogs', $equipmentPendingLogs) ->with('pendingEquipments', $pendingEquipments); - // ->with('success', 'Equipamentos Criados :' . count($listValves)) + } else { + // Se não houver equipamentos pendentes, redirecione com uma mensagem de sucesso e inclua os $linhasIgnoradas se não estiverem vazios + return redirect()->route('test2', ['id' => $request->numberProject]) + ->with('success', 'Equipamentos Criados: ' . $countNewEquipment) + ->with('dangerLogs', $ignoredLines); } - return redirect()->route('test2', ['id' => $request->numberProject]) - ->with('success', 'Equipamentos Criados :' . $countNewEquipment); + } //Nao chega aqui ainda pois volta para a pagina com dados ja carregados. @@ -1156,11 +1347,7 @@ public function processStep3(Request $request) public function index() { - // $results = DB::table('equipaments') - // ->join('specific_attributes_equipament_types', 'equipaments.equipment_ID', '=', 'specific_attributes_equipament_types.tb_equipament_id') - // ->join('general_attributes_equipaments', 'specific_attributes_equipament_types.specific_Attributes_Equipment_Type_ID', '=', 'general_attributes_equipaments.general_Attributes_Equipment_ID') - // ->select('equipaments.tag', 'general_attributes_equipaments.description', 'specific_attributes_equipament_types.value') - // ->get(); + $results = DB::table('equipments') ->join('specific_attributes_equipament_types', 'equipments.equipment_id', '=', 'specific_attributes_equipament_types.equipment_id') @@ -1284,205 +1471,4 @@ public function getAttributes($id) $equipment = Equipment::with('specificAttributes')->find($id); return response()->json($equipment->specificAttributes); } - - // public function createEquipamentProject(Request $request) - // { - // $file = $request->file('documento'); - - // // Certifique-se de que um arquivo foi enviado - // if ($file) { - // // Carregue o arquivo Excel - // $spreadsheet = IOFactory::load($file->path()); - - // // Obtenha a primeira planilha - // $worksheet = $spreadsheet->getSheet(0); - - // // Transforme os dados da planilha em um array - // $data = $worksheet->toArray(); - - // $nomesColunas = $data[0]; - - // $dadosLinha6 = $data[6]; - - // $juntarArrays = array_combine($nomesColunas, $dadosLinha6); - - // $datas = array_filter($juntarArrays, function ($chave) { - // return !empty($chave); - // }, ARRAY_FILTER_USE_KEY); - - // $equipamentType = equipament_type::where('equipment_type_name', $datas['tipo_equipamento'])->first(); - // $checkFactory = factorie::where('factories_name', $datas['fabrica'])->first(); - - - // $newEquipament = new equipament; - // //Primeiro tem de derificar se a fabrica existe, senão cria uma. - // $newEquipament->factory_id = $checkFactory->factories_id; - // $newEquipament->equipament_type_id = $equipamentType->equipament_type_id; - // $newEquipament->equipment_Description = $datas['equipment_Description']; - // $newEquipament->tag = $datas['tag']; - // $newEquipament->serial_number = $datas['n_serie']; - // $newEquipament->model = $datas['modelo']; - - // $newEquipament->save(); - - - // $receveEquipment_ID = $newEquipament->id; - // $receveEquipament_type_ID = $newEquipament->equipament_type_id; - - - // // Atributos que você quer buscar e inserir - // $attributes = ["dimension", "dn_ent", "p&id", "n_sap", "isolation", "scaffolding", "grua", "interlocks"]; - - // // $attributes = array_slice($data[0], 7); - - // foreach ($attributes as $attribute) { - - // // Buscar o atributo na tabela general_attributes_equipament - // $generalAttribute = general_attributes_equipament::where('description', $attribute)->first(); - - - // // Se o atributo foi encontrado - // if (!is_null($generalAttribute)) { - // // Criar um novo registro em specific_attributes_equipament_Types - // $specificAttribute = new specific_attributes_equipament_type; - - // $specificAttribute->tb_equipament_id = $receveEquipment_ID; - // $specificAttribute->equipament_Type_id = $receveEquipament_type_ID; - // $specificAttribute->specific_attributes_equipment_type_id = $generalAttribute->general_attributes_equipment_id; - // $specificAttribute->value = $datas[$attribute]; - - // $specificAttribute->save(); - // } - // } - // $listValves = equipament::all(); - - // return redirect()->route('testExcel')->with('success', 'Dados guardados com sucesso')->with('listValves', $listValves); - // } - // } - - - - - // public function createEquipamentProject(Request $request) - // { - // $file = $request->file('documento'); - - // // Certifique-se de que um arquivo foi enviado - // if ($file) { - // // Carregue o arquivo Excel - // $spreadsheet = IOFactory::load($file->path()); - - // // Obtenha a primeira planilha - // $worksheet = $spreadsheet->getSheet(0); - - // // Transforme os dados da planilha em um array - // $data = $worksheet->toArray(); - - // $nomesColunas = $data[0]; - - // // Atributos que você quer buscar e inserir - // $attributes = ["dimension", "dn_ent", "p&id", "n_sap", "isolation", "scaffolding", "grua", "interlocks"]; - - // // Comece a partir da sexta linha - // for ($i = 6; $i < count($data); $i++) { - - // $dadosLinha = $data[$i]; - - // //Se não preencher o campo $dadosLinha[0], não cria um novo equipamento - // //Trocar pelos 5 primeiros - // if (empty($dadosLinha[0])) { - // continue; - // } - - - // $juntarArrays = array_combine($nomesColunas, $dadosLinha); - - // $datas = array_filter($juntarArrays, function ($chave) { - // return !empty($chave); - // }, ARRAY_FILTER_USE_KEY); - - // $equipmentType = EquipmentType::where('equipment_type_name', $datas['tipo_equipamento'])->first(); - - // $checkFactory = Unit::where('unit_name', $datas['fabrica'])->first(); - - - // // Antes de criar o novo equipamento, verifique se já existe um equipamento - // // com o mesmo factory_id e tag. - // $existingEquipment = Equipment::where('unit_id', $checkFactory->unit_id) - // ->where('equipment_tag', $datas['tag']) - // ->first(); - - // if ($existingEquipment) { - // // Se o equipamento existir, crie o novo equipamento na tabela pending_equipaments. - // $pendingEquipament = new PendingEquipment; - // // Defina os atributos do pendingEquipament conforme necessário. - // $pendingEquipament->pending_equipment_unit_id = $checkFactory->unit_id; - // $pendingEquipament->pending_equipment_type_id = $equipmentType->equipment_type_id; - // $pendingEquipament->pending_equipment_tag = $datas['tag']; - // $pendingEquipament->pending_equipment_description = $datas['equipment_Description']; - // $pendingEquipament->pending_equipment_serial_number = $datas['n_serie']; - // $pendingEquipament->pending_equipment_brand = $datas['modelo']; - - // $pendingEquipament->save(); - - // // Adicione uma variável de sessão para indicar que um equipamento pendente foi criado. - // session(['pendingEquipmentCreated' => true]); - - // // Adicione uma variável de sessão para indicar que um equipamento pendente foi criado. - // session()->push('pendingEquipments', $pendingEquipament); - - // // Continue com o próximo loop. - // continue; - // } - - // $newEquipament = new Equipment; - - // $newEquipament->unit_id = $checkFactory->unit_id; - // $newEquipament->equipment_type_id = $equipmentType->equipment_type_id; - // $newEquipament->equipment_Description = $datas['equipment_Description']; - // $newEquipament->equipment_tag = $datas['tag']; - // $newEquipament->equipment_serial_number = $datas['n_serie']; - // $newEquipament->equipment_model = $datas['modelo']; - - // $newEquipament->save(); - - // $receveEquipment_ID = $newEquipament->equipment_id; - - // $receveEquipament_type_ID = $newEquipament->equipment_type_id; - - - // foreach ($attributes as $attribute) { - - // $generalAttribute = GeneralAttributesEquipment::where('general_attributes_equipment_description', $attribute)->first(); - - // if (!is_null($generalAttribute)) { - - // $specificAttribute = new SpecificAttributesEquipmentType; - - // $specificAttribute->equipment_id = $receveEquipment_ID; - // $specificAttribute->equipment_type_id = $receveEquipament_type_ID; - // $specificAttribute->specific_attributes_equipment_type_id = $generalAttribute->general_attributes_equipment_id; - // $specificAttribute->specific_attributes_value = $datas[$attribute]; - - // // $specificAttribute->save(); - // } - // } - // } - - // $listValves = Equipment::all(); - // $pendingEquipments = PendingEquipment::all(); - - // // return redirect()->route('createProject')->with('success', 'Dados guardados com sucesso')->with('listValves', $listValves); - - // // return redirect()->route('createProject')->with('success', 'Dados guardados com sucesso')->with('listValves', $listValves)->with('pendingEquipments', $pendingEquipments); - - // $listValves = Equipment::all(); - // $pendingEquipments = session('pendingEquipments'); - // if ($pendingEquipments) { - // return redirect()->route('createProject')->with('success', 'Dados guardados com sucesso')->with('listValves', $listValves)->with('pendingEquipments', $pendingEquipments); - // } else { - // return redirect()->route('createProject')->with('success', 'Dados guardados com sucesso')->with('listValves', $listValves); - // } - // } - // } } diff --git a/app/Http/Controllers/ExecutionProjectController.php b/app/Http/Controllers/ExecutionProjectController.php index 92a55e39..6d5097b8 100755 --- a/app/Http/Controllers/ExecutionProjectController.php +++ b/app/Http/Controllers/ExecutionProjectController.php @@ -80,7 +80,6 @@ public function getDataEquipment(Request $request) $receiveAllClients = $request->get('receiveAllClients'); $receiveAllPlants = $request->get('receiveAllPlants'); - $receiveAllUnits = $request->get('receiveAllUnits'); $receiveEquipmentsType = $request->get('receiveEquipmentsType'); @@ -107,14 +106,12 @@ public function getDataEquipment(Request $request) $query = Equipment::with('equipmentType', 'unit') ->whereIn('unit_id', $unitsIds) - ->select(['equipment_id', 'ispt_number', 'equipment_tag', 'unit_id', 'equipment_type_id']); - - + ->select(['equipment_id', 'equipment_tag', 'unit_id', 'equipment_type_id']); } else { // Query padrão que todas as dataTables recebem, a partir dele fazemos os filt $query = Equipment::with('equipmentType', 'unit') - ->select(['equipment_id', 'ispt_number', 'equipment_tag', 'unit_id', 'equipment_type_id']); + ->select(['equipment_id', 'equipment_tag', 'unit_id', 'equipment_type_id']); } // Consultas para a Criacao da Obra, Ambas vao ser diferentes, pois na creacao, recebes os equipamentos por obra, porem no portifolio vamos buscar todos. @@ -171,17 +168,41 @@ public function getDataEquipment(Request $request) }) ->addColumn('action', function ($equipment) use ($numberProject) { - // Verifica se $numberProject não é nulo - if (!is_null($numberProject)) { - // Se não for nulo, usa a rota 'test11' - $actionBtn = ''; - } else { - // Se for nulo, usa a rota 'test22' - $actionBtn = ''; - } - return $actionBtn; + $dropdownHtml = ''; // Fecha as tags do dropdown + + return $dropdownHtml; }) + ->editColumn('unit_id', function ($equipment) { // Isto irá substituir 'unit_id' pelo 'unit_name' associado return $equipment->unit->unit_name ?? 'N/A'; diff --git a/app/Http/Controllers/ProjectoDatacontroller.php b/app/Http/Controllers/ProjectoDatacontroller.php index 984f7928..be455019 100755 --- a/app/Http/Controllers/ProjectoDatacontroller.php +++ b/app/Http/Controllers/ProjectoDatacontroller.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use App\Models\AmbitsEquipment; +use App\Models\EquipmentWorkHistory; use App\Models\Unit; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; @@ -36,7 +37,7 @@ public function testRelatorio() $pdf = PDF::loadView('testeRelatorio', ['userLogoPath' => $userLogoPath])->setPaper('a4', 'landscape'); - return $pdf->stream('relatorio_teste.pdf'); + return $pdf->stream('relatorio_teste.pdf'); // return view('testeRelatorio',compact('userLogoPath')); } @@ -76,8 +77,12 @@ public function test11($projectID, $equipmentID) $dataEquipment = Equipment::find($equipmentID); + $receiveEquipmentWorkHistorys = EquipmentWorkHistory::where('equipment_id', $equipmentID) + ->where('company_projects_id', $projectID) + ->first(); + $attributes = SpecificAttributesEquipmentType::where('equipment_id', $equipmentID)->get(); // recebe todos os atributos espesificos do equipamento - $OrdemTasks = OrderEquipmentTasks::where('equipment_id', $equipmentID)->get(); // Todas as tarefas que o equipamento vai realizar : + $OrdemTasks = OrderEquipmentTasks::where('equipmentWorkHistorys_id', $receiveEquipmentWorkHistorys->equipmentWorkHistorys_id)->get(); // Todas as tarefas que o equipamento vai realizar : $OrdemTasksIds = $OrdemTasks->pluck('elemental_tasks_id')->all(); // Array de IDs return view('projectsClients.articulated_2_ShowEquipment', compact('dataEquipment', 'OrdemTasks', 'OrdemTasksIds')); @@ -119,18 +124,19 @@ public function getEquipmentDetails($receiveListEquipmentId) return response()->json($equipments); } - - public function receiveAllInstallationEquipment($receiveNumberProject) + public function receiveAllInstallationEquipment(Request $request) { + $projectId = $request->get('receiveNumberProject'); - $receveProject = CompanyProject::find($receiveNumberProject); + $receveProject = CompanyProject::find($projectId); $receveEquipments = Equipment::whereHas('unit.plant', function ($query) use ($receveProject) { $query->where('plants.plant_id', '=', $receveProject->plant_id); }) - ->where('company_projects_id', null) // Adiciona a condição aqui - ->with(['equipmentType', 'unit', 'equipmentAssociationAmbit.ambitsEquipment']) - ->get(); + ->where('company_projects_id', null) // Adiciona a condição aqui + ->with(['equipmentType', 'unit']) + // ->with(['equipmentType', 'unit', 'equipmentAssociationAmbit.ambitsEquipment']) + ->get(); return DataTables::of($receveEquipments) ->addColumn('equipment_type', function ($row) { diff --git a/app/Http/ViewComposers/WorkstationComposer.php b/app/Http/ViewComposers/WorkstationComposer.php index a553d9ad..3f10a6df 100755 --- a/app/Http/ViewComposers/WorkstationComposer.php +++ b/app/Http/ViewComposers/WorkstationComposer.php @@ -14,122 +14,122 @@ public function compose(View $view) $userEmail = Auth::user()->email; $equipmentsTodo = DB::select(" - WITH equipments_multiple_rows AS ( - SELECT - e.equipment_id, - e.equipment_tag, - COALESCE(MAX(oet.elemental_tasks_id), MAX(oet.further_tasks_id)) AS equipment_all_tasks - FROM - users u - JOIN - construction_workstations cw ON u.user_name = cw.name_workstations - JOIN - workstations_association_tasks wat ON cw.id_workstations = wat.id_workstations - JOIN - equipments e ON wat.company_projects_id = e.company_projects_id - JOIN - ordered_equipment_tasks oet ON e.equipment_id = oet.equipment_id - WHERE - u.email = :email1 - AND - oet.execution_order = 1 - GROUP BY - e.equipment_id, - e.equipment_tag - ), + WITH equipments_multiple_rows AS ( + SELECT + e.equipment_id, + e.equipment_tag, + COALESCE(MAX(oet.elemental_tasks_id), MAX(oet.further_tasks_id)) AS equipment_all_tasks + FROM + users u + JOIN + construction_workstations cw ON u.user_name = cw.name_workstations + JOIN + workstations_association_tasks wat ON cw.id_workstations = wat.id_workstations + JOIN + equipments e ON wat.company_projects_id = e.company_projects_id + JOIN + ordered_equipment_tasks oet ON e.equipment_id = oet.equipment_id + WHERE + u.email = :email1 + AND + oet.execution_order = 1 + GROUP BY + e.equipment_id, + e.equipment_tag + ), - workstations_multiple_rows AS ( - SELECT - cw.id_workstations, - cw.name_workstations, - COALESCE(wat.elemental_tasks_id, wat.further_tasks_id) AS all_tasks - FROM - users u - JOIN - construction_workstations cw ON u.user_name = cw.name_workstations - JOIN - workstations_association_tasks wat ON cw.id_workstations = wat.id_workstations - WHERE - u.email = :email2 - ), + workstations_multiple_rows AS ( + SELECT + cw.id_workstations, + cw.name_workstations, + COALESCE(wat.elemental_tasks_id, wat.further_tasks_id) AS all_tasks + FROM + users u + JOIN + construction_workstations cw ON u.user_name = cw.name_workstations + JOIN + workstations_association_tasks wat ON cw.id_workstations = wat.id_workstations + WHERE + u.email = :email2 + ), - workstations_control_all_tasks AS ( - SELECT - cew.control_equipment_workstation_id, - cew.equipment_id, - CASE - WHEN cew.id_workstations IS NULL THEN NULL - WHEN cew.id_workstations IN ( + workstations_control_all_tasks AS ( + SELECT + cew.control_equipment_workstation_id, + cew.equipment_id, + CASE + WHEN cew.id_workstations IS NULL THEN NULL + WHEN cew.id_workstations IN ( + SELECT wat.id_workstations + FROM workstations_association_tasks wat + JOIN construction_workstations cw ON wat.company_projects_id = cw.company_projects_id + JOIN users u ON u.user_name = cw.name_workstations + WHERE u.email = :email3 + ) THEN cew.id_workstations + ELSE NULL + END AS control_id_workstations, + COALESCE(cew.elemental_tasks_id, cew.further_tasks_id) AS control_workstation_all_tasks, + cew.equipment_comments_id, + cew.entry_date, + cew.departure_date + FROM + control_equipment_workstation cew + WHERE + cew.id_workstations IS NULL + OR cew.id_workstations IN ( SELECT wat.id_workstations FROM workstations_association_tasks wat JOIN construction_workstations cw ON wat.company_projects_id = cw.company_projects_id JOIN users u ON u.user_name = cw.name_workstations - WHERE u.email = :email3 - ) THEN cew.id_workstations - ELSE NULL - END AS control_id_workstations, - COALESCE(cew.elemental_tasks_id, cew.further_tasks_id) AS control_workstation_all_tasks, - cew.equipment_comments_id, - cew.entry_date, - cew.departure_date - FROM - control_equipment_workstation cew - WHERE - cew.id_workstations IS NULL - OR cew.id_workstations IN ( - SELECT wat.id_workstations - FROM workstations_association_tasks wat - JOIN construction_workstations cw ON wat.company_projects_id = cw.company_projects_id - JOIN users u ON u.user_name = cw.name_workstations - WHERE u.email = :email4 - ) - ) + WHERE u.email = :email4 + ) + ) - SELECT - emr.equipment_id, - emr.equipment_tag - FROM - equipments_multiple_rows emr - WHERE - ( - emr.equipment_all_tasks IN (SELECT all_tasks FROM workstations_multiple_rows) - AND NOT EXISTS ( - SELECT 1 - FROM workstations_control_all_tasks wc - WHERE wc.equipment_id = emr.equipment_id - AND wc.control_id_workstations IN (SELECT id_workstations FROM workstations_multiple_rows) + SELECT + emr.equipment_id, + emr.equipment_tag + FROM + equipments_multiple_rows emr + WHERE + ( + emr.equipment_all_tasks IN (SELECT all_tasks FROM workstations_multiple_rows) + AND NOT EXISTS ( + SELECT 1 + FROM workstations_control_all_tasks wc + WHERE wc.equipment_id = emr.equipment_id + AND wc.control_id_workstations IN (SELECT id_workstations FROM workstations_multiple_rows) + ) ) - ) - OR - ( - emr.equipment_id IN ( - SELECT equipment_id - FROM workstations_control_all_tasks - WHERE control_id_workstations IS NULL - AND entry_date IS NULL - AND departure_date IS NULL - AND control_workstation_all_tasks IN (SELECT all_tasks FROM workstations_multiple_rows) + OR + ( + emr.equipment_id IN ( + SELECT equipment_id + FROM workstations_control_all_tasks + WHERE control_id_workstations IS NULL + AND entry_date IS NULL + AND departure_date IS NULL + AND control_workstation_all_tasks IN (SELECT all_tasks FROM workstations_multiple_rows) + ) + AND NOT EXISTS ( + SELECT 1 + FROM workstations_control_all_tasks wc + WHERE wc.equipment_id = emr.equipment_id + AND wc.control_id_workstations IS NOT NULL + GROUP BY wc.equipment_id + HAVING COUNT(DISTINCT wc.control_id_workstations) > 20 + ) ) - AND NOT EXISTS ( - SELECT 1 - FROM workstations_control_all_tasks wc - WHERE wc.equipment_id = emr.equipment_id - AND wc.control_id_workstations IS NOT NULL - GROUP BY wc.equipment_id - HAVING COUNT(DISTINCT wc.control_id_workstations) > 20 - ) - ) - GROUP BY - emr.equipment_id, - emr.equipment_tag - ORDER BY - emr.equipment_id ASC; - ", [ - 'email1' => $userEmail, - 'email2' => $userEmail, - 'email3' => $userEmail, - 'email4' => $userEmail - ]); + GROUP BY + emr.equipment_id, + emr.equipment_tag + ORDER BY + emr.equipment_id ASC; + ", [ + 'email1' => $userEmail, + 'email2' => $userEmail, + 'email3' => $userEmail, + 'email4' => $userEmail + ]); $equipmentsReturned = DB::select(" diff --git a/app/Livewire/Articulado/SelectElementalTasksInWonkstation.php b/app/Livewire/Articulado/SelectElementalTasksInWonkstation.php index 59bfc98c..a3e309df 100755 --- a/app/Livewire/Articulado/SelectElementalTasksInWonkstation.php +++ b/app/Livewire/Articulado/SelectElementalTasksInWonkstation.php @@ -40,12 +40,25 @@ public function mount($workstation) { $this->workstation = $workstation; - $this->receiveAllEquipments = Equipment::where('company_projects_id', $this->workstation->company_projects_id) - ->join('equipment_association_ambits', 'equipments.equipment_id', '=', 'equipment_association_ambits.equipment_id') + // $this->receiveAllEquipments = Equipment::where('company_projects_id', $this->workstation->company_projects_id) + // ->join('equipment_association_ambits', 'equipments.equipment_id', '=', 'equipment_association_ambits.equipment_id') + // ->select('equipments.equipment_id', 'equipments.equipment_type_id', 'equipment_association_ambits.ambits_id') + // ->get() + // ->toArray(); + + $workstation = $this->workstation; // Atribuindo a uma variável local para uso na closure + + $this->receiveAllEquipments = Equipment::join('equipment_work_historys', function ($join) use ($workstation) { + $join->on('equipments.equipment_id', '=', 'equipment_work_historys.equipment_id') + ->where('equipment_work_historys.company_projects_id', '=', $workstation->company_projects_id); + }) + ->join('equipment_association_ambits', 'equipment_work_historys.equipmentWorkHistorys_id', '=', 'equipment_association_ambits.equipmentWorkHistorys_id') ->select('equipments.equipment_id', 'equipments.equipment_type_id', 'equipment_association_ambits.ambits_id') ->get() ->toArray(); + + $this->receiveAllFurtherTasks = FurtherTasks::where('company_projects_id', $this->workstation->company_projects_id) ->get(); @@ -107,7 +120,7 @@ public function mount($workstation) 'receiveAllFurtherTasks' => $this->receiveAllFurtherTasks, 'receiveElementalTasks' => $this->receiveElementalTasks, ]); - + $receiveTasksRepository = app(ReceiveTasksRepository::class); // Chama a variavel do Repositorio para amazenar a variavel e depois conseguir chamar facilmente. $receiveTasksRepository->setElementalTasks($this->receiveElementalTasks); diff --git a/app/Models/CompanyProject.php b/app/Models/CompanyProject.php index 5ba49bc4..e5c222ef 100755 --- a/app/Models/CompanyProject.php +++ b/app/Models/CompanyProject.php @@ -24,4 +24,8 @@ public function plant(){ public function user(){ return $this->hasOneThrough(User::class, Plant::class, 'plant_id', 'user_id'); } + + public function EquipmentWorkHistory(){ + return $this->hasMany(EquipmentWorkHistory::class, 'company_projects_id','company_projects_id'); + } } diff --git a/app/Models/Equipment.php b/app/Models/Equipment.php index 2c3befd4..40cf0414 100755 --- a/app/Models/Equipment.php +++ b/app/Models/Equipment.php @@ -37,6 +37,7 @@ public function specificAttributes() ->orderBy('general_attributes_equipaments.general_attributes_equipment_description', 'asc'); } + //Trocar para EquipmentWorkHistory public function equipmentAssociationAmbit() { //Antiga hasMany , apenas colocado hasOne para funcionar o datatables @@ -57,14 +58,20 @@ public function controlEquipmentWorkstation() { return $this->hasMany(ControlEquipmentWorkstation::class, 'equipment_id', 'equipment_id'); } + public function QrcodesAssociatedEquipment(){ + return $this->hasMany(QrcodesAssociatedEquipment::class,'equipment_id','equipment_id'); + } public function hasInspectionYes() { return $this->orderEquipmentTasks()->where('inspection', 'Sim')->exists(); } - public function QrcodesAssociatedEquipment(){ - return $this->hasMany(QrcodesAssociatedEquipment::class,'equipment_id','equipment_id'); + + + + public function EquipmentWorkHistory(){ + return $this->hasMany(EquipmentWorkHistory::class, 'equipment_id','equipment_id'); } } diff --git a/app/Models/EquipmentWorkHistory.php b/app/Models/EquipmentWorkHistory.php index 37797189..27f8dcc0 100644 --- a/app/Models/EquipmentWorkHistory.php +++ b/app/Models/EquipmentWorkHistory.php @@ -8,4 +8,19 @@ class EquipmentWorkHistory extends Model { use HasFactory; + + public $timestamps = false; + + protected $table = 'equipment_work_historys'; + + protected $primaryKey = 'equipmentWorkHistorys_id'; + + public function equipment() + { + return $this->belongsTo(Equipment::class, 'equipment_id', 'equipment_id'); + } + public function companyProject() + { + return $this->belongsTo(Equipment::class, 'company_projects_id', 'company_projects_id'); + } } diff --git a/public/templateExcel/FinalTemplate1.xlsx b/public/templateExcel/FinalTemplate1.xlsx deleted file mode 100755 index 2530697fa4529f5c776d98a4c6f8acbd1a78a892..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56044 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ℜmlUqn0k+p6{@ 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 diff --git a/public/templateExcel/TestTemplate.xlsx b/public/templateExcel/Valves_Template.xlsx old mode 100755 new mode 100644 similarity index 52% rename from public/templateExcel/TestTemplate.xlsx rename to public/templateExcel/Valves_Template.xlsx index 26f23f52b9ee4c1fdeb25482297fd0b8bb7a9e71..3dc9baf73bf597839515b1abe3c1f80362928f2d GIT binary patch delta 29088 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

#$lQzLwI4)Nx#T3wk@Yf@QW%oP7%0G-1 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 Aga7~l diff --git a/resources/views/Templates/templateAdmin.blade.php b/resources/views/Templates/templateAdmin.blade.php index 052a34a6..22438c10 100755 --- a/resources/views/Templates/templateAdmin.blade.php +++ b/resources/views/Templates/templateAdmin.blade.php @@ -69,6 +69,29 @@