Fall 4433: Intercompany Rechnung
parent
102c8fd704
commit
291deedcc2
|
|
@ -0,0 +1,70 @@
|
|||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
|
||||
=================================
|
||||
Product Tax Multi Company Default
|
||||
=================================
|
||||
|
||||
This module sets the default company taxes for all the existing companies when
|
||||
a product is created. It also adds a button to set all the taxes from other
|
||||
companies matching them by tax code.
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
#. As obvious, you need to have several companies.
|
||||
#. Go to Accounting > Configuration > Settings
|
||||
#. Select the proper company (if you are admin or a user with several companies
|
||||
access), or keep the current one (for a regular user).
|
||||
#. On Invoicing & Payments section, set fields "Default Sale Tax" and "Default
|
||||
Purchase Tax".
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
To use this module, you need to:
|
||||
|
||||
#. Go to Sales > Sales > Products.
|
||||
#. Create a new product and save it.
|
||||
#. Switching user company (or being as admin or user with several companies
|
||||
access), you will see that the product has the default taxes for all the
|
||||
companies.
|
||||
|
||||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
|
||||
:alt: Try me on Runbot
|
||||
:target: https://runbot.odoo-community.org/runbot/133/9.0
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues
|
||||
<https://github.com/OCA/multi-company/issues>`_. In case of trouble, please
|
||||
check there if your issue has already been reported. If you spotted it first,
|
||||
help us smashing it by providing a detailed and welcomed feedback.
|
||||
|
||||
Images
|
||||
------
|
||||
|
||||
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Carlos Dauden - Tecnativa <carlos.dauden@tecnativa.com>
|
||||
* Pedro M. Baeza <pedro.baeza@tecnativa.com>
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
.. image:: https://odoo-community.org/logo.png
|
||||
:alt: Odoo Community Association
|
||||
:target: https://odoo-community.org
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.
|
||||
|
||||
To contribute to this module, please visit https://odoo-community.org.
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Carlos Dauden - Tecnativa <carlos.dauden@tecnativa.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import models
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Carlos Dauden - Tecnativa <carlos.dauden@tecnativa.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
# noinspection PyStatementEffect
|
||||
{
|
||||
'name': 'Product Tax Multi Company Default',
|
||||
'version': '11.0.1.0.0',
|
||||
'category': 'Account',
|
||||
'website': 'https://www.tecnativa.com',
|
||||
'author': 'Tecnativa, '
|
||||
'Odoo Community Association (OCA)',
|
||||
'license': 'AGPL-3',
|
||||
'depends': [
|
||||
'account',
|
||||
'product',
|
||||
],
|
||||
'data': [
|
||||
'views/product_template_view.xml',
|
||||
],
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * product_tax_multicompany_default
|
||||
#
|
||||
# Translators:
|
||||
# Rudolf Schnapka <rs@techno-flex.de>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 9.0c\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-08-17 03:16+0000\n"
|
||||
"PO-Revision-Date: 2017-08-17 03:16+0000\n"
|
||||
"Last-Translator: Rudolf Schnapka <rs@techno-flex.de>, 2017\n"
|
||||
"Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Language: de\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_company_ids
|
||||
msgid "Companies"
|
||||
msgstr "Unternehmen"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_taxes_id
|
||||
msgid "Customer Taxes"
|
||||
msgstr ""
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_property_account_expense_id
|
||||
msgid "Expense Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_property_account_income_id
|
||||
msgid "Income Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model,name:product_tax_multicompany_default.model_product_product
|
||||
msgid "Product"
|
||||
msgstr ""
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model,name:product_tax_multicompany_default.model_product_template
|
||||
msgid "Product Template"
|
||||
msgstr "Produktvorlage"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.ui.view,arch_db:product_tax_multicompany_default.product_template_form_view
|
||||
msgid "Propagate Taxes"
|
||||
msgstr ""
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,help:product_tax_multicompany_default.field_product_product_property_account_expense_id
|
||||
msgid ""
|
||||
"This account will be used for invoices instead of the default one to value "
|
||||
"expenses for the current product."
|
||||
msgstr ""
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,help:product_tax_multicompany_default.field_product_product_property_account_income_id
|
||||
msgid ""
|
||||
"This account will be used for invoices instead of the default one to value "
|
||||
"sales for the current product."
|
||||
msgstr ""
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_supplier_taxes_id
|
||||
msgid "Vendor Taxes"
|
||||
msgstr ""
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * product_tax_multicompany_default
|
||||
#
|
||||
# Translators:
|
||||
# OCA Transbot <transbot@odoo-community.org>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 9.0c\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-08-17 03:16+0000\n"
|
||||
"PO-Revision-Date: 2017-08-17 03:16+0000\n"
|
||||
"Last-Translator: OCA Transbot <transbot@odoo-community.org>, 2017\n"
|
||||
"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Language: es\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_company_ids
|
||||
msgid "Companies"
|
||||
msgstr "Compañías"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_taxes_id
|
||||
msgid "Customer Taxes"
|
||||
msgstr ""
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_property_account_expense_id
|
||||
msgid "Expense Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_property_account_income_id
|
||||
msgid "Income Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model,name:product_tax_multicompany_default.model_product_product
|
||||
msgid "Product"
|
||||
msgstr ""
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model,name:product_tax_multicompany_default.model_product_template
|
||||
msgid "Product Template"
|
||||
msgstr "Plantilla producto"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.ui.view,arch_db:product_tax_multicompany_default.product_template_form_view
|
||||
msgid "Propagate Taxes"
|
||||
msgstr "Propagar impuestos"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,help:product_tax_multicompany_default.field_product_product_property_account_expense_id
|
||||
msgid ""
|
||||
"This account will be used for invoices instead of the default one to value "
|
||||
"expenses for the current product."
|
||||
msgstr ""
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,help:product_tax_multicompany_default.field_product_product_property_account_income_id
|
||||
msgid ""
|
||||
"This account will be used for invoices instead of the default one to value "
|
||||
"sales for the current product."
|
||||
msgstr ""
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_supplier_taxes_id
|
||||
msgid "Vendor Taxes"
|
||||
msgstr ""
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * product_tax_multicompany_default
|
||||
#
|
||||
# Translators:
|
||||
# OCA Transbot <transbot@odoo-community.org>, 2017
|
||||
# Quentin THEURET <odoo@kerpeo.com>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 9.0c\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-08-19 05:30+0000\n"
|
||||
"PO-Revision-Date: 2017-08-19 05:30+0000\n"
|
||||
"Last-Translator: Quentin THEURET <odoo@kerpeo.com>, 2017\n"
|
||||
"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Language: fr\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_company_ids
|
||||
msgid "Companies"
|
||||
msgstr "Sociétés"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_taxes_id
|
||||
msgid "Customer Taxes"
|
||||
msgstr "Taxes client"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_property_account_expense_id
|
||||
msgid "Expense Account"
|
||||
msgstr "Compte de dépense"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_property_account_income_id
|
||||
msgid "Income Account"
|
||||
msgstr "Compte de revenu"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model,name:product_tax_multicompany_default.model_product_product
|
||||
msgid "Product"
|
||||
msgstr "Produit"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model,name:product_tax_multicompany_default.model_product_template
|
||||
msgid "Product Template"
|
||||
msgstr "Template de produit"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.ui.view,arch_db:product_tax_multicompany_default.product_template_form_view
|
||||
msgid "Propagate Taxes"
|
||||
msgstr "Propager les taxes"
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,help:product_tax_multicompany_default.field_product_product_property_account_expense_id
|
||||
msgid ""
|
||||
"This account will be used for invoices instead of the default one to value "
|
||||
"expenses for the current product."
|
||||
msgstr ""
|
||||
"Ce compte sera utilisé pour les factures à la place de celui par défaut pour"
|
||||
" évaluer les dépenses pour le produit courant."
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,help:product_tax_multicompany_default.field_product_product_property_account_income_id
|
||||
msgid ""
|
||||
"This account will be used for invoices instead of the default one to value "
|
||||
"sales for the current product."
|
||||
msgstr ""
|
||||
"Ce compte sera utilisé pour les factures à la place de celui par défaut pour"
|
||||
" évaluer les ventes du produit courant."
|
||||
|
||||
#. module: product_tax_multicompany_default
|
||||
#: model:ir.model.fields,field_description:product_tax_multicompany_default.field_product_product_supplier_taxes_id
|
||||
msgid "Vendor Taxes"
|
||||
msgstr "Taxes sur la vente"
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Carlos Dauden - Tecnativa <carlos.dauden@tecnativa.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import product
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Carlos Dauden - Tecnativa <carlos.dauden@tecnativa.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class ProductTemplate(models.Model):
|
||||
_inherit = 'product.template'
|
||||
|
||||
def taxes_by_company(self, field, company_id, match_tax_ids=None):
|
||||
taxes_ids = []
|
||||
if match_tax_ids is None:
|
||||
taxes_ids = self.env['ir.values'].get_default(
|
||||
'product.template', field, company_id=company_id)
|
||||
# If None: return default taxes if []: return empty list
|
||||
if not match_tax_ids:
|
||||
return isinstance(taxes_ids, list) and taxes_ids or []
|
||||
AccountTax = self.env['account.tax']
|
||||
for tax in AccountTax.browse(match_tax_ids):
|
||||
taxes_ids.extend(AccountTax.search([
|
||||
('name', '=', tax.name),
|
||||
('company_id', '=', company_id)
|
||||
]).ids)
|
||||
return taxes_ids
|
||||
|
||||
@api.multi
|
||||
def set_multicompany_taxes(self):
|
||||
self.ensure_one()
|
||||
customer_tax_ids = self.taxes_id.ids
|
||||
supplier_tax_ids = self.supplier_taxes_id.ids
|
||||
company_id = self.env.user.company_id.id
|
||||
obj = self.sudo()
|
||||
default_customer_tax_ids = obj.taxes_by_company(
|
||||
'taxes_id', company_id)
|
||||
default_supplier_tax_ids = obj.taxes_by_company(
|
||||
'supplier_taxes_id', company_id)
|
||||
# Use list() to copy list
|
||||
match_customer_tax_ids = (
|
||||
default_customer_tax_ids != customer_tax_ids and
|
||||
list(customer_tax_ids) or None)
|
||||
match_suplier_tax_ids = (
|
||||
default_supplier_tax_ids != supplier_tax_ids and
|
||||
list(supplier_tax_ids) or None)
|
||||
for company in obj.env['res.company'].search(
|
||||
[('id', '!=', company_id)]):
|
||||
customer_tax_ids.extend(obj.taxes_by_company(
|
||||
'taxes_id', company.id, match_customer_tax_ids))
|
||||
supplier_tax_ids.extend(obj.taxes_by_company(
|
||||
'supplier_taxes_id', company.id, match_suplier_tax_ids))
|
||||
self.write({
|
||||
'taxes_id': [(6, 0, customer_tax_ids)],
|
||||
'supplier_taxes_id': [(6, 0, supplier_tax_ids)],
|
||||
})
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
res = super(ProductTemplate, self).create(vals)
|
||||
res.set_multicompany_taxes()
|
||||
return res
|
||||
|
||||
|
||||
class ProductProduct(models.Model):
|
||||
_inherit = 'product.product'
|
||||
|
||||
@api.multi
|
||||
def set_multicompany_taxes(self):
|
||||
self.product_tmpl_id.set_multicompany_taxes()
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import test_product_tax_multicompany
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Carlos Dauden - Tecnativa <carlos.dauden@tecnativa.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp.tests.common import SavepointCase
|
||||
|
||||
|
||||
class TestsProductTaxMulticompany(SavepointCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestsProductTaxMulticompany, cls).setUpClass()
|
||||
cls.company_1 = cls.env['res.company'].create(
|
||||
{'name': 'Test company 1'})
|
||||
cls.company_2 = cls.env['res.company'].create(
|
||||
{'name': 'Test company 2'})
|
||||
group_sale_manager = cls.env.ref('base.group_sale_manager')
|
||||
group_account_manager = cls.env.ref('account.group_account_manager')
|
||||
ResUsers = cls.env['res.users']
|
||||
cls.user_1 = ResUsers.create(
|
||||
{'name': 'User not admin',
|
||||
'login': 'user_1',
|
||||
'email': 'test@test.com',
|
||||
'groups_id': [(6, 0, (
|
||||
group_sale_manager | group_account_manager).ids)],
|
||||
'company_id': cls.company_1.id,
|
||||
'company_ids': [(6, 0, cls.company_1.ids)]})
|
||||
cls.user_2 = ResUsers.create(
|
||||
{'name': 'User not admin',
|
||||
'login': 'user_2',
|
||||
'email': 'test@test.com',
|
||||
'groups_id': [(6, 0, (
|
||||
group_sale_manager | group_account_manager).ids)],
|
||||
'company_id': cls.company_2.id,
|
||||
'company_ids': [(6, 0, cls.company_2.ids)]})
|
||||
AccountTax = cls.env['account.tax']
|
||||
tax_vals = {
|
||||
'name': 'Test Customer Tax 10%',
|
||||
'amount': 10.0,
|
||||
'amount_type': 'percent',
|
||||
'type_tax_use': 'sale',
|
||||
}
|
||||
cls.tax_10_cc1 = AccountTax.sudo(cls.user_1.id).create(tax_vals)
|
||||
cls.tax_10_cc2 = AccountTax.sudo(cls.user_2.id).create(tax_vals)
|
||||
tax_vals.update({
|
||||
'name': 'Test Customer Tax 20%',
|
||||
'amount': 20.0,
|
||||
})
|
||||
cls.tax_20_cc1 = AccountTax.sudo(cls.user_1.id).create(tax_vals)
|
||||
cls.tax_20_cc2 = AccountTax.sudo(cls.user_2.id).create(tax_vals)
|
||||
tax_vals.update({
|
||||
'name': 'Test Supplier Tax 10%',
|
||||
'amount': 10.0,
|
||||
'type_tax_use': 'purchase',
|
||||
})
|
||||
cls.tax_10_sc1 = AccountTax.sudo(cls.user_1.id).create(tax_vals)
|
||||
cls.tax_10_sc2 = AccountTax.sudo(cls.user_2.id).create(tax_vals)
|
||||
tax_vals.update({
|
||||
'name': 'Test Supplier Tax 20%',
|
||||
'amount': 20.0,
|
||||
})
|
||||
cls.tax_20_sc1 = AccountTax.sudo(cls.user_1.id).create(tax_vals)
|
||||
cls.tax_20_sc2 = AccountTax.sudo(cls.user_2.id).create(tax_vals)
|
||||
IrValues = cls.env['ir.values']
|
||||
IrValues.set_default(
|
||||
'product.template', "taxes_id", [cls.tax_10_cc1.id],
|
||||
for_all_users=True, company_id=cls.company_1.id)
|
||||
IrValues.set_default(
|
||||
'product.template', "supplier_taxes_id", [cls.tax_10_sc1.id],
|
||||
for_all_users=True, company_id=cls.company_1.id)
|
||||
IrValues.set_default(
|
||||
'product.template', "taxes_id", [cls.tax_20_cc2.id],
|
||||
for_all_users=True, company_id=cls.company_2.id)
|
||||
IrValues.set_default(
|
||||
'product.template', "supplier_taxes_id", [cls.tax_20_sc2.id],
|
||||
for_all_users=True, company_id=cls.company_2.id)
|
||||
|
||||
def test_multicompany_default_tax(self):
|
||||
product = self.env['product.product'].sudo(self.user_1.id).create({
|
||||
'name': 'Test Product',
|
||||
'company_id': False,
|
||||
})
|
||||
product = product.sudo()
|
||||
self.assertIn(self.tax_10_cc1, product.taxes_id)
|
||||
self.assertIn(self.tax_20_cc2, product.taxes_id)
|
||||
self.assertIn(self.tax_10_sc1, product.supplier_taxes_id)
|
||||
self.assertIn(self.tax_20_sc2, product.supplier_taxes_id)
|
||||
|
||||
def test_not_default_tax_if_set(self):
|
||||
product = self.env['product.product'].sudo(self.user_1.id).create({
|
||||
'name': 'Test Product',
|
||||
'taxes_id': [(6, 0, self.tax_20_cc1.ids)],
|
||||
'supplier_taxes_id': [(6, 0, self.tax_20_sc1.ids)],
|
||||
'company_id': False,
|
||||
})
|
||||
product = product.sudo()
|
||||
self.assertNotIn(self.tax_10_cc1, product.taxes_id)
|
||||
self.assertNotIn(self.tax_10_sc1, product.supplier_taxes_id)
|
||||
|
||||
def test_default_tax_if_set_match(self):
|
||||
product = self.env['product.product'].sudo(self.user_2.id).create({
|
||||
'name': 'Test Product',
|
||||
'taxes_id': [(6, 0, self.tax_20_cc2.ids)],
|
||||
'supplier_taxes_id': [(6, 0, self.tax_20_sc2.ids)],
|
||||
'company_id': False,
|
||||
})
|
||||
product = product.sudo()
|
||||
self.assertIn(self.tax_10_cc1, product.taxes_id)
|
||||
self.assertIn(self.tax_10_sc1, product.supplier_taxes_id)
|
||||
|
||||
def test_tax_not_default_set_match(self):
|
||||
IrValues = self.env['ir.values']
|
||||
IrValues.set_default(
|
||||
'product.template', "taxes_id", [self.tax_20_cc1.id],
|
||||
for_all_users=True, company_id=self.company_1.id)
|
||||
IrValues.set_default(
|
||||
'product.template', "supplier_taxes_id", [self.tax_20_sc1.id],
|
||||
for_all_users=True, company_id=self.company_1.id)
|
||||
|
||||
product = self.env['product.product'].sudo(self.user_1.id).create({
|
||||
'name': 'Test Product',
|
||||
'taxes_id': [(6, 0, self.tax_10_cc1.ids)],
|
||||
'supplier_taxes_id': [(6, 0, self.tax_10_sc1.ids)],
|
||||
'company_id': False,
|
||||
})
|
||||
product = product.sudo()
|
||||
self.assertIn(self.tax_10_cc2, product.taxes_id)
|
||||
self.assertIn(self.tax_10_sc2, product.supplier_taxes_id)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2017 Carlos Dauden - Tecnativa <carlos.dauden@tecnativa.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
|
||||
<odoo>
|
||||
|
||||
<record model="ir.ui.view" id="product_template_form_view">
|
||||
<field name="name">Product template form (multi-company tax button)</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="account.product_template_form_view" />
|
||||
<field name="arch" type="xml">
|
||||
<field name ="taxes_id" position="after">
|
||||
<button name="set_multicompany_taxes"
|
||||
string="Propagate Taxes"
|
||||
groups="account.group_account_user"
|
||||
type="object"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
<field name="country_id" search="[('code','=','AT')]"/>
|
||||
<field name="vat">ATU17860303</field>
|
||||
<field name="vat_check_vies" eval="False"/>
|
||||
<field name="supplier" eval="True"/>
|
||||
</record>
|
||||
|
||||
<function id="set_company_logo" model="res.company" name="set_company_logo">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# datenpol gmbh
|
||||
# Copyright (C) 2013-TODAY datenpol gmbh (<http://www.datenpol.at/>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from . import models
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# datenpol gmbh
|
||||
# Copyright (C) 2013-TODAY datenpol gmbh (<http://www.datenpol.at/>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
# noinspection PyStatementEffect
|
||||
{
|
||||
'name': 'Inter-Company Invoicing',
|
||||
'category': 'Stock',
|
||||
'version': '11.0.1.0.0',
|
||||
'description': """Inter-Company Invoicing""",
|
||||
'author': 'datenpol gmbh',
|
||||
'website': 'http://www.datenpol.at/',
|
||||
'depends': [
|
||||
'base',
|
||||
'account'
|
||||
],
|
||||
'data': [
|
||||
'views/account_views.xml',
|
||||
'views/res_company_views.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 20014-2016 datenpol gmbh (<http://www.datenpol.at/>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from . import res_company
|
||||
from . import account
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# datenpol gmbh
|
||||
# Copyright (C) 2013-TODAY datenpol gmbh (<http://www.datenpol.at/>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
@api.model
|
||||
def default_inter_company_supplier_isset(self):
|
||||
return bool(self.env.user.company_id.inter_company_supplier_id.id)
|
||||
|
||||
inter_company_supplier_isset = fields.Boolean(compute='_compute_inter_company_supplier_isset',
|
||||
default=default_inter_company_supplier_isset)
|
||||
|
||||
reimburse_invoice_id = fields.Many2one(comodel_name='account.invoice', string='Weiterverrechnung')
|
||||
charge_further = fields.Boolean(string='Weiterverrechnen', compute='_compute_charge_further', store=True,
|
||||
help='Ist gesetzt, wenn das WV-Flag von mindestens einer Zeile gesetzt ist')
|
||||
|
||||
@api.multi
|
||||
def _compute_inter_company_supplier_isset(self):
|
||||
for record in self:
|
||||
record.inter_company_supplier_isset = bool(self.env.user.company_id.inter_company_supplier_id.id)
|
||||
|
||||
@api.multi
|
||||
@api.depends('invoice_line_ids.reimbursement')
|
||||
def _compute_charge_further(self):
|
||||
for record in self:
|
||||
record.charge_further = False
|
||||
for line in record.invoice_line_ids:
|
||||
if line.reimbursement:
|
||||
record.charge_further = True
|
||||
break
|
||||
|
||||
@api.multi
|
||||
def action_set_all_wv_flag(self):
|
||||
for record in self:
|
||||
for line in record.invoice_line_ids:
|
||||
line.reimbursement = True
|
||||
|
||||
@api.multi
|
||||
def action_unset_all_wv_flag(self):
|
||||
for record in self:
|
||||
for line in record.invoice_line_ids:
|
||||
line.reimbursement = False
|
||||
|
||||
@api.multi
|
||||
def reimburse_invoice(self):
|
||||
for record in self:
|
||||
if not record.charge_further:
|
||||
raise ValidationError(_('Sie müssen mindestens eine Position mit WV markieren.'))
|
||||
if record.charge_further:
|
||||
intercompany_admin_id = record.company_id.admin_user_id
|
||||
in_invoice_vals = record._prepare_er_invoice_data()
|
||||
invoice_id = self.env['account.invoice'].sudo(intercompany_admin_id).create(
|
||||
in_invoice_vals)
|
||||
record.reimburse_invoice_id = invoice_id.id
|
||||
for line in record.invoice_line_ids:
|
||||
if line.reimbursement:
|
||||
in_line_vals = record._prepare_er_invoice_line_data(line, invoice_id)
|
||||
self.env['account.invoice.line'].sudo(intercompany_admin_id).create(in_line_vals)
|
||||
invoice_id.compute_taxes()
|
||||
|
||||
@api.multi
|
||||
def _prepare_er_invoice_data(self):
|
||||
self.ensure_one()
|
||||
|
||||
journal = self.env['account.journal'].sudo(self.company_id.admin_user_id).search(
|
||||
[('type', '=', 'purchase'), ('company_id', '=', self.company_id.id)], limit=1)
|
||||
vals = {
|
||||
'company_id': self.company_id.id,
|
||||
'type': 'in_invoice',
|
||||
'partner_id': self.company_id.inter_company_supplier_id.partner_id.id,
|
||||
'origin': "Weiterverrechnung von " + self.number,
|
||||
'journal_id': journal.id,
|
||||
'currency_id': self.currency_id and self.currency_id.id,
|
||||
}
|
||||
inv = self.env['account.invoice'].with_context(company_id=self.company_id.id).sudo(
|
||||
self.company_id.admin_user_id).new(vals)
|
||||
inv._onchange_partner_id()
|
||||
new_vals = {k: v or False for k, v in dict(inv._cache).items()}
|
||||
return inv._convert_to_write(new_vals)
|
||||
|
||||
@api.model
|
||||
def _prepare_er_invoice_line_data(self, line, invoice_id):
|
||||
vals = {
|
||||
'name': line.name,
|
||||
'price_unit': line.price_unit * (line.invoice_id.company_id.percentage_billing / 100),
|
||||
'quantity': line.quantity,
|
||||
'discount': line.discount,
|
||||
'product_id': line.product_id.id or False,
|
||||
'uom_id': line.uom_id.id or False,
|
||||
'sequence': line.sequence,
|
||||
'invoice_id': invoice_id.id
|
||||
}
|
||||
new_line = self.env['account.invoice.line'].with_context(company_id=line.invoice_id.company_id.id).sudo(
|
||||
line.invoice_id.company_id.admin_user_id).new(vals)
|
||||
new_line._onchange_product_id()
|
||||
new_line_vals = {k: v or False for k, v in dict(new_line._cache).items()}
|
||||
return new_line._convert_to_write(new_line_vals)
|
||||
|
||||
@api.multi
|
||||
def invoice_validate(self):
|
||||
res = super(AccountInvoice, self).invoice_validate()
|
||||
for record in self:
|
||||
if record.type == 'in_invoice' and record.partner_id.id == record.company_id.inter_company_supplier_id.partner_id.id:
|
||||
company_id = record.company_id.inter_company_supplier_id
|
||||
intercompany_admin_id = company_id.admin_user_id
|
||||
out_invoice_vals = record._prepare_ic_invoice_data()
|
||||
invoice_id = self.env['account.invoice'].sudo(intercompany_admin_id).create(
|
||||
out_invoice_vals)
|
||||
for line in record.invoice_line_ids:
|
||||
out_line_vals = record._prepare_ic_invoice_line_data(line, invoice_id)
|
||||
self.env['account.invoice.line'].sudo(intercompany_admin_id).create(out_line_vals)
|
||||
invoice_id.compute_taxes()
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def _prepare_ic_invoice_data(self):
|
||||
self.ensure_one()
|
||||
|
||||
journal = self.env['account.journal'].sudo(self.company_id.inter_company_supplier_id.admin_user_id).search(
|
||||
[('type', '=', 'sale'), ('company_id', '=', self.company_id.inter_company_supplier_id.id)], limit=1)
|
||||
vals = {
|
||||
'company_id': self.company_id.inter_company_supplier_id.id,
|
||||
'type': 'out_invoice',
|
||||
'partner_id': self.company_id.partner_id.id,
|
||||
'origin': self.origin,
|
||||
'journal_id': journal.id,
|
||||
'currency_id': self.currency_id and self.currency_id.id,
|
||||
}
|
||||
inv = self.env['account.invoice'].with_context(company_id=self.company_id.inter_company_supplier_id.id).sudo(
|
||||
self.company_id.inter_company_supplier_id.admin_user_id).new(vals)
|
||||
inv._onchange_partner_id()
|
||||
new_vals = {k: v or False for k, v in dict(inv._cache).items()}
|
||||
return inv._convert_to_write(new_vals)
|
||||
|
||||
@api.model
|
||||
def _prepare_ic_invoice_line_data(self, line, invoice_id):
|
||||
vals = {
|
||||
'name': line.name,
|
||||
'quantity': line.quantity,
|
||||
'discount': line.discount,
|
||||
'product_id': line.product_id.id or False,
|
||||
'uom_id': line.uom_id.id or False,
|
||||
'sequence': line.sequence,
|
||||
'invoice_id': invoice_id.id
|
||||
}
|
||||
admin_user = line.invoice_id.company_id.inter_company_supplier_id.admin_user_id
|
||||
company_id = line.invoice_id.company_id.inter_company_supplier_id.id
|
||||
new_line = self.env['account.invoice.line'].with_context(company_id=company_id).sudo(admin_user).new(vals)
|
||||
new_line._onchange_product_id()
|
||||
new_line.price_unit = line.price_unit
|
||||
new_line_vals = {k: v or False for k, v in dict(new_line._cache).items()}
|
||||
return new_line._convert_to_write(new_line_vals)
|
||||
|
||||
|
||||
class AccountInvoiceLine(models.Model):
|
||||
_inherit = 'account.invoice.line'
|
||||
|
||||
reimbursement = fields.Boolean(string='WV', help='Wenn Weiterverrechnung (WV) gesetzt ist, dann wird diese Zeile ' \
|
||||
'intern weiterverrechnet', )
|
||||
|
||||
inter_company_supplier_isset = fields.Boolean(related='invoice_id.inter_company_supplier_isset')
|
||||
|
||||
state = fields.Selection(related='invoice_id.state')
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# datenpol gmbh
|
||||
# Copyright (C) 2013-TODAY datenpol gmbh (<http://www.datenpol.at/>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from odoo import models, api, fields
|
||||
|
||||
|
||||
class Company(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
inter_company_supplier_id = fields.Many2one(comodel_name='res.company', string='Inter-Company Lieferant',
|
||||
help='Wenn gesetzt, dann wird eine Eingangsrechung von diesem ' \
|
||||
'Lieferant erstellt. Im Unternehmen des Lieferanten wird entsprechend eine Ausgangsrechnung erstellt')
|
||||
percentage_billing = fields.Float(string='Prozentsatz Weiterverrechnung',
|
||||
help='Wenn hier 70% hinterlegt ist, dann wird bei einer Weiterverrechnung eine Eingangsrechnung erstellt mit einem um 30% verminderten Preis erstellt')
|
||||
admin_user_id = fields.Many2one(comodel_name='res.users',
|
||||
help='Mit diesem User werden Inter-Company Rechnungen erstellt')
|
||||
|
|
@ -0,0 +1 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
|
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
|
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="account_invoice_form_view" model="ir.ui.view">
|
||||
<field name="name">account_invoice_form_view</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//button[@name='action_invoice_cancel']" position="after">
|
||||
<button name="reimburse_invoice" type="object"
|
||||
attrs="{'invisible': ['|', ('state', '=', 'draft'), '|', ('reimburse_invoice_id', '!=', False), '|', ('type', '!=', 'out_invoice'), ('charge_further', '=', False)]}"
|
||||
string="Weiterverrechnen" groups="account.group_account_invoice"/>
|
||||
</xpath>
|
||||
<field name="payment_term_id" position="after">
|
||||
<label for="charge_further"/>
|
||||
<div class="o_row" name="charge_further">
|
||||
<field name="charge_further"/>
|
||||
<button class="btn btn-primary" type="object" name="action_set_all_wv_flag" string="Setzen"/>
|
||||
<button class="btn btn-primary" type="object" name="action_unset_all_wv_flag" string="Löschen"/>
|
||||
</div>
|
||||
<field name="reimburse_invoice_id"/>
|
||||
</field>
|
||||
|
||||
<xpath expr="//field[@name='invoice_line_ids']/tree//field[@name='account_id']" position="before">
|
||||
<field name="inter_company_supplier_isset" invisible="1"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="reimbursement"
|
||||
attrs="{'invisible': [('inter_company_supplier_isset', '=', False)], 'readonly': [('state', '!=', 'draft')]}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_invoice_filter_search_view" model="ir.ui.view">
|
||||
<field name="name">account_invoice_filter_search_view</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.view_account_invoice_filter_inherit_invoices"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="filter[@name='draft']" position="before">
|
||||
<filter name="reimburse" string="Weiterverrechnen"
|
||||
domain="[('state', '!=', 'draft'), ('reimburse_invoice_id', '=', False), ('type', '=', 'out_invoice'), ('charge_further', '!=', False), ('inter_company_supplier_isset', '=', True)]"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="res_company_form_view" model="ir.ui.view">
|
||||
<field name="name">res_company_form_view</field>
|
||||
<field name="model">res.company</field>
|
||||
<field name="inherit_id" ref="base.view_company_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="parent_id" position="after">
|
||||
<field name="inter_company_supplier_id"/>
|
||||
<field name="percentage_billing"/>
|
||||
<field name="admin_user_id"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_reimburse_invoice" model="ir.actions.server">
|
||||
<field name="name">Intern Weiterverrechnen</field>
|
||||
<field name="model_id" ref="account.model_account_invoice"/>
|
||||
<field name="binding_model_id" ref="account.model_account_invoice"/>
|
||||
<field name="binding_type">action</field>
|
||||
<field name="state">code</field>9
|
||||
<field name="code">records.reimburse_invoice()</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -22,6 +22,7 @@ class ConfigGlaser(Config):
|
|||
'vat': 'ATU17860303',
|
||||
'vat_check_vies': True,
|
||||
'logo': '../ext/custom-addons/dp_custom/static/src/img/logo_glaser.png',
|
||||
'supplier': True,
|
||||
#'favicon_backend': '../ext/custom-addons/dp_custom/static/src/img/favicon.ico',
|
||||
#'favicon_backend_mimetype': 'image/x-icon'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ class ConfigTZA(Config):
|
|||
'vat': 'ATU 54619104',
|
||||
'vat_check_vies': True,
|
||||
'logo': '../ext/custom-addons/dp_custom/static/src/img/logo.png',
|
||||
'customer': True,
|
||||
#'favicon_backend': '../ext/custom-addons/dp_custom/static/src/img/favicon.ico',
|
||||
#'favicon_backend_mimetype': 'image/x-icon'
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue