Compare commits

...

7 Commits

Author SHA1 Message Date
jordi fita mas 5b0ca28b97 Fix the revert of contact_phone and contact_tax_details
This is mostly to be able to sqitch rebase and restart with the demo
data during development, as it is very unlikely that i will need to
revert those at this point.
2024-01-20 21:34:09 +01:00
jordi fita mas 662ba59be3 Add contacts, invoices, and expenses to the demo
This is mostly to have a better looking dashboard, especially with the
year and last year filters.
2024-01-20 21:33:16 +01:00
jordi fita mas 24a4bf2583 Use kbd and samp for menu options in cookies privacy 2024-01-20 20:32:55 +01:00
jordi fita mas 2ec88eddae Add type comment to login.gohtml 2024-01-20 20:23:47 +01:00
jordi fita mas 5f7b798eb4 Prefill login form when using the demo database
This is to help up “sell” the service: people can look around the demo
to see whether it fits them.  Of course, everyone should have the same
username in the demo.

We talked about having the username and password displayed above the
form in the template, but i think it makes more sense to give users as
little work as necessary.  Plus, that means i do not have to write them
down while developing.

Whether the database is demo or not is not something that directly
depends on the environment, but rather on which database we are
connected to, thus an environment variable would not make much sense—it
has to be something of the database.

PostgreSQL has no PRAGMA application_id or PRAGMA user_version as with
SQLite to include application-specific values to the database.  The
equivalent would be customized options[0], intended for modules
configuration, but that would require me to execute an ALTER DATABASE
in demo.sql with an specific datbase name, or force the use of psql to
run script the script, because then i can use the :DBNAME placeholder.

I guess that the most “standard” way is to just create a function that
returns a know value if the database is demo.  Sqitch does not add that
function, therefore it is unlikely to be there by change unless it is
the demo database.

https://www.postgresql.org/docs/15/runtime-config-custom.html
2024-01-20 20:23:26 +01:00
jordi fita mas 2bd7b2e952 Fix revert for contact_web
If there were contacts added with add_contact passing an empty string
to `web` parameter, contact_web would not have such row, and during the
revert the `web` parameter of contact would end up being NULL.
2024-01-20 19:47:26 +01:00
jordi fita mas 843379a908 Remove the extra logo reference from login.gohtml
It is not in the common web.gohtml template file.
2024-01-20 19:06:59 +01:00
9 changed files with 132 additions and 35 deletions

View File

