Ejemplo n.º 1
0
def queue_service_class_reports():
    from kardboard.app import app
    from kardboard.models import ServiceClassRecord, ServiceClassSnapshot
    from kardboard.util import now, month_ranges

    logger = queue_service_class_reports.get_logger()
    report_groups = app.config.get('REPORT_GROUPS', {})
    group_slugs = report_groups.keys()
    group_slugs.append('all')

    for slug in group_slugs:
        logger.info("ServiceClassSnapshot: %s" % slug)
        ServiceClassSnapshot.calculate(slug)
        for x in [1, 3, 6, 9, 12]:
            start = now()
            months_ranges = month_ranges(start, x)
            start_date = months_ranges[0][0]
            end_date = months_ranges[-1][1]
            try:
                logger.info("ServiceClassRecord: %s %s - %s" %
                            (slug, start_date, end_date))
                ServiceClassRecord.calculate(
                    start_date=start_date,
                    end_date=end_date,
                    group=slug,
                )
            except Exception, e:
                msg = "ERROR: Couldn't calc record: %s / %s / %s" % \
                    (slug, start_date, end_date)
                log_exception(e, msg)
Ejemplo n.º 2
0
def queue_service_class_reports():
    from kardboard.app import app
    from kardboard.models import ServiceClassRecord, ServiceClassSnapshot
    from kardboard.util import now, month_ranges

    logger = queue_service_class_reports.get_logger()
    report_groups = app.config.get('REPORT_GROUPS', {})
    group_slugs = report_groups.keys()
    group_slugs.append('all')

    for slug in group_slugs:
        logger.info("ServiceClassSnapshot: %s" % slug)
        ServiceClassSnapshot.calculate(slug)
        for x in [1, 3, 6, 9, 12]:
            start = now()
            months_ranges = month_ranges(start, x)
            start_date = months_ranges[0][0]
            end_date = months_ranges[-1][1]
            try:
                logger.info("ServiceClassRecord: %s %s - %s" % (slug, start_date, end_date))
                ServiceClassRecord.calculate(
                    start_date=start_date,
                    end_date=end_date,
                    group=slug,
                )
            except Exception, e:
                msg = "ERROR: Couldn't calc record: %s / %s / %s" % \
                    (slug, start_date, end_date)
                log_exception(e, msg)
Ejemplo n.º 3
0
def report_detailed_flow(group="all", months=3, cards_only=False):
    end = kardboard.util.now()
    months_ranges = month_ranges(end, months)

    start_day = make_start_date(date=months_ranges[0][0])
    end_day = make_end_date(date=end)

    if cards_only:
        only_arg = ('state_card_counts', 'date', 'group')
    else:
        only_arg = ('state_counts', 'date', 'group')

    reports = FlowReport.objects.filter(
        date__gte=start_day,
        date__lte=end_day,
        group=group).only(*only_arg)
    if not reports:
        abort(404)

    chart = {}
    chart['categories'] = []

    series = []
    for state in States():
        seri = {'name': state, 'data': []}
        series.append(seri)

    done_starting_point = 0
    for report in reports:
        chart['categories'].append(report.date.strftime("%m/%d"))
        for seri in series:
            if cards_only:
                daily_seri_data = report.state_card_counts.get(seri['name'], 0)
            else:
                daily_seri_data = report.state_counts.get(seri['name'], 0)

            if seri['name'] == "Done":
                if len(seri['data']) == 0:
                    done_starting_point = daily_seri_data
                    daily_seri_data = 0
                else:
                    daily_seri_data = daily_seri_data - done_starting_point

            seri['data'].append(daily_seri_data)
    chart['series'] = series

    start_date = reports.order_by('date').first().date
    reports.order_by('-date')
    context = {
        'title': "Detailed Cumulative Flow",
        'reports': reports,
        'months': months,
        'cards_only': cards_only,
        'chart': chart,
        'start_date': start_date,
        'updated_at': reports[0].updated_at,
        'states': States(),
        'version': VERSION,
    }
    return render_template('report-detailed-flow.html', **context)
Ejemplo n.º 4
0
def report_flow(group="all", months=3):
    end = kardboard.util.now()
    months_ranges = month_ranges(end, months)

    start_day = make_start_date(date=months_ranges[0][0])
    end_day = make_end_date(date=end)

    records = DailyRecord.objects.filter(date__gte=start_day, date__lte=end_day, group=group)

    chart = {}
    chart["categories"] = [report.date.strftime("%m/%d") for report in records]
    series = [{"name": "Planning", "data": []}, {"name": "Todo", "data": []}, {"name": "Done", "data": []}]
    for row in records:
        series[0]["data"].append(row.backlog)
        series[1]["data"].append(row.in_progress)
        series[2]["data"].append(row.done)
    chart["series"] = series

    start_date = records.order_by("date").first().date
    records.order_by("-date")
    context = {
        "title": "Cumulative Flow",
        "updated_at": datetime.datetime.now(),
        "chart": chart,
        "start_date": start_date,
        "flowdata": records,
        "version": VERSION,
    }
    return render_template("chart-flow.html", **context)
