From 4b96b2b309041c576a2c444cf3959752bc5704a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20A=2E=20S=C3=A1nchez=20L=C3=B3pez?= Date: Fri, 8 Oct 2010 08:21:48 +0000 Subject: [PATCH] * Added a taken care field to stop deadline notifications * Set 'out of date' liaisons as already taken care. * Command to notify for liaisons close to their deadlines. Fixes #384 - Legacy-Id: 2544 --- .../commands/check_liaison_deadlines.py | 63 ++++++++++ .../0008_add_taken_care_to_liaison.py | 116 ++++++++++++++++++ .../0009_set_as_taken_care_old_liaisons.py | 116 ++++++++++++++++++ ietf/liaisons/models.py | 1 + 4 files changed, 296 insertions(+) create mode 100644 ietf/liaisons/management/commands/check_liaison_deadlines.py create mode 100644 ietf/liaisons/migrations/0008_add_taken_care_to_liaison.py create mode 100644 ietf/liaisons/migrations/0009_set_as_taken_care_old_liaisons.py diff --git a/ietf/liaisons/management/commands/check_liaison_deadlines.py b/ietf/liaisons/management/commands/check_liaison_deadlines.py new file mode 100644 index 000000000..75ff11182 --- /dev/null +++ b/ietf/liaisons/management/commands/check_liaison_deadlines.py @@ -0,0 +1,63 @@ +import datetime + +from django.conf import settings +from django.core.management.base import BaseCommand +from django.template.loader import render_to_string + +from ietf.liaisons.models import LiaisonDetail +from ietf.liaisons.mail import IETFEmailMessage + + +PREVIOUS_DAYS = { + 14: 'in two weeks', + 7: 'in one week', + 4: 'in four days', + 3: 'in three days', + 2: 'in two days', + 1: 'tomorrow', + 0: 'today'} + + +class Command(BaseCommand): + help = (u"Check liaison deadlines and send a reminder if we are close to its deadline") + + def send_reminder(self, liaison, days_to_go): + if days_to_go < 0: + subject = '[Liaison OUT OF DATE] %s' % liaison.title + days_msg = 'is out of date for %s days' % (-days_to_go) + else: + subject = '[Liaison deadline %s] %s' % (PREVIOUS_DAYS[days_to_go], liaison.title) + days_msg = 'expires %s' % PREVIOUS_DAYS[days_to_go] + + from_email = settings.LIAISON_UNIVERSAL_FROM + to_email = liaison.to_poc.split(',') + cc = liaison.cc1.split(',') + if liaison.technical_contact: + cc += liaison.technical_contact.split(',') + if liaison.response_contact: + cc += liaison.response_contact.split(',') + bcc = ['statements@ietf.org'] + body = render_to_string('liaisons/liaison_deadline_mail.txt', + {'liaison': liaison, + 'days_msg': days_msg, + }) + print body + mail = IETFEmailMessage(subject=subject, + to=to_email, + from_email=from_email, + cc=cc, + bcc=bcc, + body=body) + if not settings.DEBUG: + mail.send() + print 'Liaison %05s#: Deadline reminder Sent!' % liaison.pk + else: + print 'Liaison %05s#: Deadline reminder Not Sent because in DEBUG mode!' % liaison.pk + + def handle(self, *args, **options): + today = datetime.date.today() + query = LiaisonDetail.objects.filter(deadline_date__isnull=False, taken_care=False, deadline_date__gte=today - datetime.timedelta(14)) + for liaison in query: + delta = liaison.deadline_date - today + if delta.days < 0 or delta.days in PREVIOUS_DAYS.keys(): + self.send_reminder(liaison, delta.days) diff --git a/ietf/liaisons/migrations/0008_add_taken_care_to_liaison.py b/ietf/liaisons/migrations/0008_add_taken_care_to_liaison.py new file mode 100644 index 000000000..c70afb40f --- /dev/null +++ b/ietf/liaisons/migrations/0008_add_taken_care_to_liaison.py @@ -0,0 +1,116 @@ + +from south.db import db +from django.db import models +from ietf.liaisons.models import * + +class Migration: + + def forwards(self, orm): + + # Adding field 'LiaisonDetail.taken_care' + db.add_column('liaison_detail', 'taken_care', orm['liaisons.liaisondetail:taken_care']) + + + + def backwards(self, orm): + + # Deleting field 'LiaisonDetail.taken_care' + db.delete_column('liaison_detail', 'taken_care') + + + + models = { + 'idtracker.personororginfo': { + 'Meta': {'db_table': "'person_or_org_info'"}, + 'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}), + 'created_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}), + 'date_created': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}), + 'date_modified': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), + 'first_name_key': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'last_name_key': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}), + 'middle_initial_key': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}), + 'modified_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}), + 'name_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'person_or_org_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'record_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}) + }, + 'liaisons.frombodies': { + 'Meta': {'db_table': "'from_bodies'"}, + 'body_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}), + 'email_priority': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'from_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_liaison_manager': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'other_sdo': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'poc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'null': 'True', 'db_column': "'poc'"}) + }, + 'liaisons.liaisondetail': { + 'Meta': {'db_table': "'liaison_detail'"}, + 'approval': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.OutgoingLiaisonApproval']", 'null': 'True', 'blank': 'True'}), + 'body': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'by_secretariat': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'cc1': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'cc2': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'deadline_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'detail_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'from_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'from_raw_body': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'from_raw_code': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'last_modified_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'null': 'True', 'db_column': "'person_or_org_tag'"}), + 'purpose': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.LiaisonPurpose']", 'null': 'True'}), + 'purpose_text': ('django.db.models.fields.TextField', [], {'null': 'True', 'db_column': "'purpose'", 'blank': 'True'}), + 'related_to': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.LiaisonDetail']", 'null': 'True', 'blank': 'True'}), + 'replyto': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'response_contact': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'submitted_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'submitter_email': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'submitter_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'taken_care': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'technical_contact': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'to_body': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'to_email': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'to_poc': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}) + }, + 'liaisons.liaisonmanagers': { + 'Meta': {'db_table': "'liaison_managers'"}, + 'email_priority': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}), + 'sdo': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.SDOs']"}) + }, + 'liaisons.liaisonpurpose': { + 'Meta': {'db_table': "'liaison_purpose'"}, + 'purpose_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'purpose_text': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}) + }, + 'liaisons.outgoingliaisonapproval': { + 'approval_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'liaisons.sdoauthorizedindividual': { + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}), + 'sdo': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.SDOs']"}) + }, + 'liaisons.sdos': { + 'Meta': {'db_table': "'sdos'"}, + 'sdo_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'sdo_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) + }, + 'liaisons.uploads': { + 'Meta': {'db_table': "'uploads'"}, + 'detail': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.LiaisonDetail']"}), + 'file_extension': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}), + 'file_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'file_title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}) + } + } + + complete_apps = ['liaisons'] diff --git a/ietf/liaisons/migrations/0009_set_as_taken_care_old_liaisons.py b/ietf/liaisons/migrations/0009_set_as_taken_care_old_liaisons.py new file mode 100644 index 000000000..032041fa2 --- /dev/null +++ b/ietf/liaisons/migrations/0009_set_as_taken_care_old_liaisons.py @@ -0,0 +1,116 @@ + +from south.db import db +from django.db import models +from ietf.liaisons.models import * + +class Migration: + + def forwards(self, orm): + + import datetime + from ietf.liaisons.models import LiaisonDetail + for liaison in LiaisonDetail.objects.filter(deadline_date__lt=datetime.date.today(), taken_care=False): + liaison.taken_care = True + liaison.save() + + + def backwards(self, orm): + + pass + + + models = { + 'idtracker.personororginfo': { + 'Meta': {'db_table': "'person_or_org_info'"}, + 'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}), + 'created_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}), + 'date_created': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}), + 'date_modified': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), + 'first_name_key': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'last_name_key': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}), + 'middle_initial_key': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}), + 'modified_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}), + 'name_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'person_or_org_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'record_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}) + }, + 'liaisons.frombodies': { + 'Meta': {'db_table': "'from_bodies'"}, + 'body_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}), + 'email_priority': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'from_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_liaison_manager': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'other_sdo': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'poc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'null': 'True', 'db_column': "'poc'"}) + }, + 'liaisons.liaisondetail': { + 'Meta': {'db_table': "'liaison_detail'"}, + 'approval': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.OutgoingLiaisonApproval']", 'null': 'True', 'blank': 'True'}), + 'body': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'by_secretariat': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'cc1': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'cc2': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'deadline_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'detail_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'from_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'from_raw_body': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'from_raw_code': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'last_modified_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'null': 'True', 'db_column': "'person_or_org_tag'"}), + 'purpose': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.LiaisonPurpose']", 'null': 'True'}), + 'purpose_text': ('django.db.models.fields.TextField', [], {'null': 'True', 'db_column': "'purpose'", 'blank': 'True'}), + 'related_to': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.LiaisonDetail']", 'null': 'True', 'blank': 'True'}), + 'replyto': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'response_contact': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'submitted_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'submitter_email': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'submitter_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'taken_care': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'technical_contact': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'to_body': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'to_email': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'to_poc': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}) + }, + 'liaisons.liaisonmanagers': { + 'Meta': {'db_table': "'liaison_managers'"}, + 'email_priority': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}), + 'sdo': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.SDOs']"}) + }, + 'liaisons.liaisonpurpose': { + 'Meta': {'db_table': "'liaison_purpose'"}, + 'purpose_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'purpose_text': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}) + }, + 'liaisons.outgoingliaisonapproval': { + 'approval_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'liaisons.sdoauthorizedindividual': { + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}), + 'sdo': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.SDOs']"}) + }, + 'liaisons.sdos': { + 'Meta': {'db_table': "'sdos'"}, + 'sdo_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'sdo_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) + }, + 'liaisons.uploads': { + 'Meta': {'db_table': "'uploads'"}, + 'detail': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.LiaisonDetail']"}), + 'file_extension': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}), + 'file_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'file_title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}) + } + } + + complete_apps = ['liaisons'] diff --git a/ietf/liaisons/models.py b/ietf/liaisons/models.py index bbd332bf7..3bfa06719 100644 --- a/ietf/liaisons/models.py +++ b/ietf/liaisons/models.py @@ -63,6 +63,7 @@ class LiaisonDetail(models.Model): from_raw_body = models.CharField(blank=True, null=True, max_length=255) from_raw_code = models.CharField(blank=True, null=True, max_length=255) approval = models.ForeignKey(OutgoingLiaisonApproval, blank=True, null=True) + taken_care = models.BooleanField(default=False) related_to = models.ForeignKey('LiaisonDetail', blank=True, null=True) def __str__(self): return self.title or ""