MIG account_invoice_margin adn stock_inventory_valudation_ods

FIX for my PR is merged https://github.com/odoo/odoo/pull/35073
Fix in stock_usability for manual creation of stock moves
This commit is contained in:
Alexis de Lattre
2019-07-22 16:35:38 +02:00
parent 62d0af15ac
commit a21ec776c1
13 changed files with 66 additions and 74 deletions

View File

@@ -1,4 +1,2 @@
# -*- coding: utf-8 -*-
from . import account_invoice from . import account_invoice
from . import account_invoice_report from . import account_invoice_report

View File

@@ -1,11 +1,11 @@
# -*- coding: utf-8 -*- # Copyright 2015-2019 Akretion France (http://www.akretion.com)
# © 2015-2017 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{ {
'name': 'Account Invoice Margin', 'name': 'Account Invoice Margin',
'version': '10.0.1.0.0', 'version': '12.0.1.0.0',
'category': 'Accounting & Finance', 'category': 'Invoicing Management',
'license': 'AGPL-3', 'license': 'AGPL-3',
'summary': 'Copy standard price on invoice line and compute margins', 'summary': 'Copy standard price on invoice line and compute margins',
'description': """ 'description': """

View File

@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*- # Copyright 2015-2019 Akretion France (http://www.akretion.com)
# © 2015-2017 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api from odoo import api, fields, models
import odoo.addons.decimal_precision as dp import odoo.addons.decimal_precision as dp
@@ -48,16 +47,18 @@ class AccountInvoiceLine(models.Model):
# it works in _get_current_rate # it works in _get_current_rate
# even if we set date = False in context # even if we set date = False in context
# standard_price_inv_cur is in the UoM of the invoice line # standard_price_inv_cur is in the UoM of the invoice line
date = inv._get_currency_rate_date() or\
fields.Date.context_today(self)
company = inv.company_id
company_currency = company.currency_id
standard_price_inv_cur =\ standard_price_inv_cur =\
inv.company_id.currency_id.with_context( company_currency._convert(
date=inv.date_invoice).compute( il.standard_price_company_currency,
il.standard_price_company_currency, inv.currency_id, company, date)
inv.currency_id)
margin_inv_cur =\ margin_inv_cur =\
il.price_subtotal - il.quantity * standard_price_inv_cur il.price_subtotal - il.quantity * standard_price_inv_cur
margin_comp_cur = inv.currency_id.with_context( margin_comp_cur = inv.currency_id._convert(
date=inv.date_invoice).compute( margin_inv_cur, company_currency, company, date)
margin_inv_cur, inv.company_id.currency_id)
if il.price_subtotal: if il.price_subtotal:
margin_rate = 100 * margin_inv_cur / il.price_subtotal margin_rate = 100 * margin_inv_cur / il.price_subtotal
# for a refund, margin should be negative # for a refund, margin should be negative
@@ -83,13 +84,12 @@ class AccountInvoiceLine(models.Model):
std_price = pp.standard_price std_price = pp.standard_price
inv_uom_id = vals.get('uom_id') inv_uom_id = vals.get('uom_id')
if inv_uom_id and inv_uom_id != pp.uom_id.id: if inv_uom_id and inv_uom_id != pp.uom_id.id:
inv_uom = self.env['product.uom'].browse(inv_uom_id) inv_uom = self.env['uom.uom'].browse(inv_uom_id)
std_price = pp.uom_id._compute_price( std_price = pp.uom_id._compute_price(
std_price, inv_uom) std_price, inv_uom)
vals['standard_price_company_currency'] = std_price vals['standard_price_company_currency'] = std_price
return super(AccountInvoiceLine, self).create(vals) return super(AccountInvoiceLine, self).create(vals)
@api.multi
def write(self, vals): def write(self, vals):
if not vals: if not vals:
vals = {} vals = {}
@@ -106,7 +106,7 @@ class AccountInvoiceLine(models.Model):
# uom_id is NOT a required field # uom_id is NOT a required field
if 'uom_id' in vals: if 'uom_id' in vals:
if vals.get('uom_id'): if vals.get('uom_id'):
inv_uom = self.env['product.uom'].browse( inv_uom = self.env['uom.uom'].browse(
vals['uom_id']) vals['uom_id'])
else: else:
inv_uom = False inv_uom = False
@@ -127,11 +127,11 @@ class AccountInvoice(models.Model):
margin_invoice_currency = fields.Monetary( margin_invoice_currency = fields.Monetary(
string='Margin in Invoice Currency', string='Margin in Invoice Currency',
readonly=True, compute='_compute_margin', store=True, compute='_compute_margin', store=True, readonly=True,
currency_field='currency_id') currency_field='currency_id')
margin_company_currency = fields.Monetary( margin_company_currency = fields.Monetary(
string='Margin in Company Currency', string='Margin in Company Currency',
readonly=True, compute='_compute_margin', store=True, compute='_compute_margin', store=True, readonly=True,
currency_field='company_currency_id') currency_field='company_currency_id')
@api.depends( @api.depends(
@@ -139,12 +139,14 @@ class AccountInvoice(models.Model):
'invoice_line_ids.margin_invoice_currency', 'invoice_line_ids.margin_invoice_currency',
'invoice_line_ids.margin_company_currency') 'invoice_line_ids.margin_company_currency')
def _compute_margin(self): def _compute_margin(self):
for inv in self: res = self.env['account.invoice.line'].read_group(
margin_inv_cur = 0.0 [('invoice_id', 'in', self.ids)],
margin_comp_cur = 0.0 ['invoice_id', 'margin_invoice_currency',
if inv.type in ('out_invoice', 'out_refund'): 'margin_company_currency'],
for il in inv.invoice_line_ids: ['invoice_id'])
margin_inv_cur += il.margin_invoice_currency for re in res:
margin_comp_cur += il.margin_company_currency if re['invoice_id']:
inv.margin_invoice_currency = margin_inv_cur inv = self.browse(re['invoice_id'][0])
inv.margin_company_currency = margin_comp_cur if inv.type in ('out_invoice', 'out_refund'):
inv.margin_invoice_currency = re['margin_invoice_currency']
inv.margin_company_currency = re['margin_company_currency']

