From f42a8e4e039174f220003e07da1b7225cfa4315a Mon Sep 17 00:00:00 2001 From: Maharshi Patel Date: Wed, 28 Sep 2022 12:54:00 +0530 Subject: [PATCH 01/16] fix: fetch swift_number in payment_request There isn't direct link between payment_request and bank so swift_number wasn't fetched using Fetch form. I fixed it by fetching swift_number on_change of bank_account. --- .../accounts/doctype/payment_request/payment_request.js | 7 +++++++ .../accounts/doctype/payment_request/payment_request.json | 3 +-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.js b/erpnext/accounts/doctype/payment_request/payment_request.js index 901ef1987b4..da66edc9feb 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.js +++ b/erpnext/accounts/doctype/payment_request/payment_request.js @@ -9,6 +9,13 @@ frappe.ui.form.on("Payment Request", { query: "erpnext.setup.doctype.party_type.party_type.get_party_type", }; }); + }, + "bank_account": function(frm) { + frappe.db.get_value('Bank', frm.doc.bank, ['swift_number']) + .then(r => { + let values = r.message; + frm.set_value('swift_number', values.swift_number) + }) } }) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json index 2ee356aaf40..33edb63fbf3 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.json +++ b/erpnext/accounts/doctype/payment_request/payment_request.json @@ -219,7 +219,6 @@ "label": "Branch Code" }, { - "fetch_from": "bank.swift_number", "fieldname": "swift_number", "fieldtype": "Read Only", "label": "SWIFT Number" @@ -366,7 +365,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2020-09-18 12:24:14.178853", + "modified": "2022-09-28 12:39:30.160837", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Request", From 9245d3b5cdd9ec7d2e4c63afd5797c6882e8ecfb Mon Sep 17 00:00:00 2001 From: Maharshi Patel Date: Fri, 30 Sep 2022 15:35:12 +0530 Subject: [PATCH 02/16] Revert "fix: fetch swift_number in payment_request" This reverts commit f42a8e4e039174f220003e07da1b7225cfa4315a. --- .../accounts/doctype/payment_request/payment_request.js | 7 ------- .../accounts/doctype/payment_request/payment_request.json | 3 ++- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.js b/erpnext/accounts/doctype/payment_request/payment_request.js index da66edc9feb..901ef1987b4 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.js +++ b/erpnext/accounts/doctype/payment_request/payment_request.js @@ -9,13 +9,6 @@ frappe.ui.form.on("Payment Request", { query: "erpnext.setup.doctype.party_type.party_type.get_party_type", }; }); - }, - "bank_account": function(frm) { - frappe.db.get_value('Bank', frm.doc.bank, ['swift_number']) - .then(r => { - let values = r.message; - frm.set_value('swift_number', values.swift_number) - }) } }) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json index 33edb63fbf3..2ee356aaf40 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.json +++ b/erpnext/accounts/doctype/payment_request/payment_request.json @@ -219,6 +219,7 @@ "label": "Branch Code" }, { + "fetch_from": "bank.swift_number", "fieldname": "swift_number", "fieldtype": "Read Only", "label": "SWIFT Number" @@ -365,7 +366,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-09-28 12:39:30.160837", + "modified": "2020-09-18 12:24:14.178853", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Request", From dc8d49260c626e8cee0b22a595b90d078509d1a5 Mon Sep 17 00:00:00 2001 From: Maharshi Patel Date: Fri, 30 Sep 2022 16:22:57 +0530 Subject: [PATCH 03/16] fix: payment request make bank field Link instead of Read Only --- .../doctype/payment_request/payment_request.json | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json index 2ee356aaf40..2f3516e135a 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.json +++ b/erpnext/accounts/doctype/payment_request/payment_request.json @@ -186,8 +186,10 @@ { "fetch_from": "bank_account.bank", "fieldname": "bank", - "fieldtype": "Read Only", - "label": "Bank" + "fieldtype": "Link", + "label": "Bank", + "options": "Bank", + "read_only": 1 }, { "fetch_from": "bank_account.bank_account_no", @@ -366,10 +368,11 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2020-09-18 12:24:14.178853", + "modified": "2022-09-30 16:19:43.680025", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Request", + "naming_rule": "By \"Naming Series\" field", "owner": "Administrator", "permissions": [ { @@ -401,5 +404,6 @@ } ], "sort_field": "modified", - "sort_order": "DESC" + "sort_order": "DESC", + "states": [] } \ No newline at end of file From 0b1727cf79fd84b5a9b499695ab28dd74a2e5a3f Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 3 Oct 2022 12:06:32 +0530 Subject: [PATCH 04/16] fix: not able to return sold expired batches --- .../sales_invoice/test_sales_invoice.py | 34 ++++++++++++++++++- .../delivery_note/test_delivery_note.py | 33 +++++++++++++++++- .../stock_ledger_entry/stock_ledger_entry.py | 4 ++- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 782e08e33ba..ce44ae304b3 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -8,7 +8,7 @@ import frappe from frappe.model.dynamic_links import get_dynamic_link_map from frappe.model.naming import make_autoname from frappe.tests.utils import change_settings -from frappe.utils import add_days, flt, getdate, nowdate +from frappe.utils import add_days, flt, getdate, nowdate, today import erpnext from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account @@ -3196,6 +3196,37 @@ class TestSalesInvoice(unittest.TestCase): "Accounts Settings", "Accounts Settings", "unlink_payment_on_cancel_of_invoice", unlink_enabled ) + def test_batch_expiry_for_sales_invoice_return(self): + from erpnext.controllers.sales_and_purchase_return import make_return_doc + from erpnext.stock.doctype.item.test_item import make_item + + item = make_item( + "_Test Batch Item For Return Check", + { + "is_purchase_item": 1, + "is_stock_item": 1, + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "TBIRC.#####", + }, + ) + + pr = make_purchase_receipt(qty=1, item_code=item.name) + + batch_no = pr.items[0].batch_no + si = create_sales_invoice(qty=1, item_code=item.name, update_stock=1, batch_no=batch_no) + + si.load_from_db() + batch_no = si.items[0].batch_no + self.assertTrue(batch_no) + + frappe.db.set_value("Batch", batch_no, "expiry_date", add_days(today(), -1)) + + return_si = make_return_doc(si.doctype, si.name) + return_si.save().submit() + + self.assertTrue(return_si.docstatus == 1) + def get_sales_invoice_for_e_invoice(): si = make_sales_invoice_for_ewaybill() @@ -3289,6 +3320,7 @@ def create_sales_invoice(**args): "serial_no": args.serial_no, "conversion_factor": 1, "incoming_rate": args.incoming_rate or 0, + "batch_no": args.batch_no or None, }, ) diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 6bcab737b37..1b9f16814c5 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -6,7 +6,7 @@ import json import frappe from frappe.tests.utils import FrappeTestCase -from frappe.utils import cstr, flt, nowdate, nowtime +from frappe.utils import add_days, cstr, flt, nowdate, nowtime, today from erpnext.accounts.doctype.account.test_account import get_inventory_account from erpnext.accounts.utils import get_balance_on @@ -1091,6 +1091,36 @@ class TestDeliveryNote(FrappeTestCase): frappe.db.exists("GL Entry", {"voucher_no": dn.name, "voucher_type": dn.doctype}) ) + def test_batch_expiry_for_delivery_note(self): + from erpnext.controllers.sales_and_purchase_return import make_return_doc + from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt + + item = make_item( + "_Test Batch Item For Return Check", + { + "is_purchase_item": 1, + "is_stock_item": 1, + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "TBIRC.#####", + }, + ) + + pi = make_purchase_receipt(qty=1, item_code=item.name) + + dn = create_delivery_note(qty=1, item_code=item.name, batch_no=pi.items[0].batch_no) + + dn.load_from_db() + batch_no = dn.items[0].batch_no + self.assertTrue(batch_no) + + frappe.db.set_value("Batch", batch_no, "expiry_date", add_days(today(), -1)) + + return_dn = make_return_doc(dn.doctype, dn.name) + return_dn.save().submit() + + self.assertTrue(return_dn.docstatus == 1) + def create_delivery_note(**args): dn = frappe.new_doc("Delivery Note") @@ -1117,6 +1147,7 @@ def create_delivery_note(**args): "expense_account": args.expense_account or "Cost of Goods Sold - _TC", "cost_center": args.cost_center or "_Test Cost Center - _TC", "serial_no": args.serial_no, + "batch_no": args.batch_no or None, "target_warehouse": args.target_warehouse, }, ) diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py index f7f8cbe4ee0..c64370dcdf2 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -153,7 +153,9 @@ class StockLedgerEntry(Document): def validate_batch(self): if self.batch_no and self.voucher_type != "Stock Entry": - if self.voucher_type in ["Purchase Receipt", "Purchase Invoice"] and self.actual_qty < 0: + if (self.voucher_type in ["Purchase Receipt", "Purchase Invoice"] and self.actual_qty < 0) or ( + self.voucher_type in ["Delivery Note", "Sales Invoice"] and self.actual_qty > 0 + ): return expiry_date = frappe.db.get_value("Batch", self.batch_no, "expiry_date") From ba02209f1dcd0ca0c932a05da60a2e311360b688 Mon Sep 17 00:00:00 2001 From: Sagar Sharma Date: Mon, 3 Oct 2022 14:12:42 +0530 Subject: [PATCH 05/16] fix: pick list picked-qty for batch item --- erpnext/stock/doctype/pick_list/pick_list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index adddb413824..9c1c7e56796 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -183,7 +183,7 @@ class PickList(Document): frappe.throw("Row #{0}: Item Code is Mandatory".format(item.idx)) item_code = item.item_code reference = item.sales_order_item or item.material_request_item - key = (item_code, item.uom, item.warehouse, reference) + key = (item_code, item.uom, item.warehouse, item.batch_no, reference) item.idx = None item.name = None From c35adcf5a179e35df2542d4507dc165d13b6f67b Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Mon, 3 Oct 2022 19:31:20 +0530 Subject: [PATCH 06/16] feat(JE): trigger account field when fetched from template Closes #32409 --- erpnext/accounts/doctype/journal_entry/journal_entry.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js index 7af41f398ad..763e2e6992c 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.js +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js @@ -173,8 +173,8 @@ frappe.ui.form.on("Journal Entry", { var update_jv_details = function(doc, r) { $.each(r, function(i, d) { var row = frappe.model.add_child(doc, "Journal Entry Account", "accounts"); - row.account = d.account; - row.balance = d.balance; + frappe.model.set_value(row.doctype, row.name, "account", d.account) + frappe.model.set_value(row.doctype, row.name, "balance", d.balance) }); refresh_field("accounts"); } From da43a5e371dede52acd26791ffa80ba4a13fc0ef Mon Sep 17 00:00:00 2001 From: Summayya Hashmani <58825865+sumaiya2908@users.noreply.github.com> Date: Tue, 4 Oct 2022 09:57:07 +0530 Subject: [PATCH 07/16] refactor(UI): clean up portal pages (#29018) * refactor: list view for portal pages * refactor: add align center class * refactor: change footer btn class(primary) * refactor: add order style page * refactor: import order page in website * refactor: remove table elements * fix: preview image height * fix: make string translatable * refactor: change font variables * refactor: order preview bg white * refactor: center align items * fix: breadcrumb padding * refactor: make preview image rounded * refactor: add condition for image container * refactor: change alignment for mobile view * fix: make footer button secondary * refactor: clean code * refactor: code indentantion * refactor: remove space * fix: Payment section cleanup Co-authored-by: Summayya Co-authored-by: Marica Co-authored-by: Deepesh Garg --- erpnext/public/scss/order-page.scss | 115 +++++++++ erpnext/public/scss/website.scss | 33 ++- .../includes/footer/footer_extension.html | 2 +- erpnext/templates/includes/macros.html | 2 +- .../includes/order/order_macros.html | 5 +- .../templates/includes/order/order_taxes.html | 159 +++++++----- .../templates/includes/transaction_row.html | 12 +- erpnext/templates/pages/order.html | 238 +++++++++--------- 8 files changed, 372 insertions(+), 194 deletions(-) create mode 100644 erpnext/public/scss/order-page.scss diff --git a/erpnext/public/scss/order-page.scss b/erpnext/public/scss/order-page.scss new file mode 100644 index 00000000000..6f5fe5d4d7a --- /dev/null +++ b/erpnext/public/scss/order-page.scss @@ -0,0 +1,115 @@ +#page-order { + .main-column { + .page-content-wrapper { + + .breadcrumb-container { + @media screen and (min-width: 567px) { + padding-left: var(--padding-sm); + } + } + + .container.my-4 { + background-color: var(--fg-color); + + @media screen and (min-width: 567px) { + padding: 1.25rem 1.5rem; + border-radius: var(--border-radius-md); + box-shadow: var(--card-shadow); + } + } + } + } +} + +.indicator-container { + @media screen and (max-width: 567px) { + padding-bottom: 0.8rem; + } +} + +.order-items { + padding: 1.5rem 0; + border-bottom: 1px solid var(--border-color); + color: var(--gray-700); + + @media screen and (max-width: 567px) { + align-items: flex-start !important; + } + .col-2 { + @media screen and (max-width: 567px) { + flex: auto; + max-width: 28%; + } + } + + .order-item-name { + font-size: var(--text-base); + font-weight: 500; + } + + .btn:focus, + .btn:hover { + background-color: var(--control-bg); + } + + + .col-6 { + @media screen and (max-width: 567px) { + max-width: 100%; + } + + &.order-item-name { + font-size: var(--text-base); + } + } +} + +.item-grand-total { + font-size: var(--text-base); +} + +.list-item-name, +.item-total, +.order-container, +.order-qty { + font-size: var(--text-md); +} + +.d-s-n { + @media screen and (max-width: 567px) { + display: none; + } +} + +.d-l-n { + @media screen and (min-width: 567px) { + display: none; + } +} + +.border-btm { + border-bottom: 1px solid var(--border-color); +} + +.order-taxes { + display: flex; + + @media screen and (min-width: 567px) { + justify-content: flex-end; + } + + .col-4 { + padding-right: 0; + + .col-8 { + padding-left: 0; + padding-right: 0; + } + + @media screen and (max-width: 567px) { + padding-left: 0; + flex: auto; + max-width: 100%; + } + } +} \ No newline at end of file diff --git a/erpnext/public/scss/website.scss b/erpnext/public/scss/website.scss index 9ea84160342..b5e97f1c34b 100644 --- a/erpnext/public/scss/website.scss +++ b/erpnext/public/scss/website.scss @@ -1,3 +1,4 @@ +@import './order-page'; .filter-options { max-height: 300px; @@ -32,19 +33,29 @@ height: 24px; } -.website-list .result { - margin-top: 2rem; -} +.website-list { + background-color: var(--fg-color); + padding: 0 var(--padding-lg); + border-radius: var(--border-radius-md); -.result { - border-bottom: 1px solid var(--border-color); + @media screen and (max-width: 567px) { + margin-left: -2rem; + } + + &.result { + border-bottom: 1px solid var(--border-color); + } } .transaction-list-item { padding: 1rem 0; - border-top: 1px solid var(--border-color); + border-bottom: 1px solid var(--border-color); position: relative; + &:only-child, &:last-child { + border: 0; + } + a.transaction-item-link { position: absolute; top: 0; @@ -68,3 +79,13 @@ line-height: 1.3; } } + +.list-item-name, .item-total { + font-size: var(--font-size-sm); +} + +.items-preview { + @media screen and (max-width: 567px) { + margin-top: 1rem; + } +} \ No newline at end of file diff --git a/erpnext/templates/includes/footer/footer_extension.html b/erpnext/templates/includes/footer/footer_extension.html index c7f0d06dff2..0072dc280c7 100644 --- a/erpnext/templates/includes/footer/footer_extension.html +++ b/erpnext/templates/includes/footer/footer_extension.html @@ -6,7 +6,7 @@ aria-label="{{ _('Your email address...') }}" aria-describedby="footer-subscribe-button">
-
diff --git a/erpnext/templates/includes/macros.html b/erpnext/templates/includes/macros.html index f56dc3a4549..dc9ee234d9e 100644 --- a/erpnext/templates/includes/macros.html +++ b/erpnext/templates/includes/macros.html @@ -1,5 +1,5 @@ {% macro product_image_square(website_image, css_class="") %} -
-
+
{% if d.thumbnail or d.image %} {{ product_image(d.thumbnail or d.image, no_border=True) }} {% else %} @@ -18,6 +18,9 @@
{{ html2text(d.description) | truncate(140) }}
+ + {{ _("Qty ") }}({{ d.get_formatted("qty") }}) +
{% endmacro %} diff --git a/erpnext/templates/includes/order/order_taxes.html b/erpnext/templates/includes/order/order_taxes.html index b821e6253d0..0060ab39cc9 100644 --- a/erpnext/templates/includes/order/order_taxes.html +++ b/erpnext/templates/includes/order/order_taxes.html @@ -1,84 +1,111 @@ {% if doc.taxes %} - - - {{ _("Net Total") }} - - - {{ doc.get_formatted("net_total") }} - - +
+
+
+ {{ _("Net Total") }} +
+
+ {{ doc.get_formatted("net_total") }} +
+
+
{% endif %} {% for d in doc.taxes %} {% if d.base_tax_amount %} - - - {{ d.description }} - - - {{ d.get_formatted("base_tax_amount") }} - - +
+
+
+ {{ d.description }} +
+
+ {{ doc.get_formatted("net_total") }} +
+
+
{% endif %} {% endfor %} {% if doc.doctype == 'Quotation' %} {% if doc.coupon_code %} - - - {{ _("Savings") }} - - - {% set tot_quotation_discount = [] %} - {%- for item in doc.items -%} - {% if tot_quotation_discount.append((((item.price_list_rate * item.qty) - * item.discount_percentage) / 100)) %} - {% endif %} - {% endfor %} - {{ frappe.utils.fmt_money((tot_quotation_discount | sum),currency=doc.currency) }} - - +
+
+
+ {{ _("Savings") }} +
+
+ {% set tot_quotation_discount = [] %} + {%- for item in doc.items -%} + {% if tot_quotation_discount.append((((item.price_list_rate * item.qty) + * item.discount_percentage) / 100)) %} + {% endif %} + {% endfor %} + {{ frappe.utils.fmt_money((tot_quotation_discount | sum),currency=doc.currency) }}
+
+
{% endif %} {% endif %} {% if doc.doctype == 'Sales Order' %} {% if doc.coupon_code %} - - - {{ _("Applied Coupon Code") }} - - - - {%- for row in frappe.get_all(doctype="Coupon Code", - fields=["coupon_code"], filters={ "name":doc.coupon_code}) -%} - {{ row.coupon_code }} - {% endfor %} - - - - - - {{ _("Savings") }} - - - - {% set tot_SO_discount = [] %} - {%- for item in doc.items -%} - {% if tot_SO_discount.append((((item.price_list_rate * item.qty) - * item.discount_percentage) / 100)) %}{% endif %} - {% endfor %} - {{ frappe.utils.fmt_money((tot_SO_discount | sum),currency=doc.currency) }} - - - +
+
+
+ {{ _("Total Amount") }} +
+
+ + {% set total_amount = [] %} + {%- for item in doc.items -%} + {% if total_amount.append((item.price_list_rate * item.qty)) %}{% endif %} + {% endfor %} + {{ frappe.utils.fmt_money((total_amount | sum),currency=doc.currency) }} + +
+
+
+
+
+
+ {{ _("Applied Coupon Code") }} +
+
+ + {%- for row in frappe.get_all(doctype="Coupon Code", + fields=["coupon_code"], filters={ "name":doc.coupon_code}) -%} + {{ row.coupon_code }} + {% endfor %} + +
+
+
+
+
+
+ {{ _("Savings") }} +
+
+ + {% set tot_SO_discount = [] %} + {%- for item in doc.items -%} + {% if tot_SO_discount.append((((item.price_list_rate * item.qty) + * item.discount_percentage) / 100)) %}{% endif %} + {% endfor %} + {{ frappe.utils.fmt_money((tot_SO_discount | sum),currency=doc.currency) }} + +
+
+
{% endif %} {% endif %} - - - {{ _("Grand Total") }} - - - {{ doc.get_formatted("grand_total") }} - - +
+
+
+ {{ _("Grand Total") }} +
+
+ {{ doc.get_formatted("grand_total") }} +
+
+
diff --git a/erpnext/templates/includes/transaction_row.html b/erpnext/templates/includes/transaction_row.html index 3cfb8d8440c..72d498c998f 100644 --- a/erpnext/templates/includes/transaction_row.html +++ b/erpnext/templates/includes/transaction_row.html @@ -1,20 +1,22 @@
-
+
- - {{ doc.name }} + {{ doc.name }}
{{ frappe.utils.global_date_format(doc.modified) }}
-
+
+ {{doc.status}} +
+
{{ doc.items_preview }}
{% if doc.get('grand_total') %} -
+
{{ doc.get_formatted("grand_total") }}
{% endif %} diff --git a/erpnext/templates/pages/order.html b/erpnext/templates/pages/order.html index ec1d49788bd..6b354b2fab6 100644 --- a/erpnext/templates/pages/order.html +++ b/erpnext/templates/pages/order.html @@ -5,149 +5,159 @@ {% include "templates/includes/breadcrumbs.html" %} {% endblock %} -{% block title %}{{ doc.name }}{% endblock %} +{% block title %} + {{ doc.name }} +{% endblock %} {% block header %} -

