Commit Graph

439 Commits

Author SHA1 Message Date
jordi fita mas f5a9e819eb Allow to delete expenses
I remove the related taxes and attachments, but keep related payments
because i believe it is not likely that deleting a paid expense is what
the user wants.  If the user wants to do so, she can delete the payments
first.

Part of #84
2024-09-09 00:08:02 +02:00
jordi fita mas 82da7f4697 Remove almost all data-hx-boost attributes
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.
2024-09-08 01:29:30 +02:00
jordi fita mas 2eecdcfc3e Rename “Payment method” to “Invoicing method”
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.
2024-09-06 12:13:27 +02:00
jordi fita mas 16e80b5ae0 Keep header fixed, and remove footer
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.
2024-09-05 14:37:30 +02:00
jordi fita mas 36423c8636 Shrink user menu’s button and application title
They were too big now that we have the main navigation in the header.

This is part of #98.
2024-09-05 14:23:22 +02:00
jordi fita mas 6ef551a846 Move top-level navigation bar inside body’s header
This is mostly to save on vertical space, since the header was almost
useless but took a lot of screen real estate.
2024-09-04 12:38:37 +02:00
jordi fita mas 292720de28 Add an edit form for payment methods
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.
2024-08-30 02:45:40 +02:00
jordi fita mas e8a44e480e Add field to update default payment method
It is only shown if there is more than one payment method, otherwise
it seems useless as there are nothing to change.

This closes #72.
2024-08-28 11:10:03 +02:00
jordi fita mas 0b74c7a91c Instruct htmx that HTTP 422 is not a “fatal error”
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
2024-08-27 11:07:39 +02:00
jordi fita mas 790417e12c Swap payments/collections and downloads in invoice/expenses index
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.
2024-08-26 14:47:22 +02:00
jordi fita mas b815a18967 Remove status parameter from edit_expense and forms
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
2024-08-26 10:42:38 +02:00
jordi fita mas 7b1220c9f6 Add top margin to form footers 2024-08-21 11:38:52 +02:00
jordi fita mas e3d1e1fd1d Show payments in negative in the index 2024-08-21 11:34:26 +02:00
jordi fita mas 93a95d77d0 Fix the URL to invoices from payment index 2024-08-21 11:23:55 +02:00
jordi fita mas d4ef6c3254 Add a new collection “subsection” for invoices
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.
2024-08-21 11:22:53 +02:00
jordi fita mas 7f31b10cce Add payment collection
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.
2024-08-21 03:36:12 +02:00
jordi fita mas c6c550a036 Add check constraint to payment’s amount 2024-08-18 05:20:36 +02:00
jordi fita mas 4f646e35d6 Add a new payments “subsection” for expenses
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.
2024-08-17 05:31:01 +02:00
jordi fita mas eb880fed36 Fix label for payment date input 2024-08-16 01:58:59 +02:00
jordi fita mas 268ab9989a Link from the invoice number in expense index to its edit form
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.
2024-08-16 01:44:20 +02:00
jordi fita mas dda32db683 Show the invoice number in expense’s title, if any, or slug otherwise 2024-08-16 01:40:20 +02:00
jordi fita mas a30e015639 Add inline tags form to payments 2024-08-15 04:18:35 +02:00
jordi fita mas fa57c4b191 Refactor inline tag edit form into its own file
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.
2024-08-15 04:18:18 +02:00
jordi fita mas dca8b3a719 Add the document (expense) column to payment index page 2024-08-15 03:59:30 +02:00
jordi fita mas 9ab08deaa1 Include the taxes when updating an expense to paid or partial 2024-08-15 03:51:30 +02:00
jordi fita mas 7f21a2131e Add the where company_id filter to accounts and payments queries
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.
2024-08-15 02:59:46 +02:00
jordi fita mas f95936c523 Split the tax details “mega dialog” into separate pages
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.
2024-08-14 04:08:13 +02:00
jordi fita mas e626c7b4bd Style the payment status column in index 2024-08-13 02:36:07 +02:00
jordi fita mas ac0143b2b0 Remove the status parameter from add_expense and edit_expense, and forms
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.
2024-08-13 02:34:21 +02:00
jordi fita mas 71a0a82a3f Change partial expenses to pending when reverting available status
Otherwise, i could have an expense that i have set to partial during
development that prevents sqitch to rebase because it is still in use.
2024-08-13 02:31:15 +02:00
jordi fita mas c95f172499 Add attachments to payments 2024-08-12 00:08:18 +02:00
jordi fita mas 58cef8c00b Refactor common code to download invoice and expenses attachments 2024-08-12 00:07:30 +02:00
jordi fita mas 4deb698265 No need for extension_pgcrypto for functions with UUID parameters 2024-08-11 23:30:57 +02:00
jordi fita mas 778f9c1555 Allow removal of payments
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.
2024-08-11 03:22:37 +02:00
jordi fita mas ad5bc271b6 Add the payments section
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.
2024-08-10 04:34:07 +02:00
jordi fita mas f546632a89 Remove a stray Println from expenseForm.MustFillFromDatabase 2024-08-07 00:47:34 +02:00
jordi fita mas c3fa23727f Include customer’s VAT number to the expense list in ODS too
It was requested by Clara.
2024-07-20 22:52:23 +02:00
jordi fita mas 505fa0f154 Include customer’s VAT number to the invoice list in ODS
It was requested by Clara.
2024-07-20 22:52:23 +02:00
oriol carbonell pujolàs 64be350677 Add styles for small screens 2024-04-08 09:19:52 +02:00
oriol carbonell pujolàs 4363073682 Add down-arrow icon next to download button 2024-04-08 09:18:49 +02:00
oriol carbonell pujolàs 3e6f44f778 Add Tàndem’s logo to home footer 2024-04-08 09:17:57 +02:00
jordi fita mas faf7ee8ed5 Set `white-space: pre-wrap` to first td of quotes and invoices
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.
2024-03-13 02:56:37 +01:00
jordi fita mas a689e2f734 Hide footer when printing invoices and quotes
Closes #96
2024-03-13 02:53:02 +01:00
jordi fita mas 405c833490 Add Guix file 2024-02-06 17:43:05 +01:00
jordi fita mas 65413637ac Add a column for each tax type when exporting invoices and expenses
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
2024-01-26 02:30:11 +01:00
oriol carbonell pujolàs 6fcc19bebf Update styles and home page 2024-01-21 01:58:55 +01:00
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