View File

@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*- # Copyright 2018-2019 Akretion France (http://www.akretion.com)
# Copyright 2018 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api from odoo import api, fields, models
class AccountInvoiceReport(models.Model): class AccountInvoiceReport(models.Model):
@@ -19,8 +18,8 @@ class AccountInvoiceReport(models.Model):
'account_id', 'amount_total_company_signed', 'account_id', 'amount_total_company_signed',
'commercial_partner_id', 'company_id', 'commercial_partner_id', 'company_id',
'currency_id', 'date_due', 'date_invoice', 'fiscal_position_id', 'currency_id', 'date_due', 'date_invoice', 'fiscal_position_id',
'journal_id', 'partner_bank_id', 'partner_id', 'payment_term_id', 'journal_id', 'number', 'partner_bank_id', 'partner_id',
'residual', 'state', 'type', 'user_id', 'payment_term_id', 'residual', 'state', 'type', 'user_id',
], ],
'account.invoice.line': [ 'account.invoice.line': [
'account_id', 'invoice_id', 'price_subtotal', 'product_id', 'account_id', 'invoice_id', 'price_subtotal', 'product_id',
@@ -29,26 +28,25 @@ class AccountInvoiceReport(models.Model):
], ],
'product.product': ['product_tmpl_id'], 'product.product': ['product_tmpl_id'],
'product.template': ['categ_id'], 'product.template': ['categ_id'],
'product.uom': ['category_id', 'factor', 'name', 'uom_type'], 'uom.uom': ['category_id', 'factor', 'name', 'uom_type'],
'res.currency.rate': ['currency_id', 'name'], 'res.currency.rate': ['currency_id', 'name'],
'res.partner': ['country_id'], 'res.partner': ['country_id'],
} }
@api.depends('currency_id', 'date', 'margin') @api.depends('currency_id', 'date', 'margin')
def _compute_user_currency_margin(self): def _compute_user_currency_margin(self):
context = dict(self._context or {}) user_currency = self.env.user.company_id.currency_id
user_currency_id = self.env.user.company_id.currency_id currency_rate = self.env['res.currency.rate'].search([
currency_rate_id = self.env['res.currency.rate'].search([
('rate', '=', 1), ('rate', '=', 1),
'|', '|',
('company_id', '=', self.env.user.company_id.id), ('company_id', '=', self.env.user.company_id.id),
('company_id', '=', False)], limit=1) ('company_id', '=', False)], limit=1)
base_currency_id = currency_rate_id.currency_id base_currency = currency_rate.currency_id
ctx = context.copy()
for record in self: for record in self:
ctx['date'] = record.date date = record.date or fields.Date.today()
record.user_currency_margin = base_currency_id.with_context( company = record.company_id
ctx).compute(record.margin, user_currency_id) record.user_currency_margin = base_currency._convert(
record.margin, user_currency, company, date)
# TODO check for refunds # TODO check for refunds
def _sub_select(self): def _sub_select(self):

