Initial commit
This commit is contained in:
33
cpone-dashboard/db/db.go
Normal file
33
cpone-dashboard/db/db.go
Normal 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
|
||||
}
|
||||
123
cpone-dashboard/db/migrations/001_init_schema.sql
Normal file
123
cpone-dashboard/db/migrations/001_init_schema.sql
Normal 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;
|
||||
250
cpone-dashboard/db/migrations/002_sp_generate_data.sql
Normal file
250
cpone-dashboard/db/migrations/002_sp_generate_data.sql
Normal 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 ;
|
||||
269
cpone-dashboard/db/migrations/003_sp_add_station_progress.sql
Normal file
269
cpone-dashboard/db/migrations/003_sp_add_station_progress.sql
Normal 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 ;
|
||||
17
cpone-dashboard/db/migrations/004_dashboard_user.sql
Normal file
17
cpone-dashboard/db/migrations/004_dashboard_user.sql
Normal 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');
|
||||
@@ -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');
|
||||
100
cpone-dashboard/db/migrations/006_dashboard_user_project.sql
Normal file
100
cpone-dashboard/db/migrations/006_dashboard_user_project.sql
Normal 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 ;
|
||||
108
cpone-dashboard/db/migrations/007_sp_fix_dashboard_user.sql
Normal file
108
cpone-dashboard/db/migrations/007_sp_fix_dashboard_user.sql
Normal 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
|
||||
264
cpone-dashboard/db/migrations/008_sp_fix_checkin_date.sql
Normal file
264
cpone-dashboard/db/migrations/008_sp_fix_checkin_date.sql
Normal 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 ;
|
||||
13
cpone-dashboard/db/migrations/009_checkinout_add_mcu_id.sql
Normal file
13
cpone-dashboard/db/migrations/009_checkinout_add_mcu_id.sql
Normal 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;
|
||||
259
cpone-dashboard/db/migrations/010_patient_add_age.sql
Normal file
259
cpone-dashboard/db/migrations/010_patient_add_age.sql
Normal 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 ;
|
||||
274
cpone-dashboard/db/migrations/011_patient_resume_status.sql
Normal file
274
cpone-dashboard/db/migrations/011_patient_resume_status.sql
Normal 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 ;
|
||||
Reference in New Issue
Block a user