master
kikimor 8 months ago
parent f6c78a20a3
commit 0ffd79cee9

@ -6,51 +6,50 @@
<component name="ChangeListManager"> <component name="ChangeListManager">
<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 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/mixins/LineFiltweFormMixin.py" beforeDir="false" afterPath="$PROJECT_DIR$/DepoT/mixins/LineFiltweFormMixin.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/DepoT/settings.py" beforeDir="false" afterPath="$PROJECT_DIR$/DepoT/settings.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DepoT/mixins/crudListViewMixin.py" beforeDir="false" afterPath="$PROJECT_DIR$/DepoT/mixins/crudListViewMixin.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/DepoT/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/DepoT/urls.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/accounts/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/accounts/models.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/forms.py" beforeDir="false" afterPath="$PROJECT_DIR$/booking/forms.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/client_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/booking/views/client_views.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$/booking/views/employee_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/booking/views/employee_views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/forms/company.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/forms/company.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/forms/line.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/forms/line.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/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/urls.py" 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/utils/utils.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/utils/utils.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/views/barrier_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/views/barrier_views.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/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$/common/views/employee_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/views/employee_views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/views/shared_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/views/shared_views.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/containers/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/containers/models.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/services.py" beforeDir="false" afterPath="$PROJECT_DIR$/containers/services.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/containers/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/containers/urls.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/containers/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/containers/urls.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/containers/views/barrier_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/containers/views/barrier_views.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/views/employee_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/containers/views/employee_views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/populate_database.txt" beforeDir="false" afterPath="$PROJECT_DIR$/populate_database.txt" 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$/preinfo/forms.py" beforeDir="false" afterPath="$PROJECT_DIR$/preinfo/forms.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/payments/forms.py" beforeDir="false" afterPath="$PROJECT_DIR$/payments/forms.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/payments/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/payments/models.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/payments/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/payments/urls.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/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/preinfo/urls.py" 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$/preinfo/views/employee_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/preinfo/views/employee_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$/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/base.css" beforeDir="false" afterPath="$PROJECT_DIR$/static/styles/base.css" afterDir="false" />
<change beforePath="$PROJECT_DIR$/static/styles/dashboard-content.css" beforeDir="false" afterPath="$PROJECT_DIR$/static/styles/dashboard-content.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$/static/styles/forms.css" beforeDir="false" afterPath="$PROJECT_DIR$/static/styles/forms.css" afterDir="false" />
<change beforePath="$PROJECT_DIR$/static/styles/sidebar.css" beforeDir="false" afterPath="$PROJECT_DIR$/static/styles/sidebar.css" afterDir="false" /> <change beforePath="$PROJECT_DIR$/static/styles/sidebar.css" beforeDir="false" afterPath="$PROJECT_DIR$/static/styles/sidebar.css" afterDir="false" />
<change beforePath="$PROJECT_DIR$/static/styles/styles.css" beforeDir="false" afterPath="$PROJECT_DIR$/static/styles/styles.css" afterDir="false" />
<change beforePath="$PROJECT_DIR$/static/styles/tables.css" beforeDir="false" afterPath="$PROJECT_DIR$/static/styles/tables.css" afterDir="false" /> <change beforePath="$PROJECT_DIR$/static/styles/tables.css" beforeDir="false" afterPath="$PROJECT_DIR$/static/styles/tables.css" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/barrier/barrier-base.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/barrier/barrier-base.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/barrier/barrier-dashboard.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/barrier/barrier-dashboard.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/chatgpt/round table.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/chatgpt/round table.html" 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-base.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client-base.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-sidebar.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client-sidebar.html" afterDir="false" /> <change beforePath="$PROJECT_DIR$/templates/client-sidebar.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client-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/booking-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client/booking-list.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/preinfo-create.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client/preinfo-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-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client/preinfo-list.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/container-expedition.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/container-expedition.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/container-receive.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/container-receive.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/employee/booking-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/booking-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/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-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/payment-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/payment-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/employee/preinfo-list.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/employee/preinfo-list.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/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" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -65,9 +64,9 @@
<option name="RECENT_TEMPLATES"> <option name="RECENT_TEMPLATES">
<list> <list>
<option value="JavaScript File" /> <option value="JavaScript File" />
<option value="Python Script" />
<option value="HTML File" />
<option value="CSS File" /> <option value="CSS File" />
<option value="HTML File" />
<option value="Python Script" />
</list> </list>
</option> </option>
</component> </component>
@ -89,10 +88,11 @@
"RunOnceActivity.OpenDjangoStructureViewOnStart": "true", "RunOnceActivity.OpenDjangoStructureViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true", "RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.git.unshallow": "true", "RunOnceActivity.git.unshallow": "true",
"RunOnceActivity.pycharm.django.structure.promotion.once.per.project": "true",
"django.template.preview.state": "SHOW_EDITOR_AND_PREVIEW", "django.template.preview.state": "SHOW_EDITOR_AND_PREVIEW",
"git-widget-placeholder": "master", "git-widget-placeholder": "master",
"ignore.virus.scanning.warn.message": "true", "ignore.virus.scanning.warn.message": "true",
"last_opened_file_path": "C:/dev_projects/python/Django/DepoT/templates/client", "last_opened_file_path": "C:/dev_projects/python/Django/DepoT/templates/employee",
"list.type.of.created.stylesheet": "CSS", "list.type.of.created.stylesheet": "CSS",
"node.js.detected.package.eslint": "true", "node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true", "node.js.detected.package.tslint": "true",
@ -109,17 +109,18 @@
}]]></component> }]]></component>
<component name="RecentsManager"> <component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS"> <key name="CopyFile.RECENT_KEYS">
<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\client" />
<recent name="C:\dev_projects\python\Django\DepoT\templates" /> <recent name="C:\dev_projects\python\Django\DepoT\templates" />
<recent name="C:\dev_projects\python\Django\DepoT\templates\registration" /> <recent name="C:\dev_projects\python\Django\DepoT\templates\registration" />
<recent name="C:\dev_projects\python\Django\DepoT\static\styles" /> <recent name="C:\dev_projects\python\Django\DepoT\static\styles" />
</key> </key>
<key name="MoveFile.RECENT_KEYS"> <key name="MoveFile.RECENT_KEYS">
<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\common\views" />
<recent name="C:\dev_projects\python\Django\DepoT\booking\views" /> <recent name="C:\dev_projects\python\Django\DepoT\booking\views" />
<recent name="C:\dev_projects\python\Django\DepoT\containers\views" /> <recent name="C:\dev_projects\python\Django\DepoT\containers\views" />
<recent name="C:\dev_projects\python\Django\DepoT\preinfo\views" />
<recent name="C:\dev_projects\python\Django\DepoT\templates\barrier" />
</key> </key>
</component> </component>
<component name="RunManager"> <component name="RunManager">
@ -167,7 +168,7 @@
<updated>1750784740296</updated> <updated>1750784740296</updated>
<workItem from="1750784741367" duration="240087000" /> <workItem from="1750784741367" duration="240087000" />
<workItem from="1752078951079" duration="106000" /> <workItem from="1752078951079" duration="106000" />
<workItem from="1752079161329" duration="40180000" /> <workItem from="1752079161329" duration="97669000" />
</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" />
@ -282,16 +283,36 @@
<component name="XDebuggerManager"> <component name="XDebuggerManager">
<breakpoint-manager> <breakpoint-manager>
<breakpoints> <breakpoints>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/containers/views/employee_views.py</url>
<line>110</line>
<option name="timeStamp" value="31" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line"> <line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/DepoT/mixins/crudListViewMixin.py</url> <url>file://$PROJECT_DIR$/DepoT/mixins/crudListViewMixin.py</url>
<line>7</line> <line>7</line>
<option name="timeStamp" value="55" /> <option name="timeStamp" value="55" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/common/views/client_views.py</url>
<line>118</line>
<option name="timeStamp" value="61" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/damages_api/views.py</url>
<line>15</line>
<option name="timeStamp" value="62" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/damages_api/views.py</url>
<line>39</line>
<option name="timeStamp" value="63" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/common/utils/owncloud_utls.py</url>
<line>29</line>
<option name="timeStamp" value="64" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/payments/views.py</url>
<line>40</line>
<option name="timeStamp" value="65" />
</line-breakpoint>
</breakpoints> </breakpoints>
<default-breakpoints> <default-breakpoints>
<breakpoint type="python-exception"> <breakpoint type="python-exception">

