Compare commits
	
		
			No commits in common. "production" and "main" have entirely different histories.
		
	
	
		
			production
			...
			main
		
	
		
					 17 changed files with 348 additions and 358 deletions
				
			
		
							
								
								
									
										294
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										294
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,12 +1,142 @@
 | 
			
		|||
# Byte-compiled / optimized / DLL files
 | 
			
		||||
.idea
 | 
			
		||||
 | 
			
		||||
# Created by https://www.toptal.com/developers/gitignore/api/django,python,virtualenv
 | 
			
		||||
# Edit at https://www.toptal.com/developers/gitignore?templates=django,python,virtualenv
 | 
			
		||||
 | 
			
		||||
### Django ###
 | 
			
		||||
*.log
 | 
			
		||||
*.pot
 | 
			
		||||
*.pyc
 | 
			
		||||
__pycache__/
 | 
			
		||||
local_settings.py
 | 
			
		||||
#*.sqlite3
 | 
			
		||||
#db.sqlite3
 | 
			
		||||
db.sqlite3-journal
 | 
			
		||||
media
 | 
			
		||||
#static
 | 
			
		||||
staticfiles
 | 
			
		||||
profile_images
 | 
			
		||||
 | 
			
		||||
# If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/
 | 
			
		||||
# in your Git repository. Update and uncomment the following line accordingly.
 | 
			
		||||
# <django-project-name>/staticfiles/
 | 
			
		||||
 | 
			
		||||
# db.sqlite3
 | 
			
		||||
### Django.Python Stack ###
 | 
			
		||||
# Byte-compiled / optimized / DLL files
 | 
			
		||||
*.py[cod]
 | 
			
		||||
*$py.class
 | 
			
		||||
 | 
			
		||||
# C extensions
 | 
			
		||||
*.so
 | 
			
		||||
 | 
			
		||||
# Distribution / packaging
 | 
			
		||||
.Python
 | 
			
		||||
build/
 | 
			
		||||
develop-eggs/
 | 
			
		||||
#dist/
 | 
			
		||||
downloads/
 | 
			
		||||
eggs/
 | 
			
		||||
.eggs/
 | 
			
		||||
lib/
 | 
			
		||||
lib64/
 | 
			
		||||
parts/
 | 
			
		||||
sdist/
 | 
			
		||||
var/
 | 
			
		||||
wheels/
 | 
			
		||||
share/python-wheels/
 | 
			
		||||
*.egg-info/
 | 
			
		||||
.installed.cfg
 | 
			
		||||
*.egg
 | 
			
		||||
MANIFEST
 | 
			
		||||
 | 
			
		||||
# PyInstaller
 | 
			
		||||
#  Usually these files are written by a python script from a template
 | 
			
		||||
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
 | 
			
		||||
*.manifest
 | 
			
		||||
*.spec
 | 
			
		||||
 | 
			
		||||
# Installer logs
 | 
			
		||||
pip-log.txt
 | 
			
		||||
pip-delete-this-directory.txt
 | 
			
		||||
 | 
			
		||||
# Unit test / coverage reports
 | 
			
		||||
htmlcov/
 | 
			
		||||
.tox/
 | 
			
		||||
.nox/
 | 
			
		||||
.coverage
 | 
			
		||||
.coverage.*
 | 
			
		||||
.cache
 | 
			
		||||
nosetests.xml
 | 
			
		||||
coverage.xml
 | 
			
		||||
*.cover
 | 
			
		||||
*.py,cover
 | 
			
		||||
.hypothesis/
 | 
			
		||||
.pytest_cache/
 | 
			
		||||
cover/
 | 
			
		||||
 | 
			
		||||
# Translations
 | 
			
		||||
*.mo
 | 
			
		||||
 | 
			
		||||
# Django stuff:
 | 
			
		||||
*.log
 | 
			
		||||
local_settings.py
 | 
			
		||||
db.sqlite3
 | 
			
		||||
db.sqlite3-journal
 | 
			
		||||
 | 
			
		||||
# Flask stuff:
 | 
			
		||||
instance/
 | 
			
		||||
.webassets-cache
 | 
			
		||||
 | 
			
		||||
# Scrapy stuff:
 | 
			
		||||
.scrapy
 | 
			
		||||
 | 
			
		||||
# Sphinx documentation
 | 
			
		||||
docs/_build/
 | 
			
		||||
 | 
			
		||||
# PyBuilder
 | 
			
		||||
.pybuilder/
 | 
			
		||||
target/
 | 
			
		||||
 | 
			
		||||
# Jupyter Notebook
 | 
			
		||||
.ipynb_checkpoints
 | 
			
		||||
 | 
			
		||||
# IPython
 | 
			
		||||
profile_default/
 | 
			
		||||
ipython_config.py
 | 
			
		||||
 | 
			
		||||
# pyenv
 | 
			
		||||
#   For a library or package, you might want to ignore these files since the code is
 | 
			
		||||
#   intended to run in multiple environments; otherwise, check them in:
 | 
			
		||||
# .python-version
 | 
			
		||||
 | 
			
		||||
# pipenv
 | 
			
		||||
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
 | 
			
		||||
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
 | 
			
		||||
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
 | 
			
		||||
#   install all needed dependencies.
 | 
			
		||||
#Pipfile.lock
 | 
			
		||||
 | 
			
		||||
# poetry
 | 
			
		||||
#   Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
 | 
			
		||||
#   This is especially recommended for binary packages to ensure reproducibility, and is more
 | 
			
		||||
#   commonly ignored for libraries.
 | 
			
		||||
#   https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
 | 
			
		||||
#poetry.lock
 | 
			
		||||
 | 
			
		||||
# pdm
 | 
			
		||||
#   Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
 | 
			
		||||
#pdm.lock
 | 
			
		||||
#   pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
 | 
			
		||||
#   in version control.
 | 
			
		||||
#   https://pdm.fming.dev/#use-with-ide
 | 
			
		||||
.pdm.toml
 | 
			
		||||
 | 
			
		||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
 | 
			
		||||
__pypackages__/
 | 
			
		||||
 | 
			
		||||
# Celery stuff
 | 
			
		||||
celerybeat-schedule
 | 
			
		||||
celerybeat.pid
 | 
			
		||||
 | 
			
		||||
# SageMath parsed files
 | 
			
		||||
*.sage.py
 | 
			
		||||
 | 
			
		||||
# Environments
 | 
			
		||||
.env
 | 
			
		||||
| 
						 | 
				
			
			@ -17,29 +147,141 @@ ENV/
 | 
			
		|||
env.bak/
 | 
			
		||||
venv.bak/
 | 
			
		||||
 | 
			
		||||
# Media & Static Files
 | 
			
		||||
/media/*
 | 
			
		||||
/staticfiles/*
 | 
			
		||||
# Spyder project settings
 | 
			
		||||
.spyderproject
 | 
			
		||||
.spyproject
 | 
			
		||||
 | 
			
		||||
# Rope project settings
 | 
			
		||||
.ropeproject
 | 
			
		||||
 | 
			
		||||
# Cache & Temporary Files
 | 
			
		||||
*.swp
 | 
			
		||||
*.swo
 | 
			
		||||
*.swn
 | 
			
		||||
*.bak
 | 
			
		||||
*.tmp
 | 
			
		||||
# mkdocs documentation
 | 
			
		||||
/site
 | 
			
		||||
 | 
			
		||||
# Editor-specific files
 | 
			
		||||
*.kate-swp
 | 
			
		||||
*.backup
 | 
			
		||||
.vscode/
 | 
			
		||||
.idea/
 | 
			
		||||
.DS_Store
 | 
			
		||||
._*
 | 
			
		||||
# mypy
 | 
			
		||||
.mypy_cache/
 | 
			
		||||
.dmypy.json
 | 
			
		||||
dmypy.json
 | 
			
		||||
 | 
			
		||||
# migrations
 | 
			
		||||
# */migrations/0*.py
 | 
			
		||||
