What really happens when I press duplicate? - odoo

I am going crazy with OpenERP duplicate, if I duplicate a User in Employee Directory it duplicates everything (every user of the system), If I duplicate a group it duplicates only some stuff, apparently it doesn't create a copy... If I copy a Menu it doesn't duplicate the submenu options.
WTF does duplicate do "under the hood"? Is duplicate the same as copy? Does it create a new reference that points to the same object? Is it a shallow or a deep copy?
I am on OpenERP 7 LTS.

The duplicate Menu calls the OpenERP copy method, which by default is implemented as a shallow copy, with the exception of one2many relationships.
Shallow copy means that a new copy of the record is created, with all field values copied as reference as much as possible. For example if you duplicate an Employee, the Department of the duplicated employee will simply be set to the same department as the one being copied, the system will not create a copy of the Department.
For one2many relationships (which is typically the relationship that connects a parent record with its child records, like the relationship between an Invoice and its lines), the child records are also duplicated, because the original ones cannot be ripped off their original parent.
This default behavior may cause unforeseen side-effects when a one2many relationship connects a record to mere "related records" that are not really its children: for example a one2many relation could link an Employee to her timesheet entries, but those entries should definitely not be duplicated when the employee is duplicated.
For this reason the various object models of OpenERP can implement extra logic during the copy operation, and explicitly turn off the duplication for one2many relationships that do not contain real "children", as well as alter any copied values (like appending "(copy)" in the record name).
If you're seeing incorrect behavior when duplicating records using only standard OpenERP modules, it may be a bug that should be reported on the official bugtracker. And if you are using extra modules, make sure they're not adding one2many fields on some models without overriding the copy method accordingly.
PS: If you're duplicating a record in the "Employee Directory" you're actually duplicating an employee (HR Resource), not a user (User Account with login access). Those are separate concepts in OpenERP, as some employees may not need to login (no user account), and some users may not be employees (contractors or system accounts for example).
Update: a bug exists currently in OpenERP 7.0 that causes invalid duplication of related employees when duplicating a user, and similar duplication of subordinates when duplicating an employee. This bug is an illustration of what happens when modules fail to correctly handle the duplication of the one2many relationship they define.

As Duplicate name suggest it simply duplicate the records, in the background it calls ORM's copy method,
If it's duplicating only some stuff that means for the particular model the copy method is overrided, which is preventing the duplication of all fields.
If you don't want the existing functionality you can override it and change it as per your requirement by creating child module.

Related

Is there a way to create an virtual table that would be compared to one after editing?

I have a table [contractor c] in which only one field [tin] may be edited. If the user tries to change data in other field it shall not be updated. Was wondering if making a view of the c before editing and then comparing the view with edited table is a good idea. But that would require two scripts- before and after update.
I could also make a validation on every single field except tin, but there is 'a lot' of fields.
Looking for the best and most optimal way to approach this task.
This is too long for a comment. There are many ways to do what you describe. "Views" are not one of them. In SQL, a view is a stored query. It does not store values. That is definitely not going to help, because the view changes with the underlying tables.
If only one column can be updated, then one method is to implement a trigger that checks the before- and after- versions of the record and only allows updates when no other fields change.
You can start learning about triggers in the documentation.
An alternative mechanism is to make the table unupdatable except for update permissions on a single column. You can learn about permissions in the documentation.
If for some reason you wanted to do all the work in the application, then transactions might come into use. You would not commit the transaction until the update meets your requirement. Transactions are explained in the documentation.

Database Design for basic CMS

