[IMP] improved idea module

bzr revid: fp@tinyerp.com-20120607175158-pspvowjp3hnbn09m
This commit is contained in:
Fabien Pinckaers 2012-06-07 19:51:58 +02:00
parent 001d2e84c9
commit 7a72294603
15 changed files with 51 additions and 1110 deletions

View File

@ -910,7 +910,7 @@ class crm_lead(base_stage, osv.osv):
if action == 'log': prefix = 'Logged'
else: prefix = 'Scheduled'
message = _("<b>%s a call</b> for the <em>%s</em>.") % (prefix, phonecall.date)
return self. message_append_note(cr, uid, ids, body=message, context=context)
return self.message_append_note(cr, uid, ids, body=message, context=context)
def _lead_set_partner_send_note(self, cr, uid, ids, context=None):
for lead in self.browse(cr, uid, ids, context=context):

View File

@ -20,7 +20,4 @@
##############################################################################
import idea
import wizard
import report
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -40,19 +40,15 @@ Once installed, check the menu 'Ideas' in the 'Tools' main menu.""",
'update_xml': [
'security/idea_security.xml',
'security/ir.model.access.csv',
'wizard/idea_post_vote_view.xml',
'idea_view.xml',
'idea_workflow.xml',
'report/report_vote_view.xml',
],
'demo_xml': [
"idea_data.xml"
],
'test':[
'test/test_idea.yml'
],
'installable': True,
'certificate': '0071515601309',
'images': ['images/1_ideas.jpeg','images/2_idea_categories.jpeg','images/3_vote_idea.jpeg'],
'images': [],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -30,349 +30,59 @@ DefaultVoteValue = '50'
class idea_category(osv.osv):
""" Category of Idea """
def name_get(self, cr, uid, ids, context=None):
if not len(ids):
return []
reads = self.read(cr, uid, ids, ['name','parent_id'], context=context)
res = []
for record in reads:
name = record['name']
if record['parent_id']:
name = record['parent_id'][1]+' / '+name
res.append((record['id'], name))
return res
def _categ_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
res = self.name_get(cr, uid, ids, context=context)
return dict(res)
_name = "idea.category"
_description = "Idea Category"
_columns = {
'name': fields.char('Category', size=64, required=True),
'complete_name': fields.function(_categ_name_get_fnc, type="char", string='Name'),
'summary': fields.text('Summary'),
'parent_id': fields.many2one('idea.category', 'Parent Categories', ondelete='set null', select=True),
'child_ids': fields.one2many('idea.category', 'parent_id', 'Child Categories'),
'visibility':fields.boolean('Open Idea?', required=False, help="If True creator of the idea will be visible to others"),
'name': fields.char('Category Name', size=64, required=True),
}
_sql_constraints = [
('name', 'unique(parent_id,name)', 'The name of the category must be unique' )
('name', 'unique(name)', 'The name of the category must be unique' )
]
_order = 'parent_id,name asc'
_constraints = [
(osv.osv._check_recursion, 'Error ! You cannot create recursive categories.', ['parent_id'])
]
_order = 'name asc'
idea_category()
class idea_idea(osv.osv):
""" Idea """
_name = 'idea.idea'
_rec_name = 'name'
def _vote_avg_compute(self, cr, uid, ids, name, arg, context=None):
""" compute average for voting
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of votings IDs
@return: dictionay of Idea """
if not ids:
return {}
sql = """SELECT i.id, avg(v.score::integer)
FROM idea_idea i LEFT OUTER JOIN idea_vote v ON i.id = v.idea_id
WHERE i.id IN %s
GROUP BY i.id
"""
cr.execute(sql, (tuple(ids),))
return dict(cr.fetchall())
def _vote_count(self, cr, uid, ids, name, arg, context=None):
""" count number of vote
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of voting counts IDs
@return: dictionay of Idea """
if not ids:
return {}
sql = """SELECT i.id, COUNT(1)
FROM idea_idea i LEFT OUTER JOIN idea_vote v ON i.id = v.idea_id
WHERE i.id IN %s
GROUP BY i.id
"""
cr.execute(sql, (tuple(ids),))
return dict(cr.fetchall())
def _comment_count(self, cr, uid, ids, name, arg, context=None):
""" count number of comment
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of comments IDs
@return: dictionay of Idea """
if not ids:
return {}
sql = """SELECT i.id, COUNT(1)
FROM idea_idea i LEFT OUTER JOIN idea_comment c ON i.id = c.idea_id
WHERE i.id IN %s
GROUP BY i.id
"""
cr.execute(sql, (tuple(ids),))
return dict(cr.fetchall())
def _vote_read(self, cr, uid, ids, name, arg, context=None):
""" Read Vote
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of vote reads IDs """
res = {}
for id in ids:
res[id] = '-1'
vote_obj = self.pool.get('idea.vote')
votes_ids = vote_obj.search(cr, uid, [('idea_id', 'in', ids), ('user_id', '=', uid)])
vote_obj_id = vote_obj.browse(cr, uid, votes_ids, context=context)
for vote in vote_obj_id:
res[vote.idea_id.id] = vote.score
return res
def _vote_save(self, cr, uid, id, field_name, field_value, arg, context=None):
""" save Vote
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of vote saves IDs """
vote_obj = self.pool.get('idea.vote')
vote = vote_obj.search(cr, uid, [('idea_id', '=', id), ('user_id', '=', uid)])
textual_value = str(field_value)
if vote:
if int(field_value) >= 0:
vote_obj.write(cr, uid, vote, {'score': textual_value })
else:
vote_obj.unlink(cr, uid, vote)
else:
if int(field_value) >= 0:
vote_obj.create(cr, uid, {'idea_id': id, 'user_id': uid, 'score': textual_value })
_inherit = ['mail.thread']
_columns = {
'user_id': fields.many2one('res.users', 'Creator', required=True, readonly=True),
'create_uid': fields.many2one('res.users', 'Creator', required=True, readonly=True),
'name': fields.char('Idea Summary', size=64, required=True, readonly=True, oldname='title', states={'draft':[('readonly',False)]}),
'description': fields.text('Description', help='Content of the idea', readonly=True, states={'draft':[('readonly',False)]}),
'comment_ids': fields.one2many('idea.comment', 'idea_id', 'Comments'),
'created_date': fields.datetime('Creation date', readonly=True),
'open_date': fields.datetime('Open date', readonly=True, help="Date when an idea opened"),
'vote_ids': fields.one2many('idea.vote', 'idea_id', 'Vote'),
'my_vote': fields.function(_vote_read, fnct_inv = _vote_save, string="My Vote", type="selection", selection=VoteValues),
'vote_avg': fields.function(_vote_avg_compute, string="Average Score", type="float"),
'count_votes': fields.function(_vote_count, string="Count of votes", type="integer"),
'count_comments': fields.function(_comment_count, string="Count of comments", type="integer"),
'category_id': fields.many2one('idea.category', 'Category', required=True, readonly=True, states={'draft':[('readonly',False)]}),
'category_ids': fields.many2many('idea.category', 'Tags', readonly=True, states={'draft':[('readonly',False)]}),
'state': fields.selection([('draft', 'New'),
('open', 'Opened'),
('open', 'Accepted'),
('cancel', 'Refused'),
('close', 'Accepted')],
'Status', readonly=True,
help='When the Idea is created the state is \'Draft\'.\n It is \
opened by the user, the state is \'Opened\'.\
\nIf the idea is accepted, the state is \'Accepted\'.'
),
'visibility':fields.boolean('Open Idea?', required=False),
'stat_vote_ids': fields.one2many('idea.vote.stat', 'idea_id', 'Statistics', readonly=True),
'vote_limit': fields.integer('Maximum Vote per User',
help="Set to one if you require only one Vote per user"),
('close', 'Done')],
'Status', readonly=True
)
}
_sql_constraints = [
('name', 'unique(name)', 'The name of the idea must be unique' )
]
_defaults = {
'user_id': lambda self,cr,uid,context: uid,
'my_vote': lambda *a: '-1',
'state': lambda *a: 'draft',
'vote_limit': lambda * a: 1,
'created_date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'visibility': lambda *a: True,
}
_order = 'id desc'
_order = 'name asc'
def create(self, cr, user, vals, context=None):
"""
Create a new record for a model idea_idea
@param cr: A database cursor
@param user: ID of the user currently logged in
@param vals: provides data for new record
@param context: context arguments, like lang, time zone
@return: Returns an id of the new record
"""
visibility = False
if vals.get('category_id', False):
category_pool = self.pool.get('idea.category')
category = category_pool.browse(cr, user, vals.get('category_id'), context=context)
visibility = category.visibility
vals.update({
'visibility':visibility
})
res_id = super(idea_idea, self).create(cr, user, vals, context=context)
return res_id
def copy(self, cr, uid, id, default={}, context=None):
"""
Create the new record in idea_idea model from existing one
@param cr: A database cursor
@param user: ID of the user currently logged in
@param id: list of record ids on which copy method executes
@param default: dict type contains the values to be overridden during copy of object
@param context: context arguments, like lang, time zone
@return: Returns the id of the new record
"""
default.update({
'comment_ids':False,
'vote_ids':False,
'stat_vote_ids':False
})
res_id = super(idea_idea, self).copy(cr, uid, id, default, context=context)
return res_id
def write(self, cr, user, ids, vals, context=None):
"""
Update redord(s) exist in {ids}, with new value provided in {vals}
@param cr: A database cursor
@param user: ID of the user currently logged in
@param ids: list of record ids to update
@param vals: dict of new values to be set
@param context: context arguments, like lang, time zone
@return: Returns True on success, False otherwise
"""
state = self.browse(cr, user, ids[0], context=context).state
if vals.get('my_vote', False):
if vals.get('state', state) != 'open':
raise osv.except_osv(_("Warning !"), _("You can not vote on a Draft/Accepted/Cancelled ideas."))
res = super(idea_idea, self).write(cr, user, ids, vals, context=context)
return res
def idea_cancel(self, cr, uid, ids):
def idea_cancel(self, cr, uid, ids, context={}):
self.write(cr, uid, ids, { 'state': 'cancel' })
self.message_append_note(cr, uid, ids, body=_('Idea canceled.'), context=context)
return True
def idea_open(self, cr, uid, ids):
self.write(cr, uid, ids, { 'state': 'open' ,'open_date': time.strftime('%Y-%m-%d %H:%M:%S')})
def idea_open(self, cr, uid, ids, context={}):
self.write(cr, uid, ids, { 'state': 'open'})
self.message_append_note(cr, uid, ids, body=_('Idea accepted.'), context=context)
return True
def idea_close(self, cr, uid, ids):
def idea_close(self, cr, uid, ids, context={}):
self.message_append_note(cr, uid, ids, body=_('Idea done.'), context=context)
self.write(cr, uid, ids, { 'state': 'close' })
return True
def idea_draft(self, cr, uid, ids):
def idea_draft(self, cr, uid, ids, context={}):
self.message_append_note(cr, uid, ids, body=_('Idea reset to draft.'), context=context)
self.write(cr, uid, ids, { 'state': 'draft' })
return True
idea_idea()
class idea_comment(osv.osv):
""" Apply Idea for Comment """
_name = 'idea.comment'
_description = 'Comment'
_rec_name = 'content'
_columns = {
'idea_id': fields.many2one('idea.idea', 'Idea', required=True, ondelete='cascade'),
'user_id': fields.many2one('res.users', 'User', required=True),
'content': fields.text('Comment', required=True),
'create_date': fields.datetime('Creation date', readonly=True),
}
_defaults = {
'user_id': lambda self, cr, uid, context: uid
}
_order = 'id desc'
idea_comment()
class idea_vote(osv.osv):
""" Apply Idea for Vote """
_name = 'idea.vote'
_description = 'Idea Vote'
_rec_name = 'score'
_columns = {
'user_id': fields.many2one('res.users', 'User', readonly="True"),
'idea_id': fields.many2one('idea.idea', 'Idea', readonly="True", ondelete='cascade'),
'score': fields.selection(VoteValues, 'Vote Status', readonly="True"),
'date': fields.datetime('Date', readonly="True"),
'comment': fields.text('Comment', readonly="True"),
}
_defaults = {
'score': lambda *a: DefaultVoteValue,
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
}
idea_vote()
class idea_vote_stat(osv.osv):
""" Idea votes Statistics """
_name = 'idea.vote.stat'
_description = 'Idea Votes Statistics'
_auto = False
_rec_name = 'idea_id'
_columns = {
'idea_id': fields.many2one('idea.idea', 'Idea', readonly=True),
'score': fields.selection(VoteValues, 'Score', readonly=True),
'nbr': fields.integer('Number of Votes', readonly=True),
}
def init(self, cr):
"""
initialize the sql view for the stats
cr -- the cursor
"""
cr.execute("""
CREATE OR REPLACE VIEW idea_vote_stat AS (
SELECT
MIN(v.id) AS id,
i.id AS idea_id,
v.score,
COUNT(1) AS nbr
FROM
idea_vote v
LEFT JOIN idea_idea i ON (v.idea_id = i.id)
GROUP BY
i.id, v.score, i.id )
""")
idea_vote_stat()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -2,31 +2,14 @@
<openerp>
<data>
<record model="idea.category" id="idea_category_general">
<field name="name">General</field>
<field name="summary">General Ideas</field>
<field name="visibility">True</field>
<record model="idea.category" id="idea_category_sales">
<field name="name">Sales</field>
</record>
<record model="idea.category" id="idea_category_general">
<field name="name">Organization</field>
</record>
<record model="idea.category" id="idea_category_technical">
<field name="name">Technical</field>
<field name="summary">Technical Ideas</field>
<field name="visibility">True</field>
</record>
<record model="idea.idea" id="idea_idea_one">
<field name="name">TODO: Need to put a good idea on OpenERP</field>
<field name="description">TODO: Need to put a good idea on OpenERP</field>
<field name="category_id" ref="idea_category_general"/>
<field name="visibility">True</field>
</record>
<record model="idea.idea" id="idea_idea_two">
<field name="name">Technical presentation for 1 hours in every day</field>
<field name="description">Technical presentation for 1 hours in every day</field>
<field name="category_id" ref="idea_category_technical"/>
<field name="visibility">True</field>
<field name="state">open</field>
</record>
<record id="base.user_demo" model="res.users">

View File

@ -8,14 +8,7 @@
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Ideas Categories">
<group>
<field name="name" string="Category"/>
<field name="parent_id" widget="selection"/>
</group>
<newline/>
<group expand="0" string="Group By...">
<filter string="Parent Category" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'parent_id'}"/>
</group>
<field name="name"/>
</search>
</field>
</record>
@ -26,14 +19,10 @@
<field name="model">idea.category</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Category of ideas">
<group col="4">
<form string="Category of Ideas">
<group>
<field name="name"/>
<field name="parent_id"/>
<field name="visibility"/>
</group>
<separator string="Description"/>
<field name="summary"/>
</form>
</field>
</record>
@ -43,11 +32,10 @@
<field name="name">idea.category.tree</field>
<field name="model">idea.category</field>
<field name="type">tree</field>
<field name="field_parent">child_ids</field>
<field name="field_parent"></field>
<field name="arch" type="xml">
<tree string="Category of ideas">
<field name="complete_name"/>
<field name="parent_id" invisible="1"/>
<field name="name"/>
</tree>
</field>
</record>
@ -70,95 +58,6 @@
<menuitem name="Categories" parent="menu_ideas" id="menu_idea_category" action="action_idea_category" />
<!-- Idea Category Action -->
<record model="ir.actions.act_window" id="action_idea_category_tree">
<field name="name">Ideas by Categories</field>
<field name="res_model">idea.category</field>
<field name="view_type">tree</field>
<field name="domain">[('parent_id','=',False)]</field>
</record>
<menuitem name="Ideas" parent="base.menu_tools" id="menu_ideas1" sequence="4"/>
<!-- Open Ideas Action -->
<record model="ir.actions.act_window" id="action_idea_idea_categ_open">
<field name="name">Open Ideas</field>
<field name="res_model">idea.idea</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('state','=','open'),('category_id','child_of',[active_id])]</field>
</record>
<record model="ir.values" id="action_idea_idea_categ_open_val">
<field name="key2" eval=" 'tree_but_open'" />
<field name="model" eval="'idea.category'" />
<field name="name">Ideas</field>
<field name="value" eval="'ir.actions.act_window,'+str(action_idea_idea_categ_open)" />
</record>
<!--Vote For Idea Tree View -->
<record model="ir.ui.view" id="view_idea_vote_tree">
<field name="name">idea.vote.tree</field>
<field name="model">idea.vote</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Votes">
<field name="user_id" />
<field name="idea_id"/>
<field name="score"/>
<field name="date"/>
</tree>
</field>
</record>
<!--Vote For Idea Form View -->
<record model="ir.ui.view" id="view_idea_vote_form">
<field name="name">idea.vote.form</field>
<field name="model">idea.vote</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Votes">
<group col="4">
<field name="user_id"/>
<field name="date"/>
<field name="score"/>
</group>
<separator string="Comments"/>
<field name="comment"/>
</form>
</field>
</record>
<!-- Search view for Idea vote -->
<record model="ir.ui.view" id="view_idea_vote_search">
<field name="name">idea.vote.search</field>
<field name="model">idea.vote</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Ideas vote">
<group>
<field name="idea_id" widget="selection"/>
<field name="user_id" string="User"/>
</group>
<newline/>
<group expand="0" string="Group By...">
<filter string="User" name="user" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
<separator orientation="vertical"/>
<filter string="Idea" icon="terp-idea" domain="[]" context="{'group_by':'idea_id'}"/>
<separator orientation="vertical"/>
<filter string="Vote Date" icon="terp-go-month" domain="[]" context="{'group_by':'date'}"/>
</group>
</search>
</field>
</record>
<!-- New Idea Form View -->
<record model="ir.ui.view" id="view_idea_idea_form">
@ -173,66 +72,17 @@
<button name="idea_cancel" string="Refuse" states="open" />
<field name="state" widget="statusbar" statusbar_visible="draft,open,close"/>
</header>
<sheet>
<label for="name" class="oe_form_readonly_hidden"/>
<h1><field name="name"/></h1>
<label for="category_id"/>
<h2><field name="category_id"/></h2>
<group col="4">
<field name="open_date"/>
<field name="user_id" attrs="{'invisible':[('visibility','=',False)]}"/>
<field name="visibility" invisible="1"/>
<field name="vote_avg" widget="progressbar"/>
<label name="my_vote">
<div>
<field name="my_vote" readonly="1"/>
<button name="%(idea.action_idea_post_vote)d" icon="gtk-execute" states="open" type="action" string="Submit Vote"/>
</div>
</group>
<notebook>
<page string="Idea Detail">
<field name="description" nolabel="1" colspan="4" widget="text_wiki"/>
</page>
<page string="Comments">
<field name="comment_ids" nolabel="1" colspan="4">
<form string="Comment">
<separator string="Your Comment" colspan="4"/>
<field name="content" nolabel="1" />
</form>
<tree string="Comments">
<field name="create_date"/>
<field name="content"/>
</tree>
</field>
</page>
<page string="History">
<field name="vote_ids" nolabel="1" colspan="4" readonly="True">
<tree string="Votes">
<field name="user_id"/>
<field name="score" />
</tree>
</field>
</page>
<page string="Statistics">
<group col="6" colspan="4">
<field name="count_comments" />
<field name="count_votes" />
</group>
<field name="stat_vote_ids" colspan="4" mode="graph,tree" nolabel="1">
<graph string="Votes Statistics" type="bar">
<field name="score"/>
<field name="nbr"/>
</graph>
<tree string="Votes Statistics">
<field name="score"/>
<field name="nbr"/>
</tree>
</field>
</page>
</notebook>
</sheet>
</form>
<sheet>
<label for="name" class="oe_form_readonly_hidden"/>
<h1><field name="name"/></h1>
<label for="category_ids"/>
<h2><field name="category_ids"/></h2>
<field name="description"/>
</sheet>
<footer>
<field name="message_ids" widget="ThreadView"/>
</footer>
</form>
</field>
</record>
@ -245,12 +95,7 @@
<field name="arch" type="xml">
<tree colors="blue:state == 'draft';black:state in ('open','close');gray:state == 'cancel'" string="Ideas">
<field name="name"/>
<field name="category_id"/>
<field name="user_id"/>
<field name="created_date"/>
<field name="vote_avg" widget="progressbar"/>
<field name="count_comments"/>
<field name="count_votes"/>
<field name="create_uid"/>
<field name="state"/>
</tree>
</field>
@ -271,14 +116,14 @@
domain="[('state','=','close')]" help="Accepted Ideas" />
<separator orientation="vertical"/>
<field name="name"/>
<field name="category_id"/>
<field name="user_id"/>
<field name="category_ids"/>
</group>
<newline/>
<group expand="0" string="Group By...">
<filter icon="terp-personal" string="Creator" help="By Creators" context="{'group_by':'user_id'}"/>
<filter icon="terp-personal" string="Creator" help="By Creators" context="{'group_by':'create_uid'}"/>
<separator orientation="vertical"/>
<filter icon="terp-stock_symbol-selection" string="Category" help="By Idea Category" context="{'group_by':'category_ids'}"/>
<separator orientation="vertical"/>
<filter icon="terp-stock_symbol-selection" string="Category" help="By Idea Category" context="{'group_by':'category_id'}"/>
<filter icon="terp-stock_effects-object-colorize" string="Status" help="By States" context="{'group_by':'state'}"/>
</group>
</search>
@ -295,82 +140,5 @@
<menuitem name="Ideas" parent="menu_ideas1" id="menu_idea_idea" action="action_idea_idea" sequence="1"/>
<!-- Open Idea Action -->
<record model="ir.actions.act_window" id="action_idea_idea_open">
<field name="name">Open Ideas</field>
<field name="res_model">idea.idea</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('state','=','open')]</field>
<field name="filter" eval="True"/>
</record>
<!-- Idea Votes Statistics Graph View -->
<record model="ir.ui.view" id="view_idea_vote_stat_graph">
<field name="name">idea.vote_stat.graph</field>
<field name="model">idea.vote.stat</field>
<field name="type">graph</field>
<field name="arch" type="xml">
<graph string="vote_stat of ideas">
<field name="score"/>
<field name="nbr"/>
</graph>
</field>
</record>
<!-- Idea Votes Statistics Form View -->
<record model="ir.ui.view" id="view_idea_vote_stat_form">
<field name="name">idea.vote.stat.form</field>
<field name="model">idea.vote.stat</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="vote_stat of ideas">
<field name="idea_id" select="1"/>
<field name="score" select="1"/>
<field name="nbr" />
</form>
</field>
</record>
<!-- Idea Votes Statistics Tree View -->
<record model="ir.ui.view" id="view_idea_vote_stat_tree">
<field name="name">idea.vote.stat.tree</field>
<field name="model">idea.vote.stat</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="vote_stat of ideas">
<field name="idea_id"/>
<field name="score" />
<field name="nbr" />
</tree>
</field>
</record>
<!-- Idea Votes Statistics Action -->
<record model="ir.actions.act_window" id="action_idea_vote_stat">
<field name="name">Vote Statistics</field>
<field name="res_model">idea.vote.stat</field>
<field name="view_type">form</field>
<field name="view_mode">graph,tree</field>
</record>
<menuitem name="Reporting" parent="base.menu_tools" id="base.menu_lunch_reporting" sequence="6" groups="base.group_tool_manager,base.group_tool_user"/>
<menuitem name="Idea" parent="base.menu_reporting" id="menu_idea_reporting" sequence="65"/>
<!-- Vote For Idea Action -->
<record model="ir.actions.act_window" id="action_idea_vote">
<field name="name">Idea's Votes</field>
<field name="res_model">idea.vote</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="view_idea_vote_search"/>
</record>
</data>
</openerp>

View File

@ -1,23 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import report_vote
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,78 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import tools
from osv import fields,osv
class report_vote(osv.osv):
_name = "report.vote"
_description = "Idea Vote Statistics"
_auto = False
_rec_name = 'date'
_columns = {
'date': fields.date('Date Order', readonly=True, select=True),
'year': fields.char('Year', size=4, readonly=True),
'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'),
('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'),
('10','October'), ('11','November'), ('12','December')], 'Month',readonly=True),
'day': fields.char('Day', size=128, readonly=True),
'user_id': fields.many2one('res.users', 'User Name'),
'score': fields.integer('Score',group_operator="avg"),
'idea_id': fields.many2one('idea.idea', 'Idea'),
'nbr':fields.integer('# of Lines', readonly=True),
'idea_state': fields.selection([('draft', 'Draft'),('open', 'Opened'),
('close', 'Accepted'),
('cancel', 'Cancelled')],
'Status'),
'category_id': fields.many2one('idea.category', 'Category'),
'creater_id': fields.many2one('res.users', 'User Name'),
}
_order = 'date desc'
def init(self, cr):
tools.drop_view_if_exists(cr, 'report_vote')
cr.execute("""
create or replace view report_vote as (
select
min(iv.id) as id,
count(*) as nbr,
to_date(to_char(ii.open_date, 'dd-MM-YYYY'),'dd-MM-YYYY') as date,
to_char(ii.open_date, 'YYYY') as year,
to_char(ii.open_date, 'MM') as month,
to_char(ii.open_date, 'YYYY-MM-DD') as day,
iv.user_id as user_id,
iv.idea_id as idea_id,
ii.state as idea_state,
ii.user_id as creater_id,
ii.category_id,
(sum(CAST(iv.score as integer))/count(iv.*)) as score
from
idea_vote as iv
left join idea_idea as ii on (ii.id = iv.idea_id)
group by
iv.id ,to_char(ii.open_date, 'dd-MM-YYYY'),to_char(ii.open_date, 'YYYY'),
to_char(ii.open_date, 'MM'),to_char(ii.open_date, 'YYYY-MM-DD'),ii.state,
iv.user_id,ii.user_id,ii.category_id,iv.idea_id
)
""")
report_vote()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,89 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_report_vote_tree" model="ir.ui.view">
<field name="name">report.vote.tree</field>
<field name="model">report.vote</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Idea Vote Analysis">
<field name="date" invisible="1"/>
<field name="year" invisible="1"/>
<field name="day" invisible="1"/>
<field name="month" invisible="1"/>
<field name="user_id" invisible="1"/>
<field name="idea_id" invisible="1"/>
<field name="idea_state"/>
<field name="creater_id" invisible="1"/>
<field name="category_id" invisible="1"/>
<field name="nbr" sum="# of Lines"/>
<field name="score" avg="Score"/>
</tree>
</field>
</record>
<record id="view_report_vote_search" model="ir.ui.view">
<field name="name">report.vote.search</field>
<field name="model">report.vote</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Idea Vote Analysis">
<group>
<filter icon="terp-go-year" string="Year" name="year"
domain="[('date','&lt;=', time.strftime('%%Y-%%m-%%d')),('date','&gt;=',time.strftime('%%Y-01-01'))]"
help="Idea Vote created in current year"/>
<separator orientation="vertical"/>
<filter icon="terp-go-month" string="Month" name="month"
domain="[('date','&lt;=',(datetime.date.today()+relativedelta(day=31)).strftime('%%Y-%%m-%%d')),('date','&gt;=',(datetime.date.today()-relativedelta(day=1)).strftime('%%Y-%%m-%%d'))]"
help="Idea Vote created in current month"/>
<filter icon="terp-go-month"
string="Month-1"
domain="[('date','&lt;=', (datetime.date.today() - relativedelta(day=31, months=1)).strftime('%%Y-%%m-%%d')),('date','&gt;=',(datetime.date.today() - relativedelta(day=1,months=1)).strftime('%%Y-%%m-%%d'))]"
help="Idea Vote created last month"/>
<separator orientation="vertical"/>
<filter icon="terp-camera_test"
string="In Progress"
domain="[('idea_state','=',('open'))]"/>
<filter icon="terp-check"
string="Accepted"
domain="[('idea_state','=',('close'))]"/>
<filter icon="terp-gtk-stop"
string="Refused"
domain="[('idea_state','=',('cancel'))]"/>
<separator orientation="vertical"/>
<field name="idea_id" string="Idea"/>
<field name="creater_id" string="Creator"/>
<field name="user_id"/>
</group>
<newline/>
<group expand="1" string="Group By...">
<filter string="Creator" icon="terp-personal" context="{'group_by':'creater_id'}"/>
<filter string="User" icon="terp-personal" name="User" context="{'group_by':'user_id'}"/>
<separator orientation="vertical"/>
<filter string="Idea" icon="terp-idea" context="{'group_by':'idea_id'}"/>
<separator orientation="vertical"/>
<filter string="Category" icon="terp-stock_symbol-selection" context="{'group_by':'category_id'}"/>
<separator orientation="vertical"/>
<filter string="Status" icon="terp-stock_effects-object-colorize" name="Status" context="{'group_by':'idea_state'}"/>
<separator orientation="vertical"/>
<filter string="Day" icon="terp-go-today" context="{'group_by':'day'}" help="Open Date"/>
<filter string="Month" icon="terp-go-month" context="{'group_by':'month'}" help="Open Date"/>
<filter string="Year" icon="terp-go-year" context="{'group_by':'year'}" help="Open Date"/>
</group>
</search>
</field>
</record>
<record id="action_report_vote_all" model="ir.actions.act_window">
<field name="name">Ideas Analysis</field>
<field name="res_model">report.vote</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="view_report_vote_search"/>
<field name="context">{'search_default_year':1,'search_default_month':1,'search_default_User':1,'search_default_State':1,'group_by_no_leaf':1,'group_by':[]}</field>
</record>
<menuitem action="action_report_vote_all" id="menu_report_vote_all" parent="menu_idea_reporting" sequence="1" groups="base.group_tool_manager"/>
</data>
</openerp>

View File

@ -6,12 +6,6 @@
<field name="name">User</field>
<field name="category_id" ref="base.module_category_tools"/>
</record>
<record model="res.groups" id="base.group_tool_manager">
<field name="name">Manager</field>
<field name="category_id" ref="base.module_category_tools"/>
<field name="implied_ids" eval="[(4, ref('base.group_tool_user'))]"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
</record>
</data>
</openerp>

View File

@ -1,7 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_idea_category_user,idea.category user,model_idea_category,base.group_tool_user,1,1,1,1
access_idea_idea_user,idea.idea user,model_idea_idea,base.group_tool_user,1,1,1,1
access_idea_vote_user,idea.vote user,model_idea_vote,base.group_tool_user,1,1,1,1
access_idea_vote_stat_user,idea.vote.stat user,model_idea_vote_stat,base.group_tool_user,1,1,1,1
access_idea_comment_user,idea.comment user,model_idea_comment,base.group_tool_user,1,1,1,1
access_report_vote_manager,report.vote manager,model_report_vote,base.group_tool_manager,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_idea_category_user idea.category user model_idea_category base.group_tool_user 1 1 1 1
3 access_idea_idea_user idea.idea user model_idea_idea base.group_tool_user 1 1 1 1
access_idea_vote_user idea.vote user model_idea_vote base.group_tool_user 1 1 1 1
access_idea_vote_stat_user idea.vote.stat user model_idea_vote_stat base.group_tool_user 1 1 1 1
access_idea_comment_user idea.comment user model_idea_comment base.group_tool_user 1 1 1 1
access_report_vote_manager report.vote manager model_report_vote base.group_tool_manager 1 1 1 1

View File

@ -1,42 +0,0 @@
-
In order to test the Idea module in OpenERP,
-
I open the idea "Need to put a good idea on OpenERP".
-
!workflow {model: idea.idea, action: idea_open, ref: idea_idea_one}
-
I check that the idea's state is open.
-
!assert {model: idea.idea, id: idea_idea_one}:
- state == 'open'
-
I give vote the idea as "Very Good" and put comment "It will good for openERP feature".
-
!python {model: idea.post.vote}: |
new_id = self.create(cr, uid, {'vote': "100", 'note': 'It will good for openERP feature'}, {"active_ids": [ref("idea_idea_one")]})
self.do_vote(cr, uid, [new_id], {'active_ids': [ref('idea_idea_one')]})
-
I check the Average score.
-
!assert {model: idea.idea, id: idea_idea_one}:
vote_avg: 100
-
I Accept the idea of "Need to put a good idea on OpenERP".
-
!workflow {model: idea.idea, action: idea_close, ref: idea_idea_one}
-
I check that the idea's state is now Accepted.
-
!assert {model: idea.idea, id: idea_idea_one}:
- state == 'close'
-
I Refuse the idea of "Technical presentation for 1 hours in every day".
-
!workflow {model: idea.idea, action: idea_open, ref: idea_idea_two}
-
!workflow {model: idea.idea, action: idea_cancel, ref: idea_idea_two}
-
I check that the idea's state is now Refused.
-
!assert {model: idea.idea, id: idea_idea_two}:
- state == 'cancel'

View File

@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import idea_post_vote
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,178 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields, osv
from tools.translate import _
class idea_post_vote(osv.osv_memory):
""" Post Vote For Idea """
_name = "idea.post.vote"
_description = "Post vote"
_columns = {
'vote': fields.selection([('-1', 'Not Voted'),
('0', 'Very Bad'),
('25', 'Bad'),
('50', 'Normal'),
('75', 'Good'),
('100', 'Very Good') ],
'Post Vote', required=True),
'note': fields.text('Description'),
}
def get_default(self, cr, uid, context=None):
"""
This function checks for precondition before wizard executes
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param fields: List of fields for default value
@param context: A standard dictionary for contextual values
"""
if context is None:
context = {}
idea_obj = self.pool.get('idea.idea')
if context.get('active_id'):
idea = idea_obj.browse(cr, uid, context.get('active_id'), context=context)
return idea.my_vote
else:
return 75
_defaults = {
'vote': get_default,
}
def view_init(self, cr, uid, fields, context=None):
"""
This function checks for precondition before wizard executes
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param fields: List of fields for default value
@param context: A standard dictionary for contextual values
"""
idea_obj = self.pool.get('idea.idea')
vote_obj = self.pool.get('idea.vote')
ctx_key = 'idea_ids' if context.get('idea_ids') is not None else 'active_ids'
for idea in idea_obj.browse(cr, uid, context.get(ctx_key, []), context=context):
for idea_id in context.get(ctx_key):
vote_ids = vote_obj.search(cr, uid, [('user_id', '=', uid), ('idea_id', '=', idea_id)])
vote_obj_id = vote_obj.browse(cr, uid, vote_ids)
count = 0
for vote in vote_obj_id:
count += 1
user_limit = idea.vote_limit
if count >= user_limit:
raise osv.except_osv(_('Warning !'),_("You can not give Vote for this idea more than %s times") % (user_limit))
if idea.state != 'open':
raise osv.except_osv(_('Warning !'), _('Idea must be in \
\'Open\' state before vote for that idea.'))
return False
def do_vote(self, cr, uid, ids, context=None):
"""
Create idea vote.
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Idea Post votes IDs.
@return: Dictionary {}
"""
ctx_key = 'idea_ids' if context.get('idea_ids') is not None else 'active_ids'
idea_id = context[ctx_key][0]
vote_pool = self.pool.get('idea.vote')
idea_pool = self.pool.get('idea.idea')
comment_pool = self.pool.get('idea.comment')
for do_vote_obj in self.read(cr, uid, ids, context=context):
score = str(do_vote_obj['vote'])
comment = do_vote_obj.get('note', False)
vote = {
'idea_id': idea_id,
'user_id': uid,
'score': score
}
if comment:
comment = {
'user_id':uid,
'idea_id':idea_id,
'content': comment,
}
comment = comment_pool.create(cr, uid, comment)
idea_pool._vote_save(cr, uid, idea_id, None, score, context)
#vote = vote_pool.create(cr, uid, vote)
return {'type': 'ir.actions.act_window_close'}
idea_post_vote()
class idea_select(osv.osv_memory):
""" Select idea for vote."""
_name = "idea.select"
_description = "select idea"
_columns = {
'idea_id': fields.many2one('idea.idea', 'Idea', required=True),
}
def open_vote(self, cr, uid, ids, context=None):
"""
This function load column.
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of load column,
@return: dictionary of query logs clear message window
"""
if context is None:
context = {}
idea_obj = self.browse(cr, uid, ids, context=context)
for idea in idea_obj:
idea_id = idea.idea_id.id
data_obj = self.pool.get('ir.model.data')
id2 = data_obj._get_id(cr, uid, 'idea', 'view_idea_post_vote')
if id2:
id2 = data_obj.browse(cr, uid, id2, context=context).res_id
value = {
'view_type': 'form',
'view_mode': 'form',
'res_model': 'idea.post.vote',
'views': [(id2, 'form'), (False, 'tree'), (False, 'calendar'), (False, 'graph')],
'type': 'ir.actions.act_window',
'target': 'new',
'context': {'idea_ids': [idea_id]}
}
return value
idea_select()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,69 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Post Idea for vote Form View -->
<record id="view_idea_post_vote" model="ir.ui.view">
<field name="name">idea.post.vote.form</field>
<field name="model">idea.post.vote</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Give Vote">
<group colspan="4" >
<field name="vote" colspan="4"/>
<separator string="Comment" colspan="4"/>
<field name="note" colspan="4" nolabel="1"/>
</group>
<separator string="" colspan="4" />
<group colspan="4" col="6">
<button icon="gtk-cancel" special="cancel" string="Cancel"/>
<button icon="gtk-ok" name="do_vote" string="Post" type="object"/>
</group>
</form>
</field>
</record>
<record id="view_idea_select" model="ir.ui.view">
<field name="name">idea.select.form</field>
<field name="model">idea.select</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Select Idea for Vote">
<group colspan="4" >
<separator string="Select Idea for Vote" colspan="4"/>
<field name="idea_id"/>
</group>
<separator string="" colspan="4"/>
<group colspan="4" col="6">
<label string="" colspan="2"/>
<button icon="gtk-cancel" special="cancel" string="Close"/>
<button icon="gtk-go-forward" name="open_vote" string="Next" type="object"/>
</group>
</form>
</field>
</record>
<!-- Post Idea for vote Action -->
<record id="action_idea_post_vote" model="ir.actions.act_window">
<field name="name">Vote</field>
<field name="res_model">idea.post.vote</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_idea_post_vote"/>
<field name="target">new</field>
</record>
<record id="action_idea_select" model="ir.actions.act_window">
<field name="name">Idea select</field>
<field name="res_model">idea.select</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_idea_select"/>
<field name="target">new</field>
<field name="context">{'model': 'idea.idea'}</field>
</record>
</data>
</openerp>