Ejemplo n.º 5
0
def report_throughput(group="all", months=3, start=None):
    start = start or datetime.datetime.today()
    months_ranges = month_ranges(start, months)

    month_counts = []
    for arange in months_ranges:
        start, end = arange
        filtered_cards = Kard.objects.filter(done_date__gte=start, done_date__lte=end)
        rg = ReportGroup(group, filtered_cards)
        cards = rg.queryset

        num = cards.count()
        month_counts.append((start.strftime("%B"), num))

    chart = {}
    chart["categories"] = [c[0] for c in month_counts]
    chart["series"] = [{"data": [c[1] for c in month_counts], "name": "Cards"}]

    context = {
        "title": "How much have we done?",
        "updated_at": datetime.datetime.now(),
        "chart": chart,
        "month_counts": month_counts,
        "version": VERSION,
    }

    return render_template("report-throughput.html", **context)
Ejemplo n.º 6
0
def chart_flow(group="all", months=3):
    end = kardboard.util.now()
    months_ranges = month_ranges(end, months)

    start_day = make_start_date(date=months_ranges[0][0])
    end_day = make_end_date(date=end)

    records = DailyRecord.objects.filter(
        date__gte=start_day,
        date__lte=end_day,
        group=group)

    chart = CumulativeFlowChart(900, 300)
    chart.add_data([r.backlog_cum for r in records])
    chart.add_data([r.in_progress_cum for r in records])
    chart.add_data([r.done for r in records])
    chart.setup_grid(records)

    records.order_by('-date')
    context = {
        'title': "Cumulative Flow",
        'updated_at': datetime.datetime.now(),
        'chart': chart,
        'flowdata': records,
        'version': VERSION,
    }

    return render_template('chart-flow.html', **context)
Ejemplo n.º 7
0
def report_service_class(group="all", months=None):
    from kardboard.app import app

    service_class_order = app.config.get("SERVICE_CLASSES", {}).keys()
    service_class_order.sort()
    service_classes = [app.config["SERVICE_CLASSES"][k] for k in service_class_order]

    if months is None:
        # We want the current report
        try:
            scr = ServiceClassSnapshot.objects.get(group=group)
        except ServiceClassSnapshot.DoesNotExist:
            scr = ServiceClassSnapshot.calculate(group=group)
        time_range = "current"
    else:
        start = now()
        months_ranges = month_ranges(start, months)
        start_date = months_ranges[0][0]
        end_date = months_ranges[-1][1]
        try:
            scr = ServiceClassRecord.objects.get(group=group, start_date=start_date, end_date=end_date)
        except ServiceClassRecord.DoesNotExist:
            scr = ServiceClassRecord.calculate(group=group, start_date=start_date, end_date=end_date)
        time_range = "past %s months" % months

    context = {
        "title": "Service classes: %s" % time_range,
        "service_classes": service_classes,
        "data": scr.data,
        "updated_at": scr.updated_at,
        "version": VERSION,
    }

    return render_template("report-service-class.html", **context)
Ejemplo n.º 8
0
def report_throughput(group="all", months=3, start=None):
    start = start or datetime.datetime.today()
    months_ranges = month_ranges(start, months)

    month_counts = []
    for arange in months_ranges:
        start, end = arange
        filtered_cards = Kard.objects.filter(done_date__gte=start,
            done_date__lte=end)
        rg = ReportGroup(group, filtered_cards)
        cards = rg.queryset

        num = cards.count()
        month_counts.append((start.strftime("%B"), num))

    chart = {}
    chart['categories'] = [c[0] for c in month_counts]
    chart['series'] = [{
        'data': [c[1] for c in month_counts],
        'name': 'Cards',
    }]

    context = {
        'title': "How much have we done?",
        'updated_at': datetime.datetime.now(),
        'chart': chart,
        'month_counts': month_counts,
        'version': VERSION,
    }

    return render_template('report-throughput.html', **context)
Ejemplo n.º 9
0
def chart_throughput(group="all", months=3, start=None):
    start = start or datetime.datetime.today()
    months_ranges = month_ranges(start, months)

    month_counts = []
    for arange in months_ranges:
        start, end = arange
        filtered_cards = Kard.objects.filter(done_date__gte=start,
            done_date__lte=end)
        rg = ReportGroup(group, filtered_cards)
        cards = rg.queryset

        num = cards.count()
        month_counts.append((start.strftime("%B"), num))

    chart = ThroughputChart(900, 300)
    chart.add_bars(month_counts)

    context = {
        'title': "How much have we done?",
        'updated_at': datetime.datetime.now(),
        'chart': chart,
        'month_counts': month_counts,
        'version': VERSION,
    }

    return render_template('chart-throughput.html', **context)
