pos/is4c-nf/lib/CoreState.php
<?php
/*******************************************************************************
Copyright 2001, 2004 Wedge Community Co-op
This file is part of IT CORE.
IT CORE is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
IT CORE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
in the file license.txt along with IT CORE; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*********************************************************************************/
namespace COREPOS\pos\lib;
use COREPOS\pos\lib\Database;
use COREPOS\pos\lib\DiscountModule;
use COREPOS\pos\lib\FormLib;
use COREPOS\pos\lib\MiscLib;
use COREPOS\pos\lib\models\op\TendersModel;
use \CoreLocal;
/**
@class CoreState
Setup session variables
*/
class CoreState
{
/**
Populates session with default values.
Short-hand for calling every other function
in this file. Normally called once on
startup.
*/
static public function initiateSession()
{
self::systemInit();
self::memberReset();
self::transReset();
self::printReset();
Database::getsubtotals();
Database::loadglobalvalues();
self::loadData();
self::customReceipt();
self::loadParams();
}
/**
Initialize system default values in
session. Variables defined here
should always exist but won't be reset
to these values on a regular basis.
*/
static public function systemInit()
{
/**
@var standalone
indicates whether the server
database is available.
- 0 => server is available
- 1 => server is not available
*/
CoreLocal::set("standalone",0);
/**
@var currentid
localtemptrans.trans_id for current
cursor position
*/
CoreLocal::set("currentid",1);
/**
@var currenttopid
localtemptrans.trans_id for the first
item currently shown on screen
*/
CoreLocal::set("currenttopid",1);
/**
@var training
Lane is in training mode
- 0 => not in training mode
- 1 => in training mode
*/
CoreLocal::set("training",0);
/**
@var SNR
Scale Not Ready. Set a non-zero value
(normally a UPC) to be entered when
the scale settles on a weight
*/
CoreLocal::set("SNR",0);
/**
@var weight
Currently scale weight (as float)
*/
CoreLocal::set("weight",0);
/**
@var scale
Scale has a valid weight
- 0 => scale error or settling
- 1 => scale settled on weight
*/
CoreLocal::set("scale",1);
/**
@var plainmsg
Lines of text to display on
main POS screen (pos2.php) that
are not part of a transaction. Used
for things like messages after signing
on or finishing/canceling/suspending a
transaction
*/
CoreLocal::set("plainmsg","");
/**
* @var perfLog
* Logging for performance metrics
*/
CoreLocal::set('perfLog', array());
/**
* @var portOverrides
* Track port re-negotiation
*/
CoreLocal::set('portOverrides', array());
/**
Load lane and store numbers from LaneMap array
if present
*/
if (is_array(CoreLocal::get('LaneMap'))) {
$myIPs = MiscLib::getAllIPs();
foreach ($myIPs as $ip) {
if (!isset($map[$ip])) {
continue;
}
if (isset($map[$ip]['register_id']) && isset($map[$ip]['store_id'])) {
CoreLocal::set('laneno', $map[$ip]['register_id']);
CoreLocal::set('store_id', $map[$ip]['store_id']);
}
// use first matching IP
break;
}
}
}
/**
Initialize transaction variable in session.
This function is called after the end of every
transaction so these values will be the
the defaults every time.
*/
static public function transReset()
{
/**
@var End
Indicates transaction has ended
0 => transaction in progress
1 => transaction is complete
*/
CoreLocal::set("End",0);
/**
@var memberID
Current member number
*/
CoreLocal::set("memberID","0");
/**
@var TaxExempt
Tax exempt status flag
0 => transaction is taxable
1 => transaction is tax exempt
*/
CoreLocal::set("TaxExempt",0);
/**
@var yousaved
Total savings on the transaction (as float).
Includes any if applicable:
- transaction level percent discount
- sale prices (localtemptrans.discount)
- member prices (localtemptrans.memDiscount)
*/
CoreLocal::set("yousaved",0);
/**
@var couldhavesaved
Total member savings that were not applied.
Consists of localtemptrans.memDiscount on
non-member purchases
*/
CoreLocal::set("couldhavesaved",0);
/**
@var specials
Total saving via sale prices. Consists
of localtemptrans.discount and when applicable
localtemptrans.memDiscount
*/
CoreLocal::set("specials",0);
/**
@var tare
Current tare setting (as float)
*/
CoreLocal::set("tare",0);
/**
@var change
Amount of change due (as float)
*/
CoreLocal::set("change",0);
/**
@var toggletax
Alter the next item's tax status
- 0 => do nothing
- 1 => change next tax status
*/
CoreLocal::set("toggletax",0);
/**
@var togglefoodstamp
Alter the next item's foodstamp status
- 0 => do nothing
- 1 => change next foodstamp status
*/
CoreLocal::set("togglefoodstamp",0);
/**
@var toggleDiscountable
Alter the next item's discount status
- 0 => do nothing
- 1 => change next discount status
*/
CoreLocal::set("toggleDiscountable",0);
/**
@var refund
Indicates current ring is a refund. This
is set as a session variable as it could
apply to items, open rings, or potentially
other kinds of input.
- 0 => not a refund
- 1 => refund
*/
CoreLocal::set("refund",0);
/**
@var multiple
Cashier used the "*" key to enter
a multiplier. This currently makes the
products.qttyEnforced flag work. This may
be redundant and the quantity setting below
is likely sufficient to determine whether
a multiplier was used.
*/
CoreLocal::set("multiple",0);
/**
@var quantity
Quantity for the current ring. A non-zero
value usually means the cashier used "*"
to enter a multiplier. A value of zero
gets converted to one unless the item requires
a quantity via products.scale or
products.qttyEnforced.
*/
CoreLocal::set("quantity",0);
/**
@var strEntered
Stores the last user input from the main
POS screen. Used in conjunction with the
msgrepeat option.
*/
CoreLocal::set("strEntered","");
/**
@var strRemembered
Value to use as input the next time
the main POS screen loads. Used in
conjunction with the msgrepeat
option.
*/
CoreLocal::set("strRemembered","");
/**
@var msgrepeat
Controls repeat input behavior
- 0 => do nothing
- 1 => set POS input to the value
in strRemembered
strEntered, strRemembered, and msgrepeat
are strongly interrelated.
When parsing user input on the main POS screen,
the entered value is always stored as strEntered.
msgrepeat gets used in two slightly different
ways. If you're on a page other than the main
screen, set msgrepeat to 1 and strRemembered to
the desired input, then redirect to pos2.php. This
will run the chosen value through standard input
processing.
The other way msgrepeat is used is with boxMsg2.php.
This page is a generic enter to continue, clear to
cancel prompt. If you redirect to boxMsg2.php and the
user presses enter, POS will set msgrepeat to 1 and
copy strEntered into strRemembered effectively repeating
the last input. Code using this feature will interpret
a msgrepeat value of 1 to indicate the user has given
confirmation.
msgrepeat is always cleared back to zero when input
processing finishes.
*/
CoreLocal::set("msgrepeat",0);
/**
@var lastRepeat
[Optional] Reason for the last repeated message
Useful to set & check in situations where multiple
confirmations may be required.
*/
CoreLocal::set('lastRepeat', '');
/**
@var boxMsg
Message string to display on the boxMsg2.php page
*/
CoreLocal::set("boxMsg","");
/**
@var itemPD
Line item percent discount (as integer; 5 = 5%).
Applies a percent discount to the current ring.
*/
CoreLocal::set("itemPD",0);
/**
@var cashierAgeOverride
This flag indicates a manager has given approval
for the cashier to sell age-restricted items. This
setting only comes into effect if the cashier is
too young. The value persists for the remainder of
the transaction so the manager does not have to give
approval for each individual item.
- 0 => no manager approval
- 1 => manager has given approval
*/
CoreLocal::set("cashierAgeOverride",0);
/**
@var voidOverride
This flag indicates a manager has given approval
for the cashier to void items beyond the per
transaction limit.
The value persists for the remainder of
the transaction so the manager does not have to give
approval for each individual item.
- 0 => no manager approval
- 1 => manager has given approval
*/
CoreLocal::set("voidOverride",0);
/**
@var lastWeight
The weight of the last by-weight item entered into
the transaction. It's used to monitor for scale
problems. Consecutive items with the exact same
weight often indicate the scale is stuck or not
responding properly.
*/
CoreLocal::set("lastWeight",0.00);
/**
* @var lotterySpin
* Set to a random value between 0 and 1 once per transaction
* Doing one "spin" per transaction allow for UI cues about
* the result before the end of the transaction
*/
CoreLocal::set('lotterySpin', false);
if (!is_array(CoreLocal::get('PluginList'))) {
CoreLocal::set('PluginList', array());
}
if (is_array(CoreLocal::get('PluginList'))) {
foreach(CoreLocal::get('PluginList') as $p) {
if (!class_exists($p)) continue;
$obj = new $p();
$obj->plugin_transaction_reset();
}
}
if (is_array(CoreLocal::get('Notifiers'))) {
foreach(CoreLocal::get('Notifiers') as $n) {
if (!class_exists($n)) continue;
$obj = new $n();
$obj->transactionReset();
}
}
FormLib::clearTokens();
DiscountModule::transReset();
}
/**
Initialize print related variables in session.
This function is called after the end of
every transaction.
*/
static public function printReset()
{
/**
@var receiptToggle
Control whether a receipt prints
- 0 => do not print receipt
- 1 => print receipt normally
Note that some kinds of receipts
such as credit card or store charge
signature slips cannot be suppressed
and will always print.
*/
$default = CoreLocal::get('receiptToggleDefault') !== '' ? CoreLocal::get('receiptToggleDefault') : 1;
CoreLocal::set("receiptToggle", $default);
/**
@var autoReprint
Print two receipts.
- 0 => do nothing
- 1 => print a copy of the receipt
*/
CoreLocal::set("autoReprint",0);
}
/**
Initialize member related variables in session.
This function is called after the end of
every transaction.
*/
static public function memberReset()
{
/**
@var memberID
The current member number
*/
CoreLocal::set("memberID","0");
/**
@var isMember
Indicates whether the current customer
is considered a member or just someone
who happens to have a number
0 - not considered a member
1 - is a member
This is controlled by custdata.Type. That
field must be 'PC' for the account to be
considered a member.
*/
CoreLocal::set("isMember",0);
/**
@var isStaff
Indicates whether the current customer is
an employee. Corresponds to custdata.staff.
*/
CoreLocal::set("isStaff",0);
/**
@var SSI
Corresponds to custdata.SSI for current
customer.
*/
CoreLocal::set("SSI",0);
/**
@var memMsg
Text string shown in the upper left of the
POS screen near the word MEMBER.
*/
CoreLocal::set("memMsg","");
/**
@var memType
Corresponds to custdata.memType for current
customer.
*/
CoreLocal::set("memType",0);
/**
@var balance
Current customer's charge account balance
owed.
*/
CoreLocal::set("balance",0);
/**
@var availBal
Current customer's available charge account
balance. This is equivalent to
custdata.ChargeLimit minus the balance
setting above.
*/
CoreLocal::set("availBal",0);
/**
@var percentDiscount
The current customer's transaction-level
percent discount as an integer (i.e., 5 = 5%).
Corresponds to custdata.Discount.
*/
CoreLocal::set("percentDiscount",0);
/**
@var memAge
Actually current customer's birthday
as YYYYMMDD but used to calculate age.
This is stored if the customer purchases
an age-restricted item.
*/
CoreLocal::set("memAge",date('Ymd'));
if (CoreLocal::get('AgeMode') == 'mdY') {
CoreLocal::set("memAge",date('mdY'));
}
}
/**
If there are records in localtemptrans, get the
member number and initialize session member
variables.
The only time this function does anything is
in crash recovery - if a browser is closed and
re-opened or the computer is rebooted in the
middle of a transaction.
*/
static public function loadData()
{
$queryLocal = "select card_no from localtemptrans";
$dbLocal = Database::tDataConnect();
$resultLocal = $dbLocal->query($queryLocal);
$numRowsLocal = $dbLocal->numRows($resultLocal);
if ($numRowsLocal > 0) {
$rowLocal = $dbLocal->fetchRow($resultLocal);
if ($rowLocal["card_no"] && strlen($rowLocal["card_no"]) > 0) {
\COREPOS\pos\lib\MemberLib::setMember($rowLocal['card_no'], 1);
}
}
}
/**
Fetch text fields from the customReceipt table
These fields are used for various messages that
invariably must be customized at every store.
*/
static public function customReceipt()
{
$dbc = Database::pDataConnect();
$headerQ = "select text,type,seq from customReceipt order by seq";
$headerR = $dbc->query($headerQ);
$counts = array();
while($headerW = $dbc->fetch_row($headerR)) {
$typeStr = $headerW['type'];
$numeral = $headerW['seq']+1;
$text = $headerW['text'];
// translation for really old data
if (strtolower($typeStr)=="header") {
$typeStr = "receiptHeader";
} elseif(strtolower($typeStr)=="footer") {
$typeStr = "receiptFooter";
}
CoreLocal::set($typeStr.$numeral,$text);
if (!isset($counts[$typeStr])) {
$counts[$typeStr] = 0;
}
$counts[$typeStr]++;
}
foreach($counts as $key => $num) {
CoreLocal::set($key."Count",$num);
}
}
static public function getCustomerPref($key)
{
if (!CoreLocal::get('memberID')) {
return '';
}
$dbc = Database::pDataConnect();
$prep = $dbc->prepare('SELECT pref_value FROM custPreferences WHERE
card_no=? AND pref_key=?');
$args = array(CoreLocal::get('memberID'),$key);
$val = $dbc->getValue($prep, $args);
return $val === false ? '' : $val;
}
static public function cashierLogin($transno=False, $age=0)
{
if (CoreLocal::get('CashierNo')==9999) {
CoreLocal::set('training', 1);
}
if (!is_numeric($age)) {
$age = 0;
}
CoreLocal::set('cashierAge', $age);
if($transno && is_numeric($transno)) {
CoreLocal::set('transno', $transno);
}
}
static private function setParams($parameters)
{
foreach ($parameters->find() as $global) {
$key = $global->param_key();
$value = $global->materializeValue();
CoreLocal::set($key, $value, true);
}
}
static public function loadParams()
{
$dbc = Database::pDataConnect();
// newer & optional table. should not fail
// if it's missing
if (CoreLocal::get('NoCompat') != 1 && !$dbc->table_exists('parameters')) {
return;
}
// load global settings first
$parameters = new \COREPOS\pos\lib\models\op\ParametersModel($dbc);
$parameters->lane_id(0);
$parameters->store_id(0);
self::setParams($parameters);
// apply store-specific settings next
// with any overrides that occur
$parameters->reset();
$parameters->store_id(CoreLocal::get('store_id'));
$parameters->lane_id(0);
self::setParams($parameters);
// apply lane-specific settings last
// with any overrides that occur
$parameters->reset();
$parameters->lane_id(CoreLocal::get('laneno'));
$parameters->store_id(0);
self::setParams($parameters);
// load tender map from tenders instead of parameters
$map = array();
if (CoreLocal::get('NoCompat') == 1) {
$model = new TendersModel($dbc);
$map = $model->getMap();
} else {
$table = $dbc->tableDefinition('tenders');
if (isset($table['TenderModule'])) {
$model = new TendersModel($dbc);
$map = $model->getMap();
}
}
if (count($map) > 0 || !is_array(CoreLocal::get('TenderMap'))) {
CoreLocal::set('TenderMap', $map);
}
}
}