ux(labels): shorter adjustment type labels (display-only rename)
Path A rename - DB values untouched, only TYPE_CHOICES display
labels change:
'New Loan' -> shown as 'Loan'
'Advance Payment' -> shown as 'Advance'
'Advance Repayment' -> shown as 'Advance Repaid'
Templates that render the type as visible text switched from
{{ adj.type }} to {{ adj.get_type_display }}. Data attributes and
CSS class slugs keep the raw DB value (identifiers, not labels).
Zero data migration. Zero changes to ADDITIVE_TYPES / DEDUCTIVE_TYPES
constants, hardcoded string comparisons, CSS class names, test
fixtures, or any other code that references the canonical DB value.
Every historic PayrollAdjustment row keeps type='New Loan' /
'Advance Payment' / 'Advance Repayment' as stored.
Django's makemigrations generated a no-op AlterField migration to
record the choices-metadata change.
Tests: 69/69.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e51a2f6d1d
commit
c1d9014fe1
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.2.7 on 2026-04-24 07:45
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0011_worker_tax_number'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='payrolladjustment',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('Bonus', 'Bonus'), ('Overtime', 'Overtime'), ('Deduction', 'Deduction'), ('Loan Repayment', 'Loan Repayment'), ('New Loan', 'Loan'), ('Advance Payment', 'Advance'), ('Advance Repayment', 'Advance Repaid')], max_length=50),
|
||||
),
|
||||
]
|
||||
@ -187,14 +187,21 @@ class Loan(models.Model):
|
||||
return f"{self.worker.name} - {label} - {self.date}"
|
||||
|
||||
class PayrollAdjustment(models.Model):
|
||||
# === PayrollAdjustment TYPE_CHOICES - canonical DB value | display label ===
|
||||
# Path A rename (24 Apr 2026): DB values are PRESERVED as-is. Only the
|
||||
# second tuple element (the human label) changes for three types, so
|
||||
# users see shorter labels in tables while every historic row, formula,
|
||||
# constant, test fixture, CSS class, and data-attribute KEEP WORKING
|
||||
# UNCHANGED because they all key off the DB value on the left.
|
||||
# See CLAUDE.md "UI-vs-DB naming drift" section for the full rule.
|
||||
TYPE_CHOICES = [
|
||||
('Bonus', 'Bonus'),
|
||||
('Overtime', 'Overtime'),
|
||||
('Deduction', 'Deduction'),
|
||||
('Loan Repayment', 'Loan Repayment'),
|
||||
('New Loan', 'New Loan'),
|
||||
('Advance Payment', 'Advance Payment'),
|
||||
('Advance Repayment', 'Advance Repayment'),
|
||||
('Bonus', 'Bonus'),
|
||||
('Overtime', 'Overtime'),
|
||||
('Deduction', 'Deduction'),
|
||||
('Loan Repayment', 'Loan Repayment'),
|
||||
('New Loan', 'Loan'),
|
||||
('Advance Payment', 'Advance'),
|
||||
('Advance Repayment', 'Advance Repaid'),
|
||||
]
|
||||
|
||||
worker = models.ForeignKey(Worker, on_delete=models.CASCADE, related_name='adjustments')
|
||||
|
||||
@ -34,7 +34,7 @@ Row actions differ by paid status:
|
||||
</td>
|
||||
|
||||
{# --- Type badge (colour comes from the .badge-type-<slug> CSS class) --- #}
|
||||
<td><span class="badge-type-{{ adj.type|type_slug }}">{{ adj.type }}</span></td>
|
||||
<td><span class="badge-type-{{ adj.type|type_slug }}">{{ adj.get_type_display }}</span></td>
|
||||
|
||||
{# --- Amount (sign reflects additive vs deductive) --- #}
|
||||
<td class="text-end" style="font-variant-numeric: tabular-nums;">
|
||||
|
||||
@ -367,7 +367,7 @@
|
||||
data-adj-project="{{ adj.project_id|default:'' }}"
|
||||
data-adj-worker="{{ adj.worker.name }}">
|
||||
{% if adj.type == 'Bonus' or adj.type == 'Overtime' or adj.type == 'New Loan' or adj.type == 'Advance Payment' %}+{% else %}-{% endif %}R{{ adj.amount|floatformat:2 }}
|
||||
{{ adj.type }}
|
||||
{{ adj.get_type_display }}
|
||||
{% if adj.project %}({{ adj.project.name }}){% endif %}
|
||||
</span>
|
||||
{% endfor %}
|
||||
@ -451,7 +451,7 @@
|
||||
<td class="align-middle d-none d-lg-table-cell">
|
||||
{% for adj in record.adjustments.all %}
|
||||
<span class="badge {% if adj.type == 'Bonus' or adj.type == 'Overtime' or adj.type == 'Loan Repayment' or adj.type == 'Advance Repayment' %}bg-success{% elif adj.type == 'New Loan' or adj.type == 'Advance Payment' %}bg-warning{% else %}bg-danger{% endif %} me-1">
|
||||
{{ adj.type }}: R {{ adj.amount|floatformat:2 }}
|
||||
{{ adj.get_type_display }}: R {{ adj.amount|floatformat:2 }}
|
||||
</span>
|
||||
{% empty %}
|
||||
<span class="text-muted">-</span>
|
||||
|
||||
@ -128,7 +128,7 @@
|
||||
<tbody>
|
||||
{% for adj in adjustments %}
|
||||
<tr>
|
||||
<td>{{ adj.type }}</td>
|
||||
<td>{{ adj.get_type_display }}</td>
|
||||
<td><a href="{% url 'worker_detail' adj.worker.id %}" class="text-decoration-none">{{ adj.worker.name }}</a></td>
|
||||
<td class="text-end">R {{ adj.amount|money }}</td>
|
||||
<td>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user