From 10bb1c31a22794d781f2c76157c7588119ad3f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CKhushi?= <“khushirawat.sophia@gamil.com”> Date: Wed, 13 Mar 2024 17:47:40 +0530 Subject: [PATCH 1/3] feat: added coupon code functionality onsales invoice --- .../accounts/doctype/pricing_rule/utils.py | 6 +-- .../doctype/sales_invoice/sales_invoice.json | 9 +++- .../doctype/sales_invoice/sales_invoice.py | 46 +++++++------------ 3 files changed, 27 insertions(+), 34 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index 17293adb95e..d4f634a99d1 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -736,14 +736,14 @@ def get_pricing_rule_items(pr_doc, other_items=False) -> list: def validate_coupon_code(coupon_name): coupon = frappe.get_doc("Coupon Code", coupon_name) - + print(coupon.valid_upto < getdate(today())) if coupon.valid_from: if coupon.valid_from > getdate(today()): frappe.throw(_("Sorry, this coupon code's validity has not started")) - elif coupon.valid_upto: + if coupon.valid_upto: if coupon.valid_upto < getdate(today()): frappe.throw(_("Sorry, this coupon code's validity has expired")) - elif coupon.used >= coupon.maximum_use: + if coupon.used >= coupon.maximum_use: frappe.throw(_("Sorry, this coupon code is no longer valid")) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 5e2187e91fe..51966a4ef28 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -89,6 +89,7 @@ "section_break_49", "apply_discount_on", "base_discount_amount", + "coupon_code", "is_cash_or_non_trade_discount", "additional_discount_account", "column_break_51", @@ -2170,6 +2171,12 @@ "fieldtype": "Check", "label": "Don't Create Loyalty Points", "no_copy": 1 + }, + { + "fieldname": "coupon_code", + "fieldtype": "Link", + "label": "Coupon Code", + "options": "Coupon Code" } ], "icon": "fa fa-file-text", @@ -2182,7 +2189,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2024-01-02 17:25:46.027523", + "modified": "2024-03-13 16:42:18.153555", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index abc0694a63c..6990310b59b 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -40,6 +40,7 @@ from erpnext.projects.doctype.timesheet.timesheet import get_projectwise_timeshe from erpnext.setup.doctype.company.company import update_company_current_month_sales from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so from erpnext.stock.doctype.serial_no.serial_no import get_delivery_note_serial_no, get_serial_nos +from erpnext.accounts.doctype.pricing_rule.utils import validate_coupon_code, update_coupon_code_count form_grid_templates = {"items": "templates/form_grid/item_grid.html"} @@ -51,25 +52,16 @@ class SalesInvoice(SellingController): from typing import TYPE_CHECKING if TYPE_CHECKING: - from frappe.types import DF - from erpnext.accounts.doctype.payment_schedule.payment_schedule import PaymentSchedule from erpnext.accounts.doctype.pricing_rule_detail.pricing_rule_detail import PricingRuleDetail - from erpnext.accounts.doctype.sales_invoice_advance.sales_invoice_advance import ( - SalesInvoiceAdvance, - ) + from erpnext.accounts.doctype.sales_invoice_advance.sales_invoice_advance import SalesInvoiceAdvance from erpnext.accounts.doctype.sales_invoice_item.sales_invoice_item import SalesInvoiceItem - from erpnext.accounts.doctype.sales_invoice_payment.sales_invoice_payment import ( - SalesInvoicePayment, - ) - from erpnext.accounts.doctype.sales_invoice_timesheet.sales_invoice_timesheet import ( - SalesInvoiceTimesheet, - ) - from erpnext.accounts.doctype.sales_taxes_and_charges.sales_taxes_and_charges import ( - SalesTaxesandCharges, - ) + from erpnext.accounts.doctype.sales_invoice_payment.sales_invoice_payment import SalesInvoicePayment + from erpnext.accounts.doctype.sales_invoice_timesheet.sales_invoice_timesheet import SalesInvoiceTimesheet + from erpnext.accounts.doctype.sales_taxes_and_charges.sales_taxes_and_charges import SalesTaxesandCharges from erpnext.selling.doctype.sales_team.sales_team import SalesTeam from erpnext.stock.doctype.packed_item.packed_item import PackedItem + from frappe.types import DF account_for_change_amount: DF.Link | None additional_discount_account: DF.Link | None @@ -107,6 +99,7 @@ class SalesInvoice(SellingController): contact_person: DF.Link | None conversion_rate: DF.Float cost_center: DF.Link | None + coupon_code: DF.Link | None currency: DF.Link customer: DF.Link | None customer_address: DF.Link | None @@ -183,22 +176,7 @@ class SalesInvoice(SellingController): shipping_address_name: DF.Link | None shipping_rule: DF.Link | None source: DF.Link | None - status: DF.Literal[ - "", - "Draft", - "Return", - "Credit Note Issued", - "Submitted", - "Paid", - "Partly Paid", - "Unpaid", - "Unpaid and Discounted", - "Partly Paid and Discounted", - "Overdue and Discounted", - "Overdue", - "Cancelled", - "Internal Transfer", - ] + status: DF.Literal["", "Draft", "Return", "Credit Note Issued", "Submitted", "Paid", "Partly Paid", "Unpaid", "Unpaid and Discounted", "Partly Paid and Discounted", "Overdue and Discounted", "Overdue", "Cancelled", "Internal Transfer"] subscription: DF.Link | None tax_category: DF.Link | None tax_id: DF.Data | None @@ -293,6 +271,8 @@ class SalesInvoice(SellingController): validate_inter_company_party( self.doctype, self.customer, self.company, self.inter_company_invoice_reference ) + if self.coupon_code: + validate_coupon_code(self.coupon_code) if cint(self.is_pos): self.validate_pos() @@ -473,6 +453,9 @@ class SalesInvoice(SellingController): self.update_project() update_linked_doc(self.doctype, self.name, self.inter_company_invoice_reference) + if self.coupon_code: + update_coupon_code_count(self.coupon_code, "used") + # create the loyalty point ledger entry if the customer is enrolled in any loyalty program if ( not self.is_return @@ -563,6 +546,9 @@ class SalesInvoice(SellingController): self.db_set("status", "Cancelled") self.db_set("repost_required", 0) + if self.coupon_code: + update_coupon_code_count(self.coupon_code, "cancelled") + if ( frappe.db.get_single_value("Selling Settings", "sales_update_frequency") == "Each Transaction" ): From a0247d11bda083dc25ec64ab35cc27b6bfefd4d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CKhushi?= <“khushirawat.sophia@gamil.com”> Date: Thu, 14 Mar 2024 12:04:09 +0530 Subject: [PATCH 2/3] feat: added coupon code functionality onsales invoice --- erpnext/accounts/doctype/pricing_rule/utils.py | 4 ++-- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index d4f634a99d1..8ae2eb704c6 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -740,10 +740,10 @@ def validate_coupon_code(coupon_name): if coupon.valid_from: if coupon.valid_from > getdate(today()): frappe.throw(_("Sorry, this coupon code's validity has not started")) - if coupon.valid_upto: + elif coupon.valid_upto: if coupon.valid_upto < getdate(today()): frappe.throw(_("Sorry, this coupon code's validity has expired")) - if coupon.used >= coupon.maximum_use: + elif coupon.used >= coupon.maximum_use: frappe.throw(_("Sorry, this coupon code is no longer valid")) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 6990310b59b..872327f12bb 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -271,6 +271,8 @@ class SalesInvoice(SellingController): validate_inter_company_party( self.doctype, self.customer, self.company, self.inter_company_invoice_reference ) + + # Validating coupon code if self.coupon_code: validate_coupon_code(self.coupon_code) From 11616bec26c045985db79e1cf407b1fa57686234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CKhushi?= <“khushirawat.sophia@gamil.com”> Date: Mon, 18 Mar 2024 11:18:14 +0530 Subject: [PATCH 3/3] style: removed print statement --- erpnext/accounts/doctype/pricing_rule/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index 8ae2eb704c6..73c5d59be25 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -736,7 +736,6 @@ def get_pricing_rule_items(pr_doc, other_items=False) -> list: def validate_coupon_code(coupon_name): coupon = frappe.get_doc("Coupon Code", coupon_name) - print(coupon.valid_upto < getdate(today())) if coupon.valid_from: if coupon.valid_from > getdate(today()): frappe.throw(_("Sorry, this coupon code's validity has not started"))