diff --git a/core/components/minishop3/controllers/mgr/orders.class.php b/core/components/minishop3/controllers/mgr/orders.class.php index 04175c16..a93259c7 100644 --- a/core/components/minishop3/controllers/mgr/orders.class.php +++ b/core/components/minishop3/controllers/mgr/orders.class.php @@ -38,6 +38,7 @@ public function loadCustomCssJs() $this->addJavascript($this->ms3->config['jsUrl'] . 'mgr/orders/orders.wrapper.js'); $config = $this->ms3->config; + $config['order_show_drafts'] = (bool) $this->modx->getOption('ms3_order_show_drafts', null, false); $this->addHtml(''); $this->addCss($this->ms3->config['assetsUrl'] . 'css/mgr/vue-dist/primeicons.min.css'); diff --git a/core/components/minishop3/lexicon/en/vue.inc.php b/core/components/minishop3/lexicon/en/vue.inc.php index 31b56923..00437c0f 100644 --- a/core/components/minishop3/lexicon/en/vue.inc.php +++ b/core/components/minishop3/lexicon/en/vue.inc.php @@ -489,6 +489,8 @@ $_lang['orders_title'] = 'Orders'; $_lang['orders_month'] = 'Orders'; $_lang['orders_month_sum'] = 'Total sum'; +$_lang['orders_stat_tooltip'] = 'Count and sum for placed orders only; drafts are not included'; +$_lang['ms3_orders_show_drafts'] = 'Show drafts'; $_lang['order_num'] = 'Number'; $_lang['order_customer'] = 'Customer'; $_lang['order_status'] = 'Status'; diff --git a/core/components/minishop3/lexicon/ru/vue.inc.php b/core/components/minishop3/lexicon/ru/vue.inc.php index 93520236..5dffec95 100644 --- a/core/components/minishop3/lexicon/ru/vue.inc.php +++ b/core/components/minishop3/lexicon/ru/vue.inc.php @@ -489,6 +489,8 @@ $_lang['orders_title'] = 'Заказы'; $_lang['orders_month'] = 'Заказов'; $_lang['orders_month_sum'] = 'На сумму'; +$_lang['orders_stat_tooltip'] = 'Количество и сумма по оформленным заказам; черновики не учитываются'; +$_lang['ms3_orders_show_drafts'] = 'Показывать черновики'; $_lang['order_num'] = 'Номер'; $_lang['order_customer'] = 'Клиент'; $_lang['order_status'] = 'Статус'; diff --git a/core/components/minishop3/src/Controllers/Api/Manager/OrdersController.php b/core/components/minishop3/src/Controllers/Api/Manager/OrdersController.php index 58cec930..c8b11c32 100644 --- a/core/components/minishop3/src/Controllers/Api/Manager/OrdersController.php +++ b/core/components/minishop3/src/Controllers/Api/Manager/OrdersController.php @@ -155,11 +155,7 @@ public function getList(array $params = []): array } } - $showDrafts = $this->modx->getOption('ms3_order_show_drafts', null, false); - if (!$showDrafts) { - $statusDrafts = (int) $this->modx->getOption('ms3_status_draft', null, 1) ?: 1; - $c->where(['status_id:!=' => $statusDrafts]); - } + $this->applyDraftVisibilityFilter($c, $params); if (!empty($query)) { if (is_numeric($query)) { @@ -1535,6 +1531,41 @@ protected function getOrdersStats(array $params = []): array ]; } + /** + * Whether draft orders should be included in the manager orders list query. + * + * When `show_drafts` is present in request params it overrides `ms3_order_show_drafts`. + * The Vue orders grid always sends this flag (initialized from ms3.config.order_show_drafts). + */ + protected function shouldShowDrafts(array $params): bool + { + $default = (bool) $this->modx->getOption('ms3_order_show_drafts', null, false); + + if (!array_key_exists('show_drafts', $params)) { + return $default; + } + + $value = $params['show_drafts']; + if ($value === '' || $value === null) { + return $default; + } + + return filter_var($value, FILTER_VALIDATE_BOOLEAN); + } + + /** + * Exclude draft status from getList query unless drafts are explicitly shown. + */ + protected function applyDraftVisibilityFilter($c, array $params): void + { + if ($this->shouldShowDrafts($params)) { + return; + } + + $statusDrafts = (int) $this->modx->getOption('ms3_status_draft', null, 1) ?: 1; + $c->where(['status_id:!=' => $statusDrafts]); + } + /** * Apply filter to query * diff --git a/vueManager/src/components/OrdersGrid.vue b/vueManager/src/components/OrdersGrid.vue index 711f1c7f..1812eb3b 100644 --- a/vueManager/src/components/OrdersGrid.vue +++ b/vueManager/src/components/OrdersGrid.vue @@ -2,6 +2,7 @@ import { useLexicon } from '@vuetools/useLexicon' import Button from 'primevue/button' import Card from 'primevue/card' +import Checkbox from 'primevue/checkbox' import Column from 'primevue/column' import ConfirmDialog from 'primevue/confirmdialog' import DataTable from 'primevue/datatable' @@ -20,6 +21,20 @@ import ActionsColumn from './ActionsColumn.vue' const toast = useToast() const { _ } = useLexicon() +const ms3Config = typeof ms3 !== 'undefined' ? ms3.config : null +const showDrafts = ref(Boolean(ms3Config?.order_show_drafts)) + +/** Filter keys sent as direct API params (not filter_ prefix). */ +const DIRECT_FILTER_KEYS = new Set([ + 'query', + 'status_id', + 'delivery_id', + 'payment_id', + 'context_key', + 'createdon_from', + 'createdon_to', +]) + // Bulk selection const { selectedItems, @@ -73,13 +88,13 @@ async function loadOrders() { limit: rows.value, sort: sortField.value, dir: sortOrder.value === 1 ? 'ASC' : 'DESC', + show_drafts: showDrafts.value ? 1 : 0, } // Apply filter values Object.keys(filterValues.value).forEach(key => { const value = filterValues.value[key] if (value !== null && value !== undefined && value !== '') { - // Handle daterange type const filterConfig = filters.value[key] if (filterConfig?.type === 'daterange' && Array.isArray(value)) { if (value[0]) { @@ -90,8 +105,10 @@ async function loadOrders() { } } else if (filterConfig?.type === 'datepicker' && value) { params[key] = formatDateForApi(value) - } else { + } else if (DIRECT_FILTER_KEYS.has(key)) { params[key] = value + } else { + params[`filter_${key}`] = value } } }) @@ -373,6 +390,11 @@ const hasActiveFilters = computed(() => { return Object.values(filterValues.value).some(v => v !== null && v !== '' && v !== undefined) }) +function toggleShowDrafts() { + first.value = 0 + loadOrders() +} + /** * Load grid configuration */ @@ -547,7 +569,7 @@ onMounted(async () => { @click="createNewOrder" /> -
+
{{ _('orders_month') }}: {{ stats.month_total }} @@ -648,6 +670,15 @@ onMounted(async () => {
+
+ + +