Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)

## [Unreleased]

### Work In Progress
- **Allow Multiple Terminal Logins (experimental)** (2026-04-12)
- Added a persisted soft-switch `allow_multi_login` (bumped `SETTINGS_VERSION` to 107) which allows the same `Employee` to be logged into multiple terminals when enabled.
- Exposed a new Settings switch **Allow Multiple Logins** in the Settings UI (toggles and persists immediately).
- Login logic updated so `Terminal::LoginUser` and login UI checks consult `settings->allow_multi_login` before rejecting a login for a user already online.
- Files modified: `main/data/settings.hh`, `main/data/settings.cc`, `main/ui/labels.cc`, `zone/settings_zone.cc`, `main/hardware/terminal.cc`, `zone/login_zone.cc`.
- NOTE: This feature is experimental and a work in progress — bugs are likely. Use with caution and report any issues you encounter.

### Fixed
- **Auto-Update vt_data: Prevent automatic updates when disabled (2026-04-09)**
- Fixed unexpected vt_data downloads/updates triggered when restarting or shutting down from non-server displays even when "Auto-Update vt_data on Startup" is OFF.
Expand Down
4 changes: 4 additions & 0 deletions main/data/settings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1459,6 +1459,7 @@ Settings::Settings()
expire_message3.Set("541-515-5913");
expire_message4.Set("");
allow_multi_coupons = 0;
allow_multi_login = 0;
cc_print_custinfo = 0;

for (i = 0; i < MAX_CDU_LINES; i++)
Expand Down Expand Up @@ -2132,6 +2133,8 @@ int Settings::Load(const char* file)
df.Read(report_start_midnight);
if (version >= 79)
df.Read(allow_multi_coupons);
if (version >= 107)
df.Read(allow_multi_login);
if (version >= 82)
df.Read(allow_iconify);
if (version >= 96)
Expand Down Expand Up @@ -2527,6 +2530,7 @@ int Settings::Save()
df.Write(cc_bar_mode);
df.Write(report_start_midnight);
df.Write(allow_multi_coupons);
df.Write(allow_multi_login);
df.Write(allow_iconify);
df.Write(use_embossed_text);
df.Write(use_text_antialiasing);
Expand Down
6 changes: 5 additions & 1 deletion main/data/settings.hh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
// NOTE: WHEN UPDATING SETTINGS DO NOT FORGET that you may also
// need to update archive.hh and archive.cc for settings which
// should be maintained historically.
constexpr int SETTINGS_VERSION = 106; // READ ABOVE
constexpr int SETTINGS_VERSION = 107; // READ ABOVE


