Ver 16 What a mess but app is working
This commit is contained in:
parent
4ef75c9e8d
commit
6869282de2
BIN
assets/pasted-20260222-085917-86d59323.jpg
Normal file
BIN
assets/pasted-20260222-085917-86d59323.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
BIN
assets/pasted-20260222-085955-7f073603.png
Normal file
BIN
assets/pasted-20260222-085955-7f073603.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 141 KiB |
BIN
assets/vm-shot-2026-02-22T08-59-12-939Z.jpg
Normal file
BIN
assets/vm-shot-2026-02-22T08-59-12-939Z.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
Binary file not shown.
Binary file not shown.
24
core/migrations/0018_payrolladjustment_project_and_more.py
Normal file
24
core/migrations/0018_payrolladjustment_project_and_more.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Generated by Django 5.2.7 on 2026-02-22 08:25
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0017_alter_payrolladjustment_date_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='payrolladjustment',
|
||||||
|
name='project',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='adjustments_by_project', to='core.project'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='payrolladjustment',
|
||||||
|
name='work_log',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='adjustments_by_work_log', to='core.worklog'),
|
||||||
|
),
|
||||||
|
]
|
||||||
Binary file not shown.
@ -168,8 +168,8 @@ class PayrollAdjustment(models.Model):
|
|||||||
worker = models.ForeignKey(Worker, on_delete=models.CASCADE, related_name='adjustments')
|
worker = models.ForeignKey(Worker, on_delete=models.CASCADE, related_name='adjustments')
|
||||||
payroll_record = models.ForeignKey(PayrollRecord, on_delete=models.SET_NULL, null=True, blank=True, related_name='adjustments')
|
payroll_record = models.ForeignKey(PayrollRecord, on_delete=models.SET_NULL, null=True, blank=True, related_name='adjustments')
|
||||||
loan = models.ForeignKey(Loan, on_delete=models.SET_NULL, null=True, blank=True, related_name='repayments')
|
loan = models.ForeignKey(Loan, on_delete=models.SET_NULL, null=True, blank=True, related_name='repayments')
|
||||||
work_log = models.ForeignKey(WorkLog, on_delete=models.SET_NULL, null=True, blank=True, related_name='adjustments'
|
work_log = models.ForeignKey(WorkLog, on_delete=models.SET_NULL, null=True, blank=True, related_name='adjustments_by_work_log')
|
||||||
project = models.ForeignKey(Project, on_delete=models.SET_NULL, null=True, blank=True, related_name='adjustments'
|
project = models.ForeignKey(Project, on_delete=models.SET_NULL, null=True, blank=True, related_name='adjustments_by_project')
|
||||||
|
|
||||||
amount = models.DecimalField(max_digits=10, decimal_places=2, help_text="Positive adds to pay, negative subtracts (except for Loan Repayment which is auto-handled)")
|
amount = models.DecimalField(max_digits=10, decimal_places=2, help_text="Positive adds to pay, negative subtracts (except for Loan Repayment which is auto-handled)")
|
||||||
date = models.DateField(default=timezone.now, db_index=True)
|
date = models.DateField(default=timezone.now, db_index=True)
|
||||||
|
|||||||
@ -177,7 +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 %}"
|
data-adj-project="{% if adj.project_id %}{{ adj.project_id }}{% elif 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>
|
||||||
|
|||||||
126
core/views.py
126
core/views.py
@ -140,15 +140,16 @@ def home(request):
|
|||||||
if user_is_admin:
|
if user_is_admin:
|
||||||
# Bulk-fetch all pending project-linked adjustments in one query
|
# Bulk-fetch all pending project-linked adjustments in one query
|
||||||
pending_proj_adjs = {}
|
pending_proj_adjs = {}
|
||||||
|
# Changed filter to look at adj.project or adj.work_log.project
|
||||||
for adj in PayrollAdjustment.objects.filter(
|
for adj in PayrollAdjustment.objects.filter(
|
||||||
work_log__project__isnull=False,
|
Q(project__isnull=False) | Q(work_log__project__isnull=False),
|
||||||
payroll_record__isnull=True
|
payroll_record__isnull=True
|
||||||
).select_related('work_log'):
|
).select_related('work_log', 'project'):
|
||||||
pid = adj.work_log.project_id
|
pid = adj.project_id or adj.work_log.project_id
|
||||||
pending_proj_adjs.setdefault(pid, []).append(adj)
|
pending_proj_adjs.setdefault(pid, []).append(adj)
|
||||||
|
|
||||||
for project in all_projects:
|
for project in all_projects:
|
||||||
outstanding_cost = 0
|
outstanding_cost = Decimal('0.00')
|
||||||
|
|
||||||
# Unpaid WorkLogs (use prefetch cache, check paid_in in Python)
|
# Unpaid WorkLogs (use prefetch cache, check paid_in in Python)
|
||||||
for log in project.logs.all():
|
for log in project.logs.all():
|
||||||
@ -394,14 +395,14 @@ def work_log_list(request):
|
|||||||
logs = logs.filter(paid_in__isnull=True)
|
logs = logs.filter(paid_in__isnull=True)
|
||||||
|
|
||||||
# --- 2. Fetch Adjustments ---
|
# --- 2. Fetch Adjustments ---
|
||||||
adjustments = PayrollAdjustment.objects.all().select_related('worker', 'payroll_record', 'work_log', 'work_log__project')
|
adjustments = PayrollAdjustment.objects.all().select_related('worker', 'payroll_record', 'work_log', 'work_log__project', 'project')
|
||||||
|
|
||||||
if worker_id:
|
if worker_id:
|
||||||
adjustments = adjustments.filter(worker_id=worker_id)
|
adjustments = adjustments.filter(worker_id=worker_id)
|
||||||
|
|
||||||
if project_id:
|
if project_id:
|
||||||
# Include only adjustments linked to this project (via work_log)
|
# Include only adjustments linked to this project (via work_log OR direct project field)
|
||||||
adjustments = adjustments.filter(work_log__project_id=project_id)
|
adjustments = adjustments.filter(Q(work_log__project_id=project_id) | Q(project_id=project_id))
|
||||||
|
|
||||||
if team_id:
|
if team_id:
|
||||||
adjustments = adjustments.filter(work_log__team_id=team_id)
|
adjustments = adjustments.filter(work_log__team_id=team_id)
|
||||||
@ -439,7 +440,7 @@ def work_log_list(request):
|
|||||||
|
|
||||||
# --- 4. Combine and Sort ---
|
# --- 4. Combine and Sort ---
|
||||||
user_is_admin = is_admin(request.user)
|
user_is_admin = is_admin(request.user)
|
||||||
total_amount = 0
|
total_amount = Decimal('0.00')
|
||||||
combined_records = []
|
combined_records = []
|
||||||
|
|
||||||
# Prepare Chart Data (Overtime) - Admin only
|
# Prepare Chart Data (Overtime) - Admin only
|
||||||
@ -493,11 +494,18 @@ def work_log_list(request):
|
|||||||
if adj.type in DEDUCTIVE_TYPES:
|
if adj.type in DEDUCTIVE_TYPES:
|
||||||
amt = -amt
|
amt = -amt
|
||||||
|
|
||||||
|
# Determine Project Name
|
||||||
|
pname = adj.get_type_display()
|
||||||
|
if adj.project:
|
||||||
|
pname = f"{adj.get_type_display()} ({adj.project.name})"
|
||||||
|
elif adj.work_log and adj.work_log.project:
|
||||||
|
pname = f"{adj.get_type_display()} ({adj.work_log.project.name})"
|
||||||
|
|
||||||
record = {
|
record = {
|
||||||
'type': 'ADJ',
|
'type': 'ADJ',
|
||||||
'date': adj.date,
|
'date': adj.date,
|
||||||
'obj': adj,
|
'obj': adj,
|
||||||
'project_name': f"{adj.get_type_display()} ({adj.work_log.project.name})" if adj.work_log and getattr(adj.work_log, 'project', None) else f"{adj.get_type_display()}", # Use project column for Type
|
'project_name': pname, # Use project column for Type
|
||||||
'team_name': None,
|
'team_name': None,
|
||||||
'workers': [adj.worker],
|
'workers': [adj.worker],
|
||||||
'supervisor': "System",
|
'supervisor': "System",
|
||||||
@ -637,13 +645,13 @@ def export_work_log_csv(request):
|
|||||||
logs = logs.filter(paid_in__isnull=True)
|
logs = logs.filter(paid_in__isnull=True)
|
||||||
|
|
||||||
# --- 2. Fetch Adjustments ---
|
# --- 2. Fetch Adjustments ---
|
||||||
adjustments = PayrollAdjustment.objects.all().select_related('worker', 'payroll_record', 'work_log', 'work_log__project')
|
adjustments = PayrollAdjustment.objects.all().select_related('worker', 'payroll_record', 'work_log', 'work_log__project', 'project')
|
||||||
|
|
||||||
if worker_id:
|
if worker_id:
|
||||||
adjustments = adjustments.filter(worker_id=worker_id)
|
adjustments = adjustments.filter(worker_id=worker_id)
|
||||||
|
|
||||||
if project_id:
|
if project_id:
|
||||||
adjustments = adjustments.filter(work_log__project_id=project_id)
|
adjustments = adjustments.filter(Q(work_log__project_id=project_id) | Q(project_id=project_id))
|
||||||
|
|
||||||
if team_id:
|
if team_id:
|
||||||
adjustments = adjustments.filter(work_log__team_id=team_id)
|
adjustments = adjustments.filter(work_log__team_id=team_id)
|
||||||
@ -675,7 +683,7 @@ def export_work_log_csv(request):
|
|||||||
else:
|
else:
|
||||||
workers_str = ", ".join([w.name for w in log.workers.all()])
|
workers_str = ", ".join([w.name for w in log.workers.all()])
|
||||||
|
|
||||||
amt = 0
|
amt = Decimal('0.00')
|
||||||
is_paid = False
|
is_paid = False
|
||||||
if user_is_admin:
|
if user_is_admin:
|
||||||
if target_worker:
|
if target_worker:
|
||||||
@ -701,9 +709,15 @@ def export_work_log_csv(request):
|
|||||||
|
|
||||||
is_paid = adj.payroll_record is not None
|
is_paid = adj.payroll_record is not None
|
||||||
|
|
||||||
|
pname = adj.get_type_display()
|
||||||
|
if adj.project:
|
||||||
|
pname = f"{adj.get_type_display()} ({adj.project.name})"
|
||||||
|
elif adj.work_log and adj.work_log.project:
|
||||||
|
pname = f"{adj.get_type_display()} ({adj.work_log.project.name})"
|
||||||
|
|
||||||
combined.append({
|
combined.append({
|
||||||
'date': adj.date,
|
'date': adj.date,
|
||||||
'desc': f"{adj.get_type_display()} - {adj.description}",
|
'desc': f"{pname} - {adj.description}",
|
||||||
'workers': adj.worker.name,
|
'workers': adj.worker.name,
|
||||||
'amount': amt,
|
'amount': amt,
|
||||||
'status': "Paid" if is_paid else "Pending",
|
'status': "Paid" if is_paid else "Pending",
|
||||||
@ -774,7 +788,7 @@ def payroll_dashboard(request):
|
|||||||
status_filter = request.GET.get('status', 'pending') # pending, paid, all, loans
|
status_filter = request.GET.get('status', 'pending') # pending, paid, all, loans
|
||||||
|
|
||||||
# Common Analytics (prefetch all related data to avoid per-worker queries)
|
# Common Analytics (prefetch all related data to avoid per-worker queries)
|
||||||
outstanding_total = 0
|
outstanding_total = Decimal('0.00')
|
||||||
active_workers = Worker.objects.filter(is_active=True).order_by('name').prefetch_related(
|
active_workers = Worker.objects.filter(is_active=True).order_by('name').prefetch_related(
|
||||||
Prefetch(
|
Prefetch(
|
||||||
'work_logs',
|
'work_logs',
|
||||||
@ -785,7 +799,7 @@ def payroll_dashboard(request):
|
|||||||
),
|
),
|
||||||
Prefetch(
|
Prefetch(
|
||||||
'adjustments',
|
'adjustments',
|
||||||
queryset=PayrollAdjustment.objects.filter(payroll_record__isnull=True),
|
queryset=PayrollAdjustment.objects.filter(payroll_record__isnull=True).select_related('project', 'work_log', 'work_log__project'),
|
||||||
to_attr='pending_adjustments_list'
|
to_attr='pending_adjustments_list'
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -867,27 +881,34 @@ def payroll_dashboard(request):
|
|||||||
Prefetch('logs', queryset=WorkLog.objects.prefetch_related('workers', 'paid_in')),
|
Prefetch('logs', queryset=WorkLog.objects.prefetch_related('workers', 'paid_in')),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Bulk-fetch all pending project-linked adjustments in one query
|
# Bulk-fetch all project-linked adjustments
|
||||||
pending_proj_adjs = {}
|
all_proj_adjs = {}
|
||||||
for adj in PayrollAdjustment.objects.filter(
|
for adj in PayrollAdjustment.objects.filter(
|
||||||
work_log__project__isnull=False,
|
Q(project__isnull=False) | Q(work_log__project__isnull=False)
|
||||||
work_log__project__is_active=True,
|
).select_related('work_log', 'project'):
|
||||||
payroll_record__isnull=True,
|
pid = adj.project_id or adj.work_log.project_id
|
||||||
).select_related('work_log'):
|
all_proj_adjs.setdefault(pid, []).append(adj)
|
||||||
pid = adj.work_log.project_id
|
|
||||||
pending_proj_adjs.setdefault(pid, []).append(adj)
|
|
||||||
|
|
||||||
for project in active_projects:
|
for project in active_projects:
|
||||||
# 1. Total Historical Cost
|
# 1. Total Historical Cost
|
||||||
cost = 0
|
cost = Decimal('0.00')
|
||||||
|
# WorkLogs
|
||||||
for log in project.logs.all():
|
for log in project.logs.all():
|
||||||
for worker in log.workers.all():
|
for worker in log.workers.all():
|
||||||
cost += worker.day_rate
|
cost += worker.day_rate
|
||||||
|
|
||||||
|
# Adjustments
|
||||||
|
for adj in all_proj_adjs.get(project.id, []):
|
||||||
|
if adj.type in ADDITIVE_TYPES:
|
||||||
|
cost += adj.amount
|
||||||
|
elif adj.type in DEDUCTIVE_TYPES:
|
||||||
|
cost -= adj.amount
|
||||||
|
|
||||||
if cost > 0:
|
if cost > 0:
|
||||||
project_costs.append({'name': project.name, 'cost': cost})
|
project_costs.append({'name': project.name, 'cost': cost})
|
||||||
|
|
||||||
# 2. Outstanding Cost (Unpaid)
|
# 2. Outstanding Cost (Unpaid)
|
||||||
outstanding_cost = 0
|
outstanding_cost = Decimal('0.00')
|
||||||
|
|
||||||
# Unpaid WorkLogs (check paid_in in Python using prefetch cache)
|
# Unpaid WorkLogs (check paid_in in Python using prefetch cache)
|
||||||
for log in project.logs.all():
|
for log in project.logs.all():
|
||||||
@ -895,8 +916,9 @@ def payroll_dashboard(request):
|
|||||||
for worker in log.workers.all():
|
for worker in log.workers.all():
|
||||||
outstanding_cost += worker.day_rate
|
outstanding_cost += worker.day_rate
|
||||||
|
|
||||||
# Unpaid Adjustments linked to this project (from bulk-fetched dict)
|
# Unpaid Adjustments linked to this project
|
||||||
for adj in pending_proj_adjs.get(project.id, []):
|
for adj in all_proj_adjs.get(project.id, []):
|
||||||
|
if adj.payroll_record_id is None:
|
||||||
if adj.type in ADDITIVE_TYPES:
|
if adj.type in ADDITIVE_TYPES:
|
||||||
outstanding_cost += adj.amount
|
outstanding_cost += adj.amount
|
||||||
elif adj.type in DEDUCTIVE_TYPES:
|
elif adj.type in DEDUCTIVE_TYPES:
|
||||||
@ -960,10 +982,11 @@ def payroll_dashboard(request):
|
|||||||
|
|
||||||
ot_history_totals = [ot_by_month.get(ym, 0) for ym in chart_months]
|
ot_history_totals = [ot_by_month.get(ym, 0) for ym in chart_months]
|
||||||
|
|
||||||
# 1 query + prefetch: all work logs in the 6-month period for per-project costs
|
# Per-project costs (last 6 months)
|
||||||
all_project_names = list(Project.objects.values_list('name', flat=True).order_by('name'))
|
all_project_names = list(Project.objects.values_list('name', flat=True).order_by('name'))
|
||||||
project_monthly = {name: [0] * len(chart_months) for name in all_project_names}
|
project_monthly = {name: [0] * len(chart_months) for name in all_project_names}
|
||||||
|
|
||||||
|
# 1. Work Logs
|
||||||
all_chart_logs = WorkLog.objects.filter(
|
all_chart_logs = WorkLog.objects.filter(
|
||||||
date__gte=chart_start
|
date__gte=chart_start
|
||||||
).select_related('project').prefetch_related('workers')
|
).select_related('project').prefetch_related('workers')
|
||||||
@ -977,6 +1000,26 @@ def payroll_dashboard(request):
|
|||||||
for worker in log.workers.all():
|
for worker in log.workers.all():
|
||||||
project_monthly[pname][idx] += float(worker.day_rate)
|
project_monthly[pname][idx] += float(worker.day_rate)
|
||||||
|
|
||||||
|
# 2. Adjustments
|
||||||
|
all_chart_adjs = PayrollAdjustment.objects.filter(
|
||||||
|
date__gte=chart_start,
|
||||||
|
payroll_record__isnull=False # Only count paid adjustments for historical chart? Or all?
|
||||||
|
# Actually WorkLog chart includes all logs. Let's include all adjustments for consistency.
|
||||||
|
).select_related('project', 'work_log', 'work_log__project')
|
||||||
|
|
||||||
|
for adj in all_chart_adjs:
|
||||||
|
month_key = (adj.date.year, adj.date.month)
|
||||||
|
idx = chart_month_index.get(month_key)
|
||||||
|
if idx is not None:
|
||||||
|
project = adj.project or (adj.work_log.project if adj.work_log else None)
|
||||||
|
if project:
|
||||||
|
pname = project.name
|
||||||
|
if pname in project_monthly:
|
||||||
|
amt = float(adj.amount)
|
||||||
|
if adj.type in DEDUCTIVE_TYPES:
|
||||||
|
amt = -amt
|
||||||
|
project_monthly[pname][idx] += amt
|
||||||
|
|
||||||
# Filter out projects with zero cost across all months
|
# Filter out projects with zero cost across all months
|
||||||
project_chart_data = [
|
project_chart_data = [
|
||||||
{'name': name, 'data': costs}
|
{'name': name, 'data': costs}
|
||||||
@ -1185,7 +1228,8 @@ def price_overtime(request):
|
|||||||
amount=amount,
|
amount=amount,
|
||||||
date=worklog.date,
|
date=worklog.date,
|
||||||
description=f"Overtime: {worklog.get_overtime_display()} @ {rate_pct}% - {worklog.date.strftime('%d %b %Y')}",
|
description=f"Overtime: {worklog.get_overtime_display()} @ {rate_pct}% - {worklog.date.strftime('%d %b %Y')}",
|
||||||
work_log=worklog
|
work_log=worklog,
|
||||||
|
project=worklog.project # Link project directly
|
||||||
)
|
)
|
||||||
created += 1
|
created += 1
|
||||||
|
|
||||||
@ -1296,6 +1340,10 @@ def add_adjustment(request):
|
|||||||
messages.error(request, "Amount must be greater than zero.")
|
messages.error(request, "Amount must be greater than zero.")
|
||||||
return redirect('payroll_dashboard')
|
return redirect('payroll_dashboard')
|
||||||
|
|
||||||
|
project = None
|
||||||
|
if project_id:
|
||||||
|
project = get_object_or_404(Project, pk=project_id)
|
||||||
|
|
||||||
if worker_ids and amount and adj_type:
|
if worker_ids and amount and adj_type:
|
||||||
success_names = []
|
success_names = []
|
||||||
skip_names = []
|
skip_names = []
|
||||||
@ -1335,10 +1383,6 @@ def add_adjustment(request):
|
|||||||
if project_id:
|
if project_id:
|
||||||
# Try to find a worklog for this worker and project to link the adjustment to the project
|
# 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()
|
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,
|
||||||
@ -1347,6 +1391,7 @@ def add_adjustment(request):
|
|||||||
description=description or 'Advance payment',
|
description=description or 'Advance payment',
|
||||||
date=date,
|
date=date,
|
||||||
work_log=work_log_link,
|
work_log=work_log_link,
|
||||||
|
project=project
|
||||||
)
|
)
|
||||||
|
|
||||||
advance_date = date if isinstance(date, datetime.date) else timezone.now().date()
|
advance_date = date if isinstance(date, datetime.date) else timezone.now().date()
|
||||||
@ -1354,7 +1399,6 @@ 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'
|
notes=description or 'Advance payment'
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1416,10 +1460,6 @@ def add_adjustment(request):
|
|||||||
if project_id:
|
if project_id:
|
||||||
# Try to find a worklog for this worker and project to link the adjustment to the project
|
# 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()
|
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,
|
||||||
@ -1428,7 +1468,8 @@ def add_adjustment(request):
|
|||||||
description=description,
|
description=description,
|
||||||
date=date,
|
date=date,
|
||||||
loan=loan,
|
loan=loan,
|
||||||
work_log=work_log_link
|
work_log=work_log_link,
|
||||||
|
project=project
|
||||||
)
|
)
|
||||||
success_names.append(worker.name)
|
success_names.append(worker.name)
|
||||||
|
|
||||||
@ -1479,12 +1520,13 @@ def edit_adjustment(request, pk):
|
|||||||
adj.date = date
|
adj.date = date
|
||||||
|
|
||||||
if project_id:
|
if project_id:
|
||||||
|
project = get_object_or_404(Project, pk=project_id)
|
||||||
|
adj.project = project
|
||||||
|
# Try to update work_log link too
|
||||||
work_log_link = adj.worker.work_logs.filter(project_id=project_id).order_by('-date').first()
|
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
|
adj.work_log = work_log_link
|
||||||
elif project_id == '':
|
elif project_id == '':
|
||||||
|
adj.project = None
|
||||||
adj.work_log = None
|
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)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user