İlk temizlik tamamlandı bir önceki projeden
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Redirect;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class AdminAjaxController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
public function index(Request $request, string $var) {
|
||||
$u = Auth::user();
|
||||
//$izin = explode(",","Admin,Head Of Department");
|
||||
if(!$u || !isset($u->level)) {
|
||||
echo("permission error");
|
||||
exit();
|
||||
}
|
||||
//print_r($u->level); exit();
|
||||
/*
|
||||
$this->middleware('auth');
|
||||
$path = "AdminAjax/$var.php";
|
||||
include($path);
|
||||
return $return; // return işlemi include da çalışmadığından bir değişken ile buraya aktardık
|
||||
*/
|
||||
$return = null;
|
||||
$url = "admin-ajax.$var";
|
||||
|
||||
return view($url,array(
|
||||
"request" => $request
|
||||
));
|
||||
|
||||
/*
|
||||
try {
|
||||
include("AdminAjax/$var.php");
|
||||
} catch (\Exception $e) {
|
||||
return abort(404);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class AjaxController extends Controller
|
||||
{
|
||||
public function index(Request $request, string $var) {
|
||||
$this->middleware('auth');
|
||||
$path = "Ajax/$var.php";
|
||||
try {
|
||||
include("Ajax/$var.php");
|
||||
return $return;
|
||||
} catch (\Exception $e) {
|
||||
echo $e;
|
||||
//return abort(404);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,829 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Annotation;
|
||||
use App\Models\DocumentRevision;
|
||||
use App\Models\WeldLog;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AnnotationController extends Controller
|
||||
{
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'annotations' => 'required|array',
|
||||
'annotations.*.shape_id' => 'required|string',
|
||||
'annotations.*.spool_no' => 'nullable|string',
|
||||
'annotations.*.joint_type' => 'nullable|string',
|
||||
'annotations.*.welder_id' => 'nullable|string',
|
||||
'annotations.*.classification' => 'nullable|string',
|
||||
'annotations.*.page_number' => 'required|integer',
|
||||
'annotations.*.x_coordinate' => 'required|numeric',
|
||||
'annotations.*.y_coordinate' => 'required|numeric',
|
||||
'annotations.*.width' => 'required|numeric',
|
||||
'annotations.*.height' => 'required|numeric',
|
||||
'annotations.*.shape_type' => 'required|in:rect,circle,triangle,spool,weld,shop_weld,leader_line,text,line',
|
||||
'annotations.*.pdf_file_path' => 'required|string',
|
||||
'annotations.*.created_by' => 'required|integer',
|
||||
'annotations.*.original_start_point' => 'nullable|string',
|
||||
'annotations.*.connected_shape_id' => 'nullable|string',
|
||||
]);
|
||||
|
||||
try {
|
||||
$annotations = [];
|
||||
foreach ($request->annotations as $annotationData) {
|
||||
// Check if annotation already exists
|
||||
$existingAnnotation = Annotation::where('shape_id', $annotationData['shape_id'])->first();
|
||||
|
||||
if ($existingAnnotation) {
|
||||
// Update existing annotation
|
||||
$existingAnnotation->update($annotationData);
|
||||
$annotations[] = $existingAnnotation;
|
||||
} else {
|
||||
// Create new annotation
|
||||
$annotations[] = Annotation::create($annotationData);
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $annotations,
|
||||
'message' => 'Annotations saved successfully!'
|
||||
], 201);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => $e->getMessage(),
|
||||
'message' => 'Failed to save annotations'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$pdfFile = $request->get('pdf_file');
|
||||
|
||||
$annotations = Annotation::when($pdfFile, function ($query, $pdfFile) {
|
||||
return $query->where('pdf_file_path', $pdfFile);
|
||||
})
|
||||
->where('is_active', 1)
|
||||
->orderBy('created_at', 'asc')
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $annotations
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function show(Annotation $annotation): JsonResponse
|
||||
{
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $annotation
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(Request $request, Annotation $annotation): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'spool_no' => 'nullable|string',
|
||||
'joint_type' => 'nullable|string',
|
||||
'welder_id' => 'nullable|string',
|
||||
'classification' => 'nullable|string',
|
||||
]);
|
||||
|
||||
$annotation->update($request->only(['spool_no', 'joint_type', 'welder_id', 'classification']));
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $annotation
|
||||
]);
|
||||
}
|
||||
|
||||
public function destroy(Annotation $annotation): JsonResponse
|
||||
{
|
||||
$annotation->delete();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Annotation deleted successfully'
|
||||
]);
|
||||
}
|
||||
|
||||
public function deleteMultiple(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'shape_ids' => 'required|array',
|
||||
'shape_ids.*' => 'required|string',
|
||||
'pdf_file' => 'required|string',
|
||||
'page_number' => 'required|integer'
|
||||
]);
|
||||
|
||||
try {
|
||||
$deletedCount = Annotation::whereIn('shape_id', $request->shape_ids)
|
||||
->where('pdf_file_path', $request->pdf_file)
|
||||
->where('page_number', $request->page_number)
|
||||
->delete();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'deleted_count' => $deletedCount,
|
||||
'message' => "Successfully deleted {$deletedCount} annotations from page {$request->page_number}"
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => $e->getMessage(),
|
||||
'message' => 'Failed to delete annotations'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function sync(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'annotations' => 'required|array',
|
||||
'pdf_file' => 'required|string',
|
||||
'page_number' => 'required|integer'
|
||||
]);
|
||||
|
||||
try {
|
||||
$pdfFile = $request->pdf_file;
|
||||
$pageNumber = $request->page_number;
|
||||
$userId = $request->user_id ?? auth()->id() ?? 1;
|
||||
|
||||
$lastVersion = Annotation::where('pdf_file_path', 'like', '%' . basename($pdfFile) . '%')
|
||||
->where('page_number', $pageNumber)
|
||||
->max('version');
|
||||
$newVersion = ($lastVersion ?? 0) + 1;
|
||||
|
||||
$saved = [];
|
||||
foreach ($request->annotations as $data) {
|
||||
// Use updateOrCreate to prevent duplicates - update existing annotation with same shape_id, pdf_file_path, page_number
|
||||
// Only create new version if shape_id doesn't exist in current version
|
||||
$annotation = Annotation::updateOrCreate(
|
||||
[
|
||||
'shape_id' => $data['shape_id'],
|
||||
'pdf_file_path' => $pdfFile,
|
||||
'page_number' => $pageNumber,
|
||||
'version' => $newVersion,
|
||||
'is_active' => 1
|
||||
],
|
||||
[
|
||||
'spool_no' => $data['spool_no'] ?? null,
|
||||
'joint_type' => $data['joint_type'] ?? null,
|
||||
'welder_id' => $data['welder_id'] ?? null,
|
||||
'classification' => $data['classification'] ?? null,
|
||||
'x_coordinate' => $data['x_coordinate'] ?? 0,
|
||||
'y_coordinate' => $data['y_coordinate'] ?? 0,
|
||||
'width' => $data['width'] ?? 0,
|
||||
'height' => $data['height'] ?? 0,
|
||||
'shape_type' => $data['shape_type'] ?? 'rect',
|
||||
'qr_code_data' => $data['qr_code_data'] ?? null,
|
||||
'created_by' => $data['created_by'] ?? $userId,
|
||||
'original_start_point' => $data['original_start_point'] ?? null,
|
||||
'connected_shape_id' => $data['connected_shape_id'] ?? null,
|
||||
'stroke_color' => $data['stroke_color'] ?? '#000000',
|
||||
'stroke_width' => $data['stroke_width'] ?? 2,
|
||||
]
|
||||
);
|
||||
$saved[] = $annotation;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => "Page synced successfully as version {$newVersion}",
|
||||
'version' => $newVersion,
|
||||
'data' => $saved
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => $e->getMessage(),
|
||||
'message' => 'Failed to sync annotations'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function exportPDF(Request $request)
|
||||
{
|
||||
try {
|
||||
$request->validate([
|
||||
'pdf_file' => 'required|string',
|
||||
'annotations' => 'required|array',
|
||||
'canvas_image' => 'required|string',
|
||||
'export_format' => 'required|string',
|
||||
// Optional parameters for saving to Document Revision
|
||||
'save_to_revision' => 'nullable|boolean',
|
||||
'stage' => 'nullable|in:pdf_spool_iso,pdf_as_build',
|
||||
'drawing_no' => 'nullable|string',
|
||||
'revision_id' => 'nullable|integer',
|
||||
]);
|
||||
|
||||
// Canvas image'i decode et
|
||||
$imageData = $request->canvas_image;
|
||||
|
||||
// Remove data:image/png;base64, part
|
||||
$imageData = str_replace('data:image/png;base64,', '', $imageData);
|
||||
$imageData = str_replace(' ', '+', $imageData);
|
||||
$decodedImage = base64_decode($imageData);
|
||||
|
||||
// Temporary image file oluştur
|
||||
$tempImagePath = storage_path('app/temp_export_' . time() . '.png');
|
||||
file_put_contents($tempImagePath, $decodedImage);
|
||||
|
||||
// mPDF ile PDF oluştur
|
||||
$mpdf = new \Mpdf\Mpdf([
|
||||
'mode' => 'utf-8',
|
||||
'format' => 'A4-L', // Landscape orientation
|
||||
'margin_left' => 0,
|
||||
'margin_right' => 0,
|
||||
'margin_top' => 0,
|
||||
'margin_bottom' => 0
|
||||
]);
|
||||
|
||||
// Image'i PDF'e ekle
|
||||
$html = '<img src="' . $tempImagePath . '" style="width: 100%; height: auto;" />';
|
||||
$mpdf->WriteHTML($html);
|
||||
|
||||
// Generate filename
|
||||
$originalFilename = basename($request->pdf_file, '.pdf');
|
||||
$filename = 'annotated_' . $originalFilename . '_' . time() . '.pdf';
|
||||
|
||||
// Temporary file'ı sil
|
||||
if (file_exists($tempImagePath)) {
|
||||
unlink($tempImagePath);
|
||||
}
|
||||
|
||||
// Check if we should save to Document Revision
|
||||
$saveToRevision = $request->input('save_to_revision', false);
|
||||
|
||||
if ($saveToRevision && $request->filled('stage') && $request->filled('drawing_no')) {
|
||||
$stage = $request->input('stage');
|
||||
$drawingNo = $request->input('drawing_no');
|
||||
$revisionId = $request->input('revision_id');
|
||||
|
||||
// Determine storage folder based on stage
|
||||
$folderMap = [
|
||||
'pdf_spool_iso' => 'storage/documents/001_Drawings/002_Iso',
|
||||
'pdf_as_build' => 'storage/documents/001_Drawings/003_As_Build(ID)',
|
||||
];
|
||||
|
||||
$folder = $folderMap[$stage] ?? 'storage/documents/001_Drawings/003_As_Build(ID)';
|
||||
$storagePath = public_path($folder);
|
||||
|
||||
// Ensure directory exists
|
||||
if (!is_dir($storagePath)) {
|
||||
mkdir($storagePath, 0755, true);
|
||||
}
|
||||
|
||||
// Generate unique filename with drawing number
|
||||
$safeDrawingNo = preg_replace('/[^A-Za-z0-9\-\_\.]/', '_', $drawingNo);
|
||||
$savedFilename = $safeDrawingNo . '_annotated_' . date('Ymd_His') . '.pdf';
|
||||
$fullSavePath = $storagePath . '/' . $savedFilename;
|
||||
|
||||
// Save PDF to storage
|
||||
$pdfContent = $mpdf->Output('', 'S');
|
||||
file_put_contents($fullSavePath, $pdfContent);
|
||||
|
||||
\Log::info('PDF saved to storage', [
|
||||
'path' => $fullSavePath,
|
||||
'stage' => $stage,
|
||||
'drawing_no' => $drawingNo
|
||||
]);
|
||||
|
||||
// Update document_revisions table
|
||||
$relativePath = $folder . '/' . $savedFilename;
|
||||
|
||||
$query = DocumentRevision::query()
|
||||
->where('drawing_no', $drawingNo);
|
||||
|
||||
if ($revisionId) {
|
||||
$query->where('id', $revisionId);
|
||||
}
|
||||
|
||||
$updatedRows = $query->update([
|
||||
$stage => $relativePath,
|
||||
]);
|
||||
|
||||
\Log::info('Document revision updated', [
|
||||
'updated_rows' => $updatedRows,
|
||||
'stage' => $stage,
|
||||
'pdf_path' => $relativePath
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'PDF saved to ' . $stage . ' successfully',
|
||||
'pdf_path' => $relativePath,
|
||||
'updated_rows' => $updatedRows,
|
||||
'filename' => $savedFilename,
|
||||
]);
|
||||
}
|
||||
|
||||
// Return as download (default behavior)
|
||||
return response($mpdf->Output($filename, 'S'), 200)
|
||||
->header('Content-Type', 'application/pdf')
|
||||
->header('Content-Disposition', 'attachment; filename="' . $filename . '"');
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('Export PDF failed', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => $e->getMessage(),
|
||||
'message' => 'Failed to export PDF'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function actionHistory(Request $request): JsonResponse
|
||||
{
|
||||
$pdfFile = $request->query('pdf_file');
|
||||
|
||||
$logs = Annotation::query()
|
||||
->with(['updatedUser:id,name'])
|
||||
->when($pdfFile, fn($q) => $q->where('pdf_file_path', 'like', "%{$pdfFile}%"))
|
||||
->orderByDesc('updated_at')
|
||||
->select('version', 'updated_by', 'updated_at', 'is_active')
|
||||
->limit(200)
|
||||
->get();
|
||||
|
||||
$grouped = $logs
|
||||
->sortByDesc('updated_at')
|
||||
->groupBy('version')
|
||||
->map(fn($items) => $items->sortByDesc('updated_at')->first());
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $grouped->map(fn($log) => [
|
||||
'version' => $log->version,
|
||||
'user' => $log->updatedUser->name ?? 'System',
|
||||
'action' => $log->version == 1 ? 'New Record' : 'Updated',
|
||||
'time' => $log->updated_at?->format('Y-m-d H:i:s'),
|
||||
])->values(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function versionAnnotations(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'pdf_file' => 'required|string',
|
||||
'page_number' => 'required|integer',
|
||||
'version' => 'required|integer',
|
||||
]);
|
||||
|
||||
$pdfFile = $request->pdf_file;
|
||||
$page = (int) $request->page_number;
|
||||
$version = (int) $request->version;
|
||||
|
||||
$items = Annotation::where('pdf_file_path', 'like', '%' . basename($pdfFile) . '%')
|
||||
->where('page_number', $page)
|
||||
->where('version', $version)
|
||||
->orderBy('id', 'asc')
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $items,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save joint data to Base Weldmap (weld_logs table)
|
||||
* Phase 3.2: Base Weldmap Integration
|
||||
*/
|
||||
public function saveJointData(Request $request): JsonResponse
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'drawing_number' => 'required|string',
|
||||
'joint_data' => 'required|array',
|
||||
'joint_data.*.joint_no' => 'nullable|string',
|
||||
'joint_data.*.type_of_joint' => 'nullable|string|in:F,S',
|
||||
'joint_data.*.type_of_welds' => 'nullable|string',
|
||||
'joint_data.*.welding_date' => 'nullable|date',
|
||||
'joint_data.*.spool_no1' => 'nullable|string',
|
||||
'joint_data.*.spool_no2' => 'nullable|string',
|
||||
'joint_data.*.pose_no1' => 'nullable|string',
|
||||
'joint_data.*.pose_no2' => 'nullable|string',
|
||||
'joint_data.*.member1' => 'nullable|string',
|
||||
'joint_data.*.member2' => 'nullable|string',
|
||||
'joint_data.*.material' => 'nullable|string',
|
||||
'joint_data.*.dia1' => 'nullable|numeric',
|
||||
'joint_data.*.dia2' => 'nullable|numeric',
|
||||
'joint_data.*.nps1' => 'nullable|string',
|
||||
'joint_data.*.nps2' => 'nullable|string',
|
||||
'joint_data.*.thickness1' => 'nullable|numeric',
|
||||
'joint_data.*.thickness2' => 'nullable|numeric',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Validation failed',
|
||||
'errors' => $validator->errors()
|
||||
], 422);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$drawingNumber = $request->drawing_number;
|
||||
$jointDataArray = $request->joint_data;
|
||||
$savedJoints = [];
|
||||
|
||||
foreach ($jointDataArray as $jointData) {
|
||||
// Map widget form data to weld_logs table structure
|
||||
$weldLogData = [
|
||||
'iso_number' => $drawingNumber,
|
||||
'no_of_the_joint_as_per_as_built_survey' => $jointData['joint_no'] ?? null,
|
||||
'type_of_joint' => $jointData['type_of_joint'] ?? null,
|
||||
'type_of_welds' => $jointData['type_of_welds'] ?? null,
|
||||
'welding_date' => $jointData['welding_date'] ?? null,
|
||||
];
|
||||
|
||||
// Handle spool numbers - use spool_number_1/2 if exists, otherwise use spool_number/spool_number2
|
||||
if (isset($jointData['spool_no1'])) {
|
||||
if (Schema::hasColumn('weld_logs', 'spool_number_1')) {
|
||||
$weldLogData['spool_number_1'] = $jointData['spool_no1'];
|
||||
} else {
|
||||
$weldLogData['spool_number'] = $jointData['spool_no1'];
|
||||
}
|
||||
}
|
||||
if (isset($jointData['spool_no2'])) {
|
||||
if (Schema::hasColumn('weld_logs', 'spool_number_2')) {
|
||||
$weldLogData['spool_number_2'] = $jointData['spool_no2'];
|
||||
} elseif (Schema::hasColumn('weld_logs', 'spool_number2')) {
|
||||
$weldLogData['spool_number2'] = $jointData['spool_no2'];
|
||||
}
|
||||
}
|
||||
|
||||
// Handle pose numbers - use pose_number_1/2 if exists, otherwise use pose_no_1/2
|
||||
if (isset($jointData['pose_no1'])) {
|
||||
if (Schema::hasColumn('weld_logs', 'pose_number_1')) {
|
||||
$weldLogData['pose_number_1'] = $jointData['pose_no1'];
|
||||
} else {
|
||||
$weldLogData['pose_no_1'] = $jointData['pose_no1'];
|
||||
}
|
||||
}
|
||||
if (isset($jointData['pose_no2'])) {
|
||||
if (Schema::hasColumn('weld_logs', 'pose_number_2')) {
|
||||
$weldLogData['pose_number_2'] = $jointData['pose_no2'];
|
||||
} else {
|
||||
$weldLogData['pose_no_2'] = $jointData['pose_no2'];
|
||||
}
|
||||
}
|
||||
|
||||
// Handle members - use member_1/2 if exists, otherwise use member_no_1/2
|
||||
if (isset($jointData['member1'])) {
|
||||
if (Schema::hasColumn('weld_logs', 'member_1')) {
|
||||
$weldLogData['member_1'] = $jointData['member1'];
|
||||
} else {
|
||||
$weldLogData['member_no_1'] = $jointData['member1'];
|
||||
}
|
||||
}
|
||||
if (isset($jointData['member2'])) {
|
||||
if (Schema::hasColumn('weld_logs', 'member_2')) {
|
||||
$weldLogData['member_2'] = $jointData['member2'];
|
||||
} else {
|
||||
$weldLogData['member_no_2'] = $jointData['member2'];
|
||||
}
|
||||
}
|
||||
|
||||
// Handle material - use material_1/2 if exists, otherwise use material_no_1/2
|
||||
if (isset($jointData['material'])) {
|
||||
if (Schema::hasColumn('weld_logs', 'material_1')) {
|
||||
$weldLogData['material_1'] = $jointData['material'];
|
||||
$weldLogData['material_2'] = $jointData['material'];
|
||||
} else {
|
||||
$weldLogData['material_no_1'] = $jointData['material'];
|
||||
$weldLogData['material_no_2'] = $jointData['material'];
|
||||
}
|
||||
}
|
||||
|
||||
// Handle diameter - use dia_1/2 if exists, otherwise use outside_diameter_1/2
|
||||
if (isset($jointData['dia1'])) {
|
||||
if (Schema::hasColumn('weld_logs', 'dia_1')) {
|
||||
$weldLogData['dia_1'] = $jointData['dia1'];
|
||||
} else {
|
||||
$weldLogData['outside_diameter_1'] = $jointData['dia1'];
|
||||
}
|
||||
}
|
||||
if (isset($jointData['dia2'])) {
|
||||
if (Schema::hasColumn('weld_logs', 'dia_2')) {
|
||||
$weldLogData['dia_2'] = $jointData['dia2'];
|
||||
} else {
|
||||
$weldLogData['outside_diameter_2'] = $jointData['dia2'];
|
||||
}
|
||||
}
|
||||
|
||||
// Handle NPS - nps_1/2 should exist in both cases
|
||||
if (isset($jointData['nps1'])) {
|
||||
$weldLogData['nps_1'] = $jointData['nps1'];
|
||||
}
|
||||
if (isset($jointData['nps2'])) {
|
||||
$weldLogData['nps_2'] = $jointData['nps2'];
|
||||
}
|
||||
|
||||
// Handle thickness - use thickness_1/2 if exists, otherwise use wall_thickness_1/2
|
||||
if (isset($jointData['thickness1'])) {
|
||||
if (Schema::hasColumn('weld_logs', 'thickness_1')) {
|
||||
$weldLogData['thickness_1'] = $jointData['thickness1'];
|
||||
} else {
|
||||
$weldLogData['wall_thickness_1'] = $jointData['thickness1'];
|
||||
}
|
||||
}
|
||||
if (isset($jointData['thickness2'])) {
|
||||
if (Schema::hasColumn('weld_logs', 'thickness_2')) {
|
||||
$weldLogData['thickness_2'] = $jointData['thickness2'];
|
||||
} else {
|
||||
$weldLogData['wall_thickness_2'] = $jointData['thickness2'];
|
||||
}
|
||||
}
|
||||
|
||||
// Use updateOrCreate to prevent duplicates
|
||||
// Match by iso_number and joint_no (if provided)
|
||||
// CRITICAL: Try multiple matching strategies to find existing records
|
||||
$matchConditions = [
|
||||
'iso_number' => $drawingNumber,
|
||||
];
|
||||
|
||||
// CRITICAL: Try to find existing record using multiple strategies
|
||||
// Strategy 1: Match by joint_no (e.g., "53A")
|
||||
// Strategy 2: Match by draw_joint_no (e.g., "F53A") if joint_no doesn't match
|
||||
// Strategy 3: Match by type_of_joint + joint_no combination
|
||||
$existingRecord = null;
|
||||
|
||||
if (!empty($jointData['joint_no'])) {
|
||||
$jointNo = trim($jointData['joint_no']);
|
||||
|
||||
// Strategy 1: Try exact match with joint_no
|
||||
$existingRecord = WeldLog::where('iso_number', $drawingNumber)
|
||||
->where('no_of_the_joint_as_per_as_built_survey', $jointNo)
|
||||
->first();
|
||||
|
||||
// Strategy 2: If not found, try with draw_joint_no (Type + Joint No, e.g., "F53A")
|
||||
if (!$existingRecord && !empty($jointData['draw_joint_no'])) {
|
||||
$drawJointNo = trim($jointData['draw_joint_no']);
|
||||
$existingRecord = WeldLog::where('iso_number', $drawingNumber)
|
||||
->where('no_of_the_joint_as_per_as_built_survey', $drawJointNo)
|
||||
->first();
|
||||
}
|
||||
|
||||
// Strategy 3: If still not found, try with type_of_joint + joint_no
|
||||
if (!$existingRecord && !empty($jointData['type_of_joint'])) {
|
||||
$existingRecord = WeldLog::where('iso_number', $drawingNumber)
|
||||
->where('type_of_joint', $jointData['type_of_joint'])
|
||||
->where('no_of_the_joint_as_per_as_built_survey', $jointNo)
|
||||
->first();
|
||||
}
|
||||
|
||||
// Set match conditions based on what we found
|
||||
if ($existingRecord) {
|
||||
// If we found an existing record, match by its ID to ensure update
|
||||
$matchConditions = [
|
||||
'id' => $existingRecord->id
|
||||
];
|
||||
} else {
|
||||
// If no existing record, match by iso_number + joint_no for new record
|
||||
$matchConditions['no_of_the_joint_as_per_as_built_survey'] = $jointNo;
|
||||
}
|
||||
}
|
||||
|
||||
$weldLog = WeldLog::updateOrCreate(
|
||||
$matchConditions,
|
||||
$weldLogData
|
||||
);
|
||||
|
||||
$savedJoints[] = $weldLog;
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Joint data saved successfully',
|
||||
'data' => $savedJoints,
|
||||
'count' => count($savedJoints)
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Failed to save joint data',
|
||||
'error' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get joint data by shape_id or joint_no
|
||||
* Phase 3.1: API Endpoints for Joint Data
|
||||
*/
|
||||
public function getJointData(Request $request): JsonResponse
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'drawing_number' => 'required|string',
|
||||
'joint_no' => 'nullable|string',
|
||||
'shape_id' => 'nullable|string',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Validation failed',
|
||||
'errors' => $validator->errors()
|
||||
], 422);
|
||||
}
|
||||
|
||||
try {
|
||||
$drawingNumber = $request->drawing_number;
|
||||
$query = WeldLog::where('iso_number', $drawingNumber);
|
||||
|
||||
if ($request->has('joint_no') && !empty($request->joint_no)) {
|
||||
$query->where('no_of_the_joint_as_per_as_built_survey', $request->joint_no);
|
||||
}
|
||||
|
||||
// Dynamic column selection based on schema
|
||||
$selectColumns = [
|
||||
'id',
|
||||
'no_of_the_joint_as_per_as_built_survey as joint_no',
|
||||
'type_of_joint',
|
||||
'type_of_welds',
|
||||
'welding_date',
|
||||
];
|
||||
|
||||
// Add spool numbers (check which columns exist)
|
||||
if (Schema::hasColumn('weld_logs', 'spool_number_1')) {
|
||||
$selectColumns[] = 'spool_number_1 as spool_no1';
|
||||
} else {
|
||||
$selectColumns[] = 'spool_number as spool_no1';
|
||||
}
|
||||
if (Schema::hasColumn('weld_logs', 'spool_number_2')) {
|
||||
$selectColumns[] = 'spool_number_2 as spool_no2';
|
||||
} elseif (Schema::hasColumn('weld_logs', 'spool_number2')) {
|
||||
$selectColumns[] = 'spool_number2 as spool_no2';
|
||||
}
|
||||
|
||||
// Add pose numbers
|
||||
if (Schema::hasColumn('weld_logs', 'pose_number_1')) {
|
||||
$selectColumns[] = 'pose_number_1 as pose_no1';
|
||||
} else {
|
||||
$selectColumns[] = 'pose_no_1 as pose_no1';
|
||||
}
|
||||
if (Schema::hasColumn('weld_logs', 'pose_number_2')) {
|
||||
$selectColumns[] = 'pose_number_2 as pose_no2';
|
||||
} else {
|
||||
$selectColumns[] = 'pose_no_2 as pose_no2';
|
||||
}
|
||||
|
||||
// Add members
|
||||
if (Schema::hasColumn('weld_logs', 'member_1')) {
|
||||
$selectColumns[] = 'member_1 as member1';
|
||||
} else {
|
||||
$selectColumns[] = 'member_no_1 as member1';
|
||||
}
|
||||
if (Schema::hasColumn('weld_logs', 'member_2')) {
|
||||
$selectColumns[] = 'member_2 as member2';
|
||||
} else {
|
||||
$selectColumns[] = 'member_no_2 as member2';
|
||||
}
|
||||
|
||||
// Add material
|
||||
if (Schema::hasColumn('weld_logs', 'material_1')) {
|
||||
$selectColumns[] = 'material_1 as material';
|
||||
} else {
|
||||
$selectColumns[] = 'material_no_1 as material';
|
||||
}
|
||||
|
||||
// Add diameter
|
||||
if (Schema::hasColumn('weld_logs', 'dia_1')) {
|
||||
$selectColumns[] = 'dia_1 as dia1';
|
||||
} else {
|
||||
$selectColumns[] = 'outside_diameter_1 as dia1';
|
||||
}
|
||||
if (Schema::hasColumn('weld_logs', 'dia_2')) {
|
||||
$selectColumns[] = 'dia_2 as dia2';
|
||||
} else {
|
||||
$selectColumns[] = 'outside_diameter_2 as dia2';
|
||||
}
|
||||
|
||||
// Add NPS
|
||||
$selectColumns[] = 'nps_1 as nps1';
|
||||
$selectColumns[] = 'nps_2 as nps2';
|
||||
|
||||
// Add thickness
|
||||
if (Schema::hasColumn('weld_logs', 'thickness_1')) {
|
||||
$selectColumns[] = 'thickness_1 as thickness1';
|
||||
} else {
|
||||
$selectColumns[] = 'wall_thickness_1 as thickness1';
|
||||
}
|
||||
if (Schema::hasColumn('weld_logs', 'thickness_2')) {
|
||||
$selectColumns[] = 'thickness_2 as thickness2';
|
||||
} else {
|
||||
$selectColumns[] = 'wall_thickness_2 as thickness2';
|
||||
}
|
||||
|
||||
// Add welders
|
||||
$selectColumns[] = 'welder_1';
|
||||
$selectColumns[] = 'welder_2';
|
||||
|
||||
$joints = $query->get($selectColumns);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $joints
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Failed to get joint data',
|
||||
'error' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update welder assignment in Weldlog
|
||||
* Phase 3.3: Weldlog Integration
|
||||
*/
|
||||
public function updateWelderAssignment(Request $request): JsonResponse
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'drawing_number' => 'required|string',
|
||||
'joint_no' => 'required|string',
|
||||
'welder_id1' => 'nullable|string',
|
||||
'welder_id2' => 'nullable|string',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Validation failed',
|
||||
'errors' => $validator->errors()
|
||||
], 422);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$weldLog = WeldLog::where('iso_number', $request->drawing_number)
|
||||
->where('no_of_the_joint_as_per_as_built_survey', $request->joint_no)
|
||||
->first();
|
||||
|
||||
if (!$weldLog) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Joint not found'
|
||||
], 404);
|
||||
}
|
||||
|
||||
// Update welder assignments
|
||||
if ($request->has('welder_id1')) {
|
||||
$weldLog->welder_1 = $request->welder_id1;
|
||||
// Also update real_welder_1 if it exists
|
||||
if (Schema::hasColumn('weld_logs', 'real_welder_1')) {
|
||||
$weldLog->real_welder_1 = $request->welder_id1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->has('welder_id2')) {
|
||||
$weldLog->welder_2 = $request->welder_id2;
|
||||
// Also update real_welder_2 if it exists
|
||||
if (Schema::hasColumn('weld_logs', 'real_welder_2')) {
|
||||
$weldLog->real_welder_2 = $request->welder_id2;
|
||||
}
|
||||
}
|
||||
|
||||
$weldLog->save();
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Welder assignment updated successfully',
|
||||
'data' => $weldLog
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Failed to update welder assignment',
|
||||
'error' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
/**
|
||||
* @group Read Only Endpoints
|
||||
*
|
||||
* APIs for retrieving read-only data from various system modules.
|
||||
*/
|
||||
class ApiReadOnlyController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
// Auth handled at route level with 'auth:sanctum,web' to support both token and session auth
|
||||
}
|
||||
|
||||
private function renderLegacyScript($scriptPath, Request $request)
|
||||
{
|
||||
try {
|
||||
// Merge request parameters into global $_GET for legacy script compatibility
|
||||
if (!empty($request->all())) {
|
||||
$_GET = array_merge($_GET, $request->all());
|
||||
}
|
||||
|
||||
// Define path to the view
|
||||
$fullPath = resource_path("views/admin-ajax/{$scriptPath}");
|
||||
|
||||
if (!file_exists($fullPath)) {
|
||||
return response()->json(['error' => 'Module not found: ' . $scriptPath], 404);
|
||||
}
|
||||
|
||||
// Capture output
|
||||
ob_start();
|
||||
include($fullPath);
|
||||
$output = ob_get_clean();
|
||||
|
||||
// Attempt to decode JSON to ensure it's valid, otherwise return raw string if appropriate or wrap it
|
||||
$json = json_decode($output);
|
||||
if (json_last_error() === JSON_ERROR_NONE) {
|
||||
return response()->json($json);
|
||||
}
|
||||
|
||||
// If not JSON, it might be an error or HTML. For this API, we expect JSON.
|
||||
// We'll return it as a 'raw_output' field if it's not valid JSON
|
||||
return response()->json(['raw_output' => $output]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return response()->json(['error' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function ndtRequest(Request $request)
|
||||
{
|
||||
return $this->renderLegacyScript('request-ndt.blade.php', $request);
|
||||
}
|
||||
|
||||
public function ndtCalculation(Request $request)
|
||||
{
|
||||
return $this->renderLegacyScript('ndt-calculation.blade.php', $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spool Area Release
|
||||
*
|
||||
* Get spool area release data with pagination and filtering.
|
||||
*
|
||||
* @queryParam take int Number of items to take (pagination). Default: 100. Example: 10
|
||||
* @queryParam skip int Number of items to skip (pagination). Default: 0. Example: 0
|
||||
* @queryParam filter_iso_number string Filter by ISO Number. Example: 10-BFW-RS1-0001-AH06HS-HC
|
||||
* @queryParam filter_spool_number string Filter by Spool Number. Example: SPL-0004
|
||||
* @queryParam filter_line_number string Filter by Line Number. Example: LN-001
|
||||
* @queryParam filter_painting_cycle string Filter by Painting Cycle. Example: C1
|
||||
* @queryParam filter_spool_status string Filter by Spool Status. Example: Completed
|
||||
* @queryParam module string Specific module filter (e.g., 'spool-release-paint'). Example: spool-release-paint
|
||||
*
|
||||
* @response {
|
||||
* "summary": {"Completed": 10, "Waiting": 5},
|
||||
* "esummary": {"Completed": 2},
|
||||
* "datagrid": [
|
||||
* {
|
||||
* "id": 1,
|
||||
* "iso_number": "ISO-001",
|
||||
* "spool_number": "SPL-001",
|
||||
* "spool_status": "Completed",
|
||||
* "project": "PROJECT A"
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
*/
|
||||
public function spoolAreaRelease(Request $request)
|
||||
{
|
||||
$limit = $request->get('take', 100);
|
||||
$offset = $request->get('skip', 0);
|
||||
$isFiltered = $request->has('filter_iso_number') || $request->has('filter_spool_number');
|
||||
$module = $request->get('module');
|
||||
|
||||
// Spool status order mapping
|
||||
$statusOrder = [
|
||||
'Waiting' => 1,
|
||||
'Manufacturing' => 2,
|
||||
'QC' => 3,
|
||||
'Paint' => 4,
|
||||
'Completed' => 5,
|
||||
];
|
||||
|
||||
$caseSql = "CASE spool_status ";
|
||||
foreach ($statusOrder as $status => $order) {
|
||||
$caseSql .= "WHEN '$status' THEN $order ";
|
||||
}
|
||||
$caseSql .= "ELSE 99 END";
|
||||
|
||||
// Subquery for min status order
|
||||
$minStatusSub = apply_welded_filter(db("weld_logs"))
|
||||
->select(
|
||||
'iso_number',
|
||||
'spool_number',
|
||||
\DB::raw("MIN(CASE WHEN type_of_joint = 'S' THEN {$caseSql} END) as min_status_order")
|
||||
)
|
||||
->groupBy('iso_number', 'spool_number');
|
||||
|
||||
// Base query
|
||||
$query = apply_welded_filter(db("weld_logs"))
|
||||
->leftJoinSub($minStatusSub, 'min_status_order_tbl', function($join) {
|
||||
$join->on('weld_logs.iso_number', '=', 'min_status_order_tbl.iso_number')
|
||||
->on('weld_logs.spool_number', '=', 'min_status_order_tbl.spool_number');
|
||||
});
|
||||
|
||||
// Apply filters
|
||||
if ($request->has('filter_iso_number')) {
|
||||
$query->where("weld_logs.iso_number", "like", "%" . $request->get("filter_iso_number") . "%");
|
||||
}
|
||||
if ($request->has('filter_spool_number')) {
|
||||
$query->where("weld_logs.spool_number", "like", "%" . $request->get("filter_spool_number") . "%");
|
||||
}
|
||||
if ($request->has('filter_line_number')) {
|
||||
$query->where("weld_logs.line_number", "like", "%" . $request->get("filter_line_number") . "%");
|
||||
}
|
||||
if ($request->has('filter_painting_cycle')) {
|
||||
$query->where("weld_logs.painting_cycle", "like", "%" . $request->get("filter_painting_cycle") . "%");
|
||||
}
|
||||
if ($request->has('filter_spool_status')) {
|
||||
$query->where("weld_logs.spool_status", $request->get("filter_spool_status"));
|
||||
}
|
||||
if ($module === "spool-release-paint") {
|
||||
$query->whereNotNull("painting_cycle");
|
||||
}
|
||||
|
||||
// Field selection - always group by ISO and Spool to get single row per spool
|
||||
$query->select(
|
||||
'weld_logs.id',
|
||||
'weld_logs.iso_number',
|
||||
'weld_logs.spool_number',
|
||||
\DB::raw("GROUP_CONCAT(DISTINCT no_of_the_joint_as_per_as_built_survey ORDER BY CAST(no_of_the_joint_as_per_as_built_survey AS UNSIGNED) SEPARATOR ', ') AS joint_no"),
|
||||
\DB::raw("GROUP_CONCAT(DISTINCT type_of_joint SEPARATOR '/') as type_of_joint"),
|
||||
'project',
|
||||
'iso_rev',
|
||||
'painting_cycle',
|
||||
'spool_status',
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN clearance_no END) as clearance_no"),
|
||||
\DB::raw("MIN(CASE WHEN type_of_joint = 'S' THEN clearance_date END) as min_clearance_date"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN clearance_date END) as clearance_date"),
|
||||
\DB::raw("COUNT(DISTINCT CASE WHEN type_of_joint = 'S' THEN COALESCE(clearance_date, 'NULL_VALUE') END) as clearance_date_count"),
|
||||
\DB::raw("MIN(CASE WHEN type_of_joint = 'S' THEN ndt_release_date END) as min_ndt_release_date"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN ndt_release_date END) as ndt_release_date"),
|
||||
\DB::raw("COUNT(DISTINCT CASE WHEN type_of_joint = 'S' THEN COALESCE(ndt_release_date, 'NULL_VALUE') END) as ndt_release_date_count"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN register_paint_no END) as register_paint_no"),
|
||||
\DB::raw("MIN(CASE WHEN type_of_joint = 'S' THEN register_date END) as min_register_date"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN register_date END) as register_date"),
|
||||
\DB::raw("COUNT(DISTINCT CASE WHEN type_of_joint = 'S' THEN COALESCE(register_date, 'NULL_VALUE') END) as register_date_count"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN ndt_release_no END) as ndt_release_no"),
|
||||
\DB::raw("MIN(CASE WHEN type_of_joint = 'S' THEN paint_release_date END) as min_paint_release_date"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN paint_release_date END) as paint_release_date"),
|
||||
\DB::raw("COUNT(DISTINCT CASE WHEN type_of_joint = 'S' THEN COALESCE(paint_release_date, 'NULL_VALUE') END) as paint_release_date_count"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN paint_release_no END) as paint_release_no"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN spool_zone END) as spool_zone"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN spool_ndt_check END) as spool_ndt_check"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN spool_paint_check END) as spool_paint_check"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN spool_ndt_check_no END) as spool_ndt_check_no"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN ndt_release_check END) as ndt_release_check"),
|
||||
\DB::raw("MIN(CASE WHEN type_of_joint = 'S' THEN spool_ndt_check_date END) as min_spool_ndt_check_date"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN spool_ndt_check_date END) as spool_ndt_check_date"),
|
||||
\DB::raw("COUNT(DISTINCT CASE WHEN type_of_joint = 'S' THEN COALESCE(spool_ndt_check_date, 'NULL_VALUE') END) as spool_ndt_check_date_count"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN paint_release_check END) as paint_release_check"),
|
||||
\DB::raw("MAX(CASE WHEN type_of_joint = 'S' THEN spool_remarks END) as spool_remarks"),
|
||||
'min_status_order_tbl.min_status_order'
|
||||
)
|
||||
->groupBy("weld_logs.iso_number", "weld_logs.spool_number");
|
||||
|
||||
// Get total results before pagination for summaries
|
||||
$allResults = $query->get();
|
||||
|
||||
// Summary calculations
|
||||
$summary = [];
|
||||
$esummary = [];
|
||||
$users = usersArray();
|
||||
|
||||
$documentRevisions = [];
|
||||
$revisionQuery = db("document_revisions")->select('drawing_no', 'revision_no')->get();
|
||||
foreach ($revisionQuery as $revision) {
|
||||
$documentRevisions[$revision->drawing_no] = $revision->revision_no;
|
||||
}
|
||||
|
||||
$allSpoolStatusesQuery = db("weld_logs")
|
||||
->select('spool_status', 'iso_number', 'spool_number')->where("type_of_joint", "S")->get();
|
||||
|
||||
$allSpoolStatuses = [];
|
||||
foreach ($allSpoolStatusesQuery as $statusQuery) {
|
||||
$allSpoolStatuses[$statusQuery->iso_number][$statusQuery->spool_number][] = $statusQuery->spool_status;
|
||||
}
|
||||
|
||||
$orderToStatus = array_flip($statusOrder);
|
||||
|
||||
foreach ($allResults as $q) {
|
||||
// Processing logic from Blade
|
||||
if (strpos($q->type_of_joint, 'S') !== false && isset($q->min_status_order) && $q->min_status_order >= 1 && $q->min_status_order <= 5) {
|
||||
$q->spool_status = $orderToStatus[$q->min_status_order];
|
||||
}
|
||||
|
||||
$q->revision_no = $documentRevisions[$q->iso_number] ?? null;
|
||||
$q->project = strtoupper($q->project);
|
||||
|
||||
if ($q->spool_ndt_check != "") {
|
||||
foreach (['spool_ndt_check', 'spool_paint_check', 'ndt_release_check', 'paint_release_check'] as $field) {
|
||||
if (isset($users[$q->$field])) {
|
||||
$q->$field = "✒️" . $users[$q->$field]->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($q->spool_status)) {
|
||||
$types = explode('/', $q->type_of_joint);
|
||||
$hasS = in_array('S', $types) || in_array('F/S', $types);
|
||||
$hasF = in_array('F', $types);
|
||||
|
||||
if ($hasS) {
|
||||
if (!isset($summary[$q->spool_status])) $summary[$q->spool_status] = 0;
|
||||
$summary[$q->spool_status]++;
|
||||
}
|
||||
|
||||
if ($hasF) {
|
||||
if (!isset($esummary[$q->spool_status])) $esummary[$q->spool_status] = 0;
|
||||
$esummary[$q->spool_status]++;
|
||||
}
|
||||
}
|
||||
|
||||
$spoolStatuses = $allSpoolStatuses[$q->iso_number][$q->spool_number] ?? [];
|
||||
$q->spool_status = getLowestSpoolStatus($spoolStatuses);
|
||||
$q->latest_status = getLatestSpoolStatus($spoolStatuses);
|
||||
|
||||
$dateWarnings = [
|
||||
'ndt_release_date_count' => ['min_ndt_release_date', 'ndt_release_date'],
|
||||
'clearance_date_count' => ['min_clearance_date', 'clearance_date'],
|
||||
'register_date_count' => ['min_register_date', 'register_date'],
|
||||
'paint_release_date_count' => ['min_paint_release_date', 'paint_release_date'],
|
||||
'spool_ndt_check_date_count' => ['min_spool_ndt_check_date', 'spool_ndt_check_date'],
|
||||
];
|
||||
|
||||
foreach ($dateWarnings as $countField => $dateFields) {
|
||||
if ($q->$countField > 1 || $q->{$dateFields[0]} != $q->{$dateFields[1]}) {
|
||||
$q->spool_status .= "⚠️";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply skip/take to datagrid
|
||||
$datagrid = array_slice($allResults->toArray(), $offset, $limit);
|
||||
|
||||
return response()->json([
|
||||
'summary' => $summary,
|
||||
'esummary' => $esummary,
|
||||
'datagrid' => $datagrid,
|
||||
], 200, [], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
public function rfiDashboard(Request $request)
|
||||
{
|
||||
return $this->renderLegacyScript('rfi-dashboard.blade.php', $request);
|
||||
}
|
||||
|
||||
public function welderQualificationStatus(Request $request)
|
||||
{
|
||||
return $this->renderLegacyScript('welder-qualification-status.php', $request);
|
||||
}
|
||||
|
||||
public function punchList(Request $request)
|
||||
{
|
||||
return $this->renderLegacyScript('punch-summary/punch-list.blade.php', $request);
|
||||
}
|
||||
|
||||
public function naksWelders(Request $request)
|
||||
{
|
||||
// "Naks (Welder, Consu, Equipment)" - Checking specific files usually in admin-ajax
|
||||
// Assuming welder-qualification-status covers welders.
|
||||
// Need to check for Consumables and Equipment if separate files exist.
|
||||
return $this->renderLegacyScript('welder-qualification-status.php', $request);
|
||||
}
|
||||
|
||||
public function testPackagePivot(Request $request) {
|
||||
return $this->renderLegacyScript('test-package/pivot.blade.php', $request);
|
||||
}
|
||||
|
||||
public function testPackageStatusPivot(Request $request) {
|
||||
return $this->renderLegacyScript('test-package/status-pivot.blade.php', $request);
|
||||
}
|
||||
|
||||
public function testPackageSummary(Request $request) {
|
||||
return $this->renderLegacyScript('test-package/summary.blade.php', $request);
|
||||
}
|
||||
|
||||
public function testPackageSummary2(Request $request) {
|
||||
return $this->renderLegacyScript('test-package/summary2.blade.php', $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spool Release Detail
|
||||
*
|
||||
* Get detailed spool release information with filtering options.
|
||||
*
|
||||
* @queryParam filter_iso_number string Filter by ISO Number. Example: 10-BFW-RS1-0001-AH06HS-HC
|
||||
* @queryParam filter_spool_number string Filter by Spool Number. Example: SPL-0004
|
||||
*/
|
||||
public function spoolReleaseDetail(Request $request) {
|
||||
return $this->renderLegacyScript('spool-release-detail.blade.php', $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repair Table Statistics
|
||||
*
|
||||
* Get repair table statistics including defect types by welder, NPS, and material.
|
||||
*
|
||||
* @queryParam d1 string Start date (YYYY-MM-DD). Example: 2024-01-01
|
||||
* @queryParam d2 string End date (YYYY-MM-DD). Example: 2024-03-31
|
||||
*/
|
||||
public function repairTable(Request $request)
|
||||
{
|
||||
return $this->renderLegacyScript('repair-table.blade.php', $request);
|
||||
}
|
||||
|
||||
public function welderBasedRepairRatioDistribution(Request $request)
|
||||
{
|
||||
return $this->renderLegacyScript('repair-table/welder-based-repair-ratio-distribution.blade.php', $request);
|
||||
}
|
||||
|
||||
public function defectTypeByWelder(Request $request)
|
||||
{
|
||||
return $this->renderLegacyScript('repair-table/defect-type-by-welder.blade.php', $request);
|
||||
}
|
||||
|
||||
public function welderQualificationTable(Request $request)
|
||||
{
|
||||
return $this->renderLegacyScript('welder-qualification-table.blade.php', $request);
|
||||
}
|
||||
|
||||
public function rfiTasks(Request $request)
|
||||
{
|
||||
return $this->renderLegacyScript('rfi-tasks.blade.php', $request);
|
||||
}
|
||||
|
||||
public function rfiStatus(Request $request)
|
||||
{
|
||||
$settingValue = setting('rfi-status');
|
||||
$data = json_decode($settingValue, true);
|
||||
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
$data = $settingValue;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $data
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* NDT Release List
|
||||
*
|
||||
* Get list of NDT ready spools grouped by ISO and spool number.
|
||||
*/
|
||||
public function ndtReleaseList(Request $request)
|
||||
{
|
||||
return $this->renderLegacyScript('ndt-list.blade.php', $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint Release List
|
||||
*
|
||||
* Get list of paint released spools with paint release details.
|
||||
*/
|
||||
public function paintReleaseList(Request $request)
|
||||
{
|
||||
return $this->renderLegacyScript('ndt-paint-list.blade.php', $request);
|
||||
}
|
||||
|
||||
// Placeholder for other modules as they are identified
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
/**
|
||||
* @group Authentication
|
||||
*
|
||||
* API endpoints for user authentication and token management.
|
||||
*/
|
||||
class AuthController extends Controller
|
||||
{
|
||||
/**
|
||||
* Login (Get Token)
|
||||
*
|
||||
* Authenticates a user via email and password, returning a Bearer Token.
|
||||
* @unauthenticated
|
||||
*
|
||||
* @bodyParam email string required User's email address. Example: admin@example.com
|
||||
* @bodyParam password string required User's password. Example: password
|
||||
*/
|
||||
public function login(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'email' => 'required|email',
|
||||
'password' => 'required',
|
||||
]);
|
||||
|
||||
$user = User::where('email', $request->email)->first();
|
||||
|
||||
if (! $user || ! Hash::check($request->password, $user->password)) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Invalid credentials'
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Create Token (Device name is optional)
|
||||
$token = $user->createToken($request->device_name ?? 'api-client')->plainTextToken;
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Login successful',
|
||||
'data' => [
|
||||
'user' => $user,
|
||||
'access_token' => $token,
|
||||
'token_type' => 'Bearer',
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get User Profile
|
||||
*
|
||||
* Returns the authenticated user's information.
|
||||
*/
|
||||
public function me(Request $request)
|
||||
{
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => [
|
||||
'user' => $request->user()
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout
|
||||
*
|
||||
* Revokes the user's current access token.
|
||||
*/
|
||||
public function logout(Request $request)
|
||||
{
|
||||
$request->user()->currentAccessToken()->delete();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Token revoked'
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class AutocompleteTypeController extends Controller
|
||||
{
|
||||
/**
|
||||
* Mobile API wrapper for AdminController@autocompleteType.
|
||||
*
|
||||
* Web uses "/{hash}/autocomplete_type/{type}". Mobile cannot know {hash},
|
||||
* so we expose a safe, whitelisted endpoint under "/api/autocomplete-type/{type}".
|
||||
*/
|
||||
public function handle(Request $request, string $type)
|
||||
{
|
||||
if (!auth()->check() && !$request->user()) {
|
||||
return response()->json(['message' => 'Unauthenticated.'], 401);
|
||||
}
|
||||
|
||||
// Security: whitelist the only types needed by mobile screens.
|
||||
$allowedTypes = [
|
||||
'wps_no2',
|
||||
'real_welder_1',
|
||||
'real_welder_2',
|
||||
];
|
||||
|
||||
if (!in_array($type, $allowedTypes, true)) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Unsupported autocomplete type.',
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Permission: treat this as weldmap read (options lookup).
|
||||
if (!isAuth('weldmap', 'read')) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Unauthorized action.',
|
||||
'required_permission' => 'weldmap:read',
|
||||
], 403);
|
||||
}
|
||||
|
||||
// Provide $rowData to legacy autocomplete scripts.
|
||||
$rowData = (object) $request->all();
|
||||
|
||||
// Support "*" mapping convention used in AdminController.
|
||||
$type = str_replace('*', '/', $type);
|
||||
|
||||
$file = base_path("app/Http/Controllers/AutoCompleteType/{$type}.php");
|
||||
if (!file_exists($file)) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Autocomplete script not found.',
|
||||
], 404);
|
||||
}
|
||||
|
||||
$response = [];
|
||||
include $file;
|
||||
|
||||
return response()->json($response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get dashboard summary data extracted from the cached blade file.
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function summary(): JsonResponse
|
||||
{
|
||||
try {
|
||||
// Get the cached dashboard content from the 'documents' disk
|
||||
$cachedContent = Storage::disk('local')->get('cache/dashboard.blade.php');
|
||||
|
||||
if (!$cachedContent) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Cached dashboard content not found.'
|
||||
], 404);
|
||||
}
|
||||
|
||||
// Regex pattern to extract icon, value, and label
|
||||
// Matches block-content, img src, font-size-h3 (value), and font-size-sm (label)
|
||||
$pattern = '/<div class="block-content[^>]*>.*?<img src="([^"]+)"[^>]*>.*?<div class="font-size-h3[^>]*>(.*?)<\/div>\s*<div class="font-size-sm[^>]*>(.*?)<\/div>/s';
|
||||
|
||||
preg_match_all($pattern, $cachedContent, $matches, PREG_SET_ORDER);
|
||||
|
||||
$data = [];
|
||||
$baseUrl = url('/');
|
||||
|
||||
foreach ($matches as $match) {
|
||||
$iconPath = $match[1];
|
||||
$value = trim(strip_tags($match[2]));
|
||||
$label = trim(strip_tags($match[3]));
|
||||
|
||||
// Clean up excessive whitespace and newlines
|
||||
$value = preg_replace('/\s+/', ' ', $value);
|
||||
$label = preg_replace('/\s+/', ' ', $label);
|
||||
|
||||
// Make the icon URL absolute
|
||||
$iconUrl = str_starts_with($iconPath, 'http') ? $iconPath : rtrim($baseUrl, '/') . '/' . ltrim($iconPath, '/');
|
||||
|
||||
if ($label) {
|
||||
$data[] = [
|
||||
'label' => $label,
|
||||
'value' => $value,
|
||||
'icon' => $iconUrl
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $data
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'An error occurred while extracting dashboard data: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\DocumentHistory;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* @group Document Management
|
||||
*
|
||||
* APIs for managing documents and their history.
|
||||
*/
|
||||
class DocumentHistoryController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get Document History
|
||||
*
|
||||
* Retrieve the history of a document based on file name or table reference.
|
||||
*
|
||||
* @bodyParam table string The name of the table (e.g., document_revisions). Example: document_revisions
|
||||
* @bodyParam column string The name of the column (e.g., pdf_spool_iso). Example: pdf_spool_iso
|
||||
* @bodyParam row_id integer The ID of the row. Example: 3021
|
||||
* @bodyParam file_name string The name of the file to search for. Example: MST-80-AH01PR-FE31.803.pdf
|
||||
*
|
||||
* @response {
|
||||
* "id": 345,
|
||||
* "user_name": "Linga Samiii",
|
||||
* "action": "Archive",
|
||||
* "file_name": "MST-80-AH01PR-FE31.803.pdf",
|
||||
* "file_size": "474.4 KB",
|
||||
* "moved_from": "001_Drawings",
|
||||
* "moved_to": "Archive/001_Drawings",
|
||||
* "action_date": "2025-07-19 16:11:00",
|
||||
* "file_path": "storage/documents/...",
|
||||
* "notes": "File replaced with new version..."
|
||||
* }
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$table = $request->input('table');
|
||||
$column = $request->input('column');
|
||||
$row_id = $request->input('row_id');
|
||||
$file_name = $request->input('file_name');
|
||||
|
||||
$query = DocumentHistory::query();
|
||||
|
||||
|
||||
|
||||
if ($file_name) {
|
||||
// File name'e göre arama
|
||||
$base_name = str_replace(".pdf", "", $file_name);
|
||||
// Sadece tam dosya adlarını veya '_' ile ayrılmış arşiv adlarını (örn: _2025_08_30...) eşleştir
|
||||
$query->where(function ($q) use ($base_name, $file_name) {
|
||||
$q->where('file_name', $file_name)
|
||||
->orWhere('file_name', 'LIKE', $base_name . '_%.pdf');
|
||||
});
|
||||
} elseif ($table && $row_id) {
|
||||
// Table ve row_id'ye göre dosyayı bulup arama yap
|
||||
try {
|
||||
$row = \Illuminate\Support\Facades\DB::table($table)->find($row_id);
|
||||
|
||||
if ($row) {
|
||||
$filenames = [];
|
||||
|
||||
if ($column && isset($row->$column)) {
|
||||
// Belirli bir kolon varsa
|
||||
$value = $row->$column;
|
||||
if ($value && is_string($value)) {
|
||||
$filenames[] = basename($value);
|
||||
}
|
||||
} else {
|
||||
// Kolon belirtilmemişse, olası dosya kolonlarını tara
|
||||
foreach ((array) $row as $key => $value) {
|
||||
if ($value && is_string($value) && preg_match('/\.(pdf|xls|xlsx|doc|docx|jpg|png|jpeg)$/i', $value)) {
|
||||
$filenames[] = basename($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($filenames)) {
|
||||
$query->whereIn('file_name', $filenames);
|
||||
} else {
|
||||
// Dosya bulunamadıysa boş dön
|
||||
return response()->json([]);
|
||||
}
|
||||
} else {
|
||||
return response()->json([]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Tablo hatası vs.
|
||||
return response()->json([]);
|
||||
}
|
||||
} else {
|
||||
// Hiçbir geçerli filtre yoksa boş döndür
|
||||
return response()->json([]);
|
||||
}
|
||||
|
||||
|
||||
$documentHistory = $query->orderBy('action_date', 'DESC')
|
||||
->get()
|
||||
->map(function ($item) {
|
||||
return [
|
||||
'id' => $item->id,
|
||||
'user_name' => $item->user_name,
|
||||
'action' => $item->action,
|
||||
'file_name' => $item->file_name,
|
||||
'file_size' => $item->file_size,
|
||||
'moved_from' => $item->moved_from,
|
||||
'moved_to' => $item->moved_to,
|
||||
'action_date' => $item->action_date,
|
||||
'file_path' => $item->file_path,
|
||||
'notes' => $item->notes
|
||||
];
|
||||
});
|
||||
|
||||
return response()->json($documentHistory);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,434 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @group Endpoints
|
||||
*
|
||||
* API endpoints for serving admin-ajax blade content.
|
||||
* These endpoints provide access to backend blade files that return JSON or HTML responses.
|
||||
*/
|
||||
class EndpointController extends Controller
|
||||
{
|
||||
/**
|
||||
* List Available Endpoints
|
||||
*
|
||||
* Returns a list of all available admin-ajax endpoints that can be accessed via the API.
|
||||
* Each endpoint corresponds to a blade file in the admin-ajax directory.
|
||||
*
|
||||
* The response includes all endpoints with their names, URLs, HTTP methods, response types, and categories.
|
||||
*
|
||||
* @responseFile storage/app/scribe/endpoints-response.json
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$endpoints = $this->getAvailableEndpoints();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => [
|
||||
'endpoints' => $endpoints,
|
||||
'total' => count($endpoints)
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute Endpoint
|
||||
*
|
||||
* Executes the specified admin-ajax endpoint and returns the response.
|
||||
* The response type is automatically detected:
|
||||
* - If the output is valid JSON, returns JSON response
|
||||
* - Otherwise, returns HTML response
|
||||
*
|
||||
* @urlParam endpoint string required The endpoint name (e.g., users, ndt-calculation). Example: users
|
||||
*
|
||||
* @queryParam _format string Optional. Force response format: 'json' or 'html'. Example: json
|
||||
*
|
||||
* @response 200 scenario="JSON Response" {
|
||||
* "status": "success",
|
||||
* "data": [{"id": 1, "name": "John Doe"}],
|
||||
* "format": "json"
|
||||
* }
|
||||
*
|
||||
* @response 200 scenario="HTML Response" {
|
||||
* "status": "success",
|
||||
* "html": "<div>Content here</div>",
|
||||
* "format": "html"
|
||||
* }
|
||||
*
|
||||
* @response 404 {
|
||||
* "status": "error",
|
||||
* "message": "Endpoint not found"
|
||||
* }
|
||||
*/
|
||||
public function handle(Request $request, string $endpoint)
|
||||
{
|
||||
// Sanitize endpoint name
|
||||
$endpoint = $this->sanitizeEndpoint($endpoint);
|
||||
|
||||
// Check if endpoint exists
|
||||
if (!$this->endpointExists($endpoint)) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Endpoint not found',
|
||||
'endpoint' => $endpoint
|
||||
], 404);
|
||||
}
|
||||
|
||||
// SECURITY: Only allow readonly endpoints via API
|
||||
if (!$this->isReadonlyEndpoint($endpoint)) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'This endpoint is not available via API. Only readonly endpoints are accessible.',
|
||||
'endpoint' => $endpoint
|
||||
], 403);
|
||||
}
|
||||
|
||||
try {
|
||||
// Render the blade view and capture output
|
||||
$output = $this->renderEndpoint($endpoint, $request);
|
||||
|
||||
// Detect response format
|
||||
$format = $request->input('_format');
|
||||
|
||||
if ($format === 'html') {
|
||||
return $this->htmlResponse($output);
|
||||
}
|
||||
|
||||
if ($format === 'json' || $this->isJson($output)) {
|
||||
return $this->jsonResponse($output);
|
||||
}
|
||||
|
||||
return $this->htmlResponse($output);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage(),
|
||||
'endpoint' => $endpoint
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Endpoint Info
|
||||
*
|
||||
* Returns detailed information about a specific endpoint.
|
||||
*
|
||||
* @urlParam endpoint string required The endpoint name. Example: users
|
||||
*
|
||||
* @response 200 {
|
||||
* "status": "success",
|
||||
* "data": {
|
||||
* "name": "users",
|
||||
* "url": "/api/endpoints/users",
|
||||
* "methods": ["GET", "POST"],
|
||||
* "exists": true,
|
||||
* "api_accessible": true,
|
||||
* "path": "resources/views/admin-ajax/users.blade.php"
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
public function info(Request $request, string $endpoint)
|
||||
{
|
||||
$endpoint = $this->sanitizeEndpoint($endpoint);
|
||||
$exists = $this->endpointExists($endpoint);
|
||||
$isReadonly = $exists ? $this->isReadonlyEndpoint($endpoint) : false;
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => [
|
||||
'name' => $endpoint,
|
||||
'url' => "/api/endpoints/{$endpoint}",
|
||||
'methods' => ['GET', 'POST'],
|
||||
'exists' => $exists,
|
||||
'api_accessible' => $isReadonly,
|
||||
'path' => $exists ? "resources/views/admin-ajax/{$endpoint}.blade.php" : null,
|
||||
'note' => !$isReadonly && $exists ? 'This endpoint is not marked as @api-readonly and cannot be accessed via API' : null
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize endpoint name to prevent directory traversal
|
||||
*/
|
||||
protected function sanitizeEndpoint(string $endpoint): string
|
||||
{
|
||||
// Remove any path traversal attempts
|
||||
$endpoint = str_replace(['..', '/', '\\'], '', $endpoint);
|
||||
|
||||
// Convert to lowercase and replace spaces with dashes
|
||||
$endpoint = Str::slug($endpoint);
|
||||
|
||||
return $endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if endpoint blade file exists
|
||||
*/
|
||||
protected function endpointExists(string $endpoint): bool
|
||||
{
|
||||
return View::exists("admin-ajax.{$endpoint}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if endpoint is marked as readonly (safe for API access)
|
||||
*
|
||||
* Endpoints must have the annotation {{-- @api-readonly --}} at the beginning
|
||||
* to be accessible via the API. This prevents write/delete operations from
|
||||
* being exposed externally.
|
||||
*/
|
||||
protected function isReadonlyEndpoint(string $endpoint): bool
|
||||
{
|
||||
$path = resource_path("views/admin-ajax/{$endpoint}.blade.php");
|
||||
|
||||
if (!File::exists($path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$content = File::get($path);
|
||||
|
||||
// Check for @api-readonly annotation
|
||||
// Supports: {{-- @api-readonly --}} or <?php // @api-readonly
|
||||
return Str::contains($content, '@api-readonly');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file path for an endpoint
|
||||
*/
|
||||
protected function getEndpointPath(string $endpoint): ?string
|
||||
{
|
||||
// Check main directory
|
||||
$path = resource_path("views/admin-ajax/{$endpoint}.blade.php");
|
||||
if (File::exists($path)) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
// Check subdirectories
|
||||
$parts = explode('/', $endpoint);
|
||||
if (count($parts) > 1) {
|
||||
$subPath = resource_path("views/admin-ajax/" . implode('/', $parts) . ".blade.php");
|
||||
if (File::exists($subPath)) {
|
||||
return $subPath;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the endpoint blade file
|
||||
*/
|
||||
protected function renderEndpoint(string $endpoint, Request $request): string
|
||||
{
|
||||
// Start output buffering to capture any echo/print statements
|
||||
ob_start();
|
||||
|
||||
try {
|
||||
// Render the view with request data
|
||||
$view = View::make("admin-ajax.{$endpoint}", [
|
||||
'request' => $request
|
||||
]);
|
||||
|
||||
// Get rendered content
|
||||
$rendered = $view->render();
|
||||
|
||||
// Get any buffered output (from echo statements in blade)
|
||||
$buffered = ob_get_clean();
|
||||
|
||||
// Return buffered output if exists, otherwise rendered content
|
||||
return !empty($buffered) ? $buffered : $rendered;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
ob_end_clean();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if string is valid JSON
|
||||
*/
|
||||
protected function isJson(string $string): bool
|
||||
{
|
||||
if (empty($string)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$string = trim($string);
|
||||
|
||||
// Quick check for JSON structure
|
||||
if (!in_array($string[0], ['{', '['])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
json_decode($string);
|
||||
return json_last_error() === JSON_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return JSON response
|
||||
*/
|
||||
protected function jsonResponse(string $output)
|
||||
{
|
||||
$data = json_decode($output, true);
|
||||
|
||||
// If already has status wrapper, return as-is
|
||||
if (is_array($data) && isset($data['status'])) {
|
||||
return response()->json($data);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $data,
|
||||
'format' => 'json'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return HTML response
|
||||
*/
|
||||
protected function htmlResponse(string $output)
|
||||
{
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'html' => $output,
|
||||
'format' => 'html'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all available endpoints from admin-ajax directory
|
||||
* Only returns endpoints marked with @api-readonly annotation
|
||||
*/
|
||||
public function getAvailableEndpoints(): array
|
||||
{
|
||||
$endpoints = [];
|
||||
$path = resource_path('views/admin-ajax');
|
||||
|
||||
if (!File::isDirectory($path)) {
|
||||
return $endpoints;
|
||||
}
|
||||
|
||||
// Scan all blade files recursively
|
||||
$this->scanEndpointsRecursive($path, '', $endpoints);
|
||||
|
||||
// Sort alphabetically
|
||||
usort($endpoints, fn($a, $b) => strcmp($a['name'], $b['name']));
|
||||
|
||||
return $endpoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively scan directory for readonly endpoints
|
||||
*/
|
||||
protected function scanEndpointsRecursive(string $basePath, string $prefix, array &$endpoints): void
|
||||
{
|
||||
$files = File::files($basePath);
|
||||
|
||||
foreach ($files as $file) {
|
||||
$filename = $file->getFilename();
|
||||
|
||||
// Only process .blade.php files
|
||||
if (!Str::endsWith($filename, '.blade.php')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extract endpoint name
|
||||
$name = str_replace('.blade.php', '', $filename);
|
||||
$fullName = $prefix ? "{$prefix}/{$name}" : $name;
|
||||
|
||||
// Check file content for @api-readonly annotation
|
||||
$content = File::get($file->getPathname());
|
||||
|
||||
// SECURITY: Only include endpoints marked as readonly
|
||||
if (!Str::contains($content, '@api-readonly')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$endpoints[] = [
|
||||
'name' => $fullName,
|
||||
'url' => "/api/endpoints/{$fullName}",
|
||||
'methods' => ['GET', 'POST']
|
||||
];
|
||||
}
|
||||
|
||||
// Scan subdirectories
|
||||
$directories = File::directories($basePath);
|
||||
foreach ($directories as $dir) {
|
||||
$dirName = basename($dir);
|
||||
$newPrefix = $prefix ? "{$prefix}/{$dirName}" : $dirName;
|
||||
$this->scanEndpointsRecursive($dir, $newPrefix, $endpoints);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get endpoints grouped by category (for documentation)
|
||||
*/
|
||||
public function getEndpointsByCategory(): array
|
||||
{
|
||||
$endpoints = $this->getAvailableEndpoints();
|
||||
$categories = [];
|
||||
|
||||
foreach ($endpoints as $endpoint) {
|
||||
$name = $endpoint['name'];
|
||||
|
||||
// Determine category based on prefix
|
||||
$category = $this->categorizeEndpoint($name);
|
||||
|
||||
if (!isset($categories[$category])) {
|
||||
$categories[$category] = [];
|
||||
}
|
||||
|
||||
$categories[$category][] = $endpoint;
|
||||
}
|
||||
|
||||
ksort($categories);
|
||||
return $categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Categorize endpoint based on name prefix
|
||||
*/
|
||||
protected function categorizeEndpoint(string $name): string
|
||||
{
|
||||
$prefixes = [
|
||||
'ndt-' => 'NDT Operations',
|
||||
'welder-' => 'Welder Management',
|
||||
'weld' => 'Welding',
|
||||
'register-' => 'Register Creator',
|
||||
'test-package' => 'Test Packages',
|
||||
'tp-' => 'Test Packages',
|
||||
'document-' => 'Document Management',
|
||||
'report-' => 'Reports',
|
||||
'summary' => 'Summaries',
|
||||
'excel-' => 'Excel Operations',
|
||||
'pdf' => 'PDF Operations',
|
||||
'user' => 'User Management',
|
||||
'permission' => 'Permissions',
|
||||
'content-' => 'Content Management',
|
||||
'spool-' => 'Spool Operations',
|
||||
'material-' => 'Materials',
|
||||
'paint-' => 'Paint Operations',
|
||||
'repair-' => 'Repair Operations',
|
||||
'rfi-' => 'RFI Operations',
|
||||
'punch-' => 'Punch Lists',
|
||||
'mto' => 'MTO Operations',
|
||||
];
|
||||
|
||||
foreach ($prefixes as $prefix => $category) {
|
||||
if (Str::startsWith($name, $prefix)) {
|
||||
return $category;
|
||||
}
|
||||
}
|
||||
|
||||
return 'General';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Types;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
||||
class MobileTypeController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$types = Types::where('is_mobile', true)->where('enabled', true)->orderBy("s", "ASC")->get();
|
||||
$result = [];
|
||||
|
||||
foreach ($types as $type) {
|
||||
if (!isAuth($type->slug, 'read')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$bladePath = resource_path("views/admin/type/{$type->slug}.blade.php");
|
||||
$tableName = null;
|
||||
|
||||
if (File::exists($bladePath)) {
|
||||
$content = File::get($bladePath);
|
||||
if (preg_match('/\$tableName\s*=\s*["\']([^"\']+)["\']\s*;/', $content, $matches)) {
|
||||
$tableName = $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Get saved mobile columns from settings
|
||||
$mobileColumnsJson = setting("type_{$type->id}_mobile_columns", false, '');
|
||||
$columns = [];
|
||||
if ($mobileColumnsJson) {
|
||||
$decoded = json_decode($mobileColumnsJson, true);
|
||||
if (is_array($decoded)) {
|
||||
$columns = $decoded;
|
||||
}
|
||||
}
|
||||
|
||||
$result[] = [
|
||||
'title' => $type->title,
|
||||
'slug' => $type->slug,
|
||||
'table_name' => $tableName,
|
||||
'order' => $type->s,
|
||||
'parent' => $type->kid,
|
||||
'icon' => asset("assets/icons/{$type->icon}.png"),
|
||||
'columns' => $columns,
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Services\NaksSyncService;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class NaksSyncController extends Controller
|
||||
{
|
||||
/**
|
||||
* Handle upcoming sync trigger from another project.
|
||||
* This endpoint is called by other projects when they update a record.
|
||||
*/
|
||||
public function triggerSync(Request $request, NaksSyncService $syncService)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'module' => 'required|string',
|
||||
'source_project' => 'required|string'
|
||||
]);
|
||||
|
||||
$module = $validated['module'];
|
||||
$source = $validated['source_project'];
|
||||
|
||||
Log::info("Received NAKS Sync Trigger from [$source] for module [$module]");
|
||||
|
||||
// Prevent infinite loops if logic isn't careful, but NaksSyncService checks timestamps.
|
||||
// We will queue the actual sync to perform it in background
|
||||
// We use 'dispatch' helper or creating a Job closure
|
||||
|
||||
// We can run the sync service directly here if we want immediate feedback, but it might take time.
|
||||
// Best practice is to queue it.
|
||||
|
||||
// Let's create a closure job or reuse existing mechanism.
|
||||
// Since we don't have a dedicated "RunSyncJob", we'll do it inline with fast execution or
|
||||
// dispatch a closure.
|
||||
|
||||
dispatch(function () use ($syncService, $module) {
|
||||
try {
|
||||
// Sync specific module from all projects (or finding the specific source, but the service supports 'all' or filtered)
|
||||
// The service reads from 'api/project-app-urls' list.
|
||||
// We should sync 'all' projects to be safe, or we could optimize later.
|
||||
$syncService->sync($module);
|
||||
} catch (\Exception $e) {
|
||||
Log::error("Error in Queued NAKS Sync: " . $e->getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Sync triggered successfully',
|
||||
'status' => 'queued'
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,914 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\DocumentRevision;
|
||||
use App\Models\WeldLog;
|
||||
use App\Models\WelderTest;
|
||||
use App\Models\MaterialGroupMap;
|
||||
use App\Models\IncomingControl;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class PdfEditorLookupController extends Controller
|
||||
{
|
||||
private const DRAWING_TYPES = [
|
||||
'engineering' => [
|
||||
'label' => 'Engineering Drawing',
|
||||
'column' => 'pdf_engineering',
|
||||
'folder' => 'storage/documents/001_Drawings/001_Engineering',
|
||||
],
|
||||
'spool' => [
|
||||
'label' => 'Spool Drawing',
|
||||
'column' => 'pdf_spool_iso',
|
||||
'folder' => 'storage/documents/001_Drawings/002_Iso',
|
||||
],
|
||||
'as_build' => [
|
||||
'label' => 'As-Build Drawing',
|
||||
'column' => 'pdf_as_build',
|
||||
'folder' => 'storage/documents/001_Drawings/003_As_Build(ID)',
|
||||
],
|
||||
];
|
||||
|
||||
public function drawingTypes(): JsonResponse
|
||||
{
|
||||
$types = collect(self::DRAWING_TYPES)->map(function (array $config, string $key) {
|
||||
return [
|
||||
'value' => $key,
|
||||
'label' => $config['label'],
|
||||
];
|
||||
})->values();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $types,
|
||||
]);
|
||||
}
|
||||
|
||||
public function drawings(Request $request): JsonResponse
|
||||
{
|
||||
$type = $request->query('type', 'engineering');
|
||||
$config = self::DRAWING_TYPES[$type] ?? null;
|
||||
|
||||
if ($config === null) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Unsupported drawing type',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$column = $config['column'];
|
||||
|
||||
$query = DocumentRevision::query()
|
||||
->whereNotNull('drawing_no')
|
||||
->where('drawing_no', '!=', '');
|
||||
|
||||
if ($column) {
|
||||
$query->whereNotNull($column)->where($column, '!=', '');
|
||||
}
|
||||
|
||||
$drawings = $query
|
||||
->select('drawing_no')
|
||||
->distinct()
|
||||
->orderBy('drawing_no')
|
||||
->get()
|
||||
->map(fn ($row) => [
|
||||
'value' => $row->drawing_no,
|
||||
'label' => $row->drawing_no,
|
||||
]);
|
||||
|
||||
if ($drawings->isEmpty() && isset($config['folder'])) {
|
||||
$drawings = collect($this->scanDrawingFolder($config['folder']))
|
||||
->map(fn (string $name) => [
|
||||
'value' => $name,
|
||||
'label' => $name,
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $drawings,
|
||||
]);
|
||||
}
|
||||
|
||||
public function files(Request $request): JsonResponse
|
||||
{
|
||||
$type = $request->query('type');
|
||||
$drawing = $request->query('drawing');
|
||||
|
||||
if (!$type || !$drawing) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Drawing type and drawing number are required',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$config = self::DRAWING_TYPES[$type] ?? null;
|
||||
|
||||
if ($config === null) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Unsupported drawing type',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$column = $config['column'];
|
||||
$files = collect();
|
||||
|
||||
if ($column) {
|
||||
$files = $this->buildFileListFromColumn($drawing, $column);
|
||||
}
|
||||
|
||||
if ($files->isEmpty() && $type === 'as_build') {
|
||||
$fallbackColumns = ['working_documentation', 'axonometry'];
|
||||
|
||||
foreach ($fallbackColumns as $fallbackColumn) {
|
||||
$files = $this->buildFileListFromColumn($drawing, $fallbackColumn);
|
||||
|
||||
if ($files->isNotEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($files->isEmpty() && isset($config['folder'])) {
|
||||
$publicFolder = public_path($config['folder']);
|
||||
if (is_dir($publicFolder)) {
|
||||
$pattern = $publicFolder . '/' . $drawing . '*.pdf';
|
||||
$matches = glob($pattern) ?: [];
|
||||
|
||||
$files = collect($matches)->map(function (string $filePath) {
|
||||
$relativePath = $this->relativePublicPath($filePath);
|
||||
$filename = basename($filePath);
|
||||
|
||||
return [
|
||||
'id' => md5($filePath),
|
||||
'revision' => null,
|
||||
'label' => $filename,
|
||||
'url' => $relativePath ? url($relativePath) : null,
|
||||
'path' => $relativePath,
|
||||
'is_latest' => false,
|
||||
'exists' => true,
|
||||
'updated_at' => Carbon::createFromTimestamp(filemtime($filePath))->toDateTimeString(),
|
||||
];
|
||||
})->sortByDesc('updated_at')->values();
|
||||
|
||||
if ($files->isNotEmpty()) {
|
||||
$files = $files->map(function (array $item, int $index) {
|
||||
$item['is_latest'] = $index === 0;
|
||||
return $item;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $files->values(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function updateDocumentStage(Request $request): JsonResponse
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'drawing' => ['required', 'string'],
|
||||
'stage' => ['required', Rule::in(['pdf_spool_iso', 'pdf_as_build'])],
|
||||
'pdf_path' => ['required', 'string'],
|
||||
'revision_id' => ['nullable', 'integer'],
|
||||
]);
|
||||
|
||||
$pdfPath = trim($validated['pdf_path']);
|
||||
|
||||
if ($pdfPath === '') {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'PDF path cannot be empty.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$query = DocumentRevision::query()
|
||||
->where('drawing_no', $validated['drawing']);
|
||||
|
||||
if (!empty($validated['revision_id'])) {
|
||||
$query->where('id', $validated['revision_id']);
|
||||
}
|
||||
|
||||
$updatedRows = $query->update([
|
||||
$validated['stage'] => $pdfPath,
|
||||
]);
|
||||
|
||||
if ($updatedRows === 0) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'No matching document revisions found for update.',
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'updated_rows' => $updatedRows,
|
||||
'stage' => $validated['stage'],
|
||||
'pdf_path' => $pdfPath,
|
||||
]);
|
||||
}
|
||||
|
||||
private function buildFileListFromColumn(string $drawing, string $column): \Illuminate\Support\Collection
|
||||
{
|
||||
$records = DocumentRevision::query()
|
||||
->where('drawing_no', $drawing)
|
||||
->whereNotNull($column)
|
||||
->where($column, '!=', '')
|
||||
->orderByDesc('publish_date')
|
||||
->orderByDesc('updated_at')
|
||||
->get(['id', 'drawing_no', 'revision_no', 'publish_date', 'updated_at', $column]);
|
||||
|
||||
if ($records->isEmpty()) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
$latestId = optional($records->first())->id;
|
||||
|
||||
return $records->map(function (DocumentRevision $revision) use ($latestId, $column) {
|
||||
$path = $revision->{$column};
|
||||
if (!$path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$fullPath = public_path($path);
|
||||
$exists = $fullPath ? file_exists($fullPath) : false;
|
||||
|
||||
$timestamp = $revision->publish_date
|
||||
? Carbon::parse($revision->publish_date)->startOfDay()
|
||||
: ($revision->updated_at instanceof Carbon ? $revision->updated_at : Carbon::parse($revision->updated_at));
|
||||
|
||||
return [
|
||||
'id' => $revision->id,
|
||||
'revision' => $revision->revision_no,
|
||||
'label' => $this->formatLabel($revision->revision_no, $path),
|
||||
'url' => $path ? url($path) : null,
|
||||
'path' => $path,
|
||||
'is_latest' => $revision->id === $latestId,
|
||||
'exists' => $exists,
|
||||
'updated_at' => $timestamp?->toDateTimeString(),
|
||||
];
|
||||
})->filter()->values();
|
||||
}
|
||||
|
||||
public function weldData(Request $request): JsonResponse
|
||||
{
|
||||
$drawing = trim((string) $request->query('drawing', ''));
|
||||
|
||||
if ($drawing === '') {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Drawing number is required',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$logs = WeldLog::query()
|
||||
->where('iso_number', $drawing)
|
||||
->select([
|
||||
'spool_number',
|
||||
'spool_number2',
|
||||
'no_of_the_joint_as_per_as_built_survey',
|
||||
'type_of_joint',
|
||||
'welder_1',
|
||||
'welder_2',
|
||||
'real_welder_1',
|
||||
'real_welder_2',
|
||||
])
|
||||
->orderBy('spool_number')
|
||||
->get();
|
||||
|
||||
if ($logs->isEmpty()) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'assignments' => [],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
$assignmentMap = [];
|
||||
|
||||
foreach ($logs as $log) {
|
||||
$spool = $this->sanitizeValue($log->spool_number) ?? $this->sanitizeValue($log->spool_number2);
|
||||
$joint = $this->sanitizeValue($log->no_of_the_joint_as_per_as_built_survey);
|
||||
$jointType = $this->sanitizeValue($log->type_of_joint);
|
||||
|
||||
if (!$spool && !$joint) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$key = $spool . '|' . $joint;
|
||||
|
||||
if (!isset($assignmentMap[$key])) {
|
||||
$assignmentMap[$key] = [
|
||||
'spool' => $spool,
|
||||
'joint' => $joint,
|
||||
'joint_type' => $jointType ? strtoupper($jointType) : null,
|
||||
'welders' => [],
|
||||
];
|
||||
} elseif ($jointType && empty($assignmentMap[$key]['joint_type'])) {
|
||||
$assignmentMap[$key]['joint_type'] = strtoupper($jointType);
|
||||
}
|
||||
|
||||
$welders = [
|
||||
$this->sanitizeValue($log->real_welder_1),
|
||||
$this->sanitizeValue($log->real_welder_2),
|
||||
$this->sanitizeValue($log->welder_1),
|
||||
$this->sanitizeValue($log->welder_2),
|
||||
];
|
||||
|
||||
foreach ($welders as $welder) {
|
||||
if ($welder) {
|
||||
$assignmentMap[$key]['welders'][$welder] = $welder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$assignments = collect($assignmentMap)
|
||||
->map(function (array $assignment) {
|
||||
$assignment['welders'] = array_values($assignment['welders']);
|
||||
return $assignment;
|
||||
})
|
||||
->values();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'assignments' => $assignments,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
private function formatLabel(?string $revision, ?string $path): string
|
||||
{
|
||||
$filename = $path ? basename($path) : null;
|
||||
|
||||
if ($revision && $filename) {
|
||||
return sprintf('Rev %s — %s', $revision, $filename);
|
||||
}
|
||||
|
||||
if ($revision) {
|
||||
return sprintf('Rev %s', $revision);
|
||||
}
|
||||
|
||||
return $filename ?? 'Unknown PDF';
|
||||
}
|
||||
|
||||
private function relativePublicPath(string $absolutePath): ?string
|
||||
{
|
||||
$publicPath = public_path();
|
||||
|
||||
if (Str::startsWith($absolutePath, $publicPath)) {
|
||||
return ltrim(str_replace($publicPath, '', $absolutePath), '/');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function sanitizeValue($value): ?string
|
||||
{
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$trimmed = trim((string) $value);
|
||||
|
||||
return $trimmed === '' ? null : $trimmed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function scanDrawingFolder(string $relativeFolder): array
|
||||
{
|
||||
$basePath = public_path($relativeFolder);
|
||||
|
||||
if (!is_dir($basePath)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$files = glob($basePath . DIRECTORY_SEPARATOR . '*.pdf') ?: [];
|
||||
|
||||
if (empty($files)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$names = collect($files)
|
||||
->map(fn (string $path) => pathinfo($path, PATHINFO_FILENAME))
|
||||
->filter()
|
||||
->unique()
|
||||
->sort()
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return $names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get IC Log members for a drawing
|
||||
* Note: Currently drawing_number field is empty in database, so we return all members
|
||||
* TODO: When drawing_number is populated, filter by drawing_number
|
||||
*/
|
||||
public function getICLogMembers(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate(['drawing' => 'required|string']);
|
||||
$drawingNumber = $request->drawing;
|
||||
|
||||
// First try to get by drawing_number (when it's populated)
|
||||
$members = IncomingControl::where('drawing_number', $drawingNumber)
|
||||
->whereNotNull('description_ru')
|
||||
->where('description_ru', '!=', '')
|
||||
->distinct('description_ru')
|
||||
->pluck('description_ru')
|
||||
->filter()
|
||||
->values()
|
||||
->toArray();
|
||||
|
||||
// If no results found by drawing_number, return all members
|
||||
// (This is a fallback since drawing_number field is currently empty)
|
||||
if (empty($members)) {
|
||||
$members = IncomingControl::whereNotNull('description_ru')
|
||||
->where('description_ru', '!=', '')
|
||||
->distinct('description_ru')
|
||||
->pluck('description_ru')
|
||||
->filter()
|
||||
->values()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $members,
|
||||
'filtered_by_drawing' => !empty($members) && IncomingControl::where('drawing_number', $drawingNumber)->exists()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get IC Log member details
|
||||
*/
|
||||
public function getICLogMemberDetails(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate(['member_description' => 'required|string']);
|
||||
$memberDescription = $request->member_description;
|
||||
|
||||
$details = IncomingControl::where('description_ru', $memberDescription)
|
||||
->select(
|
||||
'material',
|
||||
'odmm_1 as diameter', // Outer diameter in mm
|
||||
'dn_1 as nps', // Nominal pipe size
|
||||
'thicknessmm_1 as thickness' // Thickness in mm
|
||||
)
|
||||
->first(); // Get the first matching record
|
||||
|
||||
return response()->json(['success' => true, 'data' => $details]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check existing weldmap data for a drawing
|
||||
*/
|
||||
public function checkExistingWeldmapData(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate(['drawing' => 'required|string']);
|
||||
$drawingNumber = $request->drawing;
|
||||
|
||||
$existingJoints = WeldLog::where('iso_number', $drawingNumber)
|
||||
->select(
|
||||
'no_of_the_joint_as_per_as_built_survey as joint_no',
|
||||
'joint_type',
|
||||
'welder_1',
|
||||
'welder_2',
|
||||
'spool_number_1 as spool_no_1',
|
||||
'spool_number_2 as spool_no_2',
|
||||
'pose_number_1 as pose_no_1',
|
||||
'pose_number_2 as pose_no_2',
|
||||
'member_1',
|
||||
'member_2',
|
||||
'material_1',
|
||||
'material_2',
|
||||
'dia_1',
|
||||
'dia_2',
|
||||
'nps_1',
|
||||
'nps_2',
|
||||
'thickness_1',
|
||||
'thickness_2',
|
||||
'welding_date'
|
||||
)
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'has_data' => $existingJoints->isNotEmpty(),
|
||||
'joints' => $existingJoints
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get qualified welders based on material, welding method, and expiry dates
|
||||
* Phase 3.1: API Endpoints for Joint Data
|
||||
* Phase 6: Welder Qualification Filtering
|
||||
*/
|
||||
public function getQualifiedWelders(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'drawing_number' => 'required|string',
|
||||
'material' => 'nullable|string',
|
||||
'welding_method' => 'nullable|string',
|
||||
'joint_no' => 'nullable|string',
|
||||
'skip_qualification' => 'nullable|boolean', // Skip qualification check if true
|
||||
]);
|
||||
|
||||
try {
|
||||
$drawingNumber = $request->drawing_number;
|
||||
$jointNo = $request->joint_no;
|
||||
$skipQualification = $request->boolean('skip_qualification', false);
|
||||
|
||||
Log::debug('Phase 6: getQualifiedWelders called', [
|
||||
'drawing_number' => $drawingNumber,
|
||||
'joint_no' => $jointNo,
|
||||
'skip_qualification' => $skipQualification
|
||||
]);
|
||||
|
||||
// If skip_qualification is true, return all welders from weld_logs (legacy behavior)
|
||||
if ($skipQualification) {
|
||||
return $this->getWeldersFromWeldLogs($drawingNumber, $jointNo);
|
||||
}
|
||||
|
||||
// Get joint data from weld_logs to determine qualification criteria
|
||||
$jointData = null;
|
||||
if (!empty($jointNo)) {
|
||||
$jointData = WeldLog::where('iso_number', $drawingNumber)
|
||||
->where('no_of_the_joint_as_per_as_built_survey', $jointNo)
|
||||
->first();
|
||||
}
|
||||
|
||||
// If no joint data found, try to get any record for this drawing
|
||||
if (!$jointData) {
|
||||
$jointData = WeldLog::where('iso_number', $drawingNumber)->first();
|
||||
}
|
||||
|
||||
// If still no data, return empty list with message
|
||||
if (!$jointData) {
|
||||
Log::debug('Phase 6: No joint data found for qualification', [
|
||||
'drawing_number' => $drawingNumber,
|
||||
'joint_no' => $jointNo
|
||||
]);
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => [],
|
||||
'count' => 0,
|
||||
'message' => 'No joint data found for qualification filtering'
|
||||
]);
|
||||
}
|
||||
|
||||
// Extract qualification criteria from joint data
|
||||
$criteria = $this->extractQualificationCriteria($jointData);
|
||||
|
||||
Log::debug('Phase 6: Qualification criteria extracted', $criteria);
|
||||
|
||||
// Get qualified welders from WelderTest table
|
||||
$qualifiedWelders = $this->filterWeldersByQualification($criteria, $drawingNumber);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $qualifiedWelders,
|
||||
'count' => count($qualifiedWelders),
|
||||
'criteria' => $criteria,
|
||||
'message' => 'Welders filtered by qualification'
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Phase 6: getQualifiedWelders error', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Failed to get qualified welders',
|
||||
'error' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get welders from weld_logs without qualification filtering (legacy behavior)
|
||||
*/
|
||||
private function getWeldersFromWeldLogs(string $drawingNumber, ?string $jointNo): JsonResponse
|
||||
{
|
||||
$query = WeldLog::where('iso_number', $drawingNumber)
|
||||
->whereNotNull('welder_1')
|
||||
->where('welder_1', '!=', '');
|
||||
|
||||
if (!empty($jointNo)) {
|
||||
$query->where('no_of_the_joint_as_per_as_built_survey', $jointNo);
|
||||
}
|
||||
|
||||
$welders1 = $query->pluck('welder_1')->unique()->filter()->values();
|
||||
|
||||
$query2 = WeldLog::where('iso_number', $drawingNumber)
|
||||
->whereNotNull('welder_2')
|
||||
->where('welder_2', '!=', '');
|
||||
|
||||
if (!empty($jointNo)) {
|
||||
$query2->where('no_of_the_joint_as_per_as_built_survey', $jointNo);
|
||||
}
|
||||
|
||||
$welders2 = $query2->pluck('welder_2')->unique()->filter()->values();
|
||||
|
||||
$allWelders = $welders1->merge($welders2)->unique()->sort()->values();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $allWelders->toArray(),
|
||||
'count' => $allWelders->count(),
|
||||
'message' => 'Welders from weld_logs (no qualification filtering)'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract qualification criteria from joint data
|
||||
*/
|
||||
private function extractQualificationCriteria(WeldLog $jointData): array
|
||||
{
|
||||
return [
|
||||
'material_group_1' => $jointData->ru_material_group_1 ?? null,
|
||||
'material_group_2' => $jointData->ru_material_group_2 ?? null,
|
||||
'welding_method' => $jointData->welding_method ?? null,
|
||||
'welding_date' => $jointData->welding_date ?? now()->toDateString(),
|
||||
'outside_diameter' => $jointData->outside_diameter_1 ?? null,
|
||||
'wall_thickness' => $jointData->wall_thickness_1 ?? null,
|
||||
'iso_number' => $jointData->iso_number ?? null,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter welders by qualification criteria using WelderTest table
|
||||
* Based on existing welder-assignment/welder_1.php logic
|
||||
*/
|
||||
private function filterWeldersByQualification(array $criteria, string $drawingNumber): array
|
||||
{
|
||||
$logKey = 'PHASE6_WELDER_FILTER_' . uniqid();
|
||||
Log::debug("[$logKey] Starting welder qualification filtering", $criteria);
|
||||
|
||||
$qualifiedWelders = [];
|
||||
$today = Carbon::now();
|
||||
$welderQualificationExpiredDays = (int) setting("WelderQualitificationStatusExpiredDate", 180);
|
||||
|
||||
// Build material combinations for qualification check
|
||||
$qualifiedCombinations = $this->buildMaterialCombinations(
|
||||
$criteria['material_group_1'],
|
||||
$criteria['material_group_2']
|
||||
);
|
||||
|
||||
Log::debug("[$logKey] Material combinations", [
|
||||
'combinations' => $qualifiedCombinations
|
||||
]);
|
||||
|
||||
// If no material info, skip qualification and return welders from weld_logs
|
||||
if (empty($qualifiedCombinations)) {
|
||||
Log::debug("[$logKey] No material combinations, falling back to weld_logs welders");
|
||||
return $this->getWeldersFromWeldLogsArray($drawingNumber);
|
||||
}
|
||||
|
||||
// Build base query with WelderTest
|
||||
$query = WelderTest::leftJoin('naks_welders', function($join) {
|
||||
$join->on('naks_welders.naks_certificate_no', '=', 'welder_tests.naks_no');
|
||||
});
|
||||
|
||||
// Filter by material combinations
|
||||
$query->where(function ($q) use ($qualifiedCombinations) {
|
||||
foreach ($qualifiedCombinations as $combo) {
|
||||
$q->orWhere(function($subQ) use ($combo) {
|
||||
$subQ->where("material_group_1", "like", "%{$combo['mat1']}%")
|
||||
->where("material_group_2", "like", "%{$combo['mat2']}%");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Filter by diameter if available
|
||||
if (!empty($criteria['outside_diameter']) && is_numeric($criteria['outside_diameter'])) {
|
||||
$diameter = (float) $criteria['outside_diameter'];
|
||||
$query->where("dia_min", "<=", $diameter)
|
||||
->where(function($q) use ($diameter) {
|
||||
$q->where("dia_max", ">=", $diameter)
|
||||
->orWhereNull("dia_max")
|
||||
->orWhere("dia_max", 0);
|
||||
});
|
||||
}
|
||||
|
||||
// Filter by thickness if available
|
||||
if (!empty($criteria['wall_thickness']) && is_numeric($criteria['wall_thickness'])) {
|
||||
$thickness = (float) $criteria['wall_thickness'];
|
||||
$query->where("thk_min", "<=", $thickness)
|
||||
->where(function($q) use ($thickness) {
|
||||
$q->where("thk_max", ">=", $thickness)
|
||||
->orWhereNull("thk_max")
|
||||
->orWhere("thk_max", 0);
|
||||
});
|
||||
}
|
||||
|
||||
// Filter by welding method if available
|
||||
if (!empty($criteria['welding_method'])) {
|
||||
$weldingMethod = $criteria['welding_method'];
|
||||
$weldingMethodParts = explode(",", $weldingMethod);
|
||||
$reverseWeldingMethod = implode(",", array_reverse($weldingMethodParts));
|
||||
|
||||
$query->where(function($q) use ($weldingMethod, $reverseWeldingMethod) {
|
||||
$q->where("welding_method", $weldingMethod)
|
||||
->orWhere("welding_method", $reverseWeldingMethod);
|
||||
});
|
||||
}
|
||||
|
||||
// Filter by approval date (must be approved before welding date)
|
||||
if (!empty($criteria['welding_date'])) {
|
||||
$query->whereDate("approval_date", "<=", $criteria['welding_date']);
|
||||
}
|
||||
|
||||
// Select and group results
|
||||
$results = $query->select(
|
||||
'welder_tests.naks_id',
|
||||
'welder_tests.naks_validity',
|
||||
DB::raw('MIN(naks_welders.period_of_validity) as period_of_validity')
|
||||
)
|
||||
->groupBy('welder_tests.naks_id', 'welder_tests.naks_validity')
|
||||
->get();
|
||||
|
||||
Log::debug("[$logKey] Query results", [
|
||||
'count' => $results->count()
|
||||
]);
|
||||
|
||||
// Process results and add status indicators
|
||||
foreach ($results as $welder) {
|
||||
$welderDisplay = $welder->naks_id;
|
||||
|
||||
// Check NAKS validity
|
||||
if (!empty($welder->naks_validity)) {
|
||||
try {
|
||||
$naksValidity = Carbon::parse($welder->naks_validity);
|
||||
$remainingDays = $today->diffInDays($naksValidity, false);
|
||||
|
||||
if ($remainingDays < 10 && $remainingDays >= 0) {
|
||||
$welderDisplay = "❗" . $welderDisplay; // Expiring soon
|
||||
} elseif ($remainingDays < 0) {
|
||||
$welderDisplay = "❌" . $welderDisplay; // Expired
|
||||
continue; // Skip expired welders
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Invalid date format, skip validity check
|
||||
}
|
||||
}
|
||||
|
||||
// Check if welder is already assigned to this ISO
|
||||
$isAssigned = WeldLog::where('iso_number', $drawingNumber)
|
||||
->where(function($q) use ($welder) {
|
||||
$q->where('welder_1', 'like', "%{$welder->naks_id}%")
|
||||
->orWhere('real_welder_1', 'like', "%{$welder->naks_id}%");
|
||||
})
|
||||
->exists();
|
||||
|
||||
if ($isAssigned) {
|
||||
$welderDisplay = "🟡" . $welderDisplay; // Already assigned
|
||||
}
|
||||
|
||||
// Check period of validity
|
||||
if (!empty($welder->period_of_validity) && !empty($criteria['welding_date'])) {
|
||||
try {
|
||||
$weldingDate = Carbon::parse($criteria['welding_date']);
|
||||
$periodOfValidity = Carbon::parse($welder->period_of_validity);
|
||||
$expiredDate = $periodOfValidity->copy()->addDays($welderQualificationExpiredDays);
|
||||
|
||||
if ($weldingDate->greaterThan($expiredDate)) {
|
||||
$welderDisplay = "❌📅" . $welderDisplay; // Welding date expired
|
||||
continue; // Skip
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Invalid date format, skip check
|
||||
}
|
||||
}
|
||||
|
||||
$qualifiedWelders[] = $welderDisplay;
|
||||
}
|
||||
|
||||
Log::debug("[$logKey] Qualified welders", [
|
||||
'count' => count($qualifiedWelders),
|
||||
'welders' => $qualifiedWelders
|
||||
]);
|
||||
|
||||
return array_values(array_unique($qualifiedWelders));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build material combinations for qualification check
|
||||
*/
|
||||
private function buildMaterialCombinations(?string $mat1, ?string $mat2): array
|
||||
{
|
||||
if (empty($mat1) && empty($mat2)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$mat1 = $mat1 ?? '';
|
||||
$mat2 = $mat2 ?? $mat1;
|
||||
|
||||
$isSameMaterial = ($mat1 === $mat2);
|
||||
$materialCombination = $isSameMaterial ? $mat1 : "{$mat1}+{$mat2}";
|
||||
|
||||
$qualifiedCombinations = [];
|
||||
|
||||
// Check MaterialGroupMap for qualified materials
|
||||
$exactMatch = MaterialGroupMap::where("material_name", $materialCombination)->first();
|
||||
|
||||
if ($exactMatch && !empty($exactMatch->qualified_materials)) {
|
||||
$qualifiedMaterialsList = explode(",", $exactMatch->qualified_materials);
|
||||
foreach ($qualifiedMaterialsList as $combo) {
|
||||
$combo = trim($combo);
|
||||
$parts = explode("+", $combo);
|
||||
|
||||
if (count($parts) == 2) {
|
||||
$qualifiedCombinations[] = ['mat1' => trim($parts[0]), 'mat2' => trim($parts[1])];
|
||||
} elseif (count($parts) == 1) {
|
||||
$qualifiedCombinations[] = ['mat1' => trim($parts[0]), 'mat2' => trim($parts[0])];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Always include original combination
|
||||
if ($isSameMaterial) {
|
||||
$qualifiedCombinations[] = ['mat1' => $mat1, 'mat2' => $mat2];
|
||||
} else {
|
||||
$qualifiedCombinations[] = ['mat1' => $mat1, 'mat2' => $mat2];
|
||||
$qualifiedCombinations[] = ['mat1' => $mat2, 'mat2' => $mat1]; // Reverse
|
||||
}
|
||||
|
||||
return $qualifiedCombinations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get welders from weld_logs as array (helper for fallback)
|
||||
*/
|
||||
private function getWeldersFromWeldLogsArray(string $drawingNumber): array
|
||||
{
|
||||
$welders1 = WeldLog::where('iso_number', $drawingNumber)
|
||||
->whereNotNull('welder_1')
|
||||
->where('welder_1', '!=', '')
|
||||
->pluck('welder_1')
|
||||
->unique()
|
||||
->filter()
|
||||
->values();
|
||||
|
||||
$welders2 = WeldLog::where('iso_number', $drawingNumber)
|
||||
->whereNotNull('welder_2')
|
||||
->where('welder_2', '!=', '')
|
||||
->pluck('welder_2')
|
||||
->unique()
|
||||
->filter()
|
||||
->values();
|
||||
|
||||
return $welders1->merge($welders2)->unique()->sort()->values()->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get type of weld options from joint_types table
|
||||
* Phase 3: Type of Weld dropdown options
|
||||
*/
|
||||
public function getTypeOfWeldOptions(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$options = \DB::table('joint_types')
|
||||
->select('short_name_en')
|
||||
->whereNotNull('short_name_en')
|
||||
->where('short_name_en', '!=', '')
|
||||
->orderBy('short_name_en')
|
||||
->distinct()
|
||||
->pluck('short_name_en')
|
||||
->filter()
|
||||
->values()
|
||||
->toArray();
|
||||
|
||||
// Fallback: If no options found, use default types
|
||||
if (empty($options)) {
|
||||
$options = ['BW', 'FW', 'SW', 'TW', 'BJ', 'FJ', 'TH', 'CJ'];
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $options
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Failed to get type of weld options',
|
||||
'error' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Spool;
|
||||
use App\Models\Element;
|
||||
use App\Models\Joint;
|
||||
use App\Models\Welder;
|
||||
use App\Models\WelderAssignment;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class PdfmController extends Controller
|
||||
{
|
||||
// Spools CRUD
|
||||
public function getSpools(): JsonResponse
|
||||
{
|
||||
$spools = Spool::orderBy('spool_no')->get();
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $spools
|
||||
]);
|
||||
}
|
||||
|
||||
public function createSpool(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'spool_no' => 'required|string|unique:spools',
|
||||
'description' => 'nullable|string',
|
||||
'material' => 'nullable|string',
|
||||
'diameter' => 'nullable|string',
|
||||
'thickness' => 'nullable|string',
|
||||
'length' => 'nullable|string',
|
||||
'classification' => 'nullable|string'
|
||||
]);
|
||||
|
||||
$spool = Spool::create($request->all());
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $spool,
|
||||
'message' => 'Spool created successfully!'
|
||||
], 201);
|
||||
}
|
||||
|
||||
// Elements CRUD
|
||||
public function getElements(): JsonResponse
|
||||
{
|
||||
$elements = Element::orderBy('element_code')->get();
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $elements
|
||||
]);
|
||||
}
|
||||
|
||||
public function createElement(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'element_code' => 'required|string|unique:elements',
|
||||
'element_name' => 'required|string',
|
||||
'element_type' => 'required|string',
|
||||
'material' => 'nullable|string',
|
||||
'diameter' => 'nullable|string',
|
||||
'thickness' => 'nullable|string',
|
||||
'classification' => 'nullable|string',
|
||||
'weight' => 'nullable|numeric'
|
||||
]);
|
||||
|
||||
$element = Element::create($request->all());
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $element,
|
||||
'message' => 'Element created successfully!'
|
||||
], 201);
|
||||
}
|
||||
|
||||
// Joints CRUD
|
||||
public function getJoints(): JsonResponse
|
||||
{
|
||||
$joints = Joint::with(['spool', 'elementFrom', 'elementTo', 'welderAssignments.welder'])
|
||||
->orderBy('joint_no')
|
||||
->get();
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $joints
|
||||
]);
|
||||
}
|
||||
|
||||
public function createJoint(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'joint_no' => 'required|string|unique:joints',
|
||||
'spool_no' => 'required|string|exists:spools,spool_no',
|
||||
'element_from' => 'nullable|string|exists:elements,element_code',
|
||||
'element_to' => 'nullable|string|exists:elements,element_code',
|
||||
'joint_type' => 'nullable|string',
|
||||
'welding_type' => 'nullable|string',
|
||||
'classification' => 'nullable|string'
|
||||
]);
|
||||
|
||||
$joint = Joint::create($request->all());
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $joint,
|
||||
'message' => 'Joint created successfully!'
|
||||
], 201);
|
||||
}
|
||||
|
||||
// Welders CRUD
|
||||
public function getWelders(): JsonResponse
|
||||
{
|
||||
$welders = Welder::orderBy('welder_name')->get();
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $welders
|
||||
]);
|
||||
}
|
||||
|
||||
public function createWelder(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'welder_code' => 'required|string|unique:welders',
|
||||
'name' => 'required|string',
|
||||
'certification' => 'nullable|string',
|
||||
'specialization' => 'nullable|string'
|
||||
]);
|
||||
|
||||
$welder = Welder::create($request->all());
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $welder,
|
||||
'message' => 'Welder created successfully!'
|
||||
], 201);
|
||||
}
|
||||
|
||||
// Welder Assignments
|
||||
public function assignWelder(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'joint_no' => 'required|string|exists:joints,joint_no',
|
||||
'welder_code' => 'required|string|exists:welders,welder_code',
|
||||
'assigned_date' => 'nullable|date'
|
||||
]);
|
||||
|
||||
$assignment = WelderAssignment::create($request->all());
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $assignment,
|
||||
'message' => 'Welder assigned successfully!'
|
||||
], 201);
|
||||
}
|
||||
|
||||
// Auto Generate Spool Number
|
||||
public function generateSpoolNumber(): JsonResponse
|
||||
{
|
||||
$lastSpool = Spool::orderBy('id', 'desc')->first();
|
||||
$nextNumber = $lastSpool ? (int)substr($lastSpool->spool_no, 3) + 1 : 1;
|
||||
$spoolNumber = 'SP-' . str_pad($nextNumber, 3, '0', STR_PAD_LEFT);
|
||||
|
||||
// Auto-create the spool in database so it persists
|
||||
$spool = Spool::create([
|
||||
'spool_no' => $spoolNumber,
|
||||
'description' => 'Generated from PDF Editor'
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => ['spool_no' => $spoolNumber, 'id' => $spool->id]
|
||||
]);
|
||||
}
|
||||
|
||||
// Auto Generate Joint Number
|
||||
public function generateJointNumber(Request $request): JsonResponse
|
||||
{
|
||||
// Make spool_no optional with nullable validation
|
||||
$validated = $request->validate(['spool_no' => 'nullable|string']);
|
||||
|
||||
$spoolNo = $validated['spool_no'] ?? 'SP-001'; // Default spool if not provided
|
||||
|
||||
$lastJoint = Joint::where('spool_no', $spoolNo)
|
||||
->orderBy('id', 'desc')
|
||||
->first();
|
||||
|
||||
$nextNumber = $lastJoint ? (int)substr($lastJoint->joint_no, 3) + 1 : 1;
|
||||
$jointNumber = 'J-' . str_pad($nextNumber, 3, '0', STR_PAD_LEFT);
|
||||
|
||||
// Auto-create the joint in database so it persists
|
||||
$joint = Joint::create([
|
||||
'joint_no' => $jointNumber,
|
||||
'spool_no' => $spoolNo,
|
||||
'joint_type' => 'Auto-generated',
|
||||
'description' => 'Generated from PDF Editor'
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => ['joint_no' => $jointNumber, 'id' => $joint->id]
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* @group Project Settings
|
||||
*
|
||||
* APIs for project-related settings and configurations.
|
||||
*/
|
||||
class ProjectAppUrlsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get Project App URLs
|
||||
*
|
||||
* Returns a list of configured project names and their corresponding application URLs.
|
||||
* This endpoint is public and requires no authentication.
|
||||
*
|
||||
* @response 200 {
|
||||
* "status": "success",
|
||||
* "data": [
|
||||
* {
|
||||
* "project_name": "208 - Dzerzhinsk",
|
||||
* "url": "https://208.qms.stellarcons.com/admin"
|
||||
* },
|
||||
* {
|
||||
* "project_name": "102 - VIKSA OMK",
|
||||
* "url": "https://viksaqms.stellarcons.com/"
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
// "project-app-urls" ayarını getir
|
||||
$settings = setting('project-app-urls');
|
||||
|
||||
// Eğer string gelirse decode et, zaten array/object ise olduğu gibi kullan
|
||||
$data = is_string($settings) ? json_decode($settings, true) : $settings;
|
||||
|
||||
// Veri yoksa boş array döndür
|
||||
if (is_null($data)) {
|
||||
$data = [];
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $data
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Endroid\QrCode\QrCode as EndroidQrCode;
|
||||
use Endroid\QrCode\Writer\PngWriter;
|
||||
|
||||
class QRCodeController extends Controller
|
||||
{
|
||||
public function generate(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$request->validate([
|
||||
'shape_id' => 'required|string',
|
||||
]);
|
||||
|
||||
$shapeId = $request->get('shape_id');
|
||||
|
||||
// QR kod içeriği - shape ID ile URL oluştur
|
||||
$qrContent = url('/api/pdf-editor/annotations/' . $shapeId);
|
||||
|
||||
// QR kod PNG olarak üret (Endroid QR Code v6)
|
||||
$qrCode = new EndroidQrCode(
|
||||
data: $qrContent,
|
||||
size: 200,
|
||||
margin: 10
|
||||
);
|
||||
|
||||
$writer = new PngWriter();
|
||||
$result = $writer->write($qrCode);
|
||||
$qrCodeData = $result->getString();
|
||||
|
||||
// QR kod dosyasını kaydet
|
||||
$fileName = 'qr_' . $shapeId . '_' . time() . '.png';
|
||||
|
||||
// Klasörü oluştur
|
||||
$qrDir = storage_path('app/public/qr-codes');
|
||||
if (!file_exists($qrDir)) {
|
||||
mkdir($qrDir, 0755, true);
|
||||
}
|
||||
|
||||
// QR kod dosyasını kaydet
|
||||
$filePath = $qrDir . '/' . $fileName;
|
||||
file_put_contents($filePath, $qrCodeData);
|
||||
|
||||
// Public klasörüne de kopyala
|
||||
$publicQrDir = public_path('storage/qr-codes');
|
||||
if (!file_exists($publicQrDir)) {
|
||||
mkdir($publicQrDir, 0755, true);
|
||||
}
|
||||
$publicFilePath = $publicQrDir . '/' . $fileName;
|
||||
file_put_contents($publicFilePath, $qrCodeData);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'shape_id' => $shapeId,
|
||||
'qr_content' => $qrContent,
|
||||
'qr_code_url' => url('storage/qr-codes/' . $fileName)
|
||||
]
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => $e->getMessage(),
|
||||
'data' => null
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function generateForAnnotation($shapeId): JsonResponse
|
||||
{
|
||||
try {
|
||||
// QR kod içeriği
|
||||
$qrContent = url('/api/annotations/' . $shapeId);
|
||||
|
||||
// QR kod PNG olarak üret (Endroid QR Code v6)
|
||||
$qrCode = new EndroidQrCode(
|
||||
data: $qrContent,
|
||||
size: 150,
|
||||
margin: 5
|
||||
);
|
||||
|
||||
$writer = new PngWriter();
|
||||
$result = $writer->write($qrCode);
|
||||
$qrCodeData = $result->getString();
|
||||
|
||||
// Base64 encode for frontend
|
||||
$base64QrCode = 'data:image/png;base64,' . base64_encode($qrCodeData);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'shape_id' => $shapeId,
|
||||
'qr_code' => $base64QrCode,
|
||||
'qr_content' => $qrContent
|
||||
]
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => $e->getMessage(),
|
||||
'data' => null
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class SettingController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get a specific setting value for mobile.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $key
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function get(Request $request, $key)
|
||||
{
|
||||
$allowedKeys = [
|
||||
'unit_kgmetc',
|
||||
'akt_status',
|
||||
];
|
||||
|
||||
if (!in_array($key, $allowedKeys)) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Unauthorized or invalid key'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$value = setting($key);
|
||||
|
||||
$decoded = json_decode($value, true);
|
||||
if (json_last_error() === JSON_ERROR_NONE && (is_array($decoded) || is_object($decoded))) {
|
||||
$data = $decoded;
|
||||
} else {
|
||||
$data = $value;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'key' => $key,
|
||||
'data' => $data
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all common settings.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function common()
|
||||
{
|
||||
$keys = [
|
||||
'project_name',
|
||||
'project_name_ru',
|
||||
'project_number',
|
||||
'company_code',
|
||||
'row_count',
|
||||
'summary_mails',
|
||||
'register_creator_file_name_pattern',
|
||||
'register_creator_start_row',
|
||||
'register_creator_path',
|
||||
'register_creator_column_based',
|
||||
'hand_over_zone_column',
|
||||
'tp_register_creator_path',
|
||||
'main_subcontractor',
|
||||
'cron_job_batch_process_count',
|
||||
'cron_job_period',
|
||||
'repair_table_target_rate',
|
||||
'ndt_limit',
|
||||
'ndt_wdi',
|
||||
'repair_limit',
|
||||
'repair_wdi',
|
||||
'WelderQualitificationStatusExpiredDate',
|
||||
'WelderQualitificationStatusRemaningDays',
|
||||
'ndt_date_validation_active',
|
||||
'header_color',
|
||||
'DevExpress_Theme',
|
||||
'pdf_template_path',
|
||||
'handover_control_count'
|
||||
];
|
||||
|
||||
$data = [];
|
||||
foreach ($keys as $key) {
|
||||
$value = setting($key);
|
||||
|
||||
// Attempt to decode JSON if it looks like an array/object
|
||||
$decoded = json_decode($value, true);
|
||||
if (json_last_error() === JSON_ERROR_NONE && (is_array($decoded) || is_object($decoded))) {
|
||||
$data[$key] = $decoded;
|
||||
} else {
|
||||
$data[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $data
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* @group Spool Release Workflow
|
||||
*
|
||||
* API endpoints for managing spool release workflow steps and rollbacks.
|
||||
*/
|
||||
class SpoolReleaseWorkflowController extends Controller
|
||||
{
|
||||
/**
|
||||
* Advance Spool Release Workflow
|
||||
*
|
||||
* Advance the status of a spool through the quality control and painting workflow.
|
||||
*
|
||||
* @authenticated
|
||||
*
|
||||
* @bodyParam action string required The action to perform (paint, ndt_release, ndt_paint_release, spool_release). Example: paint
|
||||
* @bodyParam iso_number string Filter by ISO Number (for single operation). Example: 10-BFW-RS1-0001
|
||||
* @bodyParam spool_number string Filter by Spool Number (for single operation). Example: SPL-001
|
||||
* @bodyParam iso_spool_pairs string Comma-separated ISO|SPOOL pairs for bulk operations. Example: ISO-001|SPL-001,ISO-001|SPL-002
|
||||
*
|
||||
* @response {
|
||||
* "status": "success",
|
||||
* "message": "1 row affected",
|
||||
* "count": 1
|
||||
* }
|
||||
*/
|
||||
public function advance(Request $request)
|
||||
{
|
||||
$action = $request->input('action');
|
||||
$isoNumber = $request->input('iso_number');
|
||||
$spoolNumber = $request->input('spool_number');
|
||||
$isoSpoolPairs = $request->input('iso_spool_pairs');
|
||||
|
||||
if (!$isoSpoolPairs && (!$isoNumber || !$spoolNumber)) {
|
||||
return response()->json(['status' => 'error', 'message' => 'Missing ISO and Spool information']);
|
||||
}
|
||||
|
||||
// Prepare pairs array
|
||||
$pairs = [];
|
||||
if ($isoSpoolPairs) {
|
||||
$rawPairs = explode(",", $isoSpoolPairs);
|
||||
foreach ($rawPairs as $p) {
|
||||
$parts = explode("|", trim($p));
|
||||
if (count($parts) == 2) {
|
||||
$pairs[] = ['iso' => trim($parts[0]), 'spool' => trim($parts[1])];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$pairs[] = ['iso' => trim($isoNumber), 'spool' => trim($spoolNumber)];
|
||||
}
|
||||
|
||||
if (empty($pairs)) {
|
||||
return response()->json(['status' => 'error', 'message' => 'No valid ISO|Spool pairs found']);
|
||||
}
|
||||
|
||||
// Reconstruct pairs string for side effects if needed
|
||||
$reconstructedPairs = implode(',', array_map(fn($p) => "{$p['iso']}|{$p['spool']}", $pairs));
|
||||
|
||||
// Mock $_POST for legacy view calls (side effects)
|
||||
$_POST['iso_spool_pairs'] = $reconstructedPairs;
|
||||
$_POST['iso_number'] = implode(',', array_column($pairs, 'iso'));
|
||||
$_POST['spool_number'] = implode(',', array_column($pairs, 'spool'));
|
||||
|
||||
// Ensure legacy u() function works
|
||||
if ($request->user()) {
|
||||
\Session::put('cached_user', $request->user());
|
||||
\Session::put('uid', $request->user()->id);
|
||||
}
|
||||
|
||||
$userId = $request->user() ? $request->user()->id : 0;
|
||||
$totalAffected = 0;
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
if ($action == 'paint') {
|
||||
$pattern = setting("paint_release_number_pattern");
|
||||
$checkNo = str_replace("{number}", get_counter($pattern), $pattern);
|
||||
|
||||
foreach ($pairs as $pair) {
|
||||
$affected = db("weld_logs")
|
||||
->where("iso_number", $pair['iso'])
|
||||
->where("spool_number", $pair['spool'])
|
||||
->whereNotIn("spool_status", ['Completed'])
|
||||
->whereIn("spool_status", ['Paint', 'Spool Release', 'NDT Release', 'QC', 'Manufacturing', 'Weld Complete'])
|
||||
->update([
|
||||
"spool_paint_check" => $userId,
|
||||
"paint_release_no" => $checkNo,
|
||||
"paint_release_date" => simdi(),
|
||||
"spool_status" => "Completed"
|
||||
]);
|
||||
$totalAffected += $affected;
|
||||
|
||||
if ($affected > 0) {
|
||||
try {
|
||||
ob_start();
|
||||
view('admin.type.spool-release.paint-follow-up-updater', [
|
||||
'isoNumber' => $pair['iso'],
|
||||
'spoolNumber' => $pair['spool'],
|
||||
])->render();
|
||||
ob_end_clean();
|
||||
} catch (\Exception $e) {
|
||||
ob_end_clean();
|
||||
\Log::warning("Paint follow up updater error: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ($action == 'ndt_release') {
|
||||
$pattern = setting("ndt_release_number_pattern");
|
||||
$newReleaseNo = str_replace("{number}", get_counter($pattern), $pattern);
|
||||
|
||||
foreach ($pairs as $pair) {
|
||||
$affected = db("weld_logs")
|
||||
->where("iso_number", $pair['iso'])
|
||||
->where("spool_number", $pair['spool'])
|
||||
->whereNotNull("spool_ndt_check_no")
|
||||
->whereNull("ndt_release_no")
|
||||
->update([
|
||||
"ndt_release_no" => $newReleaseNo,
|
||||
"ndt_release_check" => $userId,
|
||||
"ndt_release_date" => Carbon::now(),
|
||||
'spool_status' => "Paint",
|
||||
]);
|
||||
$totalAffected += $affected;
|
||||
}
|
||||
|
||||
} elseif ($action == 'ndt_paint_release') {
|
||||
$pattern = setting("paint_release_number_pattern");
|
||||
|
||||
foreach ($pairs as $pair) {
|
||||
$newRequestNo = str_replace("{number}", get_counter($pattern), $pattern);
|
||||
|
||||
$checkPaintingCycle = db("weld_logs")
|
||||
->where('iso_number', $pair['iso'])
|
||||
->where('spool_number', $pair['spool'])
|
||||
->select("painting_cycle")
|
||||
->first();
|
||||
|
||||
$spoolStatus = (!empty($checkPaintingCycle) && !empty($checkPaintingCycle->painting_cycle)) ? "Paint" : "Completed";
|
||||
|
||||
$affected = db("weld_logs")
|
||||
->where('iso_number', $pair['iso'])
|
||||
->where('spool_number', $pair['spool'])
|
||||
->whereNotNull("spool_ndt_check_no")
|
||||
->whereNull("ndt_release_date")
|
||||
->update([
|
||||
"ndt_release_no" => $newRequestNo,
|
||||
"ndt_release_check" => $userId,
|
||||
"ndt_release_date" => Carbon::now(),
|
||||
'spool_status' => $spoolStatus,
|
||||
]);
|
||||
|
||||
$totalAffected += $affected;
|
||||
|
||||
if ($affected > 0) {
|
||||
try {
|
||||
ob_start();
|
||||
view('admin.type.spool-release.paint-follow-up-updater', [
|
||||
'isoNumber' => $pair['iso'],
|
||||
'spoolNumber' => $pair['spool'],
|
||||
])->render();
|
||||
ob_end_clean();
|
||||
} catch (\Exception $e) {
|
||||
ob_end_clean();
|
||||
\Log::warning("Paint follow up updater error: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ($action == 'spool_release' || $action == 'checklist_ok') {
|
||||
$pattern = setting("spool_release_check_number_pattern");
|
||||
$checkNo = str_replace("{number}", get_counter($pattern), $pattern);
|
||||
|
||||
foreach ($pairs as $pair) {
|
||||
$affected = db("weld_logs")
|
||||
->where("iso_number", $pair['iso'])
|
||||
->where("spool_number", $pair['spool'])
|
||||
->whereIn("spool_status", ["Spool Release", "Manufacturing", "Weld Complete"])
|
||||
->update([
|
||||
"spool_ndt_check" => $userId,
|
||||
"spool_ndt_check_no" => $checkNo,
|
||||
"spool_ndt_check_date" => simdi(),
|
||||
"spool_status" => "NDT Release"
|
||||
]);
|
||||
$totalAffected += $affected;
|
||||
}
|
||||
|
||||
// Side effects
|
||||
ob_start();
|
||||
view('admin.type.spool-release.spool-document-generate')->render();
|
||||
view('cron.spool-status-changer', ['iso_spool_pairs' => $reconstructedPairs])->render();
|
||||
ob_end_clean();
|
||||
|
||||
} else {
|
||||
DB::rollBack();
|
||||
return response()->json(['status' => 'error', 'message' => 'Invalid action']);
|
||||
}
|
||||
|
||||
dispatchCacheBladeViews();
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => $totalAffected . ' row(s) affected',
|
||||
'count' => $totalAffected
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
\Log::error("SpoolReleaseWorkflow error: " . $e->getMessage());
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Internal server error: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback Spool Release
|
||||
*
|
||||
* Reverts a spool release action using the legacy rollback system.
|
||||
*
|
||||
* @authenticated
|
||||
*
|
||||
* @bodyParam id integer required The ID of the spool or record to rollback. Example: 123
|
||||
* @bodyParam iso_number string required The ISO number to rollback. Example: 10-BFW-RS1-0001
|
||||
* @bodyParam spool_number string required The Spool number to rollback. Example: SPL-001
|
||||
*
|
||||
* @response {
|
||||
* "status": "success",
|
||||
* "message": "Rollback applied"
|
||||
* }
|
||||
* @response {
|
||||
* "status": "error",
|
||||
* "message": "Missing parameters for rollback"
|
||||
* }
|
||||
*/
|
||||
public function rollback(Request $request)
|
||||
{
|
||||
$id = $request->input('id');
|
||||
$isoNumber = $request->input('iso_number');
|
||||
$spoolNumber = $request->input('spool_number');
|
||||
|
||||
if (!$id || !$isoNumber || !$spoolNumber) {
|
||||
return response()->json(['status' => 'error', 'message' => 'Missing parameters for rollback']);
|
||||
}
|
||||
|
||||
// Ensure u() acts like authenticated API user inside rollback
|
||||
$_GET['rollback'] = $id;
|
||||
$_GET['iso_number'] = $isoNumber;
|
||||
$_GET['spool_number'] = $spoolNumber;
|
||||
|
||||
ob_start();
|
||||
include resource_path('views/admin/type/spool-release/rollback.blade.php');
|
||||
$output = ob_get_clean();
|
||||
|
||||
// Rollback outputs bilgi() which sets session flash and might render a Pjax wrapper
|
||||
// But the rollback was successful if it gets to the end. Let's just return success JSON
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Rollback applied'
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,656 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Models\WeldLog;
|
||||
use App\Models\Handover;
|
||||
use App\Models\WeldingEquipment;
|
||||
|
||||
/**
|
||||
* @group Stats
|
||||
*
|
||||
* İstatistikler ve Hesaplamalar ile ilgili endpointler.
|
||||
*/
|
||||
class StatsController extends Controller
|
||||
{
|
||||
/**
|
||||
* NDT Calculation (General)
|
||||
*
|
||||
* Genel NDT hesaplama istatistiklerini getirir.
|
||||
* Bu endpoint varsayılan 'ndt-calculation' blade cache sonucunu döndürür.
|
||||
*
|
||||
* @response 200 {
|
||||
* "status": "success",
|
||||
* "type": "general",
|
||||
* "content": "..."
|
||||
* }
|
||||
*/
|
||||
public function ndtCalculation()
|
||||
{
|
||||
// Varsayılan hesaplama (cacheBladeLoad('ndt-calculation'))
|
||||
// cacheBladeLoad echo yaptığı için çıktıyı yakalıyoruz.
|
||||
ob_start();
|
||||
cacheBladeLoad('ndt-calculation');
|
||||
$content = ob_get_clean();
|
||||
|
||||
// Eğer content bir JSON string ise decode et
|
||||
$decoded = json_decode($content);
|
||||
if (json_last_error() === JSON_ERROR_NONE) {
|
||||
$content = $decoded;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'type' => 'general',
|
||||
'content' => $content
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* NDT Calculation (Test Packs)
|
||||
*
|
||||
* Test Paketleri için NDT hesaplama istatistiklerini getirir.
|
||||
* 'ndtCalculationTestPack' ayarını döndürür.
|
||||
*
|
||||
* @response 200 {
|
||||
* "status": "success",
|
||||
* "type": "test_packs",
|
||||
* "content": "..."
|
||||
* }
|
||||
*/
|
||||
public function ndtCalculationTestPacks()
|
||||
{
|
||||
$content = setting('ndtCalculationTestPack');
|
||||
|
||||
// Eğer content bir JSON string ise decode et
|
||||
$decoded = json_decode($content);
|
||||
if (json_last_error() === JSON_ERROR_NONE) {
|
||||
$content = $decoded;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'type' => 'test_packs',
|
||||
'content' => $content
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* NDT Calculation (Backlogs)
|
||||
*
|
||||
* Backloglar için NDT hesaplama istatistiklerini getirir.
|
||||
* 'ndtCalculationBacklogs' ayarını döndürür.
|
||||
*
|
||||
* @queryParam type string Filtreleme türü (opsiyonel). Example: backlogs
|
||||
*
|
||||
* @response 200 {
|
||||
* "status": "success",
|
||||
* "type": "backlogs",
|
||||
* "content": "..."
|
||||
* }
|
||||
*/
|
||||
public function ndtCalculationBacklogs()
|
||||
{
|
||||
request()->merge(['type' => 'backlogs']);
|
||||
$_GET['type'] = 'backlogs';
|
||||
|
||||
ob_start();
|
||||
cacheBladeLoad('ndt-calculation');
|
||||
$content = ob_get_clean();
|
||||
|
||||
// Eğer content bir JSON string ise decode et
|
||||
$decoded = json_decode($content);
|
||||
if (json_last_error() === JSON_ERROR_NONE) {
|
||||
$content = $decoded;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'type' => 'backlogs',
|
||||
'content' => $content
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashboard Overview Stats
|
||||
*
|
||||
* Get aggregated statistics for project overview dashboard.
|
||||
* This endpoint is protected by a static hash.
|
||||
* Includes:
|
||||
* - WDI Monthly (Shop/Field/Total)
|
||||
* - Spool Progress
|
||||
* - NDT/Repair Backlog
|
||||
* - Hand-over Status
|
||||
* - Welding Equipment Status
|
||||
*
|
||||
* @header X-Api-Hash string required The static API hash for authentication. Example: your-secret-hash-key
|
||||
*
|
||||
* @response 200 {
|
||||
* "status": "success",
|
||||
* "data": {
|
||||
* "wdi_monthly": [...],
|
||||
* "spool_progress": [...],
|
||||
* "ndt_backlog": [...],
|
||||
* "handover_status": [...],
|
||||
* "welding_equipment": [...]
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
public function dashboardStats(\Illuminate\Http\Request $request)
|
||||
{
|
||||
$year = $request->input('year', date('Y'));
|
||||
|
||||
// 1. WDI Monthly Data (Global Aggregate) - Calendar Year
|
||||
$wdiMonthly = WeldLog::selectRaw("
|
||||
DATE_FORMAT(welding_date, '%Y-%m') as month,
|
||||
MONTH(welding_date) as month_num,
|
||||
SUM(CASE WHEN type_of_joint = 'S' THEN nps_1 ELSE 0 END) as shop,
|
||||
SUM(CASE WHEN type_of_joint != 'S' OR type_of_joint IS NULL THEN nps_1 ELSE 0 END) as field,
|
||||
SUM(nps_1) as total
|
||||
")
|
||||
->whereNotNull('welding_date')
|
||||
// ->whereYear('welding_date', $year) // Removed to allow client-side filtering
|
||||
->groupBy('month', 'month_num')
|
||||
->orderBy('month', 'asc')
|
||||
->get();
|
||||
|
||||
// 1b. WDI Monthly Data (By Project)
|
||||
$wdiByProjectRaw = WeldLog::selectRaw("
|
||||
project,
|
||||
DATE_FORMAT(welding_date, '%Y-%m') as month,
|
||||
MONTH(welding_date) as month_num,
|
||||
SUM(CASE WHEN type_of_joint = 'S' THEN nps_1 ELSE 0 END) as shop,
|
||||
SUM(CASE WHEN type_of_joint != 'S' OR type_of_joint IS NULL THEN nps_1 ELSE 0 END) as field,
|
||||
SUM(nps_1) as total
|
||||
")
|
||||
->whereNotNull('welding_date')
|
||||
->whereNotNull('project')
|
||||
->where('project', '!=', '')
|
||||
->whereYear('welding_date', $year) // Keep this for now or remove if needed, but it's unused by dashboard
|
||||
->groupBy('project', 'month', 'month_num')
|
||||
->get();
|
||||
|
||||
$wdiByProject = [];
|
||||
foreach($wdiByProjectRaw as $row) {
|
||||
// Use month_num (1-12) as key for the frontend table columns which expect 1..12
|
||||
// For the new 'wdiByProject' which is custom for the table, we simply need the integer month key
|
||||
// because the table logic iterates 1 through 12.
|
||||
$wdiByProject[$row->project][$row->month_num] = [
|
||||
'shop' => (float)$row->shop,
|
||||
'field' => (float)$row->field,
|
||||
'total' => (float)$row->total,
|
||||
'month_str' => $row->month // Useful for debugging or generic logic
|
||||
];
|
||||
}
|
||||
|
||||
// 2. Spool Progress (Time-independent)
|
||||
// Logic: Group by iso_number + spool_number (Shop only), find effective status based on priority logic.
|
||||
// Priority: Waiting < Manufacturing < QC < Paint < Completed
|
||||
|
||||
$statusCase = "CASE spool_status
|
||||
WHEN 'Waiting' THEN 1
|
||||
WHEN 'Manufacturing' THEN 2
|
||||
WHEN 'QC' THEN 3
|
||||
WHEN 'Paint' THEN 4
|
||||
WHEN 'Completed' THEN 5
|
||||
ELSE 99 END";
|
||||
|
||||
$spoolStats = DB::table('weld_logs')
|
||||
->selectRaw("status_val, COUNT(*) as count")
|
||||
->fromSub(function($query) use ($statusCase) {
|
||||
$query->select('iso_number', 'spool_number')
|
||||
->selectRaw("MIN($statusCase) as status_order")
|
||||
->selectRaw("
|
||||
CASE MIN($statusCase)
|
||||
WHEN 1 THEN 'Waiting'
|
||||
WHEN 2 THEN 'Manufacturing'
|
||||
WHEN 3 THEN 'QC'
|
||||
WHEN 4 THEN 'Paint'
|
||||
WHEN 5 THEN 'Completed'
|
||||
ELSE 'Other'
|
||||
END as status_val
|
||||
")
|
||||
->from('weld_logs')
|
||||
->where('type_of_joint', 'S') // Shop joints drive spool status
|
||||
->whereNotNull('spool_number')
|
||||
->where('spool_number', '!=', '')
|
||||
->whereNotNull('welding_date')
|
||||
->groupBy('iso_number', 'spool_number');
|
||||
}, 'sub')
|
||||
->groupBy('status_val')
|
||||
->get();
|
||||
|
||||
// Transform to array format for frontend
|
||||
$spoolProgress = [];
|
||||
foreach ($spoolStats as $row) {
|
||||
$spoolProgress[] = [
|
||||
'status' => $row->status_val,
|
||||
'count' => (int)$row->count
|
||||
];
|
||||
}
|
||||
|
||||
// 3. NDT/Repair Backlog
|
||||
// Using existing setting logic from ndt-backlog.blade.php
|
||||
$ndtData = json_decode(setting("ndtCalculation"), true);
|
||||
$ndtBacklogStats = [];
|
||||
|
||||
if (is_array($ndtData)) {
|
||||
foreach($ndtData as $d) {
|
||||
foreach($d as $field => $value) {
|
||||
if(strpos($field, "backlog") !== false) {
|
||||
$key = strtoupper(str_replace("_backlog", "", $field));
|
||||
if(!isset($ndtBacklogStats[$key])) {
|
||||
$ndtBacklogStats[$key] = 0;
|
||||
}
|
||||
if($value > 0) {
|
||||
$ndtBacklogStats[$key] += $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add dynamic limits from Settings
|
||||
$ndtBacklogStats['ndt_limit'] = setting('ndt_limit');
|
||||
$ndtBacklogStats['ndt_wdi'] = setting('ndt_wdi');
|
||||
$ndtBacklogStats['repair_limit'] = setting('repair_limit');
|
||||
$ndtBacklogStats['repair_wdi'] = setting('repair_wdi');
|
||||
|
||||
// 4. Hand-over Status
|
||||
// Statuses: Dynamically fetched from id_status
|
||||
$handoverProgress = Handover::selectRaw('id_status, COUNT(*) as count')
|
||||
->whereNotNull('id_status')
|
||||
->where('id_status', '!=', '')
|
||||
->groupBy('id_status')
|
||||
->pluck('count', 'id_status')
|
||||
->toArray();
|
||||
|
||||
// 5. Welding Equipment Status
|
||||
// Statuses: Working, Repair, Out of use
|
||||
$equipmentStats = WeldingEquipment::selectRaw('working_status, COUNT(*) as count')
|
||||
->whereNotNull('working_status')
|
||||
->groupBy('working_status')
|
||||
->get()
|
||||
->pluck('count', 'working_status');
|
||||
|
||||
$targetEquipmentStatuses = ['Working', 'Repair', 'Out of use'];
|
||||
$equipmentProgress = [];
|
||||
foreach ($targetEquipmentStatuses as $status) {
|
||||
$equipmentProgress[$status] = $equipmentStats[$status] ?? 0;
|
||||
}
|
||||
// Add others
|
||||
$otherEquipmentCount = 0;
|
||||
foreach ($equipmentStats as $status => $count) {
|
||||
if (!in_array($status, $targetEquipmentStatuses)) {
|
||||
$otherEquipmentCount += $count;
|
||||
}
|
||||
}
|
||||
if ($otherEquipmentCount > 0) {
|
||||
$equipmentProgress['Other'] = $otherEquipmentCount;
|
||||
}
|
||||
|
||||
// 6. Welding Status (Welder Distribution by Site)
|
||||
// Logic: Group by project (Site).
|
||||
// CS = distinct real_welder_1 & real_welder_2 where ru_material_group_1 matches 'M01'
|
||||
// SS/AS = distinct real_welder_1 & real_welder_2 where ru_material_group_1 does NOT match 'M01'
|
||||
|
||||
$weldingStatusData = DB::table(function ($query) {
|
||||
$query->select('project', 'type_of_joint', 'ru_material_group_1', 'real_welder_1 as welder', 'welding_date')
|
||||
->from('weld_logs')
|
||||
->whereNotNull('real_welder_1')
|
||||
->where('real_welder_1', '!=', '')
|
||||
->whereNotNull('welding_date')
|
||||
->unionAll(
|
||||
DB::table('weld_logs')
|
||||
->select('project', 'type_of_joint', 'ru_material_group_2', 'real_welder_1 as welder', 'welding_date')
|
||||
->from('weld_logs')
|
||||
->whereNotNull('real_welder_2')
|
||||
->where('real_welder_2', '!=', '')
|
||||
->whereNotNull('welding_date')
|
||||
);
|
||||
}, 'u')
|
||||
->select('project')
|
||||
->selectRaw("YEAR(welding_date) as year")
|
||||
->selectRaw("MONTH(welding_date) as month")
|
||||
->selectRaw("COUNT(DISTINCT CASE WHEN type_of_joint = 'S' THEN welder END) as shop")
|
||||
->selectRaw("COUNT(DISTINCT CASE WHEN type_of_joint != 'S' OR type_of_joint IS NULL THEN welder END) as field")
|
||||
->selectRaw("COUNT(DISTINCT CASE WHEN (ru_material_group_1 LIKE '%M01%' OR ru_material_group_1 LIKE '%М01%') THEN welder END) as cs")
|
||||
->selectRaw("COUNT(DISTINCT CASE WHEN (ru_material_group_1 NOT LIKE '%M01%' AND ru_material_group_1 NOT LIKE '%М01%') OR ru_material_group_1 IS NULL THEN welder END) as ss")
|
||||
->selectRaw("COUNT(DISTINCT welder) as actual_total")
|
||||
->whereNotNull('project')
|
||||
->where('project', '!=', '')
|
||||
->groupBy('project', 'year', 'month')
|
||||
->get();
|
||||
|
||||
$weldingStatus = [];
|
||||
foreach($weldingStatusData as $row) {
|
||||
$weldingStatus[] = [
|
||||
'site' => $row->project,
|
||||
'year' => (int)$row->year,
|
||||
'month' => (int)$row->month,
|
||||
'shop' => (int)$row->shop,
|
||||
'field' => (int)$row->field,
|
||||
'cs' => (int)$row->cs,
|
||||
'ss' => (int)$row->ss,
|
||||
'total' => (int)$row->actual_total
|
||||
];
|
||||
}
|
||||
|
||||
// 7. Welding Status Overall Summary (No Site Breakdown)
|
||||
// Count unique welders across ALL projects for Shop and Field
|
||||
// 7. Welding Status Overall Summary (No Site Breakdown)
|
||||
// Count unique welders across ALL projects for Shop and Field
|
||||
$weldingSummaryRaw = DB::table(function ($query) {
|
||||
$query->select('type_of_joint', 'real_welder_1 as welder')
|
||||
->from('weld_logs')
|
||||
->whereNotNull('real_welder_1')
|
||||
->where('real_welder_1', '!=', '')
|
||||
->whereNotNull('welding_date')
|
||||
->unionAll(
|
||||
DB::table('weld_logs')
|
||||
->select('type_of_joint', 'real_welder_2 as welder')
|
||||
->from('weld_logs')
|
||||
->whereNotNull('real_welder_2')
|
||||
->where('real_welder_2', '!=', '')
|
||||
->whereNotNull('welding_date')
|
||||
);
|
||||
}, 'u')
|
||||
->selectRaw("COUNT(DISTINCT CASE WHEN type_of_joint = 'S' THEN welder END) as shop")
|
||||
->selectRaw("COUNT(DISTINCT CASE WHEN type_of_joint != 'S' OR type_of_joint IS NULL THEN welder END) as field")
|
||||
->selectRaw("COUNT(DISTINCT welder) as actual_total")
|
||||
->first();
|
||||
|
||||
$weldingStatusSummary = [
|
||||
'shop' => (int)$weldingSummaryRaw->shop,
|
||||
'field' => (int)$weldingSummaryRaw->field,
|
||||
'total' => (int)$weldingSummaryRaw->actual_total
|
||||
];
|
||||
|
||||
// 8. Welding Status Monthly (Shop/Field/Total per Month)
|
||||
// Groups distinct welders by month and project
|
||||
// 8. Welding Status Monthly (Shop/Field/Total per Month)
|
||||
// Groups distinct welders by month (Global Site Scope)
|
||||
$weldingStatusMonthly = DB::table(function ($query) use ($year) {
|
||||
$query->select('project', 'welding_date', 'type_of_joint', 'real_welder_1 as welder')
|
||||
->from('weld_logs')
|
||||
->whereNotNull('real_welder_1')
|
||||
->where('real_welder_1', '!=', '')
|
||||
->whereNotNull('welding_date')
|
||||
->unionAll(
|
||||
DB::table('weld_logs')
|
||||
->select('project', 'welding_date', 'type_of_joint', 'real_welder_2 as welder')
|
||||
->from('weld_logs')
|
||||
->whereNotNull('real_welder_2')
|
||||
->where('real_welder_2', '!=', '')
|
||||
->whereNotNull('welding_date')
|
||||
);
|
||||
}, 'u')
|
||||
->selectRaw("
|
||||
DATE_FORMAT(welding_date, '%Y-%m') as month_key,
|
||||
MONTH(welding_date) as month,
|
||||
YEAR(welding_date) as year,
|
||||
COUNT(DISTINCT CASE WHEN type_of_joint = 'S' THEN welder END) as shop,
|
||||
COUNT(DISTINCT CASE WHEN type_of_joint != 'S' OR type_of_joint IS NULL THEN welder END) as field,
|
||||
COUNT(DISTINCT welder) as actual_total
|
||||
")
|
||||
->groupBy('month_key', 'month', 'year')
|
||||
->orderBy('month_key', 'asc')
|
||||
->get()
|
||||
->map(function($item) {
|
||||
return [
|
||||
'project' => 'Total', // Value is now aggregated for the whole site
|
||||
'month_key' => $item->month_key,
|
||||
'month' => (int)$item->month,
|
||||
'year' => (int)$item->year,
|
||||
'shop' => (int)$item->shop,
|
||||
'field' => (int)$item->field,
|
||||
'total' => (int)$item->actual_total
|
||||
];
|
||||
});
|
||||
|
||||
// 9. NDT Summary (RT & UT)
|
||||
// New calculation logic mirrored from summary-nocache.blade.php
|
||||
$ndtSummary = [];
|
||||
|
||||
// RT Logic
|
||||
$rtTotal = DB::table('radiographic_tests')->whereNotNull('rt_result')->count();
|
||||
$rtWDI = DB::table('radiographic_tests')->whereNotNull('rt_result')->sum('nps_1');
|
||||
$rtAccepted = DB::table('radiographic_tests')->where('rt_result', 'Accept / Годен')->count();
|
||||
$rtRejected = DB::table('radiographic_tests')->whereNotNull('rt_result')->whereNotIn('rt_result', ['', 'Accept / Годен'])->count();
|
||||
|
||||
// RT Repair Rate logic: (ShopRepair + FieldRepair) / (ShopTotal + FieldTotal)
|
||||
$rtShopTotal = DB::table('radiographic_tests')->where('type_of_joint', 'S')->whereNotIn('rt_result', [''])->count();
|
||||
$rtShopRepair = DB::table('radiographic_tests')->where('type_of_joint', 'S')->whereNotIn('rt_result', ['', 'Accept / Годен'])->count();
|
||||
$rtFieldTotal = DB::table('radiographic_tests')->where('type_of_joint', 'F')->whereNotIn('rt_result', [''])->count();
|
||||
$rtFieldRepair = DB::table('radiographic_tests')->where('type_of_joint', 'F')->whereNotIn('rt_result', ['', 'Accept / Годен'])->count();
|
||||
|
||||
$rtRepairRate = ($rtShopTotal + $rtFieldTotal) > 0
|
||||
? round(($rtShopRepair + $rtFieldRepair) * 100 / ($rtShopTotal + $rtFieldTotal), 2)
|
||||
: 0;
|
||||
|
||||
$ndtSummary['rt'] = [
|
||||
'total' => $rtTotal,
|
||||
'wdi' => (float)$rtWDI,
|
||||
'accepted' => $rtAccepted,
|
||||
'rejected' => $rtRejected,
|
||||
'repair_rate' => $rtRepairRate
|
||||
];
|
||||
|
||||
// UT Logic
|
||||
$utTotal = DB::table('ultrasonic_tests')->whereNotNull('ut_result')->count();
|
||||
$utWDI = DB::table('ultrasonic_tests')->whereNotNull('ut_result')->sum('nps_1');
|
||||
$utAccepted = DB::table('ultrasonic_tests')->where('ut_result', 'Accept / Годен')->count();
|
||||
$utRejected = DB::table('ultrasonic_tests')->whereNotNull('ut_result')->where('ut_result', '!=', 'Accept / Годен')->count();
|
||||
|
||||
// UT Repair Rate
|
||||
$utShopTotal = DB::table('ultrasonic_tests')->where('type_of_joint', 'S')->whereNotIn('ut_result', [''])->count();
|
||||
$utShopRepair = DB::table('ultrasonic_tests')->where('type_of_joint', 'S')->whereNotIn('ut_result', ['', 'Accept / Годен'])->count();
|
||||
$utFieldTotal = DB::table('ultrasonic_tests')->where('type_of_joint', 'F')->whereNotIn('ut_result', [''])->count();
|
||||
$utFieldRepair = DB::table('ultrasonic_tests')->where('type_of_joint', 'F')->whereNotIn('ut_result', ['', 'Accept / Годен'])->count();
|
||||
|
||||
$utRepairRate = ($utShopTotal + $utFieldTotal) > 0
|
||||
? round(($utShopRepair + $utFieldRepair) * 100 / ($utShopTotal + $utFieldTotal), 2)
|
||||
: 0;
|
||||
|
||||
$ndtSummary['ut'] = [
|
||||
'total' => $utTotal,
|
||||
'wdi' => (float)$utWDI,
|
||||
'accepted' => $utAccepted,
|
||||
'rejected' => $utRejected,
|
||||
'repair_rate' => $utRepairRate
|
||||
];
|
||||
|
||||
// 10. WDI Statistics (CS vs SS/AS) by Project
|
||||
// CS: Material Group contains M01
|
||||
// SS: Material Group does not contain M01
|
||||
$wdiStatsData = DB::table('weld_logs')
|
||||
->select('project')
|
||||
->selectRaw("YEAR(welding_date) as year")
|
||||
->selectRaw("MONTH(welding_date) as month")
|
||||
->selectRaw("SUM(CASE WHEN (ru_material_group_1 LIKE '%M01%' OR ru_material_group_1 LIKE '%М01%') THEN nps_1 ELSE 0 END) as cs_wdi")
|
||||
->selectRaw("SUM(CASE WHEN (ru_material_group_1 NOT LIKE '%M01%' AND ru_material_group_1 NOT LIKE '%М01%') OR ru_material_group_1 IS NULL THEN nps_1 ELSE 0 END) as ss_wdi")
|
||||
->whereNotNull('welding_date')
|
||||
->where('project', '!=', '')
|
||||
->whereNotNull('project')
|
||||
->groupBy('project', 'year', 'month')
|
||||
->get();
|
||||
|
||||
$wdiStats = [];
|
||||
foreach($wdiStatsData as $row) {
|
||||
$wdiStats[] = [
|
||||
'project' => $row->project,
|
||||
'year' => (int)$row->year,
|
||||
'month' => (int)$row->month,
|
||||
'cs' => (float)$row->cs_wdi,
|
||||
'ss' => (float)$row->ss_wdi,
|
||||
'total' => (float)$row->cs_wdi + (float)$row->ss_wdi
|
||||
];
|
||||
}
|
||||
|
||||
// 11. Weld Backlog (Prefab vs Field) by Project
|
||||
// Backlog: Items with no welding date, grouped by year/month from fit_up_date for frontend filtering
|
||||
$weldBacklogData = DB::table('weld_logs')
|
||||
->select('project')
|
||||
->selectRaw("SUM(CASE WHEN type_of_joint = 'S' THEN nps_1 ELSE 0 END) as prefab_backlog")
|
||||
->selectRaw("SUM(CASE WHEN type_of_joint != 'S' OR type_of_joint IS NULL THEN nps_1 ELSE 0 END) as field_backlog")
|
||||
->selectRaw("SUM(nps_1) as total_backlog")
|
||||
->whereNull('welding_date')
|
||||
->where('project', '!=', '')
|
||||
->whereNotNull('project')
|
||||
->groupBy('project')
|
||||
->get();
|
||||
|
||||
$weldBacklog = [];
|
||||
foreach($weldBacklogData as $row) {
|
||||
$weldBacklog[] = [
|
||||
'project' => $row->project,
|
||||
'prefab' => (float)$row->prefab_backlog,
|
||||
'field' => (float)$row->field_backlog,
|
||||
'total' => (float)$row->total_backlog
|
||||
];
|
||||
}
|
||||
|
||||
// 12. Welder Current (from naks_welders table)
|
||||
// Total unique welders at each site, categorized by CS/SS
|
||||
// CS: material_1 contains М01 or M01
|
||||
// SS: material_1 does NOT contain М01/M01
|
||||
// No date filter - shows total registered welders per site
|
||||
$welderCurrentData = DB::table('welder_tests')
|
||||
->selectRaw("COUNT(DISTINCT CASE WHEN (material_group_1 LIKE '%M01%' OR material_group_1 LIKE '%М01%') THEN naks_id END) as cs")
|
||||
->selectRaw("COUNT(DISTINCT CASE WHEN (material_group_1 NOT LIKE '%M01%' AND material_group_1 NOT LIKE '%М01%') OR material_group_1 IS NULL THEN naks_id END) as ss")
|
||||
->selectRaw("COUNT(DISTINCT naks_id) as total")
|
||||
->where('status', 'Active')
|
||||
->get();
|
||||
|
||||
$welderCurrent = [];
|
||||
foreach($welderCurrentData as $row) {
|
||||
$welderCurrent[] = [
|
||||
'project' => '',
|
||||
'cs' => (int)$row->cs,
|
||||
'ss' => (int)$row->ss,
|
||||
'total' => (int)$row->total
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => [
|
||||
'wdi_monthly' => $wdiMonthly,
|
||||
'spool_progress' => $spoolProgress,
|
||||
'ndt_backlog' => $ndtBacklogStats,
|
||||
'handover_status' => $handoverProgress,
|
||||
'welding_equipment' => $equipmentProgress,
|
||||
'welding_status' => $weldingStatus,
|
||||
'welding_status_monthly' => $weldingStatusMonthly,
|
||||
'welding_status_summary' => $weldingStatusSummary,
|
||||
'ndt_summary' => $ndtSummary,
|
||||
'wdi_by_project' => $wdiByProject,
|
||||
'wdi_stats' => $wdiStats,
|
||||
'weld_backlog' => $weldBacklog,
|
||||
'repair_stats_monthly' => DB::table('weld_logs')
|
||||
->selectRaw("
|
||||
DATE_FORMAT(welding_date, '%Y-%m') as month_key,
|
||||
YEAR(welding_date) as year,
|
||||
MONTH(welding_date) as month,
|
||||
|
||||
SUM(CASE WHEN type_of_joint = 'S' AND rt_result IS NOT NULL AND rt_result != '' THEN 1 ELSE 0 END) as rt_shop_total,
|
||||
SUM(CASE WHEN type_of_joint = 'S' AND rt_result NOT IN ('', 'Accept / Годен') THEN 1 ELSE 0 END) as rt_shop_repair,
|
||||
|
||||
SUM(CASE WHEN type_of_joint = 'F' AND rt_result IS NOT NULL AND rt_result != '' THEN 1 ELSE 0 END) as rt_field_total,
|
||||
SUM(CASE WHEN type_of_joint = 'F' AND rt_result NOT IN ('', 'Accept / Годен') THEN 1 ELSE 0 END) as rt_field_repair,
|
||||
|
||||
SUM(CASE WHEN type_of_joint = 'S' AND ut_result IS NOT NULL AND ut_result != '' THEN 1 ELSE 0 END) as ut_shop_total,
|
||||
SUM(CASE WHEN type_of_joint = 'S' AND ut_result NOT IN ('', 'Accept / Годен') THEN 1 ELSE 0 END) as ut_shop_repair,
|
||||
|
||||
SUM(CASE WHEN type_of_joint = 'F' AND ut_result IS NOT NULL AND ut_result != '' THEN 1 ELSE 0 END) as ut_field_total,
|
||||
SUM(CASE WHEN type_of_joint = 'F' AND ut_result NOT IN ('', 'Accept / Годен') THEN 1 ELSE 0 END) as ut_field_repair
|
||||
")
|
||||
->whereNotNull('welding_date')
|
||||
->groupBy('month_key', 'year', 'month')
|
||||
->get(),
|
||||
'test_packages' => DB::table('test_packages')
|
||||
->leftJoinSub(function ($query) {
|
||||
$query->from('weld_logs')
|
||||
->select(
|
||||
'test_package_no',
|
||||
DB::raw('MAX(project) as project'),
|
||||
DB::raw('MAX(welding_date) as last_weld_date')
|
||||
)
|
||||
->whereNotNull('test_package_no')
|
||||
->where('test_package_no', '!=', '')
|
||||
->whereNotNull('welding_date')
|
||||
->groupBy('test_package_no');
|
||||
}, 'projects', 'projects.test_package_no', '=', 'test_packages.test_package_number')
|
||||
->selectRaw("
|
||||
COALESCE(projects.project, 'Unknown') as project,
|
||||
count(test_packages.id) as total_tp,
|
||||
SUM(CASE WHEN walkdown_date IS NOT NULL THEN 1 ELSE 0 END) as line_check,
|
||||
SUM(COALESCE(a_punch_point_open, 0)) as punch_a,
|
||||
SUM(CASE WHEN test_date IS NOT NULL THEN 1 ELSE 0 END) as test,
|
||||
SUM(CASE WHEN reinstatement_date IS NOT NULL THEN 1 ELSE 0 END) as reinstatement
|
||||
")
|
||||
->groupBy(
|
||||
DB::raw("COALESCE(projects.project, 'Unknown')")
|
||||
)
|
||||
->get(),
|
||||
'welder_current' => $welderCurrent,
|
||||
|
||||
]
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* Welding Status By Project
|
||||
*
|
||||
* Get summary data for "Sahaya Göre Kaynak Durumu" (Welding Status by Site).
|
||||
* Breakdown of WDI (NPS-1) by project, grouped into SHOP and FIELD.
|
||||
*
|
||||
* @response 200 {
|
||||
* "status": "success",
|
||||
* "data": [
|
||||
* {
|
||||
* "project": "COOLER TOWER",
|
||||
* "shop": 82,
|
||||
* "field": 122,
|
||||
* "total": 204,
|
||||
* "percentage": 93
|
||||
* },
|
||||
* ...
|
||||
* ]
|
||||
* }
|
||||
*/
|
||||
public function weldingByProject()
|
||||
{
|
||||
$weldingData = DB::table('weld_logs')
|
||||
->select('project')
|
||||
->selectRaw("SUM(CASE WHEN type_of_joint = 'S' AND welding_date IS NOT NULL THEN nps_1 ELSE 0 END) as shop")
|
||||
->selectRaw("SUM(CASE WHEN (type_of_joint != 'S' OR type_of_joint IS NULL) AND welding_date IS NOT NULL THEN nps_1 ELSE 0 END) as field")
|
||||
->selectRaw("SUM(CASE WHEN welding_date IS NOT NULL THEN nps_1 ELSE 0 END) as total_welded")
|
||||
->selectRaw("SUM(nps_1) as total_scope")
|
||||
->whereNotNull('project')
|
||||
->where('project', '!=', '')
|
||||
->groupBy('project')
|
||||
->get();
|
||||
|
||||
$result = $weldingData->map(function ($row) {
|
||||
$totalWelded = (float)$row->total_welded;
|
||||
$totalScope = (float)$row->total_scope;
|
||||
$percentage = $totalScope > 0 ? round(($totalWelded / $totalScope) * 100) : 0;
|
||||
|
||||
return [
|
||||
'project' => $row->project,
|
||||
'shop' => (float)$row->shop,
|
||||
'field' => (float)$row->field,
|
||||
'total' => $totalWelded,
|
||||
'percentage' => (int)$percentage
|
||||
];
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $result
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\SurfaceAreaConstant;
|
||||
use App\Models\PaintFollowUp;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use DB;
|
||||
|
||||
class SurfaceAreaController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get distinct element types for a given standard
|
||||
*/
|
||||
public function getElements(Request $request)
|
||||
{
|
||||
$standard = $request->get('standard', 'ASME');
|
||||
|
||||
$elements = SurfaceAreaConstant::where('standard_type', $standard)
|
||||
->where('is_active', true)
|
||||
->select('element_type_en', 'element_type_ru')
|
||||
->distinct()
|
||||
->orderBy('element_type_en')
|
||||
->get();
|
||||
|
||||
return response()->json($elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get diameter options for a given standard and element
|
||||
*/
|
||||
public function getDiameters(Request $request)
|
||||
{
|
||||
$standard = $request->get('standard', 'ASME');
|
||||
$element = $request->get('element');
|
||||
|
||||
// Element can be either EN or RU, so we need to check both
|
||||
$diameters = SurfaceAreaConstant::where('standard_type', $standard)
|
||||
->where(function($query) use ($element) {
|
||||
$query->where('element_type_en', $element)
|
||||
->orWhere('element_type_ru', $element);
|
||||
})
|
||||
->where('is_active', true)
|
||||
->select('diameter_inch', 'diameter_mm', 'surface_area_m2', 'manufacturing_standard', 'element_type_en', 'element_type_ru', 'general_name')
|
||||
->orderBy('diameter_mm')
|
||||
->get();
|
||||
|
||||
return response()->json($diameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MTO total for a given iso_drawings
|
||||
*/
|
||||
public function getMtoTotal(Request $request)
|
||||
{
|
||||
$isoDrawings = $request->get('iso_drawings');
|
||||
|
||||
if (!$isoDrawings) {
|
||||
return response()->json(['error' => 'iso_drawings parameter is required'], 400);
|
||||
}
|
||||
|
||||
// MTO tablosundan pipe verilerini hesapla
|
||||
// Formula: SUM(quantity * PI * (odmm_1/2000)^2)
|
||||
$mtoTotal = DB::table('m_t_o_s')
|
||||
->where('description_en', 'like', '%pipe%')
|
||||
->where('line', $isoDrawings)
|
||||
->selectRaw('SUM(quantity * POWER(odmm_1/2000, 2) * PI()) AS total')
|
||||
->first()->total;
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'iso_drawings' => $isoDrawings,
|
||||
'mto_total' => $mtoTotal ?? 0
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get saved surface area items for a construction paint log
|
||||
*/
|
||||
public function getSavedItems(Request $request)
|
||||
{
|
||||
$constructionPaintLogId = $request->get('construction_paint_log_id');
|
||||
|
||||
if (!$constructionPaintLogId) {
|
||||
return response()->json(['error' => 'construction_paint_log_id parameter is required'], 400);
|
||||
}
|
||||
|
||||
$paintLog = DB::table('construction_paint_logs')
|
||||
->where('id', $constructionPaintLogId)
|
||||
->select('surface_area_items', 'fittings_m2', 'pipe_m2', 'total_m2')
|
||||
->first();
|
||||
|
||||
if (!$paintLog) {
|
||||
return response()->json(['error' => 'Construction Paint Log not found'], 404);
|
||||
}
|
||||
|
||||
$items = [];
|
||||
if ($paintLog->surface_area_items) {
|
||||
$items = json_decode($paintLog->surface_area_items, true) ?: [];
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'items' => $items,
|
||||
'fittings_m2' => $paintLog->fittings_m2,
|
||||
'pipe_m2' => $paintLog->pipe_m2,
|
||||
'total_m2' => $paintLog->total_m2
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save surface area calculation to construction_paint_logs and paint_follow_ups
|
||||
*/
|
||||
public function save(Request $request)
|
||||
{
|
||||
$constructionPaintLogId = $request->get('construction_paint_log_id');
|
||||
$fittingsTotal = $request->get('fittings_total');
|
||||
$pipeTotal = $request->get('pipe_total');
|
||||
$grandTotal = $request->get('grand_total');
|
||||
$cuttingMm = $request->get('cutting_mm');
|
||||
$items = json_decode($request->get('items', '[]'), true);
|
||||
$dn1 = $request->get('dn_1');
|
||||
$dn2 = $request->get('dn_2');
|
||||
$linePipeMm1 = $request->get('line_pipe_mm_1');
|
||||
$linePipeMm2 = $request->get('line_pipe_mm_2');
|
||||
$totalLineMm = $request->get('total_line_mm');
|
||||
|
||||
// Calculate total_line_mm if not provided (sum of line_pipe_mm_1 and line_pipe_mm_2)
|
||||
if ($totalLineMm === null || $totalLineMm === '') {
|
||||
$linePipeMm1Val = (float)($linePipeMm1 ?? 0);
|
||||
$linePipeMm2Val = (float)($linePipeMm2 ?? 0);
|
||||
$totalLineMm = $linePipeMm1Val + $linePipeMm2Val;
|
||||
}
|
||||
|
||||
// Get construction paint log record
|
||||
$paintLog = DB::table('construction_paint_logs')->find($constructionPaintLogId);
|
||||
|
||||
if (!$paintLog) {
|
||||
return response()->json(['error' => 'Construction Paint Log not found'], 404);
|
||||
}
|
||||
|
||||
// Process items to calculate fitting quantities and areas
|
||||
$elbowPcs = 0;
|
||||
$elbow45Pcs = 0;
|
||||
$elbowM2 = 0;
|
||||
$teePcs = 0;
|
||||
$teeM2 = 0;
|
||||
$reductionsPcs = 0;
|
||||
$reductionsM2 = 0;
|
||||
$flangePcs = 0;
|
||||
$flangeM2 = 0;
|
||||
$ventPcs = 0;
|
||||
$ventM2 = 0;
|
||||
$capPcs = 0;
|
||||
$capM2 = 0;
|
||||
|
||||
foreach ($items as $item) {
|
||||
$elementEn = $item['element_en'] ?? '';
|
||||
$elementRu = $item['element_ru'] ?? '';
|
||||
$quantity = (int)($item['quantity'] ?? 0);
|
||||
$total = (float)($item['total'] ?? 0);
|
||||
|
||||
// Check both EN and RU element names (use EN first, fallback to RU)
|
||||
$elementName = trim($elementEn ?: $elementRu);
|
||||
$elementNameLower = strtolower($elementName);
|
||||
|
||||
// Elbow 90° 1.5D
|
||||
if (stripos($elementNameLower, 'elbow') !== false &&
|
||||
(stripos($elementNameLower, '90') !== false || stripos($elementName, '90°') !== false)) {
|
||||
$elbowPcs += $quantity;
|
||||
$elbowM2 += $total;
|
||||
}
|
||||
// Elbow 45° 1.5D
|
||||
elseif (stripos($elementNameLower, 'elbow') !== false &&
|
||||
(stripos($elementNameLower, '45') !== false || stripos($elementName, '45°') !== false)) {
|
||||
$elbow45Pcs += $quantity;
|
||||
$elbowM2 += $total;
|
||||
}
|
||||
// Reductions (Concentric, Eccentric, any reducer)
|
||||
elseif (stripos($elementNameLower, 'reducer') !== false ||
|
||||
stripos($elementNameLower, 'reduction') !== false) {
|
||||
$reductionsPcs += $quantity;
|
||||
$reductionsM2 += $total;
|
||||
}
|
||||
// Slip On Flange (Class 150)
|
||||
elseif (stripos($elementNameLower, 'slip on flange') !== false ||
|
||||
(stripos($elementNameLower, 'slip') !== false && stripos($elementNameLower, 'flange') !== false)) {
|
||||
$flangePcs += $quantity;
|
||||
$flangeM2 += $total;
|
||||
}
|
||||
// Weldneck Flange (Class 150)
|
||||
elseif (stripos($elementNameLower, 'weldneck flange') !== false ||
|
||||
(stripos($elementNameLower, 'weldneck') !== false && stripos($elementNameLower, 'flange') !== false)) {
|
||||
$flangePcs += $quantity;
|
||||
$flangeM2 += $total;
|
||||
}
|
||||
// Tee (Equal Tee, Reducing Tee, Cross Tee - all types)
|
||||
elseif (stripos($elementNameLower, 'tee') !== false ||
|
||||
stripos($elementNameLower, 'cross') !== false) {
|
||||
$teePcs += $quantity;
|
||||
$teeM2 += $total;
|
||||
}
|
||||
// Nipple/Olet (replaces Vent)
|
||||
elseif (stripos($elementNameLower, 'nipple') !== false ||
|
||||
stripos($elementNameLower, 'olet') !== false ||
|
||||
stripos($elementNameLower, 'nipel') !== false ||
|
||||
stripos($elementNameLower, 'nippel') !== false) {
|
||||
$ventPcs += $quantity;
|
||||
$ventM2 += $total;
|
||||
}
|
||||
// Cap
|
||||
elseif (stripos($elementNameLower, 'cap') !== false) {
|
||||
$capPcs += $quantity;
|
||||
$capM2 += $total;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare update data
|
||||
$updateData = [
|
||||
'fittings_m2' => $fittingsTotal,
|
||||
'pipe_m2' => $pipeTotal,
|
||||
'total_m2' => $grandTotal,
|
||||
'cutting_mm' => $cuttingMm,
|
||||
'surface_area_items' => json_encode($items),
|
||||
'elbow_pcs' => $elbowPcs,
|
||||
'elbow_45_pcs' => $elbow45Pcs,
|
||||
'elbow_m2' => round($elbowM2, 2),
|
||||
'tee_pcs' => $teePcs,
|
||||
'tee_m2' => round($teeM2, 2),
|
||||
'reductions_pcs' => $reductionsPcs,
|
||||
'reductions_m2' => round($reductionsM2, 2),
|
||||
'flange_pcs' => $flangePcs,
|
||||
'flange_m2' => round($flangeM2, 2),
|
||||
'vent_pcs' => $ventPcs,
|
||||
'vent_m2' => round($ventM2, 2),
|
||||
'cap_pcs' => $capPcs,
|
||||
'cap_m2' => round($capM2, 2),
|
||||
'updated_at' => now()
|
||||
];
|
||||
|
||||
// Add pipe dimensions if provided (only if not empty and not zero)
|
||||
if ($dn1 !== null && $dn1 !== '') {
|
||||
$updateData['dn_1'] = $dn1;
|
||||
}
|
||||
if ($dn2 !== null && $dn2 !== '') {
|
||||
$updateData['dn_2'] = $dn2;
|
||||
}
|
||||
|
||||
// Check if columns exist before updating line_pipe_mm fields
|
||||
$hasLinePipeMm1 = Schema::hasColumn('construction_paint_logs', 'line_pipe_mm_1');
|
||||
$hasLinePipeMm2 = Schema::hasColumn('construction_paint_logs', 'line_pipe_mm_2');
|
||||
$hasTotalLineMm = Schema::hasColumn('construction_paint_logs', 'total_line_mm');
|
||||
|
||||
if ($hasLinePipeMm1 && $linePipeMm1 !== null && $linePipeMm1 !== '' && $linePipeMm1 != 0) {
|
||||
$updateData['line_pipe_mm_1'] = (int)$linePipeMm1;
|
||||
}
|
||||
if ($hasLinePipeMm2 && $linePipeMm2 !== null && $linePipeMm2 !== '' && $linePipeMm2 != 0) {
|
||||
$updateData['line_pipe_mm_2'] = (int)$linePipeMm2;
|
||||
}
|
||||
// Add total_line_mm (sum of line_pipe_mm_1 and line_pipe_mm_2)
|
||||
// Only update if total is greater than 0 and column exists
|
||||
if ($hasTotalLineMm && $totalLineMm !== null && $totalLineMm > 0) {
|
||||
$updateData['total_line_mm'] = (float)$totalLineMm;
|
||||
}
|
||||
|
||||
// Update construction paint log with surface area values and fitting details
|
||||
DB::table('construction_paint_logs')
|
||||
->where('id', $constructionPaintLogId)
|
||||
->update($updateData);
|
||||
|
||||
// Find or create paint follow up record based on spool/line
|
||||
$paintFollowUp = PaintFollowUp::where('spool_no_joint_no', $paintLog->spool)
|
||||
->where('line', $paintLog->line)
|
||||
->first();
|
||||
|
||||
$paintFollowUpAction = '';
|
||||
$paintFollowUpId = null;
|
||||
|
||||
if ($paintFollowUp) {
|
||||
$paintFollowUp->update([
|
||||
'volume_1' => $grandTotal,
|
||||
'volume_2' => $grandTotal,
|
||||
'volume_3' => $grandTotal,
|
||||
'total_volume' => $grandTotal * 3,
|
||||
]);
|
||||
$paintFollowUpAction = 'updated';
|
||||
$paintFollowUpId = $paintFollowUp->id;
|
||||
} else {
|
||||
$newRecord = PaintFollowUp::create([
|
||||
'line' => $paintLog->line,
|
||||
'iso_number' => $paintLog->iso_drawings,
|
||||
'spool_no_joint_no' => $paintLog->spool,
|
||||
'volume_1' => $grandTotal,
|
||||
'volume_2' => $grandTotal,
|
||||
'volume_3' => $grandTotal,
|
||||
'total_volume' => $grandTotal * 3,
|
||||
]);
|
||||
$paintFollowUpAction = 'created';
|
||||
$paintFollowUpId = $newRecord->id;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Surface area saved successfully',
|
||||
'construction_paint_log' => [
|
||||
'id' => $constructionPaintLogId,
|
||||
'spool' => $paintLog->spool,
|
||||
'line' => $paintLog->line,
|
||||
'fittings_m2' => $fittingsTotal,
|
||||
'pipe_m2' => $pipeTotal,
|
||||
'total_m2' => $grandTotal
|
||||
],
|
||||
'paint_follow_up' => [
|
||||
'action' => $paintFollowUpAction,
|
||||
'id' => $paintFollowUpId,
|
||||
'spool_no_joint_no' => $paintLog->spool,
|
||||
'line' => $paintLog->line,
|
||||
'volume_1' => $grandTotal,
|
||||
'volume_2' => $grandTotal,
|
||||
'volume_3' => $grandTotal,
|
||||
'total_volume' => $grandTotal * 3
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class WorkPermitHierarchyController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get Work Permit Hierarchy
|
||||
*
|
||||
* Returns a structured hiearchy of work permit projects, companies, and personnel.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
try {
|
||||
// Get all column names from both tables for placeholders
|
||||
$workPermitColumns = Schema::getColumnListing('work_permit_documents');
|
||||
$subcontractorColumns = Schema::getColumnListing('subcontractors');
|
||||
|
||||
$query = DB::table("work_permit_documents")
|
||||
->select([
|
||||
'work_permit_documents.id',
|
||||
'work_permit_documents.name_surname',
|
||||
'work_permit_documents.company',
|
||||
'work_permit_documents.certificates_number',
|
||||
'work_permit_documents.duty',
|
||||
'work_permit_documents.document_number',
|
||||
'work_permit_documents.attorney',
|
||||
'work_permit_documents.attorney_date',
|
||||
'work_permit_documents.zone as project',
|
||||
'work_permit_documents.sign_order as personnel_sign_order',
|
||||
'subcontractors.company_name_ru',
|
||||
'subcontractors.company_name_en',
|
||||
'subcontractors.job_description',
|
||||
'subcontractors.company_code',
|
||||
'subcontractors.operation_type',
|
||||
'subcontractors.city',
|
||||
'subcontractors.address',
|
||||
'subcontractors.logo',
|
||||
'subcontractors.sign_order as company_sign_order'
|
||||
])
|
||||
->join("subcontractors", "work_permit_documents.company", "subcontractors.company_name_ru")
|
||||
->orderBy('subcontractors.operation_type')
|
||||
->orderBy('work_permit_documents.sign_order');
|
||||
|
||||
// Apply project filter if provided
|
||||
if ($request->has('project') && !empty($request->project)) {
|
||||
$query->where('work_permit_documents.zone', 'LIKE', '%' . $request->project . '%');
|
||||
}
|
||||
|
||||
$workPermitUsers = $query->get();
|
||||
|
||||
$projectMapping = [];
|
||||
|
||||
// Parse comma-separated projects and organize
|
||||
foreach ($workPermitUsers as $user) {
|
||||
$projectParts = explode(',', $user->project);
|
||||
foreach ($projectParts as $singleProject) {
|
||||
$singleProject = trim($singleProject);
|
||||
if (empty($singleProject)) continue;
|
||||
|
||||
if ($request->has('project') && !empty($request->project)) {
|
||||
if (stripos($singleProject, $request->project) === false) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($projectMapping[$singleProject])) {
|
||||
$projectMapping[$singleProject] = [];
|
||||
}
|
||||
|
||||
// Avoid duplicates in mapping
|
||||
$found = false;
|
||||
foreach ($projectMapping[$singleProject] as $existingUser) {
|
||||
if ($existingUser->name_surname === $user->name_surname &&
|
||||
$existingUser->operation_type === $user->operation_type &&
|
||||
$existingUser->personnel_sign_order === $user->personnel_sign_order) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
// Enhance user object with placeholders
|
||||
$user->placeholders = $this->generatePlaceholders($user, $workPermitColumns, $subcontractorColumns);
|
||||
$projectMapping[$singleProject][] = $user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Group into hiearchy: Project -> Operation Type -> Companies -> Users
|
||||
$response = [];
|
||||
foreach ($projectMapping as $projectName => $users) {
|
||||
$operationGroups = collect($users)->groupBy('operation_type');
|
||||
|
||||
$projectData = [
|
||||
'project_name' => $projectName,
|
||||
'operation_types' => []
|
||||
];
|
||||
|
||||
foreach ($operationGroups as $operationType => $operationGroup) {
|
||||
$companies = [];
|
||||
$byCompany = collect($operationGroup)->groupBy('company_name_ru');
|
||||
|
||||
foreach ($byCompany as $companyName => $companyUsers) {
|
||||
$companies[] = [
|
||||
'company_name' => $companyName,
|
||||
'company_sign_order' => $companyUsers->first()->company_sign_order,
|
||||
'users' => $companyUsers->sortBy('personnel_sign_order')->values()->all()
|
||||
];
|
||||
}
|
||||
|
||||
$projectData['operation_types'][] = [
|
||||
'type' => $operationType,
|
||||
'companies' => $companies
|
||||
];
|
||||
}
|
||||
|
||||
$response[] = $projectData;
|
||||
}
|
||||
|
||||
// Sort alphabetical by project name
|
||||
usort($response, function($a, $b) {
|
||||
return strcmp($a['project_name'], $b['project_name']);
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'data' => $response
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate placeholders for a user
|
||||
*/
|
||||
private function generatePlaceholders($user, $wpColumns, $sbColumns)
|
||||
{
|
||||
$job = $user->job_description ?? '';
|
||||
$fso = $user->company_sign_order ?? '';
|
||||
$pso = $user->personnel_sign_order ?? '';
|
||||
|
||||
$prefix = "{$job}{$fso}_{$pso}_";
|
||||
|
||||
$placeholders = [
|
||||
'work_permit' => [],
|
||||
'subcontractor' => [],
|
||||
'common' => [
|
||||
'name_surname' => "{" . $prefix . "name_surname}",
|
||||
'company_name' => "{" . $prefix . "company_name}",
|
||||
'certificate_no' => "{" . $prefix . "certificate_no}",
|
||||
'duty' => "{" . $prefix . "duty}",
|
||||
]
|
||||
];
|
||||
|
||||
foreach ($wpColumns as $col) {
|
||||
$placeholders['work_permit'][$col] = "{" . $prefix . $col . "}";
|
||||
}
|
||||
|
||||
foreach ($sbColumns as $col) {
|
||||
$placeholders['subcontractor'][$col] = "{" . $prefix . "sub_" . $col . "}";
|
||||
}
|
||||
|
||||
return $placeholders;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Foundation\Auth\ConfirmsPasswords;
|
||||
|
||||
class ConfirmPasswordController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Confirm Password Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller is responsible for handling password confirmations and
|
||||
| uses a simple trait to include the behavior. You're free to explore
|
||||
| this trait and override any functions that require customization.
|
||||
|
|
||||
*/
|
||||
|
||||
use ConfirmsPasswords;
|
||||
|
||||
/**
|
||||
* Where to redirect users when the intended url fails.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = RouteServiceProvider::HOME;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||
|
||||
class ForgotPasswordController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reset Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller is responsible for handling password reset emails and
|
||||
| includes a trait which assists in sending these notifications from
|
||||
| your application to your users. Feel free to explore this trait.
|
||||
|
|
||||
*/
|
||||
|
||||
use SendsPasswordResetEmails;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Login Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller handles authenticating users for the application and
|
||||
| redirecting them to your home screen. The controller uses a trait
|
||||
| to conveniently provide its functionality to your applications.
|
||||
|
|
||||
*/
|
||||
|
||||
use AuthenticatesUsers;
|
||||
|
||||
/**
|
||||
* Where to redirect users after login.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = RouteServiceProvider::HOME;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest')->except('logout');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class RegisterController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller handles the registration of new users as well as their
|
||||
| validation and creation. By default this controller uses a trait to
|
||||
| provide this functionality without requiring any additional code.
|
||||
|
|
||||
*/
|
||||
|
||||
use RegistersUsers;
|
||||
|
||||
/**
|
||||
* Where to redirect users after registration.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = RouteServiceProvider::HOME;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a validator for an incoming registration request.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Illuminate\Contracts\Validation\Validator
|
||||
*/
|
||||
protected function validator(array $data)
|
||||
{
|
||||
return Validator::make($data, [
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
|
||||
'password' => ['required', 'string', 'min:8', 'confirmed'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new user instance after a valid registration.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \App\Models\User
|
||||
*/
|
||||
protected function create(array $data)
|
||||
{
|
||||
return User::create([
|
||||
'name' => $data['name'],
|
||||
'email' => $data['email'],
|
||||
'password' => Hash::make($data['password']),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
|
||||
class ResetPasswordController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reset Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller is responsible for handling password reset requests
|
||||
| and uses a simple trait to include this behavior. You're free to
|
||||
| explore this trait and override any methods you wish to tweak.
|
||||
|
|
||||
*/
|
||||
|
||||
use ResetsPasswords;
|
||||
|
||||
/**
|
||||
* Where to redirect users after resetting their password.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = RouteServiceProvider::HOME;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Foundation\Auth\VerifiesEmails;
|
||||
|
||||
class VerificationController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Email Verification Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller is responsible for handling email verification for any
|
||||
| user that recently registered with the application. Emails may also
|
||||
| be re-sent if the user didn't receive the original email message.
|
||||
|
|
||||
*/
|
||||
|
||||
use VerifiesEmails;
|
||||
|
||||
/**
|
||||
* Where to redirect users after verification.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = RouteServiceProvider::HOME;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
$this->middleware('signed')->only('verify');
|
||||
$this->middleware('throttle:6,1')->only('verify', 'resend');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
$getShortName = db("welding_consumables")->where("brend", $rowData->product_name)->first();
|
||||
$weldingConsumables = db("welding_consumables")->where("short_name", $getShortName->short_name)->get();
|
||||
$response = [];
|
||||
foreach($weldingConsumables AS $weldingConsumable) {
|
||||
if(trim($weldingConsumable->aws_class) !="") {
|
||||
$response[] = "{$weldingConsumable->aws_class} {$weldingConsumable->aws_specification}";
|
||||
}
|
||||
}
|
||||
|
||||
//dd($weldingConsumables) ?>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
$query = db("naks_certificates")
|
||||
->whereIn("certificate_no", $certificateNo)
|
||||
->where("technology_category", $rowData->technology_category)
|
||||
->groupBy("work_type")
|
||||
->get("work_type")
|
||||
->pluck("work_type");
|
||||
|
||||
$response = $query;
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
$query = db("naks_certificates")
|
||||
->whereIn("certificate_no", $certificateNo)
|
||||
->where("technology_category", $rowData->technology_category)
|
||||
->get();
|
||||
|
||||
|
||||
$matGroups = [];
|
||||
foreach($query AS $q) {
|
||||
$matGroups[] = explode("-", $q->mat_group_1)[1];
|
||||
$matGroups[] = explode("-", $q->mat_group_2)[1];
|
||||
|
||||
}
|
||||
|
||||
$materials = db("materials");
|
||||
|
||||
if(!getesit("value", "")) {
|
||||
$value = get("value");
|
||||
$materials = $materials->where("steel_grade","like","%$value%");
|
||||
|
||||
}
|
||||
|
||||
if(count($matGroups)>0)
|
||||
{
|
||||
$response = $materials->whereIn("short_name", $matGroups)->groupBy("steel_grade")->get()->pluck("steel_grade")->toArray();
|
||||
} else {
|
||||
$response['error'] = "No data found in Naks Certificates data: Certificate No: $certificateNo Technology Category: {$rowData->technology_category}";
|
||||
}
|
||||
|
||||
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
$response = db("incoming_controls");
|
||||
$notExcept = ['null', 'undefined', ''];
|
||||
|
||||
$ruGroups = explode(",", get("ru_group"));
|
||||
$materials = db("materials")->whereIn("ru_group", $ruGroups)->select("steel_grade")->get()->pluck("steel_grade")->toArray();
|
||||
|
||||
if(!in_array(get("line"), $notExcept))
|
||||
{
|
||||
$response = $response->where("component_code", get("line"));
|
||||
}
|
||||
|
||||
if(count($materials)>0) {
|
||||
$response = $response->whereIn("material", $materials);
|
||||
}
|
||||
|
||||
|
||||
|
||||
$response = $response->groupBy("certificate_no")
|
||||
->get("certificate_no")
|
||||
|
||||
->pluck("certificate_no");
|
||||
?>
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
|
||||
if(!isset($rowData->naks_no) || $rowData->naks_no == "")
|
||||
{
|
||||
$response['error'] = "Plase select naks no";
|
||||
} else {
|
||||
$naksCertificates = explode(",", $rowData->naks_no);
|
||||
$naksWelders = db("naks_welders")->whereIn("naks_certificate_no", $naksCertificates)->get();
|
||||
$materials = [];
|
||||
|
||||
// Dönen her bir sonucu işle
|
||||
foreach ($naksWelders as $welder) {
|
||||
// material_1'den material_4'e kadar değerleri parçala ve diziye ekle
|
||||
for ($i = 1; $i <= 4; $i++) {
|
||||
$column = "material_$i";
|
||||
if (!empty($welder->$column)) {
|
||||
$explodedValues = explode(',', $welder->$column);
|
||||
$materials = array_merge($materials, $explodedValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
// `+` işaretine göre değerleri böl ve düz bir diziye dönüştür
|
||||
$expandedMaterials = [];
|
||||
foreach ($materials as $material) {
|
||||
$splitMaterials = explode('+', $material); // '+' işaretine göre böl
|
||||
foreach ($splitMaterials as $splitMaterial) {
|
||||
$expandedMaterials[] = trim($splitMaterial); // Değerleri temizle ve diziye ekle
|
||||
}
|
||||
}
|
||||
|
||||
// Tekrar eden değerleri kaldır
|
||||
$expandedMaterials = array_unique($expandedMaterials);
|
||||
|
||||
$steelGrades = db("materials")
|
||||
->whereIn("main_material", $expandedMaterials)
|
||||
->groupBy("steel_grade")
|
||||
->get()
|
||||
->pluck("steel_grade")
|
||||
->toArray();
|
||||
|
||||
if (empty($steelGrades)) {
|
||||
$response['error'] = "No materials found for main_materials: " . implode(", ", $expandedMaterials);
|
||||
} else {
|
||||
$response = $steelGrades;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
|
||||
if(!isset($rowData->naks_no) || $rowData->naks_no == "")
|
||||
{
|
||||
$response['error'] = "Plase select naks no";
|
||||
} else {
|
||||
$naksCertificates = explode(",", $rowData->naks_no);
|
||||
$naksWelders = db("naks_welders")->whereIn("naks_certificate_no", $naksCertificates)->get();
|
||||
$materials = [];
|
||||
|
||||
// Dönen her bir sonucu işle
|
||||
foreach ($naksWelders as $welder) {
|
||||
// material_1'den material_4'e kadar değerleri parçala ve diziye ekle
|
||||
for ($i = 1; $i <= 4; $i++) {
|
||||
$column = "material_$i";
|
||||
if (!empty($welder->$column)) {
|
||||
$explodedValues = explode(',', $welder->$column);
|
||||
$materials = array_merge($materials, $explodedValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
// `+` işaretine göre değerleri böl ve düz bir diziye dönüştür
|
||||
$expandedMaterials = [];
|
||||
foreach ($materials as $material) {
|
||||
$splitMaterials = explode('+', $material); // '+' işaretine göre böl
|
||||
foreach ($splitMaterials as $splitMaterial) {
|
||||
$expandedMaterials[] = trim($splitMaterial); // Değerleri temizle ve diziye ekle
|
||||
}
|
||||
}
|
||||
|
||||
// Tekrar eden değerleri kaldır
|
||||
$expandedMaterials = array_unique($expandedMaterials);
|
||||
|
||||
|
||||
$steelGrades = db("materials")
|
||||
->whereIn("main_material", $expandedMaterials)
|
||||
->groupBy("steel_grade")
|
||||
->get()
|
||||
->pluck("steel_grade")
|
||||
->toArray();
|
||||
|
||||
if (empty($steelGrades)) {
|
||||
$response['error'] = "No materials found for main_materials: " . implode(", ", $expandedMaterials);
|
||||
} else {
|
||||
$response = $steelGrades;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
$response = db("incoming_controls")
|
||||
->where("component_code", get("line"))
|
||||
->where("certificate_no", get("certificate_number"))
|
||||
->get("heat_number")
|
||||
->pluck("heat_number");
|
||||
?>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
//definition_en
|
||||
if(isset($rowData->joint_type))
|
||||
$response = db("joint_types")->where("short_name_en", $rowData->joint_type)->first();
|
||||
else {
|
||||
$response = [];
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
if(!isset($rowData->grade_1) || $rowData->grade_1 == "") {
|
||||
$response['error'] = "Please select grade 1";
|
||||
return;
|
||||
}
|
||||
$grades = explode(",", $rowData->grade_1);
|
||||
$response = db("materials")
|
||||
->groupBy("ru_group")
|
||||
->whereIn("steel_grade", $grades)
|
||||
->get()
|
||||
->pluck("ru_group")
|
||||
->toArray();
|
||||
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
if(!isset($rowData->grade_2) || $rowData->grade_2 == "") {
|
||||
$response['error'] = "Please select grade 2";
|
||||
return;
|
||||
}
|
||||
$grades = explode(",", $rowData->grade_2);
|
||||
$response = db("materials")
|
||||
->groupBy("ru_group")
|
||||
->whereIn("steel_grade", $grades)
|
||||
->get()
|
||||
->pluck("ru_group")
|
||||
->toArray();
|
||||
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
$groups = [];
|
||||
if(isset($rowData->material_group_1) && $rowData->material_group_1 != "") {
|
||||
$groups[] = $rowData->material_group_1;
|
||||
}
|
||||
if(isset($rowData->material_group_2) && $rowData->material_group_2 != "") {
|
||||
$groups[] = $rowData->material_group_2;
|
||||
}
|
||||
|
||||
if(empty($groups)) {
|
||||
$response = [];
|
||||
} else {
|
||||
$mainMaterials = db("materials")
|
||||
->whereIn("ru_group", $groups)
|
||||
->pluck("main_material")
|
||||
->toArray();
|
||||
|
||||
$mainMaterials = array_filter($mainMaterials, function($value) {
|
||||
return !is_null($value) && $value !== '';
|
||||
});
|
||||
|
||||
$mainMaterials = array_unique($mainMaterials);
|
||||
sort($mainMaterials);
|
||||
|
||||
if(count($mainMaterials) > 0){
|
||||
$response = [implode("+", $mainMaterials)];
|
||||
} else {
|
||||
$response = [];
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
$pqr = db("prosedure_qualification_records")->where("pqr_no", $rowData->pqr_no)->first();
|
||||
|
||||
$wpsGroups = [
|
||||
$rowData->russian_standard_group_no_1,
|
||||
$rowData->russian_standard_group_no_2
|
||||
];
|
||||
$pqrGroups = explode(",", $pqr->qualitication_group_of_parent_material);
|
||||
|
||||
$ruGroups = array_merge($wpsGroups, $pqrGroups);
|
||||
|
||||
$response = db("materials")
|
||||
->whereIn("ru_group", $ruGroups
|
||||
)
|
||||
->groupBy("steel_grade")
|
||||
->get("steel_grade")
|
||||
->pluck("steel_grade")
|
||||
|
||||
->toArray();
|
||||
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
$naksCertificates = explode(",", get("naks"));
|
||||
$naksWelders = db("naks_welders")
|
||||
->where("welder_id", get("naks_id"))
|
||||
->whereIn("naks_certificate_no", $naksCertificates)
|
||||
->orderBy("period_of_validity", "DESC")
|
||||
->get();
|
||||
$response = [];
|
||||
$response['welding_method'] = [];
|
||||
|
||||
foreach($naksWelders AS $naks)
|
||||
{
|
||||
|
||||
$weldingMethod = db("welding_methods")->where("ru_short_name", $naks->process)->first();
|
||||
|
||||
$response['period_of_validity'] = $naks->period_of_validity;
|
||||
$response['welding_method'][] = "{$weldingMethod->ru_short_name}/{$weldingMethod->en_welding_number}";
|
||||
}
|
||||
$response['welding_method'] = implode(",", $response['welding_method']);
|
||||
?>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
$response = db("naks_welders")
|
||||
->where("welder_id", $rowData->naks_id)
|
||||
->get("naks_certificate_no")
|
||||
->pluck("naks_certificate_no")
|
||||
->toArray();
|
||||
?>
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
$certificates = explode(",", get("value"));
|
||||
|
||||
if(!getisset("materials"))
|
||||
{
|
||||
$response['error'] = "Please select Material Group 2";
|
||||
} else {
|
||||
$materials = explode(",", get("materials"));
|
||||
|
||||
if($materials[0] == $materials[1])
|
||||
{
|
||||
$naks = db("naks_welders")
|
||||
->whereIn("naks_certificate_no", $certificates)
|
||||
->get();
|
||||
$group = 1;
|
||||
} else {
|
||||
$naks = db("naks_welders")
|
||||
->whereIn("naks_certificate_no", $certificates)
|
||||
->orWhere("material_4", "like", "%" . $materials[0] . "+" . $materials[1] . "%")
|
||||
->orWhere("material_4", "like", "%" . $materials[0] . "," . $materials[1] . "%")
|
||||
->get();
|
||||
$group = 4;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($naks)
|
||||
{
|
||||
$min_outside_diameter = $naks->min('diameter_min_' . $group);
|
||||
$start_min = $naks->max('diameter_min_' . $group);
|
||||
$max_outside_diameter = $naks->max('diameter_max_' . $group);
|
||||
$response['max_outside_diameter'] = $max_outside_diameter;
|
||||
$response['min_outside_diameter'] = $min_outside_diameter;
|
||||
$response['start_min'] = $start_min;
|
||||
} else {
|
||||
$response['error'] = "Naks Certificate data not found in Naks Welder";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
$certificates = explode(",", get("value"));
|
||||
|
||||
if(!getisset("materials"))
|
||||
{
|
||||
$response['error'] = "Please select Material Group 2";
|
||||
} else {
|
||||
$materials = explode(",", get("materials"));
|
||||
|
||||
// Retrieve main_material values from materials table
|
||||
$searchMaterials = [];
|
||||
foreach($materials as $matGroup) {
|
||||
$matRecord = db("materials")->where("ru_group", $matGroup)->first();
|
||||
if($matRecord && !empty($matRecord->main_material)) {
|
||||
$searchMaterials[] = $matRecord->main_material;
|
||||
} else {
|
||||
// Fallback: try to extract content in parentheses (e.g., M01 from 1(M01))
|
||||
if(preg_match('/\((.*?)\)/', $matGroup, $matches)) {
|
||||
$searchMaterials[] = $matches[1];
|
||||
} else {
|
||||
$searchMaterials[] = $matGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($materials[0] == $materials[1])
|
||||
{
|
||||
$naks = db("naks_welders")
|
||||
->whereIn("naks_certificate_no", $certificates)
|
||||
->get();
|
||||
$group = 1;
|
||||
} else {
|
||||
$naks = db("naks_welders")
|
||||
->whereIn("naks_certificate_no", $certificates)
|
||||
->where(function($subQuery) use($searchMaterials){
|
||||
$m1 = $searchMaterials[0] ?? '';
|
||||
$m2 = $searchMaterials[1] ?? '';
|
||||
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m1 . "+" . $m2 . "%");
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m1 . "," . $m2 . "%");
|
||||
|
||||
// Check reverse order as well to be safe
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m2 . "+" . $m1 . "%");
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m2 . "," . $m1 . "%");
|
||||
})
|
||||
->get();
|
||||
$group = 4;
|
||||
}
|
||||
|
||||
if($naks && $naks->isNotEmpty()) {
|
||||
// Tüm 'diameter_max_' değerlerini alıyoruz
|
||||
$diameter_values = $naks->pluck('diameter_max_' . $group)->toArray();
|
||||
|
||||
// Eğer 'diameter_max_' değerlerinde sadece null varsa, $start_max'ı null olarak belirliyoruz
|
||||
$start_max = in_array(null, $diameter_values, true) ? null : max($diameter_values);
|
||||
|
||||
$response['start_max'] = $start_max;
|
||||
} else {
|
||||
// Veri bulunamazsa hata mesajı
|
||||
$response['error'] = "Naks Certificate data not found in Naks Welder";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
$certificates = explode(",", get("value"));
|
||||
|
||||
if(!getisset("materials"))
|
||||
{
|
||||
$response['error'] = "Please select Material Group 2";
|
||||
} else {
|
||||
$materials = explode(",", get("materials"));
|
||||
|
||||
// Retrieve main_material values from materials table
|
||||
$searchMaterials = [];
|
||||
foreach($materials as $matGroup) {
|
||||
$matRecord = db("materials")->where("ru_group", $matGroup)->first();
|
||||
if($matRecord && !empty($matRecord->main_material)) {
|
||||
$searchMaterials[] = $matRecord->main_material;
|
||||
} else {
|
||||
// Fallback: try to extract content in parentheses (e.g., M01 from 1(M01))
|
||||
if(preg_match('/\((.*?)\)/', $matGroup, $matches)) {
|
||||
$searchMaterials[] = $matches[1];
|
||||
} else {
|
||||
$searchMaterials[] = $matGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($materials[0] == $materials[1])
|
||||
{
|
||||
$naks = db("naks_welders")
|
||||
->whereIn("naks_certificate_no", $certificates)
|
||||
->get();
|
||||
$group = 1;
|
||||
} else {
|
||||
$naks = db("naks_welders")
|
||||
->whereIn("naks_certificate_no", $certificates)
|
||||
->where(function($subQuery) use($searchMaterials){
|
||||
$m1 = $searchMaterials[0] ?? '';
|
||||
$m2 = $searchMaterials[1] ?? '';
|
||||
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m1 . "+" . $m2 . "%");
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m1 . "," . $m2 . "%");
|
||||
|
||||
// Check reverse order as well to be safe
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m2 . "+" . $m1 . "%");
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m2 . "," . $m1 . "%");
|
||||
})
|
||||
->get();
|
||||
$group = 4;
|
||||
}
|
||||
|
||||
|
||||
if($naks)
|
||||
{
|
||||
$start_min = $naks->min('diameter_min_' . $group);
|
||||
$response['start_min'] = $start_min;
|
||||
} else {
|
||||
$response['error'] = "Naks Certificate data not found in Naks Welder";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
$certificates = explode(",", get("value"));
|
||||
|
||||
if(!getisset("materials"))
|
||||
{
|
||||
$response['error'] = "Please select Material Group 2";
|
||||
} else {
|
||||
$materials = explode(",", get("materials"));
|
||||
|
||||
if($materials[0] == $materials[1])
|
||||
{
|
||||
$naks = db("naks_welders")
|
||||
->whereIn("naks_certificate_no", $certificates)
|
||||
->get();
|
||||
$group = 1;
|
||||
} else {
|
||||
$naks = db("naks_welders")
|
||||
->whereIn("naks_certificate_no", $certificates)
|
||||
->orWhere("material_4", "like", "%" . $materials[0] . "+" . $materials[1] . "%")
|
||||
->orWhere("material_4", "like", "%" . $materials[0] . "," . $materials[1] . "%")
|
||||
->get();
|
||||
$group = 4;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($naks)
|
||||
{
|
||||
$min_thick = $naks->min('min_thick_' . $group);
|
||||
$start_min = $naks->max('min_thick_' . $group);
|
||||
$max_thick = $naks->max('max_thick_' . $group);
|
||||
$response['max_thick'] = $max_thick;
|
||||
$response['min_thick'] = $min_thick;
|
||||
$response['start_min'] = $start_min;
|
||||
} else {
|
||||
$response['error'] = "Naks Certificate data not found in Naks Welder";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
$certificates = explode(",", get("value"));
|
||||
|
||||
if(!getisset("materials"))
|
||||
{
|
||||
$response['error'] = "Please select Material Group 2";
|
||||
} else {
|
||||
$materials = explode(",", get("materials"));
|
||||
|
||||
// Retrieve main_material values from materials table
|
||||
$searchMaterials = [];
|
||||
foreach($materials as $matGroup) {
|
||||
$matRecord = db("materials")->where("ru_group", $matGroup)->first();
|
||||
if($matRecord && !empty($matRecord->main_material)) {
|
||||
$searchMaterials[] = $matRecord->main_material;
|
||||
} else {
|
||||
// Fallback: try to extract content in parentheses (e.g., M01 from 1(M01))
|
||||
if(preg_match('/\((.*?)\)/', $matGroup, $matches)) {
|
||||
$searchMaterials[] = $matches[1];
|
||||
} else {
|
||||
$searchMaterials[] = $matGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($materials[0] == $materials[1])
|
||||
{
|
||||
$naks = db("naks_welders")
|
||||
->whereIn("naks_certificate_no", $certificates)
|
||||
->get();
|
||||
$group = 1;
|
||||
} else {
|
||||
$naks = db("naks_welders")
|
||||
->whereIn("naks_certificate_no", $certificates)
|
||||
->where(function($subQuery) use($searchMaterials){
|
||||
$m1 = $searchMaterials[0] ?? '';
|
||||
$m2 = $searchMaterials[1] ?? '';
|
||||
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m1 . "+" . $m2 . "%");
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m1 . "," . $m2 . "%");
|
||||
|
||||
// Check reverse order as well to be safe
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m2 . "+" . $m1 . "%");
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m2 . "," . $m1 . "%");
|
||||
})
|
||||
->get();
|
||||
$group = 4;
|
||||
}
|
||||
|
||||
if($naks && $naks->isNotEmpty()) {
|
||||
// Tüm 'max_thick' değerlerini alıyoruz
|
||||
$thickness_values = $naks->pluck('max_thick_' . $group)->toArray();
|
||||
|
||||
// Eğer 'max_thick' değerlerinde sadece null varsa, $start_max'ı null olarak belirliyoruz
|
||||
$start_max = in_array(null, $thickness_values, true) ? null : max($thickness_values);
|
||||
|
||||
$response['start_max'] = $start_max;
|
||||
} else {
|
||||
// Veri bulunamazsa hata mesajı
|
||||
$response['error'] = "Naks Certificate data not found in Naks Welder";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
$certificates = explode(",", get("value"));
|
||||
|
||||
if(!getisset("materials"))
|
||||
{
|
||||
$response['error'] = "Please select Material Group 2";
|
||||
} else {
|
||||
$materials = explode(",", get("materials"));
|
||||
|
||||
// Retrieve main_material values from materials table
|
||||
$searchMaterials = [];
|
||||
foreach($materials as $matGroup) {
|
||||
$matRecord = db("materials")->where("ru_group", $matGroup)->first();
|
||||
if($matRecord && !empty($matRecord->main_material)) {
|
||||
$searchMaterials[] = $matRecord->main_material;
|
||||
} else {
|
||||
// Fallback: try to extract content in parentheses (e.g., M01 from 1(M01))
|
||||
if(preg_match('/\((.*?)\)/', $matGroup, $matches)) {
|
||||
$searchMaterials[] = $matches[1];
|
||||
} else {
|
||||
$searchMaterials[] = $matGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($materials[0] == $materials[1])
|
||||
{
|
||||
$naks = db("naks_welders")
|
||||
->whereIn("naks_certificate_no", $certificates)
|
||||
->get();
|
||||
$group = 1;
|
||||
} else {
|
||||
$naks = db("naks_welders")
|
||||
->whereIn("naks_certificate_no", $certificates)
|
||||
->where(function($subQuery) use($searchMaterials){
|
||||
$m1 = $searchMaterials[0] ?? '';
|
||||
$m2 = $searchMaterials[1] ?? '';
|
||||
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m1 . "+" . $m2 . "%");
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m1 . "," . $m2 . "%");
|
||||
|
||||
// Check reverse order as well to be safe
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m2 . "+" . $m1 . "%");
|
||||
$subQuery->orWhere("material_4", "like", "%" . $m2 . "," . $m1 . "%");
|
||||
})
|
||||
|
||||
->get();
|
||||
$group = 4;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($naks)
|
||||
{
|
||||
$start_min = $naks->min('min_thick_' . $group);
|
||||
$response['start_min'] = $start_min;
|
||||
} else {
|
||||
$response['error'] = "Naks Certificate data not found in Naks Welder";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
$subContractors = db("subcontractors")
|
||||
->where("job_description", "NDT")
|
||||
->get();
|
||||
$response = [];
|
||||
foreach($subContractors AS $subContractor) {
|
||||
$response[] ="{$subContractor->company_name_en}" ;
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
$welders = db("welder_tests")
|
||||
->groupBy("naks_id")
|
||||
->get();
|
||||
$response = [];
|
||||
foreach($welders AS $welder) {
|
||||
$response[] ="[{$welder->naks_id}] {$welder->name_surname}" ;
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
$response = db("incoming_control_paints")->where([
|
||||
'ral_code' => $rowData->ral_code_1,
|
||||
'component_name' => $rowData->primer_coat_name_1,
|
||||
])->get()->pluck("akt_number")->toArray(); ?>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
$response = db("incoming_control_paints")->where([
|
||||
'ral_code' => $rowData->ral_code_2,
|
||||
'component_name' => $rowData->intermediate_coat_name_2,
|
||||
])->get()->pluck("akt_number")->toArray(); ?>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
$response = db("incoming_control_paints")->where([
|
||||
'ral_code' => $rowData->ral_code_3,
|
||||
'component_name' => $rowData->final_coat_name_3,
|
||||
])->get()->pluck("akt_number")->toArray(); ?>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
$columnName = "brend_name_" . get("no");
|
||||
$response = db("incoming_control_paints")->where([
|
||||
'brend_name' => $rowData->$columnName,
|
||||
])->get()->pluck("certificate_no")->toArray(); ?>
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
$response = db("incoming_control_paints")->get()->pluck("certificate_no")->toArray(); ?>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
$query = db("naks_certificates")
|
||||
->whereIn("certificate_no", $certificateNo)
|
||||
->where("technology_category", $rowData->technology_category)
|
||||
->where("mat_group_1", "like", "%". $rowData->russian_standart_group_no ."%")
|
||||
->where("mat_group_2", "like", "%". $rowData->russian_standart_group_no_2 ."%")
|
||||
->first();
|
||||
|
||||
$weldingConsumables = db("welding_consumables");
|
||||
|
||||
if($query) {
|
||||
$matGroup1 = explode("-", $query->mat_group_1)[1];
|
||||
$matGroup2 = explode("-", $query->mat_group_2)[1];
|
||||
$weldingConsumables->whereIn("short_name", [$matGroup1, $matGroup2]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(!getesit("value", "")) {
|
||||
$value = get("value");
|
||||
$weldingConsumables = $weldingConsumables->where("brend","like","%$value%");
|
||||
|
||||
}
|
||||
|
||||
$response = $weldingConsumables->get()->pluck("brend")->toArray();
|
||||
?>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
$valid_from = db("naks_certificates")
|
||||
->whereIn("certificate_no", $certificateNo)
|
||||
->where("technology_category", $rowData->technology_category)
|
||||
->orderBy("valid_from", "DESC")
|
||||
->first();
|
||||
|
||||
$valid_to = db("naks_certificates")
|
||||
->whereIn("certificate_no", $certificateNo)
|
||||
->where("technology_category", $rowData->technology_category)
|
||||
->orderBy("valid_to", "ASC")
|
||||
->first();
|
||||
|
||||
$date['valid_from'] = $valid_from->valid_from;
|
||||
$date['valid_to'] = $valid_to->valid_to;
|
||||
$response = $date;
|
||||
?>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
if(isset($rowData->pqr_no))
|
||||
$response = db("prosedure_qualification_records")->where("pqr_no", $rowData->pqr_no)->first();
|
||||
else {
|
||||
$response = [];
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
$from =(int) $rowData->p_no_from;
|
||||
$to =(int) $rowData->p_no_to;
|
||||
$incomingValue = $from."+".$to;
|
||||
|
||||
$query = db("materials")
|
||||
->whereNotIn("ru_group", ['*', ''])
|
||||
->where(function($q) use ($from, $to) {
|
||||
$q->where("asme_number", $from)
|
||||
->orWhere("asme_number", $to);
|
||||
})
|
||||
->groupBy("ru_group")
|
||||
->get("ru_group")
|
||||
->pluck("ru_group")->toArray();
|
||||
|
||||
$material_group_test_pieces = db("material_group_test_pieces")
|
||||
->where("incoming_value", $incomingValue)
|
||||
->get("provision_value")
|
||||
->pluck("provision_value");
|
||||
|
||||
|
||||
// Explode all strings by commas and flatten into a single array
|
||||
$result = [];
|
||||
foreach ($material_group_test_pieces as $piece) {
|
||||
$items = explode(',', $piece);
|
||||
$result = array_merge($result, $items);
|
||||
}
|
||||
|
||||
|
||||
// Remove duplicates and empty strings
|
||||
|
||||
// Optional: Sort the array for readability
|
||||
$query = array_merge($query, $result);
|
||||
|
||||
$query = array_values(array_filter(array_unique($query)));
|
||||
|
||||
|
||||
$response = $query;
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
use App\Models\MaterialGroupMap;
|
||||
|
||||
$response = [];
|
||||
|
||||
// Step 1: Build search term from ru_material_group_1 and ru_material_group_2
|
||||
$ru1 = trim($rowData->ru_material_group_1 ?? '');
|
||||
$ru2 = trim($rowData->ru_material_group_2 ?? '');
|
||||
|
||||
// If ru_material_group_1 and ru_material_group_2 are different, combine them with "+"
|
||||
if ($ru1 !== '' && $ru2 !== '' && $ru1 !== $ru2) {
|
||||
$searchTerm = $ru1 . '+' . $ru2;
|
||||
$searchTermReverse = $ru2 . '+' . $ru1;
|
||||
} elseif ($ru1 !== '') {
|
||||
$searchTerm = $ru1;
|
||||
$searchTermReverse = $ru1;
|
||||
} else {
|
||||
$searchTerm = $ru2;
|
||||
$searchTermReverse = $ru2;
|
||||
}
|
||||
|
||||
// Step 2: Search for this term in qualified_materials column
|
||||
// Find all records where qualified_materials contains this search term
|
||||
$materialGroupMapRecords = MaterialGroupMap::where("qualified_materials", "like", "%{$searchTerm}%")
|
||||
->orWhere("qualified_materials", "like", "%{$searchTermReverse}%")
|
||||
->get();
|
||||
|
||||
if ($materialGroupMapRecords->isEmpty()) {
|
||||
$response["error"] = "No matching qualified_materials found in MaterialGroupMap for: {$searchTerm}";
|
||||
} else {
|
||||
// Step 3: Get all material_names from matching records
|
||||
$materialNamesToSearch = [];
|
||||
foreach ($materialGroupMapRecords as $record) {
|
||||
$materialName = trim($record->material_name ?? '');
|
||||
if (!empty($materialName)) {
|
||||
$materialNamesToSearch[] = $materialName;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($materialNamesToSearch)) {
|
||||
$response["error"] = "No material_names found in matching records.";
|
||||
} else {
|
||||
// Step 4: Determine location
|
||||
$location = "";
|
||||
if ($rowData->type_of_joint == "S") {
|
||||
$location = "Shop Active";
|
||||
} elseif ($rowData->type_of_joint == "F") {
|
||||
$location = "Field Active";
|
||||
}
|
||||
|
||||
// Step 5: Query for welders - search each material_name in welder_tests
|
||||
$welders = db("welder_tests")
|
||||
->select("welder_tests.*")
|
||||
->leftJoin('welder_locations', 'welder_tests.naks_id', '=', 'welder_locations.naks_id')
|
||||
->where(function($query) use ($materialNamesToSearch) {
|
||||
foreach ($materialNamesToSearch as $materialName) {
|
||||
$materialName = trim($materialName);
|
||||
if (empty($materialName)) continue;
|
||||
|
||||
// Each material_name can have format like "8(M11)" or "1(M01)+9(M11)"
|
||||
// Search in material_group_1 and material_group_2 columns
|
||||
$query->orWhere(function($q) use ($materialName) {
|
||||
// Check if material_name contains "+"
|
||||
if (strpos($materialName, '+') !== false) {
|
||||
// Split by + and check both parts
|
||||
$parts = array_map('trim', explode('+', $materialName));
|
||||
if (count($parts) >= 2) {
|
||||
$q->where(function($q2) use ($parts) {
|
||||
$q2->where("material_group_1", "like", "%{$parts[0]}%")
|
||||
->where("material_group_2", "like", "%{$parts[1]}%");
|
||||
})->orWhere(function($q2) use ($parts) {
|
||||
$q2->where("material_group_1", "like", "%{$parts[1]}%")
|
||||
->where("material_group_2", "like", "%{$parts[0]}%");
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Single material - check both columns
|
||||
$q->where("material_group_1", "like", "%{$materialName}%")
|
||||
->orWhere("material_group_2", "like", "%{$materialName}%");
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
->groupBy("welder_tests.naks_id")
|
||||
->where("welder_tests.status", "Active");
|
||||
|
||||
if(!is_stellar())
|
||||
{
|
||||
$u = u();
|
||||
$welders = $welders->where("welder_locations.subcontructor", $u->subcontructer);
|
||||
}
|
||||
|
||||
$welders = $welders->get();
|
||||
|
||||
// Step 6: Check if welders were found
|
||||
if ($welders->isEmpty()) {
|
||||
$response["error"] = "No welders found for specified criteria.
|
||||
Criteria used:
|
||||
- Type of Joint: {$rowData->type_of_joint} (mapped to Location: {$location})
|
||||
- Search Term: {$searchTerm}
|
||||
- Matching Material Names: " . implode(", ", $materialNamesToSearch);
|
||||
} else {
|
||||
foreach ($welders as $welder) {
|
||||
$response[] = "[{$welder->naks_id}] {$welder->name_surname}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
use App\Models\MaterialGroupMap;
|
||||
|
||||
$response = [];
|
||||
|
||||
// Step 1: Build search term from ru_material_group_1 and ru_material_group_2
|
||||
$ru1 = trim($rowData->ru_material_group_1 ?? '');
|
||||
$ru2 = trim($rowData->ru_material_group_2 ?? '');
|
||||
|
||||
// If ru_material_group_1 and ru_material_group_2 are different, combine them with "+"
|
||||
if ($ru1 !== '' && $ru2 !== '' && $ru1 !== $ru2) {
|
||||
$searchTerm = $ru1 . '+' . $ru2;
|
||||
$searchTermReverse = $ru2 . '+' . $ru1;
|
||||
} elseif ($ru1 !== '') {
|
||||
$searchTerm = $ru1;
|
||||
$searchTermReverse = $ru1;
|
||||
} else {
|
||||
$searchTerm = $ru2;
|
||||
$searchTermReverse = $ru2;
|
||||
}
|
||||
|
||||
// Step 2: Search for this term in qualified_materials column
|
||||
// Find all records where qualified_materials contains this search term
|
||||
$materialGroupMapRecords = MaterialGroupMap::where("qualified_materials", "like", "%{$searchTerm}%")
|
||||
->orWhere("qualified_materials", "like", "%{$searchTermReverse}%")
|
||||
->get();
|
||||
|
||||
if ($materialGroupMapRecords->isEmpty()) {
|
||||
$response["error"] = "No matching qualified_materials found in MaterialGroupMap for: {$searchTerm}";
|
||||
} else {
|
||||
// Step 3: Get all material_names from matching records
|
||||
$materialNamesToSearch = [];
|
||||
foreach ($materialGroupMapRecords as $record) {
|
||||
$materialName = trim($record->material_name ?? '');
|
||||
if (!empty($materialName)) {
|
||||
$materialNamesToSearch[] = $materialName;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($materialNamesToSearch)) {
|
||||
$response["error"] = "No material_names found in matching records.";
|
||||
} else {
|
||||
// Step 4: Determine location
|
||||
$location = "";
|
||||
if ($rowData->type_of_joint == "S") {
|
||||
$location = "Shop Active";
|
||||
} elseif ($rowData->type_of_joint == "F") {
|
||||
$location = "Field Active";
|
||||
}
|
||||
|
||||
// Step 5: Query for welders - search each material_name in welder_tests
|
||||
$welders = db("welder_tests")
|
||||
->select("welder_tests.*")
|
||||
->leftJoin('welder_locations', 'welder_tests.naks_id', '=', 'welder_locations.naks_id')
|
||||
->where(function($query) use ($materialNamesToSearch) {
|
||||
foreach ($materialNamesToSearch as $materialName) {
|
||||
$materialName = trim($materialName);
|
||||
if (empty($materialName)) continue;
|
||||
|
||||
// Each material_name can have format like "8(M11)" or "1(M01)+9(M11)"
|
||||
// Search in material_group_1 and material_group_2 columns
|
||||
$query->orWhere(function($q) use ($materialName) {
|
||||
// Check if material_name contains "+"
|
||||
if (strpos($materialName, '+') !== false) {
|
||||
// Split by + and check both parts
|
||||
$parts = array_map('trim', explode('+', $materialName));
|
||||
if (count($parts) >= 2) {
|
||||
$q->where(function($q2) use ($parts) {
|
||||
$q2->where("material_group_1", "like", "%{$parts[0]}%")
|
||||
->where("material_group_2", "like", "%{$parts[1]}%");
|
||||
})->orWhere(function($q2) use ($parts) {
|
||||
$q2->where("material_group_1", "like", "%{$parts[1]}%")
|
||||
->where("material_group_2", "like", "%{$parts[0]}%");
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Single material - check both columns
|
||||
$q->where("material_group_1", "like", "%{$materialName}%")
|
||||
->orWhere("material_group_2", "like", "%{$materialName}%");
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
->groupBy("welder_tests.naks_id")
|
||||
->where("welder_tests.status", "Active");
|
||||
|
||||
if(!is_stellar())
|
||||
{
|
||||
$u = u();
|
||||
$welders = $welders->where("welder_locations.subcontructor", $u->subcontructer);
|
||||
}
|
||||
|
||||
$welders = $welders->get();
|
||||
|
||||
// Step 6: Check if welders were found
|
||||
if ($welders->isEmpty()) {
|
||||
$response["error"] = "No welders found for specified criteria.
|
||||
Criteria used:
|
||||
- Type of Joint: {$rowData->type_of_joint} (mapped to Location: {$location})
|
||||
- Search Term: {$searchTerm}
|
||||
- Matching Material Names: " . implode(", ", $materialNamesToSearch);
|
||||
} else {
|
||||
foreach ($welders as $welder) {
|
||||
$response[] = "[{$welder->naks_id}] {$welder->name_surname}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
$response = db("materials")
|
||||
->where("steel_grade", $rowData->material_no_1)
|
||||
->whereNotIn("ru_group", ['','*'])
|
||||
->groupBy("ru_group")
|
||||
->get("ru_group")->pluck("ru_group");
|
||||
?>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
$response = db("materials")
|
||||
->where("steel_grade", $rowData->material_no_2)
|
||||
->whereNotIn("ru_group", ['','*'])
|
||||
->groupBy("ru_group")
|
||||
->get("ru_group")->pluck("ru_group");
|
||||
?>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
$pqr = db("prosedure_qualification_records")->where("pqr_no", $rowData->pqr_no)->first();
|
||||
|
||||
$groups = explode(",", $pqr->qualitication_group_of_parent_material);
|
||||
$response = db("materials")
|
||||
->whereIn("ru_group", $groups)
|
||||
->whereNotIn("ru_group", ['','*'])
|
||||
->groupBy("ru_group")
|
||||
->get("ru_group")->pluck("ru_group");
|
||||
?>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
$naksNo = explode(",", $rowData->naks_no);
|
||||
|
||||
$naksWelders = db("naks_welders")->whereIn("naks_certificate_no", $naksNo)->get();
|
||||
|
||||
$response = [];
|
||||
foreach($naksWelders AS $naksWelder) {
|
||||
$devices = explode(",", $naksWelder->group_of_technical_device);
|
||||
foreach($devices AS $device) {
|
||||
if(!in_array($device, $response)) {
|
||||
$response[] = $device;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
$query = db("naks_certificates")
|
||||
->whereIn("certificate_no", $certificateNo)
|
||||
->where("technology_category", $rowData->technology_category)
|
||||
->get();
|
||||
|
||||
|
||||
$matGroups = [];
|
||||
foreach($query AS $q) {
|
||||
$data = explode("-", $q->mat_group_1)[1];
|
||||
if(!in_array($data, $matGroups)) {
|
||||
$matGroups[] = $data;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$materials = db("materials");
|
||||
|
||||
if(!getesit("value", "")) {
|
||||
$value = get("value");
|
||||
$materials = $materials->where("steel_grade","like","%$value%");
|
||||
|
||||
}
|
||||
|
||||
$response = $materials->whereIn("short_name", $matGroups)->groupBy("steel_grade")->get()->pluck("steel_grade")->toArray();
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
$query = db("naks_certificates")
|
||||
->whereIn("certificate_no", $certificateNo)
|
||||
->where("technology_category", $rowData->technology_category)
|
||||
->get();
|
||||
|
||||
|
||||
$matGroups = [];
|
||||
foreach($query AS $q) {
|
||||
$data = explode("-", $q->mat_group_2)[1];
|
||||
if(!in_array($data, $matGroups)) {
|
||||
$matGroups[] = $data;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$materials = db("materials");
|
||||
|
||||
if(!getesit("value", "")) {
|
||||
$value = get("value");
|
||||
$materials = $materials->where("steel_grade","like","%$value%");
|
||||
|
||||
}
|
||||
|
||||
$response = $materials
|
||||
->whereIn("short_name", $matGroups)->groupBy("steel_grade")->get()->pluck("steel_grade");
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,507 @@
|
||||
<?php
|
||||
use Carbon\Carbon;
|
||||
use App\Models\WelderTest;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
// Generate unique log key for tracking this request
|
||||
$logKey = 'WELDER_ASSIGNMENT_' . uniqid();
|
||||
Log::debug("[$logKey] ===== WELDER ASSIGNMENT AUTOCMPLETE START =====");
|
||||
|
||||
$rowData = j(get("row"));
|
||||
Log::debug("[$logKey] Input data received", ['rowData' => $rowData]);
|
||||
|
||||
$weldingMethod = explode(",", $rowData['wm']);
|
||||
$reverseWeldingMethod = array_reverse($weldingMethod);
|
||||
$reverseWeldingMethod = implode(",", $reverseWeldingMethod);
|
||||
Log::debug("[$logKey] Welding method processed", [
|
||||
'original' => $rowData['wm'],
|
||||
'reversed' => $reverseWeldingMethod
|
||||
]);
|
||||
|
||||
$response = [
|
||||
'welders' => []
|
||||
];
|
||||
$welderQualitificationStatusExpiredDate = setting("WelderQualitificationStatusExpiredDate");
|
||||
Log::debug("[$logKey] Welder qualification status expired date setting", [
|
||||
'days' => $welderQualitificationStatusExpiredDate
|
||||
]);
|
||||
|
||||
// Get qualified materials from material group map using exact combination
|
||||
// If both materials are the same, use single material name
|
||||
// If different materials, use combination with + sign
|
||||
$isSameMaterial = ($rowData['ru_1'] === $rowData['ru_2']);
|
||||
|
||||
if ($isSameMaterial) {
|
||||
// Same material on both sides - use single material
|
||||
$materialCombination = $rowData['ru_1'];
|
||||
} else {
|
||||
// Different materials - use combination
|
||||
$materialCombination = $rowData['ru_1'] . "+" . $rowData['ru_2'];
|
||||
}
|
||||
|
||||
Log::debug("[$logKey] Material combination check", [
|
||||
'ru_1' => $rowData['ru_1'],
|
||||
'ru_2' => $rowData['ru_2'],
|
||||
'is_same_material' => $isSameMaterial,
|
||||
'material_combination' => $materialCombination
|
||||
]);
|
||||
|
||||
$exactMatch = \App\Models\MaterialGroupMap::where("material_name", $materialCombination)->first();
|
||||
|
||||
$qualifiedCombinations = [];
|
||||
if ($exactMatch && $exactMatch->qualified_materials) {
|
||||
// Found exact combination match, use its qualified materials
|
||||
$qualifiedMaterialsList = explode(",", $exactMatch->qualified_materials);
|
||||
foreach ($qualifiedMaterialsList as $combo) {
|
||||
$combo = trim($combo);
|
||||
$parts = explode("+", $combo);
|
||||
|
||||
if (count($parts) == 2) {
|
||||
// Different materials combination
|
||||
$qualifiedCombinations[] = ['mat1' => trim($parts[0]), 'mat2' => trim($parts[1])];
|
||||
} elseif (count($parts) == 1) {
|
||||
// Single material (same on both sides)
|
||||
$qualifiedCombinations[] = ['mat1' => trim($parts[0]), 'mat2' => trim($parts[0])];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Always include the original combination
|
||||
if ($isSameMaterial) {
|
||||
// Same material - add only once (no reverse needed)
|
||||
$qualifiedCombinations[] = ['mat1' => $rowData['ru_1'], 'mat2' => $rowData['ru_2']];
|
||||
} else {
|
||||
// Different materials - add both original and reverse
|
||||
$qualifiedCombinations[] = ['mat1' => $rowData['ru_1'], 'mat2' => $rowData['ru_2']];
|
||||
$qualifiedCombinations[] = ['mat1' => $rowData['ru_2'], 'mat2' => $rowData['ru_1']];
|
||||
}
|
||||
|
||||
Log::debug("[$logKey] Material group map qualified materials", [
|
||||
'ru_1' => $rowData['ru_1'],
|
||||
'ru_2' => $rowData['ru_2'],
|
||||
'is_same_material' => $isSameMaterial,
|
||||
'material_combination' => $materialCombination,
|
||||
'exact_match_found' => $exactMatch !== null,
|
||||
'qualified_combinations' => $qualifiedCombinations,
|
||||
'total_combinations' => count($qualifiedCombinations)
|
||||
]);
|
||||
|
||||
|
||||
|
||||
|
||||
$failedCriteria = [];
|
||||
|
||||
// 1. material_group eşleşmeleri (with qualified combinations)
|
||||
Log::debug("[$logKey] Checking material group criteria", [
|
||||
'ru_1' => $rowData['ru_1'],
|
||||
'ru_2' => $rowData['ru_2'],
|
||||
'qualified_combinations' => $qualifiedCombinations
|
||||
]);
|
||||
|
||||
$materialGroupCheck = WelderTest::where(function ($query) use ($qualifiedCombinations) {
|
||||
foreach ($qualifiedCombinations as $combo) {
|
||||
$query->orWhere(function($q) use ($combo) {
|
||||
$q->where("material_group_1", $combo['mat1'])
|
||||
->where("material_group_2", $combo['mat2']);
|
||||
});
|
||||
}
|
||||
})->exists();
|
||||
|
||||
Log::debug("[$logKey] Material group check result", [
|
||||
'passed' => $materialGroupCheck,
|
||||
'checked_combinations_count' => count($qualifiedCombinations)
|
||||
]);
|
||||
|
||||
if (!$materialGroupCheck) {
|
||||
$qualifiedCombosStr = implode(', ', array_map(function($c) { return $c['mat1'].'+'.$c['mat2']; }, $qualifiedCombinations));
|
||||
$failedCriteria[] = "Material group mismatch - No matching record found in WPQ Follow Up module. Please check material_group_1 and material_group_2 columns for combinations: " . $qualifiedCombosStr;
|
||||
Log::debug("[$logKey] Material group check FAILED", [
|
||||
'ru_1' => $rowData['ru_1'],
|
||||
'ru_2' => $rowData['ru_2'],
|
||||
'qualified_combinations' => $qualifiedCombinations
|
||||
]);
|
||||
}
|
||||
|
||||
// 2. dia_min ve dia_max eşleşmeleri
|
||||
Log::debug("[$logKey] Checking diameter criteria", [
|
||||
'odmm' => $rowData['odmm']
|
||||
]);
|
||||
|
||||
$diameterCheck = WelderTest::where("dia_min", "<=", $rowData['odmm'])
|
||||
->where(function($query) use($rowData) {
|
||||
$query->orWhere("dia_max", ">=", $rowData['odmm']);
|
||||
$query->orWhereNull("dia_max");
|
||||
$query->orWhere("dia_max", 0);
|
||||
})->exists();
|
||||
|
||||
Log::debug("[$logKey] Diameter check result", [
|
||||
'passed' => $diameterCheck
|
||||
]);
|
||||
|
||||
if (!$diameterCheck) {
|
||||
$failedCriteria[] = "Diameter range mismatch - No matching record found in WPQ Follow Up module. Please check dia_min and dia_max columns for diameter value: '{$rowData['odmm']}' mm";
|
||||
Log::debug("[$logKey] Diameter check FAILED", [
|
||||
'odmm' => $rowData['odmm']
|
||||
]);
|
||||
}
|
||||
|
||||
// 3. thk_min ve thk_max eşleşmeleri
|
||||
Log::debug("[$logKey] Checking thickness criteria", [
|
||||
'tck' => $rowData['tck']
|
||||
]);
|
||||
|
||||
$thicknessCheck = WelderTest::where("thk_min", "<=", $rowData['tck'])
|
||||
->where(function($query) use($rowData) {
|
||||
$query->orWhere("thk_max", ">=", $rowData['tck']);
|
||||
$query->orWhere("thk_max", 0);
|
||||
$query->orWhereNull("thk_max");
|
||||
})->exists();
|
||||
|
||||
Log::debug("[$logKey] Thickness check result", [
|
||||
'passed' => $thicknessCheck
|
||||
]);
|
||||
|
||||
if (!$thicknessCheck) {
|
||||
$failedCriteria[] = "Thickness range mismatch - No matching record found in WPQ Follow Up module. Please check thk_min and thk_max columns for thickness value: '{$rowData['tck']}' mm";
|
||||
Log::debug("[$logKey] Thickness check FAILED", [
|
||||
'tck' => $rowData['tck']
|
||||
]);
|
||||
}
|
||||
|
||||
// 4. approval_date eşleşmesi
|
||||
Log::debug("[$logKey] Checking approval date criteria", [
|
||||
'welding_date' => $rowData['welding_date']
|
||||
]);
|
||||
|
||||
$approvalDateCheck = WelderTest::whereDate("approval_date", "<=", $rowData['welding_date'])->exists();
|
||||
|
||||
Log::debug("[$logKey] Approval date check result", [
|
||||
'passed' => $approvalDateCheck
|
||||
]);
|
||||
|
||||
if (!$approvalDateCheck) {
|
||||
$failedCriteria[] = "Approval date mismatch - No matching record found in WPQ Follow Up module. Please check approval_date column for dates on or before: '{$rowData['welding_date']}'";
|
||||
Log::debug("[$logKey] Approval date check FAILED", [
|
||||
'welding_date' => $rowData['welding_date']
|
||||
]);
|
||||
}
|
||||
|
||||
// 5. welding_method eşleşmesi
|
||||
Log::debug("[$logKey] Checking welding method criteria", [
|
||||
'original' => $rowData['wm'],
|
||||
'reversed' => $reverseWeldingMethod
|
||||
]);
|
||||
|
||||
$weldingMethodCheck = WelderTest::where(function($query) use($rowData, $reverseWeldingMethod) {
|
||||
$query->orWhere("welding_method", $rowData['wm']);
|
||||
$query->orWhere("welding_method", $reverseWeldingMethod);
|
||||
})->exists();
|
||||
|
||||
Log::debug("[$logKey] Welding method check result", [
|
||||
'passed' => $weldingMethodCheck
|
||||
]);
|
||||
|
||||
if (!$weldingMethodCheck) {
|
||||
$failedCriteria[] = "Welding method mismatch - No matching record found in WPQ Follow Up module. Please check welding_method column for values: '{$rowData['wm']}' or '{$reverseWeldingMethod}'";
|
||||
Log::debug("[$logKey] Welding method check FAILED", [
|
||||
'original' => $rowData['wm'],
|
||||
'reversed' => $reverseWeldingMethod
|
||||
]);
|
||||
}
|
||||
|
||||
// Sonuçları kontrol et
|
||||
Log::debug("[$logKey] All criteria checks completed", [
|
||||
'total_failed' => count($failedCriteria),
|
||||
'failed_criteria' => $failedCriteria
|
||||
]);
|
||||
|
||||
if (empty($failedCriteria)) {
|
||||
Log::debug("[$logKey] All criteria passed successfully");
|
||||
} else {
|
||||
// Eşleşmeyen kriterleri listele
|
||||
// echo "Aşağıdaki kriterler eşleşmedi: " . implode(", ", $failedCriteria);
|
||||
$response['error'] = implode(", ", $failedCriteria);
|
||||
Log::debug("[$logKey] Criteria validation failed", [
|
||||
'errors' => $failedCriteria
|
||||
]);
|
||||
}
|
||||
|
||||
Log::debug("[$logKey] Starting database query to fetch matching welders");
|
||||
|
||||
// Step 1: Base query with join
|
||||
$baseQuery = WelderTest::leftJoin('naks_welders', function($join) {
|
||||
$join->on('naks_welders.naks_certificate_no', '=', 'welder_tests.naks_no');
|
||||
});
|
||||
|
||||
// Step 2: Material group criteria (with qualified combinations)
|
||||
Log::debug("[$logKey] Step 1: Testing with MATERIAL GROUP only (including qualified combinations)");
|
||||
$step1 = (clone $baseQuery)->where(function ($query) use ($qualifiedCombinations) {
|
||||
foreach ($qualifiedCombinations as $combo) {
|
||||
$query->orWhere(function($q) use ($combo) {
|
||||
$q->where("material_group_1", $combo['mat1'])
|
||||
->where("material_group_2", $combo['mat2']);
|
||||
});
|
||||
}
|
||||
})->count();
|
||||
Log::debug("[$logKey] Step 1 result: $step1 records found");
|
||||
|
||||
// Step 3: Add diameter criteria
|
||||
Log::debug("[$logKey] Step 2: Testing with MATERIAL GROUP + DIAMETER");
|
||||
$step2 = (clone $baseQuery)->where(function ($query) use ($qualifiedCombinations) {
|
||||
foreach ($qualifiedCombinations as $combo) {
|
||||
$query->orWhere(function($q) use ($combo) {
|
||||
$q->where("material_group_1", $combo['mat1'])
|
||||
->where("material_group_2", $combo['mat2']);
|
||||
});
|
||||
}
|
||||
})->where("dia_min", "<=", $rowData['odmm'])
|
||||
->where(function($query) use($rowData) {
|
||||
$query->orWhere("dia_max", ">=", $rowData['odmm']);
|
||||
$query->orWhereNull("dia_max");
|
||||
$query->orWhere("dia_max", 0);
|
||||
})->count();
|
||||
Log::debug("[$logKey] Step 2 result: $step2 records found (lost " . ($step1 - $step2) . " records)");
|
||||
|
||||
// Step 4: Add thickness criteria
|
||||
Log::debug("[$logKey] Step 3: Testing with MATERIAL GROUP + DIAMETER + THICKNESS");
|
||||
$step3 = (clone $baseQuery)->where(function ($query) use ($qualifiedCombinations) {
|
||||
foreach ($qualifiedCombinations as $combo) {
|
||||
$query->orWhere(function($q) use ($combo) {
|
||||
$q->where("material_group_1", $combo['mat1'])
|
||||
->where("material_group_2", $combo['mat2']);
|
||||
});
|
||||
}
|
||||
})->where("dia_min", "<=", $rowData['odmm'])
|
||||
->where(function($query) use($rowData) {
|
||||
$query->orWhere("dia_max", ">=", $rowData['odmm']);
|
||||
$query->orWhereNull("dia_max");
|
||||
$query->orWhere("dia_max", 0);
|
||||
})->where("thk_min", "<=", $rowData['tck'])
|
||||
->where(function($query) use($rowData) {
|
||||
$query->orWhere("thk_max", ">=", $rowData['tck']);
|
||||
$query->orWhere("thk_max", 0);
|
||||
$query->orWhereNull("thk_max");
|
||||
})->count();
|
||||
Log::debug("[$logKey] Step 3 result: $step3 records found (lost " . ($step2 - $step3) . " records)");
|
||||
|
||||
// Step 5: Add approval date criteria
|
||||
Log::debug("[$logKey] Step 4: Testing with MATERIAL GROUP + DIAMETER + THICKNESS + APPROVAL DATE");
|
||||
$step4 = (clone $baseQuery)->where(function ($query) use ($qualifiedCombinations) {
|
||||
foreach ($qualifiedCombinations as $combo) {
|
||||
$query->orWhere(function($q) use ($combo) {
|
||||
$q->where("material_group_1", $combo['mat1'])
|
||||
->where("material_group_2", $combo['mat2']);
|
||||
});
|
||||
}
|
||||
})->where("dia_min", "<=", $rowData['odmm'])
|
||||
->where(function($query) use($rowData) {
|
||||
$query->orWhere("dia_max", ">=", $rowData['odmm']);
|
||||
$query->orWhereNull("dia_max");
|
||||
$query->orWhere("dia_max", 0);
|
||||
})->where("thk_min", "<=", $rowData['tck'])
|
||||
->where(function($query) use($rowData) {
|
||||
$query->orWhere("thk_max", ">=", $rowData['tck']);
|
||||
$query->orWhere("thk_max", 0);
|
||||
$query->orWhereNull("thk_max");
|
||||
})->whereDate("approval_date", "<=", $rowData['welding_date'])->count();
|
||||
Log::debug("[$logKey] Step 4 result: $step4 records found (lost " . ($step3 - $step4) . " records)");
|
||||
|
||||
// Step 6: Add welding method criteria
|
||||
Log::debug("[$logKey] Step 5: Testing with ALL CRITERIA (including WELDING METHOD)");
|
||||
$step5 = (clone $baseQuery)->where(function ($query) use ($qualifiedCombinations) {
|
||||
foreach ($qualifiedCombinations as $combo) {
|
||||
$query->orWhere(function($q) use ($combo) {
|
||||
$q->where("material_group_1", $combo['mat1'])
|
||||
->where("material_group_2", $combo['mat2']);
|
||||
});
|
||||
}
|
||||
})->where("dia_min", "<=", $rowData['odmm'])
|
||||
->where(function($query) use($rowData) {
|
||||
$query->orWhere("dia_max", ">=", $rowData['odmm']);
|
||||
$query->orWhereNull("dia_max");
|
||||
$query->orWhere("dia_max", 0);
|
||||
})->where("thk_min", "<=", $rowData['tck'])
|
||||
->where(function($query) use($rowData) {
|
||||
$query->orWhere("thk_max", ">=", $rowData['tck']);
|
||||
$query->orWhere("thk_max", 0);
|
||||
$query->orWhereNull("thk_max");
|
||||
})->whereDate("approval_date", "<=", $rowData['welding_date'])
|
||||
->where(function($query) use($rowData, $weldingMethod, $reverseWeldingMethod){
|
||||
$query->orWhere("welding_method", $rowData['wm']);
|
||||
$query->orWhere("welding_method", $reverseWeldingMethod);
|
||||
})->count();
|
||||
Log::debug("[$logKey] Step 5 result: $step5 records found (lost " . ($step4 - $step5) . " records)");
|
||||
|
||||
// Final query with all criteria
|
||||
Log::debug("[$logKey] Final query: Executing with ALL CRITERIA + GROUP BY");
|
||||
$data = WelderTest::leftJoin('naks_welders', function($join) {
|
||||
$join->on('naks_welders.naks_certificate_no', '=', 'welder_tests.naks_no');
|
||||
})
|
||||
->where(function ($query) use ($qualifiedCombinations) {
|
||||
foreach ($qualifiedCombinations as $combo) {
|
||||
$query->orWhere(function($q) use ($combo) {
|
||||
$q->where("material_group_1", "like", "%{$combo['mat1']}%")
|
||||
->where("material_group_2", "like", "%{$combo['mat2']}%");
|
||||
});
|
||||
}
|
||||
})
|
||||
->where("dia_min", "<=", $rowData['odmm'])
|
||||
->where(function($query) use($rowData) {
|
||||
$query->orWhere("dia_max", ">=", $rowData['odmm']);
|
||||
$query->orWhereNull("dia_max");
|
||||
$query->orWhere("dia_max", 0);
|
||||
})
|
||||
->where("thk_min", "<=", $rowData['tck'])
|
||||
->where(function($query) use($rowData) {
|
||||
$query->orWhere("thk_max", ">=", $rowData['tck']);
|
||||
$query->orWhere("thk_max", 0);
|
||||
$query->orWhereNull("thk_max");
|
||||
})
|
||||
->whereDate("approval_date", "<=", $rowData['welding_date'])
|
||||
->where(function($query) use($rowData, $weldingMethod, $reverseWeldingMethod){
|
||||
$query->orWhere("welding_method", $rowData['wm']);
|
||||
$query->orWhere("welding_method", $reverseWeldingMethod);
|
||||
})
|
||||
->select('welder_tests.naks_id',
|
||||
'welder_tests.material_group_1',
|
||||
'welder_tests.material_group_2',
|
||||
'welder_tests.dia_min',
|
||||
'welder_tests.dia_max',
|
||||
'welder_tests.thk_min',
|
||||
'welder_tests.thk_max',
|
||||
'welder_tests.approval_date',
|
||||
'welder_tests.welding_method',
|
||||
'welder_tests.naks_validity',
|
||||
DB::raw('MIN(naks_welders.period_of_validity) as period_of_validity'))
|
||||
->groupBy("welder_tests.material_group_1",
|
||||
"welder_tests.material_group_2",
|
||||
"welder_tests.naks_id",
|
||||
"welder_tests.wpq_document_no",
|
||||
"welder_tests.welding_method",
|
||||
"welder_tests.naks_no")
|
||||
->get();
|
||||
|
||||
Log::debug("[$logKey] Database query completed", [
|
||||
'total_welders_found' => $data->count(),
|
||||
'step_summary' => [
|
||||
'step1_material_only' => $step1,
|
||||
'step2_+_diameter' => $step2,
|
||||
'step3_+_thickness' => $step3,
|
||||
'step4_+_approval_date' => $step4,
|
||||
'step5_+_welding_method' => $step5,
|
||||
'final_with_groupby' => $data->count()
|
||||
]
|
||||
]);
|
||||
|
||||
// Add step summary to response for UI display
|
||||
$response['step_summary'] = [
|
||||
'step1_material_only' => $step1,
|
||||
'step2_diameter' => $step2,
|
||||
'step3_thickness' => $step3,
|
||||
'step4_approval_date' => $step4,
|
||||
'step5_welding_method' => $step5,
|
||||
'final_with_groupby' => $data->count(),
|
||||
'criteria_details' => [
|
||||
'material_ru_1' => $rowData['ru_1'],
|
||||
'material_ru_2' => $rowData['ru_2'],
|
||||
'diameter_odmm' => $rowData['odmm'],
|
||||
'thickness_tck' => $rowData['tck'],
|
||||
'welding_date' => $rowData['welding_date'],
|
||||
'welding_method' => $rowData['wm'],
|
||||
'welding_method_reversed' => $reverseWeldingMethod
|
||||
]
|
||||
];
|
||||
|
||||
//dd($response);
|
||||
|
||||
|
||||
$today = Carbon::now();
|
||||
|
||||
Log::debug("[$logKey] Starting welder processing loop", [
|
||||
'today' => $today->toDateString(),
|
||||
'total_welders_to_process' => $data->count()
|
||||
]);
|
||||
|
||||
foreach($data AS $index => $d) {
|
||||
Log::debug("[$logKey] Processing welder #" . ($index + 1), [
|
||||
'naks_id' => $d->naks_id,
|
||||
'naks_validity' => $d->naks_validity,
|
||||
'period_of_validity' => $d->period_of_validity
|
||||
]);
|
||||
|
||||
$naksValidity = Carbon::createFromFormat('Y-m-d', $d->naks_validity);
|
||||
$remainingDays = $today->diffInDays($naksValidity, false);
|
||||
|
||||
$welder = $d->naks_id;
|
||||
|
||||
Log::debug("[$logKey] Checking welder assignment status for ISO", [
|
||||
'welder' => $welder,
|
||||
'iso_number' => $rowData['iso_number']
|
||||
]);
|
||||
|
||||
$isWorkThisIsoNumber = db("weld_logs")->where("welder_1", "like", "%$welder%")->where("iso_number", $rowData['iso_number'])->first();
|
||||
$isRealWorkThisIsoNumber = db("weld_logs")->where("real_welder_1", "like", "%$welder%")->where("iso_number", $rowData['iso_number'])->first();
|
||||
|
||||
if($isWorkThisIsoNumber) {
|
||||
$welder = "🟡 $welder";
|
||||
Log::debug("[$logKey] Welder already assigned to this ISO (yellow)", [
|
||||
'welder' => $d->naks_id
|
||||
]);
|
||||
}
|
||||
|
||||
if($isRealWorkThisIsoNumber) {
|
||||
$welder = "🔴 $welder";
|
||||
Log::debug("[$logKey] Welder is real worker for this ISO (red)", [
|
||||
'welder' => $d->naks_id
|
||||
]);
|
||||
}
|
||||
|
||||
if($remainingDays<10) {
|
||||
$welder = "❗$welder";
|
||||
Log::debug("[$logKey] Welder NAKS validity expiring soon", [
|
||||
'welder' => $d->naks_id,
|
||||
'remaining_days' => $remainingDays
|
||||
]);
|
||||
}
|
||||
|
||||
// Kaynak tarihinin geçerlilik kontrolü
|
||||
$weldingDate = Carbon::parse($rowData['welding_date']);
|
||||
$testWeldingDate = Carbon::parse($d->period_of_validity);
|
||||
$expiredDate = $testWeldingDate->copy()->addDays($welderQualitificationStatusExpiredDate);
|
||||
|
||||
Log::debug("[$logKey] Checking welding date validity", [
|
||||
'welder' => $d->naks_id,
|
||||
'row_welding_date' => $weldingDate->toDateString(),
|
||||
'test_welding_date' => $testWeldingDate->toDateString(),
|
||||
'expired_date' => $expiredDate->toDateString(),
|
||||
'qualification_expired_days' => $welderQualitificationStatusExpiredDate
|
||||
]);
|
||||
|
||||
if($weldingDate->greaterThan($expiredDate)) {
|
||||
$welder = "❌📅 $welder";
|
||||
Log::debug("[$logKey] Welding date validity check FAILED", [
|
||||
'welder' => $d->naks_id,
|
||||
'row_welding_date' => $weldingDate->toDateString(),
|
||||
'test_welding_date' => $testWeldingDate->toDateString()
|
||||
]);
|
||||
}
|
||||
|
||||
Log::debug("[$logKey] Final welder status", [
|
||||
'welder_id' => $d->naks_id,
|
||||
'final_display' => $welder,
|
||||
'row_welding_date' => $weldingDate->toDateString(),
|
||||
'test_welding_date' => $testWeldingDate->toDateString(),
|
||||
'expired_date' => $expiredDate->toDateString()
|
||||
]);
|
||||
|
||||
$response['welders'][] = $welder;
|
||||
}
|
||||
|
||||
Log::debug("[$logKey] Welder processing completed", [
|
||||
'total_welders_processed' => count($response['welders']),
|
||||
'response' => $response
|
||||
]);
|
||||
|
||||
Log::debug("[$logKey] ===== WELDER ASSIGNMENT AUTOCMPLETE END =====");
|
||||
?>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
use App\Models\WelderTest;
|
||||
$rowData = j(get("row"));
|
||||
|
||||
$weldingMethod = explode(",", $rowData['wm']);
|
||||
$reverseWeldingMethod = array_reverse($weldingMethod);
|
||||
$reverseWeldingMethod = implode(",", $reverseWeldingMethod);
|
||||
|
||||
$response = WelderTest::where(function ($query) use ($rowData) {
|
||||
$query->where("material_group_1", "like", "%{$rowData['ru_1']}%")
|
||||
->where("material_group_2", "like", "%{$rowData['ru_2']}%")
|
||||
->orWhere(function($query) use ($rowData) {
|
||||
$query->where("material_group_1", "like", "%{$rowData['ru_2']}%")
|
||||
->where("material_group_2", "like", "%{$rowData['ru_1']}%");
|
||||
});
|
||||
})
|
||||
->where("dia_min", "<=", $rowData['odmm'])
|
||||
->where(function($query) use($rowData) {
|
||||
$query->orWhere("dia_max", ">=", $rowData['odmm']);
|
||||
$query->orWhereNull("dia_max");
|
||||
$query->orWhere("dia_max", 0);
|
||||
})
|
||||
->where("thk_min", "<=", $rowData['tck'])
|
||||
->where(function($query) use($rowData) {
|
||||
$query->orWhere("thk_max", ">=", $rowData['tck']);
|
||||
$query->orWhere("thk_max", 0);
|
||||
$query->orWhereNull("thk_max");
|
||||
})
|
||||
->whereDate("approval_date", "<=", $rowData['welding_date'])
|
||||
->where(function($query) use($rowData, $weldingMethod, $reverseWeldingMethod){
|
||||
$query->orWhere("welding_method", $rowData['wm']);
|
||||
$query->orWhere("welding_method", $reverseWeldingMethod);
|
||||
})
|
||||
->where("naks_id", get("welder"))
|
||||
->first();
|
||||
|
||||
if($response) {
|
||||
$response->toArray();
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
$naksCertificates = explode(",", $rowData->naks_no);
|
||||
|
||||
$naksWelderProceses = db("naks_welders")
|
||||
->whereIn("naks_certificate_no", $naksCertificates)
|
||||
->get()?->pluck('process')
|
||||
->toArray();
|
||||
$weldingMethods = db("welding_methods")->whereIn("ru_short_name", $naksWelderProceses)->get();
|
||||
$response = [];
|
||||
foreach($weldingMethods AS $weldingMethod)
|
||||
{
|
||||
$response[] = "{$weldingMethod->ru_short_name}/{$weldingMethod->en_welding_number}";
|
||||
}
|
||||
|
||||
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
$query = db("naks_certificates")
|
||||
->whereIn("certificate_no", $certificateNo)
|
||||
->where("technology_category", $rowData->technology_category)
|
||||
->groupBy("welding_method")
|
||||
->get("welding_method")
|
||||
->pluck("welding_method")
|
||||
->toArray();
|
||||
|
||||
$weldingMethods = db("welding_methods")->whereIn("ru_short_name", $query)->select("ru_short_name", "en_welding_number")->get();
|
||||
$response = [];
|
||||
|
||||
foreach($weldingMethods AS $weldingMethod) {
|
||||
$response[] = $weldingMethod->ru_short_name . '/' . $weldingMethod->en_welding_number;
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
$pqr = db("prosedure_qualification_records")
|
||||
->where("pqr_no", $rowData->pqr_no)
|
||||
->first();
|
||||
|
||||
|
||||
|
||||
$date['start'] = $pqr->approved_date;
|
||||
|
||||
$response = $date;
|
||||
?>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
$response = db("w_p_s")
|
||||
->where("details", get("wps"))
|
||||
->first();
|
||||
?>
|
||||
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
if(!isset($rowData->material_group_gost) || $rowData->material_group_gost == "") {
|
||||
$response['error'] = "Please select material group";
|
||||
} elseif ($rowData->welding_method == "") {
|
||||
$response['error'] = "Please select welding method";
|
||||
} else {
|
||||
$group1 = isset($rowData->material_group_1) ? trim($rowData->material_group_1) : null;
|
||||
$group2 = (!empty($rowData->material_group_2)) ? trim($rowData->material_group_2) : $group1;
|
||||
|
||||
$naksCertificates = explode(",", $rowData->naks_no);
|
||||
$welding_methods = explode(",", $rowData->welding_method);
|
||||
|
||||
// Debug info collection
|
||||
$debug = [];
|
||||
$debug['input'] = [
|
||||
'material_group_1' => $rowData->material_group_1 ?? 'NULL',
|
||||
'material_group_2' => $rowData->material_group_2 ?? 'NULL',
|
||||
'group1_parsed' => $group1,
|
||||
'group2_parsed' => $group2,
|
||||
'welding_method' => $rowData->welding_method,
|
||||
'welding_methods_array' => $welding_methods,
|
||||
];
|
||||
|
||||
// Step 1: Check total WPS records with approved_date
|
||||
$totalApproved = db("w_p_s")->whereNotNull("approved_date")->count();
|
||||
$debug['step1_total_approved'] = $totalApproved;
|
||||
|
||||
// Step 2: Check material group filter only (group1 in col1, group2 in col2)
|
||||
$materialFilter1 = db("w_p_s")
|
||||
->whereNotNull("approved_date")
|
||||
->where("russian_standard_group_no_1", "like", "%" . $group1 . "%")
|
||||
->where("russian_standard_group_no_2", "like", "%" . $group2 . "%")
|
||||
->count();
|
||||
$debug['step2_material_filter_g1_g2'] = $materialFilter1;
|
||||
|
||||
// Step 3: Check material group filter only (group2 in col1, group1 in col2)
|
||||
$materialFilter2 = db("w_p_s")
|
||||
->whereNotNull("approved_date")
|
||||
->where("russian_standard_group_no_1", "like", "%" . $group2 . "%")
|
||||
->where("russian_standard_group_no_2", "like", "%" . $group1 . "%")
|
||||
->count();
|
||||
$debug['step3_material_filter_g2_g1'] = $materialFilter2;
|
||||
|
||||
// Step 4: Check combined material filter (OR condition)
|
||||
$materialFilterCombined = db("w_p_s")
|
||||
->whereNotNull("approved_date")
|
||||
->where(function ($query) use ($group1, $group2) {
|
||||
$query->where(function($q) use ($group1, $group2){
|
||||
$q->where("russian_standard_group_no_1", "like", "%" . $group1 . "%")
|
||||
->where("russian_standard_group_no_2", "like", "%" . $group2 . "%");
|
||||
})->orWhere(function($q) use ($group1, $group2){
|
||||
$q->where("russian_standard_group_no_1", "like", "%" . $group2 . "%")
|
||||
->where("russian_standard_group_no_2", "like", "%" . $group1 . "%");
|
||||
});
|
||||
})
|
||||
->count();
|
||||
$debug['step4_material_filter_combined'] = $materialFilterCombined;
|
||||
|
||||
// Step 5: Check welding method filter only
|
||||
$weldingFilter = db("w_p_s")
|
||||
->whereNotNull("approved_date")
|
||||
->where(function ($query) use ($welding_methods) {
|
||||
if(count($welding_methods) == 1) {
|
||||
foreach ($welding_methods as $method) {
|
||||
$query->where("welding_process", $method);
|
||||
}
|
||||
} else {
|
||||
foreach ($welding_methods as $method) {
|
||||
$query->where("welding_process", "like", "%$method%");
|
||||
}
|
||||
}
|
||||
})
|
||||
->count();
|
||||
$debug['step5_welding_filter_only'] = $weldingFilter;
|
||||
|
||||
// Step 6: Sample WPS records with the material groups to see actual values
|
||||
$sampleRecords = db("w_p_s")
|
||||
->whereNotNull("approved_date")
|
||||
->select("details", "russian_standard_group_no_1", "russian_standard_group_no_2", "welding_process")
|
||||
->limit(5)
|
||||
->get()
|
||||
->toArray();
|
||||
$debug['step6_sample_records'] = $sampleRecords;
|
||||
|
||||
// Step 7: Full query
|
||||
$results = db("w_p_s")
|
||||
->where(function ($query) use ($group1, $group2) {
|
||||
if($group1 && $group2) {
|
||||
$query->where(function($q) use ($group1, $group2){
|
||||
$q->where("russian_standard_group_no_1", "like", "%" . $group1 . "%")
|
||||
->where("russian_standard_group_no_2", "like", "%" . $group2 . "%");
|
||||
})->orWhere(function($q) use ($group1, $group2){
|
||||
$q->where("russian_standard_group_no_1", "like", "%" . $group2 . "%")
|
||||
->where("russian_standard_group_no_2", "like", "%" . $group1 . "%");
|
||||
});
|
||||
} else {
|
||||
$query->whereRaw("1 = 0");
|
||||
}
|
||||
})
|
||||
->where(function ($query) use ($welding_methods) {
|
||||
if(count($welding_methods) == 1)
|
||||
{
|
||||
foreach ($welding_methods as $method) {
|
||||
$query->where("welding_process", $method);
|
||||
}
|
||||
} else {
|
||||
foreach ($welding_methods as $method) {
|
||||
$query->where("welding_process", "like", "%$method%");
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
->whereNotNull("approved_date")
|
||||
->get("details")
|
||||
->pluck("details")
|
||||
->toArray();
|
||||
|
||||
$debug['step7_final_result_count'] = count($results);
|
||||
|
||||
if(empty($results)) {
|
||||
// Build detailed error message
|
||||
$errorMsg = "<b>No WPS found - Debug Report:</b><br><br>";
|
||||
$errorMsg .= "<b>Input Values:</b><br>";
|
||||
$errorMsg .= "- material_group_1: " . ($debug['input']['material_group_1']) . "<br>";
|
||||
$errorMsg .= "- material_group_2: " . ($debug['input']['material_group_2']) . "<br>";
|
||||
$errorMsg .= "- group1 (parsed): " . ($debug['input']['group1_parsed'] ?? 'NULL') . "<br>";
|
||||
$errorMsg .= "- group2 (parsed): " . ($debug['input']['group2_parsed'] ?? 'NULL') . "<br>";
|
||||
$errorMsg .= "- welding_method: " . ($debug['input']['welding_method']) . "<br>";
|
||||
$errorMsg .= "- welding_methods (array): " . implode(", ", $debug['input']['welding_methods_array']) . "<br><br>";
|
||||
|
||||
$errorMsg .= "<b>Filter Results (step by step):</b><br>";
|
||||
$errorMsg .= "1. Total approved WPS records: " . $debug['step1_total_approved'] . "<br>";
|
||||
$errorMsg .= "2. Material filter (group1 in col1, group2 in col2): " . $debug['step2_material_filter_g1_g2'] . "<br>";
|
||||
$errorMsg .= "3. Material filter (group2 in col1, group1 in col2): " . $debug['step3_material_filter_g2_g1'] . "<br>";
|
||||
$errorMsg .= "4. Material filter combined (OR): " . $debug['step4_material_filter_combined'] . "<br>";
|
||||
$errorMsg .= "5. Welding method filter only: " . $debug['step5_welding_filter_only'] . "<br>";
|
||||
$errorMsg .= "7. Final combined result: " . $debug['step7_final_result_count'] . "<br><br>";
|
||||
|
||||
$errorMsg .= "<b>Analysis:</b><br>";
|
||||
if($debug['step4_material_filter_combined'] == 0) {
|
||||
$errorMsg .= "❌ PROBLEM: Material group filter returns 0 results. Check if WPS table has records with russian_standard_group_no_1/2 matching '" . $group1 . "' and '" . $group2 . "'<br>";
|
||||
} elseif($debug['step5_welding_filter_only'] == 0) {
|
||||
$errorMsg .= "❌ PROBLEM: Welding method filter returns 0 results. Check if WPS table has records with welding_process matching '" . implode(", ", $welding_methods) . "'<br>";
|
||||
} else {
|
||||
$errorMsg .= "❌ PROBLEM: Both filters work individually but combined they return 0. No WPS has BOTH the material groups AND the welding method.<br>";
|
||||
}
|
||||
|
||||
$errorMsg .= "<br><b>Sample WPS Records (first 5):</b><br>";
|
||||
foreach($debug['step6_sample_records'] as $record) {
|
||||
$rec = (array)$record;
|
||||
$errorMsg .= "- " . ($rec['details'] ?? 'N/A') . " | RU1: " . ($rec['russian_standard_group_no_1'] ?? 'N/A') . " | RU2: " . ($rec['russian_standard_group_no_2'] ?? 'N/A') . " | Process: " . ($rec['welding_process'] ?? 'N/A') . "<br>";
|
||||
}
|
||||
|
||||
$response['error'] = $errorMsg;
|
||||
} else {
|
||||
$response = $results;
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,482 @@
|
||||
<?php
|
||||
|
||||
$outsideDiameter = $rowData->outside_diameter_1;
|
||||
$wallThickness = $rowData->wall_thickness_1;
|
||||
$run = true;
|
||||
if(is_null($wallThickness))
|
||||
{
|
||||
$errorText = "Wall Thickness 1 is required";
|
||||
$run = false;
|
||||
}
|
||||
if(is_null($outsideDiameter))
|
||||
{
|
||||
$errorText = "Outside Diameter 1 is required";
|
||||
$run = false;
|
||||
}
|
||||
|
||||
if($run)
|
||||
{
|
||||
$errorText = "No matching WPS found with the following parameters and filter results:<br><br>";
|
||||
$errorText .= "Input Parameters:<br>";
|
||||
$errorText .= "- Outside Diameter: $outsideDiameter<br>";
|
||||
$errorText .= "- Wall Thickness: $wallThickness<br>";
|
||||
$errorText .= "- Joint Type: {$rowData->type_of_welds}<br>";
|
||||
$errorText .= "- PWHT: {$rowData->pwht}<br>";
|
||||
$errorText .= "- Material Groups 1: {$rowData->ru_material_group_1}<br>";
|
||||
$errorText .= "- Material Groups 2: {$rowData->ru_material_group_2}<br><br>";
|
||||
|
||||
$errorText .= "Individual Filter Results:<br>";
|
||||
$errorText .= "- Records with Work Type 'PIPE': {debug_results['pipe_count']}<br>";
|
||||
$errorText .= "- Records matching Outside Diameter ($outsideDiameter): {debug_results['diameter_count']}<br>";
|
||||
$errorText .= "- Records matching Wall Thickness ($wallThickness): {debug_results['thickness_count']}<br>";
|
||||
$errorText .= "- Records matching Joint Type ({$rowData->type_of_welds}): {debug_results['joint_type_count']}<br>";
|
||||
$errorText .= "- Records matching PWHT requirements: {debug_results['pwht_count']}<br>";
|
||||
$errorText .= "- Records with matching PQR: {debug_results['pqr_count']}<br><br>";
|
||||
|
||||
$errorText .= "Combined Parameter Results:<br>";
|
||||
$errorText .= "Two Parameter Combinations:<br>";
|
||||
$errorText .= "- Outside Diameter + Wall Thickness: {debug_results['diameter_thickness_count']}<br>";
|
||||
$errorText .= "- Outside Diameter + Joint Type: {debug_results['diameter_joint_count']}<br>";
|
||||
$errorText .= "- Wall Thickness + Joint Type: {debug_results['thickness_joint_count']}<br><br>";
|
||||
|
||||
$errorText .= "Three Parameter Combinations:<br>";
|
||||
$errorText .= "- Outside Diameter + Wall Thickness + Joint Type: {debug_results['main_params_count']}<br>";
|
||||
$errorText .= "- Outside Diameter + Wall Thickness + PWHT: {debug_results['dimensions_pwht_count']}<br><br>";
|
||||
|
||||
$errorText .= "Four Parameter Combination:<br>";
|
||||
$errorText .= "- Outside Diameter + Wall Thickness + Joint Type + PWHT: {debug_results['four_params_count']}<br><br>";
|
||||
|
||||
$errorText .= "All Parameters Combined:<br>";
|
||||
$errorText .= "- All parameters (including PQR): {debug_results['all_params_count']}<br><br>";
|
||||
|
||||
$errorText .= "Analysis:<br>";
|
||||
$errorText .= "1. Check the individual filter results to see which single parameter is most restrictive.<br>";
|
||||
$errorText .= "2. Compare with combined results to understand how parameters interact.<br>";
|
||||
$errorText .= "3. The combination with the lowest count indicates where the restriction is coming from.<br>";
|
||||
$errorText .= "4. Compare four and five parameter results to see if PQR matching is the limiting factor.<br>";
|
||||
|
||||
$ruGroups1 = array_map('trim', explode(",", $rowData->ru_material_group_1));
|
||||
$ruGroups2 = array_map('trim', explode(",", $rowData->ru_material_group_2));
|
||||
$ruGroups = array_merge($ruGroups1, $ruGroups2);
|
||||
|
||||
$pqrs = db("prosedure_qualification_records");
|
||||
|
||||
foreach ($ruGroups1 as $ruGroup1) {
|
||||
foreach ($ruGroups2 as $ruGroup2) {
|
||||
// İkisi eşitse, sadece virgülle ayrılmış ve '+' içermeyen değerleri kontrol et
|
||||
|
||||
if ($ruGroup1 === $ruGroup2) {
|
||||
$errorText .= "The Ru Group same.";
|
||||
$pqrs->where(function($query) use ($ruGroup1) {
|
||||
$query->where("qualitication_group_of_parent_material", "like", "$ruGroup1")
|
||||
->where("qualitication_group_of_parent_material", "not like", "%+%")
|
||||
->orWhere("qualitication_group_of_parent_material", "like", "$ruGroup1,%")
|
||||
->orWhere("qualitication_group_of_parent_material", "like", "%,$ruGroup1")
|
||||
->orWhere("qualitication_group_of_parent_material", "like", "%,$ruGroup1,%");
|
||||
});
|
||||
} else {
|
||||
// '+' ile birleştirilmiş değerler için kontrol et
|
||||
$pqrs->orWhere(function($query) use ($ruGroup1, $ruGroup2) {
|
||||
$query->where("qualitication_group_of_parent_material", "like", "%$ruGroup1+$ruGroup2%")
|
||||
->orWhere("qualitication_group_of_parent_material", "like", "%$ruGroup2+$ruGroup1%");
|
||||
});
|
||||
|
||||
// Her iki grup için bağımsız koşulları kontrol et
|
||||
$pqrs->orWhere(function($subQuery) use ($ruGroup1, $ruGroup2) {
|
||||
$subQuery->where(function($q) use ($ruGroup1) {
|
||||
$q->where("qualitication_group_of_parent_material", "like", "%$ruGroup1%")
|
||||
->where("qualitication_group_of_parent_material", "not like", "%+$ruGroup1%")
|
||||
->where("qualitication_group_of_parent_material", "not like", "%$ruGroup1+%");
|
||||
})
|
||||
->where(function($q) use ($ruGroup2) {
|
||||
$q->where("qualitication_group_of_parent_material", "like", "%$ruGroup2%")
|
||||
->where("qualitication_group_of_parent_material", "not like", "%+$ruGroup2%")
|
||||
->where("qualitication_group_of_parent_material", "not like", "%$ruGroup2+%");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$pqrs = $pqrs->select("pqr_no")->get()->pluck("pqr_no")->toArray();
|
||||
try {
|
||||
$errorText .= "<br> Matching PQRs: " . implode(", ", $pqrs) . "<br>";
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (empty(array_filter($ruGroups, function($value) {
|
||||
return !empty($value); // Boş olmayan elemanları kontrol et
|
||||
}))) {
|
||||
$response['error'] = "The Ru Group must not be empty.";
|
||||
} else {
|
||||
$response = db("w_p_s")
|
||||
->whereNotNull("approved_date")
|
||||
/*
|
||||
->where(function($query) use ($ruGroups1, $ruGroups2) {
|
||||
foreach ($ruGroups1 as $key => $ruGroup1) {
|
||||
$ruGroup1 = trim($ruGroup1);
|
||||
|
||||
// Eğer ruGroup1 boşsa işlemi atla
|
||||
if ($ruGroup1 == "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ruGroups2'deki karşılık gelen değer
|
||||
$ruGroup2 = isset($ruGroups2[$key]) ? trim($ruGroups2[$key]) : null;
|
||||
|
||||
if ($ruGroup1 === $ruGroup2) {
|
||||
// Eğer eşitlerse yalnızca russian_standard_group_no_1 içinde arat
|
||||
$query->orWhere("russian_standard_group_no_1", "like", "%$ruGroup1%");
|
||||
} else {
|
||||
// Farklılarsa her iki sütunda birlikte arat
|
||||
$query->orWhere(function($subQuery) use ($ruGroup1, $ruGroup2) {
|
||||
$subQuery->where("russian_standard_group_no_1", "like", "%$ruGroup1%")
|
||||
->where("russian_standard_group_no_2", "like", "%$ruGroup2%");
|
||||
});
|
||||
|
||||
$query->orWhere(function($subQuery) use ($ruGroup1, $ruGroup2) {
|
||||
$subQuery->where("russian_standard_group_no_2", "like", "%$ruGroup1%")
|
||||
->where("russian_standard_group_no_1", "like", "%$ruGroup2%");
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
->where("min_thick", "<=", $wallThickness)
|
||||
|
||||
->where(function($query) use($wallThickness) {
|
||||
$query->orWhere("max_thick", 0);
|
||||
$query->orWhere("max_thick", ">=", $wallThickness);
|
||||
})
|
||||
->where("joint_type", $rowData->type_of_welds);
|
||||
|
||||
if(count($pqrs)>0) {
|
||||
$response = $response->whereIn("pqr_no", $pqrs);
|
||||
} else {
|
||||
$response = [];
|
||||
$materials = implode(",", array_merge($ruGroups1, $ruGroups2));
|
||||
$response['error'] = "No PQR data found for the selected qualification group of parent material.
|
||||
Ru Groups: $materials";
|
||||
return $response;
|
||||
}
|
||||
|
||||
if($rowData->pwht == "YES") {
|
||||
$response = $response
|
||||
->where(function($query) {
|
||||
$query->whereNotNull("pwht_temp_range")
|
||||
->where("pwht_temp_range", "!=", "0")
|
||||
->where("pwht_temp_range", "!=", "");
|
||||
})
|
||||
->where(function($query) {
|
||||
$query->whereNotNull("pwht_min_time")
|
||||
->where("pwht_min_time", "!=", "0")
|
||||
->where("pwht_min_time", "!=", "");
|
||||
});
|
||||
|
||||
} elseif($rowData->pwht == "NO") {
|
||||
$response = $response
|
||||
->where(function($query) {
|
||||
$query->whereNull("pwht_temp_range")
|
||||
->orWhere("pwht_temp_range", "0")
|
||||
->orWhere("pwht_temp_range", "");
|
||||
})
|
||||
->where(function($query) {
|
||||
$query->whereNull("pwht_min_time")
|
||||
->orWhere("pwht_min_time", "0")
|
||||
->orWhere("pwht_min_time", "");
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
if(strpos($rowData->piping_type ?? '', "Support") !== false) {
|
||||
$response = $response->where("work_type", "like", "%Support%");
|
||||
} else {
|
||||
$response = $response
|
||||
->where("work_type", "like", "%PIPE%")
|
||||
->where("min_outside_diameter", "<=", $outsideDiameter)
|
||||
->where(function($query) use($outsideDiameter) {
|
||||
$query->orWhere("max_outside_diameter", 0);
|
||||
$query->orWhere("max_outside_diameter", ">=", $outsideDiameter);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$response = $response->get(["details"])
|
||||
->pluck("details");
|
||||
|
||||
// Her bir filtreyi ayrı ayrı test edelim
|
||||
$debugResults = [];
|
||||
|
||||
// Temel sorgu
|
||||
$baseQuery = db("w_p_s")->whereNotNull("approved_date");
|
||||
|
||||
// PIPE kontrolü
|
||||
$pipeCheck = clone $baseQuery;
|
||||
$pipeCheck = $pipeCheck->where("work_type", "like", "%PIPE%")->count();
|
||||
if(strpos($rowData->piping_type ?? '', "Support") !== false) {
|
||||
$baseQuery = $baseQuery->where("work_type", "like", "%Support%");
|
||||
$debugResults['diameter_count'] = 0;
|
||||
} else {
|
||||
// Dış çap kontrolü
|
||||
$diameterCheck = clone $baseQuery;
|
||||
$diameterCheck = $diameterCheck->where("min_outside_diameter", "<=", $outsideDiameter)
|
||||
->where(function($query) use($outsideDiameter) {
|
||||
$query->orWhere("max_outside_diameter", 0)
|
||||
->orWhere("max_outside_diameter", ">=", $outsideDiameter);
|
||||
})->count();
|
||||
$debugResults['diameter_count'] = $diameterCheck;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$debugResults['pipe_count'] = $pipeCheck;
|
||||
|
||||
|
||||
|
||||
// Et kalınlığı kontrolü
|
||||
$thicknessCheck = clone $baseQuery;
|
||||
$thicknessCheck = $thicknessCheck->where("min_thick", "<=", $wallThickness)
|
||||
->where(function($query) use($wallThickness) {
|
||||
$query->orWhere("max_thick", 0)
|
||||
->orWhere("max_thick", ">=", $wallThickness);
|
||||
})->count();
|
||||
$debugResults['thickness_count'] = $thicknessCheck;
|
||||
// Kaynak tipi kontrolü
|
||||
$jointTypeCheck = clone $baseQuery;
|
||||
$jointTypeCheck = $jointTypeCheck->where("joint_type", $rowData->type_of_welds)->count();
|
||||
$debugResults['joint_type_count'] = $jointTypeCheck;
|
||||
|
||||
|
||||
// PWHT kontrolü
|
||||
$pwhtCheck = clone $baseQuery;
|
||||
if($rowData->pwht == "YES") {
|
||||
$pwhtCheck = $pwhtCheck->where(function($query) {
|
||||
$query->whereNotNull("pwht_temp_range")
|
||||
->where("pwht_temp_range", "!=", "0")
|
||||
->where("pwht_temp_range", "!=", "");
|
||||
})->where(function($query) {
|
||||
$query->whereNotNull("pwht_min_time")
|
||||
->where("pwht_min_time", "!=", "0")
|
||||
->where("pwht_min_time", "!=", "");
|
||||
});
|
||||
} elseif($rowData->pwht == "NO") {
|
||||
$pwhtCheck = $pwhtCheck->where(function($query) {
|
||||
$query->whereNull("pwht_temp_range")
|
||||
->orWhere("pwht_temp_range", "0")
|
||||
->orWhere("pwht_temp_range", "");
|
||||
})->where(function($query) {
|
||||
$query->whereNull("pwht_min_time")
|
||||
->orWhere("pwht_min_time", "0")
|
||||
->orWhere("pwht_min_time", "");
|
||||
});
|
||||
}
|
||||
$debugResults['pwht_count'] = $pwhtCheck->count();
|
||||
|
||||
// PQR kontrolü
|
||||
$debugResults['pqr_count'] = count($pqrs);
|
||||
|
||||
// İkili kombinasyonlar
|
||||
// Dış çap + Et kalınlığı
|
||||
$diameterThicknessCheck = clone $baseQuery;
|
||||
$diameterThicknessCheck = $diameterThicknessCheck
|
||||
->where("min_outside_diameter", "<=", $outsideDiameter)
|
||||
->where(function($query) use($outsideDiameter) {
|
||||
$query->orWhere("max_outside_diameter", 0)
|
||||
->orWhere("max_outside_diameter", ">=", $outsideDiameter);
|
||||
})
|
||||
->where("min_thick", "<=", $wallThickness)
|
||||
->where(function($query) use($wallThickness) {
|
||||
$query->orWhere("max_thick", 0)
|
||||
->orWhere("max_thick", ">=", $wallThickness);
|
||||
})->count();
|
||||
$debugResults['diameter_thickness_count'] = $diameterThicknessCheck;
|
||||
|
||||
// Dış çap + Kaynak tipi
|
||||
$diameterJointCheck = clone $baseQuery;
|
||||
$diameterJointCheck = $diameterJointCheck
|
||||
->where("min_outside_diameter", "<=", $outsideDiameter)
|
||||
->where(function($query) use($outsideDiameter) {
|
||||
$query->orWhere("max_outside_diameter", 0)
|
||||
->orWhere("max_outside_diameter", ">=", $outsideDiameter);
|
||||
})
|
||||
->where("joint_type", $rowData->type_of_welds)
|
||||
->count();
|
||||
$debugResults['diameter_joint_count'] = $diameterJointCheck;
|
||||
|
||||
// Et kalınlığı + Kaynak tipi
|
||||
$thicknessJointCheck = clone $baseQuery;
|
||||
$thicknessJointCheck = $thicknessJointCheck
|
||||
->where("min_thick", "<=", $wallThickness)
|
||||
->where(function($query) use($wallThickness) {
|
||||
$query->orWhere("max_thick", 0)
|
||||
->orWhere("max_thick", ">=", $wallThickness);
|
||||
})
|
||||
->where("joint_type", $rowData->type_of_welds)
|
||||
->count();
|
||||
$debugResults['thickness_joint_count'] = $thicknessJointCheck;
|
||||
|
||||
// Üçlü kombinasyonlar
|
||||
// Dış çap + Et kalınlığı + Kaynak tipi
|
||||
$mainParamsCheck = clone $baseQuery;
|
||||
$mainParamsCheck = $mainParamsCheck
|
||||
->where("min_outside_diameter", "<=", $outsideDiameter)
|
||||
->where(function($query) use($outsideDiameter) {
|
||||
$query->orWhere("max_outside_diameter", 0)
|
||||
->orWhere("max_outside_diameter", ">=", $outsideDiameter);
|
||||
})
|
||||
->where("min_thick", "<=", $wallThickness)
|
||||
->where(function($query) use($wallThickness) {
|
||||
$query->orWhere("max_thick", 0)
|
||||
->orWhere("max_thick", ">=", $wallThickness);
|
||||
})
|
||||
->where("joint_type", $rowData->type_of_welds)
|
||||
->count();
|
||||
$debugResults['main_params_count'] = $mainParamsCheck;
|
||||
|
||||
// Dış çap + Et kalınlığı + PWHT
|
||||
$dimensionsPwhtCheck = clone $baseQuery;
|
||||
$dimensionsPwhtCheck = $dimensionsPwhtCheck
|
||||
->where("min_outside_diameter", "<=", $outsideDiameter)
|
||||
->where(function($query) use($outsideDiameter) {
|
||||
$query->orWhere("max_outside_diameter", 0)
|
||||
->orWhere("max_outside_diameter", ">=", $outsideDiameter);
|
||||
})
|
||||
->where("min_thick", "<=", $wallThickness)
|
||||
->where(function($query) use($wallThickness) {
|
||||
$query->orWhere("max_thick", 0)
|
||||
->orWhere("max_thick", ">=", $wallThickness);
|
||||
});
|
||||
|
||||
if($rowData->pwht == "YES") {
|
||||
$dimensionsPwhtCheck = $dimensionsPwhtCheck
|
||||
->where(function($query) {
|
||||
$query->whereNotNull("pwht_temp_range")
|
||||
->where("pwht_temp_range", "!=", "0")
|
||||
->where("pwht_temp_range", "!=", "");
|
||||
})
|
||||
->where(function($query) {
|
||||
$query->whereNotNull("pwht_min_time")
|
||||
->where("pwht_min_time", "!=", "0")
|
||||
->where("pwht_min_time", "!=", "");
|
||||
});
|
||||
} elseif($rowData->pwht == "NO") {
|
||||
$dimensionsPwhtCheck = $dimensionsPwhtCheck
|
||||
->where(function($query) {
|
||||
$query->whereNull("pwht_temp_range")
|
||||
->orWhere("pwht_temp_range", "0")
|
||||
->orWhere("pwht_temp_range", "");
|
||||
})
|
||||
->where(function($query) {
|
||||
$query->whereNull("pwht_min_time")
|
||||
->orWhere("pwht_min_time", "0")
|
||||
->orWhere("pwht_min_time", "");
|
||||
});
|
||||
}
|
||||
$debugResults['dimensions_pwht_count'] = $dimensionsPwhtCheck->count();
|
||||
|
||||
// Dörtlü kombinasyonlar
|
||||
// Dış çap + Et kalınlığı + Kaynak tipi + PWHT
|
||||
$fourParamsCheck = clone $baseQuery;
|
||||
$fourParamsCheck = $fourParamsCheck
|
||||
->where("min_outside_diameter", "<=", $outsideDiameter)
|
||||
->where(function($query) use($outsideDiameter) {
|
||||
$query->orWhere("max_outside_diameter", 0)
|
||||
->orWhere("max_outside_diameter", ">=", $outsideDiameter);
|
||||
})
|
||||
->where("min_thick", "<=", $wallThickness)
|
||||
->where(function($query) use($wallThickness) {
|
||||
$query->orWhere("max_thick", 0)
|
||||
->orWhere("max_thick", ">=", $wallThickness);
|
||||
})
|
||||
->where("joint_type", $rowData->type_of_welds);
|
||||
|
||||
if($rowData->pwht == "YES") {
|
||||
$fourParamsCheck = $fourParamsCheck
|
||||
->where(function($query) {
|
||||
$query->whereNotNull("pwht_temp_range")
|
||||
->where("pwht_temp_range", "!=", "0")
|
||||
->where("pwht_temp_range", "!=", "");
|
||||
})
|
||||
->where(function($query) {
|
||||
$query->whereNotNull("pwht_min_time")
|
||||
->where("pwht_min_time", "!=", "0")
|
||||
->where("pwht_min_time", "!=", "");
|
||||
});
|
||||
} elseif($rowData->pwht == "NO") {
|
||||
$fourParamsCheck = $fourParamsCheck
|
||||
->where(function($query) {
|
||||
$query->whereNull("pwht_temp_range")
|
||||
->orWhere("pwht_temp_range", "0")
|
||||
->orWhere("pwht_temp_range", "");
|
||||
})
|
||||
->where(function($query) {
|
||||
$query->whereNull("pwht_min_time")
|
||||
->orWhere("pwht_min_time", "0")
|
||||
->orWhere("pwht_min_time", "");
|
||||
});
|
||||
}
|
||||
$debugResults['four_params_count'] = $fourParamsCheck->count();
|
||||
|
||||
// Beşli kombinasyon (Tüm parametreler)
|
||||
// Dış çap + Et kalınlığı + Kaynak tipi + PWHT + PQR
|
||||
$allParamsCheck = clone $fourParamsCheck;
|
||||
if(count($pqrs) > 0) {
|
||||
$allParamsCheck = $allParamsCheck->whereIn("pqr_no", $pqrs);
|
||||
}
|
||||
$debugResults['all_params_count'] = $allParamsCheck->count();
|
||||
|
||||
// Debug bilgilerini response'a ekleyelim
|
||||
if(count($response) == 0) {
|
||||
// Debug sonuçlarını errorText içindeki placeholder'lar ile değiştirelim
|
||||
$errorText = str_replace(
|
||||
[
|
||||
"{debug_results['pipe_count']}",
|
||||
"{debug_results['diameter_count']}",
|
||||
"{debug_results['thickness_count']}",
|
||||
"{debug_results['joint_type_count']}",
|
||||
"{debug_results['pwht_count']}",
|
||||
"{debug_results['pqr_count']}",
|
||||
"{debug_results['diameter_thickness_count']}",
|
||||
"{debug_results['diameter_joint_count']}",
|
||||
"{debug_results['thickness_joint_count']}",
|
||||
"{debug_results['main_params_count']}",
|
||||
"{debug_results['dimensions_pwht_count']}",
|
||||
"{debug_results['four_params_count']}",
|
||||
"{debug_results['all_params_count']}"
|
||||
],
|
||||
[
|
||||
$debugResults['pipe_count'],
|
||||
$debugResults['diameter_count'],
|
||||
$debugResults['thickness_count'],
|
||||
$debugResults['joint_type_count'],
|
||||
$debugResults['pwht_count'],
|
||||
$debugResults['pqr_count'],
|
||||
$debugResults['diameter_thickness_count'],
|
||||
$debugResults['diameter_joint_count'],
|
||||
$debugResults['thickness_joint_count'],
|
||||
$debugResults['main_params_count'],
|
||||
$debugResults['dimensions_pwht_count'],
|
||||
$debugResults['four_params_count'],
|
||||
$debugResults['all_params_count']
|
||||
],
|
||||
$errorText
|
||||
);
|
||||
$response['error'] = $errorText;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
$response['error'] = $errorText;
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
<?php
|
||||
$response = db("welder_tests")->select("naks_id")->groupBy("naks_id")->get()->pluck("naks_id");
|
||||
?>
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\StoreBeveelingRequest;
|
||||
use App\Http\Requests\UpdateBeveelingRequest;
|
||||
use App\Models\Beveeling;
|
||||
|
||||
class BeveelingController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\StoreBeveelingRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreBeveelingRequest $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Models\Beveeling $beveeling
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Beveeling $beveeling)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Beveeling $beveeling
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Beveeling $beveeling)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\UpdateBeveelingRequest $request
|
||||
* @param \App\Models\Beveeling $beveeling
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateBeveelingRequest $request, Beveeling $beveeling)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Beveeling $beveeling
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Beveeling $beveeling)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
// Procedure Qualification Records specific clone logic
|
||||
|
||||
if($table == "prosedure_qualification_records") {
|
||||
$data['pqr_no'] = $data['pqr_no'] . "-clone";
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
// WPS specific clone logic
|
||||
|
||||
if($table == "w_p_s") {
|
||||
$data['details'] = $data['details'] . "-clone";
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
// Weld Logs specific clone logic
|
||||
|
||||
if($table == "weld_logs") {
|
||||
unset($data['fit_up_date']);
|
||||
unset($data['welding_date']);
|
||||
unset($data['wps_no']);
|
||||
unset($data['wps_approval_date']);
|
||||
unset($data['welding_method']);
|
||||
unset($data['welding_materials_1']);
|
||||
unset($data['welding_materials_1_lot_no']);
|
||||
unset($data['welding_materials_1_certificate_no']);
|
||||
unset($data['welding_materials_2']);
|
||||
unset($data['welding_materials_2_lot_no']);
|
||||
unset($data['welding_materials_2_certificate_no']);
|
||||
unset($data['welding_materials_3']);
|
||||
unset($data['welding_materials_3_lot_no']);
|
||||
unset($data['welding_materials_3_certificate_no']);
|
||||
unset($data['real_welder_1']);
|
||||
unset($data['real_welder_2']);
|
||||
unset($data['mechanic_supervisor']);
|
||||
unset($data['mechanic_supervisor_control_date']);
|
||||
unset($data['welding_supervisor']);
|
||||
unset($data['welding_supervisor_control_date']);
|
||||
unset($data['welder_1']);
|
||||
unset($data['welder_2']);
|
||||
unset($data['certificate_no_1']);
|
||||
unset($data['wpq_report_1']);
|
||||
unset($data['certificate_no_2']);
|
||||
unset($data['wpq_report_2']);
|
||||
|
||||
unset($data['vt_request_no']);
|
||||
unset($data['vt_request_date']);
|
||||
unset($data['vt_report']);
|
||||
unset($data['vt_test_date']);
|
||||
unset($data['test_laboratory_vt']);
|
||||
unset($data['vt_result']);
|
||||
|
||||
unset($data['pt_request_no']);
|
||||
unset($data['pt_request_date']);
|
||||
unset($data['pt_report']);
|
||||
unset($data['pt_test_date']);
|
||||
unset($data['pt_test_lab']);
|
||||
unset($data['test_laboratory_pt']);
|
||||
|
||||
unset($data['rt_request_no']);
|
||||
unset($data['rt_request_date']);
|
||||
unset($data['rt_report']);
|
||||
unset($data['rt_test_date']);
|
||||
unset($data['test_laboratory_rt']);
|
||||
unset($data['rt_result']);
|
||||
|
||||
unset($data['ut_request_no']);
|
||||
unset($data['ut_type']);
|
||||
unset($data['ut_request_date']);
|
||||
unset($data['ut_report']);
|
||||
unset($data['ut_test_date']);
|
||||
unset($data['ut_test_lab']);
|
||||
unset($data['ut_result']);
|
||||
unset($data['mt_request_no']);
|
||||
unset($data['mt_request_date']);
|
||||
unset($data['mt_report']);
|
||||
unset($data['mt_test_date']);
|
||||
unset($data['test_laboratory_mt']);
|
||||
unset($data['mt_result']);
|
||||
unset($data['pmi_request_no']);
|
||||
unset($data['pmi_request_date']);
|
||||
unset($data['test_report_no']);
|
||||
unset($data['pmi_test_date']);
|
||||
unset($data['test_laboratory_pmi']);
|
||||
unset($data['pmi']);
|
||||
unset($data['pmi_result']);
|
||||
unset($data['pwht_request_no']);
|
||||
unset($data['pwht_request_date']);
|
||||
unset($data['pwht_date']);
|
||||
unset($data['pwht_diagram_number']);
|
||||
unset($data['diagram_number_pwht']);
|
||||
unset($data['no_of_pwht_report']);
|
||||
unset($data['test_laboratory_pwht']);
|
||||
unset($data['pwht_operator_name']);
|
||||
unset($data['pwht_operator_id']);
|
||||
unset($data['ht_request_no']);
|
||||
unset($data['ht_request_date']);
|
||||
unset($data['ht_test_report_no']);
|
||||
unset($data['ht_test_date']);
|
||||
unset($data['test_laboratory_ht']);
|
||||
unset($data['ht_result']);
|
||||
unset($data['ferrite_request_no']);
|
||||
unset($data['ferrite_request_date']);
|
||||
unset($data['ferrite_report_no']);
|
||||
unset($data['ferrite_test_date']);
|
||||
unset($data['test_laboratory_ferrite']);
|
||||
unset($data['ferrite_result']);
|
||||
|
||||
// Spool Area Release için ek unset işlemleri
|
||||
unset($data['clearance_no']);
|
||||
unset($data['clearance_date']);
|
||||
unset($data['ndt_release_date']);
|
||||
unset($data['register_paint_no']);
|
||||
unset($data['register_date']);
|
||||
unset($data['ndt_release_no']);
|
||||
unset($data['paint_release_date']);
|
||||
unset($data['paint_release_no']);
|
||||
unset($data['spool_zone']);
|
||||
unset($data['spool_ndt_check']);
|
||||
unset($data['spool_paint_check']);
|
||||
unset($data['spool_ndt_check_no']);
|
||||
unset($data['ndt_release_check']);
|
||||
unset($data['spool_ndt_check_date']);
|
||||
unset($data['paint_release_check']);
|
||||
unset($data['spool_remarks']);
|
||||
$data['spool_status'] = "Waiting";
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\StoreColorSystemRequest;
|
||||
use App\Http\Requests\UpdateColorSystemRequest;
|
||||
use App\Models\ColorSystem;
|
||||
|
||||
class ColorSystemController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\StoreColorSystemRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreColorSystemRequest $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Models\ColorSystem $colorSystem
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(ColorSystem $colorSystem)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\ColorSystem $colorSystem
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(ColorSystem $colorSystem)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\UpdateColorSystemRequest $request
|
||||
* @param \App\Models\ColorSystem $colorSystem
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateColorSystemRequest $request, ColorSystem $colorSystem)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\ColorSystem $colorSystem
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(ColorSystem $colorSystem)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\ColumnComment;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class ColumnCommentController extends Controller
|
||||
{
|
||||
/**
|
||||
* Save a new column comment
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function saveComment(Request $request)
|
||||
{
|
||||
// Validate the request
|
||||
$validated = $request->validate([
|
||||
'table_name' => 'required|string',
|
||||
'record_id' => 'required|numeric',
|
||||
'column_name' => 'required|string',
|
||||
'comment' => 'required|string',
|
||||
'column_value' => 'nullable|string',
|
||||
]);
|
||||
|
||||
try {
|
||||
// Create the comment
|
||||
$comment = ColumnComment::create([
|
||||
'table_name' => $validated['table_name'],
|
||||
'record_id' => $validated['record_id'],
|
||||
'column_name' => $validated['column_name'],
|
||||
'comment' => $validated['comment'],
|
||||
'column_value' => $validated['column_value'] ?? null,
|
||||
'user_id' => u()->id,
|
||||
'ip_address' => $request->ip(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Comment saved successfully',
|
||||
'comment' => $comment
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Failed to save comment: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\StoreColumnDescriptionRequest;
|
||||
use App\Http\Requests\UpdateColumnDescriptionRequest;
|
||||
use App\Models\ColumnDescription;
|
||||
|
||||
class ColumnDescriptionController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\StoreColumnDescriptionRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreColumnDescriptionRequest $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Models\ColumnDescription $columnDescription
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(ColumnDescription $columnDescription)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\ColumnDescription $columnDescription
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(ColumnDescription $columnDescription)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\UpdateColumnDescriptionRequest $request
|
||||
* @param \App\Models\ColumnDescription $columnDescription
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateColumnDescriptionRequest $request, ColumnDescription $columnDescription)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\ColumnDescription $columnDescription
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(ColumnDescription $columnDescription)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\StoreConstructionPaintLogRequest;
|
||||
use App\Http\Requests\UpdateConstructionPaintLogRequest;
|
||||
use App\Models\ConstructionPaintLog;
|
||||
|
||||
class ConstructionPaintLogController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\StoreConstructionPaintLogRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreConstructionPaintLogRequest $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Models\ConstructionPaintLog $constructionPaintLog
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(ConstructionPaintLog $constructionPaintLog)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\ConstructionPaintLog $constructionPaintLog
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(ConstructionPaintLog $constructionPaintLog)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\UpdateConstructionPaintLogRequest $request
|
||||
* @param \App\Models\ConstructionPaintLog $constructionPaintLog
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateConstructionPaintLogRequest $request, ConstructionPaintLog $constructionPaintLog)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\ConstructionPaintLog $constructionPaintLog
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(ConstructionPaintLog $constructionPaintLog)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
use App;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
|
||||
|
||||
use App\Contents;
|
||||
use Artesaos\SEOTools\Facades\SEOMeta;
|
||||
use Artesaos\SEOTools\Facades\OpenGraph;
|
||||
use Artesaos\SEOTools\Facades\TwitterCard;
|
||||
use Artesaos\SEOTools\Facades\JsonLd;
|
||||
// OR
|
||||
use Artesaos\SEOTools\Facades\SEOTools;
|
||||
|
||||
class ContentsController extends Controller
|
||||
{
|
||||
|
||||
public function index()
|
||||
{
|
||||
$url = env("APP_URL");
|
||||
$title = __('Web Site Title');
|
||||
|
||||
return view('index');
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function store(Request $request) {
|
||||
|
||||
$content = new Contents;
|
||||
$content -> slug = str_slug($request->title,"-");
|
||||
$content -> title = $request->title;
|
||||
$content -> html = $request -> html;
|
||||
$content -> uid = session("uid");
|
||||
$content -> json = $request;
|
||||
$content -> cover = $cover;
|
||||
$content -> pics = $pics;
|
||||
|
||||
}
|
||||
public function default_lang(Request $request, string $lang="tr",string $slug) {
|
||||
//App::setLocale($lang);
|
||||
return ContentsController::default($request,$slug,$lang);
|
||||
}
|
||||
public function default(Request $request, string $slug,string $lang="tr")
|
||||
{
|
||||
if($slug =="/" || $slug == "index" || $slug=="home" || $slug=="") {
|
||||
$view = "index";
|
||||
|
||||
} else {
|
||||
$view = "default";
|
||||
}
|
||||
|
||||
$c = null; // Contents::where('slug', $slug)->first();
|
||||
|
||||
if(!is_null($c) && isset($type)) {
|
||||
$c->type = $type;
|
||||
}
|
||||
$url = __('URL');
|
||||
|
||||
|
||||
try {
|
||||
$c->title = __($c->title);
|
||||
$c->html = __($c->html);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
$var = [
|
||||
'language' => [],
|
||||
'c' => "",
|
||||
'slug'=>$slug,
|
||||
'menu'=>[]
|
||||
];
|
||||
try{
|
||||
return view($slug,$var);
|
||||
} catch(\Exception $e) {
|
||||
if($c=="") {
|
||||
return abort(404);
|
||||
} else {
|
||||
$var = [
|
||||
'language' => $language,
|
||||
'c' => "",
|
||||
'slug'=>$slug,
|
||||
'menu'=>$menu
|
||||
];
|
||||
try{
|
||||
return view($c->slug,$var);
|
||||
} catch(\Exception $e) {
|
||||
try {
|
||||
return view(str_slug($c->type,"-"),$var);
|
||||
} catch (\Exception $e) {
|
||||
return view($view, $var);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\StoreCounterRequest;
|
||||
use App\Http\Requests\UpdateCounterRequest;
|
||||
use App\Models\Counter;
|
||||
|
||||
class CounterController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\StoreCounterRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreCounterRequest $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Models\Counter $counter
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Counter $counter)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Counter $counter
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Counter $counter)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\UpdateCounterRequest $request
|
||||
* @param \App\Models\Counter $counter
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateCounterRequest $request, Counter $counter)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Counter $counter
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Counter $counter)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\CurrentType;
|
||||
use App\Http\Requests\StoreCurrentTypeRequest;
|
||||
use App\Http\Requests\UpdateCurrentTypeRequest;
|
||||
|
||||
class CurrentTypeController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\StoreCurrentTypeRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreCurrentTypeRequest $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Models\CurrentType $currentType
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(CurrentType $currentType)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\CurrentType $currentType
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(CurrentType $currentType)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\UpdateCurrentTypeRequest $request
|
||||
* @param \App\Models\CurrentType $currentType
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateCurrentTypeRequest $request, CurrentType $currentType)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\CurrentType $currentType
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(CurrentType $currentType)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,664 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Models\DocumentManagerPermission;
|
||||
|
||||
class CustomElfinderController extends Controller
|
||||
{
|
||||
/**
|
||||
* Cache for access results to avoid repeated calculations
|
||||
*/
|
||||
private static $accessCache = [];
|
||||
|
||||
/**
|
||||
* Cached user instance
|
||||
*/
|
||||
private static $currentUser = null;
|
||||
|
||||
/**
|
||||
* Custom access control for Elfinder
|
||||
*
|
||||
* @param string $attr - Operation type (read, write, rm, etc.)
|
||||
* @param string $path - File/folder path
|
||||
* @param array $data - Additional data
|
||||
* @param object $volume - Volume object
|
||||
* @return bool - Whether access is allowed
|
||||
*/
|
||||
public static function access($attr, $path, $data, $volume)
|
||||
{
|
||||
// 1. Check access cache (Critical Optimization)
|
||||
// Using path + attr as key
|
||||
$cacheKey = $path . '#' . $attr;
|
||||
if (isset(self::$accessCache[$cacheKey])) {
|
||||
return self::$accessCache[$cacheKey];
|
||||
}
|
||||
|
||||
// 2. Get User (Cached)
|
||||
if (self::$currentUser === null) {
|
||||
self::$currentUser = Auth::user();
|
||||
}
|
||||
$user = self::$currentUser;
|
||||
|
||||
// If user is not authenticated, deny access
|
||||
if (!$user) {
|
||||
return self::$accessCache[$cacheKey] = false;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// GLOBAL EXCLUSION LIST (Hidden for EVERYONE - INCLUDING ADMINS)
|
||||
// ---------------------------------------------------------
|
||||
// Moved BEFORE admin check to ensure these are hidden for admins too
|
||||
|
||||
// Get folder name from path early (needed for checks)
|
||||
$folderName = self::getFolderNameFromPath($path);
|
||||
|
||||
// Default exclusions if setting is empty
|
||||
$defaultExclusions = [
|
||||
'.tmb',
|
||||
'cache',
|
||||
'register_creator_errors',
|
||||
'test',
|
||||
'NewFolder 1',
|
||||
'files',
|
||||
'document-templates',
|
||||
'Excel Form Templates',
|
||||
'Archive'
|
||||
];
|
||||
|
||||
// Get from settings - Cache this if possible or trust Laravel's config cache
|
||||
static $globalExcludedFolders = null;
|
||||
if ($globalExcludedFolders === null) {
|
||||
$settingsJson = setting('global_excluded_folders');
|
||||
$settingsExclusions = [];
|
||||
if (!empty($settingsJson)) {
|
||||
$settingsExclusions = json_decode($settingsJson, true);
|
||||
}
|
||||
$globalExcludedFolders = !empty($settingsExclusions) ? $settingsExclusions : $defaultExclusions;
|
||||
}
|
||||
|
||||
// Check if it is a root folder (no slashes in normalized path)
|
||||
$isRootFolder = strpos($folderName, '/') === false;
|
||||
|
||||
if ($isRootFolder && in_array($folderName, $globalExcludedFolders)) {
|
||||
// Hide from list
|
||||
if ($attr === 'hidden') {
|
||||
return self::$accessCache[$cacheKey] = true;
|
||||
}
|
||||
// Block read access to effectively hide contents too
|
||||
if ($attr === 'read') {
|
||||
return self::$accessCache[$cacheKey] = false;
|
||||
}
|
||||
}
|
||||
// ---------------------------------------------------------
|
||||
|
||||
// 3. Admin Optimization (Fast Track)
|
||||
if ($user->level == "Admin") {
|
||||
// Validate path for security (fast check)
|
||||
if (strpos($path, '..') !== false) {
|
||||
return self::$accessCache[$cacheKey] = false;
|
||||
}
|
||||
|
||||
// Special handling for operations that need false (NOT locked/hidden)
|
||||
if ($attr === 'hidden' || $attr === 'locked') {
|
||||
return self::$accessCache[$cacheKey] = false; // false means NOT hidden/locked (writable/deletable)
|
||||
}
|
||||
|
||||
return self::$accessCache[$cacheKey] = true; // true means ALLOW operation (read/write/rm/etc)
|
||||
}
|
||||
|
||||
// Validate path for security (Normal users)
|
||||
if (!self::validatePath($path)) {
|
||||
Log::warning("Path validation failed", ['path' => $path, 'user' => $user->level]);
|
||||
return self::$accessCache[$cacheKey] = false;
|
||||
}
|
||||
|
||||
// folderName already retrieved above for global exclusion check
|
||||
// $folderName = self::getFolderNameFromPath($path);
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// GLOBAL EXCLUSION LIST (Moved to top)
|
||||
// ---------------------------------------------------------
|
||||
|
||||
// For non-admin users, handle system folders based on operation
|
||||
if (self::isSystemFolder($folderName)) {
|
||||
// For these operations, explicitly hide/lock system folders
|
||||
if (in_array($attr, ['read', 'write', 'upload', 'mkdir', 'mkfile', 'rename', 'copy', 'move', 'rm', 'edit'])) {
|
||||
return self::$accessCache[$cacheKey] = false; // Block these operations
|
||||
}
|
||||
|
||||
// For hidden check, return true to hide
|
||||
if ($attr === 'hidden') {
|
||||
return self::$accessCache[$cacheKey] = true; // Hide system folders from non-admin
|
||||
}
|
||||
|
||||
// For locked check, return true to lock
|
||||
if ($attr === 'locked') {
|
||||
return self::$accessCache[$cacheKey] = true; // Lock system folders for non-admin
|
||||
}
|
||||
|
||||
// For other operations, return null (use default behavior)
|
||||
return self::$accessCache[$cacheKey] = null;
|
||||
}
|
||||
|
||||
// For other users, implement basic permission checks
|
||||
$module = "document-manager";
|
||||
|
||||
// Check basic module permission first
|
||||
// Cache basic permissions
|
||||
static $modulePermissions = [];
|
||||
if (!isset($modulePermissions[$user->level])) {
|
||||
$modulePermissions[$user->level] = [
|
||||
'read' => isAuth($module, "read"),
|
||||
'write' => isAuth($module, "write"),
|
||||
'modify' => isAuth($module, "modify")
|
||||
];
|
||||
}
|
||||
|
||||
$hasModuleRead = $modulePermissions[$user->level]['read'];
|
||||
$hasModuleWrite = $modulePermissions[$user->level]['write'];
|
||||
$hasModuleModify = $modulePermissions[$user->level]['modify'];
|
||||
|
||||
/*
|
||||
// DEBUG: Check if PTO user has basic permissions
|
||||
if ($user->level === 'Manager (PTO)') {
|
||||
error_log("PTO User Basic Permissions - Read: " . ($hasModuleRead ? 'YES' : 'NO') . ", Write: " . ($hasModuleWrite ? 'YES' : 'NO') . ", Modify: " . ($hasModuleModify ? 'YES' : 'NO'));
|
||||
}
|
||||
*/
|
||||
|
||||
// Debug logging - enabled for testing
|
||||
/*
|
||||
Log::info("Elfinder Access Check", [
|
||||
'user_level' => $user->level,
|
||||
'user_id' => $user->id ?? 'unknown',
|
||||
'attr' => $attr,
|
||||
'path' => $path,
|
||||
'folder_name' => $folderName,
|
||||
'module' => $module,
|
||||
'permission_separation' => 'write_edit_separated',
|
||||
'is_dir' => is_dir($path),
|
||||
'is_file' => is_file($path),
|
||||
'path_exists' => file_exists($path),
|
||||
'has_module_read' => $hasModuleRead,
|
||||
'has_module_write' => $hasModuleWrite,
|
||||
'has_module_modify' => $hasModuleModify
|
||||
]);
|
||||
*/
|
||||
|
||||
switch($attr) {
|
||||
case 'read':
|
||||
// For folders, check if user should see this folder at all
|
||||
if (is_dir($path)) {
|
||||
// First check if this is a system folder for non-admin users
|
||||
if ($user->level !== "Admin" && self::isSystemFolder($folderName)) {
|
||||
return self::$accessCache[$cacheKey] = false; // Block system folders from non-admin
|
||||
}
|
||||
|
||||
return self::$accessCache[$cacheKey] = self::checkFolderVisibility($user, $folderName, $module);
|
||||
} else {
|
||||
// For files, check if parent folder is system folder for non-admin
|
||||
if ($user->level !== "Admin" && self::isSystemFolder($folderName)) {
|
||||
return self::$accessCache[$cacheKey] = false; // Block files in system folders from non-admin
|
||||
}
|
||||
|
||||
// For files, check read permission
|
||||
return self::checkFolderReadPermission($user, $folderName, $module);
|
||||
}
|
||||
|
||||
case 'write':
|
||||
case 'upload':
|
||||
case 'mkdir':
|
||||
case 'mkfile':
|
||||
case 'rename':
|
||||
case 'copy':
|
||||
case 'move':
|
||||
// Check if user has write permission for this specific folder
|
||||
$writeAuth = self::checkFolderWritePermission($user, $folderName, $module);
|
||||
// Log::info("Write permission check", ['result' => $writeAuth, 'folder' => $folderName, 'operation' => $attr]);
|
||||
return self::$accessCache[$cacheKey] = $writeAuth;
|
||||
|
||||
case 'edit':
|
||||
// Special handling for edit operations - check file type and edit permission
|
||||
$editAuth = self::checkFileEditPermission($user, $path, $module);
|
||||
// Log::info("Edit permission check", ['result' => $editAuth, 'path' => $path, 'operation' => $attr]);
|
||||
return self::$accessCache[$cacheKey] = $editAuth;
|
||||
|
||||
case 'rm':
|
||||
// Check if user has delete permission for this specific folder
|
||||
$rmAuth = self::checkFolderDeletePermission($user, $folderName, $module);
|
||||
// Log::info("Remove permission check", ['result' => $rmAuth, 'folder' => $folderName]);
|
||||
|
||||
// Additional protection for critical files
|
||||
if (self::isCriticalFile($path)) {
|
||||
// Log::info("Critical file protection - delete blocked", ['path' => $path]);
|
||||
return self::$accessCache[$cacheKey] = false;
|
||||
}
|
||||
|
||||
return self::$accessCache[$cacheKey] = $rmAuth;
|
||||
|
||||
case 'hidden':
|
||||
// Check if folder should be hidden from user
|
||||
// For non-admin users, hide system folders
|
||||
if ($user->level !== "Admin") {
|
||||
if (self::isSystemFolder($folderName)) {
|
||||
return self::$accessCache[$cacheKey] = true; // Hide system folders from non-admin
|
||||
}
|
||||
}
|
||||
|
||||
// Check general visibility
|
||||
return self::$accessCache[$cacheKey] = !self::checkFolderVisibility($user, $folderName, $module);
|
||||
|
||||
default:
|
||||
// For other operations, return null for default behavior
|
||||
/*
|
||||
Log::info("Default permission check", [
|
||||
'attr' => $attr,
|
||||
'folder' => $folderName,
|
||||
'user_level' => $user->level
|
||||
]);
|
||||
*/
|
||||
return self::$accessCache[$cacheKey] = null; // Use Elfinder's default behavior
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache for folder names to improve performance
|
||||
*/
|
||||
private static $folderNameCache = [];
|
||||
|
||||
/**
|
||||
* Get folder name from path with improved path normalization (supports subfolders)
|
||||
*/
|
||||
private static function getFolderNameFromPath($path)
|
||||
{
|
||||
// Check cache first
|
||||
if (isset(self::$folderNameCache[$path])) {
|
||||
return self::$folderNameCache[$path];
|
||||
}
|
||||
|
||||
$originalPath = $path;
|
||||
|
||||
// Normalize path separators
|
||||
$path = str_replace('\\', '/', $path);
|
||||
|
||||
// Remove common path prefixes (case-insensitive)
|
||||
$path = preg_replace('#^.*?/storage/documents/?#i', '', $path);
|
||||
$path = preg_replace('#^.*?/storage/office-server/?#i', '', $path);
|
||||
$path = preg_replace('#^.*?/public/storage/documents/?#i', '', $path);
|
||||
$path = preg_replace('#^.*?/public/storage/office-server/?#i', '', $path);
|
||||
$path = preg_replace('#^.*?/Applications/MAMP/htdocs/stellar/public/storage/documents/?#i', '', $path);
|
||||
$path = preg_replace('#^.*?/Applications/MAMP/htdocs/stellar/public/storage/office-server/?#i', '', $path);
|
||||
|
||||
// Additional path patterns for Elfinder
|
||||
$path = preg_replace('#^.*?/storage/documents$#i', '', $path);
|
||||
$path = preg_replace('#^.*?/storage/documents/$#i', '', $path);
|
||||
|
||||
// Clean up any remaining leading/trailing slashes
|
||||
$path = trim($path, '/');
|
||||
|
||||
// For subfolder support, return the full relative path instead of just first folder
|
||||
// This allows us to check permissions for specific subfolders
|
||||
$folderName = $path;
|
||||
|
||||
// Log path processing for debugging
|
||||
/*
|
||||
Log::info("Path processing", [
|
||||
'original_path' => $originalPath,
|
||||
'normalized_path' => $path,
|
||||
'folder_name' => $folderName,
|
||||
'has_slashes' => strpos($folderName, '/') !== false,
|
||||
'is_empty' => empty($folderName)
|
||||
]);
|
||||
*/
|
||||
|
||||
self::$folderNameCache[$originalPath] = $folderName;
|
||||
|
||||
return $folderName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if folder should be visible to user (for folder listing)
|
||||
*/
|
||||
private static function checkFolderVisibility($user, $folderName, $module)
|
||||
{
|
||||
// Root path - always visible if user has basic read permission
|
||||
if (empty($folderName)) {
|
||||
return isAuth($module, "read");
|
||||
}
|
||||
|
||||
// Office Server files - only Admin can see
|
||||
if (self::isOfficeServerPath($folderName)) {
|
||||
return $user->level == "Admin";
|
||||
}
|
||||
|
||||
// Check if this is a system folder - only Admin can see
|
||||
if (self::isSystemFolder($folderName)) {
|
||||
return $user->level == "Admin";
|
||||
}
|
||||
|
||||
// Check if user has any permission for this folder (read, write, or edit)
|
||||
// This includes both explicit permissions and inherited permissions
|
||||
$hasReadPermission = self::checkFolderReadPermission($user, $folderName, $module);
|
||||
$hasWritePermission = self::checkFolderWritePermission($user, $folderName, $module);
|
||||
$hasEditPermission = self::checkFolderEditPermission($user, $folderName, $module);
|
||||
|
||||
return $hasReadPermission || $hasWritePermission || $hasEditPermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has read permission for specific folder
|
||||
*/
|
||||
private static function checkFolderReadPermission($user, $folderName, $module)
|
||||
{
|
||||
// Root path - allow access if user has basic read permission
|
||||
if (empty($folderName)) {
|
||||
return isAuth($module, "read");
|
||||
}
|
||||
|
||||
// Office Server files - only Admin can read
|
||||
if (self::isOfficeServerPath($folderName)) {
|
||||
return $user->level == "Admin";
|
||||
}
|
||||
|
||||
// Check dynamic permission using cached/recursive check
|
||||
return self::checkDynamicPermission($user->level, $folderName, 'read');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has write permission for specific folder
|
||||
* Write permission covers: upload, create, rename, copy, move, delete
|
||||
*/
|
||||
private static function checkFolderWritePermission($user, $folderName, $module)
|
||||
{
|
||||
// Office Server files - only Admin can write
|
||||
if (self::isOfficeServerPath($folderName)) {
|
||||
return $user->level == "Admin";
|
||||
}
|
||||
|
||||
// Check dynamic permission using cached/recursive check
|
||||
return self::checkDynamicPermission($user->level, $folderName, 'write');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has edit permission for specific folder
|
||||
* Edit permission covers: edit file content only (not file operations)
|
||||
*/
|
||||
private static function checkFolderEditPermission($user, $folderName, $module)
|
||||
{
|
||||
// Office Server files - only Admin can edit
|
||||
if (self::isOfficeServerPath($folderName)) {
|
||||
return $user->level == "Admin";
|
||||
}
|
||||
|
||||
// Check dynamic permission using cached/recursive check
|
||||
return self::checkDynamicPermission($user->level, $folderName, 'edit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has delete permission for specific folder
|
||||
*/
|
||||
private static function checkFolderDeletePermission($user, $folderName, $module)
|
||||
{
|
||||
// Office Server files - only Admin can delete
|
||||
if (self::isOfficeServerPath($folderName)) {
|
||||
return $user->level == "Admin";
|
||||
}
|
||||
|
||||
// Delete permission uses write permission (write includes delete operations)
|
||||
return self::checkFolderWritePermission($user, $folderName, $module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user can edit specific file types based on edit permission
|
||||
* Edit permission covers: edit file content only (not file operations)
|
||||
*/
|
||||
private static function checkFileEditPermission($user, $path, $module)
|
||||
{
|
||||
// Get file extension
|
||||
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
|
||||
|
||||
// Define editable file types
|
||||
$editableFileTypes = ['pdf', 'xlsx', 'xlsb', 'csv', 'doc', 'docx', 'txt'];
|
||||
|
||||
// Check if file type is editable
|
||||
if (!in_array($extension, $editableFileTypes)) {
|
||||
Log::info("File type not editable", ['extension' => $extension, 'path' => $path]);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check folder-based permissions for edit
|
||||
$folderName = self::getFolderNameFromPath($path);
|
||||
|
||||
// Check dynamic permission using cached/recursive check
|
||||
return self::checkDynamicPermission($user->level, $folderName, 'edit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Static cache for permissions during a single request
|
||||
* Structure: ['UserLevel' => ['folder/path' => ['read' => bool, 'write' => bool]]]
|
||||
*/
|
||||
private static $permissionsCache = [];
|
||||
|
||||
/**
|
||||
* Load all permissions for a user level into static cache
|
||||
*/
|
||||
private static function loadPermissionsIntoCache($userLevel)
|
||||
{
|
||||
if (isset(self::$permissionsCache[$userLevel])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get all permissions from Model (which uses Redis/File Cache)
|
||||
// This returns a collection grouped by folder_path
|
||||
$rawPermissions = \App\Models\DocumentManagerPermission::getUserLevelPermissions($userLevel);
|
||||
|
||||
$formatted = [];
|
||||
foreach ($rawPermissions as $path => $permissions) {
|
||||
$formatted[$path] = [];
|
||||
foreach ($permissions as $perm) {
|
||||
// Store the boolean value directly
|
||||
$formatted[$path][$perm->permission_type] = $perm->is_allowed;
|
||||
}
|
||||
}
|
||||
|
||||
self::$permissionsCache[$userLevel] = $formatted;
|
||||
|
||||
Log::info("Permissions loaded into static cache", [
|
||||
'user_level' => $userLevel,
|
||||
'folder_count' => count($formatted)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check dynamic permission using cached data with inheritance
|
||||
*/
|
||||
private static function checkDynamicPermission($userLevel, $folderName, $permissionType)
|
||||
{
|
||||
// Ensure cache is loaded
|
||||
self::loadPermissionsIntoCache($userLevel);
|
||||
|
||||
// 1. Check for explicit permission on this folder
|
||||
if (isset(self::$permissionsCache[$userLevel][$folderName])) {
|
||||
$folderPerms = self::$permissionsCache[$userLevel][$folderName];
|
||||
|
||||
if (isset($folderPerms[$permissionType])) {
|
||||
// Explicit permission found (either true or false)
|
||||
// Return exactly what is set, do not inherit if explicitly set
|
||||
return $folderPerms[$permissionType];
|
||||
}
|
||||
}
|
||||
|
||||
// 2. If no explicit permission, check parent folder inheritance
|
||||
// BUT ONLY for subfolders, not for main folders
|
||||
$parentFolder = self::getParentFolder($folderName);
|
||||
if ($parentFolder && $parentFolder !== $folderName && strpos($folderName, '/') !== false) {
|
||||
$inherited = self::checkDynamicPermission($userLevel, $parentFolder, $permissionType);
|
||||
if ($inherited) {
|
||||
// Log only if allowed via inheritance (to reduce noise)
|
||||
// Log::info("Permission granted via inheritance", ['folder' => $folderName, 'parent' => $parentFolder, 'type' => $permissionType]);
|
||||
}
|
||||
return $inherited;
|
||||
}
|
||||
|
||||
// 3. No explicit permission and no parent - default deny
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent folder from a folder path
|
||||
*/
|
||||
private static function getParentFolder($folderPath)
|
||||
{
|
||||
// Remove trailing slash if exists
|
||||
$folderPath = rtrim($folderPath, '/');
|
||||
|
||||
// Split by slash
|
||||
$parts = explode('/', $folderPath);
|
||||
|
||||
// If only one part, no parent
|
||||
if (count($parts) <= 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Remove last part to get parent
|
||||
array_pop($parts);
|
||||
return implode('/', $parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if file is a critical system file that should be protected
|
||||
*/
|
||||
private static function isCriticalFile($path)
|
||||
{
|
||||
$fileName = basename($path);
|
||||
$criticalFiles = [
|
||||
'index.php',
|
||||
'config.php',
|
||||
'.htaccess',
|
||||
'web.config',
|
||||
'robots.txt',
|
||||
'sitemap.xml',
|
||||
'.env',
|
||||
'composer.json',
|
||||
'composer.lock',
|
||||
'package.json',
|
||||
'yarn.lock'
|
||||
];
|
||||
|
||||
return in_array(strtolower($fileName), array_map('strtolower', $criticalFiles));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate file path for security
|
||||
*/
|
||||
private static function validatePath($path)
|
||||
{
|
||||
// Check for path traversal attempts
|
||||
if (strpos($path, '..') !== false || strpos($path, '//') !== false) {
|
||||
Log::warning("Path traversal attempt detected", ['path' => $path]);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for suspicious file extensions
|
||||
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
|
||||
$dangerousExtensions = ['php', 'php3', 'php4', 'php5', 'phtml', 'exe', 'bat', 'cmd', 'sh', 'js'];
|
||||
|
||||
if (in_array($extension, $dangerousExtensions)) {
|
||||
Log::warning("Dangerous file extension detected", ['path' => $path, 'extension' => $extension]);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file size in human readable format
|
||||
*/
|
||||
private static function formatFileSize($bytes)
|
||||
{
|
||||
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||
|
||||
for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
|
||||
$bytes /= 1024;
|
||||
}
|
||||
|
||||
return round($bytes, 2) . ' ' . $units[$i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if path is in Office Server directory
|
||||
*/
|
||||
private static function isOfficeServerPath($folderName)
|
||||
{
|
||||
// Check if the path contains office-server
|
||||
return strpos($folderName, 'office-server') !== false ||
|
||||
strpos($folderName, 'Office_Server') !== false ||
|
||||
strpos($folderName, 'office_server') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if path is a network drive path
|
||||
*/
|
||||
private static function isNetworkDrivePath($path)
|
||||
{
|
||||
// Check for network drive patterns
|
||||
$networkPatterns = [
|
||||
'/^\\\\/', // Windows UNC path
|
||||
'/^\/\/[^\/]+/', // Unix network path
|
||||
'/^smb:\/\//', // SMB protocol
|
||||
'/^cifs:\/\//', // CIFS protocol
|
||||
];
|
||||
|
||||
foreach ($networkPatterns as $pattern) {
|
||||
if (preg_match($pattern, $path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if folder is a system folder (only visible to Admin)
|
||||
* System folders are defined in config/document-folders.php
|
||||
* Uses static cache for performance optimization
|
||||
*/
|
||||
private static function isSystemFolder($folderName)
|
||||
{
|
||||
// Static cache to avoid repeated config reads
|
||||
static $exactMatches = null;
|
||||
static $regexPatterns = null;
|
||||
static $cache = [];
|
||||
|
||||
// Return cached result if available
|
||||
if (isset($cache[$folderName])) {
|
||||
return $cache[$folderName];
|
||||
}
|
||||
|
||||
// Load patterns once
|
||||
if ($exactMatches === null) {
|
||||
$exactMatches = config('document-folders.system_patterns.exact', []);
|
||||
$regexPatterns = config('document-folders.system_patterns.regex', []);
|
||||
}
|
||||
|
||||
// Check exact matches first (faster)
|
||||
if (in_array($folderName, $exactMatches)) {
|
||||
$cache[$folderName] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check regex patterns
|
||||
foreach ($regexPatterns as $pattern) {
|
||||
if (preg_match($pattern, $folderName)) {
|
||||
$cache[$folderName] = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$cache[$folderName] = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\CutList;
|
||||
use App\Http\Requests\StoreCutListRequest;
|
||||
use App\Http\Requests\UpdateCutListRequest;
|
||||
|
||||
class CutListController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\StoreCutListRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreCutListRequest $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Models\CutList $cutList
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(CutList $cutList)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\CutList $cutList
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(CutList $cutList)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\UpdateCutListRequest $request
|
||||
* @param \App\Models\CutList $cutList
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateCutListRequest $request, CutList $cutList)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\CutList $cutList
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(CutList $cutList)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Defect;
|
||||
use App\Http\Requests\StoreDefectRequest;
|
||||
use App\Http\Requests\UpdateDefectRequest;
|
||||
|
||||
class DefectController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\StoreDefectRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreDefectRequest $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Models\Defect $defect
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Defect $defect)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Defect $defect
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Defect $defect)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\UpdateDefectRequest $request
|
||||
* @param \App\Models\Defect $defect
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateDefectRequest $request, Defect $defect)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Defect $defect
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Defect $defect)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
$id = $request['key'];
|
||||
// Get the line list record before deletion
|
||||
$lineList = $oldData;
|
||||
|
||||
$lineNumber = $lineList->line_no ?? null;
|
||||
$area = $lineList->unit ?? null;
|
||||
|
||||
if ($lineNumber) {
|
||||
// Delete from paint_follow_ups where primer coating has not started
|
||||
$deletedFollowUps = db('paint_follow_ups')
|
||||
->where(
|
||||
[
|
||||
'line' => $lineNumber,
|
||||
'area' => $area,
|
||||
]
|
||||
)
|
||||
->whereNull('primer_coating_start_date')
|
||||
->whereNull('primer_coating_finish_date')
|
||||
->whereNull('start_intermediate_date2')
|
||||
->whereNull('finish_intermediate_date2')
|
||||
->whereNull('final_coat_start_date3')
|
||||
->whereNull('final_coat_finish_date3')
|
||||
->delete();
|
||||
|
||||
// Delete from construction_paint_logs (spool-based, where painting has not started)
|
||||
// Get all spools for this line from weld_logs
|
||||
$spools = db("weld_logs")
|
||||
->where("line_number", $lineNumber)
|
||||
->whereNotNull('spool_number')
|
||||
->where('spool_number', '!=', '')
|
||||
->distinct()
|
||||
->pluck('spool_number');
|
||||
|
||||
$deletedConstructionLogs = 0;
|
||||
|
||||
if ($spools->isNotEmpty()) {
|
||||
// Spool-based deletion
|
||||
$deletedConstructionLogs = db('construction_paint_logs')
|
||||
->where('line', $lineNumber)
|
||||
->whereIn('spool', $spools)
|
||||
->whereNull('blasting_date')
|
||||
->whereNull('blasting_finish_date')
|
||||
->whereNull('painting_date_1')
|
||||
->whereNull('painting_finish_date_1')
|
||||
->whereNull('painting_date_2')
|
||||
->whereNull('painting_finish_date_2')
|
||||
->whereNull('painting_date_3')
|
||||
->whereNull('painting_finish_date_3')
|
||||
->delete();
|
||||
|
||||
Log::debug("Construction Paint Logs deleted (spool-based)", [
|
||||
'line' => $lineNumber,
|
||||
'spool_count' => $spools->count(),
|
||||
'deleted_count' => $deletedConstructionLogs
|
||||
]);
|
||||
} else {
|
||||
// Fallback to unit-based deletion if no spools found
|
||||
$deletedConstructionLogs = db('construction_paint_logs')
|
||||
->where([
|
||||
'line' => $lineNumber,
|
||||
'unit' => $area,
|
||||
])
|
||||
->whereNull('blasting_date')
|
||||
->whereNull('blasting_finish_date')
|
||||
->whereNull('painting_date_1')
|
||||
->whereNull('painting_finish_date_1')
|
||||
->whereNull('painting_date_2')
|
||||
->whereNull('painting_finish_date_2')
|
||||
->whereNull('painting_date_3')
|
||||
->whereNull('painting_finish_date_3')
|
||||
->delete();
|
||||
|
||||
Log::debug("Construction Paint Logs deleted (unit-based fallback)", [
|
||||
'line' => $lineNumber,
|
||||
'unit' => $area,
|
||||
'deleted_count' => $deletedConstructionLogs
|
||||
]);
|
||||
}
|
||||
|
||||
spoolStatusChanger($lineNumber);
|
||||
|
||||
Log::info("Deleted related paint records for line: $lineNumber (Line List ID: $id)", [
|
||||
'deleted_follow_ups' => $deletedFollowUps,
|
||||
'deleted_construction_logs' => $deletedConstructionLogs,
|
||||
'spool_based' => $spools->isNotEmpty()
|
||||
]);
|
||||
} else {
|
||||
Log::error("Line number not found for line list ID: $id");
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
$uniqueFields = [
|
||||
'line_number' => $oldData->line,
|
||||
'support_code' => $oldData->component_code_id,
|
||||
];
|
||||
|
||||
echo db('supports')->where($uniqueFields)->delete();
|
||||
dump("delete trigger");
|
||||
dump($oldData);
|
||||
?>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
$id = $request['key'];
|
||||
|
||||
// Get the paint matrix record before deletion
|
||||
$paintMatrix = db('paint_matrices')->where('id', $id)->first();
|
||||
|
||||
if ($paintMatrix) {
|
||||
// Delete from paint_follow_ups
|
||||
db('paint_follow_ups')
|
||||
->where([
|
||||
'line' => $paintMatrix->line,
|
||||
'area' => $paintMatrix->area,
|
||||
])
|
||||
->whereNull('primer_coating_start_date') // Only delete if primer coating start date is null
|
||||
->delete();
|
||||
|
||||
// Delete from construction_paint_logs
|
||||
db('construction_paint_logs')
|
||||
->where([
|
||||
'line' => $paintMatrix->line,
|
||||
'unit' => $paintMatrix->area,
|
||||
])
|
||||
->whereNull('painting_date_1') // Only delete if primer coating start date is null
|
||||
->delete();
|
||||
|
||||
dump("Deleted related records for paint matrix ID: $id");
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
$uniqueFields = [
|
||||
'line' => $oldData->line_number,
|
||||
'component_code_id' => $oldData->support_code,
|
||||
];
|
||||
|
||||
echo db('m_t_o_s')->where($uniqueFields)->delete();
|
||||
dump("delete trigger");
|
||||
dump($oldData);
|
||||
?>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
// Get the test_pack_base_status that is being deleted
|
||||
$testPackBaseStatus = db("test_pack_base_statuses")->where("id", $request['key'])->first();
|
||||
|
||||
if ($testPackBaseStatus) {
|
||||
try {
|
||||
$testPackageNo = $testPackBaseStatus->test_package_no;
|
||||
|
||||
// Check if there are any remaining test_pack_base_statuses records with the same test_package_no
|
||||
$remainingCount = db("test_pack_base_statuses")
|
||||
->where("test_package_no", $testPackageNo)
|
||||
->where("id", "!=", $request['key']) // Exclude the current record being deleted
|
||||
->count();
|
||||
|
||||
// Only delete test_packages if no other test_pack_base_statuses records exist for this test_package_no
|
||||
if ($remainingCount == 0) {
|
||||
// Check if there are any weld_logs records with this test_package_no
|
||||
$weldLogsCount = db("weld_logs")
|
||||
->where("test_package_no", $testPackageNo)
|
||||
->count();
|
||||
|
||||
if ($weldLogsCount > 0) {
|
||||
dump("Cannot delete test_packages. Found $weldLogsCount weld_logs records for test_package_no: $testPackageNo");
|
||||
} else {
|
||||
$deletedCount = db("test_packages")
|
||||
->where("test_package_number", $testPackageNo)
|
||||
->delete();
|
||||
|
||||
dump("No remaining test_pack_base_statuses for test_package_no: $testPackageNo. Deleted $deletedCount test_packages records.");
|
||||
}
|
||||
} else {
|
||||
dump("Found $remainingCount remaining test_pack_base_statuses for test_package_no: $testPackageNo. Keeping test_packages records.");
|
||||
}
|
||||
|
||||
} catch (\Throwable $th) {
|
||||
dump("Error processing test_packages deletion: " . $th->getMessage());
|
||||
Log::error("DeleteTrigger test_pack_base_statuses error: " . $th->getMessage());
|
||||
}
|
||||
} else {
|
||||
dump("Test pack base status not found with id: " . $request['key']);
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
// Get the test package that is being deleted
|
||||
$testPackage = db("test_packages")->where("id", $request['key'])->first();
|
||||
|
||||
if ($testPackage) {
|
||||
try {
|
||||
// Check if there are any weld_logs records with this test_package_number
|
||||
$weldLogsCount = db("weld_logs")
|
||||
->where("test_package_no", $testPackage->test_package_number)
|
||||
->count();
|
||||
|
||||
if ($weldLogsCount > 0) {
|
||||
dump("Cannot delete test_pack_base_statuses. Found $weldLogsCount weld_logs records for test_package_no: " . $testPackage->test_package_number);
|
||||
} else {
|
||||
// Delete related test_pack_base_statuses records based on test_package_number
|
||||
$deletedCount = db("test_pack_base_statuses")
|
||||
->where("test_package_no", $testPackage->test_package_number)
|
||||
->delete();
|
||||
|
||||
dump("Deleted $deletedCount test_pack_base_statuses records for test_package_no: " . $testPackage->test_package_number);
|
||||
}
|
||||
|
||||
} catch (\Throwable $th) {
|
||||
dump("Error deleting test_pack_base_statuses: " . $th->getMessage());
|
||||
Log::error("DeleteTrigger test_packages error: " . $th->getMessage());
|
||||
}
|
||||
} else {
|
||||
dump("Test package not found with id: " . $request['key']);
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
if(isset($oldData->test_package_no))
|
||||
{
|
||||
$testPackWhereData = [
|
||||
'test_package_number' => $oldData->test_package_no
|
||||
];
|
||||
|
||||
$testPackBaseStatusWhereData = [
|
||||
'test_package_no' => $oldData->test_package_no,
|
||||
'drawing_no' => $oldData->iso_number,
|
||||
];
|
||||
|
||||
// Önce weld_logs tablosunda aynı test_package_no var mı kontrol et
|
||||
$weldLogCount = db("weld_logs")
|
||||
->where(['test_package_no' => $oldData->test_package_no])
|
||||
->count();
|
||||
|
||||
if ($weldLogCount > 0) {
|
||||
Log::info("{$oldData->test_package_no} nolu test package weld_logs tablosunda mevcut, silme işlemi yapılmadı.");
|
||||
} else {
|
||||
$testPackagesChanged = db("test_packages")
|
||||
->where($testPackWhereData)
|
||||
->delete();
|
||||
|
||||
$tpBaseChanged = db("test_pack_base_statuses")
|
||||
->where($testPackBaseStatusWhereData)
|
||||
->delete();
|
||||
|
||||
Log::info("{$oldData->test_package_no} nolu test package {$oldData->iso_number} iso number dan silindi\ntpBaseDeleted: $tpBaseChanged\ntestPackagesDeleted: $testPackagesChanged\n");
|
||||
}
|
||||
|
||||
} else {
|
||||
Log::error("Weld log testp package no not found for ISO number: {$oldData->iso_number}");
|
||||
}
|
||||
|
||||
spoolStatusChanger($oldData->iso_number);
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\StoreDeletedJointRequest;
|
||||
use App\Http\Requests\UpdateDeletedJointRequest;
|
||||
use App\Models\DeletedJoint;
|
||||
|
||||
class DeletedJointController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\StoreDeletedJointRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreDeletedJointRequest $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Models\DeletedJoint $deletedJoint
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(DeletedJoint $deletedJoint)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\DeletedJoint $deletedJoint
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(DeletedJoint $deletedJoint)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\UpdateDeletedJointRequest $request
|
||||
* @param \App\Models\DeletedJoint $deletedJoint
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateDeletedJointRequest $request, DeletedJoint $deletedJoint)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\DeletedJoint $deletedJoint
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(DeletedJoint $deletedJoint)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class DevextremeController extends Controller
|
||||
{
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user