DynPricing Admin
{{ systemInfo.environment === 'production' ? 'cloud_done' : (systemInfo.environment === 'testing' ? 'science' : 'laptop') }} {{ systemInfo.environment_label || systemInfo.environment }}
{{ systemInfo.environment_note }}
{{ state.lastUpdated ? 'Updated: ' + state.lastUpdated : 'Loading...' }}
arrow_downward {{ queueStats.incoming_queues.znz_in.message_count ?? 0 }} ZNZ IN
arrow_downward {{ queueStats.incoming_queues.elnino_in.message_count ?? 0 }} ELNINO IN
|
{{ queueStats?.loading ? 'sync' : 'pending_actions' }} {{ queueStats?.message_count ?? 0 }} INTRA
|
arrow_upward {{ stats.message_count }} {{ routeName }}
warning
account_circle {{ currentUser.username || currentUser.name || 'User' }} ADMIN
Refreshing {{ currentTab.label.toLowerCase() }}...
error {{ state.error }}

{{ getPageDescription(activeTab).title }}

{{ getPageDescription(activeTab).description }}

  • {{ feature }}

Configuration Overview

Active projects with their strategies and rules.

Details Actions
{{ overviewIcon(row.type) }}
{{ row.label }} {{ row.subtitle }}
{{ row.meta }} --
info No active configuration available.
{{ state.selectedItems.projects.length }} project(s) selected
Order {{ t('tableSort.projects.domain') }} {{ t('tableSort.projects.strategies') }} {{ t('tableSort.projects.warehouse') }} {{ t('tableSort.projects.status') }} Actions
{{ project.domain }}
{{ project.slug || 'N/A' }}
{{ strategy.name }} None
{{ project.warehouses_mask || 'N/A' }} {{ project.is_active ? 'Active' : 'Inactive' }}
Showing {{ paginationBounds('projects').from }}-{{ paginationBounds('projects').to }} of {{ tableMeta.projects.total }}
Page {{ tableMeta.projects.page }} of {{ tableMeta.projects.pages }}
{{ state.selectedItems.strategies.length }} strateg(ies) selected
Order {{ t('tableSort.strategies.name') }} {{ t('tableSort.strategies.route') }} {{ t('tableSort.strategies.global_rule') }} {{ t('tableSort.strategies.projects') }} Actions
{{ strategy.name }}
{{ route.name }}
{{ strategy.route || 'N/A' }}
{{ truncate(strategy.global_rule) || 'N/A' }}
{{ project.domain }} None
{{ rule.name }} None
{{ strategy.is_active ? 'Active' : 'Inactive' }}
Showing {{ paginationBounds('strategies').from }}-{{ paginationBounds('strategies').to }} of {{ tableMeta.strategies.total }}
Page {{ tableMeta.strategies.page }} of {{ tableMeta.strategies.pages }}
{{ state.selectedItems.rules.length }} rule(s) selected
Order {{ t('tableSort.rules.name') }} {{ t('tableSort.rules.expression') }} {{ t('tableSort.rules.filter') }} {{ t('tableSort.rules.strategies') }} {{ t('tableSort.rules.status') }} Actions
{{ rule.name }} {{ truncate(rule.dsl_expression) }} {{ truncate(rule.filter_expression) || 'N/A' }}
{{ strategy.name }} None
{{ rule.is_active ? 'Active' : 'Inactive' }}
Showing {{ paginationBounds('rules').from }}-{{ paginationBounds('rules').to }} of {{ tableMeta.rules.total }}
Page {{ tableMeta.rules.page }} of {{ tableMeta.rules.pages }}
shield

No guardrails found

