import baseReducer from '#utils/baseReducer' ; import { Dispatch } from 'react' ; import { BaseError } from '#typings/errors' ; import { CommerceLayerConfig } from '#context/CommerceLayerContext' ; import { Order , OrderUpdate } from '@commercelayer/sdk' ; import isEmpty from 'lodash/isEmpty' ; import { shipmentsFilled } from '#utils/shipments' ; import { PaymentResource } from './PaymentMethodReducer' ; import { PaymentSourceType } from './PaymentMethodReducer' ; import { saveBillingAddress , saveShippingAddress , saveToWallet , } from '#utils/customerOrderOptions' ; import getSdk from '#utils/getSdk' ; import getErrors from '#utils/getErrors' ; export type PlaceOrderActionType = 'setErrors' | 'setPlaceOrderPermitted' ; export type PlaceOrderOptions = { paypalPayerId ? : string ; adyen ? : { MD : string ; PaRes : string ; } ; } ; export interface PlaceOrderActionPayload { errors : BaseError [ ] ; isPermitted : boolean ; paymentType : PaymentResource ; paymentSecret : string ; paymentId : string ; paymentSource : PaymentSourceType ; options ? : PlaceOrderOptions ; } export type PlaceOrderState = Partial < PlaceOrderActionPayload > ; export interface PlaceOrderAction { type : PlaceOrderActionType ; payload : Partial < PlaceOrderActionPayload > ; } export const placeOrderInitialState = { errors : [ ] , isPermitted : false , } ; export interface SetPlaceOrderErrors { < V extends BaseError [ ] > ( errors , dispatch ? ) : void ; } export const setPlaceOrderErrors = ( errors , dispatch ) => { dispatch && dispatch ( { type : 'setErrors' , payload : { errors , } , } ) ; } ; type PlaceOrderPermitted = ( args : { config ? : CommerceLayerConfig ; dispatch : Dispatch < PlaceOrderAction > ; order ? : Order ; options ? : PlaceOrderOptions ; } ) => void ; export const placeOrderPermitted = async ( { config , order , dispatch , options , } ) => { if ( order && config ) { let isPermitted = true ; if ( order . privacy_url && order . terms_url ) { isPermitted = localStorage . getItem ( 'privacy-terms' ) === 'true' ; } const billingAddress = order . billing_address ; if ( isEmpty ( billingAddress ) ) isPermitted = false ; const shippingAddress = order . shipping_address ; if ( isEmpty ( shippingAddress ) ) isPermitted = false ; const shipments = order . shipments ; const shipment = shipments && shipmentsFilled ( shipments ) ; if ( ! isEmpty ( shipments ) && ! shipment ) isPermitted = false ; const paymentMethod = order . payment_method ; const paymentSource = order . payment_source ; if ( order . total_amount_with_taxes_cents !== 0 && isEmpty ( paymentMethod ?. id ) ) isPermitted = false ; dispatch ( { type : 'setPlaceOrderPermitted' , payload : { isPermitted , paymentType : paymentMethod ?. payment_source_type as PaymentResource , paymentSecret : paymentSource ?. client_secret , paymentId : paymentSource ?. options ?. id , paymentSource , options , } , } ) ; } } ; export type SetPlaceOrder = ( args : { config ? : CommerceLayerConfig ; order ? : Order ; state ? : PlaceOrderState ; setOrderErrors ? : ( collection : any ) => void ; paymentSource ? : Record < string , string > ; } ) => Promise < { placed : boolean ; } > ; export const setPlaceOrder = async ( { state , order , config , setOrderErrors , paymentSource , } ) => { const response = { placed : false , } ; try { if ( state && order && config ) { const sdk = getSdk ( config ) ; const { options , paymentType } = state ; if ( paymentType === 'paypal_payments' && paymentSource ) { if ( ! options ?. paypalPayerId && paymentSource ?. approval_url ) { window . location . href = paymentSource ?. approval_url as string ; return response ; } await sdk . paypal_payments . update ( { id : paymentSource . id , paypal_payer_id : options ?. paypalPayerId , } ) ; } const updateAttributes = { id : order . id , _place : true , } ; if ( saveBillingAddress ( ) ) { await sdk . orders . update ( { id : order . id , _save_billing_address_to_customer_address_book : true , } ) ; } if ( saveShippingAddress ( ) ) { await sdk . orders . update ( { id : order . id , _save_shipping_address_to_customer_address_book : true , } ) ; } switch ( paymentType ) { case 'braintree_payments' : if ( saveToWallet ( ) ) { await sdk . orders . update ( { id : order . id , _save_payment_source_to_customer_wallet : true , } ) ; } await sdk . orders . update ( updateAttributes ) ; setOrderErrors && setOrderErrors ( [ ] ) ; return { placed : true , } ; default : await sdk . orders . update ( updateAttributes ) ; if ( saveToWallet ( ) ) { await sdk . orders . update ( { id : order . id , _save_payment_source_to_customer_wallet : true , } ) ; } setOrderErrors && setOrderErrors ( [ ] ) ; return { placed : true , } ; } } return response ; } catch ( error ) { const errors = getErrors ( error , 'orders' ) ; setOrderErrors && setOrderErrors ( errors ) ; return { ... response , errors , } ; } } ; const type = [ 'setErrors' , 'setPlaceOrderPermitted' ] ; const placeOrderReducer = ( state , reducer ) : PlaceOrderState => baseReducer < PlaceOrderState , PlaceOrderAction , PlaceOrderActionType [ ] > ( state , reducer , type ) ; export default placeOrderReducer ;