@ -25,7 +25,7 @@ SECRET_KEY = "django-insecure-g%187p84o9^rr)3#9@r3n^o2v1i%@6=+puxm7hlodg+kbsk%n#
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
ALLOWED_HOSTS = [] ALLOWED_HOSTS = ['192.168.24.43', '127.0.0.1', 'localhost', ]
# Application definition # Application definition
@ -36,6 +36,7 @@ PROJECT_APPS = [
"common", "common",
"containers", "containers",
'preinfo', 'preinfo',
'payments',
] ]
@ -46,6 +47,8 @@ INSTALLED_APPS = [
"django.contrib.sessions", "django.contrib.sessions",
"django.contrib.messages", "django.contrib.messages",
"django.contrib.staticfiles", "django.contrib.staticfiles",
"rest_framework",
"damages_api",
] + PROJECT_APPS ] + PROJECT_APPS
MIDDLEWARE = [ MIDDLEWARE = [
@ -147,7 +150,19 @@ STATIC_URL = "static/"
STATICFILES_DIRS = [ STATICFILES_DIRS = [
BASE_DIR / 'static' BASE_DIR / 'static'
] ]
TEMP_FILE_FOLDER = "/tmp/damages_photos"
# Default primary key field type # Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
import environ
env = environ.Env()
import os
environ.Env.read_env(os.path.join(BASE_DIR, '.env'))
OWNCLOUD_URL = env('OWNCLOUD_URL')
OWNCLOUD_USER = env('OWNCLOUD_USER')
OWNCLOUD_PASSWORD = env('OWNCLOUD_PASSWORD')
OWNCLOUD_DAMAGES_FOLDER = env('OWNCLOUD_DAMAGES_FOLDER')

@ -25,4 +25,6 @@ urlpatterns = [
path('preinfo/', include('preinfo.urls')), path('preinfo/', include('preinfo.urls')),
path('container/', include('containers.urls')), path('container/', include('containers.urls')),
path('booking/', include('booking.urls')), path('booking/', include('booking.urls')),
path('payment/', include('payments.urls')),
path('damages/', include('damages_api.urls')),
] ]

@ -1,9 +1,13 @@
from django.urls import path from django.urls import path, include
from django.contrib.auth import views as auth_views 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('login/', views.DepotLoginView.as_view(), name='login'),
path('relogin/', auth_views.logout_then_login, name='relogin'), path('relogin/', auth_views.logout_then_login, name='relogin'),
path('register/', views.RegisterView.as_view(), name='register'), path('user/', include([
path('', views.UserListView.as_view(), name='user_list'),
path('register/', views.RegisterView.as_view(), name='user_register'),
path('<int:pk>/update/', views.UserUpdateView.as_view(), name='user_update'),
])),
] ]

@ -86,13 +86,73 @@ class RegisterView(AccessMixin, FormView):
return form return form
class UserListView(ListView): class UserListView(ListView):
template_name = 'registration/register.html' template_name = 'registration/user-list.html'
# form_class = RegisterForm
model = get_user_model() model = get_user_model()
success_url = reverse_lazy('dashboard') context_object_name = 'objects'
paginate_by = 30 # Number of containers per page
base_template = 'employee-base.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['base_template'] = self.base_template
return context
class UserEditView(UpdateView): class UserUpdateView(UpdateView):
template_name = 'registration/register.html' template_name = 'registration/register.html'
form_class = RegisterForm form_class = RegisterForm
model = get_user_model() model = get_user_model()
success_url = reverse_lazy('dashboard') success_url = reverse_lazy('user_list')
def dispatch(self, request, *args, **kwargs):
user: DepotUser = request.user
if not (user.is_superuser or user.user_type == DepotUser.UserType.COMPANY_ADMIN):
return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs)
def form_valid(self, form):
user = form.save(commit=False)
user_type = form.cleaned_data['user_type']
user.save()
# Clear irrelevant permissions based on user type
if user_type == DepotUser.UserType.CLIENT:
user.employee_permissions.clear()
user.company_permissions.set(form.cleaned_data['company_permissions'])
elif user_type == DepotUser.UserType.EMPLOYEE:
user.company_permissions.clear()
user.employee_permissions.set(form.cleaned_data['employee_permissions'])
return super().form_valid(form)
def get_form(self, form_class = None):
form = super().get_form(form_class)
user: DepotUser = self.request.user
if user.is_superuser:
# Superuser can manage all permissions and user types
form.fields['user_type'].widget.attrs['disabled'] = False
form.fields['company_permissions'].widget.attrs['disabled'] = False
form.fields['employee_permissions'].widget.attrs['disabled'] = False
# Show relevant permissions based on selected user type
if form.initial.get('user_type') == DepotUser.UserType.CLIENT:
form.fields['employee_permissions'].widget.attrs['disabled'] = True
elif form.initial.get('user_type') == DepotUser.UserType.EMPLOYEE:
form.fields['company_permissions'].widget.attrs['disabled'] = True
elif user.user_type == DepotUser.UserType.COMPANY_ADMIN:
form.fields['company'].queryset = form.fields['company'].queryset.filter(pk=user.company.pk)
form.fields['company'].initial = user.company
form.fields['company'].widget.readonly = True
form.fields['line'].queryset = form.fields['line'].queryset.filter(company=user.company.pk)
form.fields['user_type'].choices = [
(DepotUser.UserType.CLIENT, 'Client')
]
form.fields['user_type'].initial = DepotUser.UserType.CLIENT
form.fields['company_permissions'].widget.attrs['disabled'] = False
form.fields['employee_permissions'].widget.attrs['disabled'] = True
return form

@ -6,5 +6,11 @@ from booking.models import Booking
class BookingListView(ListView): class BookingListView(ListView):
template_name = 'employee/booking-list.html' template_name = 'employee/booking-list.html'
model = Booking model = Booking
context_object_name = 'bookings' context_object_name = 'objects'
paginate_by = 30 # Number of containers per page paginate_by = 30 # Number of containers per page
base_template = 'employee-base.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['base_template'] = self.base_template
return context

@ -0,0 +1,17 @@
from django.forms import ModelForm
from common.models import CompanyModel
class CompanyBaseForm(ModelForm):
class Meta:
model = CompanyModel
fields = '__all__'
class CompanyCreateForm(CompanyBaseForm):
...
class CompanyUpdateForm(CompanyBaseForm):
...

@ -0,0 +1,17 @@
from django.forms import ModelForm
from common.models import LinesModel
class LineBaseForm(ModelForm):
class Meta:
model = LinesModel
fields = '__all__'
class LineCreateForm(LineBaseForm):
...
class LineUpdateForm(LineBaseForm):
...

@ -1,14 +1,36 @@
from django.urls import path, include from django.urls import path, include
from common.views.barrier_views import BarrierDashboardView from common.views.barrier_views import BarrierDashboardView
from common.views.employee_views import EmployeeDashboardView from common.views.employee_views import EmployeeDashboardView, EmployeeCompanyListView, EmployeeCompanyCreateView, \
from common.views.client_views import ClientDashboardView EmployeeCompanyUpdateView, EmployeeLineListView, EmployeeLineCreateView, EmployeeLineUpdateView
from common.views.client_views import ClientDashboardView, ClientCompanyListView, ClientCompanyCreateView, \
ClientCompanyUpdateView, ClientLineListView, ClientLineCreateView, ClientLineUpdateView
from common.views.shared_views import IndexView, DashboardRedirectView from common.views.shared_views import IndexView, DashboardRedirectView
urlpatterns = [ urlpatterns = [
path('', IndexView.as_view(), name='index'), path('', IndexView.as_view(), name='index'),
path('dashboard/', include([ path('dashboard/', include([
path('', DashboardRedirectView.as_view(), name='dashboard'), path('', DashboardRedirectView.as_view(), name='dashboard'),
path('client/', ClientDashboardView.as_view(), name='client_dashboard'), path('client/', ClientDashboardView.as_view(), name='client_dashboard'),
path('barrier/', BarrierDashboardView.as_view(), name='barrier_dashboard'), path('barrier/', BarrierDashboardView.as_view(), name='barrier_dashboard'),
path('employee/', EmployeeDashboardView.as_view(), name='employee_dashboard'), path('employee/', EmployeeDashboardView.as_view(), name='employee_dashboard'),
])) ])),
path('client/company/', include([
path('', ClientCompanyListView.as_view(), name='client_company'),
path('create/', ClientCompanyCreateView.as_view(), name='client_company_create'),
path('<int:pk>/edit/', ClientCompanyUpdateView.as_view(), name='client_company_edit'),
])),
path('client/line/', include([
path('', ClientLineListView.as_view(), name='client_line'),
path('create/', ClientLineCreateView.as_view(), name='client_line_create'),
path('<int:pk>/edit/', ClientLineUpdateView.as_view(), name='client_line_update'),
])),
path('employee/company/', include([
path('', EmployeeCompanyListView.as_view(), name='employee_company'),
path('create/', EmployeeCompanyCreateView.as_view(), name='employee_company_create'),
path('<int:pk>/edit/', EmployeeCompanyUpdateView.as_view(), name='employee_company_update'),
])),
path('employee/line/', include([
path('', EmployeeLineListView.as_view(), name='employee_line'),
path('create/', EmployeeLineCreateView.as_view(), name='employee_line_create'),
path('<int:pk>/edit/', EmployeeLineUpdateView.as_view(), name='employee_line_update'),
])),
] ]

@ -8,7 +8,7 @@ def filter_queryset_by_user(queryset, user):
If the user has a line, it filters by that line. If the user has a line, it filters by that line.
If the user has a company, it filters by all lines associated with that company. If the user has a company, it filters by all lines associated with that company.
""" """
print(f'user: {user}, user company: {user.company}, user line: {user.line}') print(f'user: {user}, user company: {user.company}, user line: {user.line}, user type: {user.user_type}')
if user.line: if user.line:
filtered = queryset.filter(line=user.line) filtered = queryset.filter(line=user.line)
print(f"Filtering by line: {user.line.id}, count: {filtered.count()}") print(f"Filtering by line: {user.line.id}, count: {filtered.count()}")

