Code-review found a data-integrity bug: the bulk-delete endpoint
bypassed the cascade logic that single-row delete_adjustment does
for 'New Loan', 'Advance Payment', and 'Overtime' types.
Without cascade, bulk-deleting a 'New Loan' adjustment would:
- Delete the PayrollAdjustment row
- LEAVE the linked Loan row orphaned in the DB (still shown in
loan reports, still affecting remaining_balance queries)
- LEAVE any scheduled unpaid Loan Repayment adjustments pointing
at the orphaned Loan (they would silently deduct from the
worker's next pay with no visible parent)
Bulk-deleting an 'Overtime' adjustment would leave the worker
stuck in work_log.priced_workers, making price_overtime() treat
them as already-priced even though the money is gone.
Fix: extracted _delete_adjustment_with_cascade(adj) helper that
captures the exact rules from the existing delete_adjustment view
— returns (ok, reason) so both callers can translate the outcome
into their own response shape. Both views now delegate to it.
bulk_delete_adjustments now loops over the selected rows, calls
the helper per-row, and returns JSON including skipped_reasons
(e.g. {'has_paid_repayments': 1} when a Loan with paid repayments
was refused). Also hardened the id-coercion to int so a garbled
POST payload can't crash the queryset with a ValueError.
Two new tests:
- test_bulk_delete_cascades_new_loan — loan row + unpaid repayment
must also be deleted
- test_bulk_delete_skips_loan_with_paid_repayments — refuses to
delete the loan but still processes other rows in the batch
64/64 tests pass (was 62). No API surface change visible to a user
who only uses the happy path — but the audit trail on Loans is
now safe even under bulk delete.
Flatlogic Python Template Workspace
This workspace houses the Django application scaffold used for Python-based templates.
Requirements
- Python 3.11+
- MariaDB (or MySQL-compatible server) with the credentials prepared by
setup_mariadb_project.sh - System packages:
pkg-config,libmariadb-dev(already installed on golden images)
Getting Started
python3 -m pip install --break-system-packages -r requirements.txt
python3 manage.py migrate
python3 manage.py runserver 0.0.0.0:8000
Environment variables are loaded from ../.env (the executor root). See .env.example if you need to populate values manually.
Project Structure
config/– Django project settings, URLs, WSGI entrypoint.core/– Default app with a basic health-check route.manage.py– Django management entrypoint.
Next Steps
- Create additional apps and views according to the generated project requirements.
- Configure serving via Apache + mod_wsgi or gunicorn (instructions to be added).
- Run
python3 manage.py collectstaticbefore serving through Apache.
Description
Languages
JavaScript
42.5%
SCSS
41.7%
CSS
11.9%
Python
3.2%
HTML
0.6%