Saturday, 22 May 2021

VAT's in it for me? - or I call my layer.

 - or a shout-out to the various services of apilayer.com



Sorry about the intended pun in the title - but it will all make sense.

Have you ever wanted to know the various VAT rates in the EU - no? - well neither have I, because it might put me in a bad mood, but it fits the intended pun for the post, and I also wanted to show how it is done from from Delphi.

The mother company of Embarcadero, Idera acquired another company early this year - this time apilayer.com, which provides numerous "simple" cloud-based API services - among these are:

  • IP geolocation and reverse lookup
  • Language detection
  • Mail address validation
  • Phone number validation
  • Flight tracking
  • Currency conversion and rates (including crypto currency)
  • Weather data and forecast
  • News, Headline and Stock apis
  • Conversion PDF and scraping
But go to https://apilayer.com/, and read more about their various layers and tiers for these.

We will in this short demo look at the vatlayer - which does EU VAT stuff.

So I started by signing up for the free tier on https://vatlayer.com/ - which gives you an API access key and access to a dashboard. As always do not share the access key - just saying.

Now you can fire up Delphi, create a new application and either use the REST Debugger or just manually throw in the REST component or create runtime - what you prefer.

I just threw in a edit control and a couple of memos and buttons, as seem above. And then I added an parameter on the RESTClient with the access_key - since I wanted to clear the request parameters on the RESTRequest, but keep the access_key. And set the BaseURL property to http://apilayer.net/api.

I just took two of the methods/resources from https://vatlayer.com/documentation - so the VAT lookup button looks like this:

var
  json: TJSONValue;
begin
  Memo1.Clear;
  RESTRequest1.Method := rmGET;
  RESTRequest1.Resource := 'validate';
  RESTRequest1.Params.Clear;
  RESTRequest1.AddParameter('vat_number', LabeledEdit2.Text, pkGETorPOST);
  RESTRequest1.Execute;
  if RESTResponse1.StatusCode=200 then
  begin
    json := RESTResponse1.JSONValue;
    Memo1.Lines.Add(json.GetValue<string>('company_name'));
    Memo1.Lines.Add(json.GetValue<string>('company_address'));
  end;
end;

..and the VAT rates for HU (since they have a higher VAT rate than DK :D) button looks like this:

var
  json: TJSONValue;
begin
  Memo2.Clear;
  RESTRequest1.Method := rmGET;
  RESTRequest1.Resource := 'rate';
  RESTRequest1.Params.Clear;
  RESTRequest1.AddParameter('country_code', 'HU', pkGETorPOST);
  RESTRequest1.Execute;
  if RESTResponse1.StatusCode=200 then
  begin
    json := RESTResponse1.JSONValue;
    Memo2.Lines.Add(json.Format());
  end;
end;

There nice twists to these - by IP address or get list of rate types - and if combining these services by apilayer.com - I could make a speeding white-van "whistle-blower" mobile app - since all company owned registered vehicles in DK - need to have their VAT numbers on their fleet.

So I could lookup the company and their address, get their phone number by a different api layer - and then call and tell on them - MUHAAHAAAHAA (evil laughter)

..or maybe I should just create something useful and fun.

And the best part about writing this post, I now learned that Denmark has only the second highest VAT rate in EU :D

/Enjoy




Monday, 15 February 2021

Closing in on Modal Jump Lists

- or getting a WM_SYSCOMMAND to a modal dialog.

An idea that initially seemed clever, has been haunting me a bit lately - I did put a modal dialog into a project before the main Application block (Initialize .. Run). Shame on me.

So the code looks similar to like this:

if (TfrmLaunchSetting.Execute = mrOK) then
begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.Title := 'MyApplication';
  Application.CreateForm(TfrmMain, frmMain);
  Application.Run;
end;

and the TFrmLaunchSetting.Execute is just a class function returning the ModalResult, from its ShowModal.

But here comes the issue at hand - the Close Window in the task bars Jump List sends a WM_SYSCOMMAND that goes to the system menu in the main window - but if a modal form is shown the main window is disabled - and in this case I do not even have a main form yet.

So TApplication.HookMainWindow to the rescue - that would enable me to intercept messages sent to the main form - and act upon these.

So in the FormCreate of my modal dialog I hook the my hook function up like this:

Application.HookMainWindow(AppHookFunc);

And on FormDestroy I do the following:

Application.UnHookMainWindow(AppHookFunc);

The AppHookFunc goes as follows:

function TfrmLaunchSetting.AppHookFunc(var Message: TMessage): Boolean;
begin
  Result := False;
  if Message.Msg = WM_SYSCOMMAND then
  begin
    PostMessage(Handle, WM_CLOSE, 0, 0);
    Result := True;
  end;
end;

This way modal dialogs can react to Windows messages that normally be intended for the main form.

There are probably side-effects - but the issue at hand is solved - for now?

BTW: Yesterday was Delphi 26th birthday - I did not forget - but I am still wrapping up the present. Stay tuned.

/Enjoy