Odoo domain_filter not working (always enforcing JOIN) - postgresql

I am having a problem creating a filter on Odoo 11.0 Community Edition.
On my domain class I have a self-relationship with a column called parent_id. I am trying to make a search filter, but even if I add one condition to avoid make the join, it's still not working.
Here is my domain definition:
class Subscription(models.Model):
_name = "subscription"
_rec_name = 'name'
parent_id = fields.Many2one(
'subscription',
string="Derived From",
index=True,
readonly=True
)
code = fields.Char(
string="Reference",
required=True,
index=True,
readonly=True,
copy=False
)
# other field definitions ...
and here is the filter that I am trying to do:
<record id="search_view_subscription" model="ir.ui.view">
<field name="name">subscription.search</field>
<field name="model">subscription</field>
<field name="arch" type="xml">
<search string="Subscriptions">
<field name="code" string="Subscription"
filter_domain="[
'|',
'&',
('parent_id', '=', False),
('code', 'ilike', self),
'&',
('parent_id', '!=', False),
('parent_id.code', 'ilike', self)
]"
/>
<!-- ... other filters working -->
</search>
<field>
</record>
I am not sure if the prefix notation is correct to do what I want, but essentially what I am trying to do is to recover from the database all the records that match the condition:
code ilike '%CERTAIN_VALUE%' OR parent_id.code ilike '%CERTAIN_VALUE%'
Where CERTAIN_VALUE is the user input from the treeview screen.
It seems the condition ('parent_id', '=', False) is being ignored

The filter_domain attribute can contain an arbitrary domain, so you're restricted neither to searching for the same field you named in the name attribute nor to using only one term. The self variable is what the user filled in, and also the only variable that you can use here. Here's a more elaborate example from the default search view for partners:
<search >
<field name="name"
filter_domain="[ '|', '|',
('display_name', 'ilike', self),
('ref', '=', self),
('email', 'ilike', self)]"/>
</search>
pay attention
Works in search tags <search> </search>

Related

computed field that does not compute and default that does not work (odoo-12)

I have this field with a method in my model which aims to detect the changes in the many2one:
manytoone = fields.Many2one(comodel_name="product.template", string="Many to One",
required=False, )
cambio_realizado = fields.Boolean(string="Cambios en Many to One", default=False)
#api.onchange('manytoone')
def _detectar_cambio(self):
self.cambio_realizado = True
No works the default=False in Boolean Field. Always start in True.
And the other problem is that no works a computed field:
#api.multi
def computer_function(self):
self.computation = 243+234
computation = fields.Float(string="Result: ", compute=computer_function, readonly=True)
The result is zero... always in the view.
identation ok, and the model is inherited
My Class and my view with the tips:
class CustomModule(models.Model):
_inherit = 'sale.order'
name = fields.Char('campos relacionales, decoradores onchange y funcion computar')
manytoone = fields.Many2one(comodel_name="product.template", string="Many to One",
required=False, )
cambio_realizado = fields.Boolean(string="Cambios en Many to One")
#api.onchange('manytoone')
def _detectar_cambio(self):
self.cambio_realizado = True
onetomany = fields.One2many(comodel_name="sale.order", inverse_name="manytoone",
string="One to Many", required=False, )
manytomany = fields.Many2many(comodel_name="sale.order",
relation="sale_handler",
column1="order_id", column2="order_handler_id",
string="Many to Many", )
#api.depends('computation')
def computer_function(self):
for record in self:
record.computation = 300
computation = fields.Float(string="Result: ", compute=computer_function, readonly=True)
<odoo>
<!-- Inherit Form View to Modify it -->
<record id="custom_view_custom" model="ir.ui.view">
<field name="name">custom.view.custom</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//sheet" position="inside">
<group>
<field name="manytoone"/>
<field name="onetomany"/>
<field name="manytomany"/>
</group>
<group>
<field name="computation"/>
<field name="cambio_realizado"/>
</group>
</xpath>
</field>
</record>
</odoo>
#api.one
def computer_function(self):
self.computation = 243+234
computation = fields.Float(string="Result: ", compute=computer_function, readonly=True)
use #api.one in your code
1- onchnage, when you try to create a new record, the onchange called automatically then cambio_realizado set to true
#api.onchange('manytoone')
def _detectar_cambio(self):
for o in self:
if o.manytoone:
o.cambio_realizado = True
2- in compute it's preferally to use api.depends('somefield'), but the code bellow may be work for you, use a loop and don't use readonly
#api.multi
def computer_function(self):
for o in self:
o.computation = 243+234
computation2 = fields.Float(string="Result: ", compute=computer_function)

