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

View File

@@ -0,0 +1,417 @@
#!/usr/bin/env python3
"""
demo_seed.py — Generate demo data for MCU PROJECT DEMO 2026 (ID=9999)
Usage: python3 demo_seed.py | mysql -u admin -pSasone!102938 cpone_dashboard
Data distribution:
- 1500 patients, 75/day over April 20 May 9, 2026
- April 2028 (days 08, patients 1675): fully completed MCU
- every 15th patient: 2-day checkin
- April 29 (day 9, patients 676750): checked in, most stations done
- a few lab stations still processing
- April 30 (day 10, patients 751825): ongoing today
- 751810 (60 patients): checked in this morning, partial stations
- 811825 (15 patients): not yet arrived
- May 19 (days 1119, patients 8261500): not yet
"""
from datetime import date, datetime, timedelta
# ── constants ──────────────────────────────────────────────────────────────────
MCU_ID = 9999
BASE_ID = 900000 # preregister_id = BASE_ID + i (900001901500)
START_DATE = date(2026, 4, 20)
TODAY = date(2026, 4, 30)
N_PATIENTS = 1500
PER_DAY = 75
MALE_FIRST = ['Budi','Agus','Deni','Rizki','Hendra','Andi','Fajar','Rendi',
'Wahyu','Dito','Bagas','Kevin','Andre','Yoga','Raka','Faisal',
'Eko','Iwan','Joko','Teguh']
FEMALE_FIRST= ['Siti','Ani','Dewi','Rina','Fitri','Nurul','Lilis','Putri',
'Nadya','Citra','Alya','Sinta','Nabila','Dian','Reni','Maya',
'Ira','Yuni','Wati','Tini']
LAST_NAMES = ['Santoso','Wijaya','Pratama','Kurnia','Saputra','Wulandari',
'Lestari','Nugroho','Halim','Sari','Rahman','Hidayat',
'Firmansyah','Kusuma','Raharjo','Setiawan','Wahyudi','Susanto',
'Purnomo','Hakim','Mulyadi','Astuti','Permata','Handoko','Budiman']
DEPTS = ['HR','Finance','Production','Engineering','IT','QA','Procurement',
'Warehouse','Security','Marketing','Legal','Operations','HSE',
'Maintenance','Accounting','Sales','Logistics','R&D','Admin','Management']
POSITIONS = ['Staff','Supervisor','Manager','Operator','Technician','Analyst',
'Coordinator','Head','Specialist','Officer','Inspector','Foreman',
'Executive','Director','Senior Staff']
# stations: (station_id, name, source)
STATIONS = [
(1, 'Sample Station Phlebotomy', 'lab'),
(31, 'Sample Station Urine', 'lab'),
(17, 'Sample Station TB/BB', 'nonlab'),
(4, 'Sample Station Treadmill', 'nonlab'),
(5, 'Sample Station ECG', 'nonlab'),
(2, 'Sample Station Rontgen', 'nonlab'),
(7, 'Sample Station Pemeriksaan Fisik', 'nonlab'),
(33, 'Sample Station Visus dan Buta Warna','nonlab'),
]
KELAINAN_GROUPS = [
('BMI', 'BMI Abnormal', 0.28),
('Hipertensi', 'Hipertensi', 0.15),
('Kelainan Visus', 'Kelainan Refraksi', 0.20),
('Ganguan Metabolisme Lemak', 'Dislipidemia', 0.12),
('Kelainan Hematologi', 'Hemoglobin Rendah', 0.08),
('Kelainan Fisik', 'Kelainan Muskuloskeletal', 0.10),
]
FITNESS_CATS = {
'BMI': ('Fit dengan Catatan', 'Fit with Note', 2),
'Hipertensi': ('Tidak Fit Sementara','Temporary Unfit',3),
'Kelainan Visus': ('Fit dengan Catatan', 'Fit with Note', 2),
'Ganguan Metabolisme Lemak': ('Fit dengan Catatan', 'Fit with Note', 2),
'Kelainan Hematologi': ('Fit dengan Catatan', 'Fit with Note', 2),
'Kelainan Fisik': ('Fit dengan Catatan', 'Fit with Note', 2),
}
PDF_BASE = '2026/04'
PDF_COUNT = 80 # patients 180 get a PDF file
lines = []
def q(s):
if s is None:
return 'NULL'
return "'" + str(s).replace("'", "''") + "'"
def dt(d, h, m, extra_min=0):
"""Return DATETIME string for date d, time h:m plus extra_min."""
base = datetime(d.year, d.month, d.day, h, m)
base += timedelta(minutes=extra_min)
return base.strftime('%Y-%m-%d %H:%M:%S')
# ── header ─────────────────────────────────────────────────────────────────────
lines.append("SET FOREIGN_KEY_CHECKS = 0;")
lines.append("SET @mcu = 9999;")
lines.append("")
# ── cleanup ────────────────────────────────────────────────────────────────────
lines.append("-- cleanup existing demo data")
lines.append("DELETE FROM mcu_station_progress WHERE Mcu_StationProgressMcuID = 9999;")
lines.append("DELETE FROM mcu_checkinout WHERE Mcu_CheckinoutMcuID = 9999;")
lines.append("DELETE FROM mcu_patient_required_station WHERE preregister_id BETWEEN 900001 AND 901500;")
lines.append("DELETE FROM mcu_patient_schedule WHERE Mcu_PatientSchedulePreregisterID BETWEEN 900001 AND 901500;")
lines.append("DELETE FROM mcu_patient_resume_status WHERE Mcu_PatientResumeStatusMcuID = 9999;")
lines.append("DELETE FROM published_mcu_dashboard_sync WHERE Published_McuDasboardT_OrderHeaderID BETWEEN 900001 AND 901500;")
lines.append("DELETE FROM kelainan_details WHERE Mgm_McuID = 9999;")
lines.append("DELETE FROM mcu_participant_daily WHERE Mcu_ParticipantDailyMcuID = 9999;")
lines.append("DELETE FROM mcu_patient WHERE Mcu_PatientMcuID = 9999;")
lines.append("DELETE FROM mcu_project WHERE Mcu_ProjectMcuID = 9999;")
lines.append("")
# ── project ────────────────────────────────────────────────────────────────────
lines.append("-- project")
lines.append(
"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) "
"VALUES "
f"(9999, 9999, 'PT DEMO CORPORATION', 'MCU-DEMO-2026', 'MCU PROJECT DEMO 2026', "
f"1, '2026-04-20', '2026-05-10', 'Y', 1500, NOW());"
)
lines.append("")
# ── participant daily ──────────────────────────────────────────────────────────
lines.append("-- participant daily totals")
daily_rows = []
for day_idx in range(20):
d = START_DATE + timedelta(days=day_idx)
daily_rows.append(
f"(9999, '{d}', {PER_DAY}, 'Y', NOW(), NOW())"
)
lines.append(
"INSERT INTO mcu_participant_daily "
"(Mcu_ParticipantDailyMcuID, Mcu_ParticipantDailyDate, Mcu_ParticipantDailyTotal, "
" Mcu_ParticipantDailyIsActive, Mcu_ParticipantDailyCreated, Mcu_ParticipantDailyLastUpdated) "
"VALUES\n " + ",\n ".join(daily_rows) + ";"
)
lines.append("")
# ── patients, schedules, required stations, checkinout, stations ───────────────
patient_rows = []
schedule_rows = []
req_station_rows = [] # location_id 18 per station, unique per (preregister_id, location_id)
checkin_rows = []
station_rows = []
resume_rows = []
published_rows = []
kelainan_rows = []
for i in range(1, N_PATIENTS + 1):
pid = BASE_ID + i # preregister_id
oid = BASE_ID + i # order_id (same for simplicity)
day_idx = (i - 1) // PER_DAY
sched_date = START_DATE + timedelta(days=day_idx)
# name / gender
g_idx = (i - 1) % 40
if g_idx < 20:
gender = 'Male'
first = MALE_FIRST[g_idx % len(MALE_FIRST)]
else:
gender = 'Female'
first = FEMALE_FIRST[(g_idx - 20) % len(FEMALE_FIRST)]
last = LAST_NAMES[(i + 7) % len(LAST_NAMES)]
name = f"{first} {last}"
nip = f"EMP{pid}"
dept = DEPTS[(i + 3) % len(DEPTS)]
posisi = POSITIONS[i % len(POSITIONS)]
age = 22 + ((i * 3 + 7) % 34) # 2255
dob = date(2026 - age, 1, 1).isoformat()
lab_no = f"R2604{i:04d}"
patient_rows.append(
f"({pid}, {MCU_ID}, {q(name)}, {q(nip)}, {q(gender)}, "
f"{q(dob)}, {age}, {q(dept)}, {q(posisi)}, "
f"{oid}, 'Y', 'Y', NOW())"
)
schedule_rows.append(
f"({pid}, '{sched_date}', 'Y', NOW())"
)
# required stations — location_id 18 per station so unique key (preregister_id, location_id) holds
for loc_id, (sid, sname, _) in enumerate(STATIONS, start=1):
req_station_rows.append(
f"({MCU_ID}, {pid}, {oid}, {loc_id}, {sid}, {q(sname)})"
)
# ─ checkinout & station progress ─────────────────────────────────────────
is_two_day = (i % 15 == 0) and (sched_date <= date(2026, 4, 28))
cin_h = 7 + (i % 3)
cin_m = (i * 7) % 60
def add_checkin(d, h, m, out_offset_min):
ci = dt(d, h, m)
co = dt(d, h, m, out_offset_min) if out_offset_min else 'NULL'
co_val = q(co) if out_offset_min else 'NULL'
checkin_rows.append(
f"({MCU_ID}, {pid}, {oid}, '{d}', '{h:02d}:{m:02d}:00', {co_val}, 'Y', NOW())"
)
def add_station(d, sid, sname, src, sampling_off, recv_off, proc_off, done_off):
"""All offsets in minutes from d h:m; None = NULL."""
base_h, base_m = cin_h, cin_m
def ts(off):
if off is None: return 'NULL'
return q(dt(d, base_h, base_m, off))
if src == 'lab':
station_rows.append(
f"({oid}, {pid}, {MCU_ID}, {sid}, {q(sname)}, {q(src)}, '{d}', "
f"{ts(sampling_off)}, {ts(recv_off)}, {ts(proc_off)}, {ts(done_off)}, NOW())"
)
else:
station_rows.append(
f"({oid}, {pid}, {MCU_ID}, {sid}, {q(sname)}, {q(src)}, '{d}', "
f"NULL, NULL, {ts(proc_off)}, {ts(done_off)}, NOW())"
)
# ─ CASE 1: fully done (April 2028) ──────────────────────────────────────
if sched_date < date(2026, 4, 29):
if is_two_day:
# day 1: 4 stations, day 2: remaining 4
add_checkin(sched_date, cin_h, cin_m, 200)
# day 1 stations
add_station(sched_date, 1, 'Sample Station Phlebotomy', 'lab', 30, 45, 90, 120)
add_station(sched_date, 31, 'Sample Station Urine', 'lab', 20, 35, 75, 95)
add_station(sched_date, 17, 'Sample Station TB/BB', 'nonlab', None,None, 15, 25)
add_station(sched_date, 4, 'Sample Station Treadmill', 'nonlab', None,None, 45, 65)
# day 2
d2 = sched_date + timedelta(days=1)
add_checkin(d2, 8, 0, 180)
# for day2 stations, use 8:00 as base — override cin_h/cin_m temporarily
orig_h, orig_m = cin_h, cin_m
cin_h, cin_m = 8, 0
add_station(d2, 5, 'Sample Station ECG', 'nonlab', None,None, 20, 35)
add_station(d2, 2, 'Sample Station Rontgen', 'nonlab', None,None, 50, 70)
add_station(d2, 7, 'Sample Station Pemeriksaan Fisik', 'nonlab', None,None, 80, 100)
add_station(d2, 33, 'Sample Station Visus dan Buta Warna','nonlab', None,None,115, 135)
cin_h, cin_m = orig_h, orig_m
else:
add_checkin(sched_date, cin_h, cin_m, 240 + (i % 60))
add_station(sched_date, 1, 'Sample Station Phlebotomy', 'lab', 30, 45, 90, 120)
add_station(sched_date, 31, 'Sample Station Urine', 'lab', 20, 35, 75, 95)
add_station(sched_date, 17, 'Sample Station TB/BB', 'nonlab', None,None, 15, 25)
add_station(sched_date, 4, 'Sample Station Treadmill', 'nonlab', None,None, 45, 65)
add_station(sched_date, 5, 'Sample Station ECG', 'nonlab', None,None, 75, 95)
add_station(sched_date, 2, 'Sample Station Rontgen', 'nonlab', None,None,110, 130)
add_station(sched_date, 7, 'Sample Station Pemeriksaan Fisik', 'nonlab', None,None,145, 165)
add_station(sched_date, 33, 'Sample Station Visus dan Buta Warna','nonlab',None,None,175, 200)
# ─ CASE 2: April 29 — checked in, most stations done ────────────────────
elif sched_date == date(2026, 4, 29):
add_checkin(sched_date, cin_h, cin_m, None) # no checkout yet
add_station(sched_date, 17, 'Sample Station TB/BB', 'nonlab', None,None, 15, 25)
add_station(sched_date, 4, 'Sample Station Treadmill', 'nonlab', None,None, 45, 65)
add_station(sched_date, 5, 'Sample Station ECG', 'nonlab', None,None, 80, 95)
add_station(sched_date, 2, 'Sample Station Rontgen', 'nonlab', None,None, 110, 130)
add_station(sched_date, 7, 'Sample Station Pemeriksaan Fisik', 'nonlab', None,None, 145, 165)
add_station(sched_date, 33, 'Sample Station Visus dan Buta Warna','nonlab',None,None, 175, 195)
# some patients: lab still processing
if i % 4 == 0:
# lab done
add_station(sched_date, 1, 'Sample Station Phlebotomy', 'lab', 30, 45, 90, 120)
add_station(sched_date, 31, 'Sample Station Urine', 'lab', 20, 35, 75, 95)
else:
# lab in process — no DoneAt
add_station(sched_date, 1, 'Sample Station Phlebotomy', 'lab', 30, 45, None, None)
add_station(sched_date, 31, 'Sample Station Urine', 'lab', 20, 35, None, None)
# ─ CASE 3: April 30 — today ──────────────────────────────────────────────
elif sched_date == TODAY:
local_idx = i - 750 # 175 within today
if local_idx <= 60:
# arrived this morning — partial stations
add_checkin(sched_date, cin_h, cin_m, None)
add_station(sched_date, 17, 'Sample Station TB/BB', 'nonlab', None,None, 15, 25)
add_station(sched_date, 4, 'Sample Station Treadmill', 'nonlab', None,None, 45, 65)
if local_idx % 3 == 0:
# 20 patients done 3 stations
add_station(sched_date, 5, 'Sample Station ECG', 'nonlab', None,None, 80, 95)
if local_idx % 5 == 0:
# 12 patients done lab too
add_station(sched_date, 1, 'Sample Station Phlebotomy', 'lab', 30, 45, None, None)
add_station(sched_date, 31, 'Sample Station Urine', 'lab', 20, 35, None, None)
# patients 6175: not yet arrived (no checkin, no stations)
# ─ resume status & published ─────────────────────────────────────────────
# validated: April 2027 (days 07)
# published: April 2025 (days 05)
if day_idx <= 7:
validated = 'Y'
status = 'DONE'
else:
validated = 'N'
status = ''
published = 'Y' if day_idx <= 5 else 'N'
if sched_date < TODAY:
resume_rows.append(
f"({pid}, {MCU_ID}, {q(status)}, {q(validated)}, {q(published)}, NOW())"
)
# published_mcu_dashboard_sync — all patients from sched < today get a row
if sched_date < TODAY:
has_pdf = (i <= PDF_COUNT)
file_url = f"'{PDF_BASE}/R2604{i:04d}_resume_individu.pdf'" if has_pdf else 'NULL'
pdf_status = 'Y' if has_pdf else 'N'
published_rows.append(
f"({oid}, {q(pdf_status)}, {file_url}, 'Y', NOW(), 0, NOW(), 0)"
)
# kelainan_details — ~33% of validated patients (days 07)
if day_idx <= 7 and validated == 'Y' and i % 3 == 0:
for (grp, kname, prob) in KELAINAN_GROUPS:
# Use deterministic threshold based on i and grp index
grp_idx = KELAINAN_GROUPS.index((grp, kname, prob))
threshold = int(prob * 100)
if (i + grp_idx * 17) % 100 < threshold:
fcat_name, fcat_eng, fcat_lvl = FITNESS_CATS[grp]
kelainan_rows.append(
f"('MCU-DEMO-2026', {oid}, '{sched_date} 08:00:00', {q(lab_no)}, "
f"{age}, {pid}, {q(gender)}, {q(nip)}, {q(dept)}, {q(dept)}, "
f"{q(name)}, {q(name)}, {q(grp)}, 1, {q(kname)}, {q(kname)}, "
f"1, {q(kname)}, 1, {q(grp)}, "
f"1, {q(fcat_name)}, {q(fcat_eng)}, {fcat_lvl}, "
f"{MCU_ID}, NULL, NULL)"
)
# ── batch insert helpers ───────────────────────────────────────────────────────
CHUNK = 200
def emit_inserts(table, cols, rows, chunk=CHUNK):
if not rows:
return
lines.append(f"-- {table} ({len(rows)} rows)")
for start in range(0, len(rows), chunk):
batch = rows[start:start+chunk]
lines.append(
f"INSERT INTO {table} ({cols}) VALUES\n " +
",\n ".join(batch) + ";"
)
lines.append("")
emit_inserts(
"mcu_patient",
"Mcu_PatientPreregisterID, Mcu_PatientMcuID, Mcu_PatientName, Mcu_PatientNIP, "
"Mcu_PatientGender, Mcu_PatientDOB, Mcu_PatientAge, Mcu_PatientDepartment, "
"Mcu_PatientPosisi, Mcu_PatientOrderID, Mcu_PatientIsRegistered, Mcu_PatientIsActive, "
"Mcu_PatientSyncedAt",
patient_rows
)
emit_inserts(
"mcu_patient_schedule",
"Mcu_PatientSchedulePreregisterID, Mcu_PatientScheduleDate, "
"Mcu_PatientScheduleIsActive, Mcu_PatientScheduleSyncedAt",
schedule_rows
)
emit_inserts(
"mcu_patient_required_station",
"mcu_id, preregister_id, order_header_id, location_id, sample_station_id, station_name",
req_station_rows
)
emit_inserts(
"mcu_checkinout",
"Mcu_CheckinoutMcuID, Mcu_CheckinoutPreregisterID, Mcu_CheckinoutOrderID, "
"Mcu_CheckinoutDate, Mcu_CheckinoutInTime, Mcu_CheckinoutOutTime, "
"Mcu_CheckinoutIsActive, Mcu_CheckinoutSyncedAt",
checkin_rows
)
emit_inserts(
"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",
station_rows
)
emit_inserts(
"mcu_patient_resume_status",
"Mcu_PatientResumeStatusPreregisterID, Mcu_PatientResumeStatusMcuID, "
"Mcu_PatientResumeStatusStatus, Mcu_PatientResumeStatusValidated, "
"Mcu_PatientResumeStatusPublished, Mcu_PatientResumeSyncedAt",
resume_rows
)
emit_inserts(
"published_mcu_dashboard_sync",
"Published_McuDasboardT_OrderHeaderID, Published_McuDasboardStatus, "
"Published_McuDasboardFileUrl, Published_McuDasboardIsActive, "
"Published_McuDasboardCreated, Published_McuDasboardCreatedUserID, "
"Published_McuDasboardLastUpdated, Published_McuDasboardLastUpdatedUserID",
published_rows
)
emit_inserts(
"kelainan_details",
"Numbering, T_OrderHeaderID, T_OrderHeaderDate, T_OrderHeaderLabNumber, "
"AgePatient, M_PatientID, M_PatientGender, M_PatientNIP, "
"M_PatientDepartement, M_PatientDivisi, PatientName, M_PatientName, "
"GroupResult, Nat_TestID, Nat_TestCode, Nat_TestName, "
"Mcu_KelainanID, Mcu_KelainanName, Mcu_KelainanGroupSummaryID, Mcu_KelainanGroupSummaryName, "
"Mcu_FitnessCategoryID, Mcu_FitnessCategoryName, Mcu_FitnessCategoryEng, Mcu_FitnessCategoryLevel, "
"Mgm_McuID, Mcu_GenerateID, Mcu_ProjectID",
kelainan_rows
)
lines.append("SET FOREIGN_KEY_CHECKS = 1;")
lines.append("SELECT 'Demo data seeded successfully.' AS status;")
print('\n'.join(lines))