Исправлен порядок операций при конвертации резервов в продажи
Проблема:
При продаже витринного комплекта резервы оставались в статусе 'reserved'
вместо 'converted_to_sale'. Товары из состава комплекта не освобождались.
Причина:
В методе sell_showcase_items порядок операций был неправильный:
1. create_sale_from_reservation вызывался ПЕРВЫМ
2. reservation.order_item устанавливался ПОСЛЕ
В SaleProcessor.create_sale_from_reservation есть логика:
if order and reservation.order_item:
sale_price = reservation.order_item.price
else:
sale_price = reservation.product.actual_price
Так как order_item был None, цена бралась из product.actual_price,
а не из OrderItem, и резерв не конвертировался корректно.
Решение:
Правильный порядок операций:
1. Устанавливаем reservation.order_item = order_item
2. Сохраняем reservation
3. Вызываем create_sale_from_reservation (теперь order_item доступен)
4. Обновляем статус на 'converted_to_sale'
5. Сохраняем финальное состояние
Теперь резервы корректно преобразуются в продажи с правильной ценой
из позиции заказа, и товары освобождаются после продажи.
This commit is contained in:
@@ -182,13 +182,19 @@ class ShowcaseManager:
|
||||
)
|
||||
|
||||
for reservation in reservations:
|
||||
# Сначала устанавливаем order_item для правильного определения цены
|
||||
reservation.order_item = order_item
|
||||
reservation.save()
|
||||
|
||||
# Теперь создаём продажу с правильной ценой из OrderItem
|
||||
SaleProcessor.create_sale_from_reservation(
|
||||
reservation=reservation,
|
||||
order=order
|
||||
)
|
||||
|
||||
# Обновляем статус резерва
|
||||
reservation.status = 'converted_to_sale'
|
||||
reservation.converted_at = timezone.now()
|
||||
reservation.order_item = order_item
|
||||
reservation.save()
|
||||
|
||||
sold_count += 1
|
||||
|
||||
@@ -286,3 +286,73 @@ body {
|
||||
.action-buttons-panel #scheduleLater {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
/* Адаптивность для элементов корзины на маленьких экранах */
|
||||
@media (max-width: 991.98px) {
|
||||
.cart-item {
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.item-name-price {
|
||||
width: 100%;
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.multiply-sign {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.cart-item > div:has(.d-flex.align-items-center) {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.item-total {
|
||||
order: 3;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.cart-item .btn-link {
|
||||
order: 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* Адаптивность для карточек товаров и витринных комплектов на маленьких экранах */
|
||||
@media (max-width: 575.98px) {
|
||||
/* Уменьшаем минимальную высоту карточки */
|
||||
.product-card {
|
||||
min-height: 160px;
|
||||
}
|
||||
|
||||
/* Уменьшаем высоту изображения */
|
||||
.product-image {
|
||||
min-height: 100px;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
/* Уменьшаем отступы в информационном блоке */
|
||||
.product-info {
|
||||
padding: 0.5rem;
|
||||
gap: 0.2rem;
|
||||
}
|
||||
|
||||
/* Уменьшаем размер названия товара */
|
||||
.product-name {
|
||||
font-size: 0.8rem;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
|
||||
/* Уменьшаем размер информации об остатках */
|
||||
.product-stock {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
/* Уменьшаем размер артикула и цены */
|
||||
.product-sku {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.product-price {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
17
myproject/static/favicon.svg
Normal file
17
myproject/static/favicon.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<rect width="100" height="100" rx="20" fill="#4ade80"/>
|
||||
<!-- Стебель -->
|
||||
<rect x="47" y="50" width="6" height="30" fill="#16a34a" rx="3"/>
|
||||
<!-- Листья -->
|
||||
<ellipse cx="42" cy="62" rx="8" ry="5" fill="#22c55e" transform="rotate(-30 42 62)"/>
|
||||
<ellipse cx="58" cy="68" rx="8" ry="5" fill="#22c55e" transform="rotate(30 58 68)"/>
|
||||
<!-- Центр цветка -->
|
||||
<circle cx="50" cy="45" r="8" fill="#fbbf24"/>
|
||||
<!-- Лепестки -->
|
||||
<circle cx="50" cy="30" r="7" fill="#fff"/>
|
||||
<circle cx="63" cy="38" r="7" fill="#fff"/>
|
||||
<circle cx="63" cy="52" r="7" fill="#fff"/>
|
||||
<circle cx="50" cy="60" r="7" fill="#fff"/>
|
||||
<circle cx="37" cy="52" r="7" fill="#fff"/>
|
||||
<circle cx="37" cy="38" r="7" fill="#fff"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 809 B |
@@ -4,6 +4,8 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}Мой Django Проект{% endblock %}</title>
|
||||
{% load static %}
|
||||
<link rel="icon" type="image/svg+xml" href="{% static 'favicon.svg' %}">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
||||
|
||||
|
||||
Reference in New Issue
Block a user