feat: multi-company billing
sales onvoice - filter get items based on company utils - company filters in all get item helper methods utils - refactor appointemnt items
This commit is contained in:
parent
f90ea8d622
commit
c01fb2a4d8
@ -919,7 +919,7 @@ var get_healthcare_services_to_invoice = function(frm) {
|
|||||||
if(patient && patient!=selected_patient){
|
if(patient && patient!=selected_patient){
|
||||||
selected_patient = patient;
|
selected_patient = patient;
|
||||||
var method = "erpnext.healthcare.utils.get_healthcare_services_to_invoice";
|
var method = "erpnext.healthcare.utils.get_healthcare_services_to_invoice";
|
||||||
var args = {patient: patient};
|
var args = {patient: patient, company: frm.doc.company};
|
||||||
var columns = (["service", "reference_name", "reference_type"]);
|
var columns = (["service", "reference_name", "reference_type"]);
|
||||||
get_healthcare_items(frm, true, $results, $placeholder, method, args, columns);
|
get_healthcare_items(frm, true, $results, $placeholder, method, args, columns);
|
||||||
}
|
}
|
||||||
@ -1063,7 +1063,10 @@ var get_drugs_to_invoice = function(frm) {
|
|||||||
description:'Quantity will be calculated only for items which has "Nos" as UoM. You may change as required for each invoice item.',
|
description:'Quantity will be calculated only for items which has "Nos" as UoM. You may change as required for each invoice item.',
|
||||||
get_query: function(doc) {
|
get_query: function(doc) {
|
||||||
return {
|
return {
|
||||||
filters: { patient: dialog.get_value("patient"), docstatus: 1 }
|
filters: { patient: dialog.get_value("patient"),
|
||||||
|
company: frm.doc.company,
|
||||||
|
docstatus: 1
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3,66 +3,68 @@
|
|||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
import math
|
||||||
|
import json
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
import math
|
|
||||||
from frappe.utils import time_diff_in_hours, rounded
|
from frappe.utils import time_diff_in_hours, rounded
|
||||||
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_income_account
|
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_income_account
|
||||||
from erpnext.healthcare.doctype.fee_validity.fee_validity import create_fee_validity
|
from erpnext.healthcare.doctype.fee_validity.fee_validity import create_fee_validity
|
||||||
from erpnext.healthcare.doctype.lab_test.lab_test import create_multiple
|
from erpnext.healthcare.doctype.lab_test.lab_test import create_multiple
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_healthcare_services_to_invoice(patient):
|
def get_healthcare_services_to_invoice(patient, company):
|
||||||
patient = frappe.get_doc('Patient', patient)
|
patient = frappe.get_doc('Patient', patient)
|
||||||
|
items_to_invoice = []
|
||||||
if patient:
|
if patient:
|
||||||
validate_customer_created(patient)
|
validate_customer_created(patient)
|
||||||
items_to_invoice = []
|
# Customer validated, build a list of billable services
|
||||||
patient_appointments = frappe.get_list(
|
items_to_invoice += get_appointments_to_invoice(patient, company)
|
||||||
'Patient Appointment',
|
items_to_invoice += get_encounters_to_invoice(patient, company)
|
||||||
fields='*',
|
items_to_invoice += get_lab_tests_to_invoice(patient, company)
|
||||||
filters={'patient': patient.name, 'invoiced': 0},
|
items_to_invoice += get_clinical_procedures_to_invoice(patient, company)
|
||||||
order_by='appointment_date'
|
items_to_invoice += get_inpatient_services_to_invoice(patient, company)
|
||||||
)
|
|
||||||
if patient_appointments:
|
|
||||||
items_to_invoice = get_fee_validity(patient_appointments)
|
|
||||||
|
|
||||||
encounters = get_encounters_to_invoice(patient)
|
|
||||||
lab_tests = get_lab_tests_to_invoice(patient)
|
|
||||||
clinical_procedures = get_clinical_procedures_to_invoice(patient)
|
|
||||||
inpatient_services = get_inpatient_services_to_invoice(patient)
|
|
||||||
|
|
||||||
items_to_invoice += encounters + lab_tests + clinical_procedures + inpatient_services
|
|
||||||
return items_to_invoice
|
return items_to_invoice
|
||||||
|
|
||||||
|
|
||||||
def validate_customer_created(patient):
|
def validate_customer_created(patient):
|
||||||
if not frappe.db.get_value('Patient', patient.name, 'customer'):
|
if not frappe.db.get_value('Patient', patient.name, 'customer'):
|
||||||
msg = _("Please set a Customer linked to the Patient")
|
msg = _("Please set a Customer linked to the Patient")
|
||||||
msg += " <b><a href='#Form/Patient/{0}'>{0}</a></b>".format(patient.name)
|
msg += " <b><a href='#Form/Patient/{0}'>{0}</a></b>".format(patient.name)
|
||||||
frappe.throw(msg, title=_('Customer Not Found'))
|
frappe.throw(msg, title=_('Customer Not Found'))
|
||||||
|
|
||||||
def get_fee_validity(patient_appointments):
|
|
||||||
if not frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups'):
|
|
||||||
return
|
|
||||||
|
|
||||||
items_to_invoice = []
|
def get_appointments_to_invoice(patient, company):
|
||||||
|
appointments_to_invoice = []
|
||||||
|
patient_appointments = frappe.get_list(
|
||||||
|
'Patient Appointment',
|
||||||
|
fields = '*',
|
||||||
|
filters = {'patient': patient.name, 'company': company, 'invoiced': 0},
|
||||||
|
order_by = 'appointment_date'
|
||||||
|
)
|
||||||
|
|
||||||
for appointment in patient_appointments:
|
for appointment in patient_appointments:
|
||||||
|
# Procedure Appointments
|
||||||
if appointment.procedure_template:
|
if appointment.procedure_template:
|
||||||
if frappe.db.get_value('Clinical Procedure Template', appointment.procedure_template, 'is_billable'):
|
if frappe.db.get_value('Clinical Procedure Template', appointment.procedure_template, 'is_billable'):
|
||||||
items_to_invoice.append({
|
appointments_to_invoice.append({
|
||||||
'reference_type': 'Patient Appointment',
|
'reference_type': 'Patient Appointment',
|
||||||
'reference_name': appointment.name,
|
'reference_name': appointment.name,
|
||||||
'service': appointment.procedure_template
|
'service': appointment.procedure_template
|
||||||
})
|
})
|
||||||
|
# Consultation Appointments, should check fee validity
|
||||||
else:
|
else:
|
||||||
fee_validity = frappe.db.exists('Fee Validity Reference', {'appointment': appointment.name})
|
if frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups') and \
|
||||||
if not fee_validity:
|
frappe.db.exists('Fee Validity Reference', {'appointment': appointment.name}):
|
||||||
|
continue # Skip invoicing, fee validty present
|
||||||
practitioner_charge = 0
|
practitioner_charge = 0
|
||||||
income_account = None
|
income_account = None
|
||||||
service_item = None
|
service_item = None
|
||||||
if appointment.practitioner:
|
if appointment.practitioner:
|
||||||
service_item, practitioner_charge = get_service_item_and_practitioner_charge(appointment)
|
service_item, practitioner_charge = get_service_item_and_practitioner_charge(appointment)
|
||||||
income_account = get_income_account(appointment.practitioner, appointment.company)
|
income_account = get_income_account(appointment.practitioner, appointment.company)
|
||||||
items_to_invoice.append({
|
appointments_to_invoice.append({
|
||||||
'reference_type': 'Patient Appointment',
|
'reference_type': 'Patient Appointment',
|
||||||
'reference_name': appointment.name,
|
'reference_name': appointment.name,
|
||||||
'service': service_item,
|
'service': service_item,
|
||||||
@ -70,15 +72,15 @@ def get_fee_validity(patient_appointments):
|
|||||||
'income_account': income_account
|
'income_account': income_account
|
||||||
})
|
})
|
||||||
|
|
||||||
return items_to_invoice
|
return appointments_to_invoice
|
||||||
|
|
||||||
|
|
||||||
def get_encounters_to_invoice(patient):
|
def get_encounters_to_invoice(patient, company):
|
||||||
encounters_to_invoice = []
|
encounters_to_invoice = []
|
||||||
encounters = frappe.get_list(
|
encounters = frappe.get_list(
|
||||||
'Patient Encounter',
|
'Patient Encounter',
|
||||||
fields=['*'],
|
fields=['*'],
|
||||||
filters={'patient': patient.name, 'invoiced': False, 'docstatus': 1}
|
filters={'patient': patient.name, 'company': company, 'invoiced': False, 'docstatus': 1}
|
||||||
)
|
)
|
||||||
if encounters:
|
if encounters:
|
||||||
for encounter in encounters:
|
for encounter in encounters:
|
||||||
@ -101,12 +103,12 @@ def get_encounters_to_invoice(patient):
|
|||||||
return encounters_to_invoice
|
return encounters_to_invoice
|
||||||
|
|
||||||
|
|
||||||
def get_lab_tests_to_invoice(patient):
|
def get_lab_tests_to_invoice(patient, company):
|
||||||
lab_tests_to_invoice = []
|
lab_tests_to_invoice = []
|
||||||
lab_tests = frappe.get_list(
|
lab_tests = frappe.get_list(
|
||||||
'Lab Test',
|
'Lab Test',
|
||||||
fields=['name', 'template'],
|
fields=['name', 'template'],
|
||||||
filters={'patient': patient.name, 'invoiced': False, 'docstatus': 1}
|
filters={'patient': patient.name, 'company': company, 'invoiced': False, 'docstatus': 1}
|
||||||
)
|
)
|
||||||
for lab_test in lab_tests:
|
for lab_test in lab_tests:
|
||||||
item, is_billable = frappe.get_cached_value('Lab Test Template', lab_test.lab_test_code, ['item', 'is_billable'])
|
item, is_billable = frappe.get_cached_value('Lab Test Template', lab_test.lab_test_code, ['item', 'is_billable'])
|
||||||
@ -142,12 +144,12 @@ def get_lab_tests_to_invoice(patient):
|
|||||||
return lab_tests_to_invoice
|
return lab_tests_to_invoice
|
||||||
|
|
||||||
|
|
||||||
def get_clinical_procedures_to_invoice(patient):
|
def get_clinical_procedures_to_invoice(patient, company):
|
||||||
clinical_procedures_to_invoice = []
|
clinical_procedures_to_invoice = []
|
||||||
procedures = frappe.get_list(
|
procedures = frappe.get_list(
|
||||||
'Clinical Procedure',
|
'Clinical Procedure',
|
||||||
fields='*',
|
fields='*',
|
||||||
filters={'patient': patient.name, 'invoiced': False}
|
filters={'patient': patient.name, 'company': company, 'invoiced': False}
|
||||||
)
|
)
|
||||||
for procedure in procedures:
|
for procedure in procedures:
|
||||||
if not procedure.appointment:
|
if not procedure.appointment:
|
||||||
@ -203,7 +205,7 @@ def get_clinical_procedures_to_invoice(patient):
|
|||||||
return clinical_procedures_to_invoice
|
return clinical_procedures_to_invoice
|
||||||
|
|
||||||
|
|
||||||
def get_inpatient_services_to_invoice(patient):
|
def get_inpatient_services_to_invoice(patient, company):
|
||||||
services_to_invoice = []
|
services_to_invoice = []
|
||||||
inpatient_services = frappe.db.sql(
|
inpatient_services = frappe.db.sql(
|
||||||
'''
|
'''
|
||||||
@ -213,10 +215,11 @@ def get_inpatient_services_to_invoice(patient):
|
|||||||
`tabInpatient Record` ip, `tabInpatient Occupancy` io
|
`tabInpatient Record` ip, `tabInpatient Occupancy` io
|
||||||
WHERE
|
WHERE
|
||||||
ip.patient=%s
|
ip.patient=%s
|
||||||
|
and ip.company=%s
|
||||||
and io.parent=ip.name
|
and io.parent=ip.name
|
||||||
and io.left=1
|
and io.left=1
|
||||||
and io.invoiced=0
|
and io.invoiced=0
|
||||||
''', (patient.name), as_dict=1)
|
''', (patient.name, company), as_dict=1)
|
||||||
|
|
||||||
for inpatient_occupancy in inpatient_services:
|
for inpatient_occupancy in inpatient_services:
|
||||||
service_unit_type = frappe.db.get_value('Healthcare Service Unit', inpatient_occupancy.service_unit, 'service_unit_type')
|
service_unit_type = frappe.db.get_value('Healthcare Service Unit', inpatient_occupancy.service_unit, 'service_unit_type')
|
||||||
@ -376,6 +379,7 @@ def check_fee_validity(appointment):
|
|||||||
|
|
||||||
def manage_fee_validity(appointment):
|
def manage_fee_validity(appointment):
|
||||||
fee_validity = check_fee_validity(appointment)
|
fee_validity = check_fee_validity(appointment)
|
||||||
|
|
||||||
if fee_validity:
|
if fee_validity:
|
||||||
if appointment.status == 'Cancelled' and fee_validity.visited > 0:
|
if appointment.status == 'Cancelled' and fee_validity.visited > 0:
|
||||||
fee_validity.visited -= 1
|
fee_validity.visited -= 1
|
||||||
|
Loading…
Reference in New Issue
Block a user