diff --git a/config/default.json b/config/default.json index 64819d05d8..fb1612f6fc 100644 --- a/config/default.json +++ b/config/default.json @@ -184,6 +184,7 @@ } }, "orders": { + "directBackendSync": true, "endpoint": "http://localhost:8080/api/order", "payment_methods_mapping": { }, diff --git a/core/app.ts b/core/app.ts index f5e60a395e..f78272872d 100755 --- a/core/app.ts +++ b/core/app.ts @@ -77,7 +77,7 @@ export function createApp (ssrContext, config): { app: Vue, router: any, store: store.state.config = config store.state.__DEMO_MODE__ = (config.demomode === true) ? true : false if(ssrContext) Vue.prototype.$ssrRequestContext = ssrContext - + Vue.prototype.$coreRouter = router if (!store.state.config) store.state.config = buildTimeConfig // if provided from SSR, don't replace it // depreciated diff --git a/core/i18n/resource/i18n/en-US.csv b/core/i18n/resource/i18n/en-US.csv index 9aa8024835..8570a3c74c 100644 --- a/core/i18n/resource/i18n/en-US.csv +++ b/core/i18n/resource/i18n/en-US.csv @@ -65,3 +65,4 @@ "to account","to account" "Are you sure you would like to remove this item from the shopping cart?","Are you sure you would like to remove this item from the shopping cart?" "The product or category is not available in Offline mode. Redirecting to Home.","The product or category is not available in Offline mode. Redirecting to Home." +"Processing order...","Processing order..." \ No newline at end of file diff --git a/core/modules/cart/store/actions.ts b/core/modules/cart/store/actions.ts index 2f3b37d6a8..e2ccef70be 100644 --- a/core/modules/cart/store/actions.ts +++ b/core/modules/cart/store/actions.ts @@ -2,10 +2,9 @@ import Vue from 'vue' import { ActionTree } from 'vuex' import * as types from './mutation-types' import rootStore from '@vue-storefront/store' -// import router from '@vue-storefront/core/router' import i18n from '@vue-storefront/i18n' import { sha3_224 } from 'js-sha3' -import { currentStoreView } from '@vue-storefront/store/lib/multistore' +import { currentStoreView, localizedRoute} from '@vue-storefront/store/lib/multistore' import omit from 'lodash-es/omit' import RootState from '@vue-storefront/store/types/RootState' import CartState from '../types/CartState' @@ -179,11 +178,11 @@ const actions: ActionTree = { const commit = context.commit const state = context.state - if (!state.shipping.method_code) { + if (!state.shipping || !state.shipping.method_code) { let shippingMethod = context.rootGetters['shipping/shippingMethods'].find(item => item.default) commit(types.CART_UPD_SHIPPING, shippingMethod) } - if (!state.payment.code) { + if (!state.payment || !state.payment.code) { let paymentMethod = context.rootGetters['payment/paymentMethods'].find(item => item.default) commit(types.CART_UPD_PAYMENT, paymentMethod) } @@ -214,7 +213,7 @@ const actions: ActionTree = { return state.cartItems.find(p => p.sku === sku) }, goToCheckout (context) { - // router.push(localizedRoute('/checkout', currentStoreView().storeCode)) + Vue.prototype.$coreRouter.push(localizedRoute('/checkout', currentStoreView().storeCode)) }, addItem ({ commit, dispatch, state }, { productToAdd, forceServerSilence = false }) { let productsToAdd = [] diff --git a/core/modules/checkout/store/checkout/actions.ts b/core/modules/checkout/store/checkout/actions.ts index a515e41dbe..2239faff11 100644 --- a/core/modules/checkout/store/checkout/actions.ts +++ b/core/modules/checkout/store/checkout/actions.ts @@ -14,11 +14,13 @@ const actions: ActionTree = { */ placeOrder (context, { order }) { try { - context.dispatch('order/placeOrder', order, {root: true}).then(result => { - Vue.prototype.$db.usersCollection.setItem('last-cart-bypass-ts', new Date().getTime()) - context.dispatch('cart/clear', {}, {root: true}) - if (context.state.personalDetails.createAccount) { - context.commit(types.CHECKOUT_DROP_PASSWORD) + return context.dispatch('order/placeOrder', order, {root: true}).then(result => { + if (!result.resultCode || result.resultCode === 200) { + Vue.prototype.$db.usersCollection.setItem('last-cart-bypass-ts', new Date().getTime()) + context.dispatch('cart/clear', {}, {root: true}) + if (context.state.personalDetails.createAccount) { + context.commit(types.CHECKOUT_DROP_PASSWORD) + } } }) } catch (e) { diff --git a/core/modules/order/store/actions.ts b/core/modules/order/store/actions.ts index a40a8a824e..7cfa14fab9 100644 --- a/core/modules/order/store/actions.ts +++ b/core/modules/order/store/actions.ts @@ -6,6 +6,9 @@ import { ActionTree } from 'vuex' import RootState from '@vue-storefront/store/types/RootState' import OrderState from '../types/OrderState' const Ajv = require('ajv') // json validator +import rootStore from '@vue-storefront/store' +import { isOnline } from '@vue-storefront/store/lib/search' +import i18n from '@vue-storefront/i18n' const actions: ActionTree = { /** @@ -28,10 +31,41 @@ const actions: ActionTree = { throw new ValidationError(validate.errors) } else { Vue.prototype.$bus.$emit('order-before-placed', { order: order }) - commit(types.ORDER_PLACE_ORDER, order) - Vue.prototype.$bus.$emit('order-after-placed', { order: order }) - - return true + if (!rootStore.state.config.orders.directBackendSync || !isOnline()) + { + commit(types.ORDER_PLACE_ORDER, order) + Vue.prototype.$bus.$emit('order-after-placed', { order: order }) + return Promise.resolve(true) + } else { + Vue.prototype.$bus.$emit('notification-progress-start', i18n.t('Processing order...')) + return rootStore.dispatch('sync/execute', { url: rootStore.state.config.orders.endpoint, // sync the order + payload: { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + mode: 'cors', + body: JSON.stringify(order) + }, + }, { root: true }).then(task => { + Vue.prototype.$bus.$emit('notification-progress-stop') + if (task.resultCode !== 500) { + order.transmited = true + commit(types.ORDER_PLACE_ORDER, order) // archive this order but not trasmit it second time + commit(types.ORDER_LAST_ORDER_WITH_CONFIRMATION, { order: order, confirmation: task.result }) + Vue.prototype.$bus.$emit('order-after-placed', { order: order, confirmation: task.result }) + } + return task.result + }).catch(e => { + rootStore.dispatch('notification/spawnNotification', { + type: 'error', + message: i18n.t('The order can not be transfered because of server error. Order has been queued'), + action1: { label: i18n.t('OK') } + }) + order.transmited = false // queue order + commit(types.ORDER_PLACE_ORDER, order) // archive this order but not trasmit it second time + Vue.prototype.$bus.$emit('notification-progress-stop') + throw (e) + }) + } } } } diff --git a/core/modules/order/store/index.ts b/core/modules/order/store/index.ts index 43b1914ea2..2bbe6e28cb 100644 --- a/core/modules/order/store/index.ts +++ b/core/modules/order/store/index.ts @@ -7,6 +7,7 @@ import OrderState from '../types/OrderState' export const module: Module = { namespaced: true, state: { + last_order_confirmation: null }, actions, mutations diff --git a/core/modules/order/store/mutation-types.ts b/core/modules/order/store/mutation-types.ts index 8231d95869..2f00db7984 100644 --- a/core/modules/order/store/mutation-types.ts +++ b/core/modules/order/store/mutation-types.ts @@ -1,3 +1,4 @@ export const SN_ORDER = 'order' export const ORDER_PLACE_ORDER = SN_ORDER + '/PLACE_ORDER' -export const ORDER_PROCESS_QUEUE = SN_ORDER + '/PROCESS_QUEUE' \ No newline at end of file +export const ORDER_PROCESS_QUEUE = SN_ORDER + '/PROCESS_QUEUE' +export const ORDER_LAST_ORDER_WITH_CONFIRMATION = SN_ORDER + '/LAST_ORDER_CONFIRMATION' \ No newline at end of file diff --git a/core/modules/order/store/mutations.ts b/core/modules/order/store/mutations.ts index fe0699bc3f..2a554d0b6b 100644 --- a/core/modules/order/store/mutations.ts +++ b/core/modules/order/store/mutations.ts @@ -14,17 +14,21 @@ const mutations: MutationTree = { const ordersCollection = Vue.prototype.$db.ordersCollection const orderId = entities.uniqueEntityId(order) // timestamp as a order id is not the best we can do but it's enough order.order_id = orderId.toString() - order.transmited = false order.created_at = new Date() order.updated_at = new Date() ordersCollection.setItem(orderId.toString(), order, (err, resp) => { if (err) console.error(err) - Vue.prototype.$bus.$emit('order/PROCESS_QUEUE', { config: rootStore.state.config }) // process checkout queue + if (!order.transmited) { + Vue.prototype.$bus.$emit('order/PROCESS_QUEUE', { config: rootStore.state.config }) // process checkout queue + } console.info('Order placed, orderId = ' + orderId) }).catch((reason) => { console.error(reason) // it doesn't work on SSR }) // populate cache + }, + [types.ORDER_LAST_ORDER_WITH_CONFIRMATION] (state, payload) { + state.last_order_confirmation = payload } } diff --git a/core/modules/order/types/OrderState.ts b/core/modules/order/types/OrderState.ts index c65a475ca1..93cedffff4 100644 --- a/core/modules/order/types/OrderState.ts +++ b/core/modules/order/types/OrderState.ts @@ -1,2 +1,3 @@ export default interface OrderState { + last_order_confirmation: any } diff --git a/core/pages/Checkout.js b/core/pages/Checkout.js index 810f8454c8..479f06b3f1 100644 --- a/core/pages/Checkout.js +++ b/core/pages/Checkout.js @@ -14,6 +14,7 @@ export default { stockCheckCompleted: false, stockCheckOK: false, orderPlaced: false, + confirmation: null, // order confirmation from server activeSection: { personalDetails: true, shipping: false, @@ -132,10 +133,11 @@ export default { this.$forceUpdate() }) }, - onAfterPlaceOrder (order) { + onAfterPlaceOrder (payload) { + this.confirmation = payload.confirmation this.orderPlaced = true this.$store.dispatch('checkout/setThankYouPage', true) - console.debug(this.order) + console.debug(payload.order) }, onBeforeEdit (section) { this.activateSection(section) diff --git a/src/themes/default/components/core/blocks/Checkout/ThankYouPage.vue b/src/themes/default/components/core/blocks/Checkout/ThankYouPage.vue index a85e884d87..63cb36fd12 100644 --- a/src/themes/default/components/core/blocks/Checkout/ThankYouPage.vue +++ b/src/themes/default/components/core/blocks/Checkout/ThankYouPage.vue @@ -19,6 +19,7 @@ {{ $t('Your purchase') }}

+

@@ -89,6 +90,9 @@ export default { } }, computed: { + lastOrderConfirmation () { + return this.$store.state.order.last_order_confirmation.confirmation + }, isNotificationSupported () { if (Vue.prototype.$isServer || !('Notification' in window)) return false return 'Notification' in window diff --git a/src/themes/default/resource/i18n/en-US.csv b/src/themes/default/resource/i18n/en-US.csv index 436cddbc80..487cac20f7 100644 --- a/src/themes/default/resource/i18n/en-US.csv +++ b/src/themes/default/resource/i18n/en-US.csv @@ -265,3 +265,4 @@ "DPD Courier","DPD Courier" "My Recently viewed products","My Recently viewed products" "No products yet","No products yet" +"The server order id has been set to ","The server order id has been set to " \ No newline at end of file