Use similar design as for sale_promotion

- Add start/end date criteria
- Remove required on price list
- Change modification right to sale administrator group

issue4678
review11131002
This commit is contained in:
Cédric Krier committed 2015-05-11 15:27:31 +02:00
1 parent 4f5c104bad
commit 900708e481
13 files changed
+140 -70

No files matched your search

+5 -1
View File
@@ -1,2 +1,6 @@
* Add start/end date criteria
* Remove required on price list
* Change modification right to sale administrator group
Version 3.6.0 - 2015-04-20
* Initial release
* Initial release
-2
View File
@@ -3,7 +3,6 @@
from trytond.pool import Pool
from .sale import *
from .price_list import *
def register():
@@ -12,5 +11,4 @@ def register():
SaleExtraLine,
Sale,
SaleLine,
PriceList,
module='sale_extra', type_='model')
+4 -2
View File
@@ -11,9 +11,11 @@ The criteria are defined by the *Sale Extras* of the *Price List*.
Sale Extra
**********
Each matching *Sale Extra* of the *Price List* is evaluated to add an extra
line. The criteria are the fields:
Each matching *Sale Extra* is evaluated to add an extra line.
The criteria are the fields:
- *Price List*
- *Start/End Date*
- *Sale Amount*: If untaxed sale amount is greater or equal
(in the price list company currency).
-13
View File
@@ -1,13 +0,0 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.pool import PoolMeta
from trytond.model import fields
__all__ = ['PriceList']
__metaclass__ = PoolMeta
class PriceList:
__name__ = 'product.price_list'
sale_extras = fields.One2Many('sale.extra', 'price_list', 'Sale Extras')
-12
View File
@@ -1,12 +0,0 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.ui.view" id="price_list_view_form">
<field name="model">product.price_list</field>
<field name="inherit" ref="product_price_list.price_list_view_form"/>
<field name="name">price_list_form</field>
</record>
</data>
</tryton>
+90 -14
View File
@@ -1,10 +1,15 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import datetime
from decimal import Decimal
from sql import Null
from trytond.pool import PoolMeta, Pool
from trytond.model import ModelSQL, ModelView, MatchMixin, Workflow, fields
from trytond.pyson import Eval
from trytond.pyson import Eval, If
from trytond.transaction import Transaction
from trytond import backend
__all__ = ['Sale', 'SaleLine',
'SaleExtra', 'SaleExtraLine']
@@ -55,9 +60,38 @@ class SaleExtra(ModelSQL, ModelView, MatchMixin):
__name__ = 'sale.extra'
name = fields.Char('Name', translate=True, required=True)
company = fields.Many2One('company.company', 'Company', required=True,
states={
'readonly': Eval('id', 0) > 0,
},
domain=[
('id', If(Eval('context', {}).contains('company'), '=', '!='),
Eval('context', {}).get('company', -1)),
],
select=True)
active = fields.Boolean('Active')
start_date = fields.Date('Start Date',
domain=['OR',
('start_date', '<=', If(~Eval('end_date', None),
datetime.date.max,
Eval('end_date', datetime.date.max))),
('start_date', '=', None),
],
depends=['end_date'])
end_date = fields.Date('End Date',
domain=['OR',
('end_date', '>=', If(~Eval('start_date', None),
datetime.date.min,
Eval('start_date', datetime.date.min))),
('end_date', '=', None),
],
depends=['start_date'])
price_list = fields.Many2One('product.price_list', 'Price List',
required=True, ondelete='CASCADE')
ondelete='CASCADE',
domain=[
('company', '=', Eval('company', -1)),
],
depends=['company'])
sale_amount = fields.Numeric('Sale Amount',
digits=(16, Eval('currency_digits', 2)),
depends=['currency_digits'])
@@ -65,38 +99,80 @@ class SaleExtra(ModelSQL, ModelView, MatchMixin):
'on_change_with_currency_digits')
lines = fields.One2Many('sale.extra.line', 'extra', 'Lines')
@classmethod
def __register__(cls, module_name):
pool = Pool()
PriceList = pool.get('product.price_list')
TableHandler = backend.get('TableHandler')
cursor = Transaction().cursor
sql_table = cls.__table__()
price_list = PriceList.__table__()
super(SaleExtra, cls).__register__(module_name)
table = TableHandler(cursor, cls, module_name)
# Migration from 3.6: price_list not required and new company
table.not_null_action('price_list', 'remove')
query = sql_table.join(price_list,
condition=sql_table.price_list == price_list.id
).select(sql_table.id, price_list.company,
where=sql_table.company == Null)
cursor.execute(*query)
for extra_id, company_id in cursor.fetchall():
query = sql_table.update([sql_table.company], [company_id],
where=sql_table.id == extra_id)
cursor.execute(*query)
@staticmethod
def default_company():
return Transaction().context.get('company')
@staticmethod
def default_active():
return True
@fields.depends('price_list')
@fields.depends('company')
def on_change_with_currency_digits(self, name=None):
if self.price_list.company:
return self.price_list.company.currency.digits
if self.company:
return self.company.currency.digits
return 2
@classmethod
def _extras_domain(cls, sale):
return [
['OR',
('start_date', '<=', sale.sale_date),
('start_date', '=', None),
],
['OR',
('end_date', '=', None),
('end_date', '>=', sale.sale_date),
],
['OR',
('price_list', '=', None),
('price_list', '=',
sale.price_list.id if sale.price_list else None),
],
('company', '=', sale.company.id),
]
@classmethod
def get_lines(cls, sale, pattern=None):
'Return extra sale lines'
'Yield extra sale lines'
pool = Pool()
Currency = pool.get('currency.currency')
if not sale.price_list:
return []
extras = cls.search(cls._extras_domain(sale))
if pattern is None:
pattern = {}
pattern['sale_amount'] = Currency.compute(sale.currency,
sale.untaxed_amount, sale.company.currency)
lines = []
for extra in sale.price_list.sale_extras:
for extra in extras:
if extra.match(pattern):
for line in extra.lines:
if line.match(pattern):
lines.append(line.get_line(sale))
yield line.get_line(sale)
break
return lines
def match(self, pattern):
pattern = pattern.copy()
+25 -11
View File
@@ -16,10 +16,11 @@ this repository contains the full copyright notices and license terms. -->
</record>
<record model="ir.action.act_window" id="act_extra_form">
<field name="name">Sale Extras</field>
<field name="name">Extras</field>
<field name="res_model">sale.extra</field>
<field name="domain"
eval="[('price_list', 'in', Eval('active_ids'))]"
<field name="domain"></field>
<field name="search_value"
eval="['OR', ('end_date', '>=', Date()), ('end_date', '=', None)]"
pyson="1"/>
</record>
<record model="ir.action.act_window.view" id="act_extra_form_view1">
@@ -32,10 +33,23 @@ this repository contains the full copyright notices and license terms. -->
<field name="view" ref="extra_view_form"/>
<field name="act_window" ref="act_extra_form"/>
</record>
<record model="ir.action.keyword" id="act_extra_keyword1">
<menuitem parent="sale.menu_configuration" action="act_extra_form"
id="menu_extra"/>
<record model="ir.action.act_window" id="act_extra_relate">
<field name="name">Sale Extras</field>
<field name="res_model">sale.extra</field>
<field name="domain"
eval="[('price_list', 'in', Eval('active_ids', []))]"
pyson="1"/>
<field name="search_value"
eval="['OR', ('end_date', '>=', Date()), ('end_date', '=', None)]"
pyson="1"/>
</record>
<record model="ir.action.keyword" id="act_extra_relate_keyword1">
<field name="keyword">form_relate</field>
<field name="model">product.price_list,-1</field>
<field name="action" ref="act_extra_form"/>
<field name="action" ref="act_extra_relate"/>
</record>
<record model="ir.rule.group" id="rule_group_extra">
@@ -44,7 +58,7 @@ this repository contains the full copyright notices and license terms. -->
</record>
<record model="ir.rule" id="rule_extra1">
<field name="domain"
eval="[('price_list.company', '=', Eval('user', {}).get('company', None))]"
eval="[('company', '=', Eval('user', {}).get('company', None))]"
pyson="1"/>
<field name="rule_group" ref="rule_group_extra"/>
</record>
@@ -56,9 +70,9 @@ this repository contains the full copyright notices and license terms. -->
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.model.access" id="access_extra_product_admin">
<record model="ir.model.access" id="access_extra_sale_admin">
<field name="model" search="[('model', '=', 'sale.extra')]"/>
<field name="group" ref="product.group_product_admin"/>
<field name="group" ref="sale.group_sale_admin"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
@@ -91,7 +105,7 @@ this repository contains the full copyright notices and license terms. -->
</record>
<record model="ir.rule" id="rule_extra_line1">
<field name="domain"
eval="[('extra.price_list.company', '=', Eval('user', {}).get('company', None))]"
eval="[('extra.company', '=', Eval('user', {}).get('company', None))]"
pyson="1"/>
<field name="rule_group" ref="rule_group_extra_line"/>
</record>
@@ -103,9 +117,9 @@ this repository contains the full copyright notices and license terms. -->
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.model.access" id="access_extra_line_product_admin">
<record model="ir.model.access" id="access_extra_line_sale_admin">
<field name="model" search="[('model', '=', 'sale.extra.line')]"/>
<field name="group" ref="product.group_product_admin"/>
<field name="group" ref="sale.group_sale_admin"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
+1 -1
View File
@@ -41,7 +41,7 @@ if minor_version % 2:
'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
name[8:], name, version))
requires = []
requires = ['python-sql']
for dep in info.get('depends', []):
if not re.match(r'(ir|res|webdav)(\W|$)', dep):
requires.append(get_require_version('trytond_%s' % dep))
+5 -2
View File
@@ -94,8 +94,11 @@ Create payment term::
Create Extra::
>>> PriceList = Model.get('product.price_list')
>>> Extra = Model.get('sale.extra')
>>> price_list = PriceList(name='Default')
>>> extra = price_list.sale_extras.new(name='Free Extra')
>>> price_list.save()
>>> extra = Extra(name='Free Extra')
>>> extra.price_list = price_list
>>> line = extra.lines.new()
>>> line.sale_amount = Decimal('100')
>>> line.product = extra_product
@@ -105,7 +108,7 @@ Create Extra::
>>> line.sale_amount = Decimal('50')
>>> line.product = extra_product
>>> line.quantity = 1
>>> price_list.save()
>>> extra.save()
Sale for 100, 2 free extra added::
-1
View File
@@ -10,4 +10,3 @@ depends:
sale_price_list
xml:
sale.xml
price_list.xml
+7 -1
View File
@@ -6,9 +6,15 @@ this repository contains the full copyright notices and license terms. -->
<field name="name"/>
<label name="active"/>
<field name="active"/>
<label name="start_date"/>
<field name="start_date"/>
<label name="end_date"/>
<field name="end_date"/>
<label name="company"/>
<field name="company"/>
<label name="price_list"/>
<field name="price_list"/>
<newline/>
<separator id="pattern" colspan="4"/>
<label name="sale_amount"/>
<field name="sale_amount"/>
<field name="lines" colspan="4"
+3
View File
@@ -4,6 +4,9 @@ this repository contains the full copyright notices and license terms. -->
<tree string="Extras">
<field name="price_list"/>
<field name="name"/>
<field name="start_date"/>
<field name="end_date"/>
<field name="company"/>
<field name="sale_amount"/>
<field name="active" tree_invisible="1"/>
</tree>
-10
View File
@@ -1,10 +0,0 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<data>
<xpath expr="/form/notebook" position="inside">
<page name="sale_extras">
<field name="sale_extras" colspan="4"/>
</page>
</xpath>
</data>