def reconcile(request, code, form_number): """Reconciliation screen""" form_types, projects = get_forms() referrer = request.META.get('HTTP_REFERER') all_forms = Form.objects.filter(form_number=form_number, form_code=code) usernames = dict([ (u.id, u.first_name or u.username) for u in User.objects.all()]) fts = list(set([f.form_code for f in all_forms])) if len(fts) != 1: assert False, "More than one form type for form %s !" % form_number # Do we have permission... code = fts[0] mixin(DataEntryForm, form_types[code]) if not request.user.has_perm("%s.reconciler" % DataEntryForm.project): return redirect(referrer) postform = None if request.method == 'POST': postform = DataEntryForm(request.POST) # postform.clean = postform.reconcile_clean if postform.is_valid() and postform.is_really_valid(): reconcile_forms(request.user, form_number, postform) referrer = request.POST['referrer'] if request.POST.has_key('import'): returnto = postform.importurl(form_number) elif referrer and referrer != 'None': returnto = referrer else: returnto = reverse('dataentry.views.show_forms', kwargs=dict(project = postform.project)) returnto = returnto + '#' + postform.cleaned_data['form_number'] return redirect(returnto) else: logging.debug(postform.errors) tf = DataEntryForm() for form in all_forms: form.fields_dict = form.fields_dict() form.groomed = {} tf.groom_all(form.groomed, form.fields_dict) fields = Field.objects.filter(form=form) form.fields_name_dict = {} for field in fields: if not field.name in form.fields_name_dict: form.fields_name_dict[field.name] = [] form.fields_name_dict[field.name].append(field) f = dict(form_number = form_number) info = dict() for fn in tf.field_names(): vals = [] groomed = False for form in all_forms: if not form.fields_dict.has_key(fn): continue vals.append(form.fields_dict[fn]) if form.groomed.has_key(fn): groomed = True def cmp_dates(a,b): return cmp(b.date_entered, a.date_entered) history = list( reduce( set.union, [set(frm.fields_name_dict[fn] if fn in frm.fields_name_dict else []) for frm in all_forms] ) ) history.sort(cmp_dates) history = [ dict( value = fi.value, user = usernames[fi.user_id], date_entered = fi.date_entered.strftime('%d %b %Y %H:%M'), ) for fi in history ] history = dedupe(history, lambda h: "**".join(h.values())) history_groomed = (len(list(set([ h['value'] for h in history ]))) > 1 and all_forms[0].reconciled != None) info[fn] = dict( groomed = groomed and len(list(set(vals))) == 1, vals = list(set([str(v) for v in vals])), frms = dict([ (form.id, form.fields_dict.get(fn,"")) for form in all_forms]), history = history, history_groomed = history_groomed, ) if len(set([str(v) for v in vals])) == 1: f[fn] = vals[0] else: f[fn] = '' # load up the comments comments = [] for fm in all_forms: comments.append(dict( comment = fm.comment, user = fm.user, )) if postform: form = postform errors = postform.errors else: form = DataEntryForm(f) form.is_really_valid(f) errors = form.errors importable = hasattr(form_types[code], 'imported_forms') and (code, form_number) not in form_types[code].imported_forms() extra = None if hasattr(form_types[code], 'ft_annotate'): extra = form.ft_annotate(form_number) return render_to_response("dataentry/reconcile.html", dict( form_number = form_number, forms = all_forms, form = form, reconciled = all_forms[0].reconciled, reconciling = True, comments = comments, info = simplejson.dumps(info), errors = simplejson.dumps(errors), referrer = referrer, importable = importable, menuname = 'dataentry', extra = extra, ), context_instance=RequestContext(request))
def form(request, code, form_id): form_types, projects = get_forms() if not code in form_types.keys(): return HttpResponseNotFound('<h1>No form type called %s</h1>' % code) all_forms = [] mixin(DataEntryForm, form_types[code]) if not request.user.has_perm("%s.data_entry" % DataEntryForm.project) and not request.user.is_staff: return redirect(list_projects) form_number = None secondtime = False groomed = dict() thisuser = None if request.method == 'POST': form = DataEntryForm(request.POST) if request.POST.has_key('delete'): delete_form(request.user, form_id) return redirect(reverse('dataentry.views.show_forms', kwargs=dict(project = form.project))) if form.is_valid(): # If the user is trying to enter, reconcile and import in # one step, validation and redirects are different. reconciler = request.user.has_perm("%s.reconciler" % DataEntryForm.project) or request.user.is_staff importing = reconciler and request.POST.has_key('import') and hasattr(form, 'importurl') if importing: validation_stage = 'reconcile' else: validation_stage = 'entry' # Do the groom check thing here... valid = False secondtime = True form_number = form.cleaned_data['form_number'] if not request.POST.has_key('secondtime') : form.groom_all(groomed) fd = form.cleaned_data if groomed: form = DataEntryForm(fd) valid = form.is_really_valid(fd, stage=validation_stage) else: valid = form.is_really_valid(stage=validation_stage) if not valid: secondtime = False logging.debug(form.errors) elif not groomed: if form_id: f = update_form(request.user, form_id, form) else: f = create_form(request.user, form, form.generate_form_number) success = _try_to_reconcile(f.form_number, f.form_code, request.user) if importing: if success: return redirect(form.importurl(f.form_number)) if reconciler: return redirect(reverse('dataentry.views.reconcile', kwargs=dict( code=f.form_code, form_number=f.form_number))) return redirect(reverse('dataentry.views.show_forms', kwargs=dict(project = form.project))) else: logging.debug(form.errors) else: if form_id: f = load_form(form_id) form_number = f['form_number'] all_forms = Form.objects.filter(form_number=form_number, form_code=code) for form in all_forms: if form.id == int(form_id): thisuser = form.user form.matched = True form = DataEntryForm(f) else: form = DataEntryForm() if form.generate_form_number: # Fill form_number with garbage for now; fix it in create_form f = {'form_number': 100000000 + int('0x' + request.session.session_key[11:17], 16)} form = DataEntryForm(f) allow_rename = True if not form_id: importable = hasattr(form_types[code], 'importurl') elif hasattr(form_types[code], 'imported_forms') and form_number != None: importable = (code, form_number) not in form_types[code].imported_forms() # Changing the form_number of a previously imported form # causes bad things to happen, don't allow it until this is # fixed. allow_rename = importable else: importable = False extra = None if form_id and hasattr(form_types[code], 'ft_annotate'): extra = form.ft_annotate(form_number) fts_q = reduce(lambda x,y: x|y, [Q(form_code=ft.code) for ft in form_types.values() if ft.project == form.project]) keyed_forms = Form.objects.filter(Q(user = request.user) & fts_q) nforms = keyed_forms.count() enable_save_button = request.user.is_staff or not form_id or thisuser == request.user info = dict() for fn in form.field_names() + ['form_comments']: info[fn] = dict() info[fn]['desc'] = ", ".join([ gr['description'] for gr in form.grooming_rules if fn in gr['fields']]) if groomed.has_key(fn): info[fn]['groomed'] = 1 return render_to_response('dataentry/form.html', dict( enable_save_button = enable_save_button, allow_rename = allow_rename, secondtime = secondtime, info = info, errors = simplejson.dumps(form.errors), form = form, form_id = form_id, all_forms = all_forms, number_of_forms = nforms, project_name = projects[form.project].name, importable = importable, menuname = 'dataentry', extra = extra, ), context_instance=RequestContext(request))