コード例 #1
0
def add_categories():
    current_app.logger.info("Add category")

    request_body = request.get_json()

    try:
        validate(request_body, CATEGORY_SCHEMA)
    except ValidationError as e:
        current_app.logger.info("Create category - payload failed validation")
        raise ApplicationError(e.message, 400, 400)

    name = request_body["name"]
    display_name = request_body["display-name"]
    display_order = request_body["display-order"]
    permission = request_body["permission"]
    provisions = request_body["provisions"]
    instruments = request_body["instruments"]

    try:
        exists = Categories.query\
            .filter(func.lower(Categories.name) == func.lower(name)) \
            .filter(Categories.parent_id == None) \
            .first()  # noqa: E711 - Ignore "is None vs ==", is None does not produce valid sql in sqlAlchmey

        if exists is not None:
            message = "Category '{0}' already exists.".format(name)
            current_app.logger.info(message)
            raise ApplicationError(message, 409, 409)

        category = Categories(name, None, display_order, permission, display_name)
        db.session.add(category)
        db.session.flush()

        for prov in provisions:
            provision = StatutoryProvision.query\
                .filter(func.lower(StatutoryProvision.title) == func.lower(prov)).first()
            if provision is None:
                message = "Statutory provision '{0}' does not exist.".format(prov)
                current_app.logger.info(message)
                raise ApplicationError(message, 404, 404)
            mapping = CategoryStatProvisionMapping(category.id, provision.id)
            db.session.add(mapping)

        for instrument in instruments:
            exists = Instruments.query.filter(func.lower(Instruments.name) == func.lower(instrument)).first()
            if exists is None:
                message = "Instrument '{0}' does not exist.".format(instrument)
                current_app.logger.info(message)
                raise ApplicationError(message, 404, 404)
            mapping = CategoryInstrumentsMapping(category.id, exists.id)
            db.session.add(mapping)

        db.session.commit()

        return "", 201

    except Exception:
        current_app.logger.info("Rolling back transaction")
        db.session.rollback()
        raise
コード例 #2
0
    def add_to_register(add_land_charge_data):
        try:
            response = g.requests.post(
                MINT_API_URL,
                data=add_land_charge_data,
                headers={'Content-Type': 'application/json'})
        except Exception as ex:
            error_message = 'Failed to send land charge to mint-api. Exception - {}'.format(
                ex)
            current_app.logger.exception(error_message)
            raise ApplicationError(error_message, 'ADD_TO_REGISTER')

        if response.status_code != 202:
            error_message = "Failed to send land charge to mint-api. Status '{}', Message '{}'"\
                .format(response.status_code, response.text)
            current_app.logger.error(error_message)
            if response.status_code != 400:
                raise ApplicationError(error_message, 'ADD_TO_REGISTER')
            result = response.json()
        else:
            result = response.json()
            result['local-land-charge'] = encode_charge_id(
                result['local-land-charge'])
            current_app.audit_logger.info(
                "New charge created. entry number: {}".format(
                    result['entry_number']))

        return result, response.status_code
コード例 #3
0
def add_instrument():
    current_app.logger.info("Add instruments.")

    request_body = request.get_json()

    try:
        validate(request_body, INSTRUMENT_SCHEMA)
    except ValidationError as e:
        current_app.logger.info("Create instrument - payload failed validation")
        raise ApplicationError(e.message, 400, 400)

    name = request_body["name"]

    exists = Instruments.query.filter(func.lower(Instruments.name) == func.lower(name)).all()

    if exists is not None and len(exists) > 0:
        message = "Instrument '{0}' already exists.".format(name)
        current_app.logger.info(message)
        raise ApplicationError(message, 409, 409)

    instrument = Instruments(name)

    db.session.add(instrument)
    db.session.commit()

    return "", 201
コード例 #4
0
def add_statutory_provisions():
    current_app.logger.info("Add statutory provision.")

    request_body = request.get_json()

    try:
        validate(request_body, STAT_PROV_SCHEMA)
    except ValidationError as e:
        current_app.logger.info(
            "Add statutory provision - payload failed validation")
        raise ApplicationError(e.message, 400, 400)

    title = request_body["title"]
    selectable = request_body["selectable"]

    exists = StatutoryProvision.query.filter(
        func.lower(StatutoryProvision.title) == func.lower(title)).all()

    if exists is not None and len(exists) > 0:
        message = "Statutory provision '{0}' already exists.".format(title)
        current_app.logger.info(message)
        raise ApplicationError(message, 409, 409)

    stat_prov = StatutoryProvision(title, selectable)

    db.session.add(stat_prov)
    db.session.commit()

    return "", 201
