settings split for development and production.py

This commit is contained in:
2025-08-04 19:26:38 +03:00
parent f501be9794
commit 8294db9189
35 changed files with 711 additions and 66 deletions
+2
View File
@@ -29,3 +29,5 @@ production.env
# Other
gemini.cmd - Shortcut.lnk
images/
+3 -4
View File
@@ -36,7 +36,6 @@ MINIO_ENDPOINT="localhost:9000"
MINIO_ACCESS_KEY="kikimor"
MINIO_SECRET_KEY="shushunka1"
MINIO_BUCKET_NAME="damages"
#MINIO_STATIC_BUCKET_NAME=depot-static
#AWS_S3_CUSTOM_DOMAIN='localhost:9000' # For browser acce
#AWS_S3_URL_PROTOCOL='http'
#MINIO_SERVER_URL="http://localhost:9000"
AWS_S3_CUSTOM_DOMAIN='localhost:9000' # For browser acce
AWS_S3_URL_PROTOCOL='http'
MINIO_SERVER_URL="http://localhost:9000"
+70 -24
View File
@@ -5,19 +5,34 @@
</component>
<component name="ChangeListManager">
<list default="true" id="7410a44d-51b9-408b-85ad-4fa46776b372" name="Changes" comment="commit unversioned files ;)">
<change afterPath="$PROJECT_DIR$/DepoT/settings/__init__.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/DepoT/settings/base.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/DepoT/settings/development.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/unused templates/settings.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.dockerignore" beforeDir="false" afterPath="$PROJECT_DIR$/.dockerignore" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.env" beforeDir="false" afterPath="$PROJECT_DIR$/.env" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/utils/utils.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/utils/utils.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/views/client_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/views/client_views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/views/employee_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/views/employee_views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/containers/views/common.py" beforeDir="false" afterPath="$PROJECT_DIR$/containers/views/common.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/payments/views.py" beforeDir="false" afterPath="$PROJECT_DIR$/payments/views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/preinfo/views/employee_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/preinfo/views/employee_views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/client-dashboard-content.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client-dashboard-content.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/common/container-details.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/common/container-details.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/common/payment-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/common/payment-list.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/employee-dashboard-content.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee-dashboard-content.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/employee-sidebar.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee-sidebar.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/web_depot.tar" beforeDir="false" afterPath="$PROJECT_DIR$/web_depot.tar" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DepoT/settings.py" beforeDir="false" afterPath="$PROJECT_DIR$/DepoT/settings/production.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/booking/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/booking/models.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/booking/tests.py" beforeDir="false" afterPath="$PROJECT_DIR$/booking/tests.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/booking/views/client_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/booking/views/client_views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/models.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/containers/tests.py" beforeDir="false" afterPath="$PROJECT_DIR$/containers/tests.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/createbuckets_depot.tar" beforeDir="false" afterPath="$PROJECT_DIR$/images/createbuckets_depot.tar" afterDir="false" />
<change beforePath="$PROJECT_DIR$/damages_api/tests.py" beforeDir="false" afterPath="$PROJECT_DIR$/damages_api/tests.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/depot-web.tar" beforeDir="false" afterPath="$PROJECT_DIR$/images/depot-web.tar" afterDir="false" />
<change beforePath="$PROJECT_DIR$/depot_image.tar" beforeDir="false" afterPath="$PROJECT_DIR$/images/depot_image.tar" afterDir="false" />
<change beforePath="$PROJECT_DIR$/docker-compose-deploy.yml" beforeDir="false" afterPath="$PROJECT_DIR$/docker-compose-deploy.yml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/dockerfile" beforeDir="false" afterPath="$PROJECT_DIR$/dockerfile" afterDir="false" />
<change beforePath="$PROJECT_DIR$/manage.py" beforeDir="false" afterPath="$PROJECT_DIR$/manage.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/minio.tar" beforeDir="false" afterPath="$PROJECT_DIR$/images/minio.tar" afterDir="false" />
<change beforePath="$PROJECT_DIR$/payments/services.py" beforeDir="false" afterPath="$PROJECT_DIR$/payments/services.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/postgres.tar" beforeDir="false" afterPath="$PROJECT_DIR$/images/postgres.tar" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/client/booking-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client/booking-list.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/common/allowed-vehicles.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/common/allowed-vehicles.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/common/base.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/common/base.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/employee/unpaid-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/unpaid-list.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/web_depot.tar" beforeDir="false" afterPath="$PROJECT_DIR$/images/web_depot.tar" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -51,8 +66,10 @@
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"ASKED_MARK_IGNORED_FILES_AS_EXCLUDED": "true",
"DefaultHtmlFileTemplate": "HTML File",
"Django Server.DepoT.executor": "Debug",
"Django tests.Test: booking.tests.BookingViewsTestCase.executor": "Debug",
"RunOnceActivity.OpenDjangoStructureViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.git.unshallow": "true",
@@ -60,7 +77,7 @@
"django.template.preview.state": "SHOW_EDITOR",
"git-widget-placeholder": "deploy__branch",
"ignore.virus.scanning.warn.message": "true",
"last_opened_file_path": "C:/dev_projects/python/Django/DepoT",
"last_opened_file_path": "C:/dev_projects/python/Django/DepoT/DepoT/settings",
"list.type.of.created.stylesheet": "CSS",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
@@ -77,21 +94,42 @@
}]]></component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\dev_projects\python\Django\DepoT\DepoT\settings" />
<recent name="C:\dev_projects\python\Django\DepoT" />
<recent name="C:\dev_projects\python\Django\DepoT\minio_backend" />
<recent name="C:\dev_projects\python\Django\DepoT\templates\employee" />
<recent name="C:\dev_projects\python\Django\DepoT\templates\client" />
<recent name="C:\dev_projects\python\Django\DepoT\templates" />
</key>
<key name="MoveFile.RECENT_KEYS">
<recent name="C:\dev_projects\python\Django\DepoT\images" />
<recent name="C:\dev_projects\python\Django\DepoT\unused templates" />
<recent name="C:\dev_projects\python\Django\DepoT\DepoT" />
<recent name="C:\dev_projects\python\Django\DepoT" />
<recent name="C:\dev_projects\python\Django\DepoT\templates\employee" />
<recent name="C:\dev_projects\python\Django\DepoT\templates\client" />
<recent name="C:\dev_projects\python\Django\DepoT\common\views" />
<recent name="C:\dev_projects\python\Django\DepoT\booking\views" />
</key>
</component>
<component name="RunManager">
<component name="RunManager" selected="Django Server.DepoT">
<configuration name="Test: booking.tests.BookingViewsTestCase" type="DjangoTestsConfigurationType" temporary="true">
<module name="DepoT" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="TARGET" value="booking.tests.BookingViewsTestCase" />
<option name="SETTINGS_FILE" value="" />
<option name="CUSTOM_SETTINGS" value="false" />
<option name="USE_OPTIONS" value="false" />
<option name="OPTIONS" value="" />
<method v="2" />
</configuration>
<configuration name="DepoT" type="Python.DjangoServer" factoryName="Django server">
<module name="DepoT" />
<option name="ENV_FILES" value="" />
@@ -99,9 +137,10 @@
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
<env name="DJANGO_SETTINGS_MODULE" value="DepoT.settings" />
<env name="DJANGO_SETTINGS_MODULE" value="DepoT.settings.development" />
</envs>
<option name="SDK_HOME" value="" />
<option name="SDK_NAME" value="Python 3.13 (DepoT)" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
@@ -117,6 +156,15 @@
<option name="customRunCommand" value="" />
<method v="2" />
</configuration>
<list>
<item itemvalue="Django Server.DepoT" />
<item itemvalue="Django tests.Test: booking.tests.BookingViewsTestCase" />
</list>
<recent_temporary>
<list>
<item itemvalue="Django tests.Test: booking.tests.BookingViewsTestCase" />
</list>
</recent_temporary>
</component>
<component name="SharedIndexes">
<attachedChunks>
@@ -263,11 +311,6 @@
<line>7</line>
<option name="timeStamp" value="55" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/DepoT/settings.py</url>
<line>12</line>
<option name="timeStamp" value="100" />
</line-breakpoint>
<line-breakpoint enabled="true" type="javascript">
<url>file://$PROJECT_DIR$/static/js/container_validation.js</url>
<line>4</line>
@@ -283,4 +326,7 @@
</default-breakpoints>
</breakpoint-manager>
</component>
<component name="com.intellij.coverage.CoverageDataManagerImpl">
<SUITE FILE_PATH="coverage/DepoT$Test__booking_tests_BookingViewsTestCase.coverage" NAME="Test: booking.tests.BookingViewsTestCase Coverage Results" MODIFIED="1754303647560" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
</component>
</project>
Binary file not shown.
Binary file not shown.
View File
View File
+188
View File
@@ -0,0 +1,188 @@
"""
Django settings for DepoT project.
Generated by 'django-admin startproject' using Django 5.2.3.
For more information on this file, see
https://docs.djangoproject.com/en/5.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.2/ref/settings/
"""
from pathlib import Path
import os
import environ
BASE_DIR = Path(__file__).resolve().parent.parent.parent
env = environ.Env()
environ.Env.read_env(os.path.join(BASE_DIR, '.env'))
SECRET_KEY = "django-insecure-g%187p84o9^rr)3#9@r3n^o2v1i%@6=+puxm7hlodg+kbsk%n#"
DEBUG = True
ALLOWED_HOSTS = ['192.168.24.43', '127.0.0.1', 'localhost', ]
PROJECT_APPS = [
'accounts',
"booking",
"common",
"containers",
'preinfo',
'payments',
]
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"rest_framework",
"damages_api",
] + PROJECT_APPS
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "DepoT.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / 'templates']
,
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
WSGI_APPLICATION = "DepoT.wsgi.application"
# Database
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
# DATABASES = {
# "default": {
# "ENGINE": "django.db.backends.sqlite3",
# "NAME": BASE_DIR / "db.sqlite3",
# }
# }
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": env("DB_NAME"),
"USER": env("DB_USER"),
"PASSWORD": env("DB_PASSWORD"),
"HOST": env("DB_HOST"),
"PORT": env("DB_PORT"),
}
}
# Password validation
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
AUTH_USER_MODEL = 'accounts.DepotUser'
LOGIN_URL = '/user/login/'
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
]
# Internationalization
# https://docs.djangoproject.com/en/5.2/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.2/howto/static-files/
STATIC_URL = "static/"
STATICFILES_DIRS = [
BASE_DIR / 'static'
]
TEMP_FILE_FOLDER = "/tmp/damages_photos"
# Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
OWNCLOUD_URL = env('OWNCLOUD_URL')
OWNCLOUD_USER = env('OWNCLOUD_USER')
OWNCLOUD_PASSWORD = env('OWNCLOUD_PASSWORD')
OWNCLOUD_DAMAGES_FOLDER = env('OWNCLOUD_DAMAGES_FOLDER')
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = env("EMAIL_HOST", cast=str, default=None)
EMAIL_PORT = env("EMAIL_PORT", cast=str, default='587') # Recommended
EMAIL_HOST_USER = env("EMAIL_HOST_USER", cast=str, default=None)
EMAIL_HOST_PASSWORD = env("EMAIL_HOST_PASSWORD", cast=str, default=None)
EMAIL_USE_TLS = env("EMAIL_USE_TLS", cast=bool, default=True) # Use EMAIL_PORT 587 for TLS
EMAIL_USE_SSL = env("EMAIL_USE_SSL", cast=bool, default=False) # EUse MAIL_PORT 465 for SSL
ADMIN_USER_NAME=env("ADMIN_USER_NAME")
ADMIN_USER_PASSWORD=env("ADMIN_USER_PASSWORD")
ADMIN_USER_EMAIL=env("ADMIN_USER_EMAIL")
MANAGERS=[]
ADMINS=[]
if all([ADMIN_USER_NAME, ADMIN_USER_EMAIL]):
ADMINS +=[
(f'{ADMIN_USER_NAME}', f'{ADMIN_USER_EMAIL}')
]
MANAGERS=ADMINS
MINIO_ENDPOINT = env('MINIO_ENDPOINT')
AWS_S3_CUSTOM_DOMAIN = env('AWS_S3_CUSTOM_DOMAIN')
MINIO_SERVER_URL = env('MINIO_SERVER_URL')
AWS_S3_URL_PROTOCOL = env('AWS_S3_URL_PROTOCOL')
MINIO_ACCESS_KEY = env('MINIO_ACCESS_KEY')
MINIO_SECRET_KEY = env('MINIO_SECRET_KEY')
MINIO_BUCKET_NAME = env('MINIO_BUCKET_NAME')
MINIO_SECURE = False # Set to True if using HTTPS
+247
View File
@@ -0,0 +1,247 @@
"""
Django settings for DepoT project.
Generated by 'django-admin startproject' using Django 5.2.3.
For more information on this file, see
https://docs.djangoproject.com/en/5.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.2/ref/settings/
"""
from pathlib import Path
import os
import environ
from minio_backend.storage import MinioStaticStorage, MinioMediaStorage
BASE_DIR = Path(__file__).resolve().parent.parent.parent
env = environ.Env()
environ.Env.read_env(os.path.join(BASE_DIR, 'production.env'))
SECRET_KEY = "django-insecure-g%187p84o9^rr)3#9@r3n^o2v1i%@6=+puxm7hlodg+kbsk%n#"
DEBUG = False
ALLOWED_HOSTS = ['192.168.24.43', '127.0.0.1', 'localhost', 'depot.kikimor.com', ]
CSRF_TRUSTED_ORIGINS = ['https://depot.kikimor.com']
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
USE_X_FORWARDED_HOST = True
PROJECT_APPS = [
'accounts',
"booking",
"common",
"containers",
'preinfo',
'payments',
]
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"rest_framework",
"damages_api",
"django_minio_backend",
"minio_backend",
] + PROJECT_APPS
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "DepoT.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / 'templates']
,
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
WSGI_APPLICATION = "DepoT.wsgi.application"
# Database
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
# DATABASES = {
# "default": {
# "ENGINE": "django.db.backends.sqlite3",
# "NAME": BASE_DIR / "db.sqlite3",
# }
# }
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": env("DB_NAME"),
"USER": env("DB_USER"),
"PASSWORD": env("DB_PASSWORD"),
"HOST": env("DB_HOST"),
"PORT": env("DB_PORT"),
}
}
# Password validation
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
AUTH_USER_MODEL = 'accounts.DepotUser'
LOGIN_URL = '/user/login/'
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
]
# Internationalization
# https://docs.djangoproject.com/en/5.2/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.2/howto/static-files/
STATIC_URL = "static/"
STATICFILES_DIRS = [
BASE_DIR / 'static'
]
STATIC_ROOT = BASE_DIR / 'staticfiles'
TEMP_FILE_FOLDER = "/tmp/damages_photos"
# Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
OWNCLOUD_URL = env('OWNCLOUD_URL')
OWNCLOUD_USER = env('OWNCLOUD_USER')
OWNCLOUD_PASSWORD = env('OWNCLOUD_PASSWORD')
OWNCLOUD_DAMAGES_FOLDER = env('OWNCLOUD_DAMAGES_FOLDER')
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = env("EMAIL_HOST", cast=str, default=None)
EMAIL_PORT = env("EMAIL_PORT", cast=str, default='587') # Recommended
EMAIL_HOST_USER = env("EMAIL_HOST_USER", cast=str, default=None)
EMAIL_HOST_PASSWORD = env("EMAIL_HOST_PASSWORD", cast=str, default=None)
EMAIL_USE_TLS = env("EMAIL_USE_TLS", cast=bool, default=True) # Use EMAIL_PORT 587 for TLS
EMAIL_USE_SSL = env("EMAIL_USE_SSL", cast=bool, default=False) # EUse MAIL_PORT 465 for SSL
ADMIN_USER_NAME=env("ADMIN_USER_NAME")
ADMIN_USER_PASSWORD=env("ADMIN_USER_PASSWORD")
ADMIN_USER_EMAIL=env("ADMIN_USER_EMAIL")
MANAGERS=[]
ADMINS=[]
if all([ADMIN_USER_NAME, ADMIN_USER_EMAIL]):
ADMINS +=[
(f'{ADMIN_USER_NAME}', f'{ADMIN_USER_EMAIL}')
]
MANAGERS=ADMINS
MINIO_ENDPOINT = env('MINIO_ENDPOINT')
AWS_S3_CUSTOM_DOMAIN = env('AWS_S3_CUSTOM_DOMAIN')
MINIO_SERVER_URL = env('MINIO_SERVER_URL')
MINIO_EXTERNAL_ENDPOINT = AWS_S3_CUSTOM_DOMAIN
MINIO_EXTERNAL_ENDPOINT_USE_HTTPS = True
AWS_S3_URL_PROTOCOL = env('AWS_S3_URL_PROTOCOL')
MINIO_ACCESS_KEY = env('MINIO_ACCESS_KEY')
MINIO_SECRET_KEY = env('MINIO_SECRET_KEY')
MINIO_BUCKET_NAME = env('MINIO_BUCKET_NAME')
MINIO_SECURE = False # Set to True if using HTTPS
MINIO_USE_HTTPS = False # Add this line
MINIO_STATIC_BUCKET = env('MINIO_STATIC_BUCKET_NAME')
# django-minio-backend settings
MINIO_STORAGE_ENDPOINT = AWS_S3_CUSTOM_DOMAIN
MINIO_STORAGE_PORT = 443 if MINIO_SECURE else 80 # Add this line
MINIO_STORAGE_ACCESS_KEY = env('MINIO_ACCESS_KEY')
MINIO_STORAGE_SECRET_KEY = env('MINIO_SECRET_KEY')
MINIO_STORAGE_USE_HTTPS = True
MINIO_STORAGE_MEDIA_BUCKET_NAME = env('MINIO_BUCKET_NAME') # For user-uploaded media
MINIO_STORAGE_STATIC_BUCKET_NAME = env('MINIO_STATIC_BUCKET_NAME') # For static files
MINIO_STORAGE_AUTO_CREATE_MEDIA_BUCKET = True
MINIO_STORAGE_AUTO_CREATE_STATIC_BUCKET = True
MINIO_STORAGE_AUTO_CREATE_POLICY = True
MINIO_STORAGE_MEDIA_BASE_URL = f'{AWS_S3_URL_PROTOCOL}://{AWS_S3_CUSTOM_DOMAIN}/{env("MINIO_BUCKET_NAME")}/'
MINIO_STORAGE_STATIC_BASE_URL = f'{AWS_S3_URL_PROTOCOL}://{AWS_S3_CUSTOM_DOMAIN}/{env("MINIO_STATIC_BUCKET_NAME")}/'
MINIO_PRIVATE_BUCKETS = [] # If you have any private buckets
MINIO_PUBLIC_BUCKETS = [
env('MINIO_BUCKET_NAME'), # Just the bucket name as a string
env('MINIO_STATIC_BUCKET_NAME') # Just the bucket name as a string
]
MINIO_POLICY_ACTIONS = {
'GET': ['get_object'],
'PUT': ['put_object'],
'DELETE': ['delete_object'],
'LIST': ['list_multipart_uploads',
'list_parts',
'list_objects'],
}
STORAGES = {
"default": {
"BACKEND": "minio_backend.storage.MinioMediaStorage",
},
"staticfiles": {
"BACKEND": "minio_backend.storage.MinioStaticStorage",
},
}
DEFAULT_FILE_STORAGE = 'minio_backend.storage.MinioMediaStorage'
STATICFILES_STORAGE = 'minio_backend.storage.MinioStaticStorage'
STATIC_URL = f'{AWS_S3_URL_PROTOCOL}://{AWS_S3_CUSTOM_DOMAIN}/{env("MINIO_STATIC_BUCKET_NAME")}/'
STATICFILES_LOCATION = 'static'
MEDIA_ROOT = BASE_DIR / 'mediafiles'
MEDIA_URL = f'{AWS_S3_URL_PROTOCOL}://{AWS_S3_CUSTOM_DOMAIN}/{env("MINIO_BUCKET_NAME")}/'
Binary file not shown.
Binary file not shown.
+4 -1
View File
@@ -41,4 +41,7 @@ class Booking(models.Model):
@property
def containers_left(self):
return self.container_count - (self.container_expedited_count or 0)
return self.container_count - (self.container_expedited_count or 0)
class Meta:
app_label = 'booking'
+48 -2
View File
@@ -1,3 +1,49 @@
from django.test import TestCase
from django.test import TestCase, Client
from django.urls import reverse
from django.contrib.auth import get_user_model
from booking.models import Booking
from common.models import LinesModel, ContainerTypeModel
# Create your tests here.
class BookingViewsTestCase(TestCase):
def setUp(self):
self.client = Client()
DepotUser = get_user_model()
self.user = DepotUser.objects.create_user(username='testuser', password='password', user_type='EM')
self.client.login(username='testuser', password='password')
self.line = LinesModel.objects.create(name='Test Line')
self.container_type = ContainerTypeModel.objects.create(name='20ft')
self.booking = Booking.objects.create(
number='BOOK123',
container_type=self.container_type,
container_count=10,
line=self.line,
created_by=self.user.id,
updated_by=self.user.id
)
def test_booking_list_view(self):
response = self.client.get(reverse('booking-list'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'booking/booking-list.html')
self.assertContains(response, self.booking.number)
def test_booking_create_view(self):
response = self.client.post(reverse('booking-create'), {
'number': 'BOOK456',
'container_type': self.container_type.id,
'container_count': 5,
'line': self.line.id,
})
self.assertEqual(response.status_code, 302)
self.assertTrue(Booking.objects.filter(number='BOOK456').exists())
def test_booking_update_view(self):
response = self.client.post(reverse('booking-update', args=[self.booking.id]), {
'number': 'BOOK123-updated',
'container_type': self.container_type.id,
'container_count': 15,
'line': self.line.id,
})
self.assertEqual(response.status_code, 302)
self.booking.refresh_from_db()
self.assertEqual(self.booking.number, 'BOOK123-updated')
+1 -1
View File
@@ -44,7 +44,7 @@ class CreateBookingView(LoginRequiredMixin, UserPassesTestMixin, LineFilterFormM
return super().form_valid(form)
def test_func(self):
self.request.user.has_company_perm('can_edit_preinfo') or self.request.user.user_type == 'CA'
return self.request.user.has_company_perm('can_manage_booking') or self.request.user.user_type == 'CA'
class ClientBookingUpdateView(LoginRequiredMixin, UserPassesTestMixin, LineFilterFormMixin, CreateView):
Binary file not shown.
+7 -2
View File
@@ -15,7 +15,8 @@ class NomenclatureBaseModel(models.Model):
class CompanyModel(NomenclatureBaseModel):
...
class Meta:
app_label = 'common'
class LinesModel(NomenclatureBaseModel):
@@ -25,8 +26,12 @@ class LinesModel(NomenclatureBaseModel):
related_name='line_company'
)
class Meta:
app_label = 'common'
class OperationModel(NomenclatureBaseModel):
...
class Meta:
app_label = 'common'
class ContainerKindModel(NomenclatureBaseModel):
...
+47 -2
View File
@@ -1,3 +1,48 @@
from django.test import TestCase
from django.test import TestCase, Client
from django.urls import reverse
from django.contrib.auth import get_user_model
from containers.models import Container
from common.models import LinesModel, ContainerTypeModel
from preinfo.models import Preinfo
# Create your tests here.
class ContainerViewsTestCase(TestCase):
def setUp(self):
self.client = Client()
DepotUser = get_user_model()
self.user = DepotUser.objects.create_user(username='testuser', password='password', user_type='E')
self.client.login(username='testuser', password='password')
self.line = LinesModel.objects.create(name='Test Line')
self.container_type = ContainerTypeModel.objects.create(name='20ft')
self.preinfo = Preinfo.objects.create(number='PRE123', line=self.line, container_type=self.container_type)
self.container = Container.objects.create(
number='TEST1234567',
line=self.line,
container_type=self.container_type,
received_by=self.user,
preinfo=self.preinfo
)
def test_container_list_view(self):
response = self.client.get(reverse('container-list'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'containers/container-list.html')
self.assertContains(response, self.container.number)
def test_container_receive_view(self):
response = self.client.post(reverse('container-receive'), {
'number': 'TEST7654321',
'line': self.line.id,
'container_type': self.container_type.id,
'preinfo': self.preinfo.id,
})
self.assertEqual(response.status_code, 302)
self.assertTrue(Container.objects.filter(number='TEST7654321').exists())
def test_container_expedition_view(self):
response = self.client.post(reverse('container-expedition', args=[self.container.id]), {
'expedition_vehicle': 'TRUCK123',
})
self.assertEqual(response.status_code, 302)
self.container.refresh_from_db()
self.assertTrue(self.container.expedited)
self.assertEqual(self.container.expedition_vehicle, 'TRUCK123')
+48 -2
View File
@@ -1,3 +1,49 @@
from django.test import TestCase
import base64
from unittest.mock import patch
from django.test import TestCase, Client
from django.urls import reverse
from rest_framework import status
from django.contrib.auth import get_user_model
from containers.models import Container, ContainerPhotos
from common.models import LinesModel, ContainerTypeModel
from preinfo.models import Preinfo
# Create your tests here.
class DamagesAPITestCase(TestCase):
def setUp(self):
self.client = Client()
DepotUser = get_user_model()
self.user = DepotUser.objects.create_user(username='testuser', password='password', user_type='E')
self.client.login(username='testuser', password='password')
self.line = LinesModel.objects.create(name='Test Line')
self.container_type = ContainerTypeModel.objects.create(name='20ft')
self.preinfo = Preinfo.objects.create(number='PRE123', line=self.line, container_type=self.container_type)
self.container = Container.objects.create(
number='TEST1234567',
line=self.line,
container_type=self.container_type,
received_by=self.user,
preinfo=self.preinfo
)
@patch('damages_api.views.upload_damage_photo')
def test_damage_photo_upload(self, mock_upload):
mock_upload.return_value = 'http://mock-url.com/photo.jpg'
photo_data = base64.b64encode(b'test photo data').decode('utf-8')
response = self.client.post(reverse('damages-api', args=[self.container.id]), {
'photo': photo_data,
'photo_extension': 'jpg',
}, content_type='application/json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertTrue(ContainerPhotos.objects.filter(container=self.container).exists())
@patch('damages_api.views.boto3.client')
def test_damage_photo_retrieval(self, mock_boto_client):
mock_s3 = mock_boto_client.return_value
mock_s3.list_objects_v2.return_value = {
'Contents': [
{'Key': f'{self.container.id}/test.jpg'}
]
}
response = self.client.get(reverse('damages-api', args=[self.container.id]))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('url', response.data[0])
+1 -3
View File
@@ -38,8 +38,7 @@ services:
networks:
- app-network
command: >
bash -c "sleep 10 &&\
python manage.py collectstatic --noinput --verbosity 3 &&\
bash -c "python manage.py collectstatic --noinput --verbosity 3 &&\
python manage.py migrate &&\
gunicorn DepoT.wsgi:application --bind 0.0.0.0:8000 --workers 3"
@@ -70,7 +69,6 @@ services:
condition: service_healthy
entrypoint: >
/bin/sh -c "
sleep 10;
mc alias set myminio http://minio:9000 kikimor shushunka1;
mc mb myminio/damages;
mc mb myminio/static;
+1
View File
@@ -2,6 +2,7 @@ FROM python:3.11-slim
ENV PYTHONUNBUFFERED=1
WORKDIR /DepoT
ENV PYTHONPATH="${PYTHONPATH}:/DepoT:/."
ENV DJANGO_SETTINGS_MODULE=DepoT.settings.production
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
View File
Binary file not shown.
+1 -1
View File
@@ -6,7 +6,7 @@ import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "DepoT.settings")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "DepoT.settings.development")
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
Binary file not shown.
Binary file not shown.
+5 -4
View File
@@ -5,9 +5,10 @@ import urllib.parse
from datetime import datetime, timedelta
import requests
import environ
from DepoT.settings import env
# from DepoT.settings import env
env = environ.Env()
class EPay:
payment_types = {
@@ -33,8 +34,8 @@ class EPay:
datetime.today() + timedelta(days=int(env("INVOICE_EXPIRE_PERIOD")))
).strftime("%d.%m.%Y")
if amount == 0:
amount = 1000
# if amount == 0:
# amount = 1000 # for
message = f"MIN={client_id}\nINVOICE={invoice}\nAMOUNT={amount}\nCURRENCY={currency}\nEXP_TIME={expiry}\nDESCR={description}"
encoded_data, checksum = EPay.encode_message(message)
+3 -2
View File
@@ -1,6 +1,7 @@
{% extends 'list-crud.html' %}
{% load static %}
{% load filters %}
{% load custom_filters %}
{% block filter %}
<form id="filterForm" method="get" style="display: inline;">
@@ -32,8 +33,8 @@
<td>{{ object.container_number }}</td>
<td>{{ object.container_count }}</td>
<td>{{ object.containers_left }}</td>
<td>{{ object.vehicles }}</td>
<td>{{ object.vehicles_left }}</td>
<td>{{ object.vehicles|distinct_vehicles }}</td>
<td>{{ object.vehicles_left|distinct_vehicles }}</td>
<td>{{ object.created_on|bg_date }}</td>
<td>{{ object.created_by.username }}</td>
<td>{{ object.status }}</td>
+29 -17
View File
@@ -7,12 +7,14 @@
body {
font-family: Arial, sans-serif;
margin: 40px;
background-color: black;
color: white;
background-color: black;
color: white;
font-size: 2em;
}
h1 {
font-size: 2.5em;
margin-bottom: 20px;
text-align: center;
}
.table-container {
width: 90%;
@@ -21,14 +23,22 @@
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 30px;
}
th, td {
text-align: left;
padding: 12px;
border: 1px solid #ddd;
}
th {
background-color: #f5f5f5;
font-size: 2em;
background-color: white;
color: black;
}
td {
font-size: 2em;
color: white;
}
</style>
</head>
@@ -36,20 +46,22 @@
<h1>Vehicles with bookings</h1>
<div class="table-container">
<table>
<thead>
<tr>
<th>Line name</th>
</tr>
</thead>
<tbody>
<tr>
<td>BB1234TT, TT1234BB</td>
</tr>
</tbody>
</table>
</div>
{% for obj in objects %}
<div class="table-container">
<table>
<thead>
<tr>
<th>{{ obj.line }}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ obj.vehicles|upper}}</td>
</tr>
</tbody>
</table>
</div>
{% endfor %}
</body>
</html>
+4
View File
@@ -48,6 +48,10 @@
<script src="{% static 'js/container_validation.js' %}"></script>
{% endblock extra_js %}
{% block custom_js %}
{% endblock custom_js %}
</body>
</html>
+2 -1
View File
@@ -43,7 +43,7 @@
{% endblock table_data %}
{% block buttons %}
<button id="createPaymentBtn" class="btn btn-primary" data-requires-selection disabled>Create Payment</button>
<button id="createPaymentBtn" class="btn btn-primary" data-requires-selection disabled>Create Payment</button>
{% endblock buttons %}
{% block create_modal_header %}
@@ -74,5 +74,6 @@ document.getElementById('createPaymentBtn').addEventListener('click', function()
window.location.href = '{% url "payments_create" %}?' + params.toString();
}
});
</script>
{% endblock custom_js %}