diff --git a/sfdx/force-app/main/default/applications/Setup.app-meta.xml b/sfdx/force-app/main/default/applications/Setup.app-meta.xml index 974dfbca76..a34fbea1ab 100644 --- a/sfdx/force-app/main/default/applications/Setup.app-meta.xml +++ b/sfdx/force-app/main/default/applications/Setup.app-meta.xml @@ -1,8 +1,8 @@ - #FFC148 - Billing_for_light_background + #625BF6 + stripelogosquare 1 false @@ -10,6 +10,7 @@ Large false false + false Standard Setup diff --git a/sfdx/force-app/main/default/classes/constants.cls b/sfdx/force-app/main/default/classes/constants.cls index ce3c579ad3..1ad0b5b071 100644 --- a/sfdx/force-app/main/default/classes/constants.cls +++ b/sfdx/force-app/main/default/classes/constants.cls @@ -36,6 +36,8 @@ public with sharing class constants { public static final String FIELD_CURRENCY_ISO_CODE = 'CurrencyIsoCode'; + public static final String RESOLUTION_STATUS_ERROR = 'Error'; + // this seemingly-useless code is used for the bootstrap process in the setup.page public String getNamespace() { return constants.NAMESPACE; diff --git a/sfdx/force-app/main/default/classes/setupAssistant.cls b/sfdx/force-app/main/default/classes/setupAssistant.cls index c1b1d53257..9569c1cacc 100644 --- a/sfdx/force-app/main/default/classes/setupAssistant.cls +++ b/sfdx/force-app/main/default/classes/setupAssistant.cls @@ -477,25 +477,29 @@ public with sharing class setupAssistant { WITH SECURITY_ENFORCED LIMIT 1]; - if(!syncRecordList.isEmpty()) { - Sync_Record__c recordToSync = syncRecordList[0]; - String route = constants.RUBY_SERVICE_BASE_URI + '/v1/translate'; - - Map body = new Map{ - 'object_type' => (String)recordToSync.Primary_Object_Type__c, - 'object_ids' => new List { - (String)recordToSync.Primary_Record_ID__c - } - }; + if (syncRecordList.isEmpty()) { + rd.put('isSyncRecordDispactched', isSyncRecordDispactched); + return rd.getJsonString(); + } - HttpResponse response = utilities.makeCallout(route, 'POST', JSON.serialize(body)); + Sync_Record__c recordToSync = syncRecordList[0]; + + String route = constants.RUBY_SERVICE_BASE_URI + '/v1/translate'; - if(response.getStatusCode() == 200) { - isSyncRecordDispactched = true; - } else { - rd.put('isSyncRecordDispactched', false); - errorLogger.create('manualRetry', String.valueOf(response.getStatusCode()), (String)response.getStatus(), 'Sync_Record ID that failed: '+(String)recordId); + Map body = new Map{ + 'object_type' => (String)recordToSync.Primary_Object_Type__c, + 'object_ids' => new List { + (String)recordToSync.Primary_Record_ID__c } + }; + + HttpResponse response = utilities.makeCallout(route, 'POST', JSON.serialize(body)); + + if(response.getStatusCode() == 200) { + isSyncRecordDispactched = true; + } else { + rd.put('isSyncRecordDispactched', false); + errorLogger.create('manualRetry', String.valueOf(response.getStatusCode()), (String)response.getStatus(), 'Sync_Record ID that failed: '+(String)recordId); } } } catch (Exception e) { diff --git a/sfdx/force-app/main/default/contentassets/stripelogosquare.asset b/sfdx/force-app/main/default/contentassets/stripelogosquare.asset new file mode 100644 index 0000000000..6e5c9cd990 Binary files /dev/null and b/sfdx/force-app/main/default/contentassets/stripelogosquare.asset differ diff --git a/sfdx/force-app/main/default/contentassets/stripelogosquare.asset-meta.xml b/sfdx/force-app/main/default/contentassets/stripelogosquare.asset-meta.xml new file mode 100644 index 0000000000..a8300fe0b1 --- /dev/null +++ b/sfdx/force-app/main/default/contentassets/stripelogosquare.asset-meta.xml @@ -0,0 +1,17 @@ + + + false + en_US + stripelogosquare + + + VIEWER + + + + + 1 + stripe-logo-square.png + + + diff --git a/sfdx/force-app/main/default/layouts/Setup_Data__c-Setup Data Layout.layout-meta.xml b/sfdx/force-app/main/default/layouts/Setup_Data__c-Setup Data Layout.layout-meta.xml index 51e611b516..3f236a0dab 100644 --- a/sfdx/force-app/main/default/layouts/Setup_Data__c-Setup Data Layout.layout-meta.xml +++ b/sfdx/force-app/main/default/layouts/Setup_Data__c-Setup Data Layout.layout-meta.xml @@ -20,6 +20,10 @@ Edit OwnerId + + Edit + Steps_Completed__c + @@ -43,9 +47,10 @@ - false + true false true + @@ -56,4 +61,10 @@ false false false + + 00hDa0000058wpK + 4 + 0 + Default + diff --git a/sfdx/force-app/main/default/lwc/alert/alert.html b/sfdx/force-app/main/default/lwc/alert/alert.html new file mode 100644 index 0000000000..6a21df3f65 --- /dev/null +++ b/sfdx/force-app/main/default/lwc/alert/alert.html @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/sfdx/force-app/main/default/lwc/alert/alert.js b/sfdx/force-app/main/default/lwc/alert/alert.js new file mode 100644 index 0000000000..17fa2bca5b --- /dev/null +++ b/sfdx/force-app/main/default/lwc/alert/alert.js @@ -0,0 +1,66 @@ +/** + * Created by jmather-c on 3/23/23. + */ + +import { LightningElement, api } from 'lwc'; + +const AlertTypes = { + warning: { + default_title: 'Warning', + default_classes: 'slds-notify slds-notify_alert slds-alert_warning', + default_icon: 'utility:warning', + }, + alert: { + default_title: 'Alert', + default_classes: 'slds-notify slds-notify_alert', + default_icon: 'utility:question_mark', + }, + error: { + default_title: 'Error', + default_classes: 'slds-notify slds-notify_alert slds-alert_error', + default_icon: 'utility:error', + }, + offline: { + default_title: 'Offline', + default_classes: 'slds-notify slds-notify_alert slds-alert_offline', + default_icon: 'utility:offline', + }, +}; + +export default class Alert extends LightningElement { + @api type; + @api title; + @api classes; + @api icon; + @api message; + @api iconSize = 'x-small'; + + get getTitle() { + return (this.title) ? this.title : AlertTypes[this.type].default_title; + } + + get getClasses() { + return (this.classes) ? this.classes : AlertTypes[this.type].default_classes; + } + + get getIcon() { + return (this.icon) ? this.icon : AlertTypes[this.type].default_icon; + } + + get getIconSize() { + return this.iconSize; + } + + get getMessage() { + return this.message; + } +} + +const typeStrings = {}; +const typeKeys = Object.keys(AlertTypes); +for (let i = 0; i < typeKeys.length; i++) { + const typeKey = typeKeys[i]; + typeStrings[typeKey] = typeKey; +} + +Alert.Types = typeStrings; \ No newline at end of file diff --git a/sfdx/force-app/main/default/lwc/alert/alert.js-meta.xml b/sfdx/force-app/main/default/lwc/alert/alert.js-meta.xml new file mode 100644 index 0000000000..72f74d8554 --- /dev/null +++ b/sfdx/force-app/main/default/lwc/alert/alert.js-meta.xml @@ -0,0 +1,7 @@ + + + 54.0 + Alert + false + Alert + diff --git a/sfdx/force-app/main/default/lwc/dataMappingStep/dataMappingStep.html b/sfdx/force-app/main/default/lwc/dataMappingStep/dataMappingStep.html index a4e0d85120..33acc07bd0 100644 --- a/sfdx/force-app/main/default/lwc/dataMappingStep/dataMappingStep.html +++ b/sfdx/force-app/main/default/lwc/dataMappingStep/dataMappingStep.html @@ -9,7 +9,7 @@ - + @@ -19,17 +19,30 @@

