Convert party warehouse in multivalue.

This commit refs #23994
This commit is contained in:
ramon.vidal 2022-09-28 19:32:24 +02:00 committed by Sergio Morillo
parent b8fc32ca66
commit 088b0437ec
10 changed files with 197 additions and 16 deletions

View File

@ -14,7 +14,11 @@ def register():
configuration.ConfigurationPartyWarehouse,
party.Party,
party.CreateWarehouseStart,
party.PartyWarehouse,
stock.Location,
shipment.ShipmentInReturn,
shipment.ShipmentOut,
shipment.ShipmentOutReturn,
shipment.ShipmentInternal,
module='stock_party_warehouse', type_='model')
Pool.register(

View File

@ -11,6 +11,10 @@ msgctxt "field:party.party,warehouse:"
msgid "Party Warehouse"
msgstr "Almacén de tercero"
msgctxt "field:party.party,warehouses:"
msgid "Party Warehouses"
msgstr "Almacenes de tercero"
msgctxt "field:party.party,create_warehouse:"
msgid "Create Warehouse"
msgstr "Crear almacén"
@ -94,4 +98,20 @@ msgstr "Nuevo almacén"
msgctxt "view:party.party.create_warehouse.start:"
msgid "Existing warehouse"
msgstr "Almacén existente"
msgstr "Almacén existente"
msgctxt "model:party.party.warehouse,name:"
msgid "Party Warehouse"
msgstr "Almacenes de terceros"
msgctxt "model:ir.ui.menu,name:menu_party_warehouse"
msgid "Party Warehouse"
msgstr "Almacenes de terceros"
msgctxt "field:party.party.warehouse,warehouse:"
msgid "Warehouse"
msgstr "Almacén"
msgctxt "field:party.party.warehouse,party:"
msgid "Party"
msgstr "Tercero"

View File

@ -6,7 +6,29 @@ from trytond.pyson import Eval
from trytond.transaction import Transaction
class ReturnableMoveMixin(object):
class PartyWarehouseMixin(object):
def _get_party_warehouse_pattern(self):
return {}
@property
def party_with_warehouse(self):
return self.party
def get_party_warehouse_used(self, **pattern):
party = self.party_with_warehouse
if party:
wh = party.get_multivalue('warehouse', **pattern)
if not wh:
# leave only party match pattern value
pattern = {key: None if key != 'party' else value
for key, value in pattern.items()
}
wh = party.get_multivalue('warehouse', **pattern)
return wh
class ReturnableMoveMixin(PartyWarehouseMixin):
returnables_moves = fields.Function(
fields.One2Many('stock.move', None, 'Returnables moves',
@ -26,7 +48,8 @@ class ReturnableMoveMixin(object):
return moves
def is_returnable(self, move):
return getattr(self, self._party_field).warehouse
return self.get_party_warehouse_used(
**self._get_party_warehouse_pattern())
@classmethod
def create_returnables_moves(cls, records):

View File

@ -1,19 +1,21 @@
# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms.
from trytond.pool import PoolMeta, Pool
from trytond.model import fields, ModelView
from trytond.model import fields, ModelView, ModelSQL, ValueMixin
from trytond.wizard import Wizard, StateView, Button, StateTransition
from trytond.pyson import Not, Bool, Eval
from trytond.transaction import Transaction
from trytond import backend
from sql import Null
class Party(metaclass=PoolMeta):
__name__ = 'party.party'
warehouse = fields.Many2One('stock.location', 'Party Warehouse',
domain=[
('type', '=', 'warehouse'),
])
warehouse = fields.MultiValue(fields.Many2One('stock.location',
"Party Warehouse", domain=[('type', '=', 'warehouse')]))
warehouses = fields.One2Many('party.party.warehouse', 'party',
"Party Warehouses")
create_warehouse = fields.Function(
fields.Boolean('Create Warehouse',
states={
@ -50,6 +52,45 @@ class Party(metaclass=PoolMeta):
cls.save(to_save)
class PartyWarehouse(ModelSQL, ModelView, ValueMixin):
"Party Warehouse"
__name__ = 'party.party.warehouse'
party = fields.Many2One('party.party', "Party", select=True,
required=True, ondelete='CASCADE')
warehouse = fields.Many2One('stock.location', "Warehouse",
domain=[('type', '=', 'warehouse')], ondelete='RESTRICT')
@classmethod
def __register__(cls, module_name):
pool = Pool()
Party = pool.get('party.party')
cursor = Transaction().connection.cursor()
table = cls.__table__()
party = Party.__table__()
exist = backend.TableHandler.table_exist(cls._table)
super().__register__(module_name)
if not exist:
party_h = Party.__table_handler__(module_name)
if party_h.column_exist('warehouse'):
cursor.execute(*table.insert([
table.create_uid,
table.create_date,
table.party,
table.warehouse,
],
party.select(
party.create_uid,
party.create_date,
party.id,
party.warehouse,
where=party.warehouse != Null))
)
party_h.drop_column('warehouse')
class CreateWarehouseStart(ModelView):
"""Create Party Warehouse Start"""
__name__ = 'party.party.create_warehouse.start'

View File

@ -24,5 +24,36 @@
<field name="type">form</field>
<field name="name">party_create_warehouse_start_form</field>
</record>
<!-- Party Warehouse -->
<record model="ir.ui.view" id="party_warehouse_view_form">
<field name="model">party.party.warehouse</field>
<field name="type">form</field>
<field name="name">party_warehouse_form</field>
</record>
<record model="ir.ui.view" id="party_warehouse_view_tree">
<field name="model">party.party.warehouse</field>
<field name="type">tree</field>
<field name="name">party_warehouse_tree</field>
</record>
<record model="ir.action.act_window" id="act_party_warehouse">
<field name="name">Part Warehouse</field>
<field name="res_model">party.party.warehouse</field>
</record>
<record model="ir.action.act_window.view" id="act_party_warehouse_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="party_warehouse_view_tree"/>
<field name="act_window" ref="act_party_warehouse"/>
</record>
<record model="ir.action.act_window.view" id="act_party_warehouse_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="party_warehouse_view_form"/>
<field name="act_window" ref="act_party_warehouse"/>
</record>
<!-- Menus -->
<menuitem action="act_party_warehouse" id="menu_party_warehouse"
parent="stock.menu_configuration" sequence="30" name="Party Warehouse"/>
</data>
</tryton>

View File

@ -5,13 +5,14 @@ from trytond.model import fields
from trytond.pyson import Eval, Not
from trytond.exceptions import UserError
from trytond.i18n import gettext
from trytond.modules.stock_party_warehouse.model import PartyWarehouseMixin
class ShipmentInternal(metaclass=PoolMeta):
class ShipmentInternal(PartyWarehouseMixin, metaclass=PoolMeta):
__name__ = 'stock.shipment.internal'
party = fields.Many2One('party.party', 'Party',
domain=[('warehouse', '!=', None)],
domain=[('warehouses', '!=', None)],
states={
'readonly': (~Eval('state').in_(['request', 'draft'])
| Eval('moves', [0])
@ -27,22 +28,27 @@ class ShipmentInternal(metaclass=PoolMeta):
if (self.party
and self.from_location
and not self.to_location):
if self.from_location.warehouse != self.party.warehouse:
self.to_location = self.party.warehouse.storage_location
warehouse = self.get_party_warehouse_used(
**self._get_party_warehouse_pattern())
if self.from_location.warehouse != warehouse:
self.to_location = warehouse.storage_location
@fields.depends('party', 'from_location', 'to_location')
def on_change_to_location(self):
if (self.party
and self.to_location
and not self.from_location):
if self.to_location.warehouse != self.party.warehouse:
self.from_location = self.party.warehouse.storage_location
warehouse = self.get_party_warehouse_used(
**self._get_party_warehouse_pattern())
if self.to_location.warehouse != warehouse:
self.from_location = warehouse.storage_location
@classmethod
def wait(cls, shipments, moves=None):
for shipment in shipments:
if shipment.party:
wh = shipment.party.warehouse
wh = shipment.get_party_warehouse_used(
**shipment._get_party_warehouse_pattern())
if (wh != shipment.from_location.warehouse
and wh != shipment.to_location.warehouse):
raise UserError(gettext('stock_party_warehouse.'
@ -50,3 +56,27 @@ class ShipmentInternal(metaclass=PoolMeta):
shipment=shipment.rec_name,
warehouse=wh.rec_name))
super().wait(shipments, moves=moves)
class ShipmentInReturn(PartyWarehouseMixin, metaclass=PoolMeta):
__name__ = 'stock.shipment.in.return'
@property
def party_with_warehouse(self):
return self.supplier
class ShipmentOut(PartyWarehouseMixin, metaclass=PoolMeta):
__name__ = 'stock.shipment.out'
@property
def party_with_warehouse(self):
return self.customer
class ShipmentOutReturn(PartyWarehouseMixin, metaclass=PoolMeta):
__name__ = 'stock.shipment.out.return'
@property
def party_with_warehouse(self):
return self.customer

View File

@ -44,6 +44,12 @@ Add party warehouse parent to stock configuration::
>>> conf.party_warehouse_parent = view_loc
>>> conf.save()
Party Warehouse::
>>> PartyWarehouse = Model.get('party.party.warehouse')
>>> party_warehouse = PartyWarehouse.find([])
>>> len(party_warehouse)
0
Create parties::
@ -109,6 +115,16 @@ Add parties warehouses::
>>> bool(party5.create_warehouse)
True
Check create Party Warehouse::
>>> PartyWarehouse = Model.get('party.party.warehouse')
>>> party_warehouses = PartyWarehouse.find([])
>>> len(party_warehouses)
5
>>> party_warehouse, = PartyWarehouse.find([('party', '=', party)])
>>> party_warehouse.warehouse == party.warehouse
True
Add party with create_warehoues check::
>>> party6 = Party(name='Party 6')

View File

@ -4,7 +4,7 @@ depends:
ir
res
production
xml:
configuration.xml
party.xml

View File

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<form>
<label name="party"/>
<field name="party"/>
<label name="warehouse"/>
<field name="warehouse"/>
</form>

View File

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<tree editable="1">
<field name="party" expand="1"/>
<field name="warehouse" expand="1"/>
</tree>