Add may_belong_to_party and owners to product and allow to change the party related to move
This commit is contained in:
parent
2048c56f05
commit
9f9f263146
|
@ -1,3 +1,6 @@
|
|||
* Allow to change the party related to move
|
||||
* Add may_belong_to_party boolean field to product template and relation to
|
||||
posible owners
|
||||
* Adapt inventory and location to use grouping
|
||||
* Exclude party quantities from Product/Location cost value
|
||||
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
# The COPYRIGHT file at the top level of this repository contains the full
|
||||
# copyright notices and license terms.
|
||||
from trytond.pool import Pool
|
||||
from .product import *
|
||||
from .stock import *
|
||||
|
||||
|
||||
def register():
|
||||
Pool.register(
|
||||
Party,
|
||||
Template,
|
||||
TemplateOwnerParty,
|
||||
Product,
|
||||
ProductByPartyStart,
|
||||
Location,
|
||||
Move,
|
||||
ShipmentOut,
|
||||
ShipmentExternal,
|
||||
ProductByPartyStart,
|
||||
Period,
|
||||
PeriodCacheParty,
|
||||
Inventory,
|
||||
|
|
|
@ -32,6 +32,46 @@ msgctxt "field:product.by_party.start,id:"
|
|||
msgid "ID"
|
||||
msgstr "Identificador"
|
||||
|
||||
msgctxt "field:product.template,external_owners:"
|
||||
msgid "External Owners"
|
||||
msgstr "Propietaris externs"
|
||||
|
||||
msgctxt "field:product.template,may_belong_to_party:"
|
||||
msgid "May belong to party"
|
||||
msgstr "Per pert<72><74>nyer a un tercer"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,create_date:"
|
||||
msgid "Create Date"
|
||||
msgstr "Data creaci<63><69>"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,create_uid:"
|
||||
msgid "Create User"
|
||||
msgstr "Usuari creaci<63><69>"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,id:"
|
||||
msgid "ID"
|
||||
msgstr "Identificador"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,party:"
|
||||
msgid "Owner"
|
||||
msgstr "Propietari"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,product:"
|
||||
msgid "Product"
|
||||
msgstr "Producte"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,rec_name:"
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,write_date:"
|
||||
msgid "Write Date"
|
||||
msgstr "Data modificaci<63><69>n"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,write_uid:"
|
||||
msgid "Write User"
|
||||
msgstr "Usuari modificaci<63><69>"
|
||||
|
||||
msgctxt "field:stock.inventory.line,party:"
|
||||
msgid "Party"
|
||||
msgstr "Tercer"
|
||||
|
@ -118,6 +158,10 @@ msgctxt "model:product.by_party.start,name:"
|
|||
msgid "Product by Party"
|
||||
msgstr "Producte per tercer"
|
||||
|
||||
msgctxt "model:product.template-owner-party.party,name:"
|
||||
msgid "Template - Owner - Party"
|
||||
msgstr "Plantilla - Propietari - Tercer"
|
||||
|
||||
msgctxt "model:stock.period.cache.party,name:"
|
||||
msgid "Stock Period Cache per Party"
|
||||
msgstr "Estoc precalculat de periode per tercer"
|
||||
|
|
|
@ -32,13 +32,53 @@ msgctxt "field:product.by_party.start,id:"
|
|||
msgid "ID"
|
||||
msgstr "Identificador"
|
||||
|
||||
msgctxt "field:product.template,external_owners:"
|
||||
msgid "External Owners"
|
||||
msgstr "Propietarios externos"
|
||||
|
||||
msgctxt "field:product.template,may_belong_to_party:"
|
||||
msgid "May belong to party"
|
||||
msgstr "Puede pertenecer a un tercero"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,create_date:"
|
||||
msgid "Create Date"
|
||||
msgstr "Fecha creaci<63><69>n"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,create_uid:"
|
||||
msgid "Create User"
|
||||
msgstr "Usuario creaci<63><69>n"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,id:"
|
||||
msgid "ID"
|
||||
msgstr "Identificador"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,party:"
|
||||
msgid "Owner"
|
||||
msgstr "Propietario"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,product:"
|
||||
msgid "Product"
|
||||
msgstr "Producto"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,rec_name:"
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,write_date:"
|
||||
msgid "Write Date"
|
||||
msgstr "Fecha modificaci<63><69>n"
|
||||
|
||||
msgctxt "field:product.template-owner-party.party,write_uid:"
|
||||
msgid "Write User"
|
||||
msgstr "Usuario modificaci<63><69>n"
|
||||
|
||||
msgctxt "field:stock.inventory.line,party:"
|
||||
msgid "Party"
|
||||
msgstr "Tercero"
|
||||
|
||||
msgctxt "field:stock.move,party:"
|
||||
msgid "Party"
|
||||
msgstr "Terceros"
|
||||
msgstr "Tercero"
|
||||
|
||||
msgctxt "field:stock.move,party_to_check:"
|
||||
msgid "Party"
|
||||
|
@ -118,6 +158,10 @@ msgctxt "model:product.by_party.start,name:"
|
|||
msgid "Product by Party"
|
||||
msgstr "Producto por tercero"
|
||||
|
||||
msgctxt "model:product.template-owner-party.party,name:"
|
||||
msgid "Template - Owner - Party"
|
||||
msgstr "Plantilla - Propietari - Tercero"
|
||||
|
||||
msgctxt "model:stock.period.cache.party,name:"
|
||||
msgid "Stock Period Cache per Party"
|
||||
msgstr "Período precalculado por tercero"
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
# The COPYRIGHT file at the top level of this repository contains the full
|
||||
# copyright notices and license terms.
|
||||
import datetime
|
||||
|
||||
from trytond.model import fields, ModelSQL, ModelView
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.pyson import Eval, PYSONEncoder
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.wizard import Wizard, StateView, StateAction, Button
|
||||
|
||||
__all__ = ['Template', 'TemplateOwnerParty',
|
||||
'Product', 'ProductByPartyStart', 'ProductByParty',
|
||||
]
|
||||
__metaclass__ = PoolMeta
|
||||
|
||||
|
||||
class Template:
|
||||
__name__ = 'product.template'
|
||||
|
||||
may_belong_to_party = fields.Boolean('May belong to party', states={
|
||||
'readonly': ~Eval('active', True),
|
||||
}, depends=['active'])
|
||||
external_owners = fields.Many2Many('product.template-owner-party.party',
|
||||
'product', 'party', 'External Owners', states={
|
||||
'readonly': ~Eval('active', True),
|
||||
'invisible': ~Eval('may_belong_to_party', False),
|
||||
}, depends=['active', 'may_belong_to_party'])
|
||||
|
||||
|
||||
class TemplateOwnerParty(ModelSQL):
|
||||
'Template - Owner - Party'
|
||||
__name__ = 'product.template-owner-party.party'
|
||||
product = fields.Many2One('product.template', 'Product',
|
||||
ondelete='CASCADE', required=True, select=True)
|
||||
party = fields.Many2One('party.party', 'Owner', ondelete='CASCADE',
|
||||
required=True, select=True)
|
||||
|
||||
|
||||
class Product:
|
||||
__name__ = 'product.product'
|
||||
|
||||
@classmethod
|
||||
def get_cost_value(cls, products, name):
|
||||
with Transaction().set_context(exclude_party_quantities=True):
|
||||
return super(Product, cls).get_cost_value(products, name)
|
||||
|
||||
|
||||
class ProductByPartyStart(ModelView):
|
||||
'Product by Party'
|
||||
__name__ = 'product.by_party.start'
|
||||
forecast_date = fields.Date(
|
||||
'At Date', help=('Allow to compute expected '
|
||||
'stock quantities for this date.\n'
|
||||
'* An empty value is an infinite date in the future.\n'
|
||||
'* A date in the past will provide historical values.'))
|
||||
|
||||
@staticmethod
|
||||
def default_forecast_date():
|
||||
Date = Pool().get('ir.date')
|
||||
return Date.today()
|
||||
|
||||
|
||||
class ProductByParty(Wizard):
|
||||
'Product by Party'
|
||||
__name__ = 'product.by_party'
|
||||
start = StateView('product.by_party.start',
|
||||
'stock_external_party.product_by_party_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Open', 'open', 'tryton-ok', default=True),
|
||||
])
|
||||
open = StateAction('stock_external_party.act_party_quantity_tree')
|
||||
|
||||
def do_open(self, action):
|
||||
pool = Pool()
|
||||
Product = pool.get('product.product')
|
||||
Lang = pool.get('ir.lang')
|
||||
|
||||
context = {}
|
||||
product_id = Transaction().context['active_id']
|
||||
context['products'] = [product_id]
|
||||
if self.start.forecast_date:
|
||||
context['stock_date_end'] = self.start.forecast_date
|
||||
else:
|
||||
context['stock_date_end'] = datetime.date.max
|
||||
action['pyson_context'] = PYSONEncoder().encode(context)
|
||||
product = Product(product_id)
|
||||
|
||||
for code in [Transaction().language, 'en_US']:
|
||||
langs = Lang.search([
|
||||
('code', '=', code),
|
||||
])
|
||||
if langs:
|
||||
break
|
||||
lang, = langs
|
||||
date = Lang.strftime(context['stock_date_end'],
|
||||
lang.code, lang.date)
|
||||
|
||||
action['name'] += ' - %s (%s) @ %s' % (product.rec_name,
|
||||
product.default_uom.rec_name, date)
|
||||
return action, {}
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- The COPYRIGHT file at the top level of this repository contains the full
|
||||
copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<!-- product.template -->
|
||||
<record model="ir.ui.view" id="template_view_form">
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit" ref="product.template_view_form"/>
|
||||
<field name="name">template_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="template_view_tree">
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit" ref="product.template_view_tree"/>
|
||||
<field name="name">template_tree</field>
|
||||
</record>
|
||||
|
||||
<!-- product.by_party -->
|
||||
<record model="ir.action.wizard" id="wizard_product_by_party">
|
||||
<field name="name">Product By Party</field>
|
||||
<field name="wiz_name">product.by_party</field>
|
||||
<field name="model">product.product</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_party_quantity_keyword1">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.product,-1</field>
|
||||
<field name="action" ref="wizard_product_by_party"/>
|
||||
</record>
|
||||
<record model="ir.action-res.group"
|
||||
id="wizard_lot_by_location-group_stock">
|
||||
<field name="action" ref="wizard_product_by_party"/>
|
||||
<field name="group" ref="stock.group_stock"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="product_by_party_start_view_form">
|
||||
<field name="model">product.by_party.start</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">product_by_party_start_form</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
79
stock.py
79
stock.py
|
@ -1,18 +1,13 @@
|
|||
# The COPYRIGHT file at the top level of this repository contains the full
|
||||
# copyright notices and license terms.
|
||||
import datetime
|
||||
from collections import defaultdict
|
||||
from trytond.model import ModelSQL, ModelView, fields
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.pyson import PYSONEncoder
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.wizard import Wizard, StateView, StateAction, Button
|
||||
from trytond.modules.stock.move import STATES, DEPENDS
|
||||
from trytond.modules.stock import StockMixin
|
||||
|
||||
__all__ = ['Party', 'Product', 'Location',
|
||||
__all__ = ['Party', 'Location',
|
||||
'Move', 'ShipmentOut', 'ShipmentExternal',
|
||||
'ProductByPartyStart', 'ProductByParty',
|
||||
'Period', 'PeriodCacheParty',
|
||||
'Inventory', 'InventoryLine']
|
||||
__metaclass__ = PoolMeta
|
||||
|
@ -53,15 +48,6 @@ class Party(object, StockMixin):
|
|||
grouping=('product', 'party_used'))
|
||||
|
||||
|
||||
class Product:
|
||||
__name__ = 'product.product'
|
||||
|
||||
@classmethod
|
||||
def get_cost_value(cls, products, name):
|
||||
with Transaction().set_context(exclude_party_quantities=True):
|
||||
return super(Product, cls).get_cost_value(products, name)
|
||||
|
||||
|
||||
class Location:
|
||||
__name__ = 'stock.location'
|
||||
|
||||
|
@ -140,6 +126,8 @@ class Move:
|
|||
def assign_try(cls, moves, with_childs=True, grouping=('product',)):
|
||||
for move in moves:
|
||||
move._check_party()
|
||||
if 'party' not in grouping:
|
||||
grouping = grouping + ('party',)
|
||||
return super(Move, cls).assign_try(moves, with_childs=with_childs,
|
||||
grouping=grouping)
|
||||
|
||||
|
@ -153,8 +141,10 @@ class Move:
|
|||
types_to_check = self.location_types_to_check_party()
|
||||
wh_output = (getattr(self.shipment, 'warehouse_output', None)
|
||||
if self.shipment else None)
|
||||
if (self.party_used and (self.to_location.type in types_to_check or
|
||||
wh_output and self.to_location == wh_output)
|
||||
if not (self.to_location.type in types_to_check
|
||||
or wh_output and self.to_location == wh_output):
|
||||
return
|
||||
if (self.party_used and self.party_to_check
|
||||
and self.party_used != self.party_to_check):
|
||||
self.raise_user_error('diferent_party', (self.rec_name,
|
||||
self.party_used.rec_name,
|
||||
|
@ -244,61 +234,6 @@ class ShipmentExternal:
|
|||
super(ShipmentExternal, cls).wait(shipments)
|
||||
|
||||
|
||||
class ProductByPartyStart(ModelView):
|
||||
'Product by Party'
|
||||
__name__ = 'product.by_party.start'
|
||||
forecast_date = fields.Date(
|
||||
'At Date', help=('Allow to compute expected '
|
||||
'stock quantities for this date.\n'
|
||||
'* An empty value is an infinite date in the future.\n'
|
||||
'* A date in the past will provide historical values.'))
|
||||
|
||||
@staticmethod
|
||||
def default_forecast_date():
|
||||
Date = Pool().get('ir.date')
|
||||
return Date.today()
|
||||
|
||||
|
||||
class ProductByParty(Wizard):
|
||||
'Product by Party'
|
||||
__name__ = 'product.by_party'
|
||||
start = StateView('product.by_party.start',
|
||||
'stock_external_party.product_by_party_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Open', 'open', 'tryton-ok', default=True),
|
||||
])
|
||||
open = StateAction('stock_external_party.act_party_quantity_tree')
|
||||
|
||||
def do_open(self, action):
|
||||
pool = Pool()
|
||||
Product = pool.get('product.product')
|
||||
Lang = pool.get('ir.lang')
|
||||
|
||||
context = {}
|
||||
product_id = Transaction().context['active_id']
|
||||
context['products'] = [product_id]
|
||||
if self.start.forecast_date:
|
||||
context['stock_date_end'] = self.start.forecast_date
|
||||
else:
|
||||
context['stock_date_end'] = datetime.date.max
|
||||
action['pyson_context'] = PYSONEncoder().encode(context)
|
||||
product = Product(product_id)
|
||||
|
||||
for code in [Transaction().language, 'en_US']:
|
||||
langs = Lang.search([
|
||||
('code', '=', code),
|
||||
])
|
||||
if langs:
|
||||
break
|
||||
lang, = langs
|
||||
date = Lang.strftime(context['stock_date_end'],
|
||||
lang.code, lang.date)
|
||||
|
||||
action['name'] += ' - %s (%s) @ %s' % (product.rec_name,
|
||||
product.default_uom.rec_name, date)
|
||||
return action, {}
|
||||
|
||||
|
||||
class Period:
|
||||
__name__ = 'stock.period'
|
||||
party_caches = fields.One2Many('stock.period.cache.party', 'period',
|
||||
|
|
29
stock.xml
29
stock.xml
|
@ -4,6 +4,12 @@
|
|||
<tryton>
|
||||
<data>
|
||||
<!-- stock.move -->
|
||||
<record model="ir.ui.view" id="stock_move_view_form">
|
||||
<field name="model">stock.move</field>
|
||||
<field name="inherit" ref="stock.move_view_form"/>
|
||||
<field name="name">stock_move_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="stock_move_view_tree">
|
||||
<field name="model">stock.move</field>
|
||||
<field name="inherit" ref="stock.move_view_tree"/>
|
||||
|
@ -30,29 +36,6 @@
|
|||
<field name="act_window" ref="act_party_quantity_tree"/>
|
||||
</record>
|
||||
|
||||
<!-- product.by_party -->
|
||||
<record model="ir.action.wizard" id="wizard_product_by_party">
|
||||
<field name="name">Product By Party</field>
|
||||
<field name="wiz_name">product.by_party</field>
|
||||
<field name="model">product.product</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_party_quantity_keyword1">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.product,-1</field>
|
||||
<field name="action" ref="wizard_product_by_party"/>
|
||||
</record>
|
||||
<record model="ir.action-res.group"
|
||||
id="wizard_lot_by_location-group_stock">
|
||||
<field name="action" ref="wizard_product_by_party"/>
|
||||
<field name="group" ref="stock.group_stock"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="product_by_party_start_view_form">
|
||||
<field name="model">product.by_party.start</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">product_by_party_start_form</field>
|
||||
</record>
|
||||
|
||||
<!-- stock.period.cache.party -->
|
||||
<record model="ir.ui.view" id="period_cache_party_view_form">
|
||||
<field name="model">stock.period.cache.party</field>
|
||||
|
|
|
@ -3,4 +3,5 @@ version=3.4.0
|
|||
depends:
|
||||
stock_external
|
||||
xml:
|
||||
product.xml
|
||||
stock.xml
|
||||
|
|
|
@ -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. -->
|
||||
<data>
|
||||
<xpath expr="/form/field[@name='product']" position="after">
|
||||
<label name="party_used"/>
|
||||
<field name="party_used"/>
|
||||
</xpath>
|
||||
</data>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- The COPYRIGHT file at the top level of this repository contains the full
|
||||
copyright notices and license terms. -->
|
||||
<data>
|
||||
<xpath expr="/form/notebook/page[@id='general']/field[@name='cost_price_method']"
|
||||
position="after">
|
||||
<label name="may_belong_to_party"/>
|
||||
<field name="may_belong_to_party"/>
|
||||
</xpath>
|
||||
<xpath expr="/form/notebook/page[@id='general']" position="after">
|
||||
<page name="external_owners">
|
||||
<field name="external_owners" colspan="4"/>
|
||||
</page>
|
||||
</xpath>
|
||||
</data>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- The COPYRIGHT file at the top level of this repository contains the full
|
||||
copyright notices and license terms. -->
|
||||
<data>
|
||||
<xpath expr="/tree/field[@name='default_uom']" position="after">
|
||||
<field name="may_belong_to_party"/>
|
||||
</xpath>
|
||||
</data>
|
Loading…
Reference in New Issue