{friendlyStripeObjectName} - - + class="slds-text-body_regular stripe-button_inline slds-m-left_x-small"> +

Salesforce Object: {defaultSfObject}

+

{activeObjectDescription}

{ + return { + metadataMapping: { + label: '', + name: '', + value: '', + description: '', + alerts: [], + fields: [] + } + }; +} + +const mappingListDefaults = () => { + return { + customer: {}, + product: {}, + subscription_schedule: {}, + subscription_phase: {}, + subscription_item: {}, + price: {}, + price_order_item: {}, + coupon: {} + }; +}; export default class DataMappingStep extends LightningElement { /* @@ -14,6 +41,7 @@ export default class DataMappingStep extends LightningElement { friendlyStripeObjectName = 'Customer'; activeObject = 'customer'; activeObjectDescription; + activeObjectAlerts; staticValue; stripeObjectField; defaultSfObject; @@ -52,12 +80,18 @@ export default class DataMappingStep extends LightningElement { "price": { objectName: "PricebookEntry", friendlyName: 'Price', - description: 'Prices define the unit cost, currency, and (optional) billing cycle for both recurring and one-time purchases of products.' + description: 'Prices define the unit cost, currency, and (optional) billing cycle for both recurring and one-time purchases of products.', }, "priceOrderItem": { - objectName: "PricebookEntry", - friendlyName: 'Price Order Item', - description: 'Price order items define the unit cost, currency, and (optional) billing cycle for both recurring and one-time purchases of a single product.' + objectName: "OrderItem", + friendlyName: 'Price (Order Item)', + description: 'Price order items define the unit cost, currency, and (optional) billing cycle for both recurring and one-time purchases of a single product.', + alerts: [ + { + type: Alert.Types.warning, + message: 'In some cases we create Stripe Prices out of Order Items, for example when the UnitPrice on an Order Item differs from the associated Pricebook Entry\'s UnitPrice. You can set the mappings for this case here.', + }, + ], }, "coupon": { objectName: "Order_Stripe_Coupon__c", @@ -83,112 +117,31 @@ export default class DataMappingStep extends LightningElement { // allMappingList is used to retrieve and send all user mappings `saveMappingConfigurations` @track allMappingList = { // these are static values defined by the user in the mapper UI - field_defaults: { - customer: {}, - product: {}, - subscription_schedule: {}, - subscription_phase: {}, - subscription_item: {}, - price: {}, - price_order_item: {}, - coupon: {} - }, + field_defaults: mappingListDefaults(), // these are user defined mappings from Salesforce fields to Stripe fields - field_mappings: { - customer: {}, - product: {}, - subscription_schedule: {}, - subscription_phase: {}, - subscription_item: {}, - price: {}, - price_order_item: {}, - coupon: {} - }, + field_mappings: mappingListDefaults(), // these are default mappings sent from Ruby (can be overridden in map) - default_mappings: { - customer: {}, - product: {}, - subscription_schedule: {}, - subscription_phase: {}, - subscription_item: {}, - price: {}, - price_order_item: {}, - coupon: {} - }, + default_mappings: mappingListDefaults(), // these are required mappings sent from Ruby - required_mappings: { - customer: {}, - product: {}, - subscription_schedule: {}, - subscription_phase: {}, - subscription_item: {}, - price: {}, - price_order_item: {}, - coupon: {} - } - }; - @track customerMetadataFields = {metadataMapping: { - label: '', - name: '', - value: '', - description: '', - fields: [] - }}; - @track productMetadataFields = {metadataMapping: { - label: '', - name: '', - value: '', - description: '', - fields: [] - }};; - @track subscriptionScheduleMetadataFields = {metadataMapping: { - label: '', - name: '', - value: '', - description: '', - fields: [] - }};; - @track subscriptionPhaseMetadataFields = {metadataMapping: { - label: '', - name: '', - value: '', - description: '', - fields: [] - }};; - @track subscriptionItemMetadataFields = {metadataMapping: { - label: '', - name: '', - value: '', - description: '', - fields: [] - }};; - @track priceMetadataFields = {metadataMapping: { - label: '', - name: '', - value: '', - description: '', - fields: [] - }}; - @track priceOrderItemMetadataFields = {metadataMapping: { - label: '', - name: '', - value: '', - description: '', - fields: [] - }}; - @track couponMetadataFields = {metadataMapping: { - label: '', - name: '', - value: '', - description: '', - fields: [] - } + required_mappings: mappingListDefaults() }; + @track customerMetadataFields = blankMetadataMapping(); + @track productMetadataFields = blankMetadataMapping(); + @track subscriptionScheduleMetadataFields = blankMetadataMapping(); + @track subscriptionPhaseMetadataFields = blankMetadataMapping(); + @track subscriptionItemMetadataFields = blankMetadataMapping(); + @track priceMetadataFields = blankMetadataMapping(); + @track priceOrderItemMetadataFields = blankMetadataMapping(); + @track couponMetadataFields = blankMetadataMapping(); @track activeStripeObjectMappings = this.customerMappings; @track activeStripeObjectMetadataFields = this.customerMetadataFields; @track activeStripeObjectSections; + get hasActiveAlerts() { + return this.activeObjectAlerts !== undefined && this.activeObjectAlerts instanceof Array; + } + get priceOrderItemObjectActive() { return this.activeObject == 'priceOrderItem'; } @@ -577,6 +530,7 @@ export default class DataMappingStep extends LightningElement { this.dispatchEvent(this.contentLoading); this.activeObjectDescription = this.ACTIVE_OBJECT_INFO[this.activeObject]['description']; + this.activeObjectAlerts = this.ACTIVE_OBJECT_INFO[this.activeObject]['alerts']; this.updateObjectFieldsAndSetMappings(this.ACTIVE_OBJECT_INFO[this.activeObject]['objectName'], this.ACTIVE_OBJECT_INFO[this.activeObject]['friendlyName']); this.openActiveSection(); this.dispatchEvent(this.contentLoadingComplete); @@ -649,6 +603,7 @@ export default class DataMappingStep extends LightningElement { } finally { this.activeObject = 'customer'; this.activeObjectDescription = this.ACTIVE_OBJECT_INFO[this.activeObject]['description']; + this.activeObjectAlerts = this.ACTIVE_OBJECT_INFO[this.activeObject]['alerts']; this.activeStripeObjectMappings = this.customerMappings; this.activeStripeObjectMetadataFields = this.customerMetadataFields; } diff --git a/sfdx/force-app/main/default/lwc/orgSettingsStep/orgSettingsStep.html b/sfdx/force-app/main/default/lwc/orgSettingsStep/orgSettingsStep.html index 96b3219677..d2992e1c87 100644 --- a/sfdx/force-app/main/default/lwc/orgSettingsStep/orgSettingsStep.html +++ b/sfdx/force-app/main/default/lwc/orgSettingsStep/orgSettingsStep.html @@ -3,7 +3,7 @@

- "Stripe Dashboard Link" + Stripe Dashboard Link

This is a URL formula field that, when clicked, will navigate you to the Stripe record you are currently viewing in Salesforce. You can optionally add it to your Order, Order Product, Account, Opportunity, Product, and Pricebook Entry page layouts. @@ -13,7 +13,7 @@

- "Stripe ID" + Stripe ID

The Stripe ID field is used for the integration to match Salesforce records to Stripe records. If you would like to see which records are actively synchronizing with Stripe, you can include it in your Order, Order Product, Account, Opportunity, Product, and Pricebook Entry page layouts. It is recommended that the field is marked as “Read Only” on the page layouts to prevent users from accidentally modifying the values. diff --git a/sfdx/force-app/main/default/lwc/setup/setup.html b/sfdx/force-app/main/default/lwc/setup/setup.html index 09605cb7d7..77abd4ac91 100644 --- a/sfdx/force-app/main/default/lwc/setup/setup.html +++ b/sfdx/force-app/main/default/lwc/setup/setup.html @@ -212,7 +212,7 @@

diff --git a/sfdx/force-app/main/default/lwc/setup/setup.js b/sfdx/force-app/main/default/lwc/setup/setup.js index da6f5280fb..9dbcfe31e0 100644 --- a/sfdx/force-app/main/default/lwc/setup/setup.js +++ b/sfdx/force-app/main/default/lwc/setup/setup.js @@ -194,6 +194,15 @@ export default class FirstTimeSetup extends LightningElement { this.showSetupToast(errorMessage, 'error', 'sticky'); } finally { this.loading = false; + + // skip the initial landing screen by grabbing the first nav item and "clicking" + if (this.setupComplete && this.activeSectionIndex === undefined) { + const comp = this; + setTimeout(() => { + const orgSettings = comp.template.querySelector('li[data-section-name="orgSettings"]'); + orgSettings.click(); + }, 0); + } } } diff --git a/sfdx/force-app/main/default/lwc/syncPreferencesStep/syncPreferencesStep.html b/sfdx/force-app/main/default/lwc/syncPreferencesStep/syncPreferencesStep.html index 55a2700f19..3b2d87ccf9 100644 --- a/sfdx/force-app/main/default/lwc/syncPreferencesStep/syncPreferencesStep.html +++ b/sfdx/force-app/main/default/lwc/syncPreferencesStep/syncPreferencesStep.html @@ -1,270 +1,278 @@