Problem with custom processing button to generate NoteIDs - acumatica

Creating a new dummy maintenance screen to enable universal search on item cross references and gotten as far as creating the new DAC and BLC, even adding the Processing buttons to the screen, but when clicking the either processing button nothing happens (currently have it throwing a PXException). Ultimately I need to use the "Process All" (labeled "Create NoteIDs") button to fill in the NoteID field so I can actually work on the universal search part.
This is my graph. The INItemXRef is actually a new custom DAC with a NoteID field attached (no other changes, created directly from the database). Ultimately I need to update the code below to fill in random values to empty NoteIDs, so if there is any advice on the next step that would also be appreciated after solving the immediate problem:
public class INItemXRefGraph : PXGraph<INItemXRefGraph>
{
public PXSelect<INItemXRef> INItemXRef;
public PXSave<INItemXRef> Save;
public PXFilter<INItemXRef> MasterView;
[PXFilterable]
public PXProcessing<INItemXRef, Where<INItemXRef.noteID, IsNull>> INDocumentList;
public INItemXRefGraph()
{
INDocumentList.SetProcessDelegate(ReleaseDoc);
INDocumentList.SetProcessAllCaption("Create NoteIDs");
}
public static void ReleaseDoc(System.Collections.Generic.List<INItemXRef> list)
{
throw new PXException("Hello World");
}

Try this
public class INItemXRefGraph : PXGraph<INItemXRefGraph>
{
public PXSelect<INItemXRef> INItemXRef;
public PXSave<INItemXRef> Save;
public PXFilter<INItemXRef> MasterView;
[PXFilterable]
public PXProcessing<INItemXRef, Where<INItemXRef.noteID, IsNull>> INDocumentList;
public INItemXRefGraph()
{
INDocumentList.SetProcessDelegate(
delegate(System.Collections.Generic.List<INItemXRef> list)
{
System.Collections.Generic.List<INItemXRef> newlist = new System.Collections.Generic.List<INItemXRef>(list.Count);
foreach (INItemXRef doc in list)
{
newlist.Add(doc);
}
ReleaseDoc(newlist);
}
);
INDocumentList.SetProcessAllCaption("Create NoteIDs");
}
public static void ReleaseDoc(System.Collections.Generic.List<INItemXRef> list)
{
throw new PXException("Hello World");
}

Related

Create missing data on RowSelected

We have a graph extension that manages the tab we added to a screen. The tab displays data from our own DAC. We do not use a DAC extension, not going to go into the reasons right now.
When a user opens the main screen I want to create a record of our data if it does not exist, with some defaulting business logic.
I added a RowSelected event handler on the main DAC and it fires as I expect it to. When I add the code to create our missing record in the event handler Acuminator gives me error "PX1044 Changes to PXCache cannot be performed in event handlers."
I understand the error that Acuminator is raising, but I'm not sure where else to create our record. I cannot remember a section of the university specifically addressing this scenario.
Can anyone tell me how I would handle this scenario? And if possible, point me at the learning material that covers this scenario for broader information.
Unfortunatly there are only a few OK ways to do this and make Acuminator happy. You will risk data inconsistency.
https://github.com/Acumatica/Acuminator/blob/master/docs/diagnostics/PX1044.md
I would reccomend putting your data insertion code in Row Updated and hope the user updates something
I got a reply from Acumatica support, you can do this in a view select delegate.
Here's some example code, I haven't tested it though:
public class InventoryItemMaintExtension : PXGraphExtension<InventoryItemMaint>
{
public SelectFrom<MyCustomTable>.
Where<MyCustomTable.inventoryID.IsEqual<
InventoryItem.inventoryID.FromCurrent>>.
View AdditionalItemData;
public static bool IsActive() { return true; }
public IEnumerable additionalItemData()
{
var data = AdditionalItemData.SelectSingle();
if (data is null)
{
data = new MyCustomTable();
AdditionalItemData.Insert(data);
}
return AdditionalItemData.Select();
}
}
[PXCacheName("Additional Item Data")]
[Serializable]
public class MyCustomTable : IBqlTable
{
#region CashAccountID
[Inventory]
[PXDefault]
public virtual int? InventoryID { get; set; }
public abstract class inventoryID : PX.Data.BQL.BqlInt.Field<inventoryID> { }
#endregion
#region Required
[PXDBBool()]
[PXDefault(false)]
[PXUIField(DisplayName = "Required")]
public virtual bool? Required { get; set; }
public abstract class required : PX.Data.BQL.BqlBool.Field<required> { }
#endregion
}

Render Action button

I was creating a new Screen with the FormDetail template where I would be having a Filter DAC and list of DAC to display on Grid. I created the page successfully. Then,I wanted to put a button on the top of the button which would pull data from api and refresh grid. So, I wrote the below code to render an action button on page(FormDetail) like this.
But, it is not working.
using System;
using PX.Data;
namespace AcumaticaSquarePOSIntegration
{
public class SquarePOSTransactionInquiry : PXGraph<SquarePOSTransactionInquiry>
{
public PXSave<MasterTable> Save;
public PXCancel<MasterTable> Cancel;
public PXFilter<MasterTable> MasterView;
public PXFilter<DetailsTable> DetailsView;
public PXAction<MasterTable> Calc;
[PXUIField(DisplayName="Calc")]
[PXButton]
protected virtual IEnumerable calc(PXAdapter adapter)
{
return adapter.Get();
}
[Serializable]
public class MasterTable : IBqlTable
{
}
[Serializable]
public class DetailsTable : IBqlTable
{
}
}
}
I even tried add
Is there anything that I am missing here?
You have two PXFilters, change the second to PxSelect and make the PXFilter your first Data view in the list.
try using PXProcessButton instead of PXButton.
Also make sure MasterView is specified in aspx as a PrimaryView.

duplicate view upon data change?

My CardView duplicate elements upon data change, the vardView is within a tab, and the way i declared that tab fragment as following;
in the onCreateView, i declared all the necessary firebase links and value events listeners to retrieve the required data related to the elements displayed on the cards.
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if(snapshot !=null){
for (DataSnapshot child: snapshot.getChildren()) {
Log.i("MyTag", child.getValue().toString());
imagesfeedsList.add(child.child("address").getValue(String.class));
authorfeedsList.add(child.child("author").getValue(String.class));
ratingfeedsList.add(child.child("rating").getValue(String.class));
locationfeedsList.add(child.child("location").getValue(String.class));
publicIDfeedsList.add(child.child("public_id").getValue(String.class));
}
Log.i("MyTag_imagesDirFinal", imagesfeedsList.toString());
mImages = imagesfeedsList.toArray(new String[imagesfeedsList.size()]);
author = authorfeedsList.toArray(new String[authorfeedsList.size()]);
ratingV = ratingfeedsList.toArray(new String[ratingfeedsList.size()]);
locationV = locationfeedsList.toArray(new String[locationfeedsList.size()]);
publicID = publicIDfeedsList.toArray(new String[publicIDfeedsList.size()]);
numbOfAdrs = Long.valueOf(imagesfeedsList.size());
LENGTH = Integer.valueOf(String.valueOf(numbOfAdrs));
}
right after the snippet the adapter setup;
ContentAdapter adapter = new ContentAdapter(recyclerView.getContext());
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return recyclerView;
}
Then comes the view holder with a RecycleView, declaring the cardView elements. One of the elements is a ratingBar, and here where the ratingbar Listener is to submit the user rating on a specific picture.
after that the content adapter;
public static class ContentAdapter extends RecyclerView.Adapter<ViewHolder> {
// Set numbers of List in RecyclerView.
private Context mContext;
public ContentAdapter(Context context) {
this.mContext = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()), parent);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.authorName.setText(author[position]);
holder.ratingValue.setText(ratingV[position]);
holder.locationValue.setText(locationV[position]);
Picasso.with(mContext).load(mImages[position]).into(holder.picture);
#Override
public int getItemCount() {
return LENGTH;
}
}
My problem is whenever the user submits a rating or even when the data related to any of the elements on anycard changes, the view gets duplicated ( i mean by the view, the cards ), a repetition of the cards, with the new data chnages displayed ?
i a not sure what is in my above code structure causing this and how to fix this repetitions, i mean i need the cards to be updated with the new data but not duplicated?
All right, so the problem was that every time the data changes, in the onCreate the imagesFeedList, ratingFeedList, etc does not get rid of the old information stored in it from the initial build, so when the refresh happens triggered by onDataChange, the new information gets added to the previous information, which cause the view to repeat the cards, thus just at the beginning of onDataChange and before storing any information in the several feedLists, it must be cleared;
imagesfeedsList.clear();
authorfeedsList.clear();
ratingfeedsList.clear();
locationfeedsList.clear();
publicIDfeedsList.clear();
and by that i made sure the view does not repeat build up based on old information.

