Odoo - Why odoo store data of TransientModel like res.config.settings into ir.config_parameter? - odoo-12

res.config.settings model is TransientModel and TransientModel are designed to be stored temporary data, After periodically time it will remove data from the database. For saving those settings we have to implement set_param and get_param method of ir.config_parameter.
So, Here I want to know why odoo used ir.config_parameter to store those setting values. Why we can't make res.config.settings as Model instead of TransientModel and store data into that model.

I'm not odoo so I cannot answer for them, but I can explain you why I consider this logic.
In odoo, you have the traditional MVC paradigm, but there are places where you don't really have a model: you just want a view and a controller. This is the case for wizards in odoo. Wizards are just helper dialogs to let the user perform hard tasks in an easier way.
However, if they have no model, how to define the data they use? Where to attach controller logic? It would be very hard and would request a whole new programming paradigm inside odoo, so they took an easier solution: transient models.
So in odoo a transient model is basically a wizard. What happens when you open a wizard?
Odoo obtains the view definition.
Calls the controller to obtain default data (default_get()).
Draws a form for you, but there's no record yet in the database.
You can alter the form as usual, and the normal compute and onchange methods work out of the box.
You hit some button in the wizard, to perform any action.
Odoo creates a new record in the wizard table.
The method associated with that button is executed in the server.
The next time you open the wizard, it follows the same procedure. As you can imagine, this creates a lot of records, because a wizard record is always used only once, so there's a cron job that deletes that garbage every now and then. That's why they're called "transient".
The purpose of ir.config_parameter is to store and retrieve database-wide configuration. 1 record = 1 parameter. You can create parameters without using a wizard. These are not transient, so it's the proper place to store parameters.
The purpose of res.config.settings is to help you configure the system, but that's more than just storing system parameters: it involves configuring auth methods, installing modules, giving you shortcuts for mail gateways configuration, installing a theme in each website, choosing a chart of accounts for each company, etc.
It would make no sense to merge all of that in ir.config_parameter.

Related

SAPUI5 multiple users working on one table entry

I'm currently developing an application in the SAP BTP for multiple users. In the application you have one table where all responsibilities of a specific task are written down. These responsibilities may overlap between the users, which means that for one responsibility multiple users are mentioned.
In the application the users should click on either accept or reject if they still are responsible for this task. After they have given their feedback, they can click on a save button to write everything via a batch submit to the hana db. If they are not responsible anymore their name should be removed from the tasks and they should not see this task anymore.
The problem I am facing is that currently everything is stored in one database table and if one user gives feedback to some entries while another user works on the same entries, the user who saves his entries last will override the first one.
I have tried searching for a delta insert into the database or to live update after each user input or to lock the data when another user is currently working. But none of these seem to work fine, because users would still be able to override each others entries or they may lock some entries forever.
My question therefore is, what is the usual approach to manage multiple user inputs on a single table or is using a single table a bad practise at first?
My second question would be if sapui5 supports this approach or if I can handle this in another way?
You need to do server-side validation, before the save action.
UI5 does not support this directly, you can handle it by yourself.
Because we are stateless with ui5 / data you could use the draft concept
https://experience.sap.com/fiori-design-web/draft-handling/
Or something like already said backend logic with checks before safe.

CQRS client command management

