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:
@@ -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
|
||||||
|
|||||||
@@ -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': """
|
||||||
|
|||||||
@@ -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']
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from . import stock_inventory
|
from . import stock_inventory
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user