Реализована система управления стоимостью доставки и исправлен баг выбора клиента
Изменения: 1. **Стоимость доставки (автоматическая/ручная)**: - Добавлено поле `is_custom_delivery_cost` в модель Order для отслеживания ручной стоимости - Создан сервис DeliveryCostCalculator для автоматического расчета стоимости доставки - Реализована логика: бесплатная доставка от 100 руб., иначе 15 руб. - В форме поле "Ручная стоимость доставки" - если заполнено, используется ручная стоимость, если пустое - автоматический расчет - Добавлены методы Order.get_delivery_cost(), set_delivery_cost(), reset_delivery_cost(), recalculate_delivery_cost() 2. **Исправление бага выбора клиента в Select2**: - Удален избыточный обработчик события select2:opening, который блокировал клики - Добавлены проверки на наличие e.params.data в обработчиках select2:selecting и select2:select - Теперь выбор клиента работает корректно, создается черновик заказа и происходит редирект 3. **Опциональные поля адреса**: - Поля recipient_name, street, building_number в модели Address сделаны необязательными (blank=True, null=True) - Обновлены методы __str__ и full_address для безопасной работы с None значениями 4. **UI улучшения**: - Удалена звездочка обязательности с полей адреса - Добавлена подсказка под полем ручной стоимости доставки о правилах автоматического расчета 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -164,6 +164,11 @@ class OrderForm(forms.ModelForm):
|
||||
self.fields['recipient_name'].required = False
|
||||
self.fields['recipient_phone'].required = False
|
||||
|
||||
# Поле ручной стоимости доставки опционально
|
||||
self.fields['delivery_cost'].required = False
|
||||
self.fields['delivery_cost'].label = 'Ручная стоимость доставки'
|
||||
self.fields['delivery_cost'].help_text = 'Оставьте пустым для автоматического расчета'
|
||||
|
||||
# Инициализируем queryset для address_from_history
|
||||
# Это будет переопределено в представлении после выбора клиента
|
||||
if self.instance.pk and self.instance.customer:
|
||||
@@ -176,6 +181,30 @@ class OrderForm(forms.ModelForm):
|
||||
order__in=customer_orders
|
||||
).distinct().order_by('-created_at')
|
||||
|
||||
def save(self, commit=True):
|
||||
"""
|
||||
Сохраняет форму с учетом автоматического/ручного расчета стоимости доставки.
|
||||
Логика:
|
||||
- Если delivery_cost заполнено → используется ручное значение (is_custom_delivery_cost = True)
|
||||
- Если delivery_cost пустое → автоматический расчет (is_custom_delivery_cost = False)
|
||||
"""
|
||||
instance = super().save(commit=False)
|
||||
|
||||
# Получаем значение ручной стоимости доставки
|
||||
delivery_cost = self.cleaned_data.get('delivery_cost')
|
||||
|
||||
if delivery_cost is not None and delivery_cost > 0:
|
||||
# Ручное значение указано
|
||||
instance.set_delivery_cost(delivery_cost, is_custom=True)
|
||||
else:
|
||||
# Пустое поле или 0 → автоматический расчет
|
||||
instance.reset_delivery_cost()
|
||||
|
||||
if commit:
|
||||
instance.save()
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
class OrderItemForm(forms.ModelForm):
|
||||
"""Форма для позиции заказа"""
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# Generated by Django 5.0.10 on 2025-11-11 09:52
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('customers', '0002_remove_address_model'),
|
||||
('orders', '0004_remove_address_orders_addr_distric_fd94e9_idx_and_more'),
|
||||
('shops', '0001_initial'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='historicalorder',
|
||||
name='is_custom_delivery_cost',
|
||||
field=models.BooleanField(default=False, help_text='True если стоимость доставки была изменена вручную', verbose_name='Стоимость доставки установлена вручную'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='order',
|
||||
name='is_custom_delivery_cost',
|
||||
field=models.BooleanField(default=False, help_text='True если стоимость доставки была изменена вручную', verbose_name='Стоимость доставки установлена вручную'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='address',
|
||||
name='building_number',
|
||||
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='Номер здания'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='address',
|
||||
name='recipient_name',
|
||||
field=models.CharField(blank=True, help_text='Имя человека, которому будет доставлен заказ', max_length=200, null=True, verbose_name='Имя получателя'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='address',
|
||||
name='street',
|
||||
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Улица'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='order',
|
||||
index=models.Index(fields=['is_custom_delivery_cost'], name='orders_orde_is_cust_108e98_idx'),
|
||||
),
|
||||
]
|
||||
@@ -15,6 +15,8 @@ class Address(models.Model):
|
||||
# Информация о получателе
|
||||
recipient_name = models.CharField(
|
||||
max_length=200,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="Имя получателя",
|
||||
help_text="Имя человека, которому будет доставлен заказ"
|
||||
)
|
||||
@@ -29,11 +31,15 @@ class Address(models.Model):
|
||||
|
||||
street = models.CharField(
|
||||
max_length=255,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="Улица"
|
||||
)
|
||||
|
||||
building_number = models.CharField(
|
||||
max_length=20,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="Номер здания"
|
||||
)
|
||||
|
||||
@@ -94,17 +100,43 @@ class Address(models.Model):
|
||||
ordering = ['-created_at']
|
||||
|
||||
def __str__(self):
|
||||
address_line = f"{self.street}, {self.building_number}"
|
||||
# Собираем компоненты адреса
|
||||
address_parts = []
|
||||
if self.street:
|
||||
address_parts.append(self.street)
|
||||
if self.building_number:
|
||||
address_parts.append(self.building_number)
|
||||
if self.apartment_number:
|
||||
address_line += f", кв/офис {self.apartment_number}"
|
||||
address_parts.append(f"кв/офис {self.apartment_number}")
|
||||
|
||||
address_line = ", ".join(address_parts) if address_parts else "Адрес не указан"
|
||||
|
||||
# Формируем строку с именем получателя
|
||||
if self.recipient_name:
|
||||
return f"{self.recipient_name} - {address_line}"
|
||||
return address_line
|
||||
|
||||
@property
|
||||
def full_address(self):
|
||||
"""Полный адрес для доставки"""
|
||||
address = f"{self.street}, {self.building_number}"
|
||||
# Собираем основные компоненты адреса
|
||||
address_parts = []
|
||||
if self.street:
|
||||
address_parts.append(self.street)
|
||||
if self.building_number:
|
||||
address_parts.append(self.building_number)
|
||||
|
||||
# Если нет основных данных, возвращаем сообщение
|
||||
if not address_parts:
|
||||
return "Адрес не указан"
|
||||
|
||||
address = ", ".join(address_parts)
|
||||
|
||||
# Добавляем квартиру/офис
|
||||
if self.apartment_number:
|
||||
address += f", кв/офис {self.apartment_number}"
|
||||
|
||||
# Собираем дополнительные детали
|
||||
details = []
|
||||
if self.entrance:
|
||||
details.append(f"подъезд {self.entrance}")
|
||||
@@ -112,6 +144,7 @@ class Address(models.Model):
|
||||
details.append(f"этаж {self.floor}")
|
||||
if details:
|
||||
address += f" ({', '.join(details)})"
|
||||
|
||||
return address
|
||||
|
||||
|
||||
@@ -193,6 +226,12 @@ class Order(models.Model):
|
||||
help_text="0 для самовывоза"
|
||||
)
|
||||
|
||||
is_custom_delivery_cost = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name="Стоимость доставки установлена вручную",
|
||||
help_text="True если стоимость доставки была изменена вручную"
|
||||
)
|
||||
|
||||
# Статус заказа
|
||||
STATUS_CHOICES = [
|
||||
('draft', 'Черновик'),
|
||||
@@ -351,6 +390,7 @@ class Order(models.Model):
|
||||
models.Index(fields=['payment_status']),
|
||||
models.Index(fields=['created_at']),
|
||||
models.Index(fields=['order_number']),
|
||||
models.Index(fields=['is_custom_delivery_cost']),
|
||||
]
|
||||
ordering = ['-created_at']
|
||||
|
||||
@@ -387,9 +427,56 @@ class Order(models.Model):
|
||||
'delivery_time_end': 'Время окончания должно быть позже времени начала'
|
||||
})
|
||||
|
||||
def get_delivery_cost(self):
|
||||
"""
|
||||
Возвращает стоимость доставки:
|
||||
- Если установлена вручную - использует ручное значение
|
||||
- Если автоматическая - вычисляет на основе правил
|
||||
|
||||
Returns:
|
||||
Decimal: Стоимость доставки
|
||||
"""
|
||||
if self.is_custom_delivery_cost:
|
||||
return self.delivery_cost
|
||||
else:
|
||||
from orders.services.delivery_cost_calculator import DeliveryCostCalculator
|
||||
return DeliveryCostCalculator.calculate(self)
|
||||
|
||||
def set_delivery_cost(self, cost, is_custom=True):
|
||||
"""
|
||||
Устанавливает стоимость доставки.
|
||||
|
||||
Args:
|
||||
cost: Новая стоимость доставки (Decimal)
|
||||
is_custom: True если устанавливается вручную, False если автоматически
|
||||
"""
|
||||
self.delivery_cost = cost
|
||||
self.is_custom_delivery_cost = is_custom
|
||||
|
||||
def reset_delivery_cost(self):
|
||||
"""
|
||||
Сбрасывает стоимость доставки на автоматический расчет.
|
||||
"""
|
||||
from orders.services.delivery_cost_calculator import DeliveryCostCalculator
|
||||
self.delivery_cost = DeliveryCostCalculator.calculate(self)
|
||||
self.is_custom_delivery_cost = False
|
||||
|
||||
def recalculate_delivery_cost(self):
|
||||
"""
|
||||
Пересчитывает стоимость доставки, если она не установлена вручную.
|
||||
Используется при изменении параметров заказа (товаров, адреса и т.д.)
|
||||
"""
|
||||
if not self.is_custom_delivery_cost:
|
||||
from orders.services.delivery_cost_calculator import DeliveryCostCalculator
|
||||
self.delivery_cost = DeliveryCostCalculator.calculate(self)
|
||||
|
||||
def calculate_total(self):
|
||||
"""Рассчитывает итоговую сумму заказа"""
|
||||
items_total = sum(item.get_total_price() for item in self.items.all())
|
||||
|
||||
# Пересчитываем стоимость доставки если она автоматическая
|
||||
self.recalculate_delivery_cost()
|
||||
|
||||
subtotal = items_total + self.delivery_cost
|
||||
self.total_amount = subtotal - self.discount_amount
|
||||
return self.total_amount
|
||||
@@ -416,6 +503,16 @@ class Order(models.Model):
|
||||
"""Остаток к оплате"""
|
||||
return max(self.total_amount - self.amount_paid, 0)
|
||||
|
||||
@property
|
||||
def delivery_cost_display(self):
|
||||
"""
|
||||
Возвращает строку для отображения стоимости доставки с пометкой.
|
||||
Полезно в админке и шаблонах.
|
||||
"""
|
||||
cost = self.get_delivery_cost()
|
||||
suffix = " (ручная)" if self.is_custom_delivery_cost else " (авто)"
|
||||
return f"{cost} руб.{suffix}"
|
||||
|
||||
@property
|
||||
def delivery_info(self):
|
||||
"""Информация о доставке для отображения"""
|
||||
|
||||
95
myproject/orders/services/delivery_cost_calculator.py
Normal file
95
myproject/orders/services/delivery_cost_calculator.py
Normal file
@@ -0,0 +1,95 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Сервис для расчета стоимости доставки.
|
||||
Содержит расширяемую логику вычисления на основе различных условий.
|
||||
"""
|
||||
from decimal import Decimal
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from orders.models import Order
|
||||
|
||||
|
||||
class DeliveryCostCalculator:
|
||||
"""
|
||||
Калькулятор стоимости доставки.
|
||||
Применяет различные правила для автоматического расчета.
|
||||
"""
|
||||
|
||||
# Константы для правил расчета
|
||||
FREE_DELIVERY_THRESHOLD = Decimal('100.00') # Бесплатная доставка от суммы
|
||||
BASE_DELIVERY_COST = Decimal('15.00') # Базовая стоимость доставки
|
||||
MIN_DELIVERY_COST = Decimal('0.00') # Минимальная стоимость
|
||||
|
||||
@classmethod
|
||||
def calculate(cls, order: 'Order') -> Decimal:
|
||||
"""
|
||||
Рассчитывает стоимость доставки на основе условий заказа.
|
||||
|
||||
Args:
|
||||
order: Заказ для расчета
|
||||
|
||||
Returns:
|
||||
Decimal: Рассчитанная стоимость доставки
|
||||
"""
|
||||
# Самовывоз - доставка бесплатная
|
||||
if not order.is_delivery:
|
||||
return cls.MIN_DELIVERY_COST
|
||||
|
||||
# Рассчитываем сумму товаров
|
||||
items_total = sum(
|
||||
item.get_total_price()
|
||||
for item in order.items.all()
|
||||
)
|
||||
|
||||
# Применяем правила расчета
|
||||
cost = cls._apply_calculation_rules(order, items_total)
|
||||
|
||||
return cost
|
||||
|
||||
@classmethod
|
||||
def _apply_calculation_rules(cls, order: 'Order', items_total: Decimal) -> Decimal:
|
||||
"""
|
||||
Применяет правила расчета стоимости доставки.
|
||||
Этот метод легко расширить для добавления новых правил.
|
||||
|
||||
Args:
|
||||
order: Заказ
|
||||
items_total: Сумма товаров в заказе
|
||||
|
||||
Returns:
|
||||
Decimal: Стоимость доставки
|
||||
"""
|
||||
# Правило 1: Бесплатная доставка при заказе от определенной суммы
|
||||
if items_total >= cls.FREE_DELIVERY_THRESHOLD:
|
||||
return cls.MIN_DELIVERY_COST
|
||||
|
||||
# Правило 2: Базовая стоимость доставки
|
||||
cost = cls.BASE_DELIVERY_COST
|
||||
|
||||
# Правило 3: Можно добавить расчет по адресу
|
||||
# if order.delivery_address:
|
||||
# cost += cls._calculate_distance_cost(order.delivery_address)
|
||||
|
||||
# Правило 4: Можно добавить надбавку за срочность
|
||||
# if cls._is_urgent_delivery(order):
|
||||
# cost *= Decimal('1.5')
|
||||
|
||||
return cost
|
||||
|
||||
@classmethod
|
||||
def _calculate_distance_cost(cls, address) -> Decimal:
|
||||
"""
|
||||
Рассчитывает надбавку за расстояние.
|
||||
Placeholder для будущей реализации с геокодингом.
|
||||
"""
|
||||
# TODO: Интеграция с картами для расчета расстояния
|
||||
return Decimal('0.00')
|
||||
|
||||
@classmethod
|
||||
def _is_urgent_delivery(cls, order: 'Order') -> bool:
|
||||
"""
|
||||
Проверяет, является ли доставка срочной.
|
||||
"""
|
||||
# TODO: Логика определения срочности
|
||||
return False
|
||||
@@ -213,7 +213,7 @@
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.address_street.id_for_label }}" class="form-label">
|
||||
{{ form.address_street.label }} <span class="text-danger">*</span>
|
||||
{{ form.address_street.label }}
|
||||
</label>
|
||||
{{ form.address_street }}
|
||||
{% if form.address_street.errors %}
|
||||
@@ -224,7 +224,7 @@
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.address_building_number.id_for_label }}" class="form-label">
|
||||
{{ form.address_building_number.label }} <span class="text-danger">*</span>
|
||||
{{ form.address_building_number.label }}
|
||||
</label>
|
||||
{{ form.address_building_number }}
|
||||
{% if form.address_building_number.errors %}
|
||||
@@ -297,33 +297,70 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="mb-3 form-check">
|
||||
{{ form.address_confirm_with_recipient }}
|
||||
<label class="form-check-label" for="{{ form.address_confirm_with_recipient.id_for_label }}">
|
||||
<div class="mb-3">
|
||||
<!-- Крупный переключатель (switch) -->
|
||||
<div class="form-check form-switch" style="padding-left: 3.5em;">
|
||||
<input class="form-check-input" type="checkbox" role="switch"
|
||||
id="{{ form.address_confirm_with_recipient.id_for_label }}"
|
||||
name="{{ form.address_confirm_with_recipient.name }}"
|
||||
style="width: 3em; height: 1.5em; cursor: pointer;">
|
||||
<label class="form-check-label" for="{{ form.address_confirm_with_recipient.id_for_label }}"
|
||||
style="font-size: 1.1em; font-weight: 500; cursor: pointer; padding-left: 0.5em;">
|
||||
<i class="bi bi-telephone-fill text-primary"></i>
|
||||
{{ form.address_confirm_with_recipient.label }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Получатель -->
|
||||
<div class="border-top pt-3 mt-3">
|
||||
<h6 class="mb-3">Получатель</h6>
|
||||
|
||||
<!-- Чекбокс "Покупатель = получатель" -->
|
||||
<div class="mb-3 form-check">
|
||||
{{ form.customer_is_recipient }}
|
||||
<label class="form-check-label" for="{{ form.customer_is_recipient.id_for_label }}">
|
||||
<!-- Поля получателя из модели Address -->
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="id_address_recipient_name" class="form-label">
|
||||
Имя получателя
|
||||
</label>
|
||||
<input type="text" name="address_recipient_name" id="id_address_recipient_name"
|
||||
class="form-control" placeholder="Имя получателя">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="id_address_recipient_phone" class="form-label">
|
||||
Телефон получателя
|
||||
</label>
|
||||
<input type="text" name="address_recipient_phone" id="id_address_recipient_phone"
|
||||
class="form-control" placeholder="Телефон получателя">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Крупный переключатель "Покупатель = получатель" -->
|
||||
<div class="mb-3">
|
||||
<div class="form-check form-switch" style="padding-left: 3.5em;">
|
||||
<input class="form-check-input" type="checkbox" role="switch"
|
||||
id="{{ form.customer_is_recipient.id_for_label }}"
|
||||
name="{{ form.customer_is_recipient.name }}"
|
||||
style="width: 3em; height: 1.5em; cursor: pointer;">
|
||||
<label class="form-check-label" for="{{ form.customer_is_recipient.id_for_label }}"
|
||||
style="font-size: 1.1em; font-weight: 500; cursor: pointer; padding-left: 0.5em;">
|
||||
<i class="bi bi-person-check-fill text-primary"></i>
|
||||
Покупатель является получателем
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Поля получателя (показываются когда покупатель != получатель) -->
|
||||
<div class="row" id="recipient-fields" style="display: none;">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.recipient_name.id_for_label }}" class="form-label">
|
||||
Имя получателя <span class="text-danger">*</span>
|
||||
Имя получателя
|
||||
</label>
|
||||
{{ form.recipient_name }}
|
||||
{% if form.recipient_name.errors %}
|
||||
@@ -334,7 +371,7 @@
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.recipient_phone.id_for_label }}" class="form-label">
|
||||
Телефон получателя <span class="text-danger">*</span>
|
||||
Телефон получателя
|
||||
</label>
|
||||
{{ form.recipient_phone }}
|
||||
{% if form.recipient_phone.errors %}
|
||||
@@ -349,11 +386,17 @@
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.delivery_cost.id_for_label }}" class="form-label">Стоимость доставки</label>
|
||||
<label for="{{ form.delivery_cost.id_for_label }}" class="form-label">
|
||||
{{ form.delivery_cost.label }}
|
||||
</label>
|
||||
{{ form.delivery_cost }}
|
||||
{% if form.delivery_cost.errors %}
|
||||
<div class="text-danger">{{ form.delivery_cost.errors }}</div>
|
||||
{% endif %}
|
||||
<small class="d-block text-muted mt-1">
|
||||
<i class="bi bi-info-circle"></i>
|
||||
Оставьте пустым для автоматического расчета (бесплатно от 100 руб., иначе 15 руб.)
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -666,11 +709,19 @@ function initCustomerSelect2() {
|
||||
|
||||
// Обработчик для перехвата ПЕРЕД выбором (используется для фальшивых опций)
|
||||
$customerSelect.on('select2:selecting', function(e) {
|
||||
console.log('9. Событие select2:selecting, e.params:', e.params);
|
||||
|
||||
// Проверяем наличие e.params и e.params.data
|
||||
if (!e.params || !e.params.data) {
|
||||
console.log('9a. Нет данных в e.params на selecting, пропускаем');
|
||||
return;
|
||||
}
|
||||
|
||||
const data = e.params.data;
|
||||
console.log('9a. Попытка выбрать элемент (перед выбором):', data);
|
||||
console.log('9b. Попытка выбрать элемент (перед выбором):', data);
|
||||
|
||||
if (data.is_create_option) {
|
||||
console.log('9b. Это опция создания клиента - предотвращаем выбор и открываем модаль');
|
||||
console.log('9c. Это опция создания клиента - предотвращаем выбор и открываем модаль');
|
||||
// Предотвращаем выбор этой опции
|
||||
e.preventDefault();
|
||||
// Очищаем значение
|
||||
@@ -679,48 +730,21 @@ function initCustomerSelect2() {
|
||||
window.openCreateCustomerModal(data.search_text);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Обработчик прямого клика на результаты (для "create option")
|
||||
$customerSelect.on('select2:opening', function(e) {
|
||||
console.log('9_open. Dropdown открывается, добавляем обработчик клика');
|
||||
// Добавляем обработчик на клик по результатам в следующем event tick
|
||||
setTimeout(function() {
|
||||
const resultsContainer = document.querySelector('.select2-results');
|
||||
console.log('9_search. resultsContainer найден:', !!resultsContainer);
|
||||
if (resultsContainer) {
|
||||
resultsContainer.addEventListener('click', function handleCreateOptionClick(event) {
|
||||
console.log('9_click. Клик по результатам:', event.target);
|
||||
const target = event.target.closest('.select2-results__option');
|
||||
console.log('9_option. Ближайший option:', target);
|
||||
if (!target) return;
|
||||
|
||||
// Проверяем текст опции - если это "Создать клиента", открываем модаль
|
||||
const optionText = target.textContent.trim();
|
||||
console.log('9_text. Текст опции:', optionText);
|
||||
|
||||
if (optionText.startsWith('Создать клиента:')) {
|
||||
console.log('9c. Клик на create option напрямую');
|
||||
// Извлекаем поисковый текст (удаляем "Создать клиента: ")
|
||||
const searchText = optionText.replace(/^Создать\s+клиента:\s*"([^"]*)"\s*$/, '$1') || optionText;
|
||||
|
||||
console.log('9d. Открываем модаль с текстом:', searchText);
|
||||
window.openCreateCustomerModal(searchText);
|
||||
|
||||
// Закрываем dropdown
|
||||
$customerSelect.select2('close');
|
||||
|
||||
// Удаляем обработчик
|
||||
resultsContainer.removeEventListener('click', handleCreateOptionClick);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 0);
|
||||
console.log('9d. Обычный клиент, разрешаем выбор');
|
||||
});
|
||||
|
||||
$customerSelect.on('select2:select', function(e) {
|
||||
console.log('10. Событие select2:select, e.params:', e.params);
|
||||
|
||||
// Проверяем наличие e.params и e.params.data
|
||||
if (!e.params || !e.params.data) {
|
||||
console.log('10a. Нет данных в e.params, пропускаем обработку');
|
||||
return;
|
||||
}
|
||||
|
||||
const data = e.params.data;
|
||||
console.log('10. Выбран элемент:', data);
|
||||
console.log('10b. Выбран элемент:', data);
|
||||
|
||||
if (data.is_create_option) {
|
||||
console.log('11. Открываем модальное окно для создания клиента');
|
||||
@@ -731,7 +755,7 @@ function initCustomerSelect2() {
|
||||
window.openCreateCustomerModal(data.search_text);
|
||||
} else {
|
||||
// Триггерим нативное change событие для других обработчиков (например, draft-creator.js)
|
||||
console.log('12. Триггерим нативное change событие');
|
||||
console.log('12. Триггерим нативное change событие для customer ID:', data.id);
|
||||
const changeEvent = new Event('change', { bubbles: true });
|
||||
this.dispatchEvent(changeEvent);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user