View File

@@ -12,22 +12,24 @@
<field name="model">account.invoice.line</field> <field name="model">account.invoice.line</field>
<field name="inherit_id" ref="account.view_invoice_line_form"/> <field name="inherit_id" ref="account.view_invoice_line_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="company_id" position="after"> <xpath expr="//field[@name='analytic_tag_ids']/.." position="inside">
<field name="standard_price_company_currency" <field name="standard_price_company_currency"
string="Cost Price in Comp. Cur."
groups="base.group_no_one"/> groups="base.group_no_one"/>
<field name="standard_price_invoice_currency" <field name="standard_price_invoice_currency"
widget="monetary" string="Cost Price in Inv. Cur."
options="{'currency_field': 'currency_id'}"
groups="base.group_no_one"/> groups="base.group_no_one"/>
<field name="margin_invoice_currency" <field name="margin_invoice_currency"
string="Margin in Inv. Cur."
groups="base.group_no_one"/> groups="base.group_no_one"/>
<field name="margin_company_currency" <field name="margin_company_currency"
string="Margin in Comp. Cur."
groups="base.group_no_one"/> groups="base.group_no_one"/>
<label for="margin_rate" groups="base.group_no_one"/> <label for="margin_rate" groups="base.group_no_one"/>
<div name="margin_rate" groups="base.group_no_one"> <div name="margin_rate" groups="base.group_no_one">
<field name="margin_rate" class="oe_inline"/> % <field name="margin_rate" class="oe_inline"/> %
</div> </div>
</field> </xpath>
</field> </field>
</record> </record>
@@ -38,9 +40,9 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="move_id" position="after"> <field name="move_id" position="after">
<field name="margin_invoice_currency" <field name="margin_invoice_currency"
string="Margin" groups="base.group_no_one"/> string="Margin in Inv. Cur." groups="base.group_no_one"/>
<field name="margin_company_currency" <field name="margin_company_currency"
groups="base.group_no_one"/> string="Margin in Comp. Cur." groups="base.group_no_one"/>
</field> </field>
</field> </field>
</record> </record>

View File

@@ -30,6 +30,10 @@
<field name="date_approve" position="after"> <field name="date_approve" position="after">
<field name="origin"/> <field name="origin"/>
</field> </field>
<!-- Remove once this PR is merged https://github.com/odoo/odoo/pull/35073 -->
<xpath expr="//field[@name='order_line']/form//field[@name='analytic_tag_ids']" position="attributes">
<attribute name="groups">analytic.group_analytic_tags</attribute>
</xpath>
</field> </field>
</record> </record>

View File

@@ -1,3 +1 @@
# -*- coding: utf-8 -*-
from . import stock_inventory from . import stock_inventory

View File

@@ -1,12 +1,11 @@
# -*- coding: utf-8 -*- # Copyright 2016-2019 Akretion France (http://www.akretion.com)
# © 2016-2018 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{ {
'name': 'Stock Inventory Validation ODS', 'name': 'Stock Inventory Validation ODS',
'version': '10.0.1.0.0', 'version': '12.0.1.0.0',
'category': 'Tools', 'category': 'Tools',
'license': 'AGPL-3', 'license': 'AGPL-3',
'summary': 'Adds a Py3o ODS report on inventories', 'summary': 'Adds a Py3o ODS report on inventories',

View File

