diff --git a/myproject/myproject/urls.py b/myproject/myproject/urls.py index 6f9f273..73b0f29 100644 --- a/myproject/myproject/urls.py +++ b/myproject/myproject/urls.py @@ -21,6 +21,7 @@ urlpatterns = [ path('customers/', include('customers.urls')), # Управление клиентами path('inventory/', include('inventory.urls')), # Управление складом path('orders/', include('orders.urls')), # Управление заказами + path('shops/', include('shops.urls')), # Управление магазинами ] # Serve media files during development diff --git a/myproject/shops/admin.py b/myproject/shops/admin.py index 19a8835..5c5f10e 100644 --- a/myproject/shops/admin.py +++ b/myproject/shops/admin.py @@ -11,7 +11,6 @@ class ShopAdmin(admin.ModelAdmin): 'name', 'full_address', 'phone', - 'working_hours', 'is_active', 'is_pickup_point', ] @@ -19,7 +18,6 @@ class ShopAdmin(admin.ModelAdmin): list_filter = [ 'is_active', 'is_pickup_point', - 'district', ] search_fields = [ @@ -35,21 +33,14 @@ class ShopAdmin(admin.ModelAdmin): 'fields': ('name', 'description') }), ('Адрес', { - 'fields': ('street', 'building_number', 'district') + 'fields': ('street', 'building_number') }), ('Контакты', { 'fields': ('phone', 'email') }), - ('Режим работы', { - 'fields': ('opening_time', 'closing_time', 'working_days') - }), ('Настройки', { 'fields': ('is_active', 'is_pickup_point') }), - ('Дополнительно', { - 'fields': ('delivery_instructions', 'latitude', 'longitude'), - 'classes': ('collapse',) - }), ) readonly_fields = ['created_at', 'updated_at'] diff --git a/myproject/shops/forms.py b/myproject/shops/forms.py new file mode 100644 index 0000000..f0c6f01 --- /dev/null +++ b/myproject/shops/forms.py @@ -0,0 +1,56 @@ +from django import forms +from phonenumber_field.formfields import PhoneNumberField +from .models import Shop + + +class ShopForm(forms.ModelForm): + phone = PhoneNumberField( + region='BY', + required=False, + help_text='Формат: +375XXXXXXXXX или 80XXXXXXXXX', + widget=forms.TextInput(attrs={'placeholder': '+375XXXXXXXXX'}) + ) + + class Meta: + model = Shop + fields = [ + 'name', + 'description', + 'street', + 'building_number', + 'phone', + 'email', + 'is_active', + 'is_pickup_point', + ] + widgets = { + 'description': forms.Textarea(attrs={'rows': 3}), + } + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # Ensure phone displays in E.164 format + if self.instance and self.instance.phone: + self.initial['phone'] = str(self.instance.phone) + + # Mark name field as required with label + self.fields['name'].label = 'Название магазина *' + self.fields['name'].required = True + + for field_name, field in self.fields.items(): + if field_name == 'description': + # Textarea already has rows=3 from widget, just add class + field.widget.attrs.update({'class': 'form-control'}) + elif field_name in ['is_active', 'is_pickup_point']: + # Checkbox fields need form-check-input class + field.widget.attrs.update({'class': 'form-check-input'}) + elif field_name == 'phone': + # Phone field gets form-control class + field.widget.attrs.update({'class': 'form-control'}) + else: + # Regular input fields get form-control class + field.widget.attrs.update({'class': 'form-control'}) + + # Add required attribute to HTML for name field + if field_name == 'name': + field.widget.attrs.update({'required': 'required'}) diff --git a/myproject/shops/migrations/0002_remove_shop_shops_shop_distric_04626c_idx_and_more.py b/myproject/shops/migrations/0002_remove_shop_shops_shop_distric_04626c_idx_and_more.py new file mode 100644 index 0000000..02cab45 --- /dev/null +++ b/myproject/shops/migrations/0002_remove_shop_shops_shop_distric_04626c_idx_and_more.py @@ -0,0 +1,61 @@ +# Generated by Django 5.0.10 on 2025-11-11 20:55 + +import phonenumber_field.modelfields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('shops', '0001_initial'), + ] + + operations = [ + migrations.RemoveIndex( + model_name='shop', + name='shops_shop_distric_04626c_idx', + ), + migrations.RemoveField( + model_name='shop', + name='closing_time', + ), + migrations.RemoveField( + model_name='shop', + name='delivery_instructions', + ), + migrations.RemoveField( + model_name='shop', + name='district', + ), + migrations.RemoveField( + model_name='shop', + name='latitude', + ), + migrations.RemoveField( + model_name='shop', + name='longitude', + ), + migrations.RemoveField( + model_name='shop', + name='opening_time', + ), + migrations.RemoveField( + model_name='shop', + name='working_days', + ), + migrations.AlterField( + model_name='shop', + name='building_number', + field=models.CharField(blank=True, max_length=20, null=True, verbose_name='Номер здания'), + ), + migrations.AlterField( + model_name='shop', + name='phone', + field=phonenumber_field.modelfields.PhoneNumberField(blank=True, help_text='Контактный телефон магазина', max_length=128, null=True, region=None, verbose_name='Телефон'), + ), + migrations.AlterField( + model_name='shop', + name='street', + field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Улица'), + ), + ] diff --git a/myproject/shops/models.py b/myproject/shops/models.py index 1ccd8ed..5a34c84 100644 --- a/myproject/shops/models.py +++ b/myproject/shops/models.py @@ -4,34 +4,39 @@ from phonenumber_field.modelfields import PhoneNumberField class Shop(models.Model): """ - Модель магазина/пункта самовывоза для цветочного магазина в Минске. + Модель магазина/пункта самовывоза для цветочного магазина. """ name = models.CharField( max_length=200, verbose_name="Название магазина" ) + description = models.TextField( + blank=True, + null=True, + verbose_name="Описание", + help_text="Дополнительная информация о магазине" + ) + # Адрес магазина street = models.CharField( max_length=255, + blank=True, + null=True, verbose_name="Улица" ) building_number = models.CharField( max_length=20, - verbose_name="Номер здания" - ) - - district = models.CharField( - max_length=100, blank=True, null=True, - verbose_name="Район", - help_text="Район в Минске" + verbose_name="Номер здания" ) # Контактная информация phone = PhoneNumberField( + blank=True, + null=True, verbose_name="Телефон", help_text="Контактный телефон магазина" ) @@ -42,24 +47,6 @@ class Shop(models.Model): verbose_name="Email" ) - # Режим работы - opening_time = models.TimeField( - verbose_name="Время открытия", - help_text="Время начала работы магазина" - ) - - closing_time = models.TimeField( - verbose_name="Время закрытия", - help_text="Время окончания работы магазина" - ) - - working_days = models.CharField( - max_length=100, - default="Пн-Вс", - verbose_name="Рабочие дни", - help_text="Например: Пн-Пт, Пн-Вс, Пн-Сб" - ) - # Статусы и настройки is_active = models.BooleanField( default=True, @@ -73,40 +60,6 @@ class Shop(models.Model): help_text="Доступен ли магазин для самовывоза заказов" ) - # Дополнительная информация - description = models.TextField( - blank=True, - null=True, - verbose_name="Описание", - help_text="Дополнительная информация о магазине" - ) - - delivery_instructions = models.TextField( - blank=True, - null=True, - verbose_name="Инструкции для клиентов", - help_text="Как найти магазин, где припарковаться и т.д." - ) - - # Координаты для карты (опционально) - latitude = models.DecimalField( - max_digits=9, - decimal_places=6, - null=True, - blank=True, - verbose_name="Широта", - help_text="Координаты для отображения на карте" - ) - - longitude = models.DecimalField( - max_digits=9, - decimal_places=6, - null=True, - blank=True, - verbose_name="Долгота", - help_text="Координаты для отображения на карте" - ) - # Временные метки created_at = models.DateTimeField( auto_now_add=True, @@ -124,19 +77,17 @@ class Shop(models.Model): indexes = [ models.Index(fields=['is_active']), models.Index(fields=['is_pickup_point']), - models.Index(fields=['district']), ] ordering = ['name'] def __str__(self): - return f"{self.name} ({self.full_address})" + if self.street and self.building_number: + return f"{self.name} ({self.full_address})" + return self.name @property def full_address(self): """Полный адрес магазина""" - return f"{self.street}, {self.building_number}" - - @property - def working_hours(self): - """Форматированный режим работы""" - return f"{self.working_days}: {self.opening_time.strftime('%H:%M')} - {self.closing_time.strftime('%H:%M')}" + if self.street and self.building_number: + return f"{self.street}, {self.building_number}" + return "" diff --git a/myproject/shops/templates/shops/shop_confirm_delete.html b/myproject/shops/templates/shops/shop_confirm_delete.html new file mode 100644 index 0000000..9885510 --- /dev/null +++ b/myproject/shops/templates/shops/shop_confirm_delete.html @@ -0,0 +1,36 @@ +{% extends "base.html" %} + +{% block title %}Удалить магазин{% endblock %} + +{% block content %} +
Вы уверены, что хотите удалить магазин {{ object.name }}?
+ + {% if object.full_address %} +Адрес: {{ object.full_address }}
+ {% endif %} + +| Название | +Адрес | +Телефон | +Пункт самовывоза | +Статус | +Действия | +|
|---|---|---|---|---|---|---|
| {{ shop.name }} | +{{ shop.full_address|default:"—" }} | +{{ shop.phone|default:"—" }} | +{{ shop.email|default:"—" }} | ++ {% if shop.is_pickup_point %} + Да + {% else %} + Нет + {% endif %} + | ++ {% if shop.is_active %} + Активен + {% else %} + Неактивен + {% endif %} + | +
+
+
+ Редактировать
+
+
+ Удалить
+
+
+ |
+
Магазины не найдены. Создать первый магазин
+