feat(telecart): add vouchers and coupons (#9)
This commit is contained in:
@@ -348,11 +348,24 @@ TEXT,
|
|||||||
'module_tgshop_mini_app_url' => rtrim(HTTPS_CATALOG, '/') . '/image/catalog/tgshopspa/#/',
|
'module_tgshop_mini_app_url' => rtrim(HTTPS_CATALOG, '/') . '/image/catalog/tgshopspa/#/',
|
||||||
'module_tgshop_mainpage_categories' => 'latest10',
|
'module_tgshop_mainpage_categories' => 'latest10',
|
||||||
'module_tgshop_enable_store' => 1,
|
'module_tgshop_enable_store' => 1,
|
||||||
|
'module_tgshop_feature_coupons' => 0,
|
||||||
|
'module_tgshop_feature_vouchers' => 0,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getSettingsConfig(): array
|
private function getSettingsConfig(): array
|
||||||
{
|
{
|
||||||
|
$ocCouponsLink = $this->url->link(
|
||||||
|
'marketing/coupon',
|
||||||
|
'user_token=' . $this->session->data['user_token'],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
$ocVouchersLink = $this->url->link(
|
||||||
|
'sale/voucher',
|
||||||
|
'user_token=' . $this->session->data['user_token'],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'general' => [
|
'general' => [
|
||||||
'module_tgshop_status' => [
|
'module_tgshop_status' => [
|
||||||
@@ -486,6 +499,28 @@ HTML,
|
|||||||
'type' => 'categories',
|
'type' => 'categories',
|
||||||
'help' => 'На главной странице будут отображаться эти категории, если вы выберете этот вариант в настройке “Категории на главной”.',
|
'help' => 'На главной странице будут отображаться эти категории, если вы выберете этот вариант в настройке “Категории на главной”.',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'module_tgshop_feature_coupons' => [
|
||||||
|
'type' => 'select',
|
||||||
|
'options' => [
|
||||||
|
0 => 'Выключено',
|
||||||
|
1 => 'Включено',
|
||||||
|
],
|
||||||
|
'help' => <<<HTML
|
||||||
|
Позволяет использовать стандартные <a href="{$ocCouponsLink}" target="_blank">купоны OpenCart</a> для предоставления скидок при оформлении заказа.
|
||||||
|
HTML,
|
||||||
|
],
|
||||||
|
|
||||||
|
'module_tgshop_feature_vouchers' => [
|
||||||
|
'type' => 'select',
|
||||||
|
'options' => [
|
||||||
|
0 => 'Выключено',
|
||||||
|
1 => 'Включено',
|
||||||
|
],
|
||||||
|
'help' => <<<HTML
|
||||||
|
Позволяет покупателям использовать <a href="{$ocVouchersLink}" target="_blank">подарочные сертификаты OpenCart</a> при оформлении заказа.
|
||||||
|
HTML,
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
'orders' => [
|
'orders' => [
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ $_['lbl_module_tgshop_mini_app_url'] = 'Ссылка на Telegram Mini App';
|
|||||||
$_['lbl_module_tgshop_mainpage_categories'] = 'Категории на главной';
|
$_['lbl_module_tgshop_mainpage_categories'] = 'Категории на главной';
|
||||||
$_['lbl_module_tgshop_featured_categories'] = 'Избранные категории';
|
$_['lbl_module_tgshop_featured_categories'] = 'Избранные категории';
|
||||||
$_['lbl_module_tgshop_enable_store'] = 'Разрешить покупки';
|
$_['lbl_module_tgshop_enable_store'] = 'Разрешить покупки';
|
||||||
|
$_['lbl_module_tgshop_feature_coupons'] = 'Промокоды';
|
||||||
|
$_['lbl_module_tgshop_feature_vouchers'] = 'Подарочные сертификаты';
|
||||||
|
|
||||||
// Entry
|
// Entry
|
||||||
$_['entry_status'] = 'Статус';
|
$_['entry_status'] = 'Статус';
|
||||||
|
|||||||
@@ -83,23 +83,30 @@ class ControllerExtensionTgshopHandle extends Controller
|
|||||||
],
|
],
|
||||||
'cache_categories_main' => 60 * 10,
|
'cache_categories_main' => 60 * 10,
|
||||||
'cache_products_main' => 60 * 10,
|
'cache_products_main' => 60 * 10,
|
||||||
|
'feature_coupons' => filter_var(
|
||||||
|
$this->config->get('module_tgshop_feature_coupons'),
|
||||||
|
FILTER_VALIDATE_BOOLEAN
|
||||||
|
),
|
||||||
|
'feature_vouchers' => filter_var(
|
||||||
|
$this->config->get('module_tgshop_feature_vouchers'),
|
||||||
|
FILTER_VALIDATE_BOOLEAN
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$app->bind(OcModelCatalogProductAdapter::class, function () {
|
$app->bind(OcModelCatalogProductAdapter::class, function () {
|
||||||
|
|
||||||
return new OcModelCatalogProductAdapter($this->model_catalog_product);
|
return new OcModelCatalogProductAdapter($this->model_catalog_product);
|
||||||
});
|
});
|
||||||
|
|
||||||
$app->bind(Url::class, fn () => $this->url);
|
$app->bind(Url::class, fn() => $this->url);
|
||||||
$app->bind(Currency::class, fn () => $this->currency);
|
$app->bind(Currency::class, fn() => $this->currency);
|
||||||
$app->bind(Tax::class, fn () => $this->tax);
|
$app->bind(Tax::class, fn() => $this->tax);
|
||||||
$app->bind(ImageToolInterface::class, fn () => new ImageTool(DIR_IMAGE, HTTPS_SERVER));
|
$app->bind(ImageToolInterface::class, fn() => new ImageTool(DIR_IMAGE, HTTPS_SERVER));
|
||||||
$app->bind(Cart::class, fn () => $this->cart);
|
$app->bind(Cart::class, fn() => $this->cart);
|
||||||
$app->bind(OcRegistryDecorator::class, fn () => new OcRegistryDecorator($this->registry));
|
$app->bind(OcRegistryDecorator::class, fn() => new OcRegistryDecorator($this->registry));
|
||||||
$app->singleton(Log::class, fn () => $this->log);
|
$app->singleton(Log::class, fn() => $this->log);
|
||||||
|
|
||||||
$app
|
$app
|
||||||
->withLogger(fn () => new OpenCartLogAdapter($this->log, 'TeleCart'))
|
->withLogger(fn() => new OpenCartLogAdapter($this->log, 'TeleCart'))
|
||||||
->bootAndHandleRequest();
|
->bootAndHandleRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ class SettingsHandler
|
|||||||
'ya_metrika_enabled' => $this->settings->get('ya_metrika_enabled'),
|
'ya_metrika_enabled' => $this->settings->get('ya_metrika_enabled'),
|
||||||
'app_enabled' => $this->settings->get('app_enabled'),
|
'app_enabled' => $this->settings->get('app_enabled'),
|
||||||
'store_enabled' => $this->settings->get('store_enabled'),
|
'store_enabled' => $this->settings->get('store_enabled'),
|
||||||
|
'feature_coupons' => $this->settings->get('feature_coupons') ?? false,
|
||||||
|
'feature_vouchers' => $this->settings->get('feature_vouchers') ?? false,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/fixtures/criteria_builder/product_category/contains/output.sql
vendored
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/fixtures/criteria_builder/product_category/contains/output.sql
vendored
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/fixtures/criteria_builder/product_category/not_contains/output.sql
vendored
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/fixtures/criteria_builder/product_category/not_contains/output.sql
vendored
Normal file → Executable file
@@ -1,6 +1,6 @@
|
|||||||
import {defineStore} from "pinia";
|
import {defineStore} from "pinia";
|
||||||
import {isNotEmpty} from "@/helpers.js";
|
import {isNotEmpty} from "@/helpers.js";
|
||||||
import {addToCart, cartEditItem, cartRemoveItem, getCart} from "@/utils/ftch.js";
|
import {addToCart, cartEditItem, cartRemoveItem, getCart, setCoupon, setVoucher} from "@/utils/ftch.js";
|
||||||
|
|
||||||
export const useCartStore = defineStore('cart', {
|
export const useCartStore = defineStore('cart', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
@@ -12,6 +12,8 @@ export const useCartStore = defineStore('cart', {
|
|||||||
error_warning: '',
|
error_warning: '',
|
||||||
attention: '',
|
attention: '',
|
||||||
success: '',
|
success: '',
|
||||||
|
coupon: '',
|
||||||
|
voucher: '',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
getters: {
|
getters: {
|
||||||
@@ -104,5 +106,43 @@ export const useCartStore = defineStore('cart', {
|
|||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async applyCoupon() {
|
||||||
|
try {
|
||||||
|
this.isLoading = true;
|
||||||
|
this.error_warning = '';
|
||||||
|
const response = await setCoupon(this.coupon);
|
||||||
|
|
||||||
|
if (response.error) {
|
||||||
|
this.error_warning = response.error;
|
||||||
|
} else {
|
||||||
|
await this.getProducts();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
this.error_warning = 'Возникла ошибка';
|
||||||
|
} finally {
|
||||||
|
this.isLoading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async applyVoucher() {
|
||||||
|
try {
|
||||||
|
this.isLoading = true;
|
||||||
|
this.error_warning = '';
|
||||||
|
const response = await setVoucher(this.voucher);
|
||||||
|
|
||||||
|
if (response.error) {
|
||||||
|
this.error_warning = response.error;
|
||||||
|
} else {
|
||||||
|
await this.getProducts();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
this.error_warning = 'Возникла ошибка';
|
||||||
|
} finally {
|
||||||
|
this.isLoading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ export const useSettingsStore = defineStore('settings', {
|
|||||||
manifest_url: null,
|
manifest_url: null,
|
||||||
night_auto: true,
|
night_auto: true,
|
||||||
ya_metrika_enabled: false,
|
ya_metrika_enabled: false,
|
||||||
|
feature_coupons: false,
|
||||||
|
feature_vouchers: false,
|
||||||
theme: {
|
theme: {
|
||||||
light: 'light',
|
light: 'light', dark: 'dark', variables: {
|
||||||
dark: 'dark',
|
|
||||||
variables: {
|
|
||||||
'--product_list_title_max_lines': 2,
|
'--product_list_title_max_lines': 2,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -40,6 +40,8 @@ export const useSettingsStore = defineStore('settings', {
|
|||||||
this.ya_metrika_enabled = settings.ya_metrika_enabled;
|
this.ya_metrika_enabled = settings.ya_metrika_enabled;
|
||||||
this.app_enabled = settings.app_enabled;
|
this.app_enabled = settings.app_enabled;
|
||||||
this.store_enabled = settings.store_enabled;
|
this.store_enabled = settings.store_enabled;
|
||||||
|
this.feature_coupons = settings.feature_coupons;
|
||||||
|
this.feature_vouchers = settings.feature_vouchers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -72,4 +72,24 @@ export async function getFiltersForMainPage() {
|
|||||||
return await ftch('filtersForMainPage');
|
return await ftch('filtersForMainPage');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function setCoupon(coupon) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('coupon', coupon);
|
||||||
|
|
||||||
|
return await apiFetch(`${BASE_URL}index.php?route=extension/total/coupon/coupon`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setVoucher(voucher) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('voucher', voucher);
|
||||||
|
|
||||||
|
return await apiFetch(`${BASE_URL}index.php?route=extension/total/voucher/voucher`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export default ftch;
|
export default ftch;
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card card-border bg-base-100">
|
<div class="card card-border bg-base-100 mb-3">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h2 class="card-title">Ваша корзина</h2>
|
<h2 class="card-title">Ваша корзина</h2>
|
||||||
<div v-for="total in cart.totals">
|
<div v-for="total in cart.totals">
|
||||||
@@ -84,6 +84,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="settings.feature_coupons || settings.feature_vouchers"
|
||||||
|
class="card card-border bg-base-100 mb-3"
|
||||||
|
>
|
||||||
|
<div class="card-body">
|
||||||
|
<div v-if="settings.feature_coupons" class="join">
|
||||||
|
<input v-model="cart.coupon" type="text" class="input" placeholder="Промокод"/>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
:disabled="!cart.coupon"
|
||||||
|
@click="cart.applyCoupon"
|
||||||
|
>Применить</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="settings.feature_vouchers" class="join">
|
||||||
|
<input v-model="cart.voucher" type="text" class="input" placeholder="Подарочный сертификат"/>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
:disabled="!cart.voucher"
|
||||||
|
@click="cart.applyVoucher"
|
||||||
|
>Применить</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="fixed px-4 pb-10 pt-4 bottom-0 left-0 w-full bg-base-200 z-50 flex justify-between items-center gap-2 border-t-1 border-t-base-300">
|
<div class="fixed px-4 pb-10 pt-4 bottom-0 left-0 w-full bg-base-200 z-50 flex justify-between items-center gap-2 border-t-1 border-t-base-300">
|
||||||
<div>
|
<div>
|
||||||
<div v-if="lastTotal">
|
<div v-if="lastTotal">
|
||||||
@@ -122,9 +147,11 @@ import OptionCheckbox from "@/components/ProductOptions/Cart/OptionCheckbox.vue"
|
|||||||
import OptionText from "@/components/ProductOptions/Cart/OptionText.vue";
|
import OptionText from "@/components/ProductOptions/Cart/OptionText.vue";
|
||||||
import {computed} from "vue";
|
import {computed} from "vue";
|
||||||
import {useRouter} from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
|
import {useSettingsStore} from "@/stores/SettingsStore.js";
|
||||||
|
|
||||||
const cart = useCartStore();
|
const cart = useCartStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const settings = useSettingsStore();
|
||||||
|
|
||||||
// const componentMap = {
|
// const componentMap = {
|
||||||
// radio: OptionRadio,
|
// radio: OptionRadio,
|
||||||
|
|||||||
Reference in New Issue
Block a user