Added filter functionality and combined both base.html

master
kikimor 7 months ago
parent c1183c22ea
commit 2d0d33d525

@ -7,47 +7,45 @@
<list default="true" id="7410a44d-51b9-408b-85ad-4fa46776b372" name="Changes" comment="commit unversioned files ;)"> <list default="true" id="7410a44d-51b9-408b-85ad-4fa46776b372" name="Changes" comment="commit unversioned files ;)">
<change afterPath="$PROJECT_DIR$/accounts/migrations/0008_populate_permissions.py" afterDir="false" /> <change afterPath="$PROJECT_DIR$/accounts/migrations/0008_populate_permissions.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/accounts/migrations/0009_create_superuser.py" afterDir="false" /> <change afterPath="$PROJECT_DIR$/accounts/migrations/0009_create_superuser.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/booking/templatetags/__init__.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/booking/templatetags/custom_filters.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/common/migrations/0004_populate_initial_data.py" afterDir="false" /> <change afterPath="$PROJECT_DIR$/common/migrations/0004_populate_initial_data.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/common/utils/minio_utils.py" afterDir="false" /> <change afterPath="$PROJECT_DIR$/docker-compose-deploy.yml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/containers/views/common.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/docker-compose.minio.yml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/payments/migrations/0004_populate_tariffs.py" afterDir="false" /> <change afterPath="$PROJECT_DIR$/payments/migrations/0004_populate_tariffs.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/static/js/container-details.js" afterDir="false" /> <change afterPath="$PROJECT_DIR$/templates/registration/change_password.html" afterDir="false" />
<change afterPath="$PROJECT_DIR$/static/styles/details.css" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/common/base.html" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/common/container-details.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DepoT/settings.py" beforeDir="false" afterPath="$PROJECT_DIR$/DepoT/settings.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/accounts/forms.py" beforeDir="false" afterPath="$PROJECT_DIR$/accounts/forms.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/accounts/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/accounts/urls.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/accounts/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/accounts/urls.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/accounts/views.py" beforeDir="false" afterPath="$PROJECT_DIR$/accounts/views.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/accounts/views.py" beforeDir="false" afterPath="$PROJECT_DIR$/accounts/views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/booking/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/booking/urls.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/booking/views/employee_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/booking/views/employee_views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/urls.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/common/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/models.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/utils/owncloud_utls.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/utils/owncloud_utls.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/forms.py" beforeDir="false" afterPath="$PROJECT_DIR$/containers/forms.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/containers/views/employee_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/containers/views/employee_views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/containers/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/containers/urls.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$/damages_api/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/damages_api/urls.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/damages_api/views.py" beforeDir="false" afterPath="$PROJECT_DIR$/damages_api/views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/docker-compose.yml" beforeDir="false" afterPath="$PROJECT_DIR$/docker-compose.yml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/dockerfile" beforeDir="false" afterPath="$PROJECT_DIR$/dockerfile" afterDir="false" />
<change beforePath="$PROJECT_DIR$/preinfo/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/preinfo/urls.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/preinfo/views/client_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/preinfo/views/client_views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/requirements.txt" beforeDir="false" afterPath="$PROJECT_DIR$/requirements.txt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/static/js/crud-list.js" beforeDir="false" afterPath="$PROJECT_DIR$/static/js/crud-list.js" afterDir="false" /> <change beforePath="$PROJECT_DIR$/static/js/crud-list.js" beforeDir="false" afterPath="$PROJECT_DIR$/static/js/crud-list.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/static/styles/forms.css" beforeDir="false" afterPath="$PROJECT_DIR$/static/styles/forms.css" afterDir="false" /> <change beforePath="$PROJECT_DIR$/static/styles/forms.css" beforeDir="false" afterPath="$PROJECT_DIR$/static/styles/forms.css" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/client-base.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client-base.html" afterDir="false" /> <change beforePath="$PROJECT_DIR$/templates/client-booking-content.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client-booking-content.html" 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/client-dashboard-content.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client-dashboard-content.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/client/line-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client/line-list.html" afterDir="false" /> <change beforePath="$PROJECT_DIR$/templates/client-orders-content.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client-orders-content.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/client/preinfo-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client/preinfo-list.html" afterDir="false" /> <change beforePath="$PROJECT_DIR$/templates/client-preinfo-content.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client-preinfo-content.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/employee-base.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee-base.html" afterDir="false" /> <change beforePath="$PROJECT_DIR$/templates/client/booking-create.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client/booking-create.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$/templates/client/booking-edit.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client/booking-edit.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/client/line-create.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client/line-create.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/client/line-update.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client/line-update.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/client/preinfo-create.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client/preinfo-create.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/client/preinfo-edit.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client/preinfo-edit.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-dashboard-content.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee-dashboard-content.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/employee/booking-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/booking-list.html" afterDir="false" /> <change beforePath="$PROJECT_DIR$/templates/employee/booking-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/booking-list.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/employee/company-create.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/company-create.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/employee/company-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/company-list.html" afterDir="false" /> <change beforePath="$PROJECT_DIR$/templates/employee/company-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/company-list.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/employee/company-update.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/company-update.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/employee/containers-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/containers-list.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/employee/line-create.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/line-create.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/employee/line-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/line-list.html" afterDir="false" /> <change beforePath="$PROJECT_DIR$/templates/employee/line-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/line-list.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/employee/line-update.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/line-update.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/employee/payment-create.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/payment-create.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/employee/preinfo-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/preinfo-list.html" afterDir="false" /> <change beforePath="$PROJECT_DIR$/templates/employee/preinfo-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/preinfo-list.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/landing-page.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/landing-page.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/list-crud.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/list-crud.html" afterDir="false" /> <change beforePath="$PROJECT_DIR$/templates/list-crud.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/list-crud.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/registration/register.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/registration/register.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/registration/user-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/registration/user-list.html" afterDir="false" /> <change beforePath="$PROJECT_DIR$/templates/registration/user-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/registration/user-list.html" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
@ -62,10 +60,10 @@
<component name="FileTemplateManagerImpl"> <component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES"> <option name="RECENT_TEMPLATES">
<list> <list>
<option value="HTML File" />
<option value="CSS File" /> <option value="CSS File" />
<option value="JavaScript File" /> <option value="JavaScript File" />
<option value="Python Script" /> <option value="Python Script" />
<option value="HTML File" />
</list> </list>
</option> </option>
</component> </component>
@ -172,7 +170,7 @@
<workItem from="1753175068058" duration="4635000" /> <workItem from="1753175068058" duration="4635000" />
<workItem from="1753179863298" duration="8357000" /> <workItem from="1753179863298" duration="8357000" />
<workItem from="1753197869497" duration="98156000" /> <workItem from="1753197869497" duration="98156000" />
<workItem from="1753637487803" duration="30673000" /> <workItem from="1753637487803" duration="42690000" />
</task> </task>
<task id="LOCAL-00001" summary="Add IntelliJ IDEA project configuration files&#10;&#10;This commit adds IntelliJ IDEA-specific configuration files for the project, including module setup, version control integration, inspection profiles, and workspace settings. These files facilitate development environment configuration for contributors using IntelliJ IDEA."> <task id="LOCAL-00001" summary="Add IntelliJ IDEA project configuration files&#10;&#10;This commit adds IntelliJ IDEA-specific configuration files for the project, including module setup, version control integration, inspection profiles, and workspace settings. These files facilitate development environment configuration for contributors using IntelliJ IDEA.">
<option name="closed" value="true" /> <option name="closed" value="true" />
@ -312,6 +310,10 @@
<line>4</line> <line>4</line>
<option name="timeStamp" value="95" /> <option name="timeStamp" value="95" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" type="django-line">
<url>file://$PROJECT_DIR$/templates/client-dashboard-content.html</url>
<option name="timeStamp" value="103" />
</line-breakpoint>
</breakpoints> </breakpoints>
<default-breakpoints> <default-breakpoints>
<breakpoint type="python-exception"> <breakpoint type="python-exception">

