Example #1
0
 def save(self, *args, **kwargs):
     if self.id is None:
         self.created_at = now()
     if self.entered and self.exited:
         self._duration = self.duration
     self.updated_at = now()
     super(StateLog, self).save(*args, **kwargs)
Example #2
0
 def save(self, *args, **kwargs):
     if self.id is None:
         self.created_at = now()
     if self.entered and self.exited:
         self._duration = self.duration
     self.updated_at = now()
     super(StateLog, self).save(*args, **kwargs)
    def _fixtures_for_test_current_struct(self):
        from kardboard.util import now
        from kardboard.util import relativedelta

        # Speedy cards
        for i in xrange(0, 5):
            k = self.make_card(
                _service_class="Speedy",
                backlog_date=now() - relativedelta(days=3),
                start_date=now() - relativedelta(days=1),
            )
            k.save()

        # Normal cards
        for i in xrange(0, 10):
            k = self.make_card(_service_class="Normal", backlog_date=now(), start_date=now() + relativedelta(days=10))
            k.save()

        # No class cards
        for i in xrange(0, 5):
            k = self.make_card(backlog_date=now(), start_date=now() + relativedelta(days=10))
            k.save()

        for i in xrange(0, 3):
            k = self.make_card(
                _service_class="Normal",
                backlog_date=now(),
                start_date=now() + relativedelta(days=8),
                done_date=now() + relativedelta(days=15),
            )
            k.save()
Example #4
0
 def duration(self):
     if self.unblocked_at is not None:
         unblocked_at = self.unblocked_at
     else:
         unblocked_at = now()
     delta = unblocked_at - self.blocked_at
     return delta_in_hours(delta)
Example #5
0
    def kard_pre_save(cls, sender, document, **kwargs):
        observed_card = document

        if observed_card.state_changing is False:
            # No need to worry about logging it, nothing's changing!
            return None

        try:
            observed_card.old_state
        except AttributeError:
            print observed_card
            print type(observed_card)
            print dir(observed_card)
            print 'old_state' in dir(observed_card)
            raise

        # If you're here it's because the observed_card's state is changing
        if observed_card.old_state is not None:
            try:
                slo = cls.objects.get(card=observed_card, state=observed_card.old_state)
                slo.exited = now()
                slo.save()  #  Close the old state log
            except cls.DoesNotExist:
                #  For some reason we didn't record the old state, this should only happen when first rolled out
                pass
Example #6
0
    def save(self, *args, **kwargs):
        self.backlog_date = self._convert_dates_to_datetimes(self.backlog_date)
        self.start_date = self._convert_dates_to_datetimes(self.start_date)
        self.done_date = self._convert_dates_to_datetimes(self.done_date)

        if not self.created_at:
            self.created_at = now()

        # Auto move to done
        if self.done_date:
            states = States()
            self.in_progress = False
            self.state = states.done

        # Auto fill in final cycle and lead time
        if self.done_date and self.start_date:
            self._cycle_time = self.cycle_time
            self._lead_time = self.lead_time

        # If a card is blocked, inspect it's previous state and
        # if we're moving states unblock it
        if self.blocked:
            try:
                k = Kard.objects.only("state").get(key=self.key)
                if k.state != self.state:
                    # Card is blocked and it's state is about to change
                    self.unblock()
            except Kard.DoesNotExist:
                # Card isn't saved can't find its previous state
                pass

        self._service_class = self.service_class
        self.key = self.key.upper()

        super(Kard, self).save(*args, **kwargs)
