Add may_belong_to_party and owners to product and allow to change the party related to move

This commit is contained in:
Guillem Barba 2015-06-17 12:57:09 +02:00
parent 2048c56f05
commit 9f9f263146
12 changed files with 284 additions and 97 deletions

View File

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

View File

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

View File

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

View File

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

100
product.py Normal file
View File

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

42
product.xml Normal file
View File

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

View File

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

View File

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

View File

@ -3,4 +3,5 @@ version=3.4.0
depends:
stock_external
xml:
product.xml
stock.xml

9
view/stock_move_form.xml Normal file
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. -->
<data>
<xpath expr="/form/field[@name='product']" position="after">
<label name="party_used"/>
<field name="party_used"/>
</xpath>
</data>

15
view/template_form.xml Normal file
View File

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

8
view/template_tree.xml Normal file
View File

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