feat: products table in bill of payment
This commit is contained in:
13
external/billing/schemas.py
vendored
13
external/billing/schemas.py
vendored
@@ -87,3 +87,16 @@ class BillStatusUpdateRequest(BaseSchema):
|
|||||||
listener_transaction_id: int
|
listener_transaction_id: int
|
||||||
channel: NotificationChannel
|
channel: NotificationChannel
|
||||||
info: BillPaymentInfo | BillPaymentStatus
|
info: BillPaymentInfo | BillPaymentStatus
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceBillingDocumentPdf(BaseSchema):
|
||||||
|
name: str = ""
|
||||||
|
price: int
|
||||||
|
quantity: int
|
||||||
|
|
||||||
|
|
||||||
|
class ProductBillingDocumentPdf(BaseSchema):
|
||||||
|
article: str = ""
|
||||||
|
size: str = ""
|
||||||
|
price: int
|
||||||
|
quantity: int
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import backend.config
|
|||||||
import constants
|
import constants
|
||||||
from constants import MONTHS, ENV
|
from constants import MONTHS, ENV
|
||||||
from external.billing import BillingClient, CreateBillingRequestValue, CreateBillRequestSchema, CreateBillRequestItems, \
|
from external.billing import BillingClient, CreateBillingRequestValue, CreateBillRequestSchema, CreateBillRequestItems, \
|
||||||
BillStatusUpdateRequest, NotificationChannel, NotifyReceivedBillRequestSchema, DeleteBillRequestSchema
|
BillStatusUpdateRequest, NotificationChannel, NotifyReceivedBillRequestSchema, DeleteBillRequestSchema, \
|
||||||
|
ProductBillingDocumentPdf, ServiceBillingDocumentPdf
|
||||||
from models import DealBillRequest, Deal, DealProduct, DealService as DealServiceModel
|
from models import DealBillRequest, Deal, DealProduct, DealService as DealServiceModel
|
||||||
from schemas.billing import *
|
from schemas.billing import *
|
||||||
from services.base import BaseService
|
from services.base import BaseService
|
||||||
@@ -138,28 +139,41 @@ class BillingService(BaseService):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return CancelDealBillResponse(ok=False, message=str(e))
|
return CancelDealBillResponse(ok=False, message=str(e))
|
||||||
|
|
||||||
async def _get_services_for_deal(self, deal: Deal) -> List[CreateBillingRequestValue]:
|
async def _get_products_for_deal(self, deal: Deal) -> tuple[list, list, bool]:
|
||||||
services: List[CreateBillingRequestValue] = []
|
services: list[ServiceBillingDocumentPdf] = []
|
||||||
|
products: list[ProductBillingDocumentPdf] = []
|
||||||
|
is_size_needed: bool = False
|
||||||
|
|
||||||
for product in deal.products:
|
for product in deal.products:
|
||||||
|
product_price = 0
|
||||||
for service in product.services:
|
for service in product.services:
|
||||||
services.append(
|
services.append(
|
||||||
CreateBillingRequestValue(
|
ServiceBillingDocumentPdf(
|
||||||
name=f'[{product.product.name}] - {service.service.name}',
|
name=f'[{product.product.name}] - {service.service.name}',
|
||||||
price=service.price,
|
price=service.price,
|
||||||
amount=product.quantity
|
quantity=product.quantity
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
product_price += service.price
|
||||||
|
is_size_needed = is_size_needed | bool(product.product.size)
|
||||||
|
products.append(
|
||||||
|
ProductBillingDocumentPdf(
|
||||||
|
article=product.product.article,
|
||||||
|
size=product.product.size if product.product.size else "",
|
||||||
|
price=product_price,
|
||||||
|
quantity=product.quantity,
|
||||||
|
)
|
||||||
|
)
|
||||||
for service in deal.services:
|
for service in deal.services:
|
||||||
services.append(
|
services.append(
|
||||||
CreateBillingRequestValue(
|
ServiceBillingDocumentPdf(
|
||||||
name=f'{service.service.name}',
|
name=f'{service.service.name}',
|
||||||
price=service.price,
|
price=service.price,
|
||||||
amount=service.quantity
|
quantity=service.quantity
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
return services
|
return services, products, is_size_needed
|
||||||
|
|
||||||
async def _create_billing_document_html(self, deal_id: int):
|
async def _create_billing_document_html(self, deal_id: int):
|
||||||
deal: Deal | None = await self.session.scalar(
|
deal: Deal | None = await self.session.scalar(
|
||||||
@@ -176,9 +190,9 @@ class BillingService(BaseService):
|
|||||||
if not deal:
|
if not deal:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
services = await self._get_services_for_deal(deal)
|
(services, products, is_size_needed) = await self._get_products_for_deal(deal)
|
||||||
|
|
||||||
deal_price = sum((service.price * service.amount for service in services))
|
deal_price = sum((service.price * service.quantity for service in services))
|
||||||
deal_price_words = get_string_by_number(deal_price)[0:-10]
|
deal_price_words = get_string_by_number(deal_price)[0:-10]
|
||||||
deal_price = to_locale_number(deal_price)
|
deal_price = to_locale_number(deal_price)
|
||||||
template = ENV.get_template("bill-of-payment.html")
|
template = ENV.get_template("bill-of-payment.html")
|
||||||
@@ -186,7 +200,9 @@ class BillingService(BaseService):
|
|||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
curr_date = f"{now.day} {MONTHS[now.month - 1]} {now.year} г."
|
curr_date = f"{now.day} {MONTHS[now.month - 1]} {now.year} г."
|
||||||
return template.render({
|
return template.render({
|
||||||
|
"products": products,
|
||||||
"services": services,
|
"services": services,
|
||||||
|
"is_size_needed": is_size_needed,
|
||||||
"deal_price": deal_price,
|
"deal_price": deal_price,
|
||||||
"deal_price_words": deal_price_words,
|
"deal_price_words": deal_price_words,
|
||||||
"deal": deal,
|
"deal": deal,
|
||||||
|
|||||||
@@ -39,10 +39,38 @@
|
|||||||
</h2>
|
</h2>
|
||||||
<hr/>
|
<hr/>
|
||||||
<table>
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Артикул</th>
|
||||||
|
{% if is_size_needed %}
|
||||||
|
<th>Размер</th>
|
||||||
|
{% endif %}
|
||||||
|
<th style="white-space: nowrap">Кол-во</th>
|
||||||
|
<th>Цена</th>
|
||||||
|
<th>Сумма</th>
|
||||||
|
</tr>
|
||||||
|
<tfoot>
|
||||||
|
</tfoot>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for product in products %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ product.article }}</td>
|
||||||
|
{% if is_size_needed %}
|
||||||
|
<td>{{ product.size }}</td>
|
||||||
|
{% endif %}
|
||||||
|
<td>{{ '{:,}'.format(product.quantity) }} шт.</td>
|
||||||
|
<td>{{ '{:,}'.format(product.price).replace(',', ' ') }} ₽</td>
|
||||||
|
<td>{{ '{:,}'.format(product.price * product.quantity).replace(',', ' ') }} ₽</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table style="margin-top: 10px;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Наименование товара (работы, услуги)</th>
|
<th>Наименование товара (работы, услуги)</th>
|
||||||
<th>Количество</th>
|
<th style="white-space: nowrap">Кол-во</th>
|
||||||
<th>Цена</th>
|
<th>Цена</th>
|
||||||
<th>Сумма</th>
|
<th>Сумма</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -53,9 +81,9 @@
|
|||||||
{% for service in services %}
|
{% for service in services %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ service.name }}</td>
|
<td>{{ service.name }}</td>
|
||||||
<td>{{ '{:,}'.format(service.amount) }} шт.</td>
|
<td>{{ '{:,}'.format(service.quantity) }} шт.</td>
|
||||||
<td>{{ '{:,}'.format(service.price).replace(',', ' ') }} ₽</td>
|
<td>{{ '{:,}'.format(service.price).replace(',', ' ') }} ₽</td>
|
||||||
<td>{{ '{:,}'.format(service.price * service.amount).replace(',', ' ') }} ₽</td>
|
<td>{{ '{:,}'.format(service.price * service.quantity).replace(',', ' ') }} ₽</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
Reference in New Issue
Block a user