Ejemplo n.º 10
0
def report_detailed_flow(group="all", months=3, cards_only=False):
    end = kardboard.util.now()
    months_ranges = month_ranges(end, months)

    start_day = make_start_date(date=months_ranges[0][0])
    end_day = make_end_date(date=end)

    if cards_only:
        only_arg = ('state_card_counts', 'date', 'group')
    else:
        only_arg = ('state_counts', 'date', 'group')

    reports = FlowReport.objects.filter(date__gte=start_day,
                                        date__lte=end_day,
                                        group=group).only(*only_arg)
    if not reports:
        abort(404)

    chart = {}
    chart['categories'] = []

    series = []
    for state in States():
        seri = {'name': state, 'data': []}
        series.append(seri)

    done_starting_point = 0
    for report in reports:
        chart['categories'].append(report.date.strftime("%m/%d"))
        for seri in series:
            if cards_only:
                daily_seri_data = report.state_card_counts.get(seri['name'], 0)
            else:
                daily_seri_data = report.state_counts.get(seri['name'], 0)

            if seri['name'] == "Done":
                if len(seri['data']) == 0:
                    done_starting_point = daily_seri_data
                    daily_seri_data = 0
                else:
                    daily_seri_data = daily_seri_data - done_starting_point

            seri['data'].append(daily_seri_data)
    chart['series'] = series

    start_date = reports.order_by('date').first().date
    reports.order_by('-date')
    context = {
        'title': "Detailed Cumulative Flow",
        'reports': reports,
        'months': months,
        'cards_only': cards_only,
        'chart': chart,
        'start_date': start_date,
        'updated_at': reports[0].updated_at,
        'states': States(),
        'version': VERSION,
    }
    return render_template('report-detailed-flow.html', **context)
Ejemplo n.º 11
0
def report_efficiency(group="all", months=3):
    state_mappings = app.config.get("EFFICIENCY_MAPPINGS", None)
    if state_mappings is None:
        abort(404)
    stats = teams_service.EfficiencyStats(mapping=state_mappings)

    end = kardboard.util.now()
    months_ranges = month_ranges(end, months)

    start_day = make_start_date(date=months_ranges[0][0])
    end_day = make_end_date(date=end)

    records = FlowReport.objects.filter(date__gte=start_day, date__lte=end_day, group=group)

    incremented_state_counts = []
    for r in records:
        a_record = {"date": r.date}
        a_record.update(r.state_counts)
        incremented_state_counts.append(a_record)

    for group_name in app.config.get("EFFICIENCY_INCREMENTS", ()):
        stats.make_incremental(incremented_state_counts, group_name)

    data = []
    for r in incremented_state_counts:
        efficiency_stats = stats.calculate(r)
        data.append({"date": r["date"], "stats": efficiency_stats})

    chart = {}
    chart["categories"] = [report.date.strftime("%m/%d") for report in records]
    group_names = app.config.get("EFFICIENCY_MAPPINGS_ORDER", state_mappings.keys())
    series = []
    for group_name in group_names:
        seri_data = []
        for d in data:
            seri_data.append(d["stats"][group_name])
        seri = dict(name=group_name, data=seri_data)
        series.append(seri)
    chart["series"] = series

    table_data = []
    for row in data:
        table_row = {"Date": row["date"]}
        for group_name in group_names:
            table_row[group_name] = row["stats"][group_name]
        table_data.append(table_row)

    start_date = records.order_by("date").first().date
    context = {
        "title": "Efficiency",
        "start_date": start_date,
        "chart": chart,
        "table_data": table_data,
        "data_keys": ["Date"] + list(group_names),
        "updated_at": records.order_by("date")[len(records) - 1].date,
        "version": VERSION,
    }
    return render_template("chart-efficiency.html", **context)
Ejemplo n.º 12
0
def report_detailed_flow(group="all", months=3, cards_only=False):
    end = kardboard.util.now()
    months_ranges = month_ranges(end, months)

    start_day = make_start_date(date=months_ranges[0][0])
    end_day = make_end_date(date=end)

    if cards_only:
        only_arg = ("state_card_counts", "date", "group")
    else:
        only_arg = ("state_counts", "date", "group")

    reports = FlowReport.objects.filter(date__gte=start_day, date__lte=end_day, group=group).only(*only_arg)
    if not reports:
        abort(404)

    chart = {}
    chart["categories"] = []

    series = []
    for state in States():
        seri = {"name": state, "data": []}
        series.append(seri)

    done_starting_point = 0
    for report in reports:
        chart["categories"].append(report.date.strftime("%m/%d"))
        for seri in series:
            if cards_only:
                daily_seri_data = report.state_card_counts.get(seri["name"], 0)
            else:
                daily_seri_data = report.state_counts.get(seri["name"], 0)

            if seri["name"] == "Done":
                if len(seri["data"]) == 0:
                    done_starting_point = daily_seri_data
                    daily_seri_data = 0
                else:
                    daily_seri_data = daily_seri_data - done_starting_point

            seri["data"].append(daily_seri_data)
    chart["series"] = series

    start_date = reports.order_by("date").first().date
    reports.order_by("-date")
    context = {
        "title": "Detailed Cumulative Flow",
        "reports": reports,
        "months": months,
        "cards_only": cards_only,
        "chart": chart,
        "start_date": start_date,
        "updated_at": reports[0].updated_at,
        "states": States(),
        "version": VERSION,
    }
    return render_template("report-detailed-flow.html", **context)