@ -1,5 +1,6 @@
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.views import PasswordChangeView
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.forms import CharField from django.forms import CharField
from django.forms.models import ModelForm from django.forms.models import ModelForm
@ -18,7 +19,6 @@ class RegisterForm(ModelForm):
field_order = ['username', 'email', 'password1', 'password2', 'phone_number', 'company', 'line', 'user_type', 'company_permissions', 'employee_permissions', 'is_active'] field_order = ['username', 'email', 'password1', 'password2', 'phone_number', 'company', 'line', 'user_type', 'company_permissions', 'employee_permissions', 'is_active']
class Meta: class Meta:
model = get_user_model() model = get_user_model()
fields = ['username', 'email', 'password1', 'password2', 'phone_number', 'company', 'line', 'user_type', 'company_permissions', 'employee_permissions', 'is_active'] fields = ['username', 'email', 'password1', 'password2', 'phone_number', 'company', 'line', 'user_type', 'company_permissions', 'employee_permissions', 'is_active']
@ -52,3 +52,45 @@ class RegisterForm(ModelForm):
user.save() user.save()
return user return user
class UserEditForm(ModelForm):
password1 = CharField(required=False, label='Password', widget=PasswordInput)
password2 = CharField(required=False, label='Confirm Password', widget=PasswordInput)
field_order = ['username', 'email', 'password1', 'password2', 'phone_number', 'company', 'line', 'user_type', 'company_permissions', 'employee_permissions', 'is_active']
class Meta:
model = get_user_model()
fields = ['username', 'email', 'password1', 'password2', 'phone_number', 'company', 'line', 'user_type', 'company_permissions', 'employee_permissions', 'is_active']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['user_type'].widget.attrs['readonly'] = True
self.fields['company_permissions'].widget.attrs['disabled'] = True
self.fields['employee_permissions'].widget.attrs['disabled'] = True
if self.data.get('user_type') in ( 'EM', 'BS'):
self.fields['company_permissions'].required = False
if self.data.get('user_type') in ('CL', 'CA', 'BS'):
self.fields['company_permissions'].required = False
def clean(self):
cleaned_data = super().clean()
password1 = cleaned_data.get('password1')
password2 = cleaned_data.get('password2')
if password1 and password2 and password1 != password2:
raise ValidationError("Passwords don't match")
return cleaned_data
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data['password1'])
if commit:
user.save()
return user
class UserChangePasswordForm(PasswordChangeView):
old_password = CharField(widget=PasswordInput())
new_password = CharField(widget=PasswordInput())
confirm_password = CharField(widget=PasswordInput())

