fix(hrms): TETRA-1653 PC_DT/PC_BB miễn TNCN + PC_LAN đóng BHXH theo Luật 109/2025 + 41/2024 #130
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "kienta/vhrms:fix/TETRA-1653-pc-dt-bb-lan-flags"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
3 Salary Component bị seed sai cờ TNCN/BHXH so với pháp lý hiện hành (audit master data sau khi fix PC_LAN TNCN ở TETRA-1645):
is_tax_applicable=1— sai. Phụ cấp khoán điện thoại theo quy chế DN miễn TNCN trong định mức (Luật 109/2025 + TT 111/2013 Đ.2.2.đ.4).is_tax_applicable=1— sai. DN trả theo hệ số phụ cấp khu vực NĐ 76/2019/NĐ-CP cho địa bàn ven biển → nhóm phụ cấp khu vực miễn TNCN tại Luật 109/2025/QH15 Đ.3.2.b.custom_is_pay_insurance=0— sai. Lặn là CV đặc thù theo TT 11/2020 → diện đóng BHXH theo Luật BHXH 41/2024 Đ.31 (eff 2026, override CV 1198 cũ).Refs: TETRA-1653
Changes
setup/salary_components.py: flip cờ master data + update descriptions; extend backfill TNCN abbr set ({OT_*, PC_LAN}→ thêmPC_BB,PC_DT); thêm backfill BHXH block mới flipcustom_is_pay_insurance0→1 cho PC_LAN (logic ngược chiều, dùng set để dễ extend).patches/v0_8_0/seed_missing_allowance_welfare_components.py: flip seed PC_BB tax + PC_LAN BHXH cho fresh install + cập nhật header docstring.tests/test_seed_components.py: cập nhậtEXPECTED_COMPONENTS+ táchtest_og_no_insurancethànhtest_pc_lan_pays_insurance(Luật 41/2024) +test_pc_bb_no_insurance(regression guard).tests/test_payroll_deductions.py: mock_TAX_FLAGS["Phụ cấp điện thoại"]1→0 + recompute expected PIT base 34,318,182 → 33,818,182 (PC_DT 500k chuyển taxable → exempt).Test plan
python3 -m unittest vhrms.vhrms.tests.test_seed_components— pass (per-module)python3 -m unittest vhrms.vhrms.tests.test_payroll_deductions— pass (per-module)frappe.db.get_value("Salary Component", "Phụ cấp điện thoại", "is_tax_applicable")== 0frappe.db.get_value("Salary Component", "Phụ cấp bờ-biển", "is_tax_applicable")== 0frappe.db.get_value("Salary Component", "Phụ cấp lặn", "custom_is_pay_insurance")== 1Out of scope
custom_is_pay_insurance=1theo Luật 41/2024 Đ.31, ticket riêng.payroll/vietnam_calculations.py&pit_calculator.py& BHXH calculator — đọc cờ từ DB, không cần sửa logic.🤖 Generated with Claude Code
3 Salary Component bị seed sai cờ TNCN/BHXH so với pháp lý hiện hành (audit master data sau khi fix PC_LAN TNCN ở TETRA-1645): - PC_DT (Phụ cấp điện thoại) `is_tax_applicable=1` — sai vì phụ cấp khoán điện thoại theo quy chế DN miễn TNCN trong định mức (Luật 109/2025 + TT 111/2013 Đ.2.2.đ.4). - PC_BB (Phụ cấp bờ-biển) `is_tax_applicable=1` — sai vì DN trả theo hệ số phụ cấp khu vực NĐ 76/2019/NĐ-CP cho địa bàn ven biển, thuộc nhóm phụ cấp khu vực miễn TNCN tại Luật 109/2025/QH15 Đ.3.2.b (C&B confirmed căn cứ NĐ 76/2019). - PC_LAN (Phụ cấp lặn) `custom_is_pay_insurance=0` — sai vì lặn là CV đặc thù theo TT 11/2020, thuộc diện đóng BHXH theo Luật BHXH 41/2024 Đ.31 (eff 2026, override CV 1198 cũ). Cả 3 đều sai ngay trong happy path (DN cấp trong khung pháp lý), không phải edge case vượt trần. Phần vượt trần (PC_DT định mức quy chế, PC_AT 730k/tháng, PC_DH_M1..M4 5–15% LCB) ngoài scope — sẽ tạo follow-up tickets khi cần model cap/formula riêng. Thay đổi: - setup/salary_components.py: flip cờ master data + update descriptions + extend backfill block TNCN abbr set ({OT_*, PC_LAN} → thêm PC_BB, PC_DT) + thêm block backfill BHXH mới flip custom_is_pay_insurance 0→1 cho PC_LAN (logic ngược chiều, dùng set để dễ extend nếu PC_BB BHXH cần follow-up). - patches/v0_8_0/seed_missing_allowance_welfare_components.py: flip seed value PC_BB tax + PC_LAN BHXH cho fresh install ra đúng từ đầu + cập nhật header docstring. - tests/test_seed_components.py: EXPECTED_COMPONENTS table + tách test_og_no_insurance thành test_pc_lan_pays_insurance (assert =1, viện dẫn Luật 41/2024) + test_pc_bb_no_insurance (assert =0, regression guard ngăn drift). - tests/test_payroll_deductions.py: mock _TAX_FLAGS["Phụ cấp điện thoại"] 1→0 (mirror DB state) + recompute expected PIT base 34_318_182 → 33_818_182 trong scenario test (PC_DT 500k chuyển từ taxable → exempt) + cập nhật docstring/comments. PIT calculator + BHXH calculator đọc cờ thẳng từ DB → không cần sửa logic. Patches v0_5_0 (lịch sử) không sửa retroactively — backfill block ở setup file đảm nhận migration. PC_BB BHXH note: nếu C&B sau xác nhận trả cố định gắn vị trí làm việc → cần custom_is_pay_insurance=1 theo Luật 41/2024 Đ.31, ticket riêng. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>Code Review — TETRA-1653
Verdict: ✅ APPROVED
Quality cao, tuân pattern TETRA-1264/TETRA-1645, tests verify math chắc chắn.
Strengths
{OT_*, PC_LAN, PC_BB, PC_DT}(line 643). Comment trace cả 4 ticket nguồn.setđể dễ extend dù hiện chỉ có 1 element (PC_LAN). Forward-looking comment đề cập case PC_BB nếu C&B confirm sau.test_og_no_insurance(PC_LAN+PC_BB chung) → táchtest_pc_lan_pays_insurance(=1, Luật 41/2024) +test_pc_bb_no_insurance(=0). Tránh ambiguity sau khi PC_LAN đảo chiều.Findings
vhrms/vhrms/setup/salary_components.py:213-220is_tax_applicable=0sẽ miễn thuế PC_DT toàn bộ bất kể số tiền. Nếu admin nhập PC_DT > định mức DN, hệ thống sẽ silently miss tax. Đã acknowledge out-of-scope, OK; flag cho QA verify scenarios.vhrms/vhrms/setup/salary_components.py:670current_bhxh == 0. Nếu DB value làNone(column mới thêm, record cũ chưa init), điều kiện False → không flip. Same pattern với TNCN flip (line 645) → parity acceptable. Có thể normalize giốngensure_law_109_pit_exemption(line 727-732, coerce None→0).test_pit_exemption_law_109_2025.pycó thể extend cover BHXH side. Out of scope cho ticket này.Suggestions
Blockers
None.
Next Step
Có thể merge. Findings #2/#3 nên defer; #1 cần QA aware về behavior chính xác.
Known issues (out of scope)