Log when cash register is opened

Anybody know a good way to log when the cash register drawer is opened?.. We have a no sale button created to kick the drawer and print a receipt with the username and when the drawer was opened but I’d like to be able to get a report of it as well some how just in case someone gets to throw the receipt away.

Maybe this is what you are looking for:

You can also simply use the Action for Add Line to Text File to keep a log of whenever the No Sale buttons is clicked.

Well that works… I have the date, time and current user logged… I’d like to really turn this into the cash drawer log… Have it log every time the no sale button is pressed which it does but also log when cash button is pressed or any other button that opens the drawer. I was able to log for those too but is there a variable for what button is pressed so I can log that in the text file as well?

Buttons are Automation Commands.
You could make a (non-constrained) Rule for the event of Automation Command Executed.
The button name is stored in [:AutomationCommandName].

The problem with having in non-constrained is that you will be logging a lot of events, even those that are Automation Commands, but are not actually buttons. So you may want to have multiple Constraints, set the Rule to Matches Any, and list each button that you want to log.

Event: Automation Command Executed
Execute Rule if: Matches Any
Automation Command Name Equals No Sale
Automation Command Name Equals Close
Automation Command Name Equals Cash
Automation Command Name Equals Credit Card
… etc.

I was actually able to add it to the rule for when the a receipt is printed since that is how to register is opened. Since all those rules are separate i just edit the No Sale rule to add the appropriate text for each item. works for adding those items to a text log… Id really love for this to be in samba so that I can just create a report for viewing all this but Im not even sure where to begin.

This is the log file:

Ticket Logs have a Report Tag to read the Ticket Log: {REPORT TICKET LOG DETAILS}

But there is no method to Report on a File. You would need to build something in JScript to read and parse the file, then return the data to a Report Widget, Label, or Button Caption, etc.

I was thinking more of just not even recording the logs to a text file but to just store it in samba. I know I can create a log in a ticket but I also have the no sale button outside of tickets from the entity screen so currently this is the only way I’ve found to log when the no sale button is pressed. One thought I had was to create a entity and log all this under that entity but I’m not sure how to do this or even if we can do this or if it’s required to have a ticket to log things against.

You can also use Tasks to create logs. I do not have a tutorial because I have no built this yet but it is possible. Tasks can be used anywhere especially outside of tickets.

1 Like

Good idea. You should be able to use Entity State Logging. We use this Action for the Time Clock, so it does not require a Ticket. And there is a Report Tag to read State Logs.

So for the arrows you would do something like Cash Drawer open for the name and the custom data would be the information that I want logged like {DATE} - {TIME} - {:CURRENTUSER} - AND BUTTON PRESSED?.. I havent messed much with loggin entity information so im sure that im missing alot of steps other then setting up something similar to your screen shots.

You can place pretty much any kind of data you desire in any of the fields other than the 2 Date fields - the Start/End Date fields will only accept Date/Time formatted data because of the field Datatype.

The Date fields will already contain the Date/Time the State is logged if you leave the Action and Rule configured as shown, so you don’t need to set those explicitly anywhere else.

The Name field we used as an identifier. This way when we Report, we filter records by the Name so we don’t mix TimeClock with DrawerOpen. Keep this consistent at all times; something like ButtonPress or DrawerKick or whatever - you will use the Name to filter your Report.

The State Name (Group) and State fields can also store whatever you like, and in your case, they are rather arbitrary. You could even put a Username in there if you wanted, but it might be more useful to store the button name as the State and Username as the State Name (Group).

The CustomData field is intended to contain whatever you like, that has nothing to do with States or Entities.


Where you are logging to file, instead you would insert an Update Entity State Action and set the State to whatever you like. Maybe set the State to the name of the button or operation that caused the drawer to open, and State Name to the Username. Of course, set the Entity to the name of the Entity that you have defined for the purpose of logging.

Then you create a Rule for Entity State Updated and place the Log Entity State Action in there. Constrain the Rule to only act on the Entity that you defined for purpose of this log.

Here, try this:

##Log Result


##Entity Setup


##EL Update Entity State [Update Entity State] (Action)##

Action Name: EL Update Entity State
Action Type: Update Entity State
###Parameters:###
Entity Type Name: Loggers
Entity Name: [:EntityName]
Entity State Name: [:StateGroup]
Current State: [:CurrentState]
Entity State: [:NewState]
Quantity Exp:

##EL LogEntityState [Log Entity State] (Action)##

Action Name: EL LogEntityState
Action Type: Log Entity State
###Parameters:###
Name: [:Name]
Entity Id: [:EntityId]
State Name: [:SGroupName]
Start State: [:StateBeg]
Start State Date: [:SDateBeg]
End State: [:StateEnd]
End State Date: [:SDateEnd]
Custom Data: [:SCustomData]
Async: [:Async]

##Update the State

##EL Open Drawer [Automation Command Executed] (Rule)##

Rule Name: EL Open Drawer
Event Name: Automation Command Executed
Rule Tags:
Custom Constraint List (1):
Execute Rule if: Matches
Automation Command Name Equals Open Drawer

##Actions:##

EL Update Entity State

Constraint: (none)

EntityName: DrawerKick
StateGroup: {:CURRENTUSER}
CurrentState:
NewState: [:AutomationCommandName]

##Log the State

##EL LogEntityState [Entity State Updated] (Rule)##

Rule Name: EL LogEntityState
Event Name: Entity State Updated
Rule Tags: Timeclock
Custom Constraint List (1):
Execute Rule if: Matches
Entity Type Name Equals Loggers

##Actions:##

EL LogEntityState

Constraint: (none)

Name: POSaction
EntityId: [:EntityId]
SGroupName: [:StateName]
StateBeg: [:StartState]
SDateBeg: [:StartStateDate]
StateEnd: [:EndState]
SDateEnd: [:EndStateDate]
SCustomData: [:EntityName] - TEST
Async:

