forcedotcom / SFDX-Data-Move-Utility

SFDMU is a cutting-edge Salesforce data migration tool for seamless org population from other orgs or CSV files. It handles all CRUD operations on multiple related objects in one go.
BSD 3-Clause "New" or "Revised" License
444 stars 74 forks source link

[QUESTION] - Unable to Migrate the SBQQ__Quote__c object data #623

Closed kvenkatasivareddy closed 1 year ago

kvenkatasivareddy commented 1 year ago

Hi team, Firstly i want to thank you guys for building such an amazing tool to migrate the data.

My issue is related to https://github.com/forcedotcom/SFDX-Data-Move-Utility/issues/315.

I want to migrate the data of SBQQQuotec. With SBQQPricebookIdc Field.zip

I tried excluding the SBQQPricebookIdc field from SBQQQuotec SOQL query it started working. Without SBQQPricebookIdc Field.zip

I want to migrate the SBQQPricebookIdc field along with SBQQQuotec object. So as per your comments in the https://github.com/forcedotcom/SFDX-Data-Move-Utility/issues/315#issuecomment-849114243 i tried adding field mapping for SBQQPricebookIdc. Again migration is getting failed with following configuration With FieldMapping for SBQQQuotec Failed.zip

Can you please help to migrate the SBQQPricebookIdc field along with SBQQQuotec?

Also i have below question in my mind. 1) can't we map the single column to multiple columns within a same object using fieldMapping? 2) After excluding the SBQQ_PricebookIdc field from SBQQQuotec object, In the autogenerated csv files under target folder I see the SBQQPriceBookc field has the data. But the same data not getting populated in salesforce UI or Developer Console. Is this is because of excluding the SBQQPricebookIdc or it is a bug? image Opportunity_insert_target.csv [SBQQQuotec_insert_target.csv](https://github.com/forcedotcom/SFDX-Data-Move-Utility/files/12250012/SBQQQuotec_insert_target.csv) [SBQQQuotec_update_target.csv](https://github.com/forcedotcom/SFDX-Data-Move-Utility/files/12250013/SBQQQuotec_update_target.csv) [2023-08-0316_06_25.log](https://github.com/forcedotcom/SFDX-Data-Move-Utility/files/12250018/2023-08-03__16_06_25.log)

Thanks in advance:)

hknokh commented 1 year ago

Hello,

Thank you for your message!

I will review your issue as soon as possible, but please note that it may take some time to address it thoroughly. You can learn more about our support policy on our website: SFDMU support policy.

Thank you for your understanding and patience.

Best regards.

kvenkatasivareddy commented 1 year ago

Thank you for responding. Waiting for your response!!

kvenkatasivareddy commented 1 year ago

Hi @hknokh, Any update?

hknokh2 commented 1 year ago

Hello For now I haven't any update for you. I will let you know if any. Regards

mattgrimwade commented 1 year ago

@kvenkatasivareddy it's not quite clear on what you are trying to do. Am I right in understanding that your issue is as follows:

As the SBQQ__Pricebook__c field on SBQQ__Quote__c is a lookup field, this should get mapped by the tool on upload. Assuming I have understood the problem correctly, I would explore the best way to map from SBQQ__Pricebook__c to SBQQ__PricebookId__c for each SBQQ__Quote__c record.

kvenkatasivareddy commented 1 year ago

@mattgrimwade Yes, you are correct. I want sfdmu to update the value in SBQQPricebookIdc to the actual Id of the pricebook in the current environment. Because of this i'm unable to move the SBQQQuotec data between orgs. It would be helpful if you implement this support in sfdmu plugin.

hknokh2 commented 1 year ago

Hello @mattgrimwade,

Thank you for the explanation. You're spot on!

@kvenkatasivareddy,

Here's some clarity on field mapping:

Using your provided example:

"fieldMapping": [
  {
    "targetObject": "SBQQ__Quote__c"
  },
  {
    "sourceField": "Id",
    "targetField": "SBQQ__PricebookId__c"
  }
],

The actual mapping translates to:

Best regards

kvenkatasivareddy commented 1 year ago

Thanks for considering this as feature request @hknokh. It can be helpful if you implement this soon.

Waiting for this feature.

Thanks in advance:)

hknokh commented 1 year ago

Hello, I hope the issue has been resolved for you. I'm closing it for now. Please let me know if you have any further questions. Regards.

R0Wi commented 1 year ago

@kvenkatasivareddy I think you're right and I also observed that setting the Pricebook reference on SBQQ__Quote__c can only be done by uploading it in the SBQQ__Quote__c.SBQQ__PricebookId__c textfield rather than using the lookup SBQQ__Quote__c.SBQQ__PriceBook__c (which I think SFDMU does automatically). So the solution I found for taking the source SBQQ__PriceBook__c and writing it into the target SBQQ__PricebookId__c was something like this:

