feat: Repayment schedule types for term loans
diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json
index 47488f4..d245edc 100644
--- a/erpnext/loan_management/doctype/loan/loan.json
+++ b/erpnext/loan_management/doctype/loan/loan.json
@@ -407,7 +407,7 @@
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2022-07-12 11:50:31.957360",
+ "modified": "2022-09-29 11:50:31.957360",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan",
diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py
index d84eef6..d55af70 100644
--- a/erpnext/loan_management/doctype/loan/loan.py
+++ b/erpnext/loan_management/doctype/loan/loan.py
@@ -7,7 +7,17 @@
 
 import frappe
 from frappe import _
-from frappe.utils import add_months, flt, get_last_day, getdate, now_datetime, nowdate
+from frappe.utils import (
+	add_days,
+	add_months,
+	date_diff,
+	flt,
+	get_first_day,
+	get_last_day,
+	getdate,
+	now_datetime,
+	nowdate,
+)
 
 import erpnext
 from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry
@@ -107,30 +117,66 @@
 		if not self.repayment_start_date:
 			frappe.throw(_("Repayment Start Date is mandatory for term loans"))
 
+		schedule_type = frappe.db.get_value("Loan Type", self.loan_type, "repayment_schedule_type")
 		self.repayment_schedule = []
 		payment_date = self.repayment_start_date
 		balance_amount = self.loan_amount
-		while balance_amount > 0:
-			interest_amount = flt(balance_amount * flt(self.rate_of_interest) / (12 * 100))
-			principal_amount = self.monthly_repayment_amount - interest_amount
-			balance_amount = flt(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,
-				},
+		while balance_amount > 0:
+			interest_amount, principal_amount, balance_amount, total_payment = self.get_amounts(
+				payment_date, balance_amount, schedule_type
 			)
-			next_payment_date = add_single_month(payment_date)
-			payment_date = next_payment_date
+
+			if schedule_type == "Pro-rated calendar months":
+				next_payment_date = add_days(get_last_day(payment_date), 1)
+				payment_date = next_payment_date
+
+			self.add_repayment_schedule_row(
+				payment_date, principal_amount, interest_amount, total_payment, balance_amount
+			)
+
+			if schedule_type == "Monthly as per repayment start date":
+				next_payment_date = add_single_month(payment_date)
+				payment_date = next_payment_date
+
+	def get_amounts(self, payment_date, balance_amount, schedule_type):
+		first_day_of_month = get_first_day(payment_date)
+
+		if schedule_type == "Monthly as per repayment start date":
+			days = 1
+			months = 12
+		else:
+			if first_day_of_month == payment_date:
+				days = 30
+				months = 365
+			else:
+				days = date_diff(get_last_day(payment_date), payment_date)
+				months = 365
+
+		interest_amount = flt(balance_amount * flt(self.rate_of_interest) * days / (months * 100))
+		principal_amount = self.monthly_repayment_amount - interest_amount
+		balance_amount = flt(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
+
+		return interest_amount, principal_amount, balance_amount, total_payment
+
+	def add_repayment_schedule_row(
+		self, payment_date, principal_amount, interest_amount, total_payment, balance_loan_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_loan_amount,
+			},
+		)
 
 	def set_repayment_period(self):
 		if self.repayment_method == "Repay Fixed Amount per Period":
diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.json b/erpnext/loan_management/doctype/loan_type/loan_type.json
index 00337e4..e1ed3ca 100644
--- a/erpnext/loan_management/doctype/loan_type/loan_type.json
+++ b/erpnext/loan_management/doctype/loan_type/loan_type.json
@@ -16,6 +16,7 @@
   "company",
   "is_term_loan",
   "disabled",
+  "repayment_schedule_type",
   "description",
   "account_details_section",
   "mode_of_payment",
@@ -157,12 +158,20 @@
    "label": "Disbursement Account",
    "options": "Account",
    "reqd": 1
+  },
+  {
+   "depends_on": "is_term_loan",
+   "fieldname": "repayment_schedule_type",
+   "fieldtype": "Select",
+   "label": "Repayment Schedule Type",
+   "mandatory_depends_on": "is_term_loan",
+   "options": "\nMonthly as per repayment start date\nPro-rated calendar months"
   }
  ],
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2022-01-25 16:23:57.009349",
+ "modified": "2022-09-28 21:31:01.278941",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Type",
diff --git a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py
index 846be0b..403d874 100644
--- a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py
+++ b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py
@@ -15,6 +15,7 @@
 
 @frappe.whitelist()
 def get_stock_item_details(warehouse, date, item=None, barcode=None):
+	print(warehouse, date, item, "########")
 	out = {}
 	if barcode:
 		out["item"] = frappe.db.get_value(