コード例 #5
0
def update_instrument(instrument_name):
    current_app.logger.info("Update instrument {0}.".format(instrument_name))

    request_body = request.get_json()

    try:
        validate(request_body, INSTRUMENT_SCHEMA)
    except ValidationError as e:
        current_app.logger.info("Update instrument - payload failed validation")
        raise ApplicationError(e.message, 400, 400)

    name = request_body["name"]

    instrument = Instruments.query.filter(func.lower(Instruments.name) == func.lower(instrument_name)).first()

    if instrument is None:
        message = "Instrument '{0}' does not exist.".format(name)
        current_app.logger.info(message)
        raise ApplicationError(message, 404, 404)

    if instrument.name.lower() != name.lower():
        inuse = Instruments.query.filter(func.lower(Instruments.name) == func.lower(name)).first()
        if inuse is not None:
            message = "Instrument with name '{0}' already exists.".format(name)
            current_app.logger.info(message)
            raise ApplicationError(message, 409, 409)

    instrument.name = name
    db.session.commit()

    return "", 204
コード例 #6
0
def update_land_charge(land_charge_id):
    """Update a land charge"""

    current_app.logger.info("Endpoint called")

    payload = request.get_json()

    if str(payload['local-land-charge']) == land_charge_id:

        encoded_charge = encode_charge_id(payload['local-land-charge'])
        response = SearchApiService.get_by_charge_number(encoded_charge)

        if response.status_code != 200:
            current_app.logger.error("Charge does not exist")
            raise ApplicationError("Cannot find local land charge", "U101",
                                   400)

        current_app.logger.info("Sending charge to mint")

        result, status = MintApiService.add_to_register(
            json.dumps(payload, sort_keys=True, separators=(',', ':')))

        if status == 202:
            built_resp = {
                "entry_number": result['entry_number'],
                "land_charge_id": result['local-land-charge'],
                "registration_date": payload['registration-date']
            }

            if 'end-date' in payload and payload['end-date']:
                # Used for calculating performance platform metrics
                current_app.logger.performance_platform(
                    "Successfully cancelled charge '{}'".format(
                        land_charge_id))
            else:
                # Used for calculating performance platform metrics
                current_app.logger.performance_platform(
                    "Successfully updated charge '{}'".format(land_charge_id))
        else:
            # return result from Mint api
            built_resp = result
    else:
        current_app.logger.warning(
            "Cannot change local-land-charge field for charge '{}'".format(
                land_charge_id))
        raise ApplicationError("Cannot change local-land-charge field", "U100",
                               400)

    current_app.logger.info(
        "Returning update response for charge '{}'".format(land_charge_id))

    return json.dumps(built_resp, sort_keys=True,
                      separators=(',', ':')), status, {
                          'Content-Type': 'application/json'
                      }
コード例 #7
0
def get_sub_category(category, sub_category):
    current_app.logger.info("Get category for {0}.".format(category))

    category_obj = Categories.query \
        .filter(func.lower(Categories.name) == func.lower(category)) \
        .filter(Categories.parent_id == None) \
        .first()  # noqa: E711 - Ignore "is None vs ==", is None does not produce valid sql in sqlAlchmey

    if category_obj is None:
        raise ApplicationError("Category '{0}' not found.".format(category), 404, 404)

    sub_category_obj = Categories.query \
        .filter(func.lower(Categories.name) == func.lower(sub_category)) \
        .filter(Categories.parent_id == category_obj.id) \
        .first()

    if sub_category_obj is None:
        raise ApplicationError("Sub-category '{0}' not found for parent '{1}'".format(sub_category, category),
                               404, 404)

    provisions = []
    for provision_mapping in sub_category_obj.provisions:
        provisions.append(provision_mapping.provision.title)

    instruments = []
    for instruments_mapping in sub_category_obj.instruments:
        instruments.append(instruments_mapping.instrument.name)

    children = []
    for children_mapping in Categories.query \
            .filter(Categories.parent_id == sub_category_obj.id) \
            .order_by(Categories.display_order).all():
        children.append(
            {
                "name": children_mapping.name,
                "display-name": children_mapping.display_name,
                "permission": children_mapping.permission,

            })

    result = {
        "name": sub_category_obj.name,
        "display-name": sub_category_obj.display_name,
        "permission": sub_category_obj.permission,
        "statutory-provisions": provisions,
        "instruments": instruments,
        "sub-categories": children,
        "parent": category_obj.name}

    return Response(response=json.dumps(result), mimetype="application/json")
