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