From 8c78617318ff40a986ca5fc50db879c67096d5e0 Mon Sep 17 00:00:00 2001 From: Tom Conway Date: Sun, 15 Aug 2021 02:53:47 +0000 Subject: [PATCH] make length of stock id configurable. --- config-dist.php | 13 +++++++++++++ services/StockService.php | 22 +++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/config-dist.php b/config-dist.php index dc654736..a2d33e91 100644 --- a/config-dist.php +++ b/config-dist.php @@ -101,6 +101,19 @@ Setting('DEFAULT_PERMISSIONS', ['ADMIN']); // 1D (=> Code128) or 2D (=> DataMatrix) Setting('GROCYCODE_TYPE', '1D'); +// Length for stock id tags. Stock id values are unique +// to their product, so the same value for two different +// products is fine. The values are generated using +// a strong hash, so for most instances 6 or 8 digits +// is enough to make the likelyhood of collisions +// acceptably tiny, a value like 16 means we could +// generate unique entries for every tin of tomatoes +// ever made. +// +// Why make it shorter? So you can print shorter +// grocycode barcodes. But probably not shorter than 6. +Setting('STOCK_ID_LENGTH', 16); + // Label printer settings // This is the URI that grocy will POST to when asked to print a label Setting('LABEL_PRINTER_WEBHOOK', ''); diff --git a/services/StockService.php b/services/StockService.php index f73ac5bd..88c68742 100644 --- a/services/StockService.php +++ b/services/StockService.php @@ -165,7 +165,27 @@ class StockService extends BaseService $transactionId = uniqid(); } - $stockId = uniqid(); + // uniqid() basically returns a clock-like counter, + // so the characters in the string do not contribute + // equally to the uniqueness, so we can't just take + // a prefix or suffix of the value to get shorter codes. + // Instead, we hash it, and take a prefix. Because we're + // using a strong hash algorithm, the hash values will + // be very uniform, so a quite short prefix is enough + // to give a pretty good guarantee of uniqueness. + // + // Further, when we lookup stock entries, e.g. to + // consume them, we first lookup by product id, + // so the product id forms a distict namespace, + // and the collisions can only occur within entries + // for a product id. + // + $stockIdLength = 16; + if (GROCY_STOCK_ID_LENGTH) + { + $stockIdLength = GROCY_STOCK_ID_LENGTH; + } + $stockId = substr(hash("sha256", uniqid()), 0, $stockIdLength); $logRow = $this->getDatabase()->stock_log()->createRow([ 'product_id' => $productId,