Current path: home/webdevt/www/schtroumpf.fr/admin254sdct88d6xocraexw/themes/new-theme/js/pages/order/create/
?? Go up: /home/webdevt/www/schtroumpf.fr/admin254sdct88d6xocraexw/themes/new-theme/js/pages/order
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
import Router from '@components/router';
import {EventEmitter} from '@components/event-emitter';
import _ from 'lodash';
import createOrderMap from './create-order-map';
import CustomerManager from './customer-manager';
import ShippingRenderer from './shipping-renderer';
import CartProvider from './cart-provider';
import AddressesRenderer from './addresses-renderer';
import CartRulesRenderer from './cart-rules-renderer';
import CartEditor, {CartProduct} from './cart-editor';
import eventMap from './event-map';
import CartRuleManager from './cart-rule-manager';
import ProductManager from './product-manager';
import ProductRenderer from './product-renderer';
import SummaryRenderer from './summary-renderer';
import SummaryManager from './summary-manager';
import {ValidateAddresses} from './address-validator';
const {$} = window;
export interface CartAddress {
addressId: number;
alias: string;
delivery: boolean;
formattedAddress: string;
}
export interface CartInfo {
addresses: Array<CartAddress>;
cartId: number;
cartRules: any;
currencyId: number;
langId: number;
products: Array<CartInfoProduct>;
shipping: CartShipping;
summary: CartSummary;
}
export interface CartInfoProduct {
attribute: string;
attributeId: number;
availableOutOfStock: boolean;
availableStock: number;
customization: Array<CustomizationField>;
gift: boolean
imageLink: string;
name: string;
price: string;
productId: number;
quantity: number;
reference: string;
unitPrice: string;
}
export interface CartShipping {
deliveryOptions: Array<CartDeliveryOptions>;
freeShipping: boolean;
gift: boolean;
giftMessage: string;
recycledPackaging: boolean;
selectedCarrierId: number | null | string;
}
export interface CartSummary {
orderMessage: string;
processOrderLink: string;
totalDiscount: string;
totalPriceWithTaxes: string;
totalPriceWithoutTaxes: string;
totalProductsPrice: string;
totalShippingPrice: string;
totalShippingWithoutTaxes: string;
}
export interface CartDeliveryOptions {
carrierId: number;
carrierName: string;
carrierDelay: string;
}
export interface CartCustomization {
customizationId: number;
customizationFieldsData: Array<CustomizationField>;
}
export interface CustomizationField {
type: number;
name: string;
value: string;
}
/**
* Page Object for "Create order" page
*/
export default class CreateOrderPage {
cartId: number | null;
customerId: number | null;
$container: JQuery;
cartProvider: CartProvider;
timeoutId: number | null | ReturnType<typeof setTimeout>;
customerManager: CustomerManager;
shippingRenderer: ShippingRenderer;
addressesRenderer: AddressesRenderer;
cartRulesRenderer: CartRulesRenderer;
router: Router;
cartEditor: CartEditor;
cartRuleManager: CartRuleManager;
productManager: ProductManager;
productRenderer: ProductRenderer;
summaryRenderer: SummaryRenderer;
summaryManager: SummaryManager;
constructor() {
this.cartId = null;
this.customerId = null;
this.$container = $(createOrderMap.orderCreationContainer);
this.cartProvider = new CartProvider();
this.customerManager = new CustomerManager();
this.shippingRenderer = new ShippingRenderer();
this.addressesRenderer = new AddressesRenderer();
this.cartRulesRenderer = new CartRulesRenderer();
this.router = new Router();
this.cartEditor = new CartEditor();
this.cartRuleManager = new CartRuleManager();
this.productManager = new ProductManager();
this.productRenderer = new ProductRenderer();
this.summaryRenderer = new SummaryRenderer();
this.summaryManager = new SummaryManager();
this.timeoutId = 0;
this.initListeners();
this.loadCartFromUrlParams();
}
/**
* Checks if correct addresses are selected.
* There is a case when options list cannot contain cart addresses 'selected' values
* because those are outdated in db (e.g. deleted after cart creation or country is disabled)
*
* @param {Array} addresses
*
* @returns {boolean}
*/
static validateSelectedAddresses(addresses: Record<string, any>): boolean {
let deliveryValid = false;
let invoiceValid = false;
const keys = Object.keys(addresses);
for (let i = 0; i < keys.length; i += 1) {
const address = addresses[keys[i]];
if (address.delivery) {
deliveryValid = true;
}
if (address.invoice) {
invoiceValid = true;
}
if (deliveryValid && invoiceValid) {
return true;
}
}
return false;
}
/**
* Hides whole cart information wrapper
*/
hideCartInfo(): void {
$(createOrderMap.cartInfoWrapper).addClass('d-none');
}
/**
* Shows whole cart information wrapper
*/
showCartInfo(): void {
$(createOrderMap.cartInfoWrapper).removeClass('d-none');
}
/**
* Loads cart if query params contains valid cartId
*
* @private
*/
loadCartFromUrlParams(): void {
const urlParams = new URLSearchParams(window.location.search);
const cartId = Number(urlParams.get('cartId'));
if (!Number.isNaN(cartId) && cartId !== 0) {
this.cartProvider.getCart(cartId);
}
}
/**
* Initializes event listeners
*
* @private
*/
private initListeners(): void {
this.$container.on('input', createOrderMap.customerSearchInput, (e: JQueryEventObject) => this.initCustomerSearch(e),
);
this.$container.on('click', createOrderMap.chooseCustomerBtn, (e: JQueryEventObject) => this.initCustomerSelect(e),
);
this.$container.on('click', createOrderMap.useCartBtn, (e: JQueryEventObject) => this.initCartSelect(e),
);
this.$container.on('click', createOrderMap.useOrderBtn, (e: JQueryEventObject) => this.initDuplicateOrderCart(e),
);
this.$container.on('input', createOrderMap.productSearch, (e: JQueryEventObject) => this.initProductSearch(e),
);
this.$container.on('input', createOrderMap.cartRuleSearchInput, (e: JQueryEventObject) => this.initCartRuleSearch(e),
);
this.$container.on('blur', createOrderMap.cartRuleSearchInput, () => this.cartRuleManager.stopSearching(),
);
this.listenForCartEdit();
this.onCartLoaded();
this.onCustomersNotFound();
this.onCustomerSelected();
this.initAddressButtonsIframe();
this.initCartRuleButtonsIframe();
}
/**
* @private
*/
private initAddressButtonsIframe(): void {
$(createOrderMap.addressAddBtn).fancybox({
type: 'iframe',
width: '90%',
height: '90%',
});
$(createOrderMap.invoiceAddressEditBtn).fancybox({
type: 'iframe',
width: '90%',
height: '90%',
});
$(createOrderMap.deliveryAddressEditBtn).fancybox({
type: 'iframe',
width: '90%',
height: '90%',
});
}
initCartRuleButtonsIframe(): void {
$('#js-add-cart-rule-btn').fancybox({
type: 'iframe',
width: '90%',
height: '90%',
});
}
/**
* Delegates actions to events associated with cart update (e.g. change cart address)
*
* @private
*/
private listenForCartEdit(): void {
this.onCartAddressesChanged();
this.onDeliveryOptionChanged();
this.onDeliverySettingChanged();
this.addCartRuleToCart();
this.removeCartRuleFromCart();
this.onCartCurrencyChanged();
this.onCartLanguageChanged();
this.$container.on('change', createOrderMap.deliveryOptionSelect, (e) => this.cartEditor.changeDeliveryOption(
<number> this.cartId,
e.currentTarget.value,
),
);
this.$container.on('change', createOrderMap.freeShippingSwitch, () => {
this.cartEditor.updateDeliveryOptions(<number> this.cartId);
});
this.$container.on('change', createOrderMap.recycledPackagingSwitch, () => {
this.cartEditor.updateDeliveryOptions(<number> this.cartId);
});
this.$container.on('change', createOrderMap.isAGiftSwitch, () => this.cartEditor.updateDeliveryOptions(<number> this.cartId),
);
this.$container.on('blur', createOrderMap.giftMessageField, () => this.cartEditor.updateDeliveryOptions(<number> this.cartId),
);
this.$container.on('click', createOrderMap.addToCartButton, () => this.productManager.addProductToCart(<number> this.cartId),
);
this.$container.on('change', createOrderMap.cartCurrencySelect, (e) => this.cartEditor.changeCartCurrency(
<number> this.cartId,
e.currentTarget.value,
),
);
this.$container.on('change', createOrderMap.cartLanguageSelect, (e) => this.cartEditor.changeCartLanguage(
<number> this.cartId,
e.currentTarget.value,
),
);
// eslint-disable-next-line
this.$container.on('click', createOrderMap.sendProcessOrderEmailBtn, () => this.summaryManager.sendProcessOrderEmail(<number> this.cartId),
);
this.$container.on(
'change',
createOrderMap.listedProductUnitPriceInput,
(e: JQueryEventObject) => this.initProductChangePrice(e),
);
this.$container.on(
'change',
createOrderMap.listedProductQtyInput,
_.debounce((e: JQueryEventObject) => {
const inputsQty = document.querySelectorAll(
createOrderMap.listedProductQtyInput,
);
inputsQty.forEach((inputQty) => {
inputQty.setAttribute('disabled', 'true');
});
this.initProductChangeQty(e);
}, 500),
);
this.$container.on('change', createOrderMap.addressSelect, () => this.changeCartAddresses(),
);
this.$container.on(
'click',
createOrderMap.productRemoveBtn,
(e: JQueryEventObject) => this.initProductRemoveFromCart(e),
);
}
/**
* Listens for event when cart is loaded
*
* @private
*/
private onCartLoaded(): void {
EventEmitter.on(eventMap.cartLoaded, (cartInfo) => {
this.cartId = cartInfo.cartId;
this.renderCartInfo(cartInfo);
if (
cartInfo.addresses.length !== 0
&& !ValidateAddresses(cartInfo.addresses)
) {
this.changeCartAddresses();
}
this.customerManager.loadCustomerCarts(<string><unknown> this.cartId);
this.customerManager.loadCustomerOrders();
});
}
/**
* Listens for event when no customers were found by search
*
* @private
*/
private onCustomersNotFound(): void {
EventEmitter.on(eventMap.customersNotFound, () => {
this.hideCartInfo();
});
}
/**
* Listens for event when customer is selected
*
* @private
*/
private onCustomerSelected() {
EventEmitter.on(eventMap.customerSelected, () => {
this.showCartInfo();
});
}
/**
* Listens for cart addresses update event
*
* @private
*/
private onCartAddressesChanged() {
EventEmitter.on(eventMap.cartAddressesChanged, (cartInfo) => {
this.addressesRenderer.render(cartInfo.addresses, cartInfo.cartId);
this.cartRulesRenderer.renderCartRulesBlock(
cartInfo.cartRules,
cartInfo.products.length === 0,
);
this.shippingRenderer.render(
cartInfo.shipping,
cartInfo.products.length === 0,
);
this.productRenderer.renderList(cartInfo.products);
this.summaryRenderer.render(cartInfo);
});
}
/**
* Listens for cart delivery option update event
*
* @private
*/
private onDeliveryOptionChanged() {
EventEmitter.on(eventMap.cartDeliveryOptionChanged, (cartInfo) => {
this.cartRulesRenderer.renderCartRulesBlock(
cartInfo.cartRules,
cartInfo.products.length === 0,
);
this.shippingRenderer.render(
cartInfo.shipping,
cartInfo.products.length === 0,
);
this.summaryRenderer.render(cartInfo);
this.productRenderer.renderList(cartInfo.products);
});
}
/**
* Listens for cart delivery setting update event
*
* @private
*/
private onDeliverySettingChanged() {
EventEmitter.on(eventMap.cartDeliverySettingChanged, (cartInfo) => {
this.cartRulesRenderer.renderCartRulesBlock(
cartInfo.cartRules,
cartInfo.products.length === 0,
);
this.shippingRenderer.render(
cartInfo.shipping,
cartInfo.products.length === 0,
);
this.summaryRenderer.render(cartInfo);
});
}
/**
* Listens for cart language update event
*
* @private
*/
private onCartLanguageChanged() {
EventEmitter.on(eventMap.cartLanguageChanged, (cartInfo: CartInfo) => {
this.preselectCartLanguage(cartInfo.langId);
this.renderCartInfo(cartInfo);
});
}
/**
* Listens for cart currency update event
*
* @private
*/
private onCartCurrencyChanged() {
// on success
EventEmitter.on(eventMap.cartCurrencyChanged, (cartInfo: CartInfo) => {
this.renderCartInfo(cartInfo);
this.productRenderer.reset();
});
// on failure
EventEmitter.on(eventMap.cartCurrencyChangeFailed, (response) => {
this.productRenderer.renderCartBlockErrorAlert(
response.responseJSON.message,
);
});
}
/**
* Init customer searching
*
* @param event
*
* @private
*/
private initCustomerSearch(event: JQueryEventObject) {
clearTimeout(<number> this.timeoutId);
this.timeoutId = setTimeout(
() => this.customerManager.search(<string>$(event.currentTarget).val()),
300,
);
}
/**
* Init selecting customer for which order is being created
*
* @param event
*
* @private
*/
private initCustomerSelect(event: JQueryEventObject) {
const customerId = this.customerManager.selectCustomer(event);
this.customerId = customerId;
this.cartProvider.loadEmptyCart(customerId);
}
/**
* Inits selecting cart to load
*
* @param event
*
* @private
*/
private initCartSelect(event: JQueryEventObject) {
const cartId = $(event.currentTarget).data('cart-id');
this.cartProvider.getCart(cartId);
}
/**
* Inits duplicating order cart
*
* @private
*/
private initDuplicateOrderCart(event: JQueryEventObject) {
const orderId = $(event.currentTarget).data('order-id');
this.cartProvider.duplicateOrderCart(orderId);
}
/**
* Triggers cart rule searching
*
* @private
*/
private initCartRuleSearch(event: JQueryEventObject) {
const input = <HTMLInputElement>event.currentTarget;
const searchPhrase = input.value;
clearTimeout(<ReturnType<typeof setTimeout>> this.timeoutId);
this.timeoutId = setTimeout(
() => this.cartRuleManager.search(searchPhrase),
300,
);
}
/**
* Triggers cart rule select
*
* @private
*/
private addCartRuleToCart() {
this.$container
.on('mousedown', createOrderMap.foundCartRuleListItem, (event) => {
// prevent blur event to allow selecting cart rule
event.preventDefault();
const cartRuleId = $(event.currentTarget).data('cart-rule-id');
this.cartRuleManager.addCartRuleToCart(cartRuleId, <number> this.cartId);
// manually fire blur event after cart rule is selected.
})
.on('click', createOrderMap.foundCartRuleListItem, () => {
$(createOrderMap.cartRuleSearchInput).blur();
});
}
/**
* Triggers cart rule removal from cart
*
* @private
*/
private removeCartRuleFromCart() {
this.$container.on('click', createOrderMap.cartRuleDeleteBtn, (event) => {
this.cartRuleManager.removeCartRuleFromCart(
$(event.currentTarget).data('cart-rule-id'),
<number> this.cartId,
);
});
}
/**
* Inits product searching
*
* @param event
*
* @private
*/
private initProductSearch(event: JQueryEventObject) {
const $productSearchInput = $(event.currentTarget);
const searchPhrase = $productSearchInput.val();
clearTimeout(<ReturnType<typeof setTimeout>> this.timeoutId);
this.timeoutId = setTimeout(
() => this.productManager.search(<string>searchPhrase),
300,
);
}
/**
* Inits product removing from cart
*
* @param event
*
* @private
*/
private initProductRemoveFromCart(event: JQueryEventObject) {
const productQty = Number(
$(event.currentTarget)
.parents()
.find(createOrderMap.listedProductQtyInput)
.val(),
);
const product = {
productId: $(event.currentTarget).data('product-id'),
attributeId: $(event.currentTarget).data('attribute-id'),
customizationId: $(event.currentTarget).data('customization-id'),
qtyToRemove: productQty,
};
this.productManager.removeProductFromCart(<number> this.cartId, product);
}
/**
* Inits product in cart price change
*
* @param event
*
* @private
*/
private initProductChangePrice(event: JQueryEventObject) {
const product: CartProduct = {
productId: $(event.currentTarget).data('product-id'),
attributeId: $(event.currentTarget).data('attribute-id'),
customizationId: $(event.currentTarget).data('customization-id'),
price: <string>$(event.currentTarget).val(),
};
this.productManager.changeProductPrice(
<number> this.cartId,
<number> this.customerId,
product,
);
}
/**
* Inits product in cart quantity update
*
* @param event
*
* @private
*/
private initProductChangeQty(event: JQueryEventObject) {
const product: CartProduct = {
productId: $(event.currentTarget).data('product-id'),
attributeId: $(event.currentTarget).data('attribute-id'),
customizationId: $(event.currentTarget).data('customization-id'),
newQty: <string>$(event.currentTarget).val(),
prevQty: $(event.currentTarget).data('prev-qty'),
};
if (
typeof product.productId !== 'undefined'
&& product.productId !== null
&& typeof product.attributeId !== 'undefined'
&& product.attributeId !== null
) {
this.productManager.changeProductQty(<number> this.cartId, product);
} else {
const inputsQty = <NodeListOf<HTMLInputElement>>(
document.querySelectorAll(createOrderMap.listedProductQtyInput)
);
inputsQty.forEach((inputQty: HTMLInputElement) => {
// eslint-disable-next-line
inputQty.disabled = false;
});
}
}
/**
* Renders cart summary on the page
*
* @param {Object} cartInfo
*
* @private
*/
private renderCartInfo(cartInfo: CartInfo): void {
this.addressesRenderer.render(cartInfo.addresses, cartInfo.cartId);
this.cartRulesRenderer.renderCartRulesBlock(
cartInfo.cartRules,
cartInfo.products.length === 0,
);
this.shippingRenderer.render(
cartInfo.shipping,
cartInfo.products.length === 0,
);
this.productRenderer.cleanCartBlockAlerts();
this.productRenderer.renderList(cartInfo.products);
this.summaryRenderer.render(cartInfo);
this.preselectCartCurrency(cartInfo.currencyId);
this.preselectCartLanguage(cartInfo.langId);
$(createOrderMap.cartBlock).removeClass('d-none');
$(createOrderMap.cartBlock).data('cartId', cartInfo.cartId);
}
/**
* Sets cart currency selection value
*
* @param currencyId
*
* @private
*/
private preselectCartCurrency(currencyId: number) {
$(createOrderMap.cartCurrencySelect).val(currencyId);
}
/**
* Sets cart language selection value
*
* @param langId
*
* @private
*/
private preselectCartLanguage(langId: number) {
$(createOrderMap.cartLanguageSelect).val(langId);
}
/**
* Changes cart addresses
*
* @private
*/
private changeCartAddresses() {
const addresses = {
deliveryAddressId: <string>$(createOrderMap.deliveryAddressSelect).val(),
invoiceAddressId: <string>$(createOrderMap.invoiceAddressSelect).val(),
};
this.cartEditor.changeCartAddresses(<number> this.cartId, addresses);
}
/**
* Refresh addresses list
*
* @param {boolean} refreshCartAddresses optional
*/
refreshAddressesList(refreshCartAddresses: boolean): void {
const cartId = $(createOrderMap.cartBlock).data('cartId');
$.get(this.router.generate('admin_carts_info', {cartId}))
.then((cartInfo) => {
this.addressesRenderer.render(cartInfo.addresses, cartInfo.cartId);
if (refreshCartAddresses) {
this.changeCartAddresses();
}
})
.catch((e: Record<string, any>) => {
window.showErrorMessage(e.responseJSON.message);
});
}
search(string: string): void {
this.customerManager.search(string);
}
/**
* proxy to allow other scripts within the page to refresh addresses list
*/
refreshCart(): void {
const cartId = $(createOrderMap.cartBlock).data('cartId');
this.cartProvider.getCart(cartId);
}
}