Automate - Patient Apointment Invoicing

This commit is contained in:
Jamsheer 2018-08-04 12:56:36 +05:30
parent 4371c7e492
commit 363deb67c3
3 changed files with 175 additions and 36 deletions

View File

@ -241,6 +241,40 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"description": "Manage Appointment Invoice submit and cancel automatically for Patient Encounter",
"fieldname": "manage_appointment_invoice_automatically",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Manage Appointment Invoice Automatically",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -1293,7 +1327,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2018-08-01 13:30:04.448397",
"modified": "2018-08-03 15:18:36.631441",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Healthcare Settings",

View File

@ -6,11 +6,13 @@ from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
import json
from frappe.utils import getdate
from frappe.utils import getdate, add_days
from frappe import _
import datetime
from frappe.core.doctype.sms_settings.sms_settings import send_sms
from erpnext.hr.doctype.employee.employee import is_holiday
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account,get_income_account
from erpnext.healthcare.utils import validity_exists, service_item_and_practitioner_charge
class PatientAppointment(Document):
def on_update(self):
@ -41,23 +43,108 @@ class PatientAppointment(Document):
frappe.msgprint(_("{0} has fee validity till {1}").format(appointment.patient, fee_validity.valid_till))
confirm_sms(self)
if frappe.db.get_value("Healthcare Settings", None, "manage_appointment_invoice_automatically") == '1' and \
frappe.db.get_value("Patient Appointment", self.name, "invoiced") != 1:
invoice_appointment(self)
@frappe.whitelist()
def invoice_appointment(appointment_doc):
if not appointment_doc.name:
return False
sales_invoice = frappe.new_doc("Sales Invoice")
sales_invoice.customer = frappe.get_value("Patient", appointment_doc.patient, "customer")
sales_invoice.appointment = appointment_doc.name
sales_invoice.due_date = getdate()
sales_invoice.is_pos = True
sales_invoice.company = appointment_doc.company
sales_invoice.debit_to = get_receivable_account(appointment_doc.company)
item_line = sales_invoice.append("items")
service_item, practitioner_charge = service_item_and_practitioner_charge(appointment_doc)
item_line.item_code = service_item
item_line.description = "Consulting Charges: " + appointment_doc.practitioner
item_line.income_account = get_income_account(appointment_doc.practitioner, appointment_doc.company)
item_line.rate = practitioner_charge
item_line.amount = practitioner_charge
item_line.qty = 1
item_line.reference_dt = "Patient Appointment"
item_line.reference_dn = appointment_doc.name
payments_line = sales_invoice.append("payments")
payments_line.mode_of_payment = "Cash"
payments_line.amount = practitioner_charge
sales_invoice.set_missing_values(for_validate = True)
sales_invoice.save(ignore_permissions=True)
sales_invoice.submit()
frappe.msgprint(_("Sales Invoice {0} created as paid".format(sales_invoice.name)), alert=True)
def appointment_cancel(appointment_id):
appointment = frappe.get_doc("Patient Appointment", appointment_id)
# If invoiced --> fee_validity update with -1 visit
if appointment.invoiced:
validity = validity_exists(appointment.practitioner, appointment.patient)
if validity:
fee_validity = frappe.get_doc("Fee Validity", validity[0][0])
visited = fee_validity.visited - 1
frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
if visited <= 0:
frappe.msgprint(
_("Appointment cancelled, Please review and cancel the invoice {0}".format(fee_validity.ref_invoice))
)
sales_invoice = exists_sales_invoice(appointment)
if sales_invoice and cancel_sales_invoice(sales_invoice):
frappe.msgprint(
_("Appointment {0} and Sales Invoice {1} cancelled".format(appointment.name, sales_invoice.name))
)
else:
validity = validity_exists(appointment.practitioner, appointment.patient)
if validity:
fee_validity = frappe.get_doc("Fee Validity", validity[0][0])
if appointment_valid_in_fee_validity(appointment, fee_validity.valid_till, True, fee_validity.ref_invoice):
visited = fee_validity.visited - 1
frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
frappe.msgprint(
_("Appointment cancelled, Please review and cancel the invoice {0}".format(fee_validity.ref_invoice))
)
else:
frappe.msgprint(_("Appointment cancelled"))
else:
frappe.msgprint(_("Appointment cancelled"))
else:
frappe.msgprint(_("Appointment cancelled"))
def appointment_valid_in_fee_validity(appointment, valid_end_date, invoiced, ref_invoice):
valid_days = frappe.db.get_value("Healthcare Settings", None, "valid_days")
max_visit = frappe.db.get_value("Healthcare Settings", None, "max_visit")
valid_start_date = add_days(getdate(valid_end_date), -int(valid_days))
# Appointments which has same fee validity range with the appointment
appointments = frappe.get_list("Patient Appointment",{'patient': appointment.patient, 'invoiced': invoiced,
'appointment_date':("<=", getdate(valid_end_date)), 'appointment_date':(">=", getdate(valid_start_date)),
'practitioner': appointment.practitioner}, order_by="appointment_date desc", limit=int(max_visit))
if appointments and len(appointments) > 0:
appointment_obj = appointments[len(appointments)-1]
sales_invoice = exists_sales_invoice(appointment_obj)
if sales_invoice.name == ref_invoice:
return True
return False
def cancel_sales_invoice(sales_invoice):
if frappe.db.get_value("Healthcare Settings", None, "manage_appointment_invoice_automatically") == '1':
if len(sales_invoice.items) == 1:
sales_invoice.cancel()
return True
return False
def exists_sales_invoice_item(appointment):
return frappe.db.exists(
"Sales Invoice Item",
{
"reference_dt": "Patient Appointment",
"reference_dn": appointment.name
}
)
def exists_sales_invoice(appointment):
sales_item_exist = exists_sales_invoice_item(appointment)
if sales_item_exist:
sales_invoice = frappe.get_doc("Sales Invoice", frappe.db.get_value("Sales Invoice Item", sales_item_exist, "parent"))
return sales_invoice
return False
@frappe.whitelist()
def get_availability_data(date, practitioner):
@ -193,13 +280,6 @@ def confirm_sms(doc):
message = frappe.db.get_value("Healthcare Settings", None, "app_con_msg")
send_message(doc, message)
def validity_exists(practitioner, patient):
return frappe.db.exists({
"doctype": "Fee Validity",
"practitioner": practitioner,
"patient": patient})
@frappe.whitelist()
def create_encounter(appointment):
appointment = frappe.get_doc("Patient Appointment", appointment)