Click "New Guardrail" to create your first reusable pricing constraint
{{ state.selectedItems.guardrails.length }} guardrail(s) selected
Order {{ t('tableSort.guardrails.name') }} {{ t('tableSort.guardrails.expression') }} {{ t('tableSort.guardrails.note') }} {{ t('tableSort.guardrails.status') }} Global Actions
{{ guardrail.name }} {{ truncate(guardrail.dsl_expression, 80) }} {{ guardrail.note || '-' }} {{ guardrail.is_active ? 'Active' : 'Inactive' }} {{ guardrail.is_global ? 'Global' : 'Strategy' }}
Page {{ tableMeta.guardrails.page }} of {{ tableMeta.guardrails.pages }}
Validity Global Actions
#{{ rule.id }}
{{ rule.domainLabel }}
{{ truncate(rule.domainDetail, 80) }}
{{ truncate(rule.targetSummary, 80) }}
{{ truncate(rule.targetDetail, 80) }}
{{ truncate(rule.actionSummary, 80) }}
{{ truncate(rule.actionDetail, 80) }}
{{ flag }}
{{ rule.updatedLabel || '?' }} {{ rule.validityLabel }} public Yes ? {{ rule.statusLabel }} {{ rule.ownerName || '?' }}
No rules found.
Showing {{ paginationBounds('singleRules').from }}-{{ paginationBounds('singleRules').to }} of {{ tableMeta.singleRules.total }}
Page {{ tableMeta.singleRules.page }} of {{ tableMeta.singleRules.pages }}
Actions
{{ tier.tier_name }} {{ tier.tier_remote_id }} {{ tier.project_domain || 'Shared' }} {{ tier.description }}
Showing {{ paginationBounds('pricingTiers').from }}-{{ paginationBounds('pricingTiers').to }} of {{ tableMeta.pricingTiers.total }}
Page {{ tableMeta.pricingTiers.page }} of {{ tableMeta.pricingTiers.pages }}
category
touch_app
person
search
date_range
date_range
ID Entity Type Entity Name Action User Date & Time Actions
{{ log.id }} {{ log.entity_type === 'project' ? 'domain' : log.entity_type === 'strategy' ? 'hub' : log.entity_type === 'rule' ? 'rule' : log.entity_type === 'single_rule' ? 'rule_folder' : 'shield' }} {{ log.entity_type === 'single_rule' ? 'single rule' : log.entity_type }} {{ log.entity_name }} {{ log.action_type === 'create' ? 'add_circle' : log.action_type === 'delete' ? 'delete' : 'edit' }} {{ log.action_type }} person {{ log.user_name || 'Unknown' }} {{ formatDateTime(log.created_at) }}
No log entries found.
Showing {{ setupLogMeta.from }}-{{ setupLogMeta.to }} of {{ setupLogMeta.total }}
Page {{ setupLogMeta.page }} of {{ setupLogMeta.pages }}

API Key Usage Logs

ID API Key Endpoint Method Status IP Address User Agent Date & Time
{{ log.id }} {{ log.api_key_prefix || 'N/A' }} {{ log.endpoint }} {{ log.method }} {{ log.status_code }} {{ log.ip_address }} {{ log.user_agent || '-' }} {{ formatDateTime(log.created_at) }}
No API key usage logs found.
Showing {{ apiKeyLogsMeta.from }}-{{ apiKeyLogsMeta.to }} of {{ apiKeyLogsMeta.total }}
Page {{ apiKeyLogsMeta.page }} of {{ apiKeyLogsMeta.pages }}
Actions
{{ tier.tier_name }} {{ tier.project_domain || 'Shared' }} {{ displayNumber(tier.price_100) }} {{ displayNumber(tier.price_200) }} {{ displayNumber(tier.price_300) }} {{ displayNumber(tier.price_400) }} {{ displayNumber(tier.price_10000) }}
Showing {{ paginationBounds('marginLevels').from }}-{{ paginationBounds('marginLevels').to }} of {{ tableMeta.marginLevels.total }}
Page {{ tableMeta.marginLevels.page }} of {{ tableMeta.marginLevels.pages }}
Actions
{{ route.name }} {{ route.route || 'N/A' }} {{ route.description || 'N/A' }} {{ route.endpoint_url || 'N/A' }} {{ route.is_active ? 'Active' : 'Inactive' }}
Showing {{ paginationBounds('pricingRoutes').from }}-{{ paginationBounds('pricingRoutes').to }} of {{ tableMeta.pricingRoutes.total }}
Page {{ tableMeta.pricingRoutes.page }} of {{ tableMeta.pricingRoutes.pages }}
label

No dynamic tags found

