Ver 12 Working

This commit is contained in:
Flatlogic Bot 2026-02-06 07:07:50 +00:00
parent 0fbf30ddc5
commit d54bf8a44c
6 changed files with 196 additions and 0 deletions

View File

@ -0,0 +1,103 @@
from django.core.management.base import BaseCommand
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
class Command(BaseCommand):
help = 'Renames permissions to be more user-friendly'
def handle(self, *args, **options):
# Dictionary mapping (app_label, model_name, codename) -> New Name
# Or just (codename) -> New Name if unique enough, but (app, model) is safer.
# We can also map just the model's permissions generically if we want.
renames = {
# Core App - Business Logic
('core', 'project', 'add_project'): 'Manage: Create New Project',
('core', 'project', 'change_project'): 'Manage: Edit Project Details',
('core', 'project', 'delete_project'): 'Manage: Delete Project',
('core', 'project', 'view_project'): 'Manage: View Projects (Dashboard Access)',
('core', 'worker', 'add_worker'): 'Manage: Add New Worker',
('core', 'worker', 'change_worker'): 'Manage: Edit Worker Details',
('core', 'worker', 'delete_worker'): 'Manage: Delete Worker',
('core', 'worker', 'view_worker'): 'Manage: View Worker Profiles',
('core', 'team', 'add_team'): 'Manage: Create Team',
('core', 'team', 'change_team'): 'Manage: Edit Team Structure',
('core', 'team', 'delete_team'): 'Manage: Delete Team',
('core', 'team', 'view_team'): 'Manage: View Teams',
('core', 'worklog', 'add_worklog'): 'Log Work: Add Attendance Entry',
('core', 'worklog', 'change_worklog'): 'Log Work: Edit Attendance Entry',
('core', 'worklog', 'delete_worklog'): 'Log Work: Delete Attendance Entry',
('core', 'worklog', 'view_worklog'): 'Log Work: View Attendance History',
('core', 'payrollrecord', 'add_payrollrecord'): 'Payroll: Generate Payment Record',
('core', 'payrollrecord', 'change_payrollrecord'): 'Payroll: Edit Payment Record',
('core', 'payrollrecord', 'delete_payrollrecord'): 'Payroll: Delete Payment Record',
('core', 'payrollrecord', 'view_payrollrecord'): 'Payroll: View Payment History',
('core', 'loan', 'add_loan'): 'Loans: Create New Loan',
('core', 'loan', 'change_loan'): 'Loans: Edit Loan Details',
('core', 'loan', 'delete_loan'): 'Loans: Delete Loan',
('core', 'loan', 'view_loan'): 'Loans: View Loan Registry',
('core', 'expensereceipt', 'add_expensereceipt'): 'Receipts: Add Expense Receipt',
('core', 'expensereceipt', 'change_expensereceipt'): 'Receipts: Edit Expense Receipt',
('core', 'expensereceipt', 'delete_expensereceipt'): 'Receipts: Delete Expense Receipt',
('core', 'expensereceipt', 'view_expensereceipt'): 'Receipts: View Expense History',
# Auth App
('auth', 'user', 'add_user'): 'Admin: Create User Accounts',
('auth', 'user', 'change_user'): 'Admin: Edit User Accounts',
('auth', 'user', 'delete_user'): 'Admin: Delete User Accounts',
('auth', 'user', 'view_user'): 'Admin: View User Accounts',
('auth', 'group', 'add_group'): 'Admin: Create Permission Groups',
('auth', 'group', 'change_group'): 'Admin: Edit Permission Groups',
('auth', 'group', 'delete_group'): 'Admin: Delete Permission Groups',
('auth', 'group', 'view_group'): 'Admin: View Permission Groups',
# System / Technical (Marking as Technical to help user ignore them)
('sessions', 'session', 'add_session'): 'System (Tech): Add Session',
('sessions', 'session', 'change_session'): 'System (Tech): Manage Sessions',
('sessions', 'session', 'delete_session'): 'System (Tech): Clear Sessions',
('sessions', 'session', 'view_session'): 'System (Tech): View Sessions',
('admin', 'logentry', 'add_logentry'): 'System (Tech): Add Admin Log',
('admin', 'logentry', 'change_logentry'): 'System (Tech): Edit Admin Log',
('admin', 'logentry', 'delete_logentry'): 'System (Tech): Clear Admin Log',
('admin', 'logentry', 'view_logentry'): 'System (Tech): View Admin Log',
('contenttypes', 'contenttype', 'add_contenttype'): 'System (Tech): Add Content Type',
('contenttypes', 'contenttype', 'change_contenttype'): 'System (Tech): Edit Content Type',
('contenttypes', 'contenttype', 'delete_contenttype'): 'System (Tech): Delete Content Type',
('contenttypes', 'contenttype', 'view_contenttype'): 'System (Tech): View Content Types',
}
count = 0
for (app_label, model, codename), new_name in renames.items():
try:
# We need to find the content type first to be safe, or filter by codename + content_type__app_label
# but direct filter is easiest if unique.
# However, codenames can be shared across models (though rare for standard CRUD).
# Safer to lookup ContentType.
ct = ContentType.objects.filter(app_label=app_label, model=model).first()
if not ct:
self.stdout.write(self.style.WARNING(f"Model {app_label}.{model} not found, skipping."))
continue
perm = Permission.objects.filter(content_type=ct, codename=codename).first()
if perm:
perm.name = new_name
perm.save()
self.stdout.write(f"Renamed {codename} -> {new_name}")
count += 1
else:
self.stdout.write(self.style.WARNING(f"Permission {codename} for {app_label}.{model} not found."))
except Exception as e:
self.stdout.write(self.style.ERROR(f"Error renaming {codename}: {e}"))
self.stdout.write(self.style.SUCCESS(f"Successfully updated {count} permission names."))

