add contract models and register this models admin panel
This commit is contained in:
24
core/apps/contracts/admins/contract.py
Normal file
24
core/apps/contracts/admins/contract.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from core.apps.contracts.models.contract import Contract, ContractFile, ContractNotification,ContractSide, ContractSignature
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Contract)
|
||||||
|
class ContractAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ['id', 'contract_number', 'name', 'face_id', 'attach_file', 'add_folder', 'add_notification']
|
||||||
|
|
||||||
|
@admin.register(ContractSide)
|
||||||
|
class ContractSideAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ['id', 'full_name']
|
||||||
|
|
||||||
|
@admin.register(ContractFile)
|
||||||
|
class ContractFileAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ['id', 'name']
|
||||||
|
|
||||||
|
@admin.register(ContractNotification)
|
||||||
|
class ContractNotificationAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ['id', 'message', 'contract']
|
||||||
|
|
||||||
|
@admin.register(ContractSignature)
|
||||||
|
class ContractSignatureAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ['id', 'user', 'contract', 'status']
|
||||||
@@ -4,3 +4,6 @@ from django.apps import AppConfig
|
|||||||
class ContractsConfig(AppConfig):
|
class ContractsConfig(AppConfig):
|
||||||
default_auto_field = 'django.db.models.BigAutoField'
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
name = 'core.apps.contracts'
|
name = 'core.apps.contracts'
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
import core.apps.contracts.admins.contract
|
||||||
0
core/apps/contracts/enums/__init__.py
Normal file
0
core/apps/contracts/enums/__init__.py
Normal file
12
core/apps/contracts/enums/contract.py
Normal file
12
core/apps/contracts/enums/contract.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
SIDES = (
|
||||||
|
('two_or_more', 'two or more',),
|
||||||
|
('customer_only', 'customer only',),
|
||||||
|
('only_company', 'onlycompany'),
|
||||||
|
)
|
||||||
|
|
||||||
|
STATUS = (
|
||||||
|
('created', 'created',),
|
||||||
|
('signed_company', 'signed by company',),
|
||||||
|
('signed_customer', 'signed by customer',),
|
||||||
|
('cancelled', 'cancelled')
|
||||||
|
)
|
||||||
12
core/apps/contracts/enums/contract_file.py
Normal file
12
core/apps/contracts/enums/contract_file.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
FILE_TYPE = (
|
||||||
|
('all_files', 'all files',),
|
||||||
|
('PDF', 'pdf',),
|
||||||
|
('word_files', 'word files',),
|
||||||
|
('image', 'image'),
|
||||||
|
)
|
||||||
|
|
||||||
|
USER_PERMISSION = (
|
||||||
|
('all', 'all'),
|
||||||
|
('add', 'add'),
|
||||||
|
('delete', 'delete'),
|
||||||
|
)
|
||||||
15
core/apps/contracts/enums/contract_notification.py
Normal file
15
core/apps/contracts/enums/contract_notification.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
NOTIFICATION_EVENT = (
|
||||||
|
('exact_date', 'exact date'),
|
||||||
|
('counterparty_signing', 'counterparty signing'),
|
||||||
|
('signature_all_parties', 'Signature of all parties')
|
||||||
|
)
|
||||||
|
|
||||||
|
TYPE_NOTIFICATION = (
|
||||||
|
('sms', 'sms'),
|
||||||
|
('whatsup', 'whatsup'),
|
||||||
|
)
|
||||||
|
|
||||||
|
TYPE_MESSAGE = (
|
||||||
|
('krill', 'krill'),
|
||||||
|
('latin', 'latin'),
|
||||||
|
)
|
||||||
4
core/apps/contracts/enums/contract_side.py
Normal file
4
core/apps/contracts/enums/contract_side.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
ROLE = (
|
||||||
|
('physical', 'physical'),
|
||||||
|
('legal', 'legal'),
|
||||||
|
)
|
||||||
9
core/apps/contracts/enums/contract_signature.py
Normal file
9
core/apps/contracts/enums/contract_signature.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
SIGNATURE_STATUS = (
|
||||||
|
('signed', 'signed'),
|
||||||
|
('organized', 'organized')
|
||||||
|
)
|
||||||
|
|
||||||
|
SIGNATURE_TYPE = (
|
||||||
|
('sms_sign', 'sms signature'),
|
||||||
|
('electronic_sing', 'electronic signature')
|
||||||
|
)
|
||||||
116
core/apps/contracts/migrations/0001_initial.py
Normal file
116
core/apps/contracts/migrations/0001_initial.py
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
# Generated by Django 5.2 on 2025-07-15 15:55
|
||||||
|
|
||||||
|
import django.contrib.postgres.fields
|
||||||
|
import django.db.models.deletion
|
||||||
|
import uuid
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Contract',
|
||||||
|
fields=[
|
||||||
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
|
||||||
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated_at', models.DateTimeField(auto_now=True)),
|
||||||
|
('file', models.FileField(upload_to='contract/files/%Y/%m/')),
|
||||||
|
('contract_number', models.PositiveIntegerField()),
|
||||||
|
('name', models.CharField(max_length=200)),
|
||||||
|
('sides', models.CharField(choices=[('two_or_more', 'two or more'), ('customer_only', 'customer only'), ('only_company', 'onlycompany')], max_length=13)),
|
||||||
|
('status', models.CharField(choices=[('created', 'created'), ('signed_company', 'signed by company'), ('signed_customer', 'signed by customer'), ('cancelled', 'cancelled')], max_length=15)),
|
||||||
|
('face_id', models.BooleanField(default=False)),
|
||||||
|
('attach_file', models.BooleanField(default=False)),
|
||||||
|
('add_folder', models.BooleanField(default=False)),
|
||||||
|
('add_notification', models.BooleanField(default=False)),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contracts', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'contract',
|
||||||
|
'verbose_name_plural': 'contracts',
|
||||||
|
'db_table': 'contracts',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ContractFile',
|
||||||
|
fields=[
|
||||||
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
|
||||||
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated_at', models.DateTimeField(auto_now=True)),
|
||||||
|
('name', models.CharField(max_length=150)),
|
||||||
|
('file_type', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(choices=[('all_files', 'all files'), ('PDF', 'pdf'), ('word_files', 'word files'), ('image', 'image')], max_length=10), blank=True, default=list, size=None)),
|
||||||
|
('user_permission', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(choices=[('all', 'all'), ('add', 'add'), ('delete', 'delete')], max_length=10), blank=True, default=list, size=None)),
|
||||||
|
('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contract_files', to='contracts.contract')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'contract file',
|
||||||
|
'verbose_name_plural': 'contract files',
|
||||||
|
'db_table': 'contract_files',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ContractNotification',
|
||||||
|
fields=[
|
||||||
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
|
||||||
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated_at', models.DateTimeField(auto_now=True)),
|
||||||
|
('notification_event', models.CharField(choices=[('exact_date', 'exact date'), ('counterparty_signing', 'counterparty signing'), ('signature_all_parties', 'Signature of all parties')], max_length=24)),
|
||||||
|
('type_notification', models.CharField(choices=[('sms', 'sms'), ('whatsup', 'whatsup')], max_length=8)),
|
||||||
|
('type_message', models.CharField(blank=True, choices=[('krill', 'krill'), ('latin', 'latin')], max_length=8, null=True)),
|
||||||
|
('message', models.CharField(max_length=160)),
|
||||||
|
('time', models.TimeField(blank=True, null=True)),
|
||||||
|
('date', models.DateField(blank=True, null=True)),
|
||||||
|
('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contract_notifications', to='contracts.contract')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'contract notification',
|
||||||
|
'verbose_name_plural': 'contract notifications',
|
||||||
|
'db_table': 'contract_notifications',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ContractSide',
|
||||||
|
fields=[
|
||||||
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
|
||||||
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated_at', models.DateTimeField(auto_now=True)),
|
||||||
|
('full_name', models.CharField(max_length=70)),
|
||||||
|
('indentification', models.CharField(max_length=20)),
|
||||||
|
('position', models.CharField(blank=True, max_length=50, null=True)),
|
||||||
|
('has_indentification', models.BooleanField(default=False)),
|
||||||
|
('user_role', models.CharField(choices=[('physical', 'physical'), ('legal', 'legal')], max_length=9)),
|
||||||
|
('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contract_sides', to='contracts.contract')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contract_sides', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'contract side',
|
||||||
|
'verbose_name_plural': 'contract sides',
|
||||||
|
'db_table': 'contracts_sides',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ContractSignature',
|
||||||
|
fields=[
|
||||||
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
|
||||||
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated_at', models.DateTimeField(auto_now=True)),
|
||||||
|
('status', models.CharField(choices=[('signed', 'signed'), ('organized', 'organized')], max_length=20)),
|
||||||
|
('signature_type', models.CharField(choices=[('sms_sign', 'sms signature'), ('electronic_sing', 'electronic signature')], max_length=20)),
|
||||||
|
('is_signature', models.BooleanField(default=False)),
|
||||||
|
('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contract_signatures', to='contracts.contract')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contract_users', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'contract signatures',
|
||||||
|
'db_table': 'contract_signatures',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
from .contract import *
|
||||||
117
core/apps/contracts/models/contract.py
Normal file
117
core/apps/contracts/models/contract.py
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
from django.db import models
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.contrib.postgres.fields import ArrayField
|
||||||
|
|
||||||
|
from core.apps.shared.models.base import BaseModel
|
||||||
|
from core.apps.contracts.enums.contract import SIDES, STATUS
|
||||||
|
from core.apps.contracts.enums.contract_side import ROLE
|
||||||
|
from core.apps.contracts.enums.contract_file import FILE_TYPE, USER_PERMISSION
|
||||||
|
from core.apps.contracts.enums.contract_signature import SIGNATURE_TYPE, SIGNATURE_STATUS
|
||||||
|
from core.apps.contracts.enums.contract_notification import NOTIFICATION_EVENT, TYPE_MESSAGE, TYPE_NOTIFICATION
|
||||||
|
from core.apps.accounts.validators.user import phone_regex
|
||||||
|
|
||||||
|
|
||||||
|
class Contract(BaseModel):
|
||||||
|
file = models.FileField(upload_to="contract/files/%Y/%m/")
|
||||||
|
contract_number = models.PositiveIntegerField()
|
||||||
|
name = models.CharField(max_length=200)
|
||||||
|
|
||||||
|
sides = models.CharField(max_length=13, choices=SIDES) # choices
|
||||||
|
status = models.CharField(max_length=15, choices=STATUS) # choices
|
||||||
|
|
||||||
|
face_id = models.BooleanField(default=False)
|
||||||
|
attach_file = models.BooleanField(default=False)
|
||||||
|
add_folder = models.BooleanField(default=False)
|
||||||
|
add_notification = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='contracts')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.name} - {self.user}'
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'contract'
|
||||||
|
verbose_name_plural = 'contracts'
|
||||||
|
db_table = 'contracts'
|
||||||
|
|
||||||
|
|
||||||
|
class ContractSide(BaseModel):
|
||||||
|
full_name = models.CharField(max_length=70)
|
||||||
|
indentification = models.CharField(max_length=20)
|
||||||
|
position = models.CharField(max_length=50, null=True, blank=True)
|
||||||
|
|
||||||
|
has_indentification = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
user_role = models.CharField(max_length=9, choices=ROLE)
|
||||||
|
|
||||||
|
contract = models.ForeignKey(Contract, on_delete=models.CASCADE, related_name='contract_sides')
|
||||||
|
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='contract_sides')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.full_name} - {self.contract}"
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'contract side'
|
||||||
|
verbose_name_plural = 'contract sides'
|
||||||
|
db_table = 'contracts_sides'
|
||||||
|
|
||||||
|
|
||||||
|
class ContractFile(BaseModel):
|
||||||
|
name = models.CharField(max_length=150)
|
||||||
|
file_type = ArrayField(
|
||||||
|
models.CharField(max_length=10, choices=FILE_TYPE),
|
||||||
|
default=list,
|
||||||
|
blank=True
|
||||||
|
)
|
||||||
|
user_permission = ArrayField(
|
||||||
|
models.CharField(max_length=10, choices=USER_PERMISSION),
|
||||||
|
default=list,
|
||||||
|
blank=True
|
||||||
|
)
|
||||||
|
contract = models.ForeignKey(Contract, on_delete=models.CASCADE, related_name='contract_files')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.name} - {self.contract}'
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'contract file'
|
||||||
|
verbose_name_plural = 'contract files'
|
||||||
|
db_table = 'contract_files'
|
||||||
|
|
||||||
|
|
||||||
|
class ContractNotification(BaseModel):
|
||||||
|
notification_event = models.CharField(choices=NOTIFICATION_EVENT, max_length=24)
|
||||||
|
type_notification = models.CharField(choices=TYPE_NOTIFICATION, max_length=8)
|
||||||
|
type_message = models.CharField(null=True, blank=True, choices=TYPE_MESSAGE, max_length=8)
|
||||||
|
|
||||||
|
message = models.CharField(max_length=160)
|
||||||
|
time = models.TimeField(null=True, blank=True)
|
||||||
|
date = models.DateField(null=True, blank=True)
|
||||||
|
|
||||||
|
contract = models.ForeignKey(Contract, on_delete=models.CASCADE, related_name="contract_notifications")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.type_notification} - {self.contract}'
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'contract notification'
|
||||||
|
verbose_name_plural = 'contract notifications'
|
||||||
|
db_table = 'contract_notifications'
|
||||||
|
|
||||||
|
|
||||||
|
class ContractSignature(BaseModel):
|
||||||
|
contract = models.ForeignKey(Contract, on_delete=models.CASCADE, related_name='contract_signatures')
|
||||||
|
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='contract_users')
|
||||||
|
|
||||||
|
status = models.CharField(max_length=20, choices=SIGNATURE_STATUS) # choices
|
||||||
|
signature_type = models.CharField(max_length=20, choices=SIGNATURE_TYPE) # choices
|
||||||
|
|
||||||
|
is_signature = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.user} user signature for {self.contract} contract'
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'contract signature'
|
||||||
|
verbose_name = 'contract signatures'
|
||||||
|
db_table = 'contract_signatures'
|
||||||
8
core/apps/shared/admins/folder.py
Normal file
8
core/apps/shared/admins/folder.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from core.apps.shared.models.folder import Folder
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Folder)
|
||||||
|
class FolderAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ['id', 'name']
|
||||||
@@ -4,3 +4,6 @@ from django.apps import AppConfig
|
|||||||
class SharedConfig(AppConfig):
|
class SharedConfig(AppConfig):
|
||||||
default_auto_field = 'django.db.models.BigAutoField'
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
name = 'core.apps.shared'
|
name = 'core.apps.shared'
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
import core.apps.shared.admins.folder
|
||||||
29
core/apps/shared/migrations/0001_initial.py
Normal file
29
core/apps/shared/migrations/0001_initial.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Generated by Django 5.2 on 2025-07-15 15:36
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Folder',
|
||||||
|
fields=[
|
||||||
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
|
||||||
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated_at', models.DateTimeField(auto_now=True)),
|
||||||
|
('name', models.CharField(max_length=200)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'folder',
|
||||||
|
'verbose_name_plural': 'folders',
|
||||||
|
'db_table': 'folders',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -1 +1,2 @@
|
|||||||
from .base import *
|
from .base import *
|
||||||
|
from .folder import *
|
||||||
15
core/apps/shared/models/folder.py
Normal file
15
core/apps/shared/models/folder.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
from core.apps.shared.models.base import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class Folder(BaseModel):
|
||||||
|
name = models.CharField(max_length=200)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'folder'
|
||||||
|
verbose_name_plural = 'folders'
|
||||||
|
db_table = 'folders'
|
||||||
Reference in New Issue
Block a user