import collections import datetime import pathlib import werkzeug.urls from odoo.http import route, request from odoo.osv import expression from odoo.addons.runbot_merge.controllers.dashboard import MergebotDashboard DEFAULT_DELTA = datetime.timedelta(days=7) class Dashboard(MergebotDashboard): def _entries(self): changelog = pathlib.Path(__file__).parent / 'changelog' if not changelog.is_dir(): return super()._entries() return super()._entries() + [ (d.name, [f.read_text(encoding='utf-8') for f in d.iterdir() if f.is_file()]) for d in changelog.iterdir() ] @route('/forwardport/outstanding', type='http', methods=['GET'], auth="user", website=True, sitemap=False) def outstanding(self, partner=0, authors=True, reviewers=True, group=0): Partners = request.env['res.partner'] PullRequests = request.env['runbot_merge.pull_requests'] partner = Partners.browse(int(partner)) group = Partners.browse(int(group)) authors = int(authors) reviewers = int(reviewers) link = lambda **kw: '?' + werkzeug.urls.url_encode({'partner': partner.id or 0, 'authors': authors, 'reviewers': reviewers, **kw, }) groups = Partners.search([('is_company', '=', True), ('child_ids', '!=', False)]) if not (authors or reviewers): return request.render('forwardport.outstanding', { 'authors': 0, 'reviewers': 0, 'single': partner, 'culprits': partner, 'groups': groups, 'current_group': group, 'outstanding': [], 'outstanding_per_author': {partner: 0}, 'outstanding_per_reviewer': {partner: 0}, 'link': link, }) source_filter = [('merge_date', '<', datetime.datetime.now() - DEFAULT_DELTA)] partner_filter = [] if partner or group: if partner: suffix = '' arg = partner.id else: suffix = '.commercial_partner_id' arg = group.id if authors: partner_filter.append([(f'author{suffix}', '=', arg)]) if reviewers: partner_filter.append([(f'reviewed_by{suffix}', '=', arg)]) source_filter.extend(expression.OR(partner_filter)) outstanding = PullRequests.search([ ('state', 'in', ['opened', 'validated', 'approved', 'ready', 'error']), ('source_id', 'in', PullRequests._search(source_filter)), ]) outstanding_per_group = collections.Counter() outstanding_per_author = collections.Counter() outstanding_per_reviewer = collections.Counter() outstandings = [] for source in outstanding.mapped('source_id').sorted('merge_date'): prs = source.forwardport_ids.filtered(lambda p: p.state not in ['merged', 'closed']) outstandings.append({ 'source': source, 'prs': prs, }) if authors: outstanding_per_author[source.author] += len(prs) outstanding_per_group[source.author.commercial_partner_id] += len(prs) if reviewers and source: outstanding_per_reviewer[source.reviewed_by] += len(prs) outstanding_per_group[source.reviewed_by.commercial_partner_id] += len(prs) culprits = Partners.browse(p.id for p, _ in (outstanding_per_reviewer + outstanding_per_author).most_common()) return request.render('forwardport.outstanding', { 'authors': authors, 'reviewers': reviewers, 'single': partner, 'culprits': culprits, 'groups': groups, 'current_group': group, 'outstanding_per_author': outstanding_per_author, 'outstanding_per_reviewer': outstanding_per_reviewer, 'outstanding_per_group': outstanding_per_group, 'outstanding': outstandings, 'link': link, })