{{ doc.name }}

+

{{ doc.name }}

{% endblock %} {% block header_actions %} - {% endif %} -
{% if doc.terms %}
-

{{ doc.terms }}

+
+

{{ doc.terms }}

{% endif %} {% endblock %} {% block script %} - + -{% endblock %} +{% endblock %} \ No newline at end of file From 518ab93e039d68827506c3ac92db3c09aea644e3 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 4 Oct 2022 12:35:59 +0530 Subject: [PATCH 08/16] refactor: remove duplicate entries on remarks migration patch --- ...grate_remarks_from_gl_to_payment_ledger.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py b/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py index 062d24b78bd..fd2a2a39cc6 100644 --- a/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py +++ b/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py @@ -3,6 +3,29 @@ from frappe import qb from frappe.utils import create_batch +def remove_duplicate_entries(pl_entries): + unique_vouchers = set() + for x in pl_entries: + unique_vouchers.add( + (x.company, x.account, x.party_type, x.party, x.voucher_type, x.voucher_no, x.gle_remarks) + ) + + entries = [] + for x in unique_vouchers: + entries.append( + frappe._dict( + company=x[0], + account=x[1], + party_type=x[2], + party=x[3], + voucher_type=x[4], + voucher_no=x[5], + gle_remarks=x[6], + ) + ) + return entries + + def execute(): if frappe.reload_doc("accounts", "doctype", "payment_ledger_entry"): @@ -34,6 +57,8 @@ def execute(): .run(as_dict=True) ) + pl_entries = remove_duplicate_entries(pl_entries) + if pl_entries: # split into multiple batches, update and commit for each batch batch_size = 1000 From aaabba9b1e93ab90fd2afa9fb7b404b10fe8a3a4 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 5 Oct 2022 10:58:21 +0530 Subject: [PATCH 09/16] fix: TooManyWritesError during reposting of stock --- .../doctype/repost_item_valuation/repost_item_valuation.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index c4705246b3c..d6f9bae5da2 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -128,6 +128,9 @@ def repost(doc): if not frappe.db.exists("Repost Item Valuation", doc.name): return + # This is to avoid TooManyWritesError in case of large reposts + frappe.db.MAX_WRITES_PER_TRANSACTION *= 4 + doc.set_status("In Progress") if not frappe.flags.in_test: frappe.db.commit() From 0e4017cbe51394986046818946d8f6ac39798182 Mon Sep 17 00:00:00 2001 From: HENRY Florian Date: Wed, 5 Oct 2022 14:49:44 +0200 Subject: [PATCH 10/16] chore: update fr translation (#32385) --- erpnext/translations/fr.csv | 61 +++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv index b2074618a6f..7989bf7ebce 100644 --- a/erpnext/translations/fr.csv +++ b/erpnext/translations/fr.csv @@ -785,7 +785,7 @@ Default BOM for {0} not found,Nomenclature par défaut {0} introuvable, Default BOM not found for Item {0} and Project {1},La nomenclature par défaut n'a pas été trouvée pour l'Article {0} et le Projet {1}, Default Letter Head,En-Tête de Courrier par Défaut, Default Tax Template,Modèle de Taxes par Défaut, -Default Unit of Measure for Item {0} cannot be changed directly because you have already made some transaction(s) with another UOM. You will need to create a new Item to use a different Default UOM.,L’Unité de Mesure par Défaut pour l’Article {0} ne peut pas être modifiée directement parce que vous avez déjà fait une (des) transaction (s) avec une autre unité de mesure. Vous devez créer un nouvel article pour utiliser une UDM par défaut différente., +Default Unit of Measure for Item {0} cannot be changed directly because you have already made some transaction(s) with another UOM. You will need to create a new Item to use a different Default UOM.,L’Unité de Mesure par Défaut pour l’Article {0} ne peut pas être modifiée directement parce que vous avez déjà fait une (des) transaction (s) avec une autre unité de mesure. Vous devez créer un nouvel article pour utiliser une UdM par défaut différente., Default Unit of Measure for Variant '{0}' must be same as in Template '{1}',L’Unité de mesure par défaut pour la variante '{0}' doit être la même que dans le Modèle '{1}', Default settings for buying transactions.,Paramètres par défaut pour les transactions d'achat., Default settings for selling transactions.,Paramètres par défaut pour les transactions de vente., @@ -838,7 +838,7 @@ Difference Account,Compte d’Écart, "Difference Account must be a Asset/Liability type account, since this Stock Reconciliation is an Opening Entry","Le Compte d’Écart doit être un compte de type Actif / Passif, puisque cette Réconciliation de Stock est une écriture d'à-nouveau", Difference Amount,Écart de Montant, Difference Amount must be zero,L’Écart de Montant doit être égal à zéro, -Different UOM for items will lead to incorrect (Total) Net Weight value. Make sure that Net Weight of each item is in the same UOM.,Différentes UDM pour les articles conduira à un Poids Net (Total) incorrect . Assurez-vous que le Poids Net de chaque article a la même unité de mesure ., +Different UOM for items will lead to incorrect (Total) Net Weight value. Make sure that Net Weight of each item is in the same UOM.,Différentes UdM pour les articles conduira à un Poids Net (Total) incorrect . Assurez-vous que le Poids Net de chaque article a la même unité de mesure ., Direct Expenses,Charges Directes, Direct Income,Revenu direct, Disable,Désactiver, @@ -1409,7 +1409,7 @@ Lab Test,Test de laboratoire, Lab Test Report,Rapport de test de laboratoire, Lab Test Sample,Échantillon de test de laboratoire, Lab Test Template,Modèle de test de laboratoire, -Lab Test UOM,UDM de test de laboratoire, +Lab Test UOM,UdM de test de laboratoire, Lab Tests and Vital Signs,Tests de laboratoire et signes vitaux, Lab result datetime cannot be before testing datetime,La date et l'heure du résultat de laboratoire ne peuvent pas être avant la date et l'heure du test, Lab testing datetime cannot be before collection datetime,La date et l'heure du test de laboratoire ne peuvent pas être avant la date et l'heure de collecte, @@ -2806,7 +2806,7 @@ Stock Received But Not Billed,Stock Reçus Mais Non Facturés, Stock Reports,Rapports de stock, Stock Summary,Résumé du Stock, Stock Transactions,Transactions du Stock, -Stock UOM,UDM du Stock, +Stock UOM,UdM du Stock, Stock Value,Valeur du Stock, Stock balance in Batch {0} will become negative {1} for Item {2} at Warehouse {3},Solde du stock dans le Lot {0} deviendra négatif {1} pour l'Article {2} à l'Entrepôt {3}, Stock cannot be updated against Delivery Note {0},Stock ne peut pas être mis à jour pour le Bon de Livraison {0}, @@ -3161,9 +3161,9 @@ Trial Period End Date Cannot be before Trial Period Start Date,La date de fin de Trialling,Essai, Type of Business,Type de commerce, Types of activities for Time Logs,Types d'activités pour Journaux de Temps, -UOM,UDM, -UOM Conversion factor is required in row {0},Facteur de conversion de l'UDM est obligatoire dans la ligne {0}, -UOM coversion factor required for UOM: {0} in Item: {1},Facteur de coversion UDM requis pour l'UDM : {0} dans l'Article : {1}, +UOM,UdM, +UOM Conversion factor is required in row {0},Facteur de conversion de l'UdM est obligatoire dans la ligne {0}, +UOM coversion factor required for UOM: {0} in Item: {1},Facteur de coversion UdM requis pour l'UdM : {0} dans l'Article : {1}, URL,URL, Unable to find DocType {0},Impossible de trouver le DocType {0}, Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually,Impossible de trouver le taux de change pour {0} à {1} pour la date clé {2}. Veuillez créer une entrée de taux de change manuellement, @@ -3294,7 +3294,7 @@ Wednesday,Mercredi, Week,Semaine, Weekdays,Jours de la semaine, Weekly,Hebdomadaire, -"Weight is mentioned,\nPlease mention ""Weight UOM"" too","Poids est mentionné,\nVeuillez aussi mentionner ""UDM de Poids""", +"Weight is mentioned,\nPlease mention ""Weight UOM"" too","Poids est mentionné,\nVeuillez aussi mentionner ""UdM de Poids""", Welcome email sent,Email de bienvenue envoyé, Welcome to ERPNext,Bienvenue sur ERPNext, What do you need help with?,Avec quoi avez vous besoin d'aide ?, @@ -4938,12 +4938,15 @@ Is Cumulative,Est cumulatif, Coupon Code Based,Code de coupon basé, Discount on Other Item,Remise sur un autre article, Apply Rule On Other,Appliquer la règle sur autre, -Party Information,Informations sur la fête, +Party Information,Informations sur le tier, Quantity and Amount,Quantité et montant, Min Qty,Qté Min, Max Qty,Qté Max, -Min Amt,Min Amt, -Max Amt,Max Amt, +Min Amt,Montant Min, +Max Amt,Montant Max, +"If rate is zero them item will be treated as ""Free Item""",Si le prix est à 0 alors l'article sera traité comme article gratuit +Is Recursive,Est récursif +"Discounts to be applied in sequential ranges like buy 1 get 1, buy 2 get 2, buy 3 get 3 and so on",La remise sera appliquée séquentiellement telque : acheter 1 => recupérer 1, acheter 2 => recupérer 2, acheter 3 => recupérer 3, etc... Period Settings,Paramètres de période, Margin,Marge, Margin Type,Type de Marge, @@ -5053,7 +5056,7 @@ Quantity and Rate,Quantité et Prix, Received Qty,Qté Reçue, Accepted Qty,Quantité acceptée, Rejected Qty,Qté Rejetée, -UOM Conversion Factor,Facteur de Conversion de l'UDM, +UOM Conversion Factor,Facteur de Conversion de l'UdM, Discount on Price List Rate (%),Remise sur la Liste des Prix (%), Price List Rate (Company Currency),Taux de la Liste de Prix (Devise Société), Rate (Company Currency),Prix (Devise Société), @@ -5085,7 +5088,7 @@ Purchase Receipt Detail,Détail du reçu d'achat, Item Weight Details,Détails du poids de l'article, Weight Per Unit,Poids par unité, Total Weight,Poids total, -Weight UOM,UDM de Poids, +Weight UOM,UdM de Poids, Page Break,Saut de Page, Consider Tax or Charge for,Tenir Compte de la Taxe et des Frais pour, Valuation and Total,Valorisation et Total, @@ -5153,7 +5156,7 @@ Advance amount,Montant de l'Avance, Sales Invoice Item,Article de la Facture de Vente, Customer's Item Code,Code de l'Article du Client, Brand Name,Nom de la Marque, -Qty as per Stock UOM,Qté par UDM du Stock, +Qty as per Stock UOM,Qté par UdM du Stock, Discount and Margin,Remise et Marge, Rate With Margin,Prix Avec Marge, Discount (%) on Price List Rate with Margin,Remise (%) sur le prix de la Liste de Prix avec la Marge, @@ -5501,7 +5504,7 @@ Blanket Order Rate,Prix unitaire de commande avec limites, Returned Qty,Qté Retournée, Purchase Order Item Supplied,Article Fourni depuis la Commande d'Achat, BOM Detail No,N° de Détail de la nomenclature, -Stock Uom,UDM du Stock, +Stock Uom,UdM du Stock, Raw Material Item Code,Code d’Article de Matière Première, Supplied Qty,Qté Fournie, Purchase Receipt Item Supplied,Articles Fournis du Reçus d’Achat, @@ -6149,7 +6152,7 @@ Drug Name / Description,Nom / description du médicament, Dosage,Dosage, Dosage by Time Interval,Dosage par intervalle de temps, Interval,Intervalle, -Interval UOM,UDM d'Intervalle, +Interval UOM,UdM d'Intervalle, Hour,Heure, Update Schedule,Mettre à Jour le Calendrier, Exercise,Exercice, @@ -7023,7 +7026,7 @@ Petrol,Essence, Diesel,Diesel, Natural Gas,Gaz Naturel, Electric,Électrique, -Fuel UOM,UDM Carburant, +Fuel UOM,UdM Carburant, Last Carbon Check,Dernière Vérification Carbone, Wheels,Roues, Doors,Portes, @@ -7182,7 +7185,7 @@ Item to be manufactured or repacked,Article à produire ou à réemballer, Quantity of item obtained after manufacturing / repacking from given quantities of raw materials,Quantité d'article obtenue après production / reconditionnement des quantités données de matières premières, Set rate of sub-assembly item based on BOM,Définir le prix des articles de sous-assemblage en fonction de la nomenclature, Allow Alternative Item,Autoriser un article alternatif, -Item UOM,UDM de l'Article, +Item UOM,UdM de l'Article, Conversion Rate,Taux de Conversion, Rate Of Materials Based On,Prix des Matériaux Basé sur, With Operations,Avec des Opérations, @@ -7926,7 +7929,7 @@ Territory Manager,Responsable Régional, For reference,Pour référence, Territory Targets,Objectifs Régionaux, Set Item Group-wise budgets on this Territory. You can also include seasonality by setting the Distribution.,Définir des budgets par Groupes d'Articles sur ce Territoire. Vous pouvez également inclure de la saisonnalité en définissant la Répartition., -UOM Name,Nom UDM, +UOM Name,Nom UdM, Check this to disallow fractions. (for Nos),Cochez cette case pour interdire les fractions. (Pour les numéros), Website Item Group,Groupe d'Articles du Site Web, Cross Listing of Item in multiple groups,Liste Croisée d'Articles dans plusieurs groupes, @@ -8198,10 +8201,10 @@ To Package No.,Au N° de Paquet, If more than one package of the same type (for print),Si plus d'un paquet du même type (pour l'impression), Package Weight Details,Détails du Poids du Paquet, The net weight of this package. (calculated automatically as sum of net weight of items),Le poids net de ce paquet. (Calculé automatiquement comme la somme du poids net des articles), -Net Weight UOM,UDM Poids Net, +Net Weight UOM,UdM Poids Net, Gross Weight,Poids Brut, The gross weight of the package. Usually net weight + packaging material weight. (for print),Le poids brut du colis. Habituellement poids net + poids du matériau d'emballage. (Pour l'impression), -Gross Weight UOM,UDM du Poids Brut, +Gross Weight UOM,UdM du Poids Brut, Packing Slip Item,Article Emballé, DN Detail,Détail du Bon de Livraison, STO-PICK-.YYYY.-,STO-PICK-.YYYY.-, @@ -8215,7 +8218,7 @@ Pick List Item,Élément de la liste de choix, Picked Qty,Quantité choisie, Price List Master,Données de Base des Listes de Prix, Price List Name,Nom de la Liste de Prix, -Price Not UOM Dependent,Prix non dépendant de l'UOM, +Price Not UOM Dependent,Prix non dépendant de l'UdM, Applicable for Countries,Applicable pour les Pays, Price List Country,Pays de la Liste des Prix, MAT-PRE-.YYYY.-,MAT-PRE-YYYY.-, @@ -8294,7 +8297,7 @@ Purchase Receipt No,N° du Reçu d'Achat, Inspection Required,Inspection obligatoire, From BOM,Depuis la nomenclature, For Quantity,Pour la Quantité, -As per Stock UOM,Selon UDM du Stock, +As per Stock UOM,Selon UdM du Stock, Including items for sub assemblies,Incluant les articles pour des sous-ensembles, Default Source Warehouse,Entrepôt Source par Défaut, Source Warehouse Address,Adresse de l'entrepôt source, @@ -8309,7 +8312,7 @@ Total Additional Costs,Total des Coûts Additionnels, Customer or Supplier Details,Détails du Client ou du Fournisseur, Per Transferred,Par transféré, Stock Entry Detail,Détails de l'Écriture de Stock, -Basic Rate (as per Stock UOM),Prix de base (comme l’UDM du Stock), +Basic Rate (as per Stock UOM),Prix de base (comme l’UdM du Stock), Basic Amount,Montant de Base, Additional Cost,Frais Supplémentaire, Serial No / Batch,N° de Série / Lot, @@ -8339,7 +8342,7 @@ Quantity Difference,Différence de Quantité, Amount Difference,Différence de Montant, Item Naming By,Nomenclature d'Article Par, Default Item Group,Groupe d'Éléments par Défaut, -Default Stock UOM,UDM par Défaut des Articles, +Default Stock UOM,UdM par Défaut des Articles, Sample Retention Warehouse,Entrepôt de stockage des échantillons, Default Valuation Method,Méthode de Valorisation par Défaut, Show Barcode Field,Afficher Champ Code Barre, @@ -8353,8 +8356,8 @@ Stock Frozen Upto,Stock Gelé Jusqu'au, Batch Identification,Identification par lots, Use Naming Series,Utiliser la série de noms, Naming Series Prefix,Préfix du nom de série, -UOM Category,Catégorie d'unité de mesure (UDM), -UOM Conversion Detail,Détails de Conversion de l'UDM, +UOM Category,Catégorie d'unité de mesure (UdM), +UOM Conversion Detail,Détails de Conversion de l'UdM, Variant Field,Champ de Variante, A logical Warehouse against which stock entries are made.,Un Entrepôt logique dans lequel les entrées en stock sont faites., Warehouse Detail,Détail de l'Entrepôt, @@ -9869,8 +9872,8 @@ Allowed Items,Articles autorisés Party Specific Item,Restriction d'article disponible Restrict Items Based On,Type de critére de restriction Based On Value,critére de restriction -Unit of Measure (UOM),Unité de mesure (UDM), -Unit Of Measure (UOM),Unité de mesure (UDM), +Unit of Measure (UOM),Unité de mesure (UdM), +Unit Of Measure (UOM),Unité de mesure (UdM), CRM Settings,Paramètres CRM Do Not Explode,Ne pas décomposer Quick Access, Accés rapides From 8d1db0ea3db008d753048ca53356846af44de775 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 6 Oct 2022 11:28:26 +0530 Subject: [PATCH 11/16] fix: single column indexes (#32425) refactor: move single column indexes to doctypes --- erpnext/accounts/doctype/pos_invoice/pos_invoice.json | 5 +++-- erpnext/accounts/doctype/pos_invoice/pos_invoice.py | 4 ---- erpnext/e_commerce/doctype/website_item/website_item.json | 8 +++++--- erpnext/e_commerce/doctype/website_item/website_item.py | 3 --- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json index 6f8b3822c2e..eedaaaf338b 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json @@ -343,7 +343,8 @@ "no_copy": 1, "options": "POS Invoice", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "search_index": 1 }, { "default": "0", @@ -1553,7 +1554,7 @@ "icon": "fa fa-file-text", "is_submittable": 1, "links": [], - "modified": "2022-09-27 13:00:24.166684", + "modified": "2022-09-30 03:49:50.455199", "modified_by": "Administrator", "module": "Accounts", "name": "POS Invoice", diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index fbe0ef39f83..54a3e934b2d 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -743,7 +743,3 @@ def add_return_modes(doc, pos_profile): ]: payment_mode = get_mode_of_payment_info(mode_of_payment, doc.company) append_payment(payment_mode[0]) - - -def on_doctype_update(): - frappe.db.add_index("POS Invoice", ["return_against"]) diff --git a/erpnext/e_commerce/doctype/website_item/website_item.json b/erpnext/e_commerce/doctype/website_item/website_item.json index c5775ee9075..6556eabf4ab 100644 --- a/erpnext/e_commerce/doctype/website_item/website_item.json +++ b/erpnext/e_commerce/doctype/website_item/website_item.json @@ -188,7 +188,8 @@ "in_list_view": 1, "label": "Item Group", "options": "Item Group", - "read_only": 1 + "read_only": 1, + "search_index": 1 }, { "default": "1", @@ -234,7 +235,8 @@ "fieldname": "brand", "fieldtype": "Link", "label": "Brand", - "options": "Brand" + "options": "Brand", + "search_index": 1 }, { "collapsible": 1, @@ -346,7 +348,7 @@ "index_web_pages_for_search": 1, "links": [], "make_attachments_public": 1, - "modified": "2022-09-13 04:05:11.614087", + "modified": "2022-09-30 04:01:52.090732", "modified_by": "Administrator", "module": "E-commerce", "name": "Website Item", diff --git a/erpnext/e_commerce/doctype/website_item/website_item.py b/erpnext/e_commerce/doctype/website_item/website_item.py index c0f8c79283d..3e5d5f768fa 100644 --- a/erpnext/e_commerce/doctype/website_item/website_item.py +++ b/erpnext/e_commerce/doctype/website_item/website_item.py @@ -403,9 +403,6 @@ def on_doctype_update(): # since route is a Text column, it needs a length for indexing frappe.db.add_index("Website Item", ["route(500)"]) - frappe.db.add_index("Website Item", ["item_group"]) - frappe.db.add_index("Website Item", ["brand"]) - def check_if_user_is_customer(user=None): from frappe.contacts.doctype.contact.contact import get_contact_name From 07c4a7483869a06c1e00a2a71c1909fcf5cd9ed6 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 6 Oct 2022 13:01:53 +0530 Subject: [PATCH 12/16] chore: drop stale demo page (#32515) --- erpnext/templates/pages/demo.html | 77 ------------------------------- 1 file changed, 77 deletions(-) delete mode 100644 erpnext/templates/pages/demo.html diff --git a/erpnext/templates/pages/demo.html b/erpnext/templates/pages/demo.html deleted file mode 100644 index f9934a33f32..00000000000 --- a/erpnext/templates/pages/demo.html +++ /dev/null @@ -1,77 +0,0 @@ -{% extends "templates/web.html" %} - -{% block script %} - -{% endblock %} - -{% block style %} - -{% endblock %} - -{% block title %} -{{ _("ERPNext Demo") }} -{% endblock %} - -{% block page_content %} -
- -
- - {{ _("ERPNext Demo") }} -
- -

