How to insert into custom table - acumatica

I have a customization to the Invoice and Memo screen, where I have a completely custom table to which I want to write an error log entry. Since this doesn't really fit with how the training addresses the issue - is there a way to do this directly? I noticed that there's a PXInsert<> command - but there's no documentation that I could find, either in the Framework help, or here on Stack Overflow.
I know I can create a Cache object for my custom table's DAC and use the Insert command of that Cache - but I don't know the exact syntax for doing that (and I couldn't find a good fit for what I'm trying to do in the training manuals). Maybe I missed it.

The syntax to create a Cache object (or I think you might be thinking of a graph) is to use PXGraph object. Here is an example:
private void Function()
{
//TargetGraph is the name of the custom page
TargetGraph graph = PXGraph.CreateInstance<TargetGraph>();
//TargetDAC is the name of the custom DAC in your customizations
TargetDAC dac = new TargetDAC();
//Set all data to dac
dac.Log = log;
//Finally insert and perform the save action for the graph
graph.LogView.Insert(dac);
graph.Actions.PressSave();
}
Perhaps someone could add to this answer on how to grab the errors from the page if that is also what you need.

Related

Revit API reopen form an keep data

I would like to make a Plugin where the user can select a source and then a target element and get all the parameters and their values.
My problem is: After I selected the source element and got all parameters and values into comboboxes I select the target (via another button). For that the form closes again and after selecting and reopening all the data from the source element is gone.
What would be a correct way to do this?
At this time both buttons close the form run another ExternalEvent to select the element and collect the data.
Can I cache this data (Lists, dictionary with list, dictionary with dictionary with list) or do I have to write it to a file or is there another way?
How do I keep/remember the data I collected when a form closes an reopens?
Thank you for any help
Philipp
There multiple ways of doing this I guess. It is more of a general programming rather than API issue. You basically need to keep the data in memory outside of just the WPF window.
Some options of the top of my head would be
Save the data into file in temp folder and read it when needed (probably a messy solution)
Create & instantiate a class with data to keep in memory and communicate it between different windows etc.
Have a Static Class with appropriate property. Once selecting an element assign it to the property. This should persist within the Revit session. Static Class.
Option 3 should be the easiest to use.
Just use Properties -> Application settings to store the ID of the entity. Then on launch get the combo boxes to auto populate if the ID can be found.
External events are only required when editing the model.
This is assuming your using Visual studio and not sharp develop. If your still using sharp develop it is time to move on to a real IDE.
I think there are a few options. You could use the built in DataStorage that a revit model provides. Here, i made a datastorage entity to store a GUID for a project...
public Guid schemaGuid = new Guid("{5F374308-9C59-42AE-ACC3-A77EF45EC146}");
public DataStorage dataStorage;
public string schemaName = "UniqueProjectId";
public DataStorage dataStorage;
public string SimpleField = "MyProjects_GUID";
public Schema CreateNewDataStorage()
{
Guid newProjectGuid = Guid.NewGuid();
Transaction t = new Transaction(doc, "Make internal storage");
t.Start();
dataStorage = DataStorage.Create(doc);
dataStorage.Name = schemaName;
SchemaBuilder schemaBuilder = new SchemaBuilder(schemaGuid);
schemaBuilder.SetSchemaName(schemaName);
schemaBuilder.AddSimpleField(SimpleField, typeof(Guid));
schema = schemaBuilder.Finish();
entity = new Entity(schema);
entity.Set(SimpleField, newProjectGuid);
dataStorage.SetEntity(entity);
t.Commit();
return schema;
}
Another way would be to write to external database or text file. For something small, SQlite is easy. A temporary text file is also a very simple way to temporarily store data.
Lastly, you could use an Idling event and keep the dialogue box active.

Segmented Keys in ACUMATICA

I’ve created new Segmented Keys in ACUMATICA for use in a specific module. I would like to assign the Dimension name dynamically but I noticed it works only with hard code or name like [PXDimension(“VENDOR”)]
Also, I have some limitation to create an IF Conditional inside the customized field… it does not recognize the IF clause (see the image).
I would appreciate any suggestion how to solve this issue.
I haven't seen how your original attempt at PXDimension looked, but I'm going to take a guess and assume you tried to reference a new custom field contained in a setup table, something like:
[PXDimension(typeof(XXMySetup.usrMyCustomField))]
If that's indeed what you tried to do, one very important thing to do is to ensure that you have a view for your table in your graph, otherwise the attribute will not find the table and record in your cache. For instance:
public PXSetup<XXMySetup> XXMySetup;
Without this view declared in the graph, the dimension attribute will not work as expected. It would be nice if a clear exception was thrown in this case - I made the same mistake recently and it would have been helpful.

How to update records "unrelated" to current graph?

