diff --git a/README.md b/README.md index c63a25d..ab4807b 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,20 @@ # revbank - Banking for hackerspace visitors -## Using revbank (for end users) +## Using RevBank (for end users) Type `help`. More detailed help is available in Dutch on the [the RevBank page on the RevSpace wiki](https://revspace.nl/RevBank). -## Upgrading +### Exiting revbank + +Exiting is not supported because it's designed to run continuously on its main +terminal. But if you run it from a shell, you can probably stop it using ctrl+Z +and then kill the process (e.g. `kill %1`). RevBank does not keep any files +open, so it's safe to kill when idle. + +## Upgrading RevBank When upgrading from a previous version, please refer to the file [UPGRADING.md](UPGRADING.md) because there might be incompatible changes that @@ -16,7 +23,7 @@ require your attention. In general, upgrading is done by committing any changed files and then doing a `git pull`. -## Installing +## Installing RevBank 1. Install the dependencies: @@ -27,7 +34,7 @@ Generic: cpan Term::ReadLine::Gnu Curses::UI 2. Clone the repository, run `./revbank` :) -## Configuring +## Configuring RevBank `revbank` uses data files from the _working directory_ from which it runs. You can use that to your advantage, if you don't want to change anything in your @@ -38,6 +45,27 @@ deal with merge conflicts later, if you prefer. **RevBank just works out of the box** if you're in a hurry, but there's a lot you could customize. +### Pick a transaction ID scheme + +If you skip this step, RevBank will use a large timestamp as a safe fallback. + +You can use any string that Perl can increment with the ++ operator: + +```sh +# Simple, recommended: +echo 1 > .revbank.nextid +# or +echo 00001 > .revbank.nextid +# or +echo AAAA > .revbank.nextid +``` + +This should be done only once. RevBank will increment the number. If you do +wish to start a new sequence, you should clear `.revbank.undo` first if there +is any chance that the sequences will overlap. + +### Other configuration + - `revbank.plugins`: enable or disable plugins here. - `revbank.accounts`: if you're migrating from another system, you can add the existing account balances here. Only the first two columns are mandatory @@ -93,13 +121,8 @@ files, and some have actual documentation: - [products](plugins/products.pod) - [statiegeld](plugins/statiegeld.pod) - [statiegeld\_tokens](plugins/statiegeld_tokens.pod) +- [vat](plugins/vat.pod) > Note: internal links between POD files are all broken in GitHub's rendering, > because GitHub wrongly assumes that every Perl package lives on CPAN. -## Exiting revbank - -Exiting is not supported because it's designed to run continuously. But if you -run it from a shell, you can probably stop it using ctrl+Z and then kill the -process (e.g. `kill %1`). RevBank does not keep any files open, so it's safe -to kill when idle. diff --git a/UPGRADING.md b/UPGRADING.md index eb168d6..216d4da 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,3 +1,118 @@ +# (2023-09-20) RevBank 4.0.0 + +## You must pick a transaction ID style + +Transaction IDs are now sequential for better auditability. In previous +versions, they were timestamps (unix time minus 1.3e9). + +Because of this change, you must restart *every* running RevBank instance or +else the transaction IDs will no longer be monotonic between processes, which +would be bad. + +You should chose which transaction IDs you want, and write your choice to a +file called `.revbank.nextid`. + +### Option 1: continue with large IDs but increment by 1 from now on + +**If you don't write a `.revbank.nextid` file,** RevBank will create one for you, but you might not like it. +It will generate one more timestamp based ID and then increment that for +subsequent transactions. This has the advantage of not having the one-time +break of monotonicity, but you will be stuck with the long IDs and they will no +longer convey time information. + +### Option 2: beginning a new sequence + +Anything that works with Perl's `++` operator will work, and that gives a few +options. If you want to start over with transaction ID **1**, write that to the +file: + +```sh +echo 1 > .revbank.nextid +``` + +You can also use padding zeroes if you like. They will safely overflow to use +an extra digit after all-nines is reached: + +```sh +echo 00001 > .revbank.nextid +``` + +(You can also use alphanumeric IDs, but I'm not sure if you should.) + +Or, if you still have all the logs from since you started using RevBank, you +can pretend RevBank has always had simple incremental transaction IDs and use +the number of distinct transaction IDs from the log file as the basis for the +next ID: + +```sh +# This is my personal preference + +perl -lane'BEGIN { $max = time() - 1.3e9 } + /^\d+$/ and $_ > 0 and $_ < $max and $x{$_}++ for @F[1, 2]; + }{ print 1 + keys %x' .revbank.log > .revbank.nextid + +# Note: use multiple filenames (e.g. .revbank.log*) if you rotate log files +# (like when you have yearly logs). +``` + +This is safe because the timestamp based IDs were huge and are unlikely to +overlap at least the next few decades. + +### Option 3: keeping the legacy transaction ID scheme (for now) + +Finally, for those who really don't want to change the scheme now, the old +system can be retained by writing the special-cased value `LEGACY`. This +feature will be supported at least until 2024-01-01, but might be removed after +if nobody tries to convince me otherwise. + +```sh +echo LEGACY > .revbank.nextid +``` + +## Update `revbank.plugins` + +There are a few new plugins that you may wish to enable. Some have been around +longer than RevBank 3.9, but haven't been mentioned in UPGRADING.md before. + +### `vat` + +Automatically calculate and set aside VAT ("BTW" in Dutch) on generated +revenue. You will probably not need this. Before enabling this plugin, read the +documentation in `plugins/vat.pod` first. + +### `regex_gtin` + +To support GS1 Digital Links and other GS1 barcodes. The DL are a new way for +QR codes that contain product IDs and other metadata while also being usable +for promotional stuff. One popular brand of soft drinks is already using them. +There's a huge standard that describes these codes, but basically, they're URLs +with /01/ and a 14-digit product ID in them. Enabling this plugin is probably +useful and harmless; add it to `revbank.plugins` *after* plugins that deal with +product IDs like `products` and `market`. + +### `regex_angel` + +Replaces custom SHA2017/MCH2022 angel badge hacks. Add after `users` in +`revbank.plugins` after removing your custom plugin for `angel-` barcodes. + +### `adduser_note` + +Add *before* `adduser` in `revbank.plugins`. This will inform new users that +RevBank is insecure by design and what implications that can have. Enabling +this plugin is recommended. + +### `statiegeld` and `statiegeld_tokens` + +Charge and refund container deposit return ("statiegeld" in Dutch). Read the +documentation in `plugins/statiegeld.pod` and `plugins/statiegeld_tokens.pod` +for instructions. + +### `cash_drawer` + +If you have an electronic cash drawer, copy or change this plugin and add code +to trigger it whenever something is done that involves cash. + + # (2023-08-21) RevBank 3.9 A tiny change that could break things: the shebang was changed from diff --git a/lib/RevBank/Cart.pm b/lib/RevBank/Cart.pm index f41df75..7268c3c 100644 --- a/lib/RevBank/Cart.pm +++ b/lib/RevBank/Cart.pm @@ -93,7 +93,20 @@ sub checkout($self, $user) { } RevBank::FileIO::with_lock { - my $transaction_id = time() - 1300000000; + my $fn = ".revbank.nextid"; + my $transaction_id = eval { RevBank::FileIO::slurp($fn) }; + my $legacy_id = 0; + + if (defined $transaction_id) { + chomp $transaction_id; + if ($transaction_id eq "LEGACY") { + $legacy_id = 1; + $transaction_id = time() - 1300000000;; + } + } else { + warn "Could not read $fn; using timestamp as first transaction ID.\n"; + $transaction_id = time() - 1300000000; + } RevBank::Plugins::call_hooks("checkout_prepare", $self, $user, $transaction_id); for my $entry (@$entries) { @@ -101,6 +114,8 @@ sub checkout($self, $user) { $entry->user($user) if not $entry->user; } + RevBank::FileIO::spurt($fn, ++(my $next_id = $transaction_id)) unless $legacy_id; + RevBank::Plugins::call_hooks("checkout", $self, $user, $transaction_id); my %deltas = ($user => RevBank::Amount->new(0)); diff --git a/revbank b/revbank index 07ef6e9..bc84776 100755 --- a/revbank +++ b/revbank @@ -18,7 +18,7 @@ use RevBank::Global; use RevBank::Messages; use RevBank::Cart; -our $VERSION = "3.9"; +our $VERSION = "4.0.0"; our %HELP1 = ( "abort" => "Abort the current transaction", );