Click "New Dynamic Tag" to create a tag that will be assigned to products matching a filter expression
{{ state.selectedItems.dynamicTags.length }} dynamic tag(s) selected
Order {{ t('tableSort.dynamicTags.name') }} {{ t('tableSort.dynamicTags.expression') }} {{ t('tableSort.dynamicTags.note') }} {{ t('tableSort.dynamicTags.status') }} Actions
{{ tag.name }} {{ truncate(tag.dsl_expression, 80) }} {{ tag.note || '-' }} {{ tag.is_active ? 'Active' : 'Inactive' }}
Page {{ tableMeta.dynamicTags.page }} of {{ tableMeta.dynamicTags.pages }}
download Download Template
{{ selectedRrpItems.length }} items selected
Date Domain Tag EAN Abra ID Price Currency Type User Active Actions
{{ formatDate(item.datum) }} {{ item.domena || 'N/A' }} {{ item.tag || '-' }} {{ item.EAN }} {{ item.produkt }} {{ item.cena }} {{ item.mena || 'CZK' }} lock {{ item.typ === 'fixed' ? 'Fixed Price' : (item.typ === 'rrp' ? 'RRP' : 'Manual') }} {{ item.user || item.uzivatel || 'N/A' }} {{ item.aktivni == 1 ? 'Active' : 'Inactive' }}

Import RRP Data from XLSX

Step 1: Select Import Options

Import Mode:

Note: Your file can contain both RRP and Fixed prices (use 'type' column: rrp/fixed)
cloud_upload

Click to select XLSX file or drag & drop

Supported formats: .xlsx, .xls
description {{ selectedRrpFile.name }} Processing... {{ state.rrpDatabase.error }} Ready for column mapping
Analyzing Excel file...

Step 2: Map Columns to Database Fields

{{ state.rrpDatabase.totalRows || 0 }} rows detected in Excel file
No columns detected - please check Excel file format
{{ state.rrpDatabase.fileColumns.length }} columns found
Found columns: {{ column.name }},

No columns detected

The Excel file appears to be empty or doesn't have a proper header row. Please ensure:

  • The first row contains column headers
  • The file is in .xlsx or .xls format
  • The file is not corrupted

Import Preview - First 10 Products

Total: {{ state.rrpDatabase.previewData.length }} RRP: {{ state.rrpDatabase.previewData.filter(row => !row.type || row.type === 'rrp').length }} Fixed: {{ state.rrpDatabase.previewData.filter(row => row.type === 'fixed').length }} Will Create: {{ state.rrpDatabase.previewData.filter(row => row._exists && row._exists.action === 'create').length }} Will Update: {{ state.rrpDatabase.previewData.filter(row => row._exists && row._exists.action === 'update').length }}
Product Name EAN/ID Domain Price Type Tag Action
{{ row.name || '-' }}
? Has validation errors
{{ row.product_id || '-' }} {{ row.domena || '-' }} {{ row.price || '-' }} {{ row.currency }} lock {{ row.type === 'fixed' ? 'Fixed' : 'RRP' }} {{ row.tag || '-' }}
{{ row._exists.action === 'update' ? 'Will Update' : row._exists.action === 'create' ? 'Will Create' : row._exists.action === 'verify' ? 'Needs Review' : '-' }}
{{ row._exists.reason }}
Status Legend: Found in DB = Product exists, will update ? Similar Found = Similar product found, verify before import ? New Product = Will create as new product

RRP Prices Detected - Create Rules?

info
Only Fixed Prices Detected

Your import contains only fixed prices. These will be imported directly without creating rules.

Single Rules Preview

