I need to set null value i.e., "" value on a control.But I am facing exception as below
"Cannot perform 'SetProperty of Text with value ""' on the control. Additional Details:
TechnologyName: 'Web'
ControlType: 'Edit'
Id: 'ctl00_ctl00_Content_PlanContent_ucParentDeferralRule_txtAutoEnrollAmt'
Name: 'ctl00$ctl00$Content$PlanContent$ucParentDeferralRule$txtAutoEnrollAmt'
TagName: 'INPUT'"
and the code is like,
Control.Text = "";
So if we have:
public HtmlEdit EditField()
{
HtmlEdit control = new HtmlEdit(GlobalVariable.browser);
control.SearchProperties["id"] = "ctl00_ctl00_Content_PlanContent_ucParentDeferralRule_txtAutoEnrollPercent";
return control;
}
we should be able to set the value as you did (using EditField().Text = String.Empty). The fact that we can't means that there's a restriction on that field that won't accept that value as an input. Check the code to see if it's restricted to numerical values, for example, or if the value.length cannot be < 1, etc.
Related
In ClaimCenter I am trying to filter a drop down list to only display users that have a certain role. I am using a User input cell. There is no value range on the userinput cell only value. The value is set the user that they select so right now it's displaying all the users in the system instead of just the ones with the role that i want. Is there a way to show just the users that have the "Adjuster" role. I don't see a filter option either on this cell.
Right click the element and select "Change Element Type"
Then select "Range Input".
Then in the ValueRange property add a call to the code that you write.
The code to should find the subset of users that you want to show in the drop down and return them as a List or User[], something like this might work
function myValueRangeFunction(pClaim: Claim) : User[] {
//gets the group from the DB by public ID
var adjusterGroup = Group ("cc:123");
var adjustersOnly = new Set<User>();
var groupUsers = adjusterGroup.MembersNoSystemUsers
adjustersOnly.addAll(groupUsers*.Users)
return adjustersOnly.toArray()
}
You need to change the input type to Range Input (or Range Cell in case you are using List View) where valueRange property calls a method which retrieves users with a specific role.
.pcf file:
<RangeInput
editable="true"
id="userInput"
label=""Adjusters""
value="claim.AssignedUser"
valueRange="UserRoleUtil_Ext.Adjusters"
valueType="entity.User"/>
UserRoleUtil_Ext.gs:
uses gw.api.database.Query
uses gw.api.database.Relop
class UserRoleUtil_Ext {
public static property get Adjusters() : User[] {
var adjusterRole = Query.make(Role).compare(Role#Name, Relop.Equals, "Adjuster").select().AtMostOneRow
// Alternatively, you can retrieve the Role by its public-id, e.g.:
// var roleRetrievedById = Query.make(Role).compare(Role#PublicID, Relop.Equals, "cc:1").select().AtMostOneRow
return adjusterRole.AllUsersArray
}
}
I had added a custome field "UsrWgtIndex" on Allocation panel in Purchase Receipts. And its value is the sum of the other custom field "UsrWgtPerUnit".
But strange thing happened. The value of UsrWgtIndex keeps the same when I open diffrent allocation panel. It is always the value of first row of transations.
My code is below, and I'm really confused about this. In logic, the code will sum each row of transations, and assign each row of the "UsrWgtIndex". But it's always the value of the first row.
Anyone can help on this? Thanks a lot!
namespace PX.Objects.PO {
public class POReceiptEntry_Extension: PXGraphExtension < POReceiptEntry > {
#region Event Handlers
decimal totalCgt = 0 M,
tempTotal = 0 M;
protected void POReceiptLine_RowSelected(PXCache cache, PXRowSelectedEventArgs e) {
POReceiptLine poRLine = (POReceiptLine) e.Row;
if (poRLine != null) {
totalCgt = 0 M;
foreach(POReceiptLineSplit line in Base.splits.Select()) {
POReceiptLineSplitExt poReceiptLineSplitExt = line.GetExtension < POReceiptLineSplitExt > ();
var recentQty = poReceiptLineSplitExt.UsrWgtPerUnit;
var temp = Convert.ToDecimal(recentQty);
totalCgt = totalCgt + temp;
};
var cgt = Convert.ToDecimal(totalCgt);
if (totalCgt != null) {
cache.SetValue < POReceiptLineExt.usrTotalWgt > (poRLine, cgt);
//This line is setting the value of usrWgtIndex
cache.SetValue < POReceiptLineExt.usrWgtIndex > (poRLine, cgt);
};
}
}
}
}
More detail update:
The customer field “usrWgtIndex” belongs to the data class “POReceiptLine”. But I make its control on the Allocations Panel.
I had made a test: set value to the field “UnassignedQty” on allocations panel with the same value I give to “usrWgtIndex”. It works correctly. Or I changed the other field in POReceiptLine data class with same value in the same time, It works fine again.
3.It seems that if I change a custom field on allocations panel, this strange thing would happen…
More Detail Update2:
I didn't add the "UsrWgtIndex" on the DAC LotSerOptions. I added it on the POReceiptLine. Because when I add the custom field on LotSerOptions, I can't assign its value with setValueEXT methord, it seems there is no DAC named "LotSerOptionsExt".
So I just put "UsrWgtIndex" on DAC POReceiptLine, and assign its value with
cache.SetValue<POReceiptLineExt.usrWgtIndex>(poRLine, cgt);
The 'splits' DataView depends on 'Current' POReceiptLine:
PXSelect<POReceiptLineSplit, Where<POReceiptLineSplit.receiptNbr, Equal<Current<POReceiptLine.receiptNbr>>,
And<POReceiptLineSplit.lineNbr, Equal<Current<POReceiptLine.lineNbr>>,
And<Where<POLineType.goodsForInventory, Equal<Current<POReceiptLine.lineType>>,
Or<POLineType.goodsForSalesOrder, Equal<Current<POReceiptLine.lineType>>,
Or<POLineType.goodsForDropShip, Equal<Current<POReceiptLine.lineType>>>>>>>>> splits;
The issue is that 'Current' POReceiptLine doesn't change when user clicks (select) another POReceiptLine in 'transactions' grid. Setting the grid 'SyncPosition' to true in your customization project should ensure 'Current' value is properly set when users change record selection in the grid:
I am trying to copy data from one list to other list (both lists are on different sites) along with lookup columns. But, I am getting an error for lookup field as:
Value does not fall within the expected range
Code works and data gets copied for other non-lookup fields. I tried every possible way including increasing List View Lookup Threshold and all possible ways of code but still error persists at ExecuteQuery().
Below is my code for lookup field:
if (field is FieldLookup && field.InternalName == "Country")
{
var CountryLookup = (item.FieldValues["Country"] as FieldLookupValue).LookupValue.ToString();
var CountryLookupId = (item.FieldValues["Country"] as FieldLookupValue).LookupId.ToString();
FieldLookupValue flvRDS = new FieldLookupValue();
flvRDS.LookupId = int.Parse(CountryLookupId);
itemToCreate["Country"] = flvRDS;
itemToCreate.Update();
destContext.ExecuteQuery();
}
Help is really appreciated.
I assume item is the new ListItem you're trying to create on your target list.
But you're never in fact reading any value from field here! So basically, you're trying to set your new FieldLookup.LookupId with the item["Country"].LookupId, which should logically be empty at this moment.
Here's a method I use to retrieve a lookup field ListItem from a value, feel free to modify it to fit your need, since I don't know how you want to retrieve it (SPList is an alias for Microsoft.SharePoint.Client.List).
private ListItem GetLookupItem(FieldLookup lookupField, string lookupValue)
{
string mappingField = lookupField.LookupField;
Microsoft.SharePoint.Client.List lookupList = Context.Web.Lists.GetById(new Guid(lookupField.LookupList));
Context.Load(lookupList);
Context.ExecuteQuery();
ListItemCollection libListItems = lookupList.GetItems(CamlQuery.CreateAllItemsQuery());
Context.Load(libListItems, items => items.Include(
itemlookup => itemlookup.Id,
itemlookup => itemlookup[mappingField]));
Context.ExecuteQuery();
foreach (ListItem mappedItem in libListItems)
{
object mappedField = mappedItem[mappingField];
if (mappedField != null && mappedField.ToString().Equals(lookupValue))
return mappedItem;
}
return null;
}
Now that you have the corresponding ListItem, you can set your item.LookupId with its Id:
if (field is FieldLookup && field.InternalName == "Country")
{
FieldLookupValue flvRDS = new FieldLookupValue();
flvRDS.LookupId = GetLookupItem(field as FieldLookup, "France").Id; // here, dunno how you get your country's name
itemToCreate["Country"] = flvRDS;
itemToCreate.Update();
destContext.ExecuteQuery();
}
Feel free to add some more previous code if you want an answer more suited for your specific issue.
I am working on an application that uses Xpages and KendoUI. In one particular page I have a tool bar with a button with "Add Record". The button opens a window and the user will select one from a piece of data and that will create a new record.
The list of data are employee names and I must compute them. I do so in a sessionScope [could be viewScope] array in the beforePageLoad, like so:
<xp:this.beforePageLoad>
<![CDATA[#{javascript:viewScope.myArray = [];
viewScope.myArray.push("1st Val");
viewScope.myArray.push("2nd Val");
viewScope.myArray.push("3rd Val");}]]>
</xp:this.beforePageLoad>
The dropdown needs data in the following format:
var data = [
{ text: "Black", value: "1" },
{ text: "Orange", value: "2" },
{ text: "Grey", value: "3" }
];
For the life of me I cannot get the data into that format. It looks like a javascript object to me.
How do I get the array in the viewScope into the format I need?
var o = {};
o = "#{javascript:viewScope.get('myArray');";
All SSJS Array objects added to any of the scopes are converted to java.util.Vector (how to update a value in array scoped variable?) which can not be stringified with the standard toJson function. This can be circumvented by creating an intermediate object to store the array in:
viewScope.myData={myArray:[]};
viewScope.myData.myArray.push( { text : 'Mark' , value : '1' } );
viewScope.myData.myArray.push( { text : 'Bryan' , value : '2' } );
Also, I doubt your line of code returns the right data without any explicit JSON conversion. I would write it as:
var myArray = #{javascript:return toJson(viewScope.myData.myArray);};
When you set your client side js variable called o it's a string because the value is between "".
So just remove the double quotes and you'll get it as object.
o=#{javascript:viewScope.get('myArray')};
But be aware you might get an js client side error if the viewscope value is not a valid client side JS object !
You can also set the variable o to a string as you did in your example and use the eval clientside method to evaluate the string as an object.
o=eval("#{javascript:viewScope.get('myArray')}");
P.S. In your example there is a } missing is at the end of your SSJS code when you set your "o" variable.. ;-)
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 ---
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.
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.