Example #7
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)
Example #8
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)
Example #9
0
    def cards(self):
        if self._cards:
            return self._cards

        in_progress_q = Q(state__in=self.states.in_progress, team__in=self.teams)
        ordered_backlog_q = Q(state=self.states.backlog, team__in=self.teams, priority__exists=True)
        unordered_backlog_q = Q(state=self.states.backlog, team__in=self.teams, priority__exists=False)
        total_backlog_q = Q(state=self.states.backlog, team__in=self.teams)
        done_q = Q(done_date__gte=now() - relativedelta(days=self.done_days), team__in=self.teams)
        if self.backlog_limit:
            ordered_backlog_cards = Kard.objects.filter(ordered_backlog_q).order_by("priority", "created_at")
            ordered_backlog_cards = ordered_backlog_cards.limit(self.backlog_limit).exclude("_ticket_system_data")
            unordered_backlog_cards = []
            if len(ordered_backlog_cards) < self.backlog_limit:
                unordered_backlog_cards = Kard.objects.filter(unordered_backlog_q).order_by("created_at")
                unordered_backlog_cards = unordered_backlog_cards.limit(self.backlog_limit).exclude(
                    "_ticket_system_data"
                )

            backlog_cards = list(ordered_backlog_cards) + list(unordered_backlog_cards)
            backlog_cards = backlog_cards[: self.backlog_limit]

            cards_query = in_progress_q | done_q
            cards = list(Kard.objects.filter(cards_query).exclude("_ticket_system_data"))
            self._cards = backlog_cards + cards
        else:
            cards_query = total_backlog_q | in_progress_q | done_q
            self._cards = list(Kard.objects.filter(cards_query).exclude("_ticket_system_data"))

        return self._cards
Example #10
0
 def duration(self):
     if self.unblocked_at is not None:
         unblocked_at = self.unblocked_at
     else:
         unblocked_at = now()
     delta = unblocked_at - self.blocked_at
     return delta_in_hours(delta)
Example #11
0
    def kard_pre_save(cls, sender, document, **kwargs):
        observed_card = document

        if observed_card.state_changing is False:
            # No need to worry about logging it, nothing's changing!
            return None

        try:
            observed_card.old_state
        except AttributeError:
            raise

        # If you're here it's because the observed_card's state is changing
        if observed_card.old_state is not None:
            try:
                slos = cls.objects.filter(
                    card=observed_card,
                    state=observed_card.old_state,
                    service_class=observed_card.service_class.get('name'),
                    exited__exists=False)
                for s in slos:
                    s.exited = now()
                    s.save()  # Close the old state log
            except cls.DoesNotExist:
                #  For some reason we didn't record the old state, this should only happen when first rolled out
                pass
Example #12
0
    def for_team_board(self, team, backlog_limit, done_days):
        states = States()

        in_progress_q = Q(
            state__in=states.in_progress,
            team=team)
        done_q = Q(done_date__gte=now() - relativedelta(days=done_days),
            team=team)

        cards_query = in_progress_q | done_q
        wip_and_done = list(
            self.filter(cards_query).exclude('_ticket_system_data')
        )

        ordered_backlog_q = Q(
            state=states.backlog,
            team=team,
            priority__exists=True)
        unordered_backlog_q = Q(
            state=states.backlog,
            team=team,
            priority__exists=False)

        ordered_backlog_cards = self.filter(ordered_backlog_q).order_by('priority', 'created_at')
        ordered_backlog_cards = ordered_backlog_cards.limit(backlog_limit).exclude('_ticket_system_data')
        unordered_backlog_cards = []
        if len(ordered_backlog_cards) < backlog_limit:
            ordered_backlog_cards = list(ordered_backlog_cards)
            unordered_backlog_cards = Kard.objects.filter(unordered_backlog_q).order_by('created_at')
            unordered_backlog_cards = unordered_backlog_cards.limit(backlog_limit).exclude('_ticket_system_data')

        backlog = list(ordered_backlog_cards) + list(unordered_backlog_cards)
        backlog = backlog[:backlog_limit]

        return backlog + wip_and_done
Example #13
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)
Example #14
0
    def kard_pre_save(cls, sender, document, **kwargs):
        observed_card = document

        if observed_card.state_changing is False:
            # No need to worry about logging it, nothing's changing!
            return None

        try:
            observed_card.old_state
        except AttributeError:
            raise

        # If you're here it's because the observed_card's state is changing
        if observed_card.old_state is not None:
            try:
                slos = cls.objects.filter(
                        card=observed_card,
                        state=observed_card.old_state,
                        service_class=observed_card.service_class.get('name'),
                        exited__exists=False)
                for s in slos:
                    s.exited = now()
                    s.save() # Close the old state log
            except cls.DoesNotExist:
                #  For some reason we didn't record the old state, this should only happen when first rolled out
                pass