コード例 #8
0
def delete_sub_category(category, sub_category):
    current_app.logger.info("Delete category for {0}.".format(category))

    try:
        category = Categories.query \
            .filter(func.lower(Categories.name) == func.lower(category)) \
            .filter(Categories.parent_id == None) \
            .first()  # noqa: E711 - Ignore "is None vs ==", is None does not produce valid sql in sqlAlchmey

        if category is None:
            raise ApplicationError("Category '{0}' not found.".format(category), 404, 404)

        sub_category_obj = Categories.query \
            .filter(func.lower(Categories.name) == func.lower(sub_category)) \
            .filter(Categories.parent_id == category.id) \
            .first()

        if sub_category_obj is None:
            raise ApplicationError("Sub-category '{0}' not found for parent '{1}'"
                                   .format(sub_category, category), 404, 404)

        sub_categories = Categories.query \
            .filter(Categories.parent_id == sub_category_obj.id) \
            .all()

        for sub_category in sub_categories:
            CategoryInstrumentsMapping.query \
                .filter(CategoryInstrumentsMapping.category_id == sub_category.id).delete()
            CategoryStatProvisionMapping.query \
                .filter(CategoryStatProvisionMapping.category_id == sub_category.id).delete()
            Categories.query \
                .filter(Categories.id == sub_category.id).delete()

        CategoryInstrumentsMapping.query\
            .filter(CategoryInstrumentsMapping.category_id == sub_category_obj.id).delete()
        CategoryStatProvisionMapping.query\
            .filter(CategoryStatProvisionMapping.category_id == sub_category_obj.id).delete()
        Categories.query\
            .filter(Categories.id == sub_category_obj.id).delete()

        db.session.commit()

        return "", 204

    except Exception:
        current_app.logger.info("Rolling back transaction")
        db.session.rollback()
        raise
コード例 #9
0
    def test_add_charge_failed_application_error_400(self,
                                                     mock_mint_api_service,
                                                     mock_request,
                                                     mock_current_app):

        request_data = '{"further-information-location": "123 main street","further-information-reference": "123",' \
                       '"expiry-date": "2020-01-01","charge-creation-date": "2017-01-01",' \
                       '"charge-geographic-description": "More information about ' \
                       'location","geometry": {"features": [{"geometry": {"coordinates": [[[' \
                       '606371.1076853184,284813.8509437054],[544515.2768183555,217914.9341522617],' \
                       '[520410.0576399995,287147.0361743166],[606371.1076853184,284813.8509437054]]],' \
                       '"type": "Polygon"},"properties": {"id": 1},"type": "Feature"}],"type": "FeatureCollection"},' \
                       '"statutory-provision": "Building Act 1984 section 107","charge_reason": "deed",' \
                       '"originating-authority": "City of London", "registration-date": "2012-12-12"} '

        mock_request.get_json.return_value = json.loads(request_data)
        mock_mint_api_service.add_to_register.side_effect = \
            ApplicationError('Invalid request. For more information check the logs for TraceID', "test", 400)

        headers = {
            'Content-Type': 'application/json',
            'Authorization': 'NOTAREALJWT'
        }
        result = self.app.post('/v1.0/maintain/local-land-charge',
                               data=request_data,
                               headers=headers)

        self.assertEqual(result.status_code, 400)
        self.assertIn(
            'Invalid request. For more information check the logs for TraceID',
            result.data.decode())
        self.assertEqual(
            mock_current_app.logger.performance_platform.mock_calls, [])
コード例 #10
0
def get_all_statutory_provisions():
    current_app.logger.info("Get all statutory provisions.")

    selectable = request.args.get('selectable')

    if selectable is None:
        provisions = StatutoryProvision.query \
            .distinct(StatutoryProvision.title) \
            .order_by(StatutoryProvision.title) \
            .all()
    else:
        provisions = StatutoryProvision.query \
            .distinct(StatutoryProvision.title) \
            .filter(StatutoryProvision.selectable == selectable) \
            .order_by(StatutoryProvision.title) \
            .all()

    if provisions is None or len(provisions) == 0:
        raise ApplicationError("No provisions found.", 404, 404)

    provisions_json = []
    for provision in provisions:
        provisions_json.append(provision.title)

    return Response(response=json.dumps(provisions_json),
                    mimetype="application/json")
