diff --git a/services/deal.py b/services/deal.py index 501e828..eb5d144 100644 --- a/services/deal.py +++ b/services/deal.py @@ -1027,7 +1027,14 @@ class DealService(BaseService): general_services_total = sum((service.price * service.quantity for service in deal.services)) product_services_totals = await self._get_product_services_totals(deal) template = ENV.get_template("deal.html") - product_images = await fetch_images([product.product.images[0].image_url for product in deal.products]) + + product_urls: List[Optional[str]] = [] + for product in deal.products: + if len(product.product.images) > 0: + product_urls.append(product.product.images[0].image_url) + else: + product_urls.append(None) + product_images = await fetch_images(product_urls) result = template.render({ "general_services_total": general_services_total, diff --git a/static/css/deal.css b/static/css/deal.css index 3e116ff..04e0f7d 100644 --- a/static/css/deal.css +++ b/static/css/deal.css @@ -39,12 +39,12 @@ hr { .small-text { font-size: 12px; - margin-bottom: 5px; + margin-bottom: 4px; } .medium-text { font-size: 15px; - margin-bottom: 5px; + margin-bottom: 6px; } .large-text { @@ -150,8 +150,9 @@ table tfoot { } .barcode-container { - margin: 15px 0 -5px 385px; + margin: 15px 0 -5px 355px; display: flex; + white-space: nowrap; flex-direction: column; align-items: center; } diff --git a/templates/documents/deal.html b/templates/documents/deal.html index 3f3b93c..d730de4 100644 --- a/templates/documents/deal.html +++ b/templates/documents/deal.html @@ -43,8 +43,6 @@
{% if deal.comment %} Комментарий к сделке: {{ deal.comment }} - {% else %} - Комментарий к сделке отсутствует {% endif %}

@@ -62,42 +60,51 @@ {% if deal.shipping_warehouse.name %}
Склад отгрузки: {{ deal.shipping_warehouse.name }}
{% endif %} - - - - - - - - - - - - {% for service in deal.services %} + {% if deal.services|length > 0 %} +
Общие услугиКоличествоСумма
+ - - - + + + - {% endfor %} - -
{{ service.service.name }}{{ '{:,}'.format(service.quantity) }} шт.{{ '{:,}'.format(service.price * service.quantity).replace(',', ' ') }} РОбщие услугиКоличествоСумма
-
- Итого: {{ general_services_total }} Р -
+ + + + + {% for service in deal.services %} + + {{ service.service.name }} + {{ '{:,}'.format(service.quantity) }} шт. + {{ '{:,}'.format(service.price * service.quantity).replace(',', ' ') }} Р + + {% endfor %} + + +
+ Итого: {{ general_services_total }} Р +
+ {% else %} +
+
+ {% endif %} {% for product in deal.products %}

- {% if product.product.images|length != 0 %} -
+
+ {% if product.product.images|length > 0 %} Фото товара -
- {% endif %} -
+ {% else %} + Фото товара + {% endif %} +
+
{{ loop.index }}. {{ product.product.name }}
@@ -126,38 +133,46 @@
-
- {{ encode128(product.product.barcodes[0].barcode, "A") }} -
-
- {{ product.product.barcodes[0].barcode }} -
+ {% if product.product.barcodes|length > 0 %} +
+ {{ encode128(product.product.barcodes[0].barcode, "A") }} +
+
+ {{ product.product.barcodes[0].barcode }} +
+ {% else %} +
+ {% endif %}
- - - - - - - - - - - - {% for service in product.services %} + {% if product.services|length > 0 %} +
Наименование услугиЦенаСумма
+ - - - + + + - {% endfor %} - -
{{ service.service.name }}{{ '{:,}'.format(product.quantity) }} Р{{ '{:,}'.format(service.price * product.quantity).replace(',', ' ') }} РНаименование услугиЦенаСумма
-
- Итого: {{ product_services_totals[loop.index0] }} Р -
+ + + + + {% for service in product.services %} + + {{ service.service.name }} + {{ '{:,}'.format(product.quantity) }} Р + {{ '{:,}'.format(service.price * product.quantity).replace(',', ' ') }} Р + + {% endfor %} + + +
+ Итого: {{ product_services_totals[loop.index0] }} Р +
+ {% else %} +
+ {% endif %} {% endfor %}
diff --git a/utils/images_fetcher.py b/utils/images_fetcher.py index 62a5538..fb38a94 100644 --- a/utils/images_fetcher.py +++ b/utils/images_fetcher.py @@ -1,11 +1,14 @@ import asyncio import base64 -from typing import List, Tuple +from typing import List, Tuple, Optional import aiohttp -async def fetch_image(url: str) -> str: +async def fetch_image(url: Optional[str]) -> str: + if not url: + return "" + async with aiohttp.ClientSession() as session: async with session.get(url) as response: if response.status == 200: @@ -15,6 +18,6 @@ async def fetch_image(url: str) -> str: return "" -async def fetch_images(urls: List[str]) -> Tuple[str]: +async def fetch_images(urls: List[Optional[str]]) -> Tuple[str]: tasks = [fetch_image(url) for url in urls] return await asyncio.gather(*tasks)