PXDBCreatedDateTime doesn't work in Extension Table - acumatica

I have a User Defined Table that I link to the BAccount table in Acumatica. What I'm trying to do is use the PXDBCreatedDateTime attribute to save the CreateDateTime when the UDFs are set. Is this posssible? It doesn't seem to work right now.
[PXTable(typeof(BAccount.bAccountID),IsOptional=true)]
public class CustomerExtension : PXCacheExtension<BAccount>
{
[PXDBCreatedDateTime()]
[PXUIField(DisplayName = "Date")]
public DateTime? CreatedDateTime { get; set; }
public class createdDateTime : IBqlField { }
}

I would assume it would not work as the BAccount table already contains a field with the same name 'CreatedDateTime'. I would first use a different field name for table extension fields as this could create some conflicts to those fields that already exist with the same name. Also, extension tables are inserted when the base table is either inserted or updated (first time after extension table is added) which may or may not occur from changes to your extension fields. This would also cause some issues for getting a good date from your PXDBCreatedDateTime field. You might be better off using a standard date time field and use some type of formula to update the date when your fields change. I would have to research the formula. You could use logic inside the setter of your user fields and add the PXDependsOnFields attribute to your date field and set your date field if null. I have not tried PXDependsOnFields in an extension - but the logic could be promising.

Related

Dynamically changing field's DisplayName affests web service

The field in the DAC is defined like this.
#region NextMonthHours
[PXDBDecimal(2, MinValue = 0.0, MaxValue = 280.0)]
[PXUIField(DisplayName = "Next Month Hours")]
[PXDefault(TypeCode.Decimal, "0.0")]
public virtual Decimal? NextMonthHours { get; set; }
public abstract class nextMonthHours : PX.Data.BQL.BqlDecimal.Field<nextMonthHours> { }
#endregion
I change the display name of the field in RowSelected event.
PXUIFieldAttribute.SetDisplayName<EVEPPlannedHoursDetails.nextMonthHours>(sender, nextMonth+"Hours");
where nextMonth is "February".
I need to add this field to Acumatica Mobile Screen. When I go to web service schema the field name is "FebruaryHours"
<s:element minOccurs="0" maxOccurs="1" name="FebruaryHours" type="tns:Field"/>
I cannot use the name "FebruaryHours" because it changes every month but I also when I use field name NextMonthHours it is not added in the mobile screen.
Any idea how to solve this issue?
Thanks
There's quite a few ways to workaround this depending on the use case and whether the label value is static or dynamic.
If all you want to do is to change a static label in UI without having to change the display name property you can add a separate label and merge group.
Here's an example to change Billable in UI without changing DisplayName property using that technique.
Set SuppressLabel property to true to hide the original label bounded to DisplayName on UI.
Use ADD CONTROLS tab to add a Layout Rule with Merge property set to true.
Use ADD CONTROLS tab to add a label control in the merged group.
Put the original field in the merge group so they show up together on the same line in UI.
End result, label is now a UI control and wouldn't interfere with DisplayName property.

How to make Tax Category field in AP Invoice line required and still update detail total and balance

I am trying to make a field required on the line item of an AP Invoice, the Tax Category field. However when I change the field to be required I run into the problem of the detail total and the balance to no longer update on the form.
What I've tried doing is eliminating the PersistingCheck = PXPersistingCheck.Nothing of the PXDefault attribute of the TaxCategoryID. This causes the field to be required on the form, however as I've stated, it also causes the form to no longer update totals. I've tried changing the PersistingCheck to PXPersistingCheck.Null, but this also prevents the totals from being updated.
Originally the PXDefault attribute for the Tax Category field is as follows:
[PXDefault(typeof(Search<InventoryItem.taxCategoryID,
Where<InventoryItem.inventoryID, Equal<Current<APTran.inventoryID>>>>),
PersistingCheck = PXPersistingCheck.Nothing)]
This is what my code is:
[PXDefault(typeof(Search<InventoryItem.taxCategoryID,
Where<InventoryItem.inventoryID, Equal<Current<APTran.inventoryID>>>>))]
What I want is to be able to have the Tax Category field required and the totals to be updated as usual, but I am not able to due to something in the code preventing the totals to be updated when the PXDefault attribute of the Tax Category field is changed.
Is there anything additional I must do in order for these issues to be resolved or am possibly going about this the wrong way?
You need to correctly change the PersistenceCheck and add Required=true to PXUIFieldAttribute for showing a red asterisk symbol near the column's name. Please see the example of how to do that using PXMergeAttributesAttribute and PXCustomizeBaseAttribute:
public class APInvoiceEntry_Extension : PXGraphExtension<APInvoiceEntry>
{
#region Event Handlers
[PXMergeAttributes(Method = MergeMethod.Merge)]
[PXCustomizeBaseAttribute(typeof(PXUIFieldAttribute), nameof(PXUIFieldAttribute.Required),true)]
[PXCustomizeBaseAttribute(typeof(PXDefaultAttribute), nameof(PXDefaultAttribute.PersistingCheck), null)]
protected virtual void APTran_TaxCategoryID_CacheAttached(PXCache cache)
{
}
#endregion
}