Some functionality is disabled for the demo and the data will be cleared regularly.

-
-
- - -

Start a free 14-day trial -

- -{% endblock %} From 8376fbc9826e3fa7dc9a28365d96e92a2f6f52d9 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 6 Oct 2022 20:35:33 +0530 Subject: [PATCH 13/16] fix: Explicitly update modified (#32519) * fix: Explicitly update modified required after https://github.com/frappe/frappe/pull/18301 * chore: fix broken translations --- erpnext/stock/doctype/bin/bin.py | 11 +++++++---- erpnext/stock/stock_ledger.py | 2 +- erpnext/translations/fr.csv | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py index 548df318fac..c28f45aed41 100644 --- a/erpnext/stock/doctype/bin/bin.py +++ b/erpnext/stock/doctype/bin/bin.py @@ -37,8 +37,10 @@ class Bin(Document): self.set_projected_qty() - self.db_set("reserved_qty_for_production", flt(self.reserved_qty_for_production)) - self.db_set("projected_qty", self.projected_qty) + self.db_set( + "reserved_qty_for_production", flt(self.reserved_qty_for_production), update_modified=True + ) + self.db_set("projected_qty", self.projected_qty, update_modified=True) def update_reserved_qty_for_sub_contracting(self, subcontract_doctype="Subcontracting Order"): # reserved qty @@ -118,9 +120,9 @@ class Bin(Document): else: reserved_qty_for_sub_contract = 0 - self.db_set("reserved_qty_for_sub_contract", reserved_qty_for_sub_contract) + self.db_set("reserved_qty_for_sub_contract", reserved_qty_for_sub_contract, update_modified=True) self.set_projected_qty() - self.db_set("projected_qty", self.projected_qty) + self.db_set("projected_qty", self.projected_qty, update_modified=True) def on_doctype_update(): @@ -193,4 +195,5 @@ def update_qty(bin_name, args): "planned_qty": planned_qty, "projected_qty": projected_qty, }, + update_modified=True, ) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 50309647de0..9ca40c3675f 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -1053,7 +1053,7 @@ class update_entries_after(object): updated_values = {"actual_qty": data.qty_after_transaction, "stock_value": data.stock_value} if data.valuation_rate is not None: updated_values["valuation_rate"] = data.valuation_rate - frappe.db.set_value("Bin", bin_name, updated_values) + frappe.db.set_value("Bin", bin_name, updated_values, update_modified=True) def get_previous_sle_of_current_voucher(args, exclude_current_voucher=False): diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv index 7989bf7ebce..3ba5ade6299 100644 --- a/erpnext/translations/fr.csv +++ b/erpnext/translations/fr.csv @@ -4946,7 +4946,7 @@ Min Amt,Montant Min, Max Amt,Montant Max, "If rate is zero them item will be treated as ""Free Item""",Si le prix est à 0 alors l'article sera traité comme article gratuit Is Recursive,Est récursif -"Discounts to be applied in sequential ranges like buy 1 get 1, buy 2 get 2, buy 3 get 3 and so on",La remise sera appliquée séquentiellement telque : acheter 1 => recupérer 1, acheter 2 => recupérer 2, acheter 3 => recupérer 3, etc... +"Discounts to be applied in sequential ranges like buy 1 get 1, buy 2 get 2, buy 3 get 3 and so on","La remise sera appliquée séquentiellement telque : acheter 1 => recupérer 1, acheter 2 => recupérer 2, acheter 3 => recupérer 3, etc..." Period Settings,Paramètres de période, Margin,Marge, Margin Type,Type de Marge, From abf5b6be3ea13f0d00664e25e7b1742429d4f5e2 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 7 Oct 2022 14:04:36 +0530 Subject: [PATCH 14/16] fix: Tax withholding related fixes --- .../tax_withholding_category/tax_withholding_category.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py index 84c2c9a3c3e..61f52a18aab 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py @@ -425,7 +425,10 @@ def get_tds_amount(ldc, parties, inv, tax_details, tax_deducted, vouchers): ): # Get net total again as TDS is calculated on net total # Grand is used to just check for threshold breach - net_total = frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(net_total)") or 0.0 + net_total = 0 + if vouchers: + net_total = frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(net_total)") + net_total += inv.net_total supp_credit_amt = net_total - cumulative_threshold From 781d160c684f9c04b1c799449e484abff3e07d8a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 7 Oct 2022 14:22:40 +0530 Subject: [PATCH 15/16] fix: Do not add tax withheld vouchers post tax withheding in one document --- .../accounts/doctype/purchase_invoice/purchase_invoice.json | 3 ++- .../tax_withholding_category/tax_withholding_category.py | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 3020e6dc6e3..1e477776e2d 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -1430,6 +1430,7 @@ "fieldname": "tax_withheld_vouchers", "fieldtype": "Table", "label": "Tax Withheld Vouchers", + "no_copy": 1, "options": "Tax Withheld Vouchers", "read_only": 1 } @@ -1438,7 +1439,7 @@ "idx": 204, "is_submittable": 1, "links": [], - "modified": "2022-09-27 11:07:55.766844", + "modified": "2022-10-07 14:19:14.214157", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py index 61f52a18aab..7eddd81ee03 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py @@ -249,6 +249,9 @@ def get_tax_amount(party_type, parties, inv, tax_details, posting_date, pan_no=N ) else: tax_amount = net_total * tax_details.rate / 100 if net_total > 0 else 0 + + # once tds is deducted, not need to add vouchers in the invoice + voucher_wise_amount = {} else: tax_amount = get_tds_amount(ldc, parties, inv, tax_details, tax_deducted, vouchers) From d59ed24e6ca2a1ff62963c282882a2d52691b7c6 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 28 Sep 2022 12:53:18 +0530 Subject: [PATCH 16/16] feat: provision to return non consumed components against the work order --- .../doctype/work_order/test_work_order.py | 72 ++++++++++++++ .../doctype/work_order/work_order.js | 36 ++++++- .../doctype/work_order/work_order.py | 93 ++++++++++++++++--- .../work_order_item/work_order_item.json | 13 ++- .../work_order_consumed_materials.js | 2 +- .../work_order_consumed_materials.py | 38 +++++++- .../doctype/stock_entry/stock_entry.json | 25 ++--- .../stock/doctype/stock_entry/stock_entry.py | 26 ++++-- .../doctype/stock_entry/stock_entry_list.js | 9 +- 9 files changed, 274 insertions(+), 40 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index a53c42c5ec8..804f03dc519 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -17,6 +17,7 @@ from erpnext.manufacturing.doctype.work_order.work_order import ( close_work_order, make_job_card, make_stock_entry, + make_stock_return_entry, stop_unstop, ) from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order @@ -1408,6 +1409,77 @@ class TestWorkOrder(FrappeTestCase): ) self.assertEqual(manufacture_ste_doc2.items[1].qty, 1) + def test_non_consumed_material_return_against_work_order(self): + frappe.db.set_value( + "Manufacturing Settings", + None, + "backflush_raw_materials_based_on", + "Material Transferred for Manufacture", + ) + + item = make_item( + "Test FG Item To Test Return Case", + { + "is_stock_item": 1, + }, + ) + + item_code = item.name + bom_doc = make_bom( + item=item_code, + source_warehouse="Stores - _TC", + raw_materials=["Test Batch MCC Keyboard", "Test Serial No BTT Headphone"], + ) + + # Create a work order + wo_doc = make_wo_order_test_record(production_item=item_code, qty=5) + wo_doc.save() + + self.assertEqual(wo_doc.bom_no, bom_doc.name) + + # Transfer material for manufacture + ste_doc = frappe.get_doc(make_stock_entry(wo_doc.name, "Material Transfer for Manufacture", 5)) + for row in ste_doc.items: + row.qty += 2 + row.transfer_qty += 2 + nste_doc = test_stock_entry.make_stock_entry( + item_code=row.item_code, target="Stores - _TC", qty=row.qty, basic_rate=100 + ) + + row.batch_no = nste_doc.items[0].batch_no + row.serial_no = nste_doc.items[0].serial_no + + ste_doc.save() + ste_doc.submit() + ste_doc.load_from_db() + + # Create a stock entry to manufacture the item + ste_doc = frappe.get_doc(make_stock_entry(wo_doc.name, "Manufacture", 5)) + for row in ste_doc.items: + if row.s_warehouse and not row.t_warehouse: + row.qty -= 2 + row.transfer_qty -= 2 + + if row.serial_no: + serial_nos = get_serial_nos(row.serial_no) + row.serial_no = "\n".join(serial_nos[0:5]) + + ste_doc.save() + ste_doc.submit() + + wo_doc.load_from_db() + for row in wo_doc.required_items: + self.assertEqual(row.transferred_qty, 7) + self.assertEqual(row.consumed_qty, 5) + + self.assertEqual(wo_doc.status, "Completed") + return_ste_doc = make_stock_return_entry(wo_doc.name) + return_ste_doc.save() + + self.assertTrue(return_ste_doc.is_return) + for row in return_ste_doc.items: + self.assertEqual(row.qty, 2) + def prepare_data_for_backflush_based_on_materials_transferred(): batch_item_doc = make_item( diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js index f3640b93b22..4aab3fa3734 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.js +++ b/erpnext/manufacturing/doctype/work_order/work_order.js @@ -180,6 +180,37 @@ frappe.ui.form.on("Work Order", { frm.trigger("make_bom"); }); } + + frm.trigger("add_custom_button_to_return_components"); + }, + + add_custom_button_to_return_components: function(frm) { + if (frm.doc.docstatus === 1 && in_list(["Closed", "Completed"], frm.doc.status)) { + let non_consumed_items = frm.doc.required_items.filter(d =>{ + return flt(d.consumed_qty) < flt(d.transferred_qty - d.returned_qty) + }); + + if (non_consumed_items && non_consumed_items.length) { + frm.add_custom_button(__("Return Components"), function() { + frm.trigger("create_stock_return_entry"); + }).addClass("btn-primary"); + } + } + }, + + create_stock_return_entry: function(frm) { + frappe.call({ + method: "erpnext.manufacturing.doctype.work_order.work_order.make_stock_return_entry", + args: { + "work_order": frm.doc.name, + }, + callback: function(r) { + if(!r.exc) { + let doc = frappe.model.sync(r.message); + frappe.set_route("Form", doc[0].doctype, doc[0].name); + } + } + }); }, make_job_card: function(frm) { @@ -517,7 +548,8 @@ frappe.ui.form.on("Work Order Operation", { erpnext.work_order = { set_custom_buttons: function(frm) { var doc = frm.doc; - if (doc.docstatus === 1 && doc.status != "Closed") { + + if (doc.status !== "Closed") { frm.add_custom_button(__('Close'), function() { frappe.confirm(__("Once the Work Order is Closed. It can't be resumed."), () => { @@ -525,7 +557,9 @@ erpnext.work_order = { } ); }, __("Status")); + } + if (doc.docstatus === 1 && !in_list(["Closed", "Completed"], doc.status)) { if (doc.status != 'Stopped' && doc.status != 'Completed') { frm.add_custom_button(__('Stop'), function() { erpnext.work_order.change_work_order_status(frm, "Stopped"); diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 7b8625372a8..1e6d982fc91 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -20,6 +20,7 @@ from frappe.utils import ( nowdate, time_diff_in_hours, ) +from pypika import functions as fn from erpnext.manufacturing.doctype.bom.bom import ( get_bom_item_rate, @@ -859,6 +860,7 @@ class WorkOrder(Document): if self.docstatus == 1: # calculate transferred qty based on submitted stock entries self.update_transferred_qty_for_required_items() + self.update_returned_qty() # update in bin self.update_reserved_qty_for_production() @@ -930,23 +932,62 @@ class WorkOrder(Document): self.set_available_qty() def update_transferred_qty_for_required_items(self): - """update transferred qty from submitted stock entries for that item against - the work order""" + ste = frappe.qb.DocType("Stock Entry") + ste_child = frappe.qb.DocType("Stock Entry Detail") - for d in self.required_items: - transferred_qty = frappe.db.sql( - """select sum(qty) - from `tabStock Entry` entry, `tabStock Entry Detail` detail - where - entry.work_order = %(name)s - and entry.purpose = 'Material Transfer for Manufacture' - and entry.docstatus = 1 - and detail.parent = entry.name - and (detail.item_code = %(item)s or detail.original_item = %(item)s)""", - {"name": self.name, "item": d.item_code}, - )[0][0] + query = ( + frappe.qb.from_(ste) + .inner_join(ste_child) + .on((ste_child.parent == ste.name)) + .select( + ste_child.item_code, + ste_child.original_item, + fn.Sum(ste_child.qty).as_("qty"), + ) + .where( + (ste.docstatus == 1) + & (ste.work_order == self.name) + & (ste.purpose == "Material Transfer for Manufacture") + & (ste.is_return == 0) + ) + .groupby(ste_child.item_code) + ) - d.db_set("transferred_qty", flt(transferred_qty), update_modified=False) + data = query.run(as_dict=1) or [] + transferred_items = frappe._dict({d.original_item or d.item_code: d.qty for d in data}) + + for row in self.required_items: + row.db_set( + "transferred_qty", (transferred_items.get(row.item_code) or 0.0), update_modified=False + ) + + def update_returned_qty(self): + ste = frappe.qb.DocType("Stock Entry") + ste_child = frappe.qb.DocType("Stock Entry Detail") + + query = ( + frappe.qb.from_(ste) + .inner_join(ste_child) + .on((ste_child.parent == ste.name)) + .select( + ste_child.item_code, + ste_child.original_item, + fn.Sum(ste_child.qty).as_("qty"), + ) + .where( + (ste.docstatus == 1) + & (ste.work_order == self.name) + & (ste.purpose == "Material Transfer for Manufacture") + & (ste.is_return == 1) + ) + .groupby(ste_child.item_code) + ) + + data = query.run(as_dict=1) or [] + returned_dict = frappe._dict({d.original_item or d.item_code: d.qty for d in data}) + + for row in self.required_items: + row.db_set("returned_qty", (returned_dict.get(row.item_code) or 0.0), update_modified=False) def update_consumed_qty_for_required_items(self): """ @@ -1470,3 +1511,25 @@ def get_reserved_qty_for_production(item_code: str, warehouse: str) -> float: ) ) ).run()[0][0] or 0.0 + + +@frappe.whitelist() +def make_stock_return_entry(work_order): + from erpnext.stock.doctype.stock_entry.stock_entry import get_available_materials + + non_consumed_items = get_available_materials(work_order) + if not non_consumed_items: + return + + wo_doc = frappe.get_cached_doc("Work Order", work_order) + + stock_entry = frappe.new_doc("Stock Entry") + stock_entry.from_bom = 1 + stock_entry.is_return = 1 + stock_entry.work_order = work_order + stock_entry.purpose = "Material Transfer for Manufacture" + stock_entry.bom_no = wo_doc.bom_no + stock_entry.add_transfered_raw_materials_in_items() + stock_entry.set_stock_entry_type() + + return stock_entry diff --git a/erpnext/manufacturing/doctype/work_order_item/work_order_item.json b/erpnext/manufacturing/doctype/work_order_item/work_order_item.json index 3acf5727d19..f354d45381c 100644 --- a/erpnext/manufacturing/doctype/work_order_item/work_order_item.json +++ b/erpnext/manufacturing/doctype/work_order_item/work_order_item.json @@ -20,6 +20,7 @@ "column_break_11", "transferred_qty", "consumed_qty", + "returned_qty", "available_qty_at_source_warehouse", "available_qty_at_wip_warehouse" ], @@ -97,6 +98,7 @@ "fieldtype": "Column Break" }, { + "columns": 1, "depends_on": "eval:!parent.skip_transfer", "fieldname": "consumed_qty", "fieldtype": "Float", @@ -127,11 +129,19 @@ "fieldtype": "Currency", "label": "Amount", "read_only": 1 + }, + { + "columns": 1, + "fieldname": "returned_qty", + "fieldtype": "Float", + "in_list_view": 1, + "label": "Returned Qty ", + "read_only": 1 } ], "istable": 1, "links": [], - "modified": "2020-04-13 18:46:32.966416", + "modified": "2022-09-28 10:50:43.512562", "modified_by": "Administrator", "module": "Manufacturing", "name": "Work Order Item", @@ -140,5 +150,6 @@ "quick_entry": 1, "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.js b/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.js index b2428e85b74..2fb4ec67913 100644 --- a/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.js +++ b/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.js @@ -50,7 +50,7 @@ frappe.query_reports["Work Order Consumed Materials"] = { label: __("Status"), fieldname: "status", fieldtype: "Select", - options: ["In Process", "Completed", "Stopped"] + options: ["", "In Process", "Completed", "Stopped"] }, { label: __("Excess Materials Consumed"), diff --git a/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.py b/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.py index 8158bc9a02b..14e97d3dd78 100644 --- a/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.py +++ b/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.py @@ -1,6 +1,8 @@ # Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt +from collections import defaultdict + import frappe from frappe import _ @@ -18,7 +20,11 @@ def get_data(report_filters): filters = get_filter_condition(report_filters) wo_items = {} - for d in frappe.get_all("Work Order", filters=filters, fields=fields): + + work_orders = frappe.get_all("Work Order", filters=filters, fields=fields) + returned_materials = get_returned_materials(work_orders) + + for d in work_orders: d.extra_consumed_qty = 0.0 if d.consumed_qty and d.consumed_qty > d.required_qty: d.extra_consumed_qty = d.consumed_qty - d.required_qty @@ -39,6 +45,28 @@ def get_data(report_filters): return data +def get_returned_materials(work_orders): + raw_materials_qty = defaultdict(float) + + raw_materials = frappe.get_all( + "Stock Entry", + fields=["`tabStock Entry Detail`.`item_code`", "`tabStock Entry Detail`.`qty`"], + filters=[ + ["Stock Entry", "is_return", "=", 1], + ["Stock Entry Detail", "docstatus", "=", 1], + ["Stock Entry", "work_order", "in", [d.name for d in work_orders]], + ], + ) + + for d in raw_materials: + raw_materials_qty[d.item_code] += d.qty + + for row in work_orders: + row.returned_qty = 0.0 + if raw_materials_qty.get(row.raw_material_item_code): + row.returned_qty = raw_materials_qty.get(row.raw_material_item_code) + + def get_fields(): return [ "`tabWork Order Item`.`parent`", @@ -65,7 +93,7 @@ def get_filter_condition(report_filters): for field in ["name", "production_item", "company", "status"]: value = report_filters.get(field) if value: - key = f"`{field}`" + key = f"{field}" filters.update({key: value}) return filters @@ -112,4 +140,10 @@ def get_columns(): "fieldtype": "Float", "width": 100, }, + { + "label": _("Returned Qty"), + "fieldname": "returned_qty", + "fieldtype": "Float", + "width": 100, + }, ] diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json index abe98e2933e..7e9420d5035 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.json +++ b/erpnext/stock/doctype/stock_entry/stock_entry.json @@ -148,19 +148,19 @@ "search_index": 1 }, { - "depends_on": "eval:doc.purpose==\"Send to Subcontractor\"", - "fieldname": "purchase_order", - "fieldtype": "Link", - "label": "Purchase Order", - "options": "Purchase Order" + "depends_on": "eval:doc.purpose==\"Send to Subcontractor\"", + "fieldname": "purchase_order", + "fieldtype": "Link", + "label": "Purchase Order", + "options": "Purchase Order" }, { - "depends_on": "eval:doc.purpose==\"Send to Subcontractor\"", - "fieldname": "subcontracting_order", - "fieldtype": "Link", - "label": "Subcontracting Order", - "options": "Subcontracting Order" - }, + "depends_on": "eval:doc.purpose==\"Send to Subcontractor\"", + "fieldname": "subcontracting_order", + "fieldtype": "Link", + "label": "Subcontracting Order", + "options": "Subcontracting Order" + }, { "depends_on": "eval:doc.purpose==\"Sales Return\"", "fieldname": "delivery_note_no", @@ -616,6 +616,7 @@ "fieldname": "is_return", "fieldtype": "Check", "hidden": 1, + "in_list_view": 1, "label": "Is Return", "no_copy": 1, "print_hide": 1, @@ -627,7 +628,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2022-05-02 05:21:39.060501", + "modified": "2022-10-07 14:39:51.943770", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry", diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 8bcd772d909..b1167351c48 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -1212,13 +1212,19 @@ class StockEntry(StockController): def update_work_order(self): def _validate_work_order(pro_doc): + msg, title = "", "" if flt(pro_doc.docstatus) != 1: - frappe.throw(_("Work Order {0} must be submitted").format(self.work_order)) + msg = f"Work Order {self.work_order} must be submitted" if pro_doc.status == "Stopped": - frappe.throw( - _("Transaction not allowed against stopped Work Order {0}").format(self.work_order) - ) + msg = f"Transaction not allowed against stopped Work Order {self.work_order}" + + if self.is_return and pro_doc.status not in ["Completed", "Closed"]: + title = _("Stock Return") + msg = f"Work Order {self.work_order} must be completed or closed" + + if msg: + frappe.throw(_(msg), title=title) if self.job_card: job_doc = frappe.get_doc("Job Card", self.job_card) @@ -1754,10 +1760,12 @@ class StockEntry(StockController): for key, row in available_materials.items(): remaining_qty_to_produce = flt(wo_data.trans_qty) - flt(wo_data.produced_qty) - if remaining_qty_to_produce <= 0: + if remaining_qty_to_produce <= 0 and not self.is_return: continue - qty = (flt(row.qty) * flt(self.fg_completed_qty)) / remaining_qty_to_produce + qty = flt(row.qty) + if not self.is_return: + qty = (flt(row.qty) * flt(self.fg_completed_qty)) / remaining_qty_to_produce item = row.item_details if cint(frappe.get_cached_value("UOM", item.stock_uom, "must_be_whole_number")): @@ -1781,6 +1789,9 @@ class StockEntry(StockController): self.update_item_in_stock_entry_detail(row, item, qty) def update_item_in_stock_entry_detail(self, row, item, qty) -> None: + if not qty: + return + ste_item_details = { "from_warehouse": item.warehouse, "to_warehouse": "", @@ -1794,6 +1805,9 @@ class StockEntry(StockController): "original_item": item.original_item, } + if self.is_return: + ste_item_details["to_warehouse"] = item.s_warehouse + if row.serial_nos: serial_nos = row.serial_nos if item.batch_no: diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_list.js b/erpnext/stock/doctype/stock_entry/stock_entry_list.js index cbc3491eba4..4eb0da11d2f 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry_list.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry_list.js @@ -1,8 +1,13 @@ frappe.listview_settings['Stock Entry'] = { add_fields: ["`tabStock Entry`.`from_warehouse`", "`tabStock Entry`.`to_warehouse`", - "`tabStock Entry`.`purpose`", "`tabStock Entry`.`work_order`", "`tabStock Entry`.`bom_no`"], + "`tabStock Entry`.`purpose`", "`tabStock Entry`.`work_order`", "`tabStock Entry`.`bom_no`", + "`tabStock Entry`.`is_return`"], get_indicator: function (doc) { - if (doc.docstatus === 0) { + debugger + if(doc.is_return===1 && doc.purpose === "Material Transfer for Manufacture") { + return [__("Material Returned from WIP"), "orange", + "is_return,=,1|purpose,=,Material Transfer for Manufacture|docstatus,<,2"]; + } else if (doc.docstatus === 0) { return [__("Draft"), "red", "docstatus,=,0"]; } else if (doc.purpose === 'Send to Warehouse' && doc.per_transferred < 100) {