PXDBCalced - how to invoke - acumatica

I have a custom DAC in which I have an unbound field on which I've applied a PXDBCalced attribute. I used PXDBCalced because I'm using two other fields that are on the DAC row. Here's how I have the field defined:
public abstract class margin : PX.Data.IBqlField
{
}
[PXDecimal(2)]
[PXDBCalced(typeof(Sub<IsNull<CFSVCProfile.revenueBudget,CFHelper.decimal_0>,
CFSVCProfile.costBudget>), typeof(Decimal))]
[PXDefault(TypeCode.Decimal, "0.0")]
[PXUIField(DisplayName = "Margin", Enabled = false)]
public virtual decimal? Margin { get; set; }
The problem I am having is that the field that has the PXDBCalced attribute is not getting updated when I update the row in the DAC. So, how do I get the calculation to run and update the field?
Thanks!

I would try PXFormula or PXUnboundFormula on your field as its not necessary to hit the database with PXDBCalced based on your example.
[PXUnboundFormula(typeof(Sub<IsNull<CFSVCProfile.revenueBudget,CFHelper.decimal_0>,
CFSVCProfile.costBudget>))]

Related

Field filter within the grid

I'm not good at English.
I want to know if it is possible to filter field in grid.
I have a problem I am filtering a field, but it is not updated in selector, where it should show what I want.
here I show an image.
I will thank you all very much.
here I put the code I did:
#region CategoryID
[PXDBInt()]
[PXUIField(DisplayName = "Category ID")]
[PXSelector(typeof(Search<PESKPriceIndexCat.categoryID,
Where<PESKPriceIndexCat.state, Equal<Current<stateID>>,
And<PESKPriceIndexCat.active, Equal<True>>>>),
typeof(PESKPriceIndexCat.categoryID),
typeof(PESKPriceIndexCat.categoryCD),
typeof(PESKPriceIndexCat.descripcion),
DescriptionField = typeof(PESKPriceIndexCat.descripcion), SubstituteKey =
typeof(PESKPriceIndexCat.categoryCD))]
public virtual int? CategoryID { get; set; }
public abstract class categoryID : PX.Data.BQL.BqlInt.Field<categoryID> { }
#endregion
The definition of the selector in the DAC seems to be correct, therefore one possible solution would be to set the AutoRefresh property on the selector from the layout editor to true and the SyncPosition property on the grid to true as well. With these two properties the current value will update on row change and when opening the selector it will automatically refresh with the correct dataset.

Show unbound field with PXFormula

