From 2bdaf7bb2313cf8fff48732abf99d9781e9b3f75 Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Thu, 21 Oct 2021 20:23:04 +0200 Subject: [PATCH 1/9] fix: don't reset rates in Timesheet Detail when Activity Type is cleared (#28056) * fix: don't reset rates when activity type is cleared * refactor: suggestions from review Co-authored-by: Sagar Vora * refactor: suggestions from review (fix) * style: fix sider * fix: sider issue Co-authored-by: Sagar Vora --- erpnext/projects/doctype/timesheet/timesheet.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index 65a8566a274..f615f051f0c 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -283,7 +283,9 @@ frappe.ui.form.on("Timesheet Detail", { calculate_time_and_amount(frm); }, - activity_type: function(frm, cdt, cdn) { + activity_type: function (frm, cdt, cdn) { + if (!frappe.get_doc(cdt, cdn).activity_type) return; + frappe.call({ method: "erpnext.projects.doctype.timesheet.timesheet.get_activity_cost", args: { @@ -291,10 +293,10 @@ frappe.ui.form.on("Timesheet Detail", { activity_type: frm.selected_doc.activity_type, currency: frm.doc.currency }, - callback: function(r){ - if(r.message){ - frappe.model.set_value(cdt, cdn, 'billing_rate', r.message['billing_rate']); - frappe.model.set_value(cdt, cdn, 'costing_rate', r.message['costing_rate']); + callback: function (r) { + if (r.message) { + frappe.model.set_value(cdt, cdn, "billing_rate", r.message["billing_rate"]); + frappe.model.set_value(cdt, cdn, "costing_rate", r.message["costing_rate"]); calculate_billing_costing_amount(frm, cdt, cdn); } } From cc1baae5eb738a821e4e3c14987acc71b5f6318f Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 22 Oct 2021 21:43:50 +0530 Subject: [PATCH 2/9] ci: move semgrep rules out of repo (#28067) Moving semgrep rules out of repos as it's unnecessary to maintain same ruleset for different repos and different branches. --- .github/helper/semgrep_rules/README.md | 38 ---- .../semgrep_rules/frappe_correctness.py | 64 ------- .../semgrep_rules/frappe_correctness.yml | 163 ------------------ .github/helper/semgrep_rules/report.py | 15 -- .github/helper/semgrep_rules/report.yml | 34 ---- .github/helper/semgrep_rules/security.py | 6 - .github/helper/semgrep_rules/security.yml | 10 -- .github/helper/semgrep_rules/translate.js | 44 ----- .github/helper/semgrep_rules/translate.py | 61 ------- .github/helper/semgrep_rules/translate.yml | 64 ------- .github/helper/semgrep_rules/ux.js | 9 - .github/helper/semgrep_rules/ux.py | 31 ---- .github/helper/semgrep_rules/ux.yml | 30 ---- .github/workflows/linters.yml | 5 +- 14 files changed, 4 insertions(+), 570 deletions(-) delete mode 100644 .github/helper/semgrep_rules/README.md delete mode 100644 .github/helper/semgrep_rules/frappe_correctness.py delete mode 100644 .github/helper/semgrep_rules/frappe_correctness.yml delete mode 100644 .github/helper/semgrep_rules/report.py delete mode 100644 .github/helper/semgrep_rules/report.yml delete mode 100644 .github/helper/semgrep_rules/security.py delete mode 100644 .github/helper/semgrep_rules/security.yml delete mode 100644 .github/helper/semgrep_rules/translate.js delete mode 100644 .github/helper/semgrep_rules/translate.py delete mode 100644 .github/helper/semgrep_rules/translate.yml delete mode 100644 .github/helper/semgrep_rules/ux.js delete mode 100644 .github/helper/semgrep_rules/ux.py delete mode 100644 .github/helper/semgrep_rules/ux.yml diff --git a/.github/helper/semgrep_rules/README.md b/.github/helper/semgrep_rules/README.md deleted file mode 100644 index 670d8d280f2..00000000000 --- a/.github/helper/semgrep_rules/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# Semgrep linting - -## What is semgrep? -Semgrep or "semantic grep" is language agnostic static analysis tool. In simple terms semgrep is syntax-aware `grep`, so unlike regex it doesn't get confused by different ways of writing same thing or whitespaces or code split in multiple lines etc. - -Example: - -To check if a translate function is using f-string or not the regex would be `r"_\(\s*f[\"']"` while equivalent rule in semgrep would be `_(f"...")`. As semgrep knows grammer of language it takes care of unnecessary whitespace, type of quotation marks etc. - -You can read more such examples in `.github/helper/semgrep_rules` directory. - -# Why/when to use this? -We want to maintain quality of contributions, at the same time remembering all the good practices can be pain to deal with while evaluating contributions. Using semgrep if you can translate "best practice" into a rule then it can automate the task for us. - -## Running locally - -Install semgrep using homebrew `brew install semgrep` or pip `pip install semgrep`. - -To run locally use following command: - -`semgrep --config=.github/helper/semgrep_rules [file/folder names]` - -## Testing -semgrep allows testing the tests. Refer to this page: https://semgrep.dev/docs/writing-rules/testing-rules/ - -When writing new rules you should write few positive and few negative cases as shown in the guide and current tests. - -To run current tests: `semgrep --test --test-ignore-todo .github/helper/semgrep_rules` - - -## Reference - -If you are new to Semgrep read following pages to get started on writing/modifying rules: - -- https://semgrep.dev/docs/getting-started/ -- https://semgrep.dev/docs/writing-rules/rule-syntax -- https://semgrep.dev/docs/writing-rules/pattern-examples/ -- https://semgrep.dev/docs/writing-rules/rule-ideas/#common-use-cases diff --git a/.github/helper/semgrep_rules/frappe_correctness.py b/.github/helper/semgrep_rules/frappe_correctness.py deleted file mode 100644 index 83d4acfe4ab..00000000000 --- a/.github/helper/semgrep_rules/frappe_correctness.py +++ /dev/null @@ -1,64 +0,0 @@ -import frappe -from frappe import _ - -from frappe.model.document import Document - - -# ruleid: frappe-modifying-but-not-comitting -def on_submit(self): - if self.value_of_goods == 0: - frappe.throw(_('Value of goods cannot be 0')) - self.status = 'Submitted' - - -# ok: frappe-modifying-but-not-comitting -def on_submit(self): - if self.value_of_goods == 0: - frappe.throw(_('Value of goods cannot be 0')) - self.status = 'Submitted' - self.db_set('status', 'Submitted') - -# ok: frappe-modifying-but-not-comitting -def on_submit(self): - if self.value_of_goods == 0: - frappe.throw(_('Value of goods cannot be 0')) - x = "y" - self.status = x - self.db_set('status', x) - - -# ok: frappe-modifying-but-not-comitting -def on_submit(self): - x = "y" - self.status = x - self.save() - -# ruleid: frappe-modifying-but-not-comitting-other-method -class DoctypeClass(Document): - def on_submit(self): - self.good_method() - self.tainted_method() - - def tainted_method(self): - self.status = "uptate" - - -# ok: frappe-modifying-but-not-comitting-other-method -class DoctypeClass(Document): - def on_submit(self): - self.good_method() - self.tainted_method() - - def tainted_method(self): - self.status = "update" - self.db_set("status", "update") - -# ok: frappe-modifying-but-not-comitting-other-method -class DoctypeClass(Document): - def on_submit(self): - self.good_method() - self.tainted_method() - self.save() - - def tainted_method(self): - self.status = "uptate" diff --git a/.github/helper/semgrep_rules/frappe_correctness.yml b/.github/helper/semgrep_rules/frappe_correctness.yml deleted file mode 100644 index 0cf4e78b81d..00000000000 --- a/.github/helper/semgrep_rules/frappe_correctness.yml +++ /dev/null @@ -1,163 +0,0 @@ -# This file specifies rules for correctness according to how frappe doctype data model works. - -rules: -- id: frappe-modifying-but-not-comitting - patterns: - - pattern: | - def $METHOD(self, ...): - ... - self.$ATTR = ... - - pattern-not: | - def $METHOD(self, ...): - ... - self.$ATTR = ... - ... - self.db_set(..., self.$ATTR, ...) - - pattern-not: | - def $METHOD(self, ...): - ... - self.$ATTR = $SOME_VAR - ... - self.db_set(..., $SOME_VAR, ...) - - pattern-not: | - def $METHOD(self, ...): - ... - self.$ATTR = $SOME_VAR - ... - self.save() - - metavariable-regex: - metavariable: '$ATTR' - # this is negative look-ahead, add more attrs to ignore like (ignore|ignore_this_too|ignore_me) - regex: '^(?!ignore_linked_doctypes|status_updater)(.*)$' - - metavariable-regex: - metavariable: "$METHOD" - regex: "(on_submit|on_cancel)" - message: | - DocType modified in self.$METHOD. Please check if modification of self.$ATTR is commited to database. - languages: [python] - severity: ERROR - -- id: frappe-modifying-but-not-comitting-other-method - patterns: - - pattern: | - class $DOCTYPE(...): - def $METHOD(self, ...): - ... - self.$ANOTHER_METHOD() - ... - - def $ANOTHER_METHOD(self, ...): - ... - self.$ATTR = ... - - pattern-not: | - class $DOCTYPE(...): - def $METHOD(self, ...): - ... - self.$ANOTHER_METHOD() - ... - - def $ANOTHER_METHOD(self, ...): - ... - self.$ATTR = ... - ... - self.db_set(..., self.$ATTR, ...) - - pattern-not: | - class $DOCTYPE(...): - def $METHOD(self, ...): - ... - self.$ANOTHER_METHOD() - ... - - def $ANOTHER_METHOD(self, ...): - ... - self.$ATTR = $SOME_VAR - ... - self.db_set(..., $SOME_VAR, ...) - - pattern-not: | - class $DOCTYPE(...): - def $METHOD(self, ...): - ... - self.$ANOTHER_METHOD() - ... - self.save() - def $ANOTHER_METHOD(self, ...): - ... - self.$ATTR = ... - - metavariable-regex: - metavariable: "$METHOD" - regex: "(on_submit|on_cancel)" - message: | - self.$ANOTHER_METHOD is called from self.$METHOD, check if changes to self.$ATTR are commited to database. - languages: [python] - severity: ERROR - -- id: frappe-print-function-in-doctypes - pattern: print(...) - message: | - Did you mean to leave this print statement in? Consider using msgprint or logger instead of print statement. - languages: [python] - severity: WARNING - paths: - include: - - "*/**/doctype/*" - -- id: frappe-modifying-child-tables-while-iterating - pattern-either: - - pattern: | - for $ROW in self.$TABLE: - ... - self.remove(...) - - pattern: | - for $ROW in self.$TABLE: - ... - self.append(...) - message: | - Child table being modified while iterating on it. - languages: [python] - severity: ERROR - paths: - include: - - "*/**/doctype/*" - -- id: frappe-same-key-assigned-twice - pattern-either: - - pattern: | - {..., $X: $A, ..., $X: $B, ...} - - pattern: | - dict(..., ($X, $A), ..., ($X, $B), ...) - - pattern: | - _dict(..., ($X, $A), ..., ($X, $B), ...) - message: | - key `$X` is uselessly assigned twice. This could be a potential bug. - languages: [python] - severity: ERROR - -- id: frappe-manual-commit - patterns: - - pattern: frappe.db.commit() - - pattern-not-inside: | - try: - ... - except ...: - ... - message: | - Manually commiting a transaction is highly discouraged. Read about the transaction model implemented by Frappe Framework before adding manual commits: https://frappeframework.com/docs/user/en/api/database#database-transaction-model If you think manual commit is required then add a comment explaining why and `// nosemgrep` on the same line. - paths: - exclude: - - "**/patches/**" - - "**/demo/**" - languages: [python] - severity: ERROR - -- id: frappe-using-db-sql - pattern-either: - - pattern: frappe.db.sql(...) - - pattern: frappe.db.sql_ddl(...) - - pattern: frappe.db.sql_list(...) - paths: - exclude: - - "test_*.py" - message: | - The PR contains a SQL query that may be re-written with frappe.qb (https://frappeframework.com/docs/user/en/api/query-builder) or the Database API (https://frappeframework.com/docs/user/en/api/database) - languages: [python] - severity: ERROR \ No newline at end of file diff --git a/.github/helper/semgrep_rules/report.py b/.github/helper/semgrep_rules/report.py deleted file mode 100644 index ff278408e18..00000000000 --- a/.github/helper/semgrep_rules/report.py +++ /dev/null @@ -1,15 +0,0 @@ -from frappe import _ - - -# ruleid: frappe-missing-translate-function-in-report-python -{"label": "Field Label"} - -# ruleid: frappe-missing-translate-function-in-report-python -dict(label="Field Label") - - -# ok: frappe-missing-translate-function-in-report-python -{"label": _("Field Label")} - -# ok: frappe-missing-translate-function-in-report-python -dict(label=_("Field Label")) diff --git a/.github/helper/semgrep_rules/report.yml b/.github/helper/semgrep_rules/report.yml deleted file mode 100644 index f2a9b167399..00000000000 --- a/.github/helper/semgrep_rules/report.yml +++ /dev/null @@ -1,34 +0,0 @@ -rules: -- id: frappe-missing-translate-function-in-report-python - paths: - include: - - "**/report" - exclude: - - "**/regional" - pattern-either: - - patterns: - - pattern: | - {..., "label": "...", ...} - - pattern-not: | - {..., "label": _("..."), ...} - - patterns: - - pattern: dict(..., label="...", ...) - - pattern-not: dict(..., label=_("..."), ...) - message: | - All user facing text must be wrapped in translate function. Please refer to translation documentation. https://frappeframework.com/docs/user/en/guides/basics/translations - languages: [python] - severity: ERROR - -- id: frappe-translated-values-in-business-logic - paths: - include: - - "**/report" - patterns: - - pattern-inside: | - {..., filters: [...], ...} - - pattern: | - {..., options: [..., __("..."), ...], ...} - message: | - Using translated values in options field will require you to translate the values while comparing in business logic. Instead of passing translated labels provide objects that contain both label and value. e.g. { label: __("Option value"), value: "Option value"} - languages: [javascript] - severity: ERROR diff --git a/.github/helper/semgrep_rules/security.py b/.github/helper/semgrep_rules/security.py deleted file mode 100644 index f477d7c1768..00000000000 --- a/.github/helper/semgrep_rules/security.py +++ /dev/null @@ -1,6 +0,0 @@ -def function_name(input): - # ruleid: frappe-codeinjection-eval - eval(input) - -# ok: frappe-codeinjection-eval -eval("1 + 1") diff --git a/.github/helper/semgrep_rules/security.yml b/.github/helper/semgrep_rules/security.yml deleted file mode 100644 index 8b219792080..00000000000 --- a/.github/helper/semgrep_rules/security.yml +++ /dev/null @@ -1,10 +0,0 @@ -rules: -- id: frappe-codeinjection-eval - patterns: - - pattern-not: eval("...") - - pattern: eval(...) - message: | - Detected the use of eval(). eval() can be dangerous if used to evaluate - dynamic content. Avoid it or use safe_eval(). - languages: [python] - severity: ERROR diff --git a/.github/helper/semgrep_rules/translate.js b/.github/helper/semgrep_rules/translate.js deleted file mode 100644 index 9cdfb75d0be..00000000000 --- a/.github/helper/semgrep_rules/translate.js +++ /dev/null @@ -1,44 +0,0 @@ -// ruleid: frappe-translation-empty-string -__("") -// ruleid: frappe-translation-empty-string -__('') - -// ok: frappe-translation-js-formatting -__('Welcome {0}, get started with ERPNext in just a few clicks.', [full_name]); - -// ruleid: frappe-translation-js-formatting -__(`Welcome ${full_name}, get started with ERPNext in just a few clicks.`); - -// ok: frappe-translation-js-formatting -__('This is fine'); - - -// ok: frappe-translation-trailing-spaces -__('This is fine'); - -// ruleid: frappe-translation-trailing-spaces -__(' this is not ok '); -// ruleid: frappe-translation-trailing-spaces -__('this is not ok '); -// ruleid: frappe-translation-trailing-spaces -__(' this is not ok'); - -// ok: frappe-translation-js-splitting -__('You have {0} subscribers in your mailing list.', [subscribers.length]) - -// todoruleid: frappe-translation-js-splitting -__('You have') + subscribers.length + __('subscribers in your mailing list.') - -// ruleid: frappe-translation-js-splitting -__('You have' + 'subscribers in your mailing list.') - -// ruleid: frappe-translation-js-splitting -__('You have {0} subscribers' + - 'in your mailing list', [subscribers.length]) - -// ok: frappe-translation-js-splitting -__("Ctrl+Enter to add comment") - -// ruleid: frappe-translation-js-splitting -__('You have {0} subscribers \ - in your mailing list', [subscribers.length]) diff --git a/.github/helper/semgrep_rules/translate.py b/.github/helper/semgrep_rules/translate.py deleted file mode 100644 index 9de6aa94f01..00000000000 --- a/.github/helper/semgrep_rules/translate.py +++ /dev/null @@ -1,61 +0,0 @@ -# Examples taken from https://frappeframework.com/docs/user/en/translations -# This file is used for testing the tests. - -from frappe import _ - -full_name = "Jon Doe" -# ok: frappe-translation-python-formatting -_('Welcome {0}, get started with ERPNext in just a few clicks.').format(full_name) - -# ruleid: frappe-translation-python-formatting -_('Welcome %s, get started with ERPNext in just a few clicks.' % full_name) -# ruleid: frappe-translation-python-formatting -_('Welcome %(name)s, get started with ERPNext in just a few clicks.' % {'name': full_name}) - -# ruleid: frappe-translation-python-formatting -_('Welcome {0}, get started with ERPNext in just a few clicks.'.format(full_name)) - - -subscribers = ["Jon", "Doe"] -# ok: frappe-translation-python-formatting -_('You have {0} subscribers in your mailing list.').format(len(subscribers)) - -# ruleid: frappe-translation-python-splitting -_('You have') + len(subscribers) + _('subscribers in your mailing list.') - -# ruleid: frappe-translation-python-splitting -_('You have {0} subscribers \ - in your mailing list').format(len(subscribers)) - -# ok: frappe-translation-python-splitting -_('You have {0} subscribers') \ - + 'in your mailing list' - -# ruleid: frappe-translation-trailing-spaces -msg = _(" You have {0} pending invoice ") -# ruleid: frappe-translation-trailing-spaces -msg = _("You have {0} pending invoice ") -# ruleid: frappe-translation-trailing-spaces -msg = _(" You have {0} pending invoice") - -# ok: frappe-translation-trailing-spaces -msg = ' ' + _("You have {0} pending invoices") + ' ' - -# ruleid: frappe-translation-python-formatting -_(f"can not format like this - {subscribers}") -# ruleid: frappe-translation-python-splitting -_(f"what" + f"this is also not cool") - - -# ruleid: frappe-translation-empty-string -_("") -# ruleid: frappe-translation-empty-string -_('') - - -class Test: - # ok: frappe-translation-python-splitting - def __init__( - args - ): - pass diff --git a/.github/helper/semgrep_rules/translate.yml b/.github/helper/semgrep_rules/translate.yml deleted file mode 100644 index 5f03fb9fd00..00000000000 --- a/.github/helper/semgrep_rules/translate.yml +++ /dev/null @@ -1,64 +0,0 @@ -rules: -- id: frappe-translation-empty-string - pattern-either: - - pattern: _("") - - pattern: __("") - message: | - Empty string is useless for translation. - Please refer: https://frappeframework.com/docs/user/en/translations - languages: [python, javascript, json] - severity: ERROR - -- id: frappe-translation-trailing-spaces - pattern-either: - - pattern: _("=~/(^[ \t]+|[ \t]+$)/") - - pattern: __("=~/(^[ \t]+|[ \t]+$)/") - message: | - Trailing or leading whitespace not allowed in translate strings. - Please refer: https://frappeframework.com/docs/user/en/translations - languages: [python, javascript, json] - severity: ERROR - -- id: frappe-translation-python-formatting - pattern-either: - - pattern: _("..." % ...) - - pattern: _("...".format(...)) - - pattern: _(f"...") - message: | - Only positional formatters are allowed and formatting should not be done before translating. - Please refer: https://frappeframework.com/docs/user/en/translations - languages: [python] - severity: ERROR - -- id: frappe-translation-js-formatting - patterns: - - pattern: __(`...`) - - pattern-not: __("...") - message: | - Template strings are not allowed for text formatting. - Please refer: https://frappeframework.com/docs/user/en/translations - languages: [javascript, json] - severity: ERROR - -- id: frappe-translation-python-splitting - pattern-either: - - pattern: _(...) + _(...) - - pattern: _("..." + "...") - - pattern-regex: '[\s\.]_\([^\)]*\\\s*' # lines broken by `\` - - pattern-regex: '[\s\.]_\(\s*\n' # line breaks allowed by python for using ( ) - message: | - Do not split strings inside translate function. Do not concatenate using translate functions. - Please refer: https://frappeframework.com/docs/user/en/translations - languages: [python] - severity: ERROR - -- id: frappe-translation-js-splitting - pattern-either: - - pattern-regex: '__\([^\)]*[\\]\s+' - - pattern: __('...' + '...', ...) - - pattern: __('...') + __('...') - message: | - Do not split strings inside translate function. Do not concatenate using translate functions. - Please refer: https://frappeframework.com/docs/user/en/translations - languages: [javascript, json] - severity: ERROR diff --git a/.github/helper/semgrep_rules/ux.js b/.github/helper/semgrep_rules/ux.js deleted file mode 100644 index ae73f9cc603..00000000000 --- a/.github/helper/semgrep_rules/ux.js +++ /dev/null @@ -1,9 +0,0 @@ - -// ok: frappe-missing-translate-function-js -frappe.msgprint('{{ _("Both login and password required") }}'); - -// ruleid: frappe-missing-translate-function-js -frappe.msgprint('What'); - -// ok: frappe-missing-translate-function-js -frappe.throw(' {{ _("Both login and password required") }}. '); diff --git a/.github/helper/semgrep_rules/ux.py b/.github/helper/semgrep_rules/ux.py deleted file mode 100644 index a00d3cd8aef..00000000000 --- a/.github/helper/semgrep_rules/ux.py +++ /dev/null @@ -1,31 +0,0 @@ -import frappe -from frappe import msgprint, throw, _ - - -# ruleid: frappe-missing-translate-function-python -throw("Error Occured") - -# ruleid: frappe-missing-translate-function-python -frappe.throw("Error Occured") - -# ruleid: frappe-missing-translate-function-python -frappe.msgprint("Useful message") - -# ruleid: frappe-missing-translate-function-python -msgprint("Useful message") - - -# ok: frappe-missing-translate-function-python -translatedmessage = _("Hello") - -# ok: frappe-missing-translate-function-python -throw(translatedmessage) - -# ok: frappe-missing-translate-function-python -msgprint(translatedmessage) - -# ok: frappe-missing-translate-function-python -msgprint(_("Helpful message")) - -# ok: frappe-missing-translate-function-python -frappe.throw(_("Error occured")) diff --git a/.github/helper/semgrep_rules/ux.yml b/.github/helper/semgrep_rules/ux.yml deleted file mode 100644 index dd667f36c0f..00000000000 --- a/.github/helper/semgrep_rules/ux.yml +++ /dev/null @@ -1,30 +0,0 @@ -rules: -- id: frappe-missing-translate-function-python - pattern-either: - - patterns: - - pattern: frappe.msgprint("...", ...) - - pattern-not: frappe.msgprint(_("..."), ...) - - patterns: - - pattern: frappe.throw("...", ...) - - pattern-not: frappe.throw(_("..."), ...) - message: | - All user facing text must be wrapped in translate function. Please refer to translation documentation. https://frappeframework.com/docs/user/en/guides/basics/translations - languages: [python] - severity: ERROR - -- id: frappe-missing-translate-function-js - pattern-either: - - patterns: - - pattern: frappe.msgprint("...", ...) - - pattern-not: frappe.msgprint(__("..."), ...) - # ignore microtemplating e.g. msgprint("{{ _("server side translation") }}") - - pattern-not: frappe.msgprint("=~/\{\{.*\_.*\}\}/i", ...) - - patterns: - - pattern: frappe.throw("...", ...) - - pattern-not: frappe.throw(__("..."), ...) - # ignore microtemplating - - pattern-not: frappe.throw("=~/\{\{.*\_.*\}\}/i", ...) - message: | - All user facing text must be wrapped in translate function. Please refer to translation documentation. https://frappeframework.com/docs/user/en/guides/basics/translations - languages: [javascript] - severity: ERROR diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 9389eaabaa8..c59b50cb42d 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -19,10 +19,13 @@ jobs: - name: Install and Run Pre-commit uses: pre-commit/action@v2.0.3 + - name: Download Semgrep rules + run: git clone --depth 1 https://github.com/frappe/frappe-semgrep-rules.git + - uses: returntocorp/semgrep-action@v1 env: SEMGREP_TIMEOUT: 120 with: config: >- r/python.lang.correctness - .github/helper/semgrep_rules + ./frappe-semgrep-rules/rules From 4ad2b851c48d126dae07b80f756f88bb3d141b60 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 22 Oct 2021 22:38:44 +0530 Subject: [PATCH 3/9] chore: change semgrep rules repo name [skip ci] --- .github/workflows/linters.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index c59b50cb42d..ebb88c9edac 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -20,7 +20,7 @@ jobs: uses: pre-commit/action@v2.0.3 - name: Download Semgrep rules - run: git clone --depth 1 https://github.com/frappe/frappe-semgrep-rules.git + run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules - uses: returntocorp/semgrep-action@v1 env: From 2ea4c95f86a9e409b274e7a6a5a0d3266e00694b Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 20 Oct 2021 12:07:22 +0530 Subject: [PATCH 4/9] fix: Error in TDS computation summary (cherry picked from commit f12deae24b7ab164edd0868a1254bdf28bfeac09) --- .../accounts/report/tds_payable_monthly/tds_payable_monthly.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py index 621b697aca4..4a25bcdee34 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py @@ -44,7 +44,7 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map): if rate and tds_deducted: row = { - 'pan' if frappe.db.has_column('Supplier', 'pan') else 'tax_id': supplier_map.get(supplier).pan, + 'pan' if frappe.db.has_column('Supplier', 'pan') else 'tax_id': supplier_map.get(supplier, {}).get('pan'), 'supplier': supplier_map.get(supplier).name } From 881e091b8597d0ebc8782c6764fb56ebd953adac Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 20 Oct 2021 12:16:22 +0530 Subject: [PATCH 5/9] fix: Check for other properties (cherry picked from commit b7befe49dc83b938b74b7a63d31787734d7857f8) --- .../report/tds_payable_monthly/tds_payable_monthly.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py index 4a25bcdee34..5c47514cc31 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py @@ -45,7 +45,7 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map): if rate and tds_deducted: row = { 'pan' if frappe.db.has_column('Supplier', 'pan') else 'tax_id': supplier_map.get(supplier, {}).get('pan'), - 'supplier': supplier_map.get(supplier).name + 'supplier': supplier_map.get(supplier, {}).get('name') } if filters.naming_series == 'Naming Series': @@ -53,7 +53,7 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map): row.update({ 'section_code': tax_withholding_category, - 'entity_type': supplier_map.get(supplier).supplier_type, + 'entity_type': supplier_map.get(supplier, {}).get('supplier_type'), 'tds_rate': rate, 'total_amount_credited': total_amount_credited, 'tds_deducted': tds_deducted, From 7f2dde7d9451a1fb3ccd2757c0b3e8647508909d Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 20 Oct 2021 12:17:13 +0530 Subject: [PATCH 6/9] fix: Check for supplier name (cherry picked from commit 944e3d467c5ab0a2a4a76a8b532e53bca77f8e61) --- .../accounts/report/tds_payable_monthly/tds_payable_monthly.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py index 5c47514cc31..6a7f2e5b535 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py @@ -49,7 +49,7 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map): } if filters.naming_series == 'Naming Series': - row.update({'supplier_name': supplier_map.get(supplier).supplier_name}) + row.update({'supplier_name': supplier_map.get(supplier, {}).get('supplier_name')}) row.update({ 'section_code': tax_withholding_category, From fdaf93f76ca12ad7cc3d5e386b1ec5e2497cba75 Mon Sep 17 00:00:00 2001 From: Noah Jacob Date: Sat, 23 Oct 2021 21:04:42 +0530 Subject: [PATCH 7/9] refactor: shows opening balance from filtered from_date (#26877) * refactor: shows opening balance from filtered from_date * refactor: opening balance considered from filtered from_date in stock ledger * fix: check if stock reco is opening and misc cleanups --- erpnext/stock/report/stock_balance/stock_balance.py | 4 +++- erpnext/stock/report/stock_ledger/stock_ledger.py | 13 +++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index fc5d5c12da4..bb53c557371 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -202,7 +202,9 @@ def get_item_warehouse_map(filters, sle): value_diff = flt(d.stock_value_difference) - if d.posting_date < from_date: + if d.posting_date < from_date or (d.posting_date == from_date + and d.voucher_type == "Stock Reconciliation" and + frappe.db.get_value("Stock Reconciliation", d.voucher_no, "purpose") == "Opening Stock"): qty_dict.opening_qty += qty_diff qty_dict.opening_val += value_diff diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py index 1ea58fed191..4e20b472617 100644 --- a/erpnext/stock/report/stock_ledger/stock_ledger.py +++ b/erpnext/stock/report/stock_ledger/stock_ledger.py @@ -21,7 +21,7 @@ def execute(filters=None): items = get_items(filters) sl_entries = get_stock_ledger_entries(filters, items) item_details = get_item_details(items, sl_entries, include_uom) - opening_row = get_opening_balance(filters, columns) + opening_row = get_opening_balance(filters, columns, sl_entries) precision = cint(frappe.db.get_single_value("System Settings", "float_precision")) data = [] @@ -218,7 +218,7 @@ def get_sle_conditions(filters): return "and {}".format(" and ".join(conditions)) if conditions else "" -def get_opening_balance(filters, columns): +def get_opening_balance(filters, columns, sl_entries): if not (filters.item_code and filters.warehouse and filters.from_date): return @@ -230,6 +230,15 @@ def get_opening_balance(filters, columns): "posting_time": "00:00:00" }) + # check if any SLEs are actually Opening Stock Reconciliation + for sle in sl_entries: + if (sle.get("voucher_type") == "Stock Reconciliation" + and sle.get("date").split()[0] == filters.from_date + and frappe.db.get_value("Stock Reconciliation", sle.voucher_no, "purpose") == "Opening Stock" + ): + last_entry = sle + sl_entries.remove(sle) + row = { "item_code": _("'Opening'"), "qty_after_transaction": last_entry.get("qty_after_transaction", 0), From fc8307621c091f228ba3d513826f7cddcc06ea9e Mon Sep 17 00:00:00 2001 From: Subin Tom <36098155+nemesis189@users.noreply.github.com> Date: Mon, 25 Oct 2021 13:18:08 +0530 Subject: [PATCH 8/9] fix: POS Closing Entry without linked invoices (#28042) --- .../doctype/pos_closing_entry/pos_closing_entry.json | 5 ++--- .../doctype/pos_invoice_merge_log/pos_invoice_merge_log.py | 5 ++++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json index 4d6e4a2ba07..d6e35c6a50d 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json +++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json @@ -180,8 +180,7 @@ "fieldname": "pos_transactions", "fieldtype": "Table", "label": "POS Transactions", - "options": "POS Invoice Reference", - "reqd": 1 + "options": "POS Invoice Reference" }, { "fieldname": "pos_opening_entry", @@ -229,7 +228,7 @@ "link_fieldname": "pos_closing_entry" } ], - "modified": "2021-05-05 16:59:49.723261", + "modified": "2021-10-20 16:19:25.340565", "modified_by": "Administrator", "module": "Accounts", "name": "POS Closing Entry", diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index 9dae3a7b75e..4f26ed43db7 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -246,7 +246,10 @@ def get_invoice_customer_map(pos_invoices): return pos_invoice_customer_map def consolidate_pos_invoices(pos_invoices=None, closing_entry=None): - invoices = pos_invoices or (closing_entry and closing_entry.get('pos_transactions')) or get_all_unconsolidated_invoices() + invoices = pos_invoices or (closing_entry and closing_entry.get('pos_transactions')) + if frappe.flags.in_test and not invoices: + invoices = get_all_unconsolidated_invoices() + invoice_by_customer = get_invoice_customer_map(invoices) if len(invoices) >= 10 and closing_entry: From 07a3be6f6124ddc9db97a0f22d9c1c886f1782ab Mon Sep 17 00:00:00 2001 From: Kenneth Sequeira <33246109+kennethsequeira@users.noreply.github.com> Date: Mon, 25 Oct 2021 20:10:52 +0530 Subject: [PATCH 9/9] fix: remove VM from installation (#28075) --- README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/README.md b/README.md index 6fad8f4fcd3..1105a970059 100644 --- a/README.md +++ b/README.md @@ -55,14 +55,6 @@ The Easy Way: our install script for bench will install all dependencies (e.g. M New passwords will be created for the ERPNext "Administrator" user, the MariaDB root user, and the frappe user (the script displays the passwords and saves them to ~/frappe_passwords.txt). -### Virtual Image - -You can download a virtual image to run ERPNext in a virtual machine on your local system. - -- [ERPNext Download](http://erpnext.com/download) - -System and user credentials are listed on the download page. - --- ## License