mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-17 08:28:44 +00:00
fix(selling): don't email cancelled proformas or copy their PDF
Address review findings: - send_proforma_email rejects non-issued proformas, and the tab suppresses the action for cancelled rows, so a voided document can't be sent to a customer - mark proforma_pdf as no_copy and disable amendment (a proforma is created only from a Sales Order), so a copied proforma can't carry the original's PDF and number
This commit is contained in:
@@ -301,7 +301,13 @@ Object.assign(erpnext.proforma, {
|
||||
{
|
||||
icon: "mail",
|
||||
label: __("Send Email"),
|
||||
action: (row, refresh) => this.send_email(frm, row.name, refresh),
|
||||
action: (row, refresh) => {
|
||||
if (row.status === "Cancelled") {
|
||||
frappe.msgprint(__("A cancelled Proforma Invoice cannot be emailed."));
|
||||
return;
|
||||
}
|
||||
this.send_email(frm, row.name, refresh);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -187,6 +187,7 @@
|
||||
"fieldname": "proforma_pdf",
|
||||
"fieldtype": "Attach",
|
||||
"label": "Proforma PDF",
|
||||
"no_copy": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
@@ -250,7 +251,6 @@
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
@@ -264,7 +264,6 @@
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
|
||||
@@ -212,6 +212,8 @@ def _proforma_line(so_item, based_on: str, row: dict) -> dict | None:
|
||||
@frappe.whitelist()
|
||||
def send_proforma_email(proforma_name: str, recipients: str) -> None:
|
||||
proforma = frappe.get_doc("Proforma Invoice", proforma_name)
|
||||
if proforma.docstatus != 1:
|
||||
frappe.throw(_("Only an issued Proforma Invoice can be emailed."))
|
||||
if not proforma.proforma_pdf:
|
||||
frappe.throw(_("This Proforma Invoice has no PDF to send."))
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ from frappe.utils import flt
|
||||
from erpnext.selling.doctype.proforma_invoice.proforma_invoice import (
|
||||
get_sales_order_items,
|
||||
make_proforma_invoice,
|
||||
send_proforma_email,
|
||||
)
|
||||
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
|
||||
from erpnext.tests.utils import ERPNextTestSuite
|
||||
@@ -144,6 +145,13 @@ class TestProformaInvoice(ERPNextTestSuite):
|
||||
[(sales_order.items[0].name, 4)],
|
||||
)
|
||||
|
||||
def test_cannot_email_cancelled_proforma(self):
|
||||
sales_order = make_sales_order(qty=10)
|
||||
proforma = self.create_proforma(sales_order, [(sales_order.items[0].name, 4)])
|
||||
proforma.cancel()
|
||||
|
||||
self.assertRaises(frappe.ValidationError, send_proforma_email, proforma.name, "customer@example.com")
|
||||
|
||||
def test_requires_submitted_sales_order(self):
|
||||
"""The server rejects a proforma against a draft Sales Order (the button is JS-gated only)."""
|
||||
sales_order = make_sales_order(qty=10, do_not_submit=True)
|
||||
|
||||
Reference in New Issue
Block a user