Example #15
0
    def for_team_board(self, team, backlog_limit, done_days):
        states = States()

        in_progress_q = Q(state__in=states.in_progress, team=team)
        done_q = Q(done_date__gte=now() - relativedelta(days=done_days),
                   team=team)

        cards_query = in_progress_q | done_q
        wip_and_done = list(
            self.filter(cards_query).exclude('_ticket_system_data'))

        ordered_backlog_q = Q(state=states.backlog,
                              team=team,
                              priority__exists=True)
        unordered_backlog_q = Q(state=states.backlog,
                                team=team,
                                priority__exists=False)

        ordered_backlog_cards = self.filter(ordered_backlog_q).order_by(
            'priority', 'created_at')
        ordered_backlog_cards = ordered_backlog_cards.limit(
            backlog_limit).exclude('_ticket_system_data')
        unordered_backlog_cards = []
        if len(ordered_backlog_cards) < backlog_limit:
            ordered_backlog_cards = list(ordered_backlog_cards)
            unordered_backlog_cards = Kard.objects.filter(
                unordered_backlog_q).order_by('created_at')
            unordered_backlog_cards = unordered_backlog_cards.limit(
                backlog_limit).exclude('_ticket_system_data')

        backlog = list(ordered_backlog_cards) + list(unordered_backlog_cards)
        backlog = backlog[:backlog_limit]

        return backlog + wip_and_done
Example #16
0
    def kard_pre_save(cls, sender, document, **kwargs):
        observed_card = document

        if observed_card.state_changing is False:
            # No need to worry about logging it, nothing's changing!
            return None

        try:
            observed_card.old_state
        except AttributeError:
            print observed_card
            print type(observed_card)
            print dir(observed_card)
            print 'old_state' in dir(observed_card)
            raise

        # If you're here it's because the observed_card's state is changing
        if observed_card.old_state is not None:
            try:
                slo = cls.objects.get(card=observed_card,
                                      state=observed_card.old_state)
                slo.exited = now()
                slo.save()  #  Close the old state log
            except cls.DoesNotExist:
                #  For some reason we didn't record the old state, this should only happen when first rolled out
                pass
Example #17
0
    def kard_post_save(cls, sender, document, **kwargs):
        observed_card = document

        # This could be a freshly created card, so create a log for it
        sl, created = cls.objects.get_or_create(auto_save=False, card=observed_card, state=observed_card.state)
        if created:
            sl.entered = now()
            sl.save()
Example #18
0
def card_block(key):
    try:
        card = Kard.objects.get(key=key)
        action = 'block'
        if card.blocked:
            action = 'unblock'
    except Kard.DoesNotExist:
        abort(404)

    if action == 'block':
        f = CardBlockForm(request.form, blocked_at=now())
    if action == 'unblock':
        f = CardUnblockForm(request.form, unblocked_at=now())

    if 'cancel' in request.form.keys():
        return True  # redirect
    elif request.method == "POST" and f.validate():
        if action == 'block':
            blocked_at = datetime.datetime.combine(f.blocked_at.data,
                                                   datetime.time())
            blocked_at = make_start_date(date=blocked_at)
            result = card.block(f.reason.data, blocked_at)
            if result:
                card.save()
                flash("%s blocked" % card.key)
                return True  # redirect
        if action == 'unblock':
            unblocked_at = datetime.datetime.combine(f.unblocked_at.data,
                                                     datetime.time())
            unblocked_at = make_end_date(date=unblocked_at)
            result = card.unblock(unblocked_at)
            if result:
                card.save()
                flash("%s unblocked" % card.key)
                return True  # redurect

    context = {
        'title': "%s a card" % (action.capitalize(), ),
        'action': action,
        'card': card,
        'form': f,
        'updated_at': datetime.datetime.now(),
        'version': VERSION,
    }

    return render_template('card-block.html', **context)
