def __init__(self, context, request, year=None, month=None, memberid=None):
        super(BookingsDetailedView, self).__init__(context, request)
        self.year = year or self.request.form.get('year', DateTime().year())
        self.month = month or self.request.form.get('month',
                                                    DateTime().month())
        if isinstance(self.year, basestring):
            self.year = int(self.year)
        if isinstance(self.month, basestring):
            self.month = int(self.month)
        self.previous = self.request.form.get('previous')
        self.next = self.request.form.get('next')
        self.memberid = memberid or self.request.form.get('memberid')
        if self.memberid is None:
            membership = getToolByName(context, 'portal_membership')
            member = membership.getAuthenticatedMember()
            self.memberid = member.id

        if self.previous:
            self.year, self.month = getPrevYearMonth(self.year, self.month)
        elif self.next:
            self.year, self.month = getNextYearMonth(self.year, self.month)

        self.startDate = DateTime(self.year, self.month, 1)
        self.endDate = getEndOfMonth(self.year, self.month)
        # Where do we want to search?
        self.searchpath = '/'.join(context.getPhysicalPath())
        self.bookinglist = []
        self.raw_total = 0
        self.perc_billable = 0.0
        self.update()
    def __init__(self, context, request, year=None, month=None, memberid=None):
        super(BookingsDetailedView, self).__init__(context, request)
        self.year = year or self.request.form.get('year', DateTime().year())
        self.month = month or self.request.form.get('month',
                                                    DateTime().month())
        if isinstance(self.year, str):
            self.year = int(self.year)
        if isinstance(self.month, str):
            self.month = int(self.month)
        self.previous = self.request.form.get('previous')
        self.next = self.request.form.get('next')
        self.memberid = memberid or self.request.form.get('memberid')
        if self.memberid is None:
            membership = getToolByName(context, 'portal_membership')
            member = membership.getAuthenticatedMember()
            self.memberid = member.id

        if self.previous:
            self.year, self.month = getPrevYearMonth(self.year, self.month)
        elif self.__next__:
            self.year, self.month = getNextYearMonth(self.year, self.month)

        self.startDate = DateTime(self.year, self.month, 1)
        self.endDate = getEndOfMonth(self.year, self.month)
        # Where do we want to search?
        self.searchpath = '/'.join(context.getPhysicalPath())
        self.bookinglist = []
        self.raw_total = 0
        self.perc_billable = 0.0
        self.update()
    def items(self):
        ptool = self.tools.properties()
        hours_per_day = ptool.xm_properties.getProperty('hours_per_day')
        data = []
        employees = self.get_employees()
        for userid in employees:
            empldict = dict(id=userid)
            memberinfo = self.tools.membership().getMemberInfo(userid)
            if memberinfo and memberinfo is not None:
                empldict['name'] = memberinfo['fullname'] or userid
                # For each month create a list employees in a dict with
                # percentages and a url to the month view.
                results = []
                for m in self.months:
                    begin = DateTime(m.year, m.month, 1)
                    end = getEndOfMonth(m.year, m.month)
                    bookingbrains = self.tools.catalog().searchResults(
                        portal_type='Booking',
                        getBookingDate={"query": [begin, end],
                                        "range": "minmax",
                                        "sort_on": "getBookingDate"},
                        Creator=userid,
                        path=self.searchpath)
                    # Hm, it does not look like sort_on is working so
                    # we do it ourselves.
                    bookingbrains = sorted(bookingbrains, key=booking_date)
                    grouped = itertools.groupby(bookingbrains, booking_date)
                    billable = []
                    for day, bookings in grouped:
                        day_billable = 0.0
                        day_total = 0.0
                        for bb in bookings:
                            day_total += bb.actual_time
                            if bb.getBillable:
                                day_billable += bb.actual_time
                        if day_total > 0:
                            # XXX If the employee worked 1 hour or
                            # less we might want to assume it is just
                            # an hour on Saturday or something and
                            # ignore this day to avoid unnecessarily
                            # influencing the billable percentage
                            # negatively.
                            billable.append(day_billable)
                    days_worked = len(billable)
                    if days_worked > 0:
                        total = sum(billable)
                        perc = 100 * (total / hours_per_day) / days_worked
                    else:
                        perc = 0.0
                    url = "%s/booking_month?memberid=%s&month=%r&year=%r" % (
                        self.site_url, userid, m.month, m.year)
                    perc_dict = dict(percentage=fmt_perc_billable(perc),
                                     url=url)
                    results.append(perc_dict)
                results.reverse()
                empldict['monthly_percentages'] = results
            data.append(empldict)

        return data
    def update(self):
        context = aq_inner(self.context)
        ptool = self.tools().properties()
        hours_per_day = ptool.xm_properties.getProperty('hours_per_day')
        request = self.request
        weeklist = []
        # Start at first day of the week.  Note: with the
        # DateTime.week() method Monday is considered the first day,
        # even though DateTime.dow() says Sunday is day zero.  To make
        # things worse, if say Sunday is 1 October, we want to start
        # with the week of Monday 25 September.

        # Go to the beginning of the week that has the first day of
        # this month.  How many days do we have to subtract for that?
        offset = self.startDate.dow() - 1
        if offset < 0:
            # Only happens for Sunday
            offset += 7

        if offset == 0:
            date = self.startDate
            year, month = self.year, self.month
        else:
            year, month = getPrevYearMonth(
                self.year, self.month)
            last_day = getEndOfMonth(year, month).day()
            date = DateTime(year, month, last_day - offset + 1)
        daynumber = date.day()
        # Assemble info for at most one month:
        ploneview = context.restrictedTraverse('@@plone')
        month_billable = 0.0
        month_worked_days = 0

        # When comparing dates, make sure December of previous year is
        # less than January of this year.
        while date.month() + 12 * date.year() <= self.month + 12 * self.year:
            weekinfo = dict(
                week_number=date.week(),
                week_start=ploneview.toLocalizedTime(date),
            )
            # Start the week cleanly
            day_of_week = 0
            daylist = []
            week_total = 0.0
            week_strict_total = 0.0
            days_bookings = DayBookingOverview(
                context, request, memberid=self.memberid)
            week_billable = 0.0
            week_worked_days = 0
            # Strict billable means: only count days of this week that
            # are really in this month.
            week_strict_billable = 0.0
            week_strict_worked_days = 0
            while day_of_week < 7:
                day_total = days_bookings.raw_total(date=date)
                day_billable = days_bookings.raw_billable(date=date)
                ui_class = 'greyed'
                if day_total > 0:
                    # Update week stats
                    week_total += day_total
                    if day_total != 0:
                        # Only add the billable hours to the week when
                        # some work (billable or not) has been done
                        # today.
                        week_billable += day_billable
                        week_worked_days += 1
                    if date.month() == self.startDate.month():
                        # Update strict stats
                        week_strict_total += day_total
                        week_strict_billable += day_billable
                        week_strict_worked_days += 1
                        # Update month stats
                        self.raw_total += day_total
                        if day_total != 0:
                            # Only add the billable hours to the month
                            # when some work (billable or not) has
                            # been done today.
                            month_billable += day_billable
                            month_worked_days += 1
                        ui_class = 'good'
                    else:
                        ui_class = 'greyed'
                    daylist.append(dict(total=formatTime(day_total),
                                        day_of_week=date.Day(),
                                        style=ui_class))
                else:
                    daylist.append(dict(total=None, day_of_week=date.Day(),
                                        style=ui_class))
                day_of_week += 1
                daynumber += 1
                try:
                    # We used to simply do date + 1, but that gave
                    # problems with Daylight Savings Time.
                    date = DateTime(year, month, daynumber)
                except DateTime.DateError:
                    # End of month reached, so go to the next.
                    daynumber = 1
                    year, month = getNextYearMonth(
                        year, month)
                    try:
                        date = DateTime(year, month, daynumber)
                    except DateTime.DateError:
                        # This Should Not Happen (tm)
                        break

            # Add the info to the dict for this week
            weekinfo['days'] = daylist
            weekinfo['week_total'] = formatTime(week_total)
            weekinfo['week_strict_total'] = formatTime(week_strict_total)
            # Normal week stats
            if week_worked_days:
                norm = week_worked_days * hours_per_day
                week_perc_billable = 100.0 * week_billable / norm
            else:
                week_perc_billable = 0.0
            fmt_perc_billable = "%0.1f %%" % week_perc_billable
            # Strict week stats
            if week_strict_worked_days:
                norm = week_strict_worked_days * hours_per_day
                week_strict_perc_billable = 100.0 * week_strict_billable / norm
            else:
                week_strict_perc_billable = 0.0
            fmt_strict_perc_billable = "%0.1f %%" % week_strict_perc_billable
            weekinfo['total_style'] = weekinfo['perc_style'] = 'greyed'
            if date < DateTime():
                weekinfo['total_style'] = weekinfo['perc_style'] = 'good'
                if week_total < 40.0:
                    weekinfo['total_style'] = 'not-enough'
                if week_perc_billable < 50:
                    weekinfo['perc_style'] = 'not-enough'
            weekinfo['perc_billable'] = fmt_perc_billable
            weekinfo['strict_perc_billable'] = fmt_strict_perc_billable
            self.bookinglist.append(weekinfo)

        if month_worked_days > 0:
            norm = month_worked_days * hours_per_day
            self.perc_billable = 100.0 * month_billable / norm
    def items(self):
        ptool = self.tools.properties()
        hours_per_day = ptool.xm_properties.getProperty('hours_per_day')
        data = []
        employees = self.get_employees()
        for userid in employees:
            empldict = dict(id=userid)
            memberinfo = self.tools.membership().getMemberInfo(userid)
            if memberinfo and memberinfo is not None:
                empldict['name'] = memberinfo['fullname'] or userid
                # For each month create a list employees in a dict with
                # percentages and a url to the month view.
                results = []
                for m in self.months:
                    begin = DateTime(m.year, m.month, 1)
                    end = getEndOfMonth(m.year, m.month)
                    bookingbrains = self.tools.catalog().searchResults(
                        portal_type='Booking',
                        getBookingDate={
                            "query": [begin, end],
                            "range": "minmax",
                            "sort_on": "getBookingDate"
                        },
                        Creator=userid,
                        path=self.searchpath)
                    # Hm, it does not look like sort_on is working so
                    # we do it ourselves.
                    bookingbrains = sorted(bookingbrains, key=booking_date)
                    grouped = itertools.groupby(bookingbrains, booking_date)
                    billable = []
                    for day, bookings in grouped:
                        day_billable = 0.0
                        day_total = 0.0
                        for bb in bookings:
                            day_total += bb.actual_time
                            if bb.getBillable:
                                day_billable += bb.actual_time
                        if day_total > 0:
                            # XXX If the employee worked 1 hour or
                            # less we might want to assume it is just
                            # an hour on Saturday or something and
                            # ignore this day to avoid unnecessarily
                            # influencing the billable percentage
                            # negatively.
                            billable.append(day_billable)
                    days_worked = len(billable)
                    if days_worked > 0:
                        total = sum(billable)
                        perc = 100 * (total / hours_per_day) / days_worked
                    else:
                        perc = 0.0
                    url = "%s/booking_month?memberid=%s&month=%r&year=%r" % (
                        self.site_url, userid, m.month, m.year)
                    perc_dict = dict(percentage=fmt_perc_billable(perc),
                                     url=url)
                    results.append(perc_dict)
                results.reverse()
                empldict['monthly_percentages'] = results
            data.append(empldict)

        return data
    def update(self):
        context = aq_inner(self.context)
        ptool = self.tools().properties()
        hours_per_day = ptool.xm_properties.getProperty('hours_per_day')
        request = self.request
        weeklist = []
        # Start at first day of the week.  Note: with the
        # DateTime.week() method Monday is considered the first day,
        # even though DateTime.dow() says Sunday is day zero.  To make
        # things worse, if say Sunday is 1 October, we want to start
        # with the week of Monday 25 September.

        # Go to the beginning of the week that has the first day of
        # this month.  How many days do we have to subtract for that?
        offset = self.startDate.dow() - 1
        if offset < 0:
            # Only happens for Sunday
            offset += 7

        if offset == 0:
            date = self.startDate
            year, month = self.year, self.month
        else:
            year, month = getPrevYearMonth(self.year, self.month)
            last_day = getEndOfMonth(year, month).day()
            date = DateTime(year, month, last_day - offset + 1)
        daynumber = date.day()
        # Assemble info for at most one month:
        ploneview = context.restrictedTraverse('@@plone')
        month_billable = 0.0
        month_worked_days = 0

        # When comparing dates, make sure December of previous year is
        # less than January of this year.
        while date.month() + 12 * date.year() <= self.month + 12 * self.year:
            weekinfo = dict(
                week_number=date.week(),
                week_start=ploneview.toLocalizedTime(date),
            )
            # Start the week cleanly
            day_of_week = 0
            daylist = []
            week_total = 0.0
            week_strict_total = 0.0
            days_bookings = DayBookingOverview(context,
                                               request,
                                               memberid=self.memberid)
            week_billable = 0.0
            week_worked_days = 0
            # Strict billable means: only count days of this week that
            # are really in this month.
            week_strict_billable = 0.0
            week_strict_worked_days = 0
            while day_of_week < 7:
                day_total = days_bookings.raw_total(date=date)
                day_billable = days_bookings.raw_billable(date=date)
                ui_class = 'greyed'
                if day_total > 0:
                    # Update week stats
                    week_total += day_total
                    if day_total != 0:
                        # Only add the billable hours to the week when
                        # some work (billable or not) has been done
                        # today.
                        week_billable += day_billable
                        week_worked_days += 1
                    if date.month() == self.startDate.month():
                        # Update strict stats
                        week_strict_total += day_total
                        week_strict_billable += day_billable
                        week_strict_worked_days += 1
                        # Update month stats
                        self.raw_total += day_total
                        if day_total != 0:
                            # Only add the billable hours to the month
                            # when some work (billable or not) has
                            # been done today.
                            month_billable += day_billable
                            month_worked_days += 1
                        ui_class = 'good'
                    else:
                        ui_class = 'greyed'
                    daylist.append(
                        dict(total=formatTime(day_total),
                             day_of_week=date.Day(),
                             style=ui_class))
                else:
                    daylist.append(
                        dict(total=None,
                             day_of_week=date.Day(),
                             style=ui_class))
                day_of_week += 1
                daynumber += 1
                try:
                    # We used to simply do date + 1, but that gave
                    # problems with Daylight Savings Time.
                    date = DateTime(year, month, daynumber)
                except DateTime.DateError:
                    # End of month reached, so go to the next.
                    daynumber = 1
                    year, month = getNextYearMonth(year, month)
                    try:
                        date = DateTime(year, month, daynumber)
                    except DateTime.DateError:
                        # This Should Not Happen (tm)
                        break

            # Add the info to the dict for this week
            weekinfo['days'] = daylist
            weekinfo['week_total'] = formatTime(week_total)
            weekinfo['week_strict_total'] = formatTime(week_strict_total)
            # Normal week stats
            if week_worked_days:
                norm = week_worked_days * hours_per_day
                week_perc_billable = 100.0 * week_billable / norm
            else:
                week_perc_billable = 0.0
            fmt_perc_billable = "%0.1f %%" % week_perc_billable
            # Strict week stats
            if week_strict_worked_days:
                norm = week_strict_worked_days * hours_per_day
                week_strict_perc_billable = 100.0 * week_strict_billable / norm
            else:
                week_strict_perc_billable = 0.0
            fmt_strict_perc_billable = "%0.1f %%" % week_strict_perc_billable
            weekinfo['total_style'] = weekinfo['perc_style'] = 'greyed'
            if date < DateTime():
                weekinfo['total_style'] = weekinfo['perc_style'] = 'good'
                if week_total < 40.0:
                    weekinfo['total_style'] = 'not-enough'
                if week_perc_billable < 50:
                    weekinfo['perc_style'] = 'not-enough'
            weekinfo['perc_billable'] = fmt_perc_billable
            weekinfo['strict_perc_billable'] = fmt_strict_perc_billable
            self.bookinglist.append(weekinfo)

        if month_worked_days > 0:
            norm = month_worked_days * hours_per_day
            self.perc_billable = 100.0 * month_billable / norm