93 lines
4.9 KiB
Python
93 lines
4.9 KiB
Python
from django import forms
|
|
from .models import EmployeeProfile, SalarySlip, PayrollCentralizationEntry
|
|
from decimal import Decimal
|
|
|
|
class EmployeeProfileForm(forms.ModelForm):
|
|
hire_date = forms.DateField(
|
|
widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
|
|
label='Fecha de Contratación'
|
|
)
|
|
base_salary_clp = forms.DecimalField(
|
|
label='Sueldo Base Mensual (CLP)',
|
|
widget=forms.NumberInput(attrs={'class': 'form-control', 'step': '1000', 'min': '0', 'required': True})
|
|
)
|
|
colacion_clp = forms.DecimalField(
|
|
label='Asignación Colación (CLP)',
|
|
widget=forms.NumberInput(attrs={'class': 'form-control', 'step': '1000', 'min': '0'})
|
|
)
|
|
movilizacion_clp = forms.DecimalField(
|
|
label='Asignación Movilización (CLP)',
|
|
widget=forms.NumberInput(attrs={'class': 'form-control', 'step': '1000', 'min': '0'})
|
|
)
|
|
|
|
class Meta:
|
|
model = EmployeeProfile
|
|
fields = [
|
|
'rut', 'first_name', 'last_name', 'email', 'phone', 'address',
|
|
'position', 'department', 'contract_type', 'work_schedule', 'hire_date',
|
|
'afp', 'afp_rate', 'health_system', 'health_institution', 'health_plan_uf',
|
|
'has_afc', 'base_salary_clp', 'colacion_clp', 'movilizacion_clp',
|
|
'bank_name', 'account_type', 'account_number', 'is_active'
|
|
]
|
|
widgets = {
|
|
'rut': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Ej: 12.345.678-9', 'pattern': r'^(\d{7,8}-[\dkK])$', 'required': True, 'title': 'RUT sin puntos y con guion'}),
|
|
'first_name': forms.TextInput(attrs={'class': 'form-control', 'required': True, 'minlength': '2'}),
|
|
'last_name': forms.TextInput(attrs={'class': 'form-control', 'required': True, 'minlength': '2'}),
|
|
'email': forms.EmailInput(attrs={'class': 'form-control', 'required': True}),
|
|
'phone': forms.TextInput(attrs={'class': 'form-control', 'pattern': r'^\+?\d{9,15}$', 'title': 'Teléfono válido (ej: +56912345678)'}),
|
|
'address': forms.TextInput(attrs={'class': 'form-control'}),
|
|
'position': forms.TextInput(attrs={'class': 'form-control', 'required': True}),
|
|
'department': forms.TextInput(attrs={'class': 'form-control', 'required': True}),
|
|
'contract_type': forms.Select(attrs={'class': 'form-control', 'required': True}),
|
|
'work_schedule': forms.Select(attrs={'class': 'form-control', 'required': True}),
|
|
'afp': forms.Select(attrs={'class': 'form-control', 'required': True}),
|
|
'afp_rate': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01', 'min': '0', 'max': '100', 'required': True}),
|
|
'health_system': forms.Select(attrs={'class': 'form-control', 'required': True}),
|
|
'health_institution': forms.TextInput(attrs={'class': 'form-control'}),
|
|
'health_plan_uf': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.0001', 'min': '0'}),
|
|
'bank_name': forms.TextInput(attrs={'class': 'form-control', 'required': True}),
|
|
'account_type': forms.Select(attrs={'class': 'form-control', 'required': True}),
|
|
'account_number': forms.TextInput(attrs={'class': 'form-control', 'required': True, 'pattern': r'^\d+$', 'title': 'Solo números'}),
|
|
}
|
|
|
|
|
|
class SalarySlipGenerateForm(forms.Form):
|
|
month = forms.ChoiceField(
|
|
choices=[(i, f"{i:02d} - {m}") for i, m in enumerate([
|
|
"Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio",
|
|
"Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"
|
|
], 1)],
|
|
label="Mes a Liquidar",
|
|
widget=forms.Select(attrs={'class': 'form-control'})
|
|
)
|
|
year = forms.IntegerField(
|
|
initial=2026,
|
|
label="Año",
|
|
widget=forms.NumberInput(attrs={'class': 'form-control'})
|
|
)
|
|
employee = forms.ModelChoiceField(
|
|
queryset=EmployeeProfile.objects.filter(is_active=True),
|
|
required=False,
|
|
empty_label="--- Todos los colaboradores activos (Cálculo Masivo) ---",
|
|
label="Colaborador Específico",
|
|
widget=forms.Select(attrs={'class': 'form-control'})
|
|
)
|
|
overtime_hours = forms.DecimalField(
|
|
initial=Decimal('0'),
|
|
required=False,
|
|
label="Horas Extras 50% (Aplica a cálculo individual)",
|
|
widget=forms.NumberInput(attrs={'class': 'form-control', 'step': '0.5', 'min': '0'})
|
|
)
|
|
rd_bonus = forms.DecimalField(
|
|
initial=Decimal('0'),
|
|
required=False,
|
|
label="Bono I+D+i / Desempeño (CLP)",
|
|
widget=forms.NumberInput(attrs={'class': 'form-control', 'step': '10000', 'min': '0'})
|
|
)
|
|
other_deductions = forms.DecimalField(
|
|
initial=Decimal('0'),
|
|
required=False,
|
|
label="Otros Descuentos / Anticipos (CLP)",
|
|
widget=forms.NumberInput(attrs={'class': 'form-control', 'step': '1000', 'min': '0'})
|
|
)
|