diff --git a/src/constants/application-config.js b/src/constants/application-config.js index b4c0d9a1e..91a56ae10 100644 --- a/src/constants/application-config.js +++ b/src/constants/application-config.js @@ -11,12 +11,12 @@ const applicationConfig = { SITE_ENTRY_TRIGGER_VALUE: "FixMyGlass", CASH_PARENT_ACCOUNT_NUMBER: 167132, MY_ACCOUNT: process.env.VUE_APP_MY_ACCOUNT, - PAYPAL_SUCCESS_URL: + PIA_RESPONSE_URL: location.protocol + "//" + location.host + "/fmg/?fmgPage=payment-pia-return&src=concept-funnel", - PAYPAL_CANCEL_URL: + PIA_CANCEL_URL: location.protocol + "//" + location.host + diff --git a/src/constants/query-strings.js b/src/constants/query-strings.js index 1bff7bf46..40f3a2242 100644 --- a/src/constants/query-strings.js +++ b/src/constants/query-strings.js @@ -1,3 +1,4 @@ +// Note: querystring-helper will change all keys to lowercase so make sure they are here as well const queryStrings = { FMG_PAGE: "fmgPage", START_TYPE: "start_type", @@ -6,6 +7,18 @@ const queryStrings = { ERROR: "error", TOKEN: "token", PAYERID: "payerid", + SUBSCRIPTIONID: "subscriptionid", + REFERRAL_SEQ_NUM: "referralseqnum", + CARD_EXPIRATION_MONTH: "card_expirationmonth", + CARD_EXPIRATION_YEAR: "card_expirationyear", + CARD_TYPE: "sgcardtype", + BILL_TO_POSTAL_CODE: "billto_postalcode", + BILL_TO_FIRST_NAME: "billto_firstname", + BILL_TO_LAST_NAME: "billto_lastname", + REFERENCE_NUMBER: "req_reference_number", + AUTH_CODE: "auth_code", + TRANSACTION_ID: "transaction_id", + TRANS_REFERENCE_NUMBER: "auth_trans_ref_no", }; export { queryStrings }; diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js index cc1c90d61..9801ef22e 100644 --- a/src/constants/store-actions.js +++ b/src/constants/store-actions.js @@ -92,6 +92,7 @@ const storeActions = { SAVE_WORK_ORDER_FLAG: "saveWorkOrderFlag", SAVE_PIA_ERROR_CODE: "savePiaErrorCode", SAVE_PIA_WORK_ORDER: "savePiaWorkOrder", + SAVE_CCTOKEN: "saveCCToken", }; export { storeActions }; diff --git a/src/constants/store-mutations.js b/src/constants/store-mutations.js index f5f2ca432..2b2efae64 100644 --- a/src/constants/store-mutations.js +++ b/src/constants/store-mutations.js @@ -1,7 +1,9 @@ const storeMutations = { + // PAYMENT MUTATIONS UPDATE_WORK_ORDER_FLAG: "updateWorkOrderFlag", UPDATE_PIA_ERROR_CODE: "updatePiaErrorCode", UPDATE_PIA_WORK_ORDER: "updatePiaWorkOrder", + UPDATE_CCTOKEN: "updateCCToken", // VEHICLE MUTATIONS UPDATE_YEAR: "updateYear", diff --git a/src/fmg-components/add-vaps-modal-buttons/add-vaps-modal-buttons.vue b/src/fmg-components/add-vaps-modal-buttons/add-vaps-modal-buttons.vue index 9cb256f5d..4240e3514 100644 --- a/src/fmg-components/add-vaps-modal-buttons/add-vaps-modal-buttons.vue +++ b/src/fmg-components/add-vaps-modal-buttons/add-vaps-modal-buttons.vue @@ -91,6 +91,7 @@ export default { answer.SubText = "+$" + this.wipersPrice; answers.push(answer); } + if (this.showAddRainDefense) { const answer = getAnswer("RainDefenseModal", this.answersCmsData); answer.SubText = "+$" + this.rainDefensePrice; diff --git a/src/fmg-components/cart/cart.vue b/src/fmg-components/cart/cart.vue index 7107e64e8..cca06cbca 100644 --- a/src/fmg-components/cart/cart.vue +++ b/src/fmg-components/cart/cart.vue @@ -7,12 +7,14 @@ @click="toggleClass()">
Amount Due{{ amountDue }} + >{{ currencyFormatter.format(amountDue) }}
- {{ packagePrice }} + {{ + currencyFormatter.format(packagePrice) + }}
@@ -35,7 +37,7 @@ {{ lineItem.price }} @@ -45,9 +47,15 @@ >{{ recycleFee }}
-
Subtotal$320
-
Sales tax$1
-
Amount due$321
+
+ Subtotal{{ currencyFormatter.format(subTotal) }} +
+
+ Sales tax{{ currencyFormatter.format(salesTax) }} +
+
+ Amount due{{ currencyFormatter.format(amountDue) }} +
@@ -76,28 +84,16 @@ export default { return { isActive: false, packageWithVAPS: false, - amountDue: this.getAmountDue(), + currencyFormatter: new Intl.NumberFormat("en-US", { + style: "currency", + currency: "USD", + }), }; }, methods: { toggleClass: function (event) { this.isActive = !this.isActive; }, - getPackagePriceString(packageName) { - const formattedPriceFloat = parseFloat(this.getPackagePrice(packageName)).toFixed(2); - return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat; - }, - getPackagePrice(packageName) { - let priceFloat = this.isInsuranceSelected - ? 0 - : baseMixin.methods.getTierOnePackagePrice( - baseMixin.methods.filterOutFees(this.availableLineItems) - ); - - priceFloat += this.getVapsPrice(packageName); - - return priceFloat; - }, getVapsPrice(packageName) { const vapsItems = this.getVapsLineItemsForSelectedPackage(packageName); @@ -157,19 +153,24 @@ export default { this.isRepair, this.vaps ); + return tier; }, packagePrice() { - let packagePriceString; - if (this.packageLevel.length > 0) { - packagePriceString = this.getPackagePriceString(this.packageLevel); - } - return packagePriceString; - // return (packagePriceString.length > 0) ? packagePriceString : "Test String"; + let packagePrice = this.isInsuranceSelected + ? 0 + : baseMixin.methods.getTierOnePackagePrice( + baseMixin.methods.filterOutFees(this.availableLineItems) + ); + + packagePrice += this.getVapsPrice(this.packageLevel); + + return packagePrice; }, displayedPackageLineItems() { const displayedPackageLineItems = []; const packageLineItems = this.getVapsLineItemsForSelectedPackage(this.packageLevel); + // TODO Determine if we could get the same list from this.lineItems? packageLineItems?.forEach((item) => { let price = item.sellingPrice + item.kitPrice + item.laborAmount; @@ -181,6 +182,7 @@ export default { }; displayedPackageLineItems.push(packageLineItem); }); + return displayedPackageLineItems; }, displayedNonPackageLineItems() { @@ -229,6 +231,9 @@ export default { const supportingItems = this.lineItems?.supportingItems; return supportingItems?.length > 0 ? supportingItems : []; }, + removeLinkText() { + return "Remove"; // TODO: get from CMS + }, recycleLabel() { return "Recycling"; }, @@ -244,6 +249,29 @@ export default { // } return true; }, + subTotal() { + let subTotal = 0; + + this.lineItems.forEach((lineItem) => { + subTotal += + (lineItem.kitPrice ?? 0) + + (lineItem.laborAmount ?? 0) + + (lineItem.sellingPrice ?? 0); + }); + + return subTotal; + }, + salesTax() { + let salesTax = 0; + this.lineItems.forEach((lineItem) => { + salesTax += lineItem.salesTax; + }); + + return salesTax; + }, + amountDue() { + return this.subTotal + this.salesTax; + }, }, components: { textBlock, diff --git a/src/fmg-components/nav-bar/nav-bar.vue b/src/fmg-components/nav-bar/nav-bar.vue index 9cf918785..aba6897cc 100644 --- a/src/fmg-components/nav-bar/nav-bar.vue +++ b/src/fmg-components/nav-bar/nav-bar.vue @@ -16,7 +16,8 @@ @click-event="buttonClick" data-bs-target="#footerModal" data-test-id="nav-bar-main-button" - data-bs-dismiss="modal" /> + data-bs-dismiss="modal" + v-if="!isSubmitHidden" /> @@ -139,7 +139,7 @@ export default { const resultMap = await settleAllPromises(promiseResultMap); - const glassParts = (await store.getters.order.lineItems.glassParts) ?? []; + const glassParts = store.getters.order.lineItems.glassParts ?? []; const availableLineItems = [ resultMap.rainDefense, @@ -156,7 +156,24 @@ export default { "payment-method", false ); - const lineItems = store.getters.lineItems; + + const lineItems = store.getters.order.lineItems; + + const combinedLineItems = [...glassParts, ...lineItems.supportingItems, ...lineItems.vaps]; + + const taxedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging( + storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA, + { + billToAccountNumber: "87291", + providerNumber: store.getters.order.serviceLocation.provider.providerNumber, + appointmentType: store.getters.order.serviceLocation.appointmentType, + serviceLocationState: store.getters.order.serviceLocation.state, + serviceLocationZipCode: store.getters.order.serviceLocation.zipCode, + pricedLineItems: combinedLineItems, + }, + "payment-method", + false + ); const cartItems = [...glassParts, ...lineItems.supportingItems, ...lineItems.vaps]; // TOBEREMOVED BY AJC IN CSR-1384 @@ -166,7 +183,7 @@ export default { vm.setCmsContent(resultMap.cmsContent); vm.availableLineItems = pricedAvailableLineItems; - vm.lineItems = lineItems; + vm.lineItems = taxedLineItems; }); }, data() { @@ -175,8 +192,8 @@ export default { lineItems: [], availableLineItems: [], - displayPaypalAlert: this.getPaypalAlert(), paymentMethodInternalModel: this.getPaymentMethodFromStore(), + displayPiaAlert: this.getPiaAlert(), }; }, methods: { @@ -235,7 +252,7 @@ export default { openModal(modalName) { this.$refs[modalName].openModal(); }, - getPaypalAlert() { + getPiaAlert() { return store.getters.order.payment.piaErrorCode ? true : false; }, getPaymentMethodFromStore() { @@ -338,7 +355,6 @@ export default { }, computed: { damageInfo() { - // console.log("this.$store.getters.damage ", this.$store.getters.damage) return this.$store.getters.damage; }, noPiaDisclaimer() { diff --git a/src/layouts/payment-pia-return/payment-pia-return.vue b/src/layouts/payment-pia-return/payment-pia-return.vue index 8d547cd34..ec2ecd1c0 100644 --- a/src/layouts/payment-pia-return/payment-pia-return.vue +++ b/src/layouts/payment-pia-return/payment-pia-return.vue @@ -9,6 +9,7 @@ import { submitWorkOrder } from "@/helpers/heritage-integration/order-helper.js" import { queryStrings } from "@/constants/query-strings"; import { getQuerystringParameter } from "@/helpers/querystring-helper"; import { storeActions } from "@/constants/store-actions"; +import store from "@/store"; import baseMixin from "@/mixins/base-mixin.js"; import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue"; import { Form } from "vee-validate"; @@ -17,11 +18,16 @@ export default { name: "payment-pia-return", async mounted() { this.$refs.loadingModal.showModal(); + // from paypal const piaError = getQuerystringParameter(queryStrings.ERROR); const token = getQuerystringParameter(queryStrings.TOKEN); const payerId = getQuerystringParameter(queryStrings.PAYERID); + // from credit card + const subscriptionID = getQuerystringParameter(queryStrings.SUBSCRIPTIONID); + if (piaError) { + console.log("Error during payment: " + piaError); baseMixin.methods.dispatchStoreAction( storeActions.SAVE_PIA_ERROR_CODE, piaError, @@ -30,32 +36,24 @@ export default { this.$router.navigateWithoutSaving(this.navigationScenarios.PIA_ERROR, this.$route); } else { if (token && payerId) { - baseMixin.methods.dispatchStoreAction( - storeActions.SAVE_PIA_ERROR_CODE, - null, - false - ); - baseMixin.methods.dispatchStoreAction( - storeActions.SAVE_WORK_ORDER_FLAG, - true, - false - ); - - // Final work order submit after returning from PIA. - await this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE); - await submitWorkOrder({ pageNameToLog: "payment-pia-return" }); - this.$refs.loadingModal.isModalVisible = false; - this.$router.navigateWithoutSaving( - this.navigationScenarios.PIA_SUCCESS, - this.$route - ); + await this.processPaypalResponse(); } else { - baseMixin.methods.dispatchStoreAction( - storeActions.SAVE_PIA_ERROR_CODE, - piaError, - false - ); - this.$router.navigateWithoutSaving(this.navigationScenarios.PIA_ERROR, this.$route); + if (subscriptionID) { + await this.processCreditCardResponse(subscriptionID); + } else { + console.log( + "Error during payment: " + token + " : " + payerId + " : " + subscriptionID + ); + baseMixin.methods.dispatchStoreAction( + storeActions.SAVE_PIA_ERROR_CODE, + piaError, + false + ); + this.$router.navigateWithoutSaving( + this.navigationScenarios.PIA_ERROR, + this.$route + ); + } } } }, @@ -63,6 +61,68 @@ export default { arePagePrerequisitesValid() { return true; }, + async processPaypalResponse() { + baseMixin.methods.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, null, false); + baseMixin.methods.dispatchStoreAction(storeActions.SAVE_WORK_ORDER_FLAG, true, false); + + await this.saveAndSubmitWorkOrder(); + }, + async processCreditCardResponse(subscriptionID) { + baseMixin.methods.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, null, false); + baseMixin.methods.dispatchStoreAction(storeActions.SAVE_WORK_ORDER_FLAG, true, false); + + const referralSeqNum = getQuerystringParameter(queryStrings.REFERRAL_SEQ_NUM); + if (referralSeqNum != store.getters.order.referralSequenceNumber) { + console.log( + "error: unknown ref:" + + referralSeqNum + + " " + + store.getters.order.referralSequenceNumber + ); + baseMixin.methods.dispatchStoreAction( + storeActions.SAVE_PIA_ERROR_CODE, + "unknown error", + false + ); + this.$router.navigateWithoutSaving(this.navigationScenarios.PIA_ERROR, this.$route); + } else { + const expMonth = getQuerystringParameter(queryStrings.CARD_EXPIRATION_MONTH); + const expYear = getQuerystringParameter(queryStrings.CARD_EXPIRATION_YEAR); + const cardType = getQuerystringParameter(queryStrings.CARD_TYPE); + const billToPostalCode = getQuerystringParameter(queryStrings.BILL_TO_POSTAL_CODE); + const billToFirstName = getQuerystringParameter(queryStrings.BILL_TO_FIRST_NAME); + const billToLastName = getQuerystringParameter(queryStrings.BILL_TO_LAST_NAME); + const referenceNumber = getQuerystringParameter(queryStrings.REFERENCE_NUMBER); + const authCode = getQuerystringParameter(queryStrings.AUTH_CODE); + const transactionId = getQuerystringParameter(queryStrings.TRANSACTION_ID); + const transReferenceNumber = getQuerystringParameter( + queryStrings.TRANS_REFERENCE_NUMBER + ); + + var ccToken = { + subscriptionId: subscriptionID, + expMonth: expMonth, + expYear: expYear, + cardType: cardType, + billToPostalCode: billToPostalCode, + billToFirstName: billToFirstName, + billToLastName: billToLastName, + referenceNumber: referenceNumber, + authCode: authCode, + transactionId: transactionId, + transReferenceNumber: transReferenceNumber, + }; + baseMixin.methods.dispatchStoreAction(storeActions.SAVE_CCTOKEN, ccToken, false); + await this.saveAndSubmitWorkOrder(); + } + }, + async saveAndSubmitWorkOrder() { + // Final work order submit after returning from PIA. + await this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE); + await submitWorkOrder({ pageNameToLog: "payment-pia-return" }); + this.$refs.loadingModal.isModalVisible = false; + this.$router.navigateWithoutSaving(this.navigationScenarios.PIA_SUCCESS, this.$route); + }, forwardButtonAction() { this.$router.navigateWithoutSaving(this.navigationScenarios.PIA_SUCCESS, this.$route); }, diff --git a/src/layouts/payment/payment.vue b/src/layouts/payment/payment.vue index 6fd6d1511..81c298d11 100644 --- a/src/layouts/payment/payment.vue +++ b/src/layouts/payment/payment.vue @@ -1,31 +1,35 @@