Custom selector challenges - acumatica

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.

Related

In acumatica, how can I make changes in the Cost tab show up in the Revenue tab?

For example, if I change the "Original Budgeted Quantity" field to 9.00 (see first image below), I would like that to also change in the Revenue tab (see second image) without having to change the same thing twice.
Is there a way I can achieve this?
Cost Tab
Revenue Tab
Here are the details of the two fields I have highlighted in the images above:
Cost Tab Field
Revenue Tab Field
Let me know if I need to clarify anything or provide more information :)
Unfortunately I'm not very familiar with the Project Entry screen, and after a quick glance I couldn't find an easy way to tie the records from the Cost Budget tab to the Revenue Budget tab.
If you are planning on tying these two records together you may need some additional customization work to create the link that you are looking for if it doesn't already exist.
As far as the update itself, that is pretty straightforward and can be accomplished with a simple event handler, as demonstrated below.
namespace MyCompany.MyCustomization
{
public class ProjectEntryExtMyCustomization : PXGraphExtension<ProjectEntry>
{
public static bool IsActive() => true;
#region Actions
#endregion
#region Events
protected virtual void _(Events.FieldUpdated<PMCostBudget, PMCostBudget.qty> eventHandler)
{
PMCostBudget row = eventHandler.Row;
if (row is null) return;
// Replace the stub below with your PMRevenueBudget lookup
// using the link that you have defined.
PMRevenueBudget revenueDetail = new PMRevenueBudget();
// Assigns the PMRevenueBudget Qty field to match the PMCostBudget new value.
revenueDetail.Qty = eventHandler.NewValue as decimal?;
// Updates the PMRevenueBudget record in the cache.
Base.RevenueBudget.Update(revenueDetail);
}
#endregion
}
}
Don't forget to replace the line where I create a new PMRevenueBudget with the logic that you need for looking up the linked PMRevenueBudget record that you need. Let me know if you have any questions.

How to add a column to the grid that shows value from another screen in Acumatica?

I'm new to Acumatica, could you please help me? I have too screens IN202500 (stock items) and SO301000(sales orders). I added a field to stock items and now I need to show a value from that field in grid column of sale orders for each stock items. I suppose that I need to use PXDefault attribute for this?
There are a number of ways you can do this. I'll provide 3 possibilities.
If your View used by the grid contains InventoryItem, you may be able simply to select your custom field from InventoryItem and add it directly to the screen. I'll assume this is not an option or you likely would have found it already.
Create a custom field in a DAC extension on SOLine where you add your custom field as unbound (PXString, not PXDBString) and then use PXDBScalar or PXFormula to populate it. I haven't used PXDBScalar or PXFormula to retrieve a value from a DAC Extension, so I'll leave it to you to research. I do know this is super easy if you were pulling a value directly from InventoryItem, so worth doing the research.
Create as an unbound field as in #2, but populate it in the SOLine_RowSelecting event. This is similar to JvD's suggestion, but I'd go with RowSelecting because it is the point where the cache data is being built. RowSelected should be reserved, in general, for controlling the UI experience once the record is already in the cache. Keep in mind that this will require using a new PXConnectionScope, as Acuminator will advise and help you add. (Shown in example.) In a pinch, this is how I would do it if I don't have time to sort out the generally simpler solution provided as option 2.
Code for Option 3:
#region SOLine_RowSelecting
protected virtual void _(Events.RowSelecting<SOLine> e)
{
SOLine row = (SOLine)e.Row;
if (row == null)
{
return;
}
using (new PXConnectionScope())
{
SOLineExt rowExt = row.GetExtension<SOLineExt>();
InventoryItem item = SelectFrom<InventoryItem>
.Where<InventoryItem.inventoryID.IsEqual<#P.AsInt>>
.View.Select(Base, row.InventoryID);
InventoryItemExt itemExt = item.GetExtension<InventoryItemExt>();
rowExt.UsrSSMyDatAField = itemExt.UsrSSMyDataField;
}
}
#endregion

Trying to customize JAMS LaborEntry screen, looking for the line of code that will update the header

