I am building a Generic Inquiry which would list the Contract Details with FixedRecurringPriceVal and UsrCustomFixedRecurringPriceVal. The later is a custom persistent field. Now, in this Generic Inquiry I would like to list only those Contract Details from Customer Contract which have different FixedRecurringPriceVal and UsrCustomFixedRecurringPriceVal.
But, those I can use FixedRecurringPriceVal in Results Grid, it appears that I can't use this field in Condition where I needed to compare between these fields.
Upon looking at Data field source I find this.
[PXDecimal(6)]
[PXFormula(typeof(GetItemPriceValue<
ContractDetail.contractID,
ContractDetail.contractItemID,
ContractDetailType.ContractDetail,
ContractDetail.fixedRecurringPriceOption,
Selector<ContractDetail.contractItemID, ContractItem.recurringItemID>,
ContractDetail.fixedRecurringPrice,
ContractDetail.basePriceVal,
ContractDetail.qty,
Switch<
Case<Where<Parent<Contract.status>, Equal<Contract.status.draft>,
Or<Parent<Contract.status>, Equal<Contract.status.pendingActivation>>>,
IsNull<Parent<Contract.activationDate>, Parent<Contract.startDate>>,
Case<Where<Parent<Contract.status>, Equal<Contract.status.active>,
Or<Parent<Contract.status>, Equal<Contract.status.inUpgrade>>>,
IsNull<Parent<ContractBillingSchedule.nextDate>, Current<AccessInfo.businessDate>>,
Case<Where<Parent<Contract.status>, Equal<Contract.status.expired>>,
IsNull<Parent<ContractBillingSchedule.nextDate>, Parent<Contract.expireDate>>,
Case<Where<Parent<Contract.status>, Equal<Contract.status.canceled>>,
IsNull<Parent<Contract.terminationDate>, Current<AccessInfo.businessDate>>>>>>,
Current<AccessInfo.businessDate>>>))]
[PXUIField(DisplayName = "Recurring Price")]
public decimal? FixedRecurringPriceVal
{
get;
set;
}
So, for me it looks like Non Persistent field can't be used in Generic Inquiry Conditions. I did a bit of google but couldn't find any solution and also looked at the S130 Data Retrieval and Analysis and couldn't find specific to such case.
Is there any way we can achieve this?
Thanks.
No, you can't use Non Persistent fields in the Conditions.
The field dropdown is intentionally excluding them. Below is the FieldSelecting event handler from the GenericInquiryDesigner graph which is loading the dropdown.
protected void GIWhere_DataFieldName_FieldSelecting(PXCache cache, PXFieldSelectingEventArgs e)
{
string[] allParameters = this.GetAllParameters(true);
PXStringListAttribute.SetList(cache, e.Row, typeof(GIWhere.dataFieldName).Name, allParameters, allParameters);
this.a<GIWhere.dataFieldName>(cache, e.Row, true, (PXCache c, string f) => !PXGenericInqGrph.IsVirtualField(c, f, null));
}
The only way, in this case, will be to create a separate page instead of GI.
Related
I created a custom table with additional settings for customers. Next I added a field to the customer core table in which I'd like to store the id choice per customer. I extended with EntityExtensionInterface the customerDefinition :
public function extendFields(FieldCollection $collection): void
{
$collection->add(
(new OneToOneAssociationField(
'customerSetting',
'customer_setting',
'id',
WdtCustomerSettingsDefinition::class,
true
))->addFlags(new Inherited())
);
}
public function getDefinitionClass(): string
{
return CustomerDefinition::class;
}
When I manually manipulate the customer table, with an id from my custom table in the added field, I can retrieve and use the settings from my custom table in the storefront.
For the backend I created a single select to the entity custom_table,
<sw-entity-single-select entity="wdt_customer_settings" v-model="customer.extensions.customerSetting.id" >
</sw-entity-single-select>
and with the manually 'injected' id from the custom table, this choice indicates indeed 'selected' However, after changing to another choice and saving results in an error: Customer could not be saved.
What am I missing?
You should look always to the ajax responses. There is the explict error which is occured. Do you added some boilerplate code to check that your extensions is always available? Otherwise it would cause issues on new entities
I found it very odd that the base installation of Acumatica did not contain the ability to document approved Manufacturer/part number for Stock Items, so I added this functionality to my customization project. The design allows each branch to define their own approved manufacturers and part number, but I need to allow a user with access to only one branch to see the approved manufacturers from other branches.
My DAC's are SSINManufacturer (the manufacturer master) and SSINItemManufacturer (the individual branch specific manufacturer part number record for the Stock Item).
The customization was added as a new tab under Stocked Items as a grid view. Access control by branch (across the system) is handled via a user role for the branch, but I need allow any user with access to Stocked Items to see all manufacturer part numbers from any branch.
I found a post in AsiaBlog (https://asiablog.acumatica.com/2015/11/using-scopes-in-acumatica.html) that mentions the use of PXReadBranchRestrictedScope to "remove restriction by branches that will be automatically applied by the system core, if you have BranchID attribute in the selected DAC". I was advised not to use BranchID, but rather UsrBranchID in my custom DAC's, but I suspect this is the underlying reason that I'm still restricted to just the current branch data in this view.
I am just starting to learn to use a constructor to override the default results that a view would generate, and I'm not sure that this definition is correct.
public PXSelectJoin<SSINItemManufacturer,
InnerJoin<SSINManufacturer, On<SSINManufacturer.manufacturerID, Equal<SSINItemManufacturer.manufacturerID>>>,
Where<SSINItemManufacturer.inventoryID, Equal<Current<InventoryItem.inventoryID>>
>> ItemManufacturerXrefs;
public virtual IEnumerable itemmanufacturerxrefs()
{
using (new PXReadBranchRestrictedScope())
{
PXResult<SSINItemManufacturer> Results = PXSelectJoin<SSINItemManufacturer,
InnerJoin<SSINManufacturer, On<SSINManufacturer.manufacturerID, Equal<SSINItemManufacturer.manufacturerID>>>,
Where<SSINItemManufacturer.inventoryID, Equal<Current<InventoryItem.inventoryID>>
>>.Select(Base);
yield return Results;
}
}
Is the constructor defined correctly to leverage PXReadBranchRestrictedScope? And do I need to add BranchID to my DAC to make this return all records for the Stocked Item in the tenant?
Two issues found which resolved the problem. First, the PXResultset was defined as PXResult which returned only 1 value, and the subsequent method of returning the result needed to be expanded to more explicitly build the results to be returned.
public virtual IEnumerable itemmanufacturerxrefs()
{
using (new PXReadBranchRestrictedScope())
{
PXResultset<SSINItemManufacturer> Results = PXSelectJoin<SSINItemManufacturer,
InnerJoin<SSINManufacturer, On<SSINManufacturer.manufacturerID, Equal<SSINItemManufacturer.manufacturerID>>>,
Where<SSINItemManufacturer.inventoryID, Equal<Current<InventoryItem.inventoryID>>
>>.Select(Base);
foreach (PXResult<SSINItemManufacturer, SSINManufacturer> result in Results)
{
SSINItemManufacturer mfgitem = result;
SSINManufacturer mfg = result;
yield return new PXResult<SSINItemManufacturer, SSINManufacturer>(mfgitem, mfg);
}
}
}
Secondly, upon closer review of the post on AsiaBlog, the BranchID (actually Branch) ATTRIBUTE needed to be added to the field of the DAC. UsrBranchID is fine for a field name, provided the [Branch] attribute was added.
#region UsrBranchID
[Branch(IsKey = true)]
[PXDefault(typeof(AccessInfo.branchID))]
[PXUIField(DisplayName = Messages.FldUsrBranchID)]
public virtual int? UsrBranchID { get; set; }
public abstract class usrBranchID : PX.Data.BQL.BqlInt.Field<usrBranchID> { }
#endregion
The scope override works well. The use of the constructor on the view allows me to grant visibility to the data from all branches "as advertised".
In the Sales Order page, I created a custom button which purpose is to save and refresh the page. Currently it saves fine and processes the new order to an order number but when I try to add an item/edit or perform an action in the drop down menu I receive the error message.
Here's my code:
public PXAction<SOOrder> SRefresh;
[PXUIField(DisplayName = "S RefreshT")]
[PXButton(CommitChanges = true)]
protected virtual IEnumerable sRefresh(PXAdapter adapter)
{
SOOrderEntry graph = PXGraph.CreateInstance<SOOrderEntry>();
Base.Actions.PressSave();
SOLine sLine = PXSelect<SOLine, Where<SOLine.orderNbr, Equal<Required<SOLine.orderNbr>>>>.Select(graph, this.Base.Document.Current.OrderNbr);
if (sLine != null && sLine.InventoryID.HasValue)
{
graph.Document.Current = graph.Document.Search<SOLine.orderNbr>(sLine.OrderNbr);
throw new PXRedirectRequiredException(graph, null);
}
return adapter.Get();
}
I've also tried using graph.Persist() as said in the manual instead of Action.PressSave(); with no success.
I appreciate any input you guys may have, Thank you
Since you're working with the current sales order, you don't need to create a new instance of the sales order entery graph and redirect your user. You can work with the Base object and run all your logic on it.
Base.Document.Current contains a reference to the current SOOrder, and Base.Transactions contains the list of SOLine of this document. Another problem I also found in your code is that you're calling Document.Search<SOline.orderNbr>; it should be SOOrder.orerNbr since you're searching inside the Document view, which contains sales orders, and not lines. In this case, it's not even necessary to search, Base.Document.Current will already be set to the order you're looking at.
I strongly recommend completing the standard Acumatica developer trainings - T100, T200, T300; this stuff is all covered and will get you productive quickly
I'm using EF5 code first to generate my database schema, but my new navigation property is being named in an undesirable way in the table. here is the model I'm working with.
public class User
{
[Key]
public long UserId { get; set; }
...
**public virtual ICollection<ImagePermission> KeepThisNavigationName { get; set; }**
}
However, After I've updated my database and examine the table columns, the column is named:
dbo.ImagePermission.User_UserId
And I would like it to be named
dbo.ImagePermission.KeepThisNavigationName_UserId
I believe there is a way to do this using the Fluent API, but after many failed attempts, I can't get the desired outcome.
P.s. The 'ImagePermission' Entity is currently still in development, so I would prefer to drop the migration which creates this table so I can create this column name correctly during the table create, rather than having additional code to update the column name.
Many thanks, Oliver
The correct mapping with Fluent API would be:
modelBuilder.Entity<User>()
.HasMany(u => u.KeepThisNavigationName)
.WithOptional() // or WithRequired()
.Map(m => m.MapKey("KeepThisNavigationName_UserId"));
If you have a navigation property in ImagePermission refering to User you need to use WithOptional(i => i.User) (or WithRequired(i => i.User)) instead of the parameterless version.
am trying to access both the Phone's phonebook and SIM phonenook on Nokia 5130c-2 XpressMusic.
The app runs without errors but it only returns the numbers from the phone's Phonebook. When I list the available phonebooks using this code
String[] all_contact_lists=PIM.getInstance().listPIMLists(PIM.CONTACT_LIST);
it gives me both the Phonebook and SIM card lists. i.e
1. Phone
2. SIM
I have tried explicitly reading from the SIM card using this code but it still returns nothing(even though I have numbers saved in the SIM card.)
Code:
ContactList clist = (ContactList) PIM.getInstance().openPIMList(PIM.CONTACT_LIST, PIM.READ_ONLY,
"SIM");
Here's my complete code::
import javax.microedition.midlet.*;
import javax.microedition.pim.*;
import com.sun.lwuit.*;
import java.util.*;
public class contacts extends MIDlet
{
private List my_list=new List();
private String[] names=null;
public void startApp()
{
Display.init(this);
Form my_form=new Form("Contacts List");
String[] all_contact_lists=PIM.getInstance().listPIMLists(PIM.CONTACT_LIST);
//Iterate through available phonebooks
for(int db=0; db<all_contact_lists.length; db++)
{
try {
ContactList clist = (ContactList) PIM.getInstance().openPIMList(PIM.CONTACT_LIST, PIM.READ_ONLY,
all_contact_lists[db]);
Enumeration contacts=clist.items();
while(contacts.hasMoreElements())
{
Contact contact=(Contact)contacts.nextElement();
try{
String phone_contact="";
names=contact.getStringArray(Contact.NAME, 0);
for(int i=0; i<names.length; i++)
{
if(names[i]!=null)
phone_contact+=" "+names[i];
}
//my_list.addItem(phone_contact);
int phone_numbers=contact.countValues(Contact.TEL);
if(phone_numbers>0)
{
String number=contact.getString(Contact.TEL,0);
my_list.addItem(phone_contact+":"+number);
}
else
{
my_list.addItem(phone_contact);
}
//clist.removeContact(contact);
}
catch (Throwable t) {
t.printStackTrace();
}
}
} catch (PIMException ex) {
ex.printStackTrace();
}
}
//my_list.addItem(all_contact_lists);
my_list.setRenderingPrototype("WWWWWWWWWWWWWWWWWWWW");
my_form.addComponent(my_list);
my_form.show();
}
public void pauseApp(){}
public void destroyApp(boolean unconditional){}
}
If you are using the phone number for a text or to call you can do that with only one line of code. Its now evident that phone software issues can affect the way the app accesses the PIM API. Also, if memory in use in the phones contact settings is set to SIM(alone), you can't access contacts in phone memory and vice versa, make sure both are in use. Try this if you still have an issue,
//make a text field in LWUIT that is declared globally
PhnNmbr = new TextField();
//set it to only accept phonenumber
PhnNmbr.setConstraint(TextField.PHONENUMBER);
//tell the user how to access phonebook
PhnNmbr.setHint("Press T9 then 'Search' to search phonebook");
//add a button or command
//that either sends an sms to
//or calls the number in the text field
//or anything else you want to do with it
When the user presses T9, the TextField is considered an LCDUI text field with parameter PHONENUMBER which allows it to search for contacts in both Sim and phone memory, thats why you'll notice a Search command(usually at the bottom center). Also make sure that the memory in use for the phone is set to both Phone and Sim.
An excerpt from PIM javadoc
PIMItems reference its data through fields. A field is a grouping of
data values that all have similar characteristics. An example of a
field is TEL, which indicates data values for that particular field
are telephone numbers. Classes implementing the PIMItem interface
defines the possible fields that for that specific class (e.g TEL is
defined in the Contact interface as a field that a contact may
support).
PIM implementations are not required to support all of the possible
fields defined in the classes implementing the PIMItem interface. This
is because no native PIM databases contain all of the fields defined
in this API. The PIMList that a PIMItem belongs to determines what
fields a PIMItem can support and store (all PIMItems in a particular
PIMList support the same set of fields). The
PIMList.getSupportedFields() method from a particular PIMItem's
PIMList is used to find out what fields are supported within this
item. Since not all possible fields are actually supported in a
particular PIMItem, all fields should be checked for support in the
item's PIMList using PIMList.isSupportedField(int) prior to being used
in any retrieval or storage method.
Each field has the following pieces of information available for it:
Zero or more data values associated with the Field
Attributes for data values for the Field
Descriptive label for the Field
Data Type of the data associated with the Field
Complete PIM javadoc can be read at this link.
Check if the device support's PIM Fields Contact.NAME and Contact.TEL on your device. If not then you need to call PIMList.getSupportedFields() to get the supported field on device and accordingly fetch the name and the telephone number for that device. If I remember correct, the alternative field for name is Contact.FORMATTED_NAME.