Esempio n. 1
0
def show_request(request_id):
    request_id = request_id.lstrip('#')

    # receive subscription
    form_errors = []
    submitted_email = None
    if request.method == 'POST':
        submitted_email = request.form.get('update_email')
        if submitted_email:
            success = subscribe_to_sr(request_id, submitted_email)
            if not success:
                form_errors.append('Please use a valid e-mail address.')

    # TODO: Should probably use Three or something nice for this...
    url = '%s/requests/%s.json' % (app.config['OPEN311_SERVER'], request_id)
    params = {'extensions': 'true', 'legacy': 'false'}
    if app.config['OPEN311_API_KEY']:
        params['api_key'] = app.config['OPEN311_API_KEY']
    r = requests.get(url, params=params)
    if r.status_code == 404:

        # TODO: how to generalize this?
        # Chicago's SR IDs are always \d\d-\d{8}, if we get just digits, reformat and try again
        request_id_digits = re.sub(r'\D', '', request_id)
        if len(request_id_digits) == 8:
            # Try prepending the year if it's only 8 digits
            request_id_digits = datetime.date.today().strftime(
                '%y') + request_id_digits
        if len(request_id_digits) == 10:
            reformatted = '%s-%s' % (request_id_digits[:2],
                                     request_id_digits[2:])
            if reformatted != request_id:
                return redirect(url_for('show_request',
                                        request_id=reformatted))

        # It would be nice to log this for analytical purposes (what requests are being checked that we can't show?)
        # but that would be better done through GA or KISS Metrics than through server logging
        services = open311tools.services(app.config['OPEN311_SERVER'],
                                         app.config['OPEN311_API_KEY'])
        return render_app_template('error_no_sr.html',
                                   request_id=request_id,
                                   services=services), 404

    elif r.status_code != 200:
        app.logger.error('OPEN311: Error (not 404) loading data for SR %s',
                         request_id)
        return render_app_template('error_311_api.html',
                                   request_id=request_id), 500

    srs = r.json
    if srs:
        sr = fixup_sr(srs[0], request_id)

        if 'requested_datetime' in sr:
            sr['requested_datetime'] = iso8601.parse_date(
                sr['requested_datetime'])

        # sometimes an SR doesn't include notes even though there should always be an "opened" note
        if 'notes' not in sr:
            sr['notes'] = []

        relevant_notes = 0
        for note in sr['notes']:
            note['datetime'] = iso8601.parse_date(note['datetime'])
            if note['type'] in ('follow_on', 'follow_on_created', 'activity',
                                'closed'):
                relevant_notes += 1

        # add follow-on closure data, fix types, etc, etc
        by_id = {}
        follow_on_open_count = 0
        follow_on_close_count = 0
        for note in sr['notes']:
            if note['type'] in ('follow_on', 'follow_on_created',
                                'follow_on_closed'):
                note_sr_id = note['extended_attributes']['service_request_id']

                # old-style is just "follow_on" for everything related to follow-ons
                # new-style is "follow_on_created" and "follow_on_closed"
                # update old notes so templates don't get crazy complicated :(
                if note['type'] == 'follow_on_created' or note[
                        'description'].endswith('Created'):
                    note['type'] = 'follow_on_created'
                    follow_on_open_count += 1
                    by_id[note_sr_id] = note

                elif note['type'] == 'follow_on_closed' or note[
                        'description'].endswith('Closed'):
                    follow_on_close_count += 1
                    note['type'] = 'follow_on_closed'
                    if note_sr_id in by_id:
                        original = by_id[note_sr_id]
                        original['extended_attributes'][
                            'closed_datetime'] = note['datetime']

        # if we hit any follow_on_opened notes
        if follow_on_open_count > 0:
            # remove the notes that claim the request is closed
            sr['notes'] = [n for n in sr['notes'] if not n['type'] == 'closed']
            # set the request to open
            sr['status'] = 'open'

            # if we hit as many follow_on_closed as follow_on_opened notes, then request is really closed
            if follow_on_open_count == follow_on_close_count:
                # set the request status to closed
                sr['status'] = 'closed'
                tmp_note = {}
                # add a closing note
                tmp_note['type'] = 'closed'
                tmp_note['summary'] = 'Request Completed'
                # this is brittle, but shouldn't break
                tmp_datetime = sorted([
                    n['extended_attributes']['closed_datetime']
                    for n in by_id.values()
                ])
                # set the closed datetime to be the datetime of the last-closed follow-on
                tmp_note['datetime'] = tmp_datetime[0]
                # add the extra note
                sr['notes'].append(tmp_note)

        # if there's no activity yet, show 'under review'
        if relevant_notes == 0:
            sr['notes'].append({
                'type':
                'activity',
                'summary':
                'Under review by %s staff' % sr.get('agency_responsible', '')
            })

        subscribed = False
        if sr['status'] == 'open' and session.get('addr', None):
            # TODO: when subscription service supports more than e-mail,
            # we should probably be able to show all your subscriptions here
            subscribed = updater.subscription_exists(request_id, 'email',
                                                     session.get('addr', ''))

        # test media
        # sr['media_url'] = sr['media_url'] or 'http://farm5.staticflickr.com/4068/4286605571_c1a1751fdc_n.jpg'

        body = render_app_template('service_request.html',
                                   sr=sr,
                                   subscribed=subscribed,
                                   errors=form_errors,
                                   submitted_email=submitted_email)
        return (body, 200, None)

    else:
        return render_app_template('error_no_sr.html',
                                   request_id=request_id), 404