How to make sure specific line from PXSelector is chosen

I've got a PXSelector that selects several fields, the first one being a field whose value may be repeated (as follows):
Field1 Field2 Field3
1234 LL description1
1234 PS description2
1234 CC description3
4321 BB description4
PXSelector code:
[PXSelector(typeof(myTable.field1)
,typeof(myTable.field1)
,typeof(myTable.field2)
,typeof(myTable.field3)
,DescriptionField = typeof(myTable.field3))]
The DAC for the selected table has Field1 and Field2 as keys.
If I select row two or three above, I'll get the row one's Field3 description every time. Is there a way to ensure that I only get the description of the row that I've selected, instead of always getting the first occurrence?
You have to make the selector operate on a single key because the selected value is the key field not the whole DAC record.
One possible approach is to add a unique record number column to the database table, make the selector operate on that column and set a different 'TextField' property for the selector so it doesn't show the record number.
Here's how I did it to make a selector on SerialNumber/InventoryItem which is not a unique value (contains duplicate).
Database scripts will vary with database systems. I'm using this script for MSSQL to add the unique record number to the table:
--[mysql: Skip]
--[IfNotExists(Column = SOShipLineSplit.UsrUniqueID)]
BEGIN
alter table SOShipLineSplit add UsrUniqueID int identity(1,1)
END
GO
This is the DAC declaration. I use PXDBIdentity to match the DB identity field type that tag the column as a record number field:
[Serializable]
public class SOShipLineSplit_Extension : PXCacheExtension<SOShipLineSplit>
{
#region UsrUniqueID
public abstract class usrUniqueID : IBqlField { }
[PXDBIdentity(IsKey = false)]
[PXUIField(DisplayName = "ID")]
public virtual int? UsrUniqueID { get; set; }
#endregion
}
I use another DAC field for the selector which uses this unique id key and I set the description to the real field I want to appear in the selector:
#region SerialUniqueID
public abstract class serialUniqueID : IBqlField { }
[PXSelector(typeof(Search5<SOShipLineSplit_Extension.usrUniqueID,
InnerJoin<SOShipment, On<SOShipment.customerID, Equal<Current<customerID>>,
And<SOShipment.shipmentNbr, Equal<SOShipLineSplit.shipmentNbr>>>,
InnerJoin<InventoryItem, On<InventoryItem.inventoryID, Equal<SOShipLineSplit.inventoryID>>>>,
Where<SOShipLineSplit.lotSerialNbr, NotEqual<StringEmpty>>,
Aggregate<GroupBy<SOShipLineSplit.lotSerialNbr,
GroupBy<SOShipLineSplit.inventoryID>>>>),
typeof(SOShipLineSplit.lotSerialNbr),,
typeof(SOShipLineSplit.inventoryID),
typeof(InventoryItem.descr),
CacheGlobal = true,
DescriptionField = typeof(SOShipLineSplit.lotSerialNbr))]
[PXDBInt]
[PXUIField(DisplayName = "Serial Number")]
public virtual int? SerialUniqueID { get; set; }
#endregion
For this selector I want to display LotSerialNbr in the textbox instead of the unique id. Because the selector displays it's key by default I need to use the TextField property:
<px:PXSelector ID="edSerialUniqueID"
runat="server"
DataField="SerialUniqueID"
TextField="LotSerialNbr"
AutoGenerateColumns="True">
The selector value will contain the selected unique id field. To get the record you can issue another request to the database using that key.

