import template from './checkout-finalize-order.component.html'; declare const angular: ng.IAngularStatic; import { CheckoutService } from '../../../services/checkout.service'; angular .module( 'vfApp' ) .component( 'checkoutFinalizeOrder', { bindings: { acceptedPaymentTypes: '<', billingAddress: '<', extraFields: '<', shippingAddress: '<', order: '<', selectedShippingMethod: '<', isReadyToConfirm: '<', isShippingSameAsBilling: '<', }, controller: FinalizeOrderController, require: { checkoutCtrl: '^vfCheckout', }, template, } ); FinalizeOrderController.$inject = [ 'Alerts', 'Checkout', 'Utils', ]; function FinalizeOrderController( Alerts, Checkout: CheckoutService, Utils, ) { const vm = this; this.warningIcon = `${ localized.dir.url }public/images/warning.svg`; vm.$onInit = $onInit; vm.isPopoversInit = false; vm.confirmOrder = confirmOrder; vm.isOrderConfirmed = false; /** * @function initPopover */ vm.initPopover = () => { const el = jQuery( '.prop65-popover' ); if ( ! vm.isPopoversInit ) { el.popover( { trigger: 'hover focus', html: true, title: 'WARNING: ', } ); vm.isPopoversInit = true; } }; /** */ function $onInit() { vm.pageUrls = { cart: Utils.getPageUrl( 'cart' ), catalog: Utils.getPageUrl( 'catalog' ), }; vm.productSlug = localized.settings.general.product_slug || 'products'; checkPaymentGateways( vm.acceptedPaymentTypes ); const el = jQuery( 'a#checkout-review-tab' ); el.on( 'shown.bs.tab', function() { if ( vm.isReadyToConfirm ) { confirmOrder(); } } ); } vm.$onChanges = function( changes ) { if ( changes.order && changes.order.currentValue ) { vm.returnUrl = `https://${ window.location.hostname }/cc-return/?OrderID=${ vm.order.order_id }`; } }; /** * @param {Object} gateways Payment gateways */ function checkPaymentGateways( gateways ) { if ( ! gateways.payfabric && ! gateways.stripe && ! gateways.squareup && ! gateways.qualpay && ! gateways.authnet && ! gateways.paypal_checkout && ! gateways.credit_line ) { Alerts.warning( 'No Active Payment Gateways.' ); } } /** * @function confirmOrder */ function confirmOrder() { enableNavWarning(); const params = { selected_shipping_profile: { shipping_id: vm.shippingAddress.shipping_id || 0, }, selected_billing_profile: { billing_id: vm.billingAddress?.billing_id || 0, }, order: vm.order, selected_shipping_method: vm.selectedShippingMethod, shipping_first_name: vm.shippingAddress.first_name, shipping_last_name: vm.shippingAddress.last_name, shipping_email: vm.shippingAddress.email, shipping_address1: vm.shippingAddress.address1, shipping_address2: vm.shippingAddress.address2, shipping_city: vm.shippingAddress.city, shipping_state: vm.shippingAddress.state.id, shipping_zip: vm.shippingAddress.zip, shipping_phone: vm.shippingAddress.phone, billing_first_name: vm.isShippingSameAsBilling ? vm.shippingAddress.first_name : vm.billingAddress.first_name, billing_last_name: vm.isShippingSameAsBilling ? vm.shippingAddress.last_name : vm.billingAddress.last_name, billing_email: vm.isShippingSameAsBilling ? vm.shippingAddress.email : vm.billingAddress.email, billing_address1: vm.isShippingSameAsBilling ? vm.shippingAddress.address1 : vm.billingAddress.address1, billing_address2: vm.isShippingSameAsBilling ? vm.shippingAddress.address2 : vm.billingAddress.address2, billing_city: vm.isShippingSameAsBilling ? vm.shippingAddress.city : vm.billingAddress.city, billing_state: vm.isShippingSameAsBilling ? vm.shippingAddress.state.id : vm.billingAddress.state.id, billing_zip: vm.isShippingSameAsBilling ? vm.shippingAddress.zip : vm.billingAddress.zip, billing_phone: vm.isShippingSameAsBilling ? vm.shippingAddress.phone : vm.billingAddress.phone, return_url: vm.returnUrl, extraFields: getExtraFields( vm.checkoutCtrl.extraFields ), }; vm.isOrderConfirmed = false; vm.confirmedOrder = {}; Checkout.confirmOrder( params ) .then( ( response ) => response.data ) .then( ( data: any ) => { vm.confirmedOrder = data.order; vm.priceAvailability = data.priceAvailability; // If priceAvailability is returned, start the PA process before finishing confirmation, otherwise finish the confirmation if ( ! vm.priceAvailability ) { finishConfirmation( data ); } } ); } this.completePriceAvailability = ( data: any ) => { const priceAvailabilityResponse = data; const order = { order: { order_id: vm.order.order_id, }, return_url: vm.returnUrl, }; const reconfirm = true; Checkout.priceAvailabilityResponse( order, priceAvailabilityResponse, reconfirm ) .then( ( response: any ) => { if ( ! response.data.errors.length ) { vm.confirmedOrder = response.data.order; finishConfirmation( response.data ); } } ); }; /** * @param {Object} data Data returned from confirmOrder */ function finishConfirmation( data ) { vm.setHasAdditionShipping( vm.confirmedOrder.items ); vm.confirmedItems = getConfirmedItems( vm.confirmedOrder.items ); vm.extraFields = processExtraFields( data.order ); vm.payfabricUrl = data.payfabric_url; vm.isOrderConfirmed = true; vm.paypalCreateOrder = data.paypal_create_order || null; vm.qualpay = { transientKey: data.qualpay_transient_key || null, merchantId: data.qualpay_merchant_id || null, }; } /** * @param {Object} extraFields Additional or Custom Checkout fields * @return {Object} Fields with only values */ function getExtraFields( extraFields ) { return Object.fromEntries( Object.entries( extraFields ).map( ( element: any ) => { element[ 1 ] = element[ 1 ].value; return element; } ) ); } /** * @param {Object} order Order data returned from confirmOrder * @return {Array} Keyed array containing any extra fields with values. */ function processExtraFields( order ) { const fields = []; const tempFields = { Organization: order.organization, 'P.O. Number': order.rr_po_num, 'Issuing Office': order.issuing_office, 'Cost Center Code': order.cost_center_code, Attention: order.attention, Notes: order.notes, }; Object.entries( tempFields ).forEach( ( element ) => { const [ key, value ] = element; if ( value && value !== '' ) { fields.push( { key, value, } ); } } ); for ( let i = 1; i < 7; i++ ) { if ( order[ `f${ i }_value` ] ) { fields.push( { key: order[ `f${ i }_name` ], value: order[ `f${ i }_value` ], } ); } } return fields; } /** * Prevents the user from navigating away from the page without a warning. */ function enableNavWarning() { window.onbeforeunload = function( e ) { e.preventDefault(); e.returnValue = ''; }; } /** * @param {Object} oldItems Products. * @return {Array} Confirmed items. */ function getConfirmedItems( oldItems ) { return Object.values( oldItems ).map( ( item: any ) => { if ( item.prop65 ) { item.prop65.warning = getProp65Warning( item.prop65.warning ); } return item; } ); } /** * @param {string} warning Original warning message. * @return {string} Formatted warning. */ function getProp65Warning( warning ) { warning = warning.replace( /(^warning:)/gi, '' ).trim(); // Strip 'Warning' since Cal law needs it bold. warning = warning.replace( /(www.p65warnings.ca.gov)/gi, '$&' ); return warning; } this.setHasAdditionShipping = ( items: {additional_shipping: boolean}[] ) => { this.hasAdditionalShipping = Object.values( items ).some( ( item ) => item.additional_shipping ); }; }