diff --git a/DepoT/settings.py b/DepoT/settings.py index e162aa4..84c48de 100644 --- a/DepoT/settings.py +++ b/DepoT/settings.py @@ -31,13 +31,16 @@ ALLOWED_HOSTS = [] # Application definition PROJECT_APPS = [ - "common", + 'accounts', "booking", + "common", "containers", + 'preinfo', ] INSTALLED_APPS = [ + "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", @@ -101,7 +104,9 @@ DATABASES = { # Password validation # https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators -# AUTH_USER_MODEL = 'users.CustomUser' +AUTH_USER_MODEL = 'accounts.DepotUser' + +LOGIN_URL = '/user/login/' AUTH_PASSWORD_VALIDATORS = [ { @@ -118,6 +123,9 @@ AUTH_PASSWORD_VALIDATORS = [ }, ] +AUTHENTICATION_BACKENDS = [ + 'django.contrib.auth.backends.ModelBackend', +] # Internationalization # https://docs.djangoproject.com/en/5.2/topics/i18n/ diff --git a/DepoT/urls.py b/DepoT/urls.py index 5da75ef..09540d6 100644 --- a/DepoT/urls.py +++ b/DepoT/urls.py @@ -14,12 +14,14 @@ Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ - +from django.contrib import admin # from django.contrib import admin from django.urls import path, include urlpatterns = [ - # path("admin/", admin.site.urls), + path("admin/", admin.site.urls), path('', include('common.urls')), - path('user/', include('users.urls')), + path('user/', include('accounts.urls')), + path('preinfo/', include('preinfo.urls')), + path('container/', include('containers.urls')), ] diff --git a/users/__init__.py b/accounts/__init__.py similarity index 100% rename from users/__init__.py rename to accounts/__init__.py diff --git a/accounts/admin.py b/accounts/admin.py new file mode 100644 index 0000000..4a111d9 --- /dev/null +++ b/accounts/admin.py @@ -0,0 +1,34 @@ +from django.contrib import admin +from django.contrib.auth.admin import UserAdmin +from .models import DepotUser + + +@admin.register(DepotUser) +class DepotUserAdmin(UserAdmin): + # Add your custom fields to the fieldsets + fieldsets = UserAdmin.fieldsets + ( + ('Additional Info', {'fields': ( + 'phone_number', + 'company', + 'line', + 'company_permissions', + 'new_field1', + 'is_company_admin', + )}), + ) + + # Add fields to display in list view + list_display = UserAdmin.list_display + ('phone_number', 'company', 'line', 'is_company_admin') + + # Add fields to the add form + add_fieldsets = UserAdmin.add_fieldsets + ( + ('Additional Info', {'fields': ( + 'email', + 'phone_number', + 'company', + 'line', + 'company_permissions', + 'new_field1', + 'is_company_admin', + )}), + ) \ No newline at end of file diff --git a/users/apps.py b/accounts/apps.py similarity index 84% rename from users/apps.py rename to accounts/apps.py index 88f7b17..f2ab78b 100644 --- a/users/apps.py +++ b/accounts/apps.py @@ -3,4 +3,4 @@ from django.apps import AppConfig class UsersConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" - name = "users" + name = "accounts" diff --git a/accounts/backends.py b/accounts/backends.py new file mode 100644 index 0000000..a86c5b5 --- /dev/null +++ b/accounts/backends.py @@ -0,0 +1,16 @@ +from django.contrib.auth.backends import ModelBackend + + +class CompanyUserBackend(ModelBackend): + def get_user_permissions(self, user_obj, obj=None): + if not user_obj.is_active or user_obj.is_anonymous: + return set() + + if user_obj.is_superuser: + return super().get_user_permissions(user_obj, obj) + + perms = super().get_user_permissions(user_obj, obj) + if user_obj.company and user_obj.company.is_client: + # Filter permissions based on client company context + perms = {p for p in perms if p.startswith('accounts.client_')} + return perms \ No newline at end of file diff --git a/accounts/forms.py b/accounts/forms.py new file mode 100644 index 0000000..b52895a --- /dev/null +++ b/accounts/forms.py @@ -0,0 +1,7 @@ +from django.contrib.auth import get_user_model +from django.contrib.auth.forms import AuthenticationForm + +class LoginForm(AuthenticationForm): + field_order = ['username', 'password'] + class Meta: + model = get_user_model() diff --git a/users/migrations/__init__.py b/accounts/migrations/__init__.py similarity index 100% rename from users/migrations/__init__.py rename to accounts/migrations/__init__.py diff --git a/accounts/models.py b/accounts/models.py new file mode 100644 index 0000000..2d6a632 --- /dev/null +++ b/accounts/models.py @@ -0,0 +1,44 @@ +from django.contrib.auth.models import AbstractUser +from django.db import models + +class ClientPermission(models.Model): + class Meta: + managed = True + default_permissions = () + permissions = ( + ('can_book_container', 'Can book container'), + ('can_view_bookings', 'Can view bookings'), + ('can_manage_company_users', 'Can manage company users'), + ) + + +class DepotUser(AbstractUser): + + phone_number = models.CharField(max_length=15, blank=True, null=True) + email = models.EmailField(unique=True, blank=False, null=False) + company = models.ForeignKey( + 'common.CompanyModel', + on_delete=models.CASCADE, + related_name='user_lines', + blank=True, + null=True + ) + line = models.ForeignKey( + 'common.LinesModel', + on_delete=models.CASCADE, + related_name='user_lines', + blank=True, + null=True + ) + + company_permissions = models.ManyToManyField('ClientPermission') + new_field1 = models.BooleanField(default=False) + is_company_admin = models.BooleanField(default=False) + + def has_company_perm(self, perm_codename): + if self.is_superuser: + return True + return self.company_permissions.filter( + codename=perm_codename, + is_client_permission=self.company + ).exists() \ No newline at end of file diff --git a/users/tests.py b/accounts/tests.py similarity index 100% rename from users/tests.py rename to accounts/tests.py diff --git a/accounts/urls.py b/accounts/urls.py new file mode 100644 index 0000000..ac59a5c --- /dev/null +++ b/accounts/urls.py @@ -0,0 +1,8 @@ +from django.urls import path +from django.contrib.auth import views as auth_views +from accounts import views + +urlpatterns = [ + path('login/', views.DepotLoginView.as_view(), name='login'), + path('relogin/', auth_views.logout_then_login, name='relogin'), +] \ No newline at end of file diff --git a/accounts/views.py b/accounts/views.py new file mode 100644 index 0000000..509ff0a --- /dev/null +++ b/accounts/views.py @@ -0,0 +1,17 @@ +from django.contrib.auth.views import LoginView +from django.shortcuts import render +from django.urls import reverse_lazy +from django.views.generic import TemplateView, FormView + +from accounts.forms import LoginForm + + +# Create your views here. +class DepotLoginView(LoginView): + template_name = 'registration/login.html' + # success_url = reverse_lazy('dashboard') + form_class = LoginForm + next_page = reverse_lazy('dashboard') + + + diff --git a/booking/migrations/0001_initial.py b/booking/migrations/0001_initial.py deleted file mode 100644 index 958c34a..0000000 --- a/booking/migrations/0001_initial.py +++ /dev/null @@ -1,61 +0,0 @@ -# Generated by Django 5.2.3 on 2025-06-25 12:33 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ("common", "0001_initial"), - ] - - operations = [ - migrations.CreateModel( - name="BookingModel", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("number", models.CharField(max_length=50, unique=True)), - ("vehicles", models.CharField(blank=True, null=True)), - ("container_count", models.IntegerField()), - ("carrier", models.CharField(blank=True, max_length=100, null=True)), - ("visible", models.BooleanField(default=True)), - ("is_new", models.BooleanField(default=True)), - ( - "container_number", - models.CharField(blank=True, max_length=11, null=True), - ), - ("vehicles_left", models.IntegerField(blank=True, null=True)), - ("created_on", models.DateTimeField(auto_now_add=True)), - ("created_by", models.IntegerField()), - ("updated_on", models.DateTimeField(auto_now=True)), - ("updated_by", models.IntegerField()), - ( - "container_type", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="booking_container_types", - to="common.containertypemodel", - ), - ), - ( - "line", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="booking_lines", - to="common.linesmodel", - ), - ), - ], - ), - ] diff --git a/booking/models.py b/booking/models.py index 57c82c9..1b168d1 100644 --- a/booking/models.py +++ b/booking/models.py @@ -1,5 +1,5 @@ from django.db import models -from common.models import ContainerTypeModel, LinesModel, OperationModel, PayerModel +from common.models import ContainerTypeModel, LinesModel, OperationModel # Create your models here. class BookingModel(models.Model): diff --git a/booking/views.py b/booking/views.py index 91ea44a..2e779ca 100644 --- a/booking/views.py +++ b/booking/views.py @@ -1,3 +1,14 @@ from django.shortcuts import render +from django.views.generic import CreateView + # Create your views here. +class CreateBookingView(CreateView): + template_name = 'create-booking.html' + extra_context = { + 'title': 'Create Booking', + 'description': 'This is the create booking page.', + } + + def get(self, request, *args, **kwargs): + return render(request, self.template_name, self.extra_context) \ No newline at end of file diff --git a/common/migrations/0001_initial.py b/common/migrations/0001_initial.py deleted file mode 100644 index b91c610..0000000 --- a/common/migrations/0001_initial.py +++ /dev/null @@ -1,132 +0,0 @@ -# Generated by Django 5.2.3 on 2025-06-25 12:33 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [] - - operations = [ - migrations.CreateModel( - name="ContainerKindModel", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("name", models.CharField(max_length=100, unique=True)), - ("short_name", models.CharField(max_length=5, unique=True)), - ("description", models.TextField(blank=True, null=True)), - ], - options={ - "ordering": ["name"], - "abstract": False, - }, - ), - migrations.CreateModel( - name="OperationModel", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("name", models.CharField(max_length=100, unique=True)), - ("short_name", models.CharField(max_length=5, unique=True)), - ("description", models.TextField(blank=True, null=True)), - ], - options={ - "ordering": ["name"], - "abstract": False, - }, - ), - migrations.CreateModel( - name="PayerModel", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("name", models.CharField(max_length=100, unique=True)), - ("short_name", models.CharField(max_length=5, unique=True)), - ("description", models.TextField(blank=True, null=True)), - ], - options={ - "ordering": ["name"], - "abstract": False, - }, - ), - migrations.CreateModel( - name="ContainerTypeModel", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("name", models.CharField(max_length=6, unique=True)), - ("length", models.IntegerField()), - ("height", models.BooleanField()), - ("deleted", models.BooleanField(default=False)), - ( - "container_type", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="container_type_container_kinds", - to="common.containerkindmodel", - ), - ), - ], - ), - migrations.CreateModel( - name="LinesModel", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("name", models.CharField(max_length=100, unique=True)), - ("short_name", models.CharField(max_length=5, unique=True)), - ("description", models.TextField(blank=True, null=True)), - ( - "payer", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="line_payers", - to="common.payermodel", - ), - ), - ], - options={ - "ordering": ["name"], - "abstract": False, - }, - ), - ] diff --git a/common/models.py b/common/models.py index 7f241ca..883f386 100644 --- a/common/models.py +++ b/common/models.py @@ -3,7 +3,7 @@ from django.db import models # Create your models here. class NomenclatureBaseModel(models.Model): name = models.CharField(max_length=100, unique=True) - short_name = models.CharField(max_length=5, unique=True) + short_name = models.CharField(max_length=5, null=True, blank=True) description = models.TextField(blank=True, null=True) class Meta: @@ -13,14 +13,16 @@ class NomenclatureBaseModel(models.Model): def __str__(self): return self.name -class PayerModel(NomenclatureBaseModel): + +class CompanyModel(NomenclatureBaseModel): ... + class LinesModel(NomenclatureBaseModel): - payer = models.ForeignKey( - PayerModel, + company = models.ForeignKey( + 'common.CompanyModel', on_delete=models.CASCADE, - related_name='line_payers' + related_name='line_company' ) class OperationModel(NomenclatureBaseModel): @@ -34,8 +36,11 @@ class ContainerTypeModel(models.Model): length = models.IntegerField() height = models.BooleanField() container_type = models.ForeignKey( - ContainerKindModel, + 'common.ContainerKindModel', on_delete=models.CASCADE, related_name='container_type_container_kinds' ) deleted = models.BooleanField(default=False) + + def __str__(self): + return self.name \ No newline at end of file diff --git a/common/urls.py b/common/urls.py index 53367a2..965ba40 100644 --- a/common/urls.py +++ b/common/urls.py @@ -4,6 +4,7 @@ from common import views urlpatterns = [ path('', views.IndexView.as_view(), name='index'), path('client/dashboard/', views.ClientDashboardView.as_view(), name='client_dashboard'), - path ('client/preinfo/', views.ClientPreinfoView.as_view(), name='client_preinfo'), + path('barrier/dashboard/', views.BarrierDashboardView.as_view(), name='barrier_dashboard'), + path('dashboard/', views.DashboardRedirectView.as_view(), name='dashboard'), ] diff --git a/common/utils.py b/common/utils.py new file mode 100644 index 0000000..ba160bd --- /dev/null +++ b/common/utils.py @@ -0,0 +1,39 @@ +from containers.models import Container +from preinfo.models import Preinfo + + +def filter_queryset_by_user(queryset, user): + """ + Filters the queryset based on the user's line or company. + 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 user.line: + return queryset.filter(line=user.line) + elif user.company: + company_lines = user.company.line_company.all() + return queryset.filter(line__in=company_lines) + return queryset + + +def get_preinfo_by_number(number): + """ + Retrieves a PreinfoModel instance by its container number. + Returns None if no matching PreinfoModel is found. + """ + try: + return Preinfo.objects.get(container_number=number, received=False) + except Preinfo.DoesNotExist: + return None + + +def get_container_by_number(number): + """ + Retrieves a Container instance by its number. + Returns None if no matching Container is found. + """ + try: + return Container.objects.get(number=number, expedited=False) + except Container.DoesNotExist: + return None \ No newline at end of file diff --git a/common/views.py b/common/views.py index 84d84ea..5b35048 100644 --- a/common/views.py +++ b/common/views.py @@ -1,6 +1,6 @@ from django.urls import reverse_lazy from django.views.generic import TemplateView, RedirectView -from django.shortcuts import render, redirect +from django.shortcuts import render # Create your views here. @@ -20,13 +20,18 @@ class DashboardRedirectView(RedirectView): is_permanent = False def get_redirect_url(self, *args, **kwargs): - if 1==1: - return reverse_lazy('client_dashboard') - return reverse_lazy('client_dashboard') + # if self.request.user.is_authenticated: + if self.request.user.username == 'client': + return reverse_lazy('client_dashboard') + elif self.request.user.username == 'clientadmin': + return reverse_lazy('client_dashboard') + elif self.request.user.username == 'barrier': + return reverse_lazy('barrier_dashboard') + return reverse_lazy('index') class ClientDashboardView(TemplateView): - template_name = 'client-dashboard.html' + template_name = 'client-dashboard-content.html' extra_context = { 'title': 'Client Dashboard', 'description': 'This is the client dashboard page.', @@ -35,12 +40,22 @@ class ClientDashboardView(TemplateView): def get(self, request, *args, **kwargs): return render(request, self.template_name, self.extra_context) -class ClientPreinfoView(TemplateView): - template_name = 'client-preinfo.html' +class BarrierDashboardView(TemplateView): + template_name = 'barrier-dashboard.html' extra_context = { - 'title': 'Client Preinfo', - 'description': 'This is the client preinfo page.', + 'title': 'Client Dashboard', + 'description': 'This is the client dashboard page.', } def get(self, request, *args, **kwargs): - return render(request, self.template_name, self.extra_context) \ No newline at end of file + return render(request, self.template_name, self.extra_context) + + + +# class ClientPreinfoView(TemplateView): +# template_name = 'client-preinfo-content.html' +# +# +# +# def get(self, request, *args, **kwargs): +# return render(request, self.template_name, self.extra_context) \ No newline at end of file diff --git a/containers/forms.py b/containers/forms.py new file mode 100644 index 0000000..7de5e0f --- /dev/null +++ b/containers/forms.py @@ -0,0 +1,33 @@ +from django.forms import ModelForm + +from containers.models import Container + + +class ContainerBaseForm(ModelForm): + class Meta: + model = Container + fields = '__all__' + +class ContainerReceiveForm(ContainerBaseForm): + """ + Form for creating a new Container instance. + Inherits from ContainerBaseForm. + """ + class Meta(ContainerBaseForm.Meta): + fields = ['number', 'receive_vehicle', 'damages', 'heavy_damaged', 'position',] + + + + +class ContainerExpeditionForm(ContainerBaseForm): + """ + Form for updating an existing Container instance. + Inherits from ContainerBaseForm. + """ + class Meta(ContainerBaseForm.Meta): + exclude = ['created_on', + 'created_by', + 'deleted', + 'deleted_on', + 'deleted_by', + 'received'] # Exclude fields that should not be set by the user \ No newline at end of file diff --git a/containers/migrations/0001_initial.py b/containers/migrations/0001_initial.py deleted file mode 100644 index 3b84ca0..0000000 --- a/containers/migrations/0001_initial.py +++ /dev/null @@ -1,112 +0,0 @@ -# Generated by Django 5.2.3 on 2025-06-25 12:33 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ("booking", "0001_initial"), - ("common", "0001_initial"), - ] - - operations = [ - migrations.CreateModel( - name="Container", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("number", models.CharField(max_length=11)), - ("received_on", models.DateTimeField(auto_now_add=True)), - ("received_by", models.IntegerField()), - ( - "receive_vehicles", - models.CharField(blank=True, max_length=100, null=True), - ), - ("damages", models.TextField(blank=True, null=True)), - ("heavy_damaged", models.BooleanField(default=False)), - ("position", models.CharField(blank=True, max_length=100, null=True)), - ("swept", models.BooleanField(default=False)), - ("swept_on", models.DateTimeField(blank=True, null=True)), - ("swept_by", models.IntegerField(blank=True, null=True)), - ("washed", models.BooleanField(default=False)), - ("washed_on", models.DateTimeField(blank=True, null=True)), - ("washed_by", models.IntegerField(blank=True, null=True)), - ("expedited", models.BooleanField(default=False)), - ("expedited_on", models.DateTimeField(blank=True, null=True)), - ("expedited_by", models.IntegerField(blank=True, null=True)), - ( - "expedition_vehicle", - models.CharField(blank=True, max_length=100, null=True), - ), - ( - "booking", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="container_bookings", - to="booking.bookingmodel", - ), - ), - ( - "container_type", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="container_container_types", - to="common.containertypemodel", - ), - ), - ( - "line_id", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="container_lines", - to="common.linesmodel", - ), - ), - ], - ), - migrations.CreateModel( - name="ContainerHistory", - fields=[ - ( - "container_ptr", - models.OneToOneField( - auto_created=True, - on_delete=django.db.models.deletion.CASCADE, - parent_link=True, - primary_key=True, - serialize=False, - to="containers.container", - ), - ), - ("operation_date", models.DateTimeField(auto_now_add=True)), - ( - "container", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="history_containers", - to="containers.container", - ), - ), - ( - "operation", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="history_operations", - to="common.operationmodel", - ), - ), - ], - bases=("containers.container",), - ), - ] diff --git a/containers/models.py b/containers/models.py index 21f6d12..ae4b11a 100644 --- a/containers/models.py +++ b/containers/models.py @@ -4,7 +4,7 @@ from common.models import LinesModel, ContainerTypeModel # Create your models here. class Container(models.Model): number = models.CharField(max_length=11) - line_id = models.ForeignKey( + line = models.ForeignKey( LinesModel, on_delete=models.CASCADE, related_name='container_lines', @@ -15,25 +15,49 @@ class Container(models.Model): related_name='container_container_types', ) received_on = models.DateTimeField(auto_now_add=True) - received_by = models.IntegerField() - receive_vehicles = models.CharField(max_length=100, blank=True, null=True) + received_by = models.ForeignKey( + 'accounts.DepotUser', + on_delete=models.CASCADE, + related_name='container_received_by', + ) + receive_vehicle = models.CharField(max_length=100, blank=True, null=True) damages = models.TextField(blank=True, null=True) heavy_damaged = models.BooleanField(default=False) position = models.CharField(max_length=100, blank=True, null=True) swept = models.BooleanField(default=False) swept_on = models.DateTimeField(blank=True, null=True) - swept_by = models.IntegerField(blank=True, null=True) + swept_by = models.ForeignKey( + 'accounts.DepotUser', + on_delete=models.CASCADE, + related_name='container_swept_by', + blank=True, + null=True + ) washed = models.BooleanField(default=False) washed_on = models.DateTimeField(blank=True, null=True) - washed_by = models.IntegerField(blank=True, null=True) + washed_by = models.ForeignKey( + 'accounts.DepotUser', + on_delete=models.CASCADE, + related_name='container_washed_by', + blank=True, + null=True + ) booking = models.ForeignKey( 'booking.BookingModel', on_delete=models.CASCADE, related_name='container_bookings', + blank = True, + null = True ) expedited = models.BooleanField(default=False) expedited_on = models.DateTimeField(blank=True, null=True) - expedited_by = models.IntegerField(blank=True, null=True) + expedited_by = models.ForeignKey( + 'accounts.DepotUser', + on_delete=models.CASCADE, + related_name='container_expedited_by', + blank=True, + null=True + ) expedition_vehicle = models.CharField(max_length=100, blank=True, null=True) diff --git a/containers/urls.py b/containers/urls.py new file mode 100644 index 0000000..6542082 --- /dev/null +++ b/containers/urls.py @@ -0,0 +1,11 @@ +from django.urls import include, path + +from containers.views import ContainerReceive, ContainerExpedition, ContainerSearchView + +urlpatterns = [ + path('search', ContainerSearchView.as_view(), name='container_search'), + path('/', include([ + path('receive', ContainerReceive.as_view(), name='container_receive'), + path('expedition', ContainerExpedition.as_view(), name='container_expedition'), + ])), +] \ No newline at end of file diff --git a/containers/views.py b/containers/views.py index 91ea44a..d24867b 100644 --- a/containers/views.py +++ b/containers/views.py @@ -1,3 +1,98 @@ -from django.shortcuts import render +from django.shortcuts import render, redirect +from django.urls import reverse_lazy +from django.views import View +from django.views.generic import CreateView, UpdateView, FormView + +from common.utils import get_container_by_number +from containers.forms import ContainerReceiveForm, ContainerExpeditionForm +from containers.models import Container +from preinfo.models import Preinfo + # Create your views here. +class ContainerReceive(CreateView): + template_name = 'container-receive.html' + model = Container + form_class = ContainerReceiveForm + success_url = reverse_lazy('dashboard') + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + pk = self.kwargs.get('pk') + try: + preinfo =Preinfo.objects.filter(pk=pk, received=False).first() + except Preinfo.DoesNotExist: + preinfo = None + + if preinfo: + context['preinfo'] = preinfo + context['containers'] = Container.objects.order_by('-received_on').all()[:10] # Fetch the last 10 containers + return context + return redirect(reverse_lazy('container_search')) + + def form_valid(self, form): + + # Get the preinfo_id from the POST data + preinfo_id = self.request.POST.get('preinfo_id') + try: + preinfo = Preinfo.objects.get(id=preinfo_id) + except Preinfo.DoesNotExist: + preinfo = None + + # validate if data is correct, comparing user data with preinfo data + if preinfo and preinfo.container_number == form.cleaned_data.get('number') and not preinfo.received: + preinfo.received = True + preinfo.save() + + form.instance.received_by = self.request.user + form.instance.line = preinfo.line + form.instance.container_type = preinfo.container_type + else: + form.add_error('number', 'Invalid data') + + return super().form_valid(form) + + +class ContainerSearchView(View): + template_name = 'container-search.html' + + def get(self, request): + return render(request, self.template_name) + + def post(self, request): + number = request.POST.get('number') + container = get_container_by_number(number) + if container: + if container.booking: + next_url = request.POST.get('param') + return redirect(next_url, pk=container.booking.pk) + else: + return render(request, self.template_name, {'error': 'Booking not found'}) + + return render(request, self.template_name, {'error': 'Not found'}) + + +class ContainerExpedition(UpdateView): + template_name = 'container-expedition.html' + model = Container + form_class = ContainerExpeditionForm + success_url = reverse_lazy('dashboard') + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + pk = self.kwargs.get('pk') + try: + preinfo =Preinfo.objects.filter(pk=pk, received=False).first() + except Preinfo.DoesNotExist: + preinfo = None + + if preinfo: + context['preinfo'] = preinfo + context['containers'] = Container.objects.order_by('-received_on').all()[:10] # Fetch the last 10 containers + return context + return redirect(reverse_lazy('container_search')) + + + + + diff --git a/preinfo/forms.py b/preinfo/forms.py new file mode 100644 index 0000000..ed4d5a2 --- /dev/null +++ b/preinfo/forms.py @@ -0,0 +1,24 @@ +from django.forms import ModelForm +from django.urls import reverse_lazy + +from preinfo.models import Preinfo + + +class PreinfoBaseForm(ModelForm): + class Meta: + model = Preinfo + fields = '__all__' + + # success_url = reverse_lazy('client_preinfo') +class PreinfoCreateForm(PreinfoBaseForm): + """ + Form for creating a new PreinfoModel instance. + Inherits from PreinfoBaseForm. + """ + class Meta(PreinfoBaseForm.Meta): + exclude = ['created_on', + 'created_by', + 'deleted', + 'deleted_on', + 'deleted_by', + 'received'] # Exclude fields that should not be set by the user \ No newline at end of file diff --git a/preinfo/models.py b/preinfo/models.py index 427b9f5..03ffb98 100644 --- a/preinfo/models.py +++ b/preinfo/models.py @@ -1,7 +1,7 @@ from django.db import models # Create your models here. -class PreinfoModel(models.Model): +class Preinfo(models.Model): container_number = models.CharField( max_length=11, ) @@ -17,18 +17,19 @@ class PreinfoModel(models.Model): ) created_on = models.DateTimeField(auto_now_add=True) created_by = models.ForeignKey( - 'users.DepotUser', + 'accounts.DepotUser', on_delete=models.CASCADE, related_name='preinfo_created_by', db_column='created_by_id', # Ensure the column name matches your database schema ) deleted = models.BooleanField(default=False, null=False) deleted_by = models.ForeignKey( - 'users.DepotUser', + 'accounts.DepotUser', on_delete=models.CASCADE, related_name='preinfo_deleted_by', db_column='deleted_by_id', # Ensure the column name matches your database schema null=True, + blank=True ) - deleted_on = models.DateTimeField(null=True) + deleted_on = models.DateTimeField(null=True, blank=True) received = models.BooleanField(default=False, null=False) diff --git a/preinfo/urls.py b/preinfo/urls.py new file mode 100644 index 0000000..361a691 --- /dev/null +++ b/preinfo/urls.py @@ -0,0 +1,8 @@ +from django.urls import path +from preinfo.views import ClientPreinfoView, check_preinfo, PreinfoSearchView + +urlpatterns = [ + path('client/', ClientPreinfoView.as_view(), name='client_preinfo'), + path('check-preinfo/', check_preinfo, name='check_preinfo'), + path('preinfo-search/', PreinfoSearchView.as_view(), name='preinfo_search'), +] \ No newline at end of file diff --git a/preinfo/views.py b/preinfo/views.py index 91ea44a..6619cb4 100644 --- a/preinfo/views.py +++ b/preinfo/views.py @@ -1,3 +1,82 @@ -from django.shortcuts import render +from django.contrib.auth import get_user_model +from django.contrib.auth.mixins import LoginRequiredMixin +from django.forms import forms +from django.forms.widgets import HiddenInput +from django.http import JsonResponse +from django.shortcuts import render, redirect +from django.urls import reverse_lazy +from django.views import View +from django.views.generic import TemplateView, FormView, CreateView -# Create your views here. +from common.utils import filter_queryset_by_user, get_preinfo_by_number +from preinfo.forms import PreinfoBaseForm, PreinfoCreateForm +from preinfo.models import Preinfo + + + +class ClientPreinfoView(LoginRequiredMixin, CreateView): + template_name = 'client-preinfo-content.html' + form_class = PreinfoCreateForm + success_url = reverse_lazy('client_preinfo') + model = Preinfo + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + queryset = self.model.objects.all().order_by('-created_on') + user = self.request.user +# !!! important + queryset = filter_queryset_by_user( queryset, user)[:10] +# !!! important + + context['recent'] = queryset + return context + + def get_form(self, form_class=None): + form = super().get_form(form_class) + user = self.request.user + + # If user has a specific line, limit the line choices + if user.line: + form.fields['line'].queryset = form.fields['line'].queryset.filter(pk=user.line.pk) + form.fields['line'].initial = user.line + form.fields['line'].widget.attrs['disabled'] = True + # Keep the value when form is submitted + # form.fields['line'].widget = HiddenInput() + + return form + + + def form_valid(self, form): + form.instance.created_by = self.request.user + return super().form_valid(form) + + +# Check if a preinfo exists for the given container number +def check_preinfo(request): + number = request.GET.get('number') + preinfo = Preinfo.objects.filter(container_number=number, received=False).first() + if preinfo: + return JsonResponse({ + 'found': True, + 'line': preinfo.line.name, + 'container_type': preinfo.container_type.name, + 'preinfo_id': preinfo.id, + }) + return JsonResponse({'found': False}) + + +class PreinfoSearchView(View): + template_name = 'container-search.html' + + def get(self, request): + return render(request, self.template_name) + + def post(self, request): + number = request.POST.get('number') + + preinfo = get_preinfo_by_number(number) + if preinfo: + next_url = request.POST.get('param') + return redirect(next_url, pk=preinfo.pk) + + return render(request, self.template_name, {'error': 'Not found'}) \ No newline at end of file diff --git a/static/styles/chatgpt/styles.css b/static/styles/chatgpt/styles.css new file mode 100644 index 0000000..e29c32e --- /dev/null +++ b/static/styles/chatgpt/styles.css @@ -0,0 +1,92 @@ +/* === Layout === */ +.layout-root { + display: flex; + height: 100vh; + overflow: hidden; +} + +/* === Sidebar === */ +.sidebar { + width: 16rem; + height: 100%; + color: white; + display: flex; + flex-direction: column; + background: linear-gradient(180deg, #0f4c81 0%, #1a6baf 100%); + transition: all 0.3s; +} +.sidebar-header { + padding: 1.25rem; + border-bottom: 1px solid #2b6cb0; +} +.sidebar-title { + font-size: 1.25rem; + font-weight: 700; +} +.sidebar-subtitle { + font-size: 0.875rem; + color: #bfdbfe; +} +.nav-section { + padding: 1rem 0; + flex-grow: 1; +} +.nav-label { + padding: 0.5rem 1rem; + font-size: 0.75rem; + text-transform: uppercase; + color: #93c5fd; + letter-spacing: 0.05em; +} +.nav-item { + display: flex; + align-items: center; + padding: 0.75rem 1.5rem; + color: white; + transition: all 0.2s; + text-decoration: none; +} +.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; +} +.nav-icon { + width: 1.25rem; + height: 1.25rem; + margin-right: 0.75rem; +} +.user-profile { + padding: 1rem; + border-top: 1px solid #2b6cb0; + display: flex; + align-items: center; +} +.user-avatar { + width: 2.5rem; + height: 2.5rem; + border-radius: 9999px; + background-color: #3b82f6; + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + color: white; +} +.user-details { + margin-left: 0.75rem; +} +.user-name { + font-size: 0.875rem; + font-weight: 500; +} +.user-role { + font-size: 0.75rem; + color: #bfdbfe; +} +.logout-button { + margin-left: auto; + color: white; +} diff --git a/static/styles/styles.css b/static/styles/styles.css index ce4f9f1..066493a 100644 --- a/static/styles/styles.css +++ b/static/styles/styles.css @@ -196,3 +196,5 @@ input[type="password"]:focus { width: 1.5rem; height: 1.5rem; } + + diff --git a/templates/barrier-dashboard.html b/templates/barrier-dashboard.html new file mode 100644 index 0000000..cdb0d15 --- /dev/null +++ b/templates/barrier-dashboard.html @@ -0,0 +1,124 @@ + + + + + + Line Operator Dashboard | Container Depot + + + + +{% load static %} + + + + \ No newline at end of file diff --git a/templates/chatgpt/zzz.html b/templates/chatgpt/zzz.html new file mode 100644 index 0000000..4629380 --- /dev/null +++ b/templates/chatgpt/zzz.html @@ -0,0 +1,232 @@ + + + + + + Line Operator Dashboard | Container Depot + + + + + + +
+
+
+
+