Catel Cancel button in DataWindow

Then I modify "ProductName" and press "Cancel" button property is reset to passed parameter. But if i modify ProgramIds (add, or delete) and press "Cancel" button collection no set to passed. Why?
I have in ViewModel:
[Model]
[Catel.Fody.Expose("ProductName")]
[Catel.Fody.Expose("ProgramIds")]
Public ProgramDataModel DataModel
{
get { return GetValue<ProgramDataModel>(DataModelProperty); }
set { SetValue(DataModelProperty, value); }
}
In Model:
public string ProductName
{
get { return GetValue<string>(ProductNameProperty); }
set { SetValue(ProductNameProperty, value); }
}
public static readonly PropertyData ProductNameProperty = RegisterProperty(nameof(ProductName), typeof(string));
public ObservableCollection<ProgramIDModel> ProgramIds
{
get { return GetValue<ObservableCollection<ProgramIDModel>>(ProgramIdsProperty); }
set { SetValue(ProgramIdsProperty, value); }
}
public static readonly PropertyData ProgramIdsProperty = RegisterProperty(nameof(ProgramIds), typeof(ObservableCollection<ProgramIDModel>));
In MainViewModel:
var viewModel = new ProductWindowViewModel(DataViewModel);
await _uiVisualizerService.ShowDialogAsync(viewModel);
Catel uses IEditableObject in order to restore the state when the user hits cancel. Because you are using a collection of ids, Catel might have some issues resetting the collection.
Please report this issue (with repro) at the official issue tracker.
As a workaround for now, you can override the CancelAsync method and revert the collection there yourself. Or as an alternative you can use a cloned collection in the VM and only replace the items in SaveAsync.
faced exactly the same problem with an ObservableCollection, simply resolved it by adding [Serializable] Attribute to the model class
[Serializable]
public class ProgramDataModel:ValidatableModelBase
{
}