@ -20,9 +20,12 @@ func main() {
} }
defer db.Close() defer db.Close()
var demo bool
_ = db.QueryRow(context.Background(), "select database_is_numerus_demo()").Scan(&demo)
srv := http.Server{ srv := http.Server{
Addr: ":8080", Addr: ":8080",
Handler: numerus.NewRouter(db), Handler: numerus.NewRouter(db, demo),
ReadTimeout: 5 * time.Second, ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second,
IdleTimeout: 2 * time.Minute, IdleTimeout: 2 * time.Minute,

View File

@ -2,6 +2,8 @@ begin;
set search_path to auth, numerus, public; set search_path to auth, numerus, public;
create or replace function public.database_is_numerus_demo() returns bool as $$ select true $$ language sql;
alter sequence user_user_id_seq restart with 123; alter sequence user_user_id_seq restart with 123;
insert into auth."user" (email, name, password, role) insert into auth."user" (email, name, password, role)
values ('demo@numerus', 'Demo User', 'demo', 'invoicer') values ('demo@numerus', 'Demo User', 'demo', 'invoicer')
@ -54,12 +56,18 @@ values (123, 123, 'Retenció 15 %', -0.15)
; ;
alter sequence contact_contact_id_seq restart with 123; alter sequence contact_contact_id_seq restart with 123;
select add_contact (123, 'Melcior', '0732621', 'melcio@reismags.cat', '', '(Rei Blanc,1,"C/ Principal, 1",Shiraz,Fars,1,IR)', '', '', array['pesebre', 'mag']); -- customers
select add_contact (123, 'Gaspar', '111', 'gaspar@reismags.cat', '', '(Rei Ros,2,"C/ Principal, 2",Nova Delhi,Delhi,2,IN)', '', '', array['pesebre', 'mag']); select add_contact (123, 'Melcior', '0732621', 'melcio@reismags.cat', '', '(Rei Blanc,1,"C/ Principal, 1",Shiraz,Fars,1,IR)', '', '', array['pesebre', 'mag', 'client']);
select add_contact (123, 'Baltasar', '1-111-111', 'baltasar@reismags.cat', '', '(Rei Negre,3,"C/ Principal, 3",Sanaa,Sanaa,3,YE)', '', '', array['pesebre', 'mag']); select add_contact (123, 'Gaspar', '111', 'gaspar@reismags.cat', '', '(Rei Ros,2,"C/ Principal, 2",Nova Delhi,Delhi,2,IN)', '', '', array['pesebre', 'mag', 'client']);
select add_contact (123, 'Caganera', '222 222 222', 'caganera@pesebre.cat', '', '(Caganera,41414141L,"C/ De lHort, 4",Olot,Girona,17800,ES)', '', '', array['pesebre', 'persona']); select add_contact (123, 'Baltasar', '1-111-111', 'baltasar@reismags.cat', '', '(Rei Negre,3,"C/ Principal, 3",Sanaa,Sanaa,3,YE)', '', '', array['pesebre', 'mag', 'client']);
select add_contact (123, 'Bou', '333 333 333', 'bou@pesebre.cat', '', '(Bou,41414142C,"C/ De la Palla, 5",Sant Climent Sescebes,Girona,17751,ES)', '', '', array['pesebre', 'bestia']); select add_contact (123, 'Caganera', '222 222 222', 'caganera@pesebre.cat', '', '(Caganera,41414141L,"C/ De lHort, 4",Olot,Girona,17800,ES)', '', '', array['pesebre', 'persona', 'client']);
select add_contact (123, 'Rabadà', '444 444 444', 'rabada@pesebre.cat', '', '(Rabadà,41414143K,"C/ De les Ovelles, 6",Fornells de la Selva,Girona,17458,ES)', '', '', array['pesebre', 'persona']); select add_contact (123, 'Bou', '333 333 333', 'bou@pesebre.cat', '', '(Bou,41414142C,"C/ De la Palla, 5",Sant Climent Sescebes,Girona,17751,ES)', '', '', array['pesebre', 'bestia', 'client']);
select add_contact (123, 'Rabadà', '444 444 444', 'rabada@pesebre.cat', '', '(Rabadà,41414143K,"C/ De les Ovelles, 6",Fornells de la Selva,Girona,17458,ES)', '', '', array['pesebre', 'persona', 'client']);
-- suppliers
select add_contact(123, 'TGSS', '', '', '', null, '', '', array['govern']);
select add_contact(123, 'Quadre Estable', '', '', '', null, '', '', array['proveidor']);
select add_contact(123, 'De tot i +', '', '', '', null, '', '', array['proveidor']);
select add_contact(123, 'Els números', '', '', '', null, '', '', array['gestoria']);
alter sequence product_product_id_seq restart with 123; alter sequence product_product_id_seq restart with 123;
select add_product(123, 'Or', 'Metall de transició tou, brillant, groc, pesant, mal·leable, dúctil i que no reacciona amb la majoria de productes químics, però és sensible al clor i a laigua règia.', '55.92', array[124], array['metall']); select add_product(123, 'Or', 'Metall de transició tou, brillant, groc, pesant, mal·leable, dúctil i que no reacciona amb la majoria de productes químics, però és sensible al clor i a laigua règia.', '55.92', array[124], array['metall']);
@ -72,6 +80,36 @@ select add_product(123, 'Teia', 'Fusta resinosa de pi i daltres arbres, provi
alter sequence invoice_invoice_id_seq restart with 123; alter sequence invoice_invoice_id_seq restart with 123;
alter sequence invoice_product_invoice_product_id_seq restart with 123; alter sequence invoice_product_invoice_product_id_seq restart with 123;
select add_invoice(123, (current_date - '338 days'::interval)::date, 124, '', 123, '{producte,mag}','{"(124,Encens,Goma resina fragrant que desprèn una olor característica quan es crema.,2.26,460,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",4.53,1,0.0,{124})"}');
select add_invoice(123, (current_date - '334 days'::interval)::date, 124, '', 123, '{producte,mag}','{"(124,Encens,Goma resina fragrant que desprèn una olor característica quan es crema.,2.26,460,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",4.53,1,0.0,{124})"}');
select add_invoice(123, (current_date - '327 days'::interval)::date, 123, '', 123, '{producte,mag}','{"(123,Or,\"Metall de transició tou, brillant, groc, pesant, mal·leable, dúctil i que no reacciona amb la majoria de productes químics, però és sensible al clor i a laigua règia.\",57.82,18,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.43,1,0.0,{124})"}');
select add_invoice(123, (current_date - '317 days'::interval)::date, 128, 'Vol esmorzar!', 123, '{producte}','{"(129,Teia,\"Fusta resinosa de pi i daltres arbres, provinent sobretot del cor de larbre, que crema amb molta facilitat.\",7.00,1,0.0,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '314 days'::interval)::date, 123, '', 123, '{producte,mag}','{"(123,Or,\"Metall de transició tou, brillant, groc, pesant, mal·leable, dúctil i que no reacciona amb la majoria de productes químics, però és sensible al clor i a laigua règia.\",57.82,18,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.43,1,0.0,{124})"}');
select add_invoice(123, (current_date - '311 days'::interval)::date, 128, 'Vol esmorzar!', 123, '{producte}','{"(129,Teia,\"Fusta resinosa de pi i daltres arbres, provinent sobretot del cor de larbre, que crema amb molta facilitat.\",7.00,1,0.0,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '278 days'::interval)::date, 125, '', 123, '{producte,mag}','{"(125,Mirra,Goma resinosa aromàtica de color gris groguenc i gust amargant.,7.22,144,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",4.45,1,0.0,{124})"}');
select add_invoice(123, (current_date - '274 days'::interval)::date, 127, '', 123, '{producte,bestia}','{"(128,Palla,Tija seca dels cereals després que el gra o llavor ha estat separat mitjançant la trilla.,25.00,25,0.0,{125})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '267 days'::interval)::date, 126, '', 123, '{producte,higiene}','{"(126,\"Paper higiènic (pack de 32 U)\",Paper que susa per mantenir la higiene personal després de defecar o orinar.,7.99,10,0.0,{126})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '257 days'::interval)::date, 126, '', 123, '{producte,higiene}','{"(126,\"Paper higiènic (pack de 32 U)\",Paper que susa per mantenir la higiene personal després de defecar o orinar.,7.99,10,0.0,{126})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '254 days'::interval)::date, 127, '', 123, '{producte,bestia}','{"(128,Palla,Tija seca dels cereals després que el gra o llavor ha estat separat mitjançant la trilla.,25.00,25,0.0,{125})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '251 days'::interval)::date, 125, '', 123, '{producte,mag}','{"(125,Mirra,Goma resinosa aromàtica de color gris groguenc i gust amargant.,7.22,144,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",4.45,1,0.0,{124})"}');
select add_invoice(123, (current_date - '208 days'::interval)::date, 127, '', 123, '{producte,bestia}','{"(128,Palla,Tija seca dels cereals després que el gra o llavor ha estat separat mitjançant la trilla.,25.00,25,0.0,{125})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '204 days'::interval)::date, 127, '', 123, '{producte,bestia}','{"(128,Palla,Tija seca dels cereals després que el gra o llavor ha estat separat mitjançant la trilla.,25.00,25,0.0,{125})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '197 days'::interval)::date, 125, '', 123, '{producte,mag}','{"(125,Mirra,Goma resinosa aromàtica de color gris groguenc i gust amargant.,7.22,144,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",4.45,1,0.0,{124})"}');
select add_invoice(123, (current_date - '187 days'::interval)::date, 128, 'Vol esmorzar!', 123, '{producte}','{"(129,Teia,\"Fusta resinosa de pi i daltres arbres, provinent sobretot del cor de larbre, que crema amb molta facilitat.\",7.00,1,0.0,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '184 days'::interval)::date, 123, '', 123, '{producte,mag}','{"(123,Or,\"Metall de transició tou, brillant, groc, pesant, mal·leable, dúctil i que no reacciona amb la majoria de productes químics, però és sensible al clor i a laigua règia.\",57.82,18,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.43,1,0.0,{124})"}');
select add_invoice(123, (current_date - '181 days'::interval)::date, 125, '', 123, '{producte,mag}','{"(125,Mirra,Goma resinosa aromàtica de color gris groguenc i gust amargant.,7.22,144,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",4.45,1,0.0,{124})"}');
select add_invoice(123, (current_date - '148 days'::interval)::date, 126, '', 123, '{producte,higiene}','{"(126,\"Paper higiènic (pack de 32 U)\",Paper que susa per mantenir la higiene personal després de defecar o orinar.,7.99,10,0.0,{126})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '144 days'::interval)::date, 126, '', 123, '{producte,higiene}','{"(126,\"Paper higiènic (pack de 32 U)\",Paper que susa per mantenir la higiene personal després de defecar o orinar.,7.99,10,0.0,{126})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '137 days'::interval)::date, 123, '', 123, '{producte,mag}','{"(123,Or,\"Metall de transició tou, brillant, groc, pesant, mal·leable, dúctil i que no reacciona amb la majoria de productes químics, però és sensible al clor i a laigua règia.\",57.82,18,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.43,1,0.0,{124})"}');
select add_invoice(123, (current_date - '127 days'::interval)::date, 124, '', 123, '{producte,mag}','{"(124,Encens,Goma resina fragrant que desprèn una olor característica quan es crema.,2.26,460,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",4.53,1,0.0,{124})"}');
select add_invoice(123, (current_date - '124 days'::interval)::date, 124, '', 123, '{producte,mag}','{"(124,Encens,Goma resina fragrant que desprèn una olor característica quan es crema.,2.26,460,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",4.53,1,0.0,{124})"}');
select add_invoice(123, (current_date - '121 days'::interval)::date, 128, 'Vol esmorzar!', 123, '{producte}','{"(129,Teia,\"Fusta resinosa de pi i daltres arbres, provinent sobretot del cor de larbre, que crema amb molta facilitat.\",7.00,1,0.0,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '78 days'::interval)::date, 126, '', 123, '{producte,higiene}','{"(126,\"Paper higiènic (pack de 32 U)\",Paper que susa per mantenir la higiene personal després de defecar o orinar.,7.99,10,0.0,{126})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '74 days'::interval)::date, 124, '', 123, '{producte,mag}','{"(124,Encens,Goma resina fragrant que desprèn una olor característica quan es crema.,2.26,460,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",4.53,1,0.0,{124})"}');
select add_invoice(123, (current_date - '67 days'::interval)::date, 128, 'Vol esmorzar!', 123, '{producte}','{"(129,Teia,\"Fusta resinosa de pi i daltres arbres, provinent sobretot del cor de larbre, que crema amb molta facilitat.\",7.00,1,0.0,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '57 days'::interval)::date, 123, '', 123, '{producte,mag}','{"(123,Or,\"Metall de transició tou, brillant, groc, pesant, mal·leable, dúctil i que no reacciona amb la majoria de productes químics, però és sensible al clor i a laigua règia.\",57.82,18,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.43,1,0.0,{124})"}');
select add_invoice(123, (current_date - '54 days'::interval)::date, 127, '', 123, '{producte,bestia}','{"(128,Palla,Tija seca dels cereals després que el gra o llavor ha estat separat mitjançant la trilla.,25.00,25,0.0,{125})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '51 days'::interval)::date, 125, '', 123, '{producte,mag}','{"(125,Mirra,Goma resinosa aromàtica de color gris groguenc i gust amargant.,7.22,144,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",4.45,1,0.0,{124})"}');
select add_invoice(123, (current_date - '28 days'::interval)::date, 128, 'Vol esmorzar!', 123, '{producte}','{"(129,Teia,\"Fusta resinosa de pi i daltres arbres, provinent sobretot del cor de larbre, que crema amb molta facilitat.\",7.00,1,0.0,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}'); select add_invoice(123, (current_date - '28 days'::interval)::date, 128, 'Vol esmorzar!', 123, '{producte}','{"(129,Teia,\"Fusta resinosa de pi i daltres arbres, provinent sobretot del cor de larbre, que crema amb molta facilitat.\",7.00,1,0.0,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '24 days'::interval)::date, 127, '', 123, '{producte,bestia}','{"(128,Palla,Tija seca dels cereals després que el gra o llavor ha estat separat mitjançant la trilla.,25.00,25,0.0,{125})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}'); select add_invoice(123, (current_date - '24 days'::interval)::date, 127, '', 123, '{producte,bestia}','{"(128,Palla,Tija seca dels cereals després que el gra o llavor ha estat separat mitjançant la trilla.,25.00,25,0.0,{125})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
select add_invoice(123, (current_date - '17 days'::interval)::date, 126, '', 123, '{producte,higiene}','{"(126,\"Paper higiènic (pack de 32 U)\",Paper que susa per mantenir la higiene personal després de defecar o orinar.,7.99,10,0.0,{126})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}'); select add_invoice(123, (current_date - '17 days'::interval)::date, 126, '', 123, '{producte,higiene}','{"(126,\"Paper higiènic (pack de 32 U)\",Paper que susa per mantenir la higiene personal després de defecar o orinar.,7.99,10,0.0,{126})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.64,1,0.0,{124})"}');
@ -79,8 +117,32 @@ select add_invoice(123, (current_date - '7 days'::interval)::date, 125, '', 123,
select add_invoice(123, (current_date - '4 days'::interval)::date, 124, '', 123, '{producte,mag}','{"(124,Encens,Goma resina fragrant que desprèn una olor característica quan es crema.,2.26,460,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",4.53,1,0.0,{124})"}'); select add_invoice(123, (current_date - '4 days'::interval)::date, 124, '', 123, '{producte,mag}','{"(124,Encens,Goma resina fragrant que desprèn una olor característica quan es crema.,2.26,460,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",4.53,1,0.0,{124})"}');
select add_invoice(123, (current_date - '1 days'::interval)::date, 123, '', 123, '{producte,mag}','{"(123,Or,\"Metall de transició tou, brillant, groc, pesant, mal·leable, dúctil i que no reacciona amb la majoria de productes químics, però és sensible al clor i a laigua règia.\",57.82,18,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.43,1,0.0,{124})"}'); select add_invoice(123, (current_date - '1 days'::interval)::date, 123, '', 123, '{producte,mag}','{"(123,Or,\"Metall de transició tou, brillant, groc, pesant, mal·leable, dúctil i que no reacciona amb la majoria de productes químics, però és sensible al clor i a laigua règia.\",57.82,18,0.05,{124})","(127,Cavall Fort,\"Revista quinzenal en llengua catalana i de còmic en català, destinada a infants i joves.\",3.43,1,0.0,{124})"}');
update invoice set invoice_status = 'paid' where invoice_id in (123, 127); update invoice set invoice_status = 'paid' where invoice_id not in (154, 155, 156, 158);
update invoice set invoice_status = 'unpaid' where invoice_id = 125; update invoice set invoice_status = 'unpaid' where invoice_id = 155;
update invoice set invoice_status = 'sent' where invoice_id = 126; update invoice set invoice_status = 'sent' where invoice_id = 156;
alter sequence expense_expense_id_seq restart with 123;
select add_expense(123, 'paid', (date_trunc('month', current_date) - '11 months + 14 day'::interval)::date, 130, 'ABC123', '256.12', '{124}', '{}');
select add_expense(123, 'paid', (date_trunc('month', current_date) - '11 months + 8 day'::interval)::date, 131, '123ABC', '1023.17', '{124}', '{}');
select add_expense(123, 'paid', (date_trunc('month', current_date) - '11 months + 1 day'::interval)::date, 129, 'N CMDPGGNZG', '299.17', '{}', array['autonoms']);
select add_expense(123, 'paid', (date_trunc('month', current_date) - '10 months + 20 day'::interval)::date, 131, '123XYZ', '23.17', '{124}', '{}');
select add_expense(123, 'paid', (date_trunc('month', current_date) - '10 months + 1 day'::interval)::date, 129, 'N QHVLDAN29', '299.17', '{}', array['autonoms']);
select add_expense(123, 'paid', (date_trunc('month', current_date) - '9 months + 2 day'::interval)::date, 130, 'XYZ123', '62.21', '{124}', '{}');
select add_expense(123, 'paid', (date_trunc('month', current_date) - '9 months + 1 day'::interval)::date, 129, 'N WXMHH1R5Q', '299.17', '{}', array['autonoms']);
select add_expense(123, 'paid', (current_date - '9 months'::interval)::date, 132, '00/0001', '117.74', '{124}', array['gestor']);
select add_expense(123, 'paid', (date_trunc('month', current_date) - '8 months + 1 day'::interval)::date, 129, 'N NRP28PWY8', '299.17', '{}', array['autonoms']);
select add_expense(123, 'paid', (date_trunc('month', current_date) - '7 months + 1 day'::interval)::date, 129, 'N D256225DF', '299.17', '{}', array['autonoms']);
select add_expense(123, 'paid', (date_trunc('month', current_date) - '6 months + 15 day'::interval)::date, 130, 'ZZZ888', '162.21', '{124}', '{}');
select add_expense(123, 'paid', (date_trunc('month', current_date) - '6 months + 1 day'::interval)::date, 129, 'N K90XS7C3Q', '299.17', '{}', array['autonoms']);
select add_expense(123, 'paid', (current_date - '6 months'::interval)::date, 132, '00/0054', '117.74', '{124}', array['gestor']);
select add_expense(123, 'paid', (date_trunc('month', current_date) - '5 months + 1 day'::interval)::date, 129, 'N MCPDGGZNG', '299.17', '{}', array['autonoms']);
select add_expense(123, 'paid', (date_trunc('month', current_date) - '4 months + 1 day'::interval)::date, 129, 'N HQLVAD2N9', '299.17', '{}', array['autonoms']);
select add_expense(123, 'paid', (date_trunc('month', current_date) - '3 months + 1 day'::interval)::date, 129, 'N QXWHM1H5R', '299.17', '{}', array['autonoms']);
select add_expense(123, 'pending', (current_date - '3 months'::interval)::date, 132, '00/0331', '117.74', '{124}', array['gestor']);
select add_expense(123, 'paid', (date_trunc('month', current_date) - '2 months + 1 day'::interval)::date, 129, 'N 8RN2PP8YW', '299.17', '{}', array['autonoms']);
select add_expense(123, 'paid', (date_trunc('month', current_date) - '1 months + 1 day'::interval)::date, 129, 'N F2D6522D5', '299.17', '{}', array['autonoms']);
select add_expense(123, 'paid', (date_trunc('month', current_date) - '1 day'::interval)::date, 129, 'N F2D6522D5', '299.17', '{}', array['autonoms']);
select add_expense(123, 'pending', (current_date - '22 day'::interval)::date, 131, '321ABC', '1023.17', '{124}', '{}');
select add_expense(123, 'pending', (current_date - '11 day'::interval)::date, 130, 'ABC321', '256.12', '{124}', '{}');
commit; commit;

View File

@ -29,8 +29,8 @@ type loginForm struct {
Password *InputField Password *InputField
} }
func newLoginForm(locale *Locale) *loginForm { func newLoginForm(demo bool, locale *Locale) *loginForm {
return &loginForm{ form := &loginForm{
locale: locale, locale: locale,
Email: &InputField{ Email: &InputField{
Name: "email", Name: "email",
@ -53,6 +53,11 @@ func newLoginForm(locale *Locale) *loginForm {
}, },
}, },
} }
if demo {
form.Email.Val = "admin@numerus"
form.Password.Val = "admin"
}
return form
} }
func (form *loginForm) Parse(r *http.Request) error { func (form *loginForm) Parse(r *http.Request) error {
@ -74,26 +79,26 @@ func (form *loginForm) Validate() bool {
return validator.AllOK() return validator.AllOK()
} }
func GetLoginForm(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { func GetLoginForm(w http.ResponseWriter, r *http.Request, demo bool) {
user := getUser(r) user := getUser(r)
if user.LoggedIn { if user.LoggedIn {
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }
locale := getLocale(r) locale := getLocale(r)
form := newLoginForm(locale) form := newLoginForm(demo, locale)
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
mustRenderLoginForm(w, r, form) mustRenderLoginForm(w, r, form)
} }
func HandleLoginForm(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { func HandleLoginForm(w http.ResponseWriter, r *http.Request, demo bool) {
user := getUser(r) user := getUser(r)
if user.LoggedIn { if user.LoggedIn {
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }
locale := getLocale(r) locale := getLocale(r)
form := newLoginForm(locale) form := newLoginForm(demo, locale)
if err := form.Parse(r); err != nil { if err := form.Parse(r); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest) http.Error(w, err.Error(), http.StatusBadRequest)
return return

View File

@ -6,7 +6,7 @@ import (
"net/http" "net/http"
) )
func NewRouter(db *Db) http.Handler { func NewRouter(db *Db, demo bool) http.Handler {
companyRouter := httprouter.New() companyRouter := httprouter.New()
companyRouter.GET("/profile", GetProfileForm) companyRouter.GET("/profile", GetProfileForm)
companyRouter.POST("/profile", HandleProfileForm) companyRouter.POST("/profile", HandleProfileForm)
@ -62,8 +62,12 @@ func NewRouter(db *Db) http.Handler {
router := httprouter.New() router := httprouter.New()
router.ServeFiles("/static/*filepath", http.Dir("web/static")) router.ServeFiles("/static/*filepath", http.Dir("web/static"))
router.GET("/login", GetLoginForm) router.GET("/login", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
router.POST("/login", HandleLoginForm) GetLoginForm(w, r, demo)
})
router.POST("/login", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
HandleLoginForm(w, r, demo)
})
router.POST("/logout", Authenticated(HandleLogout)) router.POST("/logout", Authenticated(HandleLogout))
companyHandler := Authenticated(CompanyHandler(companyRouter)) companyHandler := Authenticated(CompanyHandler(companyRouter))

View File

@ -5,7 +5,7 @@ begin;
set search_path to numerus, public; set search_path to numerus, public;
alter table contact alter table contact
add column phone packed_phone_number add column phone packed_phone_number default '+34000000000'
; ;
update contact update contact
@ -16,6 +16,7 @@ where phone.contact_id = contact.contact_id
alter table contact alter table contact
alter column phone set not null alter column phone set not null
, alter column phone drop default
; ;
drop table if exists contact_phone; drop table if exists contact_phone;

View File

@ -6,19 +6,24 @@ set search_path to numerus, public;
alter table contact alter table contact
drop constraint name_not_empty drop constraint name_not_empty
, add column country_code country_code , add column country_code country_code default 'ES'
, add column postal_code text , add column postal_code text default ''
, add column province text , add column province text default ''
, add column city text , add column city text default ''
, add column address text , add column address text default ''
, add column vatin vatin , add column vatin vatin default 'ES40404040D'
, add column business_name text constraint business_name_not_empty check(length(trim(business_name)) > 1) , add column business_name text default 'ACME' constraint business_name_not_empty check(length(trim(business_name)) > 1)
; ;
alter table contact alter table contact
rename column name to trade_name rename column name to trade_name
; ;
update contact
set business_name = trade_name
where true
;
update contact update contact
set business_name = tax.business_name set business_name = tax.business_name
, vatin = tax.vatin , vatin = tax.vatin
@ -32,12 +37,20 @@ where tax.contact_id = contact.contact_id
; ;
alter table contact alter table contact
alter column business_name set not null alter column business_name drop default
, alter column business_name set not null
, alter column vatin drop default
, alter column vatin set not null , alter column vatin set not null
, alter column vatin set not null
, alter column address drop default
, alter column address set not null , alter column address set not null
, alter column city drop default
, alter column city set not null , alter column city set not null
, alter column province drop default
, alter column province set not null , alter column province set not null
, alter column postal_code drop default
, alter column postal_code set not null , alter column postal_code set not null
, alter column country_code drop default
, alter column country_code set not null , alter column country_code set not null
; ;

View File

@ -14,6 +14,11 @@ from contact_web as web
where web.contact_id = contact.contact_id where web.contact_id = contact.contact_id
; ;
update contact
set web = ''
where web is null
;
alter table contact alter table contact
alter column web set not null alter column web set not null
; ;

View File

@ -94,27 +94,31 @@
<dl> <dl>
<dt>Google Chrome</dt> <dt>Google Chrome</dt>
<dd>Configuració → Mostrar opcions avançades → Privacitat (Configuració de contingut) → <i <dd><kbd><kbd><samp>Configuració</samp></kbd> → <kbd><samp>Mostrar opcions avançades</samp></kbd> →
lang="en">Cookies</i></dd> <kbd><samp>Privacitat (Configuració de contingut)</samp></kbd> → <kbd><samp lang="en">Cookies</samp></kbd></kbd>
</dd>
<dd><a href="https://support.google.com/chrome/answer/95647?co=genie.platform%3DDesktop&amp;hl=ca">https://support.google.com/chrome/answer/95647?co=genie.platform%3DDesktop&amp;hl=ca</a> <dd><a href="https://support.google.com/chrome/answer/95647?co=genie.platform%3DDesktop&amp;hl=ca">https://support.google.com/chrome/answer/95647?co=genie.platform%3DDesktop&amp;hl=ca</a>
</dd> </dd>
<dt>Microsoft Internet Explorer</dt> <dt>Microsoft Internet Explorer</dt>
<dd>Opcions dInternet → Privacitat → Avançada</dd> <dd><kbd><kbd><samp>Opcions dInternet</samp></kbd> → <kbd><samp>Privacitat</samp></kbd> →
<kbd><samp>Avançada</samp></kbd></kbd></dd>
<dd><a href="https://support.microsoft.com/ca-es/help/17442/windows-internet-explorer-delete-managecookies">https://support.microsoft.com/ca-es/help/17442/windows-internet-explorer-delete-managecookies</a> <dd><a href="https://support.microsoft.com/ca-es/help/17442/windows-internet-explorer-delete-managecookies">https://support.microsoft.com/ca-es/help/17442/windows-internet-explorer-delete-managecookies</a>
</dd> </dd>
<dt>Firefox</dt> <dt>Firefox</dt>
<dd>Opcions → Privacitat → <i lang="en">Cookies</i></dd> <dd><kbd><kbd><samp>Opcions</samp></kbd> → <kbd><samp>Privacitat</samp></kbd> → <kbd><samp
lang="en">Cookies</samp></kbd></kbd></dd>
<dd><a href="https://support.mozilla.org/ca/products/firefox/protect-your-privacy/cookies">https://support.mozilla.org/ca/products/firefox/protect-your-privacy/cookies</a> <dd><a href="https://support.mozilla.org/ca/products/firefox/protect-your-privacy/cookies">https://support.mozilla.org/ca/products/firefox/protect-your-privacy/cookies</a>
</dd> </dd>
<dt>Safari, iPad i iPhone</dt> <dt>Safari, iPad i iPhone</dt>
<dd>Preferències → Privacitat</dd> <dd><kbd><kbd><samp>Preferències</samp></kbd><kbd><samp>Privacitat</samp></kbd></kbd></dd>
<dd><a href="https://support.apple.com/ca-es/105082">https://support.apple.com/ca-es/105082</a></dd> <dd><a href="https://support.apple.com/ca-es/105082">https://support.apple.com/ca-es/105082</a></dd>
<dt>Opera</dt> <dt>Opera</dt>
<dd>Configuració → Opcions → Avançat → <i lang="en">Cookies</i></dd> <dd><kbd><kbd><samp>Configuració</samp></kbd> → <kbd><samp>Opcions</samp></kbd> →
<kbd><samp>Avançat</samp></kbd> → <kbd><samp lang="en">Cookies</samp></kbd></kbd></dd>
<dd><a href="https://help.opera.com/en/latest/web-preferences/#cookies">https://help.opera.com/en/latest/web-preferences/#cookies</a> <dd><a href="https://help.opera.com/en/latest/web-preferences/#cookies">https://help.opera.com/en/latest/web-preferences/#cookies</a>
</dd> </dd>
</dl> </dl>

View File

@ -3,7 +3,7 @@
{{- end }} {{- end }}
{{ define "content" }} {{ define "content" }}
<h1><img src="/static/numerus.svg" alt="Numerus" width="620" height="77"></h1> {{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.loginForm*/ -}}
{{ if .Errors -}} {{ if .Errors -}}
<div class="error" role="alert"> <div class="error" role="alert">
{{ range $error := .Errors -}} {{ range $error := .Errors -}}