From e9ce5927bd6f354bf88cf3f0adb72049ff1e77f1 Mon Sep 17 00:00:00 2001 From: riefive Date: Wed, 26 Nov 2025 13:59:34 +0700 Subject: [PATCH] feat: recreated index SEP page with updated permissions and structure --- app/handlers/integration-sep-entry.handler.ts | 1263 ++++++++--------- .../control-letter/index.vue | 0 .../{bpjs/vclaim => bpjs-vclaim}/sep/add.vue | 0 .../vclaim => bpjs-vclaim}/sep/index.vue | 0 app/services/vclaim-control-letter.service.ts | 1 - 5 files changed, 631 insertions(+), 633 deletions(-) rename app/pages/(features)/integration/{bpjs/vclaim => bpjs-vclaim}/control-letter/index.vue (100%) rename app/pages/(features)/integration/{bpjs/vclaim => bpjs-vclaim}/sep/add.vue (100%) rename app/pages/(features)/integration/{bpjs/vclaim => bpjs-vclaim}/sep/index.vue (100%) diff --git a/app/handlers/integration-sep-entry.handler.ts b/app/handlers/integration-sep-entry.handler.ts index 99589348..ad267bef 100644 --- a/app/handlers/integration-sep-entry.handler.ts +++ b/app/handlers/integration-sep-entry.handler.ts @@ -10,22 +10,22 @@ import type { TreeItem } from '~/components/pub/my-ui/select-tree/type' // Constants import { - serviceTypes, - serviceAssessments, - registerMethods, - trafficAccidents, - supportCodes, - procedureTypes, - purposeOfVisits, - classLevels, - classLevelUpgrades, - classPaySources, + serviceTypes, + serviceAssessments, + registerMethods, + trafficAccidents, + supportCodes, + procedureTypes, + purposeOfVisits, + classLevels, + classLevelUpgrades, + classPaySources, } from '~/lib/constants.vclaim' // Services import { - getList as getSpecialistList, - getValueTreeItems as getSpecialistTreeItems, + getList as getSpecialistList, + getValueTreeItems as getSpecialistTreeItems, } from '~/services/specialist.service' import { getValueLabelList as getProvinceList } from '~/services/vclaim-region-province.service' import { getValueLabelList as getCityList } from '~/services/vclaim-region-city.service' @@ -41,652 +41,651 @@ import { create as createSep, makeSepData } from '~/services/vclaim-sep.service' // Handlers import { - patients, - selectedPatient, - selectedPatientObject, - paginationMeta, - getPatientsList, - getPatientCurrent, - getPatientByIdentifierSearch, + patients, + selectedPatient, + selectedPatientObject, + paginationMeta, + getPatientsList, + getPatientCurrent, + getPatientByIdentifierSearch, } from '~/handlers/patient.handler' export function useIntegrationSepEntry() { - const userStore = useUserStore() - const route = useRoute() + const userStore = useUserStore() + const route = useRoute() - const openPatient = ref(false) - const openLetter = ref(false) - const openHistory = ref(false) - const selectedLetter = ref('') - const selectedObjects = ref({}) - const selectedServiceType = ref('') - const selectedAdmissionType = ref('') - const histories = ref>([]) - const letters = ref>([]) - const doctors = ref>([]) - const diagnoses = ref>([]) - const facilitiesFrom = ref>([]) - const facilitiesTo = ref>([]) - const supportCodesList = ref>([]) - const serviceTypesList = ref>([]) - const registerMethodsList = ref>([]) - const accidentsList = ref>([]) - const purposeOfVisitsList = ref>([]) - const proceduresList = ref>([]) - const assessmentsList = ref>([]) - const provincesList = ref>([]) - const citiesList = ref>([]) - const districtsList = ref>([]) - const classLevelsList = ref>([]) - const classLevelUpgradesList = ref>([]) - const classPaySourcesList = ref>([]) - const isServiceHidden = ref(false) - const isSaveLoading = ref(false) - const isLetterReadonly = ref(false) - const isLoadingPatient = ref(false) - const specialistsTree = ref([]) - const resourceType = ref('') - const resourcePath = ref('') + const openPatient = ref(false) + const openLetter = ref(false) + const openHistory = ref(false) + const selectedLetter = ref('') + const selectedObjects = ref({}) + const selectedServiceType = ref('') + const selectedAdmissionType = ref('') + const histories = ref>([]) + const letters = ref>([]) + const doctors = ref>([]) + const diagnoses = ref>([]) + const facilitiesFrom = ref>([]) + const facilitiesTo = ref>([]) + const supportCodesList = ref>([]) + const serviceTypesList = ref>([]) + const registerMethodsList = ref>([]) + const accidentsList = ref>([]) + const purposeOfVisitsList = ref>([]) + const proceduresList = ref>([]) + const assessmentsList = ref>([]) + const provincesList = ref>([]) + const citiesList = ref>([]) + const districtsList = ref>([]) + const classLevelsList = ref>([]) + const classLevelUpgradesList = ref>([]) + const classPaySourcesList = ref>([]) + const isServiceHidden = ref(false) + const isSaveLoading = ref(false) + const isLetterReadonly = ref(false) + const isLoadingPatient = ref(false) + const specialistsTree = ref([]) + const resourceType = ref('') + const resourcePath = ref('') - /** - * Map letter data to form fields for save-sep - * Maps data from letters.value[0].information to selectedObjects and form values - */ - function mapLetterDataToForm(formValues: any): any { - if (selectedAdmissionType.value === '3' || letters.value.length === 0) { - return formValues - } - - const letterData = letters.value[0] - const info = letterData.information || {} - - // Map data to selectedObjects for form population - if (info.cardNumber) { - selectedObjects.value['cardNumber'] = info.cardNumber - } - if (info.medicalRecordNumber) { - selectedObjects.value['medicalRecordNumber'] = info.medicalRecordNumber - } - if (info.patientPhone) { - selectedObjects.value['phoneNumber'] = info.patientPhone - } - if (info.classLevel) { - selectedObjects.value['classLevel'] = info.classLevel - } - - // Map data to formValues for makeSepData - const mappedValues = { ...formValues } - - // response.rujukan.peserta.noKartu → cardNumber (noKartu) - if (info.cardNumber) { - mappedValues.cardNumber = info.cardNumber - } - - // response.rujukan.tglKunjungan → referralLetterDate (rujukan.tglRujukan) - if (letterData.plannedDate) { - mappedValues.referralLetterDate = letterData.plannedDate - } - - // response.rujukan.noKunjungan → referralLetterNumber (rujukan.noRujukan) - if (letterData.letterNumber) { - mappedValues.referralLetterNumber = letterData.letterNumber - } - - // response.rujukan.provPerujuk.kode → fromClinic (rujukan.ppkRujukan) - if (info.destination) { - mappedValues.referralTo = info.destination - } - - // response.rujukan.poliRujukan.kode → polyCode - if (info.poly) { - mappedValues.polyCode = info.poly - } - - // response.asalFaskes → asalRujukan (1 = Faskes 1, 2 = Faskes RS) - // Map facility to referralFrom (asalRujukan) - if (info.facility) { - mappedValues.referralFrom = info.facility - } - - // response.rujukan.diagnosa.kode → initialDiagnosis (diagAwal) - if (info.diagnoses) { - mappedValues.initialDiagnosis = info.diagnoses - } - - // response.rujukan.poliRujukan.kode → destinationClinic (poli.tujuan) - if (info.poly) { - mappedValues.destinationClinic = info.poly - } - - // response.rujukan.peserta.hakKelas.kode → classLevel (klsRawat.klsRawatHak) - if (info.classLevel) { - mappedValues.classLevel = info.classLevel - } - - // response.rujukan.peserta.mr.noMR → medicalRecordNumber (noMR) - if (info.medicalRecordNumber) { - mappedValues.medicalRecordNumber = info.medicalRecordNumber - } - - // response.rujukan.peserta.mr.noTelepon → phoneNumber (noTelp) - if (info.patientPhone) { - mappedValues.phoneNumber = info.patientPhone - } - - return mappedValues + /** + * Map letter data to form fields for save-sep + * Maps data from letters.value[0].information to selectedObjects and form values + */ + function mapLetterDataToForm(formValues: any): any { + if (selectedAdmissionType.value === '3' || letters.value.length === 0) { + return formValues } - async function getMonitoringHistoryMappers() { - histories.value = [] - const dateFirst = new Date() - const dateLast = new Date() - dateLast.setMonth(dateFirst.getMonth() - 3) - const cardNumber = - selectedPatientObject.value?.person?.residentIdentityNumber || selectedPatientObject.value?.number || '' - const result = await getMonitoringHistoryList({ - cardNumber: cardNumber, - startDate: dateFirst.toISOString().substring(0, 10), - endDate: dateLast.toISOString().substring(0, 10), + const letterData = letters.value[0] + const info = letterData.information || {} + + // Map data to selectedObjects for form population + if (info.cardNumber) { + selectedObjects.value['cardNumber'] = info.cardNumber + } + if (info.medicalRecordNumber) { + selectedObjects.value['medicalRecordNumber'] = info.medicalRecordNumber + } + if (info.patientPhone) { + selectedObjects.value['phoneNumber'] = info.patientPhone + } + if (info.classLevel) { + selectedObjects.value['classLevel'] = info.classLevel + } + + // Map data to formValues for makeSepData + const mappedValues = { ...formValues } + + // response.rujukan.peserta.noKartu → cardNumber (noKartu) + if (info.cardNumber) { + mappedValues.cardNumber = info.cardNumber + } + + // response.rujukan.tglKunjungan → referralLetterDate (rujukan.tglRujukan) + if (letterData.plannedDate) { + mappedValues.referralLetterDate = letterData.plannedDate + } + + // response.rujukan.noKunjungan → referralLetterNumber (rujukan.noRujukan) + if (letterData.letterNumber) { + mappedValues.referralLetterNumber = letterData.letterNumber + } + + // response.rujukan.provPerujuk.kode → fromClinic (rujukan.ppkRujukan) + if (info.destination) { + mappedValues.referralTo = info.destination + } + + // response.rujukan.poliRujukan.kode → polyCode + if (info.poly) { + mappedValues.polyCode = info.poly + } + + // response.asalFaskes → asalRujukan (1 = Faskes 1, 2 = Faskes RS) + // Map facility to referralFrom (asalRujukan) + if (info.facility) { + mappedValues.referralFrom = info.facility + } + + // response.rujukan.diagnosa.kode → initialDiagnosis (diagAwal) + if (info.diagnoses) { + mappedValues.initialDiagnosis = info.diagnoses + } + + // response.rujukan.poliRujukan.kode → destinationClinic (poli.tujuan) + if (info.poly) { + mappedValues.destinationClinic = info.poly + } + + // response.rujukan.peserta.hakKelas.kode → classLevel (klsRawat.klsRawatHak) + if (info.classLevel) { + mappedValues.classLevel = info.classLevel + } + + // response.rujukan.peserta.mr.noMR → medicalRecordNumber (noMR) + if (info.medicalRecordNumber) { + mappedValues.medicalRecordNumber = info.medicalRecordNumber + } + + // response.rujukan.peserta.mr.noTelepon → phoneNumber (noTelp) + if (info.patientPhone) { + mappedValues.phoneNumber = info.patientPhone + } + + return mappedValues + } + + async function getMonitoringHistoryMappers() { + histories.value = [] + const dateFirst = new Date() + const dateLast = new Date() + dateLast.setMonth(dateFirst.getMonth() - 3) + const cardNumber = + selectedPatientObject.value?.person?.residentIdentityNumber || selectedPatientObject.value?.number || '' + const result = await getMonitoringHistoryList({ + cardNumber: cardNumber, + startDate: dateFirst.toISOString().substring(0, 10), + endDate: dateLast.toISOString().substring(0, 10), + }) + if (result && result.success && result.body) { + const historiesRaw = result.body?.response?.histori || [] + if (!historiesRaw) return + historiesRaw.forEach((result: any) => { + histories.value.push({ + sepNumber: result.noSep, + sepDate: result.tglSep, + referralNumber: result.noRujukan, + diagnosis: + result.diagnosa && typeof result.diagnosa === 'string' && result.diagnosa.length > 20 + ? result.diagnosa.toString().substring(0, 17) + '...' + : '-', + serviceType: !result.jnsPelayanan ? '-' : result.jnsPelayanan === '1' ? 'Rawat Jalan' : 'Rawat Inap', + careClass: result.kelasRawat, }) - if (result && result.success && result.body) { - const historiesRaw = result.body?.response?.histori || [] - if (!historiesRaw) return - historiesRaw.forEach((result: any) => { - histories.value.push({ - sepNumber: result.noSep, - sepDate: result.tglSep, - referralNumber: result.noRujukan, - diagnosis: - result.diagnosa && typeof result.diagnosa === 'string' && result.diagnosa.length > 20 - ? result.diagnosa.toString().substring(0, 17) + '...' - : '-', - serviceType: !result.jnsPelayanan ? '-' : result.jnsPelayanan === '1' ? 'Rawat Jalan' : 'Rawat Inap', - careClass: result.kelasRawat, - }) - }) - } + }) } + } - async function getLetterMappers(admissionType: string, search: string) { - letters.value = [] - let result = null - if (admissionType !== '3') { - result = await getHospitalLetterList({ - letterNumber: search, - }) + async function getLetterMappers(admissionType: string, search: string) { + letters.value = [] + let result = null + if (admissionType !== '3') { + result = await getHospitalLetterList({ + letterNumber: search, + }) + } else { + result = await getControlLetterList({ + letterNumber: search, + mode: 'by-control', + }) + if (result && result.success && result.body) { + const lettersRaw = result.body?.response || null + if (!lettersRaw) { + result = await getControlLetterList({ + letterNumber: search, + mode: 'by-card', + }) + } + } + if (result && result.success && result.body) { + const lettersRaw = result.body?.response || null + if (!lettersRaw) { + result = await getControlLetterList({ + letterNumber: search, + mode: 'by-sep', + }) + } + } + } + if (result && result.success && result.body) { + const lettersRaw = result.body?.response || null + if (!lettersRaw) return + if (admissionType === '3') { + letters.value = [ + { + letterNumber: lettersRaw.noSuratKontrol || '', + plannedDate: lettersRaw.tglRencanaKontrol || '', + sepNumber: lettersRaw.sep.noSep || '', + patientName: lettersRaw.sep.peserta.nama || '', + bpjsCardNo: lettersRaw.sep.peserta.noKartu, + clinic: lettersRaw.sep.poli || '', + doctor: lettersRaw.sep.namaDokter || '', + }, + ] + } else { + letters.value = [ + { + letterNumber: lettersRaw?.rujukan?.noKunjungan || '', + plannedDate: lettersRaw?.rujukan?.tglKunjungan || '', + sepNumber: lettersRaw?.rujukan?.informasi?.eSEP || '-', + patientName: lettersRaw?.rujukan?.peserta.nama || '', + bpjsCardNo: lettersRaw?.rujukan?.peserta.noKartu || '', + clinic: lettersRaw?.rujukan?.poliRujukan.nama || '', + doctor: '', + information: { + facility: lettersRaw?.asalFaskes || '', + diagnose: lettersRaw?.rujukan?.diagnosa?.kode || '', + serviceType: lettersRaw?.rujukan?.pelayanan?.kode || '', + classLevel: lettersRaw?.rujukan?.peserta?.hakKelas?.kode || '', + poly: lettersRaw?.rujukan?.poliRujukan?.kode || '', + cardNumber: lettersRaw?.rujukan?.peserta?.noKartu || '', + identity: lettersRaw?.rujukan?.peserta?.nik || '', + patientName: lettersRaw?.rujukan?.peserta?.nama || '', + patientPhone: lettersRaw?.rujukan?.peserta?.mr?.noTelepon || '', + medicalRecordNumber: lettersRaw?.rujukan?.peserta?.mr?.noMR || '', + destination: lettersRaw?.rujukan?.provPerujuk?.kode || '', + }, + }, + ] + } + } + } + + async function getPatientInternalMappers(id: string) { + try { + await getPatientCurrent(id) + if (selectedPatientObject.value) { + const patient = selectedPatientObject.value + selectedObjects.value['cardNumber'] = '-' + selectedObjects.value['nationalIdentity'] = patient?.person?.residentIdentityNumber || '-' + selectedObjects.value['medicalRecordNumber'] = patient?.number || '-' + selectedObjects.value['patientName'] = patient?.person?.name || '-' + selectedObjects.value['phoneNumber'] = patient?.person?.contacts?.[0]?.value || '-' + } + } catch (err) { + console.error('Failed to load patient from query params:', err) + } + } + + async function getPatientExternalMappers(id: string, type: string) { + try { + isLoadingPatient.value = true + const result = await getMemberList({ + mode: type, + number: id, + date: new Date().toISOString().substring(0, 10), + }) + if (result && result.success && result.body) { + const memberRaws = result.body?.response || null + selectedObjects.value['cardNumber'] = memberRaws?.peserta?.noKartu || '' + selectedObjects.value['nationalIdentity'] = memberRaws?.peserta?.nik || '' + selectedObjects.value['medicalRecordNumber'] = memberRaws?.peserta?.mr?.noMR || '' + selectedObjects.value['patientName'] = memberRaws?.peserta?.nama || '' + selectedObjects.value['phoneNumber'] = memberRaws?.peserta?.mr?.noTelepon || '' + selectedObjects.value['classLevel'] = memberRaws?.peserta?.hakKelas?.kode || '' + selectedObjects.value['status'] = memberRaws?.statusPeserta?.kode || '' + } + isLoadingPatient.value = false + } catch (err) { + console.error('Failed to load patient from query params:', err) + isLoadingPatient.value = false + } + } + + function handleSaveLetter() { + // Find the selected letter and get its plannedDate + const selectedLetterData = letters.value.find((letter) => letter.letterNumber === selectedLetter.value) + if (selectedLetterData && selectedLetterData.plannedDate) { + selectedObjects.value['letterDate'] = selectedLetterData.plannedDate + } + } + + async function handleSavePatient() { + selectedPatientObject.value = null + await getPatientInternalMappers(selectedPatient.value) + } + + async function handleEvent(menu: string, value: any) { + if (menu === 'admission-type') { + selectedAdmissionType.value = value + return + } + if (menu === 'service-type') { + selectedServiceType.value = value + doctors.value = await getDoctorLabelList({ + serviceType: selectedServiceType.value || '2', + serviceDate: new Date().toISOString().substring(0, 10), + specialistCode: 0, + }) + } + if (menu === 'search-patient') { + getPatientsList({ 'page-size': 10, includes: 'person' }).then(() => { + openPatient.value = true + }) + return + } + if (menu === 'search-patient-by-identifier') { + if (isLoadingPatient.value) return + const text = value.text + const type = value.type + const prevCardNumber = selectedObjects.value['cardNumber'] || '' + const prevNationalIdentity = selectedObjects.value['nationalIdentity'] || '' + if (type === 'indentity' && text !== prevNationalIdentity) { + await getPatientByIdentifierSearch(text) + await getPatientExternalMappers(text, 'by-identity') + } + if (type === 'cardNumber' && text !== prevCardNumber) { + await getPatientExternalMappers(text, 'by-card') + } + return + } + if (menu === 'search-letter') { + isLetterReadonly.value = false + getLetterMappers(value.admissionType, value.search).then(async () => { + if (letters.value.length > 0) { + const copyObjects = { ...selectedObjects.value } + const letter = letters.value[0] + selectedObjects.value = {} + selectedLetter.value = letter.letterNumber + isLetterReadonly.value = true + if (letter.information || letter.clinic) { + const poly = value.admissionType === '3' ? letter.clinic : letter.information?.poly + if (poly) { + const resultControl = await getControlLetterList({ + mode: 'by-schedule', + controlDate: letter.plannedDate, + controlType: selectedServiceType.value, + polyCode: poly, + }) + if (resultControl && resultControl.success && resultControl.body) { + const resultData = resultControl.body?.response?.list || [] + const resultUnique = [...new Map(resultData.map((item: any) => [item.kodeDokter, item])).values()] + const controlLetters = resultUnique.map((item: any) => ({ + value: item.kodeDokter ? String(item.kodeDokter) : '', + label: `${item.kodeDokter} - ${item.namaDokter} - ${item.jadwalPraktek} (${item.kapasitas})`, + })) + doctors.value = controlLetters + } + } + } + setTimeout(async () => { + selectedObjects.value = copyObjects + selectedObjects.value['letterDate'] = letter.plannedDate + selectedObjects.value['cardNumber'] = letter.information?.cardNumber || '' + selectedObjects.value['nationalIdentity'] = letter.information?.identity || '' + selectedObjects.value['medicalRecordNumber'] = letter.information?.medicalRecordNumber || '' + selectedObjects.value['patientName'] = letter.information?.patientName || '' + selectedObjects.value['phoneNumber'] = letter.information?.patientPhone || '' + selectedObjects.value['facility'] = letter.information?.facility || '' + selectedObjects.value['diagnose'] = letter.information?.diagnose || '' + selectedObjects.value['serviceType'] = letter.information?.serviceType || '' + selectedObjects.value['classLevel'] = letter.information?.classLevel || '' + selectedObjects.value['poly'] = letter.information?.poly || '' + selectedObjects.value['destination'] = letter.information?.destination || '' + if (!!selectedObjects.value['diagnose']) { + const diagnoseRes: any = await getDiagnoseLabelList({ diagnosa: selectedObjects.value['diagnose'] }) + diagnoses.value = diagnoseRes + if (diagnoseRes && diagnoseRes.length > 0) { + selectedObjects.value['diagnoseLabel'] = diagnoseRes[0].value + } + } + }, 250) + } + }) + return + } + if (menu === 'open-letter') { + openLetter.value = true + return + } + if (menu === 'history-sep') { + getMonitoringHistoryMappers().then(() => { + openHistory.value = true + }) + return + } + if (menu === 'sep-number-changed') { + // Update sepNumber when it changes in form (only if different to prevent loop) + } + if (menu === 'back') { + navigateTo('/integration/bpjs-vclaim/sep') + } + if (menu === 'save-sep') { + isSaveLoading.value = true + + // Map letter data to form if admissionType !== '3' and letters.value has data + let mappedValues = value + if (selectedAdmissionType.value !== '3') { + if (letters.value.length > 0) { + // Map data from letters.value to form values + mappedValues = mapLetterDataToForm(value) } else { - result = await getControlLetterList({ - letterNumber: search, - mode: 'by-control', - }) - if (result && result.success && result.body) { - const lettersRaw = result.body?.response || null - if (!lettersRaw) { - result = await getControlLetterList({ - letterNumber: search, - mode: 'by-card', - }) - } + // Fallback: use getPatientExternalMappers if letters.value is empty + // Get card number from form values or selectedObjects + const cardNumberToSearch = value.cardNumber || selectedObjects.value['cardNumber'] || '' + if (cardNumberToSearch && cardNumberToSearch !== '-') { + await getPatientExternalMappers(cardNumberToSearch, 'by-card') + // Update mappedValues with data from getPatientExternalMappers + if (selectedObjects.value['cardNumber']) { + mappedValues.cardNumber = selectedObjects.value['cardNumber'] } - if (result && result.success && result.body) { - const lettersRaw = result.body?.response || null - if (!lettersRaw) { - result = await getControlLetterList({ - letterNumber: search, - mode: 'by-sep', - }) - } + if (selectedObjects.value['medicalRecordNumber']) { + mappedValues.medicalRecordNumber = selectedObjects.value['medicalRecordNumber'] } - } - if (result && result.success && result.body) { - const lettersRaw = result.body?.response || null - if (!lettersRaw) return - if (admissionType === '3') { - letters.value = [ - { - letterNumber: lettersRaw.noSuratKontrol || '', - plannedDate: lettersRaw.tglRencanaKontrol || '', - sepNumber: lettersRaw.sep.noSep || '', - patientName: lettersRaw.sep.peserta.nama || '', - bpjsCardNo: lettersRaw.sep.peserta.noKartu, - clinic: lettersRaw.sep.poli || '', - doctor: lettersRaw.sep.namaDokter || '', - }, - ] - } else { - letters.value = [ - { - letterNumber: lettersRaw?.rujukan?.noKunjungan || '', - plannedDate: lettersRaw?.rujukan?.tglKunjungan || '', - sepNumber: lettersRaw?.rujukan?.informasi?.eSEP || '-', - patientName: lettersRaw?.rujukan?.peserta.nama || '', - bpjsCardNo: lettersRaw?.rujukan?.peserta.noKartu || '', - clinic: lettersRaw?.rujukan?.poliRujukan.nama || '', - doctor: '', - information: { - facility: lettersRaw?.asalFaskes || '', - diagnose: lettersRaw?.rujukan?.diagnosa?.kode || '', - serviceType: lettersRaw?.rujukan?.pelayanan?.kode || '', - classLevel: lettersRaw?.rujukan?.peserta?.hakKelas?.kode || '', - poly: lettersRaw?.rujukan?.poliRujukan?.kode || '', - cardNumber: lettersRaw?.rujukan?.peserta?.noKartu || '', - identity: lettersRaw?.rujukan?.peserta?.nik || '', - patientName: lettersRaw?.rujukan?.peserta?.nama || '', - patientPhone: lettersRaw?.rujukan?.peserta?.mr?.noTelepon || '', - medicalRecordNumber: lettersRaw?.rujukan?.peserta?.mr?.noMR || '', - destination: lettersRaw?.rujukan?.provPerujuk?.kode || '', - }, - }, - ] + if (selectedObjects.value['phoneNumber']) { + mappedValues.phoneNumber = selectedObjects.value['phoneNumber'] } - } - } - - async function getPatientInternalMappers(id: string) { - try { - await getPatientCurrent(id) - if (selectedPatientObject.value) { - const patient = selectedPatientObject.value - selectedObjects.value['cardNumber'] = '-' - selectedObjects.value['nationalIdentity'] = patient?.person?.residentIdentityNumber || '-' - selectedObjects.value['medicalRecordNumber'] = patient?.number || '-' - selectedObjects.value['patientName'] = patient?.person?.name || '-' - selectedObjects.value['phoneNumber'] = patient?.person?.contacts?.[0]?.value || '-' + if (selectedObjects.value['classLevel']) { + mappedValues.classLevel = selectedObjects.value['classLevel'] } - } catch (err) { - console.error('Failed to load patient from query params:', err) + } } - } + } - async function getPatientExternalMappers(id: string, type: string) { - try { - isLoadingPatient.value = true - const result = await getMemberList({ - mode: type, - number: id, - date: new Date().toISOString().substring(0, 10), - }) - if (result && result.success && result.body) { - const memberRaws = result.body?.response || null - selectedObjects.value['cardNumber'] = memberRaws?.peserta?.noKartu || '' - selectedObjects.value['nationalIdentity'] = memberRaws?.peserta?.nik || '' - selectedObjects.value['medicalRecordNumber'] = memberRaws?.peserta?.mr?.noMR || '' - selectedObjects.value['patientName'] = memberRaws?.peserta?.nama || '' - selectedObjects.value['phoneNumber'] = memberRaws?.peserta?.mr?.noTelepon || '' - selectedObjects.value['classLevel'] = memberRaws?.peserta?.hakKelas?.kode || '' - selectedObjects.value['status'] = memberRaws?.statusPeserta?.kode || '' - } - isLoadingPatient.value = false - } catch (err) { - console.error('Failed to load patient from query params:', err) - isLoadingPatient.value = false - } - } + if (!value.destinationClinic) { + mappedValues.destinationClinic = selectedObjects.value['destination'] || '' + } + if (!value.clinicExcecutive) { + mappedValues.clinicExcecutive = 'no' + } - function handleSaveLetter() { - // Find the selected letter and get its plannedDate - const selectedLetterData = letters.value.find((letter) => letter.letterNumber === selectedLetter.value) - if (selectedLetterData && selectedLetterData.plannedDate) { - selectedObjects.value['letterDate'] = selectedLetterData.plannedDate - } - } + mappedValues.userName = userStore.user?.user_name || '' - async function handleSavePatient() { - selectedPatientObject.value = null - await getPatientInternalMappers(selectedPatient.value) - } - - async function handleEvent(menu: string, value: any) { - if (menu === 'admission-type') { - selectedAdmissionType.value = value + createSep(makeSepData(mappedValues)) + .then((res) => { + const body = res?.body + const code = body?.metaData?.code + const message = body?.metaData?.message + if (code && code !== '200') { + toast({ title: 'Gagal', description: message || 'Gagal membuat SEP', variant: 'destructive' }) return - } - if (menu === 'service-type') { - selectedServiceType.value = value - doctors.value = await getDoctorLabelList({ - serviceType: selectedServiceType.value || '2', - serviceDate: new Date().toISOString().substring(0, 10), - specialistCode: 0, - }) - } - if (menu === 'search-patient') { - getPatientsList({ 'page-size': 10, includes: 'person' }).then(() => { - openPatient.value = true - }) + } + toast({ title: 'Berhasil', description: 'SEP berhasil dibuat', variant: 'default' }) + if (!!resourcePath.value) { + navigateTo({ path: resourcePath.value, query: { 'sep-number': body?.response?.sep?.noSep || '-' } }) return - } - if (menu === 'search-patient-by-identifier') { - if (isLoadingPatient.value) return - const text = value.text - const type = value.type - const prevCardNumber = selectedObjects.value['cardNumber'] || '' - const prevNationalIdentity = selectedObjects.value['nationalIdentity'] || '' - if (type === 'indentity' && text !== prevNationalIdentity) { - await getPatientByIdentifierSearch(text) - await getPatientExternalMappers(text, 'by-identity') - } - if (type === 'cardNumber' && text !== prevCardNumber) { - await getPatientExternalMappers(text, 'by-card') - } - return - } - if (menu === 'search-letter') { - isLetterReadonly.value = false - getLetterMappers(value.admissionType, value.search).then(async () => { - if (letters.value.length > 0) { - const copyObjects = { ...selectedObjects.value } - const letter = letters.value[0] - selectedObjects.value = {} - selectedLetter.value = letter.letterNumber - isLetterReadonly.value = true - if (letter.information || letter.clinic) { - const poly = value.admissionType === '3' ? letter.clinic : letter.information?.poly - if (poly) { - const resultControl = await getControlLetterList({ - mode: 'by-schedule', - controlDate: letter.plannedDate, - controlType: selectedServiceType.value, - polyCode: poly, - }) - if (resultControl && resultControl.success && resultControl.body) { - const resultData = resultControl.body?.response?.list || [] - const resultUnique = [...new Map(resultData.map((item: any) => [item.kodeDokter, item])).values()] - const controlLetters = resultUnique.map((item: any) => ({ - value: item.kodeDokter ? String(item.kodeDokter) : '', - label: `${item.kodeDokter} - ${item.namaDokter} - ${item.jadwalPraktek} (${item.kapasitas})`, - })) - doctors.value = controlLetters - } - } - } - setTimeout(async () => { - selectedObjects.value = copyObjects - selectedObjects.value['letterDate'] = letter.plannedDate - selectedObjects.value['cardNumber'] = letter.information?.cardNumber || '' - selectedObjects.value['nationalIdentity'] = letter.information?.identity || '' - selectedObjects.value['medicalRecordNumber'] = letter.information?.medicalRecordNumber || '' - selectedObjects.value['patientName'] = letter.information?.patientName || '' - selectedObjects.value['phoneNumber'] = letter.information?.patientPhone || '' - selectedObjects.value['facility'] = letter.information?.facility || '' - selectedObjects.value['diagnose'] = letter.information?.diagnose || '' - selectedObjects.value['serviceType'] = letter.information?.serviceType || '' - selectedObjects.value['classLevel'] = letter.information?.classLevel || '' - selectedObjects.value['poly'] = letter.information?.poly || '' - selectedObjects.value['destination'] = letter.information?.destination || '' - if (!!selectedObjects.value['diagnose']) { - const diagnoseRes: any = await getDiagnoseLabelList({ diagnosa: selectedObjects.value['diagnose'] }) - diagnoses.value = diagnoseRes - if (diagnoseRes && diagnoseRes.length > 0) { - selectedObjects.value['diagnoseLabel'] = diagnoseRes[0].value - } - } - }, 250) - } - }) - return - } - if (menu === 'open-letter') { - openLetter.value = true - return - } - if (menu === 'history-sep') { - getMonitoringHistoryMappers().then(() => { - openHistory.value = true - }) - return - } - if (menu === 'sep-number-changed') { - // Update sepNumber when it changes in form (only if different to prevent loop) - } - if (menu === 'back') { - navigateTo('/integration/bpjs-vclaim/sep') - } - if (menu === 'save-sep') { - isSaveLoading.value = true - - // Map letter data to form if admissionType !== '3' and letters.value has data - let mappedValues = value - if (selectedAdmissionType.value !== '3') { - if (letters.value.length > 0) { - // Map data from letters.value to form values - mappedValues = mapLetterDataToForm(value) - } else { - // Fallback: use getPatientExternalMappers if letters.value is empty - // Get card number from form values or selectedObjects - const cardNumberToSearch = value.cardNumber || selectedObjects.value['cardNumber'] || '' - if (cardNumberToSearch && cardNumberToSearch !== '-') { - await getPatientExternalMappers(cardNumberToSearch, 'by-card') - // Update mappedValues with data from getPatientExternalMappers - if (selectedObjects.value['cardNumber']) { - mappedValues.cardNumber = selectedObjects.value['cardNumber'] - } - if (selectedObjects.value['medicalRecordNumber']) { - mappedValues.medicalRecordNumber = selectedObjects.value['medicalRecordNumber'] - } - if (selectedObjects.value['phoneNumber']) { - mappedValues.phoneNumber = selectedObjects.value['phoneNumber'] - } - if (selectedObjects.value['classLevel']) { - mappedValues.classLevel = selectedObjects.value['classLevel'] - } - } - } - } - - if (!value.destinationClinic) { - mappedValues.destinationClinic = selectedObjects.value['destination'] || '' - } - if (!value.clinicExcecutive) { - mappedValues.clinicExcecutive = 'no' - } - - mappedValues.userName = userStore.user?.user_name || '' - - createSep(makeSepData(mappedValues)) - .then((res) => { - const body = res?.body - const code = body?.metaData?.code - const message = body?.metaData?.message - if (code && code !== '200') { - toast({ title: 'Gagal', description: message || 'Gagal membuat SEP', variant: 'destructive' }) - return - } - toast({ title: 'Berhasil', description: 'SEP berhasil dibuat', variant: 'default' }) - if (resourceType.value === 'encounter') { - navigateTo(resourcePath.value) - return - } - navigateTo('/integration/bpjs-vclaim/sep') - }) - .catch((err) => { - console.error('Failed to save SEP:', err) - toast({ title: 'Gagal', description: err?.message || 'Gagal membuat SEP', variant: 'destructive' }) - }) - .finally(() => { - isSaveLoading.value = false - }) - } - } - - async function handleFetch(params: any) { - const menu = params.menu || '' - const value = params.value || '' - if (menu === 'diagnosis') { - diagnoses.value = await getDiagnoseLabelList({ diagnosa: value }) - } - if (menu === 'clinic-from') { - facilitiesFrom.value = await getHealthFacilityLabelList({ - healthcare: value, - healthcareType: selectedServiceType.value || 2, - }) - } - if (menu === 'clinic-to') { - facilitiesTo.value = await getHealthFacilityLabelList({ - healthcare: value, - healthcareType: selectedServiceType.value || 2, - }) - } - if (menu === 'province') { - citiesList.value = await getCityList({ province: value }) - districtsList.value = [] - } - if (menu === 'city') { - districtsList.value = await getDistrictList({ city: value }) - } - } - - async function handleFetchSpecialists() { - try { - const specialistsResult = await getSpecialistList({ 'page-size': 100, includes: 'subspecialists' }) - if (specialistsResult.success) { - const specialists = specialistsResult.body?.data || [] - specialistsTree.value = getSpecialistTreeItems(specialists) - } - } catch (error) { - console.error('Error fetching specialist-subspecialist tree:', error) - } - } - - async function handleInit() { - selectedServiceType.value = '2' - const facilities = await getHealthFacilityLabelList({ - healthcare: 'Puskesmas', - healthcareType: selectedLetter.value || 1, + } + navigateTo('/integration/bpjs-vclaim/sep') }) - diagnoses.value = await getDiagnoseLabelList({ diagnosa: 'paru' }) - facilitiesFrom.value = facilities - facilitiesTo.value = facilities - doctors.value = await getDoctorLabelList({ - serviceType: selectedServiceType.value || '2', - serviceDate: new Date().toISOString().substring(0, 10), - specialistCode: 0, + .catch((err) => { + console.error('Failed to save SEP:', err) + toast({ title: 'Gagal', description: err?.message || 'Gagal membuat SEP', variant: 'destructive' }) + }) + .finally(() => { + isSaveLoading.value = false }) - provincesList.value = await getProvinceList() - serviceTypesList.value = Object.keys(serviceTypes).map((item) => ({ - value: item.toString(), - label: serviceTypes[item], - })) as any - registerMethodsList.value = Object.keys(registerMethods) - .filter((item) => ![''].includes(item)) - .map((item) => ({ - value: item.toString(), - label: registerMethods[item], - })) as any - accidentsList.value = Object.keys(trafficAccidents).map((item) => ({ - value: item.toString(), - label: trafficAccidents[item], - })) as any - purposeOfVisitsList.value = Object.keys(purposeOfVisits).map((item) => ({ - value: item.toString(), - label: purposeOfVisits[item], - })) as any - proceduresList.value = Object.keys(procedureTypes).map((item) => ({ - value: item.toString(), - label: procedureTypes[item], - })) as any - assessmentsList.value = Object.keys(serviceAssessments).map((item) => ({ - value: item.toString(), - label: `${item.toString()} - ${serviceAssessments[item]}`, - })) as any - supportCodesList.value = Object.keys(supportCodes).map((item) => ({ - value: item.toString(), - label: `${item.toString()} - ${supportCodes[item]}`, - })) as any - classLevelsList.value = Object.keys(classLevels).map((item) => ({ - value: item.toString(), - label: classLevels[item], - })) as any - classLevelUpgradesList.value = Object.keys(classLevelUpgrades).map((item) => ({ - value: item.toString(), - label: classLevelUpgrades[item], - })) as any - classPaySourcesList.value = Object.keys(classPaySources).map((item) => ({ - value: item.toString(), - label: classPaySources[item], - })) as any - await handleFetchSpecialists() - if (route.query) { - const queries = route.query as any - isServiceHidden.value = queries['is-service'] === 'true' - selectedObjects.value = {} - if (queries['resource']) resourceType.value = queries['resource'] - if (queries['resource-path']) resourcePath.value = queries['resource-path'] - if (queries['doctor-code']) selectedObjects.value['doctorCode'] = queries['doctor-code'] - if (queries['specialist-code']) selectedObjects.value['subSpecialistCode'] = queries['specialist-code'] - if (queries['sub-specialist-code']) selectedObjects.value['subSpecialistCode'] = queries['sub-specialist-code'] - if (queries['card-number']) selectedObjects.value['cardNumber'] = queries['card-number'] - if (queries['register-date']) selectedObjects.value['registerDate'] = queries['register-date'] - if (queries['sep-type']) selectedObjects.value['sepType'] = queries['sep-type'] - if (queries['sep-number']) selectedObjects.value['sepNumber'] = queries['sep-number'] - if (queries['register-date']) selectedObjects.value['registerDate'] = queries['register-date'] - if (queries['payment-type']) selectedObjects.value['paymentType'] = queries['payment-type'] - if (queries['patient-id']) { - await getPatientInternalMappers(queries['patient-id']) - } - if (queries['card-number']) { - const resultMember = await getMemberList({ - mode: 'by-card', - number: queries['card-number'], - date: new Date().toISOString().substring(0, 10), - }) - console.log(resultMember) - } - delete selectedObjects.value['is-service'] - } } + } - return { - openPatient, - openLetter, - openHistory, - selectedLetter, - selectedObjects, - selectedServiceType, - selectedAdmissionType, - histories, - letters, - doctors, - diagnoses, - facilitiesFrom, - facilitiesTo, - supportCodesList, - serviceTypesList, - registerMethodsList, - accidentsList, - purposeOfVisitsList, - proceduresList, - assessmentsList, - provincesList, - citiesList, - districtsList, - classLevelsList, - classLevelUpgradesList, - classPaySourcesList, - isServiceHidden, - isSaveLoading, - isLetterReadonly, - isLoadingPatient, - specialistsTree, - resourceType, - resourcePath, - getMonitoringHistoryMappers, - getLetterMappers, - getPatientInternalMappers, - getPatientExternalMappers, - handleSaveLetter, - mapLetterDataToForm, - handleSavePatient, - handleEvent, - handleFetch, - handleFetchSpecialists, - handleInit, - // Exported from patient.handler - patients, - selectedPatient, - paginationMeta, - getPatientsList, - getPatientByIdentifierSearch, + async function handleFetch(params: any) { + const menu = params.menu || '' + const value = params.value || '' + if (menu === 'diagnosis') { + diagnoses.value = await getDiagnoseLabelList({ diagnosa: value }) } + if (menu === 'clinic-from') { + facilitiesFrom.value = await getHealthFacilityLabelList({ + healthcare: value, + healthcareType: selectedServiceType.value || 2, + }) + } + if (menu === 'clinic-to') { + facilitiesTo.value = await getHealthFacilityLabelList({ + healthcare: value, + healthcareType: selectedServiceType.value || 2, + }) + } + if (menu === 'province') { + citiesList.value = await getCityList({ province: value }) + districtsList.value = [] + } + if (menu === 'city') { + districtsList.value = await getDistrictList({ city: value }) + } + } + + async function handleFetchSpecialists() { + try { + const specialistsResult = await getSpecialistList({ 'page-size': 100, includes: 'subspecialists' }) + if (specialistsResult.success) { + const specialists = specialistsResult.body?.data || [] + specialistsTree.value = getSpecialistTreeItems(specialists) + } + } catch (error) { + console.error('Error fetching specialist-subspecialist tree:', error) + } + } + + async function handleInit() { + selectedServiceType.value = '2' + const facilities = await getHealthFacilityLabelList({ + healthcare: 'Puskesmas', + healthcareType: selectedLetter.value || 1, + }) + diagnoses.value = await getDiagnoseLabelList({ diagnosa: 'paru' }) + facilitiesFrom.value = facilities + facilitiesTo.value = facilities + doctors.value = await getDoctorLabelList({ + serviceType: selectedServiceType.value || '2', + serviceDate: new Date().toISOString().substring(0, 10), + specialistCode: 0, + }) + provincesList.value = await getProvinceList() + serviceTypesList.value = Object.keys(serviceTypes).map((item) => ({ + value: item.toString(), + label: serviceTypes[item], + })) as any + registerMethodsList.value = Object.keys(registerMethods) + .filter((item) => ![''].includes(item)) + .map((item) => ({ + value: item.toString(), + label: registerMethods[item], + })) as any + accidentsList.value = Object.keys(trafficAccidents).map((item) => ({ + value: item.toString(), + label: trafficAccidents[item], + })) as any + purposeOfVisitsList.value = Object.keys(purposeOfVisits).map((item) => ({ + value: item.toString(), + label: purposeOfVisits[item], + })) as any + proceduresList.value = Object.keys(procedureTypes).map((item) => ({ + value: item.toString(), + label: procedureTypes[item], + })) as any + assessmentsList.value = Object.keys(serviceAssessments).map((item) => ({ + value: item.toString(), + label: `${item.toString()} - ${serviceAssessments[item]}`, + })) as any + supportCodesList.value = Object.keys(supportCodes).map((item) => ({ + value: item.toString(), + label: `${item.toString()} - ${supportCodes[item]}`, + })) as any + classLevelsList.value = Object.keys(classLevels).map((item) => ({ + value: item.toString(), + label: classLevels[item], + })) as any + classLevelUpgradesList.value = Object.keys(classLevelUpgrades).map((item) => ({ + value: item.toString(), + label: classLevelUpgrades[item], + })) as any + classPaySourcesList.value = Object.keys(classPaySources).map((item) => ({ + value: item.toString(), + label: classPaySources[item], + })) as any + await handleFetchSpecialists() + if (route.query) { + const queries = route.query as any + isServiceHidden.value = queries['is-service'] === 'true' + selectedObjects.value = {} + if (queries['resource']) resourceType.value = queries['resource'] + if (queries['source-path']) resourcePath.value = queries['source-path'] + if (queries['doctor-code']) selectedObjects.value['doctorCode'] = queries['doctor-code'] + if (queries['specialist-code']) selectedObjects.value['subSpecialistCode'] = queries['specialist-code'] + if (queries['sub-specialist-code']) selectedObjects.value['subSpecialistCode'] = queries['sub-specialist-code'] + if (queries['card-number']) selectedObjects.value['cardNumber'] = queries['card-number'] + if (queries['register-date']) selectedObjects.value['registerDate'] = queries['register-date'] + if (queries['sep-type']) selectedObjects.value['sepType'] = queries['sep-type'] + if (queries['sep-number']) selectedObjects.value['sepNumber'] = queries['sep-number'] + if (queries['register-date']) selectedObjects.value['registerDate'] = queries['register-date'] + if (queries['payment-type']) selectedObjects.value['paymentType'] = queries['payment-type'] + if (queries['patient-id']) { + await getPatientInternalMappers(queries['patient-id']) + } + if (queries['card-number']) { + const resultMember = await getMemberList({ + mode: 'by-card', + number: queries['card-number'], + date: new Date().toISOString().substring(0, 10), + }) + console.log(resultMember) + } + delete selectedObjects.value['is-service'] + } + } + + return { + openPatient, + openLetter, + openHistory, + selectedLetter, + selectedObjects, + selectedServiceType, + selectedAdmissionType, + histories, + letters, + doctors, + diagnoses, + facilitiesFrom, + facilitiesTo, + supportCodesList, + serviceTypesList, + registerMethodsList, + accidentsList, + purposeOfVisitsList, + proceduresList, + assessmentsList, + provincesList, + citiesList, + districtsList, + classLevelsList, + classLevelUpgradesList, + classPaySourcesList, + isServiceHidden, + isSaveLoading, + isLetterReadonly, + isLoadingPatient, + specialistsTree, + resourceType, + resourcePath, + patients, + selectedPatient, + paginationMeta, + getMonitoringHistoryMappers, + getLetterMappers, + getPatientInternalMappers, + getPatientExternalMappers, + getPatientsList, + getPatientByIdentifierSearch, + handleSaveLetter, + mapLetterDataToForm, + handleSavePatient, + handleEvent, + handleFetch, + handleFetchSpecialists, + handleInit, + } } export default useIntegrationSepEntry diff --git a/app/pages/(features)/integration/bpjs/vclaim/control-letter/index.vue b/app/pages/(features)/integration/bpjs-vclaim/control-letter/index.vue similarity index 100% rename from app/pages/(features)/integration/bpjs/vclaim/control-letter/index.vue rename to app/pages/(features)/integration/bpjs-vclaim/control-letter/index.vue diff --git a/app/pages/(features)/integration/bpjs/vclaim/sep/add.vue b/app/pages/(features)/integration/bpjs-vclaim/sep/add.vue similarity index 100% rename from app/pages/(features)/integration/bpjs/vclaim/sep/add.vue rename to app/pages/(features)/integration/bpjs-vclaim/sep/add.vue diff --git a/app/pages/(features)/integration/bpjs/vclaim/sep/index.vue b/app/pages/(features)/integration/bpjs-vclaim/sep/index.vue similarity index 100% rename from app/pages/(features)/integration/bpjs/vclaim/sep/index.vue rename to app/pages/(features)/integration/bpjs-vclaim/sep/index.vue diff --git a/app/services/vclaim-control-letter.service.ts b/app/services/vclaim-control-letter.service.ts index 5747d557..2c638c2e 100644 --- a/app/services/vclaim-control-letter.service.ts +++ b/app/services/vclaim-control-letter.service.ts @@ -6,7 +6,6 @@ const name = 'rencana-kontrol' export function getList(params: any = null) { let url = path - console.log(params) if (params?.letterNumber && params.mode === 'by-control') { url += `/noSuratKontrol/${params.letterNumber}` }