Building serverless Azure Functions with custom fields in Bricknode Financial Systems

November 7, 2019. Stefan Willebrand.

A neat new cost efficient way to build smaller functions that can be consumed through simple HttpRequests are Azure Functions. Instead of building and hosting a whole web application it is now possible to build a function that can be triggered through a HttpRequest and then perform a number of things.

Ideally when building some financial functions we don’t want to set up new databases to keep our data and thanks to the Custom Fields within Bricknode Financial Systems (“BFS”) we can just create new fields ad-hoc and keep our data in BFS.

In this example we wanted to build a function that took care of closing a share offering in BFS once a certain level of subscriptions for the offer had been reached.

To start with we used the UpdateInstruments function to create a custom field to hold the number of shares that would be the limit of the offer.

First we have a function to update the instrument with custom fields and the status of the instrument.

private static async Task<UpdateInstrumentResponse> UpdateInstrument(UpdateInstrument[] entities)
{
    return await Client.UpdateInstrumentsAsync(new UpdateInstrumentsRequest
    {
        Credentials = Credentials,
        identify = BfsIdentifier,
        Fields = new UpdateInstrumentFields
        {
            CustomFields = true,
            InstrumentStatus = true
        },
        Entities = entities
    });
}

Next, we will set the custom field to 1000 shares and we name the custom field “ShareLimit”.

private static async Task CreateAndSetCustomField(Guid instrumentId)
{
    var response = await UpdateInstrument(new UpdateInstrument[]
    {
        new UpdateInstrument
        {
            BrickId = instrumentId,
            CustomFields = new CustomField[]
            {
                new CustomField
                {
                    FieldName = "ShareLimit",
                    Value = "1000"
                }
            }
        }
    });
}

Creating, updating and deleting custom fields can also be done fully in the GUI of BFS where each object supports a collection of custom fields.

In the Azure Function we can now calculate how many shares are subscribed for each time a new subscription is posted on our onboarding form which we can collect with the following function that use GetSubscriptionOrders.

private static async Task<GetSubscriptionOrderResponse> GetSubscriptionOrders(Guid instrumentId)
{
    return await Client.GetSubscriptionOrdersAsync(new GetSubscriptionOrderRequest
    {
        Credentials = Credentials,
        identify = BfsIdentifier,
        Args = new GetSubscriptionOrderArgs
        {
            BrickIds = new []{instrumentId},
            States = new[] {"Created"}
        },
        Fields = new GetSubscriptionOrderFields
        {
            BrickId = true,
            InstrumentAmount = true
        }
    });
}

private static async Task<decimal> CalculateSubscriptionVolume(Guid instrumentId)
{
    var response = await GetSubscriptionOrders(instrumentId);

    return response.Result.Sum(sum => sum.InstrumentAmount);
}

Now we need to compare the subscribed volume to the limit amount that we entered in the custom field.

First we need a function to get the instrument details.

private static async Task<GetInstrumentsResponse> GetInstrumentsById(Guid instrumentId)
{
    return await Client.GetInstrumentsAsync(new GetInstrumentsRequest()
    {
        Credentials = Credentials,
        identify = BfsIdentifier,
        Args = new GetInstrumentsArgs()
        {
            BrickIds = new Guid[] {instrumentId}
        },
        Fields = new GetInstrumentsFields()
        {
            BrickId = true,
            InstrumentType = true,
            Name = true,
            CustomFields = true
        }
    });
}
private static async Task EvaluateSubscriptionStatus(Guid instrumentId)
{
    var instrument = await GetInstrumentsById(instrumentId);

    var subscriptionVolumeLimit = Decimal.Parse(instrument.Result.First().CustomFields
        .First(t => t.FieldName == "ShareLimit").Value);

    var subscribedVolume = await CalculateSubscriptionVolume(instrumentId);

    if (subscribedVolume >= subscriptionVolumeLimit)
    {
        await CloseInstrument(instrumentId);
    }

}

Finally we can change the status of the instrument so that it is not open for further subscriptions by updating the status to Closed.

private static async Task CloseInstrument(Guid instrumentId)
{
    var response = await UpdateInstrument(new UpdateInstrument[]
    {
        new UpdateInstrument
        {
            BrickId = instrumentId,
            InstrumentStatus = 3
        }
    });
}