Adding Excel upload feature to Employee Timecard Entry doesn't show ProjectTask field - acumatica

I have a customization to the Employee Timecard Entry screen (EP305000) which enables the Excel upload functionality into the Details tab grid. I did this by adding the attribute [PXImport(typeof(EPTimeCard))] to the 'Activities' view re-declaration in a TimeCardMaint BLC extension as follows:
[PXImport(typeof(EPTimeCard))]
[PXViewName(PX.Objects.EP.Messages.TimeCardDetail)]
public PXSelectJoin<EPTimecardDetail,
InnerJoin<CREmployee,
On<CREmployee.userID, Equal<EPTimecardDetail.ownerID>>,
LeftJoin<CRActivityLink,
On<CRActivityLink.noteID, Equal<EPTimecardDetail.refNoteID>>,
LeftJoin<CRCase,
On<CRCase.noteID, Equal<CRActivityLink.refNoteID>>,
LeftJoin<PX.Objects.AR.Customer,
On<PX.Objects.AR.Customer.bAccountID, Equal<CRCase.customerID>>,
LeftJoin<PX.Objects.EP.TimeCardMaint.ContractEx,
On<PX.Objects.EP.TimeCardMaint.ContractEx.contractID, Equal<CRCase.contractID>>,
LeftJoin<PMProject,
On<PMProject.contractID, Equal<EPTimecardDetail.projectID>>>>>>>>,
Where<CREmployee.bAccountID, Equal<Current<EPTimeCard.employeeID>>,
And<EPTimecardDetail.weekID, Equal<Current<EPTimeCard.weekId>>,
And<EPTimecardDetail.trackTime, Equal<True>,
And<EPTimecardDetail.approvalStatus, NotEqual<ActivityStatusListAttribute.canceled>,
And<Where<EPTimecardDetail.timeCardCD, IsNull, Or<EPTimecardDetail.timeCardCD, Equal<Current<EPTimeCard.timeCardCD>>>>>>>>>,
OrderBy<Asc<EPTimecardDetail.date>>> Activities;
I also set the 'AllowImport' property of the grid to 'True'. This seems to work ok, except that the 'ProjectTask' field of the upload does not allow mapping - i.e., if you go through the import process, when you get to the field mapping part, you can't map the Excel field for ProjectTask to the grid's ProjectTask. It just doesn't show up.
Would this be because the source BLC has as delegate method for 'activities' that I didn't reproduce in my extension?
What could be the reason for not allowing mapping to the ProjectTask field?

