first commit
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
|
||||
/* eslint-disable max-len */
|
||||
|
||||
export default {
|
||||
mainDiv: '#order-view-page',
|
||||
orderPaymentDetailsBtn: '.js-payment-details-btn',
|
||||
orderPaymentFormAmountInput: '#order_payment_amount',
|
||||
orderPaymentInvoiceSelect: '#order_payment_id_invoice',
|
||||
viewOrderPaymentsBlock: '#view_order_payments_block',
|
||||
viewOrderPaymentsAlert: '.js-view-order-payments-alert',
|
||||
privateNoteToggleBtn: '.js-private-note-toggle-btn',
|
||||
privateNoteBlock: '.js-private-note-block',
|
||||
privateNoteInput: '#private_note_note',
|
||||
privateNoteSubmitBtn: '.js-private-note-btn',
|
||||
addCartRuleModal: '#addOrderDiscountModal',
|
||||
addCartRuleInvoiceIdSelect: '#add_order_cart_rule_invoice_id',
|
||||
addCartRuleNameInput: '#add_order_cart_rule_name',
|
||||
addCartRuleTypeSelect: '#add_order_cart_rule_type',
|
||||
addCartRuleValueInput: '#add_order_cart_rule_value',
|
||||
addCartRuleValueUnit: '#add_order_cart_rule_value_unit',
|
||||
addCartRuleSubmit: '#add_order_cart_rule_submit',
|
||||
cartRuleHelpText: '.js-cart-rule-value-help',
|
||||
updateOrderStatusActionBtn: '#update_order_status_action_btn',
|
||||
updateOrderStatusActionInput: '#update_order_status_action_input',
|
||||
updateOrderStatusActionInputWrapper: '#update_order_status_action_input_wrapper',
|
||||
updateOrderStatusActionForm: '#update_order_status_action_form',
|
||||
showOrderShippingUpdateModalBtn: '.js-update-shipping-btn',
|
||||
updateOrderShippingTrackingNumberInput: '#update_order_shipping_tracking_number',
|
||||
updateOrderShippingCurrentOrderCarrierIdInput: '#update_order_shipping_current_order_carrier_id',
|
||||
updateCustomerAddressModal: '#updateCustomerAddressModal',
|
||||
openOrderAddressUpdateModalBtn: '.js-update-customer-address-modal-btn',
|
||||
updateOrderAddressTypeInput: '#change_order_address_address_type',
|
||||
deliveryAddressEditBtn: '#js-delivery-address-edit-btn',
|
||||
invoiceAddressEditBtn: '#js-invoice-address-edit-btn',
|
||||
orderMessageNameSelect: '#order_message_order_message',
|
||||
orderMessagesContainer: '.js-order-messages-container',
|
||||
orderMessage: '#order_message_message',
|
||||
orderMessageChangeWarning: '.js-message-change-warning',
|
||||
orderDocumentsTabCount: '#orderDocumentsTab .count',
|
||||
orderDocumentsTabBody: '#orderDocumentsTabContent .card-body',
|
||||
orderShippingTabCount: '#orderShippingTab .count',
|
||||
orderShippingTabBody: '#orderShippingTabContent .card-body',
|
||||
allMessagesModal: '#view_all_messages_modal',
|
||||
allMessagesList: '#all-messages-list',
|
||||
openAllMessagesBtn: '.js-open-all-messages-btn',
|
||||
// Products table elements
|
||||
productOriginalPosition: '#orderProductsOriginalPosition',
|
||||
productModificationPosition: '#orderProductsModificationPosition',
|
||||
productsPanel: '#orderProductsPanel',
|
||||
productsCount: '#orderProductsPanelCount',
|
||||
productDeleteBtn: '.js-order-product-delete-btn',
|
||||
productsTable: '#orderProductsTable',
|
||||
productsPagination: '.order-product-pagination',
|
||||
productsNavPagination: '#orderProductsNavPagination',
|
||||
productsTablePagination: '#orderProductsTablePagination',
|
||||
productsTablePaginationNext: '#orderProductsTablePaginationNext',
|
||||
productsTablePaginationPrev: '#orderProductsTablePaginationPrev',
|
||||
productsTablePaginationLink: '.page-item:not(.d-none):not(#orderProductsTablePaginationNext):not(#orderProductsTablePaginationPrev) .page-link',
|
||||
productsTablePaginationActive: '#orderProductsTablePagination .page-item.active span',
|
||||
productsTablePaginationTemplate: '#orderProductsTablePagination .page-item.d-none',
|
||||
productsTablePaginationNumberSelector: '#orderProductsTablePaginationNumberSelector',
|
||||
productsTableRow: (productId) => `#orderProduct_${productId}`,
|
||||
productsTableRowEdited: (productId) => `#editOrderProduct_${productId}`,
|
||||
productsTableRows: 'tr.cellProduct',
|
||||
productsCellLocation: 'tr .cellProductLocation',
|
||||
productsCellRefunded: 'tr .cellProductRefunded',
|
||||
productsCellLocationDisplayed: 'tr:not(.d-none) .cellProductLocation',
|
||||
productsCellRefundedDisplayed: 'tr:not(.d-none) .cellProductRefunded',
|
||||
productsTableCustomizationRows: '#orderProductsTable .order-product-customization',
|
||||
productEditButtons: '.js-order-product-edit-btn',
|
||||
productEditBtn: (productId) => `#orderProduct_${productId} .js-order-product-edit-btn`,
|
||||
productAddBtn: '#addProductBtn',
|
||||
productActionBtn: '.js-product-action-btn',
|
||||
productAddActionBtn: '#add_product_row_add',
|
||||
productCancelAddBtn: '#add_product_row_cancel',
|
||||
productAddRow: '#addProductTableRow',
|
||||
productSearchInput: '#add_product_row_search',
|
||||
productSearchInputAutocomplete: '#addProductTableRow .dropdown',
|
||||
productSearchInputAutocompleteMenu: '#addProductTableRow .dropdown .dropdown-menu',
|
||||
productAddIdInput: '#add_product_row_product_id',
|
||||
productAddTaxRateInput: '#add_product_row_tax_rate',
|
||||
productAddCombinationsBlock: '#addProductCombinations',
|
||||
productAddCombinationsSelect: '#addProductCombinationId',
|
||||
productAddPriceTaxExclInput: '#add_product_row_price_tax_excluded',
|
||||
productAddPriceTaxInclInput: '#add_product_row_price_tax_included',
|
||||
productAddQuantityInput: '#add_product_row_quantity',
|
||||
productAddAvailableText: '#addProductAvailable',
|
||||
productAddLocationText: '#addProductLocation',
|
||||
productAddTotalPriceText: '#addProductTotalPrice',
|
||||
productAddInvoiceSelect: '#add_product_row_invoice',
|
||||
productAddFreeShippingSelect: '#add_product_row_free_shipping',
|
||||
productAddNewInvoiceInfo: '#addProductNewInvoiceInfo',
|
||||
productEditSaveBtn: '.productEditSaveBtn',
|
||||
productEditCancelBtn: '.productEditCancelBtn',
|
||||
productEditRowTemplate: '#editProductTableRowTemplate',
|
||||
productEditRow: '.editProductRow',
|
||||
productEditImage: '.cellProductImg',
|
||||
productEditName: '.cellProductName',
|
||||
productEditUnitPrice: '.cellProductUnitPrice',
|
||||
productEditQuantity: '.cellProductQuantity',
|
||||
productEditAvailableQuantity: '.cellProductAvailableQuantity',
|
||||
productEditTotalPrice: '.cellProductTotalPrice',
|
||||
productEditPriceTaxExclInput: '.editProductPriceTaxExcl',
|
||||
productEditPriceTaxInclInput: '.editProductPriceTaxIncl',
|
||||
productEditInvoiceSelect: '.editProductInvoice',
|
||||
productEditQuantityInput: '.editProductQuantity',
|
||||
productEditLocationText: '.editProductLocation',
|
||||
productEditAvailableText: '.editProductAvailable',
|
||||
productEditTotalPriceText: '.editProductTotalPrice',
|
||||
// Product Discount List
|
||||
productDiscountList: {
|
||||
list: '.table.discountList',
|
||||
},
|
||||
// Product Pack Modal
|
||||
productPackModal: {
|
||||
modal: '#product-pack-modal',
|
||||
table: '#product-pack-modal-table tbody',
|
||||
rows: '#product-pack-modal-table tbody tr:not(#template-pack-table-row)',
|
||||
template: '#template-pack-table-row',
|
||||
product: {
|
||||
img: '.cell-product-img img',
|
||||
link: '.cell-product-name a',
|
||||
name: '.cell-product-name .product-name',
|
||||
ref: '.cell-product-name .product-reference',
|
||||
supplierRef: '.cell-product-name .product-supplier-reference',
|
||||
quantity: '.cell-product-quantity',
|
||||
availableQuantity: '.cell-product-available-quantity',
|
||||
},
|
||||
},
|
||||
// Order price elements
|
||||
orderProductsTotal: '#orderProductsTotal',
|
||||
orderDiscountsTotalContainer: '#order-discounts-total-container',
|
||||
orderDiscountsTotal: '#orderDiscountsTotal',
|
||||
orderWrappingTotal: '#orderWrappingTotal',
|
||||
orderShippingTotalContainer: '#order-shipping-total-container',
|
||||
orderShippingTotal: '#orderShippingTotal',
|
||||
orderTaxesTotal: '#orderTaxesTotal',
|
||||
orderTotal: '#orderTotal',
|
||||
orderHookTabsContainer: '#order_hook_tabs',
|
||||
// Product cancel/refund elements
|
||||
cancelProduct: {
|
||||
form: 'form[name="cancel_product"]',
|
||||
buttons: {
|
||||
abort: 'button.cancel-product-element-abort',
|
||||
save: '#cancel_product_save',
|
||||
partialRefund: 'button.partial-refund-display',
|
||||
standardRefund: 'button.standard-refund-display',
|
||||
returnProduct: 'button.return-product-display',
|
||||
cancelProducts: 'button.cancel-product-display',
|
||||
},
|
||||
inputs: {
|
||||
quantity: '.cancel-product-quantity input',
|
||||
amount: '.cancel-product-amount input',
|
||||
selector: '.cancel-product-selector input',
|
||||
},
|
||||
table: {
|
||||
cell: '.cancel-product-cell',
|
||||
header: 'th.cancel-product-element p',
|
||||
actions: 'td.cellProductActions, th.product_actions',
|
||||
},
|
||||
checkboxes: {
|
||||
restock: '#cancel_product_restock',
|
||||
creditSlip: '#cancel_product_credit_slip',
|
||||
voucher: '#cancel_product_voucher',
|
||||
},
|
||||
radios: {
|
||||
voucherRefundType: {
|
||||
productPrices: 'input[voucher-refund-type="0"]',
|
||||
productPricesVoucherExcluded: 'input[voucher-refund-type="1"]',
|
||||
negativeErrorMessage: '.voucher-refund-type-negative-error',
|
||||
},
|
||||
},
|
||||
toggle: {
|
||||
partialRefund: '.cancel-product-element:not(.hidden):not(.shipping-refund), .cancel-product-amount',
|
||||
standardRefund: '.cancel-product-element:not(.hidden):not(.shipping-refund-amount):not(.restock-products), .cancel-product-selector',
|
||||
returnProduct: '.cancel-product-element:not(.hidden):not(.shipping-refund-amount), .cancel-product-selector',
|
||||
cancelProducts: '.cancel-product-element:not(.hidden):not(.shipping-refund-amount):not(.shipping-refund):not(.restock-products):not(.refund-credit-slip):not(.refund-voucher):not(.voucher-refund-type), .cancel-product-selector',
|
||||
},
|
||||
},
|
||||
printOrderViewPageButton: '.js-print-order-view-page',
|
||||
orderNoteToggleBtn: '.js-order-notes-toggle-btn',
|
||||
orderNoteBlock: '.js-order-notes-block',
|
||||
orderNoteInput: '#internal_note_note',
|
||||
orderNoteSubmitBtn: '.js-order-notes-btn',
|
||||
refreshProductsListLoadingSpinner: '#orderProductsPanel .spinner-order-products-container#orderProductsLoading',
|
||||
};
|
||||
70
admin-kalsport/themes/new-theme/js/pages/order/create.js
Normal file
70
admin-kalsport/themes/new-theme/js/pages/order/create.js
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 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 CreateOrderPage from './create/create-order-page';
|
||||
|
||||
const {$} = window;
|
||||
let orderPageManager = null;
|
||||
|
||||
/**
|
||||
* proxy to allow other scripts within the page to trigger the search
|
||||
* @param string
|
||||
*/
|
||||
function searchCustomerByString(string) {
|
||||
if (orderPageManager !== null) {
|
||||
orderPageManager.search(string);
|
||||
} else {
|
||||
console.log('Error: Could not search customer as orderPageManager is null');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* proxy to allow other scripts within the page to refresh addresses list
|
||||
*/
|
||||
function refreshAddressesList(refreshCartAddresses) {
|
||||
if (orderPageManager !== null) {
|
||||
orderPageManager.refreshAddressesList(refreshCartAddresses);
|
||||
} else {
|
||||
console.log('Error: Could not refresh addresses list as orderPageManager is null');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* proxy to allow other scripts within the Create Order page to refresh cart
|
||||
*/
|
||||
function refreshCart() {
|
||||
if (orderPageManager === null) {
|
||||
console.log('Error: Could not refresh addresses list as orderPageManager is null');
|
||||
return;
|
||||
}
|
||||
orderPageManager.refreshCart();
|
||||
}
|
||||
|
||||
$(document).ready(() => {
|
||||
orderPageManager = new CreateOrderPage();
|
||||
});
|
||||
|
||||
export {searchCustomerByString};
|
||||
export {refreshAddressesList};
|
||||
export {refreshCart};
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export const ValidateAddresses = (addresses) => {
|
||||
let deliveryValid = false;
|
||||
let invoiceValid = false;
|
||||
|
||||
addresses.forEach((address) => {
|
||||
if (address.delivery) {
|
||||
deliveryValid = true;
|
||||
}
|
||||
|
||||
if (address.invoice) {
|
||||
invoiceValid = true;
|
||||
}
|
||||
});
|
||||
|
||||
return deliveryValid && invoiceValid;
|
||||
};
|
||||
|
||||
export default ValidateAddresses;
|
||||
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* 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 createOrderMap from './create-order-map';
|
||||
import Router from '../../../components/router';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* Renders Delivery & Invoice addresses select
|
||||
*/
|
||||
export default class AddressesRenderer {
|
||||
constructor() {
|
||||
this.router = new Router();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array} addresses
|
||||
* @param {int} cartId
|
||||
*/
|
||||
render(addresses, cartId) {
|
||||
this.cleanAddresses();
|
||||
if (addresses.length === 0) {
|
||||
this.hideAddressesContent();
|
||||
this.showEmptyAddressesWarning();
|
||||
this.showAddressesBlock();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.showAddressesContent();
|
||||
this.hideEmptyAddressesWarning();
|
||||
|
||||
Object.values(addresses).forEach((address) => {
|
||||
this.renderDeliveryAddress(address, cartId);
|
||||
this.renderInvoiceAddress(address, cartId);
|
||||
});
|
||||
|
||||
this.showAddressesBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders delivery address content
|
||||
*
|
||||
* @param address
|
||||
* @param cartId
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderDeliveryAddress(address, cartId) {
|
||||
const deliveryAddressOption = {
|
||||
value: address.addressId,
|
||||
text: address.alias,
|
||||
};
|
||||
|
||||
if (address.delivery) {
|
||||
$(createOrderMap.deliveryAddressDetails).html(address.formattedAddress);
|
||||
deliveryAddressOption.selected = 'selected';
|
||||
$(createOrderMap.deliveryAddressEditBtn).prop('href', this.router.generate('admin_cart_addresses_edit', {
|
||||
addressId: address.addressId,
|
||||
cartId,
|
||||
addressType: 'delivery',
|
||||
liteDisplaying: 1,
|
||||
submitFormAjax: 1,
|
||||
}));
|
||||
}
|
||||
|
||||
$(createOrderMap.deliveryAddressSelect).append($('<option>', deliveryAddressOption));
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders invoice address content
|
||||
*
|
||||
* @param address
|
||||
* @param cartId
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderInvoiceAddress(address, cartId) {
|
||||
const invoiceAddressOption = {
|
||||
value: address.addressId,
|
||||
text: address.alias,
|
||||
};
|
||||
|
||||
if (address.invoice) {
|
||||
$(createOrderMap.invoiceAddressDetails).html(address.formattedAddress);
|
||||
invoiceAddressOption.selected = 'selected';
|
||||
$(createOrderMap.invoiceAddressEditBtn).prop('href', this.router.generate('admin_cart_addresses_edit', {
|
||||
addressId: address.addressId,
|
||||
cartId,
|
||||
addressType: 'invoice',
|
||||
liteDisplaying: 1,
|
||||
submitFormAjax: 1,
|
||||
}));
|
||||
}
|
||||
|
||||
$(createOrderMap.invoiceAddressSelect).append($('<option>', invoiceAddressOption));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows addresses block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showAddressesBlock() {
|
||||
$(createOrderMap.addressesBlock).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties addresses content
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
cleanAddresses() {
|
||||
$(createOrderMap.deliveryAddressDetails).empty();
|
||||
$(createOrderMap.deliveryAddressSelect).empty();
|
||||
$(createOrderMap.invoiceAddressDetails).empty();
|
||||
$(createOrderMap.invoiceAddressSelect).empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows addresses content and hides warning
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showAddressesContent() {
|
||||
$(createOrderMap.addressesContent).removeClass('d-none');
|
||||
$(createOrderMap.addressesWarning).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides addresses content and shows warning
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideAddressesContent() {
|
||||
$(createOrderMap.addressesContent).addClass('d-none');
|
||||
$(createOrderMap.addressesWarning).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows warning empty addresses warning
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showEmptyAddressesWarning() {
|
||||
$(createOrderMap.addressesWarning).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides empty addresses warning
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideEmptyAddressesWarning() {
|
||||
$(createOrderMap.addressesWarning).addClass('d-none');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/**
|
||||
* 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 eventMap from '@pages/order/create/event-map';
|
||||
import createOrderMap from './create-order-map';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* Provides ajax calls for cart editing actions
|
||||
* Each method emits an event with updated cart information after success.
|
||||
*/
|
||||
export default class CartEditor {
|
||||
constructor() {
|
||||
this.router = new Router();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes cart addresses
|
||||
*
|
||||
* @param {Number} cartId
|
||||
* @param {Object} addresses
|
||||
*/
|
||||
changeCartAddresses(cartId, addresses) {
|
||||
$.post(this.router.generate('admin_carts_edit_addresses', {cartId}), addresses)
|
||||
.then((cartInfo) => EventEmitter.emit(eventMap.cartAddressesChanged, cartInfo))
|
||||
.catch((response) => window.showErrorMessage(response.responseJSON.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies cart delivery option
|
||||
*
|
||||
* @param {Number} cartId
|
||||
* @param {Number} value
|
||||
*/
|
||||
changeDeliveryOption(cartId, value) {
|
||||
$.post(this.router.generate('admin_carts_edit_carrier', {cartId}), {
|
||||
carrierId: value,
|
||||
}).then((cartInfo) => EventEmitter.emit(eventMap.cartDeliveryOptionChanged, cartInfo))
|
||||
.catch((response) => window.showErrorMessage(response.responseJSON.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes cart free shipping value
|
||||
*
|
||||
* @param {Number} cartId
|
||||
*/
|
||||
updateDeliveryOptions(cartId) {
|
||||
const freeShippingEnabled = $(createOrderMap.freeShippingSwitch)[1].checked;
|
||||
const isAGiftEnabled = $(createOrderMap.isAGiftSwitchValue).val() === '1';
|
||||
const useRecycledPackagingEnabled = $(createOrderMap.recycledPackagingSwitchValue).val() === '1';
|
||||
const giftMessage = $(createOrderMap.giftMessageField).val();
|
||||
|
||||
$.post(this.router.generate('admin_carts_set_delivery_settings', {cartId}), {
|
||||
freeShipping: freeShippingEnabled,
|
||||
isAGift: isAGiftEnabled,
|
||||
useRecycledPackaging: useRecycledPackagingEnabled,
|
||||
giftMessage,
|
||||
}).then((cartInfo) => EventEmitter.emit(eventMap.cartDeliverySettingChanged, cartInfo))
|
||||
.catch((response) => window.showErrorMessage(response.responseJSON.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds cart rule to cart
|
||||
*
|
||||
* @param {Number} cartRuleId
|
||||
* @param {Number} cartId
|
||||
*/
|
||||
addCartRuleToCart(cartRuleId, cartId) {
|
||||
$.post(this.router.generate('admin_carts_add_cart_rule', {cartId}), {
|
||||
cartRuleId,
|
||||
}).then((cartInfo) => EventEmitter.emit(eventMap.cartRuleAdded, cartInfo))
|
||||
.catch((response) => EventEmitter.emit(eventMap.cartRuleFailedToAdd, response.responseJSON.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes cart rule from cart
|
||||
*
|
||||
* @param {Number} cartRuleId
|
||||
* @param {Number} cartId
|
||||
*/
|
||||
removeCartRuleFromCart(cartRuleId, cartId) {
|
||||
$.post(this.router.generate('admin_carts_delete_cart_rule', {
|
||||
cartId,
|
||||
cartRuleId,
|
||||
})).then((cartInfo) => EventEmitter.emit(eventMap.cartRuleRemoved, cartInfo))
|
||||
.catch((response) => window.showErrorMessage(response.responseJSON.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds product to cart
|
||||
*
|
||||
* @param {Number} cartId
|
||||
* @param {Object} data
|
||||
*/
|
||||
addProduct(cartId, data) {
|
||||
let fileSizeHeader = '';
|
||||
|
||||
if (!$.isEmptyObject(data.fileSizes)) {
|
||||
fileSizeHeader = JSON.stringify(data.fileSizes);
|
||||
}
|
||||
|
||||
$.ajax(this.router.generate('admin_carts_add_product', {cartId}), {
|
||||
headers: {
|
||||
// Adds custom headers with submitted file sizes, to track if all files reached server side.
|
||||
'file-sizes': fileSizeHeader,
|
||||
},
|
||||
method: 'POST',
|
||||
data: data.product,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
}).then((cartInfo) => EventEmitter.emit(eventMap.productAddedToCart, cartInfo))
|
||||
.catch((response) => EventEmitter.emit(eventMap.productAddToCartFailed, response.responseJSON.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes product from cart
|
||||
*
|
||||
* @param {Number} cartId
|
||||
* @param {Object} product
|
||||
*/
|
||||
removeProductFromCart(cartId, product) {
|
||||
$.post(this.router.generate('admin_carts_delete_product', {cartId}), {
|
||||
productId: product.productId,
|
||||
attributeId: product.attributeId,
|
||||
customizationId: product.customizationId,
|
||||
}).then((cartInfo) => EventEmitter.emit(eventMap.productRemovedFromCart, {cartInfo, product}))
|
||||
.catch((response) => window.showErrorMessage(response.responseJSON.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes product price in cart
|
||||
*
|
||||
* @param {Number} cartId
|
||||
* @param {Number} customerId
|
||||
* @param {Object} product the updated product
|
||||
*/
|
||||
changeProductPrice(cartId, customerId, product) {
|
||||
$.post(this.router.generate('admin_carts_edit_product_price', {
|
||||
cartId,
|
||||
productId: product.productId,
|
||||
productAttributeId: product.attributeId,
|
||||
}), {
|
||||
newPrice: product.price,
|
||||
customerId,
|
||||
}).then((cartInfo) => EventEmitter.emit(eventMap.productPriceChanged, cartInfo))
|
||||
.catch((response) => window.showErrorMessage(response.responseJSON.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates product quantity in cart
|
||||
*
|
||||
* @param cartId
|
||||
* @param product
|
||||
*/
|
||||
changeProductQty(cartId, product) {
|
||||
$.post(this.router.generate('admin_carts_edit_product_quantity', {
|
||||
cartId,
|
||||
productId: product.productId,
|
||||
}), {
|
||||
newQty: product.newQty,
|
||||
attributeId: product.attributeId,
|
||||
customizationId: product.customizationId,
|
||||
}).then((cartInfo) => EventEmitter.emit(eventMap.productQtyChanged, {cartInfo, product}))
|
||||
.catch((response) => EventEmitter.emit(eventMap.productQtyChangeFailed, response));
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes cart currency
|
||||
*
|
||||
* @param {Number} cartId
|
||||
* @param {Number} currencyId
|
||||
*/
|
||||
changeCartCurrency(cartId, currencyId) {
|
||||
$(createOrderMap.cartCurrencySelect).data('selectedCurrencyId', currencyId);
|
||||
|
||||
$.post(this.router.generate('admin_carts_edit_currency', {cartId}), {
|
||||
currencyId,
|
||||
}).then((cartInfo) => EventEmitter.emit(eventMap.cartCurrencyChanged, cartInfo))
|
||||
.catch((response) => EventEmitter.emit(eventMap.cartCurrencyChangeFailed, response));
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes cart language
|
||||
*
|
||||
* @param {Number} cartId
|
||||
* @param {Number} languageId
|
||||
*/
|
||||
changeCartLanguage(cartId, languageId) {
|
||||
$.post(this.router.generate('admin_carts_edit_language', {cartId}), {
|
||||
languageId,
|
||||
}).then((cartInfo) => EventEmitter.emit(eventMap.cartLanguageChanged, cartInfo))
|
||||
.catch((response) => window.showErrorMessage(response.responseJSON.message));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* 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 createOrderPageMap from '@pages/order/create/create-order-map';
|
||||
import Router from '@components/router';
|
||||
import {EventEmitter} from '@components/event-emitter';
|
||||
import eventMap from '@pages/order/create/event-map';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* Provides ajax calls for getting cart information
|
||||
*/
|
||||
export default class CartProvider {
|
||||
constructor() {
|
||||
this.$container = $(createOrderPageMap.orderCreationContainer);
|
||||
this.router = new Router();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets cart information
|
||||
*
|
||||
* @param cartId
|
||||
*
|
||||
* @returns {jqXHR}. Object with cart information in response.
|
||||
*/
|
||||
getCart(cartId) {
|
||||
$.get(this.router.generate('admin_carts_info', {cartId})).then((cartInfo) => {
|
||||
EventEmitter.emit(eventMap.cartLoaded, cartInfo);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets existing empty cart or creates new empty cart for customer.
|
||||
*
|
||||
* @param customerId
|
||||
*
|
||||
* @returns {jqXHR}. Object with cart information in response
|
||||
*/
|
||||
loadEmptyCart(customerId) {
|
||||
$.post(this.router.generate('admin_carts_create'), {
|
||||
customerId,
|
||||
}).then((cartInfo) => {
|
||||
EventEmitter.emit(eventMap.cartLoaded, cartInfo);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates cart from provided order
|
||||
*
|
||||
* @param orderId
|
||||
*
|
||||
* @returns {jqXHR}. Object with cart information in response
|
||||
*/
|
||||
duplicateOrderCart(orderId) {
|
||||
$.post(this.router.generate('admin_orders_duplicate_cart', {orderId})).then((cartInfo) => {
|
||||
EventEmitter.emit(eventMap.cartLoaded, cartInfo);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* 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 CartEditor from '@pages/order/create/cart-editor';
|
||||
import CartRulesRenderer from '@pages/order/create/cart-rules-renderer';
|
||||
import {EventEmitter} from '@components/event-emitter';
|
||||
import eventMap from '@pages/order/create/event-map';
|
||||
import Router from '@components/router';
|
||||
import SummaryRenderer from '@pages/order/create/summary-renderer';
|
||||
import ShippingRenderer from '@pages/order/create/shipping-renderer';
|
||||
import ProductRenderer from '@pages/order/create/product-renderer';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* Responsible for searching cart rules and managing cart rules search block
|
||||
*/
|
||||
export default class CartRuleManager {
|
||||
constructor() {
|
||||
this.activeSearchRequest = null;
|
||||
|
||||
this.router = new Router();
|
||||
this.cartRulesRenderer = new CartRulesRenderer();
|
||||
this.cartEditor = new CartEditor();
|
||||
this.summaryRenderer = new SummaryRenderer();
|
||||
this.shippingRenderer = new ShippingRenderer();
|
||||
this.productRenderer = new ProductRenderer();
|
||||
|
||||
this.initListeners();
|
||||
|
||||
return {
|
||||
search: (searchPhrase) => this.search(searchPhrase),
|
||||
stopSearching: () => this.cartRulesRenderer.hideResultsDropdown(),
|
||||
addCartRuleToCart: (cartRuleId, cartId) => this.cartEditor.addCartRuleToCart(cartRuleId, cartId),
|
||||
removeCartRuleFromCart: (cartRuleId, cartId) => this.cartEditor.removeCartRuleFromCart(cartRuleId, cartId),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates event listeners for cart rule actions
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
initListeners() {
|
||||
this.onCartRuleSearch();
|
||||
this.onAddCartRuleToCart();
|
||||
this.onAddCartRuleToCartFailure();
|
||||
this.onRemoveCartRuleFromCart();
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for cart rule search action
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onCartRuleSearch() {
|
||||
EventEmitter.on(eventMap.cartRuleSearched, (cartRules) => {
|
||||
this.cartRulesRenderer.renderSearchResults(cartRules);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens event of add cart rule to cart action
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onAddCartRuleToCart() {
|
||||
EventEmitter.on(eventMap.cartRuleAdded, (cartInfo) => {
|
||||
const cartIsEmpty = cartInfo.products.length === 0;
|
||||
this.cartRulesRenderer.renderCartRulesBlock(cartInfo.cartRules, cartIsEmpty);
|
||||
this.productRenderer.renderList(cartInfo.products);
|
||||
this.shippingRenderer.render(cartInfo.shipping, cartIsEmpty);
|
||||
this.summaryRenderer.render(cartInfo);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens event when add cart rule to cart fails
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onAddCartRuleToCartFailure() {
|
||||
EventEmitter.on(eventMap.cartRuleFailedToAdd, (message) => {
|
||||
this.cartRulesRenderer.displayErrorMessage(message);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens event for remove cart rule from cart action
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onRemoveCartRuleFromCart() {
|
||||
EventEmitter.on(eventMap.cartRuleRemoved, (cartInfo) => {
|
||||
const cartIsEmpty = cartInfo.products.length === 0;
|
||||
this.shippingRenderer.render(cartInfo.shipping, cartIsEmpty);
|
||||
this.cartRulesRenderer.renderCartRulesBlock(cartInfo.cartRules, cartIsEmpty);
|
||||
this.summaryRenderer.render(cartInfo);
|
||||
this.productRenderer.renderList(cartInfo.products);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for cart rules by search phrase
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
search(searchPhrase) {
|
||||
if (this.activeSearchRequest !== null) {
|
||||
this.activeSearchRequest.abort();
|
||||
}
|
||||
|
||||
this.activeSearchRequest = $.get(this.router.generate('admin_cart_rules_search'), {
|
||||
search_phrase: searchPhrase,
|
||||
});
|
||||
|
||||
this.activeSearchRequest.then((cartRules) => {
|
||||
EventEmitter.emit(eventMap.cartRuleSearched, cartRules);
|
||||
}).catch((e) => {
|
||||
if (e.statusText === 'abort') {
|
||||
return;
|
||||
}
|
||||
|
||||
window.showErrorMessage(e.responseJSON.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* 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 createOrderMap from './create-order-map';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* Renders cart rules (cartRules) block
|
||||
*/
|
||||
export default class CartRulesRenderer {
|
||||
constructor() {
|
||||
this.$cartRulesBlock = $(createOrderMap.cartRulesBlock);
|
||||
this.$cartRulesTable = $(createOrderMap.cartRulesTable);
|
||||
this.$searchResultBox = $(createOrderMap.cartRulesSearchResultBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for rendering cartRules (a.k.a cart rules/discounts) block
|
||||
*
|
||||
* @param {Array} cartRules
|
||||
* @param {Boolean} emptyCart
|
||||
*/
|
||||
renderCartRulesBlock(cartRules, emptyCart) {
|
||||
this.hideErrorBlock();
|
||||
// do not render cart rules block at all if cart has no products
|
||||
if (emptyCart) {
|
||||
this.hideCartRulesBlock();
|
||||
return;
|
||||
}
|
||||
this.showCartRulesBlock();
|
||||
|
||||
// do not render cart rules list when there are no cart rules
|
||||
if (cartRules.length === 0) {
|
||||
this.hideCartRulesList();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.renderList(cartRules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for rendering search results dropdown
|
||||
*
|
||||
* @param searchResults
|
||||
*/
|
||||
renderSearchResults(searchResults) {
|
||||
this.clearSearchResults();
|
||||
|
||||
if (searchResults.cart_rules.length === 0) {
|
||||
this.renderNotFound();
|
||||
} else {
|
||||
this.renderFoundCartRules(searchResults.cart_rules);
|
||||
}
|
||||
|
||||
this.showResultsDropdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays error message bellow search input
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
displayErrorMessage(message) {
|
||||
$(createOrderMap.cartRuleErrorText).text(message);
|
||||
this.showErrorBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides cart rules search result dropdown
|
||||
*/
|
||||
hideResultsDropdown() {
|
||||
this.$searchResultBox.addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays cart rules search result dropdown
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showResultsDropdown() {
|
||||
this.$searchResultBox.removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders warning that no cart rule was found
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderNotFound() {
|
||||
const $template = $($(createOrderMap.cartRulesNotFoundTemplate).html()).clone();
|
||||
this.$searchResultBox.html($template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties cart rule search results block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
clearSearchResults() {
|
||||
this.$searchResultBox.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders found cart rules after search
|
||||
*
|
||||
* @param cartRules
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderFoundCartRules(cartRules) {
|
||||
const $cartRuleTemplate = $($(createOrderMap.foundCartRuleTemplate).html());
|
||||
Object.values(cartRules).forEach((cartRule) => {
|
||||
const $template = $cartRuleTemplate.clone();
|
||||
|
||||
let cartRuleName = cartRule.name;
|
||||
|
||||
if (cartRule.code !== '') {
|
||||
cartRuleName = `${cartRule.name} - ${cartRule.code}`;
|
||||
}
|
||||
|
||||
$template.text(cartRuleName);
|
||||
$template.data('cart-rule-id', cartRule.cartRuleId);
|
||||
this.$searchResultBox.append($template);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for rendering the list of cart rules
|
||||
*
|
||||
* @param {Array} cartRules
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderList(cartRules) {
|
||||
this.cleanCartRulesList();
|
||||
const $cartRulesTableRowTemplate = $($(createOrderMap.cartRulesTableRowTemplate).html());
|
||||
|
||||
Object.values(cartRules).forEach((cartRule) => {
|
||||
const $template = $cartRulesTableRowTemplate.clone();
|
||||
|
||||
$template.find(createOrderMap.cartRuleNameField).text(cartRule.name);
|
||||
$template.find(createOrderMap.cartRuleDescriptionField).text(cartRule.description);
|
||||
$template.find(createOrderMap.cartRuleValueField).text(cartRule.value);
|
||||
$template.find(createOrderMap.cartRuleDeleteBtn).data('cart-rule-id', cartRule.cartRuleId);
|
||||
|
||||
this.$cartRulesTable.find('tbody').append($template);
|
||||
});
|
||||
|
||||
this.showCartRulesList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows error block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showErrorBlock() {
|
||||
$(createOrderMap.cartRuleErrorBlock).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides error block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideErrorBlock() {
|
||||
$(createOrderMap.cartRuleErrorBlock).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows cartRules block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showCartRulesBlock() {
|
||||
this.$cartRulesBlock.removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* hide cartRules block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideCartRulesBlock() {
|
||||
this.$cartRulesBlock.addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the list block of cart rules
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showCartRulesList() {
|
||||
this.$cartRulesTable.removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide list block of cart rules
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideCartRulesList() {
|
||||
this.$cartRulesTable.addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* remove items in cart rules list
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
cleanCartRulesList() {
|
||||
this.$cartRulesTable.find('tbody').empty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Encapsulates selectors for "Create order" page
|
||||
*/
|
||||
export default {
|
||||
productCustomizationFieldTypeFile: 0,
|
||||
productCustomizationFieldTypeText: 1,
|
||||
|
||||
orderCreationContainer: '#order-creation-container',
|
||||
requiredFieldMark: '.js-required-field-mark',
|
||||
cartInfoWrapper: '#js-cart-info-wrapper',
|
||||
|
||||
// selectors related to customer block
|
||||
customerSearchInput: '#customer-search-input',
|
||||
customerSearchResultsBlock: '.js-customer-search-results',
|
||||
customerSearchResultTemplate: '#customer-search-result-template',
|
||||
customerSearchEmptyResultWarning: '#customer-search-empty-result-warn',
|
||||
customerSearchLoadingNotice: '#customer-search-loading-notice',
|
||||
customerAddBtn: '#customer-add-btn',
|
||||
changeCustomerBtn: '.js-change-customer-btn',
|
||||
customerSearchRow: '.js-search-customer-row',
|
||||
chooseCustomerBtn: '.js-choose-customer-btn',
|
||||
notSelectedCustomerSearchResults: '.js-customer-search-result:not(.border-success)',
|
||||
customerSearchResultName: '.js-customer-name',
|
||||
customerSearchResultEmail: '.js-customer-email',
|
||||
customerSearchResultId: '.js-customer-id',
|
||||
customerSearchResultBirthday: '.js-customer-birthday',
|
||||
customerDetailsBtn: '.js-details-customer-btn',
|
||||
customerSearchResultColumn: '.js-customer-search-result-col',
|
||||
customerSearchBlock: '#customer-search-block',
|
||||
customerCartsTab: '.js-customer-carts-tab',
|
||||
customerOrdersTab: '.js-customer-orders-tab',
|
||||
customerCartsTable: '#customer-carts-table',
|
||||
customerCartsTableRowTemplate: '#customer-carts-table-row-template',
|
||||
customerCheckoutHistory: '#customer-checkout-history',
|
||||
customerOrdersTable: '#customer-orders-table',
|
||||
customerOrdersTableRowTemplate: '#customer-orders-table-row-template',
|
||||
cartRulesTable: '#cart-rules-table',
|
||||
cartRulesTableRowTemplate: '#cart-rules-table-row-template',
|
||||
useCartBtn: '.js-use-cart-btn',
|
||||
cartDetailsBtn: '.js-cart-details-btn',
|
||||
cartIdField: '.js-cart-id',
|
||||
cartDateField: '.js-cart-date',
|
||||
cartTotalField: '.js-cart-total',
|
||||
useOrderBtn: '.js-use-order-btn',
|
||||
orderDetailsBtn: '.js-order-details-btn',
|
||||
orderIdField: '.js-order-id',
|
||||
orderDateField: '.js-order-date',
|
||||
orderProductsField: '.js-order-products',
|
||||
orderTotalField: '.js-order-total-paid',
|
||||
orderPaymentMethod: '.js-order-payment-method',
|
||||
orderStatusField: '.js-order-status',
|
||||
emptyListRowTemplate: '#js-empty-list-row',
|
||||
loadingListRowTemplate: '#js-loading-list-row',
|
||||
emptyListRow: '.js-empty-row',
|
||||
|
||||
// selectors related to cartRules block
|
||||
cartRulesBlock: '#cart-rules-block',
|
||||
cartRuleSearchInput: '#search-cart-rules-input',
|
||||
cartRulesSearchResultBox: '#search-cart-rules-result-box',
|
||||
cartRulesNotFoundTemplate: '#cart-rules-not-found-template',
|
||||
foundCartRuleTemplate: '#found-cart-rule-template',
|
||||
foundCartRuleListItem: '.js-found-cart-rule',
|
||||
cartRuleNameField: '.js-cart-rule-name',
|
||||
cartRuleDescriptionField: '.js-cart-rule-description',
|
||||
cartRuleValueField: '.js-cart-rule-value',
|
||||
cartRuleDeleteBtn: '.js-cart-rule-delete-btn',
|
||||
cartRuleErrorBlock: '#js-cart-rule-error-block',
|
||||
cartRuleErrorText: '#js-cart-rule-error-text',
|
||||
|
||||
// selectors related to addresses block
|
||||
addressesBlock: '#addresses-block',
|
||||
deliveryAddressDetails: '#delivery-address-details',
|
||||
invoiceAddressDetails: '#invoice-address-details',
|
||||
deliveryAddressSelect: '#delivery-address-select',
|
||||
invoiceAddressSelect: '#invoice-address-select',
|
||||
addressSelect: '.js-address-select',
|
||||
addressesContent: '#addresses-content',
|
||||
addressesWarning: '#addresses-warning',
|
||||
deliveryAddressEditBtn: '#js-delivery-address-edit-btn',
|
||||
invoiceAddressEditBtn: '#js-invoice-address-edit-btn',
|
||||
addressAddBtn: '#js-add-address-btn',
|
||||
|
||||
// selectors related to summary block
|
||||
summaryBlock: '#summary-block',
|
||||
summaryTotalProducts: '.js-total-products',
|
||||
summaryTotalDiscount: '.js-total-discounts',
|
||||
summaryTotalShipping: '.js-total-shipping',
|
||||
summaryTotalTaxes: '.js-total-taxes',
|
||||
summaryTotalWithoutTax: '.js-total-without-tax',
|
||||
summaryTotalWithTax: '.js-total-with-tax',
|
||||
placeOrderCartIdField: '.js-place-order-cart-id',
|
||||
processOrderLinkTag: '#js-process-order-link',
|
||||
orderMessageField: '#js-order-message-wrap textarea',
|
||||
sendProcessOrderEmailBtn: '#js-send-process-order-email-btn',
|
||||
summarySuccessAlertBlock: '#js-summary-success-block',
|
||||
summaryErrorAlertBlock: '#js-summary-error-block',
|
||||
summarySuccessAlertText: '#js-summary-success-block .alert-text',
|
||||
summaryErrorAlertText: '#js-summary-error-block .alert-text',
|
||||
|
||||
// selectors related to shipping block
|
||||
shippingBlock: '#shipping-block',
|
||||
shippingForm: '.js-shipping-form',
|
||||
noCarrierBlock: '.js-no-carrier-block',
|
||||
deliveryOptionSelect: '#delivery-option-select',
|
||||
totalShippingField: '.js-total-shipping-tax-inc',
|
||||
freeShippingSwitch: '.js-free-shipping-switch',
|
||||
recycledPackagingSwitch: '.js-recycled-packaging-switch',
|
||||
recycledPackagingSwitchValue: '.js-recycled-packaging-switch:checked',
|
||||
isAGiftSwitch: '.js-is-gift-switch',
|
||||
isAGiftSwitchValue: '.js-is-gift-switch:checked',
|
||||
giftMessageField: '#cart_gift_message',
|
||||
|
||||
// selectors related to cart block
|
||||
cartBlock: '#cart-block',
|
||||
cartCurrencySelect: '#js-cart-currency-select',
|
||||
cartLanguageSelect: '#js-cart-language-select',
|
||||
productSearch: '#product-search',
|
||||
combinationsSelect: '#combination-select',
|
||||
productResultBlock: '#product-search-results',
|
||||
productSelect: '#product-select',
|
||||
quantityInput: '#quantity-input',
|
||||
inStockCounter: '.js-in-stock-counter',
|
||||
combinationsTemplate: '#combinations-template',
|
||||
combinationsRow: '.js-combinations-row',
|
||||
productSelectRow: '.js-product-select-row',
|
||||
productCustomFieldsContainer: '#js-custom-fields-container',
|
||||
productCustomizationContainer: '#js-customization-container',
|
||||
productCustomFileTemplate: '#js-product-custom-file-template',
|
||||
productCustomTextTemplate: '#js-product-custom-text-template',
|
||||
productCustomInputLabel: '.js-product-custom-input-label',
|
||||
productCustomInput: '.js-product-custom-input',
|
||||
quantityRow: '.js-quantity-row',
|
||||
addToCartButton: '#add-product-to-cart-btn',
|
||||
productsTable: '#products-table',
|
||||
productsTableRowTemplate: '#products-table-row-template',
|
||||
productsTableGiftRowTemplate: '#products-table-gift-row-template',
|
||||
listedProductImageField: '.js-product-image',
|
||||
listedProductNameField: '.js-product-name',
|
||||
listedProductAttrField: '.js-product-attr',
|
||||
listedProductReferenceField: '.js-product-ref',
|
||||
listedProductUnitPriceInput: '.js-product-unit-input',
|
||||
listedProductQtyInput: '.js-product-qty-input',
|
||||
listedProductQtyStock: '.js-product-qty-stock',
|
||||
listedProductGiftQty: '.js-product-gift-qty',
|
||||
productTotalPriceField: '.js-product-total-price',
|
||||
listedProductCustomizedTextTemplate: '#js-table-product-customized-text-template',
|
||||
listedProductCustomizedFileTemplate: '#js-table-product-customized-file-template',
|
||||
listedProductCustomizationName: '.js-customization-name',
|
||||
listedProductCustomizationValue: '.js-customization-value',
|
||||
listedProductDefinition: '.js-product-definition-td',
|
||||
productRemoveBtn: '.js-product-remove-btn',
|
||||
productTaxWarning: '.js-tax-warning',
|
||||
noProductsFoundWarning: '.js-no-products-found',
|
||||
searchingProductsNotice: '.js-searching-products',
|
||||
productAddForm: '#js-add-product-form',
|
||||
cartErrorAlertBlock: '#js-cart-error-block',
|
||||
cartErrorAlertText: '#js-cart-error-block .alert-text',
|
||||
createOrderButton: '#create-order-button',
|
||||
};
|
||||
@@ -0,0 +1,644 @@
|
||||
/**
|
||||
* 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 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;
|
||||
|
||||
/**
|
||||
* Page Object for "Create order" page
|
||||
*/
|
||||
export default class CreateOrderPage {
|
||||
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.initListeners();
|
||||
this.loadCartFromUrlParams();
|
||||
|
||||
return {
|
||||
refreshAddressesList: (refreshCartAddresses) => this.refreshAddressesList(refreshCartAddresses),
|
||||
refreshCart: (refreshCart) => this.refreshCart(refreshCart),
|
||||
search: (string) => this.customerManager.search(string),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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() {
|
||||
$(createOrderMap.cartInfoWrapper).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows whole cart information wrapper
|
||||
*/
|
||||
showCartInfo() {
|
||||
$(createOrderMap.cartInfoWrapper).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads cart if query params contains valid cartId
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
loadCartFromUrlParams() {
|
||||
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
|
||||
*/
|
||||
initListeners() {
|
||||
this.$container.on('input', createOrderMap.customerSearchInput, (e) => this.initCustomerSearch(e));
|
||||
this.$container.on('click', createOrderMap.chooseCustomerBtn, (e) => this.initCustomerSelect(e));
|
||||
this.$container.on('click', createOrderMap.useCartBtn, (e) => this.initCartSelect(e));
|
||||
this.$container.on('click', createOrderMap.useOrderBtn, (e) => this.initDuplicateOrderCart(e));
|
||||
this.$container.on('input', createOrderMap.productSearch, (e) => this.initProductSearch(e));
|
||||
this.$container.on('input', createOrderMap.cartRuleSearchInput, (e) => 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
|
||||
*/
|
||||
initAddressButtonsIframe() {
|
||||
$(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() {
|
||||
$('#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
|
||||
*/
|
||||
listenForCartEdit() {
|
||||
this.onCartAddressesChanged();
|
||||
this.onDeliveryOptionChanged();
|
||||
this.onDeliverySettingChanged();
|
||||
this.addCartRuleToCart();
|
||||
this.removeCartRuleFromCart();
|
||||
this.onCartCurrencyChanged();
|
||||
this.onCartLanguageChanged();
|
||||
|
||||
this.$container.on(
|
||||
'change',
|
||||
createOrderMap.deliveryOptionSelect,
|
||||
(e) => this.cartEditor.changeDeliveryOption(this.cartId, e.currentTarget.value),
|
||||
);
|
||||
|
||||
this.$container.on(
|
||||
'change',
|
||||
createOrderMap.freeShippingSwitch,
|
||||
() => this.cartEditor.updateDeliveryOptions(this.cartId),
|
||||
);
|
||||
|
||||
this.$container.on(
|
||||
'change',
|
||||
createOrderMap.recycledPackagingSwitch,
|
||||
() => this.cartEditor.updateDeliveryOptions(this.cartId),
|
||||
);
|
||||
|
||||
this.$container.on(
|
||||
'change',
|
||||
createOrderMap.isAGiftSwitch,
|
||||
() => this.cartEditor.updateDeliveryOptions(this.cartId),
|
||||
);
|
||||
|
||||
this.$container.on(
|
||||
'blur',
|
||||
createOrderMap.giftMessageField,
|
||||
() => this.cartEditor.updateDeliveryOptions(this.cartId),
|
||||
);
|
||||
|
||||
this.$container.on(
|
||||
'click',
|
||||
createOrderMap.addToCartButton,
|
||||
() => this.productManager.addProductToCart(this.cartId),
|
||||
);
|
||||
|
||||
this.$container.on(
|
||||
'change',
|
||||
createOrderMap.cartCurrencySelect,
|
||||
(e) => this.cartEditor.changeCartCurrency(this.cartId, e.currentTarget.value),
|
||||
);
|
||||
|
||||
this.$container.on(
|
||||
'change',
|
||||
createOrderMap.cartLanguageSelect,
|
||||
(e) => this.cartEditor.changeCartLanguage(this.cartId, e.currentTarget.value),
|
||||
);
|
||||
|
||||
this.$container.on(
|
||||
'click',
|
||||
createOrderMap.sendProcessOrderEmailBtn,
|
||||
() => this.summaryManager.sendProcessOrderEmail(this.cartId),
|
||||
);
|
||||
|
||||
this.$container.on('change', createOrderMap.listedProductUnitPriceInput, (e) => this.initProductChangePrice(e));
|
||||
this.$container.on(
|
||||
'change',
|
||||
createOrderMap.listedProductQtyInput,
|
||||
_.debounce((e) => {
|
||||
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) => this.initProductRemoveFromCart(e));
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for event when cart is loaded
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onCartLoaded() {
|
||||
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(this.cartId);
|
||||
this.customerManager.loadCustomerOrders();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for event when no customers were found by search
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onCustomersNotFound() {
|
||||
EventEmitter.on(eventMap.customersNotFound, () => {
|
||||
this.hideCartInfo();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for event when customer is selected
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onCustomerSelected() {
|
||||
EventEmitter.on(eventMap.customerSelected, () => {
|
||||
this.showCartInfo();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for cart addresses update event
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
onCartLanguageChanged() {
|
||||
EventEmitter.on(eventMap.cartLanguageChanged, (cartInfo) => {
|
||||
this.preselectCartLanguage(cartInfo.langId);
|
||||
this.renderCartInfo(cartInfo);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for cart currency update event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onCartCurrencyChanged() {
|
||||
// on success
|
||||
EventEmitter.on(eventMap.cartCurrencyChanged, (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
|
||||
*/
|
||||
initCustomerSearch(event) {
|
||||
clearTimeout(this.timeoutId);
|
||||
this.timeoutId = setTimeout(() => this.customerManager.search($(event.currentTarget).val()), 300);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init selecting customer for which order is being created
|
||||
*
|
||||
* @param event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
initCustomerSelect(event) {
|
||||
const customerId = this.customerManager.selectCustomer(event);
|
||||
this.customerId = customerId;
|
||||
this.cartProvider.loadEmptyCart(customerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inits selecting cart to load
|
||||
*
|
||||
* @param event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
initCartSelect(event) {
|
||||
const cartId = $(event.currentTarget).data('cart-id');
|
||||
this.cartProvider.getCart(cartId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inits duplicating order cart
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
initDuplicateOrderCart(event) {
|
||||
const orderId = $(event.currentTarget).data('order-id');
|
||||
this.cartProvider.duplicateOrderCart(orderId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers cart rule searching
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
initCartRuleSearch(event) {
|
||||
const searchPhrase = event.currentTarget.value;
|
||||
|
||||
clearTimeout(this.timeoutId);
|
||||
this.timeoutId = setTimeout(() => this.cartRuleManager.search(searchPhrase), 300);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers cart rule select
|
||||
*
|
||||
* @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, 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
|
||||
*/
|
||||
removeCartRuleFromCart() {
|
||||
this.$container.on('click', createOrderMap.cartRuleDeleteBtn, (event) => {
|
||||
this.cartRuleManager.removeCartRuleFromCart($(event.currentTarget).data('cart-rule-id'), this.cartId);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Inits product searching
|
||||
*
|
||||
* @param event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
initProductSearch(event) {
|
||||
const $productSearchInput = $(event.currentTarget);
|
||||
const searchPhrase = $productSearchInput.val();
|
||||
clearTimeout(this.timeoutId);
|
||||
|
||||
this.timeoutId = setTimeout(() => this.productManager.search(searchPhrase), 300);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inits product removing from cart
|
||||
*
|
||||
* @param event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
initProductRemoveFromCart(event) {
|
||||
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(this.cartId, product);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inits product in cart price change
|
||||
*
|
||||
* @param event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
initProductChangePrice(event) {
|
||||
const product = {
|
||||
productId: $(event.currentTarget).data('product-id'),
|
||||
attributeId: $(event.currentTarget).data('attribute-id'),
|
||||
customizationId: $(event.currentTarget).data('customization-id'),
|
||||
price: $(event.currentTarget).val(),
|
||||
};
|
||||
this.productManager.changeProductPrice(this.cartId, this.customerId, product);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inits product in cart quantity update
|
||||
*
|
||||
* @param event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
initProductChangeQty(event) {
|
||||
const product = {
|
||||
productId: $(event.currentTarget).data('product-id'),
|
||||
attributeId: $(event.currentTarget).data('attribute-id'),
|
||||
customizationId: $(event.currentTarget).data('customization-id'),
|
||||
newQty: $(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(this.cartId, product);
|
||||
} else {
|
||||
const inputsQty = document.querySelectorAll(createOrderMap.listedProductQtyInput);
|
||||
|
||||
inputsQty.forEach((inputQty) => {
|
||||
inputQty.disabled = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders cart summary on the page
|
||||
*
|
||||
* @param {Object} cartInfo
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderCartInfo(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.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
|
||||
*/
|
||||
preselectCartCurrency(currencyId) {
|
||||
$(createOrderMap.cartCurrencySelect).val(currencyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets cart language selection value
|
||||
*
|
||||
* @param langId
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
preselectCartLanguage(langId) {
|
||||
$(createOrderMap.cartLanguageSelect).val(langId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes cart addresses
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
changeCartAddresses() {
|
||||
const addresses = {
|
||||
deliveryAddressId: $(createOrderMap.deliveryAddressSelect).val(),
|
||||
invoiceAddressId: $(createOrderMap.invoiceAddressSelect).val(),
|
||||
};
|
||||
|
||||
this.cartEditor.changeCartAddresses(this.cartId, addresses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh addresses list
|
||||
*
|
||||
* @param {boolean} refreshCartAddresses optional
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
refreshAddressesList(refreshCartAddresses) {
|
||||
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) => {
|
||||
window.showErrorMessage(e.responseJSON.message);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* proxy to allow other scripts within the page to refresh addresses list
|
||||
*/
|
||||
refreshCart() {
|
||||
const cartId = $(createOrderMap.cartBlock).data('cartId');
|
||||
this.cartProvider.getCart(cartId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/**
|
||||
* 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 createOrderMap from '@pages/order/create/create-order-map';
|
||||
import CustomerRenderer from '@pages/order/create/customer-renderer';
|
||||
import {EventEmitter} from '@components/event-emitter';
|
||||
import eventMap from '@pages/order/create/event-map';
|
||||
import Router from '@components/router';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* Responsible for customers managing. (search, select, get customer info etc.)
|
||||
*/
|
||||
export default class CustomerManager {
|
||||
constructor() {
|
||||
this.customerId = null;
|
||||
this.activeSearchRequest = null;
|
||||
|
||||
this.router = new Router();
|
||||
this.$container = $(createOrderMap.customerSearchBlock);
|
||||
this.$searchInput = $(createOrderMap.customerSearchInput);
|
||||
this.$customerSearchResultBlock = $(createOrderMap.customerSearchResultsBlock);
|
||||
this.customerRenderer = new CustomerRenderer();
|
||||
|
||||
this.initListeners();
|
||||
this.initAddCustomerIframe();
|
||||
|
||||
return {
|
||||
search: (searchPhrase) => this.search(searchPhrase),
|
||||
selectCustomer: (event) => this.selectCustomer(event),
|
||||
loadCustomerCarts: (currentCartId) => this.loadCustomerCarts(currentCartId),
|
||||
loadCustomerOrders: () => this.loadCustomerOrders(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes event listeners
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
initListeners() {
|
||||
this.$container.on('click', createOrderMap.changeCustomerBtn, () => this.changeCustomer());
|
||||
this.onCustomerSearch();
|
||||
this.onCustomerSelect();
|
||||
this.onCustomersNotFound();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
initAddCustomerIframe() {
|
||||
$(createOrderMap.customerAddBtn).fancybox({
|
||||
type: 'iframe',
|
||||
width: '90%',
|
||||
height: '90%',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for customer search event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onCustomerSearch() {
|
||||
EventEmitter.on(eventMap.customerSearched, (response) => {
|
||||
this.activeSearchRequest = null;
|
||||
this.customerRenderer.hideSearchingCustomers();
|
||||
|
||||
if (response.customers.length === 0) {
|
||||
EventEmitter.emit(eventMap.customersNotFound);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.customerRenderer.renderSearchResults(response.customers);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for event of when no customers were found by search
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onCustomersNotFound() {
|
||||
EventEmitter.on(eventMap.customersNotFound, () => {
|
||||
this.customerRenderer.showNotFoundCustomers();
|
||||
this.customerRenderer.hideCheckoutHistoryBlock();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for customer select event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onCustomerSelect() {
|
||||
EventEmitter.on(eventMap.customerSelected, (event) => {
|
||||
const $chooseBtn = $(event.currentTarget);
|
||||
this.customerId = $chooseBtn.data('customer-id');
|
||||
|
||||
const createAddressUrl = this.router.generate(
|
||||
'admin_addresses_create',
|
||||
{
|
||||
liteDisplaying: 1,
|
||||
submitFormAjax: 1,
|
||||
id_customer: this.customerId,
|
||||
},
|
||||
);
|
||||
$(createOrderMap.addressAddBtn).attr('href', createAddressUrl);
|
||||
|
||||
this.customerRenderer.displaySelectedCustomerBlock($chooseBtn);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles use case when customer is changed
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
changeCustomer() {
|
||||
this.customerRenderer.showCustomerSearch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads customer carts list
|
||||
*
|
||||
* @param currentCartId
|
||||
*/
|
||||
loadCustomerCarts(currentCartId) {
|
||||
const {customerId} = this;
|
||||
|
||||
this.customerRenderer.showLoadingCarts();
|
||||
$.get(this.router.generate('admin_customers_carts', {customerId})).then((response) => {
|
||||
this.customerRenderer.renderCarts(response.carts, currentCartId);
|
||||
}).catch((e) => {
|
||||
window.showErrorMessage(e.responseJSON.message);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads customer orders list
|
||||
*/
|
||||
loadCustomerOrders() {
|
||||
const {customerId} = this;
|
||||
|
||||
this.customerRenderer.showLoadingOrders();
|
||||
$.get(this.router.generate('admin_customers_orders', {customerId})).then((response) => {
|
||||
this.customerRenderer.renderOrders(response.orders);
|
||||
}).catch((e) => {
|
||||
window.showErrorMessage(e.responseJSON.message);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Event} chooseCustomerEvent
|
||||
*
|
||||
* @return {Number}
|
||||
*/
|
||||
selectCustomer(chooseCustomerEvent) {
|
||||
EventEmitter.emit(eventMap.customerSelected, chooseCustomerEvent);
|
||||
|
||||
return this.customerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for customers
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
search(searchPhrase) {
|
||||
if (searchPhrase.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.activeSearchRequest !== null) {
|
||||
this.activeSearchRequest.abort();
|
||||
}
|
||||
|
||||
this.customerRenderer.clearShownCustomers();
|
||||
this.customerRenderer.hideNotFoundCustomers();
|
||||
this.customerRenderer.showSearchingCustomers();
|
||||
const $searchRequest = $.get(this.router.generate('admin_customers_search'), {
|
||||
customer_search: searchPhrase,
|
||||
});
|
||||
this.activeSearchRequest = $searchRequest;
|
||||
|
||||
$searchRequest.then((response) => {
|
||||
EventEmitter.emit(eventMap.customerSearched, response);
|
||||
}).catch((response) => {
|
||||
if (response.statusText === 'abort') {
|
||||
return;
|
||||
}
|
||||
|
||||
window.showErrorMessage(response.responseJSON.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
/**
|
||||
* 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 createOrderMap from '@pages/order/create/create-order-map';
|
||||
import Router from '@components/router';
|
||||
import eventMap from '@pages/order/create/event-map';
|
||||
import {EventEmitter} from '@components/event-emitter';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* Responsible for customer information rendering
|
||||
*/
|
||||
export default class CustomerRenderer {
|
||||
constructor() {
|
||||
this.$container = $(createOrderMap.customerSearchBlock);
|
||||
this.$customerSearchResultBlock = $(createOrderMap.customerSearchResultsBlock);
|
||||
this.router = new Router();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders customer search results
|
||||
*
|
||||
* @param foundCustomers
|
||||
*/
|
||||
renderSearchResults(foundCustomers) {
|
||||
if (foundCustomers.length === 0) {
|
||||
EventEmitter.emit(eventMap.customersNotFound);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Object.entries(foundCustomers).forEach(([customerId, customerResult]) => {
|
||||
const customer = {
|
||||
id: customerId,
|
||||
firstName: customerResult.firstname,
|
||||
lastName: customerResult.lastname,
|
||||
email: customerResult.email,
|
||||
birthday: customerResult.birthday !== '0000-00-00' ? customerResult.birthday : ' ',
|
||||
};
|
||||
|
||||
this.renderFoundCustomer(customer);
|
||||
});
|
||||
|
||||
// Show customer details in fancy box
|
||||
$(createOrderMap.customerDetailsBtn).fancybox({
|
||||
type: 'iframe',
|
||||
width: '90%',
|
||||
height: '90%',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for displaying customer block after customer select
|
||||
*
|
||||
* @param $targetedBtn
|
||||
*/
|
||||
displaySelectedCustomerBlock($targetedBtn) {
|
||||
this.showCheckoutHistoryBlock();
|
||||
|
||||
$targetedBtn.addClass('d-none');
|
||||
|
||||
const $customerCard = $targetedBtn.closest('.card');
|
||||
|
||||
$customerCard.addClass('border-success');
|
||||
$customerCard.find(createOrderMap.changeCustomerBtn).removeClass('d-none');
|
||||
|
||||
this.$container.find(createOrderMap.customerSearchRow).addClass('d-none');
|
||||
this.$container.find(createOrderMap.notSelectedCustomerSearchResults)
|
||||
.closest(createOrderMap.customerSearchResultColumn)
|
||||
.remove();
|
||||
|
||||
// Initial display of the customer, the cart is gonna be created then customer's carts
|
||||
// and orders are going to be fetched, but we can display the loading messages right now
|
||||
this.showLoadingCarts();
|
||||
this.showLoadingOrders();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows customer search block
|
||||
*/
|
||||
showCustomerSearch() {
|
||||
this.$container.find(createOrderMap.customerSearchRow).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty the cart list and display a loading message.
|
||||
*/
|
||||
showLoadingCarts() {
|
||||
const $cartsTable = $(createOrderMap.customerCartsTable);
|
||||
$cartsTable.find('tbody').empty();
|
||||
this.renderLoading($cartsTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders customer carts list
|
||||
*
|
||||
* @param {Array} carts
|
||||
* @param {Int} currentCartId
|
||||
*/
|
||||
renderCarts(carts, currentCartId) {
|
||||
const $cartsTable = $(createOrderMap.customerCartsTable);
|
||||
const $cartsTableRowTemplate = $($(createOrderMap.customerCartsTableRowTemplate).html());
|
||||
|
||||
$cartsTable.find('tbody').empty();
|
||||
this.showCheckoutHistoryBlock();
|
||||
this.removeEmptyListRowFromTable($cartsTable);
|
||||
|
||||
Object.values(carts).forEach((cart) => {
|
||||
// do not render current cart
|
||||
if (cart.cartId === currentCartId) {
|
||||
// render 'No records found' warn if carts only contain current cart
|
||||
if (carts.length === 1) {
|
||||
this.renderEmptyList($cartsTable);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const $cartsTableRow = $cartsTableRowTemplate.clone();
|
||||
|
||||
$cartsTableRow.find(createOrderMap.cartIdField).text(cart.cartId);
|
||||
$cartsTableRow.find(createOrderMap.cartDateField).text(cart.creationDate);
|
||||
$cartsTableRow.find(createOrderMap.cartTotalField).text(cart.totalPrice);
|
||||
$cartsTableRow.find(createOrderMap.cartDetailsBtn).prop(
|
||||
'href',
|
||||
this.router.generate('admin_carts_view', {
|
||||
cartId: cart.cartId,
|
||||
liteDisplaying: 1,
|
||||
}),
|
||||
);
|
||||
|
||||
$cartsTableRow.find(createOrderMap.useCartBtn).data('cart-id', cart.cartId);
|
||||
|
||||
$cartsTable.find('thead').removeClass('d-none');
|
||||
$cartsTable.find('tbody').append($cartsTableRow);
|
||||
});
|
||||
|
||||
// Show cart details in fancy box
|
||||
$(createOrderMap.cartDetailsBtn).fancybox({
|
||||
type: 'iframe',
|
||||
width: '90%',
|
||||
height: '90%',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty the order list and display a loading message.
|
||||
*/
|
||||
showLoadingOrders() {
|
||||
const $ordersTable = $(createOrderMap.customerOrdersTable);
|
||||
$ordersTable.find('tbody').empty();
|
||||
this.renderLoading($ordersTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders customer orders list
|
||||
*
|
||||
* @param {Array} orders
|
||||
*/
|
||||
renderOrders(orders) {
|
||||
const $ordersTable = $(createOrderMap.customerOrdersTable);
|
||||
const $rowTemplate = $($(createOrderMap.customerOrdersTableRowTemplate).html());
|
||||
|
||||
$ordersTable.find('tbody').empty();
|
||||
this.showCheckoutHistoryBlock();
|
||||
this.removeEmptyListRowFromTable($ordersTable);
|
||||
|
||||
// render 'No records found' when list is empty
|
||||
if (orders.length === 0) {
|
||||
this.renderEmptyList($ordersTable);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Object.values(orders).forEach((order) => {
|
||||
const $template = $rowTemplate.clone();
|
||||
|
||||
$template.find(createOrderMap.orderIdField).text(order.orderId);
|
||||
$template.find(createOrderMap.orderDateField).text(order.orderPlacedDate);
|
||||
$template.find(createOrderMap.orderProductsField).text(order.orderProductsCount);
|
||||
$template.find(createOrderMap.orderTotalField).text(order.totalPaid);
|
||||
$template.find(createOrderMap.orderPaymentMethod).text(order.paymentMethodName);
|
||||
$template.find(createOrderMap.orderStatusField).text(order.orderStatus);
|
||||
$template.find(createOrderMap.orderDetailsBtn).prop(
|
||||
'href',
|
||||
this.router.generate('admin_orders_view', {
|
||||
orderId: order.orderId,
|
||||
liteDisplaying: 1,
|
||||
}),
|
||||
);
|
||||
|
||||
$template.find(createOrderMap.useOrderBtn).data('order-id', order.orderId);
|
||||
|
||||
$ordersTable.find('thead').removeClass('d-none');
|
||||
$ordersTable.find('tbody').append($template);
|
||||
});
|
||||
|
||||
// Show order details in fancy box
|
||||
$(createOrderMap.orderDetailsBtn).fancybox({
|
||||
type: 'iframe',
|
||||
width: '90%',
|
||||
height: '90%',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows empty result when customer is not found
|
||||
*/
|
||||
showNotFoundCustomers() {
|
||||
$(createOrderMap.customerSearchEmptyResultWarning).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides not found customers warning
|
||||
*/
|
||||
hideNotFoundCustomers() {
|
||||
$(createOrderMap.customerSearchEmptyResultWarning).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides checkout history block where carts and orders are rendered
|
||||
*/
|
||||
hideCheckoutHistoryBlock() {
|
||||
$(createOrderMap.customerCheckoutHistory).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows searching customers notice during request
|
||||
*/
|
||||
showSearchingCustomers() {
|
||||
$(createOrderMap.customerSearchLoadingNotice).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide searching notice
|
||||
*/
|
||||
hideSearchingCustomers() {
|
||||
$(createOrderMap.customerSearchLoadingNotice).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders 'No records' warning in list
|
||||
*
|
||||
* @param $table
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderEmptyList($table) {
|
||||
const $emptyTableRow = $($(createOrderMap.emptyListRowTemplate).html()).clone();
|
||||
$table.find('tbody').append($emptyTableRow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders 'Loading' message in list
|
||||
*
|
||||
* @param $table
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderLoading($table) {
|
||||
const $emptyTableRow = $($(createOrderMap.loadingListRowTemplate).html()).clone();
|
||||
$table.find('tbody').append($emptyTableRow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes empty list row in case it was rendered
|
||||
*/
|
||||
removeEmptyListRowFromTable($table) {
|
||||
$table.find(createOrderMap.emptyListRow).remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders customer information after search action
|
||||
*
|
||||
* @param {Object} customer
|
||||
*
|
||||
* @return {jQuery}
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderFoundCustomer(customer) {
|
||||
this.hideNotFoundCustomers();
|
||||
|
||||
const $customerSearchResultTemplate = $($(createOrderMap.customerSearchResultTemplate).html());
|
||||
const $template = $customerSearchResultTemplate.clone();
|
||||
|
||||
$template.find(createOrderMap.customerSearchResultName).text(`${customer.firstName} ${customer.lastName}`);
|
||||
$template.find(createOrderMap.customerSearchResultEmail).text(customer.email);
|
||||
$template.find(createOrderMap.customerSearchResultId).text(customer.id);
|
||||
$template.find(createOrderMap.customerSearchResultBirthday).text(customer.birthday);
|
||||
$template.find(createOrderMap.chooseCustomerBtn).data('customer-id', customer.id);
|
||||
$template.find(createOrderMap.customerDetailsBtn).prop(
|
||||
'href',
|
||||
this.router.generate('admin_customers_view', {
|
||||
customerId: customer.id,
|
||||
liteDisplaying: 1,
|
||||
}),
|
||||
);
|
||||
|
||||
return this.$customerSearchResultBlock.append($template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows checkout history block where carts and orders are rendered
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showCheckoutHistoryBlock() {
|
||||
$(createOrderMap.customerCheckoutHistory).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears shown customers
|
||||
*/
|
||||
clearShownCustomers() {
|
||||
this.$customerSearchResultBlock.empty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Encapsulates js events used in create order page
|
||||
*/
|
||||
export default {
|
||||
// when customer search action is done
|
||||
customerSearched: 'OrderCreateCustomerSearched',
|
||||
// when new customer is selected
|
||||
customerSelected: 'OrderCreateCustomerSelected',
|
||||
// when no customers found by search
|
||||
customersNotFound: 'OrderCreateSearchCustomerNotFound',
|
||||
// when new cart is loaded,
|
||||
// no matter if its empty, selected from carts list or duplicated by order.
|
||||
cartLoaded: 'OrderCreateCartLoaded',
|
||||
// when cart currency has been changed
|
||||
cartCurrencyChanged: 'OrderCreateCartCurrencyChanged',
|
||||
// when cart currency changing fails
|
||||
cartCurrencyChangeFailed: 'OrderCreateCartCurrencyChangeFailed',
|
||||
// when cart language has been changed
|
||||
cartLanguageChanged: 'OrderCreateCartLanguageChanged',
|
||||
// when cart addresses information has been changed
|
||||
cartAddressesChanged: 'OrderCreateCartAddressesChanged',
|
||||
// when cart delivery option has been changed
|
||||
cartDeliveryOptionChanged: 'OrderCreateCartDeliveryOptionChanged',
|
||||
// when cart delivery setting has been changed
|
||||
cartDeliverySettingChanged: 'OrderCreateCartDeliverySettingChangedSet',
|
||||
// when cart rules search action is done
|
||||
cartRuleSearched: 'OrderCreateCartRuleSearched',
|
||||
// when cart rule is removed from cart
|
||||
cartRuleRemoved: 'OrderCreateCartRuleRemoved',
|
||||
// when cart rule is added to cart
|
||||
cartRuleAdded: 'OrderCreateCartRuleAdded',
|
||||
// when cart rule cannot be added to cart
|
||||
cartRuleFailedToAdd: 'OrderCreateCartRuleFailedToAdd',
|
||||
// when product search action is done
|
||||
productSearched: 'OrderCreateProductSearched',
|
||||
// when product is added to cart
|
||||
productAddedToCart: 'OrderCreateProductAddedToCart',
|
||||
// when adding product to cart fails
|
||||
productAddToCartFailed: 'OrderCreateProductAddToCartFailed',
|
||||
// when product is removed from cart
|
||||
productRemovedFromCart: 'OrderCreateProductRemovedFromCart',
|
||||
// when product in cart price has been changed
|
||||
productPriceChanged: 'OrderCreateProductPriceChanged',
|
||||
// when product quantity in cart has been changed
|
||||
productQtyChanged: 'OrderCreateProductQtyChanged',
|
||||
// when changing product quantity in cart failed
|
||||
productQtyChangeFailed: 'OrderCreateProductQtyChangeFailed',
|
||||
// when order process email has been sent to customer
|
||||
processOrderEmailSent: 'OrderCreateProcessOrderEmailSent',
|
||||
// when order process email sending failed
|
||||
processOrderEmailFailed: 'OrderCreateProcessOrderEmailFailed',
|
||||
};
|
||||
@@ -0,0 +1,422 @@
|
||||
/**
|
||||
* 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 CartEditor from '@pages/order/create/cart-editor';
|
||||
import createOrderMap from '@pages/order/create/create-order-map';
|
||||
import eventMap from '@pages/order/create/event-map';
|
||||
import {EventEmitter} from '@components/event-emitter';
|
||||
import ProductRenderer from '@pages/order/create/product-renderer';
|
||||
import Router from '@components/router';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* Product component Object for "Create order" page
|
||||
*/
|
||||
export default class ProductManager {
|
||||
constructor() {
|
||||
this.products = [];
|
||||
this.selectedProduct = null;
|
||||
this.selectedCombinationId = null;
|
||||
this.activeSearchRequest = null;
|
||||
|
||||
this.productRenderer = new ProductRenderer();
|
||||
this.router = new Router();
|
||||
this.cartEditor = new CartEditor();
|
||||
|
||||
this.initListeners();
|
||||
|
||||
return {
|
||||
search: (searchPhrase) => this.search(searchPhrase),
|
||||
addProductToCart: (cartId) => this.cartEditor.addProduct(cartId, this.getProductData()),
|
||||
removeProductFromCart: (cartId, product) => this.cartEditor.removeProductFromCart(cartId, product),
|
||||
/* eslint-disable-next-line max-len */
|
||||
changeProductPrice: (cartId, customerId, updatedProduct) => this.cartEditor.changeProductPrice(cartId, customerId, updatedProduct),
|
||||
changeProductQty: (cartId, updatedProduct) => this.cartEditor.changeProductQty(cartId, updatedProduct),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes event listeners
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
initListeners() {
|
||||
$(createOrderMap.productSelect).on('change', (e) => this.initProductSelect(e));
|
||||
$(createOrderMap.combinationsSelect).on('change', (e) => this.initCombinationSelect(e));
|
||||
|
||||
this.onProductSearch();
|
||||
this.onAddProductToCart();
|
||||
this.onRemoveProductFromCart();
|
||||
this.onProductPriceChange();
|
||||
this.onProductQtyChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for product search event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onProductSearch() {
|
||||
EventEmitter.on(eventMap.productSearched, (response) => {
|
||||
this.products = response.products;
|
||||
this.productRenderer.renderSearchResults(this.products);
|
||||
this.selectFirstResult();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for add product to cart event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onAddProductToCart() {
|
||||
// on success
|
||||
EventEmitter.on(eventMap.productAddedToCart, (cartInfo) => {
|
||||
this.productRenderer.cleanCartBlockAlerts();
|
||||
this.updateStockOnProductAdd();
|
||||
EventEmitter.emit(eventMap.cartLoaded, cartInfo);
|
||||
});
|
||||
|
||||
// on failure
|
||||
EventEmitter.on(eventMap.productAddToCartFailed, (errorMessage) => {
|
||||
this.productRenderer.renderCartBlockErrorAlert(errorMessage);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for remove product from cart event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onRemoveProductFromCart() {
|
||||
EventEmitter.on(eventMap.productRemovedFromCart, (data) => {
|
||||
this.updateStockOnProductRemove(data.product);
|
||||
EventEmitter.emit(eventMap.cartLoaded, data.cartInfo);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for product price change in cart event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onProductPriceChange() {
|
||||
EventEmitter.on(eventMap.productPriceChanged, (cartInfo) => {
|
||||
this.productRenderer.cleanCartBlockAlerts();
|
||||
EventEmitter.emit(eventMap.cartLoaded, cartInfo);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for product quantity change in cart success/failure event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onProductQtyChange() {
|
||||
const enableQtyInputs = () => {
|
||||
const inputsQty = document.querySelectorAll(createOrderMap.listedProductQtyInput);
|
||||
|
||||
inputsQty.forEach((inputQty) => {
|
||||
inputQty.disabled = false;
|
||||
});
|
||||
};
|
||||
|
||||
// on success
|
||||
EventEmitter.on(eventMap.productQtyChanged, (data) => {
|
||||
this.productRenderer.cleanCartBlockAlerts();
|
||||
this.updateStockOnQtyChange(data.product);
|
||||
|
||||
$(createOrderMap.createOrderButton).prop('disabled', false);
|
||||
EventEmitter.emit(eventMap.cartLoaded, data.cartInfo);
|
||||
|
||||
enableQtyInputs();
|
||||
});
|
||||
|
||||
// on failure
|
||||
EventEmitter.on(eventMap.productQtyChangeFailed, (e) => {
|
||||
this.productRenderer.renderCartBlockErrorAlert(e.responseJSON.message);
|
||||
$(createOrderMap.createOrderButton).prop('disabled', true);
|
||||
enableQtyInputs();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes product select
|
||||
*
|
||||
* @param event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
initProductSelect(event) {
|
||||
const productId = Number(
|
||||
$(event.currentTarget)
|
||||
.find(':selected')
|
||||
.val(),
|
||||
);
|
||||
this.selectProduct(productId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes combination select
|
||||
*
|
||||
* @param event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
initCombinationSelect(event) {
|
||||
const combinationId = Number(
|
||||
$(event.currentTarget)
|
||||
.find(':selected')
|
||||
.val(),
|
||||
);
|
||||
this.selectCombination(combinationId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for product
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
search(searchPhrase) {
|
||||
// Search only if the search phrase length is greater than 2 characters
|
||||
if (searchPhrase.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.productRenderer.renderSearching();
|
||||
if (this.activeSearchRequest !== null) {
|
||||
this.activeSearchRequest.abort();
|
||||
}
|
||||
|
||||
const params = {
|
||||
search_phrase: searchPhrase,
|
||||
};
|
||||
|
||||
if ($(createOrderMap.cartCurrencySelect).data('selectedCurrencyId') !== undefined) {
|
||||
params.currency_id = $(createOrderMap.cartCurrencySelect).data('selectedCurrencyId');
|
||||
}
|
||||
|
||||
const $searchRequest = $.get(this.router.generate('admin_orders_products_search'), params);
|
||||
this.activeSearchRequest = $searchRequest;
|
||||
|
||||
$searchRequest
|
||||
.then((response) => {
|
||||
EventEmitter.emit(eventMap.productSearched, response);
|
||||
})
|
||||
.catch((response) => {
|
||||
if (response.statusText === 'abort') {
|
||||
return;
|
||||
}
|
||||
|
||||
window.showErrorMessage(response.responseJSON.message);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate first result dataset after search
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
selectFirstResult() {
|
||||
this.unsetProduct();
|
||||
|
||||
if (this.products.length !== 0) {
|
||||
this.selectProduct(this.products[0].productId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles use case when product is selected from search results
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @param {Number} productId
|
||||
*/
|
||||
selectProduct(productId) {
|
||||
this.unsetCombination();
|
||||
|
||||
const selectedProduct = Object.values(this.products).find((product) => product.productId === productId);
|
||||
|
||||
if (selectedProduct) {
|
||||
this.selectedProduct = selectedProduct;
|
||||
}
|
||||
|
||||
this.productRenderer.renderProductMetadata(this.selectedProduct);
|
||||
// if product has combinations select the first else leave it null
|
||||
if (this.selectedProduct.combinations.length !== 0) {
|
||||
this.selectCombination(Object.keys(this.selectedProduct.combinations)[0]);
|
||||
}
|
||||
|
||||
return this.selectedProduct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles use case when new combination is selected
|
||||
*
|
||||
* @param combinationId
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
selectCombination(combinationId) {
|
||||
const combination = this.selectedProduct.combinations[combinationId];
|
||||
|
||||
this.selectedCombinationId = combinationId;
|
||||
this.productRenderer.renderStock(
|
||||
$(createOrderMap.inStockCounter),
|
||||
$(createOrderMap.quantityInput),
|
||||
combination.stock,
|
||||
this.selectedProduct.availableOutOfStock || combination.stock <= 0,
|
||||
);
|
||||
|
||||
return combination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the selected combination id to null
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
unsetCombination() {
|
||||
this.selectedCombinationId = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the selected product to null
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
unsetProduct() {
|
||||
this.selectedProduct = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves product data from product search result block fields
|
||||
*
|
||||
* @returns {Object}
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
getProductData() {
|
||||
const $fileInputs = $(createOrderMap.productCustomizationContainer).find('input[type="file"]');
|
||||
const formData = new FormData(document.querySelector(createOrderMap.productAddForm));
|
||||
const fileSizes = {};
|
||||
|
||||
// adds key value pairs {input name: file size} of each file in separate object
|
||||
// in case formData size exceeds server settings.
|
||||
$.each($fileInputs, (key, input) => {
|
||||
if (input.files.length !== 0) {
|
||||
fileSizes[$(input).data('customization-field-id')] = input.files[0].size;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
product: formData,
|
||||
fileSizes,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the stock when the product is added to cart in "create new order" page
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
updateStockOnProductAdd() {
|
||||
const {productId} = this.selectedProduct;
|
||||
const attributeId = this.selectedCombinationId;
|
||||
const qty = -Number($(createOrderMap.quantityInput).val());
|
||||
|
||||
this.updateStock(productId, attributeId, qty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the stock when the product is removed from cart in Orders/"create new order page"
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
updateStockOnProductRemove(product) {
|
||||
const {productId, attributeId, qtyToRemove} = product;
|
||||
const qty = qtyToRemove;
|
||||
|
||||
this.updateStock(productId, attributeId, qty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the stock when the quantity of product is changed from cart in Orders/"create new order page"
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
updateStockOnQtyChange(product) {
|
||||
const {
|
||||
productId, attributeId, prevQty, newQty,
|
||||
} = product;
|
||||
const qty = prevQty - newQty;
|
||||
|
||||
this.updateStock(productId, attributeId, qty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the stock in products object and renders the new stock
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
updateStock(productId, attributeId, qty) {
|
||||
const productKeys = Object.keys(this.products);
|
||||
const productValues = Object.values(this.products);
|
||||
|
||||
for (let i = 0; i < productKeys.length; i += 1) {
|
||||
if (productValues[i].productId === productId) {
|
||||
const $template = this.productRenderer.cloneProductTemplate(productValues[i]);
|
||||
// Update the stock value in products object
|
||||
productValues[i].stock += qty;
|
||||
|
||||
// Update the stock also for combination */
|
||||
if (attributeId && attributeId > 0) {
|
||||
productValues[i].combinations[attributeId].stock += qty;
|
||||
}
|
||||
|
||||
// Render the new stock value
|
||||
if (this.selectedProduct.productId === productId) {
|
||||
if (this.selectedProduct.combinations.length === 0) {
|
||||
this.productRenderer.renderStock(
|
||||
$template.find(createOrderMap.listedProductQtyStock),
|
||||
$template.find(createOrderMap.listedProductQtyInput),
|
||||
productValues[i].stock,
|
||||
productValues[i].availableOutOfStock || productValues[i].availableStock <= 0,
|
||||
);
|
||||
} else if (attributeId && Number(this.selectedCombinationId) === Number(attributeId)) {
|
||||
this.productRenderer.renderStock(
|
||||
$template.find(createOrderMap.listedProductQtyStock),
|
||||
$template.find(createOrderMap.listedProductQtyInput),
|
||||
productValues[i].combinations[attributeId].stock,
|
||||
productValues[i].availableOutOfStock || productValues[i].availableStock <= 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,500 @@
|
||||
/**
|
||||
* 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 createOrderMap from './create-order-map';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
export default class ProductRenderer {
|
||||
constructor() {
|
||||
this.$productsTable = $(createOrderMap.productsTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders cart products list
|
||||
*
|
||||
* @param products
|
||||
*/
|
||||
renderList(products) {
|
||||
this.cleanProductsList();
|
||||
|
||||
if (products.length === 0) {
|
||||
this.hideProductsList();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Object.values(products).forEach((product) => {
|
||||
const $template = this.cloneProductTemplate(product);
|
||||
|
||||
let customizationId = 0;
|
||||
|
||||
if (product.customization) {
|
||||
({customizationId} = product.customization);
|
||||
this.renderListedProductCustomization(product.customization, $template);
|
||||
}
|
||||
|
||||
$template.find(createOrderMap.listedProductImageField).prop('src', product.imageLink);
|
||||
$template.find(createOrderMap.listedProductNameField).text(product.name);
|
||||
$template.find(createOrderMap.listedProductAttrField).text(product.attribute);
|
||||
$template.find(createOrderMap.listedProductReferenceField).text(product.reference);
|
||||
|
||||
if (product.gift !== true) {
|
||||
$template.find(createOrderMap.listedProductUnitPriceInput).val(product.unitPrice);
|
||||
$template.find(createOrderMap.listedProductUnitPriceInput).data('product-id', product.productId);
|
||||
$template.find(createOrderMap.listedProductUnitPriceInput).data('attribute-id', product.attributeId);
|
||||
$template.find(createOrderMap.listedProductUnitPriceInput).data('customization-id', customizationId);
|
||||
$template.find(createOrderMap.listedProductQtyInput).val(product.quantity);
|
||||
$template.find(createOrderMap.listedProductQtyInput).data('product-id', product.productId);
|
||||
$template.find(createOrderMap.listedProductQtyInput).data('attribute-id', product.attributeId);
|
||||
$template.find(createOrderMap.listedProductQtyInput).data('customization-id', customizationId);
|
||||
$template.find(createOrderMap.listedProductQtyInput).data('prev-qty', product.quantity);
|
||||
this.renderStock(
|
||||
$template.find(createOrderMap.listedProductQtyStock),
|
||||
$template.find(createOrderMap.listedProductQtyInput),
|
||||
product.availableStock,
|
||||
product.availableOutOfStock || (product.availableStock <= 0),
|
||||
);
|
||||
$template.find(createOrderMap.productTotalPriceField).text(product.price);
|
||||
$template.find(createOrderMap.productRemoveBtn).data('product-id', product.productId);
|
||||
$template.find(createOrderMap.productRemoveBtn).data('attribute-id', product.attributeId);
|
||||
$template.find(createOrderMap.productRemoveBtn).data('customization-id', customizationId);
|
||||
} else {
|
||||
$template.find(createOrderMap.listedProductGiftQty).text(product.quantity);
|
||||
}
|
||||
|
||||
this.$productsTable.find('tbody').append($template);
|
||||
});
|
||||
|
||||
this.showTaxWarning();
|
||||
this.showProductsList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders customization data for listed product
|
||||
*
|
||||
* @param customization
|
||||
* @param $productRowTemplate
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderListedProductCustomization(customization, $productRowTemplate) {
|
||||
const $customizedTextTemplate = $($(createOrderMap.listedProductCustomizedTextTemplate).html());
|
||||
const $customizedFileTemplate = $($(createOrderMap.listedProductCustomizedFileTemplate).html());
|
||||
|
||||
Object.values(customization.customizationFieldsData).forEach((customizedData) => {
|
||||
let $customizationTemplate = $customizedTextTemplate.clone();
|
||||
|
||||
if (customizedData.type === createOrderMap.productCustomizationFieldTypeFile) {
|
||||
$customizationTemplate = $customizedFileTemplate.clone();
|
||||
$customizationTemplate.find(createOrderMap.listedProductCustomizationName).text(customizedData.name);
|
||||
$customizationTemplate
|
||||
.find(`${createOrderMap.listedProductCustomizationValue} img`)
|
||||
.prop('src', customizedData.value);
|
||||
} else {
|
||||
$customizationTemplate.find(createOrderMap.listedProductCustomizationName).text(customizedData.name);
|
||||
$customizationTemplate.find(createOrderMap.listedProductCustomizationValue).text(customizedData.value);
|
||||
}
|
||||
|
||||
$productRowTemplate.find(createOrderMap.listedProductDefinition).append($customizationTemplate);
|
||||
});
|
||||
}
|
||||
|
||||
renderSearching() {
|
||||
this.reset();
|
||||
this.toggleSearchingNotice(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders cart products search results block
|
||||
*
|
||||
* @param foundProducts
|
||||
*/
|
||||
renderSearchResults(foundProducts) {
|
||||
this.cleanSearchResults();
|
||||
this.toggleSearchingNotice(false);
|
||||
if (foundProducts.length === 0) {
|
||||
this.showNotFound();
|
||||
this.hideTaxWarning();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.renderFoundProducts(foundProducts);
|
||||
|
||||
this.hideNotFound();
|
||||
this.showTaxWarning();
|
||||
this.showResultBlock();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.cleanSearchResults();
|
||||
this.hideTaxWarning();
|
||||
this.hideResultBlock();
|
||||
this.toggleSearchingNotice(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders available fields related to selected product
|
||||
*
|
||||
* @param {object} product
|
||||
*/
|
||||
renderProductMetadata(product) {
|
||||
this.renderStock(
|
||||
$(createOrderMap.inStockCounter),
|
||||
$(createOrderMap.quantityInput),
|
||||
product.stock,
|
||||
product.availableOutOfStock || (product.stock <= 0),
|
||||
);
|
||||
this.renderCombinations(product.combinations);
|
||||
this.renderCustomizations(product.customizationFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates stock text helper value
|
||||
*
|
||||
* @param {object} inputStockCounter Text Help with the stock counter
|
||||
* @param {object} inputQuantity Input for the stock
|
||||
* @param {number} stock Available stock for the product
|
||||
* @param {boolean} infiniteMax If the product order has no limits
|
||||
*/
|
||||
renderStock(inputStockCounter, inputQuantity, stock, infiniteMax) {
|
||||
inputStockCounter.text(stock);
|
||||
|
||||
if (!infiniteMax) {
|
||||
inputQuantity.attr('max', stock);
|
||||
} else {
|
||||
inputQuantity.removeAttr('max');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param product
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
cloneProductTemplate(product) {
|
||||
return product.gift === true
|
||||
? $($(createOrderMap.productsTableGiftRowTemplate).html()).clone()
|
||||
: $($(createOrderMap.productsTableRowTemplate).html()).clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders found products select
|
||||
*
|
||||
* @param foundProducts
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderFoundProducts(foundProducts) {
|
||||
Object.values(foundProducts).forEach((product) => {
|
||||
let {name} = product;
|
||||
|
||||
if (product.combinations.length === 0) {
|
||||
name += ` - ${product.formattedPrice}`;
|
||||
}
|
||||
|
||||
$(createOrderMap.productSelect).append(`<option value="${product.productId}">${name}</option>`);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans product search result fields
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
cleanSearchResults() {
|
||||
$(createOrderMap.productSelect).empty();
|
||||
$(createOrderMap.combinationsSelect).empty();
|
||||
$(createOrderMap.quantityInput).empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders combinations row with select options
|
||||
*
|
||||
* @param {Array} combinations
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderCombinations(combinations) {
|
||||
this.cleanCombinations();
|
||||
|
||||
if (combinations.length === 0) {
|
||||
this.hideCombinations();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Object.values(combinations).forEach((combination) => {
|
||||
$(createOrderMap.combinationsSelect).append(
|
||||
`<option
|
||||
value="${combination.attributeCombinationId}">
|
||||
${combination.attribute} - ${combination.formattedPrice}
|
||||
</option>`,
|
||||
);
|
||||
});
|
||||
|
||||
this.showCombinations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves weather to add customization fields to result block and adds them if needed
|
||||
*
|
||||
* @param customizationFields
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderCustomizations(customizationFields) {
|
||||
// represents customization field type "file".
|
||||
const fieldTypeFile = createOrderMap.productCustomizationFieldTypeFile;
|
||||
// represents customization field type "text".
|
||||
const fieldTypeText = createOrderMap.productCustomizationFieldTypeText;
|
||||
|
||||
this.cleanCustomizations();
|
||||
if (customizationFields.length === 0) {
|
||||
this.hideCustomizations();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const $customFieldsContainer = $(createOrderMap.productCustomFieldsContainer);
|
||||
const $fileInputTemplate = $($(createOrderMap.productCustomFileTemplate).html());
|
||||
const $textInputTemplate = $($(createOrderMap.productCustomTextTemplate).html());
|
||||
|
||||
const templateTypeMap = {
|
||||
[fieldTypeFile]: $fileInputTemplate,
|
||||
[fieldTypeText]: $textInputTemplate,
|
||||
};
|
||||
|
||||
Object.values(customizationFields).forEach((customField) => {
|
||||
const $template = templateTypeMap[customField.type].clone();
|
||||
|
||||
if (customField.type === fieldTypeFile) {
|
||||
$template.on('change', (e) => {
|
||||
const fileName = e.target.files[0].name;
|
||||
|
||||
$(e.target).next('.custom-file-label').html(fileName);
|
||||
});
|
||||
}
|
||||
|
||||
$template
|
||||
.find(createOrderMap.productCustomInput)
|
||||
.attr('name', `customizations[${customField.customizationFieldId}]`)
|
||||
.data('customization-field-id', customField.customizationFieldId);
|
||||
$template
|
||||
.find(createOrderMap.productCustomInputLabel)
|
||||
.attr('for', `customizations[${customField.customizationFieldId}]`)
|
||||
.text(customField.name);
|
||||
|
||||
if (customField.required === true) {
|
||||
$template.find(createOrderMap.requiredFieldMark).removeClass('d-none');
|
||||
}
|
||||
|
||||
$customFieldsContainer.append($template);
|
||||
});
|
||||
|
||||
this.showCustomizations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders error alert for cart block
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
renderCartBlockErrorAlert(message) {
|
||||
$(createOrderMap.cartErrorAlertText).text(message);
|
||||
this.showCartBlockError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans cart block alerts content and hides them
|
||||
*/
|
||||
cleanCartBlockAlerts() {
|
||||
$(createOrderMap.cartErrorAlertText).text('');
|
||||
this.hideCartBlockError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows error alert block of cart block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showCartBlockError() {
|
||||
$(createOrderMap.cartErrorAlertBlock).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides error alert block of cart block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideCartBlockError() {
|
||||
$(createOrderMap.cartErrorAlertBlock).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows product customization container
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showCustomizations() {
|
||||
$(createOrderMap.productCustomizationContainer).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides product customization container
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideCustomizations() {
|
||||
$(createOrderMap.productCustomizationContainer).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties customization fields container
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
cleanCustomizations() {
|
||||
$(createOrderMap.productCustomFieldsContainer).empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows result block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showResultBlock() {
|
||||
$(createOrderMap.productResultBlock).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides result block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideResultBlock() {
|
||||
$(createOrderMap.productResultBlock).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows products list
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showProductsList() {
|
||||
this.$productsTable.removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides products list
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideProductsList() {
|
||||
this.$productsTable.addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties products list
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
cleanProductsList() {
|
||||
this.$productsTable.find('tbody').empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties combinations select
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
cleanCombinations() {
|
||||
$(createOrderMap.combinationsSelect).empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows combinations row
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showCombinations() {
|
||||
$(createOrderMap.combinationsRow).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides combinations row
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideCombinations() {
|
||||
$(createOrderMap.combinationsRow).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows warning of tax included/excluded
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showTaxWarning() {
|
||||
$(createOrderMap.productTaxWarning).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides warning of tax included/excluded
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideTaxWarning() {
|
||||
$(createOrderMap.productTaxWarning).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows product not found warning
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showNotFound() {
|
||||
$(createOrderMap.noProductsFoundWarning).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides product not found warning
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideNotFound() {
|
||||
$(createOrderMap.noProductsFoundWarning).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles searching product notice
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
toggleSearchingNotice(visible) {
|
||||
$(createOrderMap.searchingProductsNotice).toggleClass('d-none', !visible);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
/**
|
||||
* 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 createOrderMap from './create-order-map';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* Manipulates UI of Shipping block in Order creation page
|
||||
*/
|
||||
export default class ShippingRenderer {
|
||||
constructor() {
|
||||
this.$container = $(createOrderMap.shippingBlock);
|
||||
this.$form = $(createOrderMap.shippingForm);
|
||||
this.$noCarrierBlock = $(createOrderMap.noCarrierBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} shipping
|
||||
* @param {Boolean} emptyCart
|
||||
*/
|
||||
render(shipping, emptyCart) {
|
||||
if (emptyCart) {
|
||||
this.hideContainer();
|
||||
} else if (shipping !== null) {
|
||||
this.displayForm(shipping);
|
||||
} else {
|
||||
this.displayNoCarriersWarning();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show form block with rendered delivery options instead of warning message
|
||||
*
|
||||
* @param shipping
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
displayForm(shipping) {
|
||||
this.hideNoCarrierBlock();
|
||||
this.renderDeliveryOptions(shipping.deliveryOptions, shipping.selectedCarrierId);
|
||||
this.renderTotalShipping(shipping.shippingPrice);
|
||||
this.renderFreeShippingSwitch(shipping.freeShipping);
|
||||
this.renderRecycledPackagingSwitch(shipping.recycledPackaging);
|
||||
this.renderGiftMessageField(shipping.giftMessage);
|
||||
this.renderGiftSwitch(shipping.gift);
|
||||
this.showForm();
|
||||
this.showContainer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders free shipping switch depending on free shipping value
|
||||
*
|
||||
* @param isFreeShipping
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderFreeShippingSwitch(isFreeShipping) {
|
||||
$(createOrderMap.freeShippingSwitch).each((key, input) => {
|
||||
if (input.value === '1') {
|
||||
input.checked = isFreeShipping;
|
||||
} else {
|
||||
input.checked = !isFreeShipping;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useRecycledPackaging
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderRecycledPackagingSwitch(useRecycledPackaging) {
|
||||
$(createOrderMap.recycledPackagingSwitch).each((key, input) => {
|
||||
if (input.value === '1') {
|
||||
input.checked = useRecycledPackaging;
|
||||
} else {
|
||||
input.checked = !useRecycledPackaging;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isAGift
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderGiftSwitch(isAGift) {
|
||||
$(createOrderMap.isAGiftSwitch).each((key, input) => {
|
||||
if (input.value === '1') {
|
||||
input.checked = isAGift;
|
||||
} else {
|
||||
input.checked = !isAGift;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param giftMessage
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderGiftMessageField(giftMessage) {
|
||||
$(createOrderMap.giftMessageField).val(giftMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show warning message that no carriers are available and hide form block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
displayNoCarriersWarning() {
|
||||
this.showContainer();
|
||||
this.hideForm();
|
||||
this.showNoCarrierBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders delivery options selection block
|
||||
*
|
||||
* @param deliveryOptions
|
||||
* @param selectedVal
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderDeliveryOptions(deliveryOptions, selectedVal) {
|
||||
const $deliveryOptionSelect = $(createOrderMap.deliveryOptionSelect);
|
||||
$deliveryOptionSelect.empty();
|
||||
|
||||
Object.values(deliveryOptions).forEach((option) => {
|
||||
const deliveryOption = {
|
||||
value: option.carrierId,
|
||||
text: `${option.carrierName} - ${option.carrierDelay}`,
|
||||
};
|
||||
|
||||
if (selectedVal === deliveryOption.value) {
|
||||
deliveryOption.selected = 'selected';
|
||||
}
|
||||
|
||||
$deliveryOptionSelect.append($('<option>', deliveryOption));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders dynamic value of shipping price
|
||||
*
|
||||
* @param shippingPrice
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
renderTotalShipping(shippingPrice) {
|
||||
const $totalShippingField = $(createOrderMap.totalShippingField);
|
||||
$totalShippingField.empty();
|
||||
|
||||
$totalShippingField.append(shippingPrice);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show whole shipping container
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showContainer() {
|
||||
this.$container.removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide whole shipping container
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideContainer() {
|
||||
this.$container.addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show form block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showForm() {
|
||||
this.$form.removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide form block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideForm() {
|
||||
this.$form.addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show warning message block which warns that no carriers are available
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showNoCarrierBlock() {
|
||||
this.$noCarrierBlock.removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide warning message block which warns that no carriers are available
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideNoCarrierBlock() {
|
||||
this.$noCarrierBlock.addClass('d-none');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* 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 {EventEmitter} from '@components/event-emitter';
|
||||
import Router from '@components/router';
|
||||
import eventMap from './event-map';
|
||||
import SummaryRenderer from './summary-renderer';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* Manages summary block
|
||||
*/
|
||||
export default class SummaryManager {
|
||||
constructor() {
|
||||
this.router = new Router();
|
||||
this.summaryRenderer = new SummaryRenderer();
|
||||
this.initListeners();
|
||||
|
||||
return {
|
||||
sendProcessOrderEmail: (cartId) => this.sendProcessOrderEmail(cartId),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Inits event listeners
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
initListeners() {
|
||||
this.onProcessOrderEmailError();
|
||||
this.onProcessOrderEmailSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for process order email sending success event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onProcessOrderEmailSuccess() {
|
||||
EventEmitter.on(eventMap.processOrderEmailSent, (response) => {
|
||||
this.summaryRenderer.cleanAlerts();
|
||||
this.summaryRenderer.renderSuccessMessage(response.message);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for process order email failed event
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onProcessOrderEmailError() {
|
||||
EventEmitter.on(eventMap.processOrderEmailFailed, (response) => {
|
||||
this.summaryRenderer.cleanAlerts();
|
||||
this.summaryRenderer.renderErrorMessage(response.responseJSON.message);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends email to customer with link of order processing
|
||||
*
|
||||
* @param {Number} cartId
|
||||
*/
|
||||
sendProcessOrderEmail(cartId) {
|
||||
$.post(this.router.generate('admin_orders_send_process_order_email'), {
|
||||
cartId,
|
||||
}).then((response) => EventEmitter.emit(eventMap.processOrderEmailSent, response)).catch((e) => {
|
||||
EventEmitter.emit(eventMap.processOrderEmailFailed, e);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* 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 createOrderMap from './create-order-map';
|
||||
import {ValidateAddresses} from './address-validator';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* Responsible for summary block rendering
|
||||
*/
|
||||
export default class SummaryRenderer {
|
||||
constructor() {
|
||||
this.$totalProducts = $(createOrderMap.summaryTotalProducts);
|
||||
this.$totalDiscount = $(createOrderMap.summaryTotalDiscount);
|
||||
this.$totalShipping = $(createOrderMap.totalShippingField);
|
||||
this.$summaryTotalShipping = $(createOrderMap.summaryTotalShipping);
|
||||
this.$totalTaxes = $(createOrderMap.summaryTotalTaxes);
|
||||
this.$totalWithoutTax = $(createOrderMap.summaryTotalWithoutTax);
|
||||
this.$totalWithTax = $(createOrderMap.summaryTotalWithTax);
|
||||
this.$placeOrderCartIdField = $(createOrderMap.placeOrderCartIdField);
|
||||
this.$orderMessageField = $(createOrderMap.orderMessageField);
|
||||
this.$processOrderLink = $(createOrderMap.processOrderLinkTag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders summary block
|
||||
*
|
||||
* @param {Object} cartInfo
|
||||
*/
|
||||
render(cartInfo) {
|
||||
this.cleanSummary();
|
||||
const noProducts = cartInfo.products.length === 0;
|
||||
const noShippingOptions = cartInfo.shipping === null;
|
||||
const addressesAreValid = ValidateAddresses(cartInfo.addresses);
|
||||
|
||||
if (noProducts || noShippingOptions || !addressesAreValid) {
|
||||
this.hideSummaryBlock();
|
||||
|
||||
return;
|
||||
}
|
||||
const cartSummary = cartInfo.summary;
|
||||
this.$totalProducts.text(cartSummary.totalProductsPrice);
|
||||
this.$totalDiscount.text(cartSummary.totalDiscount);
|
||||
this.$summaryTotalShipping.text(cartSummary.totalShippingWithoutTaxes);
|
||||
this.$totalShipping.text(cartSummary.totalShippingPrice);
|
||||
this.$totalTaxes.text(cartSummary.totalTaxes);
|
||||
this.$totalWithoutTax.text(cartSummary.totalPriceWithoutTaxes);
|
||||
this.$totalWithTax.text(cartSummary.totalPriceWithTaxes);
|
||||
this.$processOrderLink.prop('href', cartSummary.processOrderLink);
|
||||
this.$orderMessageField.text(cartSummary.orderMessage);
|
||||
this.$placeOrderCartIdField.val(cartInfo.cartId);
|
||||
|
||||
this.showSummaryBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders summary success message
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
renderSuccessMessage(message) {
|
||||
$(createOrderMap.summarySuccessAlertText).text(message);
|
||||
this.showSummarySuccessAlertBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders summary error message
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
renderErrorMessage(message) {
|
||||
$(createOrderMap.summaryErrorAlertText).text(message);
|
||||
this.showSummaryErrorAlertBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans content of success/error summary alerts and hides them
|
||||
*/
|
||||
cleanAlerts() {
|
||||
$(createOrderMap.summarySuccessAlertText).text('');
|
||||
$(createOrderMap.summaryErrorAlertText).text('');
|
||||
this.hideSummarySuccessAlertBlock();
|
||||
this.hideSummaryErrorAlertBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows summary block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showSummaryBlock() {
|
||||
$(createOrderMap.summaryBlock).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides summary block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideSummaryBlock() {
|
||||
$(createOrderMap.summaryBlock).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows error alert of summary block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showSummaryErrorAlertBlock() {
|
||||
$(createOrderMap.summaryErrorAlertBlock).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides error alert of summary block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideSummaryErrorAlertBlock() {
|
||||
$(createOrderMap.summaryErrorAlertBlock).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows success alert of summary block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
showSummarySuccessAlertBlock() {
|
||||
$(createOrderMap.summarySuccessAlertBlock).removeClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides success alert of summary block
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
hideSummarySuccessAlertBlock() {
|
||||
$(createOrderMap.summarySuccessAlertBlock).addClass('d-none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties cart summary fields
|
||||
*/
|
||||
cleanSummary() {
|
||||
this.$totalProducts.empty();
|
||||
this.$totalDiscount.empty();
|
||||
this.$totalShipping.empty();
|
||||
this.$totalTaxes.empty();
|
||||
this.$totalWithoutTax.empty();
|
||||
this.$totalWithTax.empty();
|
||||
this.$processOrderLink.prop('href', '');
|
||||
this.$orderMessageField.text('');
|
||||
this.cleanAlerts();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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 TranslatableInput from '@components/translatable-input';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
$(() => {
|
||||
new TranslatableInput();
|
||||
});
|
||||
60
admin-kalsport/themes/new-theme/js/pages/order/index.js
Normal file
60
admin-kalsport/themes/new-theme/js/pages/order/index.js
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 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 Grid from '@components/grid/grid';
|
||||
import FiltersResetExtension from '@components/grid/extension/filters-reset-extension';
|
||||
import ReloadListActionExtension from '@components/grid/extension/reload-list-extension';
|
||||
import ExportToSqlManagerExtension from '@components/grid/extension/export-to-sql-manager-extension';
|
||||
import SortingExtension from '@components/grid/extension/sorting-extension';
|
||||
import LinkRowActionExtension from '@components/grid/extension/link-row-action-extension';
|
||||
import SubmitGridExtension from '@components/grid/extension/submit-grid-action-extension';
|
||||
import SubmitBulkExtension from '@components/grid/extension/submit-bulk-action-extension';
|
||||
import BulkActionCheckboxExtension from '@components/grid/extension/bulk-action-checkbox-extension';
|
||||
import FiltersSubmitButtonEnablerExtension
|
||||
from '@components/grid/extension/filters-submit-button-enabler-extension';
|
||||
import ChoiceExtension from '@components/grid/extension/choice-extension';
|
||||
import ModalFormSubmitExtension from '@components/grid/extension/modal-form-submit-extension';
|
||||
import PreviewExtension from '@components/grid/extension/preview-extension';
|
||||
import previewProductsToggler from '@pages/order/preview-products-toggler';
|
||||
import BulkOpenTabsExtension from '@components/grid/extension/bulk-open-tabs-extension';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
$(() => {
|
||||
const orderGrid = new Grid('order');
|
||||
orderGrid.addExtension(new ReloadListActionExtension());
|
||||
orderGrid.addExtension(new ExportToSqlManagerExtension());
|
||||
orderGrid.addExtension(new FiltersResetExtension());
|
||||
orderGrid.addExtension(new SortingExtension());
|
||||
orderGrid.addExtension(new LinkRowActionExtension());
|
||||
orderGrid.addExtension(new SubmitGridExtension());
|
||||
orderGrid.addExtension(new SubmitBulkExtension());
|
||||
orderGrid.addExtension(new BulkActionCheckboxExtension());
|
||||
orderGrid.addExtension(new FiltersSubmitButtonEnablerExtension());
|
||||
orderGrid.addExtension(new ModalFormSubmitExtension());
|
||||
orderGrid.addExtension(new ChoiceExtension());
|
||||
orderGrid.addExtension(new PreviewExtension(previewProductsToggler));
|
||||
orderGrid.addExtension(new BulkOpenTabsExtension());
|
||||
});
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from './OrderViewPageMap';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* Manages adding/editing note for invoice documents.
|
||||
*/
|
||||
export default class InvoiceNoteManager {
|
||||
constructor() {
|
||||
this.setupListeners();
|
||||
}
|
||||
|
||||
setupListeners() {
|
||||
this.initShowNoteFormEventHandler();
|
||||
this.initCloseNoteFormEventHandler();
|
||||
this.initEnterPaymentEventHandler();
|
||||
}
|
||||
|
||||
initShowNoteFormEventHandler() {
|
||||
$('.js-open-invoice-note-btn').on('click', (event) => {
|
||||
event.preventDefault();
|
||||
const $btn = $(event.currentTarget);
|
||||
const $noteRow = $btn.closest('tr').next();
|
||||
|
||||
$noteRow.removeClass('d-none');
|
||||
});
|
||||
}
|
||||
|
||||
initCloseNoteFormEventHandler() {
|
||||
$('.js-cancel-invoice-note-btn').on('click', (event) => {
|
||||
$(event.currentTarget).closest('tr').addClass('d-none');
|
||||
});
|
||||
}
|
||||
|
||||
initEnterPaymentEventHandler() {
|
||||
$('.js-enter-payment-btn').on('click', (event) => {
|
||||
const $btn = $(event.currentTarget);
|
||||
const paymentAmount = $btn.data('payment-amount');
|
||||
|
||||
$(OrderViewPageMap.viewOrderPaymentsBlock).get(0).scrollIntoView({behavior: 'smooth'});
|
||||
$(OrderViewPageMap.orderPaymentFormAmountInput).val(paymentAmount);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from '../OrderViewPageMap';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* All actions for order view page messages are registered in this class.
|
||||
*/
|
||||
export default class OrderViewPageMessagesHandler {
|
||||
constructor() {
|
||||
this.$orderMessageChangeWarning = $(OrderViewPageMap.orderMessageChangeWarning);
|
||||
this.$messagesContainer = $(OrderViewPageMap.orderMessagesContainer);
|
||||
|
||||
return {
|
||||
listenForPredefinedMessageSelection: () => this.handlePredefinedMessageSelection(),
|
||||
listenForFullMessagesOpen: () => this.onFullMessagesOpen(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles predefined order message selection.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
handlePredefinedMessageSelection() {
|
||||
$(document).on('change', OrderViewPageMap.orderMessageNameSelect, (e) => {
|
||||
const $currentItem = $(e.currentTarget);
|
||||
const valueId = $currentItem.val();
|
||||
|
||||
if (!valueId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const message = this.$messagesContainer.find(`div[data-id=${valueId}]`).text().trim();
|
||||
const $orderMessage = $(OrderViewPageMap.orderMessage);
|
||||
const isSameMessage = $orderMessage.val().trim() === message;
|
||||
|
||||
if (isSameMessage) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($orderMessage.val() && !window.confirm(this.$orderMessageChangeWarning.text())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$orderMessage.val(message);
|
||||
$orderMessage.trigger('input');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for event when all messages modal is being opened
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onFullMessagesOpen() {
|
||||
$(document).on('click', OrderViewPageMap.openAllMessagesBtn, () => this.scrollToMsgListBottom());
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls down to the bottom of all messages list
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
scrollToMsgListBottom() {
|
||||
const $msgModal = $(OrderViewPageMap.allMessagesModal);
|
||||
const msgList = document.querySelector(OrderViewPageMap.allMessagesList);
|
||||
|
||||
const classCheckInterval = window.setInterval(() => {
|
||||
if ($msgModal.hasClass('show')) {
|
||||
msgList.scrollTop = msgList.scrollHeight;
|
||||
clearInterval(classCheckInterval);
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from './OrderViewPageMap';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
export default class OrderShippingManager {
|
||||
constructor() {
|
||||
this.initOrderShippingUpdateEventHandler();
|
||||
}
|
||||
|
||||
initOrderShippingUpdateEventHandler() {
|
||||
$(OrderViewPageMap.mainDiv).on('click', OrderViewPageMap.showOrderShippingUpdateModalBtn, (event) => {
|
||||
const $btn = $(event.currentTarget);
|
||||
|
||||
$(OrderViewPageMap.updateOrderShippingTrackingNumberInput).val($btn.data('order-tracking-number'));
|
||||
$(OrderViewPageMap.updateOrderShippingCurrentOrderCarrierIdInput).val($btn.data('order-carrier-id'));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* Toggles hidden products in order preview block.
|
||||
*
|
||||
* @param {jQuery} $gridContainer
|
||||
*/
|
||||
export default function previewProductsToggler($row) {
|
||||
toggleStockLocationColumn($row);
|
||||
$row.on('click', '.js-preview-more-products-btn', (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
const $btn = $(event.currentTarget);
|
||||
const $hiddenProducts = $btn.closest('tbody').find('.js-product-preview-more');
|
||||
|
||||
$hiddenProducts.removeClass('d-none');
|
||||
$btn.closest('tr').remove();
|
||||
toggleStockLocationColumn($row);
|
||||
});
|
||||
}
|
||||
|
||||
function toggleStockLocationColumn($container) {
|
||||
let showColumn = false;
|
||||
$('.js-cell-product-stock-location', $container.find('tr:not(.d-none)')).filter('td').each((index, element) => {
|
||||
if ($(element).html().trim() !== '') {
|
||||
showColumn = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
$('.js-cell-product-stock-location', $container).toggle(showColumn);
|
||||
}
|
||||
220
admin-kalsport/themes/new-theme/js/pages/order/view.js
Normal file
220
admin-kalsport/themes/new-theme/js/pages/order/view.js
Normal file
@@ -0,0 +1,220 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from '@pages/order/OrderViewPageMap';
|
||||
import OrderShippingManager from '@pages/order/order-shipping-manager';
|
||||
import InvoiceNoteManager from '@pages/order/invoice-note-manager';
|
||||
import OrderViewPage from '@pages/order/view/order-view-page';
|
||||
import OrderProductAutocomplete from '@pages/order/view/order-product-add-autocomplete';
|
||||
import OrderProductAdd from '@pages/order/view/order-product-add';
|
||||
import TextWithLengthCounter from '@components/form/text-with-length-counter';
|
||||
import OrderViewPageMessagesHandler from './message/order-view-page-messages-handler';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
$(() => {
|
||||
const DISCOUNT_TYPE_AMOUNT = 'amount';
|
||||
const DISCOUNT_TYPE_PERCENT = 'percent';
|
||||
const DISCOUNT_TYPE_FREE_SHIPPING = 'free_shipping';
|
||||
|
||||
new OrderShippingManager();
|
||||
new TextWithLengthCounter();
|
||||
const orderViewPage = new OrderViewPage();
|
||||
const orderAddAutocomplete = new OrderProductAutocomplete($(OrderViewPageMap.productSearchInput));
|
||||
const orderAdd = new OrderProductAdd();
|
||||
|
||||
orderViewPage.listenForProductPack();
|
||||
orderViewPage.listenForProductDelete();
|
||||
orderViewPage.listenForProductEdit();
|
||||
orderViewPage.listenForProductAdd();
|
||||
orderViewPage.listenForProductPagination();
|
||||
orderViewPage.listenForRefund();
|
||||
orderViewPage.listenForCancelProduct();
|
||||
|
||||
orderAddAutocomplete.listenForSearch();
|
||||
orderAddAutocomplete.onItemClickedCallback = (product) => orderAdd.setProduct(product);
|
||||
|
||||
handlePaymentDetailsToggle();
|
||||
handlePrivateNoteChange();
|
||||
handleOrderNoteChange();
|
||||
handleUpdateOrderStatusButton();
|
||||
|
||||
new InvoiceNoteManager();
|
||||
const orderViewPageMessageHandler = new OrderViewPageMessagesHandler();
|
||||
orderViewPageMessageHandler.listenForPredefinedMessageSelection();
|
||||
orderViewPageMessageHandler.listenForFullMessagesOpen();
|
||||
$(OrderViewPageMap.privateNoteToggleBtn).on('click', (event) => {
|
||||
event.preventDefault();
|
||||
togglePrivateNoteBlock();
|
||||
});
|
||||
|
||||
$(OrderViewPageMap.orderNoteToggleBtn).on('click', (event) => {
|
||||
event.preventDefault();
|
||||
toggleOrderNoteBlock();
|
||||
});
|
||||
|
||||
$(OrderViewPageMap.printOrderViewPageButton).on('click', () => {
|
||||
const tempTitle = document.title;
|
||||
document.title = $(OrderViewPageMap.mainDiv).data('orderTitle');
|
||||
window.print();
|
||||
document.title = tempTitle;
|
||||
});
|
||||
|
||||
initAddCartRuleFormHandler();
|
||||
initChangeAddressFormHandler();
|
||||
initHookTabs();
|
||||
|
||||
function initHookTabs() {
|
||||
$(OrderViewPageMap.orderHookTabsContainer)
|
||||
.find('.nav-tabs li:first-child a')
|
||||
.tab('show');
|
||||
}
|
||||
|
||||
function handlePaymentDetailsToggle() {
|
||||
$(OrderViewPageMap.orderPaymentDetailsBtn).on('click', (event) => {
|
||||
const $paymentDetailRow = $(event.currentTarget)
|
||||
.closest('tr')
|
||||
.next(':first');
|
||||
|
||||
$paymentDetailRow.toggleClass('d-none');
|
||||
});
|
||||
}
|
||||
|
||||
function togglePrivateNoteBlock() {
|
||||
const $block = $(OrderViewPageMap.privateNoteBlock);
|
||||
const $btn = $(OrderViewPageMap.privateNoteToggleBtn);
|
||||
const isPrivateNoteOpened = $btn.hasClass('is-opened');
|
||||
|
||||
if (isPrivateNoteOpened) {
|
||||
$btn.removeClass('is-opened');
|
||||
$block.addClass('d-none');
|
||||
} else {
|
||||
$btn.addClass('is-opened');
|
||||
$block.removeClass('d-none');
|
||||
}
|
||||
|
||||
const $icon = $btn.find('.material-icons');
|
||||
$icon.text(isPrivateNoteOpened ? 'add' : 'remove');
|
||||
}
|
||||
|
||||
function handlePrivateNoteChange() {
|
||||
const $submitBtn = $(OrderViewPageMap.privateNoteSubmitBtn);
|
||||
|
||||
$(OrderViewPageMap.privateNoteInput).on('input', () => {
|
||||
$submitBtn.prop('disabled', false);
|
||||
});
|
||||
}
|
||||
|
||||
function toggleOrderNoteBlock() {
|
||||
const $block = $(OrderViewPageMap.orderNoteBlock);
|
||||
const $btn = $(OrderViewPageMap.orderNoteToggleBtn);
|
||||
const isNoteOpened = $btn.hasClass('is-opened');
|
||||
|
||||
$btn.toggleClass('is-opened', !isNoteOpened);
|
||||
$block.toggleClass('d-none', isNoteOpened);
|
||||
|
||||
const $icon = $btn.find('.material-icons');
|
||||
$icon.text(isNoteOpened ? 'add' : 'remove');
|
||||
}
|
||||
|
||||
function handleOrderNoteChange() {
|
||||
const $submitBtn = $(OrderViewPageMap.orderNoteSubmitBtn);
|
||||
|
||||
$(OrderViewPageMap.orderNoteInput).on('input', () => {
|
||||
$submitBtn.prop('disabled', false);
|
||||
});
|
||||
}
|
||||
|
||||
function initAddCartRuleFormHandler() {
|
||||
const $modal = $(OrderViewPageMap.addCartRuleModal);
|
||||
const $form = $modal.find('form');
|
||||
const $invoiceSelect = $modal.find(OrderViewPageMap.addCartRuleInvoiceIdSelect);
|
||||
const $valueHelp = $modal.find(OrderViewPageMap.cartRuleHelpText);
|
||||
const $valueInput = $form.find(OrderViewPageMap.addCartRuleValueInput);
|
||||
const $valueFormGroup = $valueInput.closest('.form-group');
|
||||
|
||||
$modal.on('shown.bs.modal', () => {
|
||||
$(OrderViewPageMap.addCartRuleSubmit).attr('disabled', true);
|
||||
});
|
||||
|
||||
$form.find(OrderViewPageMap.addCartRuleNameInput).on('keyup', (event) => {
|
||||
const cartRuleName = $(event.currentTarget).val();
|
||||
$(OrderViewPageMap.addCartRuleSubmit).attr('disabled', cartRuleName.trim().length === 0);
|
||||
});
|
||||
|
||||
$form.find(OrderViewPageMap.addCartRuleApplyOnAllInvoicesCheckbox).on('change', (event) => {
|
||||
const isChecked = $(event.currentTarget).is(':checked');
|
||||
$invoiceSelect.attr('disabled', isChecked);
|
||||
});
|
||||
|
||||
$form.find(OrderViewPageMap.addCartRuleTypeSelect).on('change', (event) => {
|
||||
const selectedCartRuleType = $(event.currentTarget).val();
|
||||
const $valueUnit = $form.find(OrderViewPageMap.addCartRuleValueUnit);
|
||||
|
||||
if (selectedCartRuleType === DISCOUNT_TYPE_AMOUNT) {
|
||||
$valueHelp.removeClass('d-none');
|
||||
$valueUnit.html($valueUnit.data('currencySymbol'));
|
||||
} else {
|
||||
$valueHelp.addClass('d-none');
|
||||
}
|
||||
|
||||
if (selectedCartRuleType === DISCOUNT_TYPE_PERCENT) {
|
||||
$valueUnit.html('%');
|
||||
}
|
||||
|
||||
if (selectedCartRuleType === DISCOUNT_TYPE_FREE_SHIPPING) {
|
||||
$valueFormGroup.addClass('d-none');
|
||||
$valueInput.attr('disabled', true);
|
||||
} else {
|
||||
$valueFormGroup.removeClass('d-none');
|
||||
$valueInput.attr('disabled', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleUpdateOrderStatusButton() {
|
||||
const $btn = $(OrderViewPageMap.updateOrderStatusActionBtn);
|
||||
const $wrapper = $(OrderViewPageMap.updateOrderStatusActionInputWrapper);
|
||||
|
||||
$(OrderViewPageMap.updateOrderStatusActionInput).on('change', (event) => {
|
||||
const $element = $(event.currentTarget);
|
||||
const $option = $('option:selected', $element);
|
||||
const selectedOrderStatusId = $element.val();
|
||||
|
||||
$wrapper.css('background-color', $option.data('background-color'));
|
||||
$wrapper.toggleClass('is-bright', $option.data('is-bright') !== undefined);
|
||||
|
||||
$btn.prop('disabled', parseInt(selectedOrderStatusId, 10) === $btn.data('orderStatusId'));
|
||||
});
|
||||
}
|
||||
|
||||
function initChangeAddressFormHandler() {
|
||||
const $modal = $(OrderViewPageMap.updateCustomerAddressModal);
|
||||
|
||||
$(OrderViewPageMap.openOrderAddressUpdateModalBtn).on('click', (event) => {
|
||||
$modal.find(OrderViewPageMap.updateOrderAddressTypeInput).val($(event.currentTarget).data('addressType'));
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from '@pages/order/OrderViewPageMap';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
export default class OrderDiscountsRefresher {
|
||||
constructor() {
|
||||
this.router = new Router();
|
||||
}
|
||||
|
||||
refresh(orderId) {
|
||||
$.ajax(this.router.generate('admin_orders_get_discounts', {orderId}))
|
||||
.then((response) => {
|
||||
$(OrderViewPageMap.productDiscountList.list).replaceWith(response);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from '@pages/order/OrderViewPageMap';
|
||||
import InvoiceNoteManager from '../invoice-note-manager';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
export default class OrderDocumentsRefresher {
|
||||
constructor() {
|
||||
this.router = new Router();
|
||||
this.invoiceNoteManager = new InvoiceNoteManager();
|
||||
}
|
||||
|
||||
refresh(orderId) {
|
||||
$.getJSON(this.router.generate('admin_orders_get_documents', {orderId}))
|
||||
.then((response) => {
|
||||
$(OrderViewPageMap.orderDocumentsTabCount).text(response.total);
|
||||
$(OrderViewPageMap.orderDocumentsTabBody).html(response.html);
|
||||
this.invoiceNoteManager.setupListeners();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from '@pages/order/OrderViewPageMap';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
export default class OrderInvoicesRefresher {
|
||||
constructor() {
|
||||
this.router = new Router();
|
||||
}
|
||||
|
||||
refresh(orderId) {
|
||||
$.getJSON(this.router.generate('admin_orders_get_invoices', {orderId}))
|
||||
.then((response) => {
|
||||
if (!response || !response.invoices || Object.keys(response.invoices).length <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const $paymentInvoiceSelect = $(OrderViewPageMap.orderPaymentInvoiceSelect);
|
||||
const $addProductInvoiceSelect = $(OrderViewPageMap.productAddInvoiceSelect);
|
||||
const $existingInvoicesGroup = $addProductInvoiceSelect.find('optgroup:first');
|
||||
const $productEditInvoiceSelect = $(OrderViewPageMap.productEditInvoiceSelect);
|
||||
const $addDiscountInvoiceSelect = $(OrderViewPageMap.addCartRuleInvoiceIdSelect);
|
||||
$existingInvoicesGroup.empty();
|
||||
$paymentInvoiceSelect.empty();
|
||||
$productEditInvoiceSelect.empty();
|
||||
$addDiscountInvoiceSelect.empty();
|
||||
|
||||
Object.keys(response.invoices).forEach((invoiceName) => {
|
||||
const invoiceId = response.invoices[invoiceName];
|
||||
const invoiceNameWithoutPrice = invoiceName.split(' - ')[0];
|
||||
|
||||
$existingInvoicesGroup.append(`<option value="${invoiceId}">${invoiceNameWithoutPrice}</option>`);
|
||||
$paymentInvoiceSelect.append(`<option value="${invoiceId}">${invoiceNameWithoutPrice}</option>`);
|
||||
$productEditInvoiceSelect.append(`<option value="${invoiceId}">${invoiceNameWithoutPrice}</option>`);
|
||||
$addDiscountInvoiceSelect.append(`<option value="${invoiceId}">${invoiceName}</option>`);
|
||||
});
|
||||
|
||||
document.querySelector(OrderViewPageMap.productAddInvoiceSelect).selectedIndex = 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from '@pages/order/OrderViewPageMap';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
export default class OrderPaymentsRefresher {
|
||||
constructor() {
|
||||
this.router = new Router();
|
||||
}
|
||||
|
||||
refresh(orderId) {
|
||||
$.ajax(this.router.generate('admin_orders_get_payments', {orderId}))
|
||||
.then(
|
||||
(response) => {
|
||||
$(OrderViewPageMap.viewOrderPaymentsAlert).remove();
|
||||
$(`${OrderViewPageMap.viewOrderPaymentsBlock} .card-body`).prepend(response);
|
||||
},
|
||||
(response) => {
|
||||
if (response.responseJSON && response.responseJSON.message) {
|
||||
$.growl.error({message: response.responseJSON.message});
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from '@pages/order/OrderViewPageMap';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
export default class OrderPricesRefresher {
|
||||
constructor() {
|
||||
this.router = new Router();
|
||||
}
|
||||
|
||||
refresh(orderId) {
|
||||
$.getJSON(this.router.generate('admin_orders_get_prices', {orderId})).then((response) => {
|
||||
$(OrderViewPageMap.orderTotal).text(response.orderTotalFormatted);
|
||||
$(OrderViewPageMap.orderDiscountsTotal).text(`-${response.discountsAmountFormatted}`);
|
||||
$(OrderViewPageMap.orderDiscountsTotalContainer).toggleClass('d-none', !response.discountsAmountDisplayed);
|
||||
$(OrderViewPageMap.orderProductsTotal).text(response.productsTotalFormatted);
|
||||
$(OrderViewPageMap.orderShippingTotal).text(response.shippingTotalFormatted);
|
||||
$(OrderViewPageMap.orderShippingTotalContainer).toggleClass('d-none', !response.shippingTotalDisplayed);
|
||||
$(OrderViewPageMap.orderTaxesTotal).text(response.taxesTotalFormatted);
|
||||
});
|
||||
}
|
||||
|
||||
refreshProductPrices(orderId) {
|
||||
$.getJSON(this.router.generate('admin_orders_product_prices', {orderId})).then((productPricesList) => {
|
||||
productPricesList.forEach((productPrices) => {
|
||||
const orderProductTrId = OrderViewPageMap.productsTableRow(productPrices.orderDetailId);
|
||||
let $quantity = $(productPrices.quantity);
|
||||
|
||||
if (productPrices.quantity > 1) {
|
||||
$quantity = $quantity.wrap('<span class="badge badge-secondary rounded-circle"></span>');
|
||||
}
|
||||
|
||||
$(`${orderProductTrId} ${OrderViewPageMap.productEditUnitPrice}`).text(productPrices.unitPrice);
|
||||
$(`${orderProductTrId} ${OrderViewPageMap.productEditQuantity}`).html($quantity.html());
|
||||
$(`${orderProductTrId} ${OrderViewPageMap.productEditAvailableQuantity}`).text(productPrices.availableQuantity);
|
||||
$(`${orderProductTrId} ${OrderViewPageMap.productEditTotalPrice}`).text(productPrices.totalPrice);
|
||||
|
||||
// update order row price values
|
||||
const productEditButton = $(OrderViewPageMap.productEditBtn(productPrices.orderDetailId));
|
||||
|
||||
productEditButton.data('product-price-tax-incl', productPrices.unitPriceTaxInclRaw);
|
||||
productEditButton.data('product-price-tax-excl', productPrices.unitPriceTaxExclRaw);
|
||||
productEditButton.data('product-quantity', productPrices.quantity);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will check if the same product is already present in the order
|
||||
* and if so and if the price of the 2 products doesn't match will return either
|
||||
* 'invoice' if the 2 products are in 2 different invoices or 'product' if the 2 products
|
||||
* are in the same invoice (or no invoice yet). Only products that have different customizations
|
||||
* can be twice in a same invoice.
|
||||
* Will return null if no matching products are found.
|
||||
*/
|
||||
checkOtherProductPricesMatch(givenPrice, productId, combinationId, invoiceId, orderDetailId) {
|
||||
const productRows = document.querySelectorAll('tr.cellProduct');
|
||||
// We convert the expected values into int/float to avoid a type mismatch that would be wrongly interpreted
|
||||
const expectedProductId = Number(productId);
|
||||
const expectedCombinationId = Number(combinationId);
|
||||
const expectedGivenPrice = Number(givenPrice);
|
||||
let unmatchingInvoicePriceExists = false;
|
||||
let unmatchingProductPriceExists = false;
|
||||
|
||||
productRows.forEach((productRow) => {
|
||||
const productRowId = $(productRow).attr('id');
|
||||
|
||||
// No need to check edited row (especially if it's the only one for this product)
|
||||
if (orderDetailId && productRowId === `orderProduct_${orderDetailId}`) {
|
||||
return;
|
||||
}
|
||||
|
||||
const productEditBtn = $(`#${productRowId} ${OrderViewPageMap.productEditButtons}`);
|
||||
const currentOrderInvoiceId = Number(productEditBtn.data('order-invoice-id'));
|
||||
|
||||
const currentProductId = Number(productEditBtn.data('product-id'));
|
||||
const currentCombinationId = Number(productEditBtn.data('combination-id'));
|
||||
|
||||
if (currentProductId !== expectedProductId || currentCombinationId !== expectedCombinationId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (expectedGivenPrice !== Number(productEditBtn.data('product-price-tax-incl'))) {
|
||||
if (invoiceId === '' || (invoiceId && currentOrderInvoiceId && invoiceId === currentOrderInvoiceId)) {
|
||||
unmatchingProductPriceExists = true;
|
||||
} else {
|
||||
unmatchingInvoicePriceExists = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (unmatchingInvoicePriceExists) {
|
||||
return 'invoice';
|
||||
}
|
||||
if (unmatchingProductPriceExists) {
|
||||
return 'product';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
|
||||
export default class OrderPrices {
|
||||
calculateTaxExcluded(taxIncluded, taxRatePerCent, currencyPrecision) {
|
||||
let priceTaxIncl = parseFloat(taxIncluded);
|
||||
|
||||
if (priceTaxIncl < 0 || Number.isNaN(priceTaxIncl)) {
|
||||
priceTaxIncl = 0;
|
||||
}
|
||||
const taxRate = taxRatePerCent / 100 + 1;
|
||||
|
||||
return window.ps_round(priceTaxIncl / taxRate, currencyPrecision);
|
||||
}
|
||||
|
||||
calculateTaxIncluded(taxExcluded, taxRatePerCent, currencyPrecision) {
|
||||
let priceTaxExcl = parseFloat(taxExcluded);
|
||||
|
||||
if (priceTaxExcl < 0 || Number.isNaN(priceTaxExcl)) {
|
||||
priceTaxExcl = 0;
|
||||
}
|
||||
const taxRate = taxRatePerCent / 100 + 1;
|
||||
|
||||
return window.ps_round(priceTaxExcl * taxRate, currencyPrecision);
|
||||
}
|
||||
|
||||
calculateTotalPrice(quantity, unitPrice, currencyPrecision) {
|
||||
return window.ps_round(unitPrice * quantity, currencyPrecision);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from '@pages/order/OrderViewPageMap';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
export default class OrderProductAutocomplete {
|
||||
constructor(input) {
|
||||
this.activeSearchRequest = null;
|
||||
this.router = new Router();
|
||||
this.input = input;
|
||||
this.results = [];
|
||||
this.dropdownMenu = $(OrderViewPageMap.productSearchInputAutocompleteMenu);
|
||||
/**
|
||||
* Permit to link to each value of dropdown a callback after item is clicked
|
||||
*/
|
||||
this.onItemClickedCallback = () => {};
|
||||
}
|
||||
|
||||
listenForSearch() {
|
||||
this.input.on('click', (event) => {
|
||||
event.stopImmediatePropagation();
|
||||
this.updateResults(this.results);
|
||||
});
|
||||
|
||||
this.input.on('keyup', (event) => this.delaySearch(event.currentTarget));
|
||||
$(document).on('click', () => this.dropdownMenu.hide());
|
||||
}
|
||||
|
||||
delaySearch(input) {
|
||||
clearTimeout(this.searchTimeoutId);
|
||||
|
||||
// Search only if the search phrase length is greater than 2 characters
|
||||
if (input.value.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.searchTimeoutId = setTimeout(() => {
|
||||
this.search(input.value, $(input).data('currency'), $(input).data('order'));
|
||||
}, 300);
|
||||
}
|
||||
|
||||
search(search, currency, orderId) {
|
||||
const params = {search_phrase: search};
|
||||
|
||||
if (currency) {
|
||||
params.currency_id = currency;
|
||||
}
|
||||
|
||||
if (orderId) {
|
||||
params.order_id = orderId;
|
||||
}
|
||||
|
||||
if (this.activeSearchRequest !== null) {
|
||||
this.activeSearchRequest.abort();
|
||||
}
|
||||
|
||||
this.activeSearchRequest = $.get(this.router.generate('admin_orders_products_search', params));
|
||||
this.activeSearchRequest
|
||||
.then((response) => this.updateResults(response))
|
||||
.always(() => {
|
||||
this.activeSearchRequest = null;
|
||||
});
|
||||
}
|
||||
|
||||
updateResults(results) {
|
||||
this.dropdownMenu.empty();
|
||||
|
||||
if (!results || !results.products || Object.keys(results.products).length <= 0) {
|
||||
this.dropdownMenu.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
this.results = results.products;
|
||||
|
||||
Object.values(this.results).forEach((val) => {
|
||||
const link = $(`<a class="dropdown-item" data-id="${val.productId}" href="#">${val.name}</a>`);
|
||||
|
||||
link.on('click', (event) => {
|
||||
event.preventDefault();
|
||||
this.onItemClicked($(event.target).data('id'));
|
||||
});
|
||||
|
||||
this.dropdownMenu.append(link);
|
||||
});
|
||||
|
||||
this.dropdownMenu.show();
|
||||
}
|
||||
|
||||
onItemClicked(id) {
|
||||
const selectedProduct = this.results.filter((product) => product.productId === id);
|
||||
|
||||
if (selectedProduct.length !== 0) {
|
||||
this.input.val(selectedProduct[0].name);
|
||||
this.onItemClickedCallback(selectedProduct[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from '@pages/order/OrderViewPageMap';
|
||||
import {EventEmitter} from '@components/event-emitter';
|
||||
import OrderViewEventMap from '@pages/order/view/order-view-event-map';
|
||||
import OrderPrices from '@pages/order/view/order-prices';
|
||||
import OrderProductRenderer from '@pages/order/view/order-product-renderer';
|
||||
import ConfirmModal from '@components/modal';
|
||||
import OrderPricesRefresher from '@pages/order/view/order-prices-refresher';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
export default class OrderProductAdd {
|
||||
constructor() {
|
||||
this.router = new Router();
|
||||
this.productAddActionBtn = $(OrderViewPageMap.productAddActionBtn);
|
||||
this.productIdInput = $(OrderViewPageMap.productAddIdInput);
|
||||
this.combinationsBlock = $(OrderViewPageMap.productAddCombinationsBlock);
|
||||
this.combinationsSelect = $(OrderViewPageMap.productAddCombinationsSelect);
|
||||
this.priceTaxIncludedInput = $(OrderViewPageMap.productAddPriceTaxInclInput);
|
||||
this.priceTaxExcludedInput = $(OrderViewPageMap.productAddPriceTaxExclInput);
|
||||
this.taxRateInput = $(OrderViewPageMap.productAddTaxRateInput);
|
||||
this.quantityInput = $(OrderViewPageMap.productAddQuantityInput);
|
||||
this.availableText = $(OrderViewPageMap.productAddAvailableText);
|
||||
this.locationText = $(OrderViewPageMap.productAddLocationText);
|
||||
this.totalPriceText = $(OrderViewPageMap.productAddTotalPriceText);
|
||||
this.invoiceSelect = $(OrderViewPageMap.productAddInvoiceSelect);
|
||||
this.freeShippingSelect = $(OrderViewPageMap.productAddFreeShippingSelect);
|
||||
this.productAddMenuBtn = $(OrderViewPageMap.productAddBtn);
|
||||
this.available = null;
|
||||
this.setupListener();
|
||||
this.product = {};
|
||||
this.currencyPrecision = $(OrderViewPageMap.productsTable).data('currencyPrecision');
|
||||
this.priceTaxCalculator = new OrderPrices();
|
||||
this.orderProductRenderer = new OrderProductRenderer();
|
||||
this.orderPricesRefresher = new OrderPricesRefresher();
|
||||
this.isOrderTaxIncluded = $(OrderViewPageMap.productAddRow).data('isOrderTaxIncluded');
|
||||
this.taxExcluded = null;
|
||||
this.taxIncluded = null;
|
||||
}
|
||||
|
||||
setupListener() {
|
||||
this.combinationsSelect.on('change', (event) => {
|
||||
const taxExcluded = window.ps_round(
|
||||
$(event.currentTarget)
|
||||
.find(':selected')
|
||||
.data('priceTaxExcluded'),
|
||||
this.currencyPrecision,
|
||||
);
|
||||
this.priceTaxExcludedInput.val(taxExcluded);
|
||||
this.taxExcluded = parseFloat(taxExcluded);
|
||||
|
||||
const taxIncluded = window.ps_round(
|
||||
$(event.currentTarget)
|
||||
.find(':selected')
|
||||
.data('priceTaxIncluded'),
|
||||
this.currencyPrecision,
|
||||
);
|
||||
this.priceTaxIncludedInput.val(taxIncluded);
|
||||
this.taxIncluded = parseFloat(taxIncluded);
|
||||
|
||||
this.locationText.html(
|
||||
$(event.currentTarget)
|
||||
.find(':selected')
|
||||
.data('location'),
|
||||
);
|
||||
|
||||
this.available = $(event.currentTarget)
|
||||
.find(':selected')
|
||||
.data('stock');
|
||||
|
||||
this.quantityInput.trigger('change');
|
||||
this.orderProductRenderer.toggleColumn(OrderViewPageMap.productsCellLocation);
|
||||
});
|
||||
|
||||
this.quantityInput.on('change keyup', (event) => {
|
||||
if (this.available !== null) {
|
||||
const newQuantity = Number(event.target.value);
|
||||
const remainingAvailable = this.available - newQuantity;
|
||||
const availableOutOfStock = this.availableText.data('availableOutOfStock');
|
||||
this.availableText.text(remainingAvailable);
|
||||
this.availableText.toggleClass('text-danger font-weight-bold', remainingAvailable < 0);
|
||||
const disableAddActionBtn = newQuantity <= 0 || (remainingAvailable < 0 && !availableOutOfStock);
|
||||
this.productAddActionBtn.prop('disabled', disableAddActionBtn);
|
||||
this.invoiceSelect.prop('disabled', !availableOutOfStock && remainingAvailable < 0);
|
||||
|
||||
this.taxIncluded = parseFloat(this.priceTaxIncludedInput.val());
|
||||
this.totalPriceText.html(
|
||||
this.priceTaxCalculator.calculateTotalPrice(
|
||||
newQuantity,
|
||||
this.isOrderTaxIncluded ? this.taxIncluded : this.taxExcluded,
|
||||
this.currencyPrecision,
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
this.productIdInput.on('change', () => {
|
||||
this.productAddActionBtn.removeAttr('disabled');
|
||||
this.invoiceSelect.removeAttr('disabled');
|
||||
});
|
||||
|
||||
this.priceTaxIncludedInput.on('change keyup', (event) => {
|
||||
this.taxIncluded = parseFloat(event.target.value);
|
||||
this.taxExcluded = this.priceTaxCalculator.calculateTaxExcluded(
|
||||
this.taxIncluded,
|
||||
this.taxRateInput.val(),
|
||||
this.currencyPrecision,
|
||||
);
|
||||
const quantity = parseInt(this.quantityInput.val(), 10);
|
||||
|
||||
this.priceTaxExcludedInput.val(this.taxExcluded);
|
||||
this.totalPriceText.html(
|
||||
this.priceTaxCalculator.calculateTotalPrice(
|
||||
quantity,
|
||||
this.isOrderTaxIncluded ? this.taxIncluded : this.taxExcluded,
|
||||
this.currencyPrecision,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
this.priceTaxExcludedInput.on('change keyup', (event) => {
|
||||
this.taxExcluded = parseFloat(event.target.value);
|
||||
this.taxIncluded = this.priceTaxCalculator.calculateTaxIncluded(
|
||||
this.taxExcluded,
|
||||
this.taxRateInput.val(),
|
||||
this.currencyPrecision,
|
||||
);
|
||||
const quantity = parseInt(this.quantityInput.val(), 10);
|
||||
|
||||
this.priceTaxIncludedInput.val(this.taxIncluded);
|
||||
this.totalPriceText.html(
|
||||
this.priceTaxCalculator.calculateTotalPrice(
|
||||
quantity,
|
||||
this.isOrderTaxIncluded ? this.taxIncluded : this.taxExcluded,
|
||||
this.currencyPrecision,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
this.productAddActionBtn.on('click', (event) => this.confirmNewInvoice(event));
|
||||
this.invoiceSelect.on('change', () => this.orderProductRenderer.toggleProductAddNewInvoiceInfo());
|
||||
}
|
||||
|
||||
setProduct(product) {
|
||||
this.productIdInput.val(product.productId).trigger('change');
|
||||
|
||||
const taxExcluded = window.ps_round(product.priceTaxExcl, this.currencyPrecision);
|
||||
this.priceTaxExcludedInput.val(taxExcluded);
|
||||
this.taxExcluded = parseFloat(taxExcluded);
|
||||
|
||||
const taxIncluded = window.ps_round(product.priceTaxIncl, this.currencyPrecision);
|
||||
this.priceTaxIncludedInput.val(taxIncluded);
|
||||
this.taxIncluded = parseFloat(taxIncluded);
|
||||
|
||||
this.taxRateInput.val(product.taxRate);
|
||||
this.locationText.html(product.location);
|
||||
this.available = product.stock;
|
||||
this.availableText.data('availableOutOfStock', product.availableOutOfStock);
|
||||
this.quantityInput.val(1);
|
||||
this.quantityInput.trigger('change');
|
||||
this.setCombinations(product.combinations);
|
||||
this.orderProductRenderer.toggleColumn(OrderViewPageMap.productsCellLocation);
|
||||
}
|
||||
|
||||
setCombinations(combinations) {
|
||||
this.combinationsSelect.empty();
|
||||
|
||||
Object.values(combinations).forEach((val) => {
|
||||
this.combinationsSelect.append(
|
||||
/* eslint-disable-next-line max-len */
|
||||
`<option value="${val.attributeCombinationId}" data-price-tax-excluded="${val.priceTaxExcluded}" data-price-tax-included="${val.priceTaxIncluded}" data-stock="${val.stock}" data-location="${val.location}">${val.attribute}</option>`,
|
||||
);
|
||||
});
|
||||
|
||||
this.combinationsBlock.toggleClass('d-none', Object.keys(combinations).length === 0);
|
||||
|
||||
if (Object.keys(combinations).length > 0) {
|
||||
this.combinationsSelect.trigger('change');
|
||||
}
|
||||
}
|
||||
|
||||
addProduct(orderId) {
|
||||
this.productAddActionBtn.prop('disabled', true);
|
||||
this.invoiceSelect.prop('disabled', true);
|
||||
this.combinationsSelect.prop('disabled', true);
|
||||
|
||||
const params = {
|
||||
product_id: this.productIdInput.val(),
|
||||
combination_id: $(':selected', this.combinationsSelect).val(),
|
||||
price_tax_incl: this.priceTaxIncludedInput.val(),
|
||||
price_tax_excl: this.priceTaxExcludedInput.val(),
|
||||
quantity: this.quantityInput.val(),
|
||||
invoice_id: this.invoiceSelect.val(),
|
||||
free_shipping: this.freeShippingSelect.prop('checked'),
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: this.router.generate('admin_orders_add_product', {orderId}),
|
||||
method: 'POST',
|
||||
data: params,
|
||||
}).then(
|
||||
(response) => {
|
||||
EventEmitter.emit(OrderViewEventMap.productAddedToOrder, {
|
||||
orderId,
|
||||
orderProductId: params.product_id,
|
||||
newRow: response,
|
||||
});
|
||||
},
|
||||
(response) => {
|
||||
this.productAddActionBtn.prop('disabled', false);
|
||||
this.invoiceSelect.prop('disabled', false);
|
||||
this.combinationsSelect.prop('disabled', false);
|
||||
|
||||
if (response.responseJSON && response.responseJSON.message) {
|
||||
$.growl.error({message: response.responseJSON.message});
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
confirmNewInvoice(event) {
|
||||
const invoiceId = parseInt(this.invoiceSelect.val(), 10);
|
||||
const orderId = $(event.currentTarget).data('orderId');
|
||||
|
||||
// Explicit 0 value is used when we the user selected New Invoice
|
||||
if (invoiceId === 0) {
|
||||
const modal = new ConfirmModal(
|
||||
{
|
||||
id: 'modal-confirm-new-invoice',
|
||||
confirmTitle: this.invoiceSelect.data('modal-title'),
|
||||
confirmMessage: this.invoiceSelect.data('modal-body'),
|
||||
confirmButtonLabel: this.invoiceSelect.data('modal-apply'),
|
||||
closeButtonLabel: this.invoiceSelect.data('modal-cancel'),
|
||||
},
|
||||
() => {
|
||||
this.confirmNewPrice(orderId, invoiceId);
|
||||
},
|
||||
);
|
||||
modal.show();
|
||||
} else {
|
||||
// Last case is Nan, the selector is not even present, we simply add product and let the BO handle it
|
||||
this.addProduct(orderId);
|
||||
}
|
||||
}
|
||||
|
||||
confirmNewPrice(orderId, invoiceId) {
|
||||
const combinationValue = $(':selected', this.combinationsSelect).val();
|
||||
const combinationId = typeof combinationValue === 'undefined' ? 0 : combinationValue;
|
||||
const productPriceMatch = this.orderPricesRefresher.checkOtherProductPricesMatch(
|
||||
this.priceTaxIncludedInput.val(),
|
||||
this.productIdInput.val(),
|
||||
combinationId,
|
||||
invoiceId,
|
||||
);
|
||||
|
||||
if (productPriceMatch === 'invoice') {
|
||||
const modalEditPrice = new ConfirmModal(
|
||||
{
|
||||
id: 'modal-confirm-new-price',
|
||||
confirmTitle: this.invoiceSelect.data('modal-edit-price-title'),
|
||||
confirmMessage: this.invoiceSelect.data('modal-edit-price-body'),
|
||||
confirmButtonLabel: this.invoiceSelect.data('modal-edit-price-apply'),
|
||||
closeButtonLabel: this.invoiceSelect.data('modal-edit-price-cancel'),
|
||||
},
|
||||
() => {
|
||||
this.addProduct(orderId);
|
||||
},
|
||||
);
|
||||
modalEditPrice.show();
|
||||
} else {
|
||||
this.addProduct(orderId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from '@pages/order/OrderViewPageMap';
|
||||
import {NumberFormatter} from '@app/cldr';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
/**
|
||||
* manages all product cancel actions, that includes all refund operations
|
||||
*/
|
||||
export default class OrderProductCancel {
|
||||
constructor() {
|
||||
this.router = new Router();
|
||||
this.cancelProductForm = $(OrderViewPageMap.cancelProduct.form);
|
||||
this.orderId = this.cancelProductForm.data('orderId');
|
||||
this.orderDelivered = parseInt(this.cancelProductForm.data('isDelivered'), 10) === 1;
|
||||
this.isTaxIncluded = parseInt(this.cancelProductForm.data('isTaxIncluded'), 10) === 1;
|
||||
this.discountsAmount = parseFloat(this.cancelProductForm.data('discountsAmount'));
|
||||
this.currencyFormatter = NumberFormatter.build(
|
||||
this.cancelProductForm.data('priceSpecification'),
|
||||
);
|
||||
this.useAmountInputs = true;
|
||||
this.listenForInputs();
|
||||
}
|
||||
|
||||
showPartialRefund() {
|
||||
// Always start by hiding elements then show the others, since some elements are common
|
||||
this.hideCancelElements();
|
||||
$(OrderViewPageMap.cancelProduct.toggle.partialRefund).show();
|
||||
this.useAmountInputs = true;
|
||||
this.initForm(
|
||||
$(OrderViewPageMap.cancelProduct.buttons.save).data('partialRefundLabel'),
|
||||
this.router.generate('admin_orders_partial_refund', {
|
||||
orderId: this.orderId,
|
||||
}),
|
||||
'partial-refund',
|
||||
);
|
||||
}
|
||||
|
||||
showStandardRefund() {
|
||||
// Always start by hiding elements then show the others, since some elements are common
|
||||
this.hideCancelElements();
|
||||
$(OrderViewPageMap.cancelProduct.toggle.standardRefund).show();
|
||||
this.useAmountInputs = false;
|
||||
this.initForm(
|
||||
$(OrderViewPageMap.cancelProduct.buttons.save).data('standardRefundLabel'),
|
||||
this.router.generate('admin_orders_standard_refund', {
|
||||
orderId: this.orderId,
|
||||
}),
|
||||
'standard-refund',
|
||||
);
|
||||
}
|
||||
|
||||
showReturnProduct() {
|
||||
// Always start by hiding elements then show the others, since some elements are common
|
||||
this.hideCancelElements();
|
||||
$(OrderViewPageMap.cancelProduct.toggle.returnProduct).show();
|
||||
this.useAmountInputs = false;
|
||||
this.initForm(
|
||||
$(OrderViewPageMap.cancelProduct.buttons.save).data('returnProductLabel'),
|
||||
this.router.generate('admin_orders_return_product', {
|
||||
orderId: this.orderId,
|
||||
}),
|
||||
'return-product',
|
||||
);
|
||||
}
|
||||
|
||||
hideRefund() {
|
||||
this.hideCancelElements();
|
||||
$(OrderViewPageMap.cancelProduct.table.actions).show();
|
||||
}
|
||||
|
||||
hideCancelElements() {
|
||||
$(OrderViewPageMap.cancelProduct.toggle.standardRefund).hide();
|
||||
$(OrderViewPageMap.cancelProduct.toggle.partialRefund).hide();
|
||||
$(OrderViewPageMap.cancelProduct.toggle.returnProduct).hide();
|
||||
$(OrderViewPageMap.cancelProduct.table.actions).hide();
|
||||
}
|
||||
|
||||
initForm(actionName, formAction, formClass) {
|
||||
this.updateVoucherRefund();
|
||||
|
||||
this.cancelProductForm.prop('action', formAction);
|
||||
this.cancelProductForm
|
||||
.removeClass('standard-refund partial-refund return-product cancel-product')
|
||||
.addClass(formClass);
|
||||
$(OrderViewPageMap.cancelProduct.buttons.save).html(actionName);
|
||||
$(OrderViewPageMap.cancelProduct.table.header).html(actionName);
|
||||
$(OrderViewPageMap.cancelProduct.checkboxes.restock).prop('checked', this.orderDelivered);
|
||||
$(OrderViewPageMap.cancelProduct.checkboxes.creditSlip).prop('checked', true);
|
||||
$(OrderViewPageMap.cancelProduct.checkboxes.voucher).prop('checked', false);
|
||||
}
|
||||
|
||||
listenForInputs() {
|
||||
$(document).on('change', OrderViewPageMap.cancelProduct.inputs.quantity, (event) => {
|
||||
const $productQuantityInput = $(event.target);
|
||||
const $parentCell = $productQuantityInput.parents(OrderViewPageMap.cancelProduct.table.cell);
|
||||
const $productAmount = $parentCell.find(OrderViewPageMap.cancelProduct.inputs.amount);
|
||||
const productQuantity = parseInt($productQuantityInput.val(), 10);
|
||||
|
||||
if (productQuantity <= 0) {
|
||||
$productAmount.val(0);
|
||||
this.updateVoucherRefund();
|
||||
|
||||
return;
|
||||
}
|
||||
const priceFieldName = this.isTaxIncluded ? 'productPriceTaxIncl' : 'productPriceTaxExcl';
|
||||
const productUnitPrice = parseFloat($productQuantityInput.data(priceFieldName));
|
||||
const amountRefundable = parseFloat($productQuantityInput.data('amountRefundable'));
|
||||
const guessedAmount = productUnitPrice * productQuantity < amountRefundable
|
||||
? productUnitPrice * productQuantity
|
||||
: amountRefundable;
|
||||
const amountValue = parseFloat($productAmount.val());
|
||||
|
||||
if (this.useAmountInputs) {
|
||||
this.updateAmountInput($productQuantityInput);
|
||||
}
|
||||
|
||||
if ($productAmount.val() === '' || amountValue === 0 || amountValue > guessedAmount) {
|
||||
$productAmount.val(guessedAmount);
|
||||
this.updateVoucherRefund();
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('change', OrderViewPageMap.cancelProduct.inputs.amount, () => {
|
||||
this.updateVoucherRefund();
|
||||
});
|
||||
|
||||
$(document).on('change', OrderViewPageMap.cancelProduct.inputs.selector, (event) => {
|
||||
const $productCheckbox = $(event.target);
|
||||
const $parentCell = $productCheckbox.parents(OrderViewPageMap.cancelProduct.table.cell);
|
||||
const productQuantityInput = $parentCell.find(OrderViewPageMap.cancelProduct.inputs.quantity);
|
||||
const refundableQuantity = parseInt(productQuantityInput.data('quantityRefundable'), 10);
|
||||
const productQuantity = parseInt(productQuantityInput.val(), 10);
|
||||
|
||||
if (!$productCheckbox.is(':checked')) {
|
||||
productQuantityInput.val(0);
|
||||
} else if (Number.isNaN(productQuantity) || productQuantity === 0) {
|
||||
productQuantityInput.val(refundableQuantity);
|
||||
}
|
||||
this.updateVoucherRefund();
|
||||
});
|
||||
}
|
||||
|
||||
updateAmountInput($productQuantityInput) {
|
||||
const $parentCell = $productQuantityInput.parents(OrderViewPageMap.cancelProduct.table.cell);
|
||||
const $productAmount = $parentCell.find(OrderViewPageMap.cancelProduct.inputs.amount);
|
||||
const productQuantity = parseInt($productQuantityInput.val(), 10);
|
||||
|
||||
if (productQuantity <= 0) {
|
||||
$productAmount.val(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const priceFieldName = this.isTaxIncluded ? 'productPriceTaxIncl' : 'productPriceTaxExcl';
|
||||
const productUnitPrice = parseFloat($productQuantityInput.data(priceFieldName));
|
||||
const amountRefundable = parseFloat($productQuantityInput.data('amountRefundable'));
|
||||
const guessedAmount = productUnitPrice * productQuantity < amountRefundable
|
||||
? productUnitPrice * productQuantity
|
||||
: amountRefundable;
|
||||
const amountValue = parseFloat($productAmount.val());
|
||||
|
||||
if ($productAmount.val() === '' || amountValue === 0 || amountValue > guessedAmount) {
|
||||
$productAmount.val(guessedAmount);
|
||||
}
|
||||
}
|
||||
|
||||
getRefundAmount() {
|
||||
let totalAmount = 0;
|
||||
|
||||
if (this.useAmountInputs) {
|
||||
$(OrderViewPageMap.cancelProduct.inputs.amount).each((index, amount) => {
|
||||
const floatValue = parseFloat(amount.value);
|
||||
totalAmount += !Number.isNaN(floatValue) ? floatValue : 0;
|
||||
});
|
||||
} else {
|
||||
$(OrderViewPageMap.cancelProduct.inputs.quantity).each((index, quantity) => {
|
||||
const $quantityInput = $(quantity);
|
||||
const priceFieldName = this.isTaxIncluded ? 'productPriceTaxIncl' : 'productPriceTaxExcl';
|
||||
const productUnitPrice = parseFloat($quantityInput.data(priceFieldName));
|
||||
const productQuantity = parseInt($quantityInput.val(), 10);
|
||||
totalAmount += productQuantity * productUnitPrice;
|
||||
});
|
||||
}
|
||||
|
||||
return totalAmount;
|
||||
}
|
||||
|
||||
updateVoucherRefund() {
|
||||
const refundAmount = this.getRefundAmount();
|
||||
|
||||
this.updateVoucherRefundTypeLabel(
|
||||
$(OrderViewPageMap.cancelProduct.radios.voucherRefundType.productPrices),
|
||||
refundAmount,
|
||||
);
|
||||
const refundVoucherExcluded = refundAmount - this.discountsAmount;
|
||||
this.updateVoucherRefundTypeLabel(
|
||||
$(OrderViewPageMap.cancelProduct.radios.voucherRefundType.productPricesVoucherExcluded),
|
||||
refundVoucherExcluded,
|
||||
);
|
||||
|
||||
// Disable voucher excluded option when the voucher amount is too high
|
||||
if (refundVoucherExcluded < 0) {
|
||||
$(OrderViewPageMap.cancelProduct.radios.voucherRefundType.productPricesVoucherExcluded)
|
||||
.prop('checked', false)
|
||||
.prop('disabled', true);
|
||||
$(OrderViewPageMap.cancelProduct.radios.voucherRefundType.productPrices).prop(
|
||||
'checked',
|
||||
true,
|
||||
);
|
||||
$(OrderViewPageMap.cancelProduct.radios.voucherRefundType.negativeErrorMessage).show();
|
||||
} else {
|
||||
$(OrderViewPageMap.cancelProduct.radios.voucherRefundType.productPricesVoucherExcluded).prop(
|
||||
'disabled',
|
||||
false,
|
||||
);
|
||||
$(OrderViewPageMap.cancelProduct.radios.voucherRefundType.negativeErrorMessage).hide();
|
||||
}
|
||||
}
|
||||
|
||||
updateVoucherRefundTypeLabel($input, refundAmount) {
|
||||
const defaultLabel = $input.data('defaultLabel');
|
||||
const $label = $input.parents('label');
|
||||
const formattedAmount = this.currencyFormatter.format(refundAmount);
|
||||
|
||||
// Change the ending text part only to avoid removing the input (the EOL is on purpose for better display)
|
||||
$label.get(0).lastChild.nodeValue = `
|
||||
${defaultLabel} ${formattedAmount}`;
|
||||
}
|
||||
|
||||
showCancelProductForm() {
|
||||
const cancelProductRoute = this.router.generate('admin_orders_cancellation', {orderId: this.orderId});
|
||||
this.initForm(
|
||||
$(OrderViewPageMap.cancelProduct.buttons.save).data('cancelLabel'),
|
||||
cancelProductRoute,
|
||||
'cancel-product',
|
||||
);
|
||||
this.hideCancelElements();
|
||||
$(OrderViewPageMap.cancelProduct.toggle.cancelProducts).show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from '@pages/order/OrderViewPageMap';
|
||||
import {EventEmitter} from '@components/event-emitter';
|
||||
import OrderViewEventMap from '@pages/order/view/order-view-event-map';
|
||||
import OrderPrices from '@pages/order/view/order-prices';
|
||||
import ConfirmModal from '@components/modal';
|
||||
import OrderPricesRefresher from '@pages/order/view/order-prices-refresher';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
export default class OrderProductEdit {
|
||||
constructor(orderDetailId) {
|
||||
this.router = new Router();
|
||||
this.orderDetailId = orderDetailId;
|
||||
this.productRow = $(`#orderProduct_${this.orderDetailId}`);
|
||||
this.product = {};
|
||||
this.currencyPrecision = $(OrderViewPageMap.productsTable).data('currencyPrecision');
|
||||
this.priceTaxCalculator = new OrderPrices();
|
||||
this.productEditSaveBtn = $(OrderViewPageMap.productEditSaveBtn);
|
||||
this.quantityInput = $(OrderViewPageMap.productEditQuantityInput);
|
||||
this.orderPricesRefresher = new OrderPricesRefresher();
|
||||
}
|
||||
|
||||
setupListener() {
|
||||
this.quantityInput.on('change keyup', (event) => {
|
||||
const newQuantity = Number(event.target.value);
|
||||
const availableQuantity = parseInt($(event.currentTarget).data('availableQuantity'), 10);
|
||||
const previousQuantity = parseInt(this.quantityInput.data('previousQuantity'), 10);
|
||||
const remainingAvailable = availableQuantity - (newQuantity - previousQuantity);
|
||||
const availableOutOfStock = this.availableText.data('availableOutOfStock');
|
||||
this.quantity = newQuantity;
|
||||
this.availableText.text(remainingAvailable);
|
||||
this.availableText.toggleClass('text-danger font-weight-bold', remainingAvailable < 0);
|
||||
this.updateTotal();
|
||||
const disableEditActionBtn = newQuantity <= 0 || (remainingAvailable < 0 && !availableOutOfStock);
|
||||
this.productEditSaveBtn.prop('disabled', disableEditActionBtn);
|
||||
});
|
||||
|
||||
this.productEditInvoiceSelect.on('change', () => {
|
||||
this.productEditSaveBtn.prop('disabled', false);
|
||||
});
|
||||
|
||||
this.priceTaxIncludedInput.on('change keyup', (event) => {
|
||||
this.taxIncluded = parseFloat(event.target.value);
|
||||
this.taxExcluded = this.priceTaxCalculator.calculateTaxExcluded(
|
||||
this.taxIncluded,
|
||||
this.taxRate,
|
||||
this.currencyPrecision,
|
||||
);
|
||||
this.priceTaxExcludedInput.val(this.taxExcluded);
|
||||
this.updateTotal();
|
||||
});
|
||||
|
||||
this.priceTaxExcludedInput.on('change keyup', (event) => {
|
||||
this.taxExcluded = parseFloat(event.target.value);
|
||||
this.taxIncluded = this.priceTaxCalculator.calculateTaxIncluded(
|
||||
this.taxExcluded,
|
||||
this.taxRate,
|
||||
this.currencyPrecision,
|
||||
);
|
||||
this.priceTaxIncludedInput.val(this.taxIncluded);
|
||||
this.updateTotal();
|
||||
});
|
||||
|
||||
this.productEditSaveBtn.on('click', (event) => {
|
||||
const $btn = $(event.currentTarget);
|
||||
const confirmed = window.confirm($btn.data('updateMessage'));
|
||||
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
$btn.prop('disabled', true);
|
||||
this.handleEditProductWithConfirmationModal(event);
|
||||
});
|
||||
|
||||
this.productEditCancelBtn.on('click', () => {
|
||||
EventEmitter.emit(OrderViewEventMap.productEditionCanceled, {
|
||||
orderDetailId: this.orderDetailId,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
updateTotal() {
|
||||
const updatedTotal = this.priceTaxCalculator.calculateTotalPrice(
|
||||
this.quantity,
|
||||
this.isOrderTaxIncluded ? this.taxIncluded : this.taxExcluded,
|
||||
this.currencyPrecision,
|
||||
);
|
||||
this.priceTotalText.html(updatedTotal);
|
||||
this.productEditSaveBtn.prop('disabled', updatedTotal === this.initialTotal);
|
||||
}
|
||||
|
||||
displayProduct(product) {
|
||||
this.productRowEdit = $(OrderViewPageMap.productEditRowTemplate).clone(true);
|
||||
this.productRowEdit.attr('id', `editOrderProduct_${this.orderDetailId}`);
|
||||
this.productRowEdit.find('*[id]').each(function removeAllIds() {
|
||||
$(this).removeAttr('id');
|
||||
});
|
||||
|
||||
// Find controls
|
||||
this.productEditSaveBtn = this.productRowEdit.find(OrderViewPageMap.productEditSaveBtn);
|
||||
this.productEditCancelBtn = this.productRowEdit.find(OrderViewPageMap.productEditCancelBtn);
|
||||
this.productEditInvoiceSelect = this.productRowEdit.find(OrderViewPageMap.productEditInvoiceSelect);
|
||||
this.productEditImage = this.productRowEdit.find(OrderViewPageMap.productEditImage);
|
||||
this.productEditName = this.productRowEdit.find(OrderViewPageMap.productEditName);
|
||||
this.priceTaxIncludedInput = this.productRowEdit.find(OrderViewPageMap.productEditPriceTaxInclInput);
|
||||
this.priceTaxExcludedInput = this.productRowEdit.find(OrderViewPageMap.productEditPriceTaxExclInput);
|
||||
this.quantityInput = this.productRowEdit.find(OrderViewPageMap.productEditQuantityInput);
|
||||
this.locationText = this.productRowEdit.find(OrderViewPageMap.productEditLocationText);
|
||||
this.availableText = this.productRowEdit.find(OrderViewPageMap.productEditAvailableText);
|
||||
this.priceTotalText = this.productRowEdit.find(OrderViewPageMap.productEditTotalPriceText);
|
||||
|
||||
// Init input values
|
||||
this.priceTaxExcludedInput.val(
|
||||
window.ps_round(product.price_tax_excl, this.currencyPrecision),
|
||||
);
|
||||
this.priceTaxIncludedInput.val(
|
||||
window.ps_round(product.price_tax_incl, this.currencyPrecision),
|
||||
);
|
||||
this.quantityInput.val(product.quantity)
|
||||
.data('availableQuantity', product.availableQuantity)
|
||||
.data('previousQuantity', product.quantity);
|
||||
this.availableText.data('availableOutOfStock', product.availableOutOfStock);
|
||||
|
||||
// set this product's orderInvoiceId as selected
|
||||
if (product.orderInvoiceId) {
|
||||
this.productEditInvoiceSelect.val(product.orderInvoiceId);
|
||||
}
|
||||
|
||||
// Init editor data
|
||||
this.taxRate = product.tax_rate;
|
||||
this.initialTotal = this.priceTaxCalculator.calculateTotalPrice(
|
||||
product.quantity,
|
||||
product.isOrderTaxIncluded ? product.price_tax_incl : product.price_tax_excl,
|
||||
this.currencyPrecision,
|
||||
);
|
||||
this.isOrderTaxIncluded = product.isOrderTaxIncluded;
|
||||
this.quantity = product.quantity;
|
||||
this.taxIncluded = product.price_tax_incl;
|
||||
this.taxExcluded = product.price_tax_excl;
|
||||
|
||||
// Copy product content in cells
|
||||
this.productEditImage.html(
|
||||
this.productRow.find(OrderViewPageMap.productEditImage).html(),
|
||||
);
|
||||
this.productEditName.html(
|
||||
this.productRow.find(OrderViewPageMap.productEditName).html(),
|
||||
);
|
||||
this.locationText.html(product.location);
|
||||
this.availableText.html(product.availableQuantity);
|
||||
this.priceTotalText.html(this.initialTotal);
|
||||
this.productRow.addClass('d-none').after(this.productRowEdit.removeClass('d-none'));
|
||||
|
||||
this.setupListener();
|
||||
}
|
||||
|
||||
handleEditProductWithConfirmationModal(event) {
|
||||
const productEditBtn = $(`#orderProduct_${this.orderDetailId} ${OrderViewPageMap.productEditButtons}`);
|
||||
const productId = productEditBtn.data('product-id');
|
||||
const combinationId = productEditBtn.data('combination-id');
|
||||
const orderInvoiceId = productEditBtn.data('order-invoice-id');
|
||||
const productPriceMatch = this.orderPricesRefresher.checkOtherProductPricesMatch(
|
||||
this.priceTaxIncludedInput.val(),
|
||||
productId,
|
||||
combinationId,
|
||||
orderInvoiceId,
|
||||
this.orderDetailId,
|
||||
);
|
||||
|
||||
if (productPriceMatch === null) {
|
||||
this.editProduct($(event.currentTarget).data('orderId'), this.orderDetailId);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const dataSelector = productPriceMatch === 'product' ? this.priceTaxExcludedInput : this.productEditInvoiceSelect;
|
||||
|
||||
const modalEditPrice = new ConfirmModal(
|
||||
{
|
||||
id: 'modal-confirm-new-price',
|
||||
confirmTitle: dataSelector.data('modal-edit-price-title'),
|
||||
confirmMessage: dataSelector.data('modal-edit-price-body'),
|
||||
confirmButtonLabel: dataSelector.data('modal-edit-price-apply'),
|
||||
closeButtonLabel: dataSelector.data('modal-edit-price-cancel'),
|
||||
},
|
||||
() => {
|
||||
this.editProduct($(event.currentTarget).data('orderId'), this.orderDetailId);
|
||||
},
|
||||
);
|
||||
|
||||
modalEditPrice.show();
|
||||
}
|
||||
|
||||
editProduct(orderId, orderDetailId) {
|
||||
const params = {
|
||||
price_tax_incl: this.priceTaxIncludedInput.val(),
|
||||
price_tax_excl: this.priceTaxExcludedInput.val(),
|
||||
quantity: this.quantityInput.val(),
|
||||
invoice: this.productEditInvoiceSelect.val(),
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: this.router.generate('admin_orders_update_product', {
|
||||
orderId,
|
||||
orderDetailId,
|
||||
}),
|
||||
method: 'POST',
|
||||
data: params,
|
||||
}).then(
|
||||
() => {
|
||||
EventEmitter.emit(OrderViewEventMap.productUpdated, {
|
||||
orderId,
|
||||
orderDetailId,
|
||||
});
|
||||
},
|
||||
(response) => {
|
||||
if (response.responseJSON && response.responseJSON.message) {
|
||||
$.growl.error({message: response.responseJSON.message});
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 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 OrderViewEventMap from '@pages/order/view/order-view-event-map';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
export default class OrderProductManager {
|
||||
constructor() {
|
||||
this.router = new Router();
|
||||
}
|
||||
|
||||
handleDeleteProductEvent(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const $btn = $(event.currentTarget);
|
||||
const confirmed = window.confirm($btn.data('deleteMessage'));
|
||||
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
$btn.pstooltip('dispose');
|
||||
$btn.prop('disabled', true);
|
||||
this.deleteProduct($btn.data('orderId'), $btn.data('orderDetailId'));
|
||||
}
|
||||
|
||||
deleteProduct(orderId, orderDetailId) {
|
||||
$.ajax(this.router.generate('admin_orders_delete_product', {orderId, orderDetailId}), {
|
||||
method: 'POST',
|
||||
}).then(() => {
|
||||
EventEmitter.emit(OrderViewEventMap.productDeletedFromOrder, {
|
||||
oldOrderDetailId: orderDetailId,
|
||||
orderId,
|
||||
});
|
||||
}, (response) => {
|
||||
if (response.responseJSON && response.responseJSON.message) {
|
||||
$.growl.error({message: response.responseJSON.message});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from '@pages/order/OrderViewPageMap';
|
||||
import OrderProductEdit from '@pages/order/view/order-product-edit';
|
||||
import Router from '@components/router';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
export default class OrderProductRenderer {
|
||||
constructor() {
|
||||
this.router = new Router();
|
||||
}
|
||||
|
||||
addOrUpdateProductToList($productRow, newRow) {
|
||||
if ($productRow.length > 0) {
|
||||
$productRow.html($(newRow).html());
|
||||
} else {
|
||||
$(OrderViewPageMap.productAddRow).before(
|
||||
$(newRow)
|
||||
.hide()
|
||||
.fadeIn(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
updateNumProducts(numProducts) {
|
||||
$(OrderViewPageMap.productsCount).html(numProducts);
|
||||
}
|
||||
|
||||
editProductFromList(
|
||||
orderDetailId,
|
||||
quantity,
|
||||
priceTaxIncl,
|
||||
priceTaxExcl,
|
||||
taxRate,
|
||||
location,
|
||||
availableQuantity,
|
||||
availableOutOfStock,
|
||||
orderInvoiceId,
|
||||
isOrderTaxIncluded,
|
||||
) {
|
||||
const $orderEdit = new OrderProductEdit(orderDetailId);
|
||||
$orderEdit.displayProduct({
|
||||
price_tax_excl: priceTaxExcl,
|
||||
price_tax_incl: priceTaxIncl,
|
||||
tax_rate: taxRate,
|
||||
quantity,
|
||||
location,
|
||||
availableQuantity,
|
||||
availableOutOfStock,
|
||||
orderInvoiceId,
|
||||
isOrderTaxIncluded,
|
||||
});
|
||||
$(OrderViewPageMap.productAddActionBtn).addClass('d-none');
|
||||
$(OrderViewPageMap.productAddRow).addClass('d-none');
|
||||
}
|
||||
|
||||
moveProductsPanelToModificationPosition(scrollTarget = 'body') {
|
||||
$(OrderViewPageMap.productActionBtn).addClass('d-none');
|
||||
$(
|
||||
`${OrderViewPageMap.productAddActionBtn}, ${OrderViewPageMap.productAddRow}`,
|
||||
).removeClass('d-none');
|
||||
this.moveProductPanelToTop(scrollTarget);
|
||||
}
|
||||
|
||||
moveProductsPanelToRefundPosition() {
|
||||
this.resetAllEditRows();
|
||||
$(
|
||||
/* eslint-disable-next-line max-len */
|
||||
`${OrderViewPageMap.productAddActionBtn}, ${OrderViewPageMap.productAddRow}, ${OrderViewPageMap.productActionBtn}`,
|
||||
).addClass('d-none');
|
||||
this.moveProductPanelToTop();
|
||||
}
|
||||
|
||||
moveProductPanelToTop(scrollTarget = 'body') {
|
||||
const $modificationPosition = $(
|
||||
OrderViewPageMap.productModificationPosition,
|
||||
);
|
||||
|
||||
if ($modificationPosition.find(OrderViewPageMap.productsPanel).length > 0) {
|
||||
return;
|
||||
}
|
||||
$(OrderViewPageMap.productsPanel)
|
||||
.detach()
|
||||
.appendTo($modificationPosition);
|
||||
$modificationPosition.closest('.row').removeClass('d-none');
|
||||
|
||||
// Show column location & refunded
|
||||
this.toggleColumn(OrderViewPageMap.productsCellLocation);
|
||||
this.toggleColumn(OrderViewPageMap.productsCellRefunded);
|
||||
|
||||
// Show all rows, hide pagination controls
|
||||
const $rows = $(OrderViewPageMap.productsTable).find(
|
||||
'tr[id^="orderProduct_"]',
|
||||
);
|
||||
$rows.removeClass('d-none');
|
||||
$(OrderViewPageMap.productsPagination).addClass('d-none');
|
||||
|
||||
const scrollValue = $(scrollTarget).offset().top - $('.header-toolbar').height() - 100;
|
||||
$('html,body').animate({scrollTop: scrollValue}, 'slow');
|
||||
}
|
||||
|
||||
moveProductPanelToOriginalPosition() {
|
||||
$(OrderViewPageMap.productAddNewInvoiceInfo).addClass('d-none');
|
||||
$(OrderViewPageMap.productModificationPosition)
|
||||
.closest('.row')
|
||||
.addClass('d-none');
|
||||
|
||||
$(OrderViewPageMap.productsPanel)
|
||||
.detach()
|
||||
.appendTo(OrderViewPageMap.productOriginalPosition);
|
||||
|
||||
$(OrderViewPageMap.productsPagination).removeClass('d-none');
|
||||
$(OrderViewPageMap.productActionBtn).removeClass('d-none');
|
||||
$(
|
||||
`${OrderViewPageMap.productAddActionBtn}, ${OrderViewPageMap.productAddRow}`,
|
||||
).addClass('d-none');
|
||||
|
||||
// Restore pagination
|
||||
this.paginate(1);
|
||||
}
|
||||
|
||||
resetAddRow() {
|
||||
$(OrderViewPageMap.productAddIdInput).val('');
|
||||
$(OrderViewPageMap.productSearchInput).val('');
|
||||
$(OrderViewPageMap.productAddCombinationsBlock).addClass('d-none');
|
||||
$(OrderViewPageMap.productAddCombinationsSelect).val('');
|
||||
$(OrderViewPageMap.productAddCombinationsSelect).prop('disabled', false);
|
||||
$(OrderViewPageMap.productAddPriceTaxExclInput).val('');
|
||||
$(OrderViewPageMap.productAddPriceTaxInclInput).val('');
|
||||
$(OrderViewPageMap.productAddQuantityInput).val('');
|
||||
$(OrderViewPageMap.productAddAvailableText).html('');
|
||||
$(OrderViewPageMap.productAddLocationText).html('');
|
||||
$(OrderViewPageMap.productAddNewInvoiceInfo).addClass('d-none');
|
||||
$(OrderViewPageMap.productAddActionBtn).prop('disabled', true);
|
||||
}
|
||||
|
||||
resetAllEditRows() {
|
||||
$(OrderViewPageMap.productEditButtons).each((key, editButton) => {
|
||||
this.resetEditRow($(editButton).data('orderDetailId'));
|
||||
});
|
||||
}
|
||||
|
||||
resetEditRow(orderProductId) {
|
||||
const $productRow = $(OrderViewPageMap.productsTableRow(orderProductId));
|
||||
const $productEditRow = $(
|
||||
OrderViewPageMap.productsTableRowEdited(orderProductId),
|
||||
);
|
||||
$productEditRow.remove();
|
||||
$productRow.removeClass('d-none');
|
||||
}
|
||||
|
||||
paginate(originalNumPage) {
|
||||
const $rows = $(OrderViewPageMap.productsTable).find(
|
||||
'tr[id^="orderProduct_"]',
|
||||
);
|
||||
const $customizationRows = $(
|
||||
OrderViewPageMap.productsTableCustomizationRows,
|
||||
);
|
||||
const $tablePagination = $(OrderViewPageMap.productsTablePagination);
|
||||
const numRowsPerPage = parseInt($tablePagination.data('numPerPage'), 10);
|
||||
const maxPage = Math.ceil($rows.length / numRowsPerPage);
|
||||
const numPage = Math.max(1, Math.min(originalNumPage, maxPage));
|
||||
this.paginateUpdateControls(numPage);
|
||||
|
||||
// Hide all rows...
|
||||
$rows.addClass('d-none');
|
||||
$customizationRows.addClass('d-none');
|
||||
// ... and display good ones
|
||||
|
||||
const startRow = (numPage - 1) * numRowsPerPage + 1;
|
||||
const endRow = numPage * numRowsPerPage;
|
||||
|
||||
for (let i = startRow - 1; i < Math.min(endRow, $rows.length); i += 1) {
|
||||
$($rows[i]).removeClass('d-none');
|
||||
}
|
||||
|
||||
$customizationRows.each(function () {
|
||||
if (
|
||||
!$(this)
|
||||
.prev()
|
||||
.hasClass('d-none')
|
||||
) {
|
||||
$(this).removeClass('d-none');
|
||||
}
|
||||
});
|
||||
|
||||
// Remove all edition rows (careful not to remove the template)
|
||||
$(OrderViewPageMap.productEditRow)
|
||||
.not(OrderViewPageMap.productEditRowTemplate)
|
||||
.remove();
|
||||
|
||||
// Toggle Column Location & Refunded
|
||||
this.toggleColumn(OrderViewPageMap.productsCellLocationDisplayed);
|
||||
this.toggleColumn(OrderViewPageMap.productsCellRefundedDisplayed);
|
||||
}
|
||||
|
||||
paginateUpdateControls(numPage) {
|
||||
// Why 3 ? Next & Prev & Template
|
||||
const totalPage = $(OrderViewPageMap.productsTablePagination).find('li.page-item').length
|
||||
- 3;
|
||||
$(OrderViewPageMap.productsTablePagination)
|
||||
.find('.active')
|
||||
.removeClass('active');
|
||||
$(OrderViewPageMap.productsTablePagination)
|
||||
.find(`li:has(> [data-page="${numPage}"])`)
|
||||
.addClass('active');
|
||||
$(OrderViewPageMap.productsTablePaginationPrev).removeClass('disabled');
|
||||
if (numPage === 1) {
|
||||
$(OrderViewPageMap.productsTablePaginationPrev).addClass('disabled');
|
||||
}
|
||||
$(OrderViewPageMap.productsTablePaginationNext).removeClass('disabled');
|
||||
if (numPage === totalPage) {
|
||||
$(OrderViewPageMap.productsTablePaginationNext).addClass('disabled');
|
||||
}
|
||||
this.togglePaginationControls();
|
||||
}
|
||||
|
||||
updateNumPerPage(numPerPage) {
|
||||
$(OrderViewPageMap.productsTablePagination).data('numPerPage', numPerPage);
|
||||
this.updatePaginationControls();
|
||||
}
|
||||
|
||||
togglePaginationControls() {
|
||||
// Why 3 ? Next & Prev & Template
|
||||
const totalPage = $(OrderViewPageMap.productsTablePagination).find('li.page-item').length
|
||||
- 3;
|
||||
$(OrderViewPageMap.productsNavPagination).toggleClass(
|
||||
'd-none',
|
||||
totalPage <= 1,
|
||||
);
|
||||
}
|
||||
|
||||
toggleProductAddNewInvoiceInfo() {
|
||||
$(OrderViewPageMap.productAddNewInvoiceInfo).toggleClass(
|
||||
'd-none',
|
||||
parseInt($(OrderViewPageMap.productAddInvoiceSelect).val(), 10) !== 0,
|
||||
);
|
||||
}
|
||||
|
||||
toggleColumn(target, forceDisplay = null) {
|
||||
let isColumnDisplayed = false;
|
||||
|
||||
if (forceDisplay === null) {
|
||||
$(target)
|
||||
.filter('td')
|
||||
.each(function () {
|
||||
if ($(this).html() !== '') {
|
||||
isColumnDisplayed = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
isColumnDisplayed = forceDisplay;
|
||||
}
|
||||
$(target).toggleClass('d-none', !isColumnDisplayed);
|
||||
}
|
||||
|
||||
updatePaginationControls() {
|
||||
const $tablePagination = $(OrderViewPageMap.productsTablePagination);
|
||||
const numPerPage = $tablePagination.data('numPerPage');
|
||||
const $rows = $(OrderViewPageMap.productsTable).find('tr[id^="orderProduct_"]');
|
||||
const numPages = Math.ceil($rows.length / numPerPage);
|
||||
|
||||
// Update table data fields
|
||||
$tablePagination.data('numPages', numPages);
|
||||
|
||||
// Clean all page links, reinsert the removed template
|
||||
const $linkPaginationTemplate = $(OrderViewPageMap.productsTablePaginationTemplate);
|
||||
$(OrderViewPageMap.productsTablePagination).find('li:has(> [data-page])').remove();
|
||||
$(OrderViewPageMap.productsTablePaginationNext).before($linkPaginationTemplate);
|
||||
|
||||
// Add appropriate pages
|
||||
for (let i = 1; i <= numPages; i += 1) {
|
||||
const $linkPagination = $linkPaginationTemplate.clone();
|
||||
$linkPagination.find('span').attr('data-page', i);
|
||||
$linkPagination.find('span').html(i);
|
||||
$linkPaginationTemplate.before($linkPagination.removeClass('d-none'));
|
||||
}
|
||||
|
||||
this.togglePaginationControls();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 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 OrderViewPageMap from '@pages/order/OrderViewPageMap';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
export default class OrderShippingRefresher {
|
||||
constructor() {
|
||||
this.router = new Router();
|
||||
}
|
||||
|
||||
refresh(orderId) {
|
||||
$.getJSON(this.router.generate('admin_orders_get_shipping', {orderId}))
|
||||
.then((response) => {
|
||||
$(OrderViewPageMap.orderShippingTabCount).text(response.total);
|
||||
$(OrderViewPageMap.orderShippingTabBody).html(response.html);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
|
||||
export default {
|
||||
productDeletedFromOrder: 'productDeletedFromOrder',
|
||||
productAddedToOrder: 'productAddedToOrder',
|
||||
productUpdated: 'productUpdated',
|
||||
productEditionCanceled: 'productEditionCanceled',
|
||||
productListPaginated: 'productListPaginated',
|
||||
productListNumberPerPage: 'productListNumberPerPage',
|
||||
};
|
||||
@@ -0,0 +1,369 @@
|
||||
/**
|
||||
* 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 OrderProductManager from '@pages/order/view/order-product-manager';
|
||||
import OrderViewPageMap from '@pages/order/OrderViewPageMap';
|
||||
import OrderViewEventMap from '@pages/order/view/order-view-event-map';
|
||||
import {EventEmitter} from '@components/event-emitter';
|
||||
import OrderDiscountsRefresher from '@pages/order/view/order-discounts-refresher';
|
||||
import OrderProductRenderer from '@pages/order/view/order-product-renderer';
|
||||
import OrderPricesRefresher from '@pages/order/view/order-prices-refresher';
|
||||
import OrderPaymentsRefresher from '@pages/order/view/order-payments-refresher';
|
||||
import OrderShippingRefresher from '@pages/order/view/order-shipping-refresher';
|
||||
import Router from '@components/router';
|
||||
import OrderInvoicesRefresher from './order-invoices-refresher';
|
||||
import OrderProductCancel from './order-product-cancel';
|
||||
import OrderDocumentsRefresher from './order-documents-refresher';
|
||||
|
||||
const {$} = window;
|
||||
|
||||
export default class OrderViewPage {
|
||||
constructor() {
|
||||
this.orderDiscountsRefresher = new OrderDiscountsRefresher();
|
||||
this.orderProductManager = new OrderProductManager();
|
||||
this.orderProductRenderer = new OrderProductRenderer();
|
||||
this.orderPricesRefresher = new OrderPricesRefresher();
|
||||
this.orderPaymentsRefresher = new OrderPaymentsRefresher();
|
||||
this.orderShippingRefresher = new OrderShippingRefresher();
|
||||
this.orderDocumentsRefresher = new OrderDocumentsRefresher();
|
||||
this.orderInvoicesRefresher = new OrderInvoicesRefresher();
|
||||
this.orderProductCancel = new OrderProductCancel();
|
||||
this.router = new Router();
|
||||
this.listenToEvents();
|
||||
}
|
||||
|
||||
listenToEvents() {
|
||||
$(OrderViewPageMap.invoiceAddressEditBtn).fancybox({
|
||||
type: 'iframe',
|
||||
width: '90%',
|
||||
height: '90%',
|
||||
});
|
||||
$(OrderViewPageMap.deliveryAddressEditBtn).fancybox({
|
||||
type: 'iframe',
|
||||
width: '90%',
|
||||
height: '90%',
|
||||
});
|
||||
|
||||
EventEmitter.on(OrderViewEventMap.productDeletedFromOrder, (event) => {
|
||||
this.orderPricesRefresher.refresh(event.orderId);
|
||||
this.orderPaymentsRefresher.refresh(event.orderId);
|
||||
this.refreshProductsList(event.orderId);
|
||||
this.orderDiscountsRefresher.refresh(event.orderId);
|
||||
this.orderDocumentsRefresher.refresh(event.orderId);
|
||||
this.orderShippingRefresher.refresh(event.orderId);
|
||||
});
|
||||
|
||||
EventEmitter.on(OrderViewEventMap.productEditionCanceled, (event) => {
|
||||
this.orderProductRenderer.resetEditRow(event.orderDetailId);
|
||||
const editRowsLeft = $(OrderViewPageMap.productEditRow).not(OrderViewPageMap.productEditRowTemplate).length;
|
||||
|
||||
if (editRowsLeft > 0) {
|
||||
return;
|
||||
}
|
||||
this.orderProductRenderer.moveProductPanelToOriginalPosition();
|
||||
});
|
||||
|
||||
EventEmitter.on(OrderViewEventMap.productUpdated, (event) => {
|
||||
this.orderProductRenderer.resetEditRow(event.orderDetailId);
|
||||
this.orderPricesRefresher.refresh(event.orderId);
|
||||
this.orderPricesRefresher.refreshProductPrices(event.orderId);
|
||||
this.refreshProductsList(event.orderId);
|
||||
this.orderPaymentsRefresher.refresh(event.orderId);
|
||||
this.orderDiscountsRefresher.refresh(event.orderId);
|
||||
this.orderInvoicesRefresher.refresh(event.orderId);
|
||||
this.orderDocumentsRefresher.refresh(event.orderId);
|
||||
this.orderShippingRefresher.refresh(event.orderId);
|
||||
this.listenForProductDelete();
|
||||
this.listenForProductEdit();
|
||||
this.resetToolTips();
|
||||
|
||||
const editRowsLeft = $(OrderViewPageMap.productEditRow).not(OrderViewPageMap.productEditRowTemplate).length;
|
||||
|
||||
if (editRowsLeft > 0) {
|
||||
return;
|
||||
}
|
||||
this.orderProductRenderer.moveProductPanelToOriginalPosition();
|
||||
});
|
||||
|
||||
EventEmitter.on(OrderViewEventMap.productAddedToOrder, (event) => {
|
||||
this.orderProductRenderer.resetAddRow();
|
||||
this.orderPricesRefresher.refreshProductPrices(event.orderId);
|
||||
this.orderPricesRefresher.refresh(event.orderId);
|
||||
this.refreshProductsList(event.orderId);
|
||||
this.orderPaymentsRefresher.refresh(event.orderId);
|
||||
this.orderDiscountsRefresher.refresh(event.orderId);
|
||||
this.orderInvoicesRefresher.refresh(event.orderId);
|
||||
this.orderDocumentsRefresher.refresh(event.orderId);
|
||||
this.orderShippingRefresher.refresh(event.orderId);
|
||||
this.orderProductRenderer.moveProductPanelToOriginalPosition();
|
||||
});
|
||||
}
|
||||
|
||||
listenForProductDelete() {
|
||||
$(OrderViewPageMap.productDeleteBtn)
|
||||
.off('click')
|
||||
.on('click', (event) => this.orderProductManager.handleDeleteProductEvent(event));
|
||||
}
|
||||
|
||||
resetToolTips() {
|
||||
$(OrderViewPageMap.productEditButtons).pstooltip();
|
||||
$(OrderViewPageMap.productDeleteBtn).pstooltip();
|
||||
}
|
||||
|
||||
listenForProductEdit() {
|
||||
$(OrderViewPageMap.productEditButtons).off('click').on('click', (event) => {
|
||||
const $btn = $(event.currentTarget);
|
||||
this.orderProductRenderer.moveProductsPanelToModificationPosition();
|
||||
this.orderProductRenderer.editProductFromList(
|
||||
$btn.data('orderDetailId'),
|
||||
$btn.data('productQuantity'),
|
||||
$btn.data('productPriceTaxIncl'),
|
||||
$btn.data('productPriceTaxExcl'),
|
||||
$btn.data('taxRate'),
|
||||
$btn.data('location'),
|
||||
$btn.data('availableQuantity'),
|
||||
$btn.data('availableOutOfStock'),
|
||||
$btn.data('orderInvoiceId'),
|
||||
$btn.data('isOrderTaxIncluded'),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
listenForProductPack() {
|
||||
$(OrderViewPageMap.productPackModal.modal).on('show.bs.modal', (event) => {
|
||||
const button = $(event.relatedTarget);
|
||||
const packItems = button.data('packItems');
|
||||
$(OrderViewPageMap.productPackModal.rows).remove();
|
||||
packItems.forEach((item) => {
|
||||
const $item = $(OrderViewPageMap.productPackModal.template).clone();
|
||||
$item.attr('id', `productpack_${item.id}`).removeClass('d-none');
|
||||
$item.find(OrderViewPageMap.productPackModal.product.img).attr('src', item.imagePath);
|
||||
$item.find(OrderViewPageMap.productPackModal.product.name).html(item.name);
|
||||
$item.find(OrderViewPageMap.productPackModal.product.link).attr(
|
||||
'href',
|
||||
this.router.generate('admin_product_form', {id: item.id}),
|
||||
);
|
||||
if (item.reference !== '') {
|
||||
$item.find(OrderViewPageMap.productPackModal.product.ref).append(item.reference);
|
||||
} else {
|
||||
$item.find(OrderViewPageMap.productPackModal.product.ref).remove();
|
||||
}
|
||||
if (item.supplierReference !== '') {
|
||||
$item.find(OrderViewPageMap.productPackModal.product.supplierRef).append(item.supplierReference);
|
||||
} else {
|
||||
$item.find(OrderViewPageMap.productPackModal.product.supplierRef).remove();
|
||||
}
|
||||
if (item.quantity > 1) {
|
||||
$item.find(`${OrderViewPageMap.productPackModal.product.quantity} span`).html(item.quantity);
|
||||
} else {
|
||||
$item.find(OrderViewPageMap.productPackModal.product.quantity).html(item.quantity);
|
||||
}
|
||||
$item.find(OrderViewPageMap.productPackModal.product.availableQuantity).html(item.availableQuantity);
|
||||
$(OrderViewPageMap.productPackModal.template).before($item);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
listenForProductAdd() {
|
||||
$(OrderViewPageMap.productAddBtn).on(
|
||||
'click',
|
||||
() => {
|
||||
this.orderProductRenderer.toggleProductAddNewInvoiceInfo();
|
||||
this.orderProductRenderer.moveProductsPanelToModificationPosition(OrderViewPageMap.productSearchInput);
|
||||
},
|
||||
);
|
||||
$(OrderViewPageMap.productCancelAddBtn).on(
|
||||
'click', () => this.orderProductRenderer.moveProductPanelToOriginalPosition(),
|
||||
);
|
||||
}
|
||||
|
||||
listenForProductPagination() {
|
||||
$(OrderViewPageMap.productsTablePagination).on('click', OrderViewPageMap.productsTablePaginationLink, (event) => {
|
||||
event.preventDefault();
|
||||
const $btn = $(event.currentTarget);
|
||||
EventEmitter.emit(OrderViewEventMap.productListPaginated, {
|
||||
numPage: $btn.data('page'),
|
||||
});
|
||||
});
|
||||
$(OrderViewPageMap.productsTablePaginationNext).on('click', (event) => {
|
||||
event.preventDefault();
|
||||
const $btn = $(event.currentTarget);
|
||||
|
||||
if ($btn.hasClass('disabled')) {
|
||||
return;
|
||||
}
|
||||
const activePage = this.getActivePage();
|
||||
EventEmitter.emit(OrderViewEventMap.productListPaginated, {
|
||||
numPage: parseInt($(activePage).html(), 10) + 1,
|
||||
});
|
||||
});
|
||||
$(OrderViewPageMap.productsTablePaginationPrev).on('click', (event) => {
|
||||
event.preventDefault();
|
||||
const $btn = $(event.currentTarget);
|
||||
|
||||
if ($btn.hasClass('disabled')) {
|
||||
return;
|
||||
}
|
||||
const activePage = this.getActivePage();
|
||||
EventEmitter.emit(OrderViewEventMap.productListPaginated, {
|
||||
numPage: parseInt($(activePage).html(), 10) - 1,
|
||||
});
|
||||
});
|
||||
$(OrderViewPageMap.productsTablePaginationNumberSelector).on('change', (event) => {
|
||||
event.preventDefault();
|
||||
const $select = $(event.currentTarget);
|
||||
const numPerPage = parseInt($select.val(), 10);
|
||||
EventEmitter.emit(OrderViewEventMap.productListNumberPerPage, {
|
||||
numPerPage,
|
||||
});
|
||||
});
|
||||
|
||||
EventEmitter.on(OrderViewEventMap.productListPaginated, (event) => {
|
||||
this.orderProductRenderer.paginate(event.numPage);
|
||||
this.listenForProductDelete();
|
||||
this.listenForProductEdit();
|
||||
this.resetToolTips();
|
||||
});
|
||||
|
||||
EventEmitter.on(OrderViewEventMap.productListNumberPerPage, (event) => {
|
||||
// Update pagination num per page (page links are regenerated)
|
||||
this.orderProductRenderer.updateNumPerPage(event.numPerPage);
|
||||
|
||||
// Paginate to page 1
|
||||
EventEmitter.emit(OrderViewEventMap.productListPaginated, {
|
||||
numPage: 1,
|
||||
});
|
||||
|
||||
// Save new config
|
||||
$.ajax({
|
||||
url: this.router.generate('admin_orders_configure_product_pagination'),
|
||||
method: 'POST',
|
||||
data: {numPerPage: event.numPerPage},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
listenForRefund() {
|
||||
$(OrderViewPageMap.cancelProduct.buttons.partialRefund).on('click', () => {
|
||||
this.orderProductRenderer.moveProductsPanelToRefundPosition();
|
||||
this.orderProductCancel.showPartialRefund();
|
||||
});
|
||||
|
||||
$(OrderViewPageMap.cancelProduct.buttons.standardRefund).on('click', () => {
|
||||
this.orderProductRenderer.moveProductsPanelToRefundPosition();
|
||||
this.orderProductCancel.showStandardRefund();
|
||||
});
|
||||
|
||||
$(OrderViewPageMap.cancelProduct.buttons.returnProduct).on('click', () => {
|
||||
this.orderProductRenderer.moveProductsPanelToRefundPosition();
|
||||
this.orderProductCancel.showReturnProduct();
|
||||
});
|
||||
|
||||
$(OrderViewPageMap.cancelProduct.buttons.abort).on('click', () => {
|
||||
this.orderProductRenderer.moveProductPanelToOriginalPosition();
|
||||
this.orderProductCancel.hideRefund();
|
||||
});
|
||||
}
|
||||
|
||||
listenForCancelProduct() {
|
||||
$(OrderViewPageMap.cancelProduct.buttons.cancelProducts).on('click', () => {
|
||||
this.orderProductRenderer.moveProductsPanelToRefundPosition();
|
||||
this.orderProductCancel.showCancelProductForm();
|
||||
});
|
||||
}
|
||||
|
||||
getActivePage() {
|
||||
return $(OrderViewPageMap.productsTablePagination).find('.active span').get(0);
|
||||
}
|
||||
|
||||
refreshProductsList(orderId) {
|
||||
$(OrderViewPageMap.refreshProductsListLoadingSpinner).show();
|
||||
|
||||
const $tablePagination = $(OrderViewPageMap.productsTablePagination);
|
||||
const numRowsPerPage = $tablePagination.data('numPerPage');
|
||||
const initialNumProducts = $(OrderViewPageMap.productsTableRows).length;
|
||||
const currentPage = parseInt($(OrderViewPageMap.productsTablePaginationActive).html(), 10);
|
||||
|
||||
$.ajax(this.router.generate('admin_orders_get_products', {orderId}))
|
||||
.done((response) => {
|
||||
// Delete previous product lines
|
||||
$(OrderViewPageMap.productsTable).find(OrderViewPageMap.productsTableRows).remove();
|
||||
$(OrderViewPageMap.productsTableCustomizationRows).remove();
|
||||
|
||||
$(`${OrderViewPageMap.productsTable} tbody`).prepend(response);
|
||||
|
||||
$(OrderViewPageMap.refreshProductsListLoadingSpinner).hide();
|
||||
|
||||
const newNumProducts = $(OrderViewPageMap.productsTableRows).length;
|
||||
const newPagesNum = Math.ceil(newNumProducts / numRowsPerPage);
|
||||
|
||||
this.orderProductRenderer.updateNumProducts(newNumProducts);
|
||||
this.orderProductRenderer.updatePaginationControls();
|
||||
|
||||
let numPage = 1;
|
||||
let message = '';
|
||||
|
||||
// Display alert
|
||||
if (initialNumProducts > newNumProducts) { // product deleted
|
||||
message = (initialNumProducts - newNumProducts === 1)
|
||||
? window.translate_javascripts['The product was successfully removed.']
|
||||
: window.translate_javascripts['[1] products were successfully removed.']
|
||||
.replace('[1]', (initialNumProducts - newNumProducts));
|
||||
|
||||
// Set target page to the page of the deleted item
|
||||
numPage = (newPagesNum === 1) ? 1 : currentPage;
|
||||
} else if (initialNumProducts < newNumProducts) { // product added
|
||||
message = (newNumProducts - initialNumProducts === 1)
|
||||
? window.translate_javascripts['The product was successfully added.']
|
||||
: window.translate_javascripts['[1] products were successfully added.']
|
||||
.replace('[1]', (newNumProducts - initialNumProducts));
|
||||
|
||||
// Move to first page to see the added product
|
||||
numPage = 1;
|
||||
}
|
||||
|
||||
if (message !== '') {
|
||||
$.growl.notice({
|
||||
title: '',
|
||||
message,
|
||||
});
|
||||
}
|
||||
|
||||
// Move to page of the modified item
|
||||
EventEmitter.emit(OrderViewEventMap.productListPaginated, {
|
||||
numPage,
|
||||
});
|
||||
|
||||
// Bind hover on product rows buttons
|
||||
this.resetToolTips();
|
||||
})
|
||||
.fail(() => {
|
||||
$.growl.error({
|
||||
title: '',
|
||||
message: 'Failed to reload the products list. Please reload the page',
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user