diff --git a/addons/website_forum/controllers/main.py b/addons/website_forum/controllers/main.py index 354aa52c8b3..aad4e3e4234 100644 --- a/addons/website_forum/controllers/main.py +++ b/addons/website_forum/controllers/main.py @@ -32,12 +32,21 @@ class WebsiteForum(http.Controller): return msg def _prepare_forum_values(self, forum=None, **kwargs): + Forum = request.registry['forum.forum'] user = request.registry['res.users'].browse(request.cr, request.uid, request.uid, context=request.context) public_uid = request.registry['website'].get_public_user(request.cr, request.uid, request.context) values = {'user': user, 'is_public_user': user.id == public_uid, 'notifications': self._get_notifications(), 'header': kwargs.get('header', dict()), - 'searches': kwargs.get('searches', dict())} + 'searches': kwargs.get('searches', dict()), + 'can_edit_own': True, + 'can_edit_all': user.karma > Forum._karma_modo_edit_all, + 'can_close_own': user.karma > Forum._karma_modo_close_own, + 'can_close_all': user.karma > Forum._karma_modo_close_all, + 'can_unlink_own': user.karma > Forum._karma_modo_unlink_own, + 'can_unlink_all': user.karma > Forum._karma_modo_unlink_all, + 'can_unlink_comment': user.karma > Forum._karma_modo_unlink_comment, + } if forum: values['forum'] = forum elif kwargs.get('forum_id'): @@ -45,6 +54,14 @@ class WebsiteForum(http.Controller): values.update(kwargs) return values + def _has_enough_karma(self, karma_name, uid=None): + Forum = request.registry['forum.forum'] + karma = hasattr(Forum, karma_name) and getattr(Forum, karma_name) or 0 + user = request.registry['res.users'].browse(request.cr, SUPERUSER_ID, uid or request.uid, context=request.context) + if user.karma < karma: + return False, {'error': 'not_enough_karma', 'karma': karma} + return True, {} + # Forum # -------------------------------------------------- @@ -201,6 +218,10 @@ class WebsiteForum(http.Controller): @http.route('/forum//question//ask_for_close', type='http', auth="user", multilang=True, website=True) def question_ask_for_close(self, forum, question, **post): + check_res = self._has_enough_karma(question.create_uid.id == request.uid and '_karma_modo_close_own' or '_karma_modo_close_all') + if not check_res[0]: + return werkzeug.utils.redirect("/forum/%s" % slug(forum)) + cr, uid, context = request.cr, request.uid, request.context Reason = request.registry['forum.post.reason'] reason_ids = Reason.search(cr, uid, [], context=context) @@ -208,7 +229,7 @@ class WebsiteForum(http.Controller): values = self._prepare_forum_values(**post) values.update({ - 'post': question, + 'question': question, 'forum': forum, 'reasons': reasons, }) @@ -224,6 +245,10 @@ class WebsiteForum(http.Controller): @http.route('/forum//question//close', type='http', auth="user", multilang=True, methods=['POST'], website=True) def question_close(self, forum, question, **post): + check_res = self._has_enough_karma(question.create_uid.id == request.uid and '_karma_modo_close_own' or '_karma_modo_close_all') + if not check_res[0]: + return werkzeug.utils.redirect("/forum/%s" % slug(forum)) + request.registry['forum.post'].write(request.cr, request.uid, [question.id], { 'state': 'close', 'closed_uid': request.uid, @@ -234,17 +259,28 @@ class WebsiteForum(http.Controller): @http.route('/forum//question//reopen', type='http', auth="user", multilang=True, website=True) def question_reopen(self, forum, question, **kwarg): + check_res = self._has_enough_karma(question.create_uid.id == request.uid and '_karma_modo_close_own' or '_karma_modo_close_all') + if not check_res[0]: + return werkzeug.utils.redirect("/forum/%s" % slug(forum)) + request.registry['forum.post'].write(request.cr, request.uid, [question.id], {'state': 'active'}, context=request.context) return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question))) @http.route('/forum//question//delete', type='http', auth="user", multilang=True, website=True) def question_delete(self, forum, question, **kwarg): - #instead of unlink record just change 'active' to false so user can undelete it. + check_res = self._has_enough_karma(question.create_uid.id == request.uid and '_karma_modo_unlink_own' or '_karma_modo_unlink_all') + if not check_res[0]: + return werkzeug.utils.redirect("/forum/%s" % slug(forum)) + request.registry['forum.post'].write(request.cr, request.uid, [question.id], {'active': False}, context=request.context) return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question))) @http.route('/forum//question//undelete', type='http', auth="user", multilang=True, website=True) def question_undelete(self, forum, question, **kwarg): + check_res = self._has_enough_karma(question.create_uid.id == request.uid and '_karma_modo_unlink_own' or '_karma_modo_unlink_all') + if not check_res[0]: + return werkzeug.utils.redirect("/forum/%s" % slug(forum)) + request.registry['forum.post'].write(request.cr, request.uid, [question.id], {'active': True}, context=request.context) return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question))) @@ -283,19 +319,27 @@ class WebsiteForum(http.Controller): @http.route('/forum//post//toggle_correct', type='json', auth="public", website=True) def post_toggle_correct(self, forum, post, **kwargs): cr, uid, context = request.cr, request.uid, request.context + if post.parent_id is False: + return request.redirect('/') if not request.session.uid: return {'error': 'anonymous_user'} - # if user have not access to accept answer then reise warning - if post.parent_id is False or post.parent_id.create_uid.id != uid: + user = request.registry['res.users'].browse(request.cr, SUPERUSER_ID, request.uid, context=request.context) + if post.parent_id.create_uid.id != uid: return {'error': 'own_post'} + if post.create_uid.id == user.id and user.karma < request.registry['forum.forum']._karma_answer_accept_own: + return {'error': 'not_enough_karma', 'karma': 20} # set all answers to False, only one can be accepted request.registry['forum.post'].write(cr, uid, [c.id for c in post.parent_id.child_ids], {'is_correct': False}, context=context) - request.registry['forum.post'].write(cr, uid, [post.id, post.parent_id.id], {'is_correct': not post.is_correct}, context=context) + request.registry['forum.post'].write(cr, uid, [post.id], {'is_correct': not post.is_correct}, context=context) return not post.is_correct @http.route('/forum//post//delete', type='http', auth="user", multilang=True, website=True) def post_delete(self, forum, post, **kwargs): + check_res = self._has_enough_karma(post.create_uid.id == request.uid and '_karma_modo_unlink_own' or '_karma_modo_unlink_all') + if not check_res[0]: + return werkzeug.utils.redirect("/forum/%s" % slug(forum)) + question = post.parent_id request.registry['forum.post'].unlink(request.cr, request.uid, [post.id], context=request.context) if question: @@ -304,6 +348,10 @@ class WebsiteForum(http.Controller): @http.route('/forum//post//edit', type='http', auth="user", website=True, multilang=True) def post_edit(self, forum, post, **kwargs): + check_res = self._has_enough_karma(post.create_uid.id == request.uid and '_karma_modo_edit_own' or '_karma_modo_edit_all') + if not check_res[0]: + return werkzeug.utils.redirect("/forum/%s" % slug(forum)) + tags = "" for tag_name in post.tag_ids: tags += tag_name.name + "," @@ -341,15 +389,15 @@ class WebsiteForum(http.Controller): @http.route('/forum//post//upvote', type='json', auth="public", multilang=True, website=True) def post_upvote(self, forum, post, **kwargs): - # check for karma and not self vote if not request.session.uid: return {'error': 'anonymous_user'} if request.uid == post.create_uid.id: return {'error': 'own_post'} - user = request.registry['res.users'].browse(request.cr, SUPERUSER_ID, request.uid, context=request.context) - if user.karma <= 5: - return {'error': 'not_enough_karma', 'karma': 1} - return request.registry['forum.post'].vote(request.cr, request.uid, [post.id], upvote=True, context=request.context) + check_res = self._has_enough_karma('_karma_upvote') + if not check_res[0]: + return check_res[1] + upvote = True if not post.user_vote > 0 else False + return request.registry['forum.post'].vote(request.cr, request.uid, [post.id], upvote=upvote, context=request.context) @http.route('/forum//post//downvote', type='json', auth="public", multilang=True, website=True) def post_downvote(self, forum, post, **kwargs): @@ -357,10 +405,11 @@ class WebsiteForum(http.Controller): return {'error': 'anonymous_user'} if request.uid == post.create_uid.id: return {'error': 'own_post'} - user = request.registry['res.users'].browse(request.cr, SUPERUSER_ID, request.uid, context=request.context) - if user.karma <= 50: - return {'error': 'not_enough_karma', 'karma': 50} - return request.registry['forum.post'].vote(request.cr, request.uid, [post.id], upvote=False, context=request.context) + check_res = self._has_enough_karma('_karma_downvote') + if not check_res[0]: + return check_res[1] + upvote = True if post.user_vote < 0 else False + return request.registry['forum.post'].vote(request.cr, request.uid, [post.id], upvote=upvote, context=request.context) # User # -------------------------------------------------- @@ -387,6 +436,16 @@ class WebsiteForum(http.Controller): return request.website.render("website_forum.users", values) + @http.route(['/forum//partner/'], type='http', auth="public", website=True, multilang=True) + def open_partner(self, forum, partner_id=0, **post): + cr, uid, context = request.cr, request.uid, request.context + pids = request.registry['res.partner'].search(cr, SUPERUSER_ID, [('id', '=', partner_id)], context=context) + if pids: + partner = request.registry['res.partner'].browse(cr, SUPERUSER_ID, pids[0], context=context) + if partner.user_ids: + return werkzeug.utils.redirect("/forum/%s/user/%d" % (slug(forum), partner.user_ids[0].id)) + return werkzeug.utils.redirect("/forum/%s" % slug(forum)) + @http.route(['/forum//user/'], type='http', auth="public", website=True, multilang=True) def open_user(self, forum, user_id=0, **post): cr, uid, context = request.cr, request.uid, request.context diff --git a/addons/website_forum/models/forum.py b/addons/website_forum/models/forum.py index 031ae4b33e1..662ec10d094 100644 --- a/addons/website_forum/models/forum.py +++ b/addons/website_forum/models/forum.py @@ -9,9 +9,38 @@ from openerp.tools.translate import _ class Forum(osv.Model): + """TDE TODO: set karma values for actions dynamic for a given forum""" _name = 'forum.forum' _description = 'Forums' _inherit = ['website.seo.metadata'] + # karma values + _karma_upvote = 5 # done + _karma_downvote = 50 # done + _karma_answer_accept_own = 20 # done + _karma_answer_accept_own_now = 50 + _karma_answer_accept_all = 500 + _karma_editor_link_files = 30 # done + _karma_editor_clickable_link = 50 + _karma_comment = 1 + _karma_modo_retag = 75 + _karma_modo_flag = 100 + _karma_modo_flag_see_all = 300 + _karma_modo_unlink_comment = 750 + _karma_modo_edit_own = 1 # done + _karma_modo_edit_all = 300 # done + _karma_modo_close_own = 100 # done + _karma_modo_close_all = 900 # done + _karma_modo_unlink_own = 500 # done + _karma_modo_unlink_all = 1000 # done + # karma generation + _karma_gen_quest_new = 2 # done + _karma_gen_upvote_quest = 5 # done + _karma_gen_downvote_quest = -2 # done + _karma_gen_upvote_ans = 10 # done + _karma_gen_downvote_ans = -2 # done + _karma_gen_ans_accept = 2 # done + _karma_gen_ans_accepted = 15 # done + _karma_gen_ans_flagged = -100 _columns = { 'name': fields.char('Name', required=True, translate=True), @@ -97,6 +126,13 @@ class Post(osv.Model): res[post.id] = any(answer.create_uid.id == uid for answer in post.child_ids) return res + def _get_has_validated_answer(self, cr, uid, ids, field_name, arg, context=None): + res = dict.fromkeys(ids, False) + ans_ids = self.search(cr, uid, [('parent_id', 'in', ids), ('is_correct', '=', True)], context=context) + for answer in self.browse(cr, uid, ans_ids, context=context): + res[answer.parent_id.id] = True + return res + def _is_self_reply(self, cr, uid, ids, field_name, arg, context=None): res = dict.fromkeys(ids, False) for post in self.browse(cr, uid, ids, context=context): @@ -143,7 +179,8 @@ class Post(osv.Model): }), # hierarchy 'parent_id': fields.many2one('forum.post', 'Question', ondelete='cascade'), - 'self_reply': fields.function(_is_self_reply, 'Reply to own question', type='boolean', + 'self_reply': fields.function( + _is_self_reply, 'Reply to own question', type='boolean', store={ 'forum.post': (lambda self, cr, uid, ids, c={}: ids, ['parent_id', 'create_uid'], 10), }), @@ -156,6 +193,12 @@ class Post(osv.Model): 'uid_has_answered': fields.function( _get_uid_answered, string='Has Answered', type='boolean', ), + 'has_validated_answer': fields.function( + _get_has_validated_answer, string='Has a Validated Answered', type='boolean', + store={ + 'forum.post': (_get_post_from_hierarchy, ['parent_id', 'child_ids', 'is_correct'], 10), + } + ), # closing 'closed_reason_id': fields.many2one('forum.post.reason', 'Reason'), 'closed_uid': fields.many2one('res.users', 'Closed by', select=1), @@ -183,10 +226,18 @@ class Post(osv.Model): self.message_post(cr, uid, parent.id, subject=_('Re: %s') % parent.name, body=body, subtype='website_forum.mt_answer_new', context=context) else: self.message_post(cr, uid, post_id, subject=vals.get('name', ''), body=_('New Question Created'), subtype='website_forum.mt_question_new', context=context) - self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [uid], 2, context=context) + self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [uid], self.pool['forum.forum']._karma_gen_quest_new, context=context) return post_id def write(self, cr, uid, ids, vals, context=None): + Forum = self.pool['forum.forum'] + # update karma when accepting/rejecting answers + if 'is_correct' in vals: + mult = 1 if vals['is_correct'] else -1 + for post in self.browse(cr, uid, ids, context=context): + if vals['is_correct'] != post.is_correct: + self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [post.create_uid.id], Forum._karma_gen_ans_accepted * mult, context=context) + self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [uid], Forum._karma_gen_ans_accept * mult, context=context) res = super(Post, self).write(cr, uid, ids, vals, context=context) # if post content modify, notify followers if 'content' in vals or 'name' in vals: @@ -198,11 +249,6 @@ class Post(osv.Model): body, subtype = _('Question Edited'), 'website_forum.mt_question_edit' obj_id = post.id self.message_post(cr, uid, obj_id, body=_(body), subtype=subtype, context=context) - # update karma of related user when any answer accepted - if 'correct' in vals: - for post in self.browse(cr, uid, ids, context=context): - karma_value = 15 if vals.get('correct') else -15 - self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [post.create_uid.id], {'karma': karma_value}, context=context) return res def vote(self, cr, uid, ids, upvote=True, context=None): @@ -251,16 +297,30 @@ class Vote(osv.Model): def create(self, cr, uid, vals, context=None): vote_id = super(Vote, self).create(cr, uid, vals, context=context) - karma_value = int(vals.get('vote', '1')) * 10 - post = self.pool['forum.post'].browse(cr, uid, vals.get('post_id'), context=context) - self.pool['res.users'].add_karma(cr, SUPERUSER_ID, post.create_uid.id, karma_value, context=context) + if vals.get('vote', '1') == '1': + karma = self.pool['forum.forum']._karma_upvote + elif vals.get('vote', '1') == '-1': + karma = self.pool['forum.forum']._karma_downvote + post = self.pool['forum.post'].browse(cr, uid, vals['post_id'], context=context) + self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [post.create_uid.id], karma, context=context) return vote_id def write(self, cr, uid, ids, values, context=None): + def _get_karma_value(old_vote, new_vote, up_karma, down_karma): + _karma_upd = { + '-1': {'-1': 0, '0': -1 * down_karma, '1': -1 * down_karma + up_karma}, + '0': {'-1': 1 * down_karma, '0': 0, '1': up_karma}, + '1': {'-1': -1 * up_karma + down_karma, '0': -1 * up_karma, '1': 0} + } + return _karma_upd[old_vote][new_vote] if 'vote' in values: + Forum = self.pool['forum.forum'] for vote in self.browse(cr, uid, ids, context=context): - karma_value = (int(values.get('vote')) - int(vote.vote)) * 10 - self.pool['res.users'].add_karma(cr, SUPERUSER_ID, vote.post_id.create_uid.id, karma_value, context=context) + if vote.post_id.parent_id: + karma_value = _get_karma_value(vote.vote, values['vote'], Forum._karma_gen_upvote_ans, Forum._karma_gen_downvote_ans) + else: + karma_value = _get_karma_value(vote.vote, values['vote'], Forum._karma_gen_upvote_quest, Forum._karma_gen_downvote_quest) + self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [vote.post_id.create_uid.id], karma_value, context=context) res = super(Vote, self).write(cr, uid, ids, values, context=context) return res diff --git a/addons/website_forum/models/res_users.py b/addons/website_forum/models/res_users.py index 58d43a58191..a9f2dfe0e93 100644 --- a/addons/website_forum/models/res_users.py +++ b/addons/website_forum/models/res_users.py @@ -32,8 +32,6 @@ class Users(osv.Model): } def add_karma(self, cr, uid, ids, karma, context=None): - if isinstance(ids, (int, long)): - ids = [ids] for user in self.browse(cr, uid, ids, context=context): self.write(cr, uid, [user.id], {'karma': user.karma + karma}, context=context) return True @@ -44,4 +42,4 @@ class Users(osv.Model): excluded_categories.append('forum') else: excluded_categories = ['forum'] - return super(Users, self).get_serialised_gamification_summary(cr, uid, excluded_categories=excluded_categories, context=context) \ No newline at end of file + return super(Users, self).get_serialised_gamification_summary(cr, uid, excluded_categories=excluded_categories, context=context) diff --git a/addons/website_forum/static/src/js/website_forum.js b/addons/website_forum/static/src/js/website_forum.js index 2c428740776..eed4947aab9 100644 --- a/addons/website_forum/static/src/js/website_forum.js +++ b/addons/website_forum/static/src/js/website_forum.js @@ -18,9 +18,9 @@ $(document).ready(function () { ''); } else if (data['error'] == 'not_enough_karma') { - var $warning = $('
'+ + var $warning = $('
'+ ''+ - 'Sorry, at least ' + data['karma'] + ' karma is required to vote'+ + 'Sorry, at least ' + data['karma'] + ' karma is required to vote. You can gain karma by answering questions and receiving votes.'+ '
'); } vote_alert = $link.parent().find("#vote_alert"); @@ -57,7 +57,12 @@ $(document).ready(function () { } else if (data['error'] == 'own_post'){ var $warning = $('
'+ ''+ - 'Sorry, the user who asked this question can only accept the answer as correct.'+ + 'Sorry, only the user who asked this question can accept the answer as correct.'+ + '
'); + } else if (data['error'] == 'not_enough_karma') { + var $warning = $('
'+ + ''+ + 'Sorry, at least ' + data['karma'] + ' karma is required to accept your own answers. You can gain karma by answering questions and receiving votes.'+ '
'); } correct_answer_alert = $link.parent().find("#correct_answer_alert"); diff --git a/addons/website_forum/views/website_forum.xml b/addons/website_forum/views/website_forum.xml index 2d1787a48ab..fd21c2cd1f0 100644 --- a/addons/website_forum/views/website_forum.xml +++ b/addons/website_forum/views/website_forum.xml @@ -138,7 +138,7 @@
- +
Answers
Answer
@@ -336,16 +336,16 @@