From f052c0c7ba0b5a99c511c06de13262f229e753b5 Mon Sep 17 00:00:00 2001 From: av-dev2 Date: Sun, 30 Aug 2026 18:56:10 +0300 Subject: [PATCH 1/4] chore: enforce three-stage pre-commit hooks and anchored excludes Anchor the exclude regex so it stops swallowing .github, add the pre-push full-repository-check stage, scope ruff hooks to csf_tz, and add the no-commit-to-branch guard per the pre-commit-enforcement skill. --- .pre-commit-config.yaml | 32 ++++++++++++++++++++++--- csf_tz/vfd_support/sales_invoice.py | 36 +++++++++++------------------ 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 12126078..a1335de9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ -exclude: 'node_modules|.git|frappe-semgrep-rules' +exclude: '^(node_modules/|frappe-semgrep-rules/|[.]vscode/|.*/node_modules/)' default_stages: [pre-commit] -default_install_hook_types: [pre-commit, commit-msg] +default_install_hook_types: [pre-commit, commit-msg, pre-push] fail_fast: false repos: @@ -18,6 +18,20 @@ repos: - id: check-toml - id: check-yaml - id: debug-statements + - id: no-commit-to-branch + args: + - --branch + - main + - --branch + - master + - --branch + - production + - --branch + - version-14 + - --branch + - version-15 + - --branch + - version-16 - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.11.0 @@ -25,13 +39,16 @@ repos: - id: ruff name: "Run ruff import sorter" args: ["--select=I", "--fix"] + files: '^csf_tz/.*\.py$' - id: ruff name: "Run ruff linter" args: ["--fix"] + files: '^csf_tz/.*\.py$' - id: ruff-format name: "Run ruff formatter" + files: '^csf_tz/.*\.py$' - repo: local hooks: @@ -45,6 +62,15 @@ repos: pass_filenames: true require_serial: true + - id: full-repository-check + name: "Full repository check before push" + entry: bash -c 'if command -v pre-commit >/dev/null 2>&1; then exec pre-commit run --all-files --hook-stage pre-commit --show-diff-on-failure --color=always; else exec python3 -m pre_commit run --all-files --hook-stage pre-commit --show-diff-on-failure --color=always; fi' + language: system + stages: [pre-push] + pass_filenames: false + always_run: true + verbose: true + - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook rev: v9.22.0 hooks: @@ -54,5 +80,5 @@ repos: ci: autoupdate_schedule: weekly - skip: [frappe-semgrep-rules] + skip: [frappe-semgrep-rules, full-repository-check] submodules: false diff --git a/csf_tz/vfd_support/sales_invoice.py b/csf_tz/vfd_support/sales_invoice.py index d3015ca8..060613f2 100644 --- a/csf_tz/vfd_support/sales_invoice.py +++ b/csf_tz/vfd_support/sales_invoice.py @@ -134,36 +134,28 @@ def get_item_inclusive_amount(item): @erpnext.allow_regional def get_itemised_tax_breakup_data(doc): - itemised_tax = get_itemised_tax(doc.taxes) + itemised_tax = get_itemised_tax(doc) return itemised_tax -def get_itemised_tax(taxes, with_tax_account=False): +def get_itemised_tax(doc, with_tax_account=False): itemised_tax = {} - for tax in taxes: + for row in doc.get("_item_wise_tax_details") or []: + item = row.get("item") + tax = row.get("tax") + if not item or not tax: + continue if getattr(tax, "category", None) and tax.category == "Valuation": continue - item_tax_map = json.loads(tax.item_wise_tax_detail) if tax.item_wise_tax_detail else {} - if item_tax_map: - for item_code, tax_data in item_tax_map.items(): - itemised_tax.setdefault(item_code, frappe._dict()) - - tax_rate = 0.0 - tax_amount = 0.0 - - if isinstance(tax_data, list): - tax_rate = flt(tax_data[0]) - tax_amount = flt(tax_data[1]) - else: - tax_rate = flt(tax_data) - - itemised_tax[item_code][tax.description] = frappe._dict( - dict(tax_rate=tax_rate, tax_amount=tax_amount) - ) + item_code = item.item_code or item.item_name + tax_info = itemised_tax.setdefault(item_code, frappe._dict()).setdefault( + tax.description, frappe._dict(tax_rate=flt(row.rate), tax_amount=0.0) + ) + tax_info.tax_amount += flt(row.amount) - if with_tax_account: - itemised_tax[item_code][tax.description].tax_account = tax.account_head + if with_tax_account: + tax_info.tax_account = tax.account_head return itemised_tax From c9fc1c85550931d421cdde8e9d71f264e5928a06 Mon Sep 17 00:00:00 2001 From: av-dev2 Date: Sun, 30 Aug 2026 19:00:42 +0300 Subject: [PATCH 2/4] ci: add scripts/setup-git-hooks.sh and pre-commit all-files workflow Bootstrap developer hook installs with one command and gate pull requests with a full-repository pre-commit run, per the pre-commit-enforcement skill's required file set. --- .github/workflows/pre-commit.yml | 29 +++++++++++++++++++++++++++++ scripts/setup-git-hooks.sh | 16 ++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 .github/workflows/pre-commit.yml create mode 100755 scripts/setup-git-hooks.sh diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 00000000..4df62d8d --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,29 @@ +name: Pre-commit + +on: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + pre-commit: + name: 'Run pre-commit (all files)' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.10' + cache: pip + - name: Install pre-commit + run: pip install pre-commit + - name: Run pre-commit + env: + SKIP: frappe-semgrep-rules,full-repository-check + run: pre-commit run --all-files --show-diff-on-failure --color=always diff --git a/scripts/setup-git-hooks.sh b/scripts/setup-git-hooks.sh new file mode 100755 index 00000000..db5a2219 --- /dev/null +++ b/scripts/setup-git-hooks.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +if ! command -v pre-commit >/dev/null 2>&1; then + if command -v uv >/dev/null 2>&1; then + uv tool install pre-commit + elif command -v pipx >/dev/null 2>&1; then + pipx install pre-commit + else + pip install --user pre-commit + fi +fi + +pre-commit install --install-hooks --overwrite From 5f074afaadeeb3f82c667fd7c4e0820243edbd13 Mon Sep 17 00:00:00 2001 From: av-dev2 Date: Sun, 30 Aug 2026 19:00:47 +0300 Subject: [PATCH 3/4] chore: add dev extra for pre-commit in pyproject.toml pip install -e .[dev] should pull in pre-commit so the bootstrap script has something to install if uv/pipx are unavailable. --- pyproject.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 791b7b3f..88099f08 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,11 @@ dependencies = [ "selcom-apigw-client", ] +[project.optional-dependencies] +dev = [ + "pre-commit", +] + [build-system] requires = ["flit_core >=3.4,<4"] build-backend = "flit_core.buildapi" From 11bad68f5ef1904ef08f4adfe91a952d3473f6ae Mon Sep 17 00:00:00 2001 From: av-dev2 Date: Sun, 30 Aug 2026 19:00:53 +0300 Subject: [PATCH 4/4] chore: remove semantic-release in favour of tag-and-promote workflow Both release.yml and tag-and-promote-from-pr-label.yml owned tagging and releasing at once; semantic-release would tag a release commit that tag-and-promote never sees, failing that job. --- .github/workflows/release.yml | 34 ---------------------------------- .releaserc.json | 22 ---------------------- 2 files changed, 56 deletions(-) delete mode 100644 .github/workflows/release.yml delete mode 100644 .releaserc.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 3bc54c76..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Release - -on: - workflow_dispatch: - -permissions: - contents: write - issues: write - pull-requests: write - -concurrency: - group: release-${{ github.ref }} - cancel-in-progress: true - -jobs: - release: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - persist-credentials: false - - - uses: actions/setup-node@v4 - with: - node-version: 20 - - - name: Install semantic-release - run: npm install --no-save semantic-release @semantic-release/changelog @semantic-release/exec @semantic-release/git @semantic-release/github conventional-changelog-conventionalcommits - - - name: Run semantic-release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: npx semantic-release diff --git a/.releaserc.json b/.releaserc.json deleted file mode 100644 index e40d8fe7..00000000 --- a/.releaserc.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "branches": ["version-15"], - "plugins": [ - ["@semantic-release/commit-analyzer", { - "preset": "conventionalcommits" - }], - ["@semantic-release/release-notes-generator", { - "preset": "conventionalcommits" - }], - ["@semantic-release/changelog", { - "changelogFile": "CHANGELOG.md" - }], - ["@semantic-release/exec", { - "prepareCmd": "sed -i 's/^__version__ = .*/__version__ = \"${nextRelease.version}\"/' csf_tz/__init__.py" - }], - ["@semantic-release/git", { - "assets": ["CHANGELOG.md", "csf_tz/__init__.py"], - "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" - }], - "@semantic-release/github" - ] -}