Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/review-translation-changes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Review translation PRs
description: "Posts review comments with relevant translation changes that are hard to inspect in the diff view."

on:
pull_request_target:
types: [opened, reopened, synchronize, ready_for_review]
paths:
- "**/*.po"
- "**/*.pot"

concurrency:
group: po-review-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
review-po-pr:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
issues: write
pull-requests: write

steps:
- uses: alyf-de/po-review-action@ffb92a299452595ca50fb1429ee98a7ebacb571e # v1.1.0
42 changes: 42 additions & 0 deletions hrms/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import functools
import inspect

import frappe

__version__ = "17.0.0-dev"
Expand All @@ -10,3 +13,42 @@ def refetch_resource(cache_key: str | list, user=None):
user=user or frappe.session.user,
after_commit=True,
)


def get_region(company=None):
"""Return the country used to resolve regional overrides, based on flag,
company or global settings. Mirrors erpnext.get_region.

You can also set the global company flag in `frappe.flags.company`.
"""
if not company:
company = frappe.local.flags.company

if company:
return frappe.get_cached_value("Company", company, "country")

return frappe.flags.country or frappe.get_system_settings("country")


def allow_regional(fn):
"""Decorator to make a function regionally overridable. Mirrors
erpnext.allow_regional so HRMS functions can be overridden per region via the
`regional_overrides` hook.

Example:
@hrms.allow_regional
def myfunction():
pass"""

@functools.wraps(fn)
def caller(*args, **kwargs):
overrides = frappe.get_hooks("regional_overrides", {}).get(get_region())
function_path = f"{inspect.getmodule(fn).__name__}.{fn.__name__}"

if not overrides or function_path not in overrides:
return fn(*args, **kwargs)

# Priority given to last installed app
return frappe.get_attr(overrides[function_path][-1])(*args, **kwargs)

return caller
6 changes: 3 additions & 3 deletions hrms/overrides/company.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ def make_salary_components(country):
doc.flags.ignore_permissions = True
doc.flags.ignore_mandatory = True
doc.insert(ignore_if_duplicate=True)
except frappe.NameError:
frappe.clear_messages()
except frappe.DuplicateEntryError:
except Exception as e:
frappe.error_log("Error occurred while creating Salary Component", e)
finally:
frappe.clear_messages()


Expand Down
11 changes: 11 additions & 0 deletions hrms/payroll/doctype/salary_slip/salary_slip.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from erpnext.setup.doctype.employee.employee import get_holiday_list_for_employee
from erpnext.utilities.transaction_base import TransactionBase

import hrms
from hrms.hr.utils import validate_active_employee
from hrms.payroll.doctype.additional_salary.additional_salary import get_additional_salaries
from hrms.payroll.doctype.employee_benefit_ledger.employee_benefit_ledger import (
Expand Down Expand Up @@ -941,11 +942,21 @@ def set_gross_pay_and_base_gross_pay():

set_loan_repayment(self)

# Region-specific deductions (e.g. India statutory deductions) are injected
# here so they are reflected in both saved slips and the preview generated
# by process_salary_structure, before totals are finalised below.
self.apply_regional_deductions()

self.set_precision_for_component_amounts()
self.set_net_pay()
if not skip_tax_breakup_computation:
self.compute_income_tax_breakup()

@hrms.allow_regional
def apply_regional_deductions(self):
"Hook point for region-specific salary slip deductions."
pass

def set_net_pay(self):
self.total_deduction = self.get_component_totals("deductions")
self.base_total_deduction = flt(
Expand Down
Loading