Merge remote-tracking branch 'origin/cards'
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
from sqlalchemy.orm import configure_mappers
|
||||
|
||||
from .auth import *
|
||||
from .project import *
|
||||
from .module import *
|
||||
from .board import *
|
||||
from .status import *
|
||||
from .deal import *
|
||||
from .attribute import *
|
||||
from .card import *
|
||||
from .card_tag import *
|
||||
from .auth import *
|
||||
from .card import *
|
||||
from .client import *
|
||||
from .service import *
|
||||
from .product import *
|
||||
@@ -15,7 +19,7 @@ from .marketplace import *
|
||||
from .payroll import *
|
||||
from .billing import *
|
||||
from .marketplace_products import *
|
||||
from .deal_group import *
|
||||
from .card_group import *
|
||||
from .transaction import *
|
||||
from .residues import *
|
||||
from .shipping import *
|
||||
|
||||
102
models/attribute.py
Normal file
102
models/attribute.py
Normal file
@@ -0,0 +1,102 @@
|
||||
import pickle
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from sqlalchemy import ForeignKey, Table, Column, UniqueConstraint, Index
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from models.base import BaseModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models import Project, BaseModel, Card
|
||||
|
||||
project_attribute = Table(
|
||||
'project_attribute',
|
||||
BaseModel.metadata,
|
||||
Column('project_id', ForeignKey('projects.id')),
|
||||
Column('attribute_id', ForeignKey('attributes.id')),
|
||||
)
|
||||
|
||||
|
||||
class AttributeType(BaseModel):
|
||||
__tablename__ = 'attribute_types'
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
type: Mapped[str] = mapped_column(nullable=False, unique=True)
|
||||
name: Mapped[str] = mapped_column(nullable=False, unique=True)
|
||||
is_deleted: Mapped[bool] = mapped_column(default=False)
|
||||
|
||||
attributes: Mapped['Attribute'] = relationship(
|
||||
'Attribute',
|
||||
back_populates='type',
|
||||
lazy='noload',
|
||||
)
|
||||
|
||||
|
||||
class Attribute(BaseModel):
|
||||
__tablename__ = 'attributes'
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
label: Mapped[str] = mapped_column(nullable=False)
|
||||
name: Mapped[str] = mapped_column(nullable=False, index=True)
|
||||
is_applicable_to_group: Mapped[bool] = mapped_column(
|
||||
default=False,
|
||||
comment='Применять ли изменения атрибута карточки ко всем карточкам в группе',
|
||||
)
|
||||
is_nullable: Mapped[bool] = mapped_column(default=False, nullable=False)
|
||||
default_value: Mapped[bytes] = mapped_column(nullable=True)
|
||||
is_deleted: Mapped[bool] = mapped_column(default=False)
|
||||
description: Mapped[str] = mapped_column(default="", nullable=False)
|
||||
|
||||
projects: Mapped[list['Project']] = relationship(
|
||||
'Project',
|
||||
uselist=True,
|
||||
secondary='project_attribute',
|
||||
back_populates='attributes',
|
||||
lazy='noload',
|
||||
)
|
||||
|
||||
type_id: Mapped[int] = mapped_column(ForeignKey('attribute_types.id'), nullable=False)
|
||||
type: Mapped[AttributeType] = relationship(
|
||||
'AttributeType',
|
||||
back_populates='attributes',
|
||||
lazy='joined',
|
||||
)
|
||||
|
||||
card_attributes: Mapped[list['CardAttribute']] = relationship(
|
||||
'CardAttribute',
|
||||
uselist=True,
|
||||
lazy='noload',
|
||||
back_populates='attribute',
|
||||
)
|
||||
|
||||
|
||||
class CardAttribute(BaseModel):
|
||||
__tablename__ = 'card_attributes'
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
value: Mapped[bytes] = mapped_column(nullable=True)
|
||||
|
||||
card_id: Mapped[int] = mapped_column(ForeignKey('cards.id'), nullable=False)
|
||||
card: Mapped['Card'] = relationship(
|
||||
'Card',
|
||||
back_populates='attributes',
|
||||
lazy='noload',
|
||||
)
|
||||
|
||||
attribute_id: Mapped[int] = mapped_column(ForeignKey('attributes.id'), nullable=False)
|
||||
attribute: Mapped[Attribute] = relationship(
|
||||
'Attribute',
|
||||
back_populates='card_attributes',
|
||||
lazy='joined',
|
||||
)
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint('card_id', 'attribute_id', name='uq_card_id_attribute_id'),
|
||||
Index('idx_card_id_attribute_id', 'card_id', 'attribute_id', unique=True)
|
||||
)
|
||||
|
||||
def set_value(self, value):
|
||||
self.value = pickle.dumps(value)
|
||||
|
||||
def get_value(self):
|
||||
return pickle.loads(self.value)
|
||||
@@ -10,7 +10,7 @@ from models.work_shifts import WorkShift
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models.payroll import PayRate, PaymentRecord
|
||||
from models import Deal, DealEmployees
|
||||
from models import Card, CardEmployees
|
||||
|
||||
role_permissions = Table(
|
||||
'role_permissions',
|
||||
@@ -115,7 +115,7 @@ class User(BaseModel):
|
||||
foreign_keys="WorkShift.user_id"
|
||||
)
|
||||
|
||||
managed_deals: Mapped[list["Deal"]] = relationship(
|
||||
managed_cards: Mapped[list["Card"]] = relationship(
|
||||
back_populates="manager",
|
||||
uselist=True,
|
||||
)
|
||||
@@ -127,7 +127,7 @@ class User(BaseModel):
|
||||
cascade="all, delete-orphan"
|
||||
)
|
||||
|
||||
deals: Mapped[list['DealEmployees']] = relationship(
|
||||
cards: Mapped[list['CardEmployees']] = relationship(
|
||||
back_populates='user',
|
||||
lazy='selectin'
|
||||
)
|
||||
|
||||
@@ -35,14 +35,17 @@ class BarcodeTemplate(BaseModel):
|
||||
__tablename__ = 'barcode_templates'
|
||||
id = Column(Integer, autoincrement=True, primary_key=True, index=True)
|
||||
name = Column(String, nullable=False, index=True, comment='Название шаблона')
|
||||
attributes = relationship('BarcodeTemplateAttribute',
|
||||
secondary=barcode_template_attribute_link,
|
||||
lazy='selectin'
|
||||
)
|
||||
additional_attributes = relationship('BarcodeTemplateAdditionalField',
|
||||
lazy='selectin',
|
||||
back_populates='barcode_template',
|
||||
cascade="all, delete")
|
||||
attributes = relationship(
|
||||
'BarcodeTemplateAttribute',
|
||||
secondary=barcode_template_attribute_link,
|
||||
lazy='selectin',
|
||||
)
|
||||
additional_attributes = relationship(
|
||||
'BarcodeTemplateAdditionalField',
|
||||
lazy='selectin',
|
||||
back_populates='barcode_template',
|
||||
cascade="all, delete",
|
||||
)
|
||||
additional_field = Column(String, nullable=True, comment='Дополнительное поле')
|
||||
|
||||
is_default = Column(Boolean, nullable=False, default=False, comment='По умолчанию')
|
||||
|
||||
@@ -7,17 +7,19 @@ from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from models import BaseModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models import Deal, DealGroup
|
||||
from models import Card, CardGroup
|
||||
|
||||
|
||||
class DealBillRequest(BaseModel):
|
||||
__tablename__ = 'deal_bill_requests'
|
||||
class CardBillRequest(BaseModel):
|
||||
__tablename__ = 'card_bill_requests'
|
||||
|
||||
deal_id: Mapped[int] = mapped_column(ForeignKey('deals.id'),
|
||||
nullable=False,
|
||||
primary_key=True,
|
||||
unique=True)
|
||||
deal: Mapped['Deal'] = relationship(back_populates='bill_request')
|
||||
card_id: Mapped[int] = mapped_column(
|
||||
ForeignKey('cards.id'),
|
||||
nullable=False,
|
||||
primary_key=True,
|
||||
unique=True,
|
||||
)
|
||||
card: Mapped['Card'] = relationship(back_populates='bill_request')
|
||||
|
||||
created_at: Mapped[datetime.datetime] = mapped_column(nullable=False)
|
||||
paid: Mapped[bool] = mapped_column(nullable=False, default=False)
|
||||
@@ -29,11 +31,13 @@ class DealBillRequest(BaseModel):
|
||||
class GroupBillRequest(BaseModel):
|
||||
__tablename__ = 'group_bill_requests'
|
||||
|
||||
group_id: Mapped[int] = mapped_column(ForeignKey('deal_groups.id'),
|
||||
nullable=False,
|
||||
primary_key=True,
|
||||
unique=True)
|
||||
group: Mapped['DealGroup'] = relationship(back_populates='bill_request')
|
||||
group_id: Mapped[int] = mapped_column(
|
||||
ForeignKey('card_groups.id'),
|
||||
nullable=False,
|
||||
primary_key=True,
|
||||
unique=True,
|
||||
)
|
||||
group: Mapped['CardGroup'] = relationship(back_populates='bill_request')
|
||||
|
||||
created_at: Mapped[datetime.datetime] = mapped_column(nullable=False)
|
||||
paid: Mapped[bool] = mapped_column(nullable=False, default=False)
|
||||
|
||||
@@ -4,10 +4,10 @@ from typing import TYPE_CHECKING
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from models import BaseModel
|
||||
from models.base import BaseModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models import Project, DealStatus, Deal
|
||||
from models import Project, CardStatus, Card
|
||||
|
||||
|
||||
class Board(BaseModel):
|
||||
@@ -26,6 +26,6 @@ class Board(BaseModel):
|
||||
lazy="selectin",
|
||||
)
|
||||
|
||||
deal_statuses: Mapped[list["DealStatus"]] = relationship("DealStatus", back_populates="board", lazy="selectin", cascade="all,delete")
|
||||
statuses: Mapped[list["CardStatus"]] = relationship("CardStatus", back_populates="board", lazy="selectin", cascade="all,delete")
|
||||
|
||||
deals: Mapped[list["Deal"]] = relationship("Deal", uselist=True, back_populates="board", lazy="selectin")
|
||||
cards: Mapped[list["Card"]] = relationship("Card", uselist=True, back_populates="board", lazy="selectin")
|
||||
|
||||
128
models/card.py
Normal file
128
models/card.py
Normal file
@@ -0,0 +1,128 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy.orm import relationship, backref, Mapped, mapped_column
|
||||
|
||||
from models.base import BaseModel
|
||||
from .marketplace import BaseMarketplace
|
||||
from .shipping import Pallet, Box
|
||||
from .shipping_warehouse import ShippingWarehouse
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from . import (
|
||||
CardBillRequest, User, BaseModel, Board, CardStatus, CardGroup, CardAttribute, Client, CardTag,
|
||||
CardService as CardServiceModel, CardProduct,
|
||||
)
|
||||
|
||||
|
||||
class Card(BaseModel):
|
||||
__tablename__ = 'cards'
|
||||
|
||||
# region Base card attributes
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
name: Mapped[str] = mapped_column(nullable=False, comment='Название карточки')
|
||||
comment: Mapped[str] = mapped_column(nullable=False, server_default='', comment='Комментарий')
|
||||
created_at: Mapped[datetime] = mapped_column(nullable=False, comment='Дата создания')
|
||||
|
||||
is_deleted: Mapped[bool] = mapped_column(nullable=False, server_default='0', default=False, comment='Удалена')
|
||||
is_completed: Mapped[bool] = mapped_column(nullable=False, server_default='0', default=False, comment='Завершена')
|
||||
|
||||
lexorank: Mapped[str] = mapped_column(nullable=False, comment='Lexorank', index=True)
|
||||
|
||||
board_id: Mapped[int] = mapped_column(ForeignKey('boards.id'), nullable=True, server_default='1')
|
||||
board: Mapped['Board'] = relationship(
|
||||
'Board',
|
||||
back_populates='cards',
|
||||
)
|
||||
|
||||
current_status_id: Mapped[int] = mapped_column(
|
||||
ForeignKey('card_statuses.id'),
|
||||
nullable=False,
|
||||
comment='Текущий статус',
|
||||
)
|
||||
status: Mapped['CardStatus'] = relationship(lazy='selectin')
|
||||
|
||||
status_history = relationship('CardStatusHistory', back_populates='card', cascade="all, delete-orphan")
|
||||
|
||||
attributes: Mapped[list['CardAttribute']] = relationship(
|
||||
'CardAttribute',
|
||||
uselist=True,
|
||||
back_populates='card',
|
||||
lazy='selectin',
|
||||
)
|
||||
|
||||
group: Mapped[Optional["CardGroup"]] = relationship(
|
||||
'CardGroup',
|
||||
secondary='card_relations',
|
||||
lazy='joined',
|
||||
back_populates='cards'
|
||||
)
|
||||
|
||||
tags: Mapped[list['CardTag']] = relationship(
|
||||
'CardTag',
|
||||
secondary='cards_card_tags',
|
||||
back_populates='cards',
|
||||
lazy='selectin',
|
||||
)
|
||||
# endregion
|
||||
|
||||
# region Attributes handled by modules
|
||||
|
||||
# module servicesAndProducts
|
||||
is_locked: Mapped[bool] = mapped_column(default=False, server_default='0')
|
||||
is_services_profit_accounted: Mapped[bool] = mapped_column(default=True, server_default='1')
|
||||
|
||||
shipping_warehouse_id: Mapped[int] = mapped_column(ForeignKey('shipping_warehouses.id'), nullable=True)
|
||||
shipping_warehouse: Mapped["ShippingWarehouse"] = relationship()
|
||||
|
||||
base_marketplace_key: Mapped[str] = mapped_column(ForeignKey("base_marketplaces.key"), nullable=True)
|
||||
base_marketplace: Mapped["BaseMarketplace"] = relationship(lazy="joined")
|
||||
|
||||
services: Mapped[list['CardServiceModel']] = relationship(
|
||||
'CardService',
|
||||
back_populates='card',
|
||||
cascade="all, delete-orphan",
|
||||
order_by="desc(CardService.service_id)"
|
||||
)
|
||||
|
||||
products: Mapped[list['CardProduct']] = relationship(
|
||||
'CardProduct',
|
||||
back_populates='card',
|
||||
cascade="all, delete-orphan",
|
||||
order_by="desc(CardProduct.product_id)"
|
||||
)
|
||||
|
||||
bill_request: Mapped[Optional['CardBillRequest']] = relationship(back_populates='card', lazy='joined')
|
||||
|
||||
# module client
|
||||
client_id: Mapped[Optional[int]] = mapped_column(
|
||||
ForeignKey('clients.id', ondelete='CASCADE'),
|
||||
nullable=True,
|
||||
comment='ID клиента',
|
||||
)
|
||||
client: Mapped['Client'] = relationship('Client', backref=backref('cards', cascade="all, delete-orphan"))
|
||||
|
||||
# module managers
|
||||
manager_id: Mapped[int] = mapped_column(ForeignKey('users.id'), nullable=True)
|
||||
manager: Mapped[Optional["User"]] = relationship(back_populates='managed_cards', lazy='joined')
|
||||
|
||||
# module shipment
|
||||
pallets: Mapped[list[Pallet]] = relationship(back_populates='card', lazy='selectin')
|
||||
boxes: Mapped[list[Box]] = relationship(back_populates='card', lazy='selectin')
|
||||
|
||||
# module employees
|
||||
employees: Mapped[list['CardEmployees']] = relationship(back_populates='card', lazy='selectin')
|
||||
|
||||
# endregion
|
||||
|
||||
|
||||
class CardEmployees(BaseModel):
|
||||
__tablename__ = 'card_employees'
|
||||
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True)
|
||||
user: Mapped['User'] = relationship('User', back_populates='cards', lazy='selectin')
|
||||
|
||||
card_id: Mapped[int] = mapped_column(ForeignKey('cards.id'), primary_key=True)
|
||||
card: Mapped[Card] = relationship('Card', back_populates='employees', lazy='selectin')
|
||||
|
||||
created_at: Mapped[datetime] = mapped_column()
|
||||
@@ -7,11 +7,11 @@ from models import BaseModel
|
||||
from models import GroupBillRequest
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models import Deal
|
||||
from models import Card
|
||||
|
||||
|
||||
class DealGroup(BaseModel):
|
||||
__tablename__ = 'deal_groups'
|
||||
class CardGroup(BaseModel):
|
||||
__tablename__ = 'card_groups'
|
||||
id: Mapped[int] = mapped_column(
|
||||
primary_key=True
|
||||
)
|
||||
@@ -21,9 +21,9 @@ class DealGroup(BaseModel):
|
||||
lexorank: Mapped[str] = mapped_column(
|
||||
nullable=False
|
||||
)
|
||||
deals: Mapped[list["Deal"]] = relationship(
|
||||
cards: Mapped[list["Card"]] = relationship(
|
||||
back_populates='group',
|
||||
secondary='deal_relations'
|
||||
secondary='card_relations'
|
||||
)
|
||||
bill_request: Mapped[Optional['GroupBillRequest']] = relationship(
|
||||
back_populates='group',
|
||||
@@ -31,9 +31,9 @@ class DealGroup(BaseModel):
|
||||
)
|
||||
|
||||
|
||||
deal_relations = Table(
|
||||
'deal_relations',
|
||||
card_relations = Table(
|
||||
'card_relations',
|
||||
BaseModel.metadata,
|
||||
Column('deal_id', ForeignKey('deals.id'), primary_key=True, unique=True),
|
||||
Column('group_id', ForeignKey('deal_groups.id'), primary_key=True)
|
||||
Column('card_id', ForeignKey('cards.id'), primary_key=True, unique=True),
|
||||
Column('group_id', ForeignKey('card_groups.id'), primary_key=True)
|
||||
)
|
||||
45
models/card_tag.py
Normal file
45
models/card_tag.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from sqlalchemy import ForeignKey, Column, Table, UniqueConstraint, Index
|
||||
from sqlalchemy.orm import mapped_column, Mapped, relationship
|
||||
|
||||
from models import BaseModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models import Project, Card
|
||||
|
||||
|
||||
cards_card_tags = Table(
|
||||
'cards_card_tags',
|
||||
BaseModel.metadata,
|
||||
Column('card_id', ForeignKey('cards.id'), primary_key=True),
|
||||
Column('card_tag_id', ForeignKey('card_tags.id'), primary_key=True),
|
||||
)
|
||||
|
||||
|
||||
class CardTag(BaseModel):
|
||||
__tablename__ = 'card_tags'
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
name: Mapped[str] = mapped_column(nullable=False)
|
||||
is_deleted: Mapped[bool] = mapped_column(default=False, server_default='0')
|
||||
|
||||
project_id: Mapped[int] = mapped_column(
|
||||
ForeignKey('projects.id'),
|
||||
nullable=False,
|
||||
)
|
||||
project: Mapped['Project'] = relationship(
|
||||
'Project',
|
||||
back_populates='tags',
|
||||
lazy='noload',
|
||||
)
|
||||
|
||||
cards: Mapped[list['Card']] = relationship(
|
||||
secondary='cards_card_tags',
|
||||
lazy='noload',
|
||||
back_populates='tags',
|
||||
)
|
||||
|
||||
__table_args__ = (
|
||||
Index('idx_card_name_project_id', 'name', 'project_id', 'is_deleted'),
|
||||
)
|
||||
@@ -1,70 +1,59 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
|
||||
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy.orm import relationship, Mapped, mapped_column
|
||||
|
||||
from models import BaseModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models import ResidualPallet, ResidualBox
|
||||
from models import ResidualPallet, ResidualBox, Product, BarcodeTemplate, User
|
||||
|
||||
|
||||
class Client(BaseModel):
|
||||
__tablename__ = 'clients'
|
||||
id = Column(Integer, autoincrement=True, primary_key=True, index=True)
|
||||
name = Column(String, nullable=False, unique=True, comment='Название клиента')
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
name: Mapped[str] = mapped_column(nullable=False, unique=True, comment='Название клиента')
|
||||
|
||||
# TODO replace with additional model
|
||||
company_name = Column(String,
|
||||
nullable=False,
|
||||
server_default='',
|
||||
comment='Название компании')
|
||||
company_name: Mapped[str] = mapped_column(
|
||||
nullable=False,
|
||||
server_default='',
|
||||
comment='Название компании',
|
||||
)
|
||||
|
||||
created_at = Column(DateTime, nullable=False, comment='Дата создания')
|
||||
created_at: Mapped[datetime] = mapped_column(nullable=False, comment='Дата создания')
|
||||
|
||||
products = relationship('Product', back_populates='client')
|
||||
details = relationship('ClientDetails', uselist=False, back_populates='client', cascade='all, delete',
|
||||
lazy='joined')
|
||||
products: Mapped[list['Product']] = relationship('Product', back_populates='client')
|
||||
details: Mapped['ClientDetails'] = relationship(
|
||||
uselist=False,
|
||||
back_populates='client',
|
||||
cascade='all, delete',
|
||||
lazy='joined',
|
||||
)
|
||||
|
||||
barcode_template_id = Column(Integer, ForeignKey('barcode_templates.id'), nullable=True)
|
||||
barcode_template = relationship('BarcodeTemplate', lazy='selectin')
|
||||
barcode_template_id: Mapped[int] = mapped_column(ForeignKey('barcode_templates.id'), nullable=True)
|
||||
barcode_template: Mapped['BarcodeTemplate'] = relationship('BarcodeTemplate', lazy='selectin')
|
||||
|
||||
comment: Mapped[Optional[str]] = mapped_column(nullable=True, server_default=None, comment='Комментарий')
|
||||
|
||||
pallets: Mapped[list["ResidualPallet"]] = relationship(back_populates='client', lazy='selectin')
|
||||
boxes: Mapped[list["ResidualBox"]] = relationship(back_populates='client', lazy='selectin')
|
||||
pallets: Mapped[list['ResidualPallet']] = relationship(back_populates='client', lazy='selectin')
|
||||
boxes: Mapped[list['ResidualBox']] = relationship(back_populates='client', lazy='selectin')
|
||||
|
||||
|
||||
class ClientDetails(BaseModel):
|
||||
__tablename__ = 'client_details'
|
||||
|
||||
id = Column(Integer, autoincrement=True, primary_key=True, index=True)
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
|
||||
client_id = Column(Integer, ForeignKey('clients.id'), unique=True, nullable=False, comment='ID клиента')
|
||||
client = relationship('Client', back_populates='details', cascade='all, delete', uselist=False)
|
||||
client_id: Mapped[int] = mapped_column(ForeignKey('clients.id'), unique=True, nullable=False, comment='ID клиента')
|
||||
client: Mapped[Client] = relationship('Client', back_populates='details', cascade='all, delete', uselist=False)
|
||||
|
||||
telegram = Column(String)
|
||||
phone_number = Column(String)
|
||||
inn = Column(String)
|
||||
email = Column(String)
|
||||
telegram: Mapped[Optional[str]] = mapped_column()
|
||||
phone_number: Mapped[Optional[str]] = mapped_column()
|
||||
inn: Mapped[Optional[str]] = mapped_column()
|
||||
email: Mapped[Optional[str]] = mapped_column()
|
||||
|
||||
last_modified_at = Column(DateTime, nullable=False)
|
||||
last_modified_at: Mapped[datetime] = mapped_column(nullable=False)
|
||||
|
||||
modified_by_user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
|
||||
modified_by_user = relationship('User')
|
||||
|
||||
# class ClientContact(BaseModel):
|
||||
# __tablename__ = 'client_contact'
|
||||
# id: Mapped[int] = mapped_column(primary_key=True)
|
||||
#
|
||||
# client_id: Mapped[int] = mapped_column(ForeignKey('clients.id'))
|
||||
# client: Mapped["Client"] = relationship('Client', back_populates='users')
|
||||
#
|
||||
# first_name: Mapped[str] = mapped_column()
|
||||
# last_name: Mapped[str] = mapped_column()
|
||||
#
|
||||
# telegram: Mapped[str] = mapped_column()
|
||||
# phone_number: Mapped[str] = mapped_column()
|
||||
# email: Mapped[str] = mapped_column()
|
||||
# inn: Mapped[str] = mapped_column()
|
||||
#
|
||||
modified_by_user_id: Mapped[int] = mapped_column(ForeignKey('users.id'), nullable=False)
|
||||
modified_by_user: Mapped['User'] = relationship('User')
|
||||
|
||||
106
models/deal.py
106
models/deal.py
@@ -1,106 +0,0 @@
|
||||
from datetime import datetime
|
||||
from enum import IntEnum, unique
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
|
||||
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Boolean
|
||||
from sqlalchemy.orm import relationship, backref, Mapped, mapped_column
|
||||
|
||||
from models.base import BaseModel
|
||||
from .marketplace import BaseMarketplace
|
||||
from .board import Board
|
||||
from .status import DealStatus
|
||||
from .shipping import Pallet, Box
|
||||
from .shipping_warehouse import ShippingWarehouse
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from . import (
|
||||
DealBillRequest,
|
||||
DealGroup,
|
||||
User,
|
||||
)
|
||||
|
||||
|
||||
class Deal(BaseModel):
|
||||
__tablename__ = 'deals'
|
||||
id = Column(Integer, autoincrement=True, primary_key=True, index=True)
|
||||
name = Column(String, nullable=False, comment='Название сделки')
|
||||
created_at = Column(DateTime, nullable=False, comment='Дата создания')
|
||||
|
||||
client_id = Column(Integer, ForeignKey('clients.id', ondelete='CASCADE'), nullable=False, comment='ID клиента')
|
||||
client = relationship('Client', backref=backref('deals', cascade="all, delete-orphan"))
|
||||
|
||||
status_history = relationship('DealStatusHistory', back_populates='deal', cascade="all, delete-orphan")
|
||||
|
||||
is_deleted = Column(Boolean, nullable=False, server_default='0', default=False, comment='Удалена')
|
||||
is_completed = Column(Boolean, nullable=False, server_default='0', default=False, comment='Завершена')
|
||||
is_locked: Mapped[bool] = mapped_column(default=False, server_default='0')
|
||||
is_accounted: Mapped[bool] = mapped_column(default=True, server_default='1')
|
||||
|
||||
current_status_id: Mapped[int] = mapped_column(
|
||||
ForeignKey("deal_statuses.id"),
|
||||
nullable=False,
|
||||
comment='Текущий статус',
|
||||
)
|
||||
status: Mapped["DealStatus"] = relationship(lazy="selectin")
|
||||
|
||||
|
||||
shipping_warehouse_id: Mapped[int] = mapped_column(ForeignKey('shipping_warehouses.id'), nullable=True)
|
||||
shipping_warehouse: Mapped["ShippingWarehouse"] = relationship()
|
||||
|
||||
base_marketplace_key: Mapped[str] = mapped_column(ForeignKey("base_marketplaces.key"), nullable=True)
|
||||
base_marketplace: Mapped["BaseMarketplace"] = relationship(lazy="joined")
|
||||
|
||||
delivery_date: Mapped[Optional[datetime]] = mapped_column(nullable=True)
|
||||
receiving_slot_date: Mapped[Optional[datetime]] = mapped_column(nullable=True)
|
||||
|
||||
services = relationship(
|
||||
'DealService',
|
||||
back_populates='deal',
|
||||
cascade="all, delete-orphan",
|
||||
order_by="desc(DealService.service_id)"
|
||||
)
|
||||
|
||||
products = relationship(
|
||||
'DealProduct',
|
||||
back_populates='deal',
|
||||
cascade="all, delete-orphan",
|
||||
order_by="desc(DealProduct.product_id)"
|
||||
)
|
||||
|
||||
board_id: Mapped[int] = mapped_column(ForeignKey('boards.id'), nullable=True, server_default='1')
|
||||
board: Mapped[Board] = relationship(
|
||||
"Board",
|
||||
back_populates="deals",
|
||||
)
|
||||
|
||||
# TODO remake with sequence
|
||||
lexorank = Column(String, nullable=False, comment='Lexorank', index=True)
|
||||
|
||||
comment = Column(String, nullable=False, server_default='', comment='Коментарий к заданию')
|
||||
bill_request: Mapped[Optional['DealBillRequest']] = relationship(back_populates='deal', lazy='joined')
|
||||
|
||||
group: Mapped[Optional["DealGroup"]] = relationship(
|
||||
'DealGroup',
|
||||
secondary='deal_relations',
|
||||
lazy='joined',
|
||||
back_populates='deals'
|
||||
)
|
||||
|
||||
manager_id: Mapped[int] = mapped_column(ForeignKey('users.id'), nullable=True)
|
||||
manager: Mapped[Optional["User"]] = relationship(back_populates='managed_deals', lazy='joined')
|
||||
|
||||
pallets: Mapped[list[Pallet]] = relationship(back_populates='deal', lazy='selectin')
|
||||
boxes: Mapped[list[Box]] = relationship(back_populates='deal', lazy='selectin')
|
||||
|
||||
employees: Mapped[list['DealEmployees']] = relationship(back_populates='deal', lazy='selectin')
|
||||
|
||||
|
||||
class DealEmployees(BaseModel):
|
||||
__tablename__ = 'deal_employees'
|
||||
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True)
|
||||
user: Mapped['User'] = relationship('User', back_populates='deals', lazy='selectin')
|
||||
|
||||
deal_id: Mapped[int] = mapped_column(ForeignKey('deals.id'), primary_key=True)
|
||||
deal: Mapped[Deal] = relationship('Deal', back_populates='employees', lazy='selectin')
|
||||
|
||||
created_at: Mapped[datetime] = mapped_column()
|
||||
35
models/module.py
Normal file
35
models/module.py
Normal file
@@ -0,0 +1,35 @@
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from sqlalchemy import Table, Column, ForeignKey
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from models.base import BaseModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models import Project
|
||||
|
||||
|
||||
project_module = Table(
|
||||
'project_module',
|
||||
BaseModel.metadata,
|
||||
Column('project_id', ForeignKey('projects.id')),
|
||||
Column('module_id', ForeignKey('modules.id')),
|
||||
)
|
||||
|
||||
|
||||
class Module(BaseModel):
|
||||
__tablename__ = 'modules'
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
key: Mapped[str] = mapped_column(unique=True, nullable=False)
|
||||
label: Mapped[str] = mapped_column(nullable=False)
|
||||
icon_name: Mapped[Optional[str]] = mapped_column(unique=True, nullable=False)
|
||||
is_deleted: Mapped[bool] = mapped_column(default=False)
|
||||
|
||||
projects: Mapped[list['Project']] = relationship(
|
||||
'Project',
|
||||
uselist=True,
|
||||
secondary='project_module',
|
||||
back_populates='modules',
|
||||
lazy='noload',
|
||||
)
|
||||
@@ -1,74 +1,93 @@
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from sqlalchemy import Column, Integer, String, ForeignKey, Sequence
|
||||
from sqlalchemy.orm import relationship, Mapped
|
||||
from sqlalchemy.testing.schema import mapped_column
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy.orm import relationship, Mapped, mapped_column
|
||||
|
||||
from models import BaseModel
|
||||
from models.base import BaseModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models import Marketplace
|
||||
from models import Client, BarcodeTemplate, WildberriesProduct, OzonProduct
|
||||
|
||||
|
||||
class Product(BaseModel):
|
||||
__tablename__ = 'products'
|
||||
id = Column(Integer, autoincrement=True, primary_key=True, index=True)
|
||||
name = Column(String, nullable=False, index=True)
|
||||
article = Column(String, nullable=False, default='', server_default='', index=True)
|
||||
factory_article = Column(String, nullable=False, default='', server_default='', index=True)
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
name: Mapped[str] = mapped_column(nullable=False, index=True)
|
||||
article: Mapped[str] = mapped_column(nullable=False, default='', server_default='', index=True)
|
||||
factory_article: Mapped[str] = mapped_column(nullable=False, default='', server_default='', index=True)
|
||||
|
||||
client_id = Column(Integer, ForeignKey('clients.id'), nullable=False, comment='ID сделки')
|
||||
client = relationship('Client', back_populates='products')
|
||||
barcodes = relationship('ProductBarcode', back_populates='product', cascade="all, delete-orphan")
|
||||
client_id: Mapped[int] = mapped_column(ForeignKey('clients.id'), nullable=False)
|
||||
client: Mapped['Client'] = relationship('Client', back_populates='products')
|
||||
barcodes: Mapped[list['ProductBarcode']] = relationship(
|
||||
'ProductBarcode',
|
||||
back_populates='product',
|
||||
cascade='all, delete-orphan',
|
||||
)
|
||||
|
||||
barcode_template_id = Column(Integer, ForeignKey('barcode_templates.id'), nullable=True)
|
||||
barcode_template = relationship('BarcodeTemplate', lazy='joined')
|
||||
barcode_template_id: Mapped[Optional[int]] = mapped_column(ForeignKey('barcode_templates.id'), nullable=True)
|
||||
barcode_template: Mapped['BarcodeTemplate'] = relationship('BarcodeTemplate', lazy='joined')
|
||||
|
||||
barcode_image = relationship('ProductBarcodeImage', back_populates='product', lazy='joined', uselist=False)
|
||||
barcode_image: Mapped['ProductBarcodeImage'] = relationship(
|
||||
'ProductBarcodeImage',
|
||||
back_populates='product',
|
||||
lazy='joined',
|
||||
uselist=False,
|
||||
)
|
||||
|
||||
# Attributes
|
||||
# TODO move to another table
|
||||
brand = Column(String, nullable=True, comment='Бренд')
|
||||
color = Column(String, nullable=True, comment='Цвет')
|
||||
composition = Column(String, nullable=True, comment='Состав')
|
||||
size = Column(String, nullable=True, comment='Размер')
|
||||
additional_info = Column(String, nullable=True, comment='Дополнительное поле')
|
||||
images = relationship('ProductImage',
|
||||
back_populates='product',
|
||||
lazy='selectin',
|
||||
cascade="all, delete-orphan")
|
||||
brand: Mapped[Optional[str]] = mapped_column(nullable=True, comment='Бренд')
|
||||
color: Mapped[Optional[str]] = mapped_column(nullable=True, comment='Цвет')
|
||||
composition: Mapped[Optional[str]] = mapped_column(nullable=True, comment='Состав')
|
||||
size: Mapped[Optional[str]] = mapped_column(nullable=True, comment='Размер')
|
||||
additional_info: Mapped[Optional[str]] = mapped_column(nullable=True, comment='Дополнительное поле')
|
||||
images: Mapped[list['ProductImage']] = relationship(
|
||||
'ProductImage',
|
||||
back_populates='product',
|
||||
lazy='selectin',
|
||||
cascade='all, delete-orphan',
|
||||
)
|
||||
|
||||
wildberries_products = relationship('WildberriesProduct',
|
||||
back_populates='product',
|
||||
cascade="all, delete-orphan",
|
||||
uselist=True)
|
||||
wildberries_products: Mapped[list['WildberriesProduct']] = relationship(
|
||||
'WildberriesProduct',
|
||||
back_populates='product',
|
||||
cascade='all, delete-orphan',
|
||||
uselist=True,
|
||||
)
|
||||
|
||||
ozon_products = relationship('OzonProduct',
|
||||
back_populates='product',
|
||||
cascade="all, delete-orphan",
|
||||
uselist=True)
|
||||
ozon_products: Mapped[list['OzonProduct']] = relationship(
|
||||
'OzonProduct',
|
||||
back_populates='product',
|
||||
cascade='all, delete-orphan',
|
||||
uselist=True,
|
||||
)
|
||||
|
||||
|
||||
class ProductImage(BaseModel):
|
||||
__tablename__ = 'product_images'
|
||||
id = Column(Integer, autoincrement=True, primary_key=True, index=True)
|
||||
product_id = Column(Integer, ForeignKey('products.id'), nullable=False)
|
||||
product: Mapped["Product"] = relationship(back_populates='images')
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
product_id: Mapped[int] = mapped_column(ForeignKey('products.id'), nullable=False)
|
||||
product: Mapped['Product'] = relationship(back_populates='images')
|
||||
|
||||
image_url = Column(String, nullable=False)
|
||||
image_url: Mapped[str] = mapped_column(nullable=False)
|
||||
|
||||
|
||||
class ProductBarcode(BaseModel):
|
||||
__tablename__ = 'product_barcodes'
|
||||
product_id = Column(Integer, ForeignKey('products.id'), nullable=False, comment='ID товара', primary_key=True)
|
||||
product: Mapped["Product"] = relationship(back_populates='barcodes')
|
||||
product_id: Mapped[int] = mapped_column(
|
||||
ForeignKey('products.id'),
|
||||
nullable=False,
|
||||
comment='ID товара',
|
||||
primary_key=True,
|
||||
)
|
||||
product: Mapped['Product'] = relationship(back_populates='barcodes')
|
||||
|
||||
barcode = Column(String, nullable=False, index=True, comment='ШК товара', primary_key=True)
|
||||
barcode: Mapped[str] = mapped_column(nullable=False, index=True, comment='ШК товара', primary_key=True)
|
||||
|
||||
|
||||
class ProductBarcodeImage(BaseModel):
|
||||
__tablename__ = 'product_barcode_images'
|
||||
product_id = Column(Integer, ForeignKey('products.id'), primary_key=True, comment='ID товара')
|
||||
product: Mapped["Product"] = relationship(back_populates='barcode_image')
|
||||
product_id: Mapped[int] = mapped_column(ForeignKey('products.id'), primary_key=True, comment='ID товара')
|
||||
product: Mapped['Product'] = relationship(back_populates='barcode_image')
|
||||
|
||||
filename = Column(String, nullable=False)
|
||||
filename: Mapped[str] = mapped_column(nullable=False)
|
||||
|
||||
@@ -3,22 +3,48 @@ from typing import TYPE_CHECKING
|
||||
|
||||
from sqlalchemy.orm import mapped_column, Mapped, relationship
|
||||
|
||||
from models import BaseModel
|
||||
from models.base import BaseModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from board import Board
|
||||
from attribute import Attribute
|
||||
from module import Module
|
||||
from card_tag import CardTag
|
||||
|
||||
|
||||
class Project(BaseModel):
|
||||
__tablename__ = "projects"
|
||||
__tablename__ = 'projects'
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
name: Mapped[str] = mapped_column(nullable=False)
|
||||
created_at: Mapped[datetime] = mapped_column(nullable=False)
|
||||
is_deleted: Mapped[bool] = mapped_column(default=False)
|
||||
|
||||
boards: Mapped[list["Board"]] = relationship(
|
||||
"Board",
|
||||
back_populates="project",
|
||||
lazy="noload",
|
||||
boards: Mapped[list['Board']] = relationship(
|
||||
'Board',
|
||||
back_populates='project',
|
||||
lazy='noload',
|
||||
)
|
||||
|
||||
attributes: Mapped[list['Attribute']] = relationship(
|
||||
'Attribute',
|
||||
secondary='project_attribute',
|
||||
back_populates='projects',
|
||||
lazy='selectin',
|
||||
)
|
||||
|
||||
modules: Mapped[list['Module']] = relationship(
|
||||
'Module',
|
||||
secondary='project_module',
|
||||
back_populates='projects',
|
||||
lazy='selectin',
|
||||
order_by='asc(Module.id)',
|
||||
)
|
||||
|
||||
tags: Mapped[list['CardTag']] = relationship(
|
||||
'CardTag',
|
||||
back_populates='project',
|
||||
primaryjoin="and_(Project.id == CardTag.project_id, CardTag.is_deleted == False)",
|
||||
order_by='asc(CardTag.id)',
|
||||
lazy='selectin',
|
||||
)
|
||||
|
||||
@@ -1,115 +1,138 @@
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, ForeignKeyConstraint, UniqueConstraint, String
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from sqlalchemy import Table, Column, ForeignKey, ForeignKeyConstraint, UniqueConstraint
|
||||
from sqlalchemy.orm import relationship, mapped_column, Mapped
|
||||
|
||||
from models import Product
|
||||
from models.base import BaseModel
|
||||
|
||||
deal_product_service_employees = Table(
|
||||
'deal_product_service_employees',
|
||||
if TYPE_CHECKING:
|
||||
from models import Card, Service, User
|
||||
|
||||
card_product_service_employees = Table(
|
||||
'card_product_service_employees',
|
||||
BaseModel.metadata,
|
||||
Column('deal_id', primary_key=True),
|
||||
Column('card_id', primary_key=True),
|
||||
Column('service_id', primary_key=True),
|
||||
Column('product_id', primary_key=True),
|
||||
Column('user_id', ForeignKey('users.id'), primary_key=True),
|
||||
ForeignKeyConstraint(
|
||||
['deal_id', 'product_id', 'service_id'],
|
||||
['deal_product_services.deal_id', 'deal_product_services.product_id', 'deal_product_services.service_id']
|
||||
['card_id', 'product_id', 'service_id'],
|
||||
['card_product_services.card_id', 'card_product_services.product_id', 'card_product_services.service_id']
|
||||
)
|
||||
)
|
||||
deal_service_employees = Table(
|
||||
'deal_service_employees',
|
||||
card_service_employees = Table(
|
||||
'card_service_employees',
|
||||
BaseModel.metadata,
|
||||
Column('deal_id', primary_key=True),
|
||||
Column('card_id', primary_key=True),
|
||||
Column('service_id', primary_key=True),
|
||||
Column('user_id', ForeignKey('users.id'), primary_key=True),
|
||||
ForeignKeyConstraint(
|
||||
['deal_id', 'service_id'],
|
||||
['deal_services.deal_id', 'deal_services.service_id']
|
||||
['card_id', 'service_id'],
|
||||
['card_services.card_id', 'card_services.service_id']
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class DealService(BaseModel):
|
||||
__tablename__ = 'deal_services'
|
||||
deal_id = Column(Integer, ForeignKey('deals.id'),
|
||||
nullable=False,
|
||||
comment='ID Сделки',
|
||||
primary_key=True)
|
||||
deal = relationship('Deal', back_populates='services')
|
||||
class CardService(BaseModel):
|
||||
__tablename__ = 'card_services'
|
||||
card_id: Mapped[int] = mapped_column(
|
||||
ForeignKey('cards.id'),
|
||||
comment='ID Сделки',
|
||||
primary_key=True,
|
||||
)
|
||||
card: Mapped['Card'] = relationship('Card', back_populates='services')
|
||||
|
||||
service_id = Column(Integer, ForeignKey('services.id'), nullable=False, comment='ID Услуги', primary_key=True)
|
||||
service = relationship('Service')
|
||||
service_id: Mapped[int] = mapped_column(ForeignKey('services.id'), nullable=False, comment='ID Услуги', primary_key=True)
|
||||
service: Mapped['Service'] = relationship('Service')
|
||||
|
||||
quantity = Column(Integer, nullable=False, comment='Кол-во услуги')
|
||||
price = Column(Integer, nullable=False, server_default='0', comment='Цена услуги')
|
||||
quantity: Mapped[int] = mapped_column(nullable=False, comment='Кол-во услуги')
|
||||
price: Mapped[int] = mapped_column(nullable=False, server_default='0', comment='Цена услуги')
|
||||
is_fixed_price: Mapped[bool] = mapped_column(default=False, server_default='0', comment='Фиксированная цена')
|
||||
|
||||
employees = relationship('User', secondary=deal_service_employees)
|
||||
employees: Mapped[list['User']] = relationship('User', secondary=card_service_employees)
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint('deal_id', 'service_id', name='uix_deal_service'),
|
||||
UniqueConstraint('card_id', 'service_id', name='uix_card_service'),
|
||||
)
|
||||
|
||||
|
||||
class DealProductService(BaseModel):
|
||||
__tablename__ = 'deal_product_services'
|
||||
deal_id = Column(Integer, primary_key=True, nullable=False, comment='ID Сделки')
|
||||
class CardProductService(BaseModel):
|
||||
__tablename__ = 'card_product_services'
|
||||
card_id: Mapped[int] = mapped_column(primary_key=True, nullable=False, comment='ID Сделки')
|
||||
|
||||
product_id = Column(Integer, primary_key=True, nullable=False, comment='ID Продукта')
|
||||
product_id: Mapped[int] = mapped_column(primary_key=True, nullable=False, comment='ID Продукта')
|
||||
|
||||
service_id = Column(Integer, ForeignKey('services.id'), primary_key=True, nullable=False, comment='ID Услуги')
|
||||
service_id: Mapped[int] = mapped_column(
|
||||
ForeignKey('services.id'),
|
||||
primary_key=True,
|
||||
nullable=False,
|
||||
comment='ID Услуги',
|
||||
)
|
||||
|
||||
price = Column(Integer, nullable=False, comment='Цена услуги')
|
||||
price: Mapped[int] = mapped_column(nullable=False, comment='Цена услуги')
|
||||
|
||||
is_fixed_price: Mapped[bool] = mapped_column(default=False, server_default='0', comment='Фиксированная цена')
|
||||
|
||||
deal_product = relationship('DealProduct',
|
||||
back_populates='services',
|
||||
primaryjoin="and_(DealProductService.deal_id == DealProduct.deal_id, "
|
||||
"DealProductService.product_id == DealProduct.product_id)",
|
||||
foreign_keys=[deal_id, product_id])
|
||||
card_product: Mapped['CardProduct'] = relationship(
|
||||
'CardProduct',
|
||||
back_populates='services',
|
||||
primaryjoin="and_(CardProductService.card_id == CardProduct.card_id, "
|
||||
"CardProductService.product_id == CardProduct.product_id)",
|
||||
foreign_keys=[card_id, product_id],
|
||||
)
|
||||
|
||||
service = relationship('Service',
|
||||
foreign_keys=[service_id],
|
||||
lazy='joined'
|
||||
|
||||
)
|
||||
employees = relationship('User',
|
||||
secondary=deal_product_service_employees,
|
||||
)
|
||||
service: Mapped['Service'] = relationship(
|
||||
'Service',
|
||||
foreign_keys=[service_id],
|
||||
lazy='joined',
|
||||
)
|
||||
employees: Mapped[list['User']] = relationship(
|
||||
'User',
|
||||
secondary=card_product_service_employees,
|
||||
)
|
||||
|
||||
__table_args__ = (
|
||||
ForeignKeyConstraint(
|
||||
['deal_id', 'product_id'],
|
||||
['deal_products.deal_id', 'deal_products.product_id']
|
||||
['card_id', 'product_id'],
|
||||
['card_products.card_id', 'card_products.product_id']
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class DealProduct(BaseModel):
|
||||
__tablename__ = 'deal_products'
|
||||
deal_id = Column(Integer, ForeignKey('deals.id'), primary_key=True, nullable=False, comment='ID Сделки')
|
||||
product_id = Column(Integer, ForeignKey('products.id'), primary_key=True, nullable=False, comment='ID Продукта')
|
||||
quantity = Column(Integer, nullable=False, comment='Кол-во продукта')
|
||||
comment = Column(String, nullable=False, server_default='', comment='Комментарий к товару')
|
||||
class CardProduct(BaseModel):
|
||||
__tablename__ = 'card_products'
|
||||
card_id: Mapped[int] = mapped_column(ForeignKey('cards.id'), primary_key=True, nullable=False, comment='ID карточки')
|
||||
product_id: Mapped[int] = mapped_column(
|
||||
ForeignKey('products.id'),
|
||||
primary_key=True,
|
||||
nullable=False,
|
||||
comment='ID Продукта',
|
||||
)
|
||||
quantity: Mapped[int] = mapped_column(nullable=False, comment='Кол-во продукта')
|
||||
comment: Mapped[str] = mapped_column(nullable=False, server_default='', comment='Комментарий к товару')
|
||||
|
||||
deal = relationship('Deal',
|
||||
back_populates='products',
|
||||
foreign_keys=[deal_id])
|
||||
product = relationship(
|
||||
card: Mapped['Card'] = relationship(
|
||||
'Card',
|
||||
back_populates='products',
|
||||
foreign_keys=[card_id],
|
||||
)
|
||||
product: Mapped['Product'] = relationship(
|
||||
'Product',
|
||||
lazy='joined',
|
||||
foreign_keys=[product_id],
|
||||
)
|
||||
|
||||
services = relationship('DealProductService',
|
||||
back_populates='deal_product',
|
||||
cascade="all, delete-orphan",
|
||||
primaryjoin="and_(DealProductService.deal_id == DealProduct.deal_id, "
|
||||
"DealProductService.product_id == DealProduct.product_id)",
|
||||
foreign_keys=[DealProductService.deal_id, DealProductService.product_id],
|
||||
lazy='selectin',
|
||||
order_by="desc(DealProductService.service_id)"
|
||||
)
|
||||
services: Mapped[list['CardProductService']] = relationship(
|
||||
'CardProductService',
|
||||
back_populates='card_product',
|
||||
cascade="all, delete-orphan",
|
||||
primaryjoin="and_(CardProductService.card_id == CardProduct.card_id, "
|
||||
"CardProductService.product_id == CardProduct.product_id)",
|
||||
foreign_keys=[CardProductService.card_id, CardProductService.product_id],
|
||||
lazy='selectin',
|
||||
order_by="desc(CardProductService.service_id)"
|
||||
)
|
||||
|
||||
|
||||
barcode_template_attribute_link = Table(
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
from sqlalchemy import Sequence
|
||||
|
||||
from models import BaseModel
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from sqlalchemy import Column, Integer, String, ForeignKey, Double, asc, Table
|
||||
from sqlalchemy import Column, Integer, String, ForeignKey, Double, Table
|
||||
from sqlalchemy.orm import relationship, mapped_column, Mapped
|
||||
|
||||
import enums.service
|
||||
@@ -14,11 +14,15 @@ services_kit_services = Table(
|
||||
|
||||
class Service(BaseModel):
|
||||
__tablename__ = 'services'
|
||||
id: Mapped[int] = mapped_column(Integer, autoincrement=True, primary_key=True, index=True)
|
||||
name = Column(String, nullable=False, comment='Название услуги')
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
name: Mapped[str] = mapped_column(nullable=False, comment='Название услуги')
|
||||
|
||||
category_id = Column(Integer, ForeignKey('service_categories.id'), nullable=False, comment='ID категории услуги')
|
||||
category = relationship('ServiceCategory', lazy='joined')
|
||||
category_id: Mapped[int] = mapped_column(
|
||||
ForeignKey('service_categories.id'),
|
||||
nullable=False,
|
||||
comment='ID категории услуги',
|
||||
)
|
||||
category: Mapped['ServiceCategory'] = relationship('ServiceCategory', lazy='joined')
|
||||
is_deleted: Mapped[bool] = mapped_column(
|
||||
nullable=False,
|
||||
server_default='0',
|
||||
@@ -37,15 +41,18 @@ class Service(BaseModel):
|
||||
comment='Себестоимость услуги'
|
||||
)
|
||||
|
||||
service_type = Column(Integer,
|
||||
server_default=f'{enums.service.ServiceType.DEAL_SERVICE}',
|
||||
nullable=False,
|
||||
comment='Тип услуги')
|
||||
price_ranges = relationship('ServicePriceRange',
|
||||
back_populates='service',
|
||||
lazy='selectin',
|
||||
order_by="asc(ServicePriceRange.from_quantity)",
|
||||
cascade="all, delete-orphan")
|
||||
service_type: Mapped[int] = mapped_column(
|
||||
server_default=f'{enums.service.ServiceType.DEAL_SERVICE}',
|
||||
nullable=False,
|
||||
comment='Тип услуги',
|
||||
)
|
||||
price_ranges: Mapped[list['ServicePriceRange']] = relationship(
|
||||
'ServicePriceRange',
|
||||
back_populates='service',
|
||||
lazy='selectin',
|
||||
order_by="asc(ServicePriceRange.from_quantity)",
|
||||
cascade="all, delete-orphan",
|
||||
)
|
||||
rank: Mapped[str] = mapped_column(
|
||||
nullable=False,
|
||||
server_default='',
|
||||
@@ -55,25 +62,25 @@ class Service(BaseModel):
|
||||
|
||||
class ServicePriceRange(BaseModel):
|
||||
__tablename__ = 'service_price_ranges'
|
||||
id = Column(Integer, autoincrement=True, primary_key=True, index=True)
|
||||
service_id = Column(Integer, ForeignKey('services.id'), nullable=False, comment='ID услуги')
|
||||
service = relationship('Service', back_populates='price_ranges')
|
||||
from_quantity = Column(Integer, nullable=False, comment='От количества')
|
||||
to_quantity = Column(Integer, nullable=False, comment='До количества')
|
||||
price = Column(Double, nullable=False, comment='Цена')
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
service_id: Mapped[int] = mapped_column(ForeignKey('services.id'), nullable=False, comment='ID услуги')
|
||||
service: Mapped['Service'] = relationship('Service', back_populates='price_ranges')
|
||||
from_quantity: Mapped[int] = mapped_column(nullable=False, comment='От количества')
|
||||
to_quantity: Mapped[int] = mapped_column(nullable=False, comment='До количества')
|
||||
price: Mapped[float] = mapped_column(Double, nullable=False, comment='Цена')
|
||||
|
||||
|
||||
class ServiceCategory(BaseModel):
|
||||
__tablename__ = 'service_categories'
|
||||
id = Column(Integer, autoincrement=True, primary_key=True, index=True)
|
||||
name = Column(String, nullable=False)
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
name: Mapped[str] = mapped_column(nullable=False)
|
||||
is_deleted: Mapped[bool] = mapped_column(
|
||||
nullable=False,
|
||||
server_default='0',
|
||||
comment='Удалена ли категория'
|
||||
)
|
||||
|
||||
deal_service_rank: Mapped[str] = mapped_column(
|
||||
card_service_rank: Mapped[str] = mapped_column(
|
||||
nullable=False,
|
||||
server_default='',
|
||||
comment='Ранг услуги для сделки'
|
||||
|
||||
@@ -5,15 +5,15 @@ from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from models import BaseModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models import Deal, Product, Client
|
||||
from models import Card, Product
|
||||
|
||||
|
||||
class Pallet(BaseModel):
|
||||
__tablename__ = 'pallets'
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
|
||||
deal_id: Mapped[int] = mapped_column(ForeignKey('deals.id'))
|
||||
deal: Mapped['Deal'] = relationship(back_populates='pallets')
|
||||
card_id: Mapped[int] = mapped_column(ForeignKey('cards.id'))
|
||||
card: Mapped['Card'] = relationship(back_populates='pallets')
|
||||
|
||||
boxes: Mapped[list['Box']] = relationship(
|
||||
back_populates='pallet',
|
||||
@@ -30,6 +30,24 @@ class Pallet(BaseModel):
|
||||
)
|
||||
|
||||
|
||||
class Box(BaseModel):
|
||||
__tablename__ = 'boxes'
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
|
||||
shipping_products: Mapped[list['ShippingProduct']] = relationship(
|
||||
back_populates='box',
|
||||
uselist=True,
|
||||
lazy='joined',
|
||||
cascade='all, delete-orphan',
|
||||
)
|
||||
|
||||
pallet_id: Mapped[Optional[int]] = mapped_column(ForeignKey('pallets.id'))
|
||||
pallet: Mapped[Pallet] = relationship(back_populates='boxes')
|
||||
|
||||
card_id: Mapped[Optional[int]] = mapped_column(ForeignKey('cards.id'))
|
||||
card: Mapped['Card'] = relationship(back_populates='boxes')
|
||||
|
||||
|
||||
class ShippingProduct(BaseModel):
|
||||
__tablename__ = 'shipping_products'
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
@@ -38,21 +56,8 @@ class ShippingProduct(BaseModel):
|
||||
product_id: Mapped[int] = mapped_column(ForeignKey('products.id'))
|
||||
product: Mapped['Product'] = relationship(lazy='joined')
|
||||
|
||||
pallet_id: Mapped[int] = mapped_column(ForeignKey('pallets.id'))
|
||||
pallet: Mapped['Pallet'] = relationship(lazy='joined')
|
||||
|
||||
|
||||
class Box(BaseModel):
|
||||
__tablename__ = 'boxes'
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
|
||||
quantity: Mapped[int] = mapped_column(default=0)
|
||||
|
||||
product_id: Mapped[Optional[int]] = mapped_column(ForeignKey('products.id'), nullable=True)
|
||||
product: Mapped['Product'] = relationship(lazy='joined')
|
||||
|
||||
pallet_id: Mapped[Optional[int]] = mapped_column(ForeignKey('pallets.id'))
|
||||
pallet: Mapped[Pallet] = relationship(back_populates='boxes')
|
||||
pallet: Mapped[Optional['Pallet']] = relationship(lazy='joined')
|
||||
|
||||
deal_id: Mapped[Optional[int]] = mapped_column(ForeignKey('deals.id'))
|
||||
deal: Mapped['Deal'] = relationship(back_populates='boxes')
|
||||
box_id: Mapped[Optional[int]] = mapped_column(ForeignKey('boxes.id'))
|
||||
box: Mapped[Optional['Box']] = relationship(lazy='joined')
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
from datetime import datetime
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from sqlalchemy import ForeignKey, Column, Integer, DateTime, String
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from models import BaseModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models import Board
|
||||
from models import Board, Card, User
|
||||
|
||||
|
||||
class DealStatus(BaseModel):
|
||||
__tablename__ = "deal_statuses"
|
||||
class CardStatus(BaseModel):
|
||||
__tablename__ = 'card_statuses'
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
name: Mapped[str] = mapped_column(nullable=False)
|
||||
@@ -19,43 +20,45 @@ class DealStatus(BaseModel):
|
||||
is_deleted: Mapped[bool] = mapped_column(default=False, nullable=False)
|
||||
|
||||
board_id: Mapped[int] = mapped_column(ForeignKey('boards.id'), nullable=False)
|
||||
board: Mapped["Board"] = relationship("Board", back_populates="deal_statuses")
|
||||
board: Mapped['Board'] = relationship('Board', back_populates='statuses')
|
||||
|
||||
|
||||
class DealStatusHistory(BaseModel):
|
||||
__tablename__ = 'deals_status_history'
|
||||
id = Column(Integer, autoincrement=True, primary_key=True, index=True)
|
||||
class CardStatusHistory(BaseModel):
|
||||
__tablename__ = 'cards_status_history'
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
|
||||
deal_id = Column(Integer, ForeignKey('deals.id'), nullable=False, comment='ID сделки')
|
||||
deal = relationship('Deal', back_populates='status_history')
|
||||
card_id: Mapped[int] = mapped_column(ForeignKey('cards.id'), nullable=False, comment='ID карточки')
|
||||
card: Mapped['Card'] = relationship('Card', back_populates='status_history')
|
||||
|
||||
user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
|
||||
user = relationship('User')
|
||||
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'), nullable=False)
|
||||
user: Mapped['User'] = relationship('User')
|
||||
|
||||
changed_at = Column(DateTime, nullable=False, comment='Дата и время когда произошла смена статуса')
|
||||
changed_at: Mapped[datetime] = mapped_column(nullable=False, comment='Дата и время когда произошла смена статуса')
|
||||
|
||||
from_status_id: Mapped[int] = mapped_column(
|
||||
ForeignKey('deal_statuses.id'),
|
||||
ForeignKey('card_statuses.id'),
|
||||
nullable=False,
|
||||
comment='Предыдущий статус',
|
||||
)
|
||||
from_status: Mapped[DealStatus] = relationship(
|
||||
'DealStatus',
|
||||
from_status: Mapped[CardStatus] = relationship(
|
||||
'CardStatus',
|
||||
foreign_keys=[from_status_id],
|
||||
lazy='joined',
|
||||
)
|
||||
|
||||
to_status_id: Mapped[int] = mapped_column(
|
||||
ForeignKey('deal_statuses.id'),
|
||||
ForeignKey('card_statuses.id'),
|
||||
nullable=False,
|
||||
comment='Новый статус',
|
||||
)
|
||||
to_status: Mapped[DealStatus] = relationship(
|
||||
'DealStatus',
|
||||
to_status: Mapped[CardStatus] = relationship(
|
||||
'CardStatus',
|
||||
foreign_keys=[to_status_id],
|
||||
lazy='joined',
|
||||
)
|
||||
|
||||
next_status_deadline = Column(DateTime,
|
||||
comment='Дедлайн до которого сделку нужно перевести на следующий этап')
|
||||
comment = Column(String, nullable=False, comment='Коментарий', server_default='')
|
||||
next_status_deadline: Mapped[datetime] = mapped_column(
|
||||
comment='Дедлайн до которого сделку нужно перевести на следующий этап',
|
||||
nullable=True,
|
||||
)
|
||||
comment: Mapped[str] = mapped_column(nullable=False, comment='Комментарий', server_default='')
|
||||
|
||||
Reference in New Issue
Block a user