Acumatica API:使用 .ActionConvertToBAccount 转换 Lead 失败
Acumatica API: Using .ActionConvertToBAccount for converting Lead is failing
我正在尝试将 Acumatica API(版本 4.20.2231)用于潜在客户屏幕以将潜在客户转换为企业帐户。我什至在尝试之前就有点担心,因为当您在 Acumatica 中使用 "Convert to Business Account" 操作时,它会弹出一个小对话框。选择“操作”>“转换为企业帐户”后,在 Acumatica 中显示如下:
对于 API,我尝试的第一个命令排列未能转换 Lead,并且没有产生任何类型的错误。最终,我发现了一系列命令产生了引用对话框的错误,这让我觉得我走在了正确的轨道上。也许我只是不知道如何使用命令来操作对话框。有谁知道我哪里出错了?这是我的代码:
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
这里是调用 CR301000Submit 时返回的错误:
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 ---
指定的命令应该用于对话框而不是摘要。
调用操作前应提供必填字段和对话答案。
下面是用于在收据屏幕中创建收据操作的示例。
注:C#代码
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);
希望对您有所帮助。
您当前的问题
您的错误发生是因为操作 ConvertToBAccount
正在调用 Pop-Up 对话并期待一个答案:
if (AccountInfo.AskExt((graph, view) => graph.Views[view].Cache.Clear(), true) != WebDialogResult.OK) return contacts;
告诉 Acumatica 它答案的方法是在调用操作之前发送值 "OK"。根据您的配置,您可能还需要填充此 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)
你以后的问题
从 Lead 转换为 BAccount 是一个两步过程,您将被重定向到新创建的 BAccount 以及您需要保存它的位置。 只要不保存就不会转换
这通常是一个非常简单的过程,或者您只需将 Save
提交到重定向的页面 (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
只要您保留相同的 cookie 容器,UserState
就应该 知道您当前在带有缓存信息的脏 CR303000 上。如果您使用包含 CR301000 和 CR303000 的自定义 Web 服务端点,则无需处理。
Unfortunatly, in this scenario it doesn't work.
似乎 PXRedirectRequiredException
是从 PXLongOperation
中引发的(阅读 Thread)并且 Web-Service 没有选择BAccount 的脏状态。我现在能找到的唯一解决方案是自定义操作 ConvertToBAccount
以删除线程:
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;
}
}
我正在寻找一种更好的方法来解决这个问题,我会在找到它时编辑我的答案。
我正在尝试将 Acumatica API(版本 4.20.2231)用于潜在客户屏幕以将潜在客户转换为企业帐户。我什至在尝试之前就有点担心,因为当您在 Acumatica 中使用 "Convert to Business Account" 操作时,它会弹出一个小对话框。选择“操作”>“转换为企业帐户”后,在 Acumatica 中显示如下:
对于 API,我尝试的第一个命令排列未能转换 Lead,并且没有产生任何类型的错误。最终,我发现了一系列命令产生了引用对话框的错误,这让我觉得我走在了正确的轨道上。也许我只是不知道如何使用命令来操作对话框。有谁知道我哪里出错了?这是我的代码:
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
这里是调用 CR301000Submit 时返回的错误:
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 ---
指定的命令应该用于对话框而不是摘要。 调用操作前应提供必填字段和对话答案。
下面是用于在收据屏幕中创建收据操作的示例。 注:C#代码
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);
希望对您有所帮助。
您当前的问题
您的错误发生是因为操作 ConvertToBAccount
正在调用 Pop-Up 对话并期待一个答案:
if (AccountInfo.AskExt((graph, view) => graph.Views[view].Cache.Clear(), true) != WebDialogResult.OK) return contacts;
告诉 Acumatica 它答案的方法是在调用操作之前发送值 "OK"。根据您的配置,您可能还需要填充此 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)
你以后的问题
从 Lead 转换为 BAccount 是一个两步过程,您将被重定向到新创建的 BAccount 以及您需要保存它的位置。 只要不保存就不会转换
这通常是一个非常简单的过程,或者您只需将 Save
提交到重定向的页面 (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
只要您保留相同的 cookie 容器,UserState
就应该 知道您当前在带有缓存信息的脏 CR303000 上。如果您使用包含 CR301000 和 CR303000 的自定义 Web 服务端点,则无需处理。
Unfortunatly, in this scenario it doesn't work.
似乎 PXRedirectRequiredException
是从 PXLongOperation
中引发的(阅读 Thread)并且 Web-Service 没有选择BAccount 的脏状态。我现在能找到的唯一解决方案是自定义操作 ConvertToBAccount
以删除线程:
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;
}
}
我正在寻找一种更好的方法来解决这个问题,我会在找到它时编辑我的答案。