I am creating a basic CMS for a small academic project I want to use to practice design patterns in code later and I am starting with designing the database.
The simple requirement is that a "Container" of some kind will contain "Pages" or "Controls". Also a "Page" will contain "Controls". Think of a container like the holder for several tabbed pages. So when something is saved, everything can be saved at once by simply calling save on the container.
Anyway, I have 3 tables. "Container", "Page" and "Control".
Think of a "Container" like a holder for all the things that will appear on screen. It can be split into other smaller containers if needed (for wide screen).
Think of a "Page" like a form of some kind. Something that will allow the user to place controls used to collect data.
Think of a "Control" like a label, text box, button, etc. There are various types of controls (not shown in the diagram), but the "Controls" table will hold multiple instances of any given control type. For example, a form that has 5 labels and 5 text boxes, will have 10 corresponding entries in the controls table - 5 entries for each type of control. So a control is a singular instance of a control type, will have a unique ID, and can only be used once.
If a container is deleted, I want this to cascade and delete the relevant pages and controls.
Likewise, if a page is deleted, I want this to cascade and delete the controls that were on that page.
I have 2 problems to solve.
Problem 1: A control can belong to either a container or a page, but not both. Essentially a control can have only one owner or parent. Likewise with a page. However with a control, because it can be put on either a container, or a page, I have to connect it with 2 relationships, and create a constraint on the PageId and ControlId columns that ensures only one of them is not null. This I have done successfully, but I am wondering if there is a better way?
Problem 2: Because I am using cascade update and delete with 3 tables. I am getting an error:
Introducing FOREIGN KEY constraint 'FK_Pages_Containers' on table
'Pages' may cause cycles or multiple cascade paths. Specify ON DELETE
NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY
constraints.
I want the controls belonging to a page or container, AND the pages belonging to a container deleted if either the page or container is deleted. So, in my mind, I need the cascading update and delete. So this error is forcing me to change my relationship requirements in a way that will leave orphans.
As a side note, a container could also contain other containers. This might be useful on large wide screens to display a form (page) in two parts, one on the left and one on the right for example, and still be able to save everything by clicking a save button on the parent.
So how can I overcome this? Am I overlooking something in my design?
For clarity here is an ER diagram:
You can see from the stars (*) that it is not saved yet because of the above error. My first goal is to get the database right. I don't like entity framework code first, and I want to use either entity framework database first or an alternative ORM that does it's thing as needed. But I want data integrity handled by the database where it should be.
Any suggestions would be welcome.
Based on the comments under the question. I tried a few solutions. Here is one that I came up with that seems to work best so far. I am just posting this for my own reference later, and maybe it will help others. So I still welcome any other suggestions for improvement.
To start I removed all the relationships and created a container type table. This I linked to a container manager table. Then I lined the container and pages table with a 1:1 relationship to the container management table. The logic behind this was that I currently have 2 types of containers, but later I could add more if I wanted.
In the container types I added data for "Container" and "Page" then referenced this back to the container manager table. I added an additional field in the container manager table to show who the parent of the container or page was. This is a self referencing relationship. It simplified the container and pages table somewhat.
Next I repeated the process with the controls table. It was slightly more complicated but the same idea. It just split containers from controls very nicely and then let the management tables link up to "manage" things.
From there it was simply a matter of adding a container parent to the control manager table and relating it back to the container manager table. All the relationships are cascading and work without problems. As you can see, the management tables, combined with the 1:1 relationships to controls, containers, and pages tables, provide instance specific information allowing for easy management. I really like that I don't have to build any constraints like I had in my original solution to ensure only one of 2 fields were filled in as constraints are not obvious. However, I have noticed that I could technically just combine the data from the linked 1:1 tables directly into the management tables and simplify the diagram even more. Which I may yet do as it is easier and faster to look at 2 tables, than 5. I would be interested to hear peoples opinion of this.
The general use case would be that we know the types of containers or controls in advance. So we can select the type of controls we want to put on a page or container. This information adds data to the management tables and generates a unique Id for the instance of the container, page, or control being used. Then we use that Id to create the actual container, page, or control instance the user will see. Obviously saving the data behind the controls is another matter that is not part of the question so I wont go into my solution for that here.
Thanks to D Mayuri who inspired this approach with is help and comments about separating out the relationships. I am not sure if this is how he intended me to do it. If he posts his own answer, I will of course accept and give him credit.

Breeze and Point In Time Entities

We are creating a system that allows users to create and modify bills for their clients. The modifications need to be maintained as part of the bill for auditing purposes. It is to some extent a point in time architecture but we aren't tracking by time just by revision. This is a ASP.NET MVC 5, WebAPI2, EntityFramework 6, SQL Server app using Breeze on the client and the server.
I'm trying to figure how to get back the Breeze and our data model to work correctly. When we modify an entity we essentially keep the old row, make a copy of it with the modifications and update some entity state fields w/ date/time/revision number and so on. We can always get the most recent version of the entity based off of an entity ID and an EditState field where "1" is the most current.
I made a small sample app to work on getting Breeze working as part of the solution and to enable some nice SPA architecture and inline editing on the client and it all works... except that since our entity framework code automatically creates a new entity that contains the modifications, the SaveChanges response contains the original entity but not the new "updated" entity. Reloading the data on the client works but it would of course be dumb to do that outside of just hacking around for demo purposes.
So I made a new ContextProvider and inherited from EFContextProvider, overrode the AfterSaveEntities method and then things got a bit more complicated. Not all the entities have this "point in time" / revision functionality but most of them do. If they do I can as I said above get the latest version of that entity using its EntityId and EditState but I'm not seeing a straight forward way to get the new entity (pretty new to EF and very new to Breeze) so I'm hoping to find some pointers here.
Would this solution lie in Breeze or our DataContext? I could just do some reflection, get the type, query the updated entity and shove that into the saveMap. It seems like that might break down at some point (not sure how or when but seems sketchy). Is our architecture bad? Should we have gone the route of creating audit/log tables to store the modified values instead of keeping the datamodel somewhat smaller by keeping all of the revisions of the entities in their original tables but with the revision information and making the queries slightly more complicated? Am I just missing something in EF?
... and to head of the obvious response, I know we should have used a document database but that wasn't an option on this project. We are stuck in relational land.
I haven't tried this but another approach would be to simply change the EntityState of the incoming entity in the BeforeSaveEntities method from Modified to Added. You will probably need to also update some version field in this 'new' entity so that it doesn't have a primary key conflict with the original.
But... having built apps like this in the past, I really recommend another approach. Store your 'historical' entities of each type in a separate table. It can be exactly the same shape as the 'current' table. When you save you first copy the 'current' entity into the 'historical' table ( again with some version numbering or date schema for the primary key) and then just update your 'current' entity normally.
This might not give you the answer you expected, but here is an idea:
When saving an object, intercept save on server, you get an instance of object you need to modify, read object from database that has the same ID, put copy of that old object to legacy table in your database and continue with saving into main table. That way only latest revision stays in main table while legacy table would contain all previous versions.
So, all you would need to do is have two tables containing same objects:
public DbSet<MyClass> OriginalMyClasses{get;set;}
public DbSet<MyClass> LegacyMyClasses{get;set;}
override SaveChanges function and intercept when entry E state is Modified, read E type, get the original and legacy tables, read object O from Original with same ID as E, save O to Legacy table, and finally return base.SaveChanges(); (let it save as it is supposed to by default).