Filtering of RefNbr PXSelector on Expense Claim

I need to customize the Expense Claim screen (EP301000) to do the following:
Add user field as a checkbox to header section (Done)
Use that checkbox value to filter the RefNbr PXSelector lookup to only show results for the Employee ID shown on the 'Claimed By' field.
Looking at the DAC for RefNbr, I don't see any normal PXSelector lookup that I'm used to seeing.
Is there a way to do this?
You can see the DACField is using an attribute [EPExpenceClaimSelector]
The definition of that is as below
public class EPExpenceClaimSelectorAttribute : PXSelectorAttribute
{
public EPExpenceClaimSelectorAttribute()
: base(typeof(Search2<EPExpenseClaim.refNbr,
InnerJoin<EPEmployee, On<EPEmployee.bAccountID, Equal<EPExpenseClaim.employeeID>>>,
Where<EPExpenseClaim.createdByID, Equal<Current<AccessInfo.userID>>,
Or<EPEmployee.userID, Equal<Current<AccessInfo.userID>>,
Or<EPEmployee.userID, OwnedUser<Current<AccessInfo.userID>>,
Or<EPExpenseClaim.noteID, Approver<Current<AccessInfo.userID>>,
Or<EPExpenseClaim.employeeID, WingmanUser<Current<AccessInfo.userID>>>>>>>, OrderBy<Desc<EPExpenseClaim.refNbr>>>)
, typeof(EPExpenseClaim.docDate)
, typeof(EPExpenseClaim.refNbr)
, typeof(EPExpenseClaim.status)
, typeof(EPExpenseClaim.docDesc)
, typeof(EPExpenseClaim.curyDocBal)
, typeof(EPExpenseClaim.curyID)
, typeof(EPEmployee.acctName)
, typeof(EPExpenseClaim.departmentID)
)
{
}
}
You can use the same approach to create an attribute of your own with additional condition and use it in your cache attached method to replace the default selector.

Custom selector challenges

I have a custom screen with a multiple custom selectors, which change what they select based on dropdown lists.
The solution I implemented is shown in a previous case:
Dynamically changing PXSelector in Acumatica (thanks).
My challenge is twofold:
1.) If the dropdown selection is "No Lookup", then I want the PXSelector Attribute to essentially be removed - leaving just a text entry. Not sure if this is even possible...
2.) If one of the selectors (let's say Projects) is selected, I'd like the selection of the following selector (let's say Tasks) to filter based on the Project selected.
Thanks much...
1) I think the only way to do this is to create your own attribute.
Something like that:
public class PXSelectorTextEditAttribute : PXSelectorAttribute
{
bool selectorMode;
public PXSelectorTextEditAttribute(Type type, bool selectorOn):base(type)
{
selectorMode = selectorOn;
}
public override void FieldVerifying(PXCache sender, PXFieldVerifyingEventArgs e)
{
if(selectorMode)
base.FieldVerifying(sender, e);
}
public static void SwitchSelectorMode(PXSelectorTextEditAttribute attribute, bool onOff)
{
attribute.selectorMode = onOff;
}
}
You will be able to turn on and off the 'selector' part of the attribute. With the field verifying turned off you will be able to put any value to the field just like in simple TextEdit field. However, the lookup button in the right end of the field still will be visible. I have no idea how to hide it.
2) This behavior can be implemented easily. You will need something like that(example based on cashaccount):
[PXSelector(typeof(Search<CABankTran.tranID, Where<CABankTran.cashAccountID, Equal<Current<Filter.cashAccountID>>>>))]
If you want to see all records when the cashaccount is not defined then you just modify the where clause by adding Or<Current<Filter.cashAccountID>, isNull>
Also don't forget to add AutoRefresh="true" to the PXSelector in the aspx. Without it your selector will keep the list of the records untill you press refresh inside of it.

Resources