Replace history by revision on client

There is no need to use a custom Model to show history of record since client
manage revision of any historized model.

issue5020
review16711002
This commit is contained in:
Cédric Krier
2015-11-10 13:07:11 +01:00
parent 9ad7968f1f
commit 69d7de4aab
7 changed files with 7 additions and 217 deletions
+2
View File
@@ -1,3 +1,5 @@
* Replace history by revision on client
Version 3.8.0 - 2015-11-02
* Bug fixes (see mercurial logs for details)
* Fix origin migration from 3.4
-1
View File
@@ -11,7 +11,6 @@ def register():
Pool.register(
SaleOpportunity,
SaleOpportunityLine,
SaleOpportunityHistory,
SaleOpportunityEmployee,
OpenSaleOpportunityEmployeeStart,
SaleOpportunityMonthly,
+5 -104
View File
@@ -2,22 +2,21 @@
# this repository contains the full copyright notices and license terms.
"Sales extension for managing leads and opportunities"
import datetime
import time
from sql import Column, Literal, Null
from sql.aggregate import Min, Max, Count, Sum
from sql.conditionals import Coalesce, Case
from sql import Literal, Null
from sql.aggregate import Max, Count, Sum
from sql.conditionals import Case
from sql.functions import Extract
from trytond.model import ModelView, ModelSQL, Workflow, fields, Check
from trytond.wizard import Wizard, StateView, StateAction, Button
from trytond import backend
from trytond.pyson import Equal, Eval, Not, In, If, Get, PYSONEncoder
from trytond.pyson import Eval, In, If, Get, PYSONEncoder
from trytond.transaction import Transaction
from trytond.pool import Pool
__all__ = ['SaleOpportunity', 'SaleOpportunityLine',
'SaleOpportunityHistory', 'SaleOpportunityEmployee',
'SaleOpportunityEmployee',
'OpenSaleOpportunityEmployeeStart', 'OpenSaleOpportunityEmployee',
'SaleOpportunityMonthly', 'SaleOpportunityEmployeeMonthly']
@@ -94,8 +93,6 @@ class SaleOpportunity(Workflow, ModelSQL, ModelView):
['opportunity', 'lead', 'converted']),
},
depends=['state'], help="Percentage between 0 and 100")
history = fields.One2Many('sale.opportunity.history', 'opportunity',
'History', readonly=True)
lost_reason = fields.Text('Reason for loss', states={
'invisible': Eval('state') != 'lost',
}, depends=['state'])
@@ -244,7 +241,6 @@ class SaleOpportunity(Workflow, ModelSQL, ModelView):
default = {}
default = default.copy()
default.setdefault('reference', None)
default.setdefault('history', None)
default.setdefault('sales', None)
return super(SaleOpportunity, cls).copy(opportunities, default=default)
@@ -495,101 +491,6 @@ class SaleOpportunityLine(ModelSQL, ModelView):
return sale_line
class SaleOpportunityHistory(ModelSQL, ModelView):
'Sale Opportunity History'
__name__ = 'sale.opportunity.history'
date = fields.DateTime('Change Date')
opportunity = fields.Many2One('sale.opportunity', 'Sale Opportunity')
user = fields.Many2One('res.user', 'User')
party = fields.Many2One('party.party', 'Party', datetime_field='date')
address = fields.Many2One('party.address', 'Address',
datetime_field='date')
company = fields.Many2One('company.company', 'Company',
datetime_field='date')
employee = fields.Many2One('company.employee', 'Employee',
datetime_field='date')
start_date = fields.Date('Start Date')
end_date = fields.Date('End Date')
description = fields.Char('Description')
comment = fields.Text('Comment')
lines = fields.Function(fields.One2Many('sale.opportunity.line', None,
'Lines', datetime_field='date'), 'get_lines')
amount = fields.Numeric('Amount', digits=(16, Eval('currency_digits', 2)),
depends=['currency_digits'])
currency = fields.Function(fields.Many2One('currency.currency',
'Currency'), 'get_currency')
currency_digits = fields.Function(fields.Integer('Currency Digits'),
'get_currency_digits')
state = fields.Selection(STATES, 'State')
probability = fields.Integer('Conversion Probability')
lost_reason = fields.Text('Reason for loss', states={
'invisible': Not(Equal(Eval('state'), 'lost')),
}, depends=['state'])
@classmethod
def __setup__(cls):
super(SaleOpportunityHistory, cls).__setup__()
cls._order.insert(0, ('date', 'DESC'))
def get_currency(self, name):
return self.company.currency.id
def get_currency_digits(self, name):
return self.company.currency.digits
@classmethod
def table_query(cls):
Opportunity = Pool().get('sale.opportunity')
opportunity_history = Opportunity.__table_history__()
columns = [
Min(Column(opportunity_history, '__id')).as_('id'),
opportunity_history.id.as_('opportunity'),
Min(Coalesce(opportunity_history.write_date,
opportunity_history.create_date)).as_('date'),
Coalesce(opportunity_history.write_uid,
opportunity_history.create_uid).as_('user'),
]
group_by = [
opportunity_history.id,
Coalesce(opportunity_history.write_uid,
opportunity_history.create_uid),
]
for name, field in cls._fields.iteritems():
if name in ('id', 'opportunity', 'date', 'user'):
continue
if hasattr(field, 'set'):
continue
column = Column(opportunity_history, name)
columns.append(column.as_(name))
group_by.append(column)
return opportunity_history.select(*columns, group_by=group_by)
def get_lines(self, name):
Line = Pool().get('sale.opportunity.line')
# We will always have only one id per call due to datetime_field
lines = Line.search([
('opportunity', '=', self.opportunity.id),
])
return [l.id for l in lines]
@classmethod
def read(cls, ids, fields_names=None):
res = super(SaleOpportunityHistory, cls).read(ids,
fields_names=fields_names)
# Remove microsecond from timestamp
for values in res:
if 'date' in values:
if isinstance(values['date'], basestring):
values['date'] = datetime.datetime(
*time.strptime(values['date'],
'%Y-%m-%d %H:%M:%S.%f')[:6])
values['date'] = values['date'].replace(microsecond=0)
values['date'] += datetime.timedelta(seconds=1)
return res
class SaleOpportunityReportMixin:
number = fields.Integer('Number')
converted = fields.Integer('Converted')
-46
View File
@@ -249,52 +249,6 @@ this repository contains the full copyright notices and license terms. -->
<field name="perm_delete" eval="True"/>
</record>
<record model="ir.ui.view" id="opportunity_history_view_form">
<field name="model">sale.opportunity.history</field>
<field name="type">form</field>
<field name="name">opportunity_history_form</field>
</record>
<record model="ir.ui.view" id="opportunity_history_view_tree">
<field name="model">sale.opportunity.history</field>
<field name="type">tree</field>
<field name="name">opportunity_history_tree</field>
</record>
<record model="ir.model.access" id="access_opportunity_history">
<field name="model" search="[('model', '=', 'sale.opportunity.history')]"/>
<field name="perm_read" eval="False"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.model.access" id="access_opportunity_history_sale">
<field name="model" search="[('model', '=', 'sale.opportunity.history')]"/>
<field name="group" ref="sale.group_sale"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.model.access" id="access_opportunity_history_opportunity">
<field name="model" search="[('model', '=', 'sale.opportunity.history')]"/>
<field name="group" ref="group_opportunity"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<record model="ir.rule.group" id="rule_group_opportunity_history">
<field name="model" search="[('model', '=', 'sale.opportunity.history')]"/>
<field name="global_p" eval="True"/>
</record>
<record model="ir.rule" id="rule_group_opportunity_history1">
<field name="domain"
eval="[('company', '=', Eval('user', {}).get('company', None))]"
pyson="1"/>
<field name="rule_group" ref="rule_group_opportunity_history"/>
</record>
<record model="ir.ui.view" id="opportunity_employee_view_tree">
<field name="model">sale.opportunity_employee</field>
<field name="type">tree</field>
-3
View File
@@ -57,8 +57,5 @@ this repository contains the full copyright notices and license terms. -->
<page name="sales">
<field name="sales" colspan="4"/>
</page>
<page name="history">
<field name="history"/>
</page>
</notebook>
</form>
-47
View File
@@ -1,47 +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. -->
<form string="History">
<label name="opportunity"/>
<field name="opportunity" colspan="3"/>
<label name="user"/>
<field name="user"/>
<label name="date"/>
<field name="date"/>
<label name="party"/>
<field name="party"/>
<label name="address"/>
<field name="address"/>
<label name="description"/>
<field name="description"/>
<label name="amount"/>
<group col="2" id="amount_currency">
<field name="amount"/>
<field name="currency"/>
</group>
<label name="probability"/>
<field name="probability"/>
<notebook colspan="4">
<page string="Lead/Opportunity" id="opportunity">
<label name="company"/>
<field name="company"/>
<label name="employee"/>
<field name="employee"/>
<label name="start_date"/>
<field name="start_date"/>
<label name="end_date"/>
<field name="end_date"/>
<separator name="comment" colspan="4"/>
<field name="comment" colspan="4"/>
<separator name="lost_reason" colspan="4"/>
<field name="lost_reason" colspan="4"/>
<group col="2" colspan="2" id="state">
<label name="state"/>
<field name="state"/>
</group>
</page>
<page name="lines">
<field name="lines"/>
</page>
</notebook>
</form>
-16
View File
@@ -1,16 +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. -->
<tree string="History">
<field name="date" widget="date"/>
<field name="date" widget="time" string="Change Time"/>
<field name="user"/>
<field name="start_date"/>
<field name="end_date"/>
<field name="description"/>
<field name="party"/>
<field name="amount"/>
<field name="currency"/>
<field name="state"/>
<field name="probability"/>
</tree>