Example #19
0
    def _set_dates(self):
        self.backlog_date = self._convert_dates_to_datetimes(self.backlog_date)
        self.start_date = self._convert_dates_to_datetimes(self.start_date)
        self.done_date = self._convert_dates_to_datetimes(self.done_date)
        self.due_date = self._convert_dates_to_datetimes(self.due_date)

        if not self.created_at:
            self.created_at = now()
Example #20
0
def card_block(key):
    try:
        card = Kard.objects.get(key=key)
        action = 'block'
        if card.blocked:
            action = 'unblock'
    except Kard.DoesNotExist:
        abort(404)

    if action == 'block':
        f = CardBlockForm(request.form, blocked_at=now())
    if action == 'unblock':
        f = CardUnblockForm(request.form, unblocked_at=now())

    if 'cancel' in request.form.keys():
        return True  # redirect
    elif request.method == "POST" and f.validate():
        if action == 'block':
            blocked_at = datetime.datetime.combine(
                f.blocked_at.data, datetime.time())
            blocked_at = make_start_date(date=blocked_at)
            result = card.block(f.reason.data, blocked_at)
            if result:
                card.save()
                flash("%s blocked" % card.key)
                return True  # redirect
        if action == 'unblock':
            unblocked_at = datetime.datetime.combine(
                f.unblocked_at.data, datetime.time())
            unblocked_at = make_end_date(date=unblocked_at)
            result = card.unblock(unblocked_at)
            if result:
                card.save()
                flash("%s unblocked" % card.key)
                return True  # redurect

    context = {
        'title': "%s a card" % (action.capitalize(), ),
        'action': action,
        'card': card,
        'form': f,
        'updated_at': datetime.datetime.now(),
        'version': VERSION,
    }

    return render_template('card-block.html', **context)
Example #21
0
    def _set_dates(self):
        self.backlog_date = self._convert_dates_to_datetimes(self.backlog_date)
        self.start_date = self._convert_dates_to_datetimes(self.start_date)
        self.done_date = self._convert_dates_to_datetimes(self.done_date)
        self.due_date = self._convert_dates_to_datetimes(self.due_date)

        if not self.created_at:
            self.created_at = now()
Example #22
0
def card_block(key):
    try:
        card = Kard.objects.get(key=key)
        action = "block"
        if card.blocked:
            action = "unblock"
    except Kard.DoesNotExist:
        abort(404)

    if action == "block":
        f = CardBlockForm(request.form, blocked_at=now())
    if action == "unblock":
        f = CardUnblockForm(request.form, unblocked_at=now())

    if "cancel" in request.form.keys():
        return True  # redirect
    elif request.method == "POST" and f.validate():
        if action == "block":
            blocked_at = datetime.datetime.combine(f.blocked_at.data, datetime.time())
            blocked_at = make_start_date(date=blocked_at)
            result = card.block(f.reason.data, blocked_at)
            if result:
                card.save()
                flash("%s blocked" % card.key)
                return True  # redirect
        if action == "unblock":
            unblocked_at = datetime.datetime.combine(f.unblocked_at.data, datetime.time())
            unblocked_at = make_end_date(date=unblocked_at)
            result = card.unblock(unblocked_at)
            if result:
                card.save()
                flash("%s unblocked" % card.key)
                return True  # redurect

    context = {
        "title": "%s a card" % (action.capitalize(),),
        "action": action,
        "card": card,
        "form": f,
        "updated_at": datetime.datetime.now(),
        "version": VERSION,
    }

    return render_template("card-block.html", **context)
Example #23
0
    def duration(self):
        if self._duration is not None:
            return self._duration

        if self.exited is not None:
            exited = self.exited
        else:
            exited = now()
        delta = exited - self.entered
        return delta_in_hours(delta)
Example #24
0
    def kard_post_save(cls, sender, document, **kwargs):
        observed_card = document

        # This could be a freshly created card, so create a log for it
        sl, created = cls.objects.get_or_create(auto_save=False,
                                                card=observed_card,
                                                state=observed_card.state)
        if created:
            sl.entered = now()
            sl.save()
