- core/utils.py: render_to_pdf() wrapper for xhtml2pdf - core/templates/core/pdf/payslip_pdf.html: A4 PDF payslip (matches V2 layout) - core/templates/core/email/payslip_email.html: HTML email body for Spark - core/templates/core/payslip.html: browser payslip detail page with print - core/views.py: add payslip_detail view, wire email+PDF into process_payment - core/urls.py: add payroll/payslip/<pk>/ route - config/settings.py: add SPARK_RECEIPT_EMAIL setting - payroll_dashboard.html: add "View" payslip link in Payment History tab All templates show adjustments (bonuses, deductions, overtime, loan repayments) as line items. Amounts always show 2 decimal places. Email failure does not roll back payment — handled gracefully with warning message. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
53 lines
2.3 KiB
Python
53 lines
2.3 KiB
Python
# === URL ROUTING ===
|
|
# Maps URLs to view functions. Each path() connects a web address to
|
|
# the Python function that handles it.
|
|
|
|
from django.urls import path
|
|
from . import views
|
|
|
|
urlpatterns = [
|
|
# Dashboard — the home page after login
|
|
path('', views.index, name='home'),
|
|
|
|
# Attendance logging — where supervisors log daily work
|
|
path('attendance/log/', views.attendance_log, name='attendance_log'),
|
|
|
|
# Work history — table of all work logs with filters
|
|
path('history/', views.work_history, name='work_history'),
|
|
|
|
# CSV export — downloads filtered work logs as a spreadsheet
|
|
path('history/export/', views.export_work_log_csv, name='export_work_log_csv'),
|
|
|
|
# AJAX toggle — activates/deactivates workers, projects, teams from dashboard
|
|
path('toggle/<str:model_name>/<int:item_id>/', views.toggle_active, name='toggle_active'),
|
|
|
|
# === PAYROLL ===
|
|
# Main payroll dashboard — shows pending payments, history, loans, and charts
|
|
path('payroll/', views.payroll_dashboard, name='payroll_dashboard'),
|
|
|
|
# Process payment — pays a worker and links their unpaid logs + adjustments
|
|
path('payroll/pay/<int:worker_id>/', views.process_payment, name='process_payment'),
|
|
|
|
# Price overtime — creates Overtime adjustments from unpriced OT entries
|
|
path('payroll/price-overtime/', views.price_overtime, name='price_overtime'),
|
|
|
|
# Add a new payroll adjustment (bonus, deduction, loan, etc.)
|
|
path('payroll/adjustment/add/', views.add_adjustment, name='add_adjustment'),
|
|
|
|
# Edit an existing unpaid adjustment
|
|
path('payroll/adjustment/<int:adj_id>/edit/', views.edit_adjustment, name='edit_adjustment'),
|
|
|
|
# Delete an unpaid adjustment
|
|
path('payroll/adjustment/<int:adj_id>/delete/', views.delete_adjustment, name='delete_adjustment'),
|
|
|
|
# Preview a worker's payslip (AJAX — returns JSON)
|
|
path('payroll/preview/<int:worker_id>/', views.preview_payslip, name='preview_payslip'),
|
|
|
|
# View a completed payslip (print-friendly page)
|
|
path('payroll/payslip/<int:pk>/', views.payslip_detail, name='payslip_detail'),
|
|
|
|
# === TEMPORARY: Import production data from browser ===
|
|
# Visit /import-data/ once to populate the database. Remove after use.
|
|
path('import-data/', views.import_data, name='import_data'),
|
|
]
|