Esempio n. 2
0
def show_request(request_id):
    request_id = request_id.lstrip('#')

    # receive subscription
    form_errors = []
    submitted_email = None
    if request.method == 'POST':
        submitted_email = request.form.get('update_email')
        if submitted_email:
            success = subscribe_to_sr(request_id, submitted_email)
            if not success:
                form_errors.append('Please use a valid e-mail address.')

    # TODO: Should probably use Three or something nice for this...
    url = '%s/requests/%s.json' % (app.config['OPEN311_SERVER'], request_id)
    params = {'extensions': 'true', 'legacy': 'false'}
    if app.config['OPEN311_API_KEY']:
        params['api_key'] = app.config['OPEN311_API_KEY']
    r = requests.get(url, params=params)
    if r.status_code == 404:

        # TODO: how to generalize this?
        # Chicago's SR IDs are always \d\d-\d{8}, if we get just digits, reformat and try again
        request_id_digits = re.sub(r'\D', '', request_id)
        if len(request_id_digits) == 8:
            # Try prepending the year if it's only 8 digits
            request_id_digits = datetime.date.today().strftime('%y') + request_id_digits
        if len(request_id_digits) == 10:
            reformatted = '%s-%s' % (request_id_digits[:2], request_id_digits[2:])
            if reformatted != request_id:
                return redirect(url_for('show_request', request_id=reformatted))

        # It would be nice to log this for analytical purposes (what requests are being checked that we can't show?)
        # but that would be better done through GA or KISS Metrics than through server logging
        services = open311tools.services(app.config['OPEN311_SERVER'], app.config['OPEN311_API_KEY'])
        return render_app_template('error_no_sr.html', request_id=request_id, services=services), 404

    elif r.status_code != 200:
        app.logger.error('OPEN311: Error (not 404) loading data for SR %s', request_id)
        return render_app_template('error_311_api.html', request_id=request_id), 500

    srs = r.json
    if srs:
        sr = fixup_sr(srs[0], request_id)

        if 'requested_datetime' in sr:
            sr['requested_datetime'] = iso8601.parse_date(sr['requested_datetime'])

        # sometimes an SR doesn't include notes even though there should always be an "opened" note
        if 'notes' not in sr:
            sr['notes'] = []

        relevant_notes = 0
        for note in sr['notes']:
            note['datetime'] = iso8601.parse_date(note['datetime'])
            if note['type'] in ('follow_on', 'follow_on_created', 'activity', 'closed'):
                relevant_notes += 1

        # add follow-on closure data, fix types, etc, etc
        by_id = {}
        follow_on_open_count = 0
        follow_on_close_count = 0
        for note in sr['notes']:
            if note['type'] in ('follow_on', 'follow_on_created', 'follow_on_closed'):
                note_sr_id = note['extended_attributes']['service_request_id']


                # old-style is just "follow_on" for everything related to follow-ons
                # new-style is "follow_on_created" and "follow_on_closed"
                # update old notes so templates don't get crazy complicated :(
                if note['type'] == 'follow_on_created' or note['description'].endswith('Created'):
                    note['type'] = 'follow_on_created'
                    follow_on_open_count += 1
                    by_id[note_sr_id] = note

                elif note['type'] == 'follow_on_closed' or note['description'].endswith('Closed'):
                    follow_on_close_count += 1
                    note['type'] = 'follow_on_closed'
                    if note_sr_id in by_id:
                        original = by_id[note_sr_id]
                        original['extended_attributes']['closed_datetime'] = note['datetime']

        # if we hit any follow_on_opened notes
        if follow_on_open_count >0:
            # remove the notes that claim the request is closed
            sr['notes'] = [n for n in sr['notes'] if not n['type'] == 'closed']
            # set the request to open
            sr['status'] = 'open'

            # if we hit as many follow_on_closed as follow_on_opened notes, then request is really closed
            if follow_on_open_count == follow_on_close_count:
                # set the request status to closed
                sr['status'] = 'closed'
                tmp_note = {}
                # add a closing note
                tmp_note['type'] = 'closed'
                tmp_note['summary'] = 'Request Completed'
                # this is brittle, but shouldn't break
                tmp_datetime = sorted([n['extended_attributes']['closed_datetime'] for n in by_id.values()])
                # set the closed datetime to be the datetime of the last-closed follow-on
                tmp_note['datetime'] = tmp_datetime[0]
                # add the extra note
                sr['notes'].append(tmp_note)

        # if there's no activity yet, show 'under review'
        if relevant_notes == 0:
            sr['notes'].append({
                'type': 'activity',
                'summary': 'Under review by %s staff' % sr.get('agency_responsible', '')
            })

        subscribed = False
        if sr['status'] == 'open' and session.get('addr', None):
            # TODO: when subscription service supports more than e-mail,
            # we should probably be able to show all your subscriptions here
            subscribed = updater.subscription_exists(request_id, 'email', session.get('addr', ''))

        # test media
        # sr['media_url'] = sr['media_url'] or 'http://farm5.staticflickr.com/4068/4286605571_c1a1751fdc_n.jpg'

        body = render_app_template('service_request.html', sr=sr, subscribed=subscribed, errors=form_errors, submitted_email=submitted_email)
        return (body, 200, None)

    else:
        return render_app_template('error_no_sr.html', request_id=request_id), 404
