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:
@@ -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()
|
||||
|
||||
# Обновляем состав
|
||||
|
||||
Reference in New Issue
Block a user