View File

@ -7,9 +7,8 @@ import frappe
import datetime
from frappe import _
import math
from frappe.utils import time_diff_in_hours, rounded
from frappe.utils import time_diff_in_hours, rounded, getdate, add_days
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_income_account
from erpnext.healthcare.doctype.patient_appointment.patient_appointment import validity_exists
from erpnext.healthcare.doctype.fee_validity.fee_validity import create_fee_validity, update_fee_validity
from erpnext.healthcare.doctype.lab_test.lab_test import create_multiple
@ -272,6 +271,12 @@ def manage_prescriptions(invoiced, ref_dt, ref_dn, dt, created_check_field):
doc_created = frappe.db.get_value(dt, {'prescription': ref_dn})
frappe.db.set_value(dt, doc_created, 'invoiced', invoiced)
def validity_exists(practitioner, patient):
return frappe.db.exists({
"doctype": "Fee Validity",
"practitioner": practitioner,
"patient": patient})
def manage_fee_validity(appointment_name, method, ref_invoice=None):
appointment_doc = frappe.get_doc("Patient Appointment", appointment_name)
validity_exist = validity_exists(appointment_doc.practitioner, appointment_doc.patient)
@ -282,12 +287,13 @@ def manage_fee_validity(appointment_name, method, ref_invoice=None):
# Check if the validity is valid
if (fee_validity.valid_till >= appointment_doc.appointment_date):
if (method == "on_cancel" and appointment_doc.status != "Closed"):
visited = fee_validity.visited - 1
if visited < 0:
visited = 0
frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
if ref_invoice == fee_validity.ref_invoice:
visited = fee_validity.visited - 1
if visited < 0:
visited = 0
frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
do_not_update = True
elif (fee_validity.visited < fee_validity.max_visit):
elif (method == "on_submit" and fee_validity.visited < fee_validity.max_visit):
visited = fee_validity.visited + 1
frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
do_not_update = True
@ -301,29 +307,48 @@ def manage_fee_validity(appointment_name, method, ref_invoice=None):
fee_validity = create_fee_validity(appointment_doc.practitioner, appointment_doc.patient, appointment_doc.appointment_date, ref_invoice)
visited = fee_validity.visited
print "do_not_update: ", do_not_update
print "visited: ", visited
# Mark All Patient Appointment invoiced = True in the validity range do not cross the max visit
if (method == "on_cancel"):
invoiced = True
else:
invoiced = False
patient_appointments = frappe.get_list("Patient Appointment",{'patient': fee_validity.patient, 'invoiced': invoiced,
'appointment_date':("<=", fee_validity.valid_till), 'practitioner': fee_validity.practitioner}, order_by="appointment_date")
patient_appointments = appointments_valid_in_fee_validity(appointment_doc, invoiced)
if patient_appointments and fee_validity:
visit = visited
for appointment in patient_appointments:
if (method == "on_cancel" and appointment.status != "Closed"):
visited = visited - 1
if visited < 0:
visited = 0
frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
if ref_invoice == fee_validity.ref_invoice:
visited = visited - 1
if visited < 0:
visited = 0
frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
frappe.db.set_value("Patient Appointment", appointment.name, "invoiced", False)
manage_doc_for_appoitnment("Patient Encounter", appointment.name, False)
elif int(fee_validity.max_visit) > visit:
visited = visited + 1
frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
elif method == "on_submit" and int(fee_validity.max_visit) > visit:
if ref_invoice == fee_validity.ref_invoice:
visited = visited + 1
frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
frappe.db.set_value("Patient Appointment", appointment.name, "invoiced", True)
manage_doc_for_appoitnment("Patient Encounter", appointment.name, True)
visit = visit + 1
if ref_invoice == fee_validity.ref_invoice:
visit = visit + 1
if method == "on_cancel":
ref_invoice_in_fee_validity = frappe.db.get_value("Fee Validity", fee_validity.name, 'ref_invoice')
if ref_invoice_in_fee_validity == ref_invoice:
frappe.delete_doc("Fee Validity", fee_validity.name)
def appointments_valid_in_fee_validity(appointment, invoiced):
valid_days = frappe.db.get_value("Healthcare Settings", None, "valid_days")
max_visit = frappe.db.get_value("Healthcare Settings", None, "max_visit")
valid_days_date = add_days(getdate(appointment.appointment_date), int(valid_days))
return frappe.get_list("Patient Appointment",{'patient': appointment.patient, 'invoiced': invoiced,
'appointment_date':("<=", valid_days_date), 'appointment_date':(">=", getdate(appointment.appointment_date)),
'practitioner': appointment.practitioner}, order_by="appointment_date", limit=int(max_visit)-1)
def manage_doc_for_appoitnment(dt_from_appointment, appointment, invoiced):
dn_from_appointment = frappe.db.exists(