Example #25
0
    def duration(self):
        if self._duration is not None:
            return self._duration

        if self.exited is not None:
            exited = self.exited
        else:
            exited = now()
        delta = exited - self.entered
        return delta_in_hours(delta)
Example #26
0
def _hit_due_date(card):
    if card.due_date is None:
        return ''

    due_date = make_end_date(date=card.due_date)
    if card.done_date is None:
        done_date = make_end_date(date=now())
    else:
        done_date = make_end_date(date=card.done_date)
    return done_date <= due_date
Example #27
0
def _hit_due_date(card):
    if card.due_date is None:
        return ''

    due_date = make_end_date(date=card.due_date)
    if card.done_date is None:
        done_date = make_end_date(date=now())
    else:
        done_date = make_end_date(date=card.done_date)
    return done_date <= due_date
Example #28
0
 def make_card(self, **kwargs):
     from kardboard.util import now
     key = self._make_unique_key()
     fields = {
         'key': "CMSAD-%s" % key,
         'title': "Theres always money in the banana stand",
         'backlog_date': now()
     }
     fields.update(**kwargs)
     k = self._get_card_class()(**fields)
     return k
Example #29
0
    def current_lead_time(self, today=None):
        """
        Caclucation of the number of days between the backlogging of a card
        and a comparison point (defaults to today).
        """
        if not self.backlog_date:
            return None

        if not today:
            today = now()
        return business_days_between(self.backlog_date, today)
Example #30
0
 def make_card(self, **kwargs):
     from kardboard.util import now
     key = self._make_unique_key()
     fields = {
         'key': "CMSAD-%s" % key,
         'title': "Theres always money in the banana stand",
         'backlog_date': now()
     }
     fields.update(**kwargs)
     k = self._get_card_class()(**fields)
     return k
Example #31
0
    def cards(self):
        if self._cards:
            return self._cards

        in_progress_q = Q(done_date=None, start_date__exists=True, team__in=self.teams)
        backlog_q = Q(backlog_date__exists=True, start_date=None, team__in=self.teams)
        done_q = Q(done_date__gte=now() - relativedelta(days=self.done_days), team__in=self.teams)
        cards_query = backlog_q | in_progress_q | done_q

        self._cards = list(Kard.objects.filter(cards_query))
        return self._cards
Example #32
0
    def current_cycle_time(self, today=None):
        """
        Caclucation of the number of days between the start of a card
        and a comparison point (defaults to today).
        Returns None if the card hasn't started yet.
        """
        if not self.start_date:
            return None

        if not today:
            today = now()
        return business_days_between(self.start_date, today)
Example #33
0
    def current_lead_time(self, today=None):
        """
        Caclucation of the number of days between the backlogging of a card
        and a comparison point (defaults to today).
        """
        if not self.backlog_date:
            return None

        if today is None and self.done_date is None:
            today = now()
        elif today is None and self.done_date is not None:
            today = self.done_date
        return days_between(self.backlog_date, today)
Example #34
0
    def current_lead_time(self, today=None):
        """
        Caclucation of the number of days between the backlogging of a card
        and a comparison point (defaults to today).
        """
        if not self.backlog_date:
            return None

        if today is None and self.done_date is None:
            today = now()
        elif today is None and self.done_date is not None:
            today = self.done_date
        return days_between(self.backlog_date, today)
Example #35
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)
Example #36
0
    def cards(self):
        if self._cards:
            return self._cards

        in_progress_q = Q(state__in=self.states.in_progress,
                          team__in=self.teams)
        backlog_q = Q(state__in=self.states.pre_start, team__in=self.teams)
        done_q = Q(done_date__gte=now() - relativedelta(days=self.done_days),
                   team__in=self.teams)
        cards_query = backlog_q | in_progress_q | done_q

        self._cards = list(
            Kard.objects.filter(cards_query).exclude('_ticket_system_data'))
        return self._cards
