'Ajax response method, expects a JSON input like:
{l: the PE label (from the input field),
c: boolean to indicate whether to just check
the PE label or to register payments
d: the payment data (raw data, which payments to update)
@param r: the S3Request instance
@param attr: controller parameters
@return: JSON response, structure:
{l: the actual PE label (to update the input field),
p: the person details,
f: [{n: the flag name
i: the flag instructions
u: whether there are any actionable data
s: whether the action is permitted or not
d: {t: time stamp
h: payment details (raw data)
d: payment details (HTML)
e: form error (for label field)
a: error message
w: warning message
m: success message'

def registration_ajax(self, r, **attr):

    T = current.T
    s = r.body
    s.seek(0)
    try:
        data = json.load(s)
    except (ValueError, TypeError):
        r.error(400, current.ERROR.BAD_REQUEST)
    output = {}
    alert = None
    error = None
    warning = None
    message = None
    permitted = False
    flags = []
    pe_label = data.get('l')
    person = self.get_person(pe_label)
    if (person is None):
        error = s3_str(T('No    person    found    with    this    ID    number'))
    else:
        flag_info = dvr_get_flag_instructions(person.id, action=self.ACTION)
        permitted = flag_info['permitted']
        check = data.get('c')
        if check:
            person_details = self.person_details(person)
            profile_picture = self.profile_picture(person)
            output['p'] = s3_str(person_details)
            output['l'] = person.pe_label
            output['b'] = profile_picture
            info = flag_info['info']
            for (flagname, instructions) in info:
                flags.append({'n': s3_str(T(flagname)), 'i': s3_str(T(instructions))})
            if permitted:
                payments = self.get_payment_data(person.id)
            else:
                payments = []
            date = S3DateTime.datetime_represent(current.request.utcnow, utc=True)
            output['d'] = {'d': s3_str(self.payment_data_represent(payments)), 't': s3_str(date), 'h': payments}
            if payments:
                output['u'] = True
            else:
                output['u'] = False
        elif (not permitted):
            alert = T('Payment    registration    not    permitted')
        else:
            payments = data.get('d')
            if payments:
                date = r.utcnow
                comments = data.get('c')
                (updated, failed) = self.register_payments(person.id, payments, date=date, comments=comments)
                message = (T('%(number)s    payment(s)    registered') % {'number': updated})
                if failed:
                    warning = (T('%(number)s    payment(s)    not    found') % {'number': failed})
            else:
                alert = T('No    payments    specified')
    if alert:
        output['a'] = s3_str(alert)
    if error:
        output['e'] = s3_str(error)
    if message:
        output['m'] = s3_str(message)
    if warning:
        output['w'] = s3_str(warning)
    output['s'] = permitted
    output['f'] = flags
    current.response.headers['Content-Type'] = 'application/json'
    return json.dumps(output)