Access 2010 Inside Out

I recently acquired this book from Microsoft Press. I currently have Office Enterprise 2007 (Access included) and have firmly decided to convert my Informix-SQL app to Access 2010. However, I'm not experienced with VBA, Macros and several other functionality my app needs. This is going to be a new learning process for me, but I must modernize my 20 year old char-based app and take advantage of new features. I have begun defining my tables and columns, but not the relationships. With INFORMIX, I join a serial (autoincrement) column with an INT column in another table. Now when I display a customers master row, I would like to automatically display all of the transactions associated with that customer in a sub-form and have the ability to add, update, query, delete on either tables. Can this be accomplished with A'10?
EDIT: OK, this is what I have done so far, defined tables and relationships:
there are more validation lookup tables to follow, but these are the main tables. So if now I create a form and specify the CLIENTES (customer table), LOTES (lot table), ARTICULOS (item table) and TRANSACCIONES (transaction table) it will create a CLIENT table as the master form and the other child tables as subforms on one screen?
Also, the reason I created a lot table is because when customers pawn or sell items, the pawnshop groups all these items into one lot, calculates the total loan or purchase amount, stores it all under one transaction and prints the ticket with a description of all the items and total amount. So I want the ability to say, if customer defaults on interest payments or does not redeem pawn, then customer forfeits all items and pawnshop may choose to sell some items to gold refinery and/or transfer other non-gold items to inventory to sell to the public, so would the above ER be adequate for this capability?
I also want to ensure that every row in every table has the same store_ID (company ID) while users are working within a specific company, as this system will be multi-company and there will be consolidated reports, etc.
This type of setup can be accomplished in any version of access going back to 1992.
The way you model these classic one to many relationships in access is to base the parent form on the parent table (note I said partent table, not a query – I going to repeat this again: you do not need a query that joins the data for you). You then create what is called a continues form based on the child table. You now have two forms, and you then can simple drag + drop in the form for the child table into the above parent form, and you are done.
In fact, if you design and setup the relationship correctly in the relationships window, then if you use a wizard to create the form, it will actually build and automatically insert a sub form for you.
So, there is some several interesting issues about the above process that you should know As I pointed above, you don't have to build any SQL query at all. You don't have to write sql to join together the data. Access will do all of this for you, and do it without any code.
So, when you navigate records in the main form, the child records will be automatically displayed and filtered for you in the sub form. (and if you add or delete or edit those child records, the correct relationship key is inserted and maintained for you, again done without writing any code at all).
In the following form, we have a classic accounting funds distribution example. In this example we are tracking membership donations. So, the top part of the form is one record based on the master table and is the donation event. I then created an continuous form. When dropped into the main form, it becomes a sub form. That form is the one on the left side, and it simply allows me to enter a list of members who donated for the above event.
The form looks like:
At this point the form will work without any code having been written.
In fact the above form I have the one main record, on the left side I have many members who made a donation. However, I also needed to split out each donation for those memebers on the left side to an to particular account for accounting purposes. (a classic check spliting that you see in just about every accounting package these days)
So the above models a one to many and then the many members also split out into many different accounts for each donation. A really incredible powerful setup, and one that has almost no code.
So, in the above I'm really doing three tables deep as a model. |And, to be fair, the right side (donations split into accounts) did need one line of code to update correctly, as access does not do this for me when you go 3 tables deep.
However for the most part, to model these classic parent to child table relationships in access, you don't need to write any code at all. You use a main form and then for the child table, you insert a sub-form based on the child table.
And as noted if you set the relationships up correctly, access will automatically stitch the two together for you, and maintain the relationship for you. So display of the child records belonging to the one parent record will display for you automatically. And this ability includes you to edit and delete and add those child records. And, thus as you navigate to a new reocrd, all of the child records and information will automatically be refreshed for the next form.
In other words all the above can be done without building any SQL queries, and not one line of code is required.
Unfortunately Stack Overflow works great for asking a question and having an answer. However, a serious of Q + A that builds on previous question we much find that StackOverflow REALLY breaks down here. I will give this a shot, and with all due respect to the great stack overflow, I am temped to suggest you try a forum based system as opposed to so. Perahps Utter access, or even the access dev forum here:
http://social.msdn.microsoft.com/Forums/en-US/accessdev
Anyway, lets see what we can come up with. I should also point out that your table design and how to relate those tables is not really a access question but simply that of database design. How this should be laid out will be the same for MySql, Oracle, FoxPro or in fact just about ANY relational database system that we had in the last 20+ years in our industry. So, this is not really a access question when you ask about how a database is to be setup.
Ok, lets see. In the above you have the LOTES table attached to customers. If you WERE going to attach (relate) the LOTS table to a customer, then you don't need the store_id in the LOTES tables since the table is a child to that customer record. Anytime you can go up to the parent table to get that information, you don't need to repeat it in the child table(s). So, that customer record you are thus relating back to already has the store id and you be able to get at that store id value any time since it is a relation (that is the whole idea of a relational database, you don't have to repeat data over and over again).
And, as you have it now, the same advice applies to the two child table to LOTES. Again they don't need the store id since by you above design they are already attached to the LOTES table which in turn is attached to the customer table where the store id is. So, in your current design ALL of the child tables below customer can and should and would have the store_id removed.
However, the above I suspect is not what you looking to accomplish here. It is quite likely that LOTES records belong to a store. If that is the case, then you want LOTES table to be child of stores.
You thus should have STORES->LOTES
The only part not clear here is if your design is going to allow one customer to be attached to more then one store. If this is a very rare case, then perhaps you adopt a easier design that either forces you to enter the customer again, or even via some copy code. While this breaks normalizing here often there are some issues like if the shipping address is going to change for different stores for the same customer, then often you save a lot of code and design issues by not normalizing in this case.
However, if you need this feature, then the reverse is also true and there is MANY advantages to normalizing this data correctly, but often more desing work up front.
If you really do want customers to have more then one store, then you need a table called tblCustomerStores. You will attach this table to customers as a child table, and this this table will have the store_id. You can then attached all customer transactions etc. to this child store table. And this Customer store table might even include perhaps payment type and deliver preferences (if they vary from store to store for example).
So, you start at
Customers->customer stores->Transactions->
And, it not quite clear what is in table transactions, but it possible that everthing else belongs below the above trans table.
And, it not clear if Articles are attached to a particular transaction or not? If they are, then articles for thus be a child of transactions.
I thinking more of
Customers->customer stores->Articles->lots
And you want Customers stores->Tranascation
And you want Customers stores->Articles
So, I think you are currently going too many tables deep. Just keep in mind that you can relate many table to the parent table just like you have in your diagram, but I think what you have it not what you are looking for

override constraint from no action to cascading at runtime

I feel like I have a very basic/stupid question, yet I never saw/read/heard anything in this direction.
Say I have a table users(userId, name) and a table preferences(id, userId, language). The example is trivial but could be extended to a situation with multi-level relations and way more tables..
When my UI requests to delete a user I first want to show a warning stating that also its preferences will be deleted. If at some point the database gets extended with more tables and relationships, but the software isn't adapted accordingly (the client didn't update) a generic message should be shown.
How can I implement this? The UI cannot know about the whole data structure and should not be bothered to walk down all the relations to manually delete all the depending records.
I would think this would be with constraints.
The constraint would be no action at first so the constraint will throw an error that can be caught by the UI. After the UI receives a confirmation, the constraint should become a cascade.
Somehow I'm feeling like I'm getting this all wrong..
What I would do is this:
The constraint is CASCADE
The application checks if preferences exist.
If they do, show the warning.
If no preferences exist, or the warning is accepted, delete the client.
Changing database relationships on the fly is not going to be a good idea!!
Cheers,
RB.
If you are worried about the user not realising the full impact of their delete, you might want to consider not actually deleting the data - instead you could simply set a flag on a column called say "marked_for_deletion". (the entries could then be deleted a safe time later)
The downside is that you need to remember to filter out the marked rows in other queries. This can be mitigated by creating a view on the table with the marked rows filtered out, and then always using the view in your queries.