Ejemplo n.º 13
0
def report_throughput(group="all", months=3, start=None):
    start = start or datetime.datetime.today()
    months_ranges = month_ranges(start, months)
    defect_types = app.config.get('DEFECT_TYPES', None)
    with_defects = defect_types is not None

    month_counts = []
    for arange in months_ranges:
        start, end = arange
        filtered_cards = Kard.objects.filter(done_date__gte=start,
            done_date__lte=end)
        rg = ReportGroup(group, filtered_cards)
        cards = rg.queryset

        if with_defects:
            counts = {'card': 0, 'defect': 0}
            for card in cards:
                if card.type.strip() in defect_types:
                    counts['defect'] += 1
                else:
                    counts['card'] += 1
            month_counts.append((start.strftime("%B '%y"), counts))
        else:
            num = cards.count()
            month_counts.append((start.strftime("%B, '%y"), num))

    chart = {}
    chart['categories'] = [c[0] for c in month_counts]

    if with_defects:
        chart['series'] = [
            {
                'data': [c[1]['card'] for c in month_counts],
                'name': 'Cards'
            },
            {
                'data': [c[1]['defect'] for c in month_counts],
                'name': 'Defects'
            }
        ]
    else:
        chart['series'] = [{
            'data': [c[1] for c in month_counts],
            'name': 'Cards',
        }]

    context = {
        'title': "How much have we done?",
        'updated_at': datetime.datetime.now(),
        'chart': chart,
        'month_counts': month_counts,
        'version': VERSION,
        'with_defects': with_defects,
    }

    return render_template('report-throughput.html', **context)
Ejemplo n.º 14
0
def report_throughput(group="all", months=3, start=None):
    start = start or datetime.datetime.today()
    months_ranges = month_ranges(start, months)
    defect_types = app.config.get('DEFECT_TYPES', None)
    with_defects = defect_types is not None

    month_counts = []
    for arange in months_ranges:
        start, end = arange
        filtered_cards = Kard.objects.filter(done_date__gte=start,
            done_date__lte=end)
        rg = ReportGroup(group, filtered_cards)
        cards = rg.queryset

        if with_defects:
            counts = {'card': 0, 'defect': 0}
            for card in cards:
                if card.type.strip() in defect_types:
                    counts['defect'] += 1
                else:
                    counts['card'] += 1
            month_counts.append((start.strftime("%B"), counts))
        else:
            num = cards.count()
            month_counts.append((start.strftime("%B"), num))

    chart = {}
    chart['categories'] = [c[0] for c in month_counts]

    if with_defects:
        chart['series'] = [
            {
                'data': [c[1]['card'] for c in month_counts],
                'name': 'Cards'
            },
            {
                'data': [c[1]['defect'] for c in month_counts],
                'name': 'Defects'
            }
        ]
    else:
        chart['series'] = [{
            'data': [c[1] for c in month_counts],
            'name': 'Cards',
        }]

    context = {
        'title': "How much have we done?",
        'updated_at': datetime.datetime.now(),
        'chart': chart,
        'month_counts': month_counts,
        'version': VERSION,
        'with_defects': with_defects,
    }

    return render_template('report-throughput.html', **context)
Ejemplo n.º 15
0
def report_leaderboard(group="all",
                       months=3,
                       person=None,
                       start_month=None,
                       start_year=None):
    start = datetime.datetime.today()
    if start_month and start_year:
        start = start.replace(month=start_month, year=start_year)
    months_ranges = month_ranges(start, months)

    start = months_ranges[0][0]
    end = months_ranges[-1][-1]

    rg = ReportGroup(group, Kard.objects.done())
    done = rg.queryset

    cards = done.filter(done_date__gte=start, done_date__lte=end)

    people = {}
    for card in cards:
        try:
            devs = card.ticket_system_data['developers']
            for d in devs:
                p = people.get(d, PersonCardSet(d))
                p.add_card(card)
                people[d] = p
        except KeyError:
            pass

    if person:
        person = people.get(person, None)
        people = []
        if not person:
            abort(404)
    else:
        people = people.values()
        people.sort(reverse=True)

    context = {
        'people': people,
        'person': person,
        'months': months,
        'group': group,
        'start': start,
        'end': end,
        'start_month': start_month,
        'start_year': start_year,
        'title': "Developer Leaderboard",
        'updated_at': datetime.datetime.now(),
        'version': VERSION,
    }
    if person:
        context['title'] = "%s: %s" % (person.name, context['title'])

    return render_template('leaderboard.html', **context)
Ejemplo n.º 16
0
def report_service_class(group="all", months=3, start=None):
    start = start or datetime.datetime.today()
    months_ranges = month_ranges(start, months)
    rg = ReportGroup(group, Kard.objects)
    rg_cards = rg.queryset
    classes = rg_cards.distinct('service_class')
    classes.sort()

    datatable = {
        'headers': ('Month', 'Class', 'Throughput', 'Cycle Time', 'Lead Time'),
        'rows': [],
    }

    months = []
    for arange in months_ranges:
        for cls in classes:
            row = []
            start, end = arange
            filtered_cards = Kard.objects.filter(done_date__gte=start,
                done_date__lte=end, _service_class=cls)
            rg = ReportGroup(group, filtered_cards)
            cards = rg.queryset

            if cards.count() == 0:
                # We don't need to have rows for
                # service classes we didn't do
                continue
            month_name = start.strftime("%B")
            if month_name not in months:
                row.append(month_name)
                months.append(month_name)
            else:
                row.append('')
            row.append(cls)
            row.append(cards.count())
            if cards.count() > 0:
                row.append("%d" % cards.average('_cycle_time'))
                row.append("%d" % cards.average('_lead_time'))
            else:
                row.append('N/A')
                row.append('N/A')
            row = tuple(row)
            datatable['rows'].append(row)

    context = {
        'title': "By service class",
        'updated_at': datetime.datetime.now(),
        'datatable': datatable,
        'version': VERSION,
    }

    return render_template('report-classes.html', **context)
