Acumatica API: Using .ActionConvertToBAccount for converting Lead is failing

可紊 提交于 2019-12-11 10:09:46

问题


I'm trying to use the Acumatica API (Version 4.20.2231) for the Lead screen to convert a Lead to a Business Account. I was a bit worried about this even before I tried it because when you use the "Convert to Business Account" Action in Acumatica, it pops up a small dialog box. Here's what it looks like in Acumatica after choosing Actions > Convert to Business Account:

With the API, the first arrangement of commands I tried was failing to convert the Lead and not producing any kind of error. Eventually, I found a sequence of commands that produced an error that references dialog boxes, so that makes me think I'm on the right track. Maybe I just don't know how to manipulate the dialog box using the Commands. Does anyone know where I'm going wrong? Here is my code:

Public Function ConvertLeadToCustomer(ByVal leadID As String, ByVal firstName As String, ByVal lastName As String, ByRef companyName As String) As String
    Dim CR301000 As CR301000Content = m_context.CR301000GetSchema()
    m_context.CR301000Clear()

    ' converting a lead requires that there is a value for company, so create one if it is blank
    If companyName = "" Then
        companyName = lastName & ", " & firstName
    End If

    ' create key field
    Dim leadKeyValue As Value = New Value With {.LinkedCommand = CR301000.LeadSummary.LeadID, .Value = leadID}

    ' create company field, since its required
    Dim companyValue As Value = New Value With {.LinkedCommand = CR301000.DetailsSummary.CompanyName, .Value = companyName, .Commit = True}

    Dim updateLeadCommands As Command() = {leadKeyValue, CR301000.Actions.ActionConvertToBAccount, companyValue, CR301000.Actions.Save}
    Dim updateLeadResult As CR301000Content() = m_context.CR301000Submit(updateLeadCommands)

    ' TO DO: search Business Accounts by name to find new Business Account ID
    Dim newBAID As String = ""
    Return newBAID 
End Function

And here is the error returned when CR301000Submit is called:

System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> PX.Data.PXDialogRequiredException
    at PX.Data.DialogManager.a(String A_0, PXGraph A_1, String A_2, Object A_3, String A_4, String A_5, MessageButtons A_6, MessageIcon A_7, Boolean A_8, InitializePanel A_9)
    at PX.Data.DialogManager.AskExt(PXView view, String key, InitializePanel initializeHandler, Boolean repaintControls)
    at PX.Data.PXView.AskExt(InitializePanel initializeHandler, Boolean refreshRequired)
    at PX.Objects.CR.LeadMaint.ConvertToBAccount(PXAdapter adapter)
    at PX.Data.PXAction`1.a(PXAdapter A_0)
    at PX.Data.PXAction`1.<Press>d__c.MoveNext()
    at PX.Data.PXAction`1.<Press>d__c.MoveNext()
    at PX.Data.PXAction`1.<Press>d__c.MoveNext()
    at PX.Data.PXAction`1.<Press>d__c.MoveNext()
    at PX.Api.SyImportProcessor.SyStep.CommitChanges(Object itemToBypass, PXFilterRow[] targetConditions)
    at PX.Api.SyImportProcessor.ExportTableHelper.ExportTable()
    at PX.Api.ScreenUtils.Submit(String screenId, Command[] commands, SchemaMode schemaMode, PXGraph graph)
    at PX.Api.Services.ScreenService.Submit(String id, IEnumerable`1 commands, SchemaMode schemaMode)
    at PX.Api.Soap.Screen.ScreenGate.Submit(Command[] commands)
--- End of inner exception stack trace --- 

回答1:


Your current question

Your error occurs because the action ConvertToBAccount is calling a Pop-Up Dialog and is expecting an answer:

if (AccountInfo.AskExt((graph, view) => graph.Views[view].Cache.Clear(), true) != WebDialogResult.OK) return contacts;

The way to tell Acumatica of it answer is to send the value "OK" before even calling the action. Depending on your configuration you might also want populate the field in this pop-up:

Dim commandsConvert As Command() =
    {
        New Value With {.Value = leadID, .LinkedCommand = CR301000.LeadSummary.LeadID, .Commit = True},
        New Value With {.Value = "OK", .LinkedCommand = CR301000.NewAccountServicesSettings.ServiceCommands.DialogAnswer, .Commit = True}, 'This is how close the pop-up. We fill the field from the pop-up after this line
        New Value With {.Value = newCompanyCD, .LinkedCommand = CR301000.NewAccountServicesSettings.BAccountID}, 'With autonumbering On, no need for this line.
        New Value With {.Value = newCompanyName, .LinkedCommand = CR301000.NewAccountServicesSettings.AccountName}, 'The default value will be taken from DetailsSummary.CompanyName
        CR301000.Actions.ActionConvertToBAccount
    }

m_context.CR301000Submit(commandsConvert)

Your future question

Converting from a Lead to a BAccount is a 2-step process where you are redirected to your newly created BAccount and where you need to save it. It will not be converted as long as you don't save it.

This is generally a pretty straight forward process or you simply submit Save to the page where you were redirected (CR303000):

'Once the Process is completed, We want to save the new record.
'If we want to edit some information on the new Business Account
'this is the right place to do it.

Dim newBAID As String = String.Empty
Dim commandsBAccount As Command() =
    {
        CR303000.Actions.Save,
        CR303000.AccountSummary.BusinessAccount
    }
Dim newBAccountContent As CR303000Content() = m_context.CR303000Submit(commandsBAccount)
If newBAccountContent.Length > 0 Then
    newBAID = newBAccountContent(0).AccountSummary.BusinessAccount.Value
End If

As long as you keep the same cookie container, the UserState should be aware that you are currently on a dirty CR303000 with cached information. If you use a custom web service endpoint that included both CR301000 and CR303000 there is nothing to deal with.

Unfortunatly, in this scenario it doesn't work.

It seems that the PXRedirectRequiredException is raised from within a PXLongOperation (read Thread) and that the Web-Service doesn't pick the dirty state of BAccount. The only solution I can find right now is to customize the action ConvertToBAccount to remove threading:

public class LeadMaintExt : PXGraphExtension<LeadMaint>
{
    [PXUIField(DisplayName = Messages.ConvertToBAccount, MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Select)]
    [PXButton(ImageKey = PX.Web.UI.Sprite.Main.Process)]
    public virtual IEnumerable ConvertToBAccount(PXAdapter adapter)
    {
        List<Contact> contacts = new List<Contact>(adapter.Get().Cast<Contact>());
        foreach (Contact lead in contacts)
        {
            if (Base.AccountInfo.AskExt((graph, view) => graph.Views[view].Cache.Clear(), true) != WebDialogResult.OK) return contacts;
            bool empty_required = !Base.AccountInfo.VerifyRequired();
            BAccount existing = PXSelect<BAccount, Where<BAccount.acctCD, Equal<Required<BAccount.acctCD>>>>.SelectSingleBound(Base, null, Base.AccountInfo.Current.BAccountID);
            if (existing != null)
            {
                Base.AccountInfo.Cache.RaiseExceptionHandling<LeadMaint.AccountsFilter.bAccountID>(Base.AccountInfo.Current, Base.AccountInfo.Current.BAccountID, new PXSetPropertyException(Messages.BAccountAlreadyExists, Base.AccountInfo.Current.BAccountID));
                return contacts;
            }
            if (empty_required) return contacts;

            Base.Save.Press();
            //PXLongOperation.StartOperation(this, () => ConvertToAccount(lead, AccountInfo.Current));
            LeadMaint.ConvertToAccount(lead, Base.AccountInfo.Current);
        }
        return contacts;
    }
}

I am looking for a better way to address the situation and I'll edit my answer when I find it.




回答2:


The commands specified should be for the dialog not the summary. The required fields and the dialog answer should be provided before calling the action.

Below is the sample used for create Receipt action in receipts screen. Note: C# code

   commands = new Command[]
            {          
                 new Value 
                {

                    Value = CreatedOn.HasValue ? ((DateTime)CreatedOn.Value).ToLongDateString() : "",  
                    LinkedCommand = SOSchema.SpecifyShipmentParameters.ShipmentDate, 
                    Commit = true 
                },
                new Value 
                {

                    Value = "OK", 
                    LinkedCommand = SOSchema.SpecifyShipmentParameters.ServiceCommands.DialogAnswer, 
                    Commit = true 
                },               
                SOSchema.Actions.ActionCreateReceipt
            };
                context.SO301000Submit(commands);

Hope this helps.



来源:https://stackoverflow.com/questions/34444593/acumatica-api-using-actionconverttobaccount-for-converting-lead-is-failing

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!