Example #37
0
    def current_cycle_time(self, today=None):
        """
        Caclucation of the number of days between the start of a card
        and a comparison point (defaults to today).
        Returns None if the card hasn't started yet.
        """
        if not self.start_date:
            return None

        if today is None and self.done_date is None:
            today = now()
        elif today is None and self.done_date is not None:
            today = self.done_date
        return days_between(self.start_date, today)
Example #38
0
    def _date(self, dtype, date=None, days=0):
        from kardboard.util import make_end_date, make_start_date
        from kardboard.util import now

        if not date:
            date = now()

        if dtype == 'start':
            date = make_start_date(date=date)
        elif dtype == 'end':
            date = make_end_date(date=date)

        date = date + relativedelta(days=days)
        return date
Example #39
0
    def current_cycle_time(self, today=None):
        """
        Caclucation of the number of days between the start of a card
        and a comparison point (defaults to today).
        Returns None if the card hasn't started yet.
        """
        if not self.start_date:
            return None

        if today is None and self.done_date is None:
            today = now()
        elif today is None and self.done_date is not None:
            today = self.done_date
        return days_between(self.start_date, today)
Example #40
0
    def _date(self, dtype, date=None, days=0):
        from kardboard.util import make_end_date, make_start_date
        from kardboard.util import now

        if not date:
            date = now()

        if dtype == "start":
            date = make_start_date(date=date)
        elif dtype == "end":
            date = make_end_date(date=date)

        date = date + relativedelta(days=days)
        return date
Example #41
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)
Example #42
0
    def kard_post_save(cls, sender, document, **kwargs):
        observed_card = document

        try:
            # This could be a freshly created card, so create a log for it
            sl, created = cls.objects.get_or_create(auto_save=False,
                card=observed_card,
                state=observed_card.state)
            if created:
                sl.entered = now()
        except cls.MultipleObjectsReturned:
            sl = cls.objects.filter(
                card=observed_card,
                state=observed_card.state)[0]

        sl.service_class=observed_card.service_class.get('name')
        sl.save()
Example #43
0
    def cards(self):
        if self._cards:
            return self._cards

        in_progress_q = Q(
            state__in=self.states.in_progress,
            team__in=self.teams)
        backlog_q = Q(
            state__in=self.states.pre_start,
            team__in=self.teams)
        done_q = Q(done_date__gte=now() - relativedelta(days=self.done_days),
            team__in=self.teams)
        cards_query = backlog_q | in_progress_q | done_q

        self._cards = list(
            Kard.objects.filter(cards_query).exclude('_ticket_system_data')
        )
        return self._cards
    def _fixtures_for_test_current_struct(self):
        from kardboard.util import now
        from kardboard.util import relativedelta

        # Speedy cards
        for i in xrange(0, 5):
            k = self.make_card(
                _service_class='Speedy',
                backlog_date=now() - relativedelta(days=3),
                start_date=now() - relativedelta(days=1),
            )
            k.save()

        # Normal cards
        for i in xrange(0, 10):
            k = self.make_card(
                _service_class='Normal',
                backlog_date=now(),
                start_date=now() + relativedelta(days=10),
            )
            k.save()

        # No class cards
        for i in xrange(0, 5):
            k = self.make_card(
                backlog_date=now(),
                start_date=now() + relativedelta(days=10),
            )
            k.save()

        for i in xrange(0, 3):
            k = self.make_card(_service_class='Normal',
                               backlog_date=now(),
                               start_date=now() + relativedelta(days=8),
                               done_date=now() + relativedelta(days=15))
            k.save()