@ -1,5 +1,13 @@
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.shortcuts import render from django.shortcuts import render
from django.views.generic import TemplateView from django.urls import reverse_lazy
from django.views.generic import TemplateView, ListView, CreateView, UpdateView
from DepoT.mixins.LineFiltweFormMixin import LineFilterFormMixin
from common.forms.company import CompanyCreateForm, CompanyUpdateForm
from common.forms.line import LineCreateForm, LineUpdateForm
from common.models import CompanyModel, LinesModel
from common.utils.utils import filter_queryset_by_user
class ClientDashboardView(TemplateView): class ClientDashboardView(TemplateView):
@ -10,4 +18,123 @@ class ClientDashboardView(TemplateView):
} }
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
return render(request, self.template_name, self.extra_context) return render(request, self.template_name, self.extra_context)
class ClientCompanyListView(LoginRequiredMixin, UserPassesTestMixin, ListView):
model = CompanyModel
template_name = 'common/../../templates/employee/company-list.html'
context_object_name = 'objects'
paginate_by = 3
base_template = 'client-base.html'
def test_func(self):
return True # self.request.user.has_employee_perm('can_view_preinfo') or self.request.user.user_type == 'CA'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['base_template'] = self.base_template
return context
def get_queryset(self):
queryset = super().get_queryset()
user = self.request.user
result = filter_queryset_by_user(queryset, user)
return result
class ClientCompanyCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
model = CompanyModel
template_name = 'common/../../templates/employee/company-create.html'
form_class = CompanyCreateForm
success_url = reverse_lazy('client-company')
def test_func(self):
return True # self.request.user.has_company_perm('can_create_preinfo') or self.request.user.user_type == 'CA'
# def form_valid(self, form):
# form.instance.created_by = self.request.user
# form.instance.updated_by = self.request.user
# return super().form_valid(form)
class ClientCompanyUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = CompanyModel
template_name = 'common/../../templates/employee/company-update.html'
form_class = CompanyUpdateForm
success_url = reverse_lazy('client-company')
def test_func(self):
return True # self.request.user.ha.s_company_perm('can_edit_preinfo') or self.request.user.user_type == 'CA'
# def form_valid(self, form):
# form.instance.updated_by = self.request.user
# return super().form_valid(form)
class ClientLineListView(LoginRequiredMixin, UserPassesTestMixin, ListView):
model = LinesModel
template_name = 'client/line-list.html'
context_object_name = 'objects'
paginate_by = 3
base_template = 'client-base.html'
def test_func(self):
return True # self.request.user.has_employee_perm('can_view_preinfo') or self.request.user.user_type == 'CA'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['base_template'] = self.base_template
return context
def get_queryset(self):
queryset = super().get_queryset()
user = self.request.user
result = queryset.filter(company=user.company)
return result
class ClientLineCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
model = LinesModel
template_name = 'client/line-create.html'
form_class = LineCreateForm
success_url = reverse_lazy('client-line')
def test_func(self):
return True # self.request.user.has_company_perm('can_create_preinfo') or self.request.user.user_type == 'CA'
def get_form(self, form_class=None):
form = super().get_form(form_class)
form.fields['company'].queryset = CompanyModel.objects.filter(id=self.request.user.company.id)
form.fields['company'].initial = self.request.user.company.id
return form
def form_valid(self, form):
# todo more validation
form.instance.company = self.request.user.company
return super().form_valid(form)
class ClientLineUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = LinesModel
template_name = 'client/line-update.html'
form_class = LineUpdateForm
success_url = reverse_lazy('client-company')
def test_func(self):
return True # self.request.user.ha.s_company_perm('can_edit_preinfo') or self.request.user.user_type == 'CA'
def get_form(self, form_class=None):
form = super().get_form(form_class)
form.fields['company'].queryset = CompanyModel.objects.filter(id=self.request.user.company.id)
form.fields['company'].initial = self.request.user.company.id
return form
def form_valid(self, form):
# todo more validation
form.instance.company = self.request.user.company
return super().form_valid(form)

@ -1,6 +1,11 @@
from django.views.generic import TemplateView from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.urls import reverse_lazy
from django.views.generic import TemplateView, ListView, CreateView, UpdateView
from booking.models import Booking from booking.models import Booking
from common.forms.company import CompanyCreateForm, CompanyUpdateForm
from common.forms.line import LineCreateForm, LineUpdateForm
from common.models import CompanyModel, LinesModel
from containers.models import Container from containers.models import Container
from preinfo.models import Preinfo from preinfo.models import Preinfo
@ -20,4 +25,98 @@ class EmployeeDashboardView(TemplateView):
context['containers'] = containers context['containers'] = containers
context['preinfos'] = preinfos context['preinfos'] = preinfos
context['bookings'] = bookings context['bookings'] = bookings
return context return context
class EmployeeCompanyListView(LoginRequiredMixin, UserPassesTestMixin, ListView):
model = CompanyModel
template_name = 'common/../../templates/employee/company-list.html'
context_object_name = 'objects'
paginate_by = 3
base_template = 'employee-base.html'
def test_func(self):
return True # self.request.user.has_employee_perm('can_view_preinfo') or self.request.user.user_type == 'CA'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['base_template'] = self.base_template
return context
class EmployeeCompanyCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
model = CompanyModel
template_name = 'common/../../templates/employee/company-create.html'
form_class = CompanyCreateForm
success_url = reverse_lazy('employee_company')
def test_func(self):
return True # self.request.user.has_company_perm('can_create_preinfo') or self.request.user.user_type == 'CA'
# def form_valid(self, form):
# form.instance.created_by = self.request.user
# form.instance.updated_by = self.request.user
# return super().form_valid(form)
class EmployeeCompanyUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = CompanyModel
template_name = 'common/../../templates/employee/company-update.html'
form_class = CompanyUpdateForm
success_url = reverse_lazy('employee_company')
def test_func(self):
return True # self.request.user.ha.s_company_perm('can_edit_preinfo') or self.request.user.user_type == 'CA'
# def form_valid(self, form):
# form.instance.updated_by = self.request.user
# return super().form_valid(form)
class EmployeeLineListView(LoginRequiredMixin, UserPassesTestMixin, ListView):
model = LinesModel
template_name = 'employee/line-list.html'
context_object_name = 'objects'
paginate_by = 3
base_template = 'employee-base.html'
def test_func(self):
return True # self.request.user.has_employee_perm('can_view_preinfo') or self.request.user.user_type == 'CA'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['base_template'] = self.base_template
return context
class EmployeeLineCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
model = LinesModel
template_name = 'employee/company-create.html'
form_class = LineCreateForm
success_url = reverse_lazy('employee_line')
def test_func(self):
return True # self.request.user.has_company_perm('can_create_preinfo') or self.request.user.user_type == 'CA'
# def form_valid(self, form):
# form.instance.created_by = self.request.user
# form.instance.updated_by = self.request.user
# return super().form_valid(form)
class EmployeeLineUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = LinesModel
template_name = 'employee/company-update.html'
form_class = LineUpdateForm
success_url = reverse_lazy('employee_line')
def test_func(self):
return True # self.request.user.ha.s_company_perm('can_edit_preinfo') or self.request.user.user_type == 'CA'
# def form_valid(self, form):
# form.instance.updated_by = self.request.user
# return super().form_valid(form)

@ -73,3 +73,17 @@ class ContainerHistory(Container):
on_delete=models.CASCADE, on_delete=models.CASCADE,
related_name='history_containers' related_name='history_containers'
) )
class ContainerPhotos(models.Model):
container = models.ForeignKey(
Container,
on_delete=models.CASCADE,
related_name='photos',
)
photo = models.TextField(blank=True, null=True)
uploaded_on = models.DateTimeField(auto_now_add=True)
uploaded_by = models.ForeignKey(
'accounts.DepotUser',
on_delete=models.CASCADE,
related_name='container_photos_uploaded_by',
)

