huge fix
This commit is contained in:
		
							parent
							
								
									810c87e2e0
								
							
						
					
					
						commit
						b5bf3a5dbe
					
				
					 51 changed files with 2397 additions and 326 deletions
				
			
		
							
								
								
									
										208
									
								
								installations/forms.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								installations/forms.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,208 @@
 | 
			
		|||
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'
 | 
			
		||||
            }),
 | 
			
		||||
            'seal_number': forms.TextInput(attrs={
 | 
			
		||||
                'class': 'form-control'
 | 
			
		||||
            }),
 | 
			
		||||
            'utm_x': forms.NumberInput(attrs={
 | 
			
		||||
                'class': 'form-control',
 | 
			
		||||
                'step': '1'
 | 
			
		||||
            }),
 | 
			
		||||
            'utm_y': forms.NumberInput(attrs={
 | 
			
		||||
                'class': 'form-control',
 | 
			
		||||
                'step': '1'
 | 
			
		||||
            }),
 | 
			
		||||
            'meter_type': forms.Select(attrs={
 | 
			
		||||
                'class': 'form-select'
 | 
			
		||||
            }, choices=[
 | 
			
		||||
                ('', 'انتخاب کنید'),
 | 
			
		||||
                ('smart', 'هوشمند (آبی/برق)'),
 | 
			
		||||
                ('volumetric', 'حجمی')
 | 
			
		||||
            ]),
 | 
			
		||||
            'meter_size': forms.TextInput(attrs={
 | 
			
		||||
                'class': 'form-control'
 | 
			
		||||
            }),
 | 
			
		||||
            'discharge_pipe_diameter': forms.NumberInput(attrs={
 | 
			
		||||
                'class': 'form-control',
 | 
			
		||||
                'min': '0',
 | 
			
		||||
                'step': '1'
 | 
			
		||||
            }),
 | 
			
		||||
            'usage_type': forms.Select(attrs={
 | 
			
		||||
                'class': 'form-select'
 | 
			
		||||
            }, 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'
 | 
			
		||||
            }),
 | 
			
		||||
            'pre_calibration_flow_rate': forms.NumberInput(attrs={
 | 
			
		||||
                'class': 'form-control',
 | 
			
		||||
                'min': '0',
 | 
			
		||||
                'step': '0.01'
 | 
			
		||||
            }),
 | 
			
		||||
            'post_calibration_flow_rate': forms.NumberInput(attrs={
 | 
			
		||||
                'class': 'form-control',
 | 
			
		||||
                'min': '0',
 | 
			
		||||
                'step': '0.01'
 | 
			
		||||
            }),
 | 
			
		||||
            'water_meter_manufacturer': forms.Select(attrs={
 | 
			
		||||
                'class': 'form-select',
 | 
			
		||||
                'id': 'id_water_meter_manufacturer'
 | 
			
		||||
            }),
 | 
			
		||||
            'sim_number': forms.TextInput(attrs={
 | 
			
		||||
                'class': 'form-control'
 | 
			
		||||
            }),
 | 
			
		||||
            'driving_force': forms.TextInput(attrs={
 | 
			
		||||
                'class': 'form-control'
 | 
			
		||||
            }),
 | 
			
		||||
            '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
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue