

--
-- ### Verification of a small invoice model
--
--

drop if exists procedure calctax;
@
create procedure calctax( netto in decimal(10,2), taxquote in decimal(10,2) ) return decimal(10,2)
begin
   var ptax decimal(10,4);
   var pnetto decimal(10,4);

   :pnetto = :netto;
   :ptax =  :taxquote * :pnetto;

   if :ptax - :netto * :taxquote >= (decimal)0.0050
   then
      return :netto  * :taxquote + (decimal)0.01;
   end;
   return :netto * :taxquote;
end;
@

drop if exists table company;
create table company ( cpid int, cpname string(20), debnr int);


drop if exists table invoice;
create table invoice(invid int not null,
       invnr string(20) not null,
       invdate datetime not null,
       invstatus string(20) not null,
       taxquote int not null,
       cpid int not null);

create primary btree on invoice(invid);

drop if exists table invoicepos;
create table invoicepos(posid int not null,
       posname string(20) not null,
       numpos int not null,
       amount decimal(10,2) not null,
       invid int not null);


create primary btree on invoicepos(posid);


drop if exists table debitor;
create table debitor(debnr int not null,
       debname string(20) not null);


insert into company values ( 1, 'Walter GmbH', 4711);
insert into company values ( 2, 'Hugo AG', 4712);
insert into company values ( 3, 'Frön Limited', 4713);

insert into debitor values ( 4711, 'Deb1');
insert into debitor values ( 4712, 'Deb2');
insert into debitor values ( 4713, 'Deb3');


insert into invoice ( invid, invnr, invdate, invstatus, taxquote, cpid ) values ( 1, 'RE-4711', '01.07.2025', 'BOOKED', 19, 1);
insert into invoicepos ( posid, posname, numpos, amount, invid ) values ( 1, 'A position', 1, (decimal)34.98, 1);
insert into invoicepos ( posid, posname, numpos, amount, invid ) values ( 2, 'B position', 2, (decimal)12.28, 1);


insert into invoice ( invid, invnr, invdate, invstatus, taxquote, cpid ) values ( 2, 'RE-4712', '14.07.2025', 'REMIND', 19, 2);
insert into invoicepos ( posid, posname, numpos, amount, invid ) values ( 3, 'Piece of bread', 1, (decimal)4.98, 2);
insert into invoicepos ( posid, posname, numpos, amount, invid ) values ( 4, 'Wine', 2, (decimal)11.18, 2);


insert into invoice ( invid, invnr, invdate, invstatus, taxquote, cpid ) values ( 3, 'RE-4713', '14.07.2025', 'EDIT', 19, 3);
insert into invoicepos ( posid, posname, numpos, amount, invid ) values ( 5, 'More pos', 1, (decimal)14.81, 3);
insert into invoicepos ( posid, posname, numpos, amount, invid ) values ( 6, 'Another pos', 2, (decimal)1.88, 3);


--------------------
-- invoice views ---
--------------------

drop if exists view invoicebaseview;
create view invoicebaseview as
select
    inv.invid as invid,
    inv.invnr as invnr,
    inv.invdate as invdate,
    ( select sum(amount * numpos) from invoicepos pos where pos.invid = inv.invid ) as netto,
    inv.taxquote as taxquote,
    inv.invstatus as invstatus,
    inv.cpid as cpid,
    cp.cpname as cpname,
    cp.cpname | deb.debname as cpdeb
from invoice inv
inner join company cp on inv.cpid = cp.cpid
inner join debitor deb on cp.debnr = deb.debnr;

drop if exists view invoiceview;
create view invoiceview as
select
    base.invid as invid,
    base.invnr as invnr,
    case when base.netto is not null then base.netto else (decimal)0.00 end as netto,

    case when base.netto is not null
       then (decimal)0.00 + calctax( base.netto, base.taxquote / 100.0 )
       else (decimal)0.00 end as tax,
    case when base.netto is not null
       then base.netto + calctax( base.netto, base.taxquote / 100.0 )
       else (decimal)0.00 end as brutto,

    base.invdate as invdate,
    base.invstatus as invstatus,
    base.cpid as cpid,
    base.cpname as cpname,
    base.cpdeb as cpdeb
from invoicebaseview base;

@
create procedure checkQuery001(msg out string(20)) return string(10)
begin
    var res string(10) = 'ERROR';
    var i int;

    cursor xCur as select count(*) from invoiceview where invstatus = 'BOOKED' or invstatus = 'REMIND';

    if fetch xCur into ( :i )
    then
       if :i = 2
       then
          :res = 'ok';
       end;
    end;
    close xCur;

    :msg = 'Number of invoices is 2';

    return :res;
end;
@

@
create procedure checkQuery002(msg out string(20)) return string(10)
begin
    var res string(10) = 'ERROR';
    var netto decimal(10,2);

    cursor xCur as select netto from invoiceview where invid = 1;

    if fetch xCur into ( :netto )
    then
       if :netto = (decimal)59.54
       then
          :res = 'ok';
       end;
    end;
    close xCur;

    :msg = 'Netto amount for invid 1 is ' | :netto;

    return :res;
end;
@

@
create procedure checkQuery003(msg out string(20)) return string(10)
begin
    var res string(10) = 'ERROR';
    var brutto decimal(10,2);

    cursor xCur as select brutto from invoiceview where invid = 1;

    if fetch xCur into ( :brutto )
    then
       if :brutto = (decimal)70.85
       then
          :res = 'ok';
       end;
    end;
    close xCur;

    :msg = 'Brutto amount for invid 1 is ' | :brutto;

    return :res;
end;
@

@
create procedure checkQuery004(msg out string(20)) return string(10)
begin
    var res string(10) = 'ERROR';
    var invid int;

    cursor xCur as select invid from invoiceview where lower(cpdeb) like '%limiteddeb%';

    if fetch xCur into ( :invid )
    then
       if :invid = 3
       then
          :res = 'ok';
       end;
    end;
    close xCur;

    :msg = 'Invid for cp deb pattern ' | :invid;

    return :res;
end;
@



:r = call checkQuery001(:msg);
insert into checklog values ('GATE-A', :msg, :r);

:r = call checkQuery002(:msg);
insert into checklog values ('GATE-A', :msg, :r);

:r = call checkQuery003(:msg);
insert into checklog values ('GATE-A', :msg, :r);

:r = call checkQuery004(:msg);
insert into checklog values ('GATE-A', :msg, :r);


-- print :r;
-- print :msg;


drop procedure calctax;
drop procedure checkQuery001;
drop procedure checkQuery002;
drop procedure checkQuery003;
drop procedure checkQuery004;

drop view invoiceview;
drop view invoicebaseview;

drop table company;
drop table invoice;
drop table invoicepos;
