feat(pos): add editable showcase creation date for kits

- Add showcase_created_at field to ProductKit model
- Display days ago as badge in product card (0 дней, 1 день, etc.)
- Add date input field in edit modal
- Auto-set current date/time for new showcase kits

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-24 01:37:27 +03:00
parent fce8d9eb6e
commit 977ee91fee
6 changed files with 184 additions and 42 deletions

View File

@@ -83,6 +83,7 @@ def get_showcase_kits_for_pos():
'product_kit__price',
'product_kit__sale_price',
'product_kit__base_price',
'product_kit__showcase_created_at',
'showcase_id',
'showcase__name'
).annotate(
@@ -161,7 +162,9 @@ def get_showcase_kits_for_pos():
'total_count': item['total_count'], # Всего на витрине (включая в корзине)
'showcase_item_ids': available_item_ids, # IDs только доступных
# Флаг неактуальной цены
'price_outdated': price_outdated
'price_outdated': price_outdated,
# Дата размещения на витрине
'showcase_created_at': item.get('product_kit__showcase_created_at')
})
return showcase_kits
@@ -1052,7 +1055,8 @@ def get_product_kit_details(request, kit_id):
'final_price': str(kit.actual_price),
'showcase_id': showcase_id,
'items': items,
'photo_url': photo_url
'photo_url': photo_url,
'showcase_created_at': kit.showcase_created_at.isoformat() if kit.showcase_created_at else None
}
})
except ProductKit.DoesNotExist:
@@ -1087,7 +1091,8 @@ def create_temp_kit_to_showcase(request):
sale_price_str = request.POST.get('sale_price', '')
photo_file = request.FILES.get('photo')
showcase_kit_quantity = int(request.POST.get('quantity', 1)) # Количество букетов на витрину
showcase_created_at_str = request.POST.get('showcase_created_at', '').strip()
# Парсим items из JSON
items = json.loads(items_json)
@@ -1100,7 +1105,24 @@ def create_temp_kit_to_showcase(request):
sale_price = None
except (ValueError, InvalidOperation):
sale_price = None
# Showcase created at (опционально)
showcase_created_at = None
if showcase_created_at_str:
try:
from datetime import datetime
showcase_created_at = datetime.fromisoformat(showcase_created_at_str)
except ValueError:
try:
from datetime import datetime
showcase_created_at = datetime.strptime(showcase_created_at_str, '%Y-%m-%dT%H:%M')
except ValueError:
pass # Неверный формат, оставляем как None
# Если не указана - устанавливаем текущее время для новых комплектов
if not showcase_created_at:
showcase_created_at = timezone.now()
# Валидация
if not kit_name:
return JsonResponse({
@@ -1161,7 +1183,8 @@ def create_temp_kit_to_showcase(request):
price_adjustment_type=price_adjustment_type,
price_adjustment_value=price_adjustment_value,
sale_price=sale_price,
showcase=showcase
showcase=showcase,
showcase_created_at=showcase_created_at
)
# 2. Создаём KitItem для каждого товара из корзины
@@ -1284,6 +1307,9 @@ def update_product_kit(request, kit_id):
- photo: Новое фото (опционально)
- remove_photo: '1' для удаления фото
"""
import logging
logger = logging.getLogger(__name__)
try:
kit = ProductKit.objects.prefetch_related('kit_items__product', 'photos').get(id=kit_id, is_temporary=True)
@@ -1296,7 +1322,8 @@ def update_product_kit(request, kit_id):
sale_price_str = request.POST.get('sale_price', '')
photo_file = request.FILES.get('photo')
remove_photo = request.POST.get('remove_photo', '') == '1'
showcase_created_at_str = request.POST.get('showcase_created_at', '').strip()
items = json.loads(items_json)
sale_price = None
@@ -1307,7 +1334,32 @@ def update_product_kit(request, kit_id):
sale_price = None
except (ValueError, InvalidOperation):
sale_price = None
# Showcase created at (опционально)
showcase_created_at = None
if showcase_created_at_str:
logger.warning(f"[DEBUG] showcase_created_at_str received: '{showcase_created_at_str}'")
try:
from datetime import datetime
showcase_created_at = datetime.fromisoformat(showcase_created_at_str)
logger.warning(f"[DEBUG] Parsed fromisoformat: {showcase_created_at}")
except ValueError as e:
logger.warning(f"[DEBUG] fromisoformat failed: {e}, trying strptime")
try:
showcase_created_at = datetime.strptime(showcase_created_at_str, '%Y-%m-%dT%H:%M')
logger.warning(f"[DEBUG] Parsed strptime: {showcase_created_at}")
except ValueError as e2:
logger.warning(f"[DEBUG] strptime also failed: {e2}")
pass # Неверный формат, оставляем как есть
# Делаем datetime timezone-aware
if showcase_created_at and showcase_created_at.tzinfo is None:
from django.utils import timezone
showcase_created_at = timezone.make_aware(showcase_created_at)
logger.warning(f"[DEBUG] Made aware: {showcase_created_at}")
logger.warning(f"[DEBUG] Final showcase_created_at value: {showcase_created_at}")
# Валидация
if not kit_name:
return JsonResponse({'success': False, 'error': 'Необходимо указать название'}, status=400)
@@ -1381,6 +1433,11 @@ def update_product_kit(request, kit_id):
kit.price_adjustment_type = price_adjustment_type
kit.price_adjustment_value = price_adjustment_value
kit.sale_price = sale_price
if showcase_created_at is not None: # Обновляем только если передана
kit.showcase_created_at = showcase_created_at
logger.warning(f"[DEBUG] Saving kit.showcase_created_at = {kit.showcase_created_at}")
else:
logger.warning(f"[DEBUG] showcase_created_at is None, NOT updating field")
kit.save()
# Обновляем состав