Save form data in two models in Odoo - forms

I have created two models (A and B) with the same fields, only for backup purposes. I created a form with A as model using HTML Form Builder. Normally, form data will save in table A (model A). I want to save the data that is inserted in the B model as well.

If this models are identical just override the create and write and unlink method in A model to execute the same operation in B.
But for unlink and write I think you need to keep the id of model B in model A so when you delete a record from A you delete the corresponding record in b. nothing will confirm that the ids will be the sames.
#api.model
def create(self, vals):
a_id = super(YourClassName, self).create(vals)
b_id = self.env['B'].create(vals) # here no one will confirm that both have the same id
a_id.many2one_b_id = b_id # so you can execute write and unlink
return rec_id
#api.muli
def write(self,vals):
# don't forget using api.multi self can contain more than one record
# using mapped is better than looping through records and execute write
# one by one. and using api.one have the same effect
super(YourClassName, self).write(vals)
# using mapped will execute only one update queries for all ids
self.mapped('many2one_b_id').write(vals) # mapped will return the list of B record
return True
#api.multi
def unlink(self):
# same thing for delete
# delete B record first
self.mapped('many2one_b_id').unlink()
super(YourClassName, self).unlinck()

Related

Modifying queries on the fly depending on selected filters

In an existing codebase some tables are now horizontally sharded within the same database but in different namespaces.
E.g. let's say there previously was a large table users which is now sharded by the country field so there are now the following tables: us.users, ca.users, es.users etc.
Since every single query to the tables already contains the country filter I was thinking of the following minimalistic adjustment so that there's no need to subclass the original model for every country manually or dynamically:
class SessionWithShardedTableSupport(Session):
""" Use sharded tables on the fly """
def connection(self, mapper=None, clause=None, bind=None, close_with_result=None, **kw):
if mapper and mapper.local_table.name == 'users':
mapper.local_table.schema = '???' # `us` or `ca` or `es`
return super().connection(mapper, clause, bind, close_with_result, **kw)
The solution would work fine if there was a way to get the country filter from the query from within the session but there doesn't seem any (at least inspecting both mapper & clause parameters didn't reveal them).
1) Is there a way to get the where clause / the filters from within the session?
2) Is there maybe a better way to adjust the table name / table namespace on the fly with minimalistic changes to the existing code?

Slick insert into H2, but no data inserted

I'm sure I am missing something really stupidly obvious here - I have a unit test for a very simple Slick 3.2 setup. The DAO has basic retrieve and insert methods as follows:
override def questions: Future[Seq[Tables.QuestionRow]] =
db.run(Question.result)
override def createQuestion(title: String, body: String, authorUuid: UUID): Future[Long] =
db.run(Question returning Question.map(_.id) += QuestionRow(0l, UUID.randomUUID().toString, title, body, authorUuid.toString))
And I have some unit tests - for the tests im using in memory H2 and have a setup script (passed to the jdbcurl) to initialise two basic rows in the table.
The unit tests for retriving works fine, and they fetch the two rows inserted by the init script, and I have just added a simple unit test to create a row and then retrieve them all - assuming it will fetch the three rows, but no matter what I do, it only ever retrieves the initial two:
it should "create a new question" in {
whenReady(questionDao.createQuestion("Question three", "some body", UUID.randomUUID)) { s =>
whenReady(questionDao.questions(s)) { q =>
println(s)
println(q.map(_.title))
assert(true)
}
}
}
The output shows that the original s (the returning ID from the autoinc) is 3, as I would expect (I have also tried the insert not doing the returning step and just letting it return the number of rows inserted, which returns 1, as expecteD), but looking at the values returned in q, its only ever the first two rows inserted by the init script.
What am I missing?
My assumptions are that your JDBC url is something like jdbc:h2:mem:test;INIT=RUNSCRIPT FROM 'init.sql' and no connection pooling is used.
There are two scenarios:
the connection is performed with keepAliveConnection = true (or by appending DB_CLOSE_DELAY=-1 to the JDBC url) and the init.sql is something like:
DROP TABLE IF EXISTS QUESTION;
CREATE TABLE QUESTION(...);
INSERT INTO QUESTION VALUES(null, ...);
INSERT INTO QUESTION VALUES(null, ...);
the connection is performed with keepAliveConnection = false (default) (without appending DB_CLOSE_DELAY=-1 to the JDBC url) and the init.sql is something like:
CREATE TABLE QUESTION(...);
INSERT INTO QUESTION VALUES(null, ...);
INSERT INTO QUESTION VALUES(null, ...);
The call to questionDao.createQuestion will open a new connection to your H2 database and will trigger the initialization script (init.sql).
In both scenarios, right after this call, the database contains a QUESTION table with 2 rows.
In scenario (2) after this call the connection is closed and according to H2 documentation:
By default, closing the last connection to a database closes the database. For an in-memory database, this means the content is lost. To keep the database open, add ;DB_CLOSE_DELAY=-1 to the database URL. To keep the content of an in-memory database as long as the virtual machine is alive, use jdbc:h2:mem:test;DB_CLOSE_DELAY=-1.
The call to questionDao.questions will then open a new connection to your H2 database and will trigger again the initialization script (init.sql).
In scenario (1) the first connection is kept alive (and also the database content) but the new connection will re-execute the initialization script (init.sql) erasing the database content.
Given that (in both scenarios) questionDao.createQuestion returns 3, as expected, but then the content is lost and so the subsequent call to questionDao.questions will use a freshly initialized database.

