Odoo - Is it possible to show both tax included and tax excluded total price in invoice lines ? - odoo

I try to show both columns in the account invoice form :
total of an invoice line, tax excluded
total of an invoice line, tax included.
I know that it is possible to set the tax object to be included or excluded in product price, but I don't see the way to show both in invoice form.
I already extended account.invoice.line as follow :
from openerp import api, models, fields
import openerp.addons.decimal_precision as dp
class cap_account_invoice_line(models.Model):
_inherit = 'account.invoice.line'
price_with_tax = fields.Float(string='Prix TTC', digits= dp.get_precision('Product Price'), store=True, readonly=True,)
"""
#api.multi
def button_reset_taxes(self):
#I guess I should override this method but i don't know how
#to calculate and load the total line with included tax
#into the field 'price_with_tax'
"""
Thank you in advance for your help
Victor

Solution found :
from openerp import api, models, fields
import openerp.addons.decimal_precision as dp
class AccountInvoiceLine(models.Model):
_inherit = 'account.invoice.line'
price_subtotal_tax = fields.Float(compute='_compute_price_tax', string=' Total including tax', digits= dp.get_precision('Product Price'), store=True)
#api.one
#api.depends('price_unit', 'discount', 'invoice_line_tax_id', 'quantity',
'product_id', 'invoice_id.partner_id', 'invoice_id.currency_id')
def _compute_price_tax(self):
price = self.price_unit * (1 - (self.discount or 0.0) / 100.0)
taxes = self.invoice_line_tax_id.compute_all(price, self.quantity, product=self.product_id,
partner=self.invoice_id.partner_id)
self.price_subtotal_tax = taxes['total_included']
if self.invoice_id:
self.price_subtotal_tax = self.invoice_id.currency_id.round(self.price_subtotal_tax)

Related

Grouping and summing quantity lines with same product

I have this function it filters in all selected MO's raw material lines, and then creates a report that is displayed in tree view.
But I have one problem, there can be allot lines with the same product. So my goal is to group all these lines and display them then just in one line with summed quantity.
Can someone help me with this?
class RawMaterialReport(models.Model):
_name = 'raw.material.report'
_description = 'Raw Material Report'
product_id = fields.Many2one('product.product', string='Product', required=False)
code = fields.Char(string='Code', required=True, readonly=True)
total_qty = fields.Float(string='Total Qty', digits=(6, 2), readonly=True)
virtual_qty = fields.Float(string='Forcasted Qty', digits=(6, 2), readonly=True)
origin = fields.Char(string='Origin', required=True, readonly=True)
production_id = fields.Many2one('mrp.production')
#api.multi
def open_raw_materials(self):
self.search([]).unlink()
mrp_productions = self._context.get('active_ids')
mrp_production = self.env['mrp.production'].browse(mrp_productions)
products_without_default_code = mrp_production.mapped('move_raw_ids').filtered(
lambda x: not x.product_id.default_code
)
raws = mrp_production.mapped('move_raw_ids').sorted(
key=lambda r: r.product_id.default_code
)
for r in raws:
vals = {
'product_id': r.product_id.id,
'code': r.product_id.default_code,
'total_qty': r.product_id.qty_available,
'virtual_qty': r.product_id.virtual_available,
'origin': r.reference,
'production_id': r.raw_material_production_id.id,
}
self.create(vals)
Instead of creating the record directly, keep them in dictionary grouped by product ID and when ever you find that the product all ready have a record just sum its
quantity.
#api.multi
def open_raw_materials(self):
self.search([]).unlink()
mrp_productions = self._context.get('active_ids')
mrp_production = self.env['mrp.production'].browse(mrp_productions)
products_without_default_code = mrp_production.mapped('move_raw_ids').filtered(
lambda x: not x.product_id.default_code
)
raws = mrp_production.mapped('move_raw_ids').sorted(
key=lambda r: r.product_id.default_code
)
# to group by product
recs = {}
for r in raws:
product_id = self.product_id.id
if product_id in recs:
# here just update the quantities or any other fields you want to sum
recs[product_id]['product_uom_qty'] += self.product_id.product_uom_qty
else:
# keep the record in recs
recs[product_id] = {
'product_id': r.product_id.id,
'code': r.product_id.default_code,
'total_qty': r.product_id.product_uom_qty,
'virtual_qty': r.product_id.virtual_available,
'origin': r.reference,
'production_id': r.raw_material_production_id.id,
}
for vals in recs.values():
# create records this will create a record by product
self.create(vals)