Example #45
0
    def cards(self):
        if self._cards:
            return self._cards

        in_progress_q = Q(state__in=self.states.in_progress,
                          team__in=self.teams)
        ordered_backlog_q = Q(state=self.states.backlog,
                              team__in=self.teams,
                              priority__exists=True)
        unordered_backlog_q = Q(state=self.states.backlog,
                                team__in=self.teams,
                                priority__exists=False)
        total_backlog_q = Q(state=self.states.backlog, team__in=self.teams)
        done_q = Q(done_date__gte=now() - relativedelta(days=self.done_days),
                   team__in=self.teams)
        if self.backlog_limit:
            ordered_backlog_cards = Kard.objects.filter(
                ordered_backlog_q).order_by('priority', 'created_at')
            ordered_backlog_cards = ordered_backlog_cards.limit(
                self.backlog_limit).exclude('_ticket_system_data')
            unordered_backlog_cards = []
            if len(ordered_backlog_cards) < self.backlog_limit:
                unordered_backlog_cards = Kard.objects.filter(
                    unordered_backlog_q).order_by('created_at')
                unordered_backlog_cards = unordered_backlog_cards.limit(
                    self.backlog_limit).exclude('_ticket_system_data')

            backlog_cards = list(ordered_backlog_cards) + list(
                unordered_backlog_cards)
            backlog_cards = backlog_cards[:self.backlog_limit]

            cards_query = in_progress_q | done_q
            cards = list(
                Kard.objects.filter(cards_query).exclude(
                    '_ticket_system_data'))
            self._cards = backlog_cards + cards
        else:
            cards_query = total_backlog_q | in_progress_q | done_q
            self._cards = list(
                Kard.objects.filter(cards_query).exclude(
                    '_ticket_system_data'))

        return self._cards
Example #46
0
    def kard_post_save(cls, sender, document, **kwargs):
        observed_card = document

        # Is there a currently open state log
        logs = cls.objects.filter(
            card=observed_card,
            state=observed_card.state,
            exited__exists=False,
        ).order_by('-entered')
        if len(logs) == 0:
            sl = cls(
                card=observed_card,
                state=observed_card.state,
                entered=now()
            )
        else:
            sl = logs[0]

        sl.service_class = observed_card.service_class.get('name')
        sl.save()
Example #47
0
    def cards(self):
        if self._cards:
            return self._cards

        in_progress_q = Q(
            state__in=self.states.in_progress,
            team__in=self.teams)
        backlog_q = Q(
            state=self.states.backlog,
            team__in=self.teams)
        done_q = Q(done_date__gte=now() - relativedelta(days=self.done_days),
            team__in=self.teams)
        if self.backlog_limit:
            backlog_cards = Kard.objects.filter(backlog_q).exclude('_ticket_system_data').limit(self.backlog_limit)
            cards_query = in_progress_q | done_q
            cards = list(Kard.objects.filter(cards_query).exclude('_ticket_system_data'))
            self._cards = list(backlog_cards) + cards
        else:
            cards_query = backlog_q | in_progress_q | done_q
            self._cards = list(Kard.objects.filter(cards_query).exclude('_ticket_system_data'))

        return self._cards
Example #48
0
    def save(self, *args, **kwargs):
        self.backlog_date = self._convert_dates_to_datetimes(self.backlog_date)
        self.start_date = self._convert_dates_to_datetimes(self.start_date)
        self.done_date = self._convert_dates_to_datetimes(self.done_date)

        if not self.created_at:
            self.created_at = now()

        # Auto move to done
        if self.done_date:
            states = States()
            self.in_progress = False
            self.state = states.done

        # Auto fill in final cycle and lead time
        if self.done_date and self.start_date:
            self._cycle_time = self.cycle_time
            self._lead_time = self.lead_time

        if self.blocked:
            # Do we have a state change?
            try:
                k = Kard.objects.only('state').get(key=self.key, )
                if k.state != self.state:
                    # Houston we have a state change
                    # Card is blocked and it's state is about to change
                    self.unblock()
            except Kard.DoesNotExist:
                #Card isn't saved can't find its previous state
                pass

        self._service_class = self.service_class
        self._version = self.ticket_system.get_version()
        self.key = self.key.upper()

        super(Kard, self).save(*args, **kwargs)
 def save(self, *args, **kwargs):
     self.updated_at = now()
     super(ServiceClassRecord, self).save(*args, **kwargs)
 def save(self, *args, **kwargs):
     self.updated_at = now()
     super(ServiceClassSnapshot, self).save(*args, **kwargs)
 def save(self, *args, **kwargs):
     self.updated_at = now()
     super(ServiceClassSnapshot, self).save(*args, **kwargs)