/**** Definitions & Data ****/
Expand Down Expand Up @@ -166,6 +166,7 @@ enum DrawerMode : std::uint8_t {
#define SWITCH_F3_F4_RECORDING 32 // whether to enable F3/F4 recording/replay feature
#define SWITCH_AUTO_UPDATE_VT_DATA 33 // whether to automatically download vt_data on startup
#define SWITCH_BUTTON_IMAGES 34 // toggle showing images on buttons
#define SWITCH_ALLOW_MULTI_LOGIN 35 // allow same user to login on multiple terminals

#define MOD_SEPARATE_NL 1 // New line
#define MOD_SEPARATE_CM 2 // Comma
Expand Down Expand Up @@ -624,6 +625,9 @@ public:
int split_check_view; // default to item or seat list for SplitCheckZone?
int allow_multi_coupons;

// Allow same employee to be logged into multiple terminals when set
int allow_multi_login;

// allow_user_select is primarily for ExpenseZone, but may be used elsewhere
int allow_user_select; // yes == user selection, no == force term->user

Expand Down
11 changes: 10 additions & 1 deletion main/hardware/terminal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2043,7 +2043,16 @@ int Terminal::LoginUser(Employee *employee, bool home_page)
if (AllowLogins == 0)
return 1;

if (employee == nullptr || (user != employee && parent->IsUserOnline(employee)))
if (employee == nullptr)
return 1;

// Check whether multiple logins are allowed via settings
Settings *s = GetSettings();
int allow_multi = 0;
if (s)
allow_multi = s->allow_multi_login;

if (user != employee && parent != nullptr && parent->IsUserOnline(employee) && !allow_multi)
return 1; // User already online on another terminal

if (user != nullptr && user != employee)
Expand Down
2 changes: 2 additions & 0 deletions main/ui/labels.cc
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ const genericChar* SwitchName[] = {
"24 Hour Mode", "Item Targeting",
"Expand Goodwill Adjustments", "Monetary Symbol",
"Show Modifiers", "Allow Multiple Coupons",
"Allow Multiple Logins",
"Print All Modifiers on Receipt", "Auto Print Drawer Report",
"Balance Automatic Coupons", "Enable F3/F4 Recording/Replay", "Auto-Update vt_data on Startup",
"Show Button Images", nullptr};
Expand All @@ -462,6 +463,7 @@ int SwitchValue[] = {
SWITCH_MEASUREMENTS, SWITCH_AUTHORIZE_METHOD, SWITCH_24HOURS,
SWITCH_ITEM_TARGET, SWITCH_GOODWILL, SWITCH_MONEY_SYMBOL,
SWITCH_SHOW_MODIFIERS, SWITCH_ALLOW_MULT_COUPON,
SWITCH_ALLOW_MULTI_LOGIN,
SWITCH_RECEIPT_ALL_MODS, SWITCH_DRAWER_PRINT,
SWITCH_BALANCE_AUTO_CPNS, SWITCH_F3_F4_RECORDING, SWITCH_AUTO_UPDATE_VT_DATA,
SWITCH_BUTTON_IMAGES, -1};
Expand Down
6 changes: 3 additions & 3 deletions zone/login_zone.cc
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ int LoginZone::ClockOn(Terminal *term, int job_no)
}
else
{
if (term->IsUserOnline(employee) && term->user != employee)
if (term->IsUserOnline(employee) && term->user != employee && !settings->allow_multi_login)
{
state = STATE_ON_ANOTHER_TERM;
Draw(term, 0);
Expand Down Expand Up @@ -494,7 +494,7 @@ int LoginZone::ClockOff(Terminal *term)
state = STATE_NOT_ON_CLOCK;
else if (sys->CountOpenChecks(employee) > 0)
state = STATE_OPEN_CHECK;
else if (term->IsUserOnline(employee) && term->user != employee)
else if (term->IsUserOnline(employee) && term->user != employee && !sys->settings.allow_multi_login)
state = STATE_ON_ANOTHER_TERM;
else if (term->NeedDrawerBalanced(employee))
state = STATE_NEED_BALANCE;
Expand Down Expand Up @@ -634,7 +634,7 @@ int LoginZone::Start(Terminal *term, short expedite)

return 0;
}
else if (term->IsUserOnline(employee))
else if (term->IsUserOnline(employee) && !settings->allow_multi_login)
{
// user already logged into another term
state = STATE_ON_ANOTHER_TERM;
Expand Down
8 changes: 8 additions & 0 deletions zone/settings_zone.cc
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ RenderResult SwitchZone::Render(Terminal *term, int update_flag)
case SWITCH_ALLOW_MULT_COUPON:
onoff = settings->allow_multi_coupons;
break;
case SWITCH_ALLOW_MULTI_LOGIN:
onoff = settings->allow_multi_login;
break;
case SWITCH_RECEIPT_ALL_MODS:
onoff = settings->receipt_all_modifiers;
break;
Expand Down Expand Up @@ -595,6 +598,11 @@ SignalResult SwitchZone::Touch(Terminal *term, int /*tx*/, int /*ty*/)
case SWITCH_ALLOW_MULT_COUPON:
settings->allow_multi_coupons ^= 1;
break;
case SWITCH_ALLOW_MULTI_LOGIN:
settings->allow_multi_login ^= 1;
// Persist immediately so change survives restarts
settings->Save();
break;
case SWITCH_RECEIPT_ALL_MODS:
settings->receipt_all_modifiers ^= 1;
break;
Expand Down
Loading