How can I convert the total price of an invoice to letters in odoo 11?

I have a created module called 'custom_report_module', where I make a personalized invoice ... The invoice works well but I want to add the total amount in letters .. for example .. if the purchase reached 500,000 that I printed in letters "are: five hundred thousand guaranies "or" are: five hundred thousand "
class account_invoice(models.Model):
_inherit = "account.invoice"
#api.multi
def amount_to_text(self, amount, currency='rupee'):
return amount_to_text(amount, currency)
my xml
<span t-esc="l.amount_to_text(l.price_unit, l.price_unit)"/>
Please have a look at the this code
#api.multi
def amount_to_text(self, amount):
self.ensure_one()
def _num2words(number, lang):
try:
return num2words(number, lang=lang).title()
except NotImplementedError:
return num2words(number, lang='en').title()
if num2words is None:
logging.getLogger(__name__).warning("The library 'num2words' is missing, cannot render textual amounts.")
return ""
formatted = "%.{0}f".format(self.decimal_places) % amount
parts = formatted.partition('.')
integer_value = int(parts[0])
fractional_value = int(parts[2] or 0)
lang_code = self.env.context.get('lang') or self.env.user.lang
lang = self.env['res.lang'].search([('code', '=', lang_code)])
amount_words = tools.ustr('{amt_value} {amt_word}').format(
amt_value=_num2words(integer_value, lang=lang.iso_code),
amt_word=self.currency_unit_label,
)
if not self.is_zero(amount - integer_value):
amount_words += ' ' + _('and') + tools.ustr(' {amt_value} {amt_word}').format(
amt_value=_num2words(fractional_value, lang=lang.iso_code),
amt_word=self.currency_subunit_label,
)
return amount_words

Filter lines by categ_id and count qty