Not Getting Full URL in own custom template in odoo?

I am new to odoo and I am trying to get full URL in my own custom template. Please check my code and help to sort it out what I am doing wrong.
mail_template_view.xml
<?xml version="1.0" encoding="utf-8"?>
<data noupdate = "0">
<record id="example_email_template" model="mail.template">
<field name="name">Example e-mail template</field>
<field name="email_from">bhuwankhadka2052#greenit.com.np</field>
<field name="subject">Congratz khadka</field>
<field name="email_to">benkhadka143#gmail.com</field>
<field name="model_id" ref="model_tender_manage"/>
<field name="auto_delete" eval="True"/>
<field name="body_html">
<![CDATA[
<p>Dear ,<br/><br/>
Good job, you've just created your first e-mail template!<br/></p>
My name is Bhuwan Khadka. What about you man?
A new tender record has been created
<div>
<p>Please check the link below for more details:</p>
% set website_url = object.env['ir.config_parameter'].sudo().get_param('web.base.url')
Your Odoo domain is: <b>${website_url}</b><br>
</div>
Regards,<br/>
Bhuwan Khadka
]]>
</field>
</record>
</data>
tendermanage.py
#api.model
def create(self,vals):
res = super(TenderManage,self).create(vals)
self.task_send_mail()
return res
Above code create new record and trigger automate email function
#api.multi
def task_send_mail(self):
template_email = self.env["mail.template"].search([('name','=','Example e-mail template')]).id
self.env["mail.template"].browse(template_email).sudo().send_mail(self.id, force_send=True)
Above code send email
If I remove URL code from XML file, email is sent automatically without any error but when URL code is written in email-template I get following error.
Error Message:
Please help me with your suggestion and how to get full url in email template. In XML odoo element is removed as it is not shown in above code.
mail_template_view.xml
<div>
<p>Please check the link below for more details:
Your Odoo domain is: <b>Click Here</p>
</div>
tendermanage.py
#api.multi
def get_full_url(self):
self.ensure_one()
base_url = self.env["ir.config_parameter"].get_param("web.base.url")
url_params = {
'id': self.id,
'view_type': 'form',
'model': 'your_model',
'menu_id': self.env.ref('module_name.menu_record_id').id,
'action': self.env.ref('module_name.action_record_id').id,
}
params = '/web?#%s' % url_encode(url_params)
return base_url + params
Change the mail template div and create method like this in your model..
i hope it will helps..

Odoo 10 : Failed to render mail template

I have created an mail template in Odoo 10, and call it with a cron task. The problem is that it doesn't work and give me error, here is the log : https://pastebin.com/c7zCXbxF. Could you help me?
Here is the mail template:
<odoo>
<data>
<record id="crm_lead_reminder" model="mail.template">
<field name="name">Rappel sur le pipeline</field>
<field name="email_from">admin#example.com</field>
<field name="subject">Rappel ${object.type} ${object.name} </field>
<field name="email_to">${object.user_id.partner_id.email}</field>
<field name="model_id" ref="sale_cron.model_crm_lead"/>
<field name="auto_delete" eval="True"/>
<field name="body_html">
<![CDATA[
<p>
hello world
</p>
]]>
</field>
</record>
</data>
And here is the methode that call it:
class sale_cron(models.Model):
_inherit = 'crm.lead'
def _trigger_action(self, date_action, current_date):
date_action = [int(date) for date in date_action.split('-')]
if date_action[0] == current_date.year:
if date_action[1] == current_date.month:
if date_action[2] == current_date.day or date_action[2] == current_date.day + 1:
return 0
return -1
def _check_crm_lead(self):
current_date = datetime.datetime.now()
for crm_lead_id in self.search([('stage_id', '!=', 4)]):
i = self._trigger_action(crm_lead_id.date_action, current_date)
if i == -1:
return 0
template = self.env.ref('sale_cron.crm_lead_reminder')
template.send_mail(self.user_id.id, force_send=True, raise_exception=True)
return 1
ps: the module name is sale_cron.
Try changing your code like this
template.send_mail(crm_lead_id.id, force_send=True, raise_exception=True)
def _check_crm_lead(self):
current_date = datetime.datetime.now()
for crm_lead_id in self.search([('stage_id', '!=', 4)]):
i = self._trigger_action(crm_lead_id.date_action, current_date)
if i == -1:
return 0
template = self.env.ref('sale_cron.crm_lead_reminder')
template.send_mail(crm_lead_id.id, force_send=True, raise_exception=True)
return 1