@ -1,11 +1,12 @@
from django.urls import include, path from django.urls import include, path
from containers.views.employee_views import ContainersListView from containers.views.employee_views import ContainersListView, ReportContainersUnpaidListView
from containers.views.barrier_views import ContainerReceive, ContainerExpedition, ContainerSearchView from containers.views.barrier_views import ContainerReceive, ContainerExpedition, ContainerSearchView
urlpatterns = [ urlpatterns = [
path('search/', ContainerSearchView.as_view(), name='container_search'), path('search/', ContainerSearchView.as_view(), name='container_search'),
path('employee/', ContainersListView.as_view(), name='employee_containers'), path('employee/', ContainersListView.as_view(), name='employee_containers'),
path('not-paid', ReportContainersUnpaidListView.as_view(), name='not_paid'),
path('barrier/<int:pk>/', include([ path('barrier/<int:pk>/', include([
path('receive/', ContainerReceive.as_view(), name='container_receive'), path('receive/', ContainerReceive.as_view(), name='container_receive'),
path('expedition/', ContainerExpedition.as_view(), name='container_expedition'), path('expedition/', ContainerExpedition.as_view(), name='container_expedition'),

@ -1,13 +1,52 @@
from django.views.generic import ListView from django.views.generic import ListView
from common.models import CompanyModel
from containers.models import Container from containers.models import Container
class ContainersListView(ListView): class ContainersListView(ListView):
template_name = 'employee/containers-list.html' template_name = 'employee/containers-list.html'
model = Container model = Container
context_object_name = 'containers' context_object_name = 'objects'
paginate_by = 30 # Number of containers per page paginate_by = 30 # Number of containers per page
base_template = 'employee-base.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['base_template'] = self.base_template
return context
def get_queryset(self): def get_queryset(self):
return Container.objects.filter(expedited=False).order_by('-received_on') return Container.objects.filter(expedited=False).order_by('-received_on')
class ReportContainersUnpaidListView(ListView):
template_name = 'employee/payment-list.html'
model = Container
context_object_name = 'objects'
paginate_by = 30 # Number of payments per page
base_template = 'employee-base.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['base_template'] = self.base_template
context['companies'] = CompanyModel.objects.all().order_by('name')
return context
def get_queryset(self):
queryset = self.model.objects.filter(expedited=True)
# Get date from request parameters
date = self.request.GET.get('date')
if date:
queryset = queryset.filter(expedited_on__date__lte=date)
# Get company from request parameters
company = self.request.GET.get('company')
if company:
queryset = queryset.filter(line__company_id=company)
# Add payment filter to show only unpaid containers
queryset = queryset.filter(payment_containers__isnull=True)
return queryset.order_by('-expedited_on')

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

@ -0,0 +1,6 @@
from django.apps import AppConfig
class DamagesApiConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "damages_api"

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

@ -0,0 +1,7 @@
from django.urls import path
from damages_api.views import Damages
urlpatterns = [
path('<int:depot_id>', Damages.as_view(), name='damages_list'),
]

@ -0,0 +1,43 @@
import base64
import os
import tempfile
from datetime import datetime
from django.core.exceptions import BadRequest
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from common.utils.owncloud_utls import Owncloud
from containers.models import ContainerPhotos
class Damages(APIView):
def post(self, request, depot_id):
data = request.get_json()
photo = data.pop("photo")
extension = data.pop("photo_extension")
with tempfile.NamedTemporaryFile(suffix=f'.{extension}', delete=False) as temp_file:
try:
temp_file.write(base64.b64decode(photo.encode("utf-8")))
temp_file.flush()
own_filename = Owncloud.upload_damage_photo(temp_file.name, depot_id)
container_photo = ContainerPhotos()
container_photo.container.pk = depot_id
container_photo.photo = own_filename
container_photo.uploaded_on = datetime.now()
container_photo.uploaded_by = request.user
container_photo.save()
except Exception as ex:
raise BadRequest("Invalid photo encoding")
finally:
os.unlink(temp_file.name)
return Response(status=status.HTTP_201_CREATED)
def get(self, request, depot_id):
return Owncloud.get_damages(depot_id)

@ -0,0 +1,19 @@
from django.forms import ModelForm, CheckboxSelectMultiple
from containers.models import Container
from payments.models import Payment
class PaymentCreateForm(ModelForm):
class Meta:
model = Payment
fields = ['total_amount', 'company', 'description']
widgets = {
'containers': CheckboxSelectMultiple(),
}
# def __init__(self, *args, **kwargs):
# super().__init__(*args, **kwargs)
# self.fields['containers'].queryset = Container.objects.all()
# self.fields['containers'].label_from_instance = lambda obj: f"{obj.name} ({obj.company.name})"

@ -23,3 +23,28 @@ class PaymentItem(models.Model):
container = models.ForeignKey(Container, related_name='payment_containers', on_delete=models.CASCADE) container = models.ForeignKey(Container, related_name='payment_containers', on_delete=models.CASCADE)
amount = models.DecimalField(max_digits=10, decimal_places=2) amount = models.DecimalField(max_digits=10, decimal_places=2)
class ContainerTariffPeriod(models.Model):
CONTAINER_SIZE_CHOICES = [
('20', '20 feet'),
('40', '40/45 feet'),
]
container_size = models.CharField(max_length=2, choices=CONTAINER_SIZE_CHOICES)
from_days = models.PositiveIntegerField()
to_days = models.PositiveIntegerField(null=True, blank=True) # null for last period (16+ days)
daily_rate = models.DecimalField(max_digits=6, decimal_places=2)
class Meta:
unique_together = ['container_size', 'from_days']
ordering = ['container_size', 'from_days']
class AdditionalFees(models.Model):
reefer_daily_supplement = models.DecimalField(max_digits=6, decimal_places=2, default=3.00)
sweeping_fee = models.DecimalField(max_digits=6, decimal_places=2, default=35.00)
fumigation_fee = models.DecimalField(max_digits=6, decimal_places=2, default=75.00)
class Meta:
verbose_name = 'Additional Fees'
verbose_name_plural = 'Additional Fees'

@ -0,0 +1,7 @@
from django.urls import path
from payments.views import PaymentCreateView
urlpatterns = [
path("create/", PaymentCreateView.as_view(), name="payments_create"),
]

@ -1,3 +1,47 @@
from django.shortcuts import render from django.shortcuts import render
from django.urls import reverse_lazy
from django.views.generic import ListView, CreateView
from common.models import CompanyModel
from containers.models import Container
from payments.forms import PaymentCreateForm
from payments.models import Payment
# Create your views here. # Create your views here.
class PaymentCreateView(CreateView):
model = Payment
form_class = PaymentCreateForm
template_name = 'employee/payment-create.html'
success_url = reverse_lazy('payment-list')
def form_valid(self, form):
container_ids = self.request.POST.getlist('containers')
payment = form.save(commit=False)
payment.save()
payment.containers.set(container_ids)
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
container_ids = self.request.GET.get('containers', '').split(',')
# Filter only valid IDs (non-empty strings that can be converted to int)
container_ids = [int(id) for id in container_ids if id.strip().isdigit()]
if container_ids:
# Get selected containers
context['containers'] = Container.objects.filter(
id__in=container_ids,
expedited=True,
payment_containers__isnull=True
).order_by('-expedited_on')
return context
def get_form(self, form_class=None):
form = super().get_form(form_class)
company_pk = self.request.GET.get('company', '')
form.fields['company'].initial = company_pk
# container_ids = [int(id) for id in container_ids if id.strip().isdigit()]
# form.fields['containers'].initial = container_ids
return form

@ -6,7 +6,7 @@ urlpatterns = [
path('client/', include([ path('client/', include([
path('', ClientPreinfoView.as_view(), name='client_preinfo'), path('', ClientPreinfoView.as_view(), name='client_preinfo'),
path('create/', ClientPreinfoCreateView.as_view(), name='client_preinfo_create'), path('create/', ClientPreinfoCreateView.as_view(), name='client_preinfo_create'),
path('update/<int:pk>/', ClientPreinfoUpdateView.as_view(), name='client_preinfo_update'), path('<int:pk>/update/', ClientPreinfoUpdateView.as_view(), name='client_preinfo_update'),
])), ])),
path('check-preinfo/', check_preinfo, name='check_preinfo'), path('check-preinfo/', check_preinfo, name='check_preinfo'),
path('preinfo-search/', PreinfoSearchView.as_view(), name='preinfo_search'), path('preinfo-search/', PreinfoSearchView.as_view(), name='preinfo_search'),

@ -1,17 +1,5 @@
from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.forms import forms
from django.forms.widgets import HiddenInput
from django.http import JsonResponse
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse_lazy
from django.utils import timezone
from django.views import View
from django.views.generic import TemplateView, FormView, CreateView, ListView from django.views.generic import TemplateView, FormView, CreateView, ListView
from DepoT.mixins.crudListViewMixin import CRUDListViewMixin
from common.models import ContainerTypeModel, LinesModel
from common.utils.utils import filter_queryset_by_user, get_preinfo_by_number
from preinfo.forms import PreinfoBaseForm, PreinfoCreateForm, PreinfoEditForm from preinfo.forms import PreinfoBaseForm, PreinfoCreateForm, PreinfoEditForm
from preinfo.models import Preinfo from preinfo.models import Preinfo

@ -1,36 +1,73 @@
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
const editBtn = document.getElementById('editBtn'); const table = document.getElementById('objectTable');
const deleteBtn = document.getElementById('deleteBtn'); if (!table) return;
const objectIdInput = document.getElementById('objectIdInput');
const rows = document.querySelectorAll('.selectable-row');
if (editBtn) { const selectionMode = table.dataset.selectionMode || 'single';
editBtn.setAttribute('disabled', ''); const toggleSelectAllBtn = document.getElementById('toggleSelectAllBtn');
}
if (deleteBtn) { if (table.dataset.selectionMode === 'multiple') {
deleteBtn.setAttribute('disabled', ''); toggleSelectAllBtn.style.display = 'inline-block';
} }
rows.forEach(row => { table.addEventListener('click', function(e) {
row.addEventListener('click', function() { const row = e.target.closest('.selectable-row');
// Remove previous selection if (!row) return;
document.querySelector('.selected-row')?.classList.remove('selected-row');
const checkbox = row.querySelector('input[type="checkbox"]');
// Select current row if (!checkbox) return;
this.classList.add('selected-row');
if (selectionMode === 'single') {
const objectId = this.dataset.id; // Deselect all other rows
if (editBtn) { table.querySelectorAll('.selected-row').forEach(selectedRow => {
editBtn.removeAttribute('disabled'); // Remove disabled attribute completely if (selectedRow !== row) {
editBtn.href = editBtn.dataset.url.replace('0', objectId); selectedRow.classList.remove('selected-row');
} selectedRow.querySelector('input[type="checkbox"]').checked = false;
if (deleteBtn) { }
deleteBtn.removeAttribute('disabled'); });
} }
// Check the hidden radio button // Toggle current row
const radio = this.querySelector('input[type="radio"]'); row.classList.toggle('selected-row');
radio.checked = true; checkbox.checked = !checkbox.checked;
// Update buttons state
const selectedRows = table.querySelectorAll('.selected-row');
document.querySelectorAll('[data-requires-selection]').forEach(button => {
button.disabled = selectedRows.length === 0;
});
// Handle edit/delete buttons from original crud-list.js
const objectId = row.dataset.id;
const editBtn = document.getElementById('editBtn');
const deleteBtn = document.getElementById('deleteBtn');
if (editBtn) {
editBtn.removeAttribute('disabled');
editBtn.href = editBtn.dataset.url?.replace('0', objectId);
}
if (deleteBtn) {
deleteBtn.removeAttribute('disabled');
}
});
let allSelected = false;
toggleSelectAllBtn.addEventListener('click', function() {
const rows = table.querySelectorAll('.selectable-row');
allSelected = !allSelected;
rows.forEach(row => {
const checkbox = row.querySelector('input[type="checkbox"]');
checkbox.checked = allSelected;
row.classList.toggle('selected-row', allSelected);
}); });
// Update other buttons state
document.querySelectorAll('[data-requires-selection]').forEach(button => {
button.disabled = !allSelected;
});
// Update button text
this.textContent = allSelected ? 'Unselect All' : 'Select All';
}); });
});
});

@ -246,3 +246,36 @@ button[type="submit"]:hover {
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
overflow: hidden; /* Ensure content doesn't overflow */ overflow: hidden; /* Ensure content doesn't overflow */
} }
.filter-form {
background-color: #f8f9fa;
padding: 1rem;
border-radius: 0.25rem;
margin-bottom: 1rem;
}
.filter-form form {
display: flex;
align-items: center;
gap: 1rem;
max-width: none;
width: 100%;
}
.filter-form .form-group {
display: flex;
align-items: center;
margin-bottom: 0;
}
.filter-form .form-control {
width: auto;
min-width: 200px;
}
.me-2 {
margin-right: 0.5rem;
}
.filter-form span {
display: flex;
align-items: center;
width: 100%;
}

@ -104,4 +104,12 @@
.logout:hover { .logout:hover {
border: 1px solid #a57d52; border: 1px solid #a57d52;
}
a.nav-item,
a.nav-item:visited,
a.nav-item:hover,
a.nav-item:active {
color: inherit; /* or specify your desired color */
text-decoration: none;
} }

@ -97,6 +97,21 @@ tbody tr {
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
} }
.dashboard-table,
table td {
text-align: center;
}
.dashboard-table,
table td.td-left {
text-align: left;
}
.dashboard-table,
table td.td-right {
text-align: right;
}
/*Rename dashboard-table to match exactly with your HTML */ /*Rename dashboard-table to match exactly with your HTML */
.dashboard-table, .dashboard-table,
@ -126,7 +141,6 @@ tfoot {
table th, table th,
table td { table td {
padding: 8px; padding: 8px;
text-align: center;
border-right: 1px solid #E1C6A8; /* Add vertical borders */ border-right: 1px solid #E1C6A8; /* Add vertical borders */
border-bottom: 1px solid #E1C6A8; /* Add horizontal borders */ border-bottom: 1px solid #E1C6A8; /* Add horizontal borders */
} }
@ -194,3 +208,4 @@ table tr:last-child td {
color: #990000; color: #990000;
} }

@ -19,26 +19,6 @@
</aside> </aside>
<main class="content-area"> <main class="content-area">
{# <header class="top-nav">#}
{# <div class="nav-container">#}
{# <div class="nav-left">#}
{# <h2 class="page-title">Dashboard</h2>#}
{# </div>#}
{# <div class="nav-right">#}
{# <button class="icon-button">#}
{# <svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">#}
{# <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />#}
{# </svg>#}
{# </button>#}
{# <button class="icon-button">#}
{# <svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">#}
{# <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />#}
{# </svg>#}
{# </button>#}
{# </div>#}
{# </div>#}
{# </header>#}
<div class="content"> <div class="content">
{% block content %} {% block content %}
{% endblock content %} {% endblock content %}

@ -8,6 +8,8 @@
{% url 'client_preinfo' as client_preinfo_url %} {% url 'client_preinfo' as client_preinfo_url %}
{% url 'client_booking' as client_booking_url %} {% url 'client_booking' as client_booking_url %}
{% url 'register' as register_url %} {% url 'register' as register_url %}
{% url 'client_company' as client_company_url %}
{% url 'client_line' as client_line_url %}
<nav class="nav-menu"> <nav class="nav-menu">
<div class="section-title">Main</div> <div class="section-title">Main</div>
@ -39,8 +41,8 @@
</svg> </svg>
Reports Reports
</a> </a>
{% if request.user.UserType == 'CA' %} {% if request.user.UserType == 'CA' or 1 == 1 %}
<div class="section-title account">Account</div> <div class="section-title account">Nomenclatures</div>
<a href="{{ register_url }}" class="nav-item {% if request.path == register_url %}active{% endif %}"> <a href="{{ register_url }}" class="nav-item {% if request.path == register_url %}active{% endif %}">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
@ -48,6 +50,15 @@
</svg> </svg>
Accounts Accounts
</a> </a>
<a href="{{ client_line_url }}" class="nav-item {% if request.path == client_line_url %}active{% endif %}">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
Lines
</a>
{% endif %} {% endif %}
</nav> </nav>
<div class="user-profile"> <div class="user-profile">

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

@ -3,14 +3,12 @@
{% block table_header %} {% block table_header %}
<th style="display: none;">Select</th> <th style="display: none;">Select</th>
<th>Company name</th>
<th>Line name</th> <th>Line name</th>
<th>Short name</th> <th>Short name</th>
<th>Description</th> <th>Description</th>
{% endblock table_header %} {% endblock table_header %}
{% block table_data %} {% block table_data %}
<td>{{ object.company }}</td>
<td>{{ object.name }}</td> <td>{{ object.name }}</td>
<td>{{ object.short_name }}</td> <td>{{ object.short_name }}</td>
<td>{{ object.description }}</td> <td>{{ object.description }}</td>

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

@ -4,193 +4,26 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Employee Dashboard | Container Depot</title> <title>Depot Employee Dashboard | Container Depot</title>
<script src="https://cdn.tailwindcss.com"></script> <link rel="stylesheet" href="{% static 'styles/tables.css' %}">
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f5f7fa;
}
.sidebar {
background: linear-gradient(180deg, #0f4c81 0%, #1a6baf 100%);
transition: all 0.3s;
}
.content-area {
transition: all 0.3s;
}
.nav-item {
transition: all 0.2s;
}
.nav-item:hover {
background-color: rgba(255, 255, 255, 0.1);
}
.nav-item.active {
background-color: rgba(255, 255, 255, 0.2);
border-left: 4px solid white;
}
.card {
transition: all 0.3s;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.tab {
transition: all 0.2s;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.form-section {
animation: slideIn 0.5s ease-in-out;
}
@keyframes slideIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
<link rel="stylesheet" href="{% static 'styles/forms.css' %}"> <link rel="stylesheet" href="{% static 'styles/forms.css' %}">
<link rel="stylesheet" href="{% static 'styles/sidebar.css' %}">
<link rel="stylesheet" href="{% static 'styles/base.css' %}">
<link rel="stylesheet" href="{% static 'styles/dashboard-content.css' %}">
</head> </head>
<body class="flex h-screen overflow-hidden">
<!-- Sidebar -->
<body>
<aside class="sidebar">
{% include 'employee-sidebar.html' %} {% include 'employee-sidebar.html' %}
<!-- Main Content --> </aside>
<main class="content-area flex-1 overflow-y-auto">
<!-- Top Navigation -->
<header class="bg-white shadow-sm">
<div class="flex items-center justify-between px-6 py-4">
<div class="flex items-center">
<h2 class="text-xl font-semibold text-gray-800">Dashboard</h2>
</div>
<div class="flex items-center space-x-4">
<button class="text-gray-500 hover:text-gray-700">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
</button>
<button class="text-gray-500 hover:text-gray-700">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</button>
</div>
</div>
</header>
<!-- Dashboard Content --> <main class="content-area">
<div class="p-6"> <div class="content">
{% block content %} {% block content %}
{# {% include 'client-dashboard-content.html' %}#}
{# {% include 'client-preinfo-content.html' %}#}
{# {% include 'client-orders-content.html' %}#}
{% endblock content %} {% endblock content %}
</div> </div>
</main> </main>
{# <script>#}
{# // Tab Navigation#}
{# const dashboardContent = document.getElementById('dashboardContent');#}
{# const preinfoContent = document.getElementById('preinfoContent');#}
{# const ordersContent = document.getElementById('ordersContent');#}
{# #}
{# const preinfoNav = document.getElementById('preinfoNav');#}
{# const ordersNav = document.getElementById('ordersNav');#}
{# #}
{# preinfoNav.addEventListener('click', function(e) {#}
{# e.preventDefault();#}
{# #}
{# // Update content visibility#}
{# dashboardContent.classList.remove('active');#}
{# preinfoContent.classList.add('active');#}
{# ordersContent.classList.remove('active');#}
{# #}
{# // Update navigation styling#}
{# document.querySelector('.nav-item.active').classList.remove('active');#}
{# preinfoNav.classList.add('active');#}
{# #}
{# // Update header title#}
{# document.querySelector('header h2').textContent = 'Container Preinfo';#}
{# });#}
{# #}
{# ordersNav.addEventListener('click', function(e) {#}
{# e.preventDefault();#}
{# #}
{# // Update content visibility#}
{# dashboardContent.classList.remove('active');#}
{# preinfoContent.classList.remove('active');#}
{# ordersContent.classList.add('active');#}
{# #}
{# // Update navigation styling#}
{# document.querySelector('.nav-item.active').classList.remove('active');#}
{# ordersNav.classList.add('active');#}
{# #}
{# // Update header title#}
{# document.querySelector('header h2').textContent = 'Expedition Orders';#}
{# });#}
{# #}
{# // Damage checkbox toggle#}
{# const damageCheck = document.getElementById('damageCheck');#}
{# const damageDetails = document.getElementById('damageDetails');#}
{# #}
{# damageCheck.addEventListener('change', function() {#}
{# if (this.checked) {#}
{# damageDetails.classList.remove('hidden');#}
{# } else {#}
{# damageDetails.classList.add('hidden');#}
{# }#}
{# });#}
{# #}
{# // Order type toggle#}
{# const specificContainer = document.getElementById('specificContainer');#}
{# const anyContainer = document.getElementById('anyContainer');#}
{# const specificContainerFields = document.getElementById('specificContainerFields');#}
{# const anyContainerFields = document.getElementById('anyContainerFields');#}
{# #}
{# specificContainer.addEventListener('change', function() {#}
{# if (this.checked) {#}
{# specificContainerFields.classList.remove('hidden');#}
{# anyContainerFields.classList.add('hidden');#}
{# }#}
{# });#}
{# #}
{# anyContainer.addEventListener('change', function() {#}
{# if (this.checked) {#}
{# specificContainerFields.classList.add('hidden');#}
{# anyContainerFields.classList.remove('hidden');#}
{# }#}
{# });#}
{# #}
{# // Form submissions#}
{# document.getElementById('preinfoForm').addEventListener('submit', function(e) {#}
{# e.preventDefault();#}
{# #}
{# // In a real app, this would send data to the server#}
{# alert('Preinfo submitted successfully!');#}
{# this.reset();#}
{# });#}
{# #}
{# document.getElementById('orderForm').addEventListener('submit', function(e) {#}
{# e.preventDefault();#}
{# #}
{# // In a real app, this would send data to the server#}
{# alert('Expedition order submitted successfully!');#}
{# this.reset();#}
{# });#}
{# #}
{# // Add more container button#}
{# document.getElementById('addMoreContainer').addEventListener('click', function() {#}
{# alert('In a real app, this would add fields for another container');#}
{# });#}
{# </script>#}
{#<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'947f86ac452d3130',t:'MTc0ODYyMTY4Mi4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>#}
</body> </body>
</html> </html>

@ -1,162 +1,111 @@
{% extends 'employee-base.html' %} {% extends 'employee-base.html' %}
{% block content %} {% block content %}
<div id="dashboardContent" class="tab-content active"> <div class="dashboard-wrapper">
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6"> <div class="stats-grid">
<div class="card bg-white rounded-lg shadow p-6"> <div class="dashboard-card">
<div class="flex items-center"> <div class="card-content">
<div class="p-3 rounded-full bg-blue-100 text-blue-600"> <div class="icon-circle">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" class="dashboard-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg> </svg>
</div> </div>
<div class="ml-4"> <div class="stat-info">
<h3 class="text-lg font-semibold text-gray-700">Active Containers</h3> <h3>Active Containers</h3>
<p class="text-3xl font-bold text-gray-900">{{ containers }}</p> <p class="stat-number">{{ containers }}</p>
<p class="text-sm text-green-600">+3 since last week</p> <p class="stat-change">+3 since last week</p>
</div> </div>
</div> </div>
</div> </div>
<div class="dashboard-card">
<div class="card bg-white rounded-lg shadow p-6"> <div class="card-content">
<div class="flex items-center"> <div class="icon-circle">
<div class="p-3 rounded-full bg-green-100 text-green-600"> <svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /> </svg>
</svg> </div>
</div> <div class="stat-info">
<div class="ml-4"> <h3>Active preinfos</h3>
<h3 class="text-lg font-semibold text-gray-700">Preinfo Sent</h3> <p class="stat-number">{{ preinfos }}</p>
<p class="text-3xl font-bold text-gray-900">{{ preinfos }}</p> <p class="stat-change">+7 since last week</p>
<p class="text-sm text-green-600">+5 since last week</p> </div>
</div> </div>
</div> </div>
</div> <div class="dashboard-card">
<div class="card-content">
<div class="card bg-white rounded-lg shadow p-6"> <div class="icon-circle">
<div class="flex items-center"> <svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<div class="p-3 rounded-full bg-orange-100 text-orange-600"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor"> </svg>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
</svg>
</div>
<div class="ml-4">
<h3 class="text-lg font-semibold text-gray-700">Bookings</h3>
<p class="text-3xl font-bold text-gray-900">{{ bookings }}</p>
<p class="text-sm text-orange-600">2 require attention</p>
</div>
</div>
</div>
</div> </div>
<div class="stat-info">
<h3>Active bookings</h3>
<p class="stat-number">{{ bookings }}</p>
<p class="stat-change">+8 since last week</p>
</div>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6"> <!-- Other two cards similar structure -->
<div class="bg-white rounded-lg shadow"> </div>
<div class="px-6 py-4 border-b border-gray-200">
<h3 class="text-lg font-semibold text-gray-800">Recent Container Activity</h3>
</div>
<div class="p-6">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead>
<tr>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Container</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Type</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">MSCU1234567</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">40HC</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-green-100 text-green-800">Received</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-06-15</td>
</tr>
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">MSCU7654321</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">20DV</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-blue-100 text-blue-800">Preinfo</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-06-14</td>
</tr>
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">MSCU2468135</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">40DV</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-orange-100 text-orange-800">Order</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-06-13</td>
</tr>
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">MSCU1357924</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">20RF</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-red-100 text-red-800">Expedited</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-06-12</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow"> <div class="tables-grid">
<div class="px-6 py-4 border-b border-gray-200"> <div class="dashboard-card">
<h3 class="text-lg font-semibold text-gray-800">Payment Status</h3> <div class="card-header">
</div> <h3>Recent Container Activity</h3>
<div class="p-6"> </div>
<div class="overflow-x-auto"> <div class="card-body">
<table class="min-w-full divide-y divide-gray-200"> <table class="table">
<thead> <thead>
<tr> <tr>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Invoice</th> <th>Container</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Amount</th> <th>Type</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th> <th>Status</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Due Date</th> <th>Date</th>
</tr> </tr>
</thead> </thead>
<tbody class="divide-y divide-gray-200"> <tbody>
<tr> <tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">INV-2023-0042</td> <td>MSCU1234567</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">$1,250.00</td> <td>40HC</td>
<td class="px-4 py-3 whitespace-nowrap"> <td><span class="status-tag status-received">Received</span></td>
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-green-100 text-green-800">Paid</span> <td>2023-06-15</td>
</td> </tr>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-06-10</td> <!-- Other rows similar structure -->
</tr> </tbody>
<tr> </table>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">INV-2023-0041</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">$875.50</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-yellow-100 text-yellow-800">Pending</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-06-20</td>
</tr>
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">INV-2023-0040</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">$2,100.00</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-red-100 text-red-800">Overdue</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-06-05</td>
</tr>
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">INV-2023-0039</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">$950.25</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-green-100 text-green-800">Paid</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-05-28</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div> </div>
</div>
<div class="dashboard-card">
<div class="card-header">
<h3>Recent payments</h3>
</div>
<div class="card-body">
<table class="table">
<thead>
<tr>
<th>Container</th>
<th>Type</th>
<th>Status</th>
<th>Date</th>
</tr>
</thead>
<tbody>
{# {% for container in containers %}#}
{# <tr>#}
{# <td>{{ container.number }}</td>#}
{# <td>container.container_type</td>#}
{# <td><span class="status-tag status-received">Received</span></td>#}
{# <td>{{ container.received_date }}</td>#}
{# </tr>#}
{# {% endfor %}#}
<!-- Other rows similar structure -->
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endblock %} {% endblock %}

@ -1,83 +1,93 @@
{% load static %} {% load static %}
<aside class="sidebar w-64 h-full text-white flex flex-col"> <aside class="sidebar">
<div class="p-5 border-b border-blue-700"> <div class="header">
<h1 class="text-xl font-bold">Container Depot</h1> <h1>Container Depot</h1>
<p class="text-sm text-blue-200">Employee Portal</p> <p class="subtitle">Line Operator Portal</p>
</div> </div>
{% url 'employee_dashboard' as dashboard_url %}
<nav class="flex-grow py-4"> {% url 'employee_containers' as employee_containers_url %}
<div class="px-4 py-2 text-xs text-blue-300 uppercase tracking-wider">Main</div> {% url 'employee_bookings' as employee_bookings_url %}
<a href="{% url 'dashboard' %}" class="nav-item active flex items-center px-6 py-3 text-white"> {% url 'employee_preinfo' as employee_preinfo_url %}
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor"> {% url 'register' as register_url %}
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" /> {% url 'employee_company' as employee_company_url %}
</svg> {% url 'employee_line' as employee_line_url %}
Dashboard {% url 'user_list' as user_list_url %}
</a> {% url 'not_paid' as not_paid_list_url %}
<a href="{% url 'employee_containers' %}" id="preinfoNav" class="nav-item flex items-center px-6 py-3 text-white">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
Available Containers
</a>
<a href="{% url 'employee_bookings' %}" id="ordersNav" class="nav-item flex items-center px-6 py-3 text-white">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
</svg>
Bookings
</a>
<a href="{% url 'employee_preinfo' %}" class="nav-item flex items-center px-6 py-3 text-white">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
Preinfos
</a>
{% if request.user.UserType.ADMIN %} <nav class="nav-menu">
<div class="section-title">Main</div>
<div class="px-4 py-2 mt-6 text-xs text-blue-300 uppercase tracking-wider">Account</div> <a href="{{ dashboard_url }}" class="nav-item {% if request.path == dashboard_url %}active{% endif %}">
<a href="{% url 'register' %}" class="nav-item flex items-center px-6 py-3 text-white"> <svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
Dashboard
</a>
<a href="{{ employee_containers_url }}" class="nav-item {% if request.path == employee_containers_url %}active{% endif %}" id="preinfoNav">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
Containers
</a>
<a href="{{ employee_preinfo_url }}" class="nav-item {% if request.path == employee_preinfo_url %}active{% endif %}" id="preinfoNav">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
Container Preinfo
</a>
<a href="{{ employee_bookings_url }}" class="nav-item {% if request.path == employee_bookings_url %}active{% endif %}" id="ordersNav">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
</svg>
Bookings
</a>
<div class="section-title account">Reports</div>
<a href="{{ not_paid_list_url }}" class="nav-item {% if request.path == not_paid_list_url %}active{% endif %}" id="ordersNav">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<g>
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm-1.95-9H15v2h-4.95a2.5 2.5 0 0 0 4.064 1.41l1.7 1.133A4.5 4.5 0 0 1 8.028 13H7v-2h1.027a4.5 4.5 0 0 1 7.788-2.543L14.114 9.59A2.5 2.5 0 0 0 10.05 11z"/>
</g>
</svg>
Reports
</a>
{% if request.user.UserType == 'CA' or 1 == 1 %}
<div class="section-title account">Nomenclatures</div>
<a href="{{ user_list_url }}" class="nav-item {% if request.path == user_list_url %}active{% endif %}">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg> </svg>
Accounts Accounts
</a> </a>
{# <div class="px-4 py-2 mt-6 text-xs text-blue-300 uppercase tracking-wider">Account</div>#} <a href="{{ employee_company_url }}" class="nav-item {% if request.path == employee_company_url %}active{% endif %}">
<a href="{% url 'register' %}" class="nav-item flex items-center px-6 py-3 text-white"> <svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg> </svg>
Companies Companies
</a> </a>
<a href="{% url 'register' %}" class="nav-item flex items-center px-6 py-3 text-white"> <a href="{{ employee_line_url }}" class="nav-item {% if request.path == employee_line_url %}active{% endif %}">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg> </svg>
Lines Lines
</a> </a>
{% endif %}
{% endif %} </nav>
</nav> <div class="user-profile">
<div class="avatar">LO</div>
<div class="p-4 border-t border-blue-700"> <div class="user-info">
<div class="flex items-center"> <p class="username">{{ request.user }}</p>
<div class="w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold">
LO
</div>
<div class="ml-3">
<p class="text-sm font-medium">{{ request.user }}</p>
<p class="text-xs text-blue-300">{{ request.user.company }}</p>
</div>
<a href="{% url 'login' %}" class="ml-auto text-white" >
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
</a>
</div>
</div> </div>
</aside> <a href="{% url 'login' %}" class="logout">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
</a>
</div>
</aside>

@ -1,40 +1,43 @@
{% extends 'employee-base.html' %} {% extends 'list-crud.html' %}
{% load static %} {% load static %}
{% block content %} {% block table_header %}
<table> <th style="display: none;">Select</th>
<tr> <th>Line</th>
<th>Status</th> <th>Booking №</th>
<th>Booking №</th> <th>Container type</th>
<th>Vehicles</th> <th>Container №</th>
<th>Container number</th> <th>Containers count</th>
<th>Container type</th> <th>Containers left</th>
<th>Container count</th> <th>Vehicles</th>
<th>Line</th> <th>Vehicles left</th>
<th>Carrier</th> <th>Created on</th>
<th>Containers expedited</th> <th>Created by</th>
<th>Vehicles left</th> {% endblock table_header %}
</tr>
{% for booking in bookings %} {% block table_data %}
<tr> <td>{{ object.line.short_name }}</td>
<td>{{ booking.status }}</td> <td>{{ object.number }}</td>
<td>{{ booking.number }}</td> <td>{{ object.container_type }}</td>
<td>{{ booking.vehicles }}</td> <td>{{ object.container_number }}</td>
<td>{{ booking.container_number }}</td> <td>{{ object.container_count }}</td>
<td>{{ booking.container_type }}</td> <td>{{ object.containers_left }}</td>
<td>{{ booking.container_count }}</td> <td>{{ object.vehicles }}</td>
<td>{{ booking.line.short_name }}</td> <td>{{ object.vehicles_left }}</td>
<td>{{ booking.carrier }}</td> <td>{{ object.created_on }}</td>
<td>{{ booking.container_expedited_count }}</td> <td>{{ object.created_by.username }}</td>
<td>{{ booking.vehicles_left }}</td> {% endblock %}
<td>
{# <a href="{% url 'employee:preinfo_edit' preinfo.id %}">Edit</a> |#}
{# <a href="{% url 'employee:preinfo_delete' preinfo.id %}">Delete</a>#}
</td>
</tr>
{% endfor %} {% block buttons %}
{# <a href="{% url 'employee_booking_create' %}" class="btn btn-primary">Create booking</a>#}
{# <a href="#" id="editBtn" data-url="{% url 'client_booking_update' pk=0 %}" class="btn btn-primary" disabled>Edit Preinfo</a>#}
{# <button id="deleteButton" class="btn btn-danger">Delete Preinfo</button>#}
{% endblock buttons %}
</table> {% block create_modal_header %}
{% endblock content %} <h2>Create Booking</h2>
{% endblock %}
{% block modal_header %}
<h2>Edit Booking</h2>
{% endblock modal_header %}

@ -15,8 +15,8 @@
{% endblock %} {% endblock %}
{% block buttons %} {% block buttons %}
<a href="{% url 'company_create' %}" class="btn btn-primary">Create company</a> <a href="{% url 'employee_company_create' %}" class="btn btn-primary">Create company</a>
<a href="#" id="editBtn" data-url="{% url 'company_update' pk=0 %}" class="btn btn-primary" disabled>Edit Preinfo</a> <a href="#" id="editBtn" data-url="{% url 'employee_company_update' pk=0 %}" class="btn btn-primary" disabled>Edit Preinfo</a>
<button id="deleteButton" class="btn btn-danger">Delete Preinfo</button> <button id="deleteButton" class="btn btn-danger">Delete Preinfo</button>
{% endblock buttons %} {% endblock buttons %}

@ -1,9 +1,7 @@
{% extends 'employee-base.html' %} {% extends 'list-crud.html' %}
{% load static %} {% load static %}
{% block content %} {% block table_header %}
<table>
<tr>
<th>Container №</th> <th>Container №</th>
<th>Container type</th> <th>Container type</th>
<th>Line</th> <th>Line</th>
@ -12,25 +10,26 @@
<th>Swept</th> <th>Swept</th>
<th>Washed</th> <th>Washed</th>
<th>Booking</th> <th>Booking</th>
</tr> {% endblock table_header %}
{% for container in containers %} {% block table_data %}
<tr> <td>{{ object.number }}</td>
<td>{{ container.number }}</td> <td>{{ object.container_type }}</td>
<td>{{ container.container_type }}</td> <td>{{ object.line.short_name }}</td>
<td>{{ container.line.short_name }}</td> <td>{{ object.received_on }}</td>
<td>{{ container.received_on }}</td> <td>{{ object.position }}</td>
<td>{{ container.position }}</td> <td>{{ object.swept }}</td>
<td>{{ container.swept }}</td> <td>{{ object.washed }}</td>
<td>{{ container.washed }}</td> <td>{{ object.booking.number }}</td>
<td>{{ container.booking.id }}</td> {% endblock %}
<td>
{# <a href="{% url 'employee:preinfo_edit' preinfo.id %}">Edit</a> |#}
{# <a href="{% url 'employee:preinfo_delete' preinfo.id %}">Delete</a>#}
</td>
</tr>
{% endfor %} {% block buttons %}
{% endblock buttons %}
</table> {% block create_modal_header %}
{% endblock content %} <h2>Create Container</h2>
{% endblock %}
{% block modal_header %}
<h2>Edit Container</h2>
{% endblock modal_header %}

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

@ -3,20 +3,22 @@
{% block table_header %} {% block table_header %}
<th style="display: none;">Select</th> <th style="display: none;">Select</th>
<th>Company</th>
<th>Line name</th> <th>Line name</th>
<th>Short name</th> <th>Short name</th>
<th>Description</th> <th>Description</th>
{% endblock table_header %} {% endblock table_header %}
{% block table_data %} {% block table_data %}
<td>{{ object.company }}</td>
<td>{{ object.name }}</td> <td>{{ object.name }}</td>
<td>{{ object.short_name }}</td> <td>{{ object.short_name }}</td>
<td>{{ object.description }}</td> <td>{{ object.description }}</td>
{% endblock %} {% endblock %}
{% block buttons %} {% block buttons %}
<a href="{% url 'client_line_create' %}" class="btn btn-primary">Create line</a> <a href="{% url 'employee_line_create' %}" class="btn btn-primary">Create line</a>
<a href="#" id="editBtn" data-url="{% url 'client_line_update' pk=0 %}" class="btn btn-primary" disabled>Edit Preinfo</a> <a href="#" id="editBtn" data-url="{% url 'employee_line_update' pk=0 %}" class="btn btn-primary" disabled>Edit Preinfo</a>
<button id="deleteButton" class="btn btn-danger">Delete Preinfo</button> <button id="deleteButton" class="btn btn-danger">Delete Preinfo</button>
{% endblock buttons %} {% endblock buttons %}
@ -25,5 +27,5 @@
{% endblock %} {% endblock %}
{% block modal_header %} {% block modal_header %}
<h2>edit line</h2> <h2>edit line</h2>
{% endblock modal_header %} {% endblock modal_header %}

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

@ -1,10 +1,34 @@
<!DOCTYPE html> {% extends "employee-base.html" %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body> {% block content %}
</html> {% csrf_token %}
{{ form.as_p }}
<div class="selected-containers">
<h3>Selected Containers</h3>
<table class="table">
<thead>
<tr>
<th>Container Number</th>
<th>Type</th>
<th>Company</th>
<th>Received Date</th>
<th>Expedited Date</th>
</tr>
</thead>
<tbody>
{% for container in containers %}
<tr>
<td>{{ container.number }}</td>
<td>{{ container.container_type }}</td>
<td>{{ container.line.company.short_name }}</td>
<td>{{ container.received_on|date:"Y-m-d" }}</td>
<td>{{ container.expedited_on|date:"Y-m-d" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

@ -1,10 +1,78 @@
<!DOCTYPE html> {% extends 'list-crud.html' %}
<html lang="en"> {% load static %}
<head>
<meta charset="UTF-8"> {% block filter %}
<title>$Title$</title> <div class="filter-form">
</head> <form method="GET">
<body> <span style="display: flex; align-items: center; width: 100%;">
$END$ <label for="date" style="margin-right: 8px;">Date:</label>
</body> <input type="date" id="date" name="date" value="{{ request.GET.date }}" style="margin-right: 20px;">
</html>
<label for="company" style="margin-right: 8px;">Company:</label>
<select id="company" name="company" style="margin-right: 20px;">
<option value="">Select company</option>
{% for company in companies %}
<option value="{{ company.id }}" {% if request.GET.company|add:'0' == company.id %}selected{% endif %}>
{{ company.name }}
</option>
{% endfor %}
</select>
<button type="submit">Search</button>
</span>
</form>
</div>
{% endblock %}
{% block selection %}
"multiple"
{% endblock selection %}
{% block table_header %}
<th>Container Number</th>
<th>Type</th>
<th>Company</th>
<th>Expedited Date</th>
{% endblock table_header %}
{% block table_data %}
<td class="td-left">{{ object.number }}</td>
<td>{{ object.container_type }}</td>
<td class="td-left">{{ object.line.company.short_name }}</td>
<td>{{ object.expedited_on|date:"Y-m-d h:m:s" }}</td>
{% endblock table_data %}
{% block buttons %}
<button id="createPaymentBtn" class="btn btn-primary" data-requires-selection disabled>Create Payment</button>
{% endblock buttons %}
{% block create_modal_header %}
<h2>Create Container</h2>
{% endblock %}
{% block modal_header %}
<h2>Edit Container</h2>
{% endblock modal_header %}
{% block custom_js %}
<script>
document.getElementById('createPaymentBtn').addEventListener('click', function() {
const selectedIds = Array.from(document.querySelectorAll('.selected-row'))
.map(row => row.dataset.id);
const dateInput = document.getElementById('date').value;
const companySelect = document.getElementById('company').value;
if (selectedIds.length > 0) {
const params = new URLSearchParams({
containers: selectedIds.join(','),
date: dateInput,
company: companySelect
});
window.location.href = '{% url "payments_create" %}?' + params.toString();
}
});
</script>
{% endblock custom_js %}

@ -21,5 +21,5 @@
{% endblock %} {% endblock %}
{% block modal_header %} {% block modal_header %}
<h2>Edit Preinfo</h2> <h2>Edit Preinfo</h2>
{% endblock modal_header %} {% endblock modal_header %}

@ -1,25 +1,16 @@
{% extends base_template %} {% extends base_template %}
{% load static %} {% load static %}
{% block content %} {% block content %}
{# <div class="pagination">#}
{# <span class="step-links">#} {% block filter %}
{# {% if page_obj.has_previous %}#} {% endblock filter %}
{# <a href="?page=1">&laquo; first</a>#}
{# <a href="?page={{ page_obj.previous_page_number }}">previous</a>#} <table id="objectTable" class="table" data-selection-mode=
{# {% endif %}#} {% block selection %}
{##} "single"
{# <span class="current">#} {% endblock selection%}>
{# Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.#}
{# </span>#}
{##}
{# {% if page_obj.has_next %}#}
{# <a href="?page={{ page_obj.next_page_number }}">next</a>#}
{# <a href="?page={{ page_obj.paginator.num_pages }}">last &raquo;</a>#}
{# {% endif %}#}
{# </span>#}
{# </div>#}
<table id="objectTable" class="table">
<thead> <thead>
<tr> <tr>
{% block table_header %} {% block table_header %}
@ -29,7 +20,7 @@
<tbody> <tbody>
{% for object in objects %} {% for object in objects %}
<tr class="selectable-row" data-id="{{ object.id }}"> <tr class="selectable-row" data-id="{{ object.id }}">
<td style="display: none;"><input type="radio" name="object_select" value="{{ object.id }}"></td> <td style="display: none;"><input type="checkbox" name="object_select" value="{{ object.id }}"></td>
{% block table_data %} {% block table_data %}
{% endblock table_data %} {% endblock table_data %}
</tr> </tr>
@ -42,22 +33,18 @@
<div class="footer-left"> <div class="footer-left">
{% block buttons %} {% block buttons %}
{% endblock buttons %} {% endblock buttons %}
{# <button>Добави</button>#} <button id="toggleSelectAllBtn" class="btn btn-secondary" style="display: none;">Select All</button>
{# <button>Изтрий</button>#}
{# <button>Редактирай</button>#}
</div> </div>
<div class="footer-right"> <div class="footer-right">
{% if page_obj.has_previous %} {% if page_obj.has_previous %}
<a href="?page=1">&laquo; first</a> <a href="?page=1">&laquo; first</a>
<a href="?page={{ page_obj.previous_page_number }}">previous</a> <a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %} {% endif %}
{# <button>&laquo; Назад</button>#}
<span class="page-number">Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.</span> <span class="page-number">Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.</span>
{% if page_obj.has_next %} {% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a> <a href="?page={{ page_obj.next_page_number }}">next</a>
<a href="?page={{ page_obj.paginator.num_pages }}">last &raquo;</a> <a href="?page={{ page_obj.paginator.num_pages }}">last &raquo;</a>
{% endif %} {% endif %}
{# <button>Напред &raquo;</button>#}
</div> </div>
</div> </div>
</td> </td>
@ -65,7 +52,6 @@
</tfoot> </tfoot>
</table> </table>
<script> <script>
const table = document.getElementById('objectTable'); const table = document.getElementById('objectTable');
const headerCells = table.querySelector('thead tr').children.length; const headerCells = table.querySelector('thead tr').children.length;
@ -74,11 +60,6 @@
{#footerCell.style.textAlign = 'center';#} {#footerCell.style.textAlign = 'center';#}
</script> </script>
{# <div class="buttons-container">#}
{# {% block buttons %}#}
{# {% endblock buttons %}#}
{# </div>#}
{% block custom_styles %} {% block custom_styles %}
<style> <style>
.selectable-row { .selectable-row {
@ -93,8 +74,11 @@
} }
</style> </style>
{% endblock custom_styles %} {% endblock custom_styles %}
{% block extra_js %} {% block extra_js %}
<script src="{% static 'js/crud-list.js' %}"></script> <script src="{% static 'js/crud-list.js' %}"></script>
{% endblock extra_js %} {% endblock extra_js %}
{% block custom_js %}{% endblock custom_js %} {% block custom_js %}
{% endblock custom_js %}
{% endblock content %} {% endblock content %}

@ -1,10 +1,38 @@
<!DOCTYPE html> {% extends 'list-crud.html' %}
<html lang="en"> {% load static %}
<head>
<meta charset="UTF-8"> {% block table_header %}
<title>$Title$</title> <th>Username</th>
</head> <th>User Type</th>
<body> <th>First Name</th>
$END$ <th>Last Name</th>
</body> <th>Email</th>
</html> <th>Phone</th>
<th>Company</th>
<th>Line</th>
{% endblock table_header %}
{% block table_data %}
<td class="td-left">{{ object.username }}</td>
<td class="td-left">{{ object.get_user_type_display }}</td>
<td class="td-left">{{ object.first_name }}</td>
<td class="td-left">{{ object.last_name }}</td>
<td class="td-left">{{ object.email }}</td>
<td class="td-left">{{ object.phone }}</td>
<td class="td-left">{{ object.company }}</td>
<td class="td-left">{{ object.line }}</td>
{% endblock %}
{% block buttons %}
<a href="{% url 'user_register' %}" class="btn btn-primary" type="button">Create user</a>
<a href="#" id="editBtn" data-url="{% url 'user_update' pk=0 %}" class="btn btn-primary" type="button" disabled>Edit user</a>
<button id="deleteButton" class="btn btn-danger">Delete user</button>
{% endblock buttons %}
{% block create_modal_header %}
<h2>Create User</h2>
{% endblock %}
{% block modal_header %}
<h2>Edit Container</h2>
{% endblock modal_header %}
Loading…
Cancel
Save