Ejemplo n.º 17
0
def report_leaderboard(group="all", months=3, person=None, start_month=None, start_year=None):
    start = datetime.datetime.today()
    if start_month and start_year:
        start = start.replace(month=start_month, year=start_year)
    months_ranges = month_ranges(start, months)

    start = months_ranges[0][0]
    end = months_ranges[-1][-1]

    rg = ReportGroup(group, Kard.objects.done())
    done = rg.queryset

    cards = done.filter(done_date__gte=start,
        done_date__lte=end)

    people = {}
    for card in cards:
        try:
            devs = card.ticket_system_data['developers']
            for d in devs:
                p = people.get(d, PersonCardSet(d))
                p.add_card(card)
                people[d] = p
        except KeyError:
            pass

    if person:
        person = people.get(person, None)
        people = []
        if not person:
            abort(404)
    else:
        people = people.values()
        people.sort(reverse=True)

    context = {
        'people': people,
        'person': person,
        'months': months,
        'group': group,
        'start': start,
        'end': end,
        'start_month': start_month,
        'start_year': start_year,
        'title': "Developer Leaderboard",
        'updated_at': datetime.datetime.now(),
        'version': VERSION,
    }
    if person:
        context['title'] = "%s: %s" % (person.name, context['title'])

    return render_template('leaderboard.html', **context)
Ejemplo n.º 18
0
def report_service_class(group="all", months=None):
    from kardboard.app import app
    service_class_order = app.config.get('SERVICE_CLASSES', {}).keys()
    service_class_order.sort()
    service_classes = [
        app.config['SERVICE_CLASSES'][k] for k in service_class_order
    ]

    if months is None:
        # We want the current report
        try:
            scr = ServiceClassSnapshot.objects.get(
                group=group,
            )
        except ServiceClassSnapshot.DoesNotExist:
            scr = ServiceClassSnapshot.calculate(
                group=group,
            )
        time_range = 'current'
        start_date = make_start_date(date=datetime.datetime.now())
        end_date = make_end_date(date=datetime.datetime.now())
    else:
        start = now()
        months_ranges = month_ranges(start, months)
        start_date = months_ranges[0][0]
        end_date = months_ranges[-1][1]
        try:
            scr = ServiceClassRecord.objects.get(
                group=group,
                start_date=start_date,
                end_date=end_date,
            )
        except ServiceClassRecord.DoesNotExist:
            scr = ServiceClassRecord.calculate(
                group=group,
                start_date=start_date,
                end_date=end_date,
            )
        time_range = 'past %s months' % months

    context = {
        'title': "Service classes: %s" % time_range,
        'service_classes': service_classes,
        'data': scr.data,
        'start_date': start_date,
        'end_date': end_date,
        'updated_at': scr.updated_at,
        'version': VERSION,
    }

    return render_template('report-service-class.html', **context)
Ejemplo n.º 19
0
def report_leaderboard(group="all", months=3, person=None, start_month=None, start_year=None):
    start = datetime.datetime.today()
    if start_month and start_year:
        start = start.replace(month=start_month, year=start_year)
    months_ranges = month_ranges(start, months)

    start = months_ranges[0][0]
    end = months_ranges[-1][-1]

    rg = ReportGroup(group, Kard.objects.done())
    done = rg.queryset

    cards = done.filter(done_date__gte=start, done_date__lte=end)

    people = {}
    for card in cards:
        try:
            devs = card.ticket_system_data["developers"]
            for d in devs:
                p = people.get(d, PersonCardSet(d))
                p.add_card(card)
                people[d] = p
        except KeyError:
            pass

    if person:
        person = people.get(person, None)
        people = []
        if not person:
            abort(404)
    else:
        people = people.values()
        people.sort(reverse=True)

    context = {
        "people": people,
        "person": person,
        "months": months,
        "group": group,
        "start": start,
        "end": end,
        "start_month": start_month,
        "start_year": start_year,
        "title": "Developer Leaderboard",
        "updated_at": datetime.datetime.now(),
        "version": VERSION,
    }
    if person:
        context["title"] = "%s: %s" % (person.name, context["title"])

    return render_template("leaderboard.html", **context)
Ejemplo n.º 20
0
def done(group="all", months=3, start=None):
    start = start or datetime.datetime.today()
    months_ranges = month_ranges(start, months)

    start = months_ranges[0][0]
    end = months_ranges[-1][-1]

    rg = ReportGroup(group, Kard.objects.done())
    done = rg.queryset

    cards = done.filter(done_date__gte=start, done_date__lte=end).order_by("-done_date")

    context = {"title": "Completed Cards", "cards": cards, "updated_at": datetime.datetime.now(), "version": VERSION}

    return render_template("done.html", **context)