I am not sure if i have just forgotten how to go about this or whether i havent had to do it before....
I have a new custom page with new tables and graph associated with it. It works fine for maintaining this custom data. I have an action that needs to update a custom field in INItemLotSerial (note this does not have a graph associated with it). Normally, i have created an instance of the corresponding graph and done updates using that instance.
I just need to do the equivalent of update INItemLotSerial set usr1 = 'test' where InventoryID = x and LotSerialNbr = y
I am unsure how to approach this? i was thinking i could select the record into an instance of the DAC and update the values, but i do not know how to commit that back to the DB.
you need view. Let's say you made view like this:
public PXSelect<PMTask> PMTasksSelect;
you read your object in some way
PMTask pm = PMTasksSelect.Select(Base).FirstOrDefault();
Inform cache of Acumatica that you changed object:
PMTasksSelect.Cache.SetValueExt(pm, "RateTableID", "A");
PMTasksSelect.Cache.SetStatus(task2, PXEntryStatus.Modified);
PMTasksSelect.Cache.IsDirty = true;
Finally you can persist your changes to db:
PMTasksSelect.Cache.Update(taskExt);
You need a view related to the DAC you want to update. So in this case, you can define a view for the DAC like
public PXSelect<INItemLotSerial, Where<INItemLotSerial.inventoryID, Equal<Current<YourField>>,
And<INItemLotSerial.lotSerialNbr, Equal<Current<YourField>>>>> LotSerialInfo;
So this view will cache the record you want to update. Now you can update the record anytime like
INItemLotSerial rec = LotSerialInfo.Current as INItemLotSerial;
//Get extension if you want
recExt.YourExtField = "something";
LotSerialInfo.Update(rec);
The persist of your graph will save the information you Inserted/Updated/Deleted.
Hope It gives you the idea and helps. :)

Cocoa Bindings not updating NSTextField value

