Merge branch 'healthcare_v11_wip' of https://github.com/ESS-LLP/erpnext-healthcare into ESS-LLP-healthcare_v11_wip
This commit is contained in:
commit
aacb915cae
@ -16,7 +16,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
},
|
||||
onload: function() {
|
||||
var me = this;
|
||||
this._super();
|
||||
this._super();
|
||||
console.log("class erpnext.accounts.SalesInvoiceController, onload this->", this);
|
||||
|
||||
if(!this.frm.doc.__islocal && !this.frm.doc.customer && this.frm.doc.debit_to) {
|
||||
// show debit_to in print format
|
||||
@ -466,7 +467,7 @@ cur_frm.fields_dict.write_off_cost_center.get_query = function(doc) {
|
||||
}
|
||||
}
|
||||
|
||||
//project name
|
||||
// project name
|
||||
//--------------------------
|
||||
cur_frm.fields_dict['project'].get_query = function(doc, cdt, cdn) {
|
||||
return{
|
||||
@ -543,7 +544,7 @@ cur_frm.set_query("asset", "items", function(doc, cdt, cdn) {
|
||||
|
||||
frappe.ui.form.on('Sales Invoice', {
|
||||
setup: function(frm){
|
||||
|
||||
|
||||
frm.custom_make_buttons = {
|
||||
'Delivery Note': 'Delivery',
|
||||
'Sales Invoice': 'Sales Return',
|
||||
@ -625,7 +626,7 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
}
|
||||
};
|
||||
},
|
||||
//When multiple companies are set up. in case company name is changed set default company address
|
||||
// When multiple companies are set up. in case company name is changed set default company address
|
||||
company:function(frm){
|
||||
if (frm.doc.company)
|
||||
{
|
||||
@ -712,8 +713,52 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
}
|
||||
frm.set_value("loyalty_amount", loyalty_amount);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Healthcare
|
||||
patient: function(frm) {
|
||||
if (frappe.boot.active_domains.includes("Healthcare")){
|
||||
if(frm.doc.patient){
|
||||
frappe.call({
|
||||
method: "frappe.client.get_value",
|
||||
args:{
|
||||
doctype: "Patient",
|
||||
filters: {"name": frm.doc.patient},
|
||||
fieldname: "customer"
|
||||
},
|
||||
callback:function(patient_customer) {
|
||||
if(patient_customer){
|
||||
frm.set_value("customer", patient_customer.message.customer);
|
||||
frm.refresh_fields();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else{
|
||||
frm.set_value("customer", '');
|
||||
}
|
||||
}
|
||||
},
|
||||
refresh: function(frm) {
|
||||
if (frappe.boot.active_domains.includes("Healthcare")){
|
||||
frm.set_df_property("patient", "hidden", 0);
|
||||
frm.set_df_property("patient_name", "hidden", 0);
|
||||
frm.set_df_property("ref_practitioner", "hidden", 0);
|
||||
if (cint(frm.doc.docstatus==0) && cur_frm.page.current_view_name!=="pos" && !frm.doc.is_return) {
|
||||
frm.add_custom_button(__('Healthcare Services'), function() {
|
||||
get_healthcare_services_to_invoice(frm);
|
||||
},"Get items from");
|
||||
frm.add_custom_button(__('Prescriptions'), function() {
|
||||
get_drugs_to_invoice(frm);
|
||||
},"Get items from");
|
||||
}
|
||||
}
|
||||
else{
|
||||
frm.set_df_property("patient", "hidden", 1);
|
||||
frm.set_df_property("patient_name", "hidden", 1);
|
||||
frm.set_df_property("ref_practitioner", "hidden", 1);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
frappe.ui.form.on('Sales Invoice Timesheet', {
|
||||
@ -816,3 +861,270 @@ var select_loyalty_program = function(frm, loyalty_programs) {
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
// Healthcare
|
||||
var get_healthcare_services_to_invoice = function(frm) {
|
||||
var me = this;
|
||||
let selected_patient = '';
|
||||
var dialog = new frappe.ui.Dialog({
|
||||
title: __("Get Items from Healthcare Services"),
|
||||
fields:[
|
||||
{
|
||||
fieldtype: 'Link',
|
||||
options: 'Patient',
|
||||
label: 'Patient',
|
||||
fieldname: "patient",
|
||||
reqd: true
|
||||
},
|
||||
{ fieldtype: 'Section Break' },
|
||||
{ fieldtype: 'HTML', fieldname: 'results_area' }
|
||||
]
|
||||
});
|
||||
var $wrapper;
|
||||
var $results;
|
||||
var $placeholder;
|
||||
dialog.set_values({
|
||||
'patient': frm.doc.patient
|
||||
});
|
||||
dialog.fields_dict["patient"].df.onchange = () => {
|
||||
var patient = dialog.fields_dict.patient.input.value;
|
||||
if(patient && patient!=selected_patient){
|
||||
selected_patient = patient;
|
||||
var method = "erpnext.healthcare.utils.get_healthcare_services_to_invoice";
|
||||
var args = {patient: patient};
|
||||
var columns = (["service", "reference_name", "reference_type"]);
|
||||
get_healthcare_items(frm, true, $results, $placeholder, method, args, columns);
|
||||
}
|
||||
else if(!patient){
|
||||
selected_patient = '';
|
||||
$results.empty();
|
||||
$results.append($placeholder);
|
||||
}
|
||||
}
|
||||
$wrapper = dialog.fields_dict.results_area.$wrapper.append(`<div class="results"
|
||||
style="border: 1px solid #d1d8dd; border-radius: 3px; height: 300px; overflow: auto;"></div>`);
|
||||
$results = $wrapper.find('.results');
|
||||
$placeholder = $(`<div class="multiselect-empty-state">
|
||||
<span class="text-center" style="margin-top: -40px;">
|
||||
<i class="fa fa-2x fa-heartbeat text-extra-muted"></i>
|
||||
<p class="text-extra-muted">No billable Healthcare Services found</p>
|
||||
</span>
|
||||
</div>`);
|
||||
$results.on('click', '.list-item--head :checkbox', (e) => {
|
||||
$results.find('.list-item-container .list-row-check')
|
||||
.prop("checked", ($(e.target).is(':checked')));
|
||||
});
|
||||
set_primary_action(frm, dialog, $results, true);
|
||||
dialog.show();
|
||||
};
|
||||
|
||||
var get_healthcare_items = function(frm, invoice_healthcare_services, $results, $placeholder, method, args, columns) {
|
||||
var me = this;
|
||||
$results.empty();
|
||||
frappe.call({
|
||||
method: method,
|
||||
args: args,
|
||||
callback: function(data) {
|
||||
if(data.message){
|
||||
$results.append(make_list_row(columns, invoice_healthcare_services));
|
||||
for(let i=0; i<data.message.length; i++){
|
||||
$results.append(make_list_row(columns, invoice_healthcare_services, data.message[i]));
|
||||
}
|
||||
}else {
|
||||
$results.append($placeholder);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var make_list_row= function(columns, invoice_healthcare_services, result={}) {
|
||||
var me = this;
|
||||
// Make a head row by default (if result not passed)
|
||||
let head = Object.keys(result).length === 0;
|
||||
let contents = ``;
|
||||
columns.forEach(function(column) {
|
||||
contents += `<div class="list-item__content ellipsis">
|
||||
${
|
||||
head ? `<span class="ellipsis">${__(frappe.model.unscrub(column))}</span>`
|
||||
|
||||
:(column !== "name" ? `<span class="ellipsis">${__(result[column])}</span>`
|
||||
: `<a class="list-id ellipsis">
|
||||
${__(result[column])}</a>`)
|
||||
}
|
||||
</div>`;
|
||||
})
|
||||
|
||||
let $row = $(`<div class="list-item">
|
||||
<div class="list-item__content" style="flex: 0 0 10px;">
|
||||
<input type="checkbox" class="list-row-check" ${result.checked ? 'checked' : ''}>
|
||||
</div>
|
||||
${contents}
|
||||
</div>`);
|
||||
|
||||
$row = list_row_data_items(head, $row, result, invoice_healthcare_services);
|
||||
return $row;
|
||||
};
|
||||
|
||||
var set_primary_action= function(frm, dialog, $results, invoice_healthcare_services) {
|
||||
var me = this;
|
||||
dialog.set_primary_action(__('Add'), function() {
|
||||
let checked_values = get_checked_values($results);
|
||||
if(checked_values.length > 0){
|
||||
frm.set_value("patient", dialog.fields_dict.patient.input.value);
|
||||
frm.set_value("items", []);
|
||||
add_to_item_line(frm, checked_values, invoice_healthcare_services);
|
||||
dialog.hide();
|
||||
}
|
||||
else{
|
||||
if(invoice_healthcare_services){
|
||||
frappe.msgprint(__("Please select Healthcare Service"));
|
||||
}
|
||||
else{
|
||||
frappe.msgprint(__("Please select Drug"));
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var get_checked_values= function($results) {
|
||||
return $results.find('.list-item-container').map(function() {
|
||||
let checked_values = {};
|
||||
if ($(this).find('.list-row-check:checkbox:checked').length > 0 ) {
|
||||
checked_values['dn'] = $(this).attr('data-dn');
|
||||
checked_values['dt'] = $(this).attr('data-dt');
|
||||
checked_values['item'] = $(this).attr('data-item');
|
||||
if($(this).attr('data-rate') != 'undefined'){
|
||||
checked_values['rate'] = $(this).attr('data-rate');
|
||||
}
|
||||
else{
|
||||
checked_values['rate'] = false;
|
||||
}
|
||||
if($(this).attr('data-income-account') != 'undefined'){
|
||||
checked_values['income_account'] = $(this).attr('data-income-account');
|
||||
}
|
||||
else{
|
||||
checked_values['income_account'] = false;
|
||||
}
|
||||
if($(this).attr('data-qty') != 'undefined'){
|
||||
checked_values['qty'] = $(this).attr('data-qty');
|
||||
}
|
||||
else{
|
||||
checked_values['qty'] = false;
|
||||
}
|
||||
if($(this).attr('data-description') != 'undefined'){
|
||||
checked_values['description'] = $(this).attr('data-description');
|
||||
}
|
||||
else{
|
||||
checked_values['description'] = false;
|
||||
}
|
||||
return checked_values;
|
||||
}
|
||||
}).get();
|
||||
};
|
||||
|
||||
var get_drugs_to_invoice = function(frm) {
|
||||
var me = this;
|
||||
let selected_encounter = '';
|
||||
var dialog = new frappe.ui.Dialog({
|
||||
title: __("Get Items from Prescriptions"),
|
||||
fields:[
|
||||
{ fieldtype: 'Link', options: 'Patient', label: 'Patient', fieldname: "patient", reqd: true },
|
||||
{ fieldtype: 'Link', options: 'Patient Encounter', label: 'Patient Encounter', fieldname: "encounter", reqd: true,
|
||||
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") }
|
||||
};
|
||||
}
|
||||
},
|
||||
{ fieldtype: 'Section Break' },
|
||||
{ fieldtype: 'HTML', fieldname: 'results_area' }
|
||||
]
|
||||
});
|
||||
var $wrapper;
|
||||
var $results;
|
||||
var $placeholder;
|
||||
dialog.set_values({
|
||||
'patient': frm.doc.patient,
|
||||
'encounter': ""
|
||||
});
|
||||
dialog.fields_dict["encounter"].df.onchange = () => {
|
||||
var encounter = dialog.fields_dict.encounter.input.value;
|
||||
if(encounter && encounter!=selected_encounter){
|
||||
selected_encounter = encounter;
|
||||
var method = "erpnext.healthcare.utils.get_drugs_to_invoice";
|
||||
var args = {encounter: encounter};
|
||||
var columns = (["drug_code", "quantity", "description"]);
|
||||
get_healthcare_items(frm, false, $results, $placeholder, method, args, columns);
|
||||
}
|
||||
else if(!encounter){
|
||||
selected_encounter = '';
|
||||
$results.empty();
|
||||
$results.append($placeholder);
|
||||
}
|
||||
}
|
||||
$wrapper = dialog.fields_dict.results_area.$wrapper.append(`<div class="results"
|
||||
style="border: 1px solid #d1d8dd; border-radius: 3px; height: 300px; overflow: auto;"></div>`);
|
||||
$results = $wrapper.find('.results');
|
||||
$placeholder = $(`<div class="multiselect-empty-state">
|
||||
<span class="text-center" style="margin-top: -40px;">
|
||||
<i class="fa fa-2x fa-heartbeat text-extra-muted"></i>
|
||||
<p class="text-extra-muted">No Drug Prescription found</p>
|
||||
</span>
|
||||
</div>`);
|
||||
$results.on('click', '.list-item--head :checkbox', (e) => {
|
||||
$results.find('.list-item-container .list-row-check')
|
||||
.prop("checked", ($(e.target).is(':checked')));
|
||||
});
|
||||
set_primary_action(frm, dialog, $results, false);
|
||||
dialog.show();
|
||||
};
|
||||
|
||||
var list_row_data_items = function(head, $row, result, invoice_healthcare_services) {
|
||||
if(invoice_healthcare_services){
|
||||
head ? $row.addClass('list-item--head')
|
||||
: $row = $(`<div class="list-item-container"
|
||||
data-dn= "${result.reference_name}" data-dt= "${result.reference_type}" data-item= "${result.service}"
|
||||
data-rate = ${result.rate}
|
||||
data-income-account = "${result.income_account}"
|
||||
data-qty = ${result.qty}
|
||||
data-description = "${result.description}">
|
||||
</div>`).append($row);
|
||||
}
|
||||
else{
|
||||
head ? $row.addClass('list-item--head')
|
||||
: $row = $(`<div class="list-item-container"
|
||||
data-item= "${result.drug_code}"
|
||||
data-qty = ${result.quantity}
|
||||
data-description = "${result.description}">
|
||||
</div>`).append($row);
|
||||
}
|
||||
return $row
|
||||
};
|
||||
|
||||
var add_to_item_line = function(frm, checked_values, invoice_healthcare_services){
|
||||
if(invoice_healthcare_services){
|
||||
frappe.call({
|
||||
doc: frm.doc,
|
||||
method: "set_healthcare_services",
|
||||
args:{
|
||||
checked_values: checked_values
|
||||
},
|
||||
callback: function() {
|
||||
frm.trigger("validate");
|
||||
frm.refresh_fields();
|
||||
}
|
||||
});
|
||||
}
|
||||
else{
|
||||
for(let i=0; i<checked_values.length; i++){
|
||||
var si_item = frappe.model.add_child(frm.doc, 'Sales Invoice Item', 'items');
|
||||
frappe.model.set_value(si_item.doctype, si_item.name, 'item_code', checked_values[i]['item']);
|
||||
frappe.model.set_value(si_item.doctype, si_item.name, 'qty', 1);
|
||||
if(checked_values[i]['qty'] > 1){
|
||||
frappe.model.set_value(si_item.doctype, si_item.name, 'qty', parseFloat(checked_values[i]['qty']));
|
||||
}
|
||||
}
|
||||
frm.refresh_fields();
|
||||
}
|
||||
};
|
||||
|
@ -24,6 +24,8 @@ from erpnext.accounts.general_ledger import get_round_off_account_and_cost_cente
|
||||
from erpnext.accounts.doctype.loyalty_program.loyalty_program import \
|
||||
get_loyalty_program_details_with_points, get_loyalty_details, validate_loyalty_points
|
||||
|
||||
from erpnext.healthcare.utils import manage_invoice_submit_cancel
|
||||
|
||||
from six import iteritems
|
||||
|
||||
form_grid_templates = {
|
||||
@ -179,6 +181,13 @@ class SalesInvoice(SellingController):
|
||||
if self.redeem_loyalty_points and self.loyalty_points:
|
||||
self.apply_loyalty_points()
|
||||
|
||||
# Healthcare Service Invoice.
|
||||
domain_settings = frappe.get_doc('Domain Settings')
|
||||
active_domains = [d.domain for d in domain_settings.active_domains]
|
||||
|
||||
if "Healthcare" in active_domains:
|
||||
manage_invoice_submit_cancel(self, "on_submit")
|
||||
|
||||
def validate_pos_paid_amount(self):
|
||||
if len(self.payments) == 0 and self.is_pos:
|
||||
frappe.throw(_("At least one mode of payment is required for POS invoice."))
|
||||
@ -227,6 +236,13 @@ class SalesInvoice(SellingController):
|
||||
|
||||
unlink_inter_company_invoice(self.doctype, self.name, self.inter_company_invoice_reference)
|
||||
|
||||
# Healthcare Service Invoice.
|
||||
domain_settings = frappe.get_doc('Domain Settings')
|
||||
active_domains = [d.domain for d in domain_settings.active_domains]
|
||||
|
||||
if "Healthcare" in active_domains:
|
||||
manage_invoice_submit_cancel(self, "on_cancel")
|
||||
|
||||
def update_status_updater_args(self):
|
||||
if cint(self.update_stock):
|
||||
self.status_updater.extend([{
|
||||
@ -1176,6 +1192,43 @@ class SalesInvoice(SellingController):
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
make_gl_entries(gl_entries, cancel=(self.docstatus == 2), merge_entries=True)
|
||||
|
||||
# Healthcare
|
||||
def set_healthcare_services(self, checked_values):
|
||||
self.set("items", [])
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
for checked_item in checked_values:
|
||||
item_line = self.append("items", {})
|
||||
price_list, price_list_currency = frappe.db.get_values("Price List", {"selling": 1}, ['name', 'currency'])[0]
|
||||
args = {
|
||||
'doctype': "Sales Invoice",
|
||||
'item_code': checked_item['item'],
|
||||
'company': self.company,
|
||||
'customer': frappe.db.get_value("Patient", self.patient, "customer"),
|
||||
'selling_price_list': price_list,
|
||||
'price_list_currency': price_list_currency,
|
||||
'plc_conversion_rate': 1.0,
|
||||
'conversion_rate': 1.0
|
||||
}
|
||||
item_details = get_item_details(args)
|
||||
item_line.item_code = checked_item['item']
|
||||
item_line.qty = 1
|
||||
if checked_item['qty']:
|
||||
item_line.qty = checked_item['qty']
|
||||
if checked_item['rate']:
|
||||
item_line.rate = checked_item['rate']
|
||||
else:
|
||||
item_line.rate = item_details.price_list_rate
|
||||
item_line.amount = float(item_line.rate) * float(item_line.qty)
|
||||
if checked_item['income_account']:
|
||||
item_line.income_account = checked_item['income_account']
|
||||
if checked_item['dt']:
|
||||
item_line.reference_dt = checked_item['dt']
|
||||
if checked_item['dn']:
|
||||
item_line.reference_dn = checked_item['dn']
|
||||
if checked_item['description']:
|
||||
item_line.description = checked_item['description']
|
||||
|
||||
self.set_missing_values(for_validate = True)
|
||||
|
||||
def booked_deferred_revenue(start_date=None, end_date=None):
|
||||
# check for the sales invoice for which GL entries has to be done
|
||||
|
@ -21,9 +21,30 @@ data = {
|
||||
'Patient'
|
||||
],
|
||||
'custom_fields': {
|
||||
'Sales Invoice': dict(fieldname='appointment', label='Patient Appointment',
|
||||
fieldtype='Link', options='Patient Appointment',
|
||||
insert_after='customer')
|
||||
'Sales Invoice': [
|
||||
{
|
||||
'fieldname': 'patient', 'label': 'Patient', 'fieldtype': 'Link', 'options': 'Patient',
|
||||
'insert_after': 'naming_series'
|
||||
},
|
||||
{
|
||||
'fieldname': 'patient_name', 'label': 'Patient Name', 'fieldtype': 'Data', 'fetch_from': 'patient.patient_name',
|
||||
'insert_after': 'patient', 'read_only': True
|
||||
},
|
||||
{
|
||||
'fieldname': 'ref_practitioner', 'label': 'Referring Practitioner', 'fieldtype': 'Link', 'options': 'Healthcare Practitioner',
|
||||
'insert_after': 'customer'
|
||||
}
|
||||
],
|
||||
'Sales Invoice Item': [
|
||||
{
|
||||
'fieldname': 'reference_dt', 'label': 'Reference DocType', 'fieldtype': 'Link', 'options': 'DocType',
|
||||
'insert_after': 'edit_references'
|
||||
},
|
||||
{
|
||||
'fieldname': 'reference_dn', 'label': 'Reference Name', 'fieldtype': 'Dynamic Link', 'options': 'reference_dt',
|
||||
'insert_after': 'reference_dt'
|
||||
}
|
||||
]
|
||||
},
|
||||
'on_setup': 'erpnext.healthcare.setup.setup_healthcare'
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:appointment_type",
|
||||
"beta": 1,
|
||||
@ -152,7 +152,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-06-13 00:04:24.597019",
|
||||
"modified": "2018-08-08 12:57:54.544216",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Appointment Type",
|
||||
@ -208,5 +208,6 @@
|
||||
"sort_order": "DESC",
|
||||
"title_field": "",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -264,21 +264,20 @@ frappe.ui.form.on('Clinical Procedure Item', {
|
||||
let args = null;
|
||||
if(d.item_code) {
|
||||
args = {
|
||||
'item_code' : d.item_code,
|
||||
'transfer_qty' : d.transfer_qty,
|
||||
'company' : frm.doc.company,
|
||||
'quantity' : d.qty
|
||||
'doctype' : "Clinical Procedure",
|
||||
'item_code' : d.item_code,
|
||||
'company' : frm.doc.company,
|
||||
'warehouse': frm.doc.warehouse
|
||||
};
|
||||
return frappe.call({
|
||||
doc: frm.doc,
|
||||
method: "get_item_details",
|
||||
args: args,
|
||||
method: "erpnext.stock.get_item_details.get_item_details",
|
||||
args: {args: args},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
var d = locals[cdt][cdn];
|
||||
$.each(r.message, function(k, v){
|
||||
d[k] = v;
|
||||
});
|
||||
frappe.model.set_value(cdt, cdn, "item_name", r.message.item_name);
|
||||
frappe.model.set_value(cdt, cdn, "stock_uom", r.message.stock_uom);
|
||||
frappe.model.set_value(cdt, cdn, "conversion_factor", r.message.conversion_factor);
|
||||
frappe.model.set_value(cdt, cdn, "actual_qty", r.message.actual_qty);
|
||||
refresh_field("items");
|
||||
}
|
||||
}
|
||||
|
@ -245,6 +245,39 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "prescription",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Procedure Prescription",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Procedure Prescription",
|
||||
"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,
|
||||
@ -480,7 +513,8 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "is_invoiced",
|
||||
"default": "0",
|
||||
"fieldname": "invoiced",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
@ -489,9 +523,9 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Is Invoiced",
|
||||
"label": "Invoiced",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -670,6 +704,139 @@
|
||||
"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",
|
||||
"fieldname": "invoice_separately_as_consumables",
|
||||
"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": "Consumables Invoice Separately",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"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,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "invoice_separately_as_consumables",
|
||||
"fieldname": "consumable_total_amount",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Consumable Total Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"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,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "invoice_separately_as_consumables",
|
||||
"fieldname": "consumption_details",
|
||||
"fieldtype": "Small Text",
|
||||
"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": "Consumption Details",
|
||||
"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,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"depends_on": "invoice_separately_as_consumables",
|
||||
"fieldname": "consumption_invoiced",
|
||||
"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": "Consumption Invoiced",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"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,
|
||||
@ -745,10 +912,11 @@
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
||||
|
@ -10,20 +10,29 @@ from frappe.utils import cint, flt, nowdate, nowtime
|
||||
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_account
|
||||
from erpnext.healthcare.doctype.lab_test.lab_test import create_sample_doc
|
||||
from erpnext.stock.stock_ledger import get_previous_sle
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
|
||||
class ClinicalProcedure(Document):
|
||||
def validate(self):
|
||||
if self.consume_stock and not self.status == 'Draft':
|
||||
if not self.warehouse:
|
||||
frappe.throw(("Set warehouse for Procedure {0} ").format(self.name))
|
||||
frappe.throw(_("Set warehouse for Procedure {0} ").format(self.name))
|
||||
self.set_actual_qty()
|
||||
|
||||
if self.items:
|
||||
self.invoice_separately_as_consumables = False
|
||||
for item in self.items:
|
||||
if item.invoice_separately_as_consumables == 1:
|
||||
self.invoice_separately_as_consumables = True
|
||||
|
||||
def before_insert(self):
|
||||
if self.consume_stock:
|
||||
set_stock_items(self, self.procedure_template, "Clinical Procedure Template")
|
||||
self.set_actual_qty();
|
||||
|
||||
def after_insert(self):
|
||||
if self.prescription:
|
||||
frappe.db.set_value("Procedure Prescription", self.prescription, "procedure_created", 1)
|
||||
if self.appointment:
|
||||
frappe.db.set_value("Patient Appointment", self.appointment, "status", "Closed")
|
||||
template = frappe.get_doc("Clinical Procedure Template", self.procedure_template)
|
||||
@ -38,6 +47,36 @@ class ClinicalProcedure(Document):
|
||||
create_stock_entry(self)
|
||||
frappe.db.set_value("Clinical Procedure", self.name, "status", 'Completed')
|
||||
|
||||
if self.items:
|
||||
consumable_total_amount = 0
|
||||
consumption_details = False
|
||||
for item in self.items:
|
||||
if item.invoice_separately_as_consumables:
|
||||
price_list, price_list_currency = frappe.db.get_values("Price List", {"selling": 1}, ['name', 'currency'])[0]
|
||||
args = {
|
||||
'doctype': "Sales Invoice",
|
||||
'item_code': item.item_code,
|
||||
'company': self.company,
|
||||
'warehouse': self.warehouse,
|
||||
'customer': frappe.db.get_value("Patient", self.patient, "customer"),
|
||||
'selling_price_list': price_list,
|
||||
'price_list_currency': price_list_currency,
|
||||
'plc_conversion_rate': 1.0,
|
||||
'conversion_rate': 1.0
|
||||
}
|
||||
item_details = get_item_details(args)
|
||||
item_price = item_details.price_list_rate * item.transfer_qty
|
||||
item_consumption_details = item_details.item_name+"\t"+str(item.qty)+" "+item.uom+"\t"+str(item_price)
|
||||
consumable_total_amount += item_price
|
||||
if not consumption_details:
|
||||
consumption_details = "Clinical Procedure ("+self.name+"):\n\t"+item_consumption_details
|
||||
else:
|
||||
consumption_details += "\n\t"+item_consumption_details
|
||||
if consumable_total_amount > 0:
|
||||
frappe.db.set_value("Clinical Procedure", self.name, "consumable_total_amount", consumable_total_amount)
|
||||
frappe.db.set_value("Clinical Procedure", self.name, "consumption_details", consumption_details)
|
||||
|
||||
|
||||
def start(self):
|
||||
allow_start = self.set_actual_qty()
|
||||
if allow_start:
|
||||
@ -52,16 +91,7 @@ class ClinicalProcedure(Document):
|
||||
|
||||
allow_start = True
|
||||
for d in self.get('items'):
|
||||
previous_sle = get_previous_sle({
|
||||
"item_code": d.item_code,
|
||||
"warehouse": self.warehouse,
|
||||
"posting_date": nowdate(),
|
||||
"posting_time": nowtime()
|
||||
})
|
||||
|
||||
# get actual stock at source warehouse
|
||||
d.actual_qty = previous_sle.get("qty_after_transaction") or 0
|
||||
|
||||
d.actual_qty = get_stock_qty(d.item_code, self.warehouse)
|
||||
# validate qty
|
||||
if not allow_negative_stock and d.actual_qty < d.qty:
|
||||
allow_start = False
|
||||
@ -91,28 +121,14 @@ class ClinicalProcedure(Document):
|
||||
se_child.expense_account = expense_account
|
||||
return stock_entry.as_dict()
|
||||
|
||||
def get_item_details(self, args=None):
|
||||
item = frappe.db.sql("""select stock_uom, description, image, item_name,
|
||||
expense_account, buying_cost_center, item_group from `tabItem`
|
||||
where name = %s
|
||||
and disabled=0
|
||||
and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %s)""",
|
||||
(args.get('item_code'), nowdate()), as_dict = 1)
|
||||
if not item:
|
||||
frappe.throw(_("Item {0} is not active or end of life has been reached").format(args.get('item_code')))
|
||||
|
||||
item = item[0]
|
||||
|
||||
ret = {
|
||||
'uom' : item.stock_uom,
|
||||
'stock_uom' : item.stock_uom,
|
||||
'item_name' : item.item_name,
|
||||
'quantity' : 0,
|
||||
'transfer_qty' : 0,
|
||||
'conversion_factor' : 1
|
||||
}
|
||||
return ret
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_stock_qty(item_code, warehouse):
|
||||
return get_previous_sle({
|
||||
"item_code": item_code,
|
||||
"warehouse": warehouse,
|
||||
"posting_date": nowdate(),
|
||||
"posting_time": nowtime()
|
||||
}).get("qty_after_transaction") or 0
|
||||
|
||||
@frappe.whitelist()
|
||||
def set_stock_items(doc, stock_detail_parent, parenttype):
|
||||
@ -130,6 +146,8 @@ def set_stock_items(doc, stock_detail_parent, parenttype):
|
||||
se_child.conversion_factor = flt(d["conversion_factor"])
|
||||
if d["batch_no"]:
|
||||
se_child.batch_no = d["batch_no"]
|
||||
if parenttype == "Clinical Procedure Template":
|
||||
se_child.invoice_separately_as_consumables = d["invoice_separately_as_consumables"]
|
||||
return doc
|
||||
|
||||
def get_item_dict(table, parent, parenttype):
|
||||
@ -165,6 +183,8 @@ def create_procedure(appointment):
|
||||
procedure.patient_age = appointment.patient_age
|
||||
procedure.patient_sex = appointment.patient_sex
|
||||
procedure.procedure_template = appointment.procedure_template
|
||||
procedure.procedure_prescription = appointment.procedure_prescription
|
||||
procedure.invoiced = appointment.invoiced
|
||||
procedure.medical_department = appointment.department
|
||||
procedure.start_date = appointment.appointment_date
|
||||
procedure.start_time = appointment.appointment_time
|
||||
|
@ -14,6 +14,7 @@
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
@ -46,6 +47,7 @@
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -77,6 +79,7 @@
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -108,6 +111,7 @@
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -139,6 +143,7 @@
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -171,6 +176,39 @@
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "invoice_separately_as_consumables",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Invoice Separately as Consumables",
|
||||
"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,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -201,6 +239,7 @@
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -233,6 +272,7 @@
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -264,6 +304,7 @@
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -296,6 +337,7 @@
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -327,6 +369,7 @@
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -367,7 +410,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-03-28 14:34:03.796229",
|
||||
"modified": "2018-07-26 17:05:29.402908",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Clinical Procedure Item",
|
||||
@ -381,5 +424,6 @@
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:template",
|
||||
"beta": 1,
|
||||
@ -16,6 +16,7 @@
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -43,11 +44,12 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"translatable": 0,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -75,11 +77,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -107,11 +110,12 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -139,11 +143,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -169,11 +174,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -200,11 +206,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -232,11 +239,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -263,11 +271,12 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -294,11 +303,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -325,11 +335,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -357,11 +368,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -389,11 +401,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
@ -421,11 +434,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -453,16 +467,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "sample.sample_uom",
|
||||
"fetch_from": "sample.sample_uom",
|
||||
"fieldname": "sample_uom",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@ -486,11 +501,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -517,11 +533,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -547,11 +564,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -578,11 +596,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -609,11 +628,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -640,11 +660,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -672,7 +693,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
@ -686,7 +707,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-05-16 22:43:29.674822",
|
||||
"modified": "2018-08-08 13:00:06.260997",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Clinical Procedure Template",
|
||||
@ -780,5 +801,6 @@
|
||||
"sort_order": "DESC",
|
||||
"title_field": "template",
|
||||
"track_changes": 1,
|
||||
"track_seen": 1
|
||||
}
|
||||
"track_seen": 1,
|
||||
"track_views": 0
|
||||
}
|
@ -4,6 +4,33 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from frappe.model.document import Document
|
||||
import frappe
|
||||
from frappe.utils import getdate
|
||||
import datetime
|
||||
|
||||
class FeeValidity(Document):
|
||||
pass
|
||||
|
||||
def update_fee_validity(fee_validity, date, ref_invoice=None):
|
||||
max_visit = frappe.db.get_value("Healthcare Settings", None, "max_visit")
|
||||
valid_days = frappe.db.get_value("Healthcare Settings", None, "valid_days")
|
||||
if not valid_days:
|
||||
valid_days = 1
|
||||
if not max_visit:
|
||||
max_visit = 1
|
||||
date = getdate(date)
|
||||
valid_till = date + datetime.timedelta(days=int(valid_days))
|
||||
fee_validity.max_visit = max_visit
|
||||
fee_validity.visited = 1
|
||||
fee_validity.valid_till = valid_till
|
||||
fee_validity.ref_invoice = ref_invoice
|
||||
fee_validity.save(ignore_permissions=True)
|
||||
return fee_validity
|
||||
|
||||
|
||||
def create_fee_validity(practitioner, patient, date, ref_invoice=None):
|
||||
fee_validity = frappe.new_doc("Fee Validity")
|
||||
fee_validity.practitioner = practitioner
|
||||
fee_validity.patient = patient
|
||||
fee_validity = update_fee_validity(fee_validity, date, ref_invoice)
|
||||
return fee_validity
|
||||
|
@ -5,33 +5,35 @@ from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
from erpnext.healthcare.doctype.patient_appointment.patient_appointment import invoice_appointment
|
||||
from frappe.utils.make_random import get_random
|
||||
from frappe.utils import nowdate, add_days
|
||||
# test_records = frappe.get_test_records('Fee Validity')
|
||||
from frappe.utils import nowdate, add_days, getdate
|
||||
|
||||
test_dependencies = ["Company"]
|
||||
|
||||
class TestFeeValidity(unittest.TestCase):
|
||||
def test_fee_validity(self):
|
||||
frappe.db.sql("""delete from `tabPatient Appointment`""")
|
||||
frappe.db.sql("""delete from `tabFee Validity`""")
|
||||
patient = get_random("Patient")
|
||||
practitioner = get_random("Healthcare Practitioner")
|
||||
department = get_random("Medical Department")
|
||||
|
||||
if not patient:
|
||||
patient = frappe.new_doc("Patient")
|
||||
patient.patient_name = "Test Patient"
|
||||
patient.patient_name = "_Test Patient"
|
||||
patient.sex = "Male"
|
||||
patient.save(ignore_permissions=True)
|
||||
patient = patient.name
|
||||
|
||||
if not department:
|
||||
medical_department = frappe.new_doc("Medical Department")
|
||||
medical_department.department = "Test Medical Department"
|
||||
medical_department.department = "_Test Medical Department"
|
||||
medical_department.save(ignore_permissions=True)
|
||||
department = medical_department.name
|
||||
|
||||
if not practitioner:
|
||||
practitioner = frappe.new_doc("Healthcare Practitioner")
|
||||
practitioner.first_name = "Amit Jain"
|
||||
practitioner.first_name = "_Test Healthcare Practitioner"
|
||||
practitioner.department = department
|
||||
practitioner.save(ignore_permissions=True)
|
||||
practitioner = practitioner.name
|
||||
@ -42,18 +44,22 @@ class TestFeeValidity(unittest.TestCase):
|
||||
frappe.db.set_value("Healthcare Settings", None, "valid_days", 7)
|
||||
|
||||
appointment = create_appointment(patient, practitioner, nowdate(), department)
|
||||
invoice = frappe.db.get_value("Patient Appointment", appointment.name, "sales_invoice")
|
||||
self.assertEqual(invoice, None)
|
||||
invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
|
||||
self.assertEqual(invoiced, 0)
|
||||
|
||||
invoice_appointment(appointment)
|
||||
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 4), department)
|
||||
invoice = frappe.db.get_value("Patient Appointment", appointment.name, "sales_invoice")
|
||||
self.assertTrue(invoice)
|
||||
invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
|
||||
self.assertTrue(invoiced)
|
||||
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 5), department)
|
||||
invoice = frappe.db.get_value("Patient Appointment", appointment.name, "sales_invoice")
|
||||
self.assertEqual(invoice, None)
|
||||
invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
|
||||
self.assertEqual(invoiced, 0)
|
||||
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 10), department)
|
||||
invoice = frappe.db.get_value("Patient Appointment", appointment.name, "sales_invoice")
|
||||
self.assertEqual(invoice, None)
|
||||
invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
|
||||
self.assertEqual(invoiced, 0)
|
||||
|
||||
def create_appointment(patient, practitioner, appointment_date, department):
|
||||
appointment = frappe.new_doc("Patient Appointment")
|
||||
@ -64,3 +70,34 @@ def create_appointment(patient, practitioner, appointment_date, department):
|
||||
appointment.company = "_Test Company"
|
||||
appointment.save(ignore_permissions=True)
|
||||
return appointment
|
||||
|
||||
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.due_date = getdate()
|
||||
sales_invoice.is_pos = 0
|
||||
sales_invoice.company = appointment_doc.company
|
||||
sales_invoice.debit_to = "_Test Receivable - _TC"
|
||||
|
||||
create_invoice_items(appointment_doc, sales_invoice)
|
||||
|
||||
sales_invoice.save(ignore_permissions=True)
|
||||
sales_invoice.submit()
|
||||
|
||||
def create_invoice_items(appointment, invoice):
|
||||
item_line = invoice.append("items")
|
||||
item_line.item_name = "Consulting Charges"
|
||||
item_line.description = "Consulting Charges: " + appointment.practitioner
|
||||
item_line.uom = "Nos"
|
||||
item_line.conversion_factor = 1
|
||||
item_line.income_account = "_Test Account Cost for Goods Sold - _TC"
|
||||
item_line.cost_center = "_Test Cost Center - _TC"
|
||||
item_line.rate = 250
|
||||
item_line.amount = 250
|
||||
item_line.qty = 1
|
||||
item_line.reference_dt = "Patient Appointment"
|
||||
item_line.reference_dn = appointment.name
|
||||
|
||||
return invoice
|
||||
|
@ -27,9 +27,22 @@ frappe.ui.form.on('Healthcare Practitioner', {
|
||||
}
|
||||
};
|
||||
});
|
||||
set_query_service_item(frm, 'inpatient_visit_charge_item');
|
||||
set_query_service_item(frm, 'op_consulting_charge_item');
|
||||
}
|
||||
});
|
||||
|
||||
var set_query_service_item = function(frm, service_item_field) {
|
||||
frm.set_query(service_item_field, function() {
|
||||
return {
|
||||
filters: {
|
||||
'is_sales_item': 1,
|
||||
'is_stock_item': 0
|
||||
}
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
frappe.ui.form.on("Healthcare Practitioner", "user_id",function(frm) {
|
||||
if(frm.doc.user_id){
|
||||
frappe.call({
|
||||
|
@ -201,7 +201,7 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
@ -528,6 +528,39 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "op_consulting_charge_item",
|
||||
"fieldtype": "Link",
|
||||
"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": "Out Patient Consulting Charge Item",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Item",
|
||||
"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,
|
||||
@ -561,6 +594,102 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_18",
|
||||
"fieldtype": "Column Break",
|
||||
"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,
|
||||
"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,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "inpatient_visit_charge_item",
|
||||
"fieldtype": "Link",
|
||||
"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": "Inpatient Visit Charge Item",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Item",
|
||||
"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,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "inpatient_visit_charge",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Inpatient Visit Charge",
|
||||
"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,
|
||||
@ -798,7 +927,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-07-10 11:18:58.760297",
|
||||
"modified": "2018-08-06 16:45:37.899084",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Healthcare Practitioner",
|
||||
@ -873,5 +1002,6 @@
|
||||
"sort_order": "DESC",
|
||||
"title_field": "first_name",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -21,6 +21,10 @@ class HealthcarePractitioner(Document):
|
||||
|
||||
def validate(self):
|
||||
validate_party_accounts(self)
|
||||
if self.inpatient_visit_charge_item:
|
||||
validate_service_item(self.inpatient_visit_charge_item, "Configure a service Item for Inpatient Visit Charge Item")
|
||||
if self.op_consulting_charge_item:
|
||||
validate_service_item(self.op_consulting_charge_item, "Configure a service Item for Out Patient Consulting Charge Item")
|
||||
|
||||
if self.user_id:
|
||||
self.validate_for_enabled_user_id()
|
||||
@ -57,3 +61,7 @@ class HealthcarePractitioner(Document):
|
||||
|
||||
def on_trash(self):
|
||||
delete_contact_and_address('Healthcare Practitioner', self.name)
|
||||
|
||||
def validate_service_item(item, msg):
|
||||
if frappe.db.get_value("Item", item, "is_stock_item") == 1:
|
||||
frappe.throw(_(msg))
|
||||
|
@ -9,10 +9,6 @@ def get_data():
|
||||
{
|
||||
'label': _('Appointments and Patient Encounters'),
|
||||
'items': ['Patient Appointment', 'Patient Encounter']
|
||||
},
|
||||
{
|
||||
'label': _('Lab Tests'),
|
||||
'items': ['Lab Test']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:healthcare_service_unit_name",
|
||||
"beta": 1,
|
||||
@ -43,7 +43,7 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
@ -116,7 +116,7 @@
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.is_group != 1",
|
||||
@ -246,7 +246,7 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
@ -258,10 +258,10 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"default": "",
|
||||
"depends_on": "eval:doc.inpatient_occupancy == 1",
|
||||
"fieldname": "occupied",
|
||||
"fieldtype": "Check",
|
||||
"fieldname": "occupancy_status",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@ -269,9 +269,10 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Occupied",
|
||||
"label": "Occupancy Status",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Vacant\nOccupied",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -460,7 +461,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-07-17 17:40:18.867327",
|
||||
"modified": "2018-08-08 12:57:12.709806",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Healthcare Service Unit",
|
||||
@ -535,5 +536,6 @@
|
||||
"sort_order": "DESC",
|
||||
"title_field": "healthcare_service_unit_name",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -1,3 +1,35 @@
|
||||
frappe.treeview_settings["Healthcare Service Unit"] = {
|
||||
ignore_fields:["parent_healthcare_service_unit"]
|
||||
breadcrumbs: "Healthcare Service Unit",
|
||||
title: __("Healthcare Service Unit"),
|
||||
get_tree_root: false,
|
||||
filters: [{
|
||||
fieldname: "company",
|
||||
fieldtype: "Select",
|
||||
options: erpnext.utils.get_tree_options("company"),
|
||||
label: __("Company"),
|
||||
default: erpnext.utils.get_tree_default("company")
|
||||
}],
|
||||
get_tree_nodes: 'erpnext.healthcare.utils.get_children',
|
||||
ignore_fields:["parent_healthcare_service_unit"],
|
||||
onrender: function(node) {
|
||||
if (node.data.occupied_out_of_vacant!==undefined){
|
||||
$('<span class="balance-area pull-right text-muted small">'
|
||||
+ " " + node.data.occupied_out_of_vacant
|
||||
+ '</span>').insertBefore(node.$ul);
|
||||
}
|
||||
if (node.data && node.data.inpatient_occupancy!==undefined) {
|
||||
if (node.data.inpatient_occupancy == 1){
|
||||
if (node.data.occupancy_status == "Occupied"){
|
||||
$('<span class="balance-area pull-right small">'
|
||||
+ " " + node.data.occupancy_status
|
||||
+ '</span>').insertBefore(node.$ul);
|
||||
}
|
||||
if (node.data.occupancy_status == "Vacant"){
|
||||
$('<span class="balance-area pull-right text-muted small">'
|
||||
+ " " + node.data.occupancy_status
|
||||
+ '</span>').insertBefore(node.$ul);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:service_unit_type",
|
||||
"beta": 0,
|
||||
"creation": "2018-07-11 16:47:51.414675",
|
||||
@ -43,7 +43,7 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
@ -351,8 +351,8 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "rate",
|
||||
"fieldtype": "Currency",
|
||||
"fieldname": "no_of_hours",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@ -360,7 +360,7 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Rate / UOM",
|
||||
"label": "UOM Conversion in Hours",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@ -407,6 +407,38 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "rate",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Rate / UOM",
|
||||
"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,
|
||||
@ -515,7 +547,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-07-13 16:54:59.131606",
|
||||
"modified": "2018-08-08 13:00:23.751635",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Healthcare Service Unit Type",
|
||||
@ -545,10 +577,12 @@
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "service_unit_type",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -8,6 +8,11 @@ from frappe import _
|
||||
from frappe.model.document import Document
|
||||
|
||||
class HealthcareServiceUnitType(Document):
|
||||
def validate(self):
|
||||
if self.is_billable == 1:
|
||||
if not self.uom or not self.item_group or not self.description or not self.no_of_hours > 0:
|
||||
frappe.throw(_("Configure Item Fields like UOM, Item Group, Description and No of Hours."))
|
||||
|
||||
def after_insert(self):
|
||||
if self.inpatient_occupancy and self.is_billable:
|
||||
create_item(self)
|
||||
@ -22,13 +27,16 @@ class HealthcareServiceUnitType(Document):
|
||||
def on_update(self):
|
||||
if(self.change_in_item and self.is_billable == 1 and self.item):
|
||||
updating_item(self)
|
||||
if not item_price_exist(self):
|
||||
if(self.test_rate != 0.0):
|
||||
item_price = item_price_exist(self)
|
||||
if not item_price:
|
||||
if(self.rate != 0.0):
|
||||
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
||||
if(self.test_rate):
|
||||
make_item_price(self.test_code, price_list_name, self.test_rate)
|
||||
if(self.rate):
|
||||
make_item_price(self.item_code, price_list_name, self.rate)
|
||||
else:
|
||||
make_item_price(self.test_code, price_list_name, 0.0)
|
||||
make_item_price(self.item_code, price_list_name, 0.0)
|
||||
else:
|
||||
frappe.db.set_value("Item Price", item_price, "price_list_rate", self.rate)
|
||||
|
||||
frappe.db.set_value(self.doctype,self.name,"change_in_item",0)
|
||||
elif(self.is_billable == 0 and self.item):
|
||||
@ -40,7 +48,7 @@ def item_price_exist(doc):
|
||||
"doctype": "Item Price",
|
||||
"item_code": doc.item_code})
|
||||
if(item_price):
|
||||
return True
|
||||
return item_price[0][0]
|
||||
else:
|
||||
return False
|
||||
|
||||
|
@ -23,5 +23,19 @@ frappe.ui.form.on('Healthcare Settings', {
|
||||
}
|
||||
};
|
||||
});
|
||||
set_query_service_item(frm, 'inpatient_visit_charge_item');
|
||||
set_query_service_item(frm, 'op_consulting_charge_item');
|
||||
set_query_service_item(frm, 'clinical_procedure_consumable_item');
|
||||
}
|
||||
});
|
||||
|
||||
var set_query_service_item = function(frm, service_item_field) {
|
||||
frm.set_query(service_item_field, function() {
|
||||
return {
|
||||
filters: {
|
||||
'is_sales_item': 1,
|
||||
'is_stock_item': 0
|
||||
}
|
||||
};
|
||||
});
|
||||
};
|
||||
|
@ -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,
|
||||
@ -305,6 +339,168 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fieldname": "healthcare_service_items",
|
||||
"fieldtype": "Section Break",
|
||||
"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": "Healthcare Service Items",
|
||||
"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,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "inpatient_visit_charge_item",
|
||||
"fieldtype": "Link",
|
||||
"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": "Inpatient Visit Charge Item",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Item",
|
||||
"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,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "op_consulting_charge_item",
|
||||
"fieldtype": "Link",
|
||||
"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": "Out Patient Consulting Charge Item",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Item",
|
||||
"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,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_13",
|
||||
"fieldtype": "Column Break",
|
||||
"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,
|
||||
"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,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "clinical_procedure_consumable_item",
|
||||
"fieldtype": "Link",
|
||||
"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": "Clinical Procedure Consumable Item",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Item",
|
||||
"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,
|
||||
@ -797,6 +993,38 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "create_test_on_si_submit",
|
||||
"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": "Create Lab Test(s) on Sales Invoice Submit",
|
||||
"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,
|
||||
@ -1099,7 +1327,7 @@
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-07-16 14:00:04.171717",
|
||||
"modified": "2018-08-03 15:18:36.631441",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Healthcare Settings",
|
||||
@ -1134,5 +1362,6 @@
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -10,13 +10,19 @@ from frappe.core.doctype.sms_settings.sms_settings import send_sms
|
||||
import json
|
||||
|
||||
class HealthcareSettings(Document):
|
||||
def validate(self):
|
||||
for key in ["collect_registration_fee","manage_customer","patient_master_name",
|
||||
"require_test_result_approval","require_sample_collection", "default_medical_code_standard"]:
|
||||
frappe.db.set_default(key, self.get(key, ""))
|
||||
if(self.collect_registration_fee):
|
||||
if self.registration_fee <= 0 :
|
||||
frappe.throw(_("Registration fee can not be Zero"))
|
||||
def validate(self):
|
||||
for key in ["collect_registration_fee","manage_customer","patient_master_name",
|
||||
"require_test_result_approval","require_sample_collection", "default_medical_code_standard"]:
|
||||
frappe.db.set_default(key, self.get(key, ""))
|
||||
if(self.collect_registration_fee):
|
||||
if self.registration_fee <= 0 :
|
||||
frappe.throw(_("Registration fee can not be Zero"))
|
||||
if self.inpatient_visit_charge_item:
|
||||
validate_service_item(self.inpatient_visit_charge_item, "Configure a service Item for Inpatient Visit Charge Item")
|
||||
if self.op_consulting_charge_item:
|
||||
validate_service_item(self.op_consulting_charge_item, "Configure a service Item for Out Patient Consulting Charge Item")
|
||||
if self.clinical_procedure_consumable_item:
|
||||
validate_service_item(self.clinical_procedure_consumable_item, "Configure a service Item for Clinical Procedure Consumable Item")
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_sms_text(doc):
|
||||
@ -67,3 +73,7 @@ def get_account(parent_type, parent_field, parent, company):
|
||||
if(parent_field):
|
||||
return frappe.db.get_value("Party Account",
|
||||
{"parentfield": parent_field, "parent": parent, "company": company}, "account")
|
||||
|
||||
def validate_service_item(item, msg):
|
||||
if frappe.db.get_value("Item", item, "is_stock_item") == 1:
|
||||
frappe.throw(_(msg))
|
||||
|
@ -104,7 +104,7 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
@ -140,6 +140,39 @@
|
||||
"set_only_once": 0,
|
||||
"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",
|
||||
"fieldname": "invoiced",
|
||||
"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": "Invoiced",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
@ -152,7 +185,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-07-17 18:26:46.009878",
|
||||
"modified": "2018-08-06 16:46:54.699133",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Inpatient Occupancy",
|
||||
@ -166,5 +199,6 @@
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -94,7 +94,7 @@ var admit_patient_dialog = function(frm){
|
||||
filters: {
|
||||
"is_group": 0,
|
||||
"service_unit_type": dialog.get_value("service_unit_type"),
|
||||
"occupied" : 0
|
||||
"occupancy_status" : "Vacant"
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -166,7 +166,7 @@ var transfer_patient_dialog = function(frm){
|
||||
filters: {
|
||||
"is_group": 0,
|
||||
"service_unit_type": dialog.get_value("service_unit_type"),
|
||||
"occupied" : 0
|
||||
"occupancy_status" : "Vacant"
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -968,6 +968,7 @@
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"search_fields": "patient",
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
@ -976,4 +977,4 @@
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
||||
|
@ -69,29 +69,75 @@ def schedule_inpatient(patient, encounter_id, practitioner):
|
||||
inpatient_record.save(ignore_permissions = True)
|
||||
|
||||
@frappe.whitelist()
|
||||
def schedule_discharge(patient, encounter_id, practitioner):
|
||||
def schedule_discharge(patient, encounter_id=None, practitioner=None):
|
||||
inpatient_record_id = frappe.db.get_value('Patient', patient, 'inpatient_record')
|
||||
if inpatient_record_id:
|
||||
inpatient_record = frappe.get_doc("Inpatient Record", inpatient_record_id)
|
||||
inpatient_record.discharge_practitioner = practitioner
|
||||
inpatient_record.discharge_encounter = encounter_id
|
||||
inpatient_record.status = "Discharge Scheduled"
|
||||
|
||||
check_out_inpatient(inpatient_record)
|
||||
|
||||
inpatient_record.save(ignore_permissions = True)
|
||||
frappe.db.set_value("Patient", patient, "inpatient_status", "Discharge Scheduled")
|
||||
|
||||
def discharge_patient(inpatient_record):
|
||||
def check_out_inpatient(inpatient_record):
|
||||
if inpatient_record.inpatient_occupancies:
|
||||
for inpatient_occupancy in inpatient_record.inpatient_occupancies:
|
||||
if inpatient_occupancy.left != 1:
|
||||
inpatient_occupancy.left = True
|
||||
inpatient_occupancy.check_out = now_datetime()
|
||||
frappe.db.set_value("Healthcare Service Unit", inpatient_occupancy.service_unit, "occupied", False)
|
||||
frappe.db.set_value("Healthcare Service Unit", inpatient_occupancy.service_unit, "occupancy_status", "Vacant")
|
||||
|
||||
def discharge_patient(inpatient_record):
|
||||
validate_invoiced_inpatient(inpatient_record)
|
||||
inpatient_record.discharge_date = today()
|
||||
inpatient_record.status = "Discharged"
|
||||
|
||||
inpatient_record.save(ignore_permissions = True)
|
||||
|
||||
def validate_invoiced_inpatient(inpatient_record):
|
||||
pending_invoices = []
|
||||
if inpatient_record.inpatient_occupancies:
|
||||
service_unit_names = False
|
||||
for inpatient_occupancy in inpatient_record.inpatient_occupancies:
|
||||
if inpatient_occupancy.invoiced != 1:
|
||||
if service_unit_names:
|
||||
service_unit_names += ", " + inpatient_occupancy.service_unit
|
||||
else:
|
||||
service_unit_names = inpatient_occupancy.service_unit
|
||||
if service_unit_names:
|
||||
pending_invoices.append("Inpatient Occupancy (" + service_unit_names + ")")
|
||||
|
||||
docs = ["Patient Appointment", "Patient Encounter", "Lab Test", "Clinical Procedure"]
|
||||
|
||||
for doc in docs:
|
||||
doc_name_list = get_inpatient_docs_not_invoiced(doc, inpatient_record)
|
||||
if doc_name_list:
|
||||
pending_invoices = get_pending_doc(doc, doc_name_list, pending_invoices)
|
||||
|
||||
if pending_invoices:
|
||||
frappe.throw(_("Can not mark Inpatient Record Discharged, there are Unbilled Invoices {0}").format(", "
|
||||
.join(pending_invoices)))
|
||||
|
||||
def get_pending_doc(doc, doc_name_list, pending_invoices):
|
||||
if doc_name_list:
|
||||
doc_ids = False
|
||||
for doc_name in doc_name_list:
|
||||
if doc_ids:
|
||||
doc_ids += ", "+doc_name.name
|
||||
else:
|
||||
doc_ids = doc_name.name
|
||||
if doc_ids:
|
||||
pending_invoices.append(doc + " (" + doc_ids + ")")
|
||||
|
||||
return pending_invoices
|
||||
|
||||
def get_inpatient_docs_not_invoiced(doc, inpatient_record):
|
||||
return frappe.db.get_list(doc, filters = {"patient": inpatient_record.patient,
|
||||
"inpatient_record": inpatient_record.name, "invoiced": 0})
|
||||
|
||||
def admit_patient(inpatient_record, service_unit, check_in, expected_discharge=None):
|
||||
inpatient_record.admitted_datetime = check_in
|
||||
inpatient_record.status = "Admitted"
|
||||
@ -110,7 +156,7 @@ def transfer_patient(inpatient_record, service_unit, check_in):
|
||||
|
||||
inpatient_record.save(ignore_permissions = True)
|
||||
|
||||
frappe.db.set_value("Healthcare Service Unit", service_unit, "occupied", True)
|
||||
frappe.db.set_value("Healthcare Service Unit", service_unit, "occupancy_status", "Occupied")
|
||||
|
||||
def patient_leave_service_unit(inpatient_record, check_out, leave_from):
|
||||
if inpatient_record.inpatient_occupancies:
|
||||
@ -118,7 +164,7 @@ def patient_leave_service_unit(inpatient_record, check_out, leave_from):
|
||||
if inpatient_occupancy.left != 1 and inpatient_occupancy.service_unit == leave_from:
|
||||
inpatient_occupancy.left = True
|
||||
inpatient_occupancy.check_out = check_out
|
||||
frappe.db.set_value("Healthcare Service Unit", inpatient_occupancy.service_unit, "occupied", False)
|
||||
frappe.db.set_value("Healthcare Service Unit", inpatient_occupancy.service_unit, "occupancy_status", "Vacant")
|
||||
inpatient_record.save(ignore_permissions = True)
|
||||
|
||||
@frappe.whitelist()
|
||||
|
@ -7,10 +7,11 @@ import frappe
|
||||
import unittest
|
||||
from frappe.utils import now_datetime, today
|
||||
from frappe.utils.make_random import get_random
|
||||
from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient
|
||||
from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge
|
||||
|
||||
class TestInpatientRecord(unittest.TestCase):
|
||||
def test_admit_and_discharge(self):
|
||||
frappe.db.sql("""delete from `tabInpatient Record`""")
|
||||
patient = get_patient()
|
||||
# Schedule Admission
|
||||
ip_record = create_inpatient(patient)
|
||||
@ -22,13 +23,21 @@ class TestInpatientRecord(unittest.TestCase):
|
||||
service_unit = get_healthcare_service_unit()
|
||||
admit_patient(ip_record, service_unit, now_datetime())
|
||||
self.assertEqual("Admitted", frappe.db.get_value("Patient", patient, "inpatient_status"))
|
||||
self.assertEqual(1, frappe.db.get_value("Healthcare Service Unit", service_unit, "occupied"))
|
||||
self.assertEqual("Occupied", frappe.db.get_value("Healthcare Service Unit", service_unit, "occupancy_status"))
|
||||
|
||||
# Discharge
|
||||
discharge_patient(ip_record)
|
||||
schedule_discharge(patient=patient)
|
||||
self.assertEqual("Vacant", frappe.db.get_value("Healthcare Service Unit", service_unit, "occupancy_status"))
|
||||
|
||||
ip_record1 = frappe.get_doc("Inpatient Record", ip_record.name)
|
||||
# Validate Pending Invoices
|
||||
self.assertRaises(frappe.ValidationError, ip_record.discharge)
|
||||
mark_invoiced_inpatient_occupancy(ip_record1)
|
||||
|
||||
discharge_patient(ip_record1)
|
||||
|
||||
self.assertEqual(None, frappe.db.get_value("Patient", patient, "inpatient_record"))
|
||||
self.assertEqual(None, frappe.db.get_value("Patient", patient, "inpatient_status"))
|
||||
self.assertEqual(0, frappe.db.get_value("Healthcare Service Unit", service_unit, "occupied"))
|
||||
|
||||
def test_validate_overlap_admission(self):
|
||||
frappe.db.sql("""delete from `tabInpatient Record`""")
|
||||
@ -45,6 +54,12 @@ class TestInpatientRecord(unittest.TestCase):
|
||||
self.assertRaises(frappe.ValidationError, ip_record_new.save)
|
||||
frappe.db.sql("""delete from `tabInpatient Record`""")
|
||||
|
||||
def mark_invoiced_inpatient_occupancy(ip_record):
|
||||
if ip_record.inpatient_occupancies:
|
||||
for inpatient_occupancy in ip_record.inpatient_occupancies:
|
||||
inpatient_occupancy.invoiced = 1
|
||||
ip_record.save(ignore_permissions = True)
|
||||
|
||||
def create_inpatient(patient):
|
||||
patient_obj = frappe.get_doc('Patient', patient)
|
||||
inpatient_record = frappe.new_doc('Inpatient Record')
|
||||
@ -78,7 +93,7 @@ def get_healthcare_service_unit():
|
||||
service_unit.healthcare_service_unit_name = "Test Service Unit Ip Occupancy"
|
||||
service_unit.service_unit_type = get_service_unit_type()
|
||||
service_unit.inpatient_occupancy = 1
|
||||
service_unit.occupied = 0
|
||||
service_unit.occupancy_status = "Vacant"
|
||||
service_unit.is_group = 0
|
||||
service_unit_parent_name = frappe.db.exists({
|
||||
"doctype": "Healthcare Service Unit",
|
||||
|
@ -13,6 +13,7 @@
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -40,16 +41,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "test_code.test_name",
|
||||
"fetch_from": "test_code.test_name",
|
||||
"fieldname": "test_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@ -73,17 +75,19 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "invoice",
|
||||
"fieldtype": "Link",
|
||||
"default": "0",
|
||||
"fieldname": "invoiced",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@ -91,10 +95,10 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Invoice",
|
||||
"label": "Invoiced",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Sales Invoice",
|
||||
"no_copy": 1,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -103,13 +107,14 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -135,11 +140,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -166,11 +172,12 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@ -195,9 +202,9 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
@ -211,7 +218,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-05-16 22:43:39.014193",
|
||||
"modified": "2018-08-06 16:53:02.033406",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Lab Prescription",
|
||||
@ -226,5 +233,6 @@
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -24,11 +24,6 @@ frappe.ui.form.on('Lab Test', {
|
||||
refresh : function(frm){
|
||||
refresh_field('normal_test_items');
|
||||
refresh_field('special_test_items');
|
||||
if(!frm.doc.__islocal && !frm.doc.invoice && frappe.user.has_role("Accounts User")){
|
||||
frm.add_custom_button(__('Make Invoice'), function() {
|
||||
make_invoice(frm);
|
||||
});
|
||||
}
|
||||
if(frm.doc.__islocal){
|
||||
frm.add_custom_button(__('Get from Patient Encounter'), function () {
|
||||
get_lab_test_prescribed(frm);
|
||||
@ -166,8 +161,8 @@ var show_lab_tests = function(frm, result){
|
||||
<div class="col-xs-1">\
|
||||
<a data-name="%(name)s" data-lab-test="%(lab_test)s"\
|
||||
data-encounter="%(encounter)s" data-practitioner="%(practitioner)s"\
|
||||
data-invoice="%(invoice)s" href="#"><button class="btn btn-default btn-xs">Get Lab Test\
|
||||
</button></a></div></div>', {name:y[0], lab_test: y[1], encounter:y[2], invoice:y[3], practitioner:y[4], date:y[5]})).appendTo(html_field);
|
||||
data-invoiced="%(invoiced)s" href="#"><button class="btn btn-default btn-xs">Get Lab Test\
|
||||
</button></a></div></div>', {name:y[0], lab_test: y[1], encounter:y[2], invoiced:y[3], practitioner:y[4], date:y[5]})).appendTo(html_field);
|
||||
row.find("a").click(function() {
|
||||
frm.doc.template = $(this).attr("data-lab-test");
|
||||
frm.doc.prescription = $(this).attr("data-name");
|
||||
@ -175,14 +170,11 @@ var show_lab_tests = function(frm, result){
|
||||
frm.set_df_property("template", "read_only", 1);
|
||||
frm.set_df_property("patient", "read_only", 1);
|
||||
frm.set_df_property("practitioner", "read_only", 1);
|
||||
if($(this).attr("data-invoice") != 'null'){
|
||||
frm.doc.invoice = $(this).attr("data-invoice");
|
||||
refresh_field("invoice");
|
||||
}else {
|
||||
frm.doc.invoice = "";
|
||||
refresh_field("invoice");
|
||||
frm.doc.invoiced = 0;
|
||||
if($(this).attr("data-invoiced") == 1){
|
||||
frm.doc.invoiced = 1;
|
||||
}
|
||||
|
||||
refresh_field("invoiced");
|
||||
refresh_field("template");
|
||||
d.hide();
|
||||
return false;
|
||||
@ -195,24 +187,6 @@ var show_lab_tests = function(frm, result){
|
||||
d.show();
|
||||
};
|
||||
|
||||
var make_invoice = function(frm){
|
||||
var doc = frm.doc;
|
||||
frappe.call({
|
||||
method: "erpnext.healthcare.doctype.lab_test.lab_test.create_invoice",
|
||||
args: {company:doc.company, patient:doc.patient, lab_tests: [doc.name], prescriptions:[]},
|
||||
callback: function(r){
|
||||
if(!r.exc){
|
||||
if(r.message){
|
||||
/* frappe.show_alert(__('Sales Invoice {0} created',
|
||||
['<a href="#Form/Sales Invoice/'+r.message+'">' + r.message+ '</a>'])); */
|
||||
frappe.set_route("Form", "Sales Invoice", r.message);
|
||||
}
|
||||
cur_frm.reload_doc();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
cur_frm.cscript.custom_before_submit = function(doc) {
|
||||
if(doc.normal_test_items){
|
||||
for(let result in doc.normal_test_items){
|
||||
|
@ -88,8 +88,9 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "invoice",
|
||||
"fieldtype": "Link",
|
||||
"default": "0",
|
||||
"fieldname": "invoiced",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@ -97,10 +98,10 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Invoice",
|
||||
"label": "Invoiced",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Sales Invoice",
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -1586,7 +1587,7 @@
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"search_fields": "patient,invoice,practitioner,test_name,sample",
|
||||
"search_fields": "patient,practitioner,test_name,sample",
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
@ -1594,4 +1595,4 @@
|
||||
"track_changes": 1,
|
||||
"track_seen": 1,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,9 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
import json
|
||||
from frappe.utils import getdate, cstr
|
||||
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import getdate, cstr
|
||||
|
||||
class LabTest(Document):
|
||||
def on_submit(self):
|
||||
@ -31,6 +29,8 @@ class LabTest(Document):
|
||||
def after_insert(self):
|
||||
if(self.prescription):
|
||||
frappe.db.set_value("Lab Prescription", self.prescription, "test_created", 1)
|
||||
if frappe.db.get_value("Lab Prescription", self.prescription, 'invoiced') == 1:
|
||||
self.invoiced = True
|
||||
if not self.test_name and self.template:
|
||||
self.load_test_from_template()
|
||||
self.reload()
|
||||
@ -60,20 +60,97 @@ def update_status(status, name):
|
||||
def update_lab_test_print_sms_email_status(print_sms_email, name):
|
||||
frappe.db.set_value("Lab Test",name,print_sms_email,1)
|
||||
|
||||
def create_lab_test_doc(invoice, encounter, patient, template):
|
||||
#create Test Result for template, copy vals from Invoice
|
||||
@frappe.whitelist()
|
||||
def create_multiple(doctype, docname):
|
||||
lab_test_created = False
|
||||
if doctype == "Sales Invoice":
|
||||
lab_test_created = create_lab_test_from_invoice(docname)
|
||||
elif doctype == "Patient Encounter":
|
||||
lab_test_created = create_lab_test_from_encounter(docname)
|
||||
|
||||
if lab_test_created:
|
||||
frappe.msgprint(_("Lab Test(s) "+lab_test_created+" created."))
|
||||
else:
|
||||
frappe.msgprint(_("No Lab Test created"))
|
||||
|
||||
def create_lab_test_from_encounter(encounter_id):
|
||||
lab_test_created = False
|
||||
encounter = frappe.get_doc("Patient Encounter", encounter_id)
|
||||
|
||||
lab_test_ids = frappe.db.sql("""select lp.name, lp.test_code, lp.invoiced
|
||||
from `tabPatient Encounter` et, `tabLab Prescription` lp
|
||||
where et.patient=%s and lp.parent=%s and
|
||||
lp.parent=et.name and lp.test_created=0 and et.docstatus=1""", (encounter.patient, encounter_id))
|
||||
|
||||
if lab_test_ids:
|
||||
patient = frappe.get_doc("Patient", encounter.patient)
|
||||
for lab_test_id in lab_test_ids:
|
||||
template = get_lab_test_template(lab_test_id[1])
|
||||
if template:
|
||||
lab_test = create_lab_test_doc(lab_test_id[2], encounter.practitioner, patient, template)
|
||||
lab_test.save(ignore_permissions = True)
|
||||
frappe.db.set_value("Lab Prescription", lab_test_id[0], "test_created", 1)
|
||||
if not lab_test_created:
|
||||
lab_test_created = lab_test.name
|
||||
else:
|
||||
lab_test_created += ", "+lab_test.name
|
||||
return lab_test_created
|
||||
|
||||
|
||||
def create_lab_test_from_invoice(invoice_name):
|
||||
lab_test_created = False
|
||||
invoice = frappe.get_doc("Sales Invoice", invoice_name)
|
||||
if invoice.patient:
|
||||
patient = frappe.get_doc("Patient", invoice.patient)
|
||||
for item in invoice.items:
|
||||
test_created = 0
|
||||
if item.reference_dt == "Lab Prescription":
|
||||
test_created = frappe.db.get_value("Lab Prescription", item.reference_dn, "test_created")
|
||||
elif item.reference_dt == "Lab Test":
|
||||
test_created = 1
|
||||
if test_created != 1:
|
||||
template = get_lab_test_template(item.item_code)
|
||||
if template:
|
||||
lab_test = create_lab_test_doc(True, invoice.ref_practitioner, patient, template)
|
||||
if item.reference_dt == "Lab Prescription":
|
||||
lab_test.prescription = item.reference_dn
|
||||
lab_test.save(ignore_permissions = True)
|
||||
if item.reference_dt != "Lab Prescription":
|
||||
frappe.db.set_value("Sales Invoice Item", item.name, "reference_dt", "Lab Test")
|
||||
frappe.db.set_value("Sales Invoice Item", item.name, "reference_dn", lab_test.name)
|
||||
if not lab_test_created:
|
||||
lab_test_created = lab_test.name
|
||||
else:
|
||||
lab_test_created += ", "+lab_test.name
|
||||
return lab_test_created
|
||||
|
||||
def get_lab_test_template(item):
|
||||
template_id = check_template_exists(item)
|
||||
if template_id:
|
||||
return frappe.get_doc("Lab Test Template", template_id)
|
||||
return False
|
||||
|
||||
def check_template_exists(item):
|
||||
template_exists = frappe.db.exists(
|
||||
"Lab Test Template",
|
||||
{
|
||||
'item': item
|
||||
}
|
||||
)
|
||||
if template_exists:
|
||||
return template_exists
|
||||
return False
|
||||
|
||||
def create_lab_test_doc(invoiced, practitioner, patient, template):
|
||||
lab_test = frappe.new_doc("Lab Test")
|
||||
if(invoice):
|
||||
lab_test.invoice = invoice
|
||||
if(encounter):
|
||||
lab_test.practitioner = encounter.practitioner
|
||||
lab_test.invoiced = invoiced
|
||||
lab_test.practitioner = practitioner
|
||||
lab_test.patient = patient.name
|
||||
lab_test.patient_age = patient.get_age()
|
||||
lab_test.patient_sex = patient.sex
|
||||
lab_test.email = patient.email
|
||||
lab_test.mobile = patient.mobile
|
||||
lab_test.department = template.department
|
||||
lab_test.test_name = template.test_name
|
||||
lab_test.template = template.name
|
||||
lab_test.test_group = template.test_group
|
||||
lab_test.result_date = getdate()
|
||||
@ -133,7 +210,7 @@ def create_sample_doc(template, patient, invoice):
|
||||
#create Sample Collection for template, copy vals from Invoice
|
||||
sample_collection = frappe.new_doc("Sample Collection")
|
||||
if(invoice):
|
||||
sample_collection.invoice = invoice
|
||||
sample_collection.invoiced = True
|
||||
sample_collection.patient = patient.name
|
||||
sample_collection.patient_age = patient.get_age()
|
||||
sample_collection.patient_sex = patient.sex
|
||||
@ -146,24 +223,6 @@ def create_sample_doc(template, patient, invoice):
|
||||
|
||||
return sample_collection
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_lab_test_from_desk(patient, template, prescription, invoice=None):
|
||||
lab_test_exist = frappe.db.exists({
|
||||
"doctype": "Lab Test",
|
||||
"prescription": prescription
|
||||
})
|
||||
if lab_test_exist:
|
||||
return
|
||||
template = frappe.get_doc("Lab Test Template", template)
|
||||
#skip the loop if there is no test_template for Item
|
||||
if not (template):
|
||||
return
|
||||
patient = frappe.get_doc("Patient", patient)
|
||||
encounter_id = frappe.get_value("Lab Prescription", prescription, "parent")
|
||||
encounter = frappe.get_doc("Patient Encounter", encounter_id)
|
||||
lab_test = create_lab_test(patient, template, prescription, encounter, invoice)
|
||||
return lab_test.name
|
||||
|
||||
def create_sample_collection(lab_test, template, patient, invoice):
|
||||
if(frappe.db.get_value("Healthcare Settings", None, "require_sample_collection") == "1"):
|
||||
sample_collection = create_sample_doc(template, patient, invoice)
|
||||
@ -211,16 +270,10 @@ def load_result_format(lab_test, template, prescription, invoice):
|
||||
if(prescription):
|
||||
lab_test.prescription = prescription
|
||||
if(invoice):
|
||||
frappe.db.set_value("Lab Prescription", prescription, "invoice", invoice)
|
||||
frappe.db.set_value("Lab Prescription", prescription, "invoiced", True)
|
||||
lab_test.save(ignore_permissions=True) # insert the result
|
||||
return lab_test
|
||||
|
||||
def create_lab_test(patient, template, prescription, encounter, invoice):
|
||||
lab_test = create_lab_test_doc(invoice, encounter, patient, template)
|
||||
lab_test = create_sample_collection(lab_test, template, patient, invoice)
|
||||
lab_test = load_result_format(lab_test, template, prescription, invoice)
|
||||
return lab_test
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_employee_by_user_id(user_id):
|
||||
emp_id = frappe.db.get_value("Employee",{"user_id":user_id})
|
||||
@ -248,49 +301,7 @@ def delete_lab_test_from_medical_record(self):
|
||||
if medical_record_id and medical_record_id[0][0]:
|
||||
frappe.delete_doc("Patient Medical Record", medical_record_id[0][0])
|
||||
|
||||
def create_item_line(test_code, sales_invoice):
|
||||
if test_code:
|
||||
item = frappe.get_doc("Item", test_code)
|
||||
if item:
|
||||
if not item.disabled:
|
||||
sales_invoice_line = sales_invoice.append("items")
|
||||
sales_invoice_line.item_code = item.item_code
|
||||
sales_invoice_line.item_name = item.item_name
|
||||
sales_invoice_line.qty = 1.0
|
||||
sales_invoice_line.description = item.description
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_invoice(company, patient, lab_tests, prescriptions):
|
||||
test_ids = json.loads(lab_tests)
|
||||
line_ids = json.loads(prescriptions)
|
||||
if not test_ids and not line_ids:
|
||||
return
|
||||
sales_invoice = frappe.new_doc("Sales Invoice")
|
||||
sales_invoice.customer = frappe.get_value("Patient", patient, "customer")
|
||||
sales_invoice.due_date = getdate()
|
||||
sales_invoice.is_pos = '0'
|
||||
sales_invoice.debit_to = get_receivable_account(company)
|
||||
for line in line_ids:
|
||||
test_code = frappe.get_value("Lab Prescription", line, "test_code")
|
||||
create_item_line(test_code, sales_invoice)
|
||||
for test in test_ids:
|
||||
template = frappe.get_value("Lab Test", test, "template")
|
||||
test_code = frappe.get_value("Lab Test Template", template, "item")
|
||||
create_item_line(test_code, sales_invoice)
|
||||
sales_invoice.set_missing_values()
|
||||
sales_invoice.save()
|
||||
#set invoice in lab test
|
||||
for test in test_ids:
|
||||
frappe.db.set_value("Lab Test", test, "invoice", sales_invoice.name)
|
||||
prescription = frappe.db.get_value("Lab Test", test, "prescription")
|
||||
if prescription:
|
||||
frappe.db.set_value("Lab Prescription", prescription, "invoice", sales_invoice.name)
|
||||
#set invoice in prescription
|
||||
for line in line_ids:
|
||||
frappe.db.set_value("Lab Prescription", line, "invoice", sales_invoice.name)
|
||||
return sales_invoice.name
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_lab_test_prescribed(patient):
|
||||
return frappe.db.sql("""select cp.name, cp.test_code, cp.parent, cp.invoice, ct.practitioner, ct.encounter_date from `tabPatient Encounter` ct,
|
||||
return frappe.db.sql("""select cp.name, cp.test_code, cp.parent, cp.invoiced, ct.practitioner, ct.encounter_date from `tabPatient Encounter` ct,
|
||||
`tabLab Prescription` cp where ct.patient=%s and cp.parent=ct.name and cp.test_created=0""", (patient))
|
||||
|
@ -2,7 +2,7 @@
|
||||
(c) ESS 2015-16
|
||||
*/
|
||||
frappe.listview_settings['Lab Test'] = {
|
||||
add_fields: ["name", "status", "invoice"],
|
||||
add_fields: ["name", "status", "invoiced"],
|
||||
filters:[["docstatus","=","0"]],
|
||||
get_indicator: function(doc) {
|
||||
if(doc.status=="Approved"){
|
||||
@ -11,5 +11,52 @@ frappe.listview_settings['Lab Test'] = {
|
||||
if(doc.status=="Rejected"){
|
||||
return [__("Rejected"), "yellow", "status,=,Rejected"];
|
||||
}
|
||||
},
|
||||
onload: function(listview) {
|
||||
listview.page.add_menu_item(__("Create Multiple"), function() {
|
||||
create_multiple_dialog(listview);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var create_multiple_dialog = function(listview){
|
||||
var dialog = new frappe.ui.Dialog({
|
||||
title: 'Create Multiple Lab Test',
|
||||
width: 100,
|
||||
fields: [
|
||||
{fieldtype: "Link", label: "Patient", fieldname: "patient", options: "Patient", reqd: 1},
|
||||
{fieldtype: "Select", label: "Invoice / Patient Encounter", fieldname: "doctype",
|
||||
options: "\nSales Invoice\nPatient Encounter", reqd: 1},
|
||||
{fieldtype: "Dynamic Link", fieldname: "docname", options: "doctype", reqd: 1,
|
||||
get_query: function(){
|
||||
return {
|
||||
filters: {
|
||||
"patient": dialog.get_value("patient"),
|
||||
"docstatus": 1
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
],
|
||||
primary_action_label: __("Create Lab Test"),
|
||||
primary_action : function(){
|
||||
frappe.call({
|
||||
method: 'erpnext.healthcare.doctype.lab_test.lab_test.create_multiple',
|
||||
args:{
|
||||
'doctype': dialog.get_value("doctype"),
|
||||
'docname': dialog.get_value("docname")
|
||||
},
|
||||
callback: function(data) {
|
||||
if(!data.exc){
|
||||
listview.refresh();
|
||||
}
|
||||
},
|
||||
freeze: true,
|
||||
freeze_message: "Creating Lab Test..."
|
||||
});
|
||||
dialog.hide();
|
||||
}
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
};
|
||||
|
@ -12,13 +12,16 @@ class LabTestTemplate(Document):
|
||||
#Item and Price List update --> if (change_in_item)
|
||||
if(self.change_in_item and self.is_billable == 1 and self.item):
|
||||
updating_item(self)
|
||||
if not item_price_exist(self):
|
||||
item_price = item_price_exist(self)
|
||||
if not item_price:
|
||||
if(self.test_rate != 0.0):
|
||||
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
||||
if(self.test_rate):
|
||||
make_item_price(self.test_code, price_list_name, self.test_rate)
|
||||
else:
|
||||
make_item_price(self.test_code, price_list_name, 0.0)
|
||||
else:
|
||||
frappe.db.set_value("Item Price", item_price, "price_list_rate", self.test_rate)
|
||||
|
||||
frappe.db.set_value(self.doctype,self.name,"change_in_item",0)
|
||||
elif(self.is_billable == 0 and self.item):
|
||||
@ -43,7 +46,7 @@ def item_price_exist(doc):
|
||||
"doctype": "Item Price",
|
||||
"item_code": doc.test_code})
|
||||
if(item_price):
|
||||
return True
|
||||
return item_price[0][0]
|
||||
else:
|
||||
return False
|
||||
|
||||
|
@ -13,6 +13,10 @@ def get_data():
|
||||
{
|
||||
'label': _('Lab Tests and Vital Signs'),
|
||||
'items': ['Lab Test', 'Sample Collection', 'Vital Signs']
|
||||
},
|
||||
{
|
||||
'label': _('Billing'),
|
||||
'items': ['Sales Invoice']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ frappe.provide("erpnext.queries");
|
||||
frappe.ui.form.on('Patient Appointment', {
|
||||
setup: function(frm) {
|
||||
frm.custom_make_buttons = {
|
||||
'Sales Invoice': 'Invoice',
|
||||
'Vital Signs': 'Vital Signs',
|
||||
'Patient Encounter': 'Patient Encounter'
|
||||
};
|
||||
@ -84,20 +83,21 @@ frappe.ui.form.on('Patient Appointment', {
|
||||
btn_update_status(frm, "Cancelled");
|
||||
});
|
||||
}
|
||||
|
||||
if(!frm.doc.__islocal){
|
||||
if(frm.doc.sales_invoice && frappe.user.has_role("Accounts User")){
|
||||
frm.add_custom_button(__('Invoice'), function() {
|
||||
frappe.set_route("Form", "Sales Invoice", frm.doc.sales_invoice);
|
||||
},__("View") );
|
||||
}
|
||||
else if(frm.doc.status != "Cancelled" && frappe.user.has_role("Accounts User")){
|
||||
frm.add_custom_button(__('Invoice'), function() {
|
||||
btn_invoice_encounter(frm);
|
||||
},__("Create"));
|
||||
}
|
||||
}
|
||||
frm.set_df_property("get_procedure_from_encounter", "read_only", frm.doc.__islocal ? 0 : 1);
|
||||
frappe.db.get_value('Healthcare Settings', {name: 'Healthcare Settings'}, 'manage_appointment_invoice_automatically', (r) => {
|
||||
if(r.manage_appointment_invoice_automatically == 1){
|
||||
frm.set_df_property("mode_of_payment", "hidden", 0);
|
||||
frm.set_df_property("paid_amount", "hidden", 0);
|
||||
frm.set_df_property("mode_of_payment", "reqd", 1);
|
||||
frm.set_df_property("paid_amount", "reqd", 1);
|
||||
}
|
||||
else{
|
||||
frm.set_df_property("mode_of_payment", "hidden", 1);
|
||||
frm.set_df_property("paid_amount", "hidden", 1);
|
||||
frm.set_df_property("mode_of_payment", "reqd", 0);
|
||||
frm.set_df_property("paid_amount", "reqd", 0);
|
||||
}
|
||||
});
|
||||
},
|
||||
check_availability: function(frm) {
|
||||
var { practitioner, appointment_date } = frm.doc;
|
||||
@ -339,21 +339,6 @@ var btn_update_status = function(frm, status){
|
||||
);
|
||||
};
|
||||
|
||||
var btn_invoice_encounter = function(frm){
|
||||
frappe.call({
|
||||
doc: frm.doc,
|
||||
method:"create_invoice",
|
||||
callback: function(data){
|
||||
if(!data.exc){
|
||||
if(data.message){
|
||||
frappe.set_route("Form", "Sales Invoice", data.message);
|
||||
}
|
||||
cur_frm.reload_doc();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
frappe.ui.form.on("Patient Appointment", "practitioner", function(frm) {
|
||||
if(frm.doc.practitioner){
|
||||
frappe.call({
|
||||
@ -364,6 +349,7 @@ frappe.ui.form.on("Patient Appointment", "practitioner", function(frm) {
|
||||
},
|
||||
callback: function (data) {
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "department",data.message.department);
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "paid_amount",data.message.op_consulting_charge);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -108,7 +108,7 @@
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
@ -617,7 +617,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"depends_on": "",
|
||||
"fieldname": "section_break_1",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -674,6 +674,71 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "mode_of_payment",
|
||||
"fieldtype": "Link",
|
||||
"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": "Mode of Payment",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Mode of Payment",
|
||||
"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,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "paid_amount",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Paid Amount",
|
||||
"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,
|
||||
@ -712,8 +777,9 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sales_invoice",
|
||||
"fieldtype": "Link",
|
||||
"default": "0",
|
||||
"fieldname": "invoiced",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@ -721,10 +787,10 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Sales Invoice",
|
||||
"label": "Invoiced",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Sales Invoice",
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -989,4 +1055,4 @@
|
||||
"track_changes": 1,
|
||||
"track_seen": 1,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
||||
|
@ -6,12 +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.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account,get_income_account
|
||||
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):
|
||||
@ -38,30 +39,112 @@ class PatientAppointment(Document):
|
||||
visited = fee_validity.visited + 1
|
||||
frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
|
||||
if fee_validity.ref_invoice:
|
||||
frappe.db.set_value("Patient Appointment", appointment.name, "sales_invoice", fee_validity.ref_invoice)
|
||||
frappe.db.set_value("Patient Appointment", appointment.name, "invoiced", True)
|
||||
frappe.msgprint(_("{0} has fee validity till {1}").format(appointment.patient, fee_validity.valid_till))
|
||||
confirm_sms(self)
|
||||
|
||||
def create_invoice(self):
|
||||
return invoice_appointment(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 = appointment_doc.mode_of_payment
|
||||
payments_line.amount = appointment_doc.paid_amount
|
||||
|
||||
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 invoice --> fee_validity update with -1 visit
|
||||
if appointment.sales_invoice:
|
||||
validity = frappe.db.exists({"doctype": "Fee Validity", "ref_invoice": appointment.sales_invoice})
|
||||
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(appointment.sales_invoice))
|
||||
)
|
||||
# If invoiced --> fee_validity update with -1 visit
|
||||
if appointment.invoiced:
|
||||
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):
|
||||
@ -197,100 +280,6 @@ def confirm_sms(doc):
|
||||
message = frappe.db.get_value("Healthcare Settings", None, "app_con_msg")
|
||||
send_message(doc, message)
|
||||
|
||||
|
||||
@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 = '0'
|
||||
sales_invoice.company = appointment_doc.company
|
||||
sales_invoice.debit_to = get_receivable_account(appointment_doc.company)
|
||||
|
||||
fee_validity = get_fee_validity(appointment_doc.practitioner, appointment_doc.patient, appointment_doc.appointment_date)
|
||||
procedure_template = False
|
||||
if appointment_doc.procedure_template:
|
||||
procedure_template = appointment_doc.procedure_template
|
||||
create_invoice_items(appointment_doc.practitioner, appointment_doc.company, sales_invoice, procedure_template)
|
||||
|
||||
sales_invoice.save(ignore_permissions=True)
|
||||
frappe.db.sql("""update `tabPatient Appointment` set sales_invoice=%s where name=%s""", (sales_invoice.name, appointment_doc.name))
|
||||
frappe.db.set_value("Fee Validity", fee_validity.name, "ref_invoice", sales_invoice.name)
|
||||
encounter = frappe.db.exists({
|
||||
"doctype": "Patient Encounter",
|
||||
"appointment": appointment_doc.name})
|
||||
if encounter:
|
||||
frappe.db.set_value("Patient Encounter", encounter[0][0], "invoice", sales_invoice.name)
|
||||
return sales_invoice.name
|
||||
|
||||
|
||||
def get_fee_validity(practitioner, patient, date):
|
||||
validity_exist = validity_exists(practitioner, patient)
|
||||
if validity_exist:
|
||||
fee_validity = frappe.get_doc("Fee Validity", validity_exist[0][0])
|
||||
fee_validity = update_fee_validity(fee_validity, date)
|
||||
else:
|
||||
fee_validity = create_fee_validity(practitioner, patient, date)
|
||||
return fee_validity
|
||||
|
||||
|
||||
def validity_exists(practitioner, patient):
|
||||
return frappe.db.exists({
|
||||
"doctype": "Fee Validity",
|
||||
"practitioner": practitioner,
|
||||
"patient": patient})
|
||||
|
||||
|
||||
def update_fee_validity(fee_validity, date):
|
||||
max_visit = frappe.db.get_value("Healthcare Settings", None, "max_visit")
|
||||
valid_days = frappe.db.get_value("Healthcare Settings", None, "valid_days")
|
||||
if not valid_days:
|
||||
valid_days = 1
|
||||
if not max_visit:
|
||||
max_visit = 1
|
||||
date = getdate(date)
|
||||
valid_till = date + datetime.timedelta(days=int(valid_days))
|
||||
fee_validity.max_visit = max_visit
|
||||
fee_validity.visited = 1
|
||||
fee_validity.valid_till = valid_till
|
||||
fee_validity.save(ignore_permissions=True)
|
||||
return fee_validity
|
||||
|
||||
|
||||
def create_fee_validity(practitioner, patient, date):
|
||||
fee_validity = frappe.new_doc("Fee Validity")
|
||||
fee_validity.practitioner = practitioner
|
||||
fee_validity.patient = patient
|
||||
fee_validity = update_fee_validity(fee_validity, date)
|
||||
return fee_validity
|
||||
|
||||
|
||||
def create_invoice_items(practitioner, company, invoice, procedure_template):
|
||||
item_line = invoice.append("items")
|
||||
if procedure_template:
|
||||
procedure_template_obj = frappe.get_doc("Clinical Procedure Template", procedure_template)
|
||||
item_line.item_code = procedure_template_obj.item_code
|
||||
item_line.item_name = procedure_template_obj.template
|
||||
item_line.description = procedure_template_obj.description
|
||||
else:
|
||||
item_line.item_name = "Consulting Charges"
|
||||
item_line.description = "Consulting Charges: " + practitioner
|
||||
item_line.uom = "Nos"
|
||||
item_line.conversion_factor = 1
|
||||
item_line.income_account = get_income_account(practitioner, company)
|
||||
op_consulting_charge = frappe.db.get_value("Healthcare Practitioner", practitioner, "op_consulting_charge")
|
||||
if op_consulting_charge:
|
||||
item_line.rate = op_consulting_charge
|
||||
item_line.amount = op_consulting_charge
|
||||
item_line.qty = 1
|
||||
|
||||
|
||||
return invoice
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_encounter(appointment):
|
||||
appointment = frappe.get_doc("Patient Appointment", appointment)
|
||||
@ -301,8 +290,8 @@ def create_encounter(appointment):
|
||||
encounter.visit_department = appointment.department
|
||||
encounter.patient_sex = appointment.patient_sex
|
||||
encounter.encounter_date = appointment.appointment_date
|
||||
if appointment.sales_invoice:
|
||||
encounter.invoice = appointment.sales_invoice
|
||||
if appointment.invoiced:
|
||||
encounter.invoiced = True
|
||||
return encounter.as_dict()
|
||||
|
||||
|
||||
@ -359,6 +348,7 @@ def get_events(start, end, filters=None):
|
||||
item.appointment_datetime = item.appointment_date + datetime.timedelta(minutes = item.duration)
|
||||
|
||||
return data
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_procedure_prescribed(patient):
|
||||
return frappe.db.sql("""select pp.name, pp.procedure, pp.parent, ct.practitioner,
|
||||
|
@ -10,10 +10,6 @@ def get_data():
|
||||
{
|
||||
'label': _('Consultations'),
|
||||
'items': ['Patient Encounter', 'Vital Signs', 'Patient Medical Record']
|
||||
},
|
||||
{
|
||||
'label': _('Billing'),
|
||||
'items': ['Sales Invoice']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -94,11 +94,6 @@ frappe.ui.form.on('Patient Encounter', {
|
||||
}
|
||||
};
|
||||
});
|
||||
if(!frm.doc.__islocal && !frm.doc.invoice && (frappe.user.has_role("Accounts User"))){
|
||||
frm.add_custom_button(__('Invoice'), function() {
|
||||
btn_invoice_encounter(frm);
|
||||
},__("Create"));
|
||||
}
|
||||
frm.set_df_property("appointment", "read_only", frm.doc.__islocal ? 0:1);
|
||||
frm.set_df_property("patient", "read_only", frm.doc.__islocal ? 0:1);
|
||||
frm.set_df_property("patient_age", "read_only", frm.doc.__islocal ? 0:1);
|
||||
@ -139,23 +134,6 @@ var schedule_discharge = function(frm) {
|
||||
});
|
||||
};
|
||||
|
||||
var btn_invoice_encounter = function(frm){
|
||||
var doc = frm.doc;
|
||||
frappe.call({
|
||||
method:
|
||||
"erpnext.healthcare.doctype.encounter.encounter.create_invoice",
|
||||
args: {company: doc.company, patient: doc.patient, practitioner: doc.practitioner, encounter_id: doc.name },
|
||||
callback: function(data){
|
||||
if(!data.exc){
|
||||
if(data.message){
|
||||
frappe.set_route("Form", "Sales Invoice", data.message);
|
||||
}
|
||||
cur_frm.reload_doc();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var create_medical_record = function (frm) {
|
||||
if(!frm.doc.patient){
|
||||
frappe.throw(__("Please select patient"));
|
||||
@ -203,10 +181,16 @@ frappe.ui.form.on("Patient Encounter", "appointment", function(frm){
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "patient", data.message.patient);
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "type", data.message.appointment_type);
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "practitioner", data.message.practitioner);
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "invoice", data.message.sales_invoice);
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "invoiced", data.message.invoiced);
|
||||
}
|
||||
});
|
||||
}
|
||||
else{
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "patient", "");
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "type", "");
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "practitioner", "");
|
||||
frappe.model.set_value(frm.doctype,frm.docname, "invoiced", 0);
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Patient Encounter", "practitioner", function(frm) {
|
||||
|
@ -213,6 +213,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": "",
|
||||
"fetch_from": "patient.patient_name",
|
||||
"fieldname": "patient_name",
|
||||
"fieldtype": "Data",
|
||||
"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": "Patient Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"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,
|
||||
@ -222,7 +256,7 @@
|
||||
"columns": 0,
|
||||
"fieldname": "patient_age",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
@ -235,9 +269,9 @@
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 1,
|
||||
"reqd": 0,
|
||||
@ -255,7 +289,7 @@
|
||||
"columns": 0,
|
||||
"fieldname": "patient_sex",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 1,
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
@ -268,9 +302,9 @@
|
||||
"options": "\nMale\nFemale\nOther",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 1,
|
||||
"reqd": 0,
|
||||
@ -279,39 +313,6 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "practitioner",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Healthcare Practitioner",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Healthcare Practitioner",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
@ -376,6 +377,39 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "practitioner",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Healthcare Practitioner",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Healthcare Practitioner",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
@ -482,8 +516,9 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "invoice",
|
||||
"fieldtype": "Link",
|
||||
"default": "0",
|
||||
"fieldname": "invoiced",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@ -491,10 +526,10 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Invoice",
|
||||
"label": "Invoiced",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Sales Invoice",
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -1145,4 +1180,4 @@
|
||||
"track_changes": 1,
|
||||
"track_seen": 1,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import getdate, cstr
|
||||
import json
|
||||
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account
|
||||
from frappe.utils import cstr
|
||||
|
||||
class PatientEncounter(Document):
|
||||
def on_update(self):
|
||||
@ -23,77 +21,6 @@ class PatientEncounter(Document):
|
||||
frappe.db.set_value("Patient Appointment", self.appointment, "status", "Open")
|
||||
delete_medical_record(self)
|
||||
|
||||
def set_sales_invoice_fields(company, patient):
|
||||
sales_invoice = frappe.new_doc("Sales Invoice")
|
||||
sales_invoice.customer = frappe.get_value("Patient", patient, "customer")
|
||||
# patient is custom field in sales inv.
|
||||
sales_invoice.due_date = getdate()
|
||||
sales_invoice.is_pos = '0'
|
||||
sales_invoice.debit_to = get_receivable_account(company)
|
||||
|
||||
return sales_invoice
|
||||
|
||||
def create_sales_invoice_item_lines(item, sales_invoice):
|
||||
sales_invoice_line = sales_invoice.append("items")
|
||||
sales_invoice_line.item_code = item.item_code
|
||||
sales_invoice_line.item_name = item.item_name
|
||||
sales_invoice_line.qty = 1.0
|
||||
sales_invoice_line.description = item.description
|
||||
return sales_invoice_line
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_drug_invoice(company, patient, prescriptions):
|
||||
list_ids = json.loads(prescriptions)
|
||||
if not (company or patient or prescriptions):
|
||||
return False
|
||||
|
||||
sales_invoice = set_sales_invoice_fields(company, patient)
|
||||
sales_invoice.update_stock = 1
|
||||
|
||||
for line_id in list_ids:
|
||||
line_obj = frappe.get_doc("Drug Prescription", line_id)
|
||||
if line_obj:
|
||||
if(line_obj.drug_code):
|
||||
item = frappe.get_doc("Item", line_obj.drug_code)
|
||||
sales_invoice_line = create_sales_invoice_item_lines(item, sales_invoice)
|
||||
sales_invoice_line.qty = line_obj.get_quantity()
|
||||
#income_account and cost_center in itemlines - by set_missing_values()
|
||||
sales_invoice.set_missing_values()
|
||||
return sales_invoice.as_dict()
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_invoice(company, patient, practitioner, encounter_id):
|
||||
if not encounter_id:
|
||||
return False
|
||||
sales_invoice = frappe.new_doc("Sales Invoice")
|
||||
sales_invoice.customer = frappe.get_value("Patient", patient, "customer")
|
||||
sales_invoice.due_date = getdate()
|
||||
sales_invoice.is_pos = '0'
|
||||
sales_invoice.debit_to = get_receivable_account(company)
|
||||
|
||||
create_invoice_items(practitioner, sales_invoice, company)
|
||||
|
||||
sales_invoice.save(ignore_permissions=True)
|
||||
frappe.db.sql("""update `tabPatient Encounter` set invoice=%s where name=%s""", (sales_invoice.name, encounter_id))
|
||||
appointment = frappe.db.get_value("Patient Encounter", encounter_id, "appointment")
|
||||
if appointment:
|
||||
frappe.db.set_value("Patient Appointment", appointment, "sales_invoice", sales_invoice.name)
|
||||
return sales_invoice.name
|
||||
|
||||
def create_invoice_items(practitioner, invoice, company):
|
||||
item_line = invoice.append("items")
|
||||
item_line.item_name = "Consulting Charges"
|
||||
item_line.description = "Consulting Charges: " + practitioner
|
||||
item_line.qty = 1
|
||||
item_line.uom = "Nos"
|
||||
item_line.conversion_factor = 1
|
||||
item_line.income_account = get_income_account(practitioner, company)
|
||||
op_consulting_charge = frappe.get_value("Healthcare Practitioner", practitioner, "op_consulting_charge")
|
||||
if op_consulting_charge:
|
||||
item_line.rate = op_consulting_charge
|
||||
item_line.amount = op_consulting_charge
|
||||
return invoice
|
||||
|
||||
def insert_encounter_to_medical_record(doc):
|
||||
subject = set_subject_field(doc)
|
||||
medical_record = frappe.new_doc("Patient Medical Record")
|
||||
|
@ -331,7 +331,7 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
@ -454,4 +454,4 @@
|
||||
"track_changes": 1,
|
||||
"track_seen": 1,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
||||
|
@ -236,7 +236,72 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "procedure_created",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Procedure Created",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"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": 1,
|
||||
"set_only_once": 0,
|
||||
"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",
|
||||
"fieldname": "invoiced",
|
||||
"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": "Invoiced",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
@ -252,7 +317,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-07-16 13:08:15.499491",
|
||||
"modified": "2018-08-06 16:53:36.440428",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Procedure Prescription",
|
||||
@ -266,5 +331,6 @@
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -88,8 +88,8 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "invoice",
|
||||
"fieldtype": "Link",
|
||||
"fieldname": "invoiced",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@ -97,10 +97,10 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Invoice",
|
||||
"label": "Invoiced",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Sales Invoice",
|
||||
"no_copy": 1,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -684,4 +684,4 @@
|
||||
"track_changes": 1,
|
||||
"track_seen": 1,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,24 @@
|
||||
{
|
||||
"content": null,
|
||||
"creation": "2016-08-18 12:29:52.497819",
|
||||
"docstatus": 0,
|
||||
"doctype": "Page",
|
||||
"idx": 0,
|
||||
"modified": "2016-08-18 12:29:52.497819",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "appointment-analytic",
|
||||
"owner": "Administrator",
|
||||
"page_name": "Appointment Analytics",
|
||||
"content": null,
|
||||
"creation": "2016-08-18 12:29:52.497819",
|
||||
"docstatus": 0,
|
||||
"doctype": "Page",
|
||||
"idx": 0,
|
||||
"modified": "2018-08-06 11:40:53.082863",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "appointment-analytic",
|
||||
"owner": "Administrator",
|
||||
"page_name": "Appointment Analytics",
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Physician"
|
||||
}
|
||||
],
|
||||
"script": null,
|
||||
"standard": "Yes",
|
||||
"style": null,
|
||||
],
|
||||
"script": null,
|
||||
"standard": "Yes",
|
||||
"style": null,
|
||||
"system_page": 0,
|
||||
"title": "Appointment Analytics"
|
||||
}
|
||||
}
|
@ -1,23 +1,25 @@
|
||||
{
|
||||
"content": null,
|
||||
"creation": "2016-06-09 11:33:14.025787",
|
||||
"docstatus": 0,
|
||||
"doctype": "Page",
|
||||
"icon": "icon-play",
|
||||
"idx": 0,
|
||||
"modified": "2017-03-06 11:20:40.174661",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "medical_record",
|
||||
"owner": "Administrator",
|
||||
"page_name": "medical_record",
|
||||
"content": null,
|
||||
"creation": "2016-06-09 11:33:14.025787",
|
||||
"docstatus": 0,
|
||||
"doctype": "Page",
|
||||
"icon": "icon-play",
|
||||
"idx": 0,
|
||||
"modified": "2018-08-06 11:40:39.705660",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "medical_record",
|
||||
"owner": "Administrator",
|
||||
"page_name": "medical_record",
|
||||
"restrict_to_domain": "Healthcare",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Physician"
|
||||
}
|
||||
],
|
||||
"script": null,
|
||||
"standard": "Yes",
|
||||
"style": null,
|
||||
],
|
||||
"script": null,
|
||||
"standard": "Yes",
|
||||
"style": null,
|
||||
"system_page": 0,
|
||||
"title": "Medical Record"
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -1,17 +1,17 @@
|
||||
{
|
||||
"add_total_row": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2013-04-23 18:15:29",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 1,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2017-08-23 14:54:12.593140",
|
||||
"modified": "2018-08-06 11:41:50.218737",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Lab Test Report",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"ref_doctype": "Lab Test",
|
||||
"report_name": "Lab Test Report",
|
||||
"report_type": "Script Report",
|
||||
@ -20,7 +20,13 @@
|
||||
"role": "Laboratory User"
|
||||
},
|
||||
{
|
||||
"role": "System Manager"
|
||||
"role": "Nursing User"
|
||||
},
|
||||
{
|
||||
"role": "LabTest Approver"
|
||||
},
|
||||
{
|
||||
"role": "Healthcare Administrator"
|
||||
}
|
||||
]
|
||||
}
|
@ -17,7 +17,7 @@ def execute(filters=None):
|
||||
|
||||
data = []
|
||||
for lab_test in lab_test_list:
|
||||
row = [ lab_test.test_name, lab_test.patient, lab_test.practitioner, lab_test.invoice, lab_test.status, lab_test.result_date, lab_test.department]
|
||||
row = [ lab_test.test_name, lab_test.patient, lab_test.practitioner, lab_test.invoiced, lab_test.status, lab_test.result_date, lab_test.department]
|
||||
data.append(row)
|
||||
|
||||
return columns, data
|
||||
@ -28,7 +28,7 @@ def get_columns():
|
||||
_("Test") + ":Data:120",
|
||||
_("Patient") + ":Link/Patient:180",
|
||||
_("Healthcare Practitioner") + ":Link/Healthcare Practitioner:120",
|
||||
_("Invoice") + ":Link/Sales Invoice:120",
|
||||
_("Invoiced") + ":Check:100",
|
||||
_("Status") + ":Data:120",
|
||||
_("Result Date") + ":Date:120",
|
||||
_("Department") + ":Data:120",
|
||||
@ -52,7 +52,7 @@ def get_conditions(filters):
|
||||
|
||||
def get_lab_test(filters):
|
||||
conditions = get_conditions(filters)
|
||||
return frappe.db.sql("""select name, patient, test_name, patient_name, status, result_date, practitioner, invoice, department
|
||||
return frappe.db.sql("""select name, patient, test_name, patient_name, status, result_date, practitioner, invoiced, department
|
||||
from `tabLab Test`
|
||||
where docstatus<2 %s order by submitted_date desc, name desc""" %
|
||||
conditions, filters, as_dict=1)
|
||||
|
426
erpnext/healthcare/utils.py
Normal file
426
erpnext/healthcare/utils.py
Normal file
@ -0,0 +1,426 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, earthians and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import datetime
|
||||
from frappe import _
|
||||
import math
|
||||
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.fee_validity.fee_validity import create_fee_validity, update_fee_validity
|
||||
from erpnext.healthcare.doctype.lab_test.lab_test import create_multiple
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_healthcare_services_to_invoice(patient):
|
||||
patient = frappe.get_doc("Patient", patient)
|
||||
if patient:
|
||||
if patient.customer:
|
||||
item_to_invoice = []
|
||||
patient_appointments = frappe.get_list("Patient Appointment",{'patient': patient.name, 'invoiced': False},
|
||||
order_by="appointment_date")
|
||||
if patient_appointments:
|
||||
fee_validity_details = []
|
||||
valid_days = frappe.db.get_value("Healthcare Settings", None, "valid_days")
|
||||
max_visit = frappe.db.get_value("Healthcare Settings", None, "max_visit")
|
||||
for patient_appointment in patient_appointments:
|
||||
patient_appointment_obj = frappe.get_doc("Patient Appointment", patient_appointment['name'])
|
||||
|
||||
if patient_appointment_obj.procedure_template:
|
||||
if frappe.db.get_value("Clinical Procedure Template", patient_appointment_obj.procedure_template, "is_billable") == 1:
|
||||
item_to_invoice.append({'reference_type': 'Patient Appointment', 'reference_name': patient_appointment_obj.name, 'service': patient_appointment_obj.procedure_template})
|
||||
else:
|
||||
practitioner_exist_in_list = False
|
||||
skip_invoice = False
|
||||
if fee_validity_details:
|
||||
for validity in fee_validity_details:
|
||||
if validity['practitioner'] == patient_appointment_obj.practitioner:
|
||||
practitioner_exist_in_list = True
|
||||
if validity['valid_till'] >= patient_appointment_obj.appointment_date:
|
||||
validity['visits'] = validity['visits']+1
|
||||
if int(max_visit) > validity['visits']:
|
||||
skip_invoice = True
|
||||
if not skip_invoice:
|
||||
validity['visits'] = 1
|
||||
validity['valid_till'] = patient_appointment_obj.appointment_date + datetime.timedelta(days=int(valid_days))
|
||||
if not practitioner_exist_in_list:
|
||||
valid_till = patient_appointment_obj.appointment_date + datetime.timedelta(days=int(valid_days))
|
||||
visits = 0
|
||||
validity_exist = validity_exists(patient_appointment_obj.practitioner, patient_appointment_obj.patient)
|
||||
if validity_exist:
|
||||
fee_validity = frappe.get_doc("Fee Validity", validity_exist[0][0])
|
||||
valid_till = fee_validity.valid_till
|
||||
visits = fee_validity.visited
|
||||
fee_validity_details.append({'practitioner': patient_appointment_obj.practitioner,
|
||||
'valid_till': valid_till, 'visits': visits})
|
||||
|
||||
if not skip_invoice:
|
||||
practitioner_charge = 0
|
||||
income_account = None
|
||||
service_item = None
|
||||
if patient_appointment_obj.practitioner:
|
||||
service_item, practitioner_charge = service_item_and_practitioner_charge(patient_appointment_obj)
|
||||
income_account = get_income_account(patient_appointment_obj.practitioner, patient_appointment_obj.company)
|
||||
item_to_invoice.append({'reference_type': 'Patient Appointment', 'reference_name': patient_appointment_obj.name,
|
||||
'service': service_item, 'rate': practitioner_charge,
|
||||
'income_account': income_account})
|
||||
|
||||
encounters = frappe.get_list("Patient Encounter", {'patient': patient.name, 'invoiced': False, 'docstatus': 1})
|
||||
if encounters:
|
||||
for encounter in encounters:
|
||||
encounter_obj = frappe.get_doc("Patient Encounter", encounter['name'])
|
||||
if not encounter_obj.appointment:
|
||||
practitioner_charge = 0
|
||||
income_account = None
|
||||
service_item = None
|
||||
if encounter_obj.practitioner:
|
||||
service_item, practitioner_charge = service_item_and_practitioner_charge(encounter_obj)
|
||||
income_account = get_income_account(encounter_obj.practitioner, encounter_obj.company)
|
||||
|
||||
item_to_invoice.append({'reference_type': 'Patient Encounter', 'reference_name': encounter_obj.name,
|
||||
'service': service_item, 'rate': practitioner_charge,
|
||||
'income_account': income_account})
|
||||
|
||||
lab_tests = frappe.get_list("Lab Test", {'patient': patient.name, 'invoiced': False})
|
||||
if lab_tests:
|
||||
for lab_test in lab_tests:
|
||||
lab_test_obj = frappe.get_doc("Lab Test", lab_test['name'])
|
||||
if frappe.db.get_value("Lab Test Template", lab_test_obj.template, "is_billable") == 1:
|
||||
item_to_invoice.append({'reference_type': 'Lab Test', 'reference_name': lab_test_obj.name,
|
||||
'service': frappe.db.get_value("Lab Test Template", lab_test_obj.template, "item")})
|
||||
|
||||
lab_rxs = frappe.db.sql("""select lp.name from `tabPatient Encounter` et, `tabLab Prescription` lp
|
||||
where et.patient=%s and lp.parent=et.name and lp.test_created=0 and lp.invoiced=0""", (patient.name))
|
||||
if lab_rxs:
|
||||
for lab_rx in lab_rxs:
|
||||
rx_obj = frappe.get_doc("Lab Prescription", lab_rx[0])
|
||||
if rx_obj.test_code and (frappe.db.get_value("Lab Test Template", rx_obj.test_code, "is_billable") == 1):
|
||||
item_to_invoice.append({'reference_type': 'Lab Prescription', 'reference_name': rx_obj.name,
|
||||
'service': frappe.db.get_value("Lab Test Template", rx_obj.test_code, "item")})
|
||||
|
||||
procedures = frappe.get_list("Clinical Procedure", {'patient': patient.name, 'invoiced': False})
|
||||
if procedures:
|
||||
for procedure in procedures:
|
||||
procedure_obj = frappe.get_doc("Clinical Procedure", procedure['name'])
|
||||
if not procedure_obj.appointment:
|
||||
if procedure_obj.procedure_template and (frappe.db.get_value("Clinical Procedure Template", procedure_obj.procedure_template, "is_billable") == 1):
|
||||
item_to_invoice.append({'reference_type': 'Clinical Procedure', 'reference_name': procedure_obj.name,
|
||||
'service': frappe.db.get_value("Clinical Procedure Template", procedure_obj.procedure_template, "item")})
|
||||
|
||||
procedure_rxs = frappe.db.sql("""select pp.name from `tabPatient Encounter` et,
|
||||
`tabProcedure Prescription` pp where et.patient=%s and pp.parent=et.name and
|
||||
pp.procedure_created=0 and pp.invoiced=0 and pp.appointment_booked=0""", (patient.name))
|
||||
if procedure_rxs:
|
||||
for procedure_rx in procedure_rxs:
|
||||
rx_obj = frappe.get_doc("Procedure Prescription", procedure_rx[0])
|
||||
if frappe.db.get_value("Clinical Procedure Template", rx_obj.procedure, "is_billable") == 1:
|
||||
item_to_invoice.append({'reference_type': 'Procedure Prescription', 'reference_name': rx_obj.name,
|
||||
'service': frappe.db.get_value("Clinical Procedure Template", rx_obj.procedure, "item")})
|
||||
|
||||
procedures = frappe.get_list("Clinical Procedure",
|
||||
{'patient': patient.name, 'invoice_separately_as_consumables': True, 'consumption_invoiced': False,
|
||||
'consume_stock': True, 'status': 'Completed'})
|
||||
if procedures:
|
||||
service_item = get_healthcare_service_item('clinical_procedure_consumable_item')
|
||||
if not service_item:
|
||||
msg = _(("Please Configure {0} in ").format("Clinical Procedure Consumable Item") \
|
||||
+ """<b><a href="#Form/Healthcare Settings">Healthcare Settings</a></b>""")
|
||||
frappe.throw(msg)
|
||||
for procedure in procedures:
|
||||
procedure_obj = frappe.get_doc("Clinical Procedure", procedure['name'])
|
||||
item_to_invoice.append({'reference_type': 'Clinical Procedure', 'reference_name': procedure_obj.name,
|
||||
'service': service_item, 'rate': procedure_obj.consumable_total_amount, 'description': procedure_obj.consumption_details})
|
||||
|
||||
inpatient_services = frappe.db.sql("""select io.name, io.parent from `tabInpatient Record` ip,
|
||||
`tabInpatient Occupancy` io where ip.patient=%s and io.parent=ip.name and
|
||||
io.left=1 and io.invoiced=0""", (patient.name))
|
||||
if inpatient_services:
|
||||
for inpatient_service in inpatient_services:
|
||||
inpatient_occupancy = frappe.get_doc("Inpatient Occupancy", inpatient_service[0])
|
||||
service_unit_type = frappe.get_doc("Healthcare Service Unit Type", frappe.db.get_value("Healthcare Service Unit", inpatient_occupancy.service_unit, "service_unit_type"))
|
||||
if service_unit_type and service_unit_type.is_billable == 1:
|
||||
hours_occupied = time_diff_in_hours(inpatient_occupancy.check_out, inpatient_occupancy.check_in)
|
||||
qty = 0.5
|
||||
if hours_occupied > 0:
|
||||
actual_qty = hours_occupied / service_unit_type.no_of_hours
|
||||
floor = math.floor(actual_qty)
|
||||
decimal_part = actual_qty - floor
|
||||
if decimal_part > 0.5:
|
||||
qty = rounded(floor + 1, 1)
|
||||
elif decimal_part < 0.5 and decimal_part > 0:
|
||||
qty = rounded(floor + 0.5, 1)
|
||||
if qty <= 0:
|
||||
qty = 0.5
|
||||
item_to_invoice.append({'reference_type': 'Inpatient Occupancy', 'reference_name': inpatient_occupancy.name,
|
||||
'service': service_unit_type.item, 'qty': qty})
|
||||
|
||||
return item_to_invoice
|
||||
else:
|
||||
frappe.throw(_("The Patient {0} do not have customer refrence to invoice").format(patient.name))
|
||||
|
||||
def service_item_and_practitioner_charge(doc):
|
||||
is_ip = doc_is_ip(doc)
|
||||
if is_ip:
|
||||
service_item = get_practitioner_service_item(doc.practitioner, "inpatient_visit_charge_item")
|
||||
if not service_item:
|
||||
service_item = get_healthcare_service_item("inpatient_visit_charge_item")
|
||||
else:
|
||||
service_item = get_practitioner_service_item(doc.practitioner, "op_consulting_charge_item")
|
||||
if not service_item:
|
||||
service_item = get_healthcare_service_item("op_consulting_charge_item")
|
||||
if not service_item:
|
||||
throw_config_service_item(is_ip)
|
||||
|
||||
practitioner_charge = get_practitioner_charge(doc.practitioner, is_ip)
|
||||
if not practitioner_charge:
|
||||
throw_config_practitioner_charge(is_ip, doc.practitioner)
|
||||
|
||||
return service_item, practitioner_charge
|
||||
|
||||
def throw_config_service_item(is_ip):
|
||||
service_item_lable = "Out Patient Consulting Charge Item"
|
||||
if is_ip:
|
||||
service_item_lable = "Inpatient Visit Charge Item"
|
||||
|
||||
msg = _(("Please Configure {0} in ").format(service_item_lable) \
|
||||
+ """<b><a href="#Form/Healthcare Settings">Healthcare Settings</a></b>""")
|
||||
frappe.throw(msg)
|
||||
|
||||
def throw_config_practitioner_charge(is_ip, practitioner):
|
||||
charge_name = "OP Consulting Charge"
|
||||
if is_ip:
|
||||
charge_name = "Inpatient Visit Charge"
|
||||
|
||||
msg = _(("Please Configure {0} for Healthcare Practitioner").format(charge_name) \
|
||||
+ """ <b><a href="#Form/Healthcare Practitioner/{0}">{0}</a></b>""".format(practitioner))
|
||||
frappe.throw(msg)
|
||||
|
||||
def get_practitioner_service_item(practitioner, service_item_field):
|
||||
return frappe.db.get_value("Healthcare Practitioner", practitioner, service_item_field)
|
||||
|
||||
def get_healthcare_service_item(service_item_field):
|
||||
return frappe.db.get_value("Healthcare Settings", None, service_item_field)
|
||||
|
||||
def doc_is_ip(doc):
|
||||
is_ip = False
|
||||
if doc.inpatient_record:
|
||||
is_ip = True
|
||||
return is_ip
|
||||
|
||||
def get_practitioner_charge(practitioner, is_ip):
|
||||
if is_ip:
|
||||
practitioner_charge = frappe.db.get_value("Healthcare Practitioner", practitioner, "inpatient_visit_charge")
|
||||
else:
|
||||
practitioner_charge = frappe.db.get_value("Healthcare Practitioner", practitioner, "op_consulting_charge")
|
||||
if practitioner_charge:
|
||||
return practitioner_charge
|
||||
return False
|
||||
|
||||
def manage_invoice_submit_cancel(doc, method):
|
||||
if doc.items:
|
||||
for item in doc.items:
|
||||
if item.reference_dt and item.reference_dn:
|
||||
if frappe.get_meta(item.reference_dt).has_field("invoiced"):
|
||||
set_invoiced(item, method, doc.name)
|
||||
|
||||
if method=="on_submit" and frappe.db.get_value("Healthcare Settings", None, "create_test_on_si_submit") == '1':
|
||||
create_multiple("Sales Invoice", doc.name)
|
||||
|
||||
def set_invoiced(item, method, ref_invoice=None):
|
||||
invoiced = False
|
||||
if(method=="on_submit"):
|
||||
validate_invoiced_on_submit(item)
|
||||
invoiced = True
|
||||
|
||||
if item.reference_dt == 'Clinical Procedure':
|
||||
if get_healthcare_service_item('clinical_procedure_consumable_item') == item.item_code:
|
||||
frappe.db.set_value(item.reference_dt, item.reference_dn, "consumption_invoiced", invoiced)
|
||||
else:
|
||||
frappe.db.set_value(item.reference_dt, item.reference_dn, "invoiced", invoiced)
|
||||
else:
|
||||
frappe.db.set_value(item.reference_dt, item.reference_dn, "invoiced", invoiced)
|
||||
|
||||
if item.reference_dt == 'Patient Appointment':
|
||||
if frappe.db.get_value('Patient Appointment', item.reference_dn, 'procedure_template'):
|
||||
dt_from_appointment = "Clinical Procedure"
|
||||
else:
|
||||
manage_fee_validity(item.reference_dn, method, ref_invoice)
|
||||
dt_from_appointment = "Patient Encounter"
|
||||
manage_doc_for_appoitnment(dt_from_appointment, item.reference_dn, invoiced)
|
||||
|
||||
elif item.reference_dt == 'Lab Prescription':
|
||||
manage_prescriptions(invoiced, item.reference_dt, item.reference_dn, "Lab Test", "test_created")
|
||||
|
||||
elif item.reference_dt == 'Procedure Prescription':
|
||||
manage_prescriptions(invoiced, item.reference_dt, item.reference_dn, "Clinical Procedure", "procedure_created")
|
||||
|
||||
def validate_invoiced_on_submit(item):
|
||||
if item.reference_dt == 'Clinical Procedure' and get_healthcare_service_item('clinical_procedure_consumable_item') == item.item_code:
|
||||
is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, "consumption_invoiced")
|
||||
else:
|
||||
is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, "invoiced")
|
||||
if is_invoiced == 1:
|
||||
frappe.throw(_("The item referenced by {0} - {1} is already invoiced"\
|
||||
).format(item.reference_dt, item.reference_dn))
|
||||
|
||||
def manage_prescriptions(invoiced, ref_dt, ref_dn, dt, created_check_field):
|
||||
created = frappe.db.get_value(ref_dt, ref_dn, created_check_field)
|
||||
if created == 1:
|
||||
# Fetch the doc created for the prescription
|
||||
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)
|
||||
do_not_update = False
|
||||
visited = 0
|
||||
if validity_exist:
|
||||
fee_validity = frappe.get_doc("Fee Validity", validity_exist[0][0])
|
||||
# Check if the validity is valid
|
||||
if (fee_validity.valid_till >= appointment_doc.appointment_date):
|
||||
if (method == "on_cancel" and appointment_doc.status != "Closed"):
|
||||
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 (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
|
||||
else:
|
||||
do_not_update = False
|
||||
|
||||
if not do_not_update:
|
||||
fee_validity = update_fee_validity(fee_validity, appointment_doc.appointment_date, ref_invoice)
|
||||
visited = fee_validity.visited
|
||||
else:
|
||||
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 = 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"):
|
||||
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 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)
|
||||
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(
|
||||
dt_from_appointment,
|
||||
{
|
||||
"appointment": appointment
|
||||
}
|
||||
)
|
||||
if dn_from_appointment:
|
||||
frappe.db.set_value(dt_from_appointment, dn_from_appointment, "invoiced", invoiced)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_drugs_to_invoice(encounter):
|
||||
encounter = frappe.get_doc("Patient Encounter", encounter)
|
||||
if encounter:
|
||||
patient = frappe.get_doc("Patient", encounter.patient)
|
||||
if patient and patient.customer:
|
||||
item_to_invoice = []
|
||||
for drug_line in encounter.drug_prescription:
|
||||
if drug_line.drug_code:
|
||||
qty = 1
|
||||
if frappe.db.get_value("Item", drug_line.drug_code, "stock_uom") == "Nos":
|
||||
qty = drug_line.get_quantity()
|
||||
item_to_invoice.append({'drug_code': drug_line.drug_code, 'quantity': qty,
|
||||
'description': drug_line.dosage+" for "+drug_line.period})
|
||||
return item_to_invoice
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent, company, is_root=False):
|
||||
parent_fieldname = 'parent_' + doctype.lower().replace(' ', '_')
|
||||
fields = [
|
||||
'name as value',
|
||||
'is_group as expandable',
|
||||
'lft',
|
||||
'rgt'
|
||||
]
|
||||
# fields = [ 'name', 'is_group', 'lft', 'rgt' ]
|
||||
filters = [['ifnull(`{0}`,"")'.format(parent_fieldname), '=', '' if is_root else parent]]
|
||||
|
||||
if is_root:
|
||||
fields += ['service_unit_type'] if doctype == 'Healthcare Service Unit' else []
|
||||
filters.append(['company', '=', company])
|
||||
|
||||
else:
|
||||
fields += ['service_unit_type', 'allow_appointments', 'inpatient_occupancy', 'occupancy_status'] if doctype == 'Healthcare Service Unit' else []
|
||||
fields += [parent_fieldname + ' as parent']
|
||||
|
||||
hc_service_units = frappe.get_list(doctype, fields=fields, filters=filters)
|
||||
|
||||
if doctype == 'Healthcare Service Unit':
|
||||
for each in hc_service_units:
|
||||
occupancy_msg = ""
|
||||
if each['expandable'] == 1:
|
||||
occupied = False
|
||||
vacant = False
|
||||
child_list = frappe.db.sql("""
|
||||
select name, occupancy_status from `tabHealthcare Service Unit`
|
||||
where inpatient_occupancy = 1 and
|
||||
lft > %s and rgt < %s""",
|
||||
(each['lft'], each['rgt']))
|
||||
for child in child_list:
|
||||
print child[0], child[1]
|
||||
if not occupied:
|
||||
occupied = 0
|
||||
if child[1] == "Occupied":
|
||||
occupied += 1
|
||||
if not vacant:
|
||||
vacant = 0
|
||||
if child[1] == "Vacant":
|
||||
vacant += 1
|
||||
if vacant and occupied:
|
||||
occupancy_total = vacant+occupied
|
||||
occupancy_msg = str(occupied) + " Occupied out of " + str(occupancy_total)
|
||||
each["occupied_out_of_vacant"] = occupancy_msg
|
||||
return hc_service_units
|
@ -18,7 +18,7 @@
|
||||
"is_standard": 1,
|
||||
"login_required": 1,
|
||||
"max_attachment_size": 0,
|
||||
"modified": "2018-07-16 13:10:47.940128",
|
||||
"modified": "2018-07-17 13:10:47.940128",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "lab-test",
|
||||
@ -44,13 +44,14 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "invoice",
|
||||
"fieldtype": "Link",
|
||||
"default": "0",
|
||||
"fieldname": "invoiced",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"label": "Invoice",
|
||||
"label": "Invoiced",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "Sales Invoice",
|
||||
"options": "",
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
@ -232,4 +233,4 @@
|
||||
"reqd": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -563,3 +563,4 @@ erpnext.patches.v11_0.reset_publish_in_hub_for_all_items
|
||||
erpnext.patches.v11_0.update_hub_url # 2018-08-31 # 2018-09-03
|
||||
erpnext.patches.v10_0.set_discount_amount
|
||||
erpnext.patches.v10_0.recalculate_gross_margin_for_project
|
||||
erpnext.patches.v11_0.redesign_healthcare_billing_work_flow
|
||||
|
@ -0,0 +1,60 @@
|
||||
import frappe
|
||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
||||
from erpnext.domains.healthcare import data
|
||||
from frappe.modules import scrub, get_doctype_module
|
||||
|
||||
sales_invoice_referenced_doc = {
|
||||
"Patient Appointment": "sales_invoice",
|
||||
"Patient Encounter": "invoice",
|
||||
"Lab Test": "invoice",
|
||||
"Lab Prescription": "invoice",
|
||||
"Sample Collection": "invoice"
|
||||
}
|
||||
|
||||
def execute():
|
||||
healthcare_custom_field_in_sales_invoice()
|
||||
frappe.reload_doc('accounts', 'doctype', 'sales_invoice_item')
|
||||
for si_ref_doc in sales_invoice_referenced_doc:
|
||||
if frappe.db.exists('DocType', si_ref_doc):
|
||||
frappe.reload_doc(get_doctype_module(si_ref_doc), 'doctype', scrub(si_ref_doc))
|
||||
|
||||
if frappe.db.has_column(si_ref_doc, sales_invoice_referenced_doc[si_ref_doc]) \
|
||||
and frappe.db.has_column(si_ref_doc, 'invoiced'):
|
||||
# Set Reference DocType and Reference Docname
|
||||
doc_list = frappe.db.sql("""
|
||||
select name from `tab{0}`
|
||||
where {1} is not null
|
||||
""".format(si_ref_doc, sales_invoice_referenced_doc[si_ref_doc]))
|
||||
if doc_list:
|
||||
frappe.reload_doc(get_doctype_module("Sales Invoice"), 'doctype', 'sales_invoice')
|
||||
for doc_id in doc_list:
|
||||
invoice_id = frappe.db.get_value(si_ref_doc, doc_id[0], sales_invoice_referenced_doc[si_ref_doc])
|
||||
invoice = frappe.get_doc("Sales Invoice", invoice_id)
|
||||
if invoice.items:
|
||||
marked = False
|
||||
if not marked:
|
||||
for item_line in invoice.items:
|
||||
marked = True
|
||||
frappe.db.sql("""
|
||||
update `tabSales Invoice Item`
|
||||
set reference_dt = '{0}', reference_dn = '{1}'
|
||||
where name = '{2}'
|
||||
""".format(si_ref_doc, doc_id[0], item_line.name))
|
||||
|
||||
# Documents mark invoiced for submitted sales invoice
|
||||
frappe.db.sql("""
|
||||
update `tab{0}` doc, `tabSales Invoice` si
|
||||
set doc.invoiced = 1
|
||||
where si.docstatus = 1 and doc.{1} = si.name
|
||||
""".format(si_ref_doc, sales_invoice_referenced_doc[si_ref_doc]))
|
||||
|
||||
def healthcare_custom_field_in_sales_invoice():
|
||||
frappe.reload_doc('healthcare', 'doctype', 'patient')
|
||||
frappe.reload_doc('healthcare', 'doctype', 'healthcare_practitioner')
|
||||
if data['custom_fields']:
|
||||
create_custom_fields(data['custom_fields'])
|
||||
|
||||
frappe.db.sql("""
|
||||
delete from `tabCustom Field`
|
||||
where fieldname = 'appointment' and options = 'Patient Appointment'
|
||||
""")
|
Loading…
Reference in New Issue
Block a user