Compare commits
2 Commits
31ef3ea47a
...
f77f933e4a
Author | SHA1 | Date |
---|---|---|
jordi fita mas | f77f933e4a | |
jordi fita mas | 93e92cf62d |
|
@ -14,7 +14,7 @@ begin;
|
|||
|
||||
set search_path to numerus, public;
|
||||
|
||||
create or replace function add_invoice(company_id integer, invoice_number text, invoice_date date, contact_id integer, notes text, products new_invoice_product[]) returns uuid as
|
||||
create or replace function add_invoice(company_id integer, invoice_number text, invoice_date date, contact_id integer, notes text, payment_method_id integer, products new_invoice_product[]) returns uuid as
|
||||
$$
|
||||
declare
|
||||
iid integer;
|
||||
|
@ -27,13 +27,14 @@ begin
|
|||
invoice_number = next_invoice_number(company_id, invoice_date);
|
||||
end if;
|
||||
|
||||
insert into invoice (company_id, invoice_number, invoice_date, contact_id, notes, currency_code)
|
||||
insert into invoice (company_id, invoice_number, invoice_date, contact_id, notes, currency_code, payment_method_id)
|
||||
select company.company_id
|
||||
, invoice_number
|
||||
, invoice_date
|
||||
, contact_id
|
||||
, notes
|
||||
, currency_code
|
||||
, add_invoice.payment_method_id
|
||||
from company
|
||||
where company.company_id = add_invoice.company_id
|
||||
returning invoice_id, slug, currency_code
|
||||
|
@ -65,8 +66,8 @@ end;
|
|||
$$
|
||||
language plpgsql;
|
||||
|
||||
revoke execute on function add_invoice(integer, text, date, integer, text, new_invoice_product[]) from public;
|
||||
grant execute on function add_invoice(integer, text, date, integer, text, new_invoice_product[]) to invoicer;
|
||||
grant execute on function add_invoice(integer, text, date, integer, text, new_invoice_product[]) to admin;
|
||||
revoke execute on function add_invoice(integer, text, date, integer, text, integer, new_invoice_product[]) from public;
|
||||
grant execute on function add_invoice(integer, text, date, integer, text, integer, new_invoice_product[]) to invoicer;
|
||||
grant execute on function add_invoice(integer, text, date, integer, text, integer, new_invoice_product[]) to admin;
|
||||
|
||||
commit;
|
||||
|
|
|
@ -18,6 +18,7 @@ create table invoice (
|
|||
contact_id integer not null references contact,
|
||||
invoice_status text not null default 'created' references invoice_status,
|
||||
notes text not null default '',
|
||||
payment_method_id integer not null references payment_method,
|
||||
currency_code text not null references currency,
|
||||
created_at timestamptz not null default current_timestamp
|
||||
);
|
||||
|
|
|
@ -121,19 +121,20 @@ func mustClose(closer io.Closer) {
|
|||
}
|
||||
|
||||
type invoice struct {
|
||||
Number string
|
||||
Slug string
|
||||
Date time.Time
|
||||
Invoicer taxDetails
|
||||
Invoicee taxDetails
|
||||
Notes string
|
||||
Products []*invoiceProduct
|
||||
Subtotal string
|
||||
Taxes [][]string
|
||||
TaxClasses []string
|
||||
HasDiscounts bool
|
||||
Total string
|
||||
LegalDisclaimer string
|
||||
Number string
|
||||
Slug string
|
||||
Date time.Time
|
||||
Invoicer taxDetails
|
||||
Invoicee taxDetails
|
||||
Notes string
|
||||
PaymentInstructions string
|
||||
Products []*invoiceProduct
|
||||
Subtotal string
|
||||
Taxes [][]string
|
||||
TaxClasses []string
|
||||
HasDiscounts bool
|
||||
Total string
|
||||
LegalDisclaimer string
|
||||
}
|
||||
|
||||
type taxDetails struct {
|
||||
|
@ -164,7 +165,7 @@ func mustGetInvoice(ctx context.Context, conn *Conn, company *Company, slug stri
|
|||
}
|
||||
var invoiceId int
|
||||
var decimalDigits int
|
||||
if notFoundErrorOrPanic(conn.QueryRow(ctx, "select invoice_id, decimal_digits, invoice_number, invoice_date, notes, business_name, vatin, phone, email, address, city, province, postal_code, to_price(subtotal, decimal_digits), to_price(total, decimal_digits) from invoice join contact using (contact_id) join invoice_amount using (invoice_id) join currency using (currency_code) where invoice.slug = $1", slug).Scan(&invoiceId, &decimalDigits, &inv.Number, &inv.Date, &inv.Notes, &inv.Invoicee.Name, &inv.Invoicee.VATIN, &inv.Invoicee.Phone, &inv.Invoicee.Email, &inv.Invoicee.Address, &inv.Invoicee.City, &inv.Invoicee.Province, &inv.Invoicee.PostalCode, &inv.Subtotal, &inv.Total)) {
|
||||
if notFoundErrorOrPanic(conn.QueryRow(ctx, "select invoice_id, decimal_digits, invoice_number, invoice_date, notes, instructions, business_name, vatin, phone, email, address, city, province, postal_code, to_price(subtotal, decimal_digits), to_price(total, decimal_digits) from invoice join payment_method using (payment_method_id) join contact using (contact_id) join invoice_amount using (invoice_id) join currency using (currency_code) where invoice.slug = $1", slug).Scan(&invoiceId, &decimalDigits, &inv.Number, &inv.Date, &inv.Notes, &inv.PaymentInstructions, &inv.Invoicee.Name, &inv.Invoicee.VATIN, &inv.Invoicee.Phone, &inv.Invoicee.Email, &inv.Invoicee.Address, &inv.Invoicee.City, &inv.Invoicee.Province, &inv.Invoicee.PostalCode, &inv.Subtotal, &inv.Total)) {
|
||||
return nil
|
||||
}
|
||||
if err := conn.QueryRow(ctx, "select business_name, vatin, phone, email, address, city, province, postal_code, legal_disclaimer from company where company_id = $1", company.Id).Scan(&inv.Invoicer.Name, &inv.Invoicer.VATIN, &inv.Invoicer.Phone, &inv.Invoicer.Email, &inv.Invoicer.Address, &inv.Invoicer.City, &inv.Invoicer.Province, &inv.Invoicer.PostalCode, &inv.LegalDisclaimer); err != nil {
|
||||
|
@ -290,7 +291,7 @@ func HandleAddInvoice(w http.ResponseWriter, r *http.Request, _ httprouter.Param
|
|||
mustRenderNewInvoiceForm(w, r, form)
|
||||
return
|
||||
}
|
||||
slug := conn.MustGetText(r.Context(), "", "select add_invoice($1, $2, $3, $4, $5, $6)", company.Id, form.Number, form.Date, form.Customer, form.Notes, NewInvoiceProductArray(form.Products))
|
||||
slug := conn.MustGetText(r.Context(), "", "select add_invoice($1, $2, $3, $4, $5, $6, $7)", company.Id, form.Number, form.Date, form.Customer, form.Notes, form.PaymentMethod, NewInvoiceProductArray(form.Products))
|
||||
http.Redirect(w, r, companyURI(company, "/invoices/"+slug), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
|
@ -427,9 +428,9 @@ func (form *invoiceForm) Update() {
|
|||
|
||||
func (form *invoiceForm) AddProducts(ctx context.Context, conn *Conn, productsId []string) {
|
||||
index := len(form.Products)
|
||||
taxOptions := mustGetTaxOptions(ctx, conn, form.company)
|
||||
rows := conn.MustQuery(ctx, "select product_id, name, description, to_price(price, decimal_digits), 1 as quantity, 0 as discount, array_remove(array_agg(tax_id), null) from product join company using (company_id) join currency using (currency_code) left join product_tax using (product_id) where product_id = any ($1) group by product_id, name, description, price, decimal_digits", productsId)
|
||||
defer rows.Close()
|
||||
taxOptions := mustGetTaxOptions(ctx, conn, form.company)
|
||||
for rows.Next() {
|
||||
product := newInvoiceProductForm(index, form.company, form.locale, taxOptions)
|
||||
if err := rows.Scan(product.ProductId, product.Name, product.Description, product.Price, product.Quantity, product.Discount, product.Tax); err != nil {
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
begin;
|
||||
|
||||
drop function if exists numerus.add_invoice(integer, text, date, integer, text, numerus.new_invoice_product[]);
|
||||
drop function if exists numerus.add_invoice(integer, text, date, integer, text, integer, numerus.new_invoice_product[]);
|
||||
|
||||
commit;
|
||||
|
|
|
@ -9,15 +9,15 @@ select plan(17);
|
|||
|
||||
set search_path to auth, numerus, public;
|
||||
|
||||
select has_function('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'new_invoice_product[]']);
|
||||
select function_lang_is('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'new_invoice_product[]'], 'plpgsql');
|
||||
select function_returns('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'new_invoice_product[]'], 'uuid');
|
||||
select isnt_definer('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'new_invoice_product[]']);
|
||||
select volatility_is('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'new_invoice_product[]'], 'volatile');
|
||||
select function_privs_are('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'new_invoice_product[]'], 'guest', array []::text[]);
|
||||
select function_privs_are('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'new_invoice_product[]'], 'invoicer', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'new_invoice_product[]'], 'admin', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'new_invoice_product[]'], 'authenticator', array []::text[]);
|
||||
select has_function('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'integer', 'new_invoice_product[]']);
|
||||
select function_lang_is('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'integer', 'new_invoice_product[]'], 'plpgsql');
|
||||
select function_returns('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'integer', 'new_invoice_product[]'], 'uuid');
|
||||
select isnt_definer('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'integer', 'new_invoice_product[]']);
|
||||
select volatility_is('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'integer', 'new_invoice_product[]'], 'volatile');
|
||||
select function_privs_are('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'integer', 'new_invoice_product[]'], 'guest', array []::text[]);
|
||||
select function_privs_are('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'integer', 'new_invoice_product[]'], 'invoicer', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'integer', 'new_invoice_product[]'], 'admin', array ['EXECUTE']);
|
||||
select function_privs_are('numerus', 'add_invoice', array ['integer', 'text', 'date', 'integer', 'text', 'integer', 'new_invoice_product[]'], 'authenticator', array []::text[]);
|
||||
|
||||
|
||||
set client_min_messages to warning;
|
||||
|
@ -81,37 +81,37 @@ values (12, 1, 'Contact 2.1', 'XX555', '', '777-777-777', 'c@c', '', '', '', '',
|
|||
|
||||
|
||||
select lives_ok(
|
||||
$$ select add_invoice(1, 'INV001', '2023-02-15', 12, 'Notes 1', '{"(7,Product 1,Description 1,12.24,2,0.0,{4})"}') $$,
|
||||
$$ select add_invoice(1, 'INV001', '2023-02-15', 12, 'Notes 1', 111, '{"(7,Product 1,Description 1,12.24,2,0.0,{4})"}') $$,
|
||||
'Should be able to insert an invoice for the first company with a product'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ select add_invoice(1, 'INV002', '2023-02-16', 13, 'Notes 2', '{"(7,Product 1 bis,Description 1 bis,33.33,1,0.50,\"{4,3}\")","(8,Product 2,Description 2,24.00,3,0.75,{})"}') $$,
|
||||
$$ select add_invoice(1, 'INV002', '2023-02-16', 13, 'Notes 2', 111, '{"(7,Product 1 bis,Description 1 bis,33.33,1,0.50,\"{4,3}\")","(8,Product 2,Description 2,24.00,3,0.75,{})"}') $$,
|
||||
'Should be able to insert a second invoice for the first company with two product'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ select add_invoice(2, 'INV101', '2023-02-14', 15, 'Notes 3', '{"(11,Product 4.3,,11.11,1,0.0,{6})"}') $$,
|
||||
$$ select add_invoice(2, 'INV101', '2023-02-14', 15, 'Notes 3', 222, '{"(11,Product 4.3,,11.11,1,0.0,{6})"}') $$,
|
||||
'Should be able to insert an invoice for the second company with a product'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ select add_invoice(1, NULL, '2023-03-15', 13, '', '{"(7,PA1,DA1,44.33,1,0.50,{})"}') $$,
|
||||
$$ select add_invoice(1, NULL, '2023-03-15', 13, '', 111, '{"(7,PA1,DA1,44.33,1,0.50,{})"}') $$,
|
||||
'Should be able to insert an invoice with an autogenerated number'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ select add_invoice(2, ' ', '2023-04-16', 14, '', '{"(11,PA2,DA2,55.33,10,0.75,{})"}') $$,
|
||||
$$ select add_invoice(2, ' ', '2023-04-16', 14, '', 222, '{"(11,PA2,DA2,55.33,10,0.75,{})"}') $$,
|
||||
'Should consider non-null, but otherwise empty numbers the same as null and autogenerate it'
|
||||
);
|
||||
|
||||
select bag_eq(
|
||||
$$ select company_id, invoice_number, invoice_date, contact_id, invoice_status, notes, currency_code, created_at from invoice $$,
|
||||
$$ values (1, 'INV001', '2023-02-15'::date, 12, 'created', 'Notes 1', 'EUR', current_timestamp)
|
||||
, (1, 'INV002', '2023-02-16'::date, 13, 'created', 'Notes 2', 'EUR', current_timestamp)
|
||||
, (2, 'INV101', '2023-02-14'::date, 15, 'created', 'Notes 3', 'USD', current_timestamp)
|
||||
, (1, 'F20230006', '2023-03-15'::date, 13, 'created', '', 'EUR', current_timestamp)
|
||||
, (2, 'INV056-23', '2023-04-16'::date, 14, 'created', '', 'USD', current_timestamp)
|
||||
$$ select company_id, invoice_number, invoice_date, contact_id, invoice_status, notes, payment_method_id, currency_code, created_at from invoice $$,
|
||||
$$ values (1, 'INV001', '2023-02-15'::date, 12, 'created', 'Notes 1', 111, 'EUR', current_timestamp)
|
||||
, (1, 'INV002', '2023-02-16'::date, 13, 'created', 'Notes 2', 111, 'EUR', current_timestamp)
|
||||
, (2, 'INV101', '2023-02-14'::date, 15, 'created', 'Notes 3', 222, 'USD', current_timestamp)
|
||||
, (1, 'F20230006', '2023-03-15'::date, 13, 'created', '', 111, 'EUR', current_timestamp)
|
||||
, (2, 'INV056-23', '2023-04-16'::date, 14, 'created', '', 222, 'USD', current_timestamp)
|
||||
$$,
|
||||
'Should have created all invoices'
|
||||
);
|
||||
|
|
|
@ -5,7 +5,7 @@ reset client_min_messages;
|
|||
|
||||
begin;
|
||||
|
||||
select plan(72);
|
||||
select plan(78);
|
||||
|
||||
set search_path to numerus, auth, public;
|
||||
|
||||
|
@ -75,6 +75,13 @@ select col_not_null('invoice', 'notes');
|
|||
select col_has_default('invoice', 'notes');
|
||||
select col_default_is('invoice', 'notes', '');
|
||||
|
||||
select has_column('invoice', 'payment_method_id');
|
||||
select col_is_fk('invoice', 'payment_method_id');
|
||||
select fk_ok('invoice', 'payment_method_id', 'payment_method', 'payment_method_id');
|
||||
select col_type_is('invoice', 'payment_method_id', 'integer');
|
||||
select col_not_null('invoice', 'payment_method_id');
|
||||
select col_hasnt_default('invoice', 'payment_method_id');
|
||||
|
||||
select has_column('invoice', 'currency_code');
|
||||
select col_is_fk('invoice', 'currency_code');
|
||||
select fk_ok('invoice', 'currency_code', 'currency', 'currency_code');
|
||||
|
@ -127,9 +134,9 @@ values (6, 2, 'Contact 1', 'XX555', '', '777-777-777', 'c@c', '', '', '', '', ''
|
|||
, (8, 4, 'Contact 2', 'XX666', '', '888-888-888', 'd@d', '', '', '', '', '', 'ES')
|
||||
;
|
||||
|
||||
insert into invoice (company_id, invoice_number, contact_id, currency_code)
|
||||
values (2, 'INV020001', 6, 'EUR')
|
||||
, (4, 'INV040001', 8, 'EUR')
|
||||
insert into invoice (company_id, invoice_number, contact_id, currency_code, payment_method_id)
|
||||
values (2, 'INV020001', 6, 'EUR', 222)
|
||||
, (4, 'INV040001', 8, 'EUR', 444)
|
||||
;
|
||||
|
||||
|
||||
|
@ -170,8 +177,8 @@ reset role;
|
|||
|
||||
|
||||
select throws_ok( $$
|
||||
insert into invoice (company_id, invoice_number, contact_id, currency_code)
|
||||
values (2, ' ', 6, 'EUR')
|
||||
insert into invoice (company_id, invoice_number, contact_id, currency_code, payment_method_id)
|
||||
values (2, ' ', 6, 'EUR', 222)
|
||||
$$,
|
||||
'23514', 'new row for relation "invoice" violates check constraint "invoice_number_not_empty"',
|
||||
'Should not allow invoice with blank number'
|
||||
|
|
|
@ -68,11 +68,11 @@ insert into contact (contact_id, company_id, business_name, vatin, trade_name, p
|
|||
values (7, 1, 'Contact', 'XX555', '', '777-777-777', 'c@c', '', '', '', '', '', 'ES')
|
||||
;
|
||||
|
||||
insert into invoice (invoice_id, company_id, invoice_number, invoice_date, contact_id, currency_code)
|
||||
values ( 8, 1, 'I1', current_date, 7, 'EUR')
|
||||
, ( 9, 1, 'I2', current_date, 7, 'EUR')
|
||||
, (10, 1, 'I3', current_date, 7, 'EUR')
|
||||
, (11, 1, 'I4', current_date, 7, 'EUR')
|
||||
insert into invoice (invoice_id, company_id, invoice_number, invoice_date, contact_id, currency_code, payment_method_id)
|
||||
values ( 8, 1, 'I1', current_date, 7, 'EUR', '111')
|
||||
, ( 9, 1, 'I2', current_date, 7, 'EUR', '111')
|
||||
, (10, 1, 'I3', current_date, 7, 'EUR', '111')
|
||||
, (11, 1, 'I4', current_date, 7, 'EUR', '111')
|
||||
;
|
||||
|
||||
insert into invoice_product (invoice_product_id, invoice_id, product_id, name, price, quantity, discount_rate)
|
||||
|
|
|
@ -112,9 +112,9 @@ values (6, 2, 'Contact 1', 'XX555', '', '777-777-777', 'c@c', '', '', '', '', ''
|
|||
, (8, 4, 'Contact 2', 'XX666', '', '888-888-888', 'd@d', '', '', '', '', '', 'ES')
|
||||
;
|
||||
|
||||
insert into invoice (invoice_id, company_id, invoice_number, contact_id, currency_code)
|
||||
values (10, 2, 'INV020001', 6, 'EUR')
|
||||
, (12, 4, 'INV040001', 8, 'EUR')
|
||||
insert into invoice (invoice_id, company_id, invoice_number, contact_id, currency_code, payment_method_id)
|
||||
values (10, 2, 'INV020001', 6, 'EUR', 222)
|
||||
, (12, 4, 'INV040001', 8, 'EUR', 444)
|
||||
;
|
||||
|
||||
insert into product (product_id, company_id, name, description, price)
|
||||
|
|
|
@ -68,11 +68,11 @@ insert into contact (contact_id, company_id, business_name, vatin, trade_name, p
|
|||
values (7, 1, 'Contact', 'XX555', '', '777-777-777', 'c@c', '', '', '', '', '', 'ES')
|
||||
;
|
||||
|
||||
insert into invoice (invoice_id, company_id, invoice_number, invoice_date, contact_id, currency_code)
|
||||
values ( 8, 1, 'I1', current_date, 7, 'EUR')
|
||||
, ( 9, 1, 'I2', current_date, 7, 'EUR')
|
||||
, (10, 1, 'I3', current_date, 7, 'EUR')
|
||||
, (11, 1, 'I4', current_date, 7, 'EUR')
|
||||
insert into invoice (invoice_id, company_id, invoice_number, invoice_date, contact_id, currency_code, payment_method_id)
|
||||
values ( 8, 1, 'I1', current_date, 7, 'EUR', 111)
|
||||
, ( 9, 1, 'I2', current_date, 7, 'EUR', 111)
|
||||
, (10, 1, 'I3', current_date, 7, 'EUR', 111)
|
||||
, (11, 1, 'I4', current_date, 7, 'EUR', 111)
|
||||
;
|
||||
|
||||
insert into invoice_product (invoice_product_id, invoice_id, product_id, name, price, quantity, discount_rate)
|
||||
|
|
|
@ -95,9 +95,9 @@ values ( 9, 2, 'Customer 1', 'XX555', '', '777-777-777', 'c1@e', '', '', '', '',
|
|||
, (10, 4, 'Customer 2', 'XX666', '', '888-888-888', 'c2@e', '', '', '', '', '', 'ES')
|
||||
;
|
||||
|
||||
insert into invoice (invoice_id, company_id, invoice_number, contact_id, currency_code)
|
||||
values (11, 2, 'INV001', 9, 'EUR')
|
||||
, (12, 4, 'INV002', 10, 'EUR')
|
||||
insert into invoice (invoice_id, company_id, invoice_number, contact_id, currency_code, payment_method_id)
|
||||
values (11, 2, 'INV001', 9, 'EUR', 222)
|
||||
, (12, 4, 'INV002', 10, 'EUR', 444)
|
||||
;
|
||||
|
||||
insert into invoice_product (invoice_product_id, invoice_id, product_id, name, price)
|
||||
|
|
|
@ -68,11 +68,11 @@ insert into contact (contact_id, company_id, business_name, vatin, trade_name, p
|
|||
values (7, 1, 'Contact', 'XX555', '', '777-777-777', 'c@c', '', '', '', '', '', 'ES')
|
||||
;
|
||||
|
||||
insert into invoice (invoice_id, company_id, invoice_number, invoice_date, contact_id, currency_code)
|
||||
values ( 8, 1, 'I1', current_date, 7, 'EUR')
|
||||
, ( 9, 1, 'I2', current_date, 7, 'EUR')
|
||||
, (10, 1, 'I3', current_date, 7, 'EUR')
|
||||
, (11, 1, 'I4', current_date, 7, 'EUR')
|
||||
insert into invoice (invoice_id, company_id, invoice_number, invoice_date, contact_id, currency_code, payment_method_id)
|
||||
values ( 8, 1, 'I1', current_date, 7, 'EUR', 111)
|
||||
, ( 9, 1, 'I2', current_date, 7, 'EUR', 111)
|
||||
, (10, 1, 'I3', current_date, 7, 'EUR', 111)
|
||||
, (11, 1, 'I4', current_date, 7, 'EUR', 111)
|
||||
;
|
||||
|
||||
insert into invoice_product (invoice_product_id, invoice_id, product_id, name, price, quantity, discount_rate)
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
begin;
|
||||
|
||||
select has_function_privilege('numerus.add_invoice(integer, text, date, integer, text, numerus.new_invoice_product[])', 'execute');
|
||||
select has_function_privilege('numerus.add_invoice(integer, text, date, integer, text, integer, numerus.new_invoice_product[])', 'execute');
|
||||
|
||||
rollback;
|
||||
|
|
|
@ -10,6 +10,7 @@ select invoice_id
|
|||
, contact_id
|
||||
, invoice_status
|
||||
, notes
|
||||
, payment_method_id
|
||||
, currency_code
|
||||
, created_at
|
||||
from numerus.invoice
|
||||
|
|
|
@ -55,11 +55,15 @@
|
|||
text-align: right;
|
||||
}
|
||||
|
||||
.invoice .notes {
|
||||
.invoice .notes, .invoice .payment-instructions {
|
||||
white-space: pre;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.invoice .notes + .payment-instructions {
|
||||
margin-top: 5rem;
|
||||
}
|
||||
|
||||
.invoice td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
|
|
@ -110,6 +110,7 @@
|
|||
{{ if .Notes -}}
|
||||
<p class="notes">{{ .Notes }}</p>
|
||||
{{- end }}
|
||||
<p class="payment-instructions">{{ .PaymentInstructions }}</p>
|
||||
|
||||
</div>
|
||||
</article>
|
||||
|
|
Loading…
Reference in New Issue