What will happen:

  • Import prices to database
  • Automatically create/update single pricing rules from RRP data (Fixed prices won't create rules)
  • Rules will be grouped by Tag + Domain combinations
  • All rules will be created in inactive state for safety
  • ? You can activate and configure them in Single Rules section after import

Rule Strategy: RRP-based pricing

Estimated Rules: {{ new Set(state.rrpDatabase.previewData.filter(row => (!row.type || row.type === 'rrp') && row.tag && row.domena).map(row => row.tag + '|' + row.domena)).size }} rules (based on unique Tag + Domain combinations from RRP data)

Step 3: Import Complete

Successfully imported {{ rrpImportResult?.imported || 0 }} RRP records.

Single Rules Created/Updated:

  • {{ rule.action === 'created' ? 'Created' : 'Updated' }} rule "{{ rule.tag }}" ({{ rule.product_count }} products, {{ rule.sale_percent }}% discount) - Global

All rules are inactive by default. Activate them in Single Rules section.

? RRP prices imported successfully. No single rules were created.

Single Rules Creation Warning

RRP prices were imported successfully, but there was an issue creating single rules:

{{ rrpImportResult.single_rules_error }}

Product Repricing Logs

Inspect recent MySQL output or long-term BigQuery history for a single product.

bug_report Debug Console
link GET {{ productLogEndpointPreview }}
error {{ productLogs.error }}
Loading product logs...
Entries: {{ productLogs.meta.count }}
Source: {{ productLogs.meta.scope === 'long' ? 'BigQuery history' : 'MySQL recent logs' }}
Domain: {{ productLogs.meta.domain }}
Limit: {{ productLogs.meta.limit }}
Fetched: {{ productLogs.meta.retrieved_at }}
Open endpoint
Average sell {{ formatCurrency(productLogStats.avgSell, productLogStats.currency) }}
Average buy {{ formatCurrency(productLogStats.avgBuy, productLogStats.currency) }}
Average margin {{ formatPercent(productLogStats.avgMargin) }}
Latest entry {{ productLogStats.latestAt }}

Price & Margin Timeline

Processed Domain Warehouse Buy (w/o VAT) Sell (with VAT) Margin % Strategy Competition Note Debug
{{ row.processed_at || row.recorded_at || '--' }} {{ row.domain || productLogs.meta.domain || '--' }} {{ row.warehouse_id || row.wh || row.pricelist || '--' }} {{ formatCurrency(row.buy_price_without_vat || row.buy_without_vat || row.buy_price_with_vat || row.buy, productLogs.meta.currency) }} {{ formatCurrency(row.final_price_with_vat || row.price_with_vat || row.price, productLogs.meta.currency) }} {{ formatPercent(row.margin_percentage || row.margin) }} {{ row.strategy_used || row.strategy || '--' }} {{ row.competition_count !== undefined && row.competition_count !== null ? row.competition_count : '--' }}
Date Buy (CZK) Sell (CZK) Margin % Warehouse Note
{{ row.datum || '--' }} {{ formatCurrency(row.cbuy || row.buy, 'CZK') }} {{ formatCurrency(row.cprice || row.price, 'CZK') }} {{ formatPercent(row.margin) }} {{ row.wh || '--' }}
Showing {{ displayRows.length }} BigQuery rows (limit {{ productLogs.meta.limit }}).
info No log records found for the current selection.

Debug details

{{ productLogDiagnostics.summary }}

{{ productLogDiagnostics.json }}

Global Product Logs

View repricing changes for a product across every project, without selecting a domain.

link GET {{ globalProductLogEndpointPreview }}
error {{ globalProductLogs.error }}
Loading global product logs...
Entries: {{ globalProductLogs.meta.count }}
Product ID: {{ globalProductLogs.meta.product_id }}
Warehouse: {{ globalProductLogs.meta.warehouse }}
Limit: {{ globalProductLogs.meta.limit }}
Fetched: {{ globalProductLogs.meta.retrieved_at }}
Open endpoint
Recorded Project Warehouse Buy Price Sell Price Margin Strategy
{{ row.recorded_at || '--' }} {{ row.domain || '--' }} {{ row.warehouse || row.wh || '--' }} {{ formatCurrency(row.buy || row.buy_price_without_vat || row.buy_price_with_vat, (globalProductLogs.meta && globalProductLogs.meta.currency) || 'CZK') }} {{ formatCurrency(row.price_with_vat || row.price || row.price_without_vat, (globalProductLogs.meta && globalProductLogs.meta.currency) || 'CZK') }} {{ formatPercent(row.margin) }} {{ row.strategy || row.strategy_used || '--' }}
info No global log records found for this product.

Repricing Debug Console

Inspect cached inputs, evaluate strategy coverage, and run wait-mode repricing in one place.

error {{ repricingDebug.strategyError }}
error {{ repricingDebug.submitError }}
history Product Log dataset Raw Data

{{ repricingDebug.repriceResult.data_used.basic_data?.nazev_produktu || 'Product details' }}

Product ID {{ repricingDebug.repriceResult.data_used.basic_data.id }} RegCIS {{ repricingDebug.repriceResult.data_used.basic_data.regcis }} Brand {{ repricingDebug.repriceResult.data_used.basic_data.brand }} Price Buy {{ formatCurrency(repricingDebug.repriceResult.data_used.basic_data.price_buy, repricingDebug.repriceResult.final_price?.currency || 'CZK') }} Warehouse {{ repricingDebug.repriceResult.data_used.basic_data.warehouse }} Warehouse Cnt {{ repricingDebug.repriceResult.data_used.basic_data.warehouse_cnt }} Sell (incl. VAT) {{ repricingDebugSummary.sellWithVatFormatted }} Sell (excl. VAT) {{ repricingDebugSummary.sellWithoutVatFormatted }} VAT {{ repricingDebugSummary.vatPercentFormatted }} Margin {{ repricingDebugSummary.marginFormatted }}

Strategy Overview

  • {{ strategy.applies === true ? 'play_circle' : 'pause_circle' }} {{ strategy.name }}
    {{ strategy.active ? 'Active' : 'Inactive' }} {{ strategy.rules_matched }}/{{ strategy.rules_total }} rules match

Rules for {{ selectedRepricingStrategy.name }}

# Name Filter result Expression
{{ rule.priority || '-' }} {{ rule.name }} {{ rule.matched ? 'Matched' : 'Not matched' }} {{ rule.dsl_expression || '-' }}

DSL Variables Available

{{ Object.keys(repricingDebug.repriceResult.dsl_variables_available).length }} variables you can use in DSL expressions
{{ key }} {{ formatDslVariableValue(value) }}

Repricing Output

error {{ repricingDebug.repriceError }}
terminal

Detailed Execution Log

Step-by-step repricing process

{{ logLine }}
Structured JSON (data_used)
{{ JSON.stringify(repricingDebug.repriceResult.data_used, null, 2) }}
info No repricing output captured.

Last run: {{ repricingDebug.lastRunAt }}

User Management

Debug Info:
Current User Loaded: {{ currentUser?.loaded ? 'Yes' : 'No' }}
Current User Role: {{ currentUser?.role || 'N/A' }}
Is SuperAdmin: {{ isSuperAdmin() ? 'Yes' : 'No' }}
Users in State: {{ userManagement?.users?.length || 0 }}
Loading: {{ userManagement?.loading ? 'Yes' : 'No' }}
Error: {{ userManagement?.error || 'None' }}
Loading users...
{{ userManagement.error }}
No users found. Click "Reload" button above.
Username Name Role Status Actions
{{ user?.login || 'N/A' }} {{ user?.name || 'N/A' }} {{ user?.role === 'superadmin' ? 'Super Admin' : 'User' }} {{ user?.is_active ? 'Active' : 'Inactive' }}

API Keys Management

Manage API keys for accessing remote data endpoints (PLA feeds, external data, etc.)

ID Name API Key Domain Endpoint Prefix Last Used Created Actions
{{ key.id }} {{ key.key_name }} {{ key.api_key_display }} {{ key.domain }} All domains {{ key.endpoint_prefix }} All endpoints {{ formatDateTime(key.last_used_at) }} Never {{ formatDateTime(key.created_at) }}
No API keys found. Click "Create API Key" to add one.

System Diagnostics

Comprehensive system health check including API keys, localStorage, database, endpoints, and deployment status.

Running diagnostics...
error {{ systemCheck.error }}
error
Problems Detected ({{ systemCheck.data.problems.length }})
  • {{ problem }}
lightbulb
Recommended Solutions ({{ systemCheck.data.solutions.length }})
  • {{ solution }}
{{ systemCheck.data.status === 'ok' ? 'check_circle' : systemCheck.data.status === 'warning' ? 'warning' : 'error' }}
Overall Status: {{ systemCheck.data.status.toUpperCase() }} Completed in {{ systemCheck.data.duration_ms }}ms at {{ new Date(systemCheck.data.completed_at).toLocaleString() }}
{{ systemCheck.output }}

No diagnostics have been executed yet. Click "Run Check" to start.

Showing up to {{ state.rawMarketplacesMeta.limit }} rows. Additional rows are available via more specific filters.

Mark Data ID URL Price Currency Sale Price Shipping Actions
{{ row.datum }} {{ row.domain }} {{ row.src }} {{ row.mark }} {{ row.dataid }} {{ truncate(row.url, 80) }} N/A {{ displayNumber(row.price) }} {{ row.currency || 'N/A' }} {{ row.price_sale ? displayNumber(row.price_sale) : 'N/A' }} {{ displayNumber(row.shipping) }}
Showing {{ paginationBounds('rawMarketplaces').from }}-{{ paginationBounds('rawMarketplaces').to }} of {{ tableMeta.rawMarketplaces.total }}
Page {{ tableMeta.rawMarketplaces.page }} of {{ tableMeta.rawMarketplaces.pages }}

PLA Feeds Management

Manage PLA feeds data, XLSX imports, and processing.

Available Actions

  • Upload XLSX Files: Import new PLA feed data as binary files directly to database
  • Process Feeds: Parse uploaded XLSX files into structured product data
  • Download Files: Retrieve previously uploaded XLSX files from database
  • Re-import: Reprocess existing XLSX files with updated parsing logic

Recent PLA Feeds

Upload Date Domain Action File Name Status Actions
hourglass_empty

Loading PLA feeds...

error

Error loading feeds: {{ state.plaFeeds.error }}

folder_open

No PLA feeds uploaded yet. Use the "Upload New PLA Feed" button to get started.

{{ formatDate(feed.datum) }} {{ feed.domain || 'N/A' }} {{ feed.action || 'N/A' }} {{ feed.filename || 'N/A' }} {{ feed.processed === 'processed' ? 'Processed' : 'Pending' }}

Showing up to {{ state.rawDirectSitesMeta.limit }} rows. Additional rows are available via more specific filters.

Data ID URL Actions
{{ row.datum }} {{ row.domain }} {{ row.action }} {{ row.dataid }} {{ truncate(row.url, 100) }} N/A
Showing {{ paginationBounds('rawDirectSites').from }}-{{ paginationBounds('rawDirectSites').to }} of {{ tableMeta.rawDirectSites.total }}
Page {{ tableMeta.rawDirectSites.page }} of {{ tableMeta.rawDirectSites.pages }}

Showing up to {{ state.priceEanMeta.limit }} rows. Additional rows are available via more specific filters.

Domain Base Currency Instock Partner ID URL Actions
{{ row.datum }} {{ row.recrawled }} {{ row.domain }} {{ row.domainbase }} {{ row.tag }} {{ row.ean }} {{ formatCurrency(row.price, row.cur) }} {{ formatCurrency(row.price_full, row.cur) }} {{ row.confidence != null ? row.confidence : '' }} {{ row.cur }} {{ row.instock }} {{ row.partnerid }} {{ truncate(row.url, 100) }} N/A
Showing {{ paginationBounds('priceEan').from }}-{{ paginationBounds('priceEan').to }} of {{ tableMeta.priceEan.total }}
Page {{ tableMeta.priceEan.page }} of {{ tableMeta.priceEan.pages }}
Loading products cache data...

Showing up to {{ state.productsCache.meta.limit }} rows. Additional rows are available via more specific filters.

Data Size Actions
Loading cache data...
error
Error loading cache data

{{ state.productsCache.error }}

cached

No cached products found

{{ formatDateTime(row.cache_date) }}
{{ formatTimeAgo(row.cache_date) }}
{{ row.domain }}
{{ row.product_id }}
{{ row.product_name || 'N/A' }}
{{ formatCurrency(row.final_price, row.currency || 'CZK') }}
N/A
{{ formatBytes(row.data_size) }}
Showing {{ paginationBounds('productsCache').from }}-{{ paginationBounds('productsCache').to }} of {{ tableMeta.productsCache.total }}
Page {{ tableMeta.productsCache.page }} of {{ tableMeta.productsCache.pages }}
{{ globalLoadingStatus.primary }} {{ globalLoadingStatus.detail }}