diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 45bb15acd2db..33e931c2095a 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -5,6 +5,7 @@ "creation": "2013-05-21 16:16:39", "doctype": "DocType", "document_type": "Document", + "email_append_to": 1, "engine": "InnoDB", "field_order": [ "title", @@ -192,6 +193,7 @@ "is_internal_supplier", "represents_company", "supplier_group", + "sender", "column_break_147", "inter_company_invoice_reference", "is_old_subcontracting_flow", @@ -1625,13 +1627,19 @@ "fieldname": "update_outstanding_for_self", "fieldtype": "Check", "label": "Update Outstanding for Self" + }, + { + "fieldname": "sender", + "fieldtype": "Data", + "label": "Sender", + "options": "Email" } ], "icon": "fa fa-file-text", "idx": 204, "is_submittable": 1, "links": [], - "modified": "2024-07-25 19:42:36.931278", + "modified": "2024-09-18 12:24:44.826539", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", @@ -1687,6 +1695,7 @@ } ], "search_fields": "posting_date, supplier, bill_no, base_grand_total, outstanding_amount", + "sender_field": "sender", "show_name_in_global_search": 1, "sort_field": "creation", "sort_order": "DESC", diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 4b767be42e11..46350105a362 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -165,6 +165,7 @@ class PurchaseInvoice(BuyingController): rounding_adjustment: DF.Currency scan_barcode: DF.Data | None select_print_heading: DF.Link | None + sender: DF.Data | None set_from_warehouse: DF.Link | None set_posting_time: DF.Check set_warehouse: DF.Link | None diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index ccc14353c6b5..2fdb3c201c4b 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -2025,6 +2025,16 @@ def test_repost_accounting_entries(self): ] check_gl_entries(self, pi.name, expected_gle, nowdate()) + def test_create_purchase_invoice_without_mandatory(self): + pi = frappe.new_doc("Purchase Invoice") + pi.flags.ignore_mandatory = True + pi.insert(ignore_permissions=True) + + self.assertTrue(pi.name) + self.assertEqual(pi.docstatus, 0) + + pi.delete() + @change_settings("Buying Settings", {"supplier_group": None}) def test_purchase_invoice_without_supplier_group(self): # Create a Supplier diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 4aa1d236fa43..b29a8bae4a27 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -148,14 +148,16 @@ def remove_bundle_for_non_stock_invoices(self): def ensure_supplier_is_not_blocked(self): is_supplier_payment = self.doctype == "Payment Entry" and self.party_type == "Supplier" is_buying_invoice = self.doctype in ["Purchase Invoice", "Purchase Order"] + supplier_name = self.supplier if is_buying_invoice else self.party if is_supplier_payment else None supplier = None - supplier_name = None - if is_buying_invoice or is_supplier_payment: - supplier_name = self.supplier if is_buying_invoice else self.party - supplier = frappe.get_doc("Supplier", supplier_name) + if supplier_name: + supplier = frappe.get_doc( + "Supplier", + supplier_name, + ) - if supplier and supplier_name and supplier.on_hold: + if supplier and supplier.on_hold: if (is_buying_invoice and supplier.hold_type in ["All", "Invoices"]) or ( is_supplier_payment and supplier.hold_type in ["All", "Payments"] ): @@ -2177,8 +2179,8 @@ def set_payment_schedule(self): date = self.get("due_date") due_date = date or posting_date - base_grand_total = self.get("base_rounded_total") or self.base_grand_total - grand_total = self.get("rounded_total") or self.grand_total + base_grand_total = flt(self.get("base_rounded_total") or self.base_grand_total) + grand_total = flt(self.get("rounded_total") or self.grand_total) automatically_fetch_payment_terms = 0 if self.doctype in ("Sales Invoice", "Purchase Invoice"): @@ -2252,6 +2254,8 @@ def set_payment_schedule(self): self.ignore_default_payment_terms_template = 1 def get_order_details(self): + if not self.get("items"): + return None, None, None if self.doctype == "Sales Invoice": po_or_so = self.get("items")[0].get("sales_order") po_or_so_doctype = "Sales Order" @@ -2362,8 +2366,8 @@ def validate_payment_schedule_amount(self): total += flt(d.payment_amount, d.precision("payment_amount")) base_total += flt(d.base_payment_amount, d.precision("base_payment_amount")) - base_grand_total = self.get("base_rounded_total") or self.base_grand_total - grand_total = self.get("rounded_total") or self.grand_total + base_grand_total = flt(self.get("base_rounded_total") or self.base_grand_total) + grand_total = flt(self.get("rounded_total") or self.grand_total) if self.doctype in ("Sales Invoice", "Purchase Invoice"): base_grand_total = base_grand_total - flt(self.base_write_off_amount) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 9b095df2d0c0..ac2d4da7c8c0 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -251,16 +251,16 @@ def set_total_in_words(self): if self.meta.get_field("base_in_words"): if self.meta.get_field("base_rounded_total") and not self.is_rounded_total_disabled(): - amount = abs(self.base_rounded_total) + amount = abs(flt(self.base_rounded_total)) else: - amount = abs(self.base_grand_total) + amount = abs(flt(self.base_grand_total)) self.base_in_words = money_in_words(amount, self.company_currency) if self.meta.get_field("in_words"): if self.meta.get_field("rounded_total") and not self.is_rounded_total_disabled(): - amount = abs(self.rounded_total) + amount = abs(flt(self.rounded_total)) else: - amount = abs(self.grand_total) + amount = abs(flt(self.grand_total)) self.in_words = money_in_words(amount, self.currency)