Dashboard

+
+
+ + +
+
+
+ +
+
+
+
+ + + +
+
+

Active Containers

+

42

+

+3 since last week

+
+
+ +
+
+ + + +
+
+

Preinfo Sent

+

18

+

+5 since last week

+
+
+ +
+
+ + + +
+
+

Pending Orders

+

7

+

2 require attention

+
+
+
+
+
+
+
+

Recent Container Activity

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ContainerTypeStatusDate
MSCU123456740HCReceived2023-06-15
MSCU765432120DVPreinfo2023-06-14
MSCU246813540DVOrder2023-06-13
MSCU135792420RFExpedited2023-06-12
+
+ +
+
+

Payment Status

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
InvoiceAmountStatusDue Date
INV-2023-0042$1,250.00Paid2023-06-10
INV-2023-0041$875.50Pending2023-06-20
INV-2023-0040$2,100.00Overdue2023-06-05
INV-2023-0039$950.25Paid2023-05-28
+
+
+ +
+ + + diff --git a/templates/client-base.html b/templates/client-base.html new file mode 100644 index 0000000..8790747 --- /dev/null +++ b/templates/client-base.html @@ -0,0 +1,194 @@ +{% load static %} + + + + + + Line Operator Dashboard | Container Depot + + + + + + {% include 'sidebar.html' %} + +
+ +
+
+
+

