Fall 4433: Intercompany Rechnung

develop
Ahmed Aly 2017-12-06 16:20:04 +01:00
parent 102c8fd704
commit 291deedcc2
23 changed files with 923 additions and 0 deletions

View File

@ -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.

View File

@ -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

View File

@ -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',
],
}

View File

@ -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 ""

View File

@ -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 ""

View File

@ -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"

View File

@ -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

View File

@ -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()

View File

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

View File

@ -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)

View File

@ -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>

View File

@ -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">

View File

@ -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

View File

@ -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,
}

View File

@ -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

View File

@ -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')

View File

@ -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')

View File

@ -0,0 +1 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
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

View File

@ -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>

View File

@ -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>

View File

@ -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'
}

View File

@ -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'
}