Initial commit

This commit is contained in:
sas.fajri
2026-04-30 14:27:01 +07:00
commit e29e943c27
70 changed files with 8909 additions and 0 deletions

33
cpone-dashboard/db/db.go Normal file
View File

@@ -0,0 +1,33 @@
package db
import (
"database/sql"
"fmt"
"log"
_ "github.com/go-sql-driver/mysql"
)
var DB *sql.DB
func Connect(dsn string) error {
if dsn == "" {
return fmt.Errorf("DB_DSN is not set")
}
conn, err := sql.Open("mysql", dsn)
if err != nil {
return fmt.Errorf("open db: %w", err)
}
if err := conn.Ping(); err != nil {
return fmt.Errorf("ping db: %w", err)
}
conn.SetMaxOpenConns(25)
conn.SetMaxIdleConns(10)
DB = conn
log.Println("database connected: cpone_dashboard")
return nil
}

View File

@@ -0,0 +1,123 @@
-- Migration 001: Initial schema for cpone_dashboard
-- Naming convention: table=snake_case, column=Prefix_PascalCase (mengikuti cpone)
-- Tidak menggunakan foreign key constraint
-- ============================================================
-- mcu_project
-- Source: cpone.mgm_mcu JOIN cpone.corporate
-- ============================================================
CREATE TABLE IF NOT EXISTS mcu_project (
Mcu_ProjectID INT AUTO_INCREMENT PRIMARY KEY,
Mcu_ProjectMcuID INT NOT NULL, -- Mgm_McuID
Mcu_ProjectCorporateID INT NOT NULL, -- Mgm_McuCorporateID
Mcu_ProjectCorporateName VARCHAR(255), -- corporate.CorporateName
Mcu_ProjectNumber VARCHAR(50), -- Mgm_McuNumber
Mcu_ProjectLabel VARCHAR(255), -- Mgm_McuLabel
Mcu_ProjectBranchID INT DEFAULT 0, -- Mgm_McuM_BranchID
Mcu_ProjectStartDate DATE, -- Mgm_McuStartDate
Mcu_ProjectEndDate DATE, -- Mgm_McuEndDate
Mcu_ProjectIsActive CHAR(1) DEFAULT 'Y', -- Mgm_McuIsActive
Mcu_ProjectTotalParticipant INT DEFAULT 0, -- Mgm_McuTotalParticipant
Mcu_ProjectSyncedAt DATETIME,
UNIQUE KEY uq_mcu_id (Mcu_ProjectMcuID),
INDEX idx_is_active (Mcu_ProjectIsActive),
INDEX idx_dates (Mcu_ProjectStartDate, Mcu_ProjectEndDate)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ============================================================
-- mcu_patient
-- Source: cpone.mcu_preregister_patients
-- ============================================================
CREATE TABLE IF NOT EXISTS mcu_patient (
Mcu_PatientID INT AUTO_INCREMENT PRIMARY KEY,
Mcu_PatientPreregisterID INT NOT NULL, -- Mcu_PreregisterPatientsID
Mcu_PatientMcuID INT NOT NULL, -- Mcu_PreregisterPatientsMgm_McuID
Mcu_PatientName VARCHAR(150), -- Mcu_PreregisterPatientsPatientName
Mcu_PatientNIP VARCHAR(50), -- Mcu_PreregisterPatientsNIP
Mcu_PatientGender VARCHAR(10), -- Mcu_PreregisterPatientsGender
Mcu_PatientDOB DATE, -- Mcu_PreregisterPatientsDOB
Mcu_PatientDepartment VARCHAR(500), -- Mcu_PreregisterPatientsDepartment
Mcu_PatientDivision VARCHAR(500), -- Mcu_PreregisterPatientsDivisi
Mcu_PatientPosisi VARCHAR(500), -- Mcu_PreregisterPatientsPosisi
Mcu_PatientIsRegistered CHAR(1) DEFAULT 'N', -- Mcu_PreregisterPatientsIsRegistered
Mcu_PatientOrderID INT DEFAULT 0, -- Mcu_PreregisterPatientsT_OrderHeaderID
Mcu_PatientIsActive CHAR(1) DEFAULT 'Y', -- Mcu_PreregisterPatientsIsActive
Mcu_PatientSyncedAt DATETIME,
UNIQUE KEY uq_preregister_id (Mcu_PatientPreregisterID),
INDEX idx_mcu_id (Mcu_PatientMcuID),
INDEX idx_order_id (Mcu_PatientOrderID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ============================================================
-- mcu_patient_schedule
-- Source: cpone.mcu_preregister_date
-- Catatan: tidak semua pasien punya jadwal (opsional)
-- ============================================================
CREATE TABLE IF NOT EXISTS mcu_patient_schedule (
Mcu_PatientScheduleID INT AUTO_INCREMENT PRIMARY KEY,
Mcu_PatientSchedulePreregisterID INT NOT NULL, -- Mcu_PreregisterDateMcu_PreregisterPatientsID
Mcu_PatientScheduleDate DATE NOT NULL, -- Mcu_PreregisterDateCheckinSchedule
Mcu_PatientScheduleIsActive CHAR(1) DEFAULT 'Y', -- Mcu_PreregisterDateIsActive
Mcu_PatientScheduleSyncedAt DATETIME,
INDEX idx_preregister_id (Mcu_PatientSchedulePreregisterID),
INDEX idx_schedule_date (Mcu_PatientScheduleDate)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ============================================================
-- mcu_checkinout
-- Source: cpone.preregister_checkin_checkout
-- Catatan: 1 pasien bisa punya > 1 baris (multi-hari)
-- ============================================================
CREATE TABLE IF NOT EXISTS mcu_checkinout (
Mcu_CheckinoutID INT AUTO_INCREMENT PRIMARY KEY,
Mcu_CheckinoutCheckinoutID INT NOT NULL, -- PreregisterCheckInCheckOutID
Mcu_CheckinoutPreregisterID INT NOT NULL, -- PreregisterCheckInCheckOutPreregisterID
Mcu_CheckinoutOrderID INT DEFAULT 0, -- PreregisterCheckInCheckOutT_OrderHeaderID
Mcu_CheckinoutDate DATE NOT NULL, -- PreregisterCheckInCheckOutDate
Mcu_CheckinoutInTime TIME, -- PreregisterCheckInCheckOutInTime
Mcu_CheckinoutOutTime TIME, -- PreregisterCheckInCheckOutOutTime
Mcu_CheckinoutOutUserID INT DEFAULT 0, -- PreregisterCheckInCheckOutOutUserID
Mcu_CheckinoutNextDate DATE, -- PreregisterCheckInCheckOutNextPreregisterDate
Mcu_CheckinoutNote TEXT, -- PreregisterCheckInCheckOutNote
Mcu_CheckinoutIsActive CHAR(1) DEFAULT 'Y', -- PreregisterCheckInCheckOutIsActive
Mcu_CheckinoutSyncedAt DATETIME,
UNIQUE KEY uq_checkinout_segment (
Mcu_CheckinoutPreregisterID,
Mcu_CheckinoutDate,
Mcu_CheckinoutInTime
),
INDEX idx_preregister_id (Mcu_CheckinoutPreregisterID),
INDEX idx_date (Mcu_CheckinoutDate),
INDEX idx_order_id (Mcu_CheckinoutOrderID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ============================================================
-- mcu_station_progress (Phase 2)
-- Source: cpone.t_ordersample (lab)
-- + cpone.t_orderdetail->t_test->group_resultdetail->group_result (nonlab)
-- ETL flatten kedua sumber menjadi satu tabel
-- ============================================================
CREATE TABLE IF NOT EXISTS mcu_station_progress (
Mcu_StationProgressID INT AUTO_INCREMENT PRIMARY KEY,
Mcu_StationProgressOrderID INT NOT NULL, -- T_OrderHeaderID
Mcu_StationProgressPreregisterID INT NOT NULL,
Mcu_StationProgressMcuID INT NOT NULL,
Mcu_StationProgressStationID INT NOT NULL, -- T_SampleStationID
Mcu_StationProgressStationName VARCHAR(100), -- T_SampleStationName
Mcu_StationProgressSource VARCHAR(10), -- 'lab' | 'nonlab'
Mcu_StationProgressCheckinDate DATE, -- tanggal checkin pasien
Mcu_StationProgressSamplingAt DATETIME, -- lab: SamplingDate+Time
Mcu_StationProgressReceiveAt DATETIME, -- lab: ReceiveDate+Time
Mcu_StationProgressProcessAt DATETIME, -- lab: ProcessingDate+Time
Mcu_StationProgressDoneAt DATETIME, -- lab: DoneDate+Time | nonlab: result entry time
Mcu_StationProgressSyncedAt DATETIME,
INDEX idx_order_id (Mcu_StationProgressOrderID),
INDEX idx_preregister_id (Mcu_StationProgressPreregisterID),
INDEX idx_mcu_id (Mcu_StationProgressMcuID),
INDEX idx_station_id (Mcu_StationProgressStationID),
INDEX idx_checkin_date (Mcu_StationProgressCheckinDate)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@@ -0,0 +1,250 @@
-- Migration 002: stored procedure untuk generate dashboard data dari project cpone yang sudah ada
-- Digunakan untuk testing dengan data historis (contoh: Mgm_McuID = 99)
-- Tambah unique key di mcu_patient_schedule agar ON DUPLICATE KEY UPDATE bisa berjalan
ALTER TABLE mcu_patient_schedule
ADD UNIQUE KEY uq_preregister_schedule (Mcu_PatientSchedulePreregisterID, Mcu_PatientScheduleDate);
ALTER TABLE mcu_checkinout
DROP INDEX uq_checkinout_id,
ADD UNIQUE KEY uq_checkinout_segment (
Mcu_CheckinoutPreregisterID,
Mcu_CheckinoutDate,
Mcu_CheckinoutInTime
);
-- ============================================================
-- sp_generate_dashboard_data
-- Parameter: p_mcu_id INT (Mgm_McuID dari cpone)
-- Mengisi: mcu_project, mcu_patient, mcu_patient_schedule, mcu_checkinout
-- ============================================================
DROP PROCEDURE IF EXISTS sp_generate_dashboard_data;
DELIMITER $$
CREATE PROCEDURE sp_generate_dashboard_data(IN p_mcu_id INT)
BEGIN
-- ----------------------------------------------------------
-- 1. mcu_project
-- Source: cpone.mgm_mcu JOIN cpone.corporate
-- ----------------------------------------------------------
INSERT INTO mcu_project (
Mcu_ProjectMcuID,
Mcu_ProjectCorporateID,
Mcu_ProjectCorporateName,
Mcu_ProjectNumber,
Mcu_ProjectLabel,
Mcu_ProjectBranchID,
Mcu_ProjectStartDate,
Mcu_ProjectEndDate,
Mcu_ProjectIsActive,
Mcu_ProjectTotalParticipant,
Mcu_ProjectSyncedAt
)
SELECT
m.Mgm_McuID,
m.Mgm_McuCorporateID,
c.CorporateName,
m.Mgm_McuNumber,
m.Mgm_McuLabel,
m.Mgm_McuM_BranchID,
m.Mgm_McuStartDate,
m.Mgm_McuEndDate,
m.Mgm_McuIsActive,
m.Mgm_McuTotalParticipant,
NOW()
FROM cpone.mgm_mcu m
LEFT JOIN cpone.corporate c ON c.CorporateID = m.Mgm_McuCorporateID
WHERE m.Mgm_McuID = p_mcu_id
ON DUPLICATE KEY UPDATE
Mcu_ProjectCorporateName = VALUES(Mcu_ProjectCorporateName),
Mcu_ProjectLabel = VALUES(Mcu_ProjectLabel),
Mcu_ProjectIsActive = VALUES(Mcu_ProjectIsActive),
Mcu_ProjectTotalParticipant = VALUES(Mcu_ProjectTotalParticipant),
Mcu_ProjectSyncedAt = NOW();
-- ----------------------------------------------------------
-- 2. mcu_patient
-- Source: cpone.mcu_preregister_patients
-- ----------------------------------------------------------
INSERT INTO mcu_patient (
Mcu_PatientPreregisterID,
Mcu_PatientMcuID,
Mcu_PatientName,
Mcu_PatientNIP,
Mcu_PatientGender,
Mcu_PatientDOB,
Mcu_PatientDepartment,
Mcu_PatientDivision,
Mcu_PatientPosisi,
Mcu_PatientIsRegistered,
Mcu_PatientOrderID,
Mcu_PatientIsActive,
Mcu_PatientSyncedAt
)
SELECT
p.Mcu_PreregisterPatientsID,
p.Mcu_PreregisterPatientsMgm_McuID,
p.Mcu_PreregisterPatientsPatientName,
p.Mcu_PreregisterPatientsNIP,
p.Mcu_PreregisterPatientsGender,
p.Mcu_PreregisterPatientsDOB,
p.Mcu_PreregisterPatientsDepartment,
p.Mcu_PreregisterPatientsDivisi,
p.Mcu_PreregisterPatientsPosisi,
p.Mcu_PreregisterPatientsIsRegistered,
p.Mcu_PreregisterPatientsT_OrderHeaderID,
p.Mcu_PreregisterPatientsIsActive,
NOW()
FROM cpone.mcu_preregister_patients p
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
ON DUPLICATE KEY UPDATE
Mcu_PatientName = VALUES(Mcu_PatientName),
Mcu_PatientIsRegistered = VALUES(Mcu_PatientIsRegistered),
Mcu_PatientOrderID = VALUES(Mcu_PatientOrderID),
Mcu_PatientSyncedAt = NOW();
-- ----------------------------------------------------------
-- 3. mcu_patient_schedule
-- Source: T_OrderHeaderDate sebagai jadwal checkin
-- Hanya untuk pasien yang sudah punya order
-- ----------------------------------------------------------
INSERT INTO mcu_patient_schedule (
Mcu_PatientSchedulePreregisterID,
Mcu_PatientScheduleDate,
Mcu_PatientScheduleIsActive,
Mcu_PatientScheduleSyncedAt
)
SELECT
p.Mcu_PreregisterPatientsID,
DATE(o.T_OrderHeaderDate),
'Y',
NOW()
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o
ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
ON DUPLICATE KEY UPDATE
Mcu_PatientScheduleSyncedAt = NOW();
-- ----------------------------------------------------------
-- 4. mcu_checkinout
-- Satu baris per tanggal proses.
-- Check-in : tanggal header untuk hari pertama, atau event paling awal untuk hari lanjutan.
-- Check-out : event paling akhir pada tanggal itu.
-- ----------------------------------------------------------
INSERT INTO mcu_checkinout (
Mcu_CheckinoutCheckinoutID,
Mcu_CheckinoutPreregisterID,
Mcu_CheckinoutOrderID,
Mcu_CheckinoutDate,
Mcu_CheckinoutInTime,
Mcu_CheckinoutOutTime,
Mcu_CheckinoutNextDate,
Mcu_CheckinoutIsActive,
Mcu_CheckinoutSyncedAt
)
SELECT
src.order_id,
src.preregister_id,
src.order_id,
src.segment_date,
TIME(src.checkin_dt),
TIME(src.checkout_dt),
CASE
WHEN DATE(src.checkout_dt) = src.segment_date THEN NULL
ELSE DATE(src.checkout_dt)
END,
'Y',
NOW()
FROM (
SELECT
o.T_OrderHeaderID AS order_id,
p.Mcu_PreregisterPatientsID AS preregister_id,
o.T_OrderHeaderDate AS header_dt,
ev.segment_date,
CASE
WHEN ev.segment_date = DATE(o.T_OrderHeaderDate) THEN o.T_OrderHeaderDate
ELSE MIN(ev.event_dt)
END AS checkin_dt,
MAX(ev.event_dt) AS checkout_dt
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o
ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN (
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(o2.T_OrderHeaderDate) AS segment_date,
o2.T_OrderHeaderDate AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2
ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
UNION ALL
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(TIMESTAMP(s2.T_OrderSampleReceiveDate, s2.T_OrderSampleReceiveTime)) AS segment_date,
TIMESTAMP(s2.T_OrderSampleReceiveDate, s2.T_OrderSampleReceiveTime) AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2
ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_ordersample s2
ON s2.T_OrderSampleT_OrderHeaderID = o2.T_OrderHeaderID
AND s2.T_OrderSampleIsActive = 'Y'
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
AND s2.T_OrderSampleReceiveDate IS NOT NULL
AND s2.T_OrderSampleReceiveTime IS NOT NULL
UNION ALL
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(TIMESTAMP(ts2.T_SamplingSoDoneDate, ts2.T_SamplingSoDoneTime)) AS segment_date,
TIMESTAMP(ts2.T_SamplingSoDoneDate, ts2.T_SamplingSoDoneTime) AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2
ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_samplingso ts2
ON ts2.T_SamplingSoT_OrderHeaderID = o2.T_OrderHeaderID
AND ts2.T_SamplingSoIsActive = 'Y'
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
AND ts2.T_SamplingSoDoneDate IS NOT NULL
AND ts2.T_SamplingSoDoneTime IS NOT NULL
) ev
ON ev.preregister_id = p.Mcu_PreregisterPatientsID
AND ev.order_id = o.T_OrderHeaderID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
GROUP BY
o.T_OrderHeaderID,
p.Mcu_PreregisterPatientsID,
o.T_OrderHeaderDate,
ev.segment_date
) AS src
ON DUPLICATE KEY UPDATE
Mcu_CheckinoutOutTime = VALUES(Mcu_CheckinoutOutTime),
Mcu_CheckinoutNextDate = VALUES(Mcu_CheckinoutNextDate),
Mcu_CheckinoutSyncedAt = NOW();
END $$
DELIMITER ;

View File

@@ -0,0 +1,269 @@
-- Migration 003: tambah unique key mcu_station_progress + update SP dengan station progress
ALTER TABLE mcu_station_progress
ADD UNIQUE KEY uq_order_station_source (
Mcu_StationProgressOrderID,
Mcu_StationProgressStationID,
Mcu_StationProgressSource
);
ALTER TABLE mcu_checkinout
DROP INDEX uq_checkinout_id,
ADD UNIQUE KEY uq_checkinout_segment (
Mcu_CheckinoutPreregisterID,
Mcu_CheckinoutDate,
Mcu_CheckinoutInTime
);
-- Update SP: tambah step 5 untuk mcu_station_progress
DROP PROCEDURE IF EXISTS sp_generate_dashboard_data;
DELIMITER $$
CREATE PROCEDURE sp_generate_dashboard_data(IN p_mcu_id INT)
BEGIN
-- ----------------------------------------------------------
-- 1. mcu_project
-- ----------------------------------------------------------
INSERT INTO mcu_project (
Mcu_ProjectMcuID, Mcu_ProjectCorporateID, Mcu_ProjectCorporateName,
Mcu_ProjectNumber, Mcu_ProjectLabel, Mcu_ProjectBranchID,
Mcu_ProjectStartDate, Mcu_ProjectEndDate, Mcu_ProjectIsActive,
Mcu_ProjectTotalParticipant, Mcu_ProjectSyncedAt
)
SELECT
m.Mgm_McuID, m.Mgm_McuCorporateID, c.CorporateName,
m.Mgm_McuNumber, m.Mgm_McuLabel, m.Mgm_McuM_BranchID,
m.Mgm_McuStartDate, m.Mgm_McuEndDate, m.Mgm_McuIsActive,
m.Mgm_McuTotalParticipant, NOW()
FROM cpone.mgm_mcu m
LEFT JOIN cpone.corporate c ON c.CorporateID = m.Mgm_McuCorporateID
WHERE m.Mgm_McuID = p_mcu_id
ON DUPLICATE KEY UPDATE
Mcu_ProjectCorporateName = VALUES(Mcu_ProjectCorporateName),
Mcu_ProjectLabel = VALUES(Mcu_ProjectLabel),
Mcu_ProjectIsActive = VALUES(Mcu_ProjectIsActive),
Mcu_ProjectTotalParticipant = VALUES(Mcu_ProjectTotalParticipant),
Mcu_ProjectSyncedAt = NOW();
-- ----------------------------------------------------------
-- 2. mcu_patient
-- ----------------------------------------------------------
INSERT INTO mcu_patient (
Mcu_PatientPreregisterID, Mcu_PatientMcuID, Mcu_PatientName,
Mcu_PatientNIP, Mcu_PatientGender, Mcu_PatientDOB,
Mcu_PatientDepartment, Mcu_PatientDivision, Mcu_PatientPosisi,
Mcu_PatientIsRegistered, Mcu_PatientOrderID, Mcu_PatientIsActive,
Mcu_PatientSyncedAt
)
SELECT
p.Mcu_PreregisterPatientsID, p.Mcu_PreregisterPatientsMgm_McuID,
p.Mcu_PreregisterPatientsPatientName, p.Mcu_PreregisterPatientsNIP,
p.Mcu_PreregisterPatientsGender, p.Mcu_PreregisterPatientsDOB,
p.Mcu_PreregisterPatientsDepartment, p.Mcu_PreregisterPatientsDivisi,
p.Mcu_PreregisterPatientsPosisi,
p.Mcu_PreregisterPatientsIsRegistered, p.Mcu_PreregisterPatientsT_OrderHeaderID,
p.Mcu_PreregisterPatientsIsActive, NOW()
FROM cpone.mcu_preregister_patients p
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
ON DUPLICATE KEY UPDATE
Mcu_PatientName = VALUES(Mcu_PatientName),
Mcu_PatientIsRegistered = VALUES(Mcu_PatientIsRegistered),
Mcu_PatientOrderID = VALUES(Mcu_PatientOrderID),
Mcu_PatientSyncedAt = NOW();
-- ----------------------------------------------------------
-- 3. mcu_patient_schedule
-- ----------------------------------------------------------
INSERT INTO mcu_patient_schedule (
Mcu_PatientSchedulePreregisterID, Mcu_PatientScheduleDate,
Mcu_PatientScheduleIsActive, Mcu_PatientScheduleSyncedAt
)
SELECT
p.Mcu_PreregisterPatientsID, DATE(o.T_OrderHeaderDate), 'Y', NOW()
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
ON DUPLICATE KEY UPDATE
Mcu_PatientScheduleSyncedAt = NOW();
-- ----------------------------------------------------------
-- 4. mcu_checkinout
-- Satu baris per tanggal proses.
-- ----------------------------------------------------------
INSERT INTO mcu_checkinout (
Mcu_CheckinoutCheckinoutID, Mcu_CheckinoutPreregisterID, Mcu_CheckinoutOrderID,
Mcu_CheckinoutDate, Mcu_CheckinoutInTime, Mcu_CheckinoutOutTime,
Mcu_CheckinoutNextDate, Mcu_CheckinoutIsActive, Mcu_CheckinoutSyncedAt
)
SELECT
src.order_id,
src.preregister_id,
src.order_id,
src.segment_date,
TIME(src.checkin_dt),
TIME(src.checkout_dt),
CASE
WHEN DATE(src.checkout_dt) = src.segment_date THEN NULL
ELSE DATE(src.checkout_dt)
END,
'Y', NOW()
FROM (
SELECT
o.T_OrderHeaderID AS order_id,
p.Mcu_PreregisterPatientsID AS preregister_id,
o.T_OrderHeaderDate AS header_dt,
ev.segment_date,
CASE
WHEN ev.segment_date = DATE(o.T_OrderHeaderDate) THEN o.T_OrderHeaderDate
ELSE MIN(ev.event_dt)
END AS checkin_dt,
MAX(ev.event_dt) AS checkout_dt
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN (
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(o2.T_OrderHeaderDate) AS segment_date,
o2.T_OrderHeaderDate AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2 ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
UNION ALL
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(TIMESTAMP(s2.T_OrderSampleReceiveDate, s2.T_OrderSampleReceiveTime)) AS segment_date,
TIMESTAMP(s2.T_OrderSampleReceiveDate, s2.T_OrderSampleReceiveTime) AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2 ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_ordersample s2
ON s2.T_OrderSampleT_OrderHeaderID = o2.T_OrderHeaderID
AND s2.T_OrderSampleIsActive = 'Y'
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
AND s2.T_OrderSampleReceiveDate IS NOT NULL
AND s2.T_OrderSampleReceiveTime IS NOT NULL
UNION ALL
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(TIMESTAMP(ts2.T_SamplingSoDoneDate, ts2.T_SamplingSoDoneTime)) AS segment_date,
TIMESTAMP(ts2.T_SamplingSoDoneDate, ts2.T_SamplingSoDoneTime) AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2 ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_samplingso ts2
ON ts2.T_SamplingSoT_OrderHeaderID = o2.T_OrderHeaderID
AND ts2.T_SamplingSoIsActive = 'Y'
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
AND ts2.T_SamplingSoDoneDate IS NOT NULL
AND ts2.T_SamplingSoDoneTime IS NOT NULL
) ev
ON ev.preregister_id = p.Mcu_PreregisterPatientsID
AND ev.order_id = o.T_OrderHeaderID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
GROUP BY o.T_OrderHeaderID, p.Mcu_PreregisterPatientsID, o.T_OrderHeaderDate, ev.segment_date
) AS src
ON DUPLICATE KEY UPDATE
Mcu_CheckinoutOutTime = VALUES(Mcu_CheckinoutOutTime),
Mcu_CheckinoutNextDate = VALUES(Mcu_CheckinoutNextDate),
Mcu_CheckinoutSyncedAt = NOW();
-- ----------------------------------------------------------
-- 5. mcu_station_progress — lab (dari t_ordersample)
-- GROUP BY order+station supaya satu baris per pasien per station
-- ----------------------------------------------------------
INSERT INTO mcu_station_progress (
Mcu_StationProgressOrderID, Mcu_StationProgressPreregisterID, Mcu_StationProgressMcuID,
Mcu_StationProgressStationID, Mcu_StationProgressStationName, Mcu_StationProgressSource,
Mcu_StationProgressCheckinDate,
Mcu_StationProgressSamplingAt, Mcu_StationProgressReceiveAt, Mcu_StationProgressProcessAt,
Mcu_StationProgressDoneAt, Mcu_StationProgressSyncedAt
)
SELECT
o.T_OrderHeaderID,
p.Mcu_PreregisterPatientsID,
p_mcu_id,
s.T_OrderSampleT_SampleStationID,
ss.T_SampleStationName,
'lab',
DATE(o.T_OrderHeaderDate),
NULLIF(MAX(TIMESTAMP(s.T_OrderSampleSamplingDate, s.T_OrderSampleSamplingTime)), '0000-00-00 00:00:00'),
NULLIF(MAX(TIMESTAMP(s.T_OrderSampleReceiveDate, s.T_OrderSampleReceiveTime)), '0000-00-00 00:00:00'),
NULLIF(MAX(TIMESTAMP(s.T_OrderSampleProcessingDate, s.T_OrderSampleProcessingTime)), '0000-00-00 00:00:00'),
NULL,
NOW()
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_ordersample s ON s.T_OrderSampleT_OrderHeaderID = o.T_OrderHeaderID AND s.T_OrderSampleIsActive = 'Y'
JOIN cpone.t_samplestation ss ON ss.T_SampleStationID = s.T_OrderSampleT_SampleStationID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
GROUP BY o.T_OrderHeaderID, p.Mcu_PreregisterPatientsID, s.T_OrderSampleT_SampleStationID, ss.T_SampleStationName, o.T_OrderHeaderDate
ON DUPLICATE KEY UPDATE
Mcu_StationProgressSamplingAt = VALUES(Mcu_StationProgressSamplingAt),
Mcu_StationProgressReceiveAt = VALUES(Mcu_StationProgressReceiveAt),
Mcu_StationProgressProcessAt = VALUES(Mcu_StationProgressProcessAt),
Mcu_StationProgressSyncedAt = NOW();
-- ----------------------------------------------------------
-- 6. mcu_station_progress — nonlab (dari t_samplingso)
-- ----------------------------------------------------------
INSERT INTO mcu_station_progress (
Mcu_StationProgressOrderID, Mcu_StationProgressPreregisterID, Mcu_StationProgressMcuID,
Mcu_StationProgressStationID, Mcu_StationProgressStationName, Mcu_StationProgressSource,
Mcu_StationProgressCheckinDate,
Mcu_StationProgressSamplingAt, Mcu_StationProgressReceiveAt, Mcu_StationProgressProcessAt,
Mcu_StationProgressDoneAt, Mcu_StationProgressSyncedAt
)
SELECT
o.T_OrderHeaderID,
p.Mcu_PreregisterPatientsID,
p_mcu_id,
ts.T_SamplingSoT_SampleStationID,
ss.T_SampleStationName,
'nonlab',
DATE(o.T_OrderHeaderDate),
NULL,
NULL,
NULLIF(MAX(TIMESTAMP(ts.T_SamplingSoProcessDate, ts.T_SamplingSoProcessTime)), '0000-00-00 00:00:00'),
NULLIF(MAX(TIMESTAMP(ts.T_SamplingSoDoneDate, ts.T_SamplingSoDoneTime)), '0000-00-00 00:00:00'),
NOW()
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_samplingso ts ON ts.T_SamplingSoT_OrderHeaderID = o.T_OrderHeaderID AND ts.T_SamplingSoIsActive = 'Y'
JOIN cpone.t_samplestation ss ON ss.T_SampleStationID = ts.T_SamplingSoT_SampleStationID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
GROUP BY o.T_OrderHeaderID, p.Mcu_PreregisterPatientsID, ts.T_SamplingSoT_SampleStationID, ss.T_SampleStationName, o.T_OrderHeaderDate
ON DUPLICATE KEY UPDATE
Mcu_StationProgressProcessAt = VALUES(Mcu_StationProgressProcessAt),
Mcu_StationProgressDoneAt = VALUES(Mcu_StationProgressDoneAt),
Mcu_StationProgressSyncedAt = NOW();
END $$
DELIMITER ;

View File

@@ -0,0 +1,17 @@
-- Migration 004: tabel user untuk login dashboard
CREATE TABLE IF NOT EXISTS dashboard_user (
User_ID INT AUTO_INCREMENT PRIMARY KEY,
User_Username VARCHAR(50) NOT NULL,
User_Password VARCHAR(255) NOT NULL, -- bcrypt hash
User_DisplayName VARCHAR(100),
User_IsActive CHAR(1) DEFAULT 'Y',
User_CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,
User_UpdatedAt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uq_username (User_Username),
INDEX idx_is_active (User_IsActive)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Default user: admin / admin123 (ganti password setelah pertama login)
INSERT IGNORE INTO dashboard_user (User_Username, User_Password, User_DisplayName)
VALUES ('admin', '$2a$10$dArL7F97pp/JdtIYhY/xD.W5RqAgKiW/ZvJoY75b6oer7xrQx1UNC', 'Administrator');

View File

@@ -0,0 +1,68 @@
-- Migration 005: tambah kolom salt + stored procedure upsert dashboard user
ALTER TABLE dashboard_user
ADD COLUMN User_Salt VARCHAR(36) DEFAULT NULL AFTER User_Password;
-- ============================================================
-- sp_upsert_dashboard_user
-- Parameter:
-- p_username VARCHAR(50) -- required, unique key
-- p_password VARCHAR(255) -- plain text, akan di-hash di dalam SP
-- p_display_name VARCHAR(100) -- nama tampilan (boleh NULL)
-- Behaviour:
-- - INSERT jika username belum ada
-- - UPDATE password + display_name jika sudah ada
-- - Password di-hash: SHA2(UUID_salt + ':' + password, 256)
-- ============================================================
DROP PROCEDURE IF EXISTS sp_upsert_dashboard_user;
DELIMITER $$
CREATE PROCEDURE sp_upsert_dashboard_user(
IN p_username VARCHAR(50),
IN p_password VARCHAR(255),
IN p_display_name VARCHAR(100)
)
BEGIN
DECLARE v_salt VARCHAR(36);
DECLARE v_hash VARCHAR(64);
-- Validasi input
IF p_username IS NULL OR TRIM(p_username) = '' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Username tidak boleh kosong';
END IF;
IF p_password IS NULL OR TRIM(p_password) = '' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Password tidak boleh kosong';
END IF;
IF LENGTH(p_password) < 6 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Password minimal 6 karakter';
END IF;
-- Generate salt + hash
SET v_salt = UUID();
SET v_hash = SHA2(CONCAT(v_salt, ':', p_password), 256);
INSERT INTO dashboard_user
(User_Username, User_Password, User_Salt, User_DisplayName, User_IsActive)
VALUES
(TRIM(p_username), v_hash, v_salt, p_display_name, 'Y')
ON DUPLICATE KEY UPDATE
User_Password = v_hash,
User_Salt = v_salt,
User_DisplayName = COALESCE(p_display_name, User_DisplayName),
User_IsActive = 'Y',
User_UpdatedAt = NOW();
END $$
DELIMITER ;
-- Re-seed admin menggunakan SP (mengganti hash bcrypt lama)
CALL sp_upsert_dashboard_user('admin', 'admin123', 'Administrator');

View File

@@ -0,0 +1,100 @@
-- Migration 006: mapping user ke mcu_project (many-to-many)
CREATE TABLE IF NOT EXISTS dashboard_user_project (
UserProj_ID INT AUTO_INCREMENT PRIMARY KEY,
UserProj_UserID INT NOT NULL, -- dashboard_user.User_ID
UserProj_McuID INT NOT NULL, -- mcu_project.Mcu_ProjectMcuID
UserProj_IsActive CHAR(1) DEFAULT 'Y',
UserProj_CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,
UserProj_UpdatedAt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uq_user_mcu (UserProj_UserID, UserProj_McuID),
INDEX idx_user_id (UserProj_UserID),
INDEX idx_mcu_id (UserProj_McuID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ============================================================
-- sp_assign_user_project
-- Assign satu mcu_project ke satu user (idempotent).
-- Parameter:
-- p_username VARCHAR(50) -- username di dashboard_user
-- p_mcu_id INT -- Mcu_ProjectMcuID di mcu_project
-- ============================================================
DROP PROCEDURE IF EXISTS sp_assign_user_project;
DELIMITER $$
CREATE PROCEDURE sp_assign_user_project(
IN p_username VARCHAR(50),
IN p_mcu_id INT
)
BEGIN
DECLARE v_user_id INT;
-- Cari user
SELECT User_ID INTO v_user_id
FROM dashboard_user
WHERE User_Username = p_username AND User_IsActive = 'Y'
LIMIT 1;
IF v_user_id IS NULL THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'User tidak ditemukan atau tidak aktif';
END IF;
-- Validasi mcu_project ada
IF NOT EXISTS (
SELECT 1 FROM mcu_project WHERE Mcu_ProjectMcuID = p_mcu_id
) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'mcu_id tidak ditemukan di mcu_project';
END IF;
INSERT INTO dashboard_user_project (UserProj_UserID, UserProj_McuID, UserProj_IsActive)
VALUES (v_user_id, p_mcu_id, 'Y')
ON DUPLICATE KEY UPDATE
UserProj_IsActive = 'Y',
UserProj_UpdatedAt = NOW();
END $$
DELIMITER ;
-- ============================================================
-- sp_remove_user_project
-- Cabut akses satu mcu_project dari user (soft delete).
-- Parameter:
-- p_username VARCHAR(50)
-- p_mcu_id INT
-- ============================================================
DROP PROCEDURE IF EXISTS sp_remove_user_project;
DELIMITER $$
CREATE PROCEDURE sp_remove_user_project(
IN p_username VARCHAR(50),
IN p_mcu_id INT
)
BEGIN
DECLARE v_user_id INT;
SELECT User_ID INTO v_user_id
FROM dashboard_user
WHERE User_Username = p_username
LIMIT 1;
IF v_user_id IS NULL THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'User tidak ditemukan';
END IF;
UPDATE dashboard_user_project
SET UserProj_IsActive = 'N',
UserProj_UpdatedAt = NOW()
WHERE UserProj_UserID = v_user_id
AND UserProj_McuID = p_mcu_id;
END $$
DELIMITER ;

View File

@@ -0,0 +1,108 @@
-- Migration 007: pisah sp_upsert_dashboard_user menjadi insert dan update terpisah
DROP PROCEDURE IF EXISTS sp_upsert_dashboard_user;
-- ============================================================
-- sp_insert_dashboard_user
-- Hanya untuk membuat user BARU.
-- Error jika username sudah terdaftar.
-- Parameter:
-- p_username VARCHAR(50)
-- p_password VARCHAR(255) plain text, minimal 6 karakter
-- p_display_name VARCHAR(100) boleh NULL
-- ============================================================
DROP PROCEDURE IF EXISTS sp_insert_dashboard_user;
DELIMITER $$
CREATE PROCEDURE sp_insert_dashboard_user(
IN p_username VARCHAR(50),
IN p_password VARCHAR(255),
IN p_display_name VARCHAR(100)
)
BEGIN
DECLARE v_salt VARCHAR(36);
DECLARE v_hash VARCHAR(64);
IF p_username IS NULL OR TRIM(p_username) = '' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Username tidak boleh kosong';
END IF;
IF p_password IS NULL OR TRIM(p_password) = '' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Password tidak boleh kosong';
END IF;
IF LENGTH(p_password) < 6 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Password minimal 6 karakter';
END IF;
IF EXISTS (SELECT 1 FROM dashboard_user WHERE User_Username = TRIM(p_username)) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Username sudah terdaftar';
END IF;
SET v_salt = UUID();
SET v_hash = SHA2(CONCAT(v_salt, ':', p_password), 256);
INSERT INTO dashboard_user (User_Username, User_Password, User_Salt, User_DisplayName, User_IsActive)
VALUES (TRIM(p_username), v_hash, v_salt, p_display_name, 'Y');
END $$
DELIMITER ;
-- ============================================================
-- sp_reset_dashboard_user_password
-- Hanya untuk reset password user yang SUDAH ADA.
-- Error jika username tidak ditemukan.
-- Parameter:
-- p_username VARCHAR(50)
-- p_new_password VARCHAR(255) plain text, minimal 6 karakter
-- ============================================================
DROP PROCEDURE IF EXISTS sp_reset_dashboard_user_password;
DELIMITER $$
CREATE PROCEDURE sp_reset_dashboard_user_password(
IN p_username VARCHAR(50),
IN p_new_password VARCHAR(255)
)
BEGIN
DECLARE v_salt VARCHAR(36);
DECLARE v_hash VARCHAR(64);
IF p_new_password IS NULL OR TRIM(p_new_password) = '' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Password tidak boleh kosong';
END IF;
IF LENGTH(p_new_password) < 6 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Password minimal 6 karakter';
END IF;
IF NOT EXISTS (SELECT 1 FROM dashboard_user WHERE User_Username = TRIM(p_username)) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'User tidak ditemukan';
END IF;
SET v_salt = UUID();
SET v_hash = SHA2(CONCAT(v_salt, ':', p_new_password), 256);
UPDATE dashboard_user
SET User_Password = v_hash,
User_Salt = v_salt,
User_UpdatedAt = NOW()
WHERE User_Username = TRIM(p_username);
END $$
DELIMITER ;
-- Tidak perlu re-seed, user admin sudah ada dari migration 005

View File

@@ -0,0 +1,264 @@
-- Migration 008: fix Mcu_StationProgressCheckinDate di sp_generate_dashboard_data
-- Sebelumnya pakai DATE(T_OrderHeaderDate) — tanggal order, bukan tanggal station dikerjakan.
-- Seharusnya:
-- lab → DATE(SamplingAt), fallback T_OrderHeaderDate
-- nonlab → DATE(ProcessAt), fallback T_OrderHeaderDate
DROP PROCEDURE IF EXISTS sp_generate_dashboard_data;
DELIMITER $$
CREATE PROCEDURE sp_generate_dashboard_data(IN p_mcu_id INT)
BEGIN
-- ----------------------------------------------------------
-- 1. mcu_project
-- ----------------------------------------------------------
INSERT INTO mcu_project (
Mcu_ProjectMcuID, Mcu_ProjectCorporateID, Mcu_ProjectCorporateName,
Mcu_ProjectNumber, Mcu_ProjectLabel, Mcu_ProjectBranchID,
Mcu_ProjectStartDate, Mcu_ProjectEndDate, Mcu_ProjectIsActive,
Mcu_ProjectTotalParticipant, Mcu_ProjectSyncedAt
)
SELECT
m.Mgm_McuID, m.Mgm_McuCorporateID, c.CorporateName,
m.Mgm_McuNumber, m.Mgm_McuLabel, m.Mgm_McuM_BranchID,
m.Mgm_McuStartDate, m.Mgm_McuEndDate, m.Mgm_McuIsActive,
m.Mgm_McuTotalParticipant, NOW()
FROM cpone.mgm_mcu m
LEFT JOIN cpone.corporate c ON c.CorporateID = m.Mgm_McuCorporateID
WHERE m.Mgm_McuID = p_mcu_id
ON DUPLICATE KEY UPDATE
Mcu_ProjectCorporateName = VALUES(Mcu_ProjectCorporateName),
Mcu_ProjectLabel = VALUES(Mcu_ProjectLabel),
Mcu_ProjectIsActive = VALUES(Mcu_ProjectIsActive),
Mcu_ProjectTotalParticipant = VALUES(Mcu_ProjectTotalParticipant),
Mcu_ProjectSyncedAt = NOW();
-- ----------------------------------------------------------
-- 2. mcu_patient
-- ----------------------------------------------------------
INSERT INTO mcu_patient (
Mcu_PatientPreregisterID, Mcu_PatientMcuID, Mcu_PatientName,
Mcu_PatientNIP, Mcu_PatientGender, Mcu_PatientDOB,
Mcu_PatientDepartment, Mcu_PatientDivision, Mcu_PatientPosisi,
Mcu_PatientIsRegistered, Mcu_PatientOrderID, Mcu_PatientIsActive,
Mcu_PatientSyncedAt
)
SELECT
p.Mcu_PreregisterPatientsID, p.Mcu_PreregisterPatientsMgm_McuID,
p.Mcu_PreregisterPatientsPatientName, p.Mcu_PreregisterPatientsNIP,
p.Mcu_PreregisterPatientsGender, p.Mcu_PreregisterPatientsDOB,
p.Mcu_PreregisterPatientsDepartment, p.Mcu_PreregisterPatientsDivisi,
p.Mcu_PreregisterPatientsPosisi,
p.Mcu_PreregisterPatientsIsRegistered, p.Mcu_PreregisterPatientsT_OrderHeaderID,
p.Mcu_PreregisterPatientsIsActive, NOW()
FROM cpone.mcu_preregister_patients p
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
ON DUPLICATE KEY UPDATE
Mcu_PatientName = VALUES(Mcu_PatientName),
Mcu_PatientIsRegistered = VALUES(Mcu_PatientIsRegistered),
Mcu_PatientOrderID = VALUES(Mcu_PatientOrderID),
Mcu_PatientSyncedAt = NOW();
-- ----------------------------------------------------------
-- 3. mcu_patient_schedule
-- ----------------------------------------------------------
INSERT INTO mcu_patient_schedule (
Mcu_PatientSchedulePreregisterID, Mcu_PatientScheduleDate,
Mcu_PatientScheduleIsActive, Mcu_PatientScheduleSyncedAt
)
SELECT
p.Mcu_PreregisterPatientsID, DATE(o.T_OrderHeaderDate), 'Y', NOW()
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
ON DUPLICATE KEY UPDATE
Mcu_PatientScheduleSyncedAt = NOW();
-- ----------------------------------------------------------
-- 4. mcu_checkinout
-- ----------------------------------------------------------
INSERT INTO mcu_checkinout (
Mcu_CheckinoutMcuID, Mcu_CheckinoutPreregisterID, Mcu_CheckinoutOrderID,
Mcu_CheckinoutDate, Mcu_CheckinoutInTime, Mcu_CheckinoutOutTime,
Mcu_CheckinoutNextDate, Mcu_CheckinoutIsActive, Mcu_CheckinoutSyncedAt
)
SELECT
p_mcu_id,
src.preregister_id,
src.order_id,
src.segment_date,
TIME(src.checkin_dt),
TIME(src.checkout_dt),
CASE
WHEN DATE(src.checkout_dt) = src.segment_date THEN NULL
ELSE DATE(src.checkout_dt)
END,
'Y', NOW()
FROM (
SELECT
o.T_OrderHeaderID AS order_id,
p.Mcu_PreregisterPatientsID AS preregister_id,
o.T_OrderHeaderDate AS header_dt,
ev.segment_date,
CASE
WHEN ev.segment_date = DATE(o.T_OrderHeaderDate) THEN o.T_OrderHeaderDate
ELSE MIN(ev.event_dt)
END AS checkin_dt,
MAX(ev.event_dt) AS checkout_dt
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN (
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(o2.T_OrderHeaderDate) AS segment_date,
o2.T_OrderHeaderDate AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2 ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
UNION ALL
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(TIMESTAMP(s2.T_OrderSampleReceiveDate, s2.T_OrderSampleReceiveTime)) AS segment_date,
TIMESTAMP(s2.T_OrderSampleReceiveDate, s2.T_OrderSampleReceiveTime) AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2 ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_ordersample s2
ON s2.T_OrderSampleT_OrderHeaderID = o2.T_OrderHeaderID
AND s2.T_OrderSampleIsActive = 'Y'
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
AND s2.T_OrderSampleReceiveDate IS NOT NULL
AND s2.T_OrderSampleReceiveTime IS NOT NULL
UNION ALL
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(TIMESTAMP(ts2.T_SamplingSoDoneDate, ts2.T_SamplingSoDoneTime)) AS segment_date,
TIMESTAMP(ts2.T_SamplingSoDoneDate, ts2.T_SamplingSoDoneTime) AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2 ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_samplingso ts2
ON ts2.T_SamplingSoT_OrderHeaderID = o2.T_OrderHeaderID
AND ts2.T_SamplingSoIsActive = 'Y'
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
AND ts2.T_SamplingSoDoneDate IS NOT NULL
AND ts2.T_SamplingSoDoneTime IS NOT NULL
) ev
ON ev.preregister_id = p.Mcu_PreregisterPatientsID
AND ev.order_id = o.T_OrderHeaderID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
GROUP BY o.T_OrderHeaderID, p.Mcu_PreregisterPatientsID, o.T_OrderHeaderDate, ev.segment_date
) AS src
ON DUPLICATE KEY UPDATE
Mcu_CheckinoutOutTime = VALUES(Mcu_CheckinoutOutTime),
Mcu_CheckinoutNextDate = VALUES(Mcu_CheckinoutNextDate),
Mcu_CheckinoutSyncedAt = NOW();
-- ----------------------------------------------------------
-- 5. mcu_station_progress — lab (dari t_ordersample)
-- CheckinDate = DATE(SamplingAt), fallback DATE(T_OrderHeaderDate)
-- ----------------------------------------------------------
INSERT INTO mcu_station_progress (
Mcu_StationProgressOrderID, Mcu_StationProgressPreregisterID, Mcu_StationProgressMcuID,
Mcu_StationProgressStationID, Mcu_StationProgressStationName, Mcu_StationProgressSource,
Mcu_StationProgressCheckinDate,
Mcu_StationProgressSamplingAt, Mcu_StationProgressReceiveAt, Mcu_StationProgressProcessAt,
Mcu_StationProgressDoneAt, Mcu_StationProgressSyncedAt
)
SELECT
o.T_OrderHeaderID,
p.Mcu_PreregisterPatientsID,
p_mcu_id,
s.T_OrderSampleT_SampleStationID,
ss.T_SampleStationName,
'lab',
COALESCE(
DATE(NULLIF(MAX(TIMESTAMP(s.T_OrderSampleSamplingDate, s.T_OrderSampleSamplingTime)), '0000-00-00 00:00:00')),
DATE(o.T_OrderHeaderDate)
),
NULLIF(MAX(TIMESTAMP(s.T_OrderSampleSamplingDate, s.T_OrderSampleSamplingTime)), '0000-00-00 00:00:00'),
NULLIF(MAX(TIMESTAMP(s.T_OrderSampleReceiveDate, s.T_OrderSampleReceiveTime)), '0000-00-00 00:00:00'),
NULLIF(MAX(TIMESTAMP(s.T_OrderSampleProcessingDate, s.T_OrderSampleProcessingTime)), '0000-00-00 00:00:00'),
NULL,
NOW()
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_ordersample s ON s.T_OrderSampleT_OrderHeaderID = o.T_OrderHeaderID AND s.T_OrderSampleIsActive = 'Y'
JOIN cpone.t_samplestation ss ON ss.T_SampleStationID = s.T_OrderSampleT_SampleStationID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
GROUP BY o.T_OrderHeaderID, p.Mcu_PreregisterPatientsID, s.T_OrderSampleT_SampleStationID, ss.T_SampleStationName, o.T_OrderHeaderDate
ON DUPLICATE KEY UPDATE
Mcu_StationProgressCheckinDate = VALUES(Mcu_StationProgressCheckinDate),
Mcu_StationProgressSamplingAt = VALUES(Mcu_StationProgressSamplingAt),
Mcu_StationProgressReceiveAt = VALUES(Mcu_StationProgressReceiveAt),
Mcu_StationProgressProcessAt = VALUES(Mcu_StationProgressProcessAt),
Mcu_StationProgressSyncedAt = NOW();
-- ----------------------------------------------------------
-- 6. mcu_station_progress — nonlab (dari t_samplingso)
-- CheckinDate = DATE(ProcessAt), fallback DATE(T_OrderHeaderDate)
-- ----------------------------------------------------------
INSERT INTO mcu_station_progress (
Mcu_StationProgressOrderID, Mcu_StationProgressPreregisterID, Mcu_StationProgressMcuID,
Mcu_StationProgressStationID, Mcu_StationProgressStationName, Mcu_StationProgressSource,
Mcu_StationProgressCheckinDate,
Mcu_StationProgressSamplingAt, Mcu_StationProgressReceiveAt, Mcu_StationProgressProcessAt,
Mcu_StationProgressDoneAt, Mcu_StationProgressSyncedAt
)
SELECT
o.T_OrderHeaderID,
p.Mcu_PreregisterPatientsID,
p_mcu_id,
ts.T_SamplingSoT_SampleStationID,
ss.T_SampleStationName,
'nonlab',
COALESCE(
DATE(NULLIF(MAX(TIMESTAMP(ts.T_SamplingSoProcessDate, ts.T_SamplingSoProcessTime)), '0000-00-00 00:00:00')),
DATE(o.T_OrderHeaderDate)
),
NULL,
NULL,
NULLIF(MAX(TIMESTAMP(ts.T_SamplingSoProcessDate, ts.T_SamplingSoProcessTime)), '0000-00-00 00:00:00'),
NULLIF(MAX(TIMESTAMP(ts.T_SamplingSoDoneDate, ts.T_SamplingSoDoneTime)), '0000-00-00 00:00:00'),
NOW()
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_samplingso ts ON ts.T_SamplingSoT_OrderHeaderID = o.T_OrderHeaderID AND ts.T_SamplingSoIsActive = 'Y'
JOIN cpone.t_samplestation ss ON ss.T_SampleStationID = ts.T_SamplingSoT_SampleStationID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
GROUP BY o.T_OrderHeaderID, p.Mcu_PreregisterPatientsID, ts.T_SamplingSoT_SampleStationID, ss.T_SampleStationName, o.T_OrderHeaderDate
ON DUPLICATE KEY UPDATE
Mcu_StationProgressCheckinDate = VALUES(Mcu_StationProgressCheckinDate),
Mcu_StationProgressProcessAt = VALUES(Mcu_StationProgressProcessAt),
Mcu_StationProgressDoneAt = VALUES(Mcu_StationProgressDoneAt),
Mcu_StationProgressSyncedAt = NOW();
END $$
DELIMITER ;

View File

@@ -0,0 +1,13 @@
-- Migration 009: ganti Mcu_CheckinoutCheckinoutID dengan Mcu_CheckinoutMcuID
-- Kolom lama (CheckinoutCheckinoutID) tidak dipakai di aplikasi dan di SP
-- diisi dengan order_id yang salah. Ganti dengan mcu_id supaya query lebih simpel.
ALTER TABLE mcu_checkinout
DROP COLUMN Mcu_CheckinoutCheckinoutID,
ADD COLUMN Mcu_CheckinoutMcuID INT NOT NULL DEFAULT 0 AFTER Mcu_CheckinoutID,
ADD INDEX idx_mcu_id (Mcu_CheckinoutMcuID);
-- Isi Mcu_CheckinoutMcuID dari mcu_patient untuk data yang sudah ada
UPDATE mcu_checkinout mc
JOIN mcu_patient mp ON mp.Mcu_PatientPreregisterID = mc.Mcu_CheckinoutPreregisterID
SET mc.Mcu_CheckinoutMcuID = mp.Mcu_PatientMcuID;

View File

@@ -0,0 +1,259 @@
-- Migration 010: Add age column to mcu_patient and update SP
ALTER TABLE mcu_patient
ADD COLUMN Mcu_PatientAge INT DEFAULT NULL AFTER Mcu_PatientDOB;
-- Update SP: tambah age dari T_OrderHeader.M_PatientAge
DROP PROCEDURE IF EXISTS sp_generate_dashboard_data;
DELIMITER $$
CREATE PROCEDURE sp_generate_dashboard_data(IN p_mcu_id INT)
BEGIN
-- ----------------------------------------------------------
-- 1. mcu_project
-- ----------------------------------------------------------
INSERT INTO mcu_project (
Mcu_ProjectMcuID, Mcu_ProjectCorporateID, Mcu_ProjectCorporateName,
Mcu_ProjectNumber, Mcu_ProjectLabel, Mcu_ProjectBranchID,
Mcu_ProjectStartDate, Mcu_ProjectEndDate, Mcu_ProjectIsActive,
Mcu_ProjectTotalParticipant, Mcu_ProjectSyncedAt
)
SELECT
m.Mgm_McuID, m.Mgm_McuCorporateID, c.CorporateName,
m.Mgm_McuNumber, m.Mgm_McuLabel, m.Mgm_McuM_BranchID,
m.Mgm_McuStartDate, m.Mgm_McuEndDate, m.Mgm_McuIsActive,
m.Mgm_McuTotalParticipant, NOW()
FROM cpone.mgm_mcu m
LEFT JOIN cpone.corporate c ON c.CorporateID = m.Mgm_McuCorporateID
WHERE m.Mgm_McuID = p_mcu_id
ON DUPLICATE KEY UPDATE
Mcu_ProjectCorporateName = VALUES(Mcu_ProjectCorporateName),
Mcu_ProjectLabel = VALUES(Mcu_ProjectLabel),
Mcu_ProjectIsActive = VALUES(Mcu_ProjectIsActive),
Mcu_ProjectTotalParticipant = VALUES(Mcu_ProjectTotalParticipant),
Mcu_ProjectSyncedAt = NOW();
-- ----------------------------------------------------------
-- 2. mcu_patient (with age)
-- ----------------------------------------------------------
INSERT INTO mcu_patient (
Mcu_PatientPreregisterID, Mcu_PatientMcuID, Mcu_PatientName,
Mcu_PatientNIP, Mcu_PatientGender, Mcu_PatientDOB, Mcu_PatientAge,
Mcu_PatientDepartment, Mcu_PatientDivision, Mcu_PatientPosisi,
Mcu_PatientIsRegistered, Mcu_PatientOrderID, Mcu_PatientIsActive,
Mcu_PatientSyncedAt
)
SELECT
p.Mcu_PreregisterPatientsID, p.Mcu_PreregisterPatientsMgm_McuID,
p.Mcu_PreregisterPatientsPatientName, p.Mcu_PreregisterPatientsNIP,
p.Mcu_PreregisterPatientsGender, p.Mcu_PreregisterPatientsDOB,
o.T_OrderHeaderM_PatientAge,
p.Mcu_PreregisterPatientsDepartment, p.Mcu_PreregisterPatientsDivisi,
p.Mcu_PreregisterPatientsPosisi,
p.Mcu_PreregisterPatientsIsRegistered, p.Mcu_PreregisterPatientsT_OrderHeaderID,
p.Mcu_PreregisterPatientsIsActive, NOW()
FROM cpone.mcu_preregister_patients p
LEFT JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
ON DUPLICATE KEY UPDATE
Mcu_PatientName = VALUES(Mcu_PatientName),
Mcu_PatientAge = VALUES(Mcu_PatientAge),
Mcu_PatientIsRegistered = VALUES(Mcu_PatientIsRegistered),
Mcu_PatientOrderID = VALUES(Mcu_PatientOrderID),
Mcu_PatientSyncedAt = NOW();
-- ----------------------------------------------------------
-- 3. mcu_patient_schedule
-- ----------------------------------------------------------
INSERT INTO mcu_patient_schedule (
Mcu_PatientSchedulePreregisterID, Mcu_PatientScheduleDate,
Mcu_PatientScheduleIsActive, Mcu_PatientScheduleSyncedAt
)
SELECT
p.Mcu_PreregisterPatientsID, DATE(o.T_OrderHeaderDate), 'Y', NOW()
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
ON DUPLICATE KEY UPDATE
Mcu_PatientScheduleSyncedAt = NOW();
-- ----------------------------------------------------------
-- 4. mcu_checkinout
-- Satu baris per tanggal proses.
-- ----------------------------------------------------------
INSERT INTO mcu_checkinout (
Mcu_CheckinoutCheckinoutID, Mcu_CheckinoutPreregisterID, Mcu_CheckinoutOrderID,
Mcu_CheckinoutDate, Mcu_CheckinoutInTime, Mcu_CheckinoutOutTime,
Mcu_CheckinoutNextDate, Mcu_CheckinoutIsActive, Mcu_CheckinoutSyncedAt, Mcu_CheckinoutMcuID
)
SELECT
src.order_id,
src.preregister_id,
src.order_id,
src.segment_date,
TIME(src.checkin_dt),
TIME(src.checkout_dt),
CASE
WHEN DATE(src.checkout_dt) = src.segment_date THEN NULL
ELSE DATE(src.checkout_dt)
END,
'Y', NOW(), p_mcu_id
FROM (
SELECT
o.T_OrderHeaderID AS order_id,
p.Mcu_PreregisterPatientsID AS preregister_id,
o.T_OrderHeaderDate AS header_dt,
ev.segment_date,
CASE
WHEN ev.segment_date = DATE(o.T_OrderHeaderDate) THEN o.T_OrderHeaderDate
ELSE MIN(ev.event_dt)
END AS checkin_dt,
MAX(ev.event_dt) AS checkout_dt
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN (
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(o2.T_OrderHeaderDate) AS segment_date,
o2.T_OrderHeaderDate AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2 ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
UNION ALL
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(TIMESTAMP(s2.T_OrderSampleReceiveDate, s2.T_OrderSampleReceiveTime)) AS segment_date,
TIMESTAMP(s2.T_OrderSampleReceiveDate, s2.T_OrderSampleReceiveTime) AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2 ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_ordersample s2
ON s2.T_OrderSampleT_OrderHeaderID = o2.T_OrderHeaderID
AND s2.T_OrderSampleIsActive = 'Y'
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
AND s2.T_OrderSampleReceiveDate IS NOT NULL
AND s2.T_OrderSampleReceiveTime IS NOT NULL
UNION ALL
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(TIMESTAMP(ts2.T_SamplingSoDoneDate, ts2.T_SamplingSoDoneTime)) AS segment_date,
TIMESTAMP(ts2.T_SamplingSoDoneDate, ts2.T_SamplingSoDoneTime) AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2 ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_samplingso ts2
ON ts2.T_SamplingSoT_OrderHeaderID = o2.T_OrderHeaderID
AND ts2.T_SamplingSoIsActive = 'Y'
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
AND ts2.T_SamplingSoDoneDate IS NOT NULL
AND ts2.T_SamplingSoDoneTime IS NOT NULL
) ev
ON ev.preregister_id = p.Mcu_PreregisterPatientsID
AND ev.order_id = o.T_OrderHeaderID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
GROUP BY o.T_OrderHeaderID, p.Mcu_PreregisterPatientsID, o.T_OrderHeaderDate, ev.segment_date
) AS src
ON DUPLICATE KEY UPDATE
Mcu_CheckinoutOutTime = VALUES(Mcu_CheckinoutOutTime),
Mcu_CheckinoutNextDate = VALUES(Mcu_CheckinoutNextDate),
Mcu_CheckinoutSyncedAt = NOW();
-- ----------------------------------------------------------
-- 5. mcu_station_progress — lab (dari t_ordersample)
-- GROUP BY order+station supaya satu baris per pasien per station
-- ----------------------------------------------------------
INSERT INTO mcu_station_progress (
Mcu_StationProgressOrderID, Mcu_StationProgressPreregisterID, Mcu_StationProgressMcuID,
Mcu_StationProgressStationID, Mcu_StationProgressStationName, Mcu_StationProgressSource,
Mcu_StationProgressCheckinDate,
Mcu_StationProgressSamplingAt, Mcu_StationProgressReceiveAt, Mcu_StationProgressProcessAt,
Mcu_StationProgressDoneAt, Mcu_StationProgressSyncedAt
)
SELECT
o.T_OrderHeaderID,
p.Mcu_PreregisterPatientsID,
p_mcu_id,
s.T_OrderSampleT_SampleStationID,
ss.T_SampleStationName,
'lab',
DATE(o.T_OrderHeaderDate),
NULLIF(MAX(TIMESTAMP(s.T_OrderSampleSamplingDate, s.T_OrderSampleSamplingTime)), '0000-00-00 00:00:00'),
NULLIF(MAX(TIMESTAMP(s.T_OrderSampleReceiveDate, s.T_OrderSampleReceiveTime)), '0000-00-00 00:00:00'),
NULLIF(MAX(TIMESTAMP(s.T_OrderSampleProcessingDate, s.T_OrderSampleProcessingTime)), '0000-00-00 00:00:00'),
NULL,
NOW()
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_ordersample s ON s.T_OrderSampleT_OrderHeaderID = o.T_OrderHeaderID AND s.T_OrderSampleIsActive = 'Y'
JOIN cpone.t_samplestation ss ON ss.T_SampleStationID = s.T_OrderSampleT_SampleStationID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
GROUP BY o.T_OrderHeaderID, p.Mcu_PreregisterPatientsID, s.T_OrderSampleT_SampleStationID, ss.T_SampleStationName, o.T_OrderHeaderDate
ON DUPLICATE KEY UPDATE
Mcu_StationProgressSamplingAt = VALUES(Mcu_StationProgressSamplingAt),
Mcu_StationProgressReceiveAt = VALUES(Mcu_StationProgressReceiveAt),
Mcu_StationProgressProcessAt = VALUES(Mcu_StationProgressProcessAt),
Mcu_StationProgressSyncedAt = NOW();
-- ----------------------------------------------------------
-- 6. mcu_station_progress — nonlab (dari t_samplingso)
-- ----------------------------------------------------------
INSERT INTO mcu_station_progress (
Mcu_StationProgressOrderID, Mcu_StationProgressPreregisterID, Mcu_StationProgressMcuID,
Mcu_StationProgressStationID, Mcu_StationProgressStationName, Mcu_StationProgressSource,
Mcu_StationProgressCheckinDate,
Mcu_StationProgressSamplingAt, Mcu_StationProgressReceiveAt, Mcu_StationProgressProcessAt,
Mcu_StationProgressDoneAt, Mcu_StationProgressSyncedAt
)
SELECT
o.T_OrderHeaderID,
p.Mcu_PreregisterPatientsID,
p_mcu_id,
ts.T_SamplingSoT_SampleStationID,
ss.T_SampleStationName,
'nonlab',
DATE(o.T_OrderHeaderDate),
NULL,
NULL,
NULLIF(MAX(TIMESTAMP(ts.T_SamplingSoProcessDate, ts.T_SamplingSoProcessTime)), '0000-00-00 00:00:00'),
NULLIF(MAX(TIMESTAMP(ts.T_SamplingSoDoneDate, ts.T_SamplingSoDoneTime)), '0000-00-00 00:00:00'),
NOW()
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_samplingso ts ON ts.T_SamplingSoT_OrderHeaderID = o.T_OrderHeaderID AND ts.T_SamplingSoIsActive = 'Y'
JOIN cpone.t_samplestation ss ON ss.T_SampleStationID = ts.T_SamplingSoT_SampleStationID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
GROUP BY o.T_OrderHeaderID, p.Mcu_PreregisterPatientsID, ts.T_SamplingSoT_SampleStationID, ss.T_SampleStationName, o.T_OrderHeaderDate
ON DUPLICATE KEY UPDATE
Mcu_StationProgressProcessAt = VALUES(Mcu_StationProgressProcessAt),
Mcu_StationProgressDoneAt = VALUES(Mcu_StationProgressDoneAt),
Mcu_StationProgressSyncedAt = NOW();
END $$
DELIMITER ;

View File

@@ -0,0 +1,274 @@
-- Migration 011: Add mcu_patient_resume_status table
CREATE TABLE IF NOT EXISTS mcu_patient_resume_status (
Mcu_PatientResumeStatusID INT AUTO_INCREMENT PRIMARY KEY,
Mcu_PatientResumeStatusPreregisterID INT NOT NULL,
Mcu_PatientResumeStatusMcuID INT NOT NULL,
Mcu_PatientResumeStatusStatus VARCHAR(15), -- from mcu_resume.Mcu_ResumeStatus
Mcu_PatientResumeStatusValidated CHAR(1) DEFAULT 'N', -- from mcu_resume.Mcu_ResumeValidation
Mcu_PatientResumeStatusPublished CHAR(1) DEFAULT 'N', -- default N
Mcu_PatientResumeSyncedAt DATETIME,
UNIQUE KEY uq_patient_mcu (Mcu_PatientResumeStatusPreregisterID, Mcu_PatientResumeStatusMcuID),
INDEX idx_mcu_id (Mcu_PatientResumeStatusMcuID),
INDEX idx_preregister_id (Mcu_PatientResumeStatusPreregisterID),
INDEX idx_validated (Mcu_PatientResumeStatusValidated),
INDEX idx_published (Mcu_PatientResumeStatusPublished)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Update SP: tambah step 7 untuk mcu_patient_resume_status
DROP PROCEDURE IF EXISTS sp_generate_dashboard_data;
DELIMITER $$
CREATE PROCEDURE sp_generate_dashboard_data(IN p_mcu_id INT)
BEGIN
-- ----------------------------------------------------------
-- 1. mcu_patient (with age)
-- ----------------------------------------------------------
INSERT INTO mcu_patient (
Mcu_PatientPreregisterID, Mcu_PatientMcuID, Mcu_PatientName,
Mcu_PatientNIP, Mcu_PatientGender, Mcu_PatientDOB, Mcu_PatientAge,
Mcu_PatientDepartment, Mcu_PatientDivision, Mcu_PatientPosisi,
Mcu_PatientIsRegistered, Mcu_PatientOrderID, Mcu_PatientIsActive,
Mcu_PatientSyncedAt
)
SELECT
p.Mcu_PreregisterPatientsID, p.Mcu_PreregisterPatientsMgm_McuID,
p.Mcu_PreregisterPatientsPatientName, p.Mcu_PreregisterPatientsNIP,
p.Mcu_PreregisterPatientsGender, p.Mcu_PreregisterPatientsDOB,
CAST(o.T_OrderHeaderM_PatientAge AS UNSIGNED),
p.Mcu_PreregisterPatientsDepartment, p.Mcu_PreregisterPatientsDivisi,
p.Mcu_PreregisterPatientsPosisi,
p.Mcu_PreregisterPatientsIsRegistered, p.Mcu_PreregisterPatientsT_OrderHeaderID,
p.Mcu_PreregisterPatientsIsActive, NOW()
FROM cpone.mcu_preregister_patients p
LEFT JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
ON DUPLICATE KEY UPDATE
Mcu_PatientName = VALUES(Mcu_PatientName),
Mcu_PatientAge = VALUES(Mcu_PatientAge),
Mcu_PatientIsRegistered = VALUES(Mcu_PatientIsRegistered),
Mcu_PatientOrderID = VALUES(Mcu_PatientOrderID),
Mcu_PatientSyncedAt = NOW();
-- ----------------------------------------------------------
-- 2. mcu_patient_schedule
-- ----------------------------------------------------------
INSERT INTO mcu_patient_schedule (
Mcu_PatientSchedulePreregisterID, Mcu_PatientScheduleDate,
Mcu_PatientScheduleIsActive, Mcu_PatientScheduleSyncedAt
)
SELECT
p.Mcu_PreregisterPatientsID, DATE(o.T_OrderHeaderDate), 'Y', NOW()
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
ON DUPLICATE KEY UPDATE
Mcu_PatientScheduleSyncedAt = NOW();
-- ----------------------------------------------------------
-- 3. mcu_checkinout
-- Satu baris per tanggal proses.
-- ----------------------------------------------------------
INSERT INTO mcu_checkinout (
Mcu_CheckinoutCheckinoutID, Mcu_CheckinoutPreregisterID, Mcu_CheckinoutOrderID,
Mcu_CheckinoutDate, Mcu_CheckinoutInTime, Mcu_CheckinoutOutTime,
Mcu_CheckinoutNextDate, Mcu_CheckinoutIsActive, Mcu_CheckinoutSyncedAt, Mcu_CheckinoutMcuID
)
SELECT
src.order_id,
src.preregister_id,
src.order_id,
src.segment_date,
TIME(src.checkin_dt),
TIME(src.checkout_dt),
CASE
WHEN DATE(src.checkout_dt) = src.segment_date THEN NULL
ELSE DATE(src.checkout_dt)
END,
'Y', NOW(), p_mcu_id
FROM (
SELECT
o.T_OrderHeaderID AS order_id,
p.Mcu_PreregisterPatientsID AS preregister_id,
o.T_OrderHeaderDate AS header_dt,
ev.segment_date,
CASE
WHEN ev.segment_date = DATE(o.T_OrderHeaderDate) THEN o.T_OrderHeaderDate
ELSE MIN(ev.event_dt)
END AS checkin_dt,
MAX(ev.event_dt) AS checkout_dt
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN (
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(o2.T_OrderHeaderDate) AS segment_date,
o2.T_OrderHeaderDate AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2 ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
UNION ALL
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(TIMESTAMP(s2.T_OrderSampleReceiveDate, s2.T_OrderSampleReceiveTime)) AS segment_date,
TIMESTAMP(s2.T_OrderSampleReceiveDate, s2.T_OrderSampleReceiveTime) AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2 ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_ordersample s2
ON s2.T_OrderSampleT_OrderHeaderID = o2.T_OrderHeaderID
AND s2.T_OrderSampleIsActive = 'Y'
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
AND s2.T_OrderSampleReceiveDate IS NOT NULL
AND s2.T_OrderSampleReceiveTime IS NOT NULL
UNION ALL
SELECT
p2.Mcu_PreregisterPatientsID AS preregister_id,
o2.T_OrderHeaderID AS order_id,
o2.T_OrderHeaderDate AS checkin_dt,
DATE(TIMESTAMP(ts2.T_SamplingSoDoneDate, ts2.T_SamplingSoDoneTime)) AS segment_date,
TIMESTAMP(ts2.T_SamplingSoDoneDate, ts2.T_SamplingSoDoneTime) AS event_dt
FROM cpone.mcu_preregister_patients p2
JOIN cpone.t_orderheader o2 ON o2.T_OrderHeaderID = p2.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_samplingso ts2
ON ts2.T_SamplingSoT_OrderHeaderID = o2.T_OrderHeaderID
AND ts2.T_SamplingSoIsActive = 'Y'
WHERE p2.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p2.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p2.Mcu_PreregisterPatientsIsActive = 'Y'
AND ts2.T_SamplingSoDoneDate IS NOT NULL
AND ts2.T_SamplingSoDoneTime IS NOT NULL
) ev
ON ev.preregister_id = p.Mcu_PreregisterPatientsID
AND ev.order_id = o.T_OrderHeaderID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
GROUP BY o.T_OrderHeaderID, p.Mcu_PreregisterPatientsID, o.T_OrderHeaderDate, ev.segment_date
) AS src
ON DUPLICATE KEY UPDATE
Mcu_CheckinoutOutTime = VALUES(Mcu_CheckinoutOutTime),
Mcu_CheckinoutNextDate = VALUES(Mcu_CheckinoutNextDate),
Mcu_CheckinoutSyncedAt = NOW();
-- ----------------------------------------------------------
-- 4. mcu_station_progress — lab (dari t_ordersample)
-- GROUP BY order+station supaya satu baris per pasien per station
-- ----------------------------------------------------------
INSERT INTO mcu_station_progress (
Mcu_StationProgressOrderID, Mcu_StationProgressPreregisterID, Mcu_StationProgressMcuID,
Mcu_StationProgressStationID, Mcu_StationProgressStationName, Mcu_StationProgressSource,
Mcu_StationProgressCheckinDate,
Mcu_StationProgressSamplingAt, Mcu_StationProgressReceiveAt, Mcu_StationProgressProcessAt,
Mcu_StationProgressDoneAt, Mcu_StationProgressSyncedAt
)
SELECT
o.T_OrderHeaderID,
p.Mcu_PreregisterPatientsID,
p_mcu_id,
s.T_OrderSampleT_SampleStationID,
ss.T_SampleStationName,
'lab',
DATE(o.T_OrderHeaderDate),
NULLIF(MAX(TIMESTAMP(s.T_OrderSampleSamplingDate, s.T_OrderSampleSamplingTime)), '0000-00-00 00:00:00'),
NULLIF(MAX(TIMESTAMP(s.T_OrderSampleReceiveDate, s.T_OrderSampleReceiveTime)), '0000-00-00 00:00:00'),
NULLIF(MAX(TIMESTAMP(s.T_OrderSampleProcessingDate, s.T_OrderSampleProcessingTime)), '0000-00-00 00:00:00'),
NULL,
NOW()
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_ordersample s ON s.T_OrderSampleT_OrderHeaderID = o.T_OrderHeaderID AND s.T_OrderSampleIsActive = 'Y'
JOIN cpone.t_samplestation ss ON ss.T_SampleStationID = s.T_OrderSampleT_SampleStationID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
GROUP BY o.T_OrderHeaderID, p.Mcu_PreregisterPatientsID, s.T_OrderSampleT_SampleStationID, ss.T_SampleStationName, o.T_OrderHeaderDate
ON DUPLICATE KEY UPDATE
Mcu_StationProgressSamplingAt = VALUES(Mcu_StationProgressSamplingAt),
Mcu_StationProgressReceiveAt = VALUES(Mcu_StationProgressReceiveAt),
Mcu_StationProgressProcessAt = VALUES(Mcu_StationProgressProcessAt),
Mcu_StationProgressSyncedAt = NOW();
-- ----------------------------------------------------------
-- 5. mcu_station_progress — nonlab (dari t_samplingso)
-- ----------------------------------------------------------
INSERT INTO mcu_station_progress (
Mcu_StationProgressOrderID, Mcu_StationProgressPreregisterID, Mcu_StationProgressMcuID,
Mcu_StationProgressStationID, Mcu_StationProgressStationName, Mcu_StationProgressSource,
Mcu_StationProgressCheckinDate,
Mcu_StationProgressSamplingAt, Mcu_StationProgressReceiveAt, Mcu_StationProgressProcessAt,
Mcu_StationProgressDoneAt, Mcu_StationProgressSyncedAt
)
SELECT
o.T_OrderHeaderID,
p.Mcu_PreregisterPatientsID,
p_mcu_id,
ts.T_SamplingSoT_SampleStationID,
ss.T_SampleStationName,
'nonlab',
DATE(o.T_OrderHeaderDate),
NULL,
NULL,
NULLIF(MAX(TIMESTAMP(ts.T_SamplingSoProcessDate, ts.T_SamplingSoProcessTime)), '0000-00-00 00:00:00'),
NULLIF(MAX(TIMESTAMP(ts.T_SamplingSoDoneDate, ts.T_SamplingSoDoneTime)), '0000-00-00 00:00:00'),
NOW()
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
JOIN cpone.t_samplingso ts ON ts.T_SamplingSoT_OrderHeaderID = o.T_OrderHeaderID AND ts.T_SamplingSoIsActive = 'Y'
JOIN cpone.t_samplestation ss ON ss.T_SampleStationID = ts.T_SamplingSoT_SampleStationID
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
GROUP BY o.T_OrderHeaderID, p.Mcu_PreregisterPatientsID, ts.T_SamplingSoT_SampleStationID, ss.T_SampleStationName, o.T_OrderHeaderDate
ON DUPLICATE KEY UPDATE
Mcu_StationProgressProcessAt = VALUES(Mcu_StationProgressProcessAt),
Mcu_StationProgressDoneAt = VALUES(Mcu_StationProgressDoneAt),
Mcu_StationProgressSyncedAt = NOW();
-- ----------------------------------------------------------
-- 6. mcu_patient_resume_status (dari mcu_resume)
-- ----------------------------------------------------------
INSERT INTO mcu_patient_resume_status (
Mcu_PatientResumeStatusPreregisterID, Mcu_PatientResumeStatusMcuID,
Mcu_PatientResumeStatusStatus, Mcu_PatientResumeStatusValidated,
Mcu_PatientResumeStatusPublished, Mcu_PatientResumeSyncedAt
)
SELECT
p.Mcu_PreregisterPatientsID,
p_mcu_id,
r.Mcu_ResumeStatus,
r.Mcu_ResumeValidation,
'N',
NOW()
FROM cpone.mcu_preregister_patients p
JOIN cpone.t_orderheader o ON o.T_OrderHeaderID = p.Mcu_PreregisterPatientsT_OrderHeaderID
LEFT JOIN cpone.mcu_resume r ON r.Mcu_ResumeT_OrderHeaderID = o.T_OrderHeaderID AND r.Mcu_ResumeIsActive = 'Y'
WHERE p.Mcu_PreregisterPatientsMgm_McuID = p_mcu_id
AND p.Mcu_PreregisterPatientsT_OrderHeaderID > 0
AND p.Mcu_PreregisterPatientsIsActive = 'Y'
ON DUPLICATE KEY UPDATE
Mcu_PatientResumeStatusStatus = VALUES(Mcu_PatientResumeStatusStatus),
Mcu_PatientResumeStatusValidated = VALUES(Mcu_PatientResumeStatusValidated),
Mcu_PatientResumeSyncedAt = NOW();
END $$
DELIMITER ;