fix: Update paid amount for pos return (#20543)
* fix: Paid amount updation for pos return
* fix: Remove console
* fix: Styling
* fix: get default mode of payment from POS profile
* fix: Add test cases
* fix: Codacy
diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
index 58f1216..64d347d 100644
--- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
@@ -29,27 +29,29 @@
frappe.db.sql("delete from `tabPOS Profile`")
-def make_pos_profile():
+def make_pos_profile(**args):
frappe.db.sql("delete from `tabPOS Profile`")
+ args = frappe._dict(args)
+
pos_profile = frappe.get_doc({
- "company": "_Test Company",
- "cost_center": "_Test Cost Center - _TC",
- "currency": "INR",
+ "company": args.company or "_Test Company",
+ "cost_center": args.cost_center or "_Test Cost Center - _TC",
+ "currency": args.currency or "INR",
"doctype": "POS Profile",
- "expense_account": "_Test Account Cost for Goods Sold - _TC",
- "income_account": "Sales - _TC",
- "name": "_Test POS Profile",
+ "expense_account": args.expense_account or "_Test Account Cost for Goods Sold - _TC",
+ "income_account": args.income_account or "Sales - _TC",
+ "name": args.name or "_Test POS Profile",
"naming_series": "_T-POS Profile-",
- "selling_price_list": "_Test Price List",
- "territory": "_Test Territory",
+ "selling_price_list": args.selling_price_list or "_Test Price List",
+ "territory": args.territory or "_Test Territory",
"customer_group": frappe.db.get_value('Customer Group', {'is_group': 0}, 'name'),
- "warehouse": "_Test Warehouse - _TC",
- "write_off_account": "_Test Write Off - _TC",
- "write_off_cost_center": "_Test Write Off Cost Center - _TC"
+ "warehouse": args.warehouse or "_Test Warehouse - _TC",
+ "write_off_account": args.write_off_account or "_Test Write Off - _TC",
+ "write_off_cost_center": args.write_off_cost_center or "_Test Write Off Cost Center - _TC"
})
- if not frappe.db.exists("POS Profile", "_Test POS Profile"):
+ if not frappe.db.exists("POS Profile", args.name or "_Test POS Profile"):
pos_profile.insert()
return pos_profile
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index ad3640c..f5dd6e7 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -420,7 +420,7 @@
if pos:
self.allow_print_before_pay = pos.allow_print_before_pay
-
+
if not for_validate:
self.tax_category = pos.get("tax_category")
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index a2a47b3..e48e6c9 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -705,6 +705,64 @@
self.pos_gl_entry(si, pos, 50)
+ def test_pos_returns_without_repayment(self):
+ pos_profile = make_pos_profile()
+
+ pos = create_sales_invoice(qty = 10, do_not_save=True)
+ pos.is_pos = 1
+ pos.pos_profile = pos_profile.name
+
+ pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 500})
+ pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 500})
+ pos.insert()
+ pos.submit()
+
+ pos_return = create_sales_invoice(is_return=1,
+ return_against=pos.name, qty=-5, do_not_save=True)
+
+ pos_return.is_pos = 1
+ pos_return.pos_profile = pos_profile.name
+
+ pos_return.insert()
+ pos_return.submit()
+
+ self.assertFalse(pos_return.is_pos)
+ self.assertFalse(pos_return.get('payments'))
+
+ def test_pos_returns_with_repayment(self):
+ pos_profile = make_pos_profile()
+
+ pos_profile.append('payments', {
+ 'default': 1,
+ 'mode_of_payment': 'Cash',
+ 'amount': 0.0
+ })
+
+ pos_profile.save()
+
+ pos = create_sales_invoice(qty = 10, do_not_save=True)
+
+ pos.is_pos = 1
+ pos.pos_profile = pos_profile.name
+
+ pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 500})
+ pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 500})
+ pos.insert()
+ pos.submit()
+
+ pos_return = create_sales_invoice(is_return=1,
+ return_against=pos.name, qty=-5, do_not_save=True)
+
+ pos_return.is_pos = 1
+ pos_return.pos_profile = pos_profile.name
+ pos_return.insert()
+ pos_return.submit()
+
+ self.assertEqual(pos_return.get('payments')[0].amount, -500)
+ pos_profile.payments = []
+ pos_profile.save()
+
+
def test_pos_change_amount(self):
make_pos_profile()
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index b52a07d..95e661a 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -514,7 +514,7 @@
if self.doc.doctype == "Sales Invoice":
self.calculate_paid_amount()
- if self.doc.is_return and self.doc.return_against: return
+ if self.doc.is_return and self.doc.return_against and not self.doc.get('is_pos'): return
self.doc.round_floats_in(self.doc, ["grand_total", "total_advance", "write_off_amount"])
self._set_in_company_currency(self.doc, ['write_off_amount'])
@@ -532,7 +532,7 @@
self.doc.round_floats_in(self.doc, ["paid_amount"])
change_amount = 0
- if self.doc.doctype == "Sales Invoice":
+ if self.doc.doctype == "Sales Invoice" and not self.doc.get('is_return'):
self.calculate_write_off_amount()
self.calculate_change_amount()
change_amount = self.doc.change_amount \
@@ -544,6 +544,9 @@
self.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) + flt(change_amount),
self.doc.precision("outstanding_amount"))
+ if self.doc.doctype == 'Sales Invoice' and self.doc.get('is_pos') and self.doc.get('is_return'):
+ self.update_paid_amount_for_return(total_amount_to_pay)
+
def calculate_paid_amount(self):
paid_amount = base_paid_amount = 0.0
@@ -614,6 +617,27 @@
def set_item_wise_tax_breakup(self):
self.doc.other_charges_calculation = get_itemised_tax_breakup_html(self.doc)
+ def update_paid_amount_for_return(self, total_amount_to_pay):
+ default_mode_of_payment = frappe.db.get_value('Sales Invoice Payment',
+ {'parent': self.doc.pos_profile, 'default': 1},
+ ['mode_of_payment', 'type', 'account'], as_dict=1)
+
+ self.doc.payments = []
+
+ if default_mode_of_payment:
+ self.doc.append('payments', {
+ 'mode_of_payment': default_mode_of_payment.mode_of_payment,
+ 'type': default_mode_of_payment.type,
+ 'account': default_mode_of_payment.account,
+ 'amount': total_amount_to_pay
+ })
+ else:
+ self.doc.is_pos = 0
+ self.doc.pos_profile = ''
+
+ self.calculate_paid_amount()
+
+
def get_itemised_tax_breakup_html(doc):
if not doc.taxes:
return
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index a51c2f0..9a5b750 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -39,6 +39,11 @@
this.calculate_total_advance(update_paid_amount);
}
+ if (this.frm.doc.doctype == "Sales Invoice" && this.frm.doc.is_pos &&
+ this.frm.doc.is_return) {
+ this.update_paid_amount_for_return();
+ }
+
// Sales person's commission
if(in_list(["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"], this.frm.doc.doctype)) {
this.calculate_commission();
@@ -635,23 +640,58 @@
}
},
- set_default_payment: function(total_amount_to_pay, update_paid_amount){
+ update_paid_amount_for_return: function() {
+ var grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total;
+
+ if(this.frm.doc.party_account_currency == this.frm.doc.currency) {
+ var total_amount_to_pay = flt((grand_total - this.frm.doc.total_advance
+ - this.frm.doc.write_off_amount), precision("grand_total"));
+ } else {
+ var total_amount_to_pay = flt(
+ (flt(grand_total*this.frm.doc.conversion_rate, precision("grand_total"))
+ - this.frm.doc.total_advance - this.frm.doc.base_write_off_amount),
+ precision("base_grand_total")
+ );
+ }
+
+ frappe.db.get_value('Sales Invoice Payment', {'parent': this.frm.doc.pos_profile, 'default': 1},
+ ['mode_of_payment', 'account', 'type'], (value) => {
+ if (this.frm.is_dirty()) {
+ frappe.model.clear_table(this.frm.doc, 'payments');
+ if (value) {
+ let row = frappe.model.add_child(this.frm.doc, 'Sales Invoice Payment', 'payments');
+ row.mode_of_payment = value.mode_of_payment;
+ row.type = value.type;
+ row.account = value.account;
+ row.default = 1;
+ row.amount = total_amount_to_pay;
+ } else {
+ this.frm.set_value('is_pos', 1);
+ }
+ this.frm.refresh_fields();
+ }
+ }, 'Sales Invoice');
+
+ this.calculate_paid_amount();
+ },
+
+ set_default_payment: function(total_amount_to_pay, update_paid_amount) {
var me = this;
var payment_status = true;
- if(this.frm.doc.is_pos && (update_paid_amount===undefined || update_paid_amount)){
- $.each(this.frm.doc['payments'] || [], function(index, data){
+ if(this.frm.doc.is_pos && (update_paid_amount===undefined || update_paid_amount)) {
+ $.each(this.frm.doc['payments'] || [], function(index, data) {
if(data.default && payment_status && total_amount_to_pay > 0) {
data.base_amount = flt(total_amount_to_pay, precision("base_amount"));
data.amount = flt(total_amount_to_pay / me.frm.doc.conversion_rate, precision("amount"));
payment_status = false;
- }else if(me.frm.doc.paid_amount){
+ } else if(me.frm.doc.paid_amount) {
data.amount = 0.0;
}
});
}
},
- calculate_paid_amount: function(){
+ calculate_paid_amount: function() {
var me = this;
var paid_amount = 0.0;
var base_paid_amount = 0.0;