!*/migrations/__init__.py
 | 
			
		||||
# Pyre type checker
 | 
			
		||||
.pyre/
 | 
			
		||||
 | 
			
		||||
# cursor
 | 
			
		||||
.cursor/*
 | 
			
		||||
# pytype static type analyzer
 | 
			
		||||
.pytype/
 | 
			
		||||
 | 
			
		||||
# Cython debug symbols
 | 
			
		||||
cython_debug/
 | 
			
		||||
 | 
			
		||||
# PyCharm
 | 
			
		||||
#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
 | 
			
		||||
#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
 | 
			
		||||
#  and can be added to the global gitignore or merged into this file.  For a more nuclear
 | 
			
		||||
#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
 | 
			
		||||
#.idea/
 | 
			
		||||
 | 
			
		||||
### Python ###
 | 
			
		||||
# Byte-compiled / optimized / DLL files
 | 
			
		||||
 | 
			
		||||
# C extensions
 | 
			
		||||
 | 
			
		||||
# Distribution / packaging
 | 
			
		||||
 | 
			
		||||
# PyInstaller
 | 
			
		||||
#  Usually these files are written by a python script from a template
 | 
			
		||||
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
 | 
			
		||||
 | 
			
		||||
# Installer logs
 | 
			
		||||
 | 
			
		||||
# Unit test / coverage reports
 | 
			
		||||
 | 
			
		||||
# Translations
 | 
			
		||||
 | 
			
		||||
# Django stuff:
 | 
			
		||||
 | 
			
		||||
# Flask stuff:
 | 
			
		||||
 | 
			
		||||
# Scrapy stuff:
 | 
			
		||||
 | 
			
		||||
# Sphinx documentation
 | 
			
		||||
 | 
			
		||||
# PyBuilder
 | 
			
		||||
 | 
			
		||||
# Jupyter Notebook
 | 
			
		||||
 | 
			
		||||
# IPython
 | 
			
		||||
 | 
			
		||||
# pyenv
 | 
			
		||||
#   For a library or package, you might want to ignore these files since the code is
 | 
			
		||||
#   intended to run in multiple environments; otherwise, check them in:
 | 
			
		||||
# .python-version
 | 
			
		||||
 | 
			
		||||
# pipenv
 | 
			
		||||
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
 | 
			
		||||
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
 | 
			
		||||
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
 | 
			
		||||
#   install all needed dependencies.
 | 
			
		||||
 | 
			
		||||
# poetry
 | 
			
		||||
#   Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
 | 
			
		||||
#   This is especially recommended for binary packages to ensure reproducibility, and is more
 | 
			
		||||
#   commonly ignored for libraries.
 | 
			
		||||
#   https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
 | 
			
		||||
 | 
			
		||||
# pdm
 | 
			
		||||
#   Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
 | 
			
		||||
#   pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
 | 
			
		||||
#   in version control.
 | 
			
		||||
#   https://pdm.fming.dev/#use-with-ide
 | 
			
		||||
 | 
			
		||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
 | 
			
		||||
 | 
			
		||||
# Celery stuff
 | 
			
		||||
 | 
			
		||||
# SageMath parsed files
 | 
			
		||||
 | 
			
		||||
# Environments
 | 
			
		||||
 | 
			
		||||
# Spyder project settings
 | 
			
		||||
 | 
			
		||||
# Rope project settings
 | 
			
		||||
 | 
			
		||||
# mkdocs documentation
 | 
			
		||||
 | 
			
		||||
# mypy
 | 
			
		||||
 | 
			
		||||
# Pyre type checker
 | 
			
		||||
 | 
			
		||||
# pytype static type analyzer
 | 
			
		||||
 | 
			
		||||
# Cython debug symbols
 | 
			
		||||
 | 
			
		||||
# PyCharm
 | 
			
		||||
#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
 | 
			
		||||
#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
 | 
			
		||||
#  and can be added to the global gitignore or merged into this file.  For a more nuclear
 | 
			
		||||
#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
 | 
			
		||||
 | 
			
		||||
### Python Patch ###
 | 
			
		||||
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
 | 
			
		||||
poetry.toml
 | 
			
		||||
 | 
			
		||||
# ruff
 | 
			
		||||
.ruff_cache/
 | 
			
		||||
 | 
			
		||||
# LSP config files
 | 
			
		||||
pyrightconfig.json
 | 
			
		||||
 | 
			
		||||
### VirtualEnv ###
 | 
			
		||||
# Virtualenv
 | 
			
		||||
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
 | 
			
		||||
[Bb]in
 | 
			
		||||
[Ii]nclude
 | 
			
		||||
[Ll]ib
 | 
			
		||||
[Ll]ib64
 | 
			
		||||
[Ll]ocal
 | 
			
		||||
[Ss]cripts
 | 
			
		||||
pyvenv.cfg
 | 
			
		||||
pip-selfcheck.json
 | 
			
		||||
 | 
			
		||||
# End of https://www.toptal.com/developers/gitignore/api/django,python,virtualenv
 | 
			
		||||
 | 
			
		||||
.cursor
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,8 +11,6 @@ https://docs.djangoproject.com/en/5.2/ref/settings/
 | 
			
		|||
"""
 | 
			
		||||
import os
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
from decouple import config
 | 
			
		||||
import dj_database_url
 | 
			
		||||
 | 
			
		||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
 | 
			
		||||
BASE_DIR = Path(__file__).resolve().parent.parent
 | 
			
		||||
| 
						 | 
				
			
			@ -22,28 +20,16 @@ BASE_DIR = Path(__file__).resolve().parent.parent
 | 
			
		|||
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
 | 
			
		||||
 | 
			
		||||
# SECURITY WARNING: keep the secret key used in production secret!
 | 
			
		||||
SECRET_KEY = config('DJANGO_SECRET_KEY', default="unsecure-secretkey-kjhsgfjsfgjsfgjsg")
 | 
			
		||||
SECRET_KEY = 'django-insecure-h!2hx$h=f6ktgdks!g2_*pg_s1nnuyk+j2yd*_x8r+3+3iyfy*'
 | 
			
		||||
 | 
			
		||||
# SECURITY WARNING: don't run with debug turned on in production!
 | 
			
		||||
DEBUG = config('DEBUG', cast=bool, default=True)
 | 
			
		||||
DEBUG = True
 | 
			
		||||
 | 
			
		||||
# Allowed hosts
 | 
			
		||||
ALLOWED_HOSTS = [host for host in config("DJANGO_ALLOWED_HOSTS", default="").split() if host]
 | 
			
		||||
ALLOWED_HOSTS = []
 | 
			
		||||
 | 
			
		||||
# URL scheme (http or https)
 | 
			
		||||
URL_SCHEME = config("URL_SCHEME", default="http")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# CSRF trusted origins (add both with and without port if you use a non-standard port)
 | 
			
		||||
CSRF_TRUSTED_ORIGINS = []
 | 
			
		||||
for host in ALLOWED_HOSTS:
 | 
			
		||||
    if host not in ("localhost", "127.0.0.1"):
 | 
			
		||||
        CSRF_TRUSTED_ORIGINS.append(f"{URL_SCHEME}://{host}")
 | 
			
		||||
 | 
			
		||||
# Generate base URL for absolute URLs (use first allowed host)
 | 
			
		||||
BASE_URL = f"{URL_SCHEME}://{ALLOWED_HOSTS[0]}" if ALLOWED_HOSTS else "http://localhost"
 | 
			
		||||
 | 
			
		||||
# Application definition
 | 
			
		||||
 | 
			
		||||
INSTALLED_APPS = [
 | 
			
		||||
    # ------ theme ------ #
 | 
			
		||||
    'jazzmin',
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +45,6 @@ INSTALLED_APPS = [
 | 
			
		|||
 | 
			
		||||
    # ------- third party apps ------- #
 | 
			
		||||
    'simple_history',
 | 
			
		||||
    'django_extensions',
 | 
			
		||||
    # -------------------------------- #
 | 
			
		||||
 | 
			
		||||
    # ------- my apps ------- #
 | 
			
		||||
| 
						 | 
				
			
			@ -111,20 +96,13 @@ WSGI_APPLICATION = '_base.wsgi.application'
 | 
			
		|||
# Database
 | 
			
		||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
 | 
			
		||||
 | 
			
		||||
DB_TYPE = config('DB_TYPE', default='sqlite').lower()
 | 
			
		||||
DATABASES = {
 | 
			
		||||
    'default': {
 | 
			
		||||
        'ENGINE': 'django.db.backends.sqlite3',
 | 
			
		||||
        'NAME': BASE_DIR / 'db.sqlite3',
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if DB_TYPE == 'postgres':
 | 
			
		||||
    DATABASES = {
 | 
			
		||||
        'default': dj_database_url.config(default=config('DATABASE_URL'))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
else:
 | 
			
		||||
    DATABASES = {
 | 
			
		||||
        "default": {
 | 
			
		||||
            "ENGINE": "django.db.backends.sqlite3",
 | 
			
		||||
            "NAME": BASE_DIR/"db.sqlite3",
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
# Password validation
 | 
			
		||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
 | 
			
		||||
| 
						 | 
				
			
			@ -161,15 +139,15 @@ USE_TZ = True
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
# Static files (CSS, JavaScript, Images)
 | 
			
		||||
STATIC_URL = '/static/'
 | 
			
		||||
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
 | 
			
		||||
# https://docs.djangoproject.com/en/5.2/howto/static-files/
 | 
			
		||||
STATIC_ROOT = 'ss'
 | 
			
		||||
STATIC_URL = 'static/'
 | 
			
		||||
STATICFILES_DIRS = [
 | 
			
		||||
    os.path.join(BASE_DIR, 'static'),
 | 
			
		||||
    os.path.join(BASE_DIR, 'static')
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
# Media files
 | 
			
		||||
MEDIA_URL = '/media/'
 | 
			
		||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
 | 
			
		||||
MEDIA_ROOT = BASE_DIR / 'media'
 | 
			
		||||
 | 
			
		||||
# Default primary key field type
 | 
			
		||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,6 @@
 | 
			
		|||
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
  <title>تاییدیه - {{ instance.code }}</title>
 | 
			
		||||
  {% load static %}
 | 
			
		||||
  {% load common_tags %}
 | 
			
		||||
 | 
			
		||||
  <!-- Fonts (match project) -->
 | 
			
		||||
  <link rel="preconnect" href="https://fonts.googleapis.com">
 | 
			
		||||
| 
						 | 
				
			
			@ -53,31 +52,21 @@
 | 
			
		|||
    <h6 class="my-2">مشخصات چاه و کنتور هوشمند</h6>
 | 
			
		||||
    <div class="row" style="font-size: 14px;">
 | 
			
		||||
      <div class="col-4">
 | 
			
		||||
        <div>موقعیت مکانی (UTM): X: {{ latest_report.utm_x|default:'-' }} , Y: {{ latest_report.utm_y|default:'-' }}</div>
 | 
			
		||||
        <div>موقعیت مکانی (UTM): {{ latest_report.utm_x|default:'-' }} , {{ latest_report.utm_y|default:'-' }}</div>
 | 
			
		||||
        <div>نیرو محرکه چاه: {{ latest_report.driving_force|default:'-' }}</div>
 | 
			
		||||
        <div>نوع کنتور: {{ latest_report.get_meter_type_display|default:'-' }}</div>
 | 
			
		||||
        {% if latest_report.meter_type == 'smart' %}
 | 
			
		||||
        <div>مدل کنتور: {{ latest_report.get_meter_model_display|default:'-' }}</div>
 | 
			
		||||
        {% else %}
 | 
			
		||||
        <div>سایز کنتور: {{ latest_report.meter_size|default:'-' }}</div>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
        <div>قطر لوله آبده (اینچ): {{ latest_report.discharge_pipe_diameter|default:'-' }}</div>
 | 
			
		||||
        <div>نوع مصرف: {{ latest_report.get_usage_type_display|default:'-' }}</div>
 | 
			
		||||
        <div>شماره سیمکارت: {{ latest_report.sim_number|default:'-' }}</div>
 | 
			
		||||
        <div>شارژ کنتور (متر مکعب): {{ latest_report.meter_charge|default:'-' }}</div>
 | 
			
		||||
        <div>پایان اعتبار شارژ: {{ latest_report.meter_charge_expiration_date|to_jalali|default:'-' }}</div>
 | 
			
		||||
        <div>شماره سریال کنتور: {{ instance.well.water_meter_serial_number|default:'-' }}</div>
 | 
			
		||||
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="col-4">
 | 
			
		||||
        <div>قطر لوله آبده (اینچ): {{ latest_report.discharge_pipe_diameter|default:'-' }}</div>
 | 
			
		||||
        <div>سایز کنتور: {{ latest_report.meter_size|default:'-' }}</div>
 | 
			
		||||
        <div>شماره پروانه بهرهبرداری چاه: {{ latest_report.exploitation_license_number|default:'-' }}</div>
 | 
			
		||||
        <div>قدرت موتور (کیلووات ساعت): {{ latest_report.motor_power|default:'-' }}</div>
 | 
			
		||||
        <div>دبی (لیتر بر ثانیه): {{ latest_report.flow_rate|default:'-' }}</div>
 | 
			
		||||
        <div>عدد کنتور (متر مکعب): {{ latest_report.meter_reading|default:'-' }}</div>
 | 
			
		||||
        <div>پلمپ تابلو: {{ latest_report.is_panel_sealed|yesno:'دارد,ندارد' }}</div>
 | 
			
		||||
        <div>تابلو قطع: {{ latest_report.is_panel_cut|yesno:'دارد,ندارد' }}</div>
 | 
			
		||||
        <div>انجام عملیات قطع: {{ latest_report.is_disconnection_done|yesno:'دارد,ندارد' }}</div>
 | 
			
		||||
        <div>قدرت موتور: {{ latest_report.motor_power|default:'-' }}</div>
 | 
			
		||||
        <div>دبی قبل از کالیبراسیون: {{ latest_report.pre_calibration_flow_rate|default:'-' }}</div>
 | 
			
		||||
        <div>دبی بعد از کالیبراسیون: {{ latest_report.post_calibration_flow_rate|default:'-' }}</div>
 | 
			
		||||
        <div>نام شرکت کنتورساز: {{ latest_report.water_meter_manufacturer.name|default:'-' }}</div>
 | 
			
		||||
        <div>شماره سریال کنتور: {{ instance.well.water_meter_serial_number|default:'-' }}</div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="col-4">
 | 
			
		||||
        <!-- Signature -->
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,6 @@
 | 
			
		|||
  {% load static %}
 | 
			
		||||
  {% load processes_tags %}
 | 
			
		||||
  {% load humanize %}
 | 
			
		||||
  {% load common_tags %}
 | 
			
		||||
  {% load accounts_tags %}
 | 
			
		||||
  
 | 
			
		||||
  {% block sidebar %}
 | 
			
		||||
| 
						 | 
				
			
			@ -74,30 +73,21 @@
 | 
			
		|||
                <h6 class="mb-2">مشخصات چاه و کنتور هوشمند</h6>
 | 
			
		||||
                <div class="row g-2 small">
 | 
			
		||||
                  <div class="col-12 col-md-6">
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">موقعیت مکانی (UTM):</span><span class="fw-medium">X: {{ latest_report.utm_x|default:'-' }} , Y: {{ latest_report.utm_y|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">موقعیت مکانی (UTM):</span><span class="fw-medium">{{ latest_report.utm_x|default:'-' }} , {{ latest_report.utm_y|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">نیرو محرکه چاه:</span><span class="fw-medium">{{ latest_report.driving_force|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">نوع کنتور:</span><span class="fw-medium">{{ latest_report.get_meter_type_display|default:'-' }}</span></div>
 | 
			
		||||
                    {% if latest_report.meter_type == 'smart' %}
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">مدل کنتور:</span><span class="fw-medium">{{ latest_report.get_meter_model_display|default:'-' }}</span></div>
 | 
			
		||||
                    {% else %}
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">سایز کنتور:</span><span class="fw-medium">{{ latest_report.meter_size|default:'-' }}</span></div>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">قطر لوله آبده (اینچ):</span><span class="fw-medium">{{ latest_report.discharge_pipe_diameter|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">نوع مصرف:</span><span class="fw-medium">{{ latest_report.get_usage_type_display|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">شماره سیمکارت:</span><span class="fw-medium">{{ latest_report.sim_number|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">شارژ کنتور (متر مکعب):</span><span class="fw-medium">{{ latest_report.meter_charge|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">پایان اعتبار شارژ:</span><span class="fw-medium">{{ latest_report.meter_charge_expiration_date|to_jalali|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">شماره سریال کنتور:</span><span class="fw-medium">{{ instance.well.water_meter_serial_number|default:'-' }}</span></div>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div class="col-12 col-md-6">
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">قطر لوله آبده (اینچ):</span><span class="fw-medium">{{ latest_report.discharge_pipe_diameter|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">سایز کنتور:</span><span class="fw-medium">{{ latest_report.meter_size|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">شماره پروانه بهرهبرداری چاه:</span><span class="fw-medium">{{ latest_report.exploitation_license_number|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">قدرت موتور (کیلووات ساعت):</span><span class="fw-medium">{{ latest_report.motor_power|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">دبی (لیتر بر ثانیه):</span><span class="fw-medium">{{ latest_report.flow_rate|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">عدد کنتور (متر مکعب):</span><span class="fw-medium">{{ latest_report.meter_reading|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">پلمپ تابلو:</span><span class="fw-medium">{{ latest_report.is_panel_sealed|yesno:'دارد,ندارد' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">تابلو قطع:</span><span class="fw-medium">{{ latest_report.is_panel_cut|yesno:'دارد,ندارد' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">انجام عملیات قطع:</span><span class="fw-medium">{{ latest_report.is_disconnection_done|yesno:'دارد,ندارد' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">قدرت موتور:</span><span class="fw-medium">{{ latest_report.motor_power|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">دبی قبل از کالیبراسیون:</span><span class="fw-medium">{{ latest_report.pre_calibration_flow_rate|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">دبی بعد از کالیبراسیون:</span><span class="fw-medium">{{ latest_report.post_calibration_flow_rate|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">نام شرکت کنتورساز:</span><span class="fw-medium">{{ latest_report.water_meter_manufacturer.name|default:'-' }}</span></div>
 | 
			
		||||
                    <div class="d-flex gap-2"><span class="text-muted">شماره سریال کنتور:</span><span class="fw-medium">{{ instance.well.water_meter_serial_number|default:'-' }}</span></div>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="signature-section d-flex justify-content-end">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										
											BIN
										
									
								
								db.sqlite3
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								db.sqlite3
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -24,12 +24,11 @@ class InstallationReportAdmin(admin.ModelAdmin):
 | 
			
		|||
    list_display = (
 | 
			
		||||
        'assignment', 'visited_date', 'meter_type', 'meter_size', 'water_meter_manufacturer',
 | 
			
		||||
        'discharge_pipe_diameter', 'usage_type', 'exploitation_license_number',
 | 
			
		||||
        'motor_power', 'flow_rate', 'meter_reading', 'meter_charge', 'meter_charge_expiration_date',
 | 
			
		||||
        'motor_power', 'pre_calibration_flow_rate', 'post_calibration_flow_rate',
 | 
			
		||||
        'new_water_meter_serial', 'seal_number', 'sim_number',
 | 
			
		||||
        'is_panel_sealed', 'is_panel_cut', 'is_disconnection_done',
 | 
			
		||||
        'is_meter_suspicious', 'approved', 'created'
 | 
			
		||||
    )
 | 
			
		||||
    list_filter = ('is_meter_suspicious', 'is_panel_sealed', 'is_panel_cut', 'is_disconnection_done', 'approved', 'visited_date', 'meter_type', 'usage_type', 'water_meter_manufacturer')
 | 
			
		||||
    list_filter = ('is_meter_suspicious', 'approved', 'visited_date', 'meter_type', 'usage_type', 'water_meter_manufacturer')
 | 
			
		||||
    search_fields = (
 | 
			
		||||
        'assignment__process_instance__code', 'new_water_meter_serial', 'seal_number', 'exploitation_license_number', 'sim_number'
 | 
			
		||||
    )
 | 
			
		||||
| 
						 | 
				
			
			@ -44,7 +43,7 @@ class InstallationReportAdmin(admin.ModelAdmin):
 | 
			
		|||
            )
 | 
			
		||||
        }),
 | 
			
		||||
        ('مشخصات هیدرولیکی', {
 | 
			
		||||
            'fields': ('discharge_pipe_diameter', 'flow_rate', 'meter_reading', 'meter_charge', 'meter_charge_expiration_date')
 | 
			
		||||
            'fields': ('discharge_pipe_diameter', 'pre_calibration_flow_rate', 'post_calibration_flow_rate')
 | 
			
		||||
        }),
 | 
			
		||||
        ('کاربری و مجوز', {
 | 
			
		||||
            'fields': ('usage_type', 'exploitation_license_number')
 | 
			
		||||
| 
						 | 
				
			
			@ -52,9 +51,6 @@ class InstallationReportAdmin(admin.ModelAdmin):
 | 
			
		|||
        ('توان و محرکه', {
 | 
			
		||||
            'fields': ('driving_force', 'motor_power')
 | 
			
		||||
        }),
 | 
			
		||||
        ('وضعیت تابلو/قطع', {
 | 
			
		||||
            'fields': ('is_panel_sealed', 'is_panel_cut', 'is_disconnection_done')
 | 
			
		||||
        }),
 | 
			
		||||
        ('توضیحات', {
 | 
			
		||||
            'fields': ('description',)
 | 
			
		||||
        }),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,8 +22,7 @@ class InstallationReportForm(forms.ModelForm):
 | 
			
		|||
            'visited_date', 'new_water_meter_serial', 'seal_number',
 | 
			
		||||
            'utm_x', 'utm_y', 'meter_type', 'meter_size', 'meter_model',
 | 
			
		||||
            'discharge_pipe_diameter', 'usage_type', 'exploitation_license_number',
 | 
			
		||||
            'motor_power', 'flow_rate', 'meter_reading', 'meter_charge', 'meter_charge_expiration_date',
 | 
			
		||||
            'is_panel_sealed', 'is_panel_cut', 'is_disconnection_done',
 | 
			
		||||
            'motor_power', 'pre_calibration_flow_rate', 'post_calibration_flow_rate',
 | 
			
		||||
            'water_meter_manufacturer', 'sim_number', 'driving_force',
 | 
			
		||||
            'is_meter_suspicious', 'description'
 | 
			
		||||
        ]
 | 
			
		||||
| 
						 | 
				
			
			@ -91,24 +90,17 @@ class InstallationReportForm(forms.ModelForm):
 | 
			
		|||
                'class': 'form-control',
 | 
			
		||||
                'required': True
 | 
			
		||||
            }),
 | 
			
		||||
            'flow_rate': forms.NumberInput(attrs={
 | 
			
		||||
            'pre_calibration_flow_rate': forms.NumberInput(attrs={
 | 
			
		||||
                'class': 'form-control',
 | 
			
		||||
                'min': '0',
 | 
			
		||||
                'step': '0.0001',
 | 
			
		||||
                'required': True
 | 
			
		||||
            }),
 | 
			
		||||
            'meter_reading': forms.NumberInput(attrs={
 | 
			
		||||
            'post_calibration_flow_rate': forms.NumberInput(attrs={
 | 
			
		||||
                'class': 'form-control',
 | 
			
		||||
                'min': '0',
 | 
			
		||||
                'step': '0.0001',
 | 
			
		||||
            }),
 | 
			
		||||
            'meter_charge': forms.NumberInput(attrs={
 | 
			
		||||
                'class': 'form-control',
 | 
			
		||||
                'min': '0',
 | 
			
		||||
                'step': '0.0001',
 | 
			
		||||
            }),
 | 
			
		||||
            'meter_charge_expiration_date': forms.DateInput(attrs={
 | 
			
		||||
                'type': 'date',
 | 
			
		||||
                'class': 'form-control',
 | 
			
		||||
                'required': True
 | 
			
		||||
            }),
 | 
			
		||||
            'water_meter_manufacturer': forms.Select(attrs={
 | 
			
		||||
                'class': 'form-select',
 | 
			
		||||
| 
						 | 
				
			
			@ -127,15 +119,6 @@ class InstallationReportForm(forms.ModelForm):
 | 
			
		|||
                'class': 'form-check-input',
 | 
			
		||||
                'id': 'id_is_meter_suspicious',
 | 
			
		||||
            }),
 | 
			
		||||
            'is_panel_sealed': forms.CheckboxInput(attrs={
 | 
			
		||||
                'class': 'form-check-input',
 | 
			
		||||
            }),
 | 
			
		||||
            'is_panel_cut': forms.CheckboxInput(attrs={
 | 
			
		||||
                'class': 'form-check-input',
 | 
			
		||||
            }),
 | 
			
		||||
            'is_disconnection_done': forms.CheckboxInput(attrs={
 | 
			
		||||
                'class': 'form-check-input',
 | 
			
		||||
            }),
 | 
			
		||||
            'description': forms.Textarea(attrs={
 | 
			
		||||
                'class': 'form-control',
 | 
			
		||||
                'rows': 3
 | 
			
		||||
| 
						 | 
				
			
			@ -154,17 +137,12 @@ class InstallationReportForm(forms.ModelForm):
 | 
			
		|||
            'usage_type': 'نوع مصرف',
 | 
			
		||||
            'exploitation_license_number': 'شماره پروانه بهرهبرداری',
 | 
			
		||||
            'motor_power': 'قدرت موتور (کیلووات ساعت)',
 | 
			
		||||
            'flow_rate': 'دبی (لیتر بر ثانیه)',
 | 
			
		||||
            'meter_reading': 'عدد کنتور (متر مکعب)',
 | 
			
		||||
            'meter_charge': 'شارژ کنتور (متر مکعب)',
 | 
			
		||||
            'meter_charge_expiration_date': 'تاریخ پایان اعتبار شارژ',
 | 
			
		||||
            'pre_calibration_flow_rate': 'دبی قبل از کالیبراسیون (لیتر بر ثانیه)',
 | 
			
		||||
            'post_calibration_flow_rate': 'دبی بعد از کالیبراسیون (لیتر بر ثانیه)',
 | 
			
		||||
            'water_meter_manufacturer': 'شرکت سازنده کنتور',
 | 
			
		||||
            'sim_number': 'شماره سیمکارت',
 | 
			
		||||
            'driving_force': 'نیرو محرکه چاه',
 | 
			
		||||
            'is_meter_suspicious': 'کنتور مشکوک است',
 | 
			
		||||
            'is_panel_sealed': 'پلمپ تابلو',
 | 
			
		||||
            'is_panel_cut': 'تابلو قطع',
 | 
			
		||||
            'is_disconnection_done': 'انجام عملیات قطع',
 | 
			
		||||
            'description': 'توضیحات'
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,50 +0,0 @@
 | 
			
		|||
# Generated by Django 5.2.4 on 2025-10-27 03:42
 | 
			
		||||
 | 
			
		||||
import django.core.validators
 | 
			
		||||
from decimal import Decimal
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('installations', '0011_alter_installationreport_discharge_pipe_diameter'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name='installationreport',
 | 
			
		||||
            name='flow_rate',
 | 
			
		||||
            field=models.DecimalField(blank=True, decimal_places=4, max_digits=10, null=True, verbose_name='(لیتر بر ثانیه)دبی'),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name='installationreport',
 | 
			
		||||
            name='is_disconnection_done',
 | 
			
		||||
            field=models.BooleanField(default=False, verbose_name='انجام عملیات قطع'),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name='installationreport',
 | 
			
		||||
            name='is_panel_cut',
 | 
			
		||||
            field=models.BooleanField(default=False, verbose_name='تابلو قطع'),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name='installationreport',
 | 
			
		||||
            name='is_panel_sealed',
 | 
			
		||||
            field=models.BooleanField(default=False, verbose_name='پلمپ تابلو'),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name='installationreport',
 | 
			
		||||
            name='meter_charge',
 | 
			
		||||
            field=models.DecimalField(blank=True, decimal_places=4, max_digits=10, null=True, validators=[django.core.validators.MinValueValidator(Decimal('0'))], verbose_name='شارژ کنتور (متر مکعب)'),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name='installationreport',
 | 
			
		||||
            name='meter_charge_expiration_date',
 | 
			
		||||
            field=models.DateField(blank=True, null=True, verbose_name='تاریخ پایان اعتبار شارژ'),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name='installationreport',
 | 
			
		||||
            name='meter_reading',
 | 
			
		||||
            field=models.DecimalField(blank=True, decimal_places=4, max_digits=10, null=True, validators=[django.core.validators.MinValueValidator(Decimal('0'))], verbose_name='عدد کنتور (متر مکعب)'),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			@ -1,21 +0,0 @@
 | 
			
		|||
# Generated by Django 5.2.4 on 2025-10-27 03:47
 | 
			
		||||
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('installations', '0012_installationreport_flow_rate_and_more'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.RemoveField(
 | 
			
		||||
            model_name='installationreport',
 | 
			
		||||
            name='post_calibration_flow_rate',
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.RemoveField(
 | 
			
		||||
            model_name='installationreport',
 | 
			
		||||
            name='pre_calibration_flow_rate',
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			@ -55,12 +55,6 @@ class InstallationReport(BaseModel):
 | 
			
		|||
    ]
 | 
			
		||||
    meter_model = models.CharField(max_length=20, choices=METER_MODEL_CHOICES, null=True, blank=True, verbose_name='مدل کنتور')
 | 
			
		||||
    meter_size = models.CharField(max_length=50, null=True, blank=True, verbose_name='سایز کنتور')
 | 
			
		||||
    meter_reading = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True, validators=[MinValueValidator(Decimal('0'))], verbose_name='عدد کنتور (متر مکعب)')
 | 
			
		||||
    meter_charge = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True, validators=[MinValueValidator(Decimal('0'))], verbose_name='شارژ کنتور (متر مکعب)')
 | 
			
		||||
    meter_charge_expiration_date = models.DateField(null=True, blank=True, verbose_name='تاریخ پایان اعتبار شارژ')
 | 
			
		||||
    is_panel_sealed = models.BooleanField(default=False, verbose_name='پلمپ تابلو')
 | 
			
		||||
    is_panel_cut = models.BooleanField(default=False, verbose_name='تابلو قطع')
 | 
			
		||||
    is_disconnection_done = models.BooleanField(default=False, verbose_name='انجام عملیات قطع')
 | 
			
		||||
    discharge_pipe_diameter = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True, verbose_name='قطر لوله آبده (اینچ)')
 | 
			
		||||
    USAGE_TYPE_CHOICES = [
 | 
			
		||||
        ('domestic', 'شرب و خدمات'),
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +64,8 @@ class InstallationReport(BaseModel):
 | 
			
		|||
    usage_type = models.CharField(max_length=20, choices=USAGE_TYPE_CHOICES, null=True, verbose_name='نوع مصرف')
 | 
			
		||||
    exploitation_license_number = models.CharField(max_length=50, verbose_name='شماره پروانه بهرهبرداری چاه')
 | 
			
		||||
    motor_power = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True, verbose_name='(کیلووات ساعت) قدرت موتور')
 | 
			
		||||
    flow_rate = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True, verbose_name='(لیتر بر ثانیه)دبی')
 | 
			
		||||
    pre_calibration_flow_rate = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True, verbose_name='(لیتر بر ثانیه)دبی قبل از کالیبراسیون')
 | 
			
		||||
    post_calibration_flow_rate = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True, verbose_name='(لیتر بر ثانیه)دبی بعد از کالیبراسیون')
 | 
			
		||||
    water_meter_manufacturer = models.ForeignKey('wells.WaterMeterManufacturer', on_delete=models.SET_NULL, null=True, blank=True, verbose_name='شرکت سازنده کنتور آب')
 | 
			
		||||
    sim_number = models.CharField(max_length=20, null=True, blank=True, verbose_name='شماره سیمکارت')
 | 
			
		||||
    driving_force = models.CharField(max_length=50, null=True, blank=True, verbose_name='نیرو محرکه چاه')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -156,10 +156,8 @@
 | 
			
		|||
                  {% endif %}
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-tachometer bx-sm me-2"></i>قطر لوله آبده (اینچ): {{ report.discharge_pipe_diameter|default:'-' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-building bx-sm me-2"></i>سازنده کنتور: {{ report.water_meter_manufacturer|default:'-' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-mobile bx-sm me-2"></i>شماره سیمکارت: {{ report.sim_number|default:'-' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-sim-card bx-sm me-2"></i>شماره سیمکارت: {{ report.sim_number|default:'-' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-cog bx-sm me-2"></i>نیرو محرکه چاه: {{ report.driving_force|default:'-' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-battery bx-sm me-2"></i>شارژ کنتور (متر مکعب): {{ report.meter_charge|default:'-' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-calendar-exclamation bx-sm me-2"></i>پایان اعتبار شارژ: {{ report.meter_charge_expiration_date|to_jalali|default:'-' }}</p>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="col-md-6">
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-help-circle bx-sm me-2"></i>کنتور مشکوک: {{ report.is_meter_suspicious|yesno:'بله,خیر' }}</p>
 | 
			
		||||
| 
						 | 
				
			
			@ -167,12 +165,9 @@
 | 
			
		|||
                  <p class="text-nowrap mb-2"><i class="bx bx-map-pin bx-sm me-2"></i>UTM Y: {{ report.utm_y|default:'-' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-category bx-sm me-2"></i>نوع مصرف: {{ report.get_usage_type_display|default:'-' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-id-card bx-sm me-2"></i>شماره پروانه بهرهبرداری: {{ report.exploitation_license_number|default:'-' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-bolt-circle bx-sm me-2"></i>قدرت موتور (کیلووات ساعت): {{ report.motor_power|default:'-' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-water bx-sm me-2"></i>دبی (لیتر/ثانیه): {{ report.flow_rate|default:'-' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-pen bx-sm me-2"></i>عدد کنتور (متر مکعب): {{ report.meter_reading|default:'-' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-lock-open-alt bx-sm me-2"></i>پلمپ تابلو: {{ report.is_panel_sealed|yesno:'بله,خیر' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-power-off bx-sm me-2"></i>تابلو قطع: {{ report.is_panel_cut|yesno:'بله,خیر' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-cut bx-sm me-2"></i>انجام عملیات قطع: {{ report.is_disconnection_done|yesno:'بله,خیر' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-bolt-circle bx-sm me-2"></i>قدرت موتور(کیلووات ساعت): {{ report.motor_power|default:'-' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-water bx-sm me-2"></i>دبی قبل کالیبراسیون(لیتر/ثانیه): {{ report.pre_calibration_flow_rate|default:'-' }}</p>
 | 
			
		||||
                  <p class="text-nowrap mb-2"><i class="bx bx-water bx-sm me-2"></i>دبی بعد کالیبراسیون(لیتر/ثانیه): {{ report.post_calibration_flow_rate|default:'-' }}</p>
 | 
			
		||||
                  
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -394,32 +389,17 @@
 | 
			
		|||
                    {% endif %}
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div class="col-md-3">
 | 
			
		||||
                    {{ form.flow_rate.label_tag }}
 | 
			
		||||
                    {{ form.flow_rate }}
 | 
			
		||||
                    {% if form.flow_rate.errors %}
 | 
			
		||||
                      <div class="invalid-feedback">{{ form.flow_rate.errors.0 }}</div>
 | 
			
		||||
                    {{ form.pre_calibration_flow_rate.label_tag }}
 | 
			
		||||
                    {{ form.pre_calibration_flow_rate }}
 | 
			
		||||
                    {% if form.pre_calibration_flow_rate.errors %}
 | 
			
		||||
                      <div class="invalid-feedback">{{ form.pre_calibration_flow_rate.errors.0 }}</div>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div class="col-md-3">
 | 
			
		||||
                    {{ form.meter_reading.label_tag }}
 | 
			
		||||
                    {{ form.meter_reading }}
 | 
			
		||||
                    {% if form.meter_reading.errors %}
 | 
			
		||||
                      <div class="invalid-feedback">{{ form.meter_reading.errors.0 }}</div>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div class="col-md-3">
 | 
			
		||||
                    {{ form.meter_charge.label_tag }}
 | 
			
		||||
                    {{ form.meter_charge }}
 | 
			
		||||
                    {% if form.meter_charge.errors %}
 | 
			
		||||
                      <div class="invalid-feedback">{{ form.meter_charge.errors.0 }}</div>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div class="col-md-3">
 | 
			
		||||
                    {{ form.meter_charge_expiration_date.label_tag }}
 | 
			
		||||
                    <input type="text" id="id_meter_charge_expiration_date_display" class="form-control{% if form.meter_charge_expiration_date.errors %} is-invalid{% endif %}" placeholder="انتخاب تاریخ" {% if not user_is_installer %}disabled{% endif %} readonly value="{% if report and edit_mode and report.meter_charge_expiration_date %}{{ report.meter_charge_expiration_date|date:'Y/m/d' }}{% elif form.meter_charge_expiration_date.value %}{{ form.meter_charge_expiration_date.value|date:'Y/m/d' }}{% endif %}">
 | 
			
		||||
                    <input type="hidden" id="id_meter_charge_expiration_date" name="meter_charge_expiration_date" value="{% if report and edit_mode and report.meter_charge_expiration_date %}{{ report.meter_charge_expiration_date|date:'Y-m-d' }}{% elif form.meter_charge_expiration_date.value %}{{ form.meter_charge_expiration_date.value }}{% endif %}">
 | 
			
		||||
                    {% if form.meter_charge_expiration_date.errors %}
 | 
			
		||||
                      <div class="invalid-feedback">{{ form.meter_charge_expiration_date.errors.0 }}</div>
 | 
			
		||||
                    {{ form.post_calibration_flow_rate.label_tag }}
 | 
			
		||||
                    {{ form.post_calibration_flow_rate }}
 | 
			
		||||
                    {% if form.post_calibration_flow_rate.errors %}
 | 
			
		||||
                      <div class="invalid-feedback">{{ form.post_calibration_flow_rate.errors.0 }}</div>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div class="col-md-3">
 | 
			
		||||
| 
						 | 
				
			
			@ -452,7 +432,6 @@
 | 
			
		|||
                      <div class="invalid-feedback">{{ form.driving_force.errors.0 }}</div>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div class="row mt-3">
 | 
			
		||||
                  <div class="col-md-3 d-flex align-items-end">
 | 
			
		||||
                    <div class="form-check">
 | 
			
		||||
                      {{ form.is_meter_suspicious }}
 | 
			
		||||
| 
						 | 
				
			
			@ -462,34 +441,6 @@
 | 
			
		|||
                      <div class="invalid-feedback">{{ form.is_meter_suspicious.errors.0 }}</div>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                  </div>
 | 
			
		||||
                    <div class="col-md-3 d-flex align-items-end">
 | 
			
		||||
                      <div class="form-check">
 | 
			
		||||
                        {{ form.is_panel_sealed }}
 | 
			
		||||
                        {{ form.is_panel_sealed.label_tag }}
 | 
			
		||||
                      </div>
 | 
			
		||||
                      {% if form.is_panel_sealed.errors %}
 | 
			
		||||
                        <div class="invalid-feedback">{{ form.is_panel_sealed.errors.0 }}</div>
 | 
			
		||||
                      {% endif %}
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="col-md-3 d-flex align-items-end">
 | 
			
		||||
                      <div class="form-check">
 | 
			
		||||
                        {{ form.is_panel_cut }}
 | 
			
		||||
                        {{ form.is_panel_cut.label_tag }}
 | 
			
		||||
                      </div>
 | 
			
		||||
                      {% if form.is_panel_cut.errors %}
 | 
			
		||||
                        <div class="invalid-feedback">{{ form.is_panel_cut.errors.0 }}</div>
 | 
			
		||||
                      {% endif %}
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="col-md-3 d-flex align-items-end">
 | 
			
		||||
                      <div class="form-check">
 | 
			
		||||
                        {{ form.is_disconnection_done }}
 | 
			
		||||
                        {{ form.is_disconnection_done.label_tag }}
 | 
			
		||||
                      </div>
 | 
			
		||||
                      {% if form.is_disconnection_done.errors %}
 | 
			
		||||
                        <div class="invalid-feedback">{{ form.is_disconnection_done.errors.0 }}</div>
 | 
			
		||||
                      {% endif %}
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="my-3">
 | 
			
		||||
                  {{ form.description.label_tag }}
 | 
			
		||||
| 
						 | 
				
			
			@ -702,7 +653,7 @@
 | 
			
		|||
<script src="https://unpkg.com/persian-date@latest/dist/persian-date.min.js"></script>
 | 
			
		||||
<script src="https://unpkg.com/persian-datepicker@latest/dist/js/persian-datepicker.min.js"></script>
 | 
			
		||||
<script>
 | 
			
		||||
  // Persian datepicker helper for date fields (DRY)
 | 
			
		||||
  // Persian datepicker for visited_date (exact pattern like sample: display + altField)
 | 
			
		||||
  (function(){
 | 
			
		||||
    function convertPersianToEnglishNumbers(str) {
 | 
			
		||||
      const persianNumbers = '۰۱۲۳۴۵۶۷۸۹';
 | 
			
		||||
| 
						 | 
				
			
			@ -713,12 +664,12 @@
 | 
			
		|||
      }).join('');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function initPersianDateField(displaySelector, hiddenSelector){
 | 
			
		||||
      if (!(window.$ && $.fn.persianDatepicker)) return;
 | 
			
		||||
      var $display = $(displaySelector);
 | 
			
		||||
      var $hidden = $(hiddenSelector);
 | 
			
		||||
      if (!$display.length || !$hidden.length) return;
 | 
			
		||||
    if (window.$ && $.fn.persianDatepicker && $('#id_visited_date_display').length) {
 | 
			
		||||
      try {
 | 
			
		||||
        var $display = $('#id_visited_date_display');
 | 
			
		||||
        var $hidden = $('#id_visited_date');
 | 
			
		||||
 | 
			
		||||
        // Prefill from hidden Gregorian to visible Jalali
 | 
			
		||||
        var initialGregorian = $hidden.val();
 | 
			
		||||
        if (initialGregorian) {
 | 
			
		||||
          try {
 | 
			
		||||
| 
						 | 
				
			
			@ -727,9 +678,10 @@
 | 
			
		|||
          } catch (e) {}
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $display.persianDatepicker({
 | 
			
		||||
        // Initialize datepicker with altField exactly like the sample
 | 
			
		||||
        var picker = $display.persianDatepicker({
 | 
			
		||||
          calendarType: 'persian',
 | 
			
		||||
          altField: hiddenSelector,
 | 
			
		||||
          altField: '#id_visited_date',
 | 
			
		||||
          format: 'YYYY/MM/DD',
 | 
			
		||||
          altFormat: 'YYYY-MM-DD',
 | 
			
		||||
          observer: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -742,12 +694,8 @@
 | 
			
		|||
            $hidden.val(g);
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      } catch (e) { console.error('Error initializing Persian Date Picker:', displaySelector, e); }
 | 
			
		||||
      } catch (e) { console.error('Error initializing Persian Date Picker:', e); }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Initialize both fields
 | 
			
		||||
    initPersianDateField('#id_visited_date_display', '#id_visited_date');
 | 
			
		||||
    initPersianDateField('#id_meter_charge_expiration_date_display', '#id_meter_charge_expiration_date');
 | 
			
		||||
  })();
 | 
			
		||||
 | 
			
		||||
  // Require date and show success toast on submit (persist across redirect)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,7 +23,7 @@ def installation_assign_step(request, instance_id, step_id):
 | 
			
		|||
    next_step = instance.process.steps.filter(order__gt=step.order).first()
 | 
			
		||||
 | 
			
		||||
    # Installers list (profiles that have installer role)
 | 
			
		||||
    installers = Profile.objects.filter(roles__slug=UserRoles.INSTALLER.value, county__city=instance.well.county.city).select_related('user').all()
 | 
			
		||||
    installers = Profile.objects.filter(roles__slug=UserRoles.INSTALLER.value, county=instance.well.county).select_related('user').all()
 | 
			
		||||
    assignment, _ = InstallationAssignment.objects.get_or_create(process_instance=instance)
 | 
			
		||||
 | 
			
		||||
    # Role flags
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								liara.json
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								liara.json
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,14 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
  "app": "meterplus",
 | 
			
		||||
  "port": 80,
 | 
			
		||||
  "team-id": "68822f40f04e5bc3027fc2b7",
 | 
			
		||||
  "build": {
 | 
			
		||||
    "location": "iran"
 | 
			
		||||
  },
 | 
			
		||||
  "disks": [
 | 
			
		||||
    {
 | 
			
		||||
      "name": "media",
 | 
			
		||||
      "mountTo": "/usr/src/app/media"
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -143,16 +143,12 @@
 | 
			
		|||
                  <div class="col-12 col-md-4">
 | 
			
		||||
                    <p class="text-nowrap mb-2"><i class="bx bx-category bx-sm me-2"></i>نوع کنتور: {{ latest_report.get_meter_type_display }}</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  {% if latest_report.meter_type == 'smart' %}
 | 
			
		||||
                  <div class="col-12 col-md-4">
 | 
			
		||||
                    <p class="text-nowrap mb-2"><i class="bx bx-chip bx-sm me-2"></i>مدل کنتور: {{ latest_report.get_meter_model_display|default:'-' }}</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  {% else %}
 | 
			
		||||
                  {% endif %}
 | 
			
		||||
                  {% if latest_report.meter_size %}
 | 
			
		||||
                  <div class="col-12 col-md-4">
 | 
			
		||||
                    <p class="text-nowrap mb-2"><i class="bx bx-ruler bx-sm me-2"></i>سایز کنتور: {{ latest_report.meter_size }}</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  {% endif %}
 | 
			
		||||
                  {% endif %}
 | 
			
		||||
                  {% if latest_report.water_meter_manufacturer %}
 | 
			
		||||
                  <div class="col-12 col-md-4">
 | 
			
		||||
                    <p class="text-nowrap mb-2"><i class="bx bx-buildings bx-sm me-2"></i>سازنده: {{ latest_report.water_meter_manufacturer.name }}</p>
 | 
			
		||||
| 
						 | 
				
			
			@ -183,35 +179,16 @@
 | 
			
		|||
                    <p class="text-nowrap mb-2"><i class="bx bx-id-card bx-sm me-2"></i>شماره پروانه: {{ latest_report.exploitation_license_number }}</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  {% endif %}
 | 
			
		||||
                  {% if latest_report.flow_rate %}
 | 
			
		||||
                  {% if latest_report.pre_calibration_flow_rate %}
 | 
			
		||||
                  <div class="col-12 col-md-4">
 | 
			
		||||
                    <p class="text-nowrap mb-2"><i class="bx bx-water bx-sm me-2"></i>دبی: {{ latest_report.flow_rate }} لیتر/ثانیه</p>
 | 
			
		||||
                    <p class="text-nowrap mb-2"><i class="bx bx-water bx-sm me-2"></i>دبی قبل از کالیبراسیون: {{ latest_report.pre_calibration_flow_rate }} لیتر/ثانیه</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  {% endif %}
 | 
			
		||||
                  {% if latest_report.meter_reading %}
 | 
			
		||||
                  {% if latest_report.post_calibration_flow_rate %}
 | 
			
		||||
                  <div class="col-12 col-md-4">
 | 
			
		||||
                    <p class="text-nowrap mb-2"><i class="bx bx-pen bx-sm me-2"></i>عدد کنتور: {{ latest_report.meter_reading }} متر مکعب</p>
 | 
			
		||||
                    <p class="text-nowrap mb-2"><i class="bx bx-tachometer bx-sm me-2"></i>دبی بعد از کالیبراسیون: {{ latest_report.post_calibration_flow_rate }} لیتر/ثانیه</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  {% endif %}
 | 
			
		||||
                  {% if latest_report.meter_charge %}
 | 
			
		||||
                  <div class="col-12 col-md-4">
 | 
			
		||||
                    <p class="text-nowrap mb-2"><i class="bx bx-battery bx-sm me-2"></i>شارژ کنتور: {{ latest_report.meter_charge }} متر مکعب</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  {% endif %}
 | 
			
		||||
                  {% if latest_report.meter_charge_expiration_date %}
 | 
			
		||||
                  <div class="col-12 col-md-4">
 | 
			
		||||
                    <p class="text-nowrap mb-2"><i class="bx bx-calendar-exclamation bx-sm me-2"></i>پایان اعتبار شارژ: {{ latest_report.meter_charge_expiration_date|to_jalali }}</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  {% endif %}
 | 
			
		||||
                  <div class="col-12 col-md-4">
 | 
			
		||||
                    <p class="text-nowrap mb-2"><i class="bx bx-lock-open-alt bx-sm me-2"></i>پلمپ تابلو: {{ latest_report.is_panel_sealed|yesno:'دارد,ندارد' }}</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div class="col-12 col-md-4">
 | 
			
		||||
                    <p class="text-nowrap mb-2"><i class="bx bx-power-off bx-sm me-2"></i>تابلو قطع: {{ latest_report.is_panel_cut|yesno:'دارد,ندارد' }}</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div class="col-12 col-md-4">
 | 
			
		||||
                    <p class="text-nowrap mb-2"><i class="bx bx-cut bx-sm me-2"></i>انجام عملیات قطع: {{ latest_report.is_disconnection_done|yesno:'دارد,ندارد' }}</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div class="col-12 col-md-4">
 | 
			
		||||
                    <p class="text-nowrap mb-2"><i class="bx bx-map bx-sm me-2"></i>UTM X: {{ latest_report.utm_x|default:'-' }}</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ def scope_instances_queryset(user, queryset=None):
 | 
			
		|||
        if profile.has_role(UserRoles.BROKER):
 | 
			
		||||
            return qs.filter(broker=profile.broker)
 | 
			
		||||
        if profile.has_role(UserRoles.ACCOUNTANT) or profile.has_role(UserRoles.MANAGER) or profile.has_role(UserRoles.WATER_RESOURCE_MANAGER):
 | 
			
		||||
            return qs.filter(broker__affairs__county__city=profile.county.city)
 | 
			
		||||
            return qs.filter(broker__affairs__county=profile.county)
 | 
			
		||||
        if profile.has_role(UserRoles.ADMIN):
 | 
			
		||||
            return qs
 | 
			
		||||
        # if profile.has_role(UserRoles.WATER_RESOURCE_MANAGER) or profile.has_role(UserRoles.HEADQUARTER):
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +70,7 @@ def scope_wells_queryset(user, queryset=None):
 | 
			
		|||
        if profile.has_role(UserRoles.BROKER):
 | 
			
		||||
            return qs.filter(broker=profile.broker)
 | 
			
		||||
        if profile.has_role(UserRoles.ACCOUNTANT) or profile.has_role(UserRoles.MANAGER) or profile.has_role(UserRoles.WATER_RESOURCE_MANAGER):
 | 
			
		||||
            return qs.filter(broker__affairs__county__city=profile.county.city)
 | 
			
		||||
            return qs.filter(broker__affairs__county=profile.county)
 | 
			
		||||
        if profile.has_role(UserRoles.INSTALLER):
 | 
			
		||||
            # Wells that have instances assigned to this installer
 | 
			
		||||
            from installations.models import InstallationAssignment
 | 
			
		||||
| 
						 | 
				
			
			@ -103,7 +103,7 @@ def scope_customers_queryset(user, queryset=None):
 | 
			
		|||
        if profile.has_role(UserRoles.BROKER):
 | 
			
		||||
            return qs.filter(broker=profile.broker)
 | 
			
		||||
        if profile.has_role(UserRoles.ACCOUNTANT) or profile.has_role(UserRoles.MANAGER) or profile.has_role(UserRoles.WATER_RESOURCE_MANAGER):
 | 
			
		||||
            return qs.filter(county__city=profile.county.city)
 | 
			
		||||
            return qs.filter(county=profile.county)
 | 
			
		||||
        if profile.has_role(UserRoles.INSTALLER):
 | 
			
		||||
            # Customers that are representatives of instances assigned to this installer
 | 
			
		||||
            from installations.models import InstallationAssignment
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,9 +45,6 @@ def request_list(request):
 | 
			
		|||
    status_q = (request.GET.get('status') or '').strip()
 | 
			
		||||
    affairs_q = (request.GET.get('affairs') or '').strip()
 | 
			
		||||
    broker_q = (request.GET.get('broker') or '').strip()
 | 
			
		||||
    if request.user.profile.roles.filter(slug='inst'):
 | 
			
		||||
        step_q = (request.GET.get('step') or '6').strip()
 | 
			
		||||
    else:
 | 
			
		||||
    step_q = (request.GET.get('step') or '').strip()
 | 
			
		||||
 | 
			
		||||
    if status_q:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +0,0 @@
 | 
			
		|||
asgiref==3.9.1
 | 
			
		||||
dj-database-url==3.0.1
 | 
			
		||||
Django==5.2.5
 | 
			
		||||
django-extensions==4.1
 | 
			
		||||
django-jazzmin==3.0.1
 | 
			
		||||
django-simple-history==3.10.1
 | 
			
		||||
et_xmlfile==2.0.0
 | 
			
		||||
openpyxl==3.1.5
 | 
			
		||||
pillow==11.3.0
 | 
			
		||||
psycopg2==2.9.10
 | 
			
		||||
psycopg2-binary==2.9.10
 | 
			
		||||
python-decouple==3.8
 | 
			
		||||
sqlparse==0.5.3
 | 
			
		||||
typing_extensions==4.15.0
 | 
			
		||||
utm==0.8.1
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue