Batch create based on user selection in Odoo - batch-processing

I have the following models Program, Course, ProgramAdmission, CourseEnrollment.
Each course is associated with a program.
During program admission, I am showing the list of available courses for the selected program. For each shown course, I want to show a dropdown menu with the following selections: Not Planned and Planned.
Now if the user saves the new program admission, I want also to enroll the user in the planned courses by creating CourseEnrollment in the server-side for each planned course.
And if the user discards the new program admission, nothing should be created in the database.
How can I allow for such conditional batch creation of model objects?
Thank you!

It's easy, you just need to start to coding it. Create the module with the models relations and fields. On the ProgramAdmission model add a Many2one field to the Program model and another to the Course model. If you cancel the form while creating a new record nothing will be saved in your DB, but if you hit the Save button it will call the create method for new records and write methods for existing ones. Override the create method to be able to dynamically create a new record of the CourseEnrollment model and associate it with the ProgramAdmission record to be created by saving it to a new Many2one field in the same ProgramAdmission model.
To make what I mean more clear:
from odoo import models, fields, api
class Program(models.Model):
_name = 'school.program'
name = fields.Char()
class Course(models.Model):
_name = 'school.course'
name = fields.Char()
class ProgramAdmission(models.Model):
_name = 'school.program.admission'
course_id = fields.Many2one('school.course')
program_id = fields.Many2one('school.program')
enrollment_id = fields.Many2one('school.course.enrollment')
#api.model
def create(self, vals):
enrollment_id = self.env['school.course.enrollment'].create({
'course_id': vals['course_id'],
'program_id': vals['program_id']
})
vals['enrollment_id'] = enrollment_id.id
return super(ProgramAdmission, self).create(vals)
class CourseEnrollment(models.Model):
_name = 'school.course.enrollment'
course_id = fields.Many2one('school.course')
program_id = fields.Many2one('school.program')

Related

How to store relational fields to the database?

I've been searching for this for a week now, and still don't find any satisfying answer. If we make any type of relationship to other model in Odoo (in any framework as well) it won't store the data inside it, it will only store its id. Now when the related model get changed, the change will also true for all the child models that's inheriting it.
I want just like in the Sale module, when I change any product in Products model, it doesn't change the same product that's already stored in the orders. Please, any help, I'm very new here to Odoo I used to develop with Java.
An order correspond to the model named sale.order which is in one2many relationship with the model sale.order.line (SOL). one SOL has it s OWN fields for price, vat... which are computed bases on the current state of product at the time of the customer order. That's why the order and its SOL are not updated when the corresponding product attributes (price...) are changed...
In Odoo : an inherited python class EXTENDS the original class (similar to java extends) : in the sale_coupon module, the model located at src/odoo/addons/sale_coupon/models/sale_order.py is :
class SaleOrder(models.Model):
_inherit = "sale.order"
extends the source class SaleOrder defined in the module sale : src/odoo/addons/sale/models/sale.py:
class SaleOrder(models.Model):
name = "sale.order"
That's mean that the inherited class SaleOrder (_inherit) gets the specific attributes (fields) and methods (def) provided and defined in its source(s) class(es) : saleOrder :
origin = fields.Char(string='Source Document', help="Reference of the document that generated this sales order request.")
def _amount_all(self):
""" Compute the total amounts of the SO."""
for order in self:
amount_untaxed = amount_tax = 0.0
for line in order.order_line:
amount_untaxed += line.price_subtotal
amount_tax += line.price_tax
...
And you can add new fields and new methods in your inherited class SaleOrder scope :
reward_amount = fields.Float(compute='_compute_reward_total')
def action_confirm(self):
self.generated_coupon_ids.write({'state': 'new'})
...
return super(SaleOrder, self).action_confirm()
But, you don t need to instantiate theses Classes in your code (you don t need to create yourself Objects).
Theses classes have the basic CRUD-methods provided from models.Model: def create(), def read(), def write(), def unlink()
The source and the inherited class(es) both are connected to the same database-table : sale_order
So one Class-record (python in Odoo) :
self.env['sale.order'].browse(12)
corresponds to one record in the database-table : sale_order
Theses classes (SaleOrder) have the CRUD-methods from model.Model : def create(), def read(), def write(), def unlink() and they can override them in their own scope, where you can optionally call the "parent"-def : super(SaleOrder, self).unlink() :
def unlink(self):
for order in self:
if order.state not in ('draft', 'cancel'):
raise UserError(_('You can not delete a sent quotation or a confirmed sales order. You must first cancel it.'))
return super(SaleOrder, self).unlink()
Relations betweens models are defined using fields :
A relation between the sale.order model and the res.partner model (contact) is created using fields.Many2one:
class SaleOrder(models.Model):
...
partner_id = fields.Many2one('res.partner')
which is reflected in the corresponding database-table.
First of all, If you change the product details It will these details will change accordingly in the sale order after you refresh, about store the id of relation field its the standard way to use,
but there Is another way I think this is the way you looking for which Is store data as a JSON in column with type JSON as an example for sale order line table if you want to store the product as a JSON column it will be like below:
[{"id": 1, "name": "product 1"},]
of course, there Is a way to read and update and create the data into a JSON column you can read about It.
one more way as an example if you want to store the product to the current record of relation table not just store the Id and query to get the result you can just create new fields for data you want to store like if you want to store the name and price with name and id then you must add fields for this date and when you create in order line rather than add just product Id as a relation just add the product data to the new fields you have added before but this is not a good way.
I hope I understand your question and this answer helps you.

Odoo SAAS: Add field from associated model into a tree view of another model

I have 2 fields in res.partner that I would like to display in a tree view for account.invoice based on the partner_id field. I'm wondering how I can do that (reference another model and field) through the tree view web interface, due to the SaaS version not allowing programmatic access.
Thanks in advance!
create related field in you account.invoice model to the fields of res.partner
x_invoice_preference=fields.Selection(related="partner_id.x_invoice_preference")
it's a good practice to name the related field the same name in the other model
Little exemple :
class class1(models.Model):
_name = 'table1'
name = fields.Char()
class class2(models.Model):
_name = 'table2'
table1_id = fields.Many2one('table1','table 1');
#this how you create a related field in order to
#show it in the form or the tree when you select the value of the many2one field it
# will have the same value of the vield name of the tabl1
name = fields.Char(related="table1_id.name",readonly=True)
#field_name m2onField.field_name

How to send multiple values in many2many field in odoo?

I am trying to generate purchase order from manufacturing order.I have created many2many field for getting multiple products.I want to send multiple product ids to my custom function.I am able to send 1 value but sending more than one gives error as Expected singleton: product.template(4, 3).
from openerp import models,fields,api
class generate_purchase_order(models.Model):
_name = 'mrp_to_purchase_order'
product_id = fields.Many2many('product.template',string='Products',required=True)
#api.multi
def generate_purchase_order2(self):
for wizard in self:
mrp_obj = self.env['mrp.production']
mrp_obj.generate_purchase_order(wizard.product_id.id) #function call
return { 'type': 'ir.actions.act_window_close'}
mrp_custom.py,
from openerp import models,api
class mrp_production(models.Model):
_inherit = 'mrp.production'
#api.multi
def generate_purchase_order(self,product_id):
purchase_line_obj = self.env['purchase.order.line']
context = self._context
for order in self.browse(context['active_ids']):
for line in order.bom_id.bom_line_ids:
if line.product_id.id != product_id:#problem line
continue
#rest of code
singleton: product.template(4, 3)
This error means that code is expecting single record not recordset, so you must change code to allow recordset using or make ensureone with try-catch and avoid errors. Thats general information.
Now if you want to get multiple records from many2many its not problem at all, you must pass this many2many object only and then work with it.
After getting many2many object to work with every record from this recordset you must use for record in recordset:
Also wizard.product_id.id this is error!!! product_id is many2many so you must pass product_id or if you want to browse by yourself you must pass product_id.ids

How can I create an alias name of a relational field in Odoo?

I need to create a model, to have backward compatibility with older field names.
This way,
I can develop modules that could read the "new" fields, but migrating the old ones is not necessary for this to work.
This works only for reading or presenting the fields, but not for writing them.
So I thought it would be good to create an alias for each field, and made this:
from openerp import models, fields, api
class backward_compatibility(models.Model):
_description = 'Backward compatibility'
_inherit = 'account.invoice'
new_document_class_id = fields.Integer(
compute='_comp_new_doc_class', string='Tipo')
new_document_number = fields.Char(
compute='_comp_new_doc_number', string='Folio')
#api.multi
def _comp_new_doc_class(self):
for record in self:
try:
record.new_document_class_id = record.old_document_class_id
except:
pass
#api.multi
def _comp_new_doc_number(self):
for record in self:
try:
record.new_document_number = record.old_document_number
except:
pass
This approach works for the Char field, but it doesn't for the Integer (Many2one).
What ideas do you have to make this work? Should I replicate the relationship in the new field?
oldname: the previous name of this field, so that ORM can rename it automatically at migration
Try to use "oldname". I saw this in the core modules. Never used personally.
_inherit = 'res.partner'
_columns = {
'barcode' : fields.char('Barcode', help="BarCode", oldname='ean13'),
}
Also dummy fields are user to help with backward compatibility.
'pricelist_id': fields.dummy(string='Pricelist', relation='product.pricelist', type='many2one'),

How to create a reference field in OpenERP 6

I am trying to create a field from the web gui of OpenERP and field type as reference
1st there is no better docs about reference
2nd what I want is when someone selects the field it should give another option on selection which is not happening (though it is giving some field but 2nd field throws an error)!
It throws an error object does not exist
Reference fields are mainly used for showing different model's records as reference in your record. For example you have created a model such that whenever a sale order, purchase order, delivery order, project etc are created and saved, then a new record with data like user name, date, some notes should be created in your model. So here you add a reference field which link to the original record(sale order, purchase order etc) from which your record is created. You can find this in res.request model in openerp 6
To create an reference field in your class
def _get_selection_list(self, cr, uid, context=None):
##return a list of tuples. tuples containing model name and name of the record
model_pool = self.pool.get('ir.model')
ids = model_pool.search(cr, uid, [('name','not ilike','.')])
res = model_pool.read(cr, uid, ids, ['model', 'name'])
return [(r['model'], r['name']) for r in res] + [('','')]
_columns = {
'ref': fields.reference(Reference', selection=_get_selection_list, size=128)
}