I'm trying to show a value calculated with PXFormula but the field doesn't show the value.
I have my CustomDAC named EDITran
public class EDITran : IBqlTable
{
#region Doctype
[PXDBString(50, IsKey = true, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "Doctype")]
[PXStringList
(new string[]
{"SO", "SHI", "INV" },
new string[]
{"Sales Order", "Shipment", "Invoice"}
)]
public virtual string Doctype { get; set; }
public abstract class doctype : PX.Data.BQL.BqlString.Field<doctype> { }
#endregion
#region Erprefnbr
[PXDBString(30, IsKey = true, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "ERP RefNbr")]
public virtual string Erprefnbr { get; set; }
public abstract class erprefnbr : PX.Data.BQL.BqlString.Field<erprefnbr> { }
#endregion
#region Sync
[PXDBBool()]
[PXUIField(DisplayName = "Sync")]
public virtual bool? Sync { get; set; }
public abstract class sync : PX.Data.BQL.BqlBool.Field<sync> { }
#endregion
}
}
so I what to show the value of sync field on the Sales Order screen. The key is the ERP RefNbr (which would be SOOrder.OrderNbr)
I have added the custom non persisted field on the SOOrderExt DAC with this attributes
using PX.Objects.SO;
[PXBool]
[PXUIField(DisplayName="EDI Sync" , Enabled = false)]
[PXFormula(typeof(Selector<SOOrder.orderNbr,
Selector<EDITran.erprefnbr,
EDITran.sync>>))]
But when I added a record in EDITran and try to visualize it in SOOrder Form and I checked that EDITran.Sync = 1, it doesn't show the saved value.
Sales Order Screen
What I'm I doing wrong? Is the PXFormula correctly used?
PXFormula used incorrectly. PXFormula attribute works only with current DAC (which is SOOrder) or foreign DAC, existing in PXSelector join condition (you can use Selector keyword to get it).
For example, here is the SOOrder.OrderNbr selector declaration
[SO.RefNbr(typeof(Search2<SOOrder.orderNbr,
LeftJoinSingleTable<Customer, On<SOOrder.customerID, Equal<Customer.bAccountID>,
And<Where<Match<Customer, Current<AccessInfo.userName>>>>>>,
Where<SOOrder.orderType, Equal<Optional<SOOrder.orderType>>,
And<Where<Customer.bAccountID, IsNotNull,
Or<Exists<Select<SOOrderType,
Where<SOOrderType.orderType, Equal<SOOrder.orderType>,
And<SOOrderType.aRDocType, Equal<ARDocType.noUpdate>,
And<SOOrderType.behavior, Equal<SOBehavior.sO>>>>>>>>>>,
OrderBy<Desc<SOOrder.orderNbr>>>), Filterable = true)]
public virtual String OrderNbr
you can get some fields from the related Customer record, using Selector keyword
[PXFormula(typeof(Selector<
SOOrder.orderNbr,
Customer.consolidateStatements>))]
As a result, there are two possible solutions:
1) Rewrite SOOrder.OrderNbr selector declaration with your EDITran DAC
...
[SO.RefNbr(typeof(Search2<SOOrder.orderNbr,
LeftJoinSingleTable<Customer, On<SOOrder.customerID, Equal<Customer.bAccountID>,
And<Where<Match<Customer, Current<AccessInfo.userName>>>>>,
LeftJoin<EDITran, On<EDITran.doctype, Equal<SOOrder.orderType>,
And<EDITran.erprefnbr, Equal<SOOrder.orderNbr>>>>>,
Where<SOOrder.orderType, Equal<Optional<SOOrder.orderType>>,
And<Where<Customer.bAccountID, IsNotNull,
Or<Exists<Select<SOOrderType,
Where<SOOrderType.orderType, Equal<SOOrder.orderType>,
And<SOOrderType.aRDocType, Equal<ARDocType.noUpdate>,
And<SOOrderType.behavior, Equal<SOBehavior.sO>>>>>>>>>>,
OrderBy<Desc<SOOrder.orderNbr>>>), Filterable = true)]
public virtual String OrderNbr
Then it will be possible to get you field from there
[PXFormula(typeof(Selector<
SOOrder.orderNbr,
EDITran.sync>))]
2) Use PXDBScalar attribute to just get what you need. Note this will be a separate request to the database!!
...
[PXBool]
[PXDBScalar(typeof(Search<EDITran.sync,
Where<EDITran.doctype, Equal<SOOrder.orderType>,
And<EDITran.erprefnbr, Equal<SOOrder.orderNbr>>>>))]
public virtual bool? Sync
I'm not sure that's the right use of PXFormula. Here's the reference I normally use when I need to use PXFormula. See if it helps you simplify your PXFormula. You may need to simplify to a single Selector and define a foreign key to be able to complete your lookup.
Also, are you sure that the database contains the values that you expect? I often find that my problem is not where I think, and your issue may lie in setting the values or writing them to the database in your business logic.
It appears that you need the PXFormula to look to your EDITran table to find the record identified by the key (1st field specified in Selector) to then return back the value of the second field specified, which would reside in EDITran.
From Acumatica Developers Blog (AsiaBlog):
Selector
Selector does following:
Fetches a PXSelectorAttribute defined on the foreign key field (KeyField) of the current DAC.
Fetches the foreign data record currently referenced by the selector.
Using calculates and returns an expression on that data record as defined by ForeignOperand.
public class APVendorPrice : IBqlTable
{
// Inventory attribute is an aggregate containing a PXSelectorAttribute
// inside, which is also valid for Selector<>.
[Inventory(DisplayName = "Inventory ID")]
public virtual int? InventoryID
[PXFormula(typeof(Selector<
APVendorPrice.inventoryID,
InventoryItem.purchaseUnit>))]
public virtual string UOM { get; set; }
}
From that, I'd expect your PXFormula to look more like:
[PXFormula(typeof(Selector<
SOOrder.orderNbr,
EDITran.sync>))]
... assuming you have enough defined to tell Acumatica how to relate SOOrder.orderNbr to EDITran.erprefnbr.

