Add link from training to corporation contact

This commit is contained in:
Claude Paroz 2013-04-05 16:18:18 +02:00
parent 4c12886e73
commit 80cb4ebc30
7 changed files with 173 additions and 9 deletions

View file

@ -30,4 +30,5 @@ urlpatterns = patterns('',
url(r'^student/(?P<pk>\d+)/summary/', views.StudentSummaryView.as_view()),
url(r'^availability/(?P<pk>\d+)/summary/', views.AvailabilitySummaryView.as_view()),
url(r'^corporation/(?P<pk>\d+)/contacts/', views.CorpContactJSONView.as_view()),
)

View file

@ -83,6 +83,7 @@ class AvailabilityAdminForm(forms.ModelForm):
class AvailabilityInline(admin.TabularInline):
model = Availability
form = AvailabilityAdminForm
ordering = ('corporation__name',)
extra = 1
formfield_overrides = {
models.TextField: {'widget': forms.Textarea(attrs={'rows':2, 'cols':40})},

View file

@ -0,0 +1,122 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'Training.contact'
db.add_column('stages_training', 'contact',
self.gf('django.db.models.fields.related.ForeignKey')(to=orm['stages.CorpContact'], null=True, blank=True),
keep_default=False)
def backwards(self, orm):
# Deleting field 'Training.contact'
db.delete_column('stages_training', 'contact_id')
models = {
'stages.availability': {
'Meta': {'object_name': 'Availability'},
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'corporation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['stages.Corporation']"}),
'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['stages.Domain']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'period': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['stages.Period']"})
},
'stages.corpcontact': {
'Meta': {'object_name': 'CorpContact'},
'corporation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['stages.Corporation']"}),
'email': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_main': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'role': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}),
'tel': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'})
},
'stages.corporation': {
'Meta': {'ordering': "(u'name',)", 'object_name': 'Corporation'},
'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'city': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'pcode': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
'street': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'tel': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'typ': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}),
'web': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
},
'stages.domain': {
'Meta': {'ordering': "(u'name',)", 'object_name': 'Domain'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'stages.klass': {
'Meta': {'object_name': 'Klass'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['stages.Level']"}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'section': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['stages.Section']"})
},
'stages.level': {
'Meta': {'object_name': 'Level'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '10'})
},
'stages.period': {
'Meta': {'object_name': 'Period'},
'end_date': ('django.db.models.fields.DateField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['stages.Level']"}),
'section': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['stages.Section']"}),
'start_date': ('django.db.models.fields.DateField', [], {}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '150'})
},
'stages.referent': {
'Meta': {'ordering': "(u'last_name', u'first_name')", 'object_name': 'Referent'},
'abrev': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}),
'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '40'})
},
'stages.section': {
'Meta': {'object_name': 'Section'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '20'})
},
'stages.student': {
'Meta': {'object_name': 'Student'},
'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'birth_date': ('django.db.models.fields.DateField', [], {}),
'city': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'ext_id': ('django.db.models.fields.IntegerField', [], {'unique': 'True', 'null': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'klass': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['stages.Klass']"}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'mobile': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}),
'pcode': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
'street': ('django.db.models.fields.CharField', [], {'max_length': '150', 'blank': 'True'}),
'tel': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'})
},
'stages.training': {
'Meta': {'object_name': 'Training'},
'availability': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['stages.Availability']", 'unique': 'True'}),
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'contact': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['stages.CorpContact']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'referent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['stages.Referent']", 'null': 'True', 'blank': 'True'}),
'student': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['stages.Student']"})
}
}
complete_apps = ['stages']

View file

@ -191,6 +191,7 @@ class Training(models.Model):
student = models.ForeignKey(Student, verbose_name='Étudiant')
availability = models.OneToOneField(Availability, verbose_name='Disponibilité')
referent = models.ForeignKey(Referent, null=True, blank=True, verbose_name='Référent')
contact = models.ForeignKey(CorpContact, null=True, blank=True, verbose_name='Contact institution')
comment = models.TextField(blank=True, verbose_name='Remarques')
class Meta:

View file

@ -45,6 +45,7 @@ function update_corporations(period_id) {
$('#corp_select').empty();
$('#corp_detail').html('').removeClass("filled");
current_avail = null;
$('#contact_select').find('option:gt(0)').remove();
$('input#valid_training').hide();
if (period_id == '') return;
$.getJSON('/period/' + period_id + '/corporations/', function(data) {
@ -52,10 +53,11 @@ function update_corporations(period_id) {
var domains = [];
var options = [];
$('#corp_filter').empty().append($("<option />").val('').text('Tous les domaines'));
// data contains availabilities (id is availability not corporation)
$.each(data, function() {
if (this.free) {
options.push(this);
sel.append($("<option />").val(this.id).text(this.corp_name));
sel.append($("<option />").val(this.id).text(this.corp_name).data('id_corp', this.id_corp));
}
if ($.inArray(this.domain, domains) < 0) {
domains.push(this.domain);
@ -158,13 +160,26 @@ $(document).ready(function() {
$('#corp_select').change(function(ev) {
$('#corp_detail').load('/availability/' + $(this).val() + '/summary/').addClass("filled");
current_avail = $(this).val();
if (current_student !== null) $('input#valid_training').show()
if (current_student !== null) $('input#valid_training').show();
// Fill contact select
var sel = $('#contact_select');
sel.html('<option value="">-------</option>');
var id_corp = $("option:selected", this).data('id_corp');
$.getJSON('/corporation/' + id_corp + '/contacts/', function(data) {
$.each(data, function(key, contact) {
var item = contact.first_name + ' ' + contact.last_name;
if (contact.role.length) item += ' (' + contact.role + ')';
sel.append($("<option />").val(contact.id).text(item));
});
if (data.length == 1) sel.val(data[0].id);
});
});
$('#valid_training').click(function() {
$.post('/training/new/', {
student: current_student, avail: current_avail,
referent: $('#referent_select').val(),
contact: $('#contact_select').val(),
csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val()},
function(data) {
if (data != 'OK') {

View file

@ -48,6 +48,19 @@ class TrainingsByPeriodView(ListView):
).filter(availability__period__pk=self.kwargs['pk'])
class CorpContactJSONView(ListView):
""" Return all contacts from a given corporation """
return_fields = ['id', 'first_name', 'last_name', 'role', 'is_main']
def get_queryset(self):
return CorpContact.objects.filter(corporation__pk=self.kwargs['pk'])
def render_to_response(self, context):
serialized = [dict([(field, getattr(obj, field)) for field in self.return_fields])
for obj in context['object_list']]
return HttpResponse(json.dumps(serialized), content_type="application/json")
class AttributionView(TemplateView):
template_name = 'attribution.html'
@ -100,7 +113,8 @@ def period_students(request, pk):
def period_availabilities(request, pk):
""" Return all availabilities in the specified period """
period = get_object_or_404(Period, pk=pk)
corps = [{'id': av.id, 'corp_name': av.corporation.name, 'domain': av.domain.name, 'free': av.free}
corps = [{'id': av.id, 'id_corp': av.corporation.id, 'corp_name': av.corporation.name,
'domain': av.domain.name, 'free': av.free}
for av in period.availability_set.select_related('corporation').all()]
return HttpResponse(json.dumps(corps), content_type="application/json")
@ -108,12 +122,15 @@ def new_training(request):
if request.method != 'POST':
return HttpResponseNotAllowed()
ref_key = request.POST.get('referent')
cont_key = request.POST.get('contact')
try:
ref = Referent.objects.get(pk=ref_key) if ref_key else None
contact = CorpContact.objects.get(pk=cont_key) if cont_key else None
training = Training.objects.create(
student=Student.objects.get(pk=request.POST.get('student')),
availability=Availability.objects.get(pk=request.POST.get('avail')),
referent=ref,
contact=contact,
)
except Exception as exc:
return HttpResponse(str(exc))
@ -144,7 +161,8 @@ def stages_export(request):
('NPA Inst.', 'availability__corporation__pcode'),
('Ville Inst.', 'availability__corporation__city'),
('Domaine', 'availability__domain__name'),
('Civilité contact', None), ('Prénom contact', None), ('Nom contact', None),
('Civilité contact', 'contact__title'), ('Prénom contact', 'contact__first_name'),
('Nom contact', 'contact__last_name'),
]
period_filter = request.GET.get('filter')
@ -153,6 +171,7 @@ def stages_export(request):
else:
query = Training.objects.all()
# Prepare "default" contacts (when not defined on training)
contacts = {}
for contact in CorpContact.objects.all().select_related('corporation').order_by('corporation'):
if contact.corporation.name not in contacts or contact.is_main is True:
@ -170,11 +189,13 @@ def stages_export(request):
for row_idx, tr in enumerate(query.values(*query_keys), start=1):
for col_idx, field in enumerate(query_keys):
ws.cell(row=row_idx, column=col_idx).value = tr[field]
contact = contacts.get(tr['availability__corporation__name'])
if contact:
ws.cell(row=row_idx, column=col_idx+1).value = contact.title
ws.cell(row=row_idx, column=col_idx+2).value = contact.first_name
ws.cell(row=row_idx, column=col_idx+3).value = contact.last_name
if tr['contact__last_name'] is None:
# Use default contact
contact = contacts.get(tr['availability__corporation__name'])
if contact:
ws.cell(row=row_idx, column=col_idx-2).value = contact.title
ws.cell(row=row_idx, column=col_idx-1).value = contact.first_name
ws.cell(row=row_idx, column=col_idx).value = contact.last_name
response = HttpResponse(save_virtual_workbook(wb), mimetype='application/ms-excel')
response['Content-Disposition'] = 'attachment; filename=%s%s.xlsx' % (

View file

@ -85,6 +85,9 @@
<select id="referent_select"><option value="">-------</option>
{% for ref in referents %}<option value="{{ ref.id }}">{{ ref }} ({{ ref.num_refs }})</option>{% endfor %}</select>
</div>
<div id="contact_choice"><label for="contact_select">Contact institution:</label>
<select id="contact_select"><option value="">-------</option></select>
</div>
<div id="buttons_div"><input id="valid_training" type="button" value="Valider ce stage"></div>
</form>
</div>