Dashboard

+
+
+ + +
+
+
+ + +
+ {% block content %} +{# {% include 'client-dashboard-content.html' %}#} +{# {% include 'client-preinfo-content.html' %}#} +{# {% include 'client-orders-content.html' %}#} + {% endblock content %} +
+
+ +{# #} +{##} + + diff --git a/templates/client-booking-content.html b/templates/client-booking-content.html new file mode 100644 index 0000000..0b12224 --- /dev/null +++ b/templates/client-booking-content.html @@ -0,0 +1,63 @@ +{% extends 'client-base.html' %} +{% block content %} + +
+
+
+

Submit Container Preinfo

+

Provide information about containers that will arrive at the depot

+
+
+
+ + {{ form.as_p }} + {% csrf_token %} + +
+ +
+
+
+
+ +
+
+

Recent Preinfo Submissions

+
+
+
+ + + + + + + + + + + + {% for preinfo in recent %} + + + + + + + + + {% endfor %} + +
ContainerTypeEst. ArrivalStatusActions
{{ preinfo.container_number }}{{ preinfo.container_type }}{{ preinfo.created_on }} + Pending + + + +
+
+
+
+
+{% endblock content %} \ No newline at end of file diff --git a/templates/client-dashboard-content.html b/templates/client-dashboard-content.html new file mode 100644 index 0000000..944e180 --- /dev/null +++ b/templates/client-dashboard-content.html @@ -0,0 +1,162 @@ +{% extends 'client-base.html' %} +{% block content %} + +
+
+
+
+
+ + + +
+
+

Active Containers

+

42

+

+3 since last week

+
+
+
+ +
+
+
+ + + +
+
+

Preinfo Sent

+

18

+

+5 since last week

+
+
+
+ +
+
+
+ + + +
+
+

Pending Orders

+

7

+

2 require attention

+
+
+
+
+ +
+
+
+

Recent Container Activity

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ContainerTypeStatusDate
MSCU123456740HC + Received + 2023-06-15
MSCU765432120DV + Preinfo + 2023-06-14
MSCU246813540DV + Order + 2023-06-13
MSCU135792420RF + Expedited + 2023-06-12
+
+
+
+ +
+
+

Payment Status

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
InvoiceAmountStatusDue Date
INV-2023-0042$1,250.00 + Paid + 2023-06-10
INV-2023-0041$875.50 + Pending + 2023-06-20
INV-2023-0040$2,100.00 + Overdue + 2023-06-05
INV-2023-0039$950.25 + Paid + 2023-05-28
+
+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/templates/client-dashboard.html b/templates/client-dashboard.html deleted file mode 100644 index f2169b9..0000000 --- a/templates/client-dashboard.html +++ /dev/null @@ -1,689 +0,0 @@ - - - - - - - - Line Operator Dashboard | Container Depot - - - - - - - - -
- -
-
-
-

Dashboard

-
-
- - -
-
-
- - -
- -
-
-
-
-
- - - -
-
-

Active Containers

-

42

-

+3 since last week

-
-
-
- -
-
-
- - - -
-
-

Preinfo Sent

-

18

-

+5 since last week

-
-
-
- -
-
-
- - - -
-
-

Pending Orders

-

7

-

2 require attention

-
-
-
-
- -
-
-
-

Recent Container Activity

-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ContainerTypeStatusDate
MSCU123456740HC - Received - 2023-06-15
MSCU765432120DV - Preinfo - 2023-06-14
MSCU246813540DV - Order - 2023-06-13
MSCU135792420RF - Expedited - 2023-06-12
-
-
-
- -
-
-

Payment Status

-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
InvoiceAmountStatusDue Date
INV-2023-0042$1,250.00 - Paid - 2023-06-10
INV-2023-0041$875.50 - Pending - 2023-06-20
INV-2023-0040$2,100.00 - Overdue - 2023-06-05
INV-2023-0039$950.25 - Paid - 2023-05-28
-
-
-
-
-
- - -
-
-
-

Submit Container Preinfo

-

Provide information about containers that will arrive at the depot

-
-
-
-
-
- - -

Enter the full container number including prefix

-
- -
- - -
-
- -
-
- - -
- -
- - -
-
- -
- - -
- -
- - -
- - - -
- - -
-
-
-
- -
-
-

Recent Preinfo Submissions

-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ContainerTypeEst. ArrivalStatusActions
MSCU765432120DV2023-06-18 - Pending - - - -
MSCU987654340HC2023-06-17 - Received - - -
MSCU112233420RF2023-06-16 - Delayed - - - -
-
-
-
-
- - -
-
-
-

Create Expedition Order

-

Request containers to be expedited from the depot

-
-
-
-
- -
-
- - -
-
- - -
-
-
- -
- - -

Enter the full container number including prefix

-
- - - -
-
- - -
- -
- - -
-
- -
- -
- - -
-
- -
- - -
- -
- -
-
-
-
- -
-
-

Active Expedition Orders

-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Order IDContainerPickup DateStatusActions
ORD-2023-0015MSCU24681352023-06-20 - Approved - - - -
ORD-2023-0014Any 40HC2023-06-19 - Pending - - - -
ORD-2023-0013MSCU13579242023-06-15 - Completed - - -
-
-
-
-
-
-
- - - - diff --git a/templates/client-orders-content.html b/templates/client-orders-content.html new file mode 100644 index 0000000..d382ce9 --- /dev/null +++ b/templates/client-orders-content.html @@ -0,0 +1,151 @@ +{% extends 'client-base.html' %} +{% block content %} +
+
+
+

Create Expedition Order

+

Request containers to be expedited from the depot

+
+
+
+
+ +
+
+ + +
+
+ + +
+
+
+ +
+ + +

Enter the full container number including prefix

+
+ + + +
+
+ + +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ + +
+ +
+ +
+
+
+
+ +
+
+

Active Expedition Orders

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Order IDContainerPickup DateStatusActions
ORD-2023-0015MSCU24681352023-06-20 + Approved + + + +
ORD-2023-0014Any 40HC2023-06-19 + Pending + + + +
ORD-2023-0013MSCU13579242023-06-15 + Completed + + +
+
+
+
+
+{% endblock content %} diff --git a/templates/client-preinfo-content.html b/templates/client-preinfo-content.html new file mode 100644 index 0000000..bfc63b8 --- /dev/null +++ b/templates/client-preinfo-content.html @@ -0,0 +1,139 @@ +{% extends 'client-base.html' %} +{% block content %} + +
+
+
+

Submit Container Preinfo

+

Provide information about containers that will arrive at the depot

+
+
+
+ + {{ form.as_p }} + {% csrf_token %} +{#
#} +{#
#} +{# #} +{# #} +{#

Enter the full container number including prefix

#} +{#
#} +{##} +{#
#} +{# #} +{# #} +{#
#} +{#
#} +{##} +{#
#} +{#
#} +{# #} +{# #} +{#
#} +{##} +{#
#} +{# #} +{# #} +{#
#} +{#
#} +{##} +{#
#} +{# #} +{# #} +{#
#} +{##} +{#
#} +{# #} +{# #} +{#
#} +{##} +{# #} + +
+ + +
+
+
+
+ +
+
+

Recent Preinfo Submissions

+
+
+
+ + + + + + + + + + + + {% for preinfo in recent %} + + + + + + + + + {% endfor %} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} + +
ContainerTypeEst. ArrivalStatusActions
{{ preinfo.container_number }}{{ preinfo.container_type }}{{ preinfo.created_on }} + Pending + + + +
MSCU987654340HC2023-06-17#} +{# Received#} +{# #} +{# #} +{#
MSCU112233420RF2023-06-16#} +{# Delayed#} +{# #} +{# #} +{# #} +{#
+
+
+
+
+{% endblock content %} \ No newline at end of file diff --git a/templates/barrier receive.html b/templates/container-expedition.html similarity index 59% rename from templates/barrier receive.html rename to templates/container-expedition.html index af8ffc0..c64f61e 100644 --- a/templates/barrier receive.html +++ b/templates/container-expedition.html @@ -112,66 +112,7 @@ - +
@@ -198,244 +139,6 @@ - -
-
-
-
-

Container Reception

-

Process incoming containers

-
-
- Gate Open -
-
-
-
-
-
- -
- - -
-

Enter the full container number including prefix

-
- -
- - -
-
- - - -
-
-
- -
-
-

Recent Container Movements

-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ContainerTypeLineTimeDirectionStatus
MSCU123456740HCMaersk10:15 AMIN - Complete -
CMAU765432120DVCMA CGM09:42 AMOUT - Complete -
OOLU246813540DVONE09:15 AMIN - Complete -
HLXU135792420RFHapag-Lloyd08:30 AMOUT - Complete -
-
-
-
-
-
diff --git a/templates/barrier expedition.html b/templates/container-receive-original.html similarity index 100% rename from templates/barrier expedition.html rename to templates/container-receive-original.html diff --git a/templates/container-receive.html b/templates/container-receive.html new file mode 100644 index 0000000..1e1ef7c --- /dev/null +++ b/templates/container-receive.html @@ -0,0 +1,593 @@ + + + + + + + + Barrier Staff Interface | Container Depot + + + + + + + + +
+ +
+
+
+

Receive Container

+
+
+
+ + + 3 + + +
+ Gate North +
+
+
+ + +
+
+
+
+

Container Reception

+

Process incoming containers

+
+
+ Gate Open +
+
+
+ {% csrf_token %} +
+ +{# #} +{# #} +{# #} + + + +{# #} +{#
#} +{# #} +{# #} +{#
#} + + + +
+ + +
+
+
+
+ + + +
+
+

Preinfo Found

+
+
+
+
+ Container Number: + +
+
+ Container Type: + +
+
+ Line Operator: + +
+
+
+ {#

Notes: Container reported with minor damage on right side panel.

#} +
+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+ + + +
+
+ +
+
+

Recent Container Movements

+
+
+
+ + + + + + + +{# #} +{# #} + + + + {% for container in containers %} + + + + + +{# #} +{# #} + + {% endfor %} + +
ContainerTypeLineTimeDirectionStatus
+ {{ container.number }}{{ container.container_type }}{{ container.line.name }}{{ container.received_on }}IN#} +{# Complete#} +{#
+
+
+
+
+ + +
+ + +
+
+
+

Take Container Photo

+ +
+ +
+
+
+ + + + + + +
+ + +
+
+
+
+
+
+
+ +
+ +
+
+
+ +{# #} +{##} +{##} +{##} + + diff --git a/templates/container-search.html b/templates/container-search.html new file mode 100644 index 0000000..643e271 --- /dev/null +++ b/templates/container-search.html @@ -0,0 +1,131 @@ + + + + + + Barrier Staff Interface | Container Depot + + + + +
+ {% csrf_token %} +
+ +
+ + + + {% if error %} +
+ {{ error }} +
+ {% endif %} +
+
+
+ + \ No newline at end of file diff --git a/templates/preinfo-search.html b/templates/preinfo-search.html new file mode 100644 index 0000000..0e2a9fc --- /dev/null +++ b/templates/preinfo-search.html @@ -0,0 +1,126 @@ + + + + + + Barrier Staff Interface | Container Depot + + + + +
+ {% csrf_token %} +
+ +
+ + + +
+
+
+ + \ No newline at end of file diff --git a/templates/registration/login.html b/templates/registration/login.html new file mode 100644 index 0000000..c39460b --- /dev/null +++ b/templates/registration/login.html @@ -0,0 +1,96 @@ +{% load static %} + + + + + + Container Depot Management System + + + +{# {{ title|default:"Container Depot Management System" }} {{ description|default:"Login to the Container Depot Management System" }}#} +
+
+ + + + \ No newline at end of file diff --git a/templates/sidebar.html b/templates/sidebar.html new file mode 100644 index 0000000..a1b5803 --- /dev/null +++ b/templates/sidebar.html @@ -0,0 +1,61 @@ +{% load static %} + diff --git a/users/admin.py b/users/admin.py deleted file mode 100644 index 8c38f3f..0000000 --- a/users/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/users/forms.py b/users/forms.py deleted file mode 100644 index bc46453..0000000 --- a/users/forms.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.forms import forms - - -class LoginForm(forms.Form): - field_order = ['username', 'password'] \ No newline at end of file diff --git a/users/models.py b/users/models.py deleted file mode 100644 index abb6a9a..0000000 --- a/users/models.py +++ /dev/null @@ -1,21 +0,0 @@ -from django.contrib.auth.models import AbstractUser -from django.db import models - -class DepotUser(AbstractUser): - USER_TYPES = ( - ('management', 'Management'), - ('barrier', 'Barrier Staff'), - ('client', 'Client'), - ) - user_type = models.CharField(max_length=20, choices=USER_TYPES, default='client') - - # Add any other fields you want - phone_number = models.CharField(max_length=15, blank=True, null=True) - email = models.EmailField(unique=True, blank=False, null=False) - line = models.ForeignKey( - 'common.LinesModel', - on_delete=models.CASCADE, - related_name='user_lines', - blank=True, - null=True - ) \ No newline at end of file diff --git a/users/urls.py b/users/urls.py deleted file mode 100644 index 4d2fe64..0000000 --- a/users/urls.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.urls import path - -from users import views - -urlpatterns = [ - path('login/', views.LoginView.as_view(), name='login'), -] \ No newline at end of file diff --git a/users/views.py b/users/views.py deleted file mode 100644 index d0a8dcc..0000000 --- a/users/views.py +++ /dev/null @@ -1,12 +0,0 @@ -from django.shortcuts import render -from django.urls import reverse_lazy -from django.views.generic import TemplateView, FormView - -from users.forms import LoginForm - - -# Create your views here. -class LoginView(FormView): - template_name = 'logintest.html' - success_url = reverse_lazy('dashboard') - form_class = LoginForm \ No newline at end of file