def end(self): end = self.contained.period.end() end = TimeAgent.utc2est(end) if self.TZ == 'ET' else end end = datetime(end.year, end.month, end.day, 0, 0) + timedelta(days = 1)\ if self.end_cutoff else end return end
def start(self): start = self.contained.period.start if self.TZ == 'ET': start = TimeAgent.utc2est(start) if self.start_cutoff: start = datetime(start.year, start.month, start.day) + timedelta(days = 1) return start
def get_end(self, tzname = None): """ If this is a fixed maintenance period then return the period's end, if not return the end of the week. """ if self.period: end = self.period.end() return TimeAgent.utc2est(end) if tzname == 'ET' else end else: return self.get_week() + timedelta(7)
def get_start(self, tzname = None): """ If this is a fixed maintenance period there will have been a period assigned. If so, return this period's start. If not, return the start-of-week date. """ if self.period: start = self.period.start return TimeAgent.utc2est(start) if tzname == 'ET' else start else: return self.get_week()
def jsondict(self, tz): start = self.period.start if tz == 'UTC' else TimeAgent.utc2est(self.period.start) end = self.period.end() if tz == 'UTC' else TimeAgent.utc2est(self.period.end()) w = self.period.window # stakeholder want's 'T' or '' for this sponsored = self.period.session.project.is_sponsored() sponsored = '' if not sponsored else 'T' js = {"id" : self.period.id , "session" : SessionHttpAdapter(self.period.session).jsondict() , "session_name" : self.period.session.name , "handle" : self.period.toHandle() , "stype" : self.period.session.session_type.type[0].swapcase() , "end_date" : d2str(end) , "end_time" : t2str(end) , "date" : d2str(start) , "time" : t2str(start) , "lst" : str(TimeAgent.dt2tlst(self.period.start)) , "duration" : self.period.duration , "sscore" : self.period.score # scheduling score , "cscore" : -1.0 # current score , "forecast" : dt2str(self.period.forecast) , "backup" : self.period.backup , "moc_ack" : self.period.moc_ack if self.period.moc_ack is not None else False , "state" : self.period.state.abbreviation if self.period.state is not None else "" , "windowed" : True if w is not None else False , "wdefault" : self.period.is_windowed_default() \ if w is not None else None , "wstart" : d2str(w.start_date()) if w is not None else None , "wend" : d2str(w.last_date()) if w is not None else None , "sponsored" : sponsored , "sponsor" : self.period.session.project.sponsor_text() , "receivers" : self.period.get_rcvrs_json() } # include the accounting but keep the dict flat if self.period.accounting is not None: accounting_js = self.period.accounting.jsondict() # make sure the final jsondict has only one 'id' accounting_id = accounting_js.pop('id') accounting_js.update({'accounting_id' : accounting_id}) js.update(accounting_js) return js
def clone(self, group = None): """ Creates a clone of the template, assigning the 'group' field to the parameter 'group' if this parameter is provided. The object will not be identical: there will be a different id, for instance. """ ma = Maintenance_Activity(); ma.save() # will be overwritten if template and group provided. ma.group = group if group else self.group # subject to a more recent one being found (see below) template = self # If this is a repeat template: if self.repeat_interval: ma.repeat_interval = 0 ma.repeat_end = None ma.repeat_template = self.repeat_template \ if self.repeat_template else self if group: template = self.get_template(group) # all maintenance activities are based on local time, # i.e. start 8:00 AM means that regardless of whether # DST is active or not. To do this, we get ET version # of group and template start so that it can be saved # as the appropriate UTC time to account for DST. t_start = template.get_start('ET') g_start = TimeAgent.utc2est(group.get_start()) start = datetime(g_start.year, g_start.month, g_start.day, t_start.hour, t_start.minute) # if this is a template, include the original creation # date for the repeat activity. ma.modifications.add(template.modifications.all()[0]) else: # we want the group's date, and the original's time in ET if group: start = datetime(group.get_start().date().year, group.get_start().date().month, group.get_start().date().day, self.get_start('ET').hour, self.get_start('ET').minute) else: start = self.get_start('ET') ma.copy_data(template) ma.set_start(start if start else template.start, 'ET' if start else None) ma.save() return ma
def GenerateBlackoutReport(): outfile = open("./DssBlackoutReport.txt", 'w') now = datetime.utcnow() later = now + timedelta(days = 7) outfile.write("Project | Start (UTC) | End (UTC) | Start (ET) | End (ET)\n") outfile.write("-------------------------------------------------------------------\n") sorted_projects = sorted(Project.objects.filter(complete = False) , lambda x, y: cmp(x.pcode, y.pcode)) for p in sorted_projects: blackouts = p.get_blackout_times(now, later) if blackouts: for start, end in blackouts: outfile.write("%s | %s | %s | %s | %s\n" % \ (p.pcode.ljust(11) , start.strftime("%m-%d %H:%M") , end.strftime("%m-%d %H:%M") , TimeAgent.utc2est(start).strftime("%m-%d %H:%M") , TimeAgent.utc2est(end).strftime("%m-%d %H:%M"))) outfile.close()
def get_start(self, tzname = None): if self.group: date = self.group.get_start().date() if self._start.hour < self.group.get_start().hour and \ self._start.hour < self.group.get_end().hour: date = date + timedelta(1) start = datetime(date.year, date.month, date.day, self._start.hour, self._start.minute) else: start = self._start return TimeAgent.utc2est(start) if tzname == 'ET' else start
def add_activity(request, group_id = None, year = None, month = None, day = None): u = get_requestor(request) supervisors = get_rescal_supervisors() user = _get_user_name(u) supervisor_mode = True if (u in supervisors) else False if request.method == 'POST': form = RCAddActivityForm(request.POST) if form.is_valid(): # process the returned stuff here... ma = Maintenance_Activity() if group_id: ma.group = Maintenance_Activity_Group.objects.get(id = group_id) ma.save() # needs to have a primary key for many-to-many # relationships to be set. _process_activity(request, ma, form) view_url = "http://%s/resourcecal_display_activity/%s/" % (request.get_host(), ma.id) rc_notifier.notify(supervisors, "new", ma.get_start("ET").date(), view_url) if request.POST['ActionEvent'] =="Submit And Continue": if form.cleaned_data['entity_id']: redirect_url = '/resourcecal_add_activity/%s/' % \ (form.cleaned_data['entity_id']) elif year and month and day: redirect_url = '/resourcecal_add_activity/%s/%s/%s/' % \ (year, month, day) else: redirect_url = '/resourcecal_add_activity/' return HttpResponseRedirect(redirect_url) else: return HttpResponseRedirect('/schedule/') else: default_telescope = Maintenance_Telescope_Resources.objects \ .filter(rc_code = 'N')[0] default_software = Maintenance_Software_Resources.objects \ .filter(rc_code = 'N')[0] if group_id: g = Maintenance_Activity_Group.objects.get(id = group_id) start = TimeAgent.utc2est(g.get_start()) elif year and month and day: start = datetime(int(year), int(month), int(day)) initial_data = {'date' : start.date(), 'time_hr' : start.hour, 'time_min' : start.minute, 'end_choice' : "end_time", 'end_time_hr' : start.hour + 1, 'end_time_min' : 0, 'responsible' : user, 'telescope' : default_telescope.id, 'software' : default_software.id, 'entity_id' : group_id, 'recurrency_until' : start + timedelta(days = 30), } form = RCAddActivityForm(initial = initial_data) return render_to_response('users/rc_add_activity_form.html', {'form': form, 'supervisor_mode': supervisor_mode, 'add_activity': True })
def scheduling_email(request, *args, **kwds): address_key = ["observer_address", "changed_address", "staff_address"] subject_key = ["observer_subject", "changed_subject", "staff_subject"] body_key = ["observer_body", "changed_body", "staff_body"] email_key = ["observer", "changed", "staff"] if request.method == 'GET': # Show the schedule from now until 8am eastern 'duration' days from now. start = datetime.utcnow() duration = int(request.GET.get("duration")) end = TimeAgent.est2utc(TimeAgent.utc2est(start + timedelta(days = duration - 1)) .replace(hour = 8, minute = 0, second = 0, microsecond = 0)) # The class that sets up the emails needs the periods in the # scheduling range, and all the periods in the future. currentPs = list(Period.objects.filter(start__gt = start , start__lt = end)) futurePs = list(Period.objects.filter(start__gte = start).order_by("start")) notifier.setPeriods(currentPs, futurePs) return HttpResponse( json.dumps({ 'observer_address' : notifier.getAddresses("observer"), 'observer_subject' : notifier.getSubject("observer"), 'observer_body' : notifier.getBody("observer"), 'changed_address' : notifier.getAddresses("changed"), 'changed_subject' : notifier.getSubject("changed"), 'changed_body' : notifier.getBody("changed"), 'staff_address' : notifier.getAddresses("staff"), 'staff_subject' : notifier.getSubject("staff"), 'staff_body' : notifier.getBody("staff"), 'obs_periods' : [p.id for p in notifier.observingPeriods], 'changed_periods' : [p.id for p in notifier.changedPeriods] }) , mimetype = "text/plain") elif request.method == 'POST': # here we are overriding what/who gets sent for the first round # of emails for i in xrange(3): addr = str(request.POST.get(address_key[i], "")).replace(" ", "").split(",") notifier.setAddresses(email_key[i], addr) notifier.setSubject(email_key[i], request.POST.get(subject_key[i], "")) notifier.setBody(email_key[i], request.POST.get(body_key[i], "")) notifier.notify() # Remember when we did this to allow time-tagging of the schedule sn = Schedule_Notification(date = datetime.utcnow()) sn.save() # Emails for a given period shouldn't be sent more then is # necessary, so here we set the last_notification timestamp. # However, the client can change the recipients and text of the # 'changes' email - this ignores those changes. # See Story: https://www.pivotaltracker.com/story/show/14550249 now = datetime.utcnow() set_periods_last_notification(now, request, "changed_periods") set_periods_last_notification(now, request, "obs_periods") return HttpResponse(json.dumps({'success':'ok'}) , mimetype = "text/plain") else: return HttpResponse( json.dumps({'error': 'request.method is neither GET or POST!'}) , mimetype = "text/plain")