mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[ADD] Partner Location Auto Create
This commit is contained in:
committed by
Cyril Gaudin
parent
ab621e0223
commit
fb70e9fad3
69
partner_location_auto_create/README.rst
Normal file
69
partner_location_auto_create/README.rst
Normal file
@@ -0,0 +1,69 @@
|
||||
.. 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
|
||||
|
||||
============================
|
||||
Partner Location Auto Create
|
||||
============================
|
||||
|
||||
This module allows to create locations automatically when creating a partner.
|
||||
One use case of this feature is to allow a company not only to manage the stocks
|
||||
in its own warehouses, but also the warehouses of its suppliers.
|
||||
For example, an hatchery manages farms. Each farm is a partner and has its own inventory.
|
||||
The hatchery doesn't own the farms but manages their stocks.
|
||||
|
||||
Whether the partner is a customer, a supplier or both, the proper locations will be created and
|
||||
the fields property_stock_customer and property_stock_supplier will be filled automatically.
|
||||
|
||||
The modules also adds a button on the partner form to view the related locations.
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
To install this module, you just need to select the module and ensure yourself dependencies are available.
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
* Add users to the group "Sales Pricelists" or "Purchase Pricelists" to view the stock location properties on the partner view.
|
||||
* In the company form, select the default customer and supplier locations. This will set the default parent locations for the partner locations.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
To use this module, you need to :
|
||||
|
||||
- Create a partner
|
||||
- Click on the locations button and add specific locations for the partner
|
||||
|
||||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
|
||||
:alt: Try me on Runbot
|
||||
:target: https://runbot.odoo-community.org/runbot/153/8.0
|
||||
|
||||
|
||||
Known issues / Roadmap
|
||||
======================
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Module developed and tested with Odoo version 8.0
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* David DUFRESNE <david.dufresne@savoirfairelinux.com>
|
||||
* Sandy CARTER <sandy.carter@savoirfairelinux.com>
|
||||
* Adriana IERFINO <adriana.ierfino@savoirfairelinux.com>
|
||||
* Bruno JOLIVEAU <bruno.joliveau@savoirfairelinux.com>
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
Odoo Community Association
|
||||
|
||||
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 http://odoo-community.org.
|
||||
23
partner_location_auto_create/__init__.py
Normal file
23
partner_location_auto_create/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# This module copyright (C) 2015 Savoir-faire Linux
|
||||
# (<http://www.savoirfairelinux.com>).
|
||||
#
|
||||
# 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
|
||||
44
partner_location_auto_create/__openerp__.py
Normal file
44
partner_location_auto_create/__openerp__.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# This module copyright (C) 2015 Savoir-faire Linux
|
||||
# (<http://www.savoirfairelinux.com>).
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
{
|
||||
'name': 'Partner Location Auto Create',
|
||||
'version': '0.1',
|
||||
'author': 'Savoir-faire Linux,Odoo Community Association (OCA)',
|
||||
'category': 'Warehouse',
|
||||
'license': 'AGPL-3',
|
||||
'complexity': 'normal',
|
||||
'images': [],
|
||||
'website': 'http://www.savoirfairelinux.com',
|
||||
'depends': [
|
||||
'sale_stock',
|
||||
],
|
||||
'demo': [],
|
||||
'data': [
|
||||
'views/res_partner_view.xml',
|
||||
'views/res_company_view.xml',
|
||||
'views/stock_location_view.xml',
|
||||
],
|
||||
'test': [],
|
||||
'auto_install': False,
|
||||
'installable': True,
|
||||
}
|
||||
45
partner_location_auto_create/i18n/fr.po
Normal file
45
partner_location_auto_create/i18n/fr.po
Normal file
@@ -0,0 +1,45 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * partner_location_auto_create
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 8.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-04-28 13:22+0000\n"
|
||||
"PO-Revision-Date: 2015-04-28 09:25-0500\n"
|
||||
"Last-Translator: David Dufresne <david.dufresne@savoirfairelinux.com>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: \n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
|
||||
#. module: partner_location_auto_create
|
||||
#: model:ir.model,name:partner_location_auto_create.model_res_company
|
||||
msgid "Companies"
|
||||
msgstr "Sociétés"
|
||||
|
||||
#. module: partner_location_auto_create
|
||||
#: field:res.company,default_customer_location:0
|
||||
msgid "Default Customer Location"
|
||||
msgstr "Emplacement client par défaut"
|
||||
|
||||
#. module: partner_location_auto_create
|
||||
#: field:res.company,default_supplier_location:0
|
||||
msgid "Default Supplier Location"
|
||||
msgstr "Emplacement fournisseur par défaut"
|
||||
|
||||
#. module: partner_location_auto_create
|
||||
#: code:addons/partner_location_auto_create/models/res_partner.py:44
|
||||
#: view:res.partner:partner_location_auto_create.view_partner_form
|
||||
#: field:res.partner,location_ids:0
|
||||
#, python-format
|
||||
msgid "Locations"
|
||||
msgstr "Emplacements"
|
||||
|
||||
#. module: partner_location_auto_create
|
||||
#: model:ir.model,name:partner_location_auto_create.model_res_partner
|
||||
msgid "Partner"
|
||||
msgstr "Partenaire"
|
||||
@@ -0,0 +1,44 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * partner_location_auto_create
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 8.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-04-28 13:22+0000\n"
|
||||
"PO-Revision-Date: 2015-04-28 13:22+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: partner_location_auto_create
|
||||
#: model:ir.model,name:partner_location_auto_create.model_res_company
|
||||
msgid "Companies"
|
||||
msgstr ""
|
||||
|
||||
#. module: partner_location_auto_create
|
||||
#: field:res.company,default_customer_location:0
|
||||
msgid "Default Customer Location"
|
||||
msgstr ""
|
||||
|
||||
#. module: partner_location_auto_create
|
||||
#: field:res.company,default_supplier_location:0
|
||||
msgid "Default Supplier Location"
|
||||
msgstr ""
|
||||
|
||||
#. module: partner_location_auto_create
|
||||
#: code:addons/partner_location_auto_create/models/res_partner.py:44
|
||||
#: view:res.partner:partner_location_auto_create.view_partner_form
|
||||
#: field:res.partner,location_ids:0
|
||||
#, python-format
|
||||
msgid "Locations"
|
||||
msgstr ""
|
||||
|
||||
#. module: partner_location_auto_create
|
||||
#: model:ir.model,name:partner_location_auto_create.model_res_partner
|
||||
msgid "Partner"
|
||||
msgstr ""
|
||||
25
partner_location_auto_create/models/__init__.py
Normal file
25
partner_location_auto_create/models/__init__.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# This module copyright (C) 2015 Savoir-faire Linux
|
||||
# (<http://www.savoirfairelinux.com>).
|
||||
#
|
||||
# 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 res_partner
|
||||
from . import stock_location
|
||||
44
partner_location_auto_create/models/res_company.py
Normal file
44
partner_location_auto_create/models/res_company.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# This module copyright (C) 2015 Savoir-faire Linux
|
||||
# (<http://www.savoirfairelinux.com>).
|
||||
#
|
||||
# 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 openerp import models, fields, api
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
default_customer_location = fields.Many2one(
|
||||
'stock.location', 'Default Customer Location',
|
||||
default=lambda self: self.env.ref('stock.stock_location_customers'))
|
||||
|
||||
default_supplier_location = fields.Many2one(
|
||||
'stock.location', 'Default Supplier Location',
|
||||
default=lambda self: self.env.ref('stock.stock_location_suppliers'))
|
||||
|
||||
@api.multi
|
||||
def get_default_location(self, usage):
|
||||
"Return the company's default location related to a usage type"
|
||||
self.ensure_one()
|
||||
|
||||
return (
|
||||
self.default_customer_location if usage == 'customer' else
|
||||
self.default_supplier_location)
|
||||
156
partner_location_auto_create/models/res_partner.py
Normal file
156
partner_location_auto_create/models/res_partner.py
Normal file
@@ -0,0 +1,156 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# This module copyright (C) 2015 Savoir-faire Linux
|
||||
# (<http://www.savoirfairelinux.com>).
|
||||
#
|
||||
# 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 openerp import models, fields, api, _
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
locations_count = fields.Integer(
|
||||
compute='_compute_locations_count', store=False)
|
||||
|
||||
location_ids = fields.One2many(
|
||||
'stock.location', 'partner_id', string='Locations')
|
||||
|
||||
@api.one
|
||||
@api.depends('location_ids')
|
||||
def _compute_locations_count(self):
|
||||
self.locations_count = len(self.location_ids)
|
||||
|
||||
@api.multi
|
||||
def button_locations(self):
|
||||
self.ensure_one()
|
||||
|
||||
res = {
|
||||
'name': _('Locations'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'stock.location',
|
||||
'view_type': 'form',
|
||||
}
|
||||
|
||||
if len(self.location_ids) == 1:
|
||||
res['res_id'] = self.location_ids.id
|
||||
res['view_mode'] = 'form'
|
||||
else:
|
||||
res['domain'] = [('partner_id', '=', self.id)]
|
||||
res['view_mode'] = 'tree,form'
|
||||
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def get_main_location(self, usage):
|
||||
self.ensure_one()
|
||||
return self.location_ids.filtered(
|
||||
lambda l: l.usage == usage and l.main_partner_location)
|
||||
|
||||
@api.one
|
||||
def _create_main_partner_location(self):
|
||||
if self.customer and self.property_stock_customer.partner_id != self:
|
||||
location_customer = (
|
||||
self.get_main_location('customer') or
|
||||
self._create_main_location('customer'))
|
||||
|
||||
self.write({'property_stock_customer': location_customer})
|
||||
|
||||
if self.supplier and self.property_stock_supplier.partner_id != self:
|
||||
location_supplier = (
|
||||
self.get_main_location('supplier') or
|
||||
self._create_main_location('supplier'))
|
||||
|
||||
self.write({'property_stock_supplier': location_supplier})
|
||||
|
||||
@api.multi
|
||||
def _create_main_location(self, usage):
|
||||
self.ensure_one()
|
||||
|
||||
parent = (
|
||||
self.get_main_location(usage) or
|
||||
self.company_id.get_default_location(usage)
|
||||
)
|
||||
|
||||
return self.env['stock.location'].create({
|
||||
'name': self.name,
|
||||
'usage': usage,
|
||||
'partner_id': self.id,
|
||||
'company_id': self.company_id.id,
|
||||
'location_id': parent.id,
|
||||
'main_partner_location': True,
|
||||
})
|
||||
|
||||
@api.one
|
||||
def _remove_locations(self):
|
||||
"""
|
||||
Unlink all locations related to the partner
|
||||
where no stock have been moved.
|
||||
|
||||
This is required to prevent unrequired locations to
|
||||
be created when a new partner is tagged as a company
|
||||
by mistake.
|
||||
"""
|
||||
move_obj = self.env['stock.move']
|
||||
for location in self.location_ids:
|
||||
moves = move_obj.search([
|
||||
'|',
|
||||
('location_id', 'child_of', location.id),
|
||||
('location_dest_id', 'child_of', location.id),
|
||||
])
|
||||
if not moves:
|
||||
location.unlink()
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
""" The first time a partner is created, a main customer
|
||||
and / or supplier location is created for this partner """
|
||||
partner = super(ResPartner, self).create(vals)
|
||||
|
||||
if vals.get('is_company', False):
|
||||
partner._create_main_partner_location()
|
||||
|
||||
return partner
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
if vals.get('name'):
|
||||
for partner in self:
|
||||
locations = partner.location_ids.filtered(
|
||||
lambda l: l.name == partner.name)
|
||||
locations.write({'name': vals.get('name')})
|
||||
|
||||
res = super(ResPartner, self).write(vals)
|
||||
|
||||
if (
|
||||
vals.get('is_company') or
|
||||
vals.get('customer') or
|
||||
vals.get('supplier')
|
||||
):
|
||||
for partner in self.filtered('is_company'):
|
||||
partner._create_main_partner_location()
|
||||
|
||||
if 'is_company' in vals and not vals['is_company']:
|
||||
# When False is written to field 'is_company'
|
||||
self._remove_locations()
|
||||
|
||||
if 'active' in vals:
|
||||
self.location_ids.write({'active': vals['active']})
|
||||
|
||||
return res
|
||||
48
partner_location_auto_create/models/stock_location.py
Normal file
48
partner_location_auto_create/models/stock_location.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# This module copyright (C) 2015 Savoir-faire Linux
|
||||
# (<http://www.savoirfairelinux.com>).
|
||||
#
|
||||
# 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 openerp import models, fields, api, _
|
||||
from openerp.exceptions import Warning
|
||||
|
||||
|
||||
class StockLocation(models.Model):
|
||||
_inherit = 'stock.location'
|
||||
|
||||
main_partner_location = fields.Boolean(
|
||||
'Main Partner Location',
|
||||
help="The root location for a partner's location for a specific "
|
||||
"type.")
|
||||
|
||||
@api.one
|
||||
@api.constrains('partner_id', 'main_partner_location', 'usage')
|
||||
def _check_main_location(self):
|
||||
partner = self.partner_id
|
||||
|
||||
if partner and len(partner.get_main_location(self.usage)) > 1:
|
||||
raise Warning(
|
||||
_('The partner %s already has a main location '
|
||||
'of type %s.') % (partner.name, self.usage))
|
||||
|
||||
@api.onchange('partner_id', 'usage')
|
||||
def _onchange_parent_location(self):
|
||||
if self.partner_id:
|
||||
self.location_id = self.partner_id.get_main_location(self.usage).id
|
||||
23
partner_location_auto_create/tests/__init__.py
Normal file
23
partner_location_auto_create/tests/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# This module copyright (C) 2015 Savoir-faire Linux
|
||||
# (<http://www.savoirfairelinux.com>).
|
||||
#
|
||||
# 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 test_res_partner
|
||||
279
partner_location_auto_create/tests/test_res_partner.py
Normal file
279
partner_location_auto_create/tests/test_res_partner.py
Normal file
@@ -0,0 +1,279 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# This module copyright (C) 2015 Savoir-faire Linux
|
||||
# (<http://www.savoirfairelinux.com>).
|
||||
#
|
||||
# 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 openerp.tests.common import TransactionCase
|
||||
|
||||
|
||||
class TestPartnerLocations(TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestPartnerLocations, self).setUp()
|
||||
|
||||
self.partner_model = self.env['res.partner']
|
||||
self.location_model = self.env['stock.location']
|
||||
self.company_model = self.env['res.company']
|
||||
|
||||
self.company_2 = self.company_model.create({'name': 'Test Company'})
|
||||
|
||||
self.customer_location = self.env.ref('stock.stock_location_customers')
|
||||
self.supplier_location = self.env.ref('stock.stock_location_suppliers')
|
||||
|
||||
self.customer_location_2 = self.location_model.create({
|
||||
'usage': 'customer',
|
||||
'name': 'Default Customer Location 2',
|
||||
'company_id': self.company_2.id,
|
||||
})
|
||||
|
||||
self.supplier_location_2 = self.location_model.create({
|
||||
'usage': 'supplier',
|
||||
'name': 'Default Supplier Location 2',
|
||||
'company_id': self.company_2.id,
|
||||
})
|
||||
|
||||
self.company_2.write({
|
||||
'default_customer_location': self.customer_location_2.id,
|
||||
'default_supplier_location': self.supplier_location_2.id,
|
||||
})
|
||||
|
||||
self.customer_a = self.partner_model.create({
|
||||
'name': 'Customer A',
|
||||
'customer': True,
|
||||
'supplier': False,
|
||||
'is_company': True,
|
||||
'company_id': self.company_2.id,
|
||||
})
|
||||
|
||||
self.supplier_b = self.partner_model.create({
|
||||
'name': 'Supplier B',
|
||||
'customer': False,
|
||||
'supplier': True,
|
||||
'is_company': True,
|
||||
'company_id': self.company_2.id,
|
||||
})
|
||||
|
||||
self.partner_c = self.partner_model.create({
|
||||
'name': 'Partner C',
|
||||
'customer': True,
|
||||
'supplier': True,
|
||||
'is_company': True,
|
||||
})
|
||||
|
||||
def _create_locations(self):
|
||||
self.locations = [
|
||||
self.location_model.create({
|
||||
'partner_id': record[0].id,
|
||||
'name': record[1],
|
||||
'usage': record[2],
|
||||
'company_id': record[0].company_id.id,
|
||||
}) for record in [
|
||||
(self.customer_a, 'Location A-1', 'customer'),
|
||||
(self.customer_a, 'Location A-2', 'supplier'),
|
||||
(self.supplier_b, 'Location B-1', 'customer'),
|
||||
(self.supplier_b, 'Location B-2', 'supplier'),
|
||||
(self.supplier_b, 'Location B-3', 'supplier'),
|
||||
]
|
||||
]
|
||||
|
||||
self.customer_a.refresh()
|
||||
self.supplier_b.refresh()
|
||||
|
||||
def test_partner_inactive(self):
|
||||
self._create_locations()
|
||||
|
||||
self.assertEqual(len(self.customer_a.location_ids), 3)
|
||||
|
||||
self.customer_a.write({'active': False})
|
||||
self.customer_a.refresh()
|
||||
self.assertEqual(len(self.customer_a.location_ids), 0)
|
||||
|
||||
for location in self.customer_a.location_ids:
|
||||
self.assertFalse(location.active)
|
||||
|
||||
def test_partner_change_name(self):
|
||||
# Test with customer A
|
||||
self.assertEqual(
|
||||
self.customer_a.property_stock_customer.name,
|
||||
'Customer A')
|
||||
|
||||
self.customer_a.property_stock_customer.write({
|
||||
'name': 'Location A-1',
|
||||
})
|
||||
|
||||
self.customer_a.write({'name': 'Customer AA'})
|
||||
|
||||
self.customer_a.refresh()
|
||||
self.assertEqual(
|
||||
self.customer_a.property_stock_customer.name,
|
||||
'Location A-1')
|
||||
|
||||
# Test with partner C
|
||||
self.assertEqual(
|
||||
self.partner_c.property_stock_customer.name,
|
||||
'Partner C')
|
||||
|
||||
self.partner_c.write({'name': 'Partner CC'})
|
||||
self.partner_c.refresh()
|
||||
self.assertEqual(
|
||||
self.partner_c.property_stock_customer.name,
|
||||
'Partner CC')
|
||||
|
||||
self.assertEqual(
|
||||
self.partner_c.property_stock_supplier.name,
|
||||
'Partner CC')
|
||||
|
||||
def test_partner_location_parent(self):
|
||||
self.assertEqual(
|
||||
self.customer_a.property_stock_customer.location_id,
|
||||
self.customer_location_2)
|
||||
|
||||
self.assertEqual(
|
||||
self.supplier_b.property_stock_supplier.location_id,
|
||||
self.supplier_location_2)
|
||||
|
||||
self.assertEqual(
|
||||
self.partner_c.property_stock_customer.location_id,
|
||||
self.customer_location)
|
||||
|
||||
self.assertEqual(
|
||||
self.partner_c.property_stock_supplier.location_id,
|
||||
self.supplier_location)
|
||||
|
||||
def test_partner_not_company(self):
|
||||
"""
|
||||
Partners that are not companies must not generate locations
|
||||
"""
|
||||
self.partner_d = self.partner_model.create({
|
||||
'name': 'Partner D',
|
||||
'customer': True,
|
||||
'supplier': True,
|
||||
'is_company': False,
|
||||
'company_id': self.company_2.id,
|
||||
})
|
||||
|
||||
self.assertEqual(len(self.partner_d.location_ids), 0)
|
||||
|
||||
# If the partner becomes a company, the locations must
|
||||
# be created
|
||||
self.partner_d.write({'is_company': True})
|
||||
self.partner_d.refresh()
|
||||
self.assertEqual(len(self.partner_d.location_ids), 2)
|
||||
|
||||
def test_location_parent(self):
|
||||
self.assertEqual(len(self.partner_c.location_ids), 2)
|
||||
for location in self.partner_c.location_ids:
|
||||
self.assertEqual(location.location_id.usage, location.usage)
|
||||
|
||||
def test_count_locations(self):
|
||||
self._create_locations()
|
||||
self.assertEqual(len(self.customer_a.location_ids), 3)
|
||||
self.assertEqual(len(self.supplier_b.location_ids), 4)
|
||||
self.assertEqual(len(self.partner_c.location_ids), 2)
|
||||
|
||||
def test_multi_company(self):
|
||||
self._create_locations()
|
||||
|
||||
self.assertEqual(len(self.customer_a.location_ids), 3)
|
||||
for location in self.customer_a.location_ids:
|
||||
self.assertEqual(location.company_id, self.company_2)
|
||||
|
||||
def check_partner_c(self):
|
||||
self.assertEqual(len(self.partner_c.location_ids), 2)
|
||||
|
||||
location_c1 = self.partner_c.property_stock_customer
|
||||
location_c2 = self.partner_c.property_stock_supplier
|
||||
locations = self.partner_c.location_ids
|
||||
|
||||
self.assertIn(location_c1, locations)
|
||||
self.assertEqual(location_c1.usage, 'customer')
|
||||
self.assertIn(location_c2, locations)
|
||||
self.assertEqual(location_c2.usage, 'supplier')
|
||||
|
||||
def test_partner_create(self):
|
||||
self.assertEqual(len(self.customer_a.location_ids), 1)
|
||||
location_a = self.customer_a.location_ids[0]
|
||||
self.assertEqual(self.customer_a.location_ids[0].usage, 'customer')
|
||||
self.assertEqual(self.customer_a.property_stock_customer, location_a)
|
||||
|
||||
self.assertEqual(len(self.supplier_b.location_ids), 1)
|
||||
location_b = self.supplier_b.location_ids[0]
|
||||
self.assertEqual(location_b.usage, 'supplier')
|
||||
self.assertEqual(self.supplier_b.property_stock_supplier, location_b)
|
||||
|
||||
self.check_partner_c()
|
||||
|
||||
def check_customer_a_supplier_location(self):
|
||||
location_a = self.customer_a.property_stock_supplier
|
||||
self.assertIn(location_a, self.customer_a.location_ids)
|
||||
self.assertEqual(location_a.usage, 'supplier')
|
||||
|
||||
def check_supplier_b_customer_location(self):
|
||||
location_b = self.supplier_b.property_stock_customer
|
||||
self.assertIn(location_b, self.supplier_b.location_ids)
|
||||
self.assertEqual(location_b.usage, 'customer')
|
||||
|
||||
def test_partner_write(self):
|
||||
"""
|
||||
Test write method when partner does not already have the required
|
||||
location
|
||||
"""
|
||||
self.customer_a.write({'supplier': True})
|
||||
self.supplier_b.write({'customer': True})
|
||||
|
||||
self.assertEqual(len(self.customer_a.location_ids), 2)
|
||||
self.check_customer_a_supplier_location()
|
||||
|
||||
self.assertEqual(len(self.supplier_b.location_ids), 2)
|
||||
self.check_supplier_b_customer_location()
|
||||
|
||||
def test_partner_write_existing_location(self):
|
||||
"""
|
||||
Test write method when partner already has the required location
|
||||
"""
|
||||
self._create_locations()
|
||||
|
||||
self.customer_a.write({'supplier': True})
|
||||
self.customer_a.refresh()
|
||||
self.assertEqual(len(self.customer_a.location_ids), 4)
|
||||
self.check_customer_a_supplier_location()
|
||||
|
||||
self.supplier_b.write({'customer': True})
|
||||
self.supplier_b.refresh()
|
||||
self.assertEqual(len(self.supplier_b.location_ids), 5)
|
||||
self.check_supplier_b_customer_location()
|
||||
|
||||
self.partner_c.write({'supplier': True, 'customer': True})
|
||||
self.check_partner_c()
|
||||
|
||||
def test_partner_write_is_company_false(self):
|
||||
"""
|
||||
Test that locations related to a partner are unlinked
|
||||
when a is_company is set to False
|
||||
"""
|
||||
self._create_locations()
|
||||
|
||||
self.assertEqual(len(self.customer_a.location_ids), 3)
|
||||
self.customer_a.write({
|
||||
'supplier': True,
|
||||
'is_company': False,
|
||||
})
|
||||
self.customer_a.refresh()
|
||||
self.assertEqual(len(self.customer_a.location_ids), 0)
|
||||
18
partner_location_auto_create/views/res_company_view.xml
Normal file
18
partner_location_auto_create/views/res_company_view.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_company_form" model="ir.ui.view" >
|
||||
<field name="name">Company Form Default Stock Locations</field>
|
||||
<field name="model">res.company</field>
|
||||
<field name="inherit_id" ref="procurement.mrp_company"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="logistics_grp" position="inside">
|
||||
<field name="default_customer_location"/>
|
||||
<field name="default_supplier_location"/>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
42
partner_location_auto_create/views/res_partner_view.xml
Normal file
42
partner_location_auto_create/views/res_partner_view.xml
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_partner_form" model="ir.ui.view" >
|
||||
<field name="name">Partner Form Locations</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="stock.view_partner_property_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="buttons" position="inside">
|
||||
<button
|
||||
class="oe_inline oe_stat_button"
|
||||
type="object"
|
||||
context="{
|
||||
'default_partner_id': id,
|
||||
'default_usage': supplier and 'supplier' or 'customer',
|
||||
}"
|
||||
name="button_locations"
|
||||
icon="fa-list">
|
||||
<field string="Locations" name="locations_count" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<field name="property_stock_customer" position="attributes">
|
||||
<attribute name="domain">[
|
||||
('partner_id', 'in', [id, False]),
|
||||
('usage', '=', 'customer'),
|
||||
('company_id', 'in', [company_id, False]),
|
||||
]</attribute>
|
||||
</field>
|
||||
<field name="property_stock_supplier" position="attributes">
|
||||
<attribute name="domain">[
|
||||
('partner_id', 'in', [id, False]),
|
||||
('usage', '=', 'supplier'),
|
||||
('company_id', 'in', [company_id, False]),
|
||||
]</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
17
partner_location_auto_create/views/stock_location_view.xml
Normal file
17
partner_location_auto_create/views/stock_location_view.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_location_form" model="ir.ui.view">
|
||||
<field name="name">stock.location.form</field>
|
||||
<field name="model">stock.location</field>
|
||||
<field name="inherit_id" ref="stock.view_location_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="partner_id" position="after">
|
||||
<field name="main_partner_location"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
Reference in New Issue
Block a user