Harry (OpenERP) has proposed merging lp:~openerp-dev/openobject-addons/trunk-project_merge_proposal-hmo into lp:openobject-addons.
Requested reviews: OpenERP R&D Team (openerp-dev) For more details, see: https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-project_merge_proposal-hmo/+merge/83274 Introduce new module (project_merge_proposal) to store details of Merge Proposal of Launchapad branch into OpenERP. - inherited project.task.work to add new fields like diff_lines, added_new_lines, remove_lines, date_created, date also some function fields to calculate avg. of need fixing, avg. of approved. - new model: project.task.work.review to indicate details of comments/feedback of merge proposal. Thanks -- https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-project_merge_proposal-hmo/+merge/83274 Your team OpenERP R&D Team is requested to review the proposed merge of lp:~openerp-dev/openobject-addons/trunk-project_merge_proposal-hmo into lp:openobject-addons.
=== added directory 'project_merge_proposal' === added file 'project_merge_proposal/__init__.py' --- project_merge_proposal/__init__.py 1970-01-01 00:00:00 +0000 +++ project_merge_proposal/__init__.py 2011-11-24 11:24:19 +0000 @@ -0,0 +1,26 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 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 project_merge_proposal +import project_launchpad_scheduler + + + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: === added file 'project_merge_proposal/__openerp__.py' --- project_merge_proposal/__openerp__.py 1970-01-01 00:00:00 +0000 +++ project_merge_proposal/__openerp__.py 2011-11-24 11:24:19 +0000 @@ -0,0 +1,47 @@ +# -*- 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/>. +# +############################################################################## + + +{ + 'name': 'Merge Proposal', + 'version': '1.0', + 'category': 'Generic Modules/Project Management', + 'description': """ + + """, + 'author': 'OpenERP SA', + 'website': 'http://www.openerp.com', + 'depends': ['project'], + 'init_xml': ['scheduler_data.xml'], + 'update_xml': [ + "scheduler_view.xml", + "project_merge_proposal_view.xml" + ], + 'demo_xml': [ + + ], + 'test':[ + 'test/merge_proposal.yml' + ], + 'installable': True, + 'active': False, +} +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: === added file 'project_merge_proposal/project_launchpad_scheduler.py' --- project_merge_proposal/project_launchpad_scheduler.py 1970-01-01 00:00:00 +0000 +++ project_merge_proposal/project_launchpad_scheduler.py 2011-11-24 11:24:19 +0000 @@ -0,0 +1,276 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 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 osv + +from launchpadlib.launchpad import Launchpad, EDGE_SERVICE_ROOT +from datetime import datetime, date +from bzrlib.branch import Branch +import os + +MERGE_STATUS = {} +MERGE_STATUS_FILTERS = ['rejected', 'pending', 'cancelled', 'done'] +MERGE_STATUS.update({'Rejected':'rejected' , 'Queued': 'pending', 'Superseded':'cancelled', 'Merged':'done' }) +MERGE_STATUS.update({'Needs review': 'needs_review', 'Code failed to merge':'code_failed', 'Work in progress':'in_reviewing', 'Approved': 'ready' }) + +BRANCH_STATUS = {} +BRANCH_STATUS.update({'Merged':'merged', 'Abandoned':'cancelled'}) +BRANCH_STATUS.update({'Experimental':'experimental', 'Development': 'development', 'Mature':'mature'}) + +COMMENT_STATUS = { 'Resubmit':'resubmit', + 'Approve': 'approved', + 'Needs Fixing': 'need_fixing', + 'Needs Information': 'need_information', + 'Disapprove': 'disapproved' } +DEFAULT_LOGIN = 'openerp' +DEFAULT_CACHE_PATH = "~/.launchpadlib/cache" + +TEAMS = ['openerp', 'openerp-dev'] #,'openobject-training', 'openerp-opw'] +PROJECTS = ['openerp', 'openobject-addons', 'openobject-client', 'openerp-web', 'openobject-server','openobject-client-web'] + +LP_API_LINK = "https://api.edge.launchpad.net/1.0/" +def get_lp(): + cachedir = os.path.expanduser(DEFAULT_CACHE_PATH) + return Launchpad.login_with(DEFAULT_LOGIN, EDGE_SERVICE_ROOT, cachedir) + +class project_launchpad_scheduler(osv.osv_memory): + _name = "project.launchpad.scheduler" + launchpad = None + + def get_email_address(self, people): + return [email_address.email for email_address in people.confirmed_email_addresses] + + def lp_load_link(self, link): + if self.launchpad is None: + self.launchpad = get_lp() + res = False + try: + res = self.launchpad.load(link) + except Exception, e: + print e + return res + + def get_lp_people(self, people): + if self.launchpad is None: + self.launchpad = get_lp() + return self.launchpad.people[people] + + def get_lp_project(self, project): + if project is None or not project or project == 'none': + return False + if self.launchpad is None: + self.launchpad = get_lp() + return self.launchpad.projects[project] + + def get_lp_people_by_email(self, email): + if self.launchpad is None: + self.launchpad = get_lp() + return self.launchpad.people.getByEmail(email=email) + + def get_lp_branches(self, people): + return people.getBranches(status=BRANCH_STATUS.keys()) + + def _lp_merge_proposal(self, proposal, from_date=False): + merge_request = {} + if proposal is None: + return merge_request + proposal_date = proposal.date_created + + if from_date and datetime(proposal_date.year, proposal_date.month, proposal_date.day) <= datetime(from_date.year, from_date.month, from_date.day): + return merge_request + + merge_request['date_created'] = proposal_date + merge_request['date_merged'] = proposal.date_merged + preview_diff = proposal.preview_diff #_link and self.load_link(proposal.preview_diff_link) or None + + merge_request['added_lines_count'] = preview_diff and preview_diff.added_lines_count or 0 + merge_request['remove_lines_count'] = preview_diff and preview_diff.removed_lines_count or 0 + merge_request['diff_lines_count'] = preview_diff and preview_diff.diff_lines_count or 0 + merge_request['diffstat'] = preview_diff and (preview_diff.diffstat or {}) or {} + merge_request['diffstat_files_count'] = len(merge_request['diffstat'].keys()) + merge_request['description'] = proposal.description + merge_request['state'] = MERGE_STATUS.get(proposal.queue_status) + merge_request['name'] = proposal.self_link.replace(LP_API_LINK, "") + merge_request['source_branch_link'] = proposal.source_branch_link.replace(LP_API_LINK, "") + merge_request['date_created_branch'] = proposal.source_branch.date_created + merge_request['target_branch_link'] = proposal.target_branch_link.replace(LP_API_LINK, "") + merge_request['registrant_name'] = proposal.registrant.name + merge_request['merge_reporter'] = proposal.merge_reporter and proposal.merge_reporter.name or False + merge_request['registrant_email_address'] = self.get_email_address(proposal.registrant) + + comments = [] + for review in proposal.all_comments_collection: + comment = {} + comment['date'] = review.date_created + comment['author_name'] = review.author.name + comment['author_email'] = self.get_email_address(review.author) + comment['message'] = review.message_body + comment['title'] = review.title + comment['id'] = review.id + comment['vote'] = COMMENT_STATUS.get(review.vote) + comment['branch'] = proposal.source_branch_link + comments.append(comment) + merge_request['comments'] = comments + return merge_request + + def get_lp_merge_proposal(self, team, from_date=False): + merge_requests = [] + merge_state = [] + for key, value in MERGE_STATUS.items(): + if value in MERGE_STATUS_FILTERS: + continue + merge_state.append(key) + + for proposal in team.getMergeProposals(status=merge_state): + merge_requests.append(self._lp_merge_proposal(proposal, from_date)) + return merge_requests + + def get_revisions(self, branch_name, location, from_date=False): + branch = Branch.open_containing(location)[0] + + #last_revision = branch.revno() - 100 + revisions = branch.revision_history() + commits = [] + for revision in revisions: + rev_id = branch.repository.get_revision(revision) + commit_time = rev_id.timestamp + commit_date = date.fromtimestamp(commit_time) + if from_date and datetime(commit_date.year, commit_date.month, commit_date.day) <= datetime(from_date.year, from_date.month, from_date.day): + continue + commit = {} + commit['date'] = commit_date + rev_no = branch.revision_id_to_revno(rev_id) + commit['rev_id'] = rev_id + commit['rev_no'] = rev_no + commit['message'] = revision.get_summary().encode('utf-8') + commit['author_email'] = revision.get_apparent_author().encode('utf-8') + commit['ass_bugs'] =[[rev_no,bug] for bug in revision.iter_bugs()] + commit['branch'] = branch_name + commits.append(commit) + return commits + + def get_user_by_launchpad_login(self, cr, uid, launchpad_login): + if not launchpad_login: + return False + res_users = self.pool.get('res.users') + login = launchpad_login.split('-') + user_ids = res_users.search(cr, uid, [('login','=',login[0])]) + if user_ids: + return user_ids[0] + return False + + def _create_work_review(self, cr, uid, work_id, commits, context=None): + task_work_review = self.pool.get('project.task.work.review') + new_ids = [] + for commit in commits: + user_id = self.get_user_by_launchpad_login(cr, uid, commit['author_name']) + vals = { + 'ref_id': commit['id'], + 'name': commit['title'], + 'description': commit['message'], + 'date': commit['date'], + 'state': commit.get('vote', 'none') or 'none', + 'user_id': user_id, + 'user_name': commit['author_name'], + 'work_id': work_id, + } + ids = task_work_review.search(cr, uid, [('ref_id','=', commit['id'])]) + if ids and len(ids): + task_work_review.write(cr, uid, ids, vals, context=context) + new_id = ids[0] + else: + new_id = task_work_review.create(cr, uid, vals, context=context) + new_ids.append(new_id) + return new_ids + + def _create_work(self, cr, uid, merge_proposals,context=None): + task_work = self.pool.get('project.task.work') + new_ids = [] + for merge_proposal in merge_proposals: + user_id = self.get_user_by_launchpad_login(cr, uid, merge_proposal['registrant_name']) + reporter_user_id = self.get_user_by_launchpad_login(cr, uid, merge_proposal['merge_reporter']) + vals = { + 'name':merge_proposal['name'], + 'date':merge_proposal['date_created'], + 'date_started': merge_proposal['date_created_branch'], + 'date_done': merge_proposal['date_merged'], + 'user_id':user_id, + 'reporter_user_id': reporter_user_id, + 'user_name': merge_proposal['registrant_name'], + 'reporter_name': merge_proposal['merge_reporter'], + 'description':merge_proposal['description'], + 'state':merge_proposal['state'], + 'source_branch_link': merge_proposal['source_branch_link'], + 'target_branch_link': merge_proposal['target_branch_link'], + 'diff_new_lines':merge_proposal['added_lines_count'], + 'diff_rem_lines':merge_proposal['remove_lines_count'], + 'diff_modification_files':merge_proposal['diffstat_files_count'], + 'diff_modification_lines':merge_proposal['diff_lines_count'] + } + ids = task_work.search(cr, uid, [('name','=', merge_proposal['name'])]) + if ids and len(ids): + task_work.write(cr, uid, ids, vals, context=context) + new_id = ids[0] + else: + new_id = task_work.create(cr, uid, vals, context=context) + # Take all comments of merge proposal + self._create_work_review(cr, uid, new_id, merge_proposal['comments'], context=context) + new_ids.append(new_id) + return new_ids + + def update_merge_proposals(self, cr, uid, ids=None, context=None): + task_work = self.pool.get('project.task.work') + merge_state = [] + for key, value in MERGE_STATUS.items(): + if value in MERGE_STATUS_FILTERS: + continue + merge_state.append(value) + work_ids = task_work.search(cr, uid, [('state', 'in', merge_state)]) + for work in task_work.browse(cr, uid, work_ids, context=context): + proposal_link = "%s%s"%(LP_API_LINK, work.name) + try: + proposal = self.lp_load_link(proposal_link) + if proposal: + merge_proposals = [self._lp_merge_proposal(proposal)] + self._create_work(cr, uid, merge_proposals, context=context) + except Exception, e: + print 'Error on Updatation:::', e + return True + + def process_merge_proposals(self, cr, uid, ids=None, context=None): + print 'started process...' + #update details of current merge proposals + if len(MERGE_STATUS_FILTERS): + self.update_merge_proposals(cr, uid, ids=ids, context=context) + + #take merge new proposals from LP + for team in TEAMS: + lp_people = self.get_lp_people(team) + #take all merge proposal from lp which is sent by contributors + try: + merge_proposals = self.get_lp_merge_proposal(lp_people) + self._create_work(cr, uid, merge_proposals, context=context) + cr.commit() + except Exception, ex: + print 'ERROR::::', ex + print 'end process...' + return True +project_launchpad_scheduler() === added file 'project_merge_proposal/project_merge_proposal.py' --- project_merge_proposal/project_merge_proposal.py 1970-01-01 00:00:00 +0000 +++ project_merge_proposal/project_merge_proposal.py 2011-11-24 11:24:19 +0000 @@ -0,0 +1,115 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 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 osv, fields +import datetime +import time +from tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT + +WORK_STATE = [('draft', 'New'), ('open', 'In Progress'), ('needs_review', 'Needs review'), ('code_failed', 'Code failed to merge'), ('pending', 'Pending'),('in_reviewing','Review in progress'), ('ready', 'Approved'), ('done', 'Done'), ('cancelled', 'Cancelled'), ('rejected', 'Rejected')] + +REVIEW_STATE = [('resubmit', 'Resubmit'), ('none','No Comments'), + ('approved', 'Approve'), + ('need_fixing', 'Needs Fixing'), + ('need_information', 'Needs Information'), + ('disapproved', 'Disapprove') + ] + +class project_work_review(osv.osv): + _name = "project.task.work.review" + _columns = { + 'ref_id': fields.integer('Ref. Id'), + 'name': fields.char('Review summary', size=128), + 'date': fields.datetime('Date', select="1"), + 'work_id': fields.many2one('project.task.work', 'Work', ondelete='cascade', required=True, select="1"), + 'hours': fields.float('Time Spent'), + 'user_id': fields.many2one('res.users', 'Review by'), + 'company_id': fields.related('work_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True), + 'user_name': fields.char('Reviewer', size=128, help="Launchpad Login of Reviewer"), + 'description': fields.text('Description'), + 'state': fields.selection(REVIEW_STATE, 'State', required=True), + } + _defaults = { + 'state': 'none', + 'user_id': lambda obj, cr, uid, context: uid, + 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c) + } +project_work_review() + +class project_merge_proposal(osv.osv): + _inherit = "project.task.work" + def _compute(self, cr, uid, ids, fields, arg, context=None): + res = {} + resource_calendar = self.pool.get('resource.calendar') + resource_calendar_id = False + for work in self.browse(cr, uid, ids, context=context): + approved = 0.000 + need_fixing = 0.000 + resubmit = 0.000 + hours = 0.0 + if 'hours' in fields and work.date_started and work.date: + date_started = datetime.datetime.strptime(work.date_started, DEFAULT_SERVER_DATETIME_FORMAT) + date = datetime.datetime.strptime(work.date, DEFAULT_SERVER_DATETIME_FORMAT) + resource_calendar_id = (work.task_id and work.task_id.project_id) and work.task_id.project_id.resource_calendar_id or False + if resource_calendar_id: + hours = resource_calendar.interval_hours_get(cr, uid, resource_calendar_id.id, date_started, date, resource=work.user_id and work.user_id.id or False) + else: + hours = (time.mktime(date.timetuple()) - time.mktime(date_started.timetuple()))/3600 + for review in work.review_ids: + if review.state == 'approved': approved += 1.000 + if review.state == 'need_fixing': need_fixing += 1.000 + if review.state == 'resubmit': resubmit += 1.000 + res[work.id] = { + 'approve_ratio': len(work.review_ids) and approved/len(work.review_ids) or 0.000, + 'need_fixing_ratio': len(work.review_ids) and need_fixing/len(work.review_ids) or 0.000, + 'resubmit_ratio': len(work.review_ids) and resubmit/len(work.review_ids) or 0.000, + 'hours': hours + } + return res + _columns = { + 'review_ids': fields.one2many('project.task.work.review', 'work_id', 'Reviews'), + 'task_id': fields.many2one('project.task', 'Task'), + 'date_started': fields.datetime('Started Date'), + 'date_done': fields.datetime('Done Date', help="Date of Merged"), + 'date': fields.datetime('Submitted Date'), + 'source_branch_link': fields.char('Source Branch', size=512), + 'target_branch_link': fields.char('Target Branch', size=512), + 'state': fields.selection(WORK_STATE, 'State', required=True), + 'description': fields.text('Description'), + 'user_name': fields.char('Submitter',size=128, help="Launchpad Login of Submitter"), + 'reporter_name': fields.char('Merger Reporter',size=128), + 'reporter_user_id': fields.many2one('res.users', 'Merger Reporter', help="Launchpad Login of Merger"), + 'user_id': fields.many2one('res.users', 'Submitted by'), + 'diff_new_lines': fields.integer('Diff. New Lines'), + 'diff_rem_lines': fields.integer('Diff. Remove Lines'), + 'diff_modification_files': fields.integer('Diff. Modification Files'), + 'diff_modification_lines': fields.integer('Diff. Modification Lines'), + 'approve_ratio': fields.function(_compute, string='Ratio of Approved', multi='approve_ratio', help="Ratio = No. of Approved Review / Total Reviews"), + 'need_fixing_ratio': fields.function(_compute, string='Ratio of Need Fixing', multi='need_fixing_ratio', help="Ratio = No. of Need Fixing Review / Total Reviews"), + 'resubmit_ratio': fields.function(_compute, string='Ratio of Resubmit', multi='resubmit_ratio', help="Ratio = No. of ReSubmit / Total Reviews"), + #'hours': fields.function(_compute, string='Time Spent', multi='hours', help="Hours = Start Date - Submmitted Date"), + } + _defaults = { + 'state': 'draft', + } + +project_merge_proposal() +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: === added file 'project_merge_proposal/project_merge_proposal_view.xml' --- project_merge_proposal/project_merge_proposal_view.xml 1970-01-01 00:00:00 +0000 +++ project_merge_proposal/project_merge_proposal_view.xml 2011-11-24 11:24:19 +0000 @@ -0,0 +1,157 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + + <record id="view_task_work_form" model="ir.ui.view"> + <field name="name">project.task.work.form</field> + <field name="model">project.task.work</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Task Work"> + <group colspan="4" col="6"> + <field name="name" /> + <field name="user_id" /> + <field name="user_name" /> + <field name="date_started" /> + <field name="date" /> + <field name="hours" widget="float_time"/> + </group> + <field name="company_id" groups="base.group_multi_company" widget="selection"/> + <notebook colspan="4"> + <page string="Details"> + <field name="source_branch_link" /> + <field name="target_branch_link" /> + <field name="diff_new_lines" /> + <field name="diff_rem_lines" /> + <field name="diff_modification_files" /> + <field name="diff_modification_lines" /> + <separator string="Feedback" colspan="4"/> + <group colspan="4" col="6"> + <field name="approve_ratio"/> + <field name="need_fixing_ratio"/> + <field name="resubmit_ratio"/> + <field name="date_done" attrs="{'invisible': [('state','!=','done')]}"/> + <field name="reporter_user_id" attrs="{'invisible': [('state','!=','done')]}"/> + <field name="reporter_name" attrs="{'invisible': [('state','!=','done')]}"/> + </group> + <separator string="Description" colspan="4"/> + <field name="description" colspan="4" nolabel="1"/> + + + </page> + <page string="Review Details"> + <field colspan="4" name="review_ids" nolabel="1" mode="tree,form" attrs="{'readonly':[('state','in',['done','draft'])]}"> + <form string="Work Review"> + <field name="user_id" /> + <field name="user_name" /> + <field name="date" /> + <field name="hours" widget="float_time" sum="Spent Hours"/> + <field name="name"/> + <field name="state" readonly="1"/> + <field name="description" nolabel="1" colspan="4"/> + </form> + <tree string="Work Review"> + <field name="date" /> + <field name="user_id" /> + <field name="user_name" /> + <field name="state" readonly="1"/> + </tree> + </field> + </page> + + </notebook> + <field name="state" readonly="1"/> + </form> + </field> + </record> + + <record id="view_task_work_tree" model="ir.ui.view"> + <field name="name">project.task.work.tree</field> + <field name="model">project.task.work</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="Task Work"> + <field name="name"/> + <field name="diff_new_lines" sum="Added Lines"/> + <field name="diff_rem_lines" sum="Removed Lines"/> + <field name="diff_modification_files" sum="Modified Files"/> + <field name="diff_modification_lines" sum="Modified Lines"/> + <field name="approve_ratio"/> + <field name="need_fixing_ratio"/> + <field name="resubmit_ratio"/> + <field name="user_id"/> + <field name="user_name"/> + <field name="date"/> + <field name="hours" widget="float_time"/> + <field name="state" readonly="1"/> + </tree> + </field> + </record> + + + <record id="view_task_work_search_form" model="ir.ui.view"> + <field name="name">project.task.work.search.form</field> + <field name="model">project.task.work</field> + <field name="type">search</field> + <field name="arch" type="xml"> + <search string="work details"> + <group> + <filter string="This Month" icon="terp-go-month" name="month" domain="[('date','<=',(datetime.date.today()+relativedelta(day=31)).strftime('%%Y-%%m-%%d')),('date','>=',(datetime.date.today()-relativedelta(day=1)).strftime('%%Y-%%m-%%d'))]"/> + <separator orientation="vertical"/> + <filter name="need_review" string="Need Review" domain="[('state','=','needs_review')]" help="Need Review" icon="terp-check"/> + <filter string="Done" domain="[('state','=','done')]" name="done" help="Done" icon="terp-dialog-close"/> + <filter string="Rejected" domain="[('state','=','rejected')]" help="Rejected" icon="gtk-cancel"/> + <separator orientation="vertical"/> + <field name="date"/> + <separator orientation="vertical"/> + <field name="name"/> + + <field name="user_id"> + <filter domain="[('user_id','=',uid)]" help="My Works" icon="terp-personal" /> + </field> + <field name="user_name"/> + </group> + <newline/> + <group expand="0" string="Group By..."> + <filter string="Users" name="group_user_id" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/> + <filter string="Users By Name" name="group_user_id" icon="terp-personal" domain="[]" context="{'group_by':'user_name'}"/> + <separator orientation="vertical"/> + <filter string="State" name="group_state" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> + <separator orientation="vertical"/> + <filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'date'}"/> + </group> + </search> + </field> + </record> + + <record id="action_view_task_work" model="ir.actions.act_window"> + <field name="name">Works</field> + <field name="res_model">project.task.work</field> + + <field name="view_mode">tree,form</field> + + <field name="view_id" ref="view_task_work_tree"/> + <field name="context">{"search_default_month": 1, "search_default_done": 1}</field> + <field name="search_view_id" ref="view_task_work_search_form"/> + </record> + + <record model="ir.actions.act_window.view" id="action_tree_view_merge_proposal"> + <field name="sequence" eval="1"/> + <field name="view_mode">tree</field> + <field name="view_id" ref="view_task_work_tree"/> + <field name="act_window_id" ref="action_view_task_work"/> + </record> + + <record model="ir.actions.act_window.view" id="action_form_view_merge_proposal"> + <field name="sequence" eval="3"/> + <field name="view_mode">form</field> + <field name="view_id" ref="view_task_work_form"/> + <field name="act_window_id" ref="action_view_task_work"/> + </record> + + + <menuitem action="action_view_task_work" id="menu_action_view_task_work" parent="project.menu_project_management" sequence="3"/> + + +</data> +</openerp> === added file 'project_merge_proposal/scheduler_data.xml' --- project_merge_proposal/scheduler_data.xml 1970-01-01 00:00:00 +0000 +++ project_merge_proposal/scheduler_data.xml 2011-11-24 11:24:19 +0000 @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data noupdate="1"> + <record forcecreate="True" id="ir_cron_merge_scheduler_action" model="ir.cron"> + <field name="name">Merge Proposal Manager</field> + <field name="user_id" ref="base.user_root"/> + <field name="interval_number">1</field> + <field name="interval_type">hours</field> + <field name="numbercall">-1</field> + <field eval="False" name="doall"/> + <field eval="'project.launchpad.scheduler'" name="model"/> + <field eval="'process_merge_proposals'" name="function"/> + <field eval="'()'" name="args"/> + </record> + + + </data> +</openerp> === added file 'project_merge_proposal/scheduler_view.xml' --- project_merge_proposal/scheduler_view.xml 1970-01-01 00:00:00 +0000 +++ project_merge_proposal/scheduler_view.xml 2011-11-24 11:24:19 +0000 @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + + <!-- Compute Schedulers --> + + <record id="view_compute_scheduler_wizard" model="ir.ui.view"> + <field name="name">Compute Scheduler</field> + <field name="model">project.launchpad.scheduler</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Scheduler"> + <button name="process_merge_proposals" string="Compute Scheduler" + colspan="1" type="object" icon="gtk-ok" /> + </form> + </field> + </record> + + <act_window name="Compute Scheduler" + res_model="project.launchpad.scheduler" + src_model="project.task" + view_mode="form" + target="new" + key2="client_action_multi" + id="action_schedule_task"/> + + + <menuitem action="action_schedule_task" id="menu_project_merge_proposal_schedulers" parent="project.menu_project_management" sequence="20" /> + + </data> +</openerp> === added directory 'project_merge_proposal/test' === added file 'project_merge_proposal/test/merge_proposal.yml' --- project_merge_proposal/test/merge_proposal.yml 1970-01-01 00:00:00 +0000 +++ project_merge_proposal/test/merge_proposal.yml 2011-11-24 11:24:19 +0000 @@ -0,0 +1,8 @@ +- + process merge proposal +- + !python {model: project.launchpad.scheduler}: | + self.process_merge_proposals(cr, uid, [], context=context) + + +
_______________________________________________ Mailing list: https://launchpad.net/~openerp-dev-gtk Post to : [email protected] Unsubscribe : https://launchpad.net/~openerp-dev-gtk More help : https://help.launchpad.net/ListHelp