My goal is to loop through all lines with the same categ_id and calculate total quantity they have and if qty_categ_total < categ_id.qty_for_discount ( I added this field to 'product.category' than I need to post a message in text fields. the problem my code is not working as I want.
Example.
If I have 2 lines with the same categ_id with qty 2 and 5 and my categ_id.qty_for_discount is 10. The message should say that I need to add 3 more products with the same categ_id to get discount
Update
And if there are products with different categories I should get a message for each category
class PurchaseOrder(models.Model):
_inherit = 'purchase.order'
discount_warning_message = fields.Text(string='Discount Warning', compute='discount_warning')
#api.depends('order_line.product_id', 'order_line.product_qty')
def discount_warning(self):
qty_categ_total = 0.0
for line in self.order_line:
qty_categ_total += line.product_qty
if qty_categ_total < line.product_id.categ_id.qty_for_discount:
message = (_("You can get discount if you add %s more %s\n")) % (qty_categ_total, line.product_id.categ_id.name)
self.discount_warning_message = message
Your code seems to be correct, but i would change something. First either use #api.one to let odoo automatically loop through all orders or add one more for each loop and #api.multi. And secondly what about more than one category?
#api.multi
#api.depends('order_line.product_id', 'order_line.product_qty')
def discount_warning(self):
msg = _("You can get discount if you add %s more %s\n")
for order in self:
categ_qtys = {}
for line in order.order_line:
if line.product_id.categ_id not in categ_qtys:
categ_qtys[line.product_id.categ_id] = 0.0
categ_qtys[line.product_id.categ_id] += line.product_qty
msgs = []
for categ, qty in categ_qtys.iteritems():
if qty < categ.qty_for_discount:
msgs.append(msg % (qty, categ.name))
if msgs:
order.discount_warning_message = "".join(msgs)
General advice: Always try to debug into your methods. Are they even called? If not, the methods aren't the problem.

POS order product total

my goal is to add a field in product form view that will show how many time this product was bought with POS. really stuck with this one and would be nice to have an idea how to do this.
class Product(models.Model):
_inherit = 'product.product'
pos_product_order_total = fields.Char(
string='Product POS Orders', compute='_product_pos_orders')
def _product_pos_orders(self):
Order = self.env['pos.order']
for product in self:
domain = [('product_id', '=', product.id)]
for o in Order.search(domain):
pass
Try below solution:
class Product(models.Model):
_inherit = 'product.product'
pos_product_order_total = fields.Char(
string='Product POS Orders', compute='_product_pos_orders')
def _product_pos_orders(self):
OrderLine = self.env['pos.order.line']
for product in self:
domain = [('product_id', '=', product.id)]
product.pos_product_order_total = sum(OrderLine.search(domain).mapped('qty'))

TypeError: generate_purchase_order() takes exactly 1 argument (5 given)

I am trying to convert openerp 7 code to odoo8. In V7 browse() method had several parameters like self,cr,uid,ids,context but in V8 I think none of these is needed.In my custom module I am trying to create a purchase order based on the information obtained from mrp.I have done a custom calculation for how many Kgs of paper needed for 10000 quantities of books to be manufactured.After calculation this info should go to purchase invoice.Products will be obtained from bill of materials,quantity from no of kgs of paper needed and unit price from product cost attribute.I am unable to solve this error "method takes exactly 1 argument (5 given)"
mrp.py,
from openerp import models
class mrp_production(models.Model):
_inherit = 'mrp.production'
def generate_purchase_order(self,supplier_id,warehouse_id):
purchase_obj = self.env['purchase.order']
purchase_line_obj = self.env['purchase.order.line']
warehouse_obj = self.env['stock.warehouse']
warehouse = warehouse_obj.browse(warehouse_id)
if not warehouse:
return False
if isinstance(warehouse, list):
warehouse = warehouse[0]
for order in self:
vals = {}
vals = purchase_obj.onchange_partner_id()
vals['origin'] = order.name
vals['partner_id'] = supplier_id
vals['warehouse_id'] = warehouse_id
vals['location_id'] = warehouse.lot_stock_id.id
vals['date_order'] = order.date_planned
purchase_id = purchase_obj.create(vals)
for line in self.bom_id.bom_line_ids:
if not line.product_id:
continue
line_vals = purchase_line_obj.onchange_product_id(line.product_id.id,
line.product_uom_qty, line.product_uom.id, supplier_id,
date_planned=line.date_planned)['value']
line_vals['name'] = line.name
line_vals['product_id'] = line.product_id.id
if not line_vals.get('price_unit', False):
line_vals['price_unit'] = line.product_id.list_price
line_vals['product_uom'] = line.product_uom.id
line_vals['product_uom_qty'] = 181.13
line_vals['order_id'] = purchase_id
purchase_line_obj.create(line_vals)
return True
generate_purchase_order.py,
from openerp import models,fields,api
class generate_purchase_order(models.Model):
_name = 'mrp_to_purchase_order.generate_purchase_order'
_description = 'Generate Purchase Order'
partner_id = fields.Many2one('res.partner', 'Supplier', required=True, domain="[('supplier','=',True)]")
warehouse_id = fields.Many2one('stock.warehouse', 'Warehouse', required=True)
#api.multi
def onchange_partner_id(self,partner_id):
return {}
def generate_purchase_order(self):
for wizard in self:
#mrp_order_ids = [context['active_id']]
mrp_obj = self.env['mrp.production']
mrp_obj.generate_purchase_order(wizard.partner_id.id, wizard.warehouse_id.id)
return { 'type': 'ir.actions.act_window_close'}
If you are calling the generate_purchase_order method from some other method in your model, then use the decorator #api.multi for that method.
Also in your generate_purchase_order method, replace
for order in self.browse():
by
for order in self:
EDIT
#api.multi
def generate_purchase_order(self):
for wizard in self:
#mrp_order_ids = [context['active_id']]
mrp_obj = self.env['mrp.production']
# Get the mrp record
mrp_rec = code to get mrp record
mrp_rec.generate_purchase_order(wizard.partner_id.id, wizard.warehouse_id.id)
return { 'type': 'ir.actions.act_window_close'}