pindah klinik belum service

This commit is contained in:
Fanrouver
2026-06-05 08:21:56 +07:00
parent 0928e78bec
commit f81dd57a16
9 changed files with 702 additions and 95 deletions

No files matched your search

+71 -10
View File
@@ -784,10 +784,29 @@ const fetchPatientsForLoket = async (loketId, force = false) => {
const patientsRaw = rawData.data || [];
// Fetch temporary subspesialis mapping
let subspesialisMap = {};
try {
const subRes = await fetch('/api/patient-subspesialis');
if (subRes.ok) {
subspesialisMap = await subRes.json();
}
} catch (e) {
console.error('Failed to fetch temporary subspesialis mapping', e);
}
// Map API data to store format
const mappedPatients = patientsRaw.map((apiPatient, index) =>
mapApiPatientToStoreFormat(apiPatient, index)
).filter(p => isTodayPatient(p));
const mappedPatients = patientsRaw.map((apiPatient, index) => {
const mapped = mapApiPatientToStoreFormat(apiPatient, index);
// Merge temporary subspesialis mapping
const barcodeKey = mapped.barcode || mapped.idtiket;
if (barcodeKey && subspesialisMap[barcodeKey]) {
mapped.ruang = subspesialisMap[barcodeKey].namaRuang || subspesialisMap[barcodeKey].nama;
mapped.nomorRuang = subspesialisMap[barcodeKey].nomorRuang || subspesialisMap[barcodeKey].ruang;
mapped.kodeRuang = subspesialisMap[barcodeKey].kodeRuang || subspesialisMap[barcodeKey].id;
}
return mapped;
}).filter(p => isTodayPatient(p));
// Deduplicate patients by idtiket
// API returns multiple entries if patient is at multiple positions
@@ -891,6 +910,25 @@ const fetchPatientsForLoket = async (loketId, force = false) => {
return true; // Keep the currently processing patient
}
// CRITICAL FIX: Protect patients manually moved to a different loket via changeKlinik.
// The backend API doesn't know about this move yet, so API refresh would wipe the patient.
// We protect them for 10 minutes (600000ms) to give admin time to process them.
if (p.manuallyMoved && p.movedAt) {
const timeSinceMoved = Date.now() - p.movedAt;
const tenMinutes = 10 * 60 * 1000;
if (timeSinceMoved < tenMinutes) {
console.log(`🛡️ [queueStore] Protecting manually-moved patient ${p.noAntrian?.split(' |')[0]} (moved ${Math.round(timeSinceMoved/1000)}s ago) from API overwrite`);
// Prevent the old loket's API data from overwriting this patient
if (newPatientMap.has(key)) {
newPatientMap.delete(key);
}
return true; // Keep the moved patient
} else {
// After 10 minutes, allow API to take over
console.log(`⏰ [queueStore] manuallyMoved patient ${p.noAntrian?.split(' |')[0]} protection expired. Allowing API overwrite.`);
}
}
// If it's still in loket stage but marked as processed, and it's in the API batch,
// we might be experiencing API lag. Keep it as processed.
if (p.status === 'processed' && newPatientMap.has(key)) {
@@ -2297,7 +2335,8 @@ const fetchPatientsForLoket = async (loketId, force = false) => {
if (newPatient.kodeKlinik) {
const allLokets = loketStore.lokets || [];
const targetLoket = allLokets.find(l =>
l.pelayanan && Array.isArray(l.pelayanan) && l.pelayanan.includes(newPatient.kodeKlinik)
l.pelayanan && Array.isArray(l.pelayanan) &&
(l.pelayanan.includes(newPatient.kodeKlinik) || l.pelayanan.includes(newPatient.kodeKlinik?.split('-')[0]))
);
if (targetLoket) {
newPatient.loketId = targetLoket.id;
@@ -2672,7 +2711,7 @@ const fetchPatientsForLoket = async (loketId, force = false) => {
const getPatientsByKlinikRuang = (kodeKlinik, nomorRuang, tipeLayanan = null) => {
return computed(() => {
let patients = allPatients.value.filter(p =>
p.kodeKlinik === kodeKlinik &&
(p.kodeKlinik === kodeKlinik || (p.kodeKlinik && p.kodeKlinik.split('-')[0] === kodeKlinik)) &&
p.nomorRuang === nomorRuang &&
p.processStage === 'klinik-ruang'
);
@@ -2694,7 +2733,7 @@ const fetchPatientsForLoket = async (loketId, force = false) => {
// Call next patient for a specific room and tipeLayanan
const callNextKlinikRuang = (kodeKlinik, nomorRuang, tipeLayanan, allowMultiple = false) => {
const patients = allPatients.value.filter(p =>
p.kodeKlinik === kodeKlinik &&
(p.kodeKlinik === kodeKlinik || (p.kodeKlinik && p.kodeKlinik.split('-')[0] === kodeKlinik)) &&
p.nomorRuang === nomorRuang &&
p.tipeLayanan === tipeLayanan &&
p.processStage === 'klinik-ruang' &&
@@ -2854,7 +2893,8 @@ const fetchPatientsForLoket = async (loketId, force = false) => {
if (newKlinik.kode) {
const allLokets = loketStore.lokets || [];
const foundLoket = allLokets.find(l =>
l.pelayanan && Array.isArray(l.pelayanan) && l.pelayanan.includes(newKlinik.kode)
l.pelayanan && Array.isArray(l.pelayanan) &&
(l.pelayanan.includes(newKlinik.kode) || l.pelayanan.includes(newKlinik.kode?.split('-')[0]))
);
if (foundLoket) {
@@ -2881,13 +2921,16 @@ const fetchPatientsForLoket = async (loketId, force = false) => {
}
// Update the patient in allPatients
// Mark as manuallyMoved so API refresh doesn't wipe this patient from the destination loket
const updatedPatient = {
...oldPatient,
klinik: newKlinik.name,
kodeKlinik: newKlinik.kode,
loketId: targetLoketId,
loket: targetLoketName,
status: newStatus
status: newStatus,
manuallyMoved: isMovedToDifferentLoket ? true : (oldPatient.manuallyMoved || false),
movedAt: isMovedToDifferentLoket ? Date.now() : (oldPatient.movedAt || null)
};
allPatients.value[patientIndex] = updatedPatient;
@@ -3022,7 +3065,8 @@ const fetchPatientsForLoket = async (loketId, force = false) => {
if (!newPatient.loketId && newPatient.kodeKlinik) {
const allLokets = loketStore.lokets || [];
const targetLoket = allLokets.find(l =>
l.pelayanan && Array.isArray(l.pelayanan) && l.pelayanan.includes(newPatient.kodeKlinik)
l.pelayanan && Array.isArray(l.pelayanan) &&
(l.pelayanan.includes(newPatient.kodeKlinik) || l.pelayanan.includes(newPatient.kodeKlinik?.split('-')[0]))
);
if (targetLoket) {
@@ -3061,7 +3105,8 @@ const fetchPatientsForLoket = async (loketId, force = false) => {
// Find loket that handles BOTH the clinic AND the payment type
const targetLoket = allLokets.find(l => {
if (l.source !== 'api' || l.id >= 1000) return false;
const handlesClinic = l.pelayanan && Array.isArray(l.pelayanan) && l.pelayanan.includes(clinic.kode);
const handlesClinic = l.pelayanan && Array.isArray(l.pelayanan) &&
(l.pelayanan.includes(clinic.kode) || l.pelayanan.includes(clinic.kode?.split('-')[0]));
if (handlesClinic) {
return isPaymentCompatible(paymentTypeForMatching, l.pembayaran);
}
@@ -3179,6 +3224,22 @@ const fetchPatientsForLoket = async (loketId, force = false) => {
allPatients.value.push(newPatient);
// NOTE: Kita tidak perlu incrementBarcodeCounter() di sini karena barcode berasal dari API
// Temporary: Save subSpesialis mapping to local JSON API
if (subSpesialis) {
try {
await fetch('/api/patient-subspesialis', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
barcode: barcode,
subspesialis: subSpesialis
})
});
} catch (e) {
console.error('Failed to save temporary subSpesialis mapping', e);
}
}
return {
success: true,