From ee36f17d1d48fcf8a2736ef8cd8b56f10f366dcc Mon Sep 17 00:00:00 2001 From: No0ne558 Date: Sat, 31 Jan 2026 14:03:51 -0800 Subject: [PATCH] feat: Add out of stock (86) toggle feature for menu items - Add out_of_stock boolean field to SalesItem class - Update data file version to 17 for backward compatibility - Modify ItemZone rendering to show 'Item Name - Out of stock' in red - Add toggle in item editing interface - Update changelog with feature details This allows managers to mark items as unavailable and provides clear visual feedback to staff with red text on buttons. --- docs/changelog.md | 17 +++++++++++++++++ main/business/sales.cc | 10 ++++++++++ main/business/sales.hh | 3 ++- zone/inventory_zone.cc | 5 ++++- zone/order_zone.cc | 39 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 71 insertions(+), 3 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index 7fdc5000..5c2042bf 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -44,6 +44,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - `main/business/check.hh` (SplitCheckEqually declaration, later removed) - **Impact**: Split check interface now provides clean, simple, and functional experience with clear visual feedback, proper pricing display, and intuitive manual item selection +- **Out of Stock (86) Toggle Feature for Menu Items (2026-01-31)** + - Added ability to mark menu items as "86" (out of stock) with visual feedback on buttons + - **Changes Made**: + - Added `out_of_stock` boolean field to SalesItem class for tracking availability + - Updated data file version to 17 for backward compatibility + - Modified ItemZone rendering to display "Item Name - Out of stock" in red when item is unavailable + - Added "Out of Stock (86'd)?" toggle in item editing interface + - Implemented safe color override during rendering to maintain visual consistency + - **Root Cause**: No built-in way to temporarily disable menu items without removing them entirely + - **Solution**: Added toggleable out-of-stock status with clear visual indicators + - **Files modified**: + - `main/business/sales.hh` (added out_of_stock field) + - `main/business/sales.cc` (updated serialization and data handling) + - `zone/inventory_zone.cc` (added editing interface) + - `zone/order_zone.cc` (modified rendering logic) + - **Impact**: Staff can now easily identify unavailable items, managers can quickly toggle item availability, improves operational efficiency during stock shortages + ### Fixed - **Fixed GCC 14 Warning in Date Library (2026-01-25)** - Resolved stringop-overflow warning in external/date/include/date/date.h when compiling on Raspberry Pi Compute Module 5 with GCC 14 diff --git a/main/business/sales.cc b/main/business/sales.cc index 451424a2..1a642200 100644 --- a/main/business/sales.cc +++ b/main/business/sales.cc @@ -101,6 +101,7 @@ SalesItem::SalesItem(const char* name) changed = 0; allow_increase = 1; ignore_split = 0; + out_of_stock = 0; } // Member Functions @@ -146,6 +147,7 @@ int SalesItem::Copy(SalesItem *target) target->price_type = price_type; target->allow_increase = allow_increase; target->ignore_split = ignore_split; + target->out_of_stock = out_of_stock; retval = 0; } return retval; @@ -184,6 +186,7 @@ int SalesItem::Read(InputDataFile &df, int version) // 14 (04/30/15) added all properties relating to cinema mode. // 15 (11/06/15) added ignore split kitchen // 16 (11/03/25) added image_path persistence + // 17 (01/31/26) added out_of_stock flag if (version < 8) return 1; @@ -248,6 +251,11 @@ int SalesItem::Read(InputDataFile &df, int version) else image_path.Clear(); + if (version >= 17) + df.Read(out_of_stock); + else + out_of_stock = 0; + // Item property checks if (call_order < 0) call_order = 0; @@ -317,6 +325,8 @@ int SalesItem::Write(OutputDataFile &df, int version) error += df.Write(ignore_split); if (version >= 16) error += df.Write(image_path); + if (version >= 17) + error += df.Write(out_of_stock); return error; } diff --git a/main/business/sales.hh b/main/business/sales.hh index 9755f60c..c67b2ccc 100644 --- a/main/business/sales.hh +++ b/main/business/sales.hh @@ -28,7 +28,7 @@ /**** Definitions ****/ -constexpr int SALES_ITEM_VERSION = 16; +constexpr int SALES_ITEM_VERSION = 17; // Family Difinitions #define FAMILY_APPETIZERS 0 @@ -194,6 +194,7 @@ public: short has_zone; // boolean - is there a zone that can order this item? short allow_increase; // whether to show the OrderAddZone button. short ignore_split; // ignore split kitchen? + short out_of_stock; // boolean - is item 86'd or out of stock int period; // time of day served int prepare_time; // time to make menu item int quanity; // Number of item remaining diff --git a/zone/inventory_zone.cc b/zone/inventory_zone.cc index ee72a2bb..a1337eaf 100644 --- a/zone/inventory_zone.cc +++ b/zone/inventory_zone.cc @@ -1162,6 +1162,7 @@ int ItemListZone::AddFields() AddListField("Is Item Stocked?", NoYesName); AddListField("Allow Increase Button?", NoYesName); AddListField("Ignore Split Kitchen?", NoYesName); + AddListField("Out of Stock (86'd)?", NoYesName); return 0; } @@ -1382,7 +1383,8 @@ int ItemListZone::LoadRecord(Terminal *t, int record) f->Set(si->call_order); f = f->next; f->Set(si->stocked); f = f->next; f->Set(si->allow_increase); f = f->next; - f->Set(si->ignore_split); + f->Set(si->ignore_split); f = f->next; + f->Set(si->out_of_stock); return 0; } @@ -1422,6 +1424,7 @@ int ItemListZone::SaveRecord(Terminal *t, int record, int write_file) f->Get(tmp); f = f->next; si->stocked = tmp; f->Get(tmp); f = f->next; si->allow_increase = tmp; f->Get(tmp); f = f->next; si->ignore_split = tmp; + f->Get(tmp); si->out_of_stock = tmp; if (item_name != si->item_name) { name_change = 1; diff --git a/zone/order_zone.cc b/zone/order_zone.cc index 6c0bbf32..744c0d62 100644 --- a/zone/order_zone.cc +++ b/zone/order_zone.cc @@ -1619,6 +1619,18 @@ RenderResult ItemZone::Render(Terminal *t, int update_flag) { FnTrace("ItemZone::Render()"); + // Handle out of stock color override + int saved_color[3]; + int color_modified = 0; + if (item && item->out_of_stock) { + int num_states = ZoneStates(); + for (int i = 0; i < num_states; i++) { + saved_color[i] = color[i]; + color[i] = COLOR_DK_RED; + } + color_modified = 1; + } + if (update_flag) { item = Item(&(t->system_data->menu)); @@ -1635,6 +1647,12 @@ RenderResult ItemZone::Render(Terminal *t, int update_flag) if (item == nullptr) { + if (color_modified) { + int num_states = ZoneStates(); + for (int i = 0; i < num_states; i++) { + color[i] = saved_color[i]; + } + } RenderZone(t, "", update_flag); return RENDER_OKAY; } @@ -1666,6 +1684,16 @@ RenderResult ItemZone::Render(Terminal *t, int update_flag) const char* zn = item->type == ITEM_ADMISSION ? "" : item->ZoneName(); const bool has_custom_image = ImagePath() && ImagePath()->size() > 0; + // Handle out of stock display + Str display_text; + genericChar str[256]; + if (item->out_of_stock) { + vt_safe_string::safe_format(str, 256, "%s - %s", zn, GlobalTranslate("Out of stock")); + display_text.Set(str); + } else { + display_text.Set(zn); + } + int font_width = 0; int font_height = 0; t->FontSize(font, font_width, font_height); @@ -1789,7 +1817,7 @@ RenderResult ItemZone::Render(Terminal *t, int update_flag) else { // Normal rendering without image - RenderZone(t, zn, update_flag); + RenderZone(t, display_text.Value(), update_flag); } // Continue with normal ItemZone rendering logic for pricing, etc. @@ -1895,6 +1923,15 @@ RenderResult ItemZone::Render(Terminal *t, int update_flag) t->RenderText(str, x + border, y + border + 45, col, FONT_TIMES_14, ALIGN_LEFT, w - border); } + + // Restore colors if modified + if (color_modified) { + int num_states = ZoneStates(); + for (int i = 0; i < num_states; i++) { + color[i] = saved_color[i]; + } + } + return RENDER_OKAY; }