Odoo One2many relation with VIEW table in postgresql

I have the following report model:
class crm_purchased_products(models.Model):
_name = "crm.purchased_products"
_description = "Most purchased products report"
_auto = False
partner_id = fields.Many2one('res.partner', string='Customer')
product_id = fields.Many2one('product.product', string='Product')
invoice_qty = fields.Integer('Number of invoices')
quantity = fields.Integer('Quantity')
total_amount_untaxed = fields.Float(string='Total amount', digits=dp.get_precision('Account'))
def init(self, cr):
tools.drop_view_if_exists(cr, self._table)
_query = """CREATE OR REPLACE VIEW crm_purchased_products AS (
SELECT ail.partner_id AS partner_id, ail.product_id AS product_id,
COUNT(ail.invoice_id) AS invoice_qty, SUM(ail.quantity) AS quantity,
SUM(ail.price_subtotal) AS total_amount_untaxed, MAX(ai.date_invoice) AS last_purchase,
(MAX(ai.date_invoice) - MIN(ai.date_invoice))/COUNT(ail.invoice_id) AS days_between_purchases
FROM account_invoice_line AS ail
JOIN account_invoice AS ai ON ail.invoice_id = ai.id
WHERE ai.type = 'out_invoice' AND ai.state IN ('open','paid')
GROUP BY ail.partner_id, ail.product_id HAVING ail.product_id > 0 ORDER BY ail.partner_id ASC
);
"""
def search(self, cr, uid, args, offset=0, limit=None, order=None,context=None, count=False):
return super(crm_purchased_products, self).search(cr, uid, args=args, offset=offset, limit=limit, order=order,
context=context, count=count)
crm_purchased_products()
I want to insert as a tree field in res.partner form view to show only the products associated to the contact:
<page name="internal_notes" string="Internal Notes">
<field name="purchased_products">
<tree string="Most purchased products">
<field name="partner_id" invisible="1"/>
<field name="product_id"/>
<field name="invoice_qty"/>
<field name="quantity"/>
<field name="total_amount_untaxed"/>
</tree>
</field>
</page>
But, when I try to relate it from res.partner:
purchased_products = fields.One2many('crm.purchased_products', 'partner_id', string='Purchased products', readonly=True, copy=True)
I get this error:
ProgrammingError: relation "crm_purchased_products" does not exist
LINE 1: SELECT "crm_purchased_products".id FROM "crm_purchased_produ...
ID field is auto added to all models from models.Model, so you must get it. Try this:
def init(self, cr):
tools.drop_view_if_exists(cr, self._table)
_query = """CREATE OR REPLACE VIEW crm_purchased_products AS (
SELECT row_number() OVER () AS id, ail.partner_id AS partner_id, ail.product_id AS product_id,
COUNT(ail.invoice_id) AS invoice_qty, SUM(ail.quantity) AS quantity,
SUM(ail.price_subtotal) AS total_amount_untaxed, MAX(ai.date_invoice) AS last_purchase,
(MAX(ai.date_invoice) - MIN(ai.date_invoice))/COUNT(ail.invoice_id) AS days_between_purchases
FROM account_invoice_line AS ail
JOIN account_invoice AS ai ON ail.invoice_id = ai.id
WHERE ai.type = 'out_invoice' AND ai.state IN ('open','paid')
GROUP BY row_number() OVER (), ail.partner_id, ail.product_id HAVING ail.product_id > 0 ORDER BY ail.partner_id ASC
);
"""

Magento2- How to copy custom data from quote to order and order item

