def get_amount_based_on_payment_days(self, row, joining_date, relieving_date): amount, additional_amount = row.amount, row.additional_amount if (self.salary_structure and cint(row.depends_on_payment_days) and cint(self.total_working_days) and (not self.salary_slip_based_on_timesheet or getdate(self.start_date) < joining_date or getdate(self.end_date) > relieving_date)): additional_amount = flt( (flt(row.additional_amount) * flt(self.payment_days) / cint(self.total_working_days)), row.precision("additional_amount")) amount = flt((flt(row.default_amount) * flt(self.payment_days) / cint(self.total_working_days)), row.precision("amount")) + additional_amount elif not self.payment_days and not self.salary_slip_based_on_timesheet and cint( row.depends_on_payment_days): amount, additional_amount = 0, 0 elif not row.amount: amount = flt(row.default_amount) + flt(row.additional_amount) # apply rounding if dataent.get_cached_value("Salary Component", row.salary_component, "round_to_the_nearest_integer"): amount, additional_amount = rounded(amount), rounded( additional_amount) return amount, additional_amount
def make_repayment_schedule(self): self.repayment_schedule = [] payment_date = self.repayment_start_date balance_amount = self.loan_amount while (balance_amount > 0): interest_amount = rounded(balance_amount * flt(self.rate_of_interest) / (12 * 100)) principal_amount = self.monthly_repayment_amount - interest_amount balance_amount = rounded(balance_amount + interest_amount - self.monthly_repayment_amount) if balance_amount < 0: principal_amount += balance_amount balance_amount = 0.0 total_payment = principal_amount + interest_amount self.append( "repayment_schedule", { "payment_date": payment_date, "principal_amount": principal_amount, "interest_amount": interest_amount, "total_payment": total_payment, "balance_loan_amount": balance_amount }) next_payment_date = add_months(payment_date, 1) payment_date = next_payment_date
def calculate_payable_amount(self): balance_amount = self.loan_amount self.total_payable_amount = 0 self.total_payable_interest = 0 while (balance_amount > 0): interest_amount = rounded(balance_amount * flt(self.rate_of_interest) / (12 * 100)) balance_amount = rounded(balance_amount + interest_amount - self.repayment_amount) self.total_payable_interest += interest_amount self.total_payable_amount = self.loan_amount + self.total_payable_interest
def calculate_net_pay(self): if self.salary_structure: self.calculate_component_amounts() self.gross_pay = self.get_component_totals("earnings") self.total_deduction = self.get_component_totals("deductions") self.set_loan_repayment() self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment)) self.rounded_total = rounded(self.net_pay)
def validate_max_benefit(self, earning_component_name): max_benefit_amount = dataent.db.get_value("Salary Component", earning_component_name, "max_benefit_amount") benefit_amount = 0 for employee_benefit in self.employee_benefits: if employee_benefit.earning_component == earning_component_name: benefit_amount += employee_benefit.amount prev_sal_slip_flexi_amount = get_sal_slip_total_benefit_given( self.employee, dataent.get_doc("Payroll Period", self.payroll_period), earning_component_name) benefit_amount += prev_sal_slip_flexi_amount if rounded(benefit_amount, 2) > max_benefit_amount: dataent.throw( _("Maximum benefit amount of component {0} exceeds {1}"). format(earning_component_name, max_benefit_amount))
def validate_remaining_benefit_amount(self): # check salary structure earnings have flexi component (sum of max_benefit_amount) # without pro-rata which satisfy the remaining_benefit # else pro-rata component for the amount # again comes the same validation and satisfy or throw benefit_components = [] if self.employee_benefits: for employee_benefit in self.employee_benefits: benefit_components.append(employee_benefit.earning_component) salary_struct_name = get_assigned_salary_structure( self.employee, self.date) if salary_struct_name: non_pro_rata_amount = 0 pro_rata_amount = 0 salary_structure = dataent.get_doc("Salary Structure", salary_struct_name) if salary_structure.earnings: for earnings in salary_structure.earnings: if earnings.is_flexible_benefit == 1 and earnings.salary_component not in benefit_components: pay_against_benefit_claim, max_benefit_amount = dataent.db.get_value( "Salary Component", earnings.salary_component, [ "pay_against_benefit_claim", "max_benefit_amount" ]) if pay_against_benefit_claim != 1: pro_rata_amount += max_benefit_amount else: non_pro_rata_amount += max_benefit_amount if pro_rata_amount == 0 and non_pro_rata_amount == 0: dataent.throw( _("Please add the remaining benefits {0} to any of the existing component" ).format(self.remaining_benefit)) elif non_pro_rata_amount > 0 and non_pro_rata_amount < rounded( self.remaining_benefit): dataent.throw( _("You can claim only an amount of {0}, the rest amount {1} should be in the application \ as pro-rata component").format( non_pro_rata_amount, self.remaining_benefit - non_pro_rata_amount)) elif non_pro_rata_amount == 0: dataent.throw( _("Please add the remaining benefits {0} to the application as \ pro-rata component").format(self.remaining_benefit))
def get_healthcare_services_to_invoice(patient): patient = dataent.get_doc("Patient", patient) if patient: if patient.customer: item_to_invoice = [] patient_appointments = dataent.get_list( "Patient Appointment", { 'patient': patient.name, 'invoiced': False }, order_by="appointment_date") if patient_appointments: fee_validity_details = [] valid_days = dataent.db.get_value("Healthcare Settings", None, "valid_days") max_visit = dataent.db.get_value("Healthcare Settings", None, "max_visit") for patient_appointment in patient_appointments: patient_appointment_obj = dataent.get_doc( "Patient Appointment", patient_appointment['name']) if patient_appointment_obj.procedure_template: if dataent.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 = dataent.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 = dataent.get_list("Patient Encounter", { 'patient': patient.name, 'invoiced': False, 'docstatus': 1 }) if encounters: for encounter in encounters: encounter_obj = dataent.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 = dataent.get_list("Lab Test", { 'patient': patient.name, 'invoiced': False, 'docstatus': 1 }) if lab_tests: for lab_test in lab_tests: lab_test_obj = dataent.get_doc("Lab Test", lab_test['name']) if dataent.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': dataent.db.get_value("Lab Test Template", lab_test_obj.template, "item") }) lab_rxs = dataent.db.sql( """select lp.name from `tabPatient Encounter` et, `tabLab Prescription` lp where et.patient=%s and lp.parent=et.name and lp.lab_test_created=0 and lp.invoiced=0""", (patient.name)) if lab_rxs: for lab_rx in lab_rxs: rx_obj = dataent.get_doc("Lab Prescription", lab_rx[0]) if rx_obj.lab_test_code and (dataent.db.get_value( "Lab Test Template", rx_obj.lab_test_code, "is_billable") == 1): item_to_invoice.append({ 'reference_type': 'Lab Prescription', 'reference_name': rx_obj.name, 'service': dataent.db.get_value("Lab Test Template", rx_obj.lab_test_code, "item") }) procedures = dataent.get_list("Clinical Procedure", { 'patient': patient.name, 'invoiced': False }) if procedures: for procedure in procedures: procedure_obj = dataent.get_doc("Clinical Procedure", procedure['name']) if not procedure_obj.appointment: if procedure_obj.procedure_template and ( dataent.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': dataent.db.get_value( "Clinical Procedure Template", procedure_obj.procedure_template, "item") }) procedure_rxs = dataent.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 = dataent.get_doc("Procedure Prescription", procedure_rx[0]) if dataent.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': dataent.db.get_value("Clinical Procedure Template", rx_obj.procedure, "item") }) procedures = dataent.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>""") dataent.throw(msg) for procedure in procedures: procedure_obj = dataent.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 = dataent.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 = dataent.get_doc( "Inpatient Occupancy", inpatient_service[0]) service_unit_type = dataent.get_doc( "Healthcare Service Unit Type", dataent.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: dataent.throw( _("The Patient {0} do not have customer refrence to invoice"). format(patient.name))