Esempio n. 3
0
def show_request(request_id):
    request_id = request_id.lstrip('#')
    
    # TODO: Should probably use Three or something nice for this...
    url = '%s/requests/%s.json' % (app.config['OPEN311_SERVER'], request_id)
    params = {'extensions': 'true', 'legacy': 'false'}
    if app.config['OPEN311_API_KEY']:
        params['api_key'] = app.config['OPEN311_API_KEY']
    r = requests.get(url, params=params)
    if r.status_code == 404:
        # TODO: need a template
#        logger.error("There is no service request on file for #%s" % request_id)
#        debugresponse (r)
#        debugrequest (request)    
        return render_template('no_service_request_found.html', rid=request_id)
        
    elif r.status_code != 200:
        # TODO: need a template
        logger.error("There was an error getting data about service request #%s" % request_id)
        debugresponse (r)
        debugrequest (request)    
        return ("There was an error getting data about service request #%s" % request_id, 404, None)
        
    srs = r.json
    if srs:

        # debug the data
        logger.debug("got data %s" % pp.pformat(srs))            

        # check the return data, it should be a list
        if (not isinstance(srs, types.ListType)):
            return ("There was an error getting data about service request #%s" % request_id, 404, None)

        sr = srs[0]
        sr['requested_datetime'] = iso8601.parse_date(sr['requested_datetime'])
        for note in sr['notes']:
            note['datetime'] = iso8601.parse_date(note['datetime'])
        
        # add follow-on closure data
        by_id = {}
        for note in sr['notes']:

            if(note['extended_attributes']['closed_datetime']):
                note['extended_attributes']['closed_datetime']= iso8601.parse_date(  note['extended_attributes']['closed_datetime']   )

            if note['type'] == 'follow_on':
                note_sr_id = note['extended_attributes']['service_request_id']
                if note_sr_id in by_id:
                    if note['description'].endswith('Closed'):
                        original = by_id[note_sr_id]
                        original['extended_attributes']['closed_datetime'] = note['datetime']
                else:
                    by_id[note_sr_id] = note
        
        sr['notes'].reverse()
        
        subscribed = False
        if sr['status'] == 'open' and session.get('email', None):
            # TODO: when subscription service supports more than e-mail, 
            # we should probably be able to show all your subscriptions here
            subscribed = updater.subscription_exists(request_id, 'email', session.get('email', ''))


        #more checks that should not be in the template, but in the app. lets have some type of logical separation here.
        assert(sr['address'])
        assert isinstance(sr['address'], types.StringTypes)
        assert(sr['service_name'])
        assert(sr['description'])
        assert(sr['status'])
        assert(sr['extended_attributes'])
        assert(sr['extended_attributes']['channel'])
        assert(sr['agency_responsible'])
        assert(sr['service_request_id'])



        body = render_template('service_request.html', sr=sr, subscribed=subscribed)
        return (body, 200, None)
    
    else:
        return render_template('no_service_request_found.html', rid=request_id)