@ -0,0 +1,44 @@
from django.db import migrations
def create_permissions(apps, schema_editor):
EmployeePermission = apps.get_model('accounts', 'EmployeePermission')
ClientPermission = apps.get_model('accounts', 'ClientPermission')
employee_permissions = [
(1, 'can_manage_containers', 'Can manage containers'),
(2, 'can_view_reports', 'Can view reports'),
(3, 'can_handle_operations', 'Can handle operations'),
]
for _id, codename, name in employee_permissions:
EmployeePermission.objects.create(id=_id, codename=codename, name=name)
client_permissions = [
(1, 'can_view_booking', 'Can view booking'),
(2, 'can_manage_booking', 'Can book container'),
(3, 'can_view_preinfo', 'Can view preinfo'),
(4, 'can_manage_preinfo', 'Can manage preinfo'),
(5, 'can_view_payment', 'Can view payment'),
(6, 'can_manage_payment', 'Can manage payment'),
(7, 'can_manage_company_users', 'Can manage company users'),
]
for _id, codename, name in client_permissions:
ClientPermission.objects.create(id=_id, codename=codename, name=name)
def reverse_permissions(apps, schema_editor):
EmployeePermission = apps.get_model('accounts', 'EmployeePermission')
ClientPermission = apps.get_model('accounts', 'ClientPermission')
EmployeePermission.objects.all().delete()
ClientPermission.objects.all().delete()
class Migration(migrations.Migration):
dependencies = [
('accounts', '0007_auto_20250725_1920'), # Adjust this to your last migration
]
operations = [
migrations.RunPython(create_permissions, reverse_permissions),
]

@ -0,0 +1,29 @@
from django.db import migrations
from django.conf import settings
from django.contrib.auth.hashers import make_password
def create_superuser(apps, schema_editor):
User = apps.get_model('accounts', 'DepotUser')
if not User.objects.filter(email=settings.ADMIN_USER_EMAIL).exists():
user = User.objects.create(
email=settings.ADMIN_USER_EMAIL,
username=settings.ADMIN_USER_NAME,
is_staff=True,
is_superuser=True,
is_active=True,
user_type='AD',
password=make_password(settings.ADMIN_USER_PASSWORD)
)
def reverse_superuser(apps, schema_editor):
User = apps.get_model('accounts', 'DepotUser')
User.objects.filter(email=settings.ADMIN_USER_EMAIL).delete()
class Migration(migrations.Migration):
dependencies = [
('accounts', '0008_populate_permissions'),
]
operations = [
migrations.RunPython(create_superuser, reverse_superuser),
]