コード例 #11
0
def get_current_timestamp():
    cur = None
    conn = None
    try:
        conn = psycopg2.connect(current_app.config['SQLALCHEMY_DATABASE_URI'])
        cur = conn.cursor()
        cur.execute("SELECT CURRENT_TIMESTAMP;")
        result = cur.fetchone()
        return result[0]
    except psycopg2.DataError as e:
        raise ApplicationError('Input data error: ' + str(e),
                               'DB',
                               http_code=400)
    except (psycopg2.OperationalError, psycopg2.ProgrammingError) as e:
        raise ApplicationError('Database error: ' + str(e),
                               'DB',
                               http_code=400)
    finally:
        if cur:
            cur.close()
        if conn:
            conn.close()
コード例 #12
0
def update_statutory_provisions(stat_prov):
    current_app.logger.info(
        "Update statutory provision {0}.".format(stat_prov))

    request_body = request.get_json()

    try:
        validate(request_body, STAT_PROV_SCHEMA)
    except ValidationError as e:
        current_app.logger.info(
            "Update statutory provision - payload failed validation")
        raise ApplicationError(e.message, 400, 400)

    title = request_body["title"]
    selectable = request_body["selectable"]

    provision = StatutoryProvision.query.filter(
        func.lower(StatutoryProvision.title) == func.lower(stat_prov)).first()

    if provision is None:
        message = "Statutory provision '{0}' does not exist.".format(stat_prov)
        current_app.logger.info(message)
        raise ApplicationError(message, 404, 404)

    if provision.title.lower() != title.lower():
        inuse = StatutoryProvision.query.filter(
            func.lower(StatutoryProvision.title) == func.lower(title)).first()
        if inuse is not None:
            message = "Statutory provision with name '{0}' already exists.".format(
                title)
            current_app.logger.info(message)
            raise ApplicationError(message, 409, 409)

    provision.title = title
    provision.selectable = selectable
    db.session.commit()

    return "", 204
コード例 #13
0
def delete_instrument(instrument_name):
    current_app.logger.info("Delete instruments.")

    instrument = Instruments.query.filter(func.lower(Instruments.name) == func.lower(instrument_name)).first()

    if instrument is None:
        message = "Instrument '{0}' does not exist.".format(instrument_name)
        current_app.logger.info(message)
        raise ApplicationError(message, 404, 404)

    Instruments.query.filter(Instruments.id == instrument.id).delete()
    db.session.commit()

    return "", 204
コード例 #14
0
def before_request():
    # Sets the transaction trace id into the global object if it has been provided in the HTTP header from the caller.
    # Generate a new one if it has not. We will use this in log messages.
    g.trace_id = request.headers.get('X-Trace-ID', uuid.uuid4().hex)
    # We also create a session-level requests object for the app to use with the header pre-set, so other APIs will
    # receive it. These lines can be removed if the app will not make requests to other LR APIs!
    g.requests = requests.Session()
    g.requests.headers.update({'X-Trace-ID': g.trace_id})

    # Don't check for a JWT on health endpoints
    if '/health' in request.path:
        return

    if 'Authorization' not in request.headers:
        raise ApplicationError("Missing Authorization header", "AUTH1", 401)

    try:
        validate(app.config['AUTHENTICATION_API_URL'] + '/authentication/validate',
                 request.headers['Authorization'], g.requests)
    except ValidationFailure as fail:
        raise ApplicationError(fail.message, "AUTH1", 401)

    g.requests.headers.update({'Authorization': request.headers['Authorization']})
コード例 #15
0
def get_all_instruments():
    current_app.logger.info("Get all instruments.")
    instruments = Instruments.query \
        .distinct(Instruments.name) \
        .order_by(Instruments.name) \
        .all()

    if instruments is None or len(instruments) == 0:
        raise ApplicationError("No instruments found.", 404, 404)

    instruments_json = []
    for instrument in instruments:
        instruments_json.append(instrument.name)

    return Response(response=json.dumps(instruments_json), mimetype="application/json")