I am building a custom module in Magento 2 that has a custom discount. I am trying to copy the discount from quote, quote item to order and order item.
In Magento 1, I declare the config.xml like this:
<fieldsets>
<sales_convert_quote_address>
<custom_discount_amount><to_order>*</to_order></custome_discount_amount>
<base_custom_discount_amount><to_order>*</to_order></base_custome_discount_amount>
</sales_convert_quote_address>
<sales_convert_quote_item>
<custome_discount_amount><to_order_item>*</to_order_item></custome_discount_amount>
<base_custom_discount_amount><to_order_item>*</to_order_item></base_custom_discount_amount>
</sales_convert_quote_item>
</fieldsets>
and my custom discount amount was copied to tables: sales_flat_order and sales_flat_order_item as expected.
In Magento 2, I created a file named fieldset.xml with this code:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Object/etc/fieldset.xsd">
<scope id="global">
<fieldset id="sales_convert_quote_item">
<field name="custom_discount_amount">
<aspect name="to_order_item" />
</field>
<field name="base_custom_discount_amount">
<aspect name="to_order_item" />
</field>
</fieldset>
<fieldset id="sales_convert_quote_address">
<field name="custom_discount_amount">
<aspect name="to_order" />
</field>
<field name="base_custom_discount_amount">
<aspect name="to_order" />
</field>
</fieldset>
</scope>
</config>
but there is no success.
What else do I need to do in Magento 2 to make it work? Can you guys please help me?
In Magento 2 without using fieldset you can also copy custom data from quote item to order item by using plugin.
create di.xml in your module etc folder.
app/code/Vender/Yourmodule/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
<type name="Magento\Quote\Model\Quote\Item\ToOrderItem">
<plugin name="cedapi_quote_to_order_item" type="Vender\Yourmodule\Model\Plugin\Quote\QuoteToOrderItem"/>
</type>
</config>
Create a class to your module and define a function. app/code/Vender/Yourmodule/Model/Plugin/Quote
Create QuoteToOrderItem.php file
<?php
namespace Vender\Yourmodule\Model\Plugin\Quote;
use Closure;
class QuoteToOrderItem
{
/**
* #param \Magento\Quote\Model\Quote\Item\ToOrderItem $subject
* #param callable $proceed
* #param \Magento\Quote\Model\Quote\Item\AbstractItem $item
* #param array $additional
* #return \Magento\Sales\Model\Order\Item
* #SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function aroundConvert(
\Magento\Quote\Model\Quote\Item\ToOrderItem $subject,
Closure $proceed,
\Magento\Quote\Model\Quote\Item\AbstractItem $item,
$additional = []
) {
/** #var $orderItem \Magento\Sales\Model\Order\Item */
$orderItem = $proceed($item, $additional);//result of function 'convert' in class 'Magento\Quote\Model\Quote\Item\ToOrderItem'
$orderItem->setCustomDesign($item->getCustomDesign());//set your required
return $orderItem;// return an object '$orderItem' which will replace result of function 'convert' in class 'Magento\Quote\Model\Quote\Item\ToOrderItem'
}
}
After spend some time and research issue, i stucked here:
Magento\Quote\Model\QuoteManagement.php
line 446
public function mergeDataObjects(
$interfaceName,
$firstDataObject,
$secondDataObject
) {
if (!$firstDataObject instanceof $interfaceName || !$secondDataObject instanceof $interfaceName) {
throw new \LogicException('Wrong prototype object given. It can only be of "' . $interfaceName . '" type.');
}
$secondObjectArray = $this->objectProcessor->buildOutputDataArray($secondDataObject, $interfaceName);
$this->_setDataValues($firstDataObject, $secondObjectArray, $interfaceName);
return $this;
}
Which ignores converted attributes because logic of merging based on presence getters and setters of target model\interface. So, if you converting attributes which haven't setters and getters in target model they will be ignored here:
Magento\Framework\Reflection\DataObjectProcessor.php line 75
public function buildOutputDataArray($dataObject, $dataObjectType)
{
$methods = $this->methodsMapProcessor->getMethodsMap($dataObjectType);
$outputData = [];
/** #var MethodReflection $method */
foreach (array_keys($methods) as $methodName) {
if (!$this->methodsMapProcessor->isMethodValidForDataField($dataObjectType, $methodName)) {
continue;
}
$value = $dataObject->{$methodName}();
$isMethodReturnValueRequired = $this->methodsMapProcessor->isMethodReturnValueRequired(
$dataObjectType,
$methodName
);
Maybe you might to use observer or plugin to avoid this problem. (issue encountered in 2.0.6 Magento version)
For anybody looking at this in the future, the fact that the fieldset XML doesn't work has been acknowledged by Magento as a bug. There is a core patch available in the ticket (not reproduced here since it may need to be tweaked with new Magento versions).
https://github.com/magento/magento2/issues/5823