Brand new to Acumatica development and stuck on a simple thing. :(
I am customizing the LaborEntry screen of the JAMS MFG.
I have added a field to the header by extending the AMBatch DAC, called UsrTimeClocked.
For now I simply wish to set this field to a number right at the end of the RowInserted event at the detail level of the AMMTran and see my number on the screen, up on the header AMBatch.
public class LaborEntry_Extension : PXGraphExtension<LaborEntry>
{
protected virtual void _(Events.RowInserted<AMMTran> e)
{
AMBatchExt ext = Base.batch.Current.GetExtension<AMBatchExt>();
ext.UsrTimeClocked = 5.32;
//Insert line to update the correct object to see 5.32 in the TextBox, before RowSelected is done.
}
}
As is my value goes in the field and any refresh/save/delete of the row does update the correct object and I see my value where I want it. I wish to know the way to force this update.

TestFx - How to test validation dialogs with no ids

I have an application with grid of records and button insert. After clicking insert, there is a form, where you fill in data and click Ok for adding new record to the grid. After clicking Ok, there is validation which fires dialog with error informations, if any of the text fields do not match validation rules. Is there any posible way to test text on the dialog with textFx, if the dialog has no id?
This is an example for Alert based dialog:
In your test:
alert_dialog_has_header_and_content(
"Removing 'Almaty' location", "Are you sure to remove this record?");
In you helper test class:
public void alert_dialog_has_header_and_content(final String expectedHeader, final String expectedContent) {
final javafx.stage.Stage actualAlertDialog = getTopModalStage();
assertNotNull(actualAlertDialog);
final DialogPane dialogPane = (DialogPane) actualAlertDialog.getScene().getRoot();
assertEquals(expectedHeader, dialogPane.getHeaderText());
assertEquals(expectedContent, dialogPane.getContentText());
}
private javafx.stage.Stage getTopModalStage() {
// Get a list of windows but ordered from top[0] to bottom[n] ones.
// It is needed to get the first found modal window.
final List<Window> allWindows = new ArrayList<>(robot.robotContext().getWindowFinder().listWindows());
Collections.reverse(allWindows);
return (javafx.stage.Stage) allWindows
.stream()
.filter(window -> window instanceof javafx.stage.Stage)
.filter(window -> ((javafx.stage.Stage) window).getModality() == Modality.APPLICATION_MODAL)
.findFirst()
.orElse(null);
}
I know this issue is a little old and probably got fixed, but for documentation purpose in case someone else look for a fix for an issue alike, I see dialog.getDialogPane() in Dialog documentation, which would help lookup for specific controls inside the pane. So further on #plaidshirt query, we could retrieve buttons and input fields with:
dialog.getDialogPane().lookupAll()
Then narrow that down to buttons and input fields for example.

Resharper create property with backing field

How do you create property with a backing field in Resharper?
This is the first thing you would want to do with a class and I cannot find how to it.
Its so simple.
Within the body of the class, type prop and hit Tab. Supply the property's type and name. This will create an autoproperty (these days, it is typically one of these you would want to create).
Then, with the cursor on the property name, hit Alt+Enter and choose To property with backing field.
The quickest way I've found is to type your property as if it exists already:
this.MyProperty = "hello";
Then Alt-Return on the property name, and choose Create Property 'MyProperty' then hit tab to choose between auto-property, managed backing field, or default member body.
I believe this is quicker than using the prop shortcut, hitting tab, specifying the property type, hitting tab twice, specifying the name, and then pressing Alt-Return on the property name and choosing the 'to property with backing field' selection.
You could also create a Live Template so that there is slightly less work, e.g:
/// <summary>
/// Private backing field for $Property$ property
/// </summary>
private $Type$ $BackingField$;
public $Type$ $Property$
{
get
{
return this.$BackingField$;
}
set
{
this.$BackingField$ = value;
}
}
The parameter $BackingField$ can be generated automatically from $Property$ by the "first character in lower case" macro of the template editor and setting it to "Not editable".
But I believe the first method is the quickest and easiest.
If you already have a property with a getter and setter, sometimes you will find that the backing field you used is no longer available because you changed the base class for the current class or you made other changes. For example, in the LinesMax property below, the backing field Height is available from an inherited class:
public int LinesMax
{
get { return ConvertValGet(AdjustMetricEnum.Height, Height); }
set { Height = ConvertValSet(AdjustMetricEnum.Height, value); }
}
If the above code works but I decide afterwards no longer to inherit the class that exposes the Height property, the two Height variable names will turn red in the IDE to indicate that they're no longer available to the code.
At that point, I may want to create a private backing field. To easily create that, I can first modify the Height name to _height, then place the cursor on either _height name, hit Alt-Enter then choose Create field '_height'. A backing field will be created.

Resources