Since the ProjectTask field is disabled by default, this was solved by adding a parameter to the [ProjectTask] attribute, called "AlwaysEnabled" via the CacheAttached event, as shown below:
public class TimeCardMaint_Extension : PXGraphExtension<TimeCardMaint>
{
[PXDefault(typeof(Search<PMTask.taskID, Where<PMTask.projectID, Equal<Current<TimeCardMaint.EPTimecardDetail.projectID>>, And<PMTask.isDefault, Equal<True>>>>), PersistingCheck = PXPersistingCheck.Nothing)]
[ProjectTask(typeof(TimeCardMaint.EPTimecardDetail.projectID),
BatchModule.TA,
DisplayName = "Project Task",
BqlField = typeof(PMTimeActivity.projectTaskID),
AlwaysEnabled = true)]
protected virtual void EPTimecardDetail_ProjectTaskID_CacheAttached(PXCache cache)
{
}

Related

Why I'm getting Muti-part identifier error in view query(after added the newly created extension field into the query?)

Multi-part identifier error
I newly created one extension field in Contacts screen (UsrLocationCD int field). After creatimg that field I added that field into the view query and I got the above error.
The concept is the "Customer and Location ID" (Customer Location screen) should match in Contacts screen "Business Account and Location ID" (Location ID, newly added). After this condition is satisfied that related Contact ID should display in Customer Location screen under the Contacts Tab.
Full concept
This the query what I wrote:
[PXViewName(Messages.Contacts)]
[PXFilterable]
[PXViewSavedDetailsButton(typeof(Location))]
public PXSelectJoin<Contact,
LeftJoin<Address, On<Address.addressID, Equal<Contact.defAddressID>>>,
Where<Contact.bAccountID, Equal<Current<Location.bAccountID>>,
And<Where<ContactExt.usrLocationCD, Equal<Location.locationID>,
And<Where<Contact.contactType, Equal<ContactTypesAttribute.person>,
Or<Contact.contactType, Equal<ContactTypesAttribute.lead>>>>>>>> Contacts;
here is the newly created extension field:
public class ContactExt : PXCacheExtension<PX.Objects.CR.Contact> /*, IBqlTable*/
{
#region UsrLocationCD
[PXDBInt()]
[PXUIField(DisplayName = "Location ID")]
[PXSelector(
typeof(Search<Location.locationID, Where<Location.bAccountID,
Equal<Current<Contact.bAccountID>>>>),
SubstituteKey = typeof(Location.locationCD), ValidateValue = false)]
public virtual int? UsrLocationCD { get; set; }
public abstract class usrLocationCD : PX.Data.BQL.BqlInt.Field<usrLocationCD> { }
#endregion
}
I'm sharing one point here that newly created extension field is not creating any problem in the Contacts screen, successfully I'm able to saving the record you can see the below imgs.
Before saving the record
After saving the record
In the contacts screen location id field is "Int".
Where is the mistake and how to overcome this issue?
Your PXSelect is missing a Current<> on where you added in your usrLocationCD.
Original line with missing Current<>:
And<Where<ContactExt.usrLocationCD, Equal<Location.locationID>,
After adding the missing Current<> back in:
[PXViewName(Messages.Contacts)]
[PXFilterable]
[PXViewSavedDetailsButton(typeof(Location))]
public PXSelectJoin<Contact,
LeftJoin<Address, On<Address.addressID, Equal<Contact.defAddressID>>>,
Where<Contact.bAccountID, Equal<Current<Location.bAccountID>>,
And<Where<ContactExt.usrLocationCD, Equal<Current<Location.locationID>>,
And<Where<Contact.contactType, Equal<ContactTypesAttribute.person>,
Or<Contact.contactType, Equal<ContactTypesAttribute.lead>>>>>>>> Contacts;
When selecting data, you always must connect the referenced DAC's in some way... either by joining directly to another table selected in the join, by joining the field to a Current value (such as a field in a parent view), or by supplying a parameter that you pass in.
Also, for consistency, I'd recommend changing the name of your new field from usrLocationCD to usrLocationID. ID means "identifier" and CD means "code". LocationID (the identifier) is the integer field used to identify the Location record, in this case. LocationCD is the field of the Location record that contains the Location Code that we normally see in the display. When another Acumatica developer looks at the code above, the first impression is that you are trying to relate a string field to an integer field. Technically, as long as your field type matches on both sides of the equals then it will work, but consistency is important in coding standards.
In the above code, join is missed for location DAC. I hope this may help you.
[PXViewName(PX.Objects.CR.Messages.Contacts)]
[PXFilterable]
[PXViewSavedDetailsButton(typeof(Location))]
public PXSelectJoin<Contact,
LeftJoin<Address, On<Address.addressID, Equal<Contact.defAddressID>>,
LeftJoin<Location, On <Location.bAccountID,Equal<Contact.bAccountID>>>>,
Where<Contact.bAccountID, Equal<Current<Location.bAccountID>>,
And<Where<ContactExt.usrLocationCD, Equal<Location.locationID>,
And<Where<Contact.contactType, Equal<ContactTypesAttribute.person>,
Or<Contact.contactType, Equal<ContactTypesAttribute.lead>>>>>>>> Contacts;

How to default in a key value and retrieve existing record on first load?

I'm creating a new screen with one new table (AMClockItem) where the key field is the employee ID. I want it to default to the logged in user employee ID. If there isn't an AMClockItem record for the employee it will treat it as a new record, but if there is an existing record for the employee I want it to retrieve the existing record. This all works perfectly EXCEPT the very first time the screen is loaded. The logged in user defaults properly but it doesn't retrieve the existing record. If I click Cancel or change another field it will retrieve the record properly.
My Graph
public PXSelect<AMClockItem, Where<AMClockItem.employeeID, Equal<Optional<AMClockItem.employeeID>>>> header;
DAC:
public abstract class employeeID : PX.Data.BQL.BqlInt.Field<employeeID> { }
protected Int32? _EmployeeID;
[PXDBInt(IsKey = true)]
[ProductionEmployeeSelector]
[PXDefault(typeof(Search<EPEmployee.bAccountID,
Where<EPEmployee.userID, Equal<Current<AccessInfo.userID>>>>), PersistingCheck = PXPersistingCheck.Null)]
[PXUIField(DisplayName = "Employee ID")]
public virtual Int32? EmployeeID
{
get
{
return this._EmployeeID;
}
set
{
this._EmployeeID = value;
}
}
#endregion
On first load, it defaults in the correct logged in user, but the rest of the fields are blank, treating it as a new record.
I hit the cancel button and the existing record loads correctly.
I tried looking for a similar Acumatica screen but can't find an example where a key value is defaulted in on load. Is there a way to force the existing record to load the first time you visit the screen?
I'm not sure this is allowed, there's no mechanism that selects record like that to my knowledge as well.
I suspect the formulas do not execute in order too.
Make sure all key fields have proper value. Record can't be selected if one of the key fields resolve to null on load.
If some key fields initialization are dependent on other key fields initialization decorate them with the PXDependsOnFields attribute:
[PXDependsOnFields(typeof(employeeID))]
You can use the PageLoadBehavior property of "DataSource". Select "SearchSavedKeys". This will help.

Getting the value of the base record in a PXSelector

I am trying to add a selector to a field on a DAC Extension (PMChangeOrder), and I need to get a value from the base record to put in a where statement on the PXSelector search.
The selector will give the user the ability to put in a new value, or select from the values that have been previously entered, based on the current Project ID. Do I use Current<>? Do I override cache attached? I cant seem to have the selector filter by the current value of projectID.
public abstract class usrPCONo : PX.Data.BQL.BqlInt.Field<usrPCONo> { }
[PXDBInt()]
[PXUIField(DisplayName = "PCO No.", Visibility = PXUIVisibility.SelectorVisible)]
[PXSelector(typeof(Search4<usrPCONo, Where<PMChangeOrder.projectID, Equal<Current<PMChangeOrder.projectID>>>,
Aggregate<GroupBy<usrPCONo>>>), typeof(usrPCONo), typeof(PMChangeOrder.description), ValidateValue = false )]
public virtual int? UsrPCONo
{
get;
set;
}
Thanks
The code you provided in your question seems to work correctly. Make sure you have AutoRefresh set to true in the aspx file. This will make it so the records in the selector are automatically refreshed when you open the selector popup to reflect the current ProjectID that the user selected. Without this, if the user opened up the selector popup, changed the ProjectID, then reopened the selector popup the records would still reflect the old value unless the user manually pressed the refresh button in the popup. My guess is that this is what you are experiencing.
<px:PXSelector runat="server" ID="edUsrPCONo" DataField="UsrPCONo" AutoRefresh="True" CommitChanges="True" />

If Statement to Check for Current Null Values in a Selector Overwrite?

I am customizing the ARPaymentEntry logic so that it uses a custom field that we have on the "Invoices and Memos" screen and impacts the "Payments and Applications" screen. This required field is an extension of ARRegister and currently has only two states, A and B.
With the way the code is below, if I have a payment saved in the P&A screen with one line with an "A" record, it will only allow me to add "A" records to that payment. So if we get a line in there with an "A" or "B" value, it will only allow those values through the selector. This is the first half of what I would like to do.
If I change the code to manually set the value that it checks against to "A", the selector will only show records with that letter on the "Payments and Applications" screen, but it also only allows "A" records to come from the "Invoices and Memos" screen via the "Enter Payment Button".
What I'd like to do next is create some kind of if statement that can see if the value of Current2 Custom.DAC.ARRegisterExtension.customField is null, and if it is, do no evaluation, but if it is not null, it should evaluate against the current value. This way, the I&M screen still can pass single records over to P&A and users can select a starting document on the P&A screen from any invoice and it will restrict the user to that type after the first invoice is chosen. I've been working on if statements in this BQL query to try to get the correct result, but I have not been able to come up with the correct solution.
Please let me know if there is anything that I can clarify here, I know it was a bit long-winded...
The section that I changed was:
Where<Custom.DAC.ARRegisterExtension.customField, Equal<Current2<Custom.DAC.ARRegisterExtension.customField>>,
Here is the code:
using PX.Data;
using Custom.DAC;
namespace PX.Objects.AR
{
public class ARPaymentEntry_Extension : PXGraphExtension<ARPaymentEntry>
{
#region AdjdRefNbr
protected string _AdjdRefNbr;
[PXDBString(15, IsKey = true, IsUnicode = true, InputMask = ">CCCCCCCCCCCCCCC")]
[PXDefault()]
[PXUIField(DisplayName = "Reference Nbr.", Visibility = PXUIVisibility.Visible)]
[ARInvoiceType.AdjdRefNbr(typeof(Search2<ARInvoice.refNbr,
LeftJoin<ARAdjust, On<ARAdjust.adjdDocType, Equal<ARInvoice.docType>,
And<ARAdjust.adjdRefNbr, Equal<ARInvoice.refNbr>,
And<ARAdjust.released, NotEqual<True>,
And<ARAdjust.voided, NotEqual<True>,
And<Where<ARAdjust.adjgDocType, NotEqual<Current<ARRegister.docType>>,
Or<ARAdjust.adjgRefNbr, NotEqual<Current<ARRegister.refNbr>>>>>>>>>,
LeftJoin<ARAdjust2, On<ARAdjust2.adjgDocType, Equal<ARInvoice.docType>,
And<ARAdjust2.adjgRefNbr, Equal<ARInvoice.refNbr>,
And<ARAdjust2.released, NotEqual<True>,
And<ARAdjust2.voided, NotEqual<True>>>>>,
LeftJoin<Customer, On<ARInvoice.customerID, Equal<Customer.bAccountID>>>>>,
Where<Custom.DAC.ARRegisterExtension.customField, Equal<Current2<Custom.DAC.ARRegisterExtension.customField>>,
And<ARInvoice.docType, Equal<Optional<ARAdjust.adjdDocType>>,
And<ARInvoice.released, Equal<True>,
And<ARInvoice.openDoc, Equal<True>,
And<ARAdjust.adjgRefNbr, IsNull,
And<ARAdjust2.adjdRefNbr, IsNull,
And<ARInvoice.customerID, In2<Search<Override.BAccount.bAccountID,
Where<Override.BAccount.bAccountID, Equal<Optional<ARRegister.customerID>>,
Or<Override.BAccount.consolidatingBAccountID, Equal<Optional<ARRegister.customerID>>>>>>,
And<Where<ARInvoice.pendingPPD, NotEqual<True>,
Or<Current<ARRegister.pendingPPD>, Equal<True>>>>>>>>>>>>), Filterable = true)]
#endregion
protected virtual void ARAdjust_AdjdRefNbr_CacheAttached(PXCache cache)
{
}
}
}

Change Display Name of Description Field

I want to change the display name of PXSelector Description Field for a specific page. I try as below but it is not working:
PXUIFieldAttribute.SetDisplayName(sender, "DistributorID_description", "ABC-XYZ");
try using the initialize() instead of row selected to set the same using the below syntax
PXUIFieldAttribute.SetDisplayName<DACName.fieldName>(CacheRelatedToYourDAC, "newValue");
OR
you can use the CacheAttached Event to change the displayname of your field. Dont forget to copy all your existing attributes here
[DAC_Field_Attribute_1]
...
[DAC_Field_Attribute_N]
protected virtual void DACName_FieldName_CacheAttached(PXCache sender)
{
...
}

Resources