I'm building a new project using CQRS, It's a 3 tier application and it's expected that clients state are synchronized. The server receive commands and callback events to clients.
Currently, the model has several sub model that can be added/removed/updated, each of which has it's own command. Events are field specific i.e.
UpdateItemCommand
CreateSubItemCommand
RemoveSubItemCommand
UpdateSubItemCommand
...
ItemFieldAUpdatedEvent
SubItemFieldAUpdatedEvent
SubItemFieldBUpdatedEvent
...
So here's my interrogation, the client get the current state of the model, user edit the local model, click the Save button and this is where I bug. Should I
Compare the original state of the model (updated with received events) and the edited state of the model to generate a set of commands (on every received events it's required to identify the fields that has been updated and notify the user if he edited a field that has changed),
Create commands as user are editing the model doing and undoing edit (that would be hard to manage),
...
Basically I don't know which strategy I should apply to generate the commands!
Is there an example out there, I've Google around but found noting on that subject.
Thanks,
Dominik
I recommend you to read about Task-based UI.

how to invoke an operation with the data we get after processing

Hello guys I'm looking for creating an work flow where it will do some processing and will fetch some persons. I need to enforce each person by invoking an extension which takes a person entity as in put.
Any suggestions or pointers will be deeply appreciated.
I going to to assume you want to use an ITIM operation to do this, and you are not going to use an operation tied to an activity (e.g. person/account modify, restore, suspend, add, delete, etc.).
So for example, if you want to create an operation that fetches all users where their department=sales and you want to make a change to those persons (e.g. change all their phone numbers to be 800-555-1212) then you could use a lifecycle rule coupled with an operation.
First create an operation. I would suggest creating the operation at the entity type level of Person unless you need to specifically only allow this operation to work on one person type. Once you get into the operation diagram java applet, click the Properties button and change the operation type to Non Static.
Now, do your coding and flow in the operation. Your person will be coming in as the relevant data object Entity. So make your changes in a script node, then send it through a modify person extension, and finally a policy enforcement extension. I recommend the policy enforcement extension because if you are using provisioning policies then you want any accounts to be updated when you update the extension.
Save your operation, and create a lifecycle at the same level (either at the global Person at the entity level of a specific Person type). Set the operation for the lifecycle to the same operation you just created. On the event page, set your filter to be what you are wanting the operation to apply to (e.g. (department=sales)). You can set a schedule on the lifecycle to automate it, or you can simply save it and run the lifecycle manually by selecting it and clicking the Run button.
Check within IBM's InfoCenter pages for more information on all the workflow extensions that are available out of the box, as well as all of the javascript functions that are available.

Where to put my application logic when using Entity Framework and MVVM

In the last days I spent a lot of time creating the architecture for my program, but still have a problem with it. At the moment it looks like this:
DataLayer: Here my context class which derived from DbContext and the mapper classes which derived from EntityTypeConfiguration like JobMap for the Domain objects reside
DomainLayer: Here my domain/business objects like Job or Schedule reside.
Presentation Layer: Here I have the *ViewModel and *View classes (I use WPF for the views)
Now to my question: I want to build a scheduling application with some optimization abilities (it is a single user and single pc application so no further decoupling like web application is needed). But I have the problem that I don't know where this application fits into this architecture?
Considering the following use case: The user clicks a button "Start" on the View which calls the ViewModel which redirects to my scheduling/optimization application. This app then gets all the new jobs from the database and creates/updates the current schedule. The ViewModel should then update the old schedule with the new created one. Finally the View shows the generated schedule to the user.
In this case my ViewModel knows about my application (because it calls it) and about my domain/business objects (because my app will deliver e.g. a Schedule domain object, which the ViewModel encapsulates).
Is this a correct usage of the EF, MVVM and my application?
Regards
To start, you'll want to identify which pieces of your application go where, and that's fairly easy to do. Essentially, you have to ask yourself: Does this method or class help define my domain. If the answer is yes, you put it in the domain layer, and if not, you'll put it in presentation.
Here's how you'd look at it in your example:
Your Presentation layer (PL) receives a message via the start
button.
The PL calls the Domain and tells it to generate a schedule. This call is probably to a domain service.
Your domain service is then in charge of populating the Job domain objects, creating a new Schedule domain object (or modifying an existing one), and returning the Schedule domain object.
Your PL then simply displays the returned Schedule.
This might be different if you just wanted to obtain an existing Schedule object. Instead of calling a domain service, you would ask a domain repository to get the existing schedule. The repository would be the way of encapsulating or otherwise obscuring the data layer from your PL and from your Domain.
Now, what you DON'T want to do:
Do not get the list of jobs in your PL, and then use that list of jobs to create the schedule in the controller of your MVVM. This would be business logic that defines your domain.
If Schedules are commonly generated from Jobs, regardless of whether it's called from MVVM or a PHP site, then don't add complexity in your PL and Domain Layer by forcing the PL to first get the jobs and pass them back into the Domain for a Schedule to be generated. The fact that those two concepts are tied to each other means that the relationship helps define your domain, and thus belongs in your domain layer. An exception might be when both the jobs and the schedule to be modified both rely on context from the front end (user input), but even this isn't always an exception.
Do not pass in VMs to your domain. Let your controller filter out the data and determine what needs to be sent to which domain part.
It's really hard to give a precise detail of what you should place where because only you would have a clear view of what defines your domain, but here's essentially how I break it down:
Could I change/replace this without affecting how my business/domain works?
If the answer is yes, it does not belong in your domain. Example: You could replace your entire MVVM front-end to flat PHP or ASPX, and even though it'd be a lot of work and a huge pain, you could to do it without affecting how the rest of the business operates.

How to programmatically create a new version of a CQ5 page?

Is it possible to programmatically create a new version of a CQ5 page that has a start time some time in the future?
As an example, let's say we have a page that displays tax rates. We have a component that allows the author to upload a new rates table (in the form of a css file) and it creates the rates page content. We would like to allow the author to upload rates that will be effective the first of next month.
I know the jcr supports multiple versions of nodes, but its unclear how (or whether) this relates to cq5 page versioning. And, further, whether a new version can be activated in the future.
Given the requirements as you've described them, I would probably accomplish the task in a slightly different way...
Instead of storing my rates table information directly within the page's jcr:content node (or a sub node their of) I'd probably abstract it out to somewhere else in the repository. You could then, if you so desired, create some sort of an admin interface to allow content authors to upload their csv file of new rates, and ingest that into the repository as needed. Alternatively, assuming that data comes from some sort of a database, you could probably just write a job to automatically injest it on some sort of a scheduled basis by using a JDBC connection from CQ. Once the data is in the repository, you could then write the display component to read the data from the repository, instead of it being directly inside the page.
This approach has the advantage of making that data re-useable within CQ to be shown on multiple pages, multiple sites, even many different display formats if need be. In addition, you can design your jcr structure to support whatever requirement you have around updates to the data, including daily, monthly, weekly, yearly etc., obviously this will depend on the specific requirements.
The one downside to this is that since there is a separation b/w the data and the page(s) where it is displayed, you may need to find a way to ensure the cache is properly cleared whenever the data does change.
Update (based on your comment):
The problem I foresee with versioning the page, and granted I've not tried this so maybe it will work, is that there can only ever be one active version at a time. Therefore, once the next months data is uploaded, you need to maintain the old data (active) and the new data (not yet active) at the same time. What happens if you require a separate content change during that window...from a business process perspective that just seems messy to me.
Back to cache clear issues, If you know the affected pages, especially if they are all in one subtree, you could write a custom workflow process that uses the replicator service to clear the cache for the affected pages, then set up a launcher to run the wf on node change for the data.
The other option, and this one is less defined in my head, so some experimentation required, would be to use CQs built in activate later and de-activate later functionality.
Maybe create a specific template for the rates data, with the implicit requirement that only one page using that template is ever active at one time. Your display components could use a query to find the currently active rates data.
I have not personally tried this, but...
I assume that you can use the PageManager service's createRevision method, and then if that returns without throwing an exception, you may call page.getContentResource.adaptTo(Node.class), and from there take the node that is returned and edit the JCR properties for your tax rates component.
See PageManager
You could write a workflow that includes a publish step that is triggered by the arrival of a calendar date. The version of the page with the new tax rates remains in the workflow pipeline in draft form and is only published/activated when the date arrives. (So you'd need some sort of process that wakes up once a day to check the calendar.)
Each time a page is modified cq creates a version of the page.
This modified page's modification time is set in jcr:lastModified property of the page.
Manipulation of this property can be done to save future date and activate page on that date though its not preferred way.
You can store the future date as a property in the page.
Later as suggested by #David you can create a workflow or a scheduled job which activates pages with a future date.