Hey guys, still on this project. This round was all about the stuff that sits on top of the modules, instead of new modules.
-
Per-user formatting preferences. There’s a new “My preferences” page in the user menu. Every user picks how they want to see numbers and dates: thousands separator, decimal separator, currency (any ISO code, the symbol gets resolved automatically), how many decimals, whether the symbol goes before or after the number, and whether to cut trailing zeros. Same thing for the date format. There’s a live preview box that updates while you touch the selects, so you see1.234,50 €turn into$ 1,234.5as you change this. The setting applies everywhere, lists, record details and so on. -
Tags. These are cross-module, which is the whole point; a tag can sit on a lead and on a ticket. There are two kinds: shared ones, visible to the whole workspace, and private ones, which only you see. Each one has a color. You can attach and detach them from any record, and there’s a “all records with this tag” view that goes across modules, filtered by your permissions, so if you can see tickets but not opportunities, you only get the tickets.I did not build this as a field type, even though I already have a TAGS one. That one belongs to a single ObjectType with its own fixed options, so it gives you neither the shared catalog nor the cross-module search. -
Duplicate merge. You pick a module and it gives you back the candidate pairs, ranked by how similar their titles are (there’s a threshold you can move, default 0.6). Then you get the two records side by side and choose, field by field, which value survives. When you confirm:- the winner keeps everything you picked,
- every relation that pointed at the loser now points at the winner,
- ids of the loser mentioned inside other records get rewritten too, including the ones stored in lists,
- notes and tags move over (and if the winner already had that tag, the duplicate link is dropped),
- the loser goes to the trash, not deleted. A wrong merge has to be recoverable, and I already have a bin, so I used it.
-
Document numbering. Documents now number themselves. It’s configurable per module: prefix, whether to include the year, padding, separator.
Right now it’s on for three of them:
- quotes → 2025-47
- invoices → FT2025-0001
- tickets → TT643
The counter is per module and per year, and it’s locked while it’s being read, so two people creating a quote at the same time can’t get the same number. If you type a number by hand, yours wins, that matters when you’re entering an old document with its original number.
On top of that, quotes have revisions. Revising 2025-13 gives you 2025-13_2, a brand new document that links back to its parent, while the parent moves to the “revised” stage. And you can revise a revision, so 2025-13_2_2 works too, the counter is progressive per parent, not global, which took a bit more care than I expected.
Next up is the big one: document lines. Quote → order → delivery note → invoice, with quantities, discounts and VAT per line. It’s the only part of this CRM that doesn’t fit the dynamic JSON engine everything else is built on, so it gets its own real tables.
See ya in the next devlog, I hope you like the project.
P.S. you’ll see the tag in the next devlog, I still have to implement the frontend
Comments 0
No comments yet. Be the first!
Sign in to join the conversation.