Esempio n. 4
0
def show_request(request_id):
    request_id = request_id.lstrip("#")

    # receive subscription
    form_errors = []
    submitted_email = None
    if request.method == "POST":
        submitted_email = request.form.get("update_email")
        if submitted_email:
            success = subscribe_to_sr(request_id, submitted_email)
            if not success:
                form_errors.append("Please use a valid e-mail address.")

    # TODO: Should probably use Three or something nice for this...
    url = "%s/requests/%s.json" % (app.config["OPEN311_SERVER"], request_id)
    params = {"extensions": "true", "legacy": "false"}
    if app.config["OPEN311_API_KEY"]:
        params["api_key"] = app.config["OPEN311_API_KEY"]
    r = requests.get(url, params=params)
    if r.status_code == 404:

        # TODO: how to generalize this?
        # Chicago's SR IDs are always \d\d-\d{8}, if we get just digits, reformat and try again
        request_id_digits = re.sub(r"\D", "", request_id)
        if len(request_id_digits) == 8:
            # Try prepending the year if it's only 8 digits
            request_id_digits = datetime.date.today().strftime("%y") + request_id_digits
        if len(request_id_digits) == 10:
            reformatted = "%s-%s" % (request_id_digits[:2], request_id_digits[2:])
            if reformatted != request_id:
                return redirect(url_for("show_request", request_id=reformatted))

        # It would be nice to log this for analytical purposes (what requests are being checked that we can't show?)
        # but that would be better done through GA or KISS Metrics than through server logging
        services = open311tools.services(app.config["OPEN311_SERVER"], app.config["OPEN311_API_KEY"])
        return render_app_template("error_no_sr.html", request_id=request_id, services=services), 404

    elif r.status_code != 200:
        app.logger.error("OPEN311: Error (not 404) loading data for SR %s", request_id)
        return render_app_template("error_311_api.html", request_id=request_id), 500

    srs = r.json
    if srs:
        sr = fixup_sr(srs[0], request_id)

        if "requested_datetime" in sr:
            sr["requested_datetime"] = iso8601.parse_date(sr["requested_datetime"])

        # sometimes an SR doesn't include notes even though there should always be an "opened" note
        if "notes" not in sr:
            sr["notes"] = []

        relevant_notes = 0
        for note in sr["notes"]:
            note["datetime"] = iso8601.parse_date(note["datetime"])
            if note["type"] in ("follow_on", "follow_on_created", "activity", "closed"):
                relevant_notes += 1

        # add follow-on closure data, fix types, etc, etc
        by_id = {}
        follow_on_open_count = 0
        follow_on_close_count = 0
        for note in sr["notes"]:
            if note["type"] in ("follow_on", "follow_on_created", "follow_on_closed"):
                note_sr_id = note["extended_attributes"]["service_request_id"]

                # old-style is just "follow_on" for everything related to follow-ons
                # new-style is "follow_on_created" and "follow_on_closed"
                # update old notes so templates don't get crazy complicated :(
                if note["type"] == "follow_on_created" or note["description"].endswith("Created"):
                    note["type"] = "follow_on_created"
                    follow_on_open_count += 1
                    by_id[note_sr_id] = note

                elif note["type"] == "follow_on_closed" or note["description"].endswith("Closed"):
                    follow_on_close_count += 1
                    note["type"] = "follow_on_closed"
                    if note_sr_id in by_id:
                        original = by_id[note_sr_id]
                        original["extended_attributes"]["closed_datetime"] = note["datetime"]

        # if we hit any follow_on_opened notes
        if follow_on_open_count > 0:
            # remove the notes that claim the request is closed
            sr["notes"] = [n for n in sr["notes"] if not n["type"] == "closed"]
            # set the request to open
            sr["status"] = "open"

            # if we hit as many follow_on_closed as follow_on_opened notes, then request is really closed
            if follow_on_open_count == follow_on_close_count:
                # set the request status to closed
                sr["status"] = "closed"
                tmp_note = {}
                # add a closing note
                tmp_note["type"] = "closed"
                tmp_note["summary"] = "Request Completed"
                # this is brittle, but shouldn't break
                tmp_datetime = sorted([n["extended_attributes"]["closed_datetime"] for n in by_id.values()])
                # set the closed datetime to be the datetime of the last-closed follow-on
                tmp_note["datetime"] = tmp_datetime[0]
                # add the extra note
                sr["notes"].append(tmp_note)

        # if there's no activity yet, show 'under review'
        if relevant_notes == 0:
            sr["notes"].append(
                {"type": "activity", "summary": "Under review by %s staff" % sr.get("agency_responsible", "")}
            )

        subscribed = False
        if sr["status"] == "open" and session.get("addr", None):
            # TODO: when subscription service supports more than e-mail,
            # we should probably be able to show all your subscriptions here
            subscribed = updater.subscription_exists(request_id, "email", session.get("addr", ""))

        # test media
        # sr['media_url'] = sr['media_url'] or 'http://farm5.staticflickr.com/4068/4286605571_c1a1751fdc_n.jpg'

        body = render_app_template(
            "service_request.html", sr=sr, subscribed=subscribed, errors=form_errors, submitted_email=submitted_email
        )
        return (body, 200, None)

    else:
        return render_app_template("error_no_sr.html", request_id=request_id), 404