mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-06 21:59:13 +00:00
feat: partly paid pos invoices (#48246)
* fix: partial payment in pos * fix: show alerts for update failure * fix: partial payment validation * fix: remove setting clearance date * fix: partly paid invoices in pos * fix: throw error if user tries to make payment for consolidated invoice * fix: include unpaid invoices in partly paid invoice filter * refactor: function rename * feat: button to open form view for partly paid invoices in pos order summary * fix: payment menu item visible for unpaid invoices * refactor: update_payments function * fix: set outstanding amount for pos invoice * test: partly paid pos invoices * test: removed frappe.db.commit * refactor: using before_submit to set outstanding amount
This commit is contained in:
@@ -477,22 +477,28 @@ def get_invoice_filters(doctype, status, name=None, customer=None):
|
||||
|
||||
if doctype == "POS Invoice":
|
||||
filters["status"] = status
|
||||
if status == "Partly Paid":
|
||||
filters["status"] = ["in", ["Partly Paid", "Overdue", "Unpaid"]]
|
||||
return filters
|
||||
|
||||
if doctype == "Sales Invoice":
|
||||
filters["is_created_using_pos"] = 1
|
||||
filters["is_consolidated"] = 0
|
||||
|
||||
if status == "Draft":
|
||||
filters["docstatus"] = 0
|
||||
if status == "Consolidated":
|
||||
filters["pos_closing_entry"] = ["is", "set"]
|
||||
else:
|
||||
filters["docstatus"] = 1
|
||||
if status == "Paid":
|
||||
filters["is_return"] = 0
|
||||
if status == "Return":
|
||||
filters["is_return"] = 1
|
||||
|
||||
filters["pos_closing_entry"] = ["is", "set"] if status == "Consolidated" else ["is", "not set"]
|
||||
filters["pos_closing_entry"] = ["is", "not set"]
|
||||
if status == "Draft":
|
||||
filters["docstatus"] = 0
|
||||
elif status == "Partly Paid":
|
||||
filters["status"] = ["in", ["Partly Paid", "Overdue", "Unpaid"]]
|
||||
else:
|
||||
filters["docstatus"] = 1
|
||||
if status == "Paid":
|
||||
filters["is_return"] = 0
|
||||
if status == "Return":
|
||||
filters["is_return"] = 1
|
||||
|
||||
return filters
|
||||
|
||||
|
||||
@@ -561,6 +561,13 @@ erpnext.PointOfSale.Controller = class {
|
||||
() => frappe.dom.unfreeze(),
|
||||
]);
|
||||
},
|
||||
open_in_form_view: (doctype, name) => {
|
||||
frappe.run_serially([
|
||||
() => frappe.dom.freeze(),
|
||||
() => frappe.set_route("Form", doctype, name),
|
||||
() => frappe.dom.unfreeze(),
|
||||
]);
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1042,6 +1042,7 @@ erpnext.PointOfSale.ItemCart = class {
|
||||
"Credit Note Issued": "gray",
|
||||
"Partly Paid": "yellow",
|
||||
Overdue: "yellow",
|
||||
Unpaid: "red",
|
||||
};
|
||||
|
||||
transaction_container.append(
|
||||
|
||||
@@ -66,7 +66,7 @@ erpnext.PointOfSale.PastOrderList = class {
|
||||
df: {
|
||||
label: __("Invoice Status"),
|
||||
fieldtype: "Select",
|
||||
options: `Draft\nPaid\nConsolidated\nReturn`,
|
||||
options: ["Draft", "Paid", "Consolidated", "Return", "Partly Paid"].join("\n"),
|
||||
placeholder: __("Filter by invoice status"),
|
||||
onchange: function () {
|
||||
if (me.$component.is(":visible")) me.refresh_list();
|
||||
|
||||
@@ -75,8 +75,9 @@ erpnext.PointOfSale.PastOrderSummary = class {
|
||||
let indicator_color = "";
|
||||
|
||||
["Paid", "Consolidated"].includes(status) && (indicator_color = "green");
|
||||
status === "Draft" && (indicator_color = "red");
|
||||
status === "Return" && (indicator_color = "grey");
|
||||
["Partly Paid", "Overdue"].includes(status) && (indicator_color = "yellow");
|
||||
["Draft", "Unpaid"].includes(status) && (indicator_color = "red");
|
||||
["Credit Note Issued", "Return"].includes(status) && (indicator_color = "grey");
|
||||
|
||||
return `<div class="left-section">
|
||||
<div class="customer-name">${doc.customer}</div>
|
||||
@@ -243,6 +244,10 @@ erpnext.PointOfSale.PastOrderSummary = class {
|
||||
this.$summary_container.on("click", ".print-btn", () => {
|
||||
this.print_receipt();
|
||||
});
|
||||
|
||||
this.$summary_container.on("click", ".open-btn", () => {
|
||||
this.events.open_in_form_view(this.doc.doctype, this.doc.name);
|
||||
});
|
||||
}
|
||||
|
||||
print_receipt() {
|
||||
@@ -361,7 +366,14 @@ erpnext.PointOfSale.PastOrderSummary = class {
|
||||
return [
|
||||
{ condition: this.doc.docstatus === 0, visible_btns: ["Edit Order", "Delete Order"] },
|
||||
{
|
||||
condition: !this.doc.is_return && this.doc.docstatus === 1,
|
||||
condition: ["Partly Paid", "Overdue", "Unpaid"].includes(this.doc.status),
|
||||
visible_btns: ["Print Receipt", "Email Receipt", "Open in Form View"],
|
||||
},
|
||||
{
|
||||
condition:
|
||||
!this.doc.is_return &&
|
||||
this.doc.docstatus === 1 &&
|
||||
!["Partly Paid", "Overdue", "Unpaid"].includes(this.doc.status),
|
||||
visible_btns: ["Print Receipt", "Email Receipt", "Return"],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ erpnext.PointOfSale.Payment = class {
|
||||
this.events = events;
|
||||
this.set_gt_to_default_mop = settings.set_grand_total_to_default_mop;
|
||||
this.invoice_fields = settings.invoice_fields;
|
||||
this.allow_partial_payment = settings.allow_partial_payment;
|
||||
|
||||
this.init_component();
|
||||
}
|
||||
@@ -224,7 +225,12 @@ erpnext.PointOfSale.Payment = class {
|
||||
const paid_amount = doc.paid_amount;
|
||||
const items = doc.items;
|
||||
|
||||
if (!items.length || (paid_amount == 0 && doc.additional_discount_percentage != 100)) {
|
||||
if (
|
||||
!items.length ||
|
||||
(paid_amount == 0 &&
|
||||
doc.additional_discount_percentage != 100 &&
|
||||
this.allow_partial_payment === 0)
|
||||
) {
|
||||
const message = items.length
|
||||
? __("You cannot submit the order without payment.")
|
||||
: __("You cannot submit empty order.");
|
||||
|
||||
Reference in New Issue
Block a user