@ -3,11 +3,12 @@ from django.contrib.auth import views as auth_views
from accounts import views from accounts import views
urlpatterns = [ urlpatterns = [
path('login/', views.DepotLoginView.as_view(), name='login'), path('', include([
path('relogin/', auth_views.logout_then_login, name='relogin'),
path('user/', include([
path('', views.UserListView.as_view(), name='user_list'), path('', views.UserListView.as_view(), name='user_list'),
path('register/', views.RegisterView.as_view(), name='user_register'), path('register/', views.RegisterView.as_view(), name='user_register'),
path('login/', views.DepotLoginView.as_view(), name='login'),
path('relogin/', auth_views.logout_then_login, name='relogin'),
path('change-password/', views.UserChangePasswordView.as_view(), name='change_password'),
path('<int:pk>/update/', views.UserUpdateView.as_view(), name='user_update'), path('<int:pk>/update/', views.UserUpdateView.as_view(), name='user_update'),
path('<int:pk>/active/', views.UserActiveView.as_view(), name='user_active'), path('<int:pk>/active/', views.UserActiveView.as_view(), name='user_active'),
])), ])),

@ -8,7 +8,7 @@ from django.views import View
from django.views.generic import TemplateView, FormView, ListView, UpdateView from django.views.generic import TemplateView, FormView, ListView, UpdateView
from rest_framework.generics import get_object_or_404 from rest_framework.generics import get_object_or_404
from accounts.forms import LoginForm, RegisterForm from accounts.forms import LoginForm, RegisterForm, UserChangePasswordForm
from accounts.models import DepotUser from accounts.models import DepotUser
from django.contrib.auth.decorators import login_required, user_passes_test from django.contrib.auth.decorators import login_required, user_passes_test
@ -106,6 +106,11 @@ class UserListView(ListView):
queryset = super().get_queryset() queryset = super().get_queryset()
user = self.request.user user = self.request.user
data_filter = self.request.GET.get('filter')
if data_filter != 'all':
queryset = queryset.filter(is_active=True)
# Filter users based on permissions # Filter users based on permissions
if user.is_superuser: if user.is_superuser:
return queryset.all() return queryset.all()
@ -184,4 +189,10 @@ class UserActiveView(LoginRequiredMixin, View):
target_user.is_active = not target_user.is_active target_user.is_active = not target_user.is_active
target_user.save() target_user.save()
return JsonResponse({'success': True, 'is_active': target_user.is_active}) return JsonResponse({'success': True, 'is_active': target_user.is_active})
class UserChangePasswordView(LoginRequiredMixin, View):
template_name = 'registration/change_password.html'
form_class = UserChangePasswordForm
success_url = reverse_lazy('home')

@ -13,4 +13,15 @@ class BookingListView(ListView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context['base_template'] = self.base_template context['base_template'] = self.base_template
return context return context
def get_queryset(self):
queryset = super().get_queryset()
data_filter = self.request.GET.get('filter')
if data_filter != 'all':
queryset = queryset.filter(status='active')
queryset = queryset.order_by('-created_on')
return queryset

@ -0,0 +1,91 @@
from django.db import migrations
def create_initial_data(apps, schema_editor):
ContainerKindModel = apps.get_model('common', 'ContainerKindModel')
ContainerTypeModel = apps.get_model('common', 'ContainerTypeModel')
CompanyModel = apps.get_model('common', 'CompanyModel')
LinesModel = apps.get_model('common', 'LinesModel')
# Container Kinds
container_kinds = [
(1, 'Standart', '', ''),
(2, 'Reefer', '', ''),
(3, 'Opentop', '', ''),
(4, 'FlatRack', '', ''),
(5, 'Tank', '', ''),
(6, 'Platform', '', ''),
]
for _id, name, *rest in container_kinds:
ContainerKindModel.objects.create(id=_id, name=name)
# Container Types
container_types = [
(1, '20GP', 20, False, 1, False),
(2, '40GP', 40, False, 1, False),
(3, '40HC', 40, True, 1, False),
(4, '20RF', 20, False, 2, False),
(5, '40RF', 40, False, 2, False),
(6, '20OT', 20, False, 3, False),
(7, '40OT', 40, False, 3, False),
(8, '20FR', 20, False, 4, False),
(9, '20FRPL', 20, False, 6, False),
(10, '45HC', 45, True, 1, False),
(11, '40FRPL', 40, False, 6, False),
(12, '40HR', 40, True, 2, False),
]
for _id, name, length, height, container_type_id, deleted in container_types:
ContainerTypeModel.objects.create(
id=_id,
name=name,
length=length,
height=height,
container_type_id=container_type_id,
deleted=deleted
)
# Companies and Lines
companies = [
(1, 'GMS', 'GMS', 'Global Maritime Servises'),
(2, 'TO', 'TO', 'Терминален оператор'),
]
for _id, name, short_name, description in companies:
CompanyModel.objects.create(
id=_id,
name=name,
short_name=short_name,
description=description
)
lines = [
(1, 'GMS', 'GMS', 'GMS line', 1),
(2, 'HPG', 'HPG', 'Hapag Lloyds line', 1),
(3, 'TO', 'TO', 'Терминален оператор line', 2),
]
for _id, name, short_name, description, company_id in lines:
LinesModel.objects.create(
id=_id,
name=name,
short_name=short_name,
description=description,
company_id=company_id
)
def reverse_initial_data(apps, schema_editor):
ContainerKindModel = apps.get_model('common', 'ContainerKindModel')
ContainerTypeModel = apps.get_model('common', 'ContainerTypeModel')
CompanyModel = apps.get_model('common', 'CompanyModel')
LinesModel = apps.get_model('common', 'LinesModel')
ContainerKindModel.objects.all().delete()
ContainerTypeModel.objects.all().delete()
CompanyModel.objects.all().delete()
LinesModel.objects.all().delete()
class Migration(migrations.Migration):
dependencies = [
('common', '0003_auto_20250725_1920'), # Adjust this to your last migration
]
operations = [
migrations.RunPython(create_initial_data, reverse_initial_data),
]

@ -5,7 +5,7 @@ class NomenclatureBaseModel(models.Model):
name = models.CharField(max_length=100, unique=True) name = models.CharField(max_length=100, unique=True)
short_name = models.CharField(max_length=5, null=True, blank=True) short_name = models.CharField(max_length=5, null=True, blank=True)
description = models.TextField(blank=True, null=True) description = models.TextField(blank=True, null=True)
active = models.BooleanField(default=True)
class Meta: class Meta:
abstract = True abstract = True
ordering = ['name'] ordering = ['name']

@ -43,7 +43,16 @@ class EmployeeCompanyListView(LoginRequiredMixin, UserPassesTestMixin, ListView)
context['base_template'] = self.base_template context['base_template'] = self.base_template
return context return context
def get_queryset(self):
queryset = super().get_queryset()
data_filter = self.request.GET.get('filter')
if data_filter != 'all':
queryset = queryset.filter(active=True)
queryset = queryset.order_by('name')
return queryset
class EmployeeCompanyCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView): class EmployeeCompanyCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
model = CompanyModel model = CompanyModel
@ -90,7 +99,16 @@ class EmployeeLineListView(LoginRequiredMixin, UserPassesTestMixin, ListView):
context['base_template'] = self.base_template context['base_template'] = self.base_template
return context return context
def get_queryset(self):
queryset = super().get_queryset()
data_filter = self.request.GET.get('filter')
if data_filter != 'all':
queryset = queryset.filter(active=True)
queryset = queryset.order_by('name')
return queryset
class EmployeeLineCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView): class EmployeeLineCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
model = LinesModel model = LinesModel

@ -20,7 +20,14 @@ class ContainersListView(ListView):
return context return context
def get_queryset(self): def get_queryset(self):
return Container.objects.filter(expedited=False).order_by('-received_on') queryset = super().get_queryset()
data_filter = self.request.GET.get('filter')
if data_filter != 'all':
queryset = queryset.filter(expedited=False)
queryset = queryset.order_by('-received_on')
return queryset
class ReportContainersUnpaidListView(ListView): class ReportContainersUnpaidListView(ListView):

@ -0,0 +1,84 @@
version: '3.8'
services:
database:
image: postgres
environment:
- POSTGRES_DB=depot # Matches DB_NAME in production.env
- POSTGRES_USER=postgres # Matches DB_USER in production.env
- POSTGRES_PASSWORD=admin # Matches DB_PASSWORD in production.env
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d depot"] # Check specific database
interval: 5s
timeout: 5s
retries: 5
networks:
- app-network
web:
build: .
ports:
- "8000:8000"
env_file:
- production.env
depends_on:
database:
condition: service_healthy
networks:
- app-network
command: >
bash -c "python manage.py migrate &&
python manage.py runserver 0.0.0.0:8000"
minio:
image: minio/minio:latest
ports:
- "9000:9000" # API Port
- "9001:9001" # Console Port
environment:
MINIO_ROOT_USER: kikimor # Change this
MINIO_ROOT_PASSWORD: shushunka1
MINIO_SERVER_URL: http://localhost:9000
MINIO_ADDRESS: "0.0.0.0:9000"
MINIO_BROWSER_REDIRECT_URL: "http://localhost:9001" # Console URL
volumes:
- minio_data:/data
command: server --console-address ":9001" /data
healthcheck:
test: ["CMD", "mc", "ready", "local"]
interval: 30s
timeout: 20s
retries: 3
networks:
- app-network
# Optional: Create buckets and users on startup
createbuckets:
image: minio/mc
depends_on:
- minio
entrypoint: >
/bin/sh -c "
sleep 10;
mc alias set myminio http://minio:9000 kikimor shushunka1;
mc mb myminio/damages;
mc anonymous set download myminio/damages;
mc policy set public myminio/damages;
echo '{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetObject\"],\"Resource\":[\"arn:aws:s3:::damages/*\"]}]}' > /tmp/policy.json;
mc admin policy add myminio getonly /tmp/policy.json;
mc admin policy set myminio getonly user=kikimor;
exit 0;
"
networks:
- app-network
volumes:
postgres_data:
minio_data:
networks:
app-network:
driver: bridge

@ -0,0 +1,53 @@
from django.db import migrations
from decimal import Decimal
def create_tariffs(apps, schema_editor):
ContainerTariffPeriod = apps.get_model('payments', 'ContainerTariffPeriod')
AdditionalFees = apps.get_model('payments', 'AdditionalFees')
tariffs_20 = [
('20', 1, 3, Decimal('5.00')),
('20', 4, 7, Decimal('10.00')),
('20', 8, 15, Decimal('15.00')),
('20', 16, None, Decimal('20.00')),
]
tariffs_40 = [
('40', 1, 3, Decimal('10.00')),
('40', 4, 7, Decimal('15.00')),
('40', 8, 15, Decimal('20.00')),
('40', 16, None, Decimal('25.00')),
]
for container_size, from_days, to_days, daily_rate in tariffs_20 + tariffs_40:
ContainerTariffPeriod.objects.create(
container_size=container_size,
from_days=from_days,
to_days=to_days,
daily_rate=daily_rate
)
AdditionalFees.objects.create(
reefer_daily_supplement=Decimal('3.00'),
sweeping_fee=Decimal('35.00'),
fumigation_fee=Decimal('75.00')
)
def reverse_tariffs(apps, schema_editor):
ContainerTariffPeriod = apps.get_model('payments', 'ContainerTariffPeriod')
AdditionalFees = apps.get_model('payments', 'AdditionalFees')
ContainerTariffPeriod.objects.all().delete()
AdditionalFees.objects.all().delete()
class Migration(migrations.Migration):
dependencies = [
('payments', '0003_auto_20250725_1920'), # Adjust this to your last migration
]
operations = [
migrations.RunPython(create_tariffs, reverse_tariffs),
]

@ -17,4 +17,17 @@ class EmployeePreinfoView(LoginRequiredMixin, UserPassesTestMixin, ListView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context['base_template'] = self.base_template context['base_template'] = self.base_template
return context return context
def get_queryset(self):
queryset = super().get_queryset()
data_filter = self.request.GET.get('filter')
if data_filter == 'all':
queryset = queryset.filter(deleted=False)
else:
queryset = queryset.filter(received=False,deleted=False)
queryset = queryset.order_by('-created_on')
return queryset

@ -81,30 +81,30 @@ document.addEventListener('DOMContentLoaded', function() {
deleteModal.style.display = 'none'; deleteModal.style.display = 'none';
}); });
confirmDelete.addEventListener('click', function() { confirmDelete.addEventListener('click', function() {
if (selectedId) { if (selectedId) {
const deleteUrl = deleteBtn.dataset.url.replace('0', selectedId); const deleteUrl = deleteBtn.dataset.url.replace('0', selectedId);
fetch(deleteUrl, { fetch(deleteUrl, {
method: 'POST', method: 'POST',
headers: { headers: {
'X-CSRFToken': getCookie('csrftoken') 'X-CSRFToken': getCookie('csrftoken')
}, },
}) })
.then(response => { .then(response => {
if (response.ok) { if (response.ok) {
window.location.reload(); // This reloads the page after success window.location.reload(); // This reloads the page after success
} else { } else {
alert('Error deleting item');
}
})
.catch(error => {
console.error('Error:', error);
alert('Error deleting item'); alert('Error deleting item');
} });
}) }
.catch(error => { deleteModal.style.display = 'none';
console.error('Error:', error); });
alert('Error deleting item');
});
}
deleteModal.style.display = 'none';
});
window.addEventListener('click', function(event) { window.addEventListener('click', function(event) {
if (event.target === deleteModal) { if (event.target === deleteModal) {
@ -126,4 +126,45 @@ confirmDelete.addEventListener('click', function() {
} }
return cookieValue; return cookieValue;
} }
const filterInput = document.getElementById('filterInput');
const activeBtn = document.getElementById('activeBtn');
const allBtn = document.getElementById('allBtn');
const filterForm = document.getElementById('filterForm');
if (activeBtn && allBtn && filterInput && filterForm) {
// Read filter from cookie if present
const filterCookie = getCookie('list_filter');
if (filterCookie && !filterInput.value) {
filterInput.value = filterCookie;
}
function updateButtons() {
if (filterInput.value === 'all') {
allBtn.classList.add('active');
activeBtn.classList.remove('active');
} else {
activeBtn.classList.add('active');
allBtn.classList.remove('active');
}
}
updateButtons();
activeBtn.addEventListener('click', function() {
filterInput.value = 'active';
document.cookie = 'list_filter=active;path=/';
updateButtons();
filterForm.submit();
});
allBtn.addEventListener('click', function() {
filterInput.value = 'all';
document.cookie = 'list_filter=all;path=/';
updateButtons();
filterForm.submit();
});
}
}); });

