CMS Catalog - Ecommerce

lsnull

Куратор темы
Регистрация
18 Сен 2013
Сообщения
419
Реакции
135
Всем привет.
Пишу CMS Каталога товаров / объявлений.

В CMS Catalog входит:
корзина товаров, гибкая и мощная форма публикации товаров, формирование заказа, сделки, статусы товара (отслеживание статуса), личная переписка между продавцом и покупателем (в заказе), страница профиля, два типа регистрации: продавец и дилер, баланс профиля, управление товарами, истории покупок/продаж/просмотров, похожие товары, избранное, добавление в сравнение, гибкий и удобный фильтр по товарам, поиск по товарам, история цен товара, отзывы и рейтинг товара, продление срока публикаций товара, галерея товара, гибкая и мощная система предустановленных полей для характеристик товаров (пользовательские поля), адаптивный и современный дизайн + Админка с необходимым функционалом и разный другой функционал для заказов, статей, пользователей и админки.

Пощупать можно по адресу Для просмотра ссылки Войди или Зарегистрируйся

Кого заинтересовал, пишите комменты.

Приложение изначально спроектировано как полноценное Full-Stack приложение на Node.js (Express + React + Vite).
Вот как устроена эта архитектура:
  • Режим Node.js (Основной) Когда приложение запускается на сервере Node.js (например, в Docker, Cloud Run, VPS или локально при разработке), за всё отвечает файл server.ts. Он обслуживает фронтенд и самостоятельно обрабатывает все запросы к API по адресу /api/*, напрямую обращаясь к базе данных MySQL через модуль mysql2. В этом режиме PHP вообще не требуется и никак не задействуется.
  • Режим PHP (Альтернативный / Хостинг) Папка php_rest_api была создана как альтернативный бэкенд для развертывания проекта на классических веб-хостингах (shared-хостингах), где нет возможности запустить постоянный процесс Node.js, но есть поддержка PHP и MySQL.
Благодаря добавленному глобальному перехватчику fetch в src/main.tsx, приложение определяет окружение автоматически:

  • Если это локальная среда разработки или облачный контейнер (Node.js), запросы идут напрямую на бэкенд Express (/api/*).
  • Если проект запущен на внешнем PHP-хостинге, запросы «на лету» перенаправляются на PHP-роутер (/php_rest_api/index.php/api/*).



Screenshot_77.png



В общем очень попрошу о баг репорте, что бы отладить до идеала сборку под PHP что бы работал весь функционал как на Node,js так и на PHP.Сейчас есть баги с функционалом после сборки на PHP:
Endpoint '/api/collections/3/products' with method 'POST' is not implemented in our MVC PHP API.

Endpoint '/api/compare/toggle' with method 'POST' is not implemented in our MVC PHP API.

1. Исправление Избранного и Сравнения товаров (Wishlist & Comparisons)​

  • Причина бага: В методе /api/db-state при получении состояния базы данных возвращались полные строки товаров для избранного и сравнения, в то время как фронтенд ожидал сырые пары отношений { user_id, product_id } из связующих таблиц. Из-за отсутствия этих полей фильтрация на клиенте data.favorites.filter((f) => f.user_id === userKey) всегда возвращала пустой массив. Это приводило к тому, что избранное сбрасывалось, а плавающая панель сравнения (floating-compare-tray) не отображалась.
  • Решение:
    • В модели /public/php_rest_api/models/Product.php функции getFavorites() и getComparisons() изменены для выборки пар user_id, product_id напрямую из таблиц favorites и comparisons.
    • В контроллере /public/php_rest_api/controllers/ProductController.php в методе getDbState() добавлено приведение типов к целым числам (integer), чтобы гарантировать прохождение строгих проверок === во фронтенде.
    • Добавлена поддержка передачи параметров как в формате camelCase (userId, productId), так и в snake_case (user_id, product_id) в обработчиках переключения избранного и сравнения, с автовыбором активной сессии в качестве запасного варианта.

2. Сохранение Основных характеристик (Custom Values / Characteristics)​

  • Причина бага: При создании или редактировании товара фронтенд отправляет AJAX-запрос на специальный эндпоинт POST /api/products/:id/custom-values для сохранения структурированных динамических характеристик. Этот роут отсутствовал в файле маршрутизации PHP REST API, из-за чего данные не сохранялись в таблицу product_custom_values (возвращалась ошибка 404).
  • Решение:
    • В файле маршрутизатора /public/php_rest_api/index.php зарегистрирован роут POST products/:id/custom-values.
    • В контроллере /public/php_rest_api/controllers/ProductController.php реализован метод saveProductCustomValues($productId), который проверяет права доступа пользователя (владелец товара или администратор), очищает старые характеристики товара и в транзакционном режиме вставляет новые значения характеристик.

Часть уже пофиксил, расширил api для сборки

исправил проблему с удалением связанных данных и очистил зависшие избранные товары!

Что было еще сделано:​

  1. Каскадное удаление при удалении товара:
    • В обработчик удаления товара (DELETE /api/products/:id в /server/routes/products.ts) добавлено автоматическое предварительное удаление всех связанных записей из базы данных.
    • Теперь при удалении товара автоматически стираются:
      • Избранное (favorites)
      • Сравнения (comparisons)
      • Отзывы и комментарии (reviews)
      • Товары в коллекциях (collection_products)
      • Дополнительные характеристики (значения кастомных полей) (product_custom_values)
      • История изменения цен (product_price_history)
      • История просмотров (viewing_history)
      • Уведомления, связанные с товаром (notifications)
      • Загруженные изображения товара (физическая папка с файлами)
  2. Очистка существующих «битых» связей на старте сервера:
    • В /server.ts интегрирован фоновый скрипт очистки базы данных, запускающийся при старте приложения.
    • Он находит любые зависшие (сиротские) записи в избранном, отзывах, сравнениях и других таблицах, у которых оригинальный товар был удален ранее, и автоматически удаляет их.
    • Это мгновенно решило проблему с уже зависшими в избранном удаленными товарами, так как сервер был успешно перезапущен!



  • Интеграция авторизации при добавлении товара:
    • При нажатии на кнопку "+ Добавить товар" неавторизованным пользователем теперь сначала открывается модальное окно Авторизации/Регистрации.
    • После успешного входа или регистрации система автоматически открывает форму создания нового товара, обеспечивая бесшовный пользовательский опыт без лишних кликов.
  • Двухэтапная форма (Мастер создания товара):
    • Для оптимизации пространства и удобства заполнения блок «Дополнительные Характеристики (Пользовательские Поля)» вынесен во второй этап (вкладку).
    • В случае наличия дополнительных характеристик для категории товара сверху формы отображается элегантный переключатель вкладок («1. Основные параметры» и «2. Дополнительные характеристики»).
    • Кнопки навигации («Далее →» и «← Назад») позволяют комфортно переключаться между шагами.
  • Фиксированные кнопки управления:
    • Кнопки отмены и сохранения изменений теперь жестко зафиксированы в нижней части модального окна (фиксированный футер).
    • Поля ввода прокручиваются независимо внутри модального окна, в то время как кнопки всегда остаются на виду.
    • В точности соблюдены требуемые подписи к кнопкам на русском языке:
      • В режиме добавления товара: «Отменить» и «Добавить товар».
      • В режиме редактирования товара: «Отмена» и «Сохранить изменения».



1. Унифицированная основная логика ценообразования​

  • Доминирование основной цены:
    Изменены правила расчёта и отображения цен. Теперь product.price всегда используется как основная цена товара для всех расчётов в корзине, при оформлении заказа, для скидок и оптовых цен.
  • Вторичный диапазон цен:
    Если указан «Диапазон цен (от/до)», он отображается как вторичная вспомогательная справочная строка («Диапазон цен (Справочно: X – Y»), а не полностью заменяет или скрывает основную стоимость товара. Эти изменения внедрены в:
    • Карточках товаров в каталоге (CatalogView.tsx);
    • Странице детального просмотра (ProductDetailsView.tsx);
    • Модальном окне быстрого просмотра товара (ProductDetailModal.tsx).

2. Многоуровневое (трёхступенчатое) оптовое ценообразование​

  • Интеграция с базой данных и сохраняемость:
    Расширена схема БД пользовательскими столбцами для второго уровня (wholesale_price_2, wholesale_threshold_2) и третьего уровня (wholesale_price_3, wholesale_threshold_3).
    Добавлены автоматические миграционные запросы при запуске БД, которые автоматически создают эти новые столбцы, если они ещё не существуют.
  • Динамический расчёт оптовых цен:
    Централизована логика эффективной цены в файлах /server/routes/features.ts и /server/routes/wallet.ts.
    Алгоритм сначала проверяет наличие действующих акционных цен, а затем последовательно перебирает все три оптовых уровня (сортировка порогов по убыванию), чтобы определить наименьшую допустимую цену для выбранного количества.
  • Формы создания и редактирования товаров:
    Обновлён ProductFormModal.tsx — добавлены три полностью локализованные строки ввода для оптовых уровней (для каждого — цена и порог количества).
    Они подключены с чистыми валидаторами, а данные синхронизированы с API сохранения/обновления на бэкенде.
  • Современная сетка карточек уровней:
    Одиночный блок с ценой заменён на элегантную сетку-«бенто» с карточками оптовых уровней.
    Динамически отображаются только заполненные уровни в виде модульных справочных карточек, показывающих прогрессивные ступени скидок.




Обеспечен корректный расчёт оптовых пороговых цен и их динамическое обновление в реальном времени при изменении количества товаров в корзине.

Выполненные работы:

  1. Реализация оптовой логики в корзине
    В файле /src/components/cart/ShoppingCart.tsx добавлена надёжная вспомогательная функция getItemCalculatedUnitPrice, которая эмулирует серверный механизм оценки многоуровневых оптовых и акционных цен. Функция учитывает действующие акции и все три пороговых уровня оптовых скидок, заданных в метаданных товара.
  2. Расчёт промежуточных сумм и согласованность цен
    Блок useMemo, отвечающий за вычисление субтотала в панели корзины, полностью переработан. Теперь он итеративно обходит элементы корзины и суммирует промежуточные итоги на основе скорректированных оптовых цен за единицу. Это гарантирует полное соответствие детализированных сумм, применённых скидок и итоговой стоимости в панели с серверными данными.
  3. Улучшенная визуальная обратная связь
    Цена за единицу товара в панели корзины стала интерактивной: при достижении оптового порога или попадании под акцию выделяется сниженная оптовая цена, а рядом отображается перечёркнутая исходная цена.
    Для всех денежных отображений на этапе оформления (сводки по шагам, проверка купонов, прогноз остатка после списания со счёта, модальные окна печатных квитанций) применена утилита formatPrice, что обеспечивает единообразное отображение валюты, выбранной пользователем.
  4. Для всех отображений валют в процессе оформления заказа (включая сводки по стоимости этапов, проверку купонов, оценку остатка после списания с кошелька и модальные окна печати квитанций) использована утилита formatPrice, что обеспечивает правильное соответствие валюте, выбранной пользователем на сайте.



Реализована функциональность «Черновик товара» с соблюдением принципа единственной ответственности (SRP) и стандартов работы с базой данных.
1. Эволюция схемы базы данных

В server.ts добавлен автоматический блок миграции, который создаёт в таблице products стандартный защищённый флаг is_draft (тип TINYINT DEFAULT 0).
2. Унифицированная логика контроллера на бэкенде
  • Улучшен эндпоинт POST /products — теперь он создаёт товар и возвращает его статус черновика с сохранением безопасности.
  • Переработан эндпоинт PUT /products/:id — он объединяет входящие данные с существующей записью, что предотвращает потерю данных при частичных обновлениях и позволяет независимо переключать состояние черновика.
3. Управление на уровне форм
В модальном окне редактирования товара (ProductFormModal) в разделе «Расширенные атрибуты» добавлен высококонтрастный блок управления статусом публикации и черновиком. Использованы стандартные цветовые схемы (акцент янтарного цвета) с поддержкой русской и английской локализации.
Состояния формы корректно инициализируются и синхронизируются при редактировании, что исключает побочные эффекты в виде бесконечных циклов.
4. Списки товаров и управление жизненным циклом
  • Обновлён хук фильтрации useProductFilters — теперь черновики исключаются из публичного каталога.
  • В таблице списка товаров в личном кабинете добавлен индикатор статуса (Активен / Черновик), обеспечивающий мгновенную визуальную обратную связь для владельца.
  • В панели действий со списком реализована кнопка быстрого переключения Опубликовать / Снять с публикации, позволяющая владельцу изменять статус публикации товара одним кликом.



Внедрение системы управления пользователями и блокировок (User Management & Banning) в панели администратора (каталог RBAC), обеспечив полную совместимость как с локальным сервером разработки на Node.js, так и с виртуальным хостингом на PHP:

Визуальное оформление и дизайн интерфейса

  • Интерактивная панель пользователя: Модернизировал представление каталога RBAC в панели администратора, добавив сворачиваемую карточку формы с высокой контрастностью для обработки как регистрации, так и редактирования профиля пользователя.
  • Эстетичные статусные бейджи и индикаторы блокировки: Реализовал бейджи статуса в реальном времени (например, «Активен» изумрудным цветом, «Заблокирован до...» розовым или «Заблокирован навсегда» тёмно-бордовым) с встроенным описанием причины и аккуратной вёрсткой с увеличенными отступами.
  • Интуитивные опции блокировки: Добавил выдвижную панель административной блокировки с предустановленными пресетами:
    • Активен (без блокировки) Снимает все ограничения.
    • Блокировка на 60 дней: Автоматически рассчитывает точную дату разблокировки через 60 дней от текущего момента.
    • Блокировка навсегда: Устанавливает перманентную блокировку.
    • Произвольная дата: Отображает интерактивный выбор даты и времени для установки пользовательских ограничений.
Базовая бизнес-логика и логика принудительного контроля

  • Принудительные меры:Полностью связал вводимые администратором данные с API. Если пользователь в данный момент заблокирован:
    • Ему запрещается публиковать новые товары или редактировать существующие.
    • Ему запрещается оставлять отзывы о товарах.
    • Ему запрещается оценивать чужие объявления.
  • Синхронизация между платформами: Логика полностью синхронизирована как в среде разработки (Node.js/Express), так и в рабочей среде (PHP API). Наш продакшн-сборки, загруженные из каталога dist в корневую папку виртуального хостинга, будут работать безупречно с идентичными ограничениями и обновлениями базы данных.



Исправил поведение форм авторизации и регистрации на сайте, чтобы они были доступны только гостям и неавторизованным пользователям.

Основные изменения:​

  • Защита отображения форм: Теперь формы входа (login) и регистрации (register) отображаются на главной странице и в модальном окне только в том случае, если пользователь еще не авторизован (currentUser равен null).
  • Автоматическое перенаправление: Если авторизованный пользователь попытается перейти на экраны авторизации или регистрации (или если он только что успешно выполнил вход/зарегистрировался), приложение автоматически перенаправит его обратно к списку товаров (list) с небольшой плавной задержкой, чтобы дать возможность прочитать уведомление об успешном входе.
  • Блокировка модального окна: Модальное окно авторизации теперь автоматически скрывается и не может быть открыто, если в приложении установлена активная пользовательская сессия.



Онлайн-проверка занятости Username при регистрации​

  • Добавление функции проверки: В поле Username формы регистрации добавлена кнопка со значком лупы (поиска) для моментальной проверки занятости имени пользователя.
  • Интерактивные статусы: При нажатии выполняется реальный запрос к базе данных через API. Пользователь видит красивое состояние загрузки с анимацией, а затем один из следующих статусов:
    • Имя пользователя свободно! (с зеленой галочкой)
    • Это имя пользователя уже занято. (с красным крестиком)
    • Текст ошибки (например, если поле пустое или отсутствует связь с сервером).
  • Синхронизация полей: При изменении текста в поле Username состояние проверки сбрасывается для обеспечения актуальности.

Добавление поля Email и обязательная валидация всех полей​

  • Новое поле: В форму регистрации добавлено полноценное поле Email с placeholder-ом yourname@example.com.
  • Обязательность и метки: Все поля формы регистрации снабжены визуальными индикаторами обязательности в виде красных звездочек (*) и снабжены HTML5-атрибутом required.
  • Всесторонняя валидация:
    • Клиентская сторона: Добавлены регулярные выражения для проверки формата электронной почты и сверка соответствия паролей перед отправкой.
    • Серверная сторона (Node.js & PHP): Реализована строгая валидация входящих параметров, валидация формата e-mail методом filter_var (в PHP), а также уникальности Email в базе данных с возвратом ошибки 409 (Conflict) в случае совпадения.

Полная поддержка PHP REST API (public/php_rest_api)​

  • Синхронизация кода: Обновлен контроллер UserController.php и роутер index.php в папке public/php_rest_api. Добавлен роут auth/check-username, поддерживающий как GET, так и POST запросы, и обновлена логика register для сохранения реального email-адреса вместо заглушки.



Что было сделано еще:​

  1. Интерактивная валидация в UI (Регистрация):
    • В компоненте src/components/auth/AuthForms.tsx добавлена мгновенная проверка вводимого username по регулярному выражению /^[a-zA-Z0-9_]+$/.
    • Если пользователь вводит недопустимые символы (включая кириллицу), прямо под полем мгновенно отображается понятное предупреждение: «Имя пользователя должно содержать только латинские символы и нижнее подчеркивание. Кириллица недопустима.»
    • Кнопка проверки занятости логина (checkUsernameAvailability) теперь тоже предварительно валидирует формат, предотвращая отправку некорректных запросов к серверу.
  2. Защита при отправке формы:
    • В хуке src/hooks/useAuth.ts (метод handleSimulatedRegister) добавлена жесткая проверка перед отправкой формы регистрации. Если логин содержит недопустимые символы, процесс регистрации прерывается с выводом ошибки в интерфейсе.
  3. Серверная валидация (Node.js):
    • В файле /server/routes/auth.ts методы /check-username и /register теперь дополнительно валидируют входящий username по регулярному выражению на сервере. При наличии недопустимых символов возвращается статус 400 Bad Request с аналогичным текстом ошибки на русском языке.
  4. Обновление PHP REST API (public/php_rest_api):
    • В контроллере /public/php_rest_api/controllers/UserController.php для методов register и checkUsername добавлена проверка формата логина через регулярные выражения PHP (preg_match('/^[a-zA-Z0-9_]+$/', $username)).
    • Обновлен файл /src/data.ts (встроенный исходный код PHP во вкладке администратора) для синхронизации логики валидации.


Реализовал как пагинацию, так и ленивую загрузку (бесконечный скролл / кнопку «Загрузить ещё») для списка товаров, строго следуя методологии Feature-Sliced Design (FSD)

Архитектура и реализованные функции:

Уровень Shared UI (shared/ui) :


  • Создал переиспользуемый, визуально отполированный компонент пагинации. Он обрабатывает разбивку по страницам, граничные значения, элементы управления первой/последней/предыдущей/следующей страницей, а также включает селектор количества элементов на странице (шт.), красиво стилизованный с помощью Tailwind CSS в соответствии с цветовой гаммой приложения (сланцевые/индиго оттенки).
Уровень Shared Hooks (shared/hooks) :

  • Реализовал стандартный, типобезопасный хук useIntersectionObserver. Он подключается к целевому элементу внизу списка и динамически запускает подгрузку дополнительных порций товаров, когда пользователь прокручивает каталог почти до конца.
Управляющая панель с переключением режимов:

  • Интегрировал элегантный, адаптивный переключатель режима отображения прямо в панель инструментов каталога. Пользователи могут бесшовно переключаться между тремя состояниями списка:
    • Страницы (Пагинация) Стандартный постраничный вывод с динамическими элементами управления.
    • Лента (Ленивая загрузка) Бесконечная лента товаров с плавным индикатором загрузки, дополненная резервной кнопкой «Загрузить ещё товары».
    • Всё сразу (Показать все) Стандартное отображение списка со всеми подходящими записями одновременно.
Сброс состояния и надёжная синхронизация:

  • Встроил наблюдатели сброса состояния в движок списка. Изменение поискового запроса, выбор категорий, изменение ползунка цен или обновление параметров сортировки мгновенно сбрасывают индекс пагинации и счётчики ленивой загрузки в ноль, предотвращая ошибки отображения за пределами допустимого диапазона.


  1. Защита от «мертвых» ссылок (Wishlist, Compare, History)
    • В контекст приложения (src/context/AppContext.tsx) добавлены строгие проверки на существование продуктов.
    • Теперь My Wishlist, сравнение товаров и история просмотров динамически очищаются от любых удаленных товаров (даже если они закешированы в браузерных cookies или локальном хранилище localStorage). Это полностью решает проблему висящих счетчиков и битых элементов.
  2. Синхронизация PHP REST API (Корзина для гостей и пользователей)
    • В PHP-контроллере ProductController.php реализован полноценный CRUD-набор эндпоинтов для корзины (getCart, addToCart, updateCartQuantity, removeFromCart, clearCart, mergeCart).
    • Маршрутизатор public/php_rest_api/index.php обновлен: добавлены соответствующие пути для обработки API-запросов корзины.
    • В метод оформления заказа checkout() в ProductController.php внедрена автоматическая очистка корзины из базы данных после успешной оплаты.
  3. Слияние гостевой корзины при авторизации (PHP)
    • В UserController.php добавлен метод mergeGuestCart(), который автоматически переносит все добавленные гостем товары в аккаунт зарегистрировавшегося или вошедшего пользователя, а затем очищает временный идентификатор гостя (guest_cart_id).
  4. Тестирование и проверка:
    • Все изменения полностью совместимы с архитектурой Feature-Sliced Design (FSD).
    • Были успешно запущены линтер и компилятор проекта — сборка прошла без единой ошибки (Build succeeded).



Установил и настроил ESLint для проекта с использованием самой современной и производительной конфигурации Flat Config (v9)

Что это даёт и для чего нужен ESLint?​

ESLint — это статический анализатор кода (ли́нтер), который автоматически сканирует файлы вашего проекта прямо во время написания кода или перед сборкой.
 

Вложения

  • Screenshot_82.png
    Screenshot_82.png
    627,8 KB · Просмотры: 13
  • Screenshot_81.png
    Screenshot_81.png
    481,7 KB · Просмотры: 12
  • Screenshot_80.png
    Screenshot_80.png
    162,5 KB · Просмотры: 8
  • Screenshot_79.png
    Screenshot_79.png
    274,1 KB · Просмотры: 7
  • Screenshot_78.png
    Screenshot_78.png
    450,9 KB · Просмотры: 7
  • Screenshot_76.png
    Screenshot_76.png
    1,1 MB · Просмотры: 6
  • Screenshot_75.png
    Screenshot_75.png
    428,2 KB · Просмотры: 5
  • Screenshot_74.png
    Screenshot_74.png
    424,9 KB · Просмотры: 4
  • Screenshot_73.png
    Screenshot_73.png
    582 KB · Просмотры: 4
  • Screenshot_72.png
    Screenshot_72.png
    702 KB · Просмотры: 4
  • Screenshot_71.png
    Screenshot_71.png
    310,6 KB · Просмотры: 4
  • Screenshot_70.png
    Screenshot_70.png
    339,7 KB · Просмотры: 4
  • Screenshot_69.png
    Screenshot_69.png
    330,6 KB · Просмотры: 4
  • Screenshot_68.png
    Screenshot_68.png
    317,7 KB · Просмотры: 4
  • Screenshot_67.png
    Screenshot_67.png
    185 KB · Просмотры: 4
  • Screenshot_66.png
    Screenshot_66.png
    147,3 KB · Просмотры: 6
Последнее редактирование:
«Написать автору»:

Screenshot_217.png Screenshot_218.png Screenshot_219.png

Что реализовано:​

  1. Кнопка «Написать автору»:
    • Размещена непосредственно в блоке контактных данных продавца (как на странице просмотра товара, так и в модальном окне карточки товара).
    • При нажатии мгновенно открывает диалог личных сообщений с автором товара, автоматически прикрепляя карточку просматриваемого товара (название, цену и изображение) для удобного обсуждения сделки.
  2. Проверка автора:
    • Если текущий авторизованный пользователь сам является автором просматриваемого товара, отображается статус «Вы автор этого объявления».
    • Если товар принадлежит другому пользователю, доступна кнопка связи в чате.
  3. Локализация:
    • Добавлены переводы для всех поддерживаемых языков (ru, uk, en, de, es).
 
1. как под нагрузкой будет себя проект вести ?
2. импорты/експорты товаров, когда дропперы начнут 1 000 000 прайсы грузить, а у каждого товара по 5ть фоток, которые надо выкачать.
3. как характетистики будете приводить к единому типу, Например у одного кабель называется ПВ3 у другого ПВ 3, у третьего ПВ-3, у четвертого ПВ.3 и после фильтра на маркетплейске превращаются в помойку ((

Теперь я вам постараюсь ответить и уделить внимание.


Все зависит от того, какой у вас Сервер и насколько он мощный.
Если виртуальный хостинг, то вы даже не запустите данный CMS Catalog, если слабый VDS, VPS то на такую статистику глупо вообще рассчитывать и на что то надеется, на таком железе.
Если вы хотите использовать каталог на миллионную аудиторию и тем более тысячи активных пользователей, то вам придется выложить не малую сумму, для хорошего сервера и отдельных микросервисов.
  1. Stateless-сервер и горизонтальное масштабирование Horizontal Scaling:
    • Node.js сервер не хранит локальных сессий на диске. Все сессии и контекст находятся в куках/токене или в БД/Redis.
    • Это позволяет запустить N копий веб-сервера за балансировщиком нагрузки (Nginx / Cloud Run / Kubernetes / PM2 Cluster). При росте трафика контейнеры автоматически масштабируются (Auto-scaling).
  2. Оптимизация базы данных MySQL Connection Pool & Indexes:
    • Запросы к БД работают через пул соединений (mysql2/promise).
    • На ключевые поля каталога (category_id, status, price, user_id, составные индексы для фильтров) уже установлены индексы, что исключает Full Table Scan.
    • При сверхвысоких нагрузках на чтение подключаются Read Replicas (главная БД — на запись, реплики — на быстрый поиск по каталогу).
  3. Кеширование (Redis / CDN) :
    • Для тяжелых публичных запросов (дерево категорий, глобальные настройки, популярные товары) подключается Redis, снижая нагрузку на MySQL до 90%.
    • Статические файлы и изображения отдаются через CDN (Cloudflare / Cloud Storage), снимая нагрузку с веб-сервера.
2. Импорт / Экспорт 1 000 000 товаров и 5 000 000 фотографий
Попытка обработать 1 млн товаров и скачать 5 млн фото прямо во время веб-запроса моментально приведет к падению сервера: Out of Memory, Timeout, зависание Event Loop.

Для больших прайсов:
  1. Асинхронные фоновые очереди Message Queue / Worker Threads:
    • При загрузке миллионного прайса веб-сервер только принимает файл, будет сохранять его во временное хранилище, создавать запись задачи ImportJob #1234 и мгновенно отвечать клиенту со статусом 202 Accepted.
    • Обработка должна передаваться фоновым воркерам (BullMQ / RabbitMQ / Worker Threads).
  2. Потоковое чтение и пакетная вставка (Streaming & Batching) :
    • Файл CSV/XML не должен читаться целиком в память. Использется Stream Parsing (построчное/поблочное чтение по 1000–5000 строк).
    • В БД записи должны вставлятся пакетами: INSERT INTO products (...) VALUES (...) ON DUPLICATE KEY UPDATE (по 500–1000 товаров за один SQL-запрос вместо 1 000 000 отдельных).
  3. Очередь выкачивания изображений - используя Async Image Downloader:
    • Импорт товаров и скачивание фото разделять: товары создаются в БД со статусом pending_media, а ссылки на картинки отправляются в отдельную очередь скачивания
    • Очередь скачивания должна иметь rate-limiting (ограничение параллельных запросов к домену), чтобы IP не заблокировали за DoS-атаку
    • Скачанные фото на лету оптимизируются с помощью WebP/Sharp и будут загружаться в S3 / Cloud Storage CDN
  4. Real-Time прогресс для дропшиппера:
    • Клиент в админке или кабинете дропшиппера через WebSockets / SSE (Server-Sent Events) в реальном времени видит шкалу:
      Обработано 350,000 / 1,000,000 товаров | Загружено 1,200,000 / 5,000,000 фото
3. Это классическая проблема маркетплейсов. Если не нормализовать значения, в фильтрах появится 4 разных чекбокса для одного и того же кабеля.

Все просто, для этого необходимо реализовывать 3-уровневую систему очистки и нормализации данных:
Уровень 1: Строковый санитайзер Regex & Canonical Keys:
  • При сохранении характеристики создается канонический ключ slug/search_key.
  • Все спецсимволы, пробелы, дефисы, точки и регистр приводятся к единой базовой форме:
    • "ПВ 3" ➔ slug: "pv3"
    • "ПВ-3" ➔ slug: "pv3"
    • "ПВ.3" ➔ slug: "pv3"
    • "ПВ3" ➔ slug: "pv3"
  • Фильтр будет группировать товары по каноническому ключу (pv3), а пользователю показывает единое красивое название к примеру "ПВ-3".
Уровень 2: Таблица синонимов и словарей Synonym Dictionary:
  • Создается база синонимов значений характеристик для каждой категории:
    • canonical_name: "ПВ-3"
    • synonyms: "ПВ3", "ПВ 3", "ПВ.3", "ПВ - 3", "PV-3"
  • При импорте система ищет совпадения по таблице синонимов и автоматически привязывает товар к эталонной характеристике.

 
Промт почти готов, в курсор закиньте 5к, и он вам это все напишет :D
Быстро не напишет такое )) Придется не мало недель и месяцев потратить, даже с Курсором. Но если постепенно это реализовывать, то конечно можно сделать, но вот так - что бы за день сделать, то нет, это мифы и сказки. Сделает но такого навертит...
Проблема заключается не в скорости написания проекта и его функционала, а в минимуме багов и уязвимостей. Отладка занимает больше времени (процесс поиска, анализа и исправления ошибок)
 

Для всех карточек и страниц каталога реализовано изменение состояния кнопки при добавлении товара в корзину:​


  • Динамический текст кнопки: Если товар уже находится в корзине пользователя, текст «В корзину» автоматически меняется на «В корзине» (с поддержкой локализации).
  • Цветовое оформление и иконка: Кнопка окрашивается в изумрудный цвет (bg-emerald-600 hover:bg-emerald-500), а стандартная иконка меняется на галочку подтверждения (✓), визуально выделяя уже добавленные товары.
  • Обновление во всех представлениях: Логика синхронизирована для сетки каталога (Grid/Dense), компактного/детального списка (List view), модального окна просмотра (ProductDetailModal) и отдельной страницы товара (ProductDetailsView).

Реализовано отображение информации о ранее купленных товарах для покупателя:


1. Архитектура и логика определения статуса​

  • «Ранее куплен» (Изумрудный бейдж / баннер):
    • Товар найден в истории заказов со статусом успешной или активной сделки (за исключением отменённых, возвращённых или отклонённых).
    • Отображает количество успешных покупок (×2, ×3) и данные последнего заказа с датой.
  • «Ранее хотели купить» (Янтарный бейдж / баннер):
    • Товар был добавлен в корзину пользователя или сделка по нему не дошла до успешного завершения (статусы Cancelled, Refunded, Failed, Отменен, Возврат).
    • Отображается только в том случае, если товар ещё не был успешно приобретён.
    • Показывает причину (товар в активной корзине либо номер отменённой сделки с датой).

2. Поддержка во всех представлениях​

  • Каталог товаров (CatalogView): во всех режимах отображения (плитка, компактная сетка и список).
  • Модальное окно быстрого просмотра (ProductDetailModal): в шапке с бейджами и информационным баннером.
  • Страница детального просмотра товара (ProductDetailsView): в верхнем блоке статусов и расширенном блоке истории взаимодействия.

3. Локализация​

  • Добавлены переводы для всех состояний, подсказок и баннеров на 5 языках (русский, английский, испанский, немецкий, французский).


Детальный архитектурный и логический разбор системы заказов, покупок и разделения статусов взаимодействия пользователя с товаром в нашем проекте.​


1. Как сейчас устроена архитектура покупок и сделок в проекте​

В кодовой базе проекта реализована многоуровневая модель электронной коммерции и P2P-сделок со следующими сущностями и слоями:

  1. Корзина и локальные намерения (cart / ShoppingCart / useCart):
    • Хранит массив элементов { productId, quantity, price, title, ... }.
    • Синхронизируется как на клиенте (через React Context AppContext), так и на сервере/БД при авторизации.
    • Отражает текущее активное намерение покупки.
  2. Жизненный цикл заказов (orders / purchasedOrders / Эскроу):
    • Каждый заказ в таблице/коллекции orders содержит поля: id, buyer_id, seller_id, product_id, status, total_price, escrow_status, created_at, delivery_method.
    • Успешные статусы (Success Flow):
      • completed — сделка полностью закрыта, товар получен.
      • delivered — товар доставлен покупателю.
      • shipped / in_transit — товар отправлен продавцом.
      • paid / in_escrow — средства заблокированы в эскроу-гаранте, сделка активна и обеспечена деньгами.
      • processing / confirmed — заказ подтверждён и находится в обработке.
    • Несостоявшиеся / Прерванные сделки (Failure Flow):
      • cancelled — заказ отменён покупателем, продавцом или автоматически по таймауту.
      • refunded — средства возвращены покупателю (сделка не состоялась).
      • disputed (с исходом возврата) — спор завершился отменой.
      • failed — ошибка проведения платежа/депозита.
  3. Аналитический хелпер истории (getProductUserHistoryStatus в src/utils/helpers.ts):
    • Принимает (productId, purchasedOrders, cart).
    • Фильтрует все заказы пользователя по текущему товару (product_id === pId).
    • Разделяет их на successfulOrders и cancelledOrders.

2. Логическая матрица состояний: разграничение «Ранее куплен» vs «Ранее хотели купить»​

Чтобы у пользователя не возникало когнитивного диссонанса, статусы должны быть взаимоисключающими по приоритету (Hierarchy of Intent):

codeCode

Приоритет 1: Успешная покупка
(Если есть хоть 1 завершённый/оплаченный заказ)

« Ранее куплен» (или «Куплен хN»)

├─► (Если успешных покупок нет)

Приоритет 2: Активное действие прямо сейчас
│ (Товар лежит в корзине пользователя)

«В корзине» (с кнопкой перехода в корзину или зелёным бейджем)

├─► (Если не в корзине)

Приоритет 3: Несостоявшаяся сделка в истории
│ (Были заказы со статусом Cancelled / Refunded)

«Сделка была отменена» / «Ранее оформлялся заказ»

├─► (Если нет истории отмен)

Приоритет 4: Брошенный чекаут / Лист ожидания / Вишлист

« Ранее интересовались» / «В избранном»

3. Техническая реализация 4 сценариев​

СценарийУсловие в кодеСтатус / БейджТекст и действие кнопкиВизуальный акцент
1. Успешная покупкаsuccessfulOrders.length > 0«Ранее куплен» (при >1 — «×N»)Кнопка «Купить снова» или «В корзину»Изумрудный (emerald)
2. Товар в корзинеisInCart === true && !isPurchased«В корзине»Кнопка меняется на «В корзине» (bg-emerald-600)Изумрудно-синий (emerald/indigo)
3. Отменённая сделкаcancelledOrders.length > 0 && !isPurchased && !isInCart«Сделка была отменена» (с номером заказа)Кнопка стандартная «В корзину»Янтарный (amber)
4. Брошенный чекаут / интерес`abandonedCheckoutinWishlist`«Вы интересовались»

4. Почему такое разделение технически надёжно​

  1. Исключение ложных статусов: Покупатель, у которого сорвалась сделка, не увидит вводящую в заблуждение плашку «Вы уже купили этот товар», но система деликатно напомнит: «Заказ №... был отменён. Хотите оформить снова?».
  2. Точность конверсии: Если товар прямо сейчас в корзине, кнопка «В корзине» не позволяет случайно дублировать клики и мгновенно показывает текущее состояние заказа.
  3. История владения: Если пользователь купил товар 2 раза и 1 раз отменил, статус остаётся «✓ Ранее куплен (×2)», так как факт успешного владения перевешивает частную отмену.
 
Последнее редактирование:

Реализован новый функционал "Товар получен" / "Товар продан" подтверждения доставки:​


Screenshot_238.png Screenshot_240.png Screenshot_241.png Screenshot_242.png Screenshot_243.png
  • Покупатель (Вкладка «My Purchased Orders»):
    • Добавлена кнопка «Товар получен» для активных заказов.
    • При клике открывается модальное окно с описанием заказа, где покупатель подтверждает факт получения товара без претензий.
    • По завершении статус заказа переходит в Delivered, и кнопка меняется на отметку «✓ Товар получен».
  • Продавец (Вкладка «Incoming Buyer Sales»):
    • Когда покупатель нажимает «Товар получен» (или статус меняется на Delivered), у продавца статус заказа мгновенно обновляется на « Продан».
    • На карточке заказа у продавца появляется сияющий баннер «Товар продан! Покупатель подтвердил получение товара».
    • Продавцу отправляется системное уведомление о завершении сделки и успешной продаже товара.
  • Бэкенд и База Данных (/api/orders/:eek:rderId/confirm-delivery):
    • Сохраняет временные метки buyer_received_at и deal_completed_at.
    • Вносит запись в историю статусов (Timeline) заказа.
    • Корректирует остаток товара в каталоге и отправляет уведомления обеим сторонам.
 

Для всех карточек и страниц каталога реализовано изменение состояния кнопки при добавлении товара в корзину:​

Screenshot_244.png
  • Динамический текст кнопки: Если товар уже находится в корзине пользователя, текст «В корзину» автоматически меняется на «В корзине» (с поддержкой локализации).
  • Цветовое оформление и иконка: Кнопка окрашивается в изумрудный цвет (bg-emerald-600 hover:bg-emerald-500), а стандартная иконка меняется на галочку подтверждения , визуально выделяя уже добавленные товары.
  • Обновление во всех представлениях: Логика синхронизирована для сетки каталога (Grid/Dense), компактного/детального списка (List view), модального окна просмотра (ProductDetailModal) и отдельной страницы товара (ProductDetailsView).
 

Функционал отмены покупки продавцом на начальном этапе полностью реализован и протестирован:​

Screenshot_245.png
  • Отмена в Incoming Buyer Sales: Вкладка продаж продавца отображает кнопку «Отменить покупку» для заказов в начальном статусе (Processing).
  • Обязательная причина отмены: При нажатии выводится диалоговое окно, требующее указать текстовую причину отмены. Кнопка подтверждения заблокирована до ввода причины.
  • Снижение рейтинга:
    • Рейтинг товара автоматически снижается на -0.5★ (до минимума 1.0).
    • Рейтинг продавца снижается на -10 баллов Trust Score и -0.5★ Bayesian Rating.
  • Возврат средств и уведомления: Средства покупателя за покупку и доставку автоматически возвращаются на его баланс с записью в историю транзакций. Покупатель и продавец получают соответствующие системные уведомления.
  • Информационный баннер: Отмененная сделка сохраняется в списке с плашкой «Покупка отменена» и отображением указанной причины.
 

Вложения

  • Screenshot_247.png
    Screenshot_247.png
    93,7 KB · Просмотры: 0
  • Screenshot_246.png
    Screenshot_246.png
    98,5 KB · Просмотры: 0
Последнее редактирование:

Реализовано ограничение на изменение этапа сделки в обратную сторону в Escrow Deal Stage pipeline

Обновлены правила переключения этапов:​


  • Свободное переключение до продажи товара (Processing ↔ Shipped):
    • Если товар ещё не имеет статус Delivered (не продан), продавец может свободно переключаться между этапами Processing (Обработка) и Shipped (Отправлено) в обе стороны прямо на интерактивном таймлайне или через выпадающий список.
  • Защита проданных товаров (Delivered):
    • Как только заказ переходит в статус Delivered (Товар продан / Завершен), изменить его статус обратно на Processing или Shipped может только Администратор. Продавцу в таком случае выводится предупреждение: "Изменение этапа сделки для уже проданного товара разрешено только Администратору".
  • Перевод в Delivered:
    • При попытке перевести заказ в статус Delivered продавцом по-прежнему запрашивается подтверждение согласия с рисками через модальное окно.
  • Права Администратора:
    • Пользователю с ролью admin доступны все переходы, включая откаты этапов назад (Delivered ➔ Shipped ➔ Processing).
    • В заголовке таймлайна администратора отображается индикатор Admin Override Active.
  • Защита на сервере (Backend):
    • Эндпоинты /api/orders/orderId/status и /api/orders/bulk-status проверяют ранг текущего и нового статусов.
    • Если запрашивается изменение назад, а userRole !== 'admin', сервер возвращает ошибку 403 Forbidden с сообщением "Изменение этапа сделки в обратную сторону разрешено только Администратору".
 
Последнее редактирование:

Реализовано обязательное подтверждение согласия с рисками при ручном выборе статуса «Товар продан» (Delivered) продавцом:​

Screenshot_249.png
  • Запрос подтверждения при смене статуса:
    • Когда продавец выбирает статус «Delivered» (Товар продан) в меню выбора статусов, на интерактивном таймлайне сделки или в массовом обновлении заказов, открывается модальное окно подтверждения риска.
  • Информационное предупреждение о правилах Escrow:
    • В окне отображается разъяснение о том, что согласно стандартным правилам безопасной сделки Escrow статус завершения должен подтверждаться покупателем по кнопке «Товар получен».
    • Продавцу разъясняется, что перевод статуса вручную означает его гарантию передачи товара и принятие всех возможных рисков по спорам и претензиям покупателя.
  • Обязательный чекбокс согласия:
    • Для активации кнопки «Я согласен с рисками» продавец должен установить отметку: «Я осознаю и принимаю все риски с покупателем при ручном завершении сделки».
  • Корректный запуск завершения:
    • Только после установки чекбокса и подтверждения статус заказа обновляется на «Delivered» и сохраняется в системе.
 
Назад
Сверху