Updating specific columns not all model entities

Zend 1.8 Geeks!
I always use model_mapper to update insert and fetch data from the db by this example :
$a=somthin;
$y=qwe;
$dataMapper = new model_mapper_data();
$dataModel = new model_data();
$dataEntity=$dataModel->AA=$a ;
=> $dataMapper->update($dataEntity,'x'=$y);
Now on the last line the Mapper generates a query to update all table row columns AA and rest stored in the data-model where 'x'=$y.
isn't there a way to force the Mapper to update specific columns only?
Well all what you need is to not give the update method the model entity Since the model initialize objects for all of the columns .
Just give it an array of the columns names you would like to modify and Pair them to their values like below :
Mapper->update('column_name'=>value);

Select and insert by keeping references to original data in OrientDB

I am exploring graphDB query languages. At the moment looking at OrientDB query language. I would like to see how a transaction would look like in OrientDB with the following structure:
Suppose, I have two vertices, A and QA:
CREATE CLASS A EXTENDS V
CREATE CLASS QA EXTENDS V
Class A has a property called p1 of Integer:
CREATE PROPERTY A.p1 integer
Assume that A has three records called a1,a2,a3 with their corresponding values for p1 are a1.p1=2; a2.p1=5; a3.p1=10;:
INSERT INTO A SET p1 = 2 // call this a1
Created record with RID #11:1
INSERT INTO A SET p1 = 5 // call this a2
Created record with RID #11:2
INSERT INTO A SET p1 = 10 // call this a3
Created record with RID #11:3
And assume that I have an edge called isA from QA to A.
CREATE CLASS isA EXTENDS E // it seems that I can not restrict isA records to connect only QA records to A
I would like to see how the following transaction would look like in OrientDB:
first: select all A's content where p1 < 6 => so I will get {a1,a2}
second: for each element in the first query create an element in QA => so I will get for example {qa1,qa2}
third: Add records to isA Edge such that they connect elements in QA to their corresponding elements in A; =>so, for example connect qa1 to a1 and qa2 to a2.
It seems all three queries are inter-related.
My 1th Question: how the above transaction (i.e., set of inter-related queries) would look like in OrientDB?
Note that elements of A are dynamic (not fixed during my system) and I would like to synch QA elements with A, whenever A's content changes by employing the above transaction; for example, if I add a4 to A with p1=3, and run the above set of queries, I am expecting to get a new record in QA, say qa4 which is linked to a4.

How to assign foreign keys in Access within imported table from Excel

I will use Access database instead of Excel. But I need to import data from one huge Excel sheet into several pre-prepared normalized tables in Access. In the core Access table I have mainly the foreign keys from other tables (of course some other fields are texts or dates).
How should I perform the import in the easiest way? I cannot perform import directly, because there is NOT, for example, "United States" string in the Access field 'Country'; there must be foreign key no. 84 from the table tblCountries. I think about DLOOKUP function in the Excel and replace strings for FK... Do you know any more simple method?
Thank you, Martin
You don’t mention how you will get the Excel data into several Access tables, so I will assume you will import the entire Excel file into ONE large table then break out the data from there. I assume the imported data may NOT match with existing Access keys (i.e. misspellings, new values, etc.) so you will need to locate those so you can make corrections. This will involve creating a number of ‘unmatched queries’ then a number of ‘Update queries’, finally you can use Append queries to pull data from your import table into the final resting place. Using your example, you have imported ‘Country = United States’, but you need to relate that value to key “84”?
Let’s set some examples:
Assume you imported your Excel data into one large Access table. Also assume your import has three fields you need to get keys for.
You already have several control tables in Access similar to the following:
a. tblRegion: contains RegionCode, RegionName (i.e. 1=Pacific, 2=North America, 3=Asia, …)
b. tblCountry: contains CountryCode, Country, Region (i.e. 84 | United States | 2
c. tblProductType: contains ProdCode, ProductType (i.e. VEH | vehicles; ELE | electrical; etc.)
d. Assume your imported data has fields
Here are the steps I would take:
If your Excel file does not already have columns to hold the key values (i.e. 84), add them before the import. Or after the import, modify the table to add the columns.
Create ‘Unmatched query’ for each key field you need to relate. (Use ‘Query Wizard’, ‘Find Unmatched Query Wizard’. This will show you all imported data that does not have a match in your key table and you will need to correct those valuse. i.e.:
SELECT tblFromExcel.Country, tblFromExcel.Region, tblFromExcel.ProductType, tblFromExcel.SomeData
FROM tblFromExcel LEFT JOIN tblCountry ON tblFromExcel.[Country] = tblCountry.[CountryName]
WHERE (((tblCountry.CountryName) Is Null));
Update the FK with matching values:
UPDATE tblCountry
INNER JOIN tblFromExcel ON tblCountry.CountryName = tblFromExcel.Country
SET tblFromExcel.CountryFK = [CountryNbr];
Repeat the above Unmatched / Matched for all other key fields.