some fields validation and model cleaning
This commit is contained in:
Generated
+1
-1
@@ -16,7 +16,7 @@
|
|||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.13 (DepoT)" jdkType="Python SDK" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
<component name="TemplatesService">
|
<component name="TemplatesService">
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="dataSourceStorageLocal" created-in="PY-251.26927.74">
|
<component name="dataSourceStorageLocal" created-in="PY-242.23339.19">
|
||||||
<data-source name="depot@localhost" uuid="2186be09-0cb1-4210-bad0-d279af5e6702">
|
<data-source name="depot@localhost" uuid="2186be09-0cb1-4210-bad0-d279af5e6702">
|
||||||
<database-info product="PostgreSQL" version="17.4" jdbc-version="4.2" driver-name="PostgreSQL JDBC Driver" driver-version="42.7.3" dbms="POSTGRES" exact-version="17.4" exact-driver-version="42.7">
|
<database-info product="PostgreSQL" version="17.4" jdbc-version="4.2" driver-name="PostgreSQL JDBC Driver" driver-version="42.7.3" dbms="POSTGRES" exact-version="17.4" exact-driver-version="42.7">
|
||||||
<identifier-quote-string>"</identifier-quote-string>
|
<identifier-quote-string>"</identifier-quote-string>
|
||||||
|
|||||||
Generated
+1
@@ -3,4 +3,5 @@
|
|||||||
<component name="Black">
|
<component name="Black">
|
||||||
<option name="sdkName" value="Python 3.13 (DepoT)" />
|
<option name="sdkName" value="Python 3.13 (DepoT)" />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 (depot_django)" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
||||||
Generated
+28
-30
@@ -5,14 +5,18 @@
|
|||||||
</component>
|
</component>
|
||||||
<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 afterPath="$PROJECT_DIR$/common/fields.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/DepoT.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/DepoT.iml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/dataSources.local.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/dataSources.local.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/DepoT/settings/development.py" beforeDir="false" afterPath="$PROJECT_DIR$/DepoT/settings/development.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/booking/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/booking/models.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/DepoT/settings/production.py" beforeDir="false" afterPath="$PROJECT_DIR$/DepoT/settings/production.py" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/booking/tests.py" beforeDir="false" afterPath="$PROJECT_DIR$/booking/tests.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/booking/tests.py" beforeDir="false" afterPath="$PROJECT_DIR$/booking/tests.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/client_views.py" beforeDir="false" afterPath="$PROJECT_DIR$/booking/views/client_views.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/common/migrations/0004_populate_initial_data.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/migrations/0004_populate_initial_data.py" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/common/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/models.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/common/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/models.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/images/web_depot.tar" beforeDir="false" afterPath="$PROJECT_DIR$/images/web_depot.tar" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/containers/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/containers/models.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/payments/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/payments/models.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/preinfo/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/preinfo/models.py" 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" />
|
||||||
@@ -67,6 +71,7 @@
|
|||||||
"node.js.selected.package.eslint": "(autodetect)",
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
"node.js.selected.package.tslint": "(autodetect)",
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
"nodejs_package_manager_path": "npm",
|
"nodejs_package_manager_path": "npm",
|
||||||
|
"settings.editor.selected.configurable": "preferences.editor",
|
||||||
"vue.rearranger.settings.migration": "true"
|
"vue.rearranger.settings.migration": "true"
|
||||||
},
|
},
|
||||||
"keyToStringList": {
|
"keyToStringList": {
|
||||||
@@ -91,7 +96,7 @@
|
|||||||
<recent name="C:\dev_projects\python\Django\DepoT\templates\employee" />
|
<recent name="C:\dev_projects\python\Django\DepoT\templates\employee" />
|
||||||
</key>
|
</key>
|
||||||
</component>
|
</component>
|
||||||
<component name="RunManager" selected="Django tests.Test: booking.tests.BookingViewsTestCase">
|
<component name="RunManager" selected="Django Server.DepoT">
|
||||||
<configuration name="Test: booking.tests.BookingViewsTestCase" type="DjangoTestsConfigurationType" temporary="true">
|
<configuration name="Test: booking.tests.BookingViewsTestCase" type="DjangoTestsConfigurationType" temporary="true">
|
||||||
<module name="DepoT" />
|
<module name="DepoT" />
|
||||||
<option name="ENV_FILES" value="" />
|
<option name="ENV_FILES" value="" />
|
||||||
@@ -101,9 +106,10 @@
|
|||||||
<env name="PYTHONUNBUFFERED" value="1" />
|
<env name="PYTHONUNBUFFERED" value="1" />
|
||||||
<env name="DJANGO_SETTINGS_MODULE" value="DepoT.settings.development" />
|
<env name="DJANGO_SETTINGS_MODULE" value="DepoT.settings.development" />
|
||||||
</envs>
|
</envs>
|
||||||
<option name="SDK_HOME" value="" />
|
<option name="SDK_HOME" value="$PROJECT_DIR$/.venv/Scripts/python.exe" />
|
||||||
|
<option name="SDK_NAME" value="Python 3.13 (depot_django)" />
|
||||||
<option name="WORKING_DIRECTORY" value="" />
|
<option name="WORKING_DIRECTORY" value="" />
|
||||||
<option name="IS_MODULE_SDK" value="true" />
|
<option name="IS_MODULE_SDK" value="false" />
|
||||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||||
@@ -189,7 +195,7 @@
|
|||||||
<env name="DJANGO_SETTINGS_MODULE" value="DepoT.settings.development" />
|
<env name="DJANGO_SETTINGS_MODULE" value="DepoT.settings.development" />
|
||||||
</envs>
|
</envs>
|
||||||
<option name="SDK_HOME" value="" />
|
<option name="SDK_HOME" value="" />
|
||||||
<option name="SDK_NAME" value="Python 3.13 (DepoT)" />
|
<option name="SDK_NAME" value="Python 3.13 (depot_django)" />
|
||||||
<option name="WORKING_DIRECTORY" value="" />
|
<option name="WORKING_DIRECTORY" value="" />
|
||||||
<option name="IS_MODULE_SDK" value="false" />
|
<option name="IS_MODULE_SDK" value="false" />
|
||||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
@@ -224,8 +230,8 @@
|
|||||||
<component name="SharedIndexes">
|
<component name="SharedIndexes">
|
||||||
<attachedChunks>
|
<attachedChunks>
|
||||||
<set>
|
<set>
|
||||||
<option value="bundled-js-predefined-d6986cc7102b-09060db00ec0-JavaScript-PY-251.26927.74" />
|
<option value="bundled-js-predefined-d6986cc7102b-5c90d61e3bab-JavaScript-PY-242.23339.19" />
|
||||||
<option value="bundled-python-sdk-657d8234b839-64d779b69b7a-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-251.26927.74" />
|
<option value="bundled-python-sdk-0029f7779945-399fe30bd8c1-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-242.23339.19" />
|
||||||
</set>
|
</set>
|
||||||
</attachedChunks>
|
</attachedChunks>
|
||||||
</component>
|
</component>
|
||||||
@@ -247,6 +253,7 @@
|
|||||||
<workItem from="1753637487803" duration="71422000" />
|
<workItem from="1753637487803" duration="71422000" />
|
||||||
<workItem from="1754046655407" duration="19056000" />
|
<workItem from="1754046655407" duration="19056000" />
|
||||||
<workItem from="1754068089083" duration="32822000" />
|
<workItem from="1754068089083" duration="32822000" />
|
||||||
|
<workItem from="1754408990802" duration="7521000" />
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00001" summary="Add IntelliJ IDEA project configuration files 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 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" />
|
||||||
@@ -366,30 +373,20 @@
|
|||||||
<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$/booking/tests.py</url>
|
||||||
|
<line>97</line>
|
||||||
|
<option name="timeStamp" value="127" />
|
||||||
|
</line-breakpoint>
|
||||||
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
||||||
<url>file://$PROJECT_DIR$/booking/tests.py</url>
|
<url>file://$PROJECT_DIR$/booking/tests.py</url>
|
||||||
<line>90</line>
|
<line>90</line>
|
||||||
<option name="timeStamp" value="109" />
|
<option name="timeStamp" value="128" />
|
||||||
</line-breakpoint>
|
</line-breakpoint>
|
||||||
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
||||||
<url>file://$PROJECT_DIR$/booking/tests.py</url>
|
<url>file://$PROJECT_DIR$/booking/tests.py</url>
|
||||||
<line>76</line>
|
<line>11</line>
|
||||||
<option name="timeStamp" value="117" />
|
<option name="timeStamp" value="129" />
|
||||||
</line-breakpoint>
|
|
||||||
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
|
||||||
<url>file://$PROJECT_DIR$/booking/views/client_views.py</url>
|
|
||||||
<line>40</line>
|
|
||||||
<option name="timeStamp" value="119" />
|
|
||||||
</line-breakpoint>
|
|
||||||
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
|
||||||
<url>file://$PROJECT_DIR$/booking/views/client_views.py</url>
|
|
||||||
<line>46</line>
|
|
||||||
<option name="timeStamp" value="120" />
|
|
||||||
</line-breakpoint>
|
|
||||||
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
|
||||||
<url>file://$PROJECT_DIR$/booking/tests.py</url>
|
|
||||||
<line>75</line>
|
|
||||||
<option name="timeStamp" value="121" />
|
|
||||||
</line-breakpoint>
|
</line-breakpoint>
|
||||||
<line-breakpoint enabled="true" type="javascript">
|
<line-breakpoint enabled="true" type="javascript">
|
||||||
<url>file://$PROJECT_DIR$/static/js/container_validation.js</url>
|
<url>file://$PROJECT_DIR$/static/js/container_validation.js</url>
|
||||||
@@ -407,9 +404,10 @@
|
|||||||
</breakpoint-manager>
|
</breakpoint-manager>
|
||||||
</component>
|
</component>
|
||||||
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
||||||
|
<SUITE FILE_PATH="coverage/DepoT$Test__booking_tests_BookingViewsTestCase_test_booking_list_view__user_no_rights__expect_forbidden.coverage" NAME="Test: booking.tests.BookingViewsTestCase.test_booking_list_view__user_no_rights__expect_forbidden Coverage Results" MODIFIED="1754372596969" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
|
||||||
|
<SUITE FILE_PATH="coverage/depot_django$Test__booking_tests_BookingViewsTestCase.coverage" NAME="Test: booking.tests.BookingViewsTestCase Coverage Results" MODIFIED="1754414003823" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
|
||||||
<SUITE FILE_PATH="coverage/DepoT$Test__booking_tests_BookingViewsTestCase_test_booking_list_view.coverage" NAME="Test: booking.tests.BookingViewsTestCase.test_booking_list_view Coverage Results" MODIFIED="1754333059580" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
|
<SUITE FILE_PATH="coverage/DepoT$Test__booking_tests_BookingViewsTestCase_test_booking_list_view.coverage" NAME="Test: booking.tests.BookingViewsTestCase.test_booking_list_view Coverage Results" MODIFIED="1754333059580" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
|
||||||
<SUITE FILE_PATH="coverage/DepoT$Test__booking_tests_BookingViewsTestCase.coverage" NAME="Test: booking.tests.BookingViewsTestCase Coverage Results" MODIFIED="1754386070100" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
|
<SUITE FILE_PATH="coverage/DepoT$Test__booking_tests_BookingViewsTestCase.coverage" NAME="Test: booking.tests.BookingViewsTestCase Coverage Results" MODIFIED="1754386070100" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
|
||||||
<SUITE FILE_PATH="coverage/DepoT$Test__booking_tests_BookingViewsTestCase_test_booking_list_view__user_no_rights__expect_forbidden.coverage" NAME="Test: booking.tests.BookingViewsTestCase.test_booking_list_view__user_no_rights__expect_forbidden Coverage Results" MODIFIED="1754372596969" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
|
|
||||||
<SUITE FILE_PATH="coverage/DepoT$Test__booking_tests_BookingViewsTestCase_test_booking_list_view__user_all_rights__expect_OK.coverage" NAME="Test: booking.tests.BookingViewsTestCase.test_booking_list_view__user_all_rights__expect_OK Coverage Results" MODIFIED="1754372722226" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
|
<SUITE FILE_PATH="coverage/DepoT$Test__booking_tests_BookingViewsTestCase_test_booking_list_view__user_all_rights__expect_OK.coverage" NAME="Test: booking.tests.BookingViewsTestCase.test_booking_list_view__user_all_rights__expect_OK Coverage Results" MODIFIED="1754372722226" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+16
-8
@@ -1,4 +1,8 @@
|
|||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
from accounts.models import DepotUser
|
||||||
|
from common.fields import ContainerNumberField, UpperCaseCharField
|
||||||
from common.models import ContainerTypeModel, LinesModel, OperationModel
|
from common.models import ContainerTypeModel, LinesModel, OperationModel
|
||||||
|
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
@@ -10,15 +14,15 @@ class Booking(models.Model):
|
|||||||
('canceled', 'Canceled'),
|
('canceled', 'Canceled'),
|
||||||
]
|
]
|
||||||
|
|
||||||
number = models.CharField(max_length=50, unique=True)
|
number = UpperCaseCharField(max_length=50)
|
||||||
vehicles = models.CharField(blank=True, null=True)
|
vehicles = UpperCaseCharField(blank=True, null=True)
|
||||||
container_type = models.ForeignKey(
|
container_type = models.ForeignKey(
|
||||||
ContainerTypeModel,
|
ContainerTypeModel,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name='booking_container_types',
|
related_name='booking_container_types',
|
||||||
)
|
)
|
||||||
container_count = models.IntegerField()
|
container_count = models.PositiveIntegerField()
|
||||||
container_expedited_count = models.IntegerField(default=0)
|
container_expedited_count = models.PositiveIntegerField(default=0)
|
||||||
carrier = models.CharField(max_length=100, blank=True, null=True)
|
carrier = models.CharField(max_length=100, blank=True, null=True)
|
||||||
line = models.ForeignKey(
|
line = models.ForeignKey(
|
||||||
LinesModel,
|
LinesModel,
|
||||||
@@ -27,12 +31,12 @@ class Booking(models.Model):
|
|||||||
)
|
)
|
||||||
visible = models.BooleanField(default=True)
|
visible = models.BooleanField(default=True)
|
||||||
is_new = models.BooleanField(default=True)
|
is_new = models.BooleanField(default=True)
|
||||||
container_number = models.CharField(max_length=11, blank=True, null=True)
|
container_number = ContainerNumberField(max_length=11, blank=True, null=True)
|
||||||
vehicles_left = models.CharField(blank=True, null=True)
|
vehicles_left = models.CharField(blank=True, null=True)
|
||||||
created_on = models.DateTimeField(auto_now_add=True)
|
created_on = models.DateTimeField(auto_now_add=True)
|
||||||
created_by = models.IntegerField()
|
created_by = models.ForeignKey(DepotUser, related_name='booking_user', on_delete=models.CASCADE)
|
||||||
updated_on = models.DateTimeField(auto_now=True)
|
updated_on = models.DateTimeField(auto_now=True)
|
||||||
updated_by = models.IntegerField()
|
updated_by = models.ForeignKey(DepotUser, related_name='booking_user', on_delete=models.CASCADE)
|
||||||
status = models.CharField(
|
status = models.CharField(
|
||||||
max_length=10,
|
max_length=10,
|
||||||
choices=STATUS_CHOICES,
|
choices=STATUS_CHOICES,
|
||||||
@@ -44,4 +48,8 @@ class Booking(models.Model):
|
|||||||
return self.container_count - (self.container_expedited_count or 0)
|
return self.container_count - (self.container_expedited_count or 0)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
app_label = 'booking'
|
app_label = 'booking'
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
if Booking.objects.filter(number=self.number, status='active').exclude(id=self.id).exists():
|
||||||
|
raise ValidationError(f'Booking with number {self.number} already exists and is active.')
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
+16
-15
@@ -45,8 +45,8 @@ class BookingViewsTestCase(TestCase):
|
|||||||
line=self.line,
|
line=self.line,
|
||||||
created_by=self.user_employee_all_rights.id,
|
created_by=self.user_employee_all_rights.id,
|
||||||
updated_by=self.user_employee_all_rights.id,
|
updated_by=self.user_employee_all_rights.id,
|
||||||
vehicles='',
|
vehicles='K1,J2,K3',
|
||||||
vehicles_left='',
|
vehicles_left='K1,J2,K3',
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -72,8 +72,8 @@ class BookingViewsTestCase(TestCase):
|
|||||||
self.assertTemplateUsed(response, 'employee/booking-list.html')
|
self.assertTemplateUsed(response, 'employee/booking-list.html')
|
||||||
self.assertContains(response, self.booking.number)
|
self.assertContains(response, self.booking.number)
|
||||||
|
|
||||||
def test_booking_create_view(self):
|
def test_client_create_booking__expect_redirect_to_booking_list_and_booking_in_db(self):
|
||||||
self.assertTrue( self.user_client_all_rights.has_company_perm('can_view_booking'))
|
self.assertTrue( self.user_client_all_rights.has_company_perm('can_manage_booking'))
|
||||||
self.client.login(username=self.user_client_all_rights.username, password=self.user_password)
|
self.client.login(username=self.user_client_all_rights.username, password=self.user_password)
|
||||||
|
|
||||||
response = self.client.post(reverse('client_booking_create'), {
|
response = self.client.post(reverse('client_booking_create'), {
|
||||||
@@ -84,16 +84,17 @@ class BookingViewsTestCase(TestCase):
|
|||||||
'vehicles': 'Truck1,Truck2',
|
'vehicles': 'Truck1,Truck2',
|
||||||
'vehicles_left': 'Truck1,Truck2',
|
'vehicles_left': 'Truck1,Truck2',
|
||||||
})
|
})
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 302)
|
||||||
self.assertTrue(Booking.objects.filter(number='BOOK456').exists())
|
self.assertTrue(Booking.objects.filter(number='BOOK456').exists())
|
||||||
|
|
||||||
# def test_booking_update_view(self):
|
def test_booking_update_view(self):
|
||||||
# response = self.client.post(reverse('booking-update', args=[self.booking.id]), {
|
self.client.login(username=self.user_client_all_rights.username, password=self.user_password)
|
||||||
# 'number': 'BOOK123-updated',
|
response = self.client.post(reverse('client_booking_update', args=[self.booking.id]), {
|
||||||
# 'container_type': self.container_type.id,
|
'number': 'BOOK123-updated',
|
||||||
# 'container_count': 15,
|
'container_type': self.container_type.id,
|
||||||
# 'line': self.line.id,
|
'container_count': 15,
|
||||||
# })
|
'line': self.line.id,
|
||||||
# self.assertEqual(response.status_code, 302)
|
})
|
||||||
# self.booking.refresh_from_db()
|
self.assertEqual(response.status_code, 302)
|
||||||
# self.assertEqual(self.booking.number, 'BOOK123-updated')
|
self.booking.refresh_from_db()
|
||||||
|
self.assertEqual(self.booking.number, 'BOOK123-updated')
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -59,4 +59,4 @@ class ClientBookingUpdateView(LoginRequiredMixin, UserPassesTestMixin, LineFilte
|
|||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
def test_func(self):
|
def test_func(self):
|
||||||
return self.request.user.has_company_perm('can_edit_preinfo') or self.request.user.user_type == 'CA'
|
return self.request.user.has_company_perm('can_manage_booking') or self.request.user.user_type == 'CA'
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,29 @@
|
|||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class UpperCaseCharField(models.CharField):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_prep_value(self, value):
|
||||||
|
value = super().get_prep_value(value)
|
||||||
|
if value is not None:
|
||||||
|
return value.upper()
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class ContainerNumberField(UpperCaseCharField):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_prep_value(self, value):
|
||||||
|
value = super().get_prep_value(value)
|
||||||
|
if value is not None:
|
||||||
|
return value.upper()
|
||||||
|
return value
|
||||||
|
|
||||||
|
def validate(self, value, model_instance):
|
||||||
|
super().validate(value, model_instance)
|
||||||
|
if value and len(value) != 11:
|
||||||
|
raise ValidationError('Container number must be exactly 11 characters long.')
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
+30
-8
@@ -1,22 +1,39 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
|
from common.fields import UpperCaseCharField
|
||||||
|
|
||||||
|
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
class NomenclatureBaseModel(models.Model):
|
class NomenclatureBaseModel(models.Model):
|
||||||
name = models.CharField(max_length=100, unique=True)
|
name = UpperCaseCharField(max_length=100)
|
||||||
short_name = models.CharField(max_length=5, null=True, blank=True)
|
short_name = UpperCaseCharField(max_length=5, null=True, blank=True)
|
||||||
description = models.TextField(blank=True, null=True)
|
description = models.TextField(blank=True, null=True)
|
||||||
active = models.BooleanField(default=True)
|
active = models.BooleanField(default=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
ordering = ['name']
|
ordering = ['name']
|
||||||
app_label = 'common'
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
if not self.name:
|
||||||
|
raise ValidationError('Name cannot be empty.')
|
||||||
|
if self.short_name and len(self.short_name) > 5:
|
||||||
|
raise ValidationError('Short name cannot exceed 5 characters.')
|
||||||
|
if self.description and len(self.description) > 255:
|
||||||
|
raise ValidationError('Description cannot exceed 255 characters.')
|
||||||
|
|
||||||
|
|
||||||
class CompanyModel(NomenclatureBaseModel):
|
class CompanyModel(NomenclatureBaseModel):
|
||||||
class Meta:
|
def clean(self):
|
||||||
app_label = 'common'
|
super().clean()
|
||||||
|
if CompanyModel.objects.filter(name=self.name, active=True).exclude(id=self.id).exists():
|
||||||
|
raise ValidationError(f'Company with name {self.name} already exists and is active.')
|
||||||
|
if CompanyModel.objects.filter(short_name=self.short_name, active=True).exclude(id=self.id).exists():
|
||||||
|
raise ValidationError(f'Company with short name {self.short_name} already exists and is active.')
|
||||||
|
|
||||||
|
|
||||||
class LinesModel(NomenclatureBaseModel):
|
class LinesModel(NomenclatureBaseModel):
|
||||||
@@ -26,8 +43,13 @@ class LinesModel(NomenclatureBaseModel):
|
|||||||
related_name='line_company'
|
related_name='line_company'
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
def clean(self):
|
||||||
app_label = 'common'
|
super().clean()
|
||||||
|
if LinesModel.objects.filter(name=self.name, active=True).exclude(id=self.id).exists():
|
||||||
|
raise ValidationError(f'Line with name {self.name} already exists and is active.')
|
||||||
|
if LinesModel.objects.filter(short_name=self.short_name, active=True).exclude(id=self.id).exists():
|
||||||
|
raise ValidationError(f'Line with short name {self.short_name} already exists and is active.')
|
||||||
|
|
||||||
|
|
||||||
class OperationModel(NomenclatureBaseModel):
|
class OperationModel(NomenclatureBaseModel):
|
||||||
...
|
...
|
||||||
@@ -50,4 +72,4 @@ class ContainerTypeModel(models.Model):
|
|||||||
app_label = 'common'
|
app_label = 'common'
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+10
-3
@@ -1,11 +1,13 @@
|
|||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
from common.fields import ContainerNumberField
|
||||||
from common.models import LinesModel, ContainerTypeModel
|
from common.models import LinesModel, ContainerTypeModel
|
||||||
# from payments.models import ContainerTariffPeriod, AdditionalFees
|
# from payments.models import ContainerTariffPeriod, AdditionalFees
|
||||||
|
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
class Container(models.Model):
|
class Container(models.Model):
|
||||||
number = models.CharField(max_length=11)
|
number = ContainerNumberField(max_length=11)
|
||||||
line = models.ForeignKey(
|
line = models.ForeignKey(
|
||||||
LinesModel,
|
LinesModel,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
@@ -25,7 +27,7 @@ class Container(models.Model):
|
|||||||
receive_vehicle = models.CharField(max_length=100, blank=True, null=True)
|
receive_vehicle = models.CharField(max_length=100, blank=True, null=True)
|
||||||
damages = models.TextField(blank=True, null=True)
|
damages = models.TextField(blank=True, null=True)
|
||||||
heavy_damaged = models.BooleanField(default=False)
|
heavy_damaged = models.BooleanField(default=False)
|
||||||
position = models.CharField(max_length=100, blank=True, null=True)
|
position = models.CharField(max_length=7, blank=True, null=True)
|
||||||
swept = models.BooleanField(default=False)
|
swept = models.BooleanField(default=False)
|
||||||
swept_on = models.DateTimeField(blank=True, null=True)
|
swept_on = models.DateTimeField(blank=True, null=True)
|
||||||
swept_by = models.ForeignKey(
|
swept_by = models.ForeignKey(
|
||||||
@@ -67,6 +69,11 @@ class Container(models.Model):
|
|||||||
)
|
)
|
||||||
expedition_vehicle = models.CharField(max_length=100, blank=True, null=True)
|
expedition_vehicle = models.CharField(max_length=100, blank=True, null=True)
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
if Container.objects.filter(number=self.number, expedited=False).exclude(id=self.id).exists():
|
||||||
|
raise ValidationError(f'Container with number {self.number} already exists in the depot.!')
|
||||||
|
if self.heavy_damaged and not self.damages.strip():
|
||||||
|
raise ValidationError('Heavy damaged containers must have damages specified.')
|
||||||
|
|
||||||
|
|
||||||
class ContainerHistory(Container):
|
class ContainerHistory(Container):
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user