Ejemplo n.º 21
0
def report_types(group="all", months=3, start=None):
    start = start or datetime.datetime.today()
    months_ranges = month_ranges(start, months)
    rg = ReportGroup(group, Kard.objects)
    rg_cards = rg.queryset
    types = list(rg_cards.distinct('_type'))
    types.sort()

    datatable = {
        'headers': ('Month', 'Type', 'Throughput', 'Cycle Time', 'Lead Time'),
        'rows': [],
    }

    months = []
    for arange in months_ranges:
        for typ in types:
            row = []
            start, end = arange
            filtered_cards = Kard.objects.filter(done_date__gte=start,
                                                 done_date__lte=end,
                                                 _type=typ)
            rg = ReportGroup(group, filtered_cards)
            cards = rg.queryset

            if cards.count() > 0:
                month_name = start.strftime("%B")
                if month_name not in months:
                    row.append(month_name)
                    months.append(month_name)
                else:
                    row.append('')

                row.append(typ)
                row.append(cards.count())
                row.append("%d" % cards.average('_cycle_time'))
                row.append("%d" % cards.average('_lead_time'))
            if row:
                row = tuple(row)
                datatable['rows'].append(row)

    context = {
        'title': "By type",
        'updated_at': datetime.datetime.now(),
        'datatable': datatable,
        'version': VERSION,
    }

    return render_template('report-types.html', **context)
Ejemplo n.º 22
0
def report_service_class(group="all", months=None):
    from kardboard.app import app
    service_class_order = app.config.get('SERVICE_CLASSES', {}).keys()
    service_class_order.sort()
    service_classes = [
        app.config['SERVICE_CLASSES'][k] for k in service_class_order
    ]

    if months is None:
        # We want the current report
        try:
            scr = ServiceClassSnapshot.objects.get(group=group, )
        except ServiceClassSnapshot.DoesNotExist:
            scr = ServiceClassSnapshot.calculate(group=group, )
        time_range = 'current'
        start_date = make_start_date(date=datetime.datetime.now())
        end_date = make_end_date(date=datetime.datetime.now())
    else:
        start = now()
        months_ranges = month_ranges(start, months)
        start_date = months_ranges[0][0]
        end_date = months_ranges[-1][1]
        try:
            scr = ServiceClassRecord.objects.get(
                group=group,
                start_date=start_date,
                end_date=end_date,
            )
        except ServiceClassRecord.DoesNotExist:
            scr = ServiceClassRecord.calculate(
                group=group,
                start_date=start_date,
                end_date=end_date,
            )
        time_range = 'past %s months' % months

    context = {
        'title': "Service classes: %s" % time_range,
        'service_classes': service_classes,
        'data': scr.data,
        'start_date': start_date,
        'end_date': end_date,
        'updated_at': scr.updated_at,
        'version': VERSION,
    }

    return render_template('report-service-class.html', **context)
Ejemplo n.º 23
0
def report_throughput(group="all", months=3, start=None):
    start = start or datetime.datetime.today()
    months_ranges = month_ranges(start, months)
    defect_types = app.config.get("DEFECT_TYPES", None)
    with_defects = defect_types is not None

    month_counts = []
    for arange in months_ranges:
        start, end = arange
        filtered_cards = Kard.objects.filter(done_date__gte=start, done_date__lte=end)
        rg = ReportGroup(group, filtered_cards)
        cards = rg.queryset

        if with_defects:
            counts = {"card": 0, "defect": 0}
            for card in cards:
                if card.type.strip() in defect_types:
                    counts["defect"] += 1
                else:
                    counts["card"] += 1
            month_counts.append((start.strftime("%B"), counts))
        else:
            num = cards.count()
            month_counts.append((start.strftime("%B"), num))

    chart = {}
    chart["categories"] = [c[0] for c in month_counts]

    if with_defects:
        chart["series"] = [
            {"data": [c[1]["card"] for c in month_counts], "name": "Cards"},
            {"data": [c[1]["defect"] for c in month_counts], "name": "Defects"},
        ]
    else:
        chart["series"] = [{"data": [c[1] for c in month_counts], "name": "Cards"}]

    context = {
        "title": "How much have we done?",
        "updated_at": datetime.datetime.now(),
        "chart": chart,
        "month_counts": month_counts,
        "version": VERSION,
        "with_defects": with_defects,
    }

    return render_template("report-throughput.html", **context)
Ejemplo n.º 24
0
def report_flow(group="all", months=3):
    end = kardboard.util.now()
    months_ranges = month_ranges(end, months)

    start_day = make_start_date(date=months_ranges[0][0])
    end_day = make_end_date(date=end)

    records = DailyRecord.objects.filter(date__gte=start_day,
                                         date__lte=end_day,
                                         group=group)

    chart = {}
    chart['categories'] = [report.date.strftime("%m/%d") for report in records]
    series = [
        {
            'name': "Planning",
            'data': []
        },
        {
            'name': "Todo",
            'data': []
        },
        {
            'name': "Done",
            'data': []
        },
    ]
    for row in records:
        series[0]['data'].append(row.backlog)
        series[1]['data'].append(row.in_progress)
        series[2]['data'].append(row.done)
    chart['series'] = series

    start_date = records.order_by('date').first().date
    records.order_by('-date')
    context = {
        'title': "Cumulative Flow",
        'updated_at': datetime.datetime.now(),
        'chart': chart,
        'start_date': start_date,
        'flowdata': records,
        'version': VERSION,
    }
    return render_template('chart-flow.html', **context)
