feat(customers): track order meta and OC sync

- add telecart_order_meta table and orders_count column for customers
- introduce OcCustomerService and OrderMetaService for syncing OC data
- rework OrderCreateService transaction flow, metadata handling and tests
- increment telegram customer orders_count and expose it via handlers/UI
- update stats dashboard with rub formatting, tooltips and customers count
- sync SPA theme colors with Telegram WebApp and fix dark variant behavior
- add helpers for RUB formatting and bool casting; simplify logs handler
This commit is contained in:
2025-11-24 14:08:56 +03:00
committed by Nikita Kiselev
parent b39a344a7d
commit 952d8e58da
18 changed files with 489 additions and 172 deletions

View File

@@ -17,28 +17,41 @@
</div>
<div class="tw:flex tw:items-center tw:flex-wrap tw:gap-8">
<div>
<span class="tw:text-surface-500 tw:dark:text-surface-300">Количество заказов</span>
<span
v-tooltip.top="'Общее количество заказов, сделанное через TeleCart за всё время.'"
class="tw:text-surface-500 tw:dark:text-surface-300"
>
Количество заказов
</span>
<div
class="tw:text-surface-700 tw:dark:text-surface-100 tw:mt-1 tw:text-sm tw:font-semibold">
class="tw:text-surface-700 tw:dark:text-surface-100 tw:mt-1 tw:text-sm tw:font-semibold"
>
{{ stats.items.orders_count ?? '-' }}
</div>
</div>
<div>
<span class="tw:text-surface-500 tw:dark:text-surface-300">Общая сумма</span>
<span
v-tooltip.top="'Итоговая сумма заказов, сделанных через TeleCart за всё время.'"
class="tw:text-surface-500 tw:dark:text-surface-300"
>Общая сумма</span>
<div
class="tw:text-surface-700 tw:dark:text-surface-100 tw:mt-1 tw:text-sm tw:font-semibold">
{{ stats.items.orders_total_amount ?? '-' }}
{{ rub(stats.items.orders_total_amount ?? 0) }}
</div>
</div>
<div>
<span class="tw:text-surface-500 tw:dark:text-surface-300">Уникальные товары</span>
<span
v-tooltip.top="'Общее количество уникальных Telegram-посетителей, взаимодействовавших с магазином за всё время включая тех, кто просто заходил посмотреть, без оформления заказа.'"
class="tw:text-surface-500 tw:dark:text-surface-300">Кол-во посетителей</span>
<div
class="tw:text-surface-700 tw:dark:text-surface-100 tw:mt-1 tw:text-sm tw:font-semibold">
{{ stats.items.order_products_count ?? '-' }}
<RouterLink to="/customers">{{ stats.items.customers_count ?? 0 }}</RouterLink>
</div>
</div>
<div>
<span class="tw:text-surface-500 tw:dark:text-surface-300">Статус магазина</span>
<span
v-tooltip.top="'Текущий статус магазина'"
class="tw:text-surface-500 tw:dark:text-surface-300">Статус магазина</span>
<div
class="tw:text-surface-700 tw:dark:text-surface-100 tw:mt-1 tw:text-sm tw:font-semibold">
<div v-if="settings.items.app.app_enabled" class="tw:flex tw:items-center">
@@ -102,6 +115,7 @@ import OcImagePicker from "@/components/OcImagePicker.vue";
import {apiGet} from "@/utils/http.js";
import ResetCacheBtn from "@/components/Form/ResetCacheBtn.vue";
import {Button, ButtonGroup} from "primevue";
import {rub} from "@/utils/helpers.js";
const settings = useSettingsStore();
const stats = useStatsStore();