Lwuit touch screen strange behaviour

I am making an application using LWUIT.
There is a form
There is a list embedded on the form.
The list has 5 elements.
Initially, when I first load the app, if I choose the 1st element, 2nd gets chosen; when I choose the second the 3rd gets chose and and so on (Weird!)
I am not able to click any button on the screen either
next what I do is, shift to a different from using arrow keys (of the keyboard... I am running the app on a simulator btw)
Then I come back to the first form and now everything works as expected(no weird behaviour).
What could be the issue?
I am using Sun Java Micro Edition SDK 3.0 (default touch screen for testing)
My code is:
List dummy = new List();
dummy.addItem("wewerwer");
dummy.addItem("wewerdswer");
dummy.addItem("wewqweerwer");
dummy.addItem("dscxwewerwer");
dummy.addItem("jhgwewerwer");
mainListForm.setLayout(new BorderLayout());
mainListForm.addComponent(BorderLayout.CENTER,dummy);
mainListForm.show();
What could possible be going wrong here?
UPDATE 1
I think there is a bug here. I have attached the complete code below along with the screen shot
import javax.microedition.midlet.*;
import com.sun.lwuit.*;
import com.sun.lwuit.events.*;
import com.sun.lwuit.plaf.UIManager;
import com.sun.lwuit.util.Resources;
public class Demo extends MIDlet implements ActionListener {
private Form mForm;
List abc;
public void startApp() {
Display.init(this);
try {
Resources r = Resources.open("/Test.res");
UIManager.getInstance().setThemeProps(r.getTheme(
r.getThemeResourceNames()[0])
);
} catch (Exception e){
System.out.println(e.toString());
}
if (mForm == null) {
Button click = new Button("Press me!");
click.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
System.out.println("I have been pressed");
}
});
abc = new List();
abc.addItem("Str1");
abc.addItem("Str2");
abc.addItem("Str3");
abc.addItem("Str4");
abc.addItem("Str5");
abc.addItem("Str6");
Form f = new Form("Hello, LWUIT!");
abc.addActionListener(this);
f.addComponent(abc);
Command exitCommand = new Command("Exit");
f.addCommand(exitCommand);
f.addCommandListener(this);
f.addComponent(click);
f.show();
}
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void actionPerformed(ActionEvent ae) {
System.out.println(abc.getSelectedIndex());
}
}
So now when I click on 'Str1' of the list Str2 gets selected and so on.
IDE: Netbeans
Emulator: Default Touch screen phone
On the action event set the list to active again after the event by invoking setHandlesInput(true)
OK....so this is how you resolve it.
After the form is displayed remove the list from the form and again add it to the form and then repaint the form.
Earlier Code
1) form.addComponenet(BorderLayout.center,list);
2) form.show();
Word Around for the problem
1)form.addComponenet(BorderLayout.center,list);
2)form.show();
3)form.setScrollable(false);
I know its kind of strange, but this way the list index selection works smooth for touch screen phones.

Resources