Ver 15.07 Adjustment to projects save (gemini)
This commit is contained in:
parent
18701fcaef
commit
fe7d0d6a70
Binary file not shown.
@ -177,6 +177,7 @@
|
|||||||
data-adj-description="{{ adj.description }}"
|
data-adj-description="{{ adj.description }}"
|
||||||
data-adj-date="{{ adj.date|date:'Y-m-d' }}"
|
data-adj-date="{{ adj.date|date:'Y-m-d' }}"
|
||||||
data-adj-worker="{{ item.worker.name }}"
|
data-adj-worker="{{ item.worker.name }}"
|
||||||
|
data-adj-project="{% if adj.work_log %}{{ adj.work_log.project_id }}{% endif %}"
|
||||||
title="{% if adj.type == 'ADVANCE' %}Click to delete (cannot edit){% else %}Click to edit{% endif %}">
|
title="{% if adj.type == 'ADVANCE' %}Click to delete (cannot edit){% else %}Click to edit{% endif %}">
|
||||||
{{ adj.get_type_display }}: R {{ adj.amount }} {% if adj.type != 'ADVANCE' %}✎{% endif %}
|
{{ adj.get_type_display }}: R {{ adj.amount }} {% if adj.type != 'ADVANCE' %}✎{% endif %}
|
||||||
</span>
|
</span>
|
||||||
@ -487,6 +488,15 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Project</label>
|
||||||
|
<select name="project_id" class="form-select">
|
||||||
|
<option value="">Select a project (Optional)...</option>
|
||||||
|
{% for project in all_projects %}
|
||||||
|
<option value="{{ project.id }}">{{ project.name }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">Amount (R)</label>
|
<label class="form-label">Amount (R)</label>
|
||||||
<input type="number" name="amount" class="form-control" step="0.01" min="1" required>
|
<input type="number" name="amount" class="form-control" step="0.01" min="1" required>
|
||||||
@ -530,6 +540,15 @@
|
|||||||
</select>
|
</select>
|
||||||
<div class="form-text" id="editAdjTypeHint" style="display:none;">Type cannot be changed for Loan, Overtime, or Repayment adjustments.</div>
|
<div class="form-text" id="editAdjTypeHint" style="display:none;">Type cannot be changed for Loan, Overtime, or Repayment adjustments.</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Project</label>
|
||||||
|
<select name="project_id" id="editAdjProject" class="form-select">
|
||||||
|
<option value="">Select a project (Optional)...</option>
|
||||||
|
{% for project in all_projects %}
|
||||||
|
<option value="{{ project.id }}">{{ project.name }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">Amount (R)</label>
|
<label class="form-label">Amount (R)</label>
|
||||||
<input type="number" name="amount" id="editAdjAmount" class="form-control" step="0.01" min="0.01" required>
|
<input type="number" name="amount" id="editAdjAmount" class="form-control" step="0.01" min="0.01" required>
|
||||||
@ -760,6 +779,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('editAdjWorkerName').textContent = this.dataset.adjWorker;
|
document.getElementById('editAdjWorkerName').textContent = this.dataset.adjWorker;
|
||||||
|
document.getElementById("editAdjProject").value = this.dataset.adjProject || "";
|
||||||
document.getElementById('editAdjAmount').value = this.dataset.adjAmount;
|
document.getElementById('editAdjAmount').value = this.dataset.adjAmount;
|
||||||
document.getElementById('editAdjDescription').value = this.dataset.adjDescription;
|
document.getElementById('editAdjDescription').value = this.dataset.adjDescription;
|
||||||
document.getElementById('editAdjDate').value = this.dataset.adjDate;
|
document.getElementById('editAdjDate').value = this.dataset.adjDate;
|
||||||
|
|||||||
@ -994,6 +994,7 @@ def payroll_dashboard(request):
|
|||||||
'active_tab': status_filter,
|
'active_tab': status_filter,
|
||||||
'all_workers': all_workers,
|
'all_workers': all_workers,
|
||||||
'all_teams': all_teams,
|
'all_teams': all_teams,
|
||||||
|
'all_projects': Project.objects.filter(is_active=True).order_by('name'),
|
||||||
'team_workers_map_json': json.dumps(team_workers_map),
|
'team_workers_map_json': json.dumps(team_workers_map),
|
||||||
'adjustment_types': PayrollAdjustment.ADJUSTMENT_TYPES,
|
'adjustment_types': PayrollAdjustment.ADJUSTMENT_TYPES,
|
||||||
'loans': loans,
|
'loans': loans,
|
||||||
@ -1283,6 +1284,7 @@ def add_adjustment(request):
|
|||||||
description = request.POST.get('description')
|
description = request.POST.get('description')
|
||||||
date = request.POST.get('date') or timezone.now().date()
|
date = request.POST.get('date') or timezone.now().date()
|
||||||
loan_id = request.POST.get('loan_id') # Optional, for repayments
|
loan_id = request.POST.get('loan_id') # Optional, for repayments
|
||||||
|
project_id = request.POST.get('project_id') # Optional, for linking to a project
|
||||||
|
|
||||||
try:
|
try:
|
||||||
amount = Decimal(amount_str) if amount_str else None
|
amount = Decimal(amount_str) if amount_str else None
|
||||||
@ -1329,12 +1331,22 @@ def add_adjustment(request):
|
|||||||
|
|
||||||
# Create ADVANCE adjustment + PayrollRecord atomically
|
# Create ADVANCE adjustment + PayrollRecord atomically
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
|
work_log_link = None
|
||||||
|
if project_id:
|
||||||
|
# Try to find a worklog for this worker and project to link the adjustment to the project
|
||||||
|
work_log_link = worker.work_logs.filter(project_id=project_id).order_by('-date').first()
|
||||||
|
if not work_log_link:
|
||||||
|
# Fallback: any worklog for project
|
||||||
|
from .models import WorkLog
|
||||||
|
work_log_link = WorkLog.objects.filter(project_id=project_id).order_by('-date').first()
|
||||||
|
|
||||||
PayrollAdjustment.objects.create(
|
PayrollAdjustment.objects.create(
|
||||||
worker=worker,
|
worker=worker,
|
||||||
type='ADVANCE',
|
type='ADVANCE',
|
||||||
amount=advance_amount,
|
amount=advance_amount,
|
||||||
description=description or 'Advance payment',
|
description=description or 'Advance payment',
|
||||||
date=date,
|
date=date,
|
||||||
|
work_log=work_log_link,
|
||||||
)
|
)
|
||||||
|
|
||||||
advance_date = date if isinstance(date, datetime.date) else timezone.now().date()
|
advance_date = date if isinstance(date, datetime.date) else timezone.now().date()
|
||||||
@ -1342,6 +1354,8 @@ def add_adjustment(request):
|
|||||||
worker=worker,
|
worker=worker,
|
||||||
amount=advance_amount,
|
amount=advance_amount,
|
||||||
date=advance_date,
|
date=advance_date,
|
||||||
|
type='ADVANCE',
|
||||||
|
notes=description or 'Advance payment'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Send advance payslip to Spark (outside transaction)
|
# Send advance payslip to Spark (outside transaction)
|
||||||
@ -1398,13 +1412,23 @@ def add_adjustment(request):
|
|||||||
reason=description
|
reason=description
|
||||||
)
|
)
|
||||||
|
|
||||||
|
work_log_link = None
|
||||||
|
if project_id:
|
||||||
|
# Try to find a worklog for this worker and project to link the adjustment to the project
|
||||||
|
work_log_link = worker.work_logs.filter(project_id=project_id).order_by('-date').first()
|
||||||
|
if not work_log_link:
|
||||||
|
# Fallback: any worklog for project
|
||||||
|
from .models import WorkLog
|
||||||
|
work_log_link = WorkLog.objects.filter(project_id=project_id).order_by("-date").first()
|
||||||
|
|
||||||
PayrollAdjustment.objects.create(
|
PayrollAdjustment.objects.create(
|
||||||
worker=worker,
|
worker=worker,
|
||||||
type=adj_type,
|
type=adj_type,
|
||||||
amount=amount,
|
amount=amount,
|
||||||
description=description,
|
description=description,
|
||||||
date=date,
|
date=date,
|
||||||
loan=loan
|
loan=loan,
|
||||||
|
work_log=work_log_link
|
||||||
)
|
)
|
||||||
success_names.append(worker.name)
|
success_names.append(worker.name)
|
||||||
|
|
||||||
@ -1445,6 +1469,7 @@ def edit_adjustment(request, pk):
|
|||||||
description = request.POST.get('description')
|
description = request.POST.get('description')
|
||||||
date = request.POST.get('date')
|
date = request.POST.get('date')
|
||||||
new_type = request.POST.get('type')
|
new_type = request.POST.get('type')
|
||||||
|
project_id = request.POST.get('project_id')
|
||||||
|
|
||||||
if amount:
|
if amount:
|
||||||
adj.amount = Decimal(amount)
|
adj.amount = Decimal(amount)
|
||||||
@ -1453,6 +1478,15 @@ def edit_adjustment(request, pk):
|
|||||||
if date:
|
if date:
|
||||||
adj.date = date
|
adj.date = date
|
||||||
|
|
||||||
|
if project_id:
|
||||||
|
work_log_link = adj.worker.work_logs.filter(project_id=project_id).order_by('-date').first()
|
||||||
|
if not work_log_link:
|
||||||
|
from .models import WorkLog
|
||||||
|
work_log_link = WorkLog.objects.filter(project_id=project_id).order_by('-date').first()
|
||||||
|
adj.work_log = work_log_link
|
||||||
|
elif project_id == '':
|
||||||
|
adj.work_log = None
|
||||||
|
|
||||||
# Only allow type change for BONUS/DEDUCTION (others have linked objects)
|
# Only allow type change for BONUS/DEDUCTION (others have linked objects)
|
||||||
if new_type and adj.type in ('BONUS', 'DEDUCTION') and new_type in ('BONUS', 'DEDUCTION'):
|
if new_type and adj.type in ('BONUS', 'DEDUCTION') and new_type in ('BONUS', 'DEDUCTION'):
|
||||||
adj.type = new_type
|
adj.type = new_type
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user