657 lines
28 KiB
PHP
657 lines
28 KiB
PHP
<?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
|
||
]);
|
||
}
|
||
}
|