-- Deploy camper:add_invoice to pg
-- requires: roles
-- requires: schema_camper
-- requires: invoice
-- requires: company
-- requires: currency
-- requires: parse_price
-- requires: new_invoice_product
-- requires: tax
-- requires: invoice_product
-- requires: invoice_product_product
-- requires: invoice_product_tax
-- requires: next_invoice_number

begin;

set search_path to camper, public;

create or replace function add_invoice(company integer, invoice_date date, contact_id integer, notes text, payment_method_id integer, products new_invoice_product[]) returns uuid as
$$
declare
	iid integer;
	pslug uuid;
	product new_invoice_product;
	ccode text;
	ipid integer;
begin
	insert into invoice (company_id, invoice_number, invoice_date, contact_id, notes, currency_code, payment_method_id)
	select company_id
	     , next_invoice_number(add_invoice.company, invoice_date)
	     , invoice_date
	     , contact_id
	     , notes
	     , currency_code
	     , add_invoice.payment_method_id
	from company
	where company.company_id = add_invoice.company
	returning invoice_id, slug, currency_code
	into iid, pslug, ccode;

	foreach product in array products
	loop
		insert into invoice_product (invoice_id, name, description, price, quantity, discount_rate)
		select iid
		     , product.name
		     , coalesce(product.description, '')
		     , parse_price(product.price, currency.decimal_digits)
		     , product.quantity
		     , product.discount_rate
		from currency
		where currency_code = ccode
		returning invoice_product_id
		into ipid;

		if product.product_id is not null then
			insert into invoice_product_product (invoice_product_id, product_id)
			values (ipid, product.product_id);
		end if;

		insert into invoice_product_tax (invoice_product_id, tax_id, tax_rate)
		select ipid, tax_id, tax.rate
		from tax
		join unnest(product.tax) as ptax(tax_id) using (tax_id);
	end loop;

	return pslug;
end;
$$
language plpgsql;

revoke execute on function add_invoice(integer, date, integer, text, integer, new_invoice_product[]) from public;
grant execute on function add_invoice(integer, date, integer, text, integer, new_invoice_product[]) to employee;
grant execute on function add_invoice(integer, date, integer, text, integer, new_invoice_product[]) to admin;

commit;
