shafafiyat/installations/forms.py

221 lines
8.9 KiB
Python

from django import forms
from django.core.exceptions import ValidationError
from .models import InstallationReport
from wells.models import WaterMeterManufacturer
class InstallationReportForm(forms.ModelForm):
# Additional fields for manufacturer handling
new_manufacturer = forms.CharField(
max_length=100,
required=False,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'شرکت سازنده جدید',
'style': 'display:none;'
})
)
class Meta:
model = InstallationReport
fields = [
'visited_date', 'new_water_meter_serial', 'seal_number',
'utm_x', 'utm_y', 'meter_type', 'meter_size',
'discharge_pipe_diameter', 'usage_type', 'exploitation_license_number',
'motor_power', 'pre_calibration_flow_rate', 'post_calibration_flow_rate',
'water_meter_manufacturer', 'sim_number', 'driving_force',
'is_meter_suspicious', 'description'
]
widgets = {
'visited_date': forms.DateInput(attrs={
'type': 'date',
'class': 'form-control',
'required': True
}),
'new_water_meter_serial': forms.TextInput(attrs={
'class': 'form-control',
'required': True
}),
'seal_number': forms.TextInput(attrs={
'class': 'form-control',
'required': True
}),
'utm_x': forms.NumberInput(attrs={
'class': 'form-control',
'step': '1',
'required': True
}),
'utm_y': forms.NumberInput(attrs={
'class': 'form-control',
'step': '1',
'required': True
}),
'meter_type': forms.Select(attrs={
'class': 'form-select',
'required': True
}, choices=[
('', 'انتخاب کنید'),
('smart', 'هوشمند (آب و برق)'),
('volumetric', 'حجمی')
]),
'meter_size': forms.TextInput(attrs={
'class': 'form-control'
}),
'discharge_pipe_diameter': forms.NumberInput(attrs={
'class': 'form-control',
'min': '0',
'step': '1',
'required': True
}),
'usage_type': forms.Select(attrs={
'class': 'form-select',
'required': True
}, choices=[
('', 'انتخاب کنید'),
('domestic', 'شرب و خدمات'),
('agriculture', 'کشاورزی'),
('industrial', 'صنعتی')
]),
'exploitation_license_number': forms.TextInput(attrs={
'class': 'form-control',
'required': True
}),
'motor_power': forms.NumberInput(attrs={
'class': 'form-control',
'min': '0',
'step': '1',
'required': True
}),
'pre_calibration_flow_rate': forms.NumberInput(attrs={
'class': 'form-control',
'min': '0',
'step': '0.01',
'required': True
}),
'post_calibration_flow_rate': forms.NumberInput(attrs={
'class': 'form-control',
'min': '0',
'step': '0.01',
'required': True
}),
'water_meter_manufacturer': forms.Select(attrs={
'class': 'form-select',
'id': 'id_water_meter_manufacturer',
'required': True
}),
'sim_number': forms.TextInput(attrs={
'class': 'form-control',
'required': True
}),
'driving_force': forms.TextInput(attrs={
'class': 'form-control',
'required': True
}),
'is_meter_suspicious': forms.CheckboxInput(attrs={
'class': 'form-check-input',
'id': 'id_is_meter_suspicious',
}),
'description': forms.Textarea(attrs={
'class': 'form-control',
'rows': 3
})
}
labels = {
'visited_date': 'تاریخ مراجعه',
'new_water_meter_serial': 'سریال کنتور جدید',
'seal_number': 'شماره پلمپ',
'utm_x': 'UTM X',
'utm_y': 'UTM Y',
'meter_type': 'نوع کنتور',
'meter_size': 'سایز کنتور',
'discharge_pipe_diameter': 'قطر لوله آبده (اینچ)',
'usage_type': 'نوع مصرف',
'exploitation_license_number': 'شماره پروانه بهره‌برداری',
'motor_power': 'قدرت موتور (کیلووات ساعت)',
'pre_calibration_flow_rate': 'دبی قبل از کالیبراسیون (لیتر بر ثانیه)',
'post_calibration_flow_rate': 'دبی بعد از کالیبراسیون (لیتر بر ثانیه)',
'water_meter_manufacturer': 'شرکت سازنده کنتور',
'sim_number': 'شماره سیمکارت',
'driving_force': 'نیرو محرکه چاه',
'is_meter_suspicious': 'کنتور مشکوک است',
'description': 'توضیحات'
}
def __init__(self, *args, **kwargs):
self.user_is_installer = kwargs.pop('user_is_installer', False)
self.instance_well = kwargs.pop('instance_well', None)
super().__init__(*args, **kwargs)
# Set manufacturer choices
manufacturers = WaterMeterManufacturer.objects.filter(is_deleted=False)
manufacturer_choices = [('', 'انتخاب شرکت سازنده')]
manufacturer_choices.extend([(m.id, m.name) for m in manufacturers])
self.fields['water_meter_manufacturer'].choices = manufacturer_choices
# Pre-fill UTM from well if available and no existing report data
if self.instance_well and not self.instance.pk:
if self.instance_well.utm_x:
self.initial['utm_x'] = self.instance_well.utm_x
if self.instance_well.utm_y:
self.initial['utm_y'] = self.instance_well.utm_y
# Disable fields for non-installers
if not self.user_is_installer:
for field_name, field in self.fields.items():
if field_name != 'new_manufacturer': # Keep this always disabled via CSS
field.widget.attrs['readonly'] = True
if isinstance(field.widget, (forms.Select, forms.CheckboxInput)):
field.widget.attrs['disabled'] = True
def clean(self):
cleaned_data = super().clean()
# Handle new manufacturer creation
new_manufacturer = cleaned_data.get('new_manufacturer')
water_meter_manufacturer = cleaned_data.get('water_meter_manufacturer')
if new_manufacturer and not water_meter_manufacturer:
# Create new manufacturer
manufacturer, created = WaterMeterManufacturer.objects.get_or_create(
name=new_manufacturer,
defaults={'is_deleted': False}
)
cleaned_data['water_meter_manufacturer'] = manufacturer
return cleaned_data
def clean_visited_date(self):
visited_date = self.cleaned_data.get('visited_date')
if not visited_date:
raise ValidationError('تاریخ مراجعه الزامی است.')
return visited_date
def clean_exploitation_license_number(self):
license_number = self.cleaned_data.get('exploitation_license_number')
if not license_number or not license_number.strip():
raise ValidationError('شماره پروانه بهره‌برداری الزامی است.')
return license_number.strip()
def validate_photos(self, request_files, existing_photos, deleted_photo_ids):
"""
Validate that at least one photo is present (either existing or newly uploaded)
This method should be called from the view after form.is_valid()
"""
# Count existing photos that are not deleted
kept_existing = 0
if existing_photos:
for photo in existing_photos:
if str(photo.id) not in deleted_photo_ids:
kept_existing += 1
# Count new photos
new_photos = len(request_files.getlist('photos')) if request_files else 0
total_photos = kept_existing + new_photos
if total_photos <= 0:
raise ValidationError('بارگذاری حداقل یک عکس الزامی است.')
return True