How to update records "unrelated" to current graph? - acumatica

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. :)

Related

How to create and update with the same form

I use the repositoryFactory in a custom plugin's Vue file in Shopware 6. When I save an entity I do this:
this.settingsRepository
.save(this.setting, Shopware.Context.api)
.then((result) => {
In case the person sends the form and this function is called, I want to get back the id of the setting in case the person hit's the save button again. But then the entity needs to be updated and not created. As I see from the response, there is an id, but it's in config.data -> json serialised.
How's the default way of solving this issue?
The best practice would be to re-fetch the entity after persisting it. This is because some entities may have fields that get automatically computed or indexed server-side and you'd probably always want to have the entity in its actual current state. If you're absolutely sure you don't want to fetch the entity again, you could manually set the _isNew flag to false after persisting:
this.setting._isNew = false;
This will then cause the save function to use the update instead of the create route. Keep in mind that this is actually kind of an internal property, as there is no setter for it and as already mentioned fetching the entity again is encouraged.
Also you shouldn't have to worry about the id. It should've already been generated client-side and set to the entity, when using the repository to create a new entity like that:
this.setting = this.settingsRepository.create();

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.

How to insert into custom table

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.

microsoft dynamics crm - SQL changes

Hi I'm facing a task that requires me (or not?) to do some small changes directly on the CRM SQL DB.
Situation:
1) there was a N:1 relation between two entities that was changed to N:N.
2) For each entities I need to move related stuff from previous relation to new one.
For active entities it was no problem cause customer didn't care about changing fields "ModifiedOn", "ModifiedBy" and "ClosedOn" but for inactive (an incident that is closed for example) he'd like to migrate the related entities, but not to change these three fields. Because all those incidents are closed/inactive I cannot just call "AssociateRequest" I need to re-open case, associate, close it again. this of course will change these fields.
Is there any way to do this via the API and not directly on SQL? If not - could it be a problem?
If you already have the mechanism to change the Relationship and just need to modify the records CreatedOn, CreatedBy, ModifiedOn, and ModifiedBy...You should be able to do this using late bound code:
Entity YourTargetEntity= new Entity("YourTargetEntity");
YourTargetEntity["createdon"] = new DateTime(2015,01,01); // or whatever the date you want
YourTargetEntity["overriddencreatedon"] = new DateTime(2015,01,01); // or whatever the date you want
YourTargetEntity["createdby"] = new EntityReference("systemuser", new Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"));
TargetEntity["modifiedby"] = new EntityReference("systemuser", new Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"));
TargetEntity["modifiedon"] = new DateTime(2015,01,01); // or whatever the date you want
_service.Update(YourTargetEntity);
Hope that helps.

New ContentItem from code, when is it saved?

I can't get my head around this.
If I have a ContentType called Contacts. The ContentType has two fields attached to it.
FirstName (textfield) and LastName (textfield).
If I want to create a new contentitem of this type then I can write code like this.
dynamic contact = _services.ContentManager.New("Contacts");
contact.Contacts.FirstName.Value = "John";
contact.Contacts.LastName.Value = "Doe";
_services.ContentManager.Create(contact, VersionOptions.Published);
This does not work. The Contentitem gets created but the fields are empty.
However, if I write it like this it works. Why is that? Must I set the fields values after ContentManager.Create is called?
dynamic contact = _services.ContentManager.New("Contacts");
_services.ContentManager.Create(contact, VersionOptions.Published);
contact.Contacts.FirstName.Value = "John";
contact.Contacts.LastName.Value = "Doe";
What you observed is indeed the intended behaviour and is by design. I've come across this before too and also created an issue about it. As you can see there it was closed by Sebastien, the lead developer stating that this is by design but unfortunately not explaining why.
FYI the standard workflow for managing content items is the following:
Instantiate item.
Create it.
Update its values.
If the update happened through the model binder then check if the ModelState is valid. If not, cancel the transaction and return.
If everything's OK and the content type is set to be draftable, publish the item.
You can see an explained example of this in the Orchard Training Demo module (ContentsAdminController.PersonListDashboardPost()).

Resources