Since 16e80b5ae, <body> no longer has overflow, thus no scroll. As a
consequence, htmx no longer is able to scroll up <main> when it changes
due to the default, implicit `show:true` applied to the request: is
calls <main>’s scrollIntoView, however there is nothing to scroll to.
I probably could fix it by changing the target of `show`, or even add
a `scroll` directive to all boosted links, but at this point i think it
is better no not boost links at all, as they do what i want—show the new
page from the top—with less markup, plus the browser now show a loading
animation, and it is not that slower, too.
This is only for user-visible strings; the name from the point of view
of code and database remains the same.
This is an attempt to force a distinction between payment method, used
in invoices, and payment accounts, for payments.
Closes#100.
Now that the navigation is inside the header, and the header is not
as tall as it once was, it makes sense to keep it always on the top of
the page, scrolling only within <main>, since it is the main menu, and
fairly used to switch from screen to screen.
I removed the footer because now it would be always visible, and i was
a bit weary of having the application name repeated that much. It was
there mainly for the version number, that helps me check i installed the
application’s latest version on the server, but that role can also be
filled with meta tags.
Closes#97.
I do not particularly enjoy an htmx-only way of doing that, because it
means that it can only work with JavaScript, but i think this is already
a lost cause, unfortunately. If i have time, i will try to make the
HTML-only form work too.
In this case, i have to put back the same row when updating or
cancelling the form, which is inside index.html. Instead of moving that
part to a separate file, i tried to define a block as a “template
fragment” and try to render that part only. Surprisingly, it works;
i am happy.
Closes#74.
I use HTTP 422 to signal that a form was submitted with bad data,
which i believe is the correct status code: “indicates that the server
understands the content type of the request content […], and the syntax
of the request content is correct, but it was unable to process the
contained instructions.”[0]
htmx, however, treats all 4xx status codes as error and, by default,
does not swap the target with the response’s content. Until i found out
that i could change that behaviour, i worked around this limitation by
returning HTTP 200 for htmx requests, but it is a waste of time given
that htmx _can_ accept HTTP 422 as a non-error.
[0]: https://www.rfc-editor.org/rfc/rfc9110#name-422-unprocessable-content
It makes more sense to have the payment link readily available, given
that downloads for expenses are rather uncommon, and, when we implement
electronic invoicing, the invoice PDF will be less useful too.
For the same reasons as with expenses[0], users are no longer expected
to manually set invoice status, and is now linked to their collections.
In this case, however, we had to remove the ‘sent’ and ‘unpaid’ status
options, because these _should_ only be set manually, as there is no
way for the application to know when to set them. Thus, there could
be inconsistencies, like invoices set to ‘unpaid’ when they actually
have collections, or invoices that were ‘sent’, then transitioned to
‘partial’/‘paid’ due to a collection, but then reset to ‘created’ if the
collection was deleted.
[0]: ac0143b2b0
This is mostly the same subsection as payments is for expense, added in
4f646e35d. In this case i call it “collections”, but it is actually
the same payments section.
This is the same as a payment, but the user is the payee instead of the
payer.
I used a different relation than payment because i do not know any other
way to encode the constraint that only invoices can have a collection,
while expenses have only payments.
Besides the name and the fact that they are related to invoices, a
collection is pretty much the same as a payment.
With Oriol we agreed that to add new payments to expenses we should
direct users to a separate payments section, much like the general
payments but centered around the payments of the given expense.
In fact, the only thing i had to do is extract the expense from the
URL, and then adjust the base URI to keep things always within the
correct section; the rest of the code is shared with the general
section.
If there is no invoice number, then they can use the edit item from the
menu, but most expenses do have an invoice, thus this is easier for the
most usual case.
I was repeating myself a lot for this use case, because each one needed
a different URL and SQL query, however they were kind of structurally
similar and could be refactored into common functions.
I actually did not forget them, and i did not add them on purpose,
mistakenly believing that PostgreSQL’s row-level policies would project
only rows from the current company. That is actually how Camper works,
but that’s because we use the request’s domain name to select the
company; here we use the path, and the row-level policy would return
rows from all companies the user belongs to.
I needed to place the payment accounts section somewhere, and the most
logical place seemed to be that dialog, where users can set up company
parameters.
However, that dialog was already saturated with related, but ultimately
independent forms, and adding the account section would make things
even worse, specially given that we need to be able to edit those
accounts in a separate page.
We agreed to separate that dialog into tabs, which means separate pages.
When i had everything in a separated page, then i did not know how to
actually share the code for the tabs, and decided that, for now, these
“tabs” would be items from the profile menu. Same function, different
presentation.
Users are no longer expected to manually set the status of an expense
and, instead, have to add payments to such expense to mark it as partial
or paid.
That means that the PL/pgSQL functions must not accept a status
parameter, the edit and new forms should no longer have a field for
the status, and that the expense list should no longer have the “quick
edit” for their status. That’s why it no longer should have a pointer
cursor, unlike invoice or quote status.
I am using an htmx-infused button to remove the payment, but that
button can not have the CSRF token as value, thus i have to send it in a
header.
The removal of payments warrants a functions, instead of just DELETE
(and CASCADE) as i do for payment methods, because i have to adjust the
status of expenses too. Since i already have functions for everything,
it is not worth using triggers just for that.
This actually should be the “payments and receivables” section, however
this is quite a mouthful; a “receivable” is a payment made **to** you,
therefore “payments” is ok.
In fact, there is still no receivables in there, as they should be in
a separate relation, to constraint them to invoices instead of expenses.
It will be done in a separate commit.
Since this section will be, in a sense, sort of simplified accounting,
i needed to introduce the “payment account” concept. There is no way,
yet, for users to add them, because i have to revamp the “tax details”
section, but this commit started to grow too big already.
The same reasoning for the attachment payment slips as PDF to payment:
something i have to add, but not yet in this commit.
It is common to want to enumerate in a description, for instance when
adding specifications for a hosting, and that enumeration should be
formatted as the user wrote, otherwise it becomes useless.
Closes#94.
In the HTML tables i only compute the aggregated amount by tax class
(e.g., IVA, IRPF), but here we need the actual tax (e.g., IVA 4 %)
because this spreadsheet is intended for accountants.
I can easily extract the amounts from invoice_tax_amount and
expense_tax_amount, but i also need to add the columns to the
spreadsheet, and always with the same order—does not matter much which,
only the same—, that’s why i had to sort the tax IDs when exporting, as
Go does not guarantee an order for maps.
Closes#92
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.
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