Acumatica Numbering Sequence - cant default to the new symbol

I've got a custom table storing serviceable components within fixed assets. The list is accessed using a grid on the AssetMaint screen.
I've set up an ID field to populate using a numbering sequence. I'm unsure how to set the default so this field populates with "<NEW>" by default, which is then updated by the numbering sequence when the component is saved.
It's sort of working, but there are a few issues. When I click the add button, the ID field is blank, but when I click add again, it populates with the "<NEW>" symbol. However if I add a third record before hitting save, the second record does not populate with "<NEW>". The second record is also not saved, unless I manually put "<NEW>" in the ID field.
This is part of the DAC for the component table:
[Serializable]
public class FAServiceComponent : IBqlTable
{
#region AssetID
public abstract class assetID : IBqlField { }
[PXDBInt(IsKey = true)]
[PXDBDefault(typeof(FixedAsset.assetID), DefaultForUpdate = false)]
[PXParent(typeof(Select<FixedAsset, Where<FixedAsset.assetID, Equal<Current<FAServiceComponent.assetID>>>>))]
[PXUIField(DisplayName = "Asset ID", Visible = false, Enabled = false)]
public virtual int? AssetID { get; set; }
#endregion
#region serviceComponentID
public abstract class serviceComponentID : IBqlField { }
[PXDBString(30, IsKey = true, IsUnicode = true)]
[PXUIField(DisplayName = "Component ID")]
[PXDefault(typeof(Search2<Numbering.newSymbol,
InnerJoin<FixedAsset, On<FixedAssetExt.usrServiceComponentNumberingSeq, Equal<Numbering.numberingID>, And<FixedAsset.assetID, Equal<Current<FixedAsset.classID>>>>>>))]
[Numbering]
public virtual string ServiceComponentID { get; set; }
#endregion
#region serviceComponentDescription
public abstract class description : IBqlField { }
[PXDBString(255)]
[PXUIField(DisplayName = "Description")]
[PXDefault(PersistingCheck = PXPersistingCheck.Nothing)]
public virtual string Description { get; set; }
#endregion
public class NumberingAttribute : AutoNumberAttribute
{
public NumberingAttribute():
base(typeof(Search<FixedAssetExt.usrServiceComponentNumberingSeq, Where<FixedAsset.assetID, Equal<Current<FixedAsset.classID>>>>),
typeof(AccessInfo.businessDate)) {; }
}
}
Check out T200 course available at Acumatica Open University. Part 4 Lesson 8 show you how to use the AutoNumberAttribute.
I would first suggest to remove the following code, as it is not required to make the < New > symbol work.
[PXDefault(typeof(Search2<Numbering.newSymbol,
InnerJoin<FixedAsset, On<FixedAssetExt.usrServiceComponentNumberingSeq, Equal<Numbering.numberingID>, And<FixedAsset.assetID, Equal<Current<FixedAsset.classID>>>>>>))]
You should have a setup screen where you choose the numbering sequence you want to use. As an example, the Sales Orders Preferences screen (SO101000) has the Shipment Numbering Sequence field, bound to SOSetup.ShipmentNumberingID.
In your graph, make sure you have the setup data view, something like public PXSetup<Setup> AutoNumSetup;. The PXSetup DAC should match with your setup screen, e.g. PXSetup<SOSetup> ShipmentSetup
In your DAC, the numbered field should have the AutoNumberAttribute referencing the setup table. e.g.
[AutoNumber(typeof(SOSetup.ShipmentNumberingID), typeof(SOShipment.shipDate))]
In Numbering Sequence screen (CS201010), make sure that Manual Numbering is unchecked and that you have a New Number Symbol set for the numbering sequence you are using.

How to default an employeeid field to the current logged in user