View File

@ -0,0 +1,53 @@
# Generated by Django 5.2.7 on 2026-02-04 20:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('core', '0009_worker_date_of_employment_worker_id_photo_and_more'),
]
operations = [
migrations.AlterModelOptions(
name='expenselineitem',
options={'verbose_name': 'Expense Line Item', 'verbose_name_plural': 'Expense Line Items'},
),
migrations.AlterModelOptions(
name='expensereceipt',
options={'verbose_name': 'Expense Receipt', 'verbose_name_plural': 'Expense Receipts'},
),
migrations.AlterModelOptions(
name='loan',
options={'verbose_name': 'Loan', 'verbose_name_plural': 'Loans'},
),
migrations.AlterModelOptions(
name='payrolladjustment',
options={'verbose_name': 'Payroll Adjustment', 'verbose_name_plural': 'Payroll Adjustments'},
),
migrations.AlterModelOptions(
name='payrollrecord',
options={'verbose_name': 'Payroll Record', 'verbose_name_plural': 'Payroll Records'},
),
migrations.AlterModelOptions(
name='project',
options={'verbose_name': 'Project', 'verbose_name_plural': 'Projects'},
),
migrations.AlterModelOptions(
name='team',
options={'verbose_name': 'Team', 'verbose_name_plural': 'Teams'},
),
migrations.AlterModelOptions(
name='userprofile',
options={'verbose_name': 'User Profile', 'verbose_name_plural': 'User Profiles'},
),
migrations.AlterModelOptions(
name='worker',
options={'verbose_name': 'Worker', 'verbose_name_plural': 'Workers'},
),
migrations.AlterModelOptions(
name='worklog',
options={'verbose_name': 'Work Log / Attendance', 'verbose_name_plural': 'Work Logs / Attendance'},
),
]

View File

@ -9,6 +9,10 @@ class UserProfile(models.Model):
pin = models.CharField(max_length=4, help_text="4-digit PIN for login")
is_admin = models.BooleanField(default=False)
class Meta:
verbose_name = "User Profile"
verbose_name_plural = "User Profiles"
def __str__(self):
return f"{self.user.username}'s profile"
@ -19,6 +23,10 @@ class Project(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
class Meta:
verbose_name = "Project"
verbose_name_plural = "Projects"
def __str__(self):
return self.name
@ -37,6 +45,10 @@ class Worker(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
class Meta:
verbose_name = "Worker"
verbose_name_plural = "Workers"
@property
def day_rate(self):
return self.monthly_salary / Decimal('20.0')
@ -56,6 +68,10 @@ class Team(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
class Meta:
verbose_name = "Team"
verbose_name_plural = "Teams"
def __str__(self):
return self.name
@ -66,6 +82,10 @@ class WorkLog(models.Model):
supervisor = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
notes = models.TextField(blank=True)
class Meta:
verbose_name = "Work Log / Attendance"
verbose_name_plural = "Work Logs / Attendance"
def __str__(self):
return f"{self.date} - {self.project.name}"
@ -76,6 +96,10 @@ class PayrollRecord(models.Model):
work_logs = models.ManyToManyField(WorkLog, related_name='paid_in')
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "Payroll Record"
verbose_name_plural = "Payroll Records"
def __str__(self):
return f"Payment to {self.worker.name} on {self.date}"
@ -87,6 +111,10 @@ class Loan(models.Model):
reason = models.TextField(blank=True)
is_active = models.BooleanField(default=True)
class Meta:
verbose_name = "Loan"
verbose_name_plural = "Loans"
def save(self, *args, **kwargs):
if not self.pk: # On creation
self.balance = self.amount
@ -112,6 +140,10 @@ class PayrollAdjustment(models.Model):
description = models.CharField(max_length=255)
type = models.CharField(max_length=20, choices=ADJUSTMENT_TYPES, default='DEDUCTION')
class Meta:
verbose_name = "Payroll Adjustment"
verbose_name_plural = "Payroll Adjustments"
def __str__(self):
return f"{self.get_type_display()} - {self.amount} for {self.worker.name}"
@ -142,6 +174,10 @@ class ExpenseReceipt(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "Expense Receipt"
verbose_name_plural = "Expense Receipts"
def __str__(self):
return f"Receipt from {self.vendor} - {self.date}"
@ -150,5 +186,9 @@ class ExpenseLineItem(models.Model):
product = models.CharField(max_length=255, verbose_name="Product/Item")
amount = models.DecimalField(max_digits=10, decimal_places=2)
class Meta:
verbose_name = "Expense Line Item"
verbose_name_plural = "Expense Line Items"
def __str__(self):
return f"{self.product} - {self.amount}"