コード例 #16
0
def encode_base_31(charge_id):
    """Encodes the given base 10 charge_id into a base 31 string.

    Throws ApplicationError if charge_id is less than ChargeId.FLOOR or greater than ChargeId.CEILING.
    """
    if charge_id < ChargeId.FLOOR or charge_id > ChargeId.CEILING:
        raise ApplicationError('The given charge id ({}) is less than the allowed floor ({}), or greater than the '
                               'allowed ceiling ({})'.format(charge_id, ChargeId.FLOOR, ChargeId.CEILING), 500)

    encoded = ''
    while charge_id > 0:
        charge_id, remainder = divmod(charge_id, 31)
        encoded = ChargeId.CHARACTERS[remainder] + encoded

    return encoded
コード例 #17
0
def delete_statutory_provisions(stat_prov):
    current_app.logger.info(
        "Delete statutory provision {0}.".format(stat_prov))

    provision = StatutoryProvision.query.filter(
        func.lower(StatutoryProvision.title) == func.lower(stat_prov)).first()

    if provision is None:
        message = "Statutory provision '{0}' does not exist.".format(stat_prov)
        current_app.logger.info(message)
        raise ApplicationError(message, 404, 404)

    StatutoryProvision.query.filter(
        StatutoryProvision.id == provision.id).delete()
    db.session.commit()

    return "", 204
コード例 #18
0
def update_sub_category(category, sub_category):
    current_app.logger.info("Update category")

    request_body = request.get_json()

    try:
        validate(request_body, CATEGORY_SCHEMA)
    except ValidationError as e:
        current_app.logger.info("Update category - payload failed validation")
        raise ApplicationError(e.message, 400, 400)

    name = request_body["name"]
    display_name = request_body["display-name"]
    display_order = request_body["display-order"]
    permission = request_body["permission"]
    provisions = request_body["provisions"]
    instruments = request_body["instruments"]

    try:
        parent = Categories.query \
            .filter(func.lower(Categories.name) == func.lower(category)) \
            .filter(Categories.parent_id == None) \
            .first()  # noqa: E711 - Ignore "is None vs ==", is None does not produce valid sql in sqlAlchmey

        if parent is None:
            message = "Category '{0}' does not exist.".format(category)
            current_app.logger.info(message)
            raise ApplicationError(message, 404, 404)

        sub_category_obj = Categories.query \
            .filter(func.lower(Categories.name) == func.lower(sub_category)) \
            .filter(Categories.parent_id == parent.id) \
            .first()

        if sub_category_obj is None:
            raise ApplicationError("Sub-category '{0}' not found for parent '{1}'"
                                   .format(sub_category, category), 404, 404)

        if sub_category_obj.name.lower() != sub_category.lower():
            inuse = Categories.query \
                .filter(func.lower(Categories.name) == func.lower(sub_category)) \
                .filter(Categories.parent_id == parent.id) \
                .first()
            if inuse is not None:
                message = "sub-category with the name '{0}' already exists under {1}.".format(name, category)
                current_app.logger.info(message)
                raise ApplicationError(message, 409, 409)

        sub_category_obj.name = name
        sub_category_obj.display_name = display_name
        sub_category_obj.permission = permission
        sub_category_obj.display_order = display_order

        CategoryInstrumentsMapping.query.filter(CategoryInstrumentsMapping.category_id == sub_category_obj.id).delete()
        CategoryStatProvisionMapping.query.filter(
            CategoryStatProvisionMapping.category_id == sub_category_obj.id).delete()

        for prov in provisions:
            provision = StatutoryProvision.query \
                .filter(func.lower(StatutoryProvision.title) == func.lower(prov)).first()
            if provision is None:
                message = "Statutory provision '{0}' does not exist.".format(prov)
                current_app.logger.info(message)
                raise ApplicationError(message, 404, 404)
            mapping = CategoryStatProvisionMapping(sub_category_obj.id, provision.id)
            db.session.add(mapping)

        for instrument in instruments:
            exists = Instruments.query.filter(func.lower(Instruments.name) == func.lower(instrument)).first()
            if exists is None:
                message = "Instrument '{0}' does not exist.".format(instrument)
                current_app.logger.info(message)
                raise ApplicationError(message, 404, 404)
            mapping = CategoryInstrumentsMapping(sub_category_obj.id, exists.id)
            db.session.add(mapping)

        db.session.commit()

        return "", 204

    except Exception:
        current_app.logger.info("Rolling back transaction")
        db.session.rollback()
        raise