@@ -2,7 +2,7 @@
<odoo> <odoo>
<record id="stock_inventory_valuation_ods" model="ir.actions.report.xml"> <record id="stock_inventory_valuation_ods" model="ir.actions.report">
<field name="name">Inventory Valuation per Location (ODS)</field> <field name="name">Inventory Valuation per Location (ODS)</field>
<field name="model">stock.inventory</field> <field name="model">stock.inventory</field>
<field name="report_name">stock.inventory.ods</field> <field name="report_name">stock.inventory.ods</field>
@@ -10,16 +10,11 @@
<field name="py3o_filetype">ods</field> <field name="py3o_filetype">ods</field>
<field name="module">stock_inventory_valuation_ods</field> <field name="module">stock_inventory_valuation_ods</field>
<field name="py3o_template_fallback">inventory.ods</field> <field name="py3o_template_fallback">inventory.ods</field>
<field name="binding_type">report</field>
<field name="binding_model_id" ref="stock.model_stock_inventory"/>
</record> </record>
<record id="stock_inventory_valuation_ods_button" model="ir.values"> <record id="stock_inventory_valuation_grouped_ods" model="ir.actions.report">
<field name="name">Inventory Valuation per Location ODS</field>
<field name="model">stock.inventory</field>
<field name="key2">client_print_multi</field>
<field name="value" eval="'ir.actions.report.xml,%d'%stock_inventory_valuation_ods"/>
</record>
<record id="stock_inventory_valuation_grouped_ods" model="ir.actions.report.xml">
<field name="name">Inventory Valuation (ODS)</field> <field name="name">Inventory Valuation (ODS)</field>
<field name="model">stock.inventory</field> <field name="model">stock.inventory</field>
<field name="report_name">stock.inventory.grouped.ods</field> <field name="report_name">stock.inventory.grouped.ods</field>
@@ -27,13 +22,9 @@
<field name="py3o_filetype">ods</field> <field name="py3o_filetype">ods</field>
<field name="module">stock_inventory_valuation_ods</field> <field name="module">stock_inventory_valuation_ods</field>
<field name="py3o_template_fallback">inventory_grouped.ods</field> <field name="py3o_template_fallback">inventory_grouped.ods</field>
<field name="binding_type">report</field>
<field name="binding_model_id" ref="stock.model_stock_inventory"/>
</record> </record>
<record id="stock_inventory_valuation_grouped_ods_button" model="ir.values">
<field name="name">Inventory Valuation ODS</field>
<field name="model">stock.inventory</field>
<field name="key2">client_print_multi</field>
<field name="value" eval="'ir.actions.report.xml,%d'%stock_inventory_valuation_grouped_ods"/>
</record>
</odoo> </odoo>

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # Copyright 2016-2019 Akretion France (http://www.akretion.com/)
# Copyright 2016-2018 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>) # @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models from odoo import models

View File

@@ -30,8 +30,8 @@
<xpath expr="//field[@name='move_ids_without_package']/tree/field[@name='location_id']" position="replace"/> <xpath expr="//field[@name='move_ids_without_package']/tree/field[@name='location_id']" position="replace"/>
<xpath expr="//field[@name='move_ids_without_package']/tree/field[@name='location_dest_id']" position="replace"/> <xpath expr="//field[@name='move_ids_without_package']/tree/field[@name='location_dest_id']" position="replace"/>
<xpath expr="//field[@name='move_ids_without_package']/tree/field[@name='product_id']" position="after"> <xpath expr="//field[@name='move_ids_without_package']/tree/field[@name='product_id']" position="after">
<field name="location_id" groups="stock.group_stock_multi_locations" readonly="1"/> <field name="location_id" groups="stock.group_stock_multi_locations"/>
<field name="location_dest_id" groups="stock.group_stock_multi_locations" readonly="1"/> <field name="location_dest_id" groups="stock.group_stock_multi_locations"/>
</xpath> </xpath>
<xpath expr="//field[@name='move_line_ids_without_package']/tree/field[@name='location_id']" position="attributes"> <xpath expr="//field[@name='move_line_ids_without_package']/tree/field[@name='location_id']" position="attributes">
<attribute name="attrs">{}</attribute> <attribute name="attrs">{}</attribute>