Ejemplo n.º 25
0
def report_service_class(group="all", months=3, start=None):
    start = start or datetime.datetime.today()
    months_ranges = month_ranges(start, months)
    rg = ReportGroup(group, Kard.objects)
    rg_cards = rg.queryset
    classes = rg_cards.distinct("service_class")
    classes.sort()

    datatable = {"headers": ("Month", "Class", "Throughput", "Cycle Time", "Lead Time"), "rows": []}

    months = []
    for arange in months_ranges:
        for cls in classes:
            row = []
            start, end = arange
            filtered_cards = Kard.objects.filter(done_date__gte=start, done_date__lte=end, _service_class=cls)
            rg = ReportGroup(group, filtered_cards)
            cards = rg.queryset

            if cards.count() > 0:
                month_name = start.strftime("%B")
                if month_name not in months:
                    row.append(month_name)
                    months.append(month_name)
                else:
                    row.append("")

                row.append(cls)
                row.append(cards.count())
                row.append("%d" % cards.average("_cycle_time"))
                row.append("%d" % cards.average("_lead_time"))
            if row:
                row = tuple(row)
                datatable["rows"].append(row)

    context = {
        "title": "By service class",
        "updated_at": datetime.datetime.now(),
        "datatable": datatable,
        "version": VERSION,
    }

    return render_template("report-classes.html", **context)
Ejemplo n.º 26
0
def done(group="all", months=3, start=None):
    start = start or datetime.datetime.today()
    months_ranges = month_ranges(start, months)

    start = months_ranges[0][0]
    end = months_ranges[-1][-1]

    rg = ReportGroup(group, Kard.objects.done())
    done = rg.queryset

    cards = done.filter(done_date__gte=start,
                        done_date__lte=end).order_by('-done_date')

    context = {
        'title': "Completed Cards",
        'cards': cards,
        'updated_at': datetime.datetime.now(),
        'version': VERSION,
    }

    return render_template('done.html', **context)
Ejemplo n.º 27
0
def done(group="all", months=3, start=None):
    start = start or datetime.datetime.today()
    months_ranges = month_ranges(start, months)

    start = months_ranges[0][0]
    end = months_ranges[-1][-1]

    rg = ReportGroup(group, Kard.objects.done())
    done = rg.queryset

    cards = done.filter(done_date__gte=start,
        done_date__lte=end).order_by('-done_date')

    context = {
        'title': "Completed Cards",
        'cards': cards,
        'updated_at': datetime.datetime.now(),
        'version': VERSION,
    }

    return render_template('done.html', **context)
Ejemplo n.º 28
0
def report_detailed_flow(group="all", months=3):
    end = kardboard.util.now()
    months_ranges = month_ranges(end, months)

    start_day = make_start_date(date=months_ranges[0][0])
    end_day = make_end_date(date=end)

    reports = FlowReport.objects.filter(date__gte=start_day, date__lte=end_day, group=group)
    if not reports:
        abort(404)

    chart = {}
    chart["categories"] = []

    series = []
    for state in States():
        seri = {"name": state, "data": []}
        series.append(seri)

    for report in reports:
        chart["categories"].append(report.date.strftime("%m/%d"))
        for seri in series:
            daily_seri_data = report.snapshot.get(seri["name"], {}).get("count", 0)
            seri["data"].append(daily_seri_data)
    chart["series"] = series

    start_date = reports.order_by("date").first().date
    reports.order_by("-date")
    context = {
        "title": "Detailed Cumulative Flow",
        "reports": reports,
        "months": months,
        "chart": chart,
        "start_date": start_date,
        "updated_at": reports[0].updated_at,
        "states": States(),
        "version": VERSION,
    }
    return render_template("report-detailed-flow.html", **context)
Ejemplo n.º 29
0
def blocked(group="all", months=3, start=None):
    start = start or datetime.datetime.today()
    months_ranges = month_ranges(start, months)

    start = months_ranges[0][0]
    end = months_ranges[-1][-1]

    rg = ReportGroup(group, Kard.objects())
    blocked_cards = rg.queryset

    blocked_cards = blocked_cards.filter(start_date__gte=start,
        start_date__lte=end, blocked_ever=True).order_by('-start_date')

    context = {
        'title': "Blocked",
        'cards': blocked_cards,
        'start': start,
        'end': end,
        'updated_at': datetime.datetime.now(),
        'version': VERSION,
    }

    return render_template('blocked.html', **context)
Ejemplo n.º 30
0
def blocked(group="all", months=3, start=None):
    start = start or datetime.datetime.today()
    months_ranges = month_ranges(start, months)

    start = months_ranges[0][0]
    end = months_ranges[-1][-1]

    rg = ReportGroup(group, Kard.objects())
    blocked_cards = rg.queryset

    blocked_cards = blocked_cards.filter(
        start_date__gte=start, start_date__lte=end,
        blocked_ever=True).order_by('-start_date')

    context = {
        'title': "Blocked",
        'cards': blocked_cards,
        'start': start,
        'end': end,
        'updated_at': datetime.datetime.now(),
        'version': VERSION,
    }

    return render_template('blocked.html', **context)
