feat: split bills for one deal
This commit is contained in:
@@ -24,7 +24,9 @@ TELEGRAM_BOT_TOKEN = os.environ.get('TELEGRAM_BOT_TOKEN')
|
|||||||
SECRET_KEY = os.environ.get('SECRET_KEY')
|
SECRET_KEY = os.environ.get('SECRET_KEY')
|
||||||
S3_API_KEY = os.environ.get('S3_API_KEY')
|
S3_API_KEY = os.environ.get('S3_API_KEY')
|
||||||
|
|
||||||
|
# Billing
|
||||||
BILLING_API_KEY = os.environ.get('BILLING_API_KEY')
|
BILLING_API_KEY = os.environ.get('BILLING_API_KEY')
|
||||||
|
BILLING_URL = os.environ.get('BILLING_URL')
|
||||||
|
|
||||||
CHAT_TELEGRAM_BOT_TOKEN = os.environ.get('CHAT_TELEGRAM_BOT_TOKEN')
|
CHAT_TELEGRAM_BOT_TOKEN = os.environ.get('CHAT_TELEGRAM_BOT_TOKEN')
|
||||||
CHAT_CONNECTOR_API_KEY = os.environ.get('CHAT_CONNECTOR_API_KEY')
|
CHAT_CONNECTOR_API_KEY = os.environ.get('CHAT_CONNECTOR_API_KEY')
|
||||||
|
|||||||
3
external/billing/billing_client.py
vendored
3
external/billing/billing_client.py
vendored
@@ -1,5 +1,6 @@
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
|
from backend.config import BILLING_URL
|
||||||
from .schemas import *
|
from .schemas import *
|
||||||
|
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ class BillingClient:
|
|||||||
self.headers = {
|
self.headers = {
|
||||||
'Authorization': f'Bearer {self.api_key}'
|
'Authorization': f'Bearer {self.api_key}'
|
||||||
}
|
}
|
||||||
self.base_url = 'https://billing.denco.store'
|
self.base_url = BILLING_URL
|
||||||
|
|
||||||
async def _method(self, http_method, method, **kwargs):
|
async def _method(self, http_method, method, **kwargs):
|
||||||
async with aiohttp.ClientSession(headers=self.headers) as session:
|
async with aiohttp.ClientSession(headers=self.headers) as session:
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ if TYPE_CHECKING:
|
|||||||
class CardBillRequest(BaseModel):
|
class CardBillRequest(BaseModel):
|
||||||
__tablename__ = 'card_bill_requests'
|
__tablename__ = 'card_bill_requests'
|
||||||
|
|
||||||
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
|
|
||||||
card_id: Mapped[int] = mapped_column(
|
card_id: Mapped[int] = mapped_column(
|
||||||
ForeignKey('cards.id'),
|
ForeignKey('cards.id'),
|
||||||
nullable=False,
|
nullable=False,
|
||||||
primary_key=True,
|
|
||||||
unique=True,
|
|
||||||
)
|
)
|
||||||
card: Mapped['Card'] = relationship(back_populates='bill_request')
|
card: Mapped['Card'] = relationship(back_populates='bill_requests')
|
||||||
|
|
||||||
created_at: Mapped[datetime.datetime] = mapped_column(nullable=False)
|
created_at: Mapped[datetime.datetime] = mapped_column(nullable=False)
|
||||||
paid: Mapped[bool] = mapped_column(nullable=False, default=False)
|
paid: Mapped[bool] = mapped_column(nullable=False, default=False)
|
||||||
@@ -31,13 +31,13 @@ class CardBillRequest(BaseModel):
|
|||||||
class GroupBillRequest(BaseModel):
|
class GroupBillRequest(BaseModel):
|
||||||
__tablename__ = 'group_bill_requests'
|
__tablename__ = 'group_bill_requests'
|
||||||
|
|
||||||
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
|
|
||||||
group_id: Mapped[int] = mapped_column(
|
group_id: Mapped[int] = mapped_column(
|
||||||
ForeignKey('card_groups.id'),
|
ForeignKey('card_groups.id'),
|
||||||
nullable=False,
|
nullable=False,
|
||||||
primary_key=True,
|
|
||||||
unique=True,
|
|
||||||
)
|
)
|
||||||
group: Mapped['CardGroup'] = relationship(back_populates='bill_request')
|
group: Mapped['CardGroup'] = relationship(back_populates='bill_requests')
|
||||||
|
|
||||||
created_at: Mapped[datetime.datetime] = mapped_column(nullable=False)
|
created_at: Mapped[datetime.datetime] = mapped_column(nullable=False)
|
||||||
paid: Mapped[bool] = mapped_column(nullable=False, default=False)
|
paid: Mapped[bool] = mapped_column(nullable=False, default=False)
|
||||||
|
|||||||
@@ -93,7 +93,11 @@ class Card(BaseModel):
|
|||||||
order_by="desc(CardProduct.product_id)"
|
order_by="desc(CardProduct.product_id)"
|
||||||
)
|
)
|
||||||
|
|
||||||
bill_request: Mapped[Optional['CardBillRequest']] = relationship(back_populates='card', lazy='joined')
|
bill_requests: Mapped[list['CardBillRequest']] = relationship(
|
||||||
|
back_populates='card',
|
||||||
|
lazy='selectin',
|
||||||
|
uselist=True,
|
||||||
|
)
|
||||||
|
|
||||||
# module client
|
# module client
|
||||||
client_id: Mapped[Optional[int]] = mapped_column(
|
client_id: Mapped[Optional[int]] = mapped_column(
|
||||||
|
|||||||
@@ -25,9 +25,10 @@ class CardGroup(BaseModel):
|
|||||||
back_populates='group',
|
back_populates='group',
|
||||||
secondary='card_relations'
|
secondary='card_relations'
|
||||||
)
|
)
|
||||||
bill_request: Mapped[Optional['GroupBillRequest']] = relationship(
|
bill_requests: Mapped[list['GroupBillRequest']] = relationship(
|
||||||
back_populates='group',
|
back_populates='group',
|
||||||
lazy='joined'
|
lazy='joined',
|
||||||
|
uselist=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -45,9 +45,8 @@ async def create_deal_bill(
|
|||||||
async def cancel_deal_billing(
|
async def cancel_deal_billing(
|
||||||
session: SessionDependency,
|
session: SessionDependency,
|
||||||
request: CancelCardBillRequest,
|
request: CancelCardBillRequest,
|
||||||
user: CurrentUserDependency
|
|
||||||
):
|
):
|
||||||
return await BillingService(session).cancel_card_billing(user, request)
|
return await BillingService(session).cancel_card_billing(request)
|
||||||
|
|
||||||
|
|
||||||
@billing_router.get(
|
@billing_router.get(
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ class CreateCardBillRequest(BaseSchema):
|
|||||||
|
|
||||||
class CancelCardBillRequest(BaseSchema):
|
class CancelCardBillRequest(BaseSchema):
|
||||||
card_id: int
|
card_id: int
|
||||||
force: Optional[bool] = False
|
|
||||||
|
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class CardSummary(BaseSchema):
|
|||||||
shipment_warehouse_id: Optional[int]
|
shipment_warehouse_id: Optional[int]
|
||||||
shipment_warehouse_name: Optional[str]
|
shipment_warehouse_name: Optional[str]
|
||||||
|
|
||||||
bill_request: Optional[CardBillRequestSchema] = None
|
bill_requests: list[CardBillRequestSchema]
|
||||||
group: Optional[CardGroupSchema] = None
|
group: Optional[CardGroupSchema] = None
|
||||||
|
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ class BaseCardSchema(BaseSchema):
|
|||||||
client_id: Optional[int]
|
client_id: Optional[int]
|
||||||
client: Optional[ClientSchema]
|
client: Optional[ClientSchema]
|
||||||
shipping_warehouse: Optional[Union[ShippingWarehouseSchema, str]] = None
|
shipping_warehouse: Optional[Union[ShippingWarehouseSchema, str]] = None
|
||||||
bill_request: Optional[CardBillRequestSchema] = None
|
bill_requests: list[CardBillRequestSchema] = []
|
||||||
group: Optional[CardGroupSchema] = None
|
group: Optional[CardGroupSchema] = None
|
||||||
manager: Optional[UserSchema] = None
|
manager: Optional[UserSchema] = None
|
||||||
pallets: List[PalletSchema] = []
|
pallets: List[PalletSchema] = []
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class CardGroupSchema(BaseSchema):
|
|||||||
id: int
|
id: int
|
||||||
name: Optional[str] = None
|
name: Optional[str] = None
|
||||||
lexorank: str
|
lexorank: str
|
||||||
bill_request: Optional[GroupBillRequestSchema] = None
|
bill_requests: list[GroupBillRequestSchema] = []
|
||||||
|
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ class BillingService(BaseService):
|
|||||||
prefix = "group-"
|
prefix = "group-"
|
||||||
if not request.listener_transaction_id.startswith(prefix):
|
if not request.listener_transaction_id.startswith(prefix):
|
||||||
return
|
return
|
||||||
group_id = int(request.listener_transaction_id.removeprefix(prefix))
|
request_id = int(request.listener_transaction_id.removeprefix(prefix))
|
||||||
group_bill_request = await self._get_group_bill_by_id(group_id)
|
group_bill_request = await self._get_group_bill_by_id(request_id)
|
||||||
if not group_bill_request:
|
if not group_bill_request:
|
||||||
return
|
return
|
||||||
group_bill_request.pdf_url = request.info.pdf_url
|
group_bill_request.pdf_url = request.info.pdf_url
|
||||||
@@ -117,24 +117,43 @@ class BillingService(BaseService):
|
|||||||
elif request.channel == NotificationChannel.PAYMENT_VERIFICATION:
|
elif request.channel == NotificationChannel.PAYMENT_VERIFICATION:
|
||||||
await self._process_update_verification(request)
|
await self._process_update_verification(request)
|
||||||
|
|
||||||
async def create_card_bill_request(self, card: Card):
|
async def create_card_bill_request(self, card: Card) -> CardBillRequest:
|
||||||
card_bill_request = CardBillRequest(
|
card_bill_request = CardBillRequest(
|
||||||
card_id=card.id,
|
card_id=card.id,
|
||||||
created_at=datetime.datetime.now()
|
created_at=datetime.datetime.now()
|
||||||
)
|
)
|
||||||
self.session.add(card_bill_request)
|
self.session.add(card_bill_request)
|
||||||
card.is_locked = True
|
await self.session.flush()
|
||||||
await self.session.commit()
|
return card_bill_request
|
||||||
|
|
||||||
async def create_group_bill_request(self, group: CardGroup):
|
async def create_group_bill_request(self, group: CardGroup) -> GroupBillRequest:
|
||||||
group_bill_request = GroupBillRequest(
|
group_bill_request = GroupBillRequest(
|
||||||
group_id=group.id,
|
group_id=group.id,
|
||||||
created_at=datetime.datetime.now()
|
created_at=datetime.datetime.now()
|
||||||
)
|
)
|
||||||
self.session.add(group_bill_request)
|
self.session.add(group_bill_request)
|
||||||
for card in group.cards:
|
|
||||||
card.is_locked = True
|
await self.session.flush()
|
||||||
await self.session.commit()
|
return group_bill_request
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_billing_values_from_services(services) -> List[
|
||||||
|
CreateBillingRequestValue
|
||||||
|
]:
|
||||||
|
billing_request_values: List[CreateBillingRequestValue] = []
|
||||||
|
|
||||||
|
for service in services:
|
||||||
|
# Omit services that have no price
|
||||||
|
if not service.price:
|
||||||
|
continue
|
||||||
|
billing_request_values.append(
|
||||||
|
CreateBillingRequestValue(
|
||||||
|
name=service.name,
|
||||||
|
price=service.price,
|
||||||
|
amount=service.quantity
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return billing_request_values
|
||||||
|
|
||||||
async def create_card_billing(self, user, request: CreateCardBillRequest) -> CreateCardBillResponse:
|
async def create_card_billing(self, user, request: CreateCardBillRequest) -> CreateCardBillResponse:
|
||||||
try:
|
try:
|
||||||
@@ -151,56 +170,79 @@ class BillingService(BaseService):
|
|||||||
services: dict[str, ServiceBillingDocumentPdf]
|
services: dict[str, ServiceBillingDocumentPdf]
|
||||||
products: dict[str, ProductBillingDocumentPdf]
|
products: dict[str, ProductBillingDocumentPdf]
|
||||||
is_size_needed: bool
|
is_size_needed: bool
|
||||||
billing_request_values: List[CreateBillingRequestValue] = []
|
billing_request_values: List[CreateBillingRequestValue] = self._get_billing_values_from_services(
|
||||||
|
services.values()
|
||||||
for service in services.values():
|
)
|
||||||
# Omit services that have no price
|
|
||||||
if not service.price:
|
|
||||||
continue
|
|
||||||
billing_request_values.append(
|
|
||||||
CreateBillingRequestValue(
|
|
||||||
name=service.name,
|
|
||||||
price=service.price,
|
|
||||||
amount=service.quantity
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
card = basic_card
|
card = basic_card
|
||||||
listener_transaction_id = card.id
|
transaction_prefix = "group-" if card.group else ""
|
||||||
if card.group:
|
inn: str = card.client.details.inn.strip()
|
||||||
listener_transaction_id = f"group-{basic_card.group.id}"
|
|
||||||
inn: str = card.client.details.inn
|
one_request_size = 100
|
||||||
create_bill_request = CreateBillRequestSchema(
|
for i in range(0, len(billing_request_values), one_request_size):
|
||||||
listener_transaction_id=listener_transaction_id,
|
values = billing_request_values[i:i + one_request_size]
|
||||||
payer_name=card.client.name,
|
|
||||||
payer_inn=inn.strip(),
|
if basic_card.group:
|
||||||
payer_phone=card.client.details.phone_number,
|
bill_request = await self.create_group_bill_request(basic_card.group)
|
||||||
items=CreateBillRequestItems(
|
else:
|
||||||
values=billing_request_values
|
bill_request = await self.create_card_bill_request(basic_card)
|
||||||
|
|
||||||
|
listener_transaction_id = transaction_prefix + str(bill_request.id)
|
||||||
|
create_bill_request = CreateBillRequestSchema(
|
||||||
|
listener_transaction_id=listener_transaction_id,
|
||||||
|
payer_name=card.client.name,
|
||||||
|
payer_inn=inn,
|
||||||
|
payer_phone=card.client.details.phone_number,
|
||||||
|
items=CreateBillRequestItems(
|
||||||
|
values=values,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
create_bill_response = await billing_client.create(create_bill_request)
|
||||||
create_bill_response = await billing_client.create(create_bill_request)
|
|
||||||
if not create_bill_response.ok and 'Request already exists' in create_bill_response.message:
|
|
||||||
await self.cancel_card_billing(user, CancelCardBillRequest(card_id=request.card_id, force=True))
|
|
||||||
return await self.create_card_billing(user, request)
|
|
||||||
if not create_bill_response.ok:
|
|
||||||
return CreateCardBillResponse(ok=create_bill_response.ok,
|
|
||||||
message=create_bill_response.message or 'Неизвестная ошибка')
|
|
||||||
|
|
||||||
if basic_card.group:
|
if not create_bill_response.ok and 'Request already exists' in create_bill_response.message:
|
||||||
await self.create_group_bill_request(basic_card.group)
|
await self._cancel_one_bill(bill_request, listener_transaction_id)
|
||||||
|
create_bill_response = await billing_client.create(create_bill_request)
|
||||||
|
|
||||||
|
if not create_bill_response.ok:
|
||||||
|
raise Exception(create_bill_response.message or 'Неизвестная ошибка')
|
||||||
|
|
||||||
|
if card.group:
|
||||||
|
for card in card.group.cards:
|
||||||
|
card.is_locked = True
|
||||||
else:
|
else:
|
||||||
await self.create_card_bill_request(basic_card)
|
card.is_locked = True
|
||||||
|
|
||||||
return CreateCardBillResponse(ok=create_bill_response.ok, message='Заявка успешно создана!')
|
await self.session.commit()
|
||||||
|
return CreateCardBillResponse(ok=True, message='Заявка успешно создана!')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
await self.session.rollback()
|
||||||
return CreateCardBillResponse(ok=False, message=str(e))
|
return CreateCardBillResponse(ok=False, message=str(e))
|
||||||
|
|
||||||
async def _get_card_bill_by_id(self, card_id: int) -> Optional[CardBillRequest]:
|
async def _get_card_bill_by_id(self, request_id: int) -> Optional[CardBillRequest]:
|
||||||
return await self.session.scalar(select(CardBillRequest).where(CardBillRequest.card_id == card_id))
|
return await self.session.scalar(
|
||||||
|
select(CardBillRequest)
|
||||||
|
.where(CardBillRequest.id == request_id)
|
||||||
|
)
|
||||||
|
|
||||||
async def _get_group_bill_by_id(self, group_id: int) -> Optional[GroupBillRequest]:
|
async def _get_card_bill_by_card_id(self, card_id: int) -> List[CardBillRequest]:
|
||||||
return await self.session.scalar(select(GroupBillRequest).where(GroupBillRequest.group_id == group_id))
|
result = await self.session.scalars(
|
||||||
|
select(CardBillRequest)
|
||||||
|
.where(CardBillRequest.card_id == card_id)
|
||||||
|
)
|
||||||
|
return [*result.all()]
|
||||||
|
|
||||||
|
async def _get_group_bill_by_id(self, request_id: int) -> Optional[GroupBillRequest]:
|
||||||
|
return await self.session.scalar(
|
||||||
|
select(GroupBillRequest)
|
||||||
|
.where(GroupBillRequest.id == request_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
async def _get_group_bill_by_group_id(self, group_id: int) -> List[GroupBillRequest]:
|
||||||
|
result = await self.session.scalars(
|
||||||
|
select(GroupBillRequest)
|
||||||
|
.where(GroupBillRequest.group_id == group_id)
|
||||||
|
)
|
||||||
|
return [*result.all()]
|
||||||
|
|
||||||
async def get_card_bill_by_id(self, card_id: int) -> GetCardBillById:
|
async def get_card_bill_by_id(self, card_id: int) -> GetCardBillById:
|
||||||
bill = await self._get_card_bill_by_id(card_id)
|
bill = await self._get_card_bill_by_id(card_id)
|
||||||
@@ -208,34 +250,42 @@ class BillingService(BaseService):
|
|||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='Card bill was not found')
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='Card bill was not found')
|
||||||
return GetCardBillById(card_bill=CardBillRequestSchema.model_validate(bill))
|
return GetCardBillById(card_bill=CardBillRequestSchema.model_validate(bill))
|
||||||
|
|
||||||
async def cancel_card_billing(self, user, request: CancelCardBillRequest) -> CancelCardBillResponse:
|
async def _cancel_one_bill(self, bill: CardBillRequest | GroupBillRequest, listener_transaction_id: str) -> None:
|
||||||
|
billing_client = BillingClient(backend.config.BILLING_API_KEY)
|
||||||
|
response = await billing_client.delete(
|
||||||
|
DeleteBillRequestSchema(listener_transaction_id=listener_transaction_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not response.ok:
|
||||||
|
raise Exception('Ошибка удаления счета со стороны Billing сервиса')
|
||||||
|
|
||||||
|
await self.session.delete(bill)
|
||||||
|
|
||||||
|
async def cancel_card_billing(self, request: CancelCardBillRequest) -> CancelCardBillResponse:
|
||||||
try:
|
try:
|
||||||
card = await self._get_card_by_id(request.card_id)
|
card = await self._get_card_by_id(request.card_id)
|
||||||
if not card:
|
if not card:
|
||||||
return CancelCardBillResponse(ok=False, message='Сделка не найдена')
|
return CancelCardBillResponse(ok=False, message='Сделка не найдена')
|
||||||
|
|
||||||
if card.group:
|
if card.group:
|
||||||
bill = await self._get_group_bill_by_id(card.group.id)
|
bills = await self._get_group_bill_by_group_id(card.group.id)
|
||||||
if not bill and not request.force:
|
|
||||||
return CancelCardBillResponse(ok=False, message='Заявка не найдена')
|
|
||||||
billing_client = BillingClient(backend.config.BILLING_API_KEY)
|
|
||||||
listener_transaction_id = f"group-{card.group.id}"
|
|
||||||
|
|
||||||
response = await billing_client.delete(DeleteBillRequestSchema(listener_transaction_id=listener_transaction_id))
|
|
||||||
else:
|
else:
|
||||||
bill = await self._get_card_bill_by_id(request.card_id)
|
bills = await self._get_card_bill_by_card_id(request.card_id)
|
||||||
if not bill and not request.force:
|
if not bills:
|
||||||
return CancelCardBillResponse(ok=False, message='Заявка не найдена')
|
return CancelCardBillResponse(ok=False, message='Заявка не найдена')
|
||||||
billing_client = BillingClient(backend.config.BILLING_API_KEY)
|
|
||||||
response = await billing_client.delete(DeleteBillRequestSchema(listener_transaction_id=request.card_id))
|
|
||||||
|
|
||||||
if not response.ok:
|
for bill in bills:
|
||||||
return CancelCardBillResponse(ok=False, message='Ошибка')
|
if card.group:
|
||||||
if bill:
|
listener_transaction_id = f"group-{bill.id}"
|
||||||
await self.session.delete(bill)
|
else:
|
||||||
await self.session.commit()
|
listener_transaction_id = str(bill.id)
|
||||||
|
|
||||||
|
await self._cancel_one_bill(bill, listener_transaction_id)
|
||||||
|
|
||||||
|
await self.session.commit()
|
||||||
return CancelCardBillResponse(ok=True, message='Заявка успешно отозвана')
|
return CancelCardBillResponse(ok=True, message='Заявка успешно отозвана')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
await self.session.rollback()
|
||||||
return CancelCardBillResponse(ok=False, message=str(e))
|
return CancelCardBillResponse(ok=False, message=str(e))
|
||||||
|
|
||||||
def _gen_key_for_service(self, service: ServiceBillingDocumentPdf) -> str:
|
def _gen_key_for_service(self, service: ServiceBillingDocumentPdf) -> str:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import lexorank
|
|||||||
import math
|
import math
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
from sqlalchemy import select, func, update, delete, insert, and_, Select
|
from sqlalchemy import select, func, update, delete, insert, and_, Select
|
||||||
from sqlalchemy.orm import joinedload, selectinload
|
from sqlalchemy.orm import joinedload, selectinload, noload
|
||||||
from starlette import status
|
from starlette import status
|
||||||
|
|
||||||
from card_attributes import CardAttributesCommandHandler
|
from card_attributes import CardAttributesCommandHandler
|
||||||
@@ -252,9 +252,10 @@ class CardsService(BaseService):
|
|||||||
selectinload(Card.status_history),
|
selectinload(Card.status_history),
|
||||||
joinedload(Card.client),
|
joinedload(Card.client),
|
||||||
joinedload(Card.shipping_warehouse),
|
joinedload(Card.shipping_warehouse),
|
||||||
joinedload(Card.bill_request),
|
selectinload(Card.bill_requests),
|
||||||
joinedload(Card.status),
|
joinedload(Card.status),
|
||||||
joinedload(Card.board),
|
joinedload(Card.board),
|
||||||
|
joinedload(Card.group).selectinload(CardGroup.bill_requests)
|
||||||
)
|
)
|
||||||
.outerjoin(
|
.outerjoin(
|
||||||
price_subquery, Card.id == price_subquery.c.card_id,
|
price_subquery, Card.id == price_subquery.c.card_id,
|
||||||
@@ -299,7 +300,7 @@ class CardsService(BaseService):
|
|||||||
shipment_warehouse_id=card.shipping_warehouse_id,
|
shipment_warehouse_id=card.shipping_warehouse_id,
|
||||||
shipment_warehouse_name=shipment_warehouse_name,
|
shipment_warehouse_name=shipment_warehouse_name,
|
||||||
total_products=products_count,
|
total_products=products_count,
|
||||||
bill_request=card.bill_request,
|
bill_requests=card.bill_requests,
|
||||||
tags=card.tags,
|
tags=card.tags,
|
||||||
attributes=attributes,
|
attributes=attributes,
|
||||||
)
|
)
|
||||||
@@ -335,7 +336,7 @@ class CardsService(BaseService):
|
|||||||
.joinedload(CardStatusHistory.user),
|
.joinedload(CardStatusHistory.user),
|
||||||
selectinload(Card.status_history)
|
selectinload(Card.status_history)
|
||||||
.noload(CardStatusHistory.card),
|
.noload(CardStatusHistory.card),
|
||||||
|
selectinload(Card.bill_requests),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1229,14 +1230,16 @@ class CardsService(BaseService):
|
|||||||
async def _recalculate_price_group(self, group: CardGroup):
|
async def _recalculate_price_group(self, group: CardGroup):
|
||||||
cards = await self.session.scalars(
|
cards = await self.session.scalars(
|
||||||
select(Card)
|
select(Card)
|
||||||
|
.join(card_relations, Card.id == card_relations.c.card_id)
|
||||||
.options(
|
.options(
|
||||||
selectinload(Card.services)
|
selectinload(Card.services)
|
||||||
.joinedload(CardService.service),
|
.joinedload(CardService.service),
|
||||||
selectinload(Card.products)
|
selectinload(Card.products)
|
||||||
.selectinload(CardProduct.services)
|
.selectinload(CardProduct.services)
|
||||||
.joinedload(CardProductService.service),
|
.joinedload(CardProductService.service),
|
||||||
|
noload(Card.group)
|
||||||
)
|
)
|
||||||
.where(Card.group == group)
|
.where(card_relations.c.group_id == group.id)
|
||||||
)
|
)
|
||||||
cards = list(cards.all())
|
cards = list(cards.all())
|
||||||
services_quantity = await self.get_quantity_dict(cards)
|
services_quantity = await self.get_quantity_dict(cards)
|
||||||
|
|||||||
@@ -52,8 +52,13 @@ class ClientService(BaseService):
|
|||||||
async def get_all(self) -> ClientGetAllResponse:
|
async def get_all(self) -> ClientGetAllResponse:
|
||||||
clients_query = await self.session.scalars(
|
clients_query = await self.session.scalars(
|
||||||
select(Client)
|
select(Client)
|
||||||
.options(joinedload(Client.details))
|
.options(
|
||||||
.order_by(Client.id.desc())
|
joinedload(Client.details),
|
||||||
|
noload(Client.products),
|
||||||
|
noload(Client.pallets),
|
||||||
|
noload(Client.boxes),
|
||||||
|
noload(Client.chat)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
clients = clients_query.all()
|
clients = clients_query.all()
|
||||||
result = []
|
result = []
|
||||||
|
|||||||
Reference in New Issue
Block a user