{
    "objectSets" : [
        {
            "objects": [
                {
                    "query": "SELECT IsActive,Name,Description FROM Pricebook2",
                    "operation": "Upsert",
                    "externalId": "Name;Description",
                    "master": false
                },
                {
                    "query": "SELECT SBQQ__ConsumptionRateOverride__c,SBQQ__LineItemsGrouped__c,SBQQ__LineItemsPrinted__c,SBQQ__OrderByQuoteLineGroup__c,SBQQ__Ordered__c,SBQQ__Primary__c,SBQQ__Unopened__c,SBQQ__WatermarkShown__c,SBQQ__Account__c,SBQQ__BillingCity__c,SBQQ__BillingCountry__c,SBQQ__BillingFrequency__c,SBQQ__BillingName__c,SBQQ__BillingPostalCode__c,SBQQ__BillingState__c,SBQQ__BillingStreet__c,SBQQ__ContractingMethod__c,SBQQ__CustomerDiscount__c,SBQQ__DefaultTemplate__c,SBQQ__DeliveryMethod__c,SBQQ__DistributorDiscount__c,SBQQ__Distributor__c,SBQQ__DocumentStatus__c,SBQQ__EmailTemplateId__c,SBQQ__EndDate__c,SBQQ__ExpirationDate__c,SBQQ__FirstSegmentTermEndDate__c,SBQQ__GenerateContractedPrice__c,SBQQ__Key__c,SBQQ__LastCalculatedOn__c,SBQQ__LastSavedOn__c,SBQQ__MarkupRate__c,SBQQ__MasterContract__c,SBQQ__MasterEvergreenContract__c,SBQQ__Opportunity2__c,SBQQ__OrderBy__c,SBQQ__OrderGroupID__c,SBQQ__OriginalQuote__c,SBQQ__PaperSize__c,SBQQ__PartnerDiscount__c,SBQQ__Partner__c,SBQQ__PaymentTerms__c,SBQQ__PriceBook__c,SBQQ__PricebookId__c,SBQQ__PrimaryContact__c,SBQQ__ProrationDayOfMonth__c,SBQQ__QuoteLanguage__c,SBQQ__QuoteProcessId__c,SBQQ__QuoteTemplateId__c,SBQQ__RenewalTerm__c,SBQQ__RenewalUpliftRate__c,SBQQ__SalesRep__c,SBQQ__ShippingCity__c,SBQQ__ShippingCountry__c,SBQQ__ShippingName__c,SBQQ__ShippingPostalCode__c,SBQQ__ShippingState__c,SBQQ__ShippingStreet__c,SBQQ__Source__c,SBQQ__StartDate__c,SBQQ__Status__c,SBQQ__SubscriptionTerm__c,SBQQ__TargetCustomerAmount__c,SBQQ__Type__c FROM SBQQ__Quote__c LIMIT 50",
                    "operation": "Upsert",
                    "externalId": "SBQQ__BillingCity__c;SBQQ__BillingCountry__c;SBQQ__BillingName__c;SBQQ__BillingPostalCode__c;SBQQ__BillingState__c;SBQQ__CustomerDiscount__c;SBQQ__DistributorDiscount__c;SBQQ__EmailTemplateId__c;SBQQ__Key__c;SBQQ__MarkupRate__c;SBQQ__OrderGroupID__c;SBQQ__PartnerDiscount__c;SBQQ__PricebookId__c;SBQQ__QuoteProcessId__c;SBQQ__QuoteTemplateId__c;SBQQ__RenewalUpliftRate__c;SBQQ__ShippingCity__c;SBQQ__ShippingCountry__c;SBQQ__ShippingName__c;SBQQ__ShippingPostalCode__c;SBQQ__ShippingState__c",
                    "beforeUpdateAddons" : [
                        {                        
                            "module" : "core:RecordsTransform",
                            "args": {
                                "fields": [
                                    {
                                        "alias": "pricebookId",
                                        "sourceObject": "SBQQ__Quote__c",
                                        "sourceField": "SBQQ__PriceBook__c"
                                    }
                                ],
                                "transformations": [
                                    {
                                        "targetObject": "SBQQ__Quote__c",
                                        "targetField": "SBQQ__PricebookId__c",
                                        "formula": "formula.pricebookId"
                                    },
                                    {
                                        "targetObject": "SBQQ__Quote__c",
                                        "targetField": "SBQQ__PriceBook__c",
                                        "formula": "''"
                                    }
                                ]
                            }
                        }
                    ]
                }
            ]
        }
    ]
}

You can see I'm using the record transformation module to set the SBQQ__PricebookId__c and to clear the SBQQ__PriceBook__c before uploading to Salesforce.

Maybe this approach will unblock you and you won't have to wait for any additional SFDMU feature, good luck 😄

kvenkatasivareddy commented 1 year ago

thank you @R0Wi

kvenkatasivareddy commented 5 months ago

@R0Wi in the above case we know the field value which holds the reference id and we directly using SBQQPriceBookc field value to update the SBQQPricebookIdc.

In the case of SBQQQuoteLinec object, there is a field SBQQPricebookEntryIdc which is type of string but actually holds the reference of pricebookentry id. When we move from source org to target org, whatever the value source has the plugin is copying is the same reference id. Which is not there in the target.

Kindly can you please respond to this?

R0Wi commented 5 months ago

In the case of SBQQQuoteLinec object, there is a field SBQQPricebookEntryIdc which is type of string but actually holds the reference of pricebookentry id. When we move from source org to target org, whatever the value source has the plugin is copying is the same reference id. Which is not there in the target.

That's the reason why we came up with the record transformation. This module will be executed just before actually uploading the data to the target org. At this stage the property SBQQ__Quote__c.SBQQ__PriceBook__c should already be filled with the proper target object id, since SFDMU will do the mapping prior to that stage based on your ExternalId.

I'm afraid this approach won't work if the source object does not contain a Lookup field, like it seems to be the case for SBQQ__QuoteLine__c, which only holds a SBQQ__PricebookEntryId__c Text(64). Maybe you want to check out the custom SFDMU add-on documentation and try to develop a custom add-on which does the mapping. I guess you would need to have access to both the source- and target PricebookEntry records and use some ExternalId to map source to target.