Ejemplo n.º 31
0
def report_flow(group="all", months=3):
    end = kardboard.util.now()
    months_ranges = month_ranges(end, months)

    start_day = make_start_date(date=months_ranges[0][0])
    end_day = make_end_date(date=end)

    records = DailyRecord.objects.filter(
        date__gte=start_day,
        date__lte=end_day,
        group=group)

    chart = {}
    chart['categories'] = [report.date.strftime("%m/%d") for report in records]
    series = [
        {'name': "Planning", 'data': []},
        {'name': "Todo", 'data': []},
        {'name': "Done", 'data': []},
    ]
    for row in records:
        series[0]['data'].append(row.backlog)
        series[1]['data'].append(row.in_progress)
        series[2]['data'].append(row.done)
    chart['series'] = series

    start_date = records.order_by('date').first().date
    records.order_by('-date')
    context = {
        'title': "Cumulative Flow",
        'updated_at': datetime.datetime.now(),
        'chart': chart,
        'start_date': start_date,
        'flowdata': records,
        'version': VERSION,
    }
    return render_template('chart-flow.html', **context)
Ejemplo n.º 32
0
def report_efficiency(group="all", months=3):
    state_mappings = app.config.get('EFFICIENCY_MAPPINGS', None)
    if state_mappings is None:
        abort(404)
    stats = teams_service.EfficiencyStats(mapping=state_mappings)

    end = kardboard.util.now()
    months_ranges = month_ranges(end, months)

    start_day = make_start_date(date=months_ranges[0][0])
    end_day = make_end_date(date=end)

    records = FlowReport.objects.filter(
        date__gte=start_day,
        date__lte=end_day,
        group=group
    )

    incremented_state_counts = []
    for r in records:
        a_record = {'date': r.date}
        a_record.update(r.state_counts)
        incremented_state_counts.append(a_record)

    for group_name in app.config.get('EFFICIENCY_INCREMENTS', ()):
        stats.make_incremental(incremented_state_counts, group_name)

    data = []
    for r in incremented_state_counts:
        efficiency_stats = stats.calculate(r)
        data.append(
            {'date': r['date'], 'stats': efficiency_stats}
        )

    chart = {}
    chart['categories'] = [report.date.strftime("%m/%d") for report in records]
    group_names = app.config.get('EFFICIENCY_MAPPINGS_ORDER', state_mappings.keys())
    series = []
    for group_name in group_names:
        seri_data = []
        for d in data:
            seri_data.append(d['stats'][group_name])
        seri = dict(name=group_name, data=seri_data)
        series.append(seri)
    chart['series'] = series

    table_data = []
    for row in data:
        table_row = {'Date': row['date']}
        for group_name in group_names:
            table_row[group_name] = row['stats'][group_name]
        table_data.append(table_row)

    start_date = records.order_by('date').first().date
    context = {
        'title': "Efficiency",
        'start_date': start_date,
        'chart': chart,
        'table_data': table_data,
        'data_keys': ['Date', ] + list(group_names),
        'updated_at': records.order_by('date')[len(records) - 1].date,
        'version': VERSION,
    }
    return render_template('chart-efficiency.html', **context)
Ejemplo n.º 33
0
def report_efficiency(group="all", months=3):
    state_mappings = app.config.get('EFFICIENCY_MAPPINGS', None)
    if state_mappings is None:
        abort(404)
    stats = teams_service.EfficiencyStats(mapping=state_mappings)

    end = kardboard.util.now()
    months_ranges = month_ranges(end, months)

    start_day = make_start_date(date=months_ranges[0][0])
    end_day = make_end_date(date=end)

    records = FlowReport.objects.filter(date__gte=start_day,
                                        date__lte=end_day,
                                        group=group)

    incremented_state_counts = []
    for r in records:
        a_record = {'date': r.date}
        a_record.update(r.state_counts)
        incremented_state_counts.append(a_record)

    for group_name in app.config.get('EFFICIENCY_INCREMENTS', ()):
        stats.make_incremental(incremented_state_counts, group_name)

    data = []
    for r in incremented_state_counts:
        efficiency_stats = stats.calculate(r)
        data.append({'date': r['date'], 'stats': efficiency_stats})

    chart = {}
    chart['categories'] = [report.date.strftime("%m/%d") for report in records]
    group_names = app.config.get('EFFICIENCY_MAPPINGS_ORDER',
                                 state_mappings.keys())
    series = []
    for group_name in group_names:
        seri_data = []
        for d in data:
            seri_data.append(d['stats'][group_name])
        seri = dict(name=group_name, data=seri_data)
        series.append(seri)
    chart['series'] = series

    table_data = []
    for row in data:
        table_row = {'Date': row['date']}
        for group_name in group_names:
            table_row[group_name] = row['stats'][group_name]
        table_data.append(table_row)

    start_date = records.order_by('date').first().date
    context = {
        'title': "Efficiency",
        'start_date': start_date,
        'chart': chart,
        'table_data': table_data,
        'data_keys': [
            'Date',
        ] + list(group_names),
        'updated_at': records.order_by('date')[len(records) - 1].date,
        'version': VERSION,
    }
    return render_template('chart-efficiency.html', **context)