I have a custom inquiry screen which uses an employeeid as the header filter field. What I'd like to do is default that employeeid field to the current logged in user, if possible. I've tried the following, but both give me a cast error (version 5.3.2562):
1.) [PXDBDefault(typeof(Search<EPEmployee.bAccountID,
Where<EPEmployee.bAccountID, Equal<Current<AccessInfo.userID>>>>))]
2.) [PXDBDefault(typeof(AccessInfo.userID))]
Here's the entire DAC code for the filter field:
#region EmployeeID
public abstract class employeeID : IBqlField
{
}
[PXInt]
[PXDBDefault(typeof(AccessInfo.userID))]
[PXUIField(DisplayName = "Employee ID")]
[PXSelector(typeof(Search<EPEmployee.bAccountID,
Where<EPEmployee.status, Equal<SetupTypes.active>>>),
typeof(EPEmployee.acctCD),
typeof(EPEmployee.acctName),
SubstituteKey = typeof(EPEmployee.acctCD),
DescriptionField = typeof(EPEmployee.acctName))]
public virtual int? EmployeeID { get; set; }
#endregion
What's the correct way to obtain this?
Update 6/30/2017:
After implementing the solution (using PXDefault instead of PXDBDefault) as follows:
[PXDefault(typeof(Search<EPEmployee.bAccountID,
Where<EPEmployee.bAccountID, Equal<Current<AccessInfo.userID>>>>))]
I get the following error:
We have a non filter field in a transaction able that defaults to the current employee.
This should work:
[PXDefault(typeof(Search<EPEmployee.bAccountID,
Where<EPEmployee.bAccountID, Equal<Current<AccessInfo.userID>>>>))]
Note that you do not want to use PXDBDefault for default values unless they are values coming from a parent DAC when linked with PXParent. Use PXDefault for defaults.
If this does not work in your filter, try PXUnboundDefault in place of PXDefault.
Edit 6/30/2017: new error might be on your selector. There is an employee selector already available. Remove your PXSelector and use [PXEPEmployeeSelector] on your field and see if this solves your error between uniqueidentifier and int
AccessInfo.userID seems to be a GUID. In order to avoid the casting error you need to relate AccessInfo.userID to EPEmployee.userID while searching for EPEmployee.bAccountID. Final code should look like this:
#region EmployeeID
public abstract class usrEmployeeID : IBqlField
{
}
[PXEPEmployeeSelector]
[PXUnboundDefault(typeof(Search<EPEmployee.bAccountID,
Where<EPEmployee.userID, Equal<Current<AccessInfo.userID>>>>))]
[PXUIField(DisplayName = "Employee ID")]
public virtual int? UsrEmployeeID { get; set; }
#endregion

Accessing user-defined fields added via an extension in Acumatica

I have a custom field called 'UsrIsTeacherBook` which was added to the InventoryItem with the following extension:
namespace Lasalle.TeacherBooks
{
public class InventoryItem_TeacherBooks_Extension : PXCacheExtension<InventoryItem>
{
[PXDBBool]
[PXUIField(DisplayName = "Is Teacher Book")]
public virtual bool? UsrIsTeacherBook { get; set; }
public abstract class usrIsTeacherBook : IBqlField { }
}
}
I need to be able to access the value of this IsTeacherBook field from the SOLine grid on the SalesOrder screen. I added a custom field UsrTeacherBook to the SOLine grid on the sales order screen, but I cannot figure out how to populate this field with the value of InventoryItem UsrIsTeacherBook.
I tried customizing the attributes on the SOLine field in the following way:
[PXDBBool]
[PXUIField(DisplayName="Teacher Manual", Visible = true, Enabled = false)]
[PXFormula(typeof(Selector<SOLine.inventoryID, InventoryItemExt.usrIsTeacherBook>))]
But this produced a validation error, "The type name 'usrIsTeacherBook' does not exist in the type 'PX.Objects.IN.InventoryItemExt'."
What is the correct way to access the InventoryItem IsTeacherBook field to populate my field on the SOLine grid?
Your extension class name is InventoryItem_TeacherBooks_Extension, not InventoryItemExt used in PXFormulaAttribute. You should either change your extension name to InventoryItemExt or modify PXFormula declaration with InventoryItem_TeacherBooks_Extension.usrIsTeacherBook

Resources