-
- ₽
-
-
Цена изменена
diff --git a/myproject/pos/views.py b/myproject/pos/views.py
index 05684ee..01dc21e 100644
--- a/myproject/pos/views.py
+++ b/myproject/pos/views.py
@@ -766,7 +766,8 @@ def get_items_api(request):
)
).prefetch_related(
'categories',
- first_product_photo
+ first_product_photo,
+ 'sales_units' # Загружаем единицы продажи для POS
)
# Фильтруем по категории, если указана
@@ -794,11 +795,34 @@ def get_items_api(request):
available = p.available_qty
reserved = p.reserved_qty
free_qty = available - reserved
-
- # Подсчитываем активные единицы продажи
- sales_units_count = p.sales_units.filter(is_active=True).count()
+
+ # Получаем активные единицы продажи
+ active_sales_units = [su for su in p.sales_units.all() if su.is_active]
+ sales_units_count = len(active_sales_units)
has_sales_units = sales_units_count > 0
-
+
+ # Находим единицу продажи по умолчанию
+ default_sales_unit = None
+ available_qty_in_unit = free_qty # Количество в единицах продажи
+ price_in_unit = str(p.actual_price) # Цена в единицах продажи
+
+ if has_sales_units:
+ # Ищем единицу с is_default=True или берем первую активную
+ default_unit = next((su for su in active_sales_units if su.is_default), active_sales_units[0])
+ if default_unit and default_unit.conversion_factor and default_unit.conversion_factor > 0:
+ # Конвертируем свободное количество в единицы продажи
+ available_qty_in_unit = free_qty * default_unit.conversion_factor
+ price_in_unit = str(default_unit.actual_price)
+ default_sales_unit = {
+ 'id': default_unit.id,
+ 'name': default_unit.name,
+ 'price': str(default_unit.actual_price),
+ 'conversion_factor': str(default_unit.conversion_factor),
+ 'min_quantity': str(default_unit.min_quantity),
+ 'quantity_step': str(default_unit.quantity_step),
+ 'is_default': default_unit.is_default
+ }
+
products.append({
'id': p.id,
'name': p.name,
@@ -811,9 +835,12 @@ def get_items_api(request):
'available_qty': str(available),
'reserved_qty': str(reserved),
'free_qty': str(free_qty), # Передаём как строку для сохранения точности
- 'free_qty_sort': float(free_qty), # Для сортировки отдельное поле
+ 'free_qty_sort': float(available_qty_in_unit if has_sales_units and default_sales_unit else free_qty), # Для сортировки
'sales_units_count': sales_units_count,
- 'has_sales_units': has_sales_units
+ 'has_sales_units': has_sales_units,
+ 'default_sales_unit': default_sales_unit,
+ 'available_qty_in_unit': str(available_qty_in_unit),
+ 'price_in_unit': price_in_unit
})
# Prefetch для первого фото комплектов
diff --git a/myproject/products/admin.py b/myproject/products/admin.py
index 485839c..6f70c2e 100644
--- a/myproject/products/admin.py
+++ b/myproject/products/admin.py
@@ -408,7 +408,7 @@ class ProductAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
fieldsets = (
('Основная информация', {
- 'fields': ('name', 'sku', 'variant_suffix', 'description', 'short_description', 'categories', 'external_category', 'base_unit', 'unit', 'price', 'sale_price')
+ 'fields': ('name', 'sku', 'variant_suffix', 'description', 'short_description', 'categories', 'external_category', 'base_unit', 'price', 'sale_price')
}),
('Себестоимость', {
'fields': ('cost_price_details_display',),
@@ -834,10 +834,9 @@ class ProductSalesUnitInline(admin.TabularInline):
model = ProductSalesUnit
extra = 0
fields = (
- 'unit', 'name', 'conversion_factor', 'price', 'sale_price',
+ 'name', 'conversion_factor', 'price', 'sale_price',
'min_quantity', 'quantity_step', 'is_default', 'is_active'
)
- autocomplete_fields = ['unit']
verbose_name = "Единица продажи"
verbose_name_plural = "Единицы продажи"
@@ -984,18 +983,18 @@ class UnitOfMeasureAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
class ProductSalesUnitAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
"""Админка для единиц продажи товаров"""
list_display = (
- 'product', 'name', 'unit', 'conversion_factor',
+ 'product', 'name', 'conversion_factor',
'get_price_display', 'min_quantity', 'is_default', 'is_active'
)
- list_filter = ('is_active', 'is_default', 'unit')
+ list_filter = ('is_active', 'is_default')
search_fields = ('product__name', 'product__sku', 'name')
- autocomplete_fields = ['product', 'unit']
+ autocomplete_fields = ['product']
list_editable = ('is_default', 'is_active')
ordering = ('product', 'position')
fieldsets = (
- ('Товар и единица', {
- 'fields': ('product', 'unit', 'name')
+ ('Товар и название', {
+ 'fields': ('product', 'name')
}),
('Конверсия', {
'fields': ('conversion_factor',),
diff --git a/myproject/products/forms.py b/myproject/products/forms.py
index 2953dc3..6b6a335 100644
--- a/myproject/products/forms.py
+++ b/myproject/products/forms.py
@@ -156,8 +156,8 @@ class ProductForm(SKUUniqueMixin, forms.ModelForm):
self.fields['base_unit'].queryset = UnitOfMeasure.objects.filter(
is_active=True
).order_by('position', 'code')
- self.fields['base_unit'].required = False
- self.fields['base_unit'].help_text = 'Базовая единица для учета товара на складе. На основе этой единицы можно создать единицы продажи.'
+ self.fields['base_unit'].required = True
+ self.fields['base_unit'].help_text = 'Базовая единица хранения и закупки. На её основе создаются единицы продажи.'
# Маркетинговые флаги (switch-стиль)
for flag_field in ['is_new', 'is_popular', 'is_special']:
@@ -1085,13 +1085,12 @@ class ProductSalesUnitForm(forms.ModelForm):
class Meta:
model = ProductSalesUnit
fields = [
- 'product', 'unit', 'name', 'conversion_factor',
+ 'product', 'name', 'conversion_factor',
'price', 'sale_price', 'min_quantity', 'quantity_step',
'is_default', 'is_active', 'position'
]
labels = {
'product': 'Товар',
- 'unit': 'Единица измерения',
'name': 'Название',
'conversion_factor': 'Коэффициент конверсии',
'price': 'Цена продажи',
@@ -1104,7 +1103,6 @@ class ProductSalesUnitForm(forms.ModelForm):
}
widgets = {
'product': forms.Select(attrs={'class': 'form-control'}),
- 'unit': forms.Select(attrs={'class': 'form-control'}),
'name': forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Например: Ветка большая, Стебель средний'
@@ -1155,11 +1153,6 @@ class ProductSalesUnitForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- # Фильтруем только активные единицы измерения
- self.fields['unit'].queryset = UnitOfMeasure.objects.filter(
- is_active=True
- ).order_by('position', 'code')
-
# Фильтруем только активные товары
self.fields['product'].queryset = Product.objects.filter(
status='active'
@@ -1167,3 +1160,150 @@ class ProductSalesUnitForm(forms.ModelForm):
# Сделать sale_price необязательным
self.fields['sale_price'].required = False
+
+
+class UnitOfMeasureForm(forms.ModelForm):
+ """
+ Форма для создания и редактирования единицы измерения
+ """
+ class Meta:
+ model = UnitOfMeasure
+ fields = ['code', 'name', 'short_name', 'position', 'is_active']
+ labels = {
+ 'code': 'Код',
+ 'name': 'Название',
+ 'short_name': 'Сокращение',
+ 'position': 'Порядок сортировки',
+ 'is_active': 'Активна',
+ }
+ widgets = {
+ 'code': forms.TextInput(attrs={
+ 'class': 'form-control',
+ 'placeholder': 'шт, кг, банч'
+ }),
+ 'name': forms.TextInput(attrs={
+ 'class': 'form-control',
+ 'placeholder': 'Штука, Килограмм, Банч'
+ }),
+ 'short_name': forms.TextInput(attrs={
+ 'class': 'form-control',
+ 'placeholder': 'шт., кг., бан.'
+ }),
+ 'position': forms.NumberInput(attrs={
+ 'class': 'form-control',
+ 'value': '0'
+ }),
+ 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
+ }
+ help_texts = {
+ 'code': 'Короткий уникальный код (используется в системе)',
+ 'name': 'Полное название для отображения',
+ 'short_name': 'Сокращённое название для таблиц',
+ 'position': 'Порядок в списках (меньше = выше)',
+ }
+
+
+# === INLINE FORMSET ДЛЯ ЕДИНИЦ ПРОДАЖИ ===
+
+class ProductSalesUnitInlineForm(forms.ModelForm):
+ """
+ Форма единицы продажи для inline редактирования в форме товара
+ """
+ class Meta:
+ model = ProductSalesUnit
+ fields = [
+ 'name', 'conversion_factor',
+ 'price', 'sale_price', 'min_quantity', 'quantity_step',
+ 'is_default', 'is_active', 'position'
+ ]
+ widgets = {
+ 'name': forms.TextInput(attrs={
+ 'class': 'form-control form-control-sm',
+ 'placeholder': 'Ветка большая'
+ }),
+ 'conversion_factor': forms.NumberInput(attrs={
+ 'class': 'form-control form-control-sm',
+ 'step': '0.000001',
+ 'min': '0.000001',
+ 'placeholder': '15.0'
+ }),
+ 'price': forms.NumberInput(attrs={
+ 'class': 'form-control form-control-sm',
+ 'step': '0.01',
+ 'min': '0',
+ }),
+ 'sale_price': forms.NumberInput(attrs={
+ 'class': 'form-control form-control-sm',
+ 'step': '0.01',
+ 'min': '0',
+ }),
+ 'min_quantity': forms.NumberInput(attrs={
+ 'class': 'form-control form-control-sm',
+ 'step': '0.001',
+ 'min': '0.001',
+ 'value': '1'
+ }),
+ 'quantity_step': forms.NumberInput(attrs={
+ 'class': 'form-control form-control-sm',
+ 'step': '0.001',
+ 'min': '0.001',
+ 'value': '1'
+ }),
+ 'is_default': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
+ 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
+ 'position': forms.NumberInput(attrs={
+ 'class': 'form-control form-control-sm',
+ 'style': 'width: 60px;'
+ }),
+ }
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.fields['sale_price'].required = False
+
+ def has_changed(self):
+ """
+ Считаем форму неизмененной, если это новая форма без заполненных полей.
+ Это позволяет избежать ошибок валидации для пустых добавленных форм.
+ """
+ # Если это существующая запись - используем стандартную логику
+ if self.instance.pk:
+ return super().has_changed()
+
+ # Для новых форм проверяем, есть ли заполненные данные
+ try:
+ # Проверяем ключевые поля
+ cleaned_data = getattr(self, 'cleaned_data', {})
+ if cleaned_data.get('name'):
+ return True
+ if cleaned_data.get('price'):
+ return True
+
+ # Если cleaned_data ещё нет, проверяем raw data
+ data = self.data if hasattr(self, 'data') else {}
+ prefix = self.prefix
+ name_field = f'{prefix}-name'
+ price_field = f'{prefix}-price'
+
+ if data.get(name_field):
+ return True
+ if data.get(price_field):
+ return True
+
+ # Форма пустая - считаем неизмененной
+ return False
+ except Exception:
+ # При ошибке используем стандартную логику
+ return super().has_changed()
+
+
+# Inline formset для единиц продажи
+ProductSalesUnitFormSet = inlineformset_factory(
+ Product,
+ ProductSalesUnit,
+ form=ProductSalesUnitInlineForm,
+ extra=1,
+ can_delete=True,
+ min_num=0,
+ validate_min=False,
+)
diff --git a/myproject/products/migrations/0002_migrate_unit_to_base_unit.py b/myproject/products/migrations/0002_migrate_unit_to_base_unit.py
new file mode 100644
index 0000000..445e90d
--- /dev/null
+++ b/myproject/products/migrations/0002_migrate_unit_to_base_unit.py
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+"""
+Миграция данных: перенос значений unit -> base_unit и удаление поля unit.
+
+Этапы:
+1. Создать недостающие UnitOfMeasure из старых UNIT_CHOICES
+2. Для товаров без base_unit установить соответствующую единицу из справочника
+3. Удалить поле unit
+"""
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+# Старые UNIT_CHOICES для миграции
+OLD_UNIT_CHOICES = {
+ 'шт': {'code': 'шт', 'name': 'Штука', 'short_name': 'шт.', 'position': 1},
+ 'м': {'code': 'м', 'name': 'Метр', 'short_name': 'м.', 'position': 2},
+ 'г': {'code': 'г', 'name': 'Грамм', 'short_name': 'г.', 'position': 3},
+ 'л': {'code': 'л', 'name': 'Литр', 'short_name': 'л.', 'position': 4},
+ 'кг': {'code': 'кг', 'name': 'Килограмм', 'short_name': 'кг.', 'position': 5},
+}
+
+
+def migrate_unit_to_base_unit(apps, schema_editor):
+ """Перенести значения unit -> base_unit для всех товаров"""
+ UnitOfMeasure = apps.get_model('products', 'UnitOfMeasure')
+ Product = apps.get_model('products', 'Product')
+
+ # 1. Создать недостающие UnitOfMeasure
+ for code, data in OLD_UNIT_CHOICES.items():
+ UnitOfMeasure.objects.get_or_create(
+ code=code,
+ defaults={
+ 'name': data['name'],
+ 'short_name': data['short_name'],
+ 'position': data['position'],
+ 'is_active': True,
+ }
+ )
+
+ # 2. Получить дефолтную единицу (штука)
+ default_unit = UnitOfMeasure.objects.get(code='шт')
+
+ # 3. Для товаров без base_unit - установить из unit или дефолтную
+ products_without_base_unit = Product.objects.filter(base_unit__isnull=True)
+
+ for product in products_without_base_unit:
+ # Получаем значение старого поля unit
+ old_unit_code = getattr(product, 'unit', 'шт') or 'шт'
+
+ # Находим соответствующую единицу в справочнике
+ try:
+ unit = UnitOfMeasure.objects.get(code=old_unit_code)
+ except UnitOfMeasure.DoesNotExist:
+ unit = default_unit
+
+ product.base_unit = unit
+ product.save(update_fields=['base_unit'])
+
+ print(f"Миграция завершена: обновлено {products_without_base_unit.count()} товаров")
+
+
+def reverse_migration(apps, schema_editor):
+ """Обратная миграция не нужна - поле unit удалено"""
+ pass
+
+
+class Migration(migrations.Migration):
+ # Отключаем атомарность, чтобы избежать конфликта с триггерами PostgreSQL
+ atomic = False
+
+ dependencies = [
+ ('products', '0001_initial'),
+ ]
+
+ operations = [
+ # 1. Сначала делаем base_unit nullable для data migration
+ # (если он уже nullable - это ничего не изменит)
+
+ # 2. Запускаем data migration
+ migrations.RunPython(migrate_unit_to_base_unit, reverse_migration),
+
+ # 3. Удаляем старое поле unit
+ migrations.RemoveField(
+ model_name='product',
+ name='unit',
+ ),
+
+ # 4. Делаем base_unit обязательным (NOT NULL)
+ migrations.AlterField(
+ model_name='product',
+ name='base_unit',
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.PROTECT,
+ related_name='products',
+ to='products.unitofmeasure',
+ verbose_name='Базовая единица',
+ help_text='Единица хранения и закупки (банч, кг, шт). Товар принимается и хранится в этих единицах.',
+ ),
+ ),
+ ]
diff --git a/myproject/products/migrations/0003_remove_unit_from_sales_unit.py b/myproject/products/migrations/0003_remove_unit_from_sales_unit.py
new file mode 100644
index 0000000..c6aaf96
--- /dev/null
+++ b/myproject/products/migrations/0003_remove_unit_from_sales_unit.py
@@ -0,0 +1,18 @@
+# Generated manually
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('products', '0002_migrate_unit_to_base_unit'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='productsalesunit',
+ name='unit',
+ ),
+ ]
diff --git a/myproject/products/models/products.py b/myproject/products/models/products.py
index dc4d2b6..cdb066c 100644
--- a/myproject/products/models/products.py
+++ b/myproject/products/models/products.py
@@ -16,14 +16,6 @@ class Product(BaseProductEntity):
Базовый товар (цветок, упаковка, аксессуар).
Наследует общие поля из BaseProductEntity.
"""
- UNIT_CHOICES = [
- ('шт', 'Штука'),
- ('м', 'Метр'),
- ('г', 'Грамм'),
- ('л', 'Литр'),
- ('кг', 'Килограмм'),
- ]
-
# Специфичные поля Product
variant_suffix = models.CharField(
max_length=20,
@@ -53,23 +45,13 @@ class Product(BaseProductEntity):
verbose_name="Группы вариантов"
)
- unit = models.CharField(
- max_length=10,
- choices=UNIT_CHOICES,
- default='шт',
- verbose_name="Единица измерения (deprecated)"
- )
-
- # Новое поле: ссылка на справочник единиц измерения
+ # Базовая единица измерения (единица закупки/хранения)
base_unit = models.ForeignKey(
'UnitOfMeasure',
on_delete=models.PROTECT,
- null=True,
- blank=True,
related_name='products',
verbose_name="Базовая единица",
- help_text="Единица хранения и закупки (банч, кг, шт). "
- "Если указана, используется вместо поля 'unit'."
+ help_text="Единица хранения и закупки (банч, кг, шт). Товар принимается и хранится в этих единицах."
)
# ЦЕНООБРАЗОВАНИЕ - переименованные поля
@@ -183,11 +165,9 @@ class Product(BaseProductEntity):
def unit_display(self):
"""
Отображаемое название единицы измерения.
- Приоритет: base_unit.code > unit
+ Возвращает код базовой единицы.
"""
- if self.base_unit:
- return self.base_unit.code
- return self.unit
+ return self.base_unit.code if self.base_unit else 'шт'
@property
def has_sales_units(self):
diff --git a/myproject/products/models/units.py b/myproject/products/models/units.py
index 819cf08..8624994 100644
--- a/myproject/products/models/units.py
+++ b/myproject/products/models/units.py
@@ -66,11 +66,6 @@ class ProductSalesUnit(models.Model):
related_name='sales_units',
verbose_name="Товар"
)
- unit = models.ForeignKey(
- UnitOfMeasure,
- on_delete=models.PROTECT,
- verbose_name="Единица измерения"
- )
name = models.CharField(
max_length=100,
verbose_name="Название",
@@ -135,7 +130,7 @@ class ProductSalesUnit(models.Model):
unique_together = [['product', 'name']]
def __str__(self):
- return f"{self.product.name} - {self.name} ({self.unit.code})"
+ return f"{self.product.name} - {self.name}"
def clean(self):
super().clean()
diff --git a/myproject/products/services/import_export.py b/myproject/products/services/import_export.py
index 4ab6b76..b62b060 100644
--- a/myproject/products/services/import_export.py
+++ b/myproject/products/services/import_export.py
@@ -333,10 +333,20 @@ class ProductImporter:
if not unit:
unit = 'шт'
- # Валидация единицы измерения
- valid_units = [choice[0] for choice in Product.UNIT_CHOICES]
- if unit not in valid_units:
- unit = 'шт' # fallback
+ # Находим единицу измерения в справочнике
+ from products.models import UnitOfMeasure
+ base_unit = UnitOfMeasure.objects.filter(code=unit, is_active=True).first()
+ if not base_unit:
+ # Пробуем найти по названию или короткому имени
+ base_unit = UnitOfMeasure.objects.filter(
+ Q(name__iexact=unit) | Q(short_name__iexact=unit),
+ is_active=True
+ ).first()
+ if not base_unit:
+ # Fallback на штуку
+ base_unit = UnitOfMeasure.objects.filter(code='шт').first()
+ if not base_unit:
+ base_unit = UnitOfMeasure.objects.first()
# Пытаемся найти существующего товара
existing = None
@@ -366,7 +376,7 @@ class ProductImporter:
if short_description:
existing.short_description = short_description
if unit:
- existing.unit = unit
+ existing.base_unit = base_unit
existing.price = price
if cost_price is not None:
@@ -406,7 +416,7 @@ class ProductImporter:
sku=sku or None,
description=description or "",
short_description=short_description or "",
- unit=unit,
+ base_unit=base_unit,
price=price,
cost_price=cost_price or 0, # Устанавливаем 0 вместо None (для CostPriceHistory)
sale_price=sale_price,
diff --git a/myproject/products/static/products/js/sales-units.js b/myproject/products/static/products/js/sales-units.js
index c7d1bca..9f8241e 100644
--- a/myproject/products/static/products/js/sales-units.js
+++ b/myproject/products/static/products/js/sales-units.js
@@ -57,7 +57,7 @@
data-min-qty="${unit.min_quantity}"
data-step="${unit.quantity_step}"
data-available="${unit.available_quantity || ''}">
- ${unit.name} (${unit.unit_short_name}) - ${price} руб.${isDefault}
+ ${unit.name} - ${price} руб.${isDefault}
`;
});
diff --git a/myproject/products/templates/products/product_detail.html b/myproject/products/templates/products/product_detail.html
index 00f3de8..8bd9796 100644
--- a/myproject/products/templates/products/product_detail.html
+++ b/myproject/products/templates/products/product_detail.html
@@ -292,7 +292,6 @@
| Название |
- Единица |
Коэфф. |
Цена |
Мин. кол-во |
@@ -306,9 +305,6 @@
{{ su.name }}
{% if su.is_default %}По умолчанию{% endif %}
-
- {{ su.unit.short_name }}
- |
{{ su.conversion_factor }} |
{% if su.sale_price %}
diff --git a/myproject/products/templates/products/product_form.html b/myproject/products/templates/products/product_form.html
index d00ffa9..f4a68ab 100644
--- a/myproject/products/templates/products/product_form.html
+++ b/myproject/products/templates/products/product_form.html
@@ -581,6 +581,157 @@
+
+ {% if sales_unit_formset %}
+
+
+
+
+ Настройте, в каких единицах продается товар (ветка, кг, штука).
+ Коэффициент указывает, сколько единиц продажи получается из 1 базовой единицы.
+
+
+ {{ sales_unit_formset.management_form }}
+
+
+
+ {% with form=sales_unit_formset.empty_form %}
+
+
+
+
+ {{ form.unit }}
+
+
+
+ {{ form.name }}
+
+
+
+ {{ form.conversion_factor }}
+
+
+
+ {{ form.price }}
+
+
+
+ {{ form.sale_price }}
+
+
+
+ {{ form.min_quantity }}
+
+
+
+ {{ form.quantity_step }}
+
+
+
+ {{ form.position }}
+
+
+
+ {{ form.is_default }}
+
+
+
+
+ {{ form.is_active }}
+
+
+
+
+
+ {% endwith %}
+
+
+
+ {% for form in sales_unit_formset %}
+
+ {% endfor %}
+
+
+
+
+
+ {% endif %}
+
+
+
{% if object %}
@@ -686,6 +837,58 @@ document.addEventListener('DOMContentLoaded', function() {
});
}, 250);
});
+
+ // === Динамическое добавление единиц продажи ===
+ const addButton = document.getElementById('add-sales-unit');
+ const container = document.getElementById('sales-units-container');
+ const totalFormsInput = document.querySelector('[name="sales_units-TOTAL_FORMS"]');
+
+ if (addButton && container && totalFormsInput) {
+ addButton.addEventListener('click', function() {
+ const formCount = parseInt(totalFormsInput.value);
+ const template = document.getElementById('empty-sales-unit-template');
+
+ if (template) {
+ // Клонируем содержимое шаблона
+ const newRow = template.content.cloneNode(true);
+ const rowDiv = newRow.querySelector('.sales-unit-row');
+
+ // Обновляем имена и id полей
+ rowDiv.querySelectorAll('input, select').forEach(input => {
+ const name = input.getAttribute('name');
+ const id = input.getAttribute('id');
+
+ if (name) {
+ // Заменяем __prefix__ на текущий индекс
+ input.setAttribute('name', name.replace('__prefix__', formCount));
+ }
+ if (id) {
+ input.setAttribute('id', id.replace('__prefix__', formCount));
+ }
+
+ // Устанавливаем значения по умолчанию
+ if (input.type === 'checkbox') {
+ if (input.name.includes('is_active')) {
+ input.checked = true;
+ } else {
+ input.checked = false;
+ }
+ } else if (input.type !== 'hidden') {
+ if (input.name.includes('min_quantity') || input.name.includes('quantity_step')) {
+ input.value = '1';
+ } else if (input.name.includes('position')) {
+ input.value = formCount;
+ } else if (input.name.includes('conversion_factor')) {
+ input.value = '1';
+ }
+ }
+ });
+
+ container.appendChild(rowDiv);
+ totalFormsInput.value = formCount + 1;
+ }
+ });
+ }
});
{% endblock %}
diff --git a/myproject/products/templates/products/uom/sales_unit_delete.html b/myproject/products/templates/products/uom/sales_unit_delete.html
index 11c5e8b..6a3979a 100644
--- a/myproject/products/templates/products/uom/sales_unit_delete.html
+++ b/myproject/products/templates/products/uom/sales_unit_delete.html
@@ -22,9 +22,6 @@
Название:
{{ sales_unit.name }}
- Единица:
- {{ sales_unit.unit.name }} ({{ sales_unit.unit.short_name }})
-
Коэффициент:
{{ sales_unit.conversion_factor }}
diff --git a/myproject/products/templates/products/uom/sales_unit_form.html b/myproject/products/templates/products/uom/sales_unit_form.html
index 035a430..8e3a53b 100644
--- a/myproject/products/templates/products/uom/sales_unit_form.html
+++ b/myproject/products/templates/products/uom/sales_unit_form.html
@@ -20,32 +20,18 @@
{% endif %}
-
-
-
-
- {{ form.product }}
- {% if form.product.help_text %}
- {{ form.product.help_text }}
- {% endif %}
- {% if form.product.errors %}
- {{ form.product.errors }}
- {% endif %}
-
-
-
- {{ form.unit }}
- {% if form.unit.help_text %}
- {{ form.unit.help_text }}
- {% endif %}
- {% if form.unit.errors %}
- {{ form.unit.errors }}
- {% endif %}
-
+
+
+
+ {{ form.product }}
+ {% if form.product.help_text %}
+ {{ form.product.help_text }}
+ {% endif %}
+ {% if form.product.errors %}
+ {{ form.product.errors }}
+ {% endif %}
diff --git a/myproject/products/templates/products/uom/sales_unit_list.html b/myproject/products/templates/products/uom/sales_unit_list.html
index 690fcf9..d2d4ac6 100644
--- a/myproject/products/templates/products/uom/sales_unit_list.html
+++ b/myproject/products/templates/products/uom/sales_unit_list.html
@@ -17,19 +17,9 @@
|