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