Here, try this:



##EL Update Entity State [Update Entity State] (Action)##

Action Name: EL Update Entity State
Action Type: Update Entity State
###Parameters:###
Entity Type Name: Loggers
Entity Name: [:EntityName]
Entity State Name: [:StateGroup]
Current State: [:CurrentState]
Entity State: [:NewState]
Quantity Exp:

##EL LogEntityState [Log Entity State] (Action)##

Action Name: EL LogEntityState
Action Type: Log Entity State
###Parameters:###
Name: [:Name]
Entity Id: [:EntityId]
State Name: [:SGroupName]
Start State: [:StateBeg]
Start State Date: [:SDateBeg]
End State: [:StateEnd]
End State Date: [:SDateEnd]
Custom Data: [:SCustomData]
Async: [:Async]

##EL Open Drawer [Automation Command Executed] (Rule)##

Rule Name: EL Open Drawer
Event Name: Automation Command Executed
Rule Tags:
Custom Constraint List (1):
Execute Rule if: Matches
Automation Command Name Equals Open Drawer

##Actions:##

EL Update Entity State

Constraint: (none)

EntityName: DrawerKick
StateGroup: {:CURRENTUSER}
CurrentState:
NewState: [:AutomationCommandName]

##EL Open Drawer on Payment Processed [Payment Processed] (Rule)##

Rule Name: EL Open Drawer on Payment Processed
Event Name: Payment Processed
Rule Tags:
Custom Constraint List (1):
Execute Rule if: Matches
Payment Type Name Not Equals Customer Account

##Actions (1):##

EL Update Entity State

Constraint: (none)

EntityName: DrawerKick
StateGroup: {:CURRENTUSER}
CurrentState:
NewState: Payment Processed - [:PaymentTypeName]

##EL LogEntityState [Entity State Updated] (Rule)##

Rule Name: EL LogEntityState
Event Name: Entity State Updated
Rule Tags: Timeclock
Custom Constraint List (1):
Execute Rule if: Matches
Entity Type Name Equals Loggers

##Actions:##

EL LogEntityState

Constraint: (none)

Name: POSaction
EntityId: [:EntityId]
SGroupName: [:StateName]
StateBeg: [:StartState]
SDateBeg: [:StartStateDate]
StateEnd: [:EndState]
SDateEnd: [:EndStateDate]
SCustomData: [:EntityName] - TEST
Async:

#Report

[Logs:1,1,1,1,1,1,1]
>Ent|LogName|User (SName)|Command (EState)|DT|TM|Data
{REPORT ENTITY STATE DETAILS:L.EntityName,L.Name,L.StateName,L.EndState,L.EndDate,L.EndTime,L.CustomData:(ELN=POSaction)}

Actually the more I look at this the more I think loggin this with Tasks would be more simple. I actually was able to create a task and log what I want… but im not sure how to format the report to view the Time, Date, and Current User and If it was No Sale, Cash or Credit.

Up to you, but the Entity State Log works very well for this. It does most of the work for you already IMO.

  • 2 Actions
  • Update State
  • Log State
  • 1 Rule
  • Log State change
  • x Rules to Update Entity State.

I just need to find the Report Tag so SQL isn’t required to read it…

Ill give this a shot as well, Thanks for the walkthrough. I was starting to look at tasks because I could get it working with that like this…

Not 100% clean or perfect but it was a start. Your way may be better. As long as I can pull it up in a report.

  • We named the log entries as POSaction so we can filter on that.
  • We are logging State updates to the Entity named DrawerKick.
  • We stored the Username as the State Name
  • We stored the “action” or “button” as the End State
[Logs:1,1,1,1,1,1,1]
@ Q,Courtice,Ovania
>Ent|LogName|User (SName)|Command (EState)|DT|TM|Data
{REPORT ENTITY STATE DETAILS:L.EntityName,L.Name,L.StateName,L.EndState,L.EndDate,L.EndTime,L.CustomData:(ELSN=$1) AND (ELN=POSaction)}

This line list Users. They are expanded one at a time into $1
@ Q,Courtice,Ovania

This constraint causes the User list to be grouped per user:
(ELSN=$1)
Because we are pulling records based on the User list, the timestamps are out of order between 1 user and another, but they are in order for that particular user.

This constraint shows only Entity Logs belonging to the Name POSaction:
(ELN=POSaction)

:warning: This is going to appear to not work the very first time. But from the second time the State is updated, it will continue to log properly.

:bulb: There are other ways to arrange this obviously. You could store different things in different fields and read and filter it however you like. But the concept is actually a very good one, and a decent use for State Logging that is simple to set up.

:exclamation: Of course, Tasks could be used as well, but you will first need to define Custom Fields for the different pieces you want to store. As it turns out, State Logs already have all the fields you need.

Let’s see what we can do with Tasks

##Task Type

##Action

##Rule

customFields: Terminal={:CURRENTTERMINAL},User={:CURRENTUSER},Action=[:AutomationCommandName],ADate={DATE:yyyy-MM-dd HH:mm:ss}


##Database:

##Report

[TaskLog:1,1,1,1,1,1,1,1,1,1]
>TaskType|TaskUser|TaskName|Date|Time|CFterminal|CFuser|CFaction|CFadate|TaskContent
{REPORT TASK DETAILS:T.TaskType,T.UserName,T.Name,T.StartDate,T.StartTime,TSC.Terminal,TSC.User,TSC.Action,TSC.ADate,T.ContentText:(TST=POSactions)}


Well that was easy.

In retrospect, that was at least as simple to set up as Entity State Logging. Maybe even easier. :stuck_out_tongue_winking_eye:

1 Like