From e6aa28ea1409dee499e5ada0d8b0f16ccf1c4d61 Mon Sep 17 00:00:00 2001 From: HENRY Florian Date: Thu, 14 Apr 2022 14:16:47 +0200 Subject: [PATCH 01/19] fix: update translation (#30716) * fix: update translation * fix: update translation * fix: update translation * fix: update translation --- erpnext/translations/fr.csv | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv index 3295136047e..8518156eb21 100644 --- a/erpnext/translations/fr.csv +++ b/erpnext/translations/fr.csv @@ -271,7 +271,7 @@ Assessment Report,Rapport d'Évaluation, Assessment Reports,Rapports d'évaluation, Assessment Result,Résultat de l'Évaluation, Assessment Result record {0} already exists.,Le Résultat d'Évaluation {0} existe déjà., -Asset,Atout, +Asset,Actif - Immo., Asset Category,Catégorie d'Actif, Asset Category is mandatory for Fixed Asset item,Catégorie d'Actif est obligatoire pour l'article Immobilisé, Asset Maintenance,Maintenance des actifs, @@ -3037,6 +3037,7 @@ To Date must be greater than From Date,La date de fin doit être supérieure à To Date should be within the Fiscal Year. Assuming To Date = {0},La Date Finale doit être dans l'exercice. En supposant Date Finale = {0}, To Datetime,À la Date, To Deliver,À Livrer, +{} To Deliver,{} à livrer To Deliver and Bill,À Livrer et Facturer, To Fiscal Year,À l'année fiscale, To GSTIN,GSTIN (Destination), @@ -9871,3 +9872,4 @@ Show Barcode Field in Stock Transactions,Afficher le champ Code Barre dans les t Convert Item Description to Clean HTML in Transactions,Convertir les descriptions d'articles en HTML valide lors des transactions Have Default Naming Series for Batch ID?,Nom de série par défaut pour les Lots ou Séries "The percentage you are allowed to transfer more against the quantity ordered. For example, if you have ordered 100 units, and your Allowance is 10%, then you are allowed transfer 110 units","Le pourcentage de quantité que vous pourrez réceptionner en plus de la quantité commandée. Par exemple, vous avez commandé 100 unités, votre pourcentage de dépassement est de 10%, vous pourrez réceptionner 110 unités" +Unit Of Measure (UOM),Unité de mesure (UDM), From 64ac22af82e6cbba32720bbb009c39016e45afab Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 11 Apr 2022 14:31:15 +0530 Subject: [PATCH 02/19] refactor: add filter type info --- .../report/stock_balance/stock_balance.py | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index afbc6fe249d..a5136a3babb 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -3,6 +3,7 @@ from operator import itemgetter +from typing import Optional, TypedDict import frappe from frappe import _ @@ -14,7 +15,20 @@ from erpnext.stock.report.stock_ledger.stock_ledger import get_item_group_condit from erpnext.stock.utils import add_additional_uom_columns, is_reposting_item_valuation_in_progress -def execute(filters=None): +class StockBalanceFilter(TypedDict): + company: Optional[str] + from_date: str + to_date: str + item_group: Optional[str] + item: Optional[str] + warehouse: Optional[str] + warehouse_type: Optional[str] + include_uom: Optional[str] # include extra info in converted UOM + show_stock_ageing_data: bool + show_variant_attributes: bool + + +def execute(filters: Optional[StockBalanceFilter] = None): is_reposting_item_valuation_in_progress() if not filters: filters = {} @@ -92,7 +106,7 @@ def execute(filters=None): return columns, data -def get_columns(filters): +def get_columns(filters: StockBalanceFilter): """return columns""" columns = [ { @@ -215,7 +229,7 @@ def get_columns(filters): return columns -def get_conditions(filters): +def get_conditions(filters: StockBalanceFilter): conditions = "" if not filters.get("from_date"): frappe.throw(_("'From Date' is required")) @@ -249,7 +263,7 @@ def get_conditions(filters): return conditions -def get_stock_ledger_entries(filters, items): +def get_stock_ledger_entries(filters: StockBalanceFilter, items): item_conditions_sql = "" if items: item_conditions_sql = " and sle.item_code in ({})".format( @@ -274,7 +288,7 @@ def get_stock_ledger_entries(filters, items): ) -def get_item_warehouse_map(filters, sle): +def get_item_warehouse_map(filters: StockBalanceFilter, sle): iwb_map = {} from_date = getdate(filters.get("from_date")) to_date = getdate(filters.get("to_date")) @@ -349,7 +363,7 @@ def filter_items_with_no_transactions(iwb_map, float_precision): return iwb_map -def get_items(filters): +def get_items(filters: StockBalanceFilter): "Get items based on item code, item group or brand." conditions = [] if filters.get("item_code"): @@ -368,7 +382,7 @@ def get_items(filters): return items -def get_item_details(items, sle, filters): +def get_item_details(items, sle, filters: StockBalanceFilter): item_details = {} if not items: items = list(set(d.item_code for d in sle)) From 8b2432dfa074146e50c4ad9c88630a78d6b34459 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 11 Apr 2022 14:04:41 +0530 Subject: [PATCH 03/19] test: stock balance report tests --- .../stock_balance/test_stock_balance.py | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 erpnext/stock/report/stock_balance/test_stock_balance.py diff --git a/erpnext/stock/report/stock_balance/test_stock_balance.py b/erpnext/stock/report/stock_balance/test_stock_balance.py new file mode 100644 index 00000000000..52c48a06115 --- /dev/null +++ b/erpnext/stock/report/stock_balance/test_stock_balance.py @@ -0,0 +1,77 @@ +from typing import Any, Dict + +import frappe +from frappe import _dict +from frappe.tests.utils import FrappeTestCase +from frappe.utils import today + +from erpnext.stock.doctype.item.test_item import make_item +from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry +from erpnext.stock.report.stock_balance.stock_balance import execute + + +def stock_balance(filters): + return list(map(_dict, execute(filters)[1])) + + +class TestStockBalance(FrappeTestCase): + # ----------- utils + + def setUp(self): + self.item = make_item() + self.filters = { + "company": "_Test Company", + "item_code": self.item.name, + "from_date": str(today()), + "to_date": str(today()), + } + + def tearDown(self): + frappe.db.rollback() + + def assertPartialDictionary(self, expected: Dict[str, Any], actual: Dict[str, Any]): + for k, v in expected.items(): + self.assertEqual(v, actual[k], msg=f"{expected=}\n{actual=}") + + def generate_stock_ledger(self, item_code: str, movements): + + for movement in map(_dict, movements): + make_stock_entry( + item_code=item_code, + **movement, + to_warehouse=movement.to_warehouse or "_Test Warehouse - _TC", + ) + + def assertBasicInvariants(self, rows): + for row in rows: + msg = f"Invariants not met for {rows=}" + # qty invariant + self.assertAlmostEqual(row.bal_qty, row.opening_qty + row.in_qty - row.out_qty, msg) + + # value invariant + self.assertAlmostEqual(row.bal_val, row.opening_val + row.in_val - row.out_val, msg) + + # ----------- tests + + def test_basic_stock_balance(self): + """Check very basic functionality and item info""" + rows = stock_balance(self.filters) + self.assertEqual(rows, []) + + self.generate_stock_ledger(self.item.name, [_dict(qty=5, rate=10)]) + + # check item info + rows = stock_balance(self.filters) + self.assertPartialDictionary( + { + "item_code": self.item.name, + "item_name": self.item.item_name, + "item_group": self.item.item_group, + "stock_uom": self.item.stock_uom, + "in_qty": 5, + "in_val": 50, + "val_rate": 10, + }, + rows[0], + ) + self.assertBasicInvariants(rows) From f4766ae4eb7bf68e2b176793b32c56d51168b391 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 11 Apr 2022 14:54:44 +0530 Subject: [PATCH 04/19] test: opening balance in stock balance report --- .../stock_balance/test_stock_balance.py | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/report/stock_balance/test_stock_balance.py b/erpnext/stock/report/stock_balance/test_stock_balance.py index 52c48a06115..360ad3a75b8 100644 --- a/erpnext/stock/report/stock_balance/test_stock_balance.py +++ b/erpnext/stock/report/stock_balance/test_stock_balance.py @@ -19,12 +19,14 @@ class TestStockBalance(FrappeTestCase): def setUp(self): self.item = make_item() - self.filters = { - "company": "_Test Company", - "item_code": self.item.name, - "from_date": str(today()), - "to_date": str(today()), - } + self.filters = _dict( + { + "company": "_Test Company", + "item_code": self.item.name, + "from_date": str(today()), + "to_date": str(today()), + } + ) def tearDown(self): frappe.db.rollback() @@ -51,6 +53,9 @@ class TestStockBalance(FrappeTestCase): # value invariant self.assertAlmostEqual(row.bal_val, row.opening_val + row.in_val - row.out_val, msg) + # valuation rate + self.assertAlmostEqual(row.val_rate, row.bal_val / row.bal_qty, 3, msg) + # ----------- tests def test_basic_stock_balance(self): @@ -75,3 +80,23 @@ class TestStockBalance(FrappeTestCase): rows[0], ) self.assertBasicInvariants(rows) + + def test_opening_balance(self): + self.generate_stock_ledger( + self.item.name, + [ + _dict(qty=1, rate=1, posting_date="2021-01-01"), + _dict(qty=2, rate=2, posting_date="2021-01-02"), + _dict(qty=3, rate=3, posting_date="2021-01-03"), + ], + ) + rows = stock_balance(self.filters) + self.assertBasicInvariants(rows) + + rows = stock_balance(self.filters.update({"from_date": "2021-01-02"})) + self.assertBasicInvariants(rows) + self.assertPartialDictionary({"opening_qty": 1, "in_qty": 5}, rows[0]) + + rows = stock_balance(self.filters.update({"from_date": "2022-01-01"})) + self.assertBasicInvariants(rows) + self.assertPartialDictionary({"opening_qty": 6, "in_qty": 0}, rows[0]) From af0ea7b532892e39c68fa7c57c016762f523e2bd Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 11 Apr 2022 15:16:19 +0530 Subject: [PATCH 05/19] test: assert balanaces against SLE --- .../stock_balance/test_stock_balance.py | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/report/stock_balance/test_stock_balance.py b/erpnext/stock/report/stock_balance/test_stock_balance.py index 360ad3a75b8..778195c7ba2 100644 --- a/erpnext/stock/report/stock_balance/test_stock_balance.py +++ b/erpnext/stock/report/stock_balance/test_stock_balance.py @@ -23,7 +23,7 @@ class TestStockBalance(FrappeTestCase): { "company": "_Test Company", "item_code": self.item.name, - "from_date": str(today()), + "from_date": "2020-01-01", "to_date": str(today()), } ) @@ -44,7 +44,27 @@ class TestStockBalance(FrappeTestCase): to_warehouse=movement.to_warehouse or "_Test Warehouse - _TC", ) - def assertBasicInvariants(self, rows): + def assertInvariants(self, rows): + last_balance = frappe.db.sql( + """ + WITH last_balances AS ( + SELECT item_code, warehouse, + stock_value, qty_after_transaction, + ROW_NUMBER() OVER (PARTITION BY item_code, warehouse + ORDER BY timestamp(posting_date, posting_time) desc, creation desc) + AS rn + FROM `tabStock Ledger Entry` + where is_cancelled=0 + ) + SELECT * FROM last_balances WHERE rn = 1""", + as_dict=True, + ) + + item_wh_stock = _dict() + + for line in last_balance: + item_wh_stock.setdefault((line.item_code, line.warehouse), line) + for row in rows: msg = f"Invariants not met for {rows=}" # qty invariant @@ -56,6 +76,11 @@ class TestStockBalance(FrappeTestCase): # valuation rate self.assertAlmostEqual(row.val_rate, row.bal_val / row.bal_qty, 3, msg) + # check against SLE + last_sle = item_wh_stock[(row.item_code, row.warehouse)] + self.assertAlmostEqual(row.bal_qty, last_sle.qty_after_transaction, 3) + self.assertAlmostEqual(row.bal_val, last_sle.stock_value, 3) + # ----------- tests def test_basic_stock_balance(self): @@ -79,7 +104,7 @@ class TestStockBalance(FrappeTestCase): }, rows[0], ) - self.assertBasicInvariants(rows) + self.assertInvariants(rows) def test_opening_balance(self): self.generate_stock_ledger( @@ -91,12 +116,12 @@ class TestStockBalance(FrappeTestCase): ], ) rows = stock_balance(self.filters) - self.assertBasicInvariants(rows) + self.assertInvariants(rows) rows = stock_balance(self.filters.update({"from_date": "2021-01-02"})) - self.assertBasicInvariants(rows) + self.assertInvariants(rows) self.assertPartialDictionary({"opening_qty": 1, "in_qty": 5}, rows[0]) rows = stock_balance(self.filters.update({"from_date": "2022-01-01"})) - self.assertBasicInvariants(rows) + self.assertInvariants(rows) self.assertPartialDictionary({"opening_qty": 6, "in_qty": 0}, rows[0]) From 8a499e95d3cfbe3d741c8b4c337f48e961dac89d Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 11 Apr 2022 15:25:16 +0530 Subject: [PATCH 06/19] test: uom conversion in stock balance report --- .../stock/report/stock_balance/test_stock_balance.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/erpnext/stock/report/stock_balance/test_stock_balance.py b/erpnext/stock/report/stock_balance/test_stock_balance.py index 778195c7ba2..2783d278780 100644 --- a/erpnext/stock/report/stock_balance/test_stock_balance.py +++ b/erpnext/stock/report/stock_balance/test_stock_balance.py @@ -125,3 +125,13 @@ class TestStockBalance(FrappeTestCase): rows = stock_balance(self.filters.update({"from_date": "2022-01-01"})) self.assertInvariants(rows) self.assertPartialDictionary({"opening_qty": 6, "in_qty": 0}, rows[0]) + + def test_uom_converted_info(self): + + self.item.append("uoms", {"conversion_factor": 5, "uom": "Box"}) + self.item.save() + + self.generate_stock_ledger(self.item.name, [_dict(qty=5, rate=10)]) + + rows = stock_balance(self.filters.update({"include_uom": "Box"})) + self.assertEqual(rows[0].bal_qty_alt, 1) From febc74a21b8f6d7a05c47049bf656018396c4234 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 11 Apr 2022 15:34:53 +0530 Subject: [PATCH 07/19] refactor: rewrite stock balance query to QB --- .../report/stock_balance/stock_balance.py | 128 ++++++++++-------- .../stock_balance/test_stock_balance.py | 25 +++- 2 files changed, 88 insertions(+), 65 deletions(-) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index a5136a3babb..7fa417ac310 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -7,11 +7,13 @@ from typing import Optional, TypedDict import frappe from frappe import _ +from frappe.query_builder.functions import CombineDatetime from frappe.utils import cint, date_diff, flt, getdate +from frappe.utils.nestedset import get_descendants_of +from pypika.terms import ExistsCriterion import erpnext from erpnext.stock.report.stock_ageing.stock_ageing import FIFOSlots, get_average_age -from erpnext.stock.report.stock_ledger.stock_ledger import get_item_group_condition from erpnext.stock.utils import add_additional_uom_columns, is_reposting_item_valuation_in_progress @@ -33,8 +35,6 @@ def execute(filters: Optional[StockBalanceFilter] = None): if not filters: filters = {} - to_date = filters.get("to_date") - if filters.get("company"): company_currency = erpnext.get_company_currency(filters.get("company")) else: @@ -62,6 +62,7 @@ def execute(filters: Optional[StockBalanceFilter] = None): _func = itemgetter(1) + to_date = filters.get("to_date") for (company, item, warehouse) in sorted(iwb_map): if item_map.get(item): qty_dict = iwb_map[(company, item, warehouse)] @@ -229,64 +230,75 @@ def get_columns(filters: StockBalanceFilter): return columns -def get_conditions(filters: StockBalanceFilter): - conditions = "" +def apply_conditions(query, filters): + sle = frappe.qb.DocType("Stock Ledger Entry") + warehouse_table = frappe.qb.DocType("Warehouse") + if not filters.get("from_date"): frappe.throw(_("'From Date' is required")) - if filters.get("to_date"): - conditions += " and sle.posting_date <= %s" % frappe.db.escape(filters.get("to_date")) + if to_date := filters.get("to_date"): + query = query.where(sle.posting_date <= to_date) else: frappe.throw(_("'To Date' is required")) - if filters.get("company"): - conditions += " and sle.company = %s" % frappe.db.escape(filters.get("company")) + if company := filters.get("company"): + query = query.where(sle.company == company) - if filters.get("warehouse"): - warehouse_details = frappe.db.get_value( - "Warehouse", filters.get("warehouse"), ["lft", "rgt"], as_dict=1 - ) - if warehouse_details: - conditions += ( - " and exists (select name from `tabWarehouse` wh \ - where wh.lft >= %s and wh.rgt <= %s and sle.warehouse = wh.name)" - % (warehouse_details.lft, warehouse_details.rgt) + if warehouse := filters.get("warehouse"): + lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"]) + chilren_subquery = ( + frappe.qb.from_(warehouse_table) + .select(warehouse_table.name) + .where( + (warehouse_table.lft >= lft) + & (warehouse_table.rgt <= rgt) + & (warehouse_table.name == sle.warehouse) ) - - if filters.get("warehouse_type") and not filters.get("warehouse"): - conditions += ( - " and exists (select name from `tabWarehouse` wh \ - where wh.warehouse_type = '%s' and sle.warehouse = wh.name)" - % (filters.get("warehouse_type")) + ) + query = query.where(ExistsCriterion(chilren_subquery)) + elif warehouse_type := filters.get("warehouse_type"): + query = ( + query.join(warehouse_table) + .on(warehouse_table.name == sle.warehouse) + .where(warehouse_table.warehouse_type == warehouse_type) ) - return conditions + return query def get_stock_ledger_entries(filters: StockBalanceFilter, items): - item_conditions_sql = "" - if items: - item_conditions_sql = " and sle.item_code in ({})".format( - ", ".join(frappe.db.escape(i, percent=False) for i in items) + sle = frappe.qb.DocType("Stock Ledger Entry") + + query = ( + frappe.qb.from_(sle) + .select( + sle.item_code, + sle.warehouse, + sle.posting_date, + sle.actual_qty, + sle.valuation_rate, + sle.company, + sle.voucher_type, + sle.qty_after_transaction, + sle.stock_value_difference, + sle.item_code.as_("name"), + sle.voucher_no, + sle.stock_value, + sle.batch_no, ) - - conditions = get_conditions(filters) - - return frappe.db.sql( - """ - select - sle.item_code, warehouse, sle.posting_date, sle.actual_qty, sle.valuation_rate, - sle.company, sle.voucher_type, sle.qty_after_transaction, sle.stock_value_difference, - sle.item_code as name, sle.voucher_no, sle.stock_value, sle.batch_no - from - `tabStock Ledger Entry` sle - where sle.docstatus < 2 %s %s - and is_cancelled = 0 - order by sle.posting_date, sle.posting_time, sle.creation, sle.actual_qty""" - % (item_conditions_sql, conditions), # nosec - as_dict=1, + .where((sle.docstatus < 2) & (sle.is_cancelled == 0)) + .orderby(CombineDatetime(sle.posting_date, sle.posting_time)) + .orderby(sle.creation) + .orderby(sle.actual_qty) ) + if items: + query = query.where(sle.item_code.isin(items)) + + query = apply_conditions(query, filters) + return query.run(as_dict=True) + def get_item_warehouse_map(filters: StockBalanceFilter, sle): iwb_map = {} @@ -365,21 +377,17 @@ def filter_items_with_no_transactions(iwb_map, float_precision): def get_items(filters: StockBalanceFilter): "Get items based on item code, item group or brand." - conditions = [] - if filters.get("item_code"): - conditions.append("item.name=%(item_code)s") + if item_code := filters.get("item_code"): + return [item_code] else: - if filters.get("item_group"): - conditions.append(get_item_group_condition(filters.get("item_group"))) - if filters.get("brand"): # used in stock analytics report - conditions.append("item.brand=%(brand)s") + item_filters = {} + if item_group := filters.get("item_group"): + children = get_descendants_of("Item Group", item_group, ignore_permissions=True) + item_filters["item_group"] = ("in", children + [item_group]) + if brand := filters.get("brand"): + item_filters["brand"] = brand - items = [] - if conditions: - items = frappe.db.sql_list( - """select name from `tabItem` item where {}""".format(" and ".join(conditions)), filters - ) - return items + return frappe.get_all("Item", filters=item_filters, pluck="name", order_by=None, debug=1) def get_item_details(items, sle, filters: StockBalanceFilter): @@ -416,7 +424,7 @@ def get_item_details(items, sle, filters: StockBalanceFilter): for item in res: item_details.setdefault(item.name, item) - if filters.get("show_variant_attributes", 0) == 1: + if filters.get("show_variant_attributes"): variant_values = get_variant_values_for(list(item_details)) item_details = {k: v.update(variant_values.get(k, {})) for k, v in item_details.items()} @@ -443,7 +451,7 @@ def get_item_reorder_details(items): def get_variants_attributes(): """Return all item variant attributes.""" - return [i.name for i in frappe.get_all("Item Attribute")] + return frappe.get_all("Item Attribute", pluck="name") def get_variant_values_for(items): diff --git a/erpnext/stock/report/stock_balance/test_stock_balance.py b/erpnext/stock/report/stock_balance/test_stock_balance.py index 2783d278780..111bdc9a7e5 100644 --- a/erpnext/stock/report/stock_balance/test_stock_balance.py +++ b/erpnext/stock/report/stock_balance/test_stock_balance.py @@ -38,11 +38,9 @@ class TestStockBalance(FrappeTestCase): def generate_stock_ledger(self, item_code: str, movements): for movement in map(_dict, movements): - make_stock_entry( - item_code=item_code, - **movement, - to_warehouse=movement.to_warehouse or "_Test Warehouse - _TC", - ) + if "to_warehouse" not in movement: + movement.to_warehouse = "_Test Warehouse - _TC" + make_stock_entry(item_code=item_code, **movement) def assertInvariants(self, rows): last_balance = frappe.db.sql( @@ -135,3 +133,20 @@ class TestStockBalance(FrappeTestCase): rows = stock_balance(self.filters.update({"include_uom": "Box"})) self.assertEqual(rows[0].bal_qty_alt, 1) + + def test_item_group(self): + self.filters.pop("item_code", None) + rows = stock_balance(self.filters.update({"item_group": self.item.item_group})) + self.assertTrue(all(r.item_group == self.item.item_group for r in rows)) + + def test_child_warehouse_balances(self): + # This is default + self.generate_stock_ledger(self.item.name, [_dict(qty=5, rate=10, to_warehouse="Stores - _TC")]) + + self.filters.pop("item_code", None) + rows = stock_balance(self.filters.update({"warehouse": "All Warehouses - _TC"})) + + self.assertTrue( + any(r.item_code == self.item.name and r.warehouse == "Stores - _TC" for r in rows), + msg=f"Expected child warehouse balances \n{rows}", + ) From e278ee359aabf20eb52199bc25d4ba2a52929556 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 12 Apr 2022 12:41:56 +0530 Subject: [PATCH 08/19] test: item attribute columns --- .../stock_balance/test_stock_balance.py | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/report/stock_balance/test_stock_balance.py b/erpnext/stock/report/stock_balance/test_stock_balance.py index 111bdc9a7e5..9130e8d1a4e 100644 --- a/erpnext/stock/report/stock_balance/test_stock_balance.py +++ b/erpnext/stock/report/stock_balance/test_stock_balance.py @@ -31,7 +31,7 @@ class TestStockBalance(FrappeTestCase): def tearDown(self): frappe.db.rollback() - def assertPartialDictionary(self, expected: Dict[str, Any], actual: Dict[str, Any]): + def assertPartialDictEq(self, expected: Dict[str, Any], actual: Dict[str, Any]): for k, v in expected.items(): self.assertEqual(v, actual[k], msg=f"{expected=}\n{actual=}") @@ -90,7 +90,7 @@ class TestStockBalance(FrappeTestCase): # check item info rows = stock_balance(self.filters) - self.assertPartialDictionary( + self.assertPartialDictEq( { "item_code": self.item.name, "item_name": self.item.item_name, @@ -118,11 +118,11 @@ class TestStockBalance(FrappeTestCase): rows = stock_balance(self.filters.update({"from_date": "2021-01-02"})) self.assertInvariants(rows) - self.assertPartialDictionary({"opening_qty": 1, "in_qty": 5}, rows[0]) + self.assertPartialDictEq({"opening_qty": 1, "in_qty": 5}, rows[0]) rows = stock_balance(self.filters.update({"from_date": "2022-01-01"})) self.assertInvariants(rows) - self.assertPartialDictionary({"opening_qty": 6, "in_qty": 0}, rows[0]) + self.assertPartialDictEq({"opening_qty": 6, "in_qty": 0}, rows[0]) def test_uom_converted_info(self): @@ -150,3 +150,20 @@ class TestStockBalance(FrappeTestCase): any(r.item_code == self.item.name and r.warehouse == "Stores - _TC" for r in rows), msg=f"Expected child warehouse balances \n{rows}", ) + + def test_show_item_attr(self): + from erpnext.controllers.item_variant import create_variant + + self.item.has_variants = True + self.item.append("attributes", {"attribute": "Test Size"}) + self.item.save() + + attributes = {"Test Size": "Large"} + variant = create_variant(self.item.name, attributes) + variant.save() + + self.generate_stock_ledger(variant.name, [_dict(qty=5, rate=10)]) + rows = stock_balance( + self.filters.update({"show_variant_attributes": 1, "item_code": variant.name}) + ) + self.assertPartialDictEq(attributes, rows[0]) From ba29323e116e525b898e0e685511c08118e2cf2d Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 12 Apr 2022 12:51:40 +0530 Subject: [PATCH 09/19] test: increase assertions to cover all cases --- erpnext/stock/report/stock_balance/stock_balance.py | 2 +- .../stock/report/stock_balance/test_stock_balance.py | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index 7fa417ac310..e5ea8e06121 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -387,7 +387,7 @@ def get_items(filters: StockBalanceFilter): if brand := filters.get("brand"): item_filters["brand"] = brand - return frappe.get_all("Item", filters=item_filters, pluck="name", order_by=None, debug=1) + return frappe.get_all("Item", filters=item_filters, pluck="name", order_by=None) def get_item_details(items, sle, filters: StockBalanceFilter): diff --git a/erpnext/stock/report/stock_balance/test_stock_balance.py b/erpnext/stock/report/stock_balance/test_stock_balance.py index 9130e8d1a4e..09054fb9728 100644 --- a/erpnext/stock/report/stock_balance/test_stock_balance.py +++ b/erpnext/stock/report/stock_balance/test_stock_balance.py @@ -71,14 +71,16 @@ class TestStockBalance(FrappeTestCase): # value invariant self.assertAlmostEqual(row.bal_val, row.opening_val + row.in_val - row.out_val, msg) - # valuation rate - self.assertAlmostEqual(row.val_rate, row.bal_val / row.bal_qty, 3, msg) - # check against SLE last_sle = item_wh_stock[(row.item_code, row.warehouse)] self.assertAlmostEqual(row.bal_qty, last_sle.qty_after_transaction, 3) self.assertAlmostEqual(row.bal_val, last_sle.stock_value, 3) + # valuation rate + if not row.bal_qty: + continue + self.assertAlmostEqual(row.val_rate, row.bal_val / row.bal_qty, 3, msg) + # ----------- tests def test_basic_stock_balance(self): @@ -133,6 +135,7 @@ class TestStockBalance(FrappeTestCase): rows = stock_balance(self.filters.update({"include_uom": "Box"})) self.assertEqual(rows[0].bal_qty_alt, 1) + self.assertInvariants(rows) def test_item_group(self): self.filters.pop("item_code", None) @@ -167,3 +170,4 @@ class TestStockBalance(FrappeTestCase): self.filters.update({"show_variant_attributes": 1, "item_code": variant.name}) ) self.assertPartialDictEq(attributes, rows[0]) + self.assertInvariants(rows) From 9af2d689455eb51ee527f900b2b437497beb62ae Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 14 Apr 2022 13:52:07 +0530 Subject: [PATCH 10/19] refactor: convert queries to ORM/QB, add types --- .../report/stock_balance/stock_balance.py | 94 ++++++++++--------- .../stock_balance/test_stock_balance.py | 3 +- 2 files changed, 50 insertions(+), 47 deletions(-) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index e5ea8e06121..6369f910a41 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -3,7 +3,7 @@ from operator import itemgetter -from typing import Optional, TypedDict +from typing import Any, Dict, List, Optional, TypedDict import frappe from frappe import _ @@ -30,6 +30,9 @@ class StockBalanceFilter(TypedDict): show_variant_attributes: bool +SLEntry = Dict[str, Any] + + def execute(filters: Optional[StockBalanceFilter] = None): is_reposting_item_valuation_in_progress() if not filters: @@ -267,7 +270,7 @@ def apply_conditions(query, filters): return query -def get_stock_ledger_entries(filters: StockBalanceFilter, items): +def get_stock_ledger_entries(filters: StockBalanceFilter, items: List[str]) -> List[SLEntry]: sle = frappe.qb.DocType("Stock Ledger Entry") query = ( @@ -300,7 +303,7 @@ def get_stock_ledger_entries(filters: StockBalanceFilter, items): return query.run(as_dict=True) -def get_item_warehouse_map(filters: StockBalanceFilter, sle): +def get_item_warehouse_map(filters: StockBalanceFilter, sle: List[SLEntry]): iwb_map = {} from_date = getdate(filters.get("from_date")) to_date = getdate(filters.get("to_date")) @@ -358,7 +361,7 @@ def get_item_warehouse_map(filters: StockBalanceFilter, sle): return iwb_map -def filter_items_with_no_transactions(iwb_map, float_precision): +def filter_items_with_no_transactions(iwb_map, float_precision: float): for (company, item, warehouse) in sorted(iwb_map): qty_dict = iwb_map[(company, item, warehouse)] @@ -375,7 +378,7 @@ def filter_items_with_no_transactions(iwb_map, float_precision): return iwb_map -def get_items(filters: StockBalanceFilter): +def get_items(filters: StockBalanceFilter) -> List[str]: "Get items based on item code, item group or brand." if item_code := filters.get("item_code"): return [item_code] @@ -390,7 +393,7 @@ def get_items(filters: StockBalanceFilter): return frappe.get_all("Item", filters=item_filters, pluck="name", order_by=None) -def get_item_details(items, sle, filters: StockBalanceFilter): +def get_item_details(items: List[str], sle: List[SLEntry], filters: StockBalanceFilter): item_details = {} if not items: items = list(set(d.item_code for d in sle)) @@ -398,31 +401,33 @@ def get_item_details(items, sle, filters: StockBalanceFilter): if not items: return item_details - cf_field = cf_join = "" - if filters.get("include_uom"): - cf_field = ", ucd.conversion_factor" - cf_join = ( - "left join `tabUOM Conversion Detail` ucd on ucd.parent=item.name and ucd.uom=%s" - % frappe.db.escape(filters.get("include_uom")) - ) + item_table = frappe.qb.DocType("Item") - res = frappe.db.sql( - """ - select - item.name, item.item_name, item.description, item.item_group, item.brand, item.stock_uom %s - from - `tabItem` item - %s - where - item.name in (%s) - """ - % (cf_field, cf_join, ",".join(["%s"] * len(items))), - items, - as_dict=1, + query = ( + frappe.qb.from_(item_table) + .select( + item_table.name, + item_table.item_name, + item_table.description, + item_table.item_group, + item_table.brand, + item_table.stock_uom, + ) + .where(item_table.name.isin(items)) ) - for item in res: - item_details.setdefault(item.name, item) + if uom := filters.get("include_uom"): + uom_conv_detail = frappe.qb.DocType("UOM Conversion Detail") + query = ( + query.left_join(uom_conv_detail) + .on((uom_conv_detail.parent == item_table.name) & (uom_conv_detail.uom == uom)) + .select(uom_conv_detail.conversion_factor) + ) + + result = query.run(as_dict=1) + + for item_table in result: + item_details.setdefault(item_table.name, item_table) if filters.get("show_variant_attributes"): variant_values = get_variant_values_for(list(item_details)) @@ -435,21 +440,16 @@ def get_item_reorder_details(items): item_reorder_details = frappe._dict() if items: - item_reorder_details = frappe.db.sql( - """ - select parent, warehouse, warehouse_reorder_qty, warehouse_reorder_level - from `tabItem Reorder` - where parent in ({0}) - """.format( - ", ".join(frappe.db.escape(i, percent=False) for i in items) - ), - as_dict=1, + item_reorder_details = frappe.get_all( + "Item Reorder", + ["parent", "warehouse", "warehouse_reorder_qty", "warehouse_reorder_level"], + filters={"parent": ("in", items)}, ) return dict((d.parent + d.warehouse, d) for d in item_reorder_details) -def get_variants_attributes(): +def get_variants_attributes() -> List[str]: """Return all item variant attributes.""" return frappe.get_all("Item Attribute", pluck="name") @@ -457,14 +457,16 @@ def get_variants_attributes(): def get_variant_values_for(items): """Returns variant values for items.""" attribute_map = {} - for attr in frappe.db.sql( - """select parent, attribute, attribute_value - from `tabItem Variant Attribute` where parent in (%s) - """ - % ", ".join(["%s"] * len(items)), - tuple(items), - as_dict=1, - ): + + attribute_info = frappe.get_all( + "Item Variant Attribute", + ["parent", "attribute", "attribute_value"], + { + "parent": ("in", items), + }, + ) + + for attr in attribute_info: attribute_map.setdefault(attr["parent"], {}) attribute_map[attr["parent"]].update({attr["attribute"]: attr["attribute_value"]}) diff --git a/erpnext/stock/report/stock_balance/test_stock_balance.py b/erpnext/stock/report/stock_balance/test_stock_balance.py index 09054fb9728..e963de293ab 100644 --- a/erpnext/stock/report/stock_balance/test_stock_balance.py +++ b/erpnext/stock/report/stock_balance/test_stock_balance.py @@ -11,7 +11,8 @@ from erpnext.stock.report.stock_balance.stock_balance import execute def stock_balance(filters): - return list(map(_dict, execute(filters)[1])) + """Get rows from stock balance report""" + return [_dict(row) for row in execute(filters)[1]] class TestStockBalance(FrappeTestCase): From 72757994f8a8fd19d7ed666b7cf93a2fb3369947 Mon Sep 17 00:00:00 2001 From: Bhavesh Maheshwari <34086262+bhavesh95863@users.noreply.github.com> Date: Fri, 25 Mar 2022 11:27:19 +0530 Subject: [PATCH 11/19] fix: process statement to_date override (cherry picked from commit 378d15d388ae9cac7a5f897af83c99605403503a) --- .../process_statement_of_accounts.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py index fea55a3f289..01f716daa21 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py @@ -34,8 +34,9 @@ class ProcessStatementOfAccounts(Document): frappe.throw(_("Customers not selected.")) if self.enable_auto_email: - self.to_date = self.start_date - self.from_date = add_months(self.to_date, -1 * self.filter_duration) + if self.start_date and getdate(self.start_date) >= getdate(today()): + self.to_date = self.start_date + self.from_date = add_months(self.to_date, -1 * self.filter_duration) def get_report_pdf(doc, consolidated=True): From 0a67b0239e6dfac0dd5f30bf73df7d7834313afd Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 16 Apr 2022 19:43:59 +0530 Subject: [PATCH 12/19] fix: Consistent customer and supplier forms --- erpnext/buying/doctype/supplier/supplier.json | 23 ++++++++++--------- erpnext/hooks.py | 1 + .../selling/doctype/customer/customer.json | 21 +++++++++-------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json index a57d9a92bb3..e0ee658c18a 100644 --- a/erpnext/buying/doctype/supplier/supplier.json +++ b/erpnext/buying/doctype/supplier/supplier.json @@ -18,16 +18,16 @@ "tax_id", "tax_category", "tax_withholding_category", - "is_transporter", - "is_internal_supplier", - "represents_company", "image", "column_break0", "supplier_group", "supplier_type", "allow_purchase_invoice_creation_without_purchase_order", "allow_purchase_invoice_creation_without_purchase_receipt", + "is_internal_supplier", + "represents_company", "disabled", + "is_transporter", "warn_rfqs", "warn_pos", "prevent_rfqs", @@ -38,12 +38,6 @@ "default_currency", "column_break_10", "default_price_list", - "section_credit_limit", - "payment_terms", - "cb_21", - "on_hold", - "hold_type", - "release_date", "address_contacts", "address_html", "column_break1", @@ -57,6 +51,12 @@ "primary_address", "default_payable_accounts", "accounts", + "section_credit_limit", + "payment_terms", + "cb_21", + "on_hold", + "hold_type", + "release_date", "default_tax_withholding_config", "column_break2", "website", @@ -258,7 +258,7 @@ "collapsible": 1, "fieldname": "section_credit_limit", "fieldtype": "Section Break", - "label": "Credit Limit" + "label": "Payment Terms" }, { "fieldname": "payment_terms", @@ -432,7 +432,7 @@ "link_fieldname": "party" } ], - "modified": "2021-10-20 22:03:33.147249", + "modified": "2022-04-16 18:02:27.838623", "modified_by": "Administrator", "module": "Buying", "name": "Supplier", @@ -497,6 +497,7 @@ "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "ASC", + "states": [], "title_field": "supplier_name", "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 1c009d3a893..fe0a89a2769 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -59,6 +59,7 @@ treeviews = [ "Warehouse", "Item Group", "Customer Group", + "Supplier Group", "Sales Person", "Territory", "Assessment Group", diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index ae406306170..1d0950da861 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -15,23 +15,23 @@ "salutation", "customer_name", "gender", - "customer_type", "tax_withholding_category", "default_bank_account", + "tax_id", + "tax_category", "lead_name", "opportunity_name", "image", "column_break0", - "account_manager", "customer_group", + "customer_type", "territory", - "tax_id", - "tax_category", + "account_manager", "so_required", "dn_required", - "disabled", "is_internal_customer", "represents_company", + "disabled", "allowed_to_transact_section", "companies", "currency_and_price_list", @@ -40,7 +40,6 @@ "default_price_list", "address_contacts", "address_html", - "website", "column_break1", "contact_html", "primary_address_and_contact_detail", @@ -60,6 +59,7 @@ "column_break_45", "market_segment", "industry", + "website", "language", "is_frozen", "column_break_38", @@ -100,7 +100,7 @@ "fieldname": "customer_name", "fieldtype": "Data", "in_global_search": 1, - "label": "Full Name", + "label": "Customer Name", "no_copy": 1, "oldfieldname": "customer_name", "oldfieldtype": "Data", @@ -118,7 +118,7 @@ "default": "Company", "fieldname": "customer_type", "fieldtype": "Select", - "label": "Type", + "label": "Customer Type", "oldfieldname": "customer_type", "oldfieldtype": "Select", "options": "Company\nIndividual", @@ -337,7 +337,7 @@ "collapsible": 1, "fieldname": "default_receivable_accounts", "fieldtype": "Section Break", - "label": "Accounting" + "label": "Default Receivable Accounts" }, { "description": "Mention if non-standard receivable account", @@ -511,7 +511,7 @@ "link_fieldname": "party" } ], - "modified": "2021-10-20 22:07:52.485809", + "modified": "2022-04-16 18:02:24.499110", "modified_by": "Administrator", "module": "Selling", "name": "Customer", @@ -595,6 +595,7 @@ "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "ASC", + "states": [], "title_field": "customer_name", "track_changes": 1 } \ No newline at end of file From 5cdd0d671989d398d9683cdf55932b96343cb420 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 16 Apr 2022 20:34:56 +0530 Subject: [PATCH 13/19] fix: Move tax withholding category field --- erpnext/selling/doctype/customer/customer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index 1d0950da861..7cba141eec0 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -15,10 +15,10 @@ "salutation", "customer_name", "gender", - "tax_withholding_category", "default_bank_account", "tax_id", "tax_category", + "tax_withholding_category", "lead_name", "opportunity_name", "image", @@ -511,7 +511,7 @@ "link_fieldname": "party" } ], - "modified": "2022-04-16 18:02:24.499110", + "modified": "2022-04-16 20:32:34.000304", "modified_by": "Administrator", "module": "Selling", "name": "Customer", From 9c081947ec65c86ed54b4bddf022ef50b16cbbec Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 18 Apr 2022 10:21:15 +0530 Subject: [PATCH 14/19] fix: Price changing on creating Sales retrun from Delivery Note --- erpnext/public/js/controllers/transaction.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index c9faf683f92..767221e99d0 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1388,6 +1388,11 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe return; } + // Target doc created from a mapped doc + if (this.frm.doc.__onload && this.frm.doc.__onload.ignore_price_list) { + return; + } + return this.frm.call({ method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.apply_pricing_rule", args: { args: args, doc: me.frm.doc }, @@ -1504,7 +1509,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe me.remove_pricing_rule(frappe.get_doc(d.doctype, d.name)); } - if (d.free_item_data) { + if (d.free_item_data.length > 0) { me.apply_product_discount(d); } From 41249c57c436e8ceb4b1737a7de824f8b7e80dbd Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 18 Apr 2022 10:38:22 +0530 Subject: [PATCH 15/19] chore: Add sematic releases --- .github/workflows/release.yml | 25 +++++++++++++++++++++++++ .releaserc | 25 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 .github/workflows/release.yml create mode 100644 .releaserc diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000000..0fff48a2678 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,25 @@ +name: Generate Semantic Release +on: + push: + branches: + - test-release +jobs: + release: + name: Release + runs-on: ubuntu-18.04 + steps: + - name: Checkout Entire Repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Setup Node.js v14 + uses: actions/setup-node@v2 + with: + node-version: 14 + - name: Setup dependencies + run: | + npm install @semantic-release/git @semantic-release/exec --no-save + - name: Create Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: npx semantic-release \ No newline at end of file diff --git a/.releaserc b/.releaserc new file mode 100644 index 00000000000..4ac5466f6c0 --- /dev/null +++ b/.releaserc @@ -0,0 +1,25 @@ +{ + "branches": ["version-13"], + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + [ + "@semantic-release/exec", { + "prepareCmd": 'sed -ir "s/[0-9]*\.[0-9]*\.[0-9]*/${nextRelease.version}/" erpnext/__init__.py' + } + ], + [ + "@semantic-release/git", { + "assets": ["erpnext/__init__.py"], + "message": "chore(release): Bumped to Version ${nextRelease.version}\n\n${nextRelease.notes}" + } + ], + [ + "@semantic-release/github", { + "assets": [ + {"path": "dist/*"}, + ] + } + ] + ] +} \ No newline at end of file From cc1bdd426b188d450fac9f7604ad6e9b52696d59 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 18 Apr 2022 10:48:31 +0530 Subject: [PATCH 16/19] chore: Update branch name --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0fff48a2678..5c4ece5416e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,7 +2,7 @@ name: Generate Semantic Release on: push: branches: - - test-release + - version-13 jobs: release: name: Release From c12a36aed90c82794a1092d1f5a1d9ff25d40040 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 18 Apr 2022 13:05:56 +0530 Subject: [PATCH 17/19] chore: block major releases --- .releaserc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.releaserc b/.releaserc index 4ac5466f6c0..4d2c1333f07 100644 --- a/.releaserc +++ b/.releaserc @@ -1,7 +1,12 @@ { "branches": ["version-13"], "plugins": [ - "@semantic-release/commit-analyzer", + "@semantic-release/commit-analyzer", { + "preset": "angular", + "releaseRules": [ + {"breaking": true, "release": false} + ] + }, "@semantic-release/release-notes-generator", [ "@semantic-release/exec", { From 6fc11cb4c57264574cd64ccf588feae88b1236e5 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 18 Apr 2022 16:17:36 +0530 Subject: [PATCH 18/19] ci: use latest ubuntu container --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5c4ece5416e..532485f21f9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,7 @@ on: jobs: release: name: Release - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - name: Checkout Entire Repository uses: actions/checkout@v2 From e0a9a69d764c015ea6be287b31686ebb764a7067 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 18 Apr 2022 16:45:01 +0530 Subject: [PATCH 19/19] chore: do not publish any assets --- .releaserc | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.releaserc b/.releaserc index 4d2c1333f07..8a758ed30a6 100644 --- a/.releaserc +++ b/.releaserc @@ -19,12 +19,6 @@ "message": "chore(release): Bumped to Version ${nextRelease.version}\n\n${nextRelease.notes}" } ], - [ - "@semantic-release/github", { - "assets": [ - {"path": "dist/*"}, - ] - } - ] + "@semantic-release/github" ] } \ No newline at end of file