# uganda-payroll

Standalone Uganda payroll package built from the payroll patterns in this repository's HRM module, the `create_payment_category` / `paysheet_table` treatment, and the January 2026 workbook you shared.

## What it supports

- `basic`, `gross`, or `net` driven payroll requests
- Custom payment categories with explicit PAYE, NSSF, cash, and employer-cost behavior
- Existing project-style category natures: `Increment`, `Deduction`, `Increment2`, `Do nothing`, `Bonus`
- Resident, non-resident, secondary-employment, and secondary-employment-above-10M modes
- Configurable Uganda PAYE, NSSF, and Local Service Tax policies
- Dynamic paysheet rows and standalone HTML payslip rendering

## Install locally

```bash
cd packages/uganda-payroll
pip install -e .
```

## Quick example

```python
from uganda_payroll import (
    EmployerProfile,
    EmployeeProfile,
    EmploymentTaxMode,
    InputMode,
    PayrollCalculator,
    PayrollLineItem,
    PayrollPeriod,
    PayrollRequest,
    PaymentCategory,
    render_payslip_html,
)

calculator = PayrollCalculator()

overtime = PaymentCategory.from_nature(
    code="overtime",
    name="Overtime",
    nature="Increment",
    attracts_paye=True,
    attracts_nssf=True,
)

request = PayrollRequest(
    employer=EmployerProfile(name="BDO East Africa Advisory Services Ltd", tin="1000943373"),
    employee=EmployeeProfile(
        full_name="Simon Mukisa",
        staff_number="4954",
        tin="1019532691",
        nssf_number="9317200292098",
        department="Advisory",
        employment_tax_mode=EmploymentTaxMode.PRIMARY_RESIDENT,
    ),
    period=PayrollPeriod.from_month(year=2026, month=1),
    input_mode=InputMode.BASIC_PAY,
    target_amount=3_870_000,
    items=[
        PayrollLineItem(category=overtime, amount=333_000),
    ],
)

result = calculator.calculate(request)
html = render_payslip_html(result)

print(result.net_pay)         # 2829950
print(result.total_paye)      # 1162900
print(result.nssf_employee)   # 210150
```

## Notes on defaults

- Resident monthly PAYE bands match the workbook logic and the current project formulas.
- Secondary-employment defaults match the current project flags: `30%` flat, or `40%` if all employments exceed UGX 10M.
- Non-resident defaults are exposed as configurable tables. The packaged default corrects the evident `0.01` typo in the current project logic to `0.10` for the first bracket.
- LST is configurable because collection timing varies by employer and local authority. The default mirrors the existing project's `Chop Once` / `Chop Four times` behavior.

## Package layout

- `src/uganda_payroll/models.py`: domain objects and category controls
- `src/uganda_payroll/policies.py`: Uganda PAYE, NSSF, and LST defaults
- `src/uganda_payroll/engine.py`: payroll calculations and net/gross solving
- `src/uganda_payroll/renderers.py`: paysheet rows and HTML payslips
- `tests/test_payroll.py`: regression and behavior tests