I have two windows, one is a table view to display content. One is a window for inputting content.
I have an NSTextField binded to a property in my app delegate. When I change a value in the text field, the app delegate property will change. However, if I go the other way and programmatically change the property's binded key, the value of the text field does not update. However, it does in the table view.
What is going wrong here? How can I update text field?
EDIT:
I tried all 3 of these with the same result
[_addEntry setValue:#"Chet" forKey:#"payee"];
[_addEntry setPayee:#"chet"];
_addEntry.payee = #"chet";
EDIT:
Here's a simple example to elaborate on my point
https://dl.dropboxusercontent.com/u/48014761/test.zip
the label and the textfield are bound to the "str" property. It is initially null. press log to see that in the console. press change str button to change the string. Log to verify. Note that the label and the textfield do not update!
EDIT:
"What am I trying to accomplish?"
Here's the project I am working with:
https://dl.dropboxusercontent.com/u/48014761/Write-Offs.zip
I am trying to use Cocoa Bindings as much as possible. I have a table with a bunch of data. However, each entry is going to have an array of images associated with it. Thus, when I add a new entry, I need to open up a new window so I can set the properties of that entry (rather than through the table) along with upload some images.
I am not sure I am implementing the addEntryWindow correctly. It seems like I should create and destroy the window each time I open and close it. This doesn't appear to be happening.
Also, [[self addEntry] setDate:[NSDate date]]; doesn't seem to fix the problem for me.
Thanks
Chet
How are you programmatically changing the field? Are you using KVO? Is the field inside of a NSManagedObject instance?
Bindings work through KVO. Core Data disables some aspects of KVO for its own internal uses and you might be tripping over one of those.
Update your question with the code sample and lets see what is going on.
Update
Both windows don't necessarily need to be in the same xib but they do need to be talking to the same instances. Ideally they should both be talking to the same instance of NSManagedObject and therefore talking to the same NSManagedObjectContext.
Who is the owner of each window?
Is the owner the same?
If not, is a new Core Data stack being created?
Update
In your test, I was able to correct it by how you were editing the property
- (IBAction)press:(id)sender {
[self setStr:#"this"];
}
You were accessing the iVar directly instead of the property. When you access the iVar directly KVO does not fire.
In addition, in your xib files you were accessing self.str which is unnecessary. It should be just str.
Are you doing any direct property access in your actual project?
Update
You can do a get accessor and then a set accessor:
[[self addEntry] setPayee:xxx];
Based on the variables you are using I wonder what you are trying to accomplish. Can you post the exact code of the programmatic change you are trying to enact?

Help to restructure my Doc/View more correctly

Edited by OP.
My program is in need of a lot of cleanup and restructuring.
In another post I asked about leaving the MFC DocView framework and going to the WinProc & Message Loop way (what is that called for short?). Well at present I am thinking that I should clean up what I have in Doc View and perhaps later convert to non-MFC it that even makes sense. My Document class currently has almost nothing useful in it.
I think a place to start is the InitInstance() function (posted below).
In this part:
POSITION pos=pDocTemplate->GetFirstDocPosition();
CLCWDoc *pDoc=(CLCWDoc *)pDocTemplate->GetNextDoc(pos);
ASSERT_VALID(pDoc);
POSITION vpos=pDoc->GetFirstViewPosition();
CChildView *pCV=(CChildView *)pDoc->GetNextView(vpos);
This seem strange to me. I only have one doc and one view. I feel like I am going about it backwards with GetNextDoc() and GetNextView(). To try to use a silly analogy; it's like I have a book in my hand but I have to look up in it's index to find out what page the Title of the book is on. I'm tired of feeling embarrassed about my code. I either need correction or reassurance, or both. :)
Also, all the miscellaneous items are in no particular order. I would like to rearrange them into an order that may be more standard, structured or straightforward.
ALL suggestions welcome!
BOOL CLCWApp::InitInstance()
{
InitCommonControls();
if(!AfxOleInit())
return FALSE;
// Initialize the Toolbar dll. (Toolbar code by Nikolay Denisov.)
InitGuiLibDLL(); // NOTE: insert GuiLib.dll into the resource chain
SetRegistryKey(_T("Real Name Removed"));
// Register document templates
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CLCWDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CChildView));
AddDocTemplate(pDocTemplate);
// Parse command line for standard shell commands, DDE, file open
CCmdLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line
// The window frame appears on the screen in here.
if (!ProcessShellCommand(cmdInfo))
{
AfxMessageBox("Failure processing Command Line");
return FALSE;
}
POSITION pos=pDocTemplate->GetFirstDocPosition();
CLCWDoc *pDoc=(CLCWDoc *)pDocTemplate->GetNextDoc(pos);
ASSERT_VALID(pDoc);
POSITION vpos=pDoc->GetFirstViewPosition();
CChildView *pCV=(CChildView *)pDoc->GetNextView(vpos);
if(!cmdInfo.m_Fn1.IsEmpty() && !cmdInfo.m_Fn2.IsEmpty())
{
pCV->OpenF1(cmdInfo.m_Fn1);
pCV->OpenF2(cmdInfo.m_Fn2);
pCV->DoCompare(); // Sends a paint message when complete
}
// enable file manager drag/drop and DDE Execute open
m_pMainWnd->DragAcceptFiles(TRUE);
m_pMainWnd->ShowWindow(SW_SHOWNORMAL);
m_pMainWnd->UpdateWindow(); // paints the window background
pCV->bDoSize=true; //Prevent a dozen useless size calculations
return TRUE;
}
Thanks
Hard to give you good recommendations without knowing what your program shall do. I have only a few general remarks:
Your InitInstance does not look very messed up for me. It's pretty much standard with a bit of custom code in it.
Also the ugly construction to retrieve the first view from the application class (the chain GetDocTemplate -> GetDoc -> GetView) is standard to my knowledge. I actually don't know another way. You might think about moving it into a separate method like CChildView* CLCWApp::GetFirstView() but well, that's only cosmetic as long as you need it only at one place.
What you are doing and which data you are placing in your Document class and in your View class(es) is more a semantic question if you only have one view. (You have only one document anyway because it's an SDI application.). From a technical viewpoint often both is possible.
But to be open for (perhaps) later extensions to more than one view and to follow the standard pattern of a doc/view architecture there are a few rules of thumb:
Data which exist and have a meaning independent of the way to present and view them (a document file, a database handle, etc.) belong to the document class. I don't know what your pCV->OpenF1(cmdInfo.m_Fn1) ... and so on does but if it's something like a file or filename or a parameter to be used to access data in any way OpenF1 might be better a method of the document class.
Methods which do any kind of data processing or modification of your underlying data belong to the document class as well
Data and methods which are only needed for a specific way to display a document belong to a view class (for instance a selected font, colours, etc.)
On the other side: If you have a fixed number of views which open with the document it might not be wrong to put view specific data into the document, especially if you want to make those view parameters persistent. An example would be a file with some statistical data - your document - and a splitter frame with two views: one displays the data as a grid table and the other as a pie chart. The table has "view data" describing the order of and width of columns, the pie chart has data to configure the colours of the pie pieces and the legend location, for instance. If you want to make sure that the user gets the last view configuration displayed when he opens the document file you have to store these view parameters somewhere. It wouldn't be wrong or bad design in my opinion to store those parameters in the document too, to store and retrieve them from any permanent storage, even if you need them only in the view classes.
If your application allows to open an unlimited number of views for a document dynamically and those views are only temporary as long as the application runs, storing all view configuration parameters directly in the view classes seems more natural to me. Otherwise in the document you would need to manage any kind of dynamic data structure and establish a relationship between a View and an entry in this data structure (an index in an array, or a key in a map, etc.)
If you are in doubt whether to place any data in the document or view class I'd prefer the document because you always have the easy GetDocument() accessor in the View class to retrieve members or call methods of the Doc. To fetch data from the View into the Document requires to iterate through the list of views. (Remember: Doc-View is a 1-n relationship, even in a SDI application.)
Just a few cents.

Resources