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:
anoop 2020-04-13 16:42:03 +05:30
parent f90ea8d622
commit c01fb2a4d8
2 changed files with 55 additions and 48 deletions

View File

@ -919,7 +919,7 @@ var get_healthcare_services_to_invoice = function(frm) {
if(patient && patient!=selected_patient){
selected_patient = patient;
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"]);
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.',
get_query: function(doc) {
return {
filters: { patient: dialog.get_value("patient"), docstatus: 1 }
filters: { patient: dialog.get_value("patient"),
company: frm.doc.company,
docstatus: 1
}
};
}
},

View File

@ -3,82 +3,84 @@
# For license information, please see license.txt
from __future__ import unicode_literals
import math
import json
import frappe
from frappe import _
import math
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.fee_validity.fee_validity import create_fee_validity
from erpnext.healthcare.doctype.lab_test.lab_test import create_multiple
@frappe.whitelist()
def get_healthcare_services_to_invoice(patient):
def get_healthcare_services_to_invoice(patient, company):
patient = frappe.get_doc('Patient', patient)
items_to_invoice = []
if patient:
validate_customer_created(patient)
items_to_invoice = []
patient_appointments = frappe.get_list(
'Patient Appointment',
fields='*',
filters={'patient': patient.name, 'invoiced': 0},
order_by='appointment_date'
)
if patient_appointments:
items_to_invoice = get_fee_validity(patient_appointments)
# Customer validated, build a list of billable services
items_to_invoice += get_appointments_to_invoice(patient, company)
items_to_invoice += get_encounters_to_invoice(patient, company)
items_to_invoice += get_lab_tests_to_invoice(patient, company)
items_to_invoice += get_clinical_procedures_to_invoice(patient, company)
items_to_invoice += get_inpatient_services_to_invoice(patient, company)
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
def validate_customer_created(patient):
if not frappe.db.get_value('Patient', patient.name, 'customer'):
msg = _("Please set a Customer linked to the Patient")
msg += " <b><a href='#Form/Patient/{0}'>{0}</a></b>".format(patient.name)
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:
# Procedure Appointments
if appointment.procedure_template:
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_name': appointment.name,
'service': appointment.procedure_template
})
# Consultation Appointments, should check fee validity
else:
fee_validity = frappe.db.exists('Fee Validity Reference', {'appointment': appointment.name})
if not fee_validity:
practitioner_charge = 0
income_account = None
service_item = None
if appointment.practitioner:
service_item, practitioner_charge = get_service_item_and_practitioner_charge(appointment)
income_account = get_income_account(appointment.practitioner, appointment.company)
items_to_invoice.append({
'reference_type': 'Patient Appointment',
'reference_name': appointment.name,
'service': service_item,
'rate': practitioner_charge,
'income_account': income_account
})
if frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups') and \
frappe.db.exists('Fee Validity Reference', {'appointment': appointment.name}):
continue # Skip invoicing, fee validty present
practitioner_charge = 0
income_account = None
service_item = None
if appointment.practitioner:
service_item, practitioner_charge = get_service_item_and_practitioner_charge(appointment)
income_account = get_income_account(appointment.practitioner, appointment.company)
appointments_to_invoice.append({
'reference_type': 'Patient Appointment',
'reference_name': appointment.name,
'service': service_item,
'rate': practitioner_charge,
'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 = frappe.get_list(
'Patient Encounter',
fields=['*'],
filters={'patient': patient.name, 'invoiced': False, 'docstatus': 1}
filters={'patient': patient.name, 'company': company, 'invoiced': False, 'docstatus': 1}
)
if encounters:
for encounter in encounters:
@ -101,12 +103,12 @@ def get_encounters_to_invoice(patient):
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 = frappe.get_list(
'Lab Test',
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:
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
def get_clinical_procedures_to_invoice(patient):
def get_clinical_procedures_to_invoice(patient, company):
clinical_procedures_to_invoice = []
procedures = frappe.get_list(
'Clinical Procedure',
fields='*',
filters={'patient': patient.name, 'invoiced': False}
filters={'patient': patient.name, 'company': company, 'invoiced': False}
)
for procedure in procedures:
if not procedure.appointment:
@ -203,7 +205,7 @@ def get_clinical_procedures_to_invoice(patient):
return clinical_procedures_to_invoice
def get_inpatient_services_to_invoice(patient):
def get_inpatient_services_to_invoice(patient, company):
services_to_invoice = []
inpatient_services = frappe.db.sql(
'''
@ -213,10 +215,11 @@ def get_inpatient_services_to_invoice(patient):
`tabInpatient Record` ip, `tabInpatient Occupancy` io
WHERE
ip.patient=%s
and ip.company=%s
and io.parent=ip.name
and io.left=1
and io.invoiced=0
''', (patient.name), as_dict=1)
''', (patient.name, company), as_dict=1)
for inpatient_occupancy in inpatient_services:
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):
fee_validity = check_fee_validity(appointment)
if fee_validity:
if appointment.status == 'Cancelled' and fee_validity.visited > 0:
fee_validity.visited -= 1