@ -101,6 +101,13 @@ button.btn-secondary:hover{
background-color: #EDDECB; background-color: #EDDECB;
} }
.btn.active {
background-color: #0d6efd;
color: #fff;
border-color: #0d6efd;
}
/* Error messages */ /* Error messages */
.errorlist { .errorlist {
color: #dc3545; color: #dc3545;
@ -340,4 +347,9 @@ button.btn-secondary:hover{
box-shadow: none !important; box-shadow: none !important;
border: none !important; border: none !important;
} }
}
#filterForm {
border: none !important;
margin: 0 !important;
padding: 0 !important;
} }

@ -1,4 +1,4 @@
{% extends 'client-base.html' %} {% extends 'common/base.html' %}
{% block content %} {% block content %}
<div id="preinfoContent" class="tab-content active"> <div id="preinfoContent" class="tab-content active">

@ -1,4 +1,4 @@
{% extends 'client-base.html' %} {% extends 'common/base.html' %}
{% block content %} {% block content %}
{# <div id="dashboardContent" class="tab-content active">#} {# <div id="dashboardContent" class="tab-content active">#}

@ -1,4 +1,4 @@
{% extends 'client-base.html' %} {% extends 'common/base.html' %}
{% block content %} {% block content %}
<div id="ordersContent" class="tab-content"> <div id="ordersContent" class="tab-content">
<div class="bg-white rounded-lg shadow"> <div class="bg-white rounded-lg shadow">

@ -1,4 +1,4 @@
{% extends 'client-base.html' %} {% extends 'common/base.html' %}
{% block content %} {% block content %}
<div id="preinfoContent" class="tab-content active"> <div id="preinfoContent" class="tab-content active">

@ -1,4 +1,4 @@
{% extends 'client-base.html' %} {% extends 'common/base.html' %}
{% load static %} {% load static %}
{% block content %} {% block content %}

@ -1,4 +1,4 @@
{% extends 'client-base.html' %} {% extends 'common/base.html' %}
{% load static %} {% load static %}
{% block content %} {% block content %}

@ -1,4 +1,4 @@
{% extends 'client-base.html' %} {% extends 'common/base.html' %}
{% load static %} {% load static %}
{% block content %} {% block content %}

@ -1,4 +1,4 @@
{% extends 'client-base.html' %} {% extends 'common/base.html' %}
{% load static %} {% load static %}
{% block content %} {% block content %}

@ -1,4 +1,4 @@
{% extends 'client-base.html' %} {% extends 'common/base.html' %}
{% load static %} {% load static %}
{% block content %} {% block content %}

@ -1,4 +1,4 @@
{% extends 'client-base.html' %} {% extends 'common/base.html' %}
{% load static %} {% load static %}
{% block content %} {% block content %}

@ -17,6 +17,11 @@
<body> <body>
<aside class="sidebar"> <aside class="sidebar">
{% block aside %} {% block aside %}
{% if user.user_type == 'AD' or user.user_type == 'EM' %}
{% include 'employee-sidebar.html' %}
{% elif user.user_type == 'CL' or user.user_type == 'CA' %}
{% include 'client-sidebar.html' %}
{% endif %}
{% endblock aside %} {% endblock aside %}
</aside> </aside>

@ -1,4 +1,4 @@
{% extends 'employee-base.html' %} {% extends 'common/base.html' %}
{% block content %} {% block content %}
<div class="dashboard-wrapper"> <div class="dashboard-wrapper">

@ -2,6 +2,14 @@
{% load custom_filters %} {% load custom_filters %}
{% load static %} {% load static %}
{% block filter %}
<form id="filterForm" method="get" style="display: inline;">
<input type="hidden" name="filter" id="filterInput" value="{{ request.GET.filter|default:'active' }}">
<button type="button" class="btn btn-primary" id="activeBtn">Active</button>
<button type="button" class="btn btn-primary" id="allBtn">All</button>
</form>
{% endblock filter %}
{% block table_header %} {% block table_header %}
<th style="display: none;">Select</th> <th style="display: none;">Select</th>
<th>Line</th> <th>Line</th>

@ -1,4 +1,4 @@
{% extends 'employee-base.html' %} {% extends 'common/base.html' %}
{% load static %} {% load static %}
{% block content %} {% block content %}

@ -1,6 +1,14 @@
{% extends 'list-crud.html' %} {% extends 'list-crud.html' %}
{% load static %} {% load static %}
{% block filter %}
<form id="filterForm" method="get" style="display: inline;">
<input type="hidden" name="filter" id="filterInput" value="{{ request.GET.filter|default:'active' }}">
<button type="button" class="btn btn-primary" id="activeBtn">Active</button>
<button type="button" class="btn btn-primary" id="allBtn">All</button>
</form>
{% endblock filter %}
{% block table_header %} {% block table_header %}
<th style="display: none;">Select</th> <th style="display: none;">Select</th>
<th>Company name</th> <th>Company name</th>

@ -1,4 +1,4 @@
{% extends 'employee-base.html' %} {% extends 'common/base.html' %}
{% load static %} {% load static %}
{% block content %} {% block content %}

@ -1,6 +1,14 @@
{% extends 'list-crud.html' %} {% extends 'list-crud.html' %}
{% load static %} {% load static %}
{% block filter %}
<form id="filterForm" method="get" style="display: inline;">
<input type="hidden" name="filter" id="filterInput" value="{{ request.GET.filter|default:'active' }}">
<button type="button" class="btn btn-primary" id="activeBtn">Active</button>
<button type="button" class="btn btn-primary" id="allBtn">All</button>
</form>
{% endblock filter %}
{% block table_header %} {% block table_header %}
<th>Container №</th> <th>Container №</th>
<th>Container type</th> <th>Container type</th>

@ -1,4 +1,4 @@
{% extends 'employee-base.html' %} {% extends 'common/base.html' %}
{% load static %} {% load static %}
{% block content %} {% block content %}

@ -1,6 +1,14 @@
{% extends 'list-crud.html' %} {% extends 'list-crud.html' %}
{% load static %} {% load static %}
{% block filter %}
<form id="filterForm" method="get" style="display: inline;">
<input type="hidden" name="filter" id="filterInput" value="{{ request.GET.filter|default:'active' }}">
<button type="button" class="btn btn-primary" id="activeBtn">Active</button>
<button type="button" class="btn btn-primary" id="allBtn">All</button>
</form>
{% endblock filter %}
{% block table_header %} {% block table_header %}
<th style="display: none;">Select</th> <th style="display: none;">Select</th>
<th>Company</th> <th>Company</th>

@ -1,4 +1,4 @@
{% extends 'employee-base.html' %} {% extends 'common/base.html' %}
{% load static %} {% load static %}
{% block content %} {% block content %}

@ -1,4 +1,4 @@
{% extends "employee-base.html" %} {% extends 'common/base.html' %}
{% block content %} {% block content %}
<form method="POST"> <form method="POST">

@ -1,6 +1,14 @@
{% extends 'list-crud.html' %} {% extends 'list-crud.html' %}
{% load static %} {% load static %}
{% block filter %}
<form id="filterForm" method="get" style="display: inline;">
<input type="hidden" name="filter" id="filterInput" value="{{ request.GET.filter|default:'active' }}">
<button type="button" class="btn btn-primary" id="activeBtn">Active</button>
<button type="button" class="btn btn-primary" id="allBtn">All</button>
</form>
{% endblock filter %}
{% block table_header %} {% block table_header %}
<th style="display: none;">Select</th> <th style="display: none;">Select</th>
<th>Preinfo №</th> <th>Preinfo №</th>

@ -1,4 +1,4 @@
{% extends base_template %} {% extends 'common/base.html' %}
{% load static %} {% load static %}
{% block content %} {% block content %}

@ -0,0 +1,10 @@
{% extends 'common/base.html' %}
{% block content %}
<h2>Change Password</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Change Password</button>
</form>
{% endblock %}

@ -1,4 +1,4 @@
{% extends 'employee-base.html' %} {% extends 'common/base.html' %}
{% block content %} {% block content %}
<form method="post"> <form method="post">

@ -1,6 +1,15 @@
{% extends 'list-crud.html' %} {% extends 'list-crud.html' %}
{% load static %} {% load static %}
{% block filter %}
<form id="filterForm" method="get" style="display: inline;">
<input type="hidden" name="filter" id="filterInput" value="{{ request.GET.filter|default:'active' }}">
<button type="button" class="btn btn-primary" id="activeBtn">Active</button>
<button type="button" class="btn btn-primary" id="allBtn">All</button>
</form>
{% endblock filter %}
{% block table_header %} {% block table_header %}
<th>Username</th> <th>Username</th>
<th>User Type</th> <th>User Type</th>

Loading…
Cancel
Save