This TFA example comprises a variety of tasks and services, some of which also include the use of the Point of Sale (POS) app

1 Introduction

A luxury hotel wants to manage their employees, with the goal of improving customer service. Their objective is to optimize work efficiency. In order to achieve their targets, the system will create an app used to monitor the performance of hotel room cleaning/maintenance.

2 User Registration

After creating the app, application users should be registered in the system, so as to be able to perform their assignments.

Admins ensure that the user to be registered on the app already exists on the server (if the user must be entered in the server, the manager must be notified). If the user is not yet registered on the server, it will be impossible to register them on the app.


Steps to be followed to register app users:


  • 1- Branch: A branch code must be defined for users in order to classify them in groups.



  • 2- User roles: App users will be granted a variety of different functional roles. Depending on the type of work employees have to perform, they will be given different permissions for app use.



  • 3- User registration: Once the above points have been handled, the user can be registered in the system. The form below must be filled in with the corresponding branch code and role code.



3 Tasks Created

At this point, the company has established the different measures they wish to evaluate. The four different tasks which employees should follow in order to be monitored will also be presented.


Instead of classifying the task by "GENERIC", a personal classification code can also be created if desired. See the ones created for this example:



3.1 Room Cleaning

A task will be created for hotel cleaning staff. Employees should mark, consecutively, when they have finished cleaning each part of the room. They should also indicate the guest's minibar consumption, and whether any issues were detected in the room.

3.1.1 First step: Task form configuration

Set all task values.



3.1.2 Second step: Groups

Set the names of the groups which will classify questions, as well as their conditions if needed. In this particular case, no conditions are required.



3.1.3 Third step: Questions

Set the questions which the user should answer.

Questions can be assigned to one of the previously-defined groups. The question type can be specified, and the system will indicate whether a response is obligatory. An activation condition (condition that, if true, will enable question display) can also be set.

This example uses the condition that if an issue arises, questions related to the incident will be displayed.

Question 11 is a POS question. With it, the employee indicates how many minibar items the customer purchased. Its code will indicate the type of ticket used (ECOM) and the label given to the POS button. (This question will be explained in further detail below.)

If an answer requires a combo-box/radio-button, see the fourth step.



As mentioned in the task, the POS transaction question type is also available. The POS is a module that manages receipts and documents. In this case, it will handle every receipt generated by the cleaning staff, indicating the customer who consumed minibar items.

To execute this question, certain parameters must first be defined:

1- STORE. The system will configure a store to know the source of the items sold.

This form should be filled out with all desired parameters.


2- TERMINAL. A store terminal must be defined.

However, it is first necessary to define the warehouse where products will be stored.


Next, the terminal can be defined:



3- RECEIPT TYPE. The system will automatically define four receipt types (see in the image below). However, it is also possible to define as many tickets as desired.

In this example, only one receipt type is used: ECOM. This receipt type indicates a customer's amount of consumption. As others indicate, it shows sales for a specific user, sales to customer, or a return receipt.


4- ITEMS. The items to be used in the task should be defined. There are two setup options: First, items can be defined by entering them in all the required system forms. Second, a configured Excel file can be uploaded to the system with all necessary information.

For this example, we have used the option to register them in the system by uploading an Excel file, which will have to follow the same structure as the TEMPLATE file to update correctly.

To start with, the "Download Excel file" form must be opened.


Path to access the form: Mobile / Point of Sales / Processes / Download Excel Files

The template file exists by default in the form. This file will help configure the information in the upload file.


The template file should be downloaded and filled in with the desired information.


The file downloaded should be saved and uploaded to the system. The uploaded file must be named and inserted into the form.


Once the file is in the form, it can be executed, uploading all items to the corresponding system tables.


The results of file execution can be viewed here (for example, new rows inserted into the tables, as well as updated rows).


3.1.4 Fourth step: Combos

For users to choose between a set of multiple answers, a combo must be created. See images below:

Create combo:



To set different answer options for the combo:



3.2 Room Cleaning (Manual)

This task is identical to the one above, with the exception that an extra group and question are added. The question is: Room Number?. They will be added, because it will exist the option for the employee to assign itself the task, using a widget button (this will be explained below, in Assignments), without being assigned by anyone.

The added question's response type is Soft Reference. This soft reference will be related to the list of customer codes, and will render a label in the task: "ROOM".



3.3 Maintenance

When the cleaning task is complete, if an issue/incident in the room is detected during the review phase, a service is created with the maintenance task. The service manager will assign the service to the corresponding maintenance employee.



3.3.1 Groups

The groups created for the task are found here.



3.3.2 Questions

The questions used for the task are defined below.

Some questions have an activation condition assigned. This condition will enable responses to the question, if the answer to the first question ("Incident resolved?") is "NO".

For this first question, a combo-box must be created, in the same way as in the Cleaning task.



3.4 Supervisor

The supervisor is defined as the person in charge of final room evaluation, and will check if staff fully and correctly cleaned the area.

After the cleaning task ends, the system will automatically create an assignment for the supervisor.

Below is the task created for the supervisor:



3.4.1 Groups

The groups created for the task are found here.



3.4.2 Questions

The questions used for the task are defined below.



3.4.3 Automatize Script

Script to automatize the creation of the supervisor's assignment, if no room issues/incidents have occurred.

Script Path: wic_hotel / Business logic / Scripts (hotel_sfa_responses_procesa)


Copy
<!-- ========================================================================== -->
<!--                                                                            -->
<!--    XSQL: hotel_sfa_responses_procesa                                       -->
<!--                                                                            -->
<!--                                                                            -->
<!-- ========================================================================== -->
<xsql-script name='hotel_sfa_responses_procesa'>

    <body>

        <!-- ======================================================================== -->
        <!-- Process responses                                                        -->
        <!-- ======================================================================== -->
        <foreach>
            <select prefix='m_'>
                <columns>
                    apps_sys_users.user_name,
                    apps_sfa_task_assign.assign_user,
                    apps_sfa_task_assign.assign_type,
                    apps_sfa_task_assign.assign_number,
                    apps_sfa_task_assign.assign_coment,
                    apps_sfa_task_assign.assign_customer customer_ori
                </columns>
                <from table='apps_sfa_task_assign'>
                    <join table='apps_sys_users'>
                        <on>apps_sfa_task_assign.assign_user = apps_sys_users.user_code</on>
                    </join>
                </from>
                <where>
                    apps_sfa_task_assign.assign_state = 2
                </where>
            </select>
            <do>

                <if>
                    <expr>
                        <not>
                            <select>
                                <columns>
                                    COUNT(*)
                                </columns>
                                <from table='apps_sfa_task_resl'/>
                                <where>
                                    apps_sfa_task_resl.assign_user    = <m_assign_user/>    AND
                                    apps_sfa_task_resl.assign_type    = <m_assign_type />   AND
                                    apps_sfa_task_resl.assign_number  = <m_assign_number /> AND
                                    apps_sfa_task_resl.response_state = 1
                                </where>
                            </select>
                        </not>
                    </expr>
                    <then>
                        <foreach.continue/>
                    </then>
                </if>

                <map name='map_a'/>
                <!-- ================================================================ -->
                <!-- Process responses and display on map                             -->
                <!-- ================================================================ -->
                <foreach>
                    <select prefix='m_'>
                        <columns>
                            apps_sfa_task_resh.task_code,
                            apps_sfa_task_resh.assign_customer,
                            apps_sfa_task_askl.ask_code,
                            apps_sfa_task_resl.response_text
                        </columns>
                        <from table='apps_sfa_task_resh'>
                           <join table='apps_sfa_task_askl'>
                                <on>apps_sfa_task_resh.task_code = apps_sfa_task_askl.task_code</on>
                                <join type='left' table='apps_sfa_task_resl'>
                                    <on>apps_sfa_task_resh.assign_user = apps_sfa_task_resl.assign_user</on>
                                    <on>apps_sfa_task_resh.assign_type = apps_sfa_task_resl.assign_type</on>
                                    <on>apps_sfa_task_resh.assign_number = apps_sfa_task_resl.assign_number</on>
                                    <on>apps_sfa_task_askl.ask_code = apps_sfa_task_resl.ask_code</on>
                                </join>
                            </join>

                        </from>
                        <where>
                           apps_sfa_task_resh.assign_user    = <m_assign_user/>   AND
                           apps_sfa_task_resh.assign_type    = <m_assign_type />  AND
                           apps_sfa_task_resh.assign_number  = <m_assign_number />
                        </where>
                    </select>
                    <do>
                        <map.put name='map_a'><string><m_ask_code/></string><string><m_response_text/></string></map.put>
                    </do>
                </foreach>

                <!-- ================================================================ -->
                <!--  Struct from map                                                 -->
                <!-- ================================================================ -->
                <!--
                <set name='s1'>
                    <struct.fromMap>
                        <map_a/>
                    </struct.fromMap>
                </set>
                -->

                <!-- ==================================================== -->
                <!-- Possible parseable tasks R001|VCOMP                  -->
                <!-- ==================================================== -->
                <switch name='m_task_code' regexp='true'>
                    <case value='ROOM'>

                        <!-- ============================================ -->
                        <!-- STRUCTURE                                    -->
                        <!-- ============================================ -->
                        <!-- (1)   ducha.clean                            -->
                        <!-- (1)   baño.clean                             -->
                        <!-- (1)   baño.papel                             -->
                        <!-- (1)   aseo.clean                             -->
                        <!-- (1)   aseo.consumibles                       -->
                        <!-- (1)   baño.toallas                           -->
                        <!-- (1)   baño.toallas_cambio                    -->
                        <!-- (2)   rec.clean                              -->
                        <!-- (2)   rec.armario                            -->
                        <!-- (3)   mini.clean                             -->
                        <!-- (4)   room.bed                               -->
                        <!-- (4)   room.room                              -->
                        <!-- (5)   terr.clean                             -->
                        <!-- (6)   room.alert                             -->
                        <!-- (6)   room.alert_zone                        -->
                        <!-- (6)   room.alert_notes                       -->
                        <!-- (6)   room.alert_man                         -->
                        <!-- (6)   room.alert_pic1                        -->
                        <!-- (6)   room.alert_pic2                        -->
                        <!-- ============================================ -->
                        <if>
                            <expr><isnotnull><map.get name='map_a'>room.alert_man</map.get></isnotnull></expr>
                            <then>
                                <if>
                                    <expr><map.get name='map_a'>room.alert_man</map.get></expr>
                                    <then>

                                        <select prefix='m_'>
                                            <columns>
                                                customer_name, customer_phone1, customer_contact, customer_email
                                            </columns>
                                            <from table='apps_customers'/>
                                            <where>
                                                customer_code = <m_customer_ori />
                                            </where>
                                        </select>
                                        <!-- =================================== -->
                                        <!-- Gen new service                     -->
                                        <!-- =================================== -->
                                        <insert table='apps_sfa_services'>
                                            <column name='service_id'>0</column>
                                            <column name='customer_code'><m_customer_ori /></column>
                                            <column name='task_code'>MAN001</column>
                                            <column name='service_coment'><map.get name='map_a'>room.alert_notes</map.get></column>
                                            <column name='service_date'><date.current /></column>
                                            <column name='service_time'>0</column>
                                            <column name='service_direcc'><m_customer_name/></column>
                                            <column name='service_contact'><m_user_name /></column>
                                            <column name='service_phone1'><m_customer_phone1 /></column>
                                            <column name='service_email'><m_customer_email /></column>
                                            <column name='service_docori'><string><m_assign_user />|<m_assign_type/>|<m_assign_number/></string></column>
                                        </insert>
                                    </then>

                                </if>
                            </then>
                            <else>
                                <!-- Send task to supervisor -->
                                <set name='m_user_code'>hotel.supervisor</set>
                                
                                <select prefix='m_'>
                                    <columns>
                                        customer_code, customer_name, customer_phone1, customer_contact, customer_email
                                    </columns>
                                    <from table='apps_customers'/>
                                    <where>
                                        customer_code = 'HOTEL'
                                    </where>
                                </select>

                                <!-- ============================================================ -->
                                <!--   Header                                                     -->
                                <!-- ============================================================ -->
                                <insert table='apps_sfa_task_assign'>
                                    <column name='assign_user'><m_user_code /></column>
                                    <column name='assign_type'>1</column>
                                    <column name='assign_number'>0</column>
                                    <column name='assign_desc'><m_customer_ori /></column>
                                    <column name='assign_customer'><m_customer_code /></column>
                                    <column name='task_code'>SUPERV</column>
                                    <column name='assign_date'><date.current /></column>
                                    <column name='assign_time'>10</column>
                                    <column name='assign_state'>1</column>
                                    <column name='assign_progress'>0</column>
                                    <column name='assign_coment'><null /></column>
                                    <column name='assign_tabori'><null /></column>
                                    <column name='assign_docori'><null /></column>
                                    <column name='date_to_sync'><date.current /></column>
                                </insert>

                            </else>
                        </if>

                    </case>
                    <case value='MAN001'>
                        <!-- ============================================ -->
                        <!-- STRUCTURE                                    -->
                        <!-- ============================================ -->
                        <!-- (1)   inci.solved                            -->
                        <!-- (1)   inci.notes                             -->
                        <!-- (2)   inci.time                              -->
                        <!-- (3)   inci.new_parte                         -->
                        <!-- (3)   inci.pic1                              -->
                        <!-- (3)   inci.pic2                              -->
                        <!-- ============================================ -->
                        <if>
                            <expr><isnotnull><map.get name='map_a'>inci.new_parte</map.get></isnotnull></expr>
                            <then>
                                <if>
                                    <expr><map.get name='map_a'>inci.new_parte</map.get></expr>
                                    <then>

                                        <select prefix='m_'>
                                            <columns>
                                                customer_name, customer_phone1, customer_contact, customer_email
                                            </columns>
                                            <from table='apps_customers'/>
                                            <where>
                                                customer_code = <m_customer_ori />
                                            </where>
                                        </select>


                                        <!-- =================================== -->
                                        <!-- Generate new service                     -->
                                        <!-- =================================== -->
                                        <insert table='apps_sfa_services'>
                                            <column name='service_id'>0</column>
                                            <column name='customer_code'><m_customer_ori /></column>
                                            <column name='task_code'>MAN001</column>
                                            <column name='service_coment'><map.get name='map_a'>inci.notes</map.get></column>
                                            <column name='service_date'><date.current /></column>
                                            <column name='service_time'>0</column>
                                            <column name='service_direcc'><m_customer_name/></column>
                                            <column name='service_contact'><m_user_name /></column>
                                            <column name='service_phone1'><m_customer_phone1 /></column>
                                            <column name='service_email'><m_customer_email /></column>
                                            <column name='service_docori'><string><m_assign_user />|<m_assign_type/>|<m_assign_number/></string></column>
                                        </insert>
                                    </then>

                                </if>
                            </then>
                            <else>
                                <!-- Send task to supervisor -->
                                <set name='m_user_code'>hotel.supervisor</set>
                                <!-- ============================================================ -->
                                <!-- Obtain last assignment number for user                       -->
                                <!-- ============================================================ -->
                                

                                <select prefix='m_'>
                                    <columns>
                                        customer_code, customer_name, customer_phone1, customer_contact, customer_email
                                    </columns>
                                    <from table='apps_customers'/>
                                    <where>
                                        customer_code = 'HOTEL'
                                    </where>
                                </select>

                                <!-- ============================================================ -->
                                <!--   Header                                                     -->
                                <!-- ============================================================ -->
                                <insert table='apps_sfa_task_assign'>
                                    <column name='assign_user'><m_user_code /></column>
                                    <column name='assign_type'>1</column>
                                    <column name='assign_number'>0</column>
                                    <column name='assign_desc'><string>MAN: <m_customer_ori /></string></column>
                                    <column name='assign_customer'><m_customer_code /></column>
                                    <column name='task_code'>SUPERV</column>
                                    <column name='assign_date'><date.current /></column>
                                    <column name='assign_time'>10</column>
                                    <column name='assign_state'>1</column>
                                    <column name='assign_progress'>0</column>
                                    <column name='assign_coment'><m_assign_coment /></column>
                                    <column name='assign_tabori'><null /></column>
                                    <column name='assign_docori'><null /></column>
                                    <column name='date_to_sync'><date.current /></column>
                                </insert>

                            </else>
                        </if>
                    </case>
                </switch>

                <update table='apps_sfa_task_assign'>
                   <column name='assign_state'>5</column>
                   <where>
                       assign_user = <m_assign_user/>  AND
                       assign_type = <m_assign_type/>  AND
                       assign_number = <m_assign_number/>
                   </where>
               </update>


            </do>
        </foreach>

    </body>
</xsql-script>

4 Assignments

Various options are available to create assignments for users. The options used to create a task assignment are explained below.


                                

Assignment Options

Loading...

4.1 Manual (Server)

Once all necessary tasks have been created, they must be assigned to a user. They will also need a specific time and date assigned to them.

The form should be filled in, with the chosen user, task, date and time. Then an assignment will be created.

To finalize the assignment, the CONFIRM button will have to be pressed. Like this, the assignment will be uploaded in the device, once it is synchronized.

No attributes, packages, and default values, are needed to be created in this assignment



OR


The option exists to create several assignments together simultaneously. This is achieved by loading many services to the server and processing them.

As explained in the Data Model section, to insert different services, an Excel file must be filled out with the structure specified in the template file.



RESULT:




4.2 Manual (Device - Widget Button)

Users manually create this assignment from their devices. This will create a widget button, allowing the user to create assignments when needed.

Steps for the creation of the widget button:

First step: Set trigger actions for the widget button to perform.

  • Create a Calendar in the Triggering folder. The actions that the triggers will perform are therefore within the selected date range.


  • Create the Trigger Actions. The widget button performs two actions:

    1- Assignment: Select an Assignment action. By pressing the widget button, this action creates the selected task in the device for the current time and date.

    2- Redirect: To simplify user interaction with the device, a Redirect action will be created. Pressing the widget button redirects the users to the current day task's screen.

    Actions must first be AUDITED before being assigned to widget buttons.


Second step: Select the users who can create their own assignments. A widget button will be created for them.



Third step: Fill in fields with the desired button label, the created trigger action, and the desired colors. (An image can also be set as the button icon.)

A set time before the button is executed can be configured by adding a countdown value. This will allow the user to cancel the execution of an action with advance notice, if it was accidentally or incorrectly activated.



RESULT:




4.3 Manual (Device - NFC)

As in the above point, this assignment will be created directly on the device. However, this will be accomplished by reading the NFC code unique to each room.

Steps for the creation of NFC code reading:

First step: set a trigger action for each hotel room.

The NFC Action will have to perform two actions:

1- Assignment: An Assignment action will be selected. This action will create a selected task in the device when the NFC is read, for the current time and date and a specified room.

2- Redirect: To simplify user interaction with the device, a Redirect Action will be created. As such, when the NFC code is read, it will redirect users to the current day's task screen.

Actions must first be AUDITED before being assigned.



Second step: create an NFC tag for each room.

This tag comprises the NFC code used to identify each room.



Third step: assign the NFC an action and a user.

Each NFC code must be assigned a user, an execution time range, and an action to perform.

A set time before the button is executed can be configured by adding a countdown value. This will allow the user to cancel the execution of an action with advance notice, if it was accidentally or incorrectly activated.




RESULT:



5 Monitoring

A monitor is created with the number of desired channels. This will provide a view of employees' workload to the hotel manager/administrator.



5.1 Daily Task List

This channel provides a view of the number of daily tasks for each employee, as well as the status of each task.

When a cleaning task is completed and revised, a supervision task (checking the room's status) is automatically assigned to the supervisor.



5.2 Current Day's Task Details

This channel will present more detailed information on the tasks assigned for the current day.



5.3 Current Day's Services

This channel provides a list of the services created for the current day.

Cleaning tasks are revised after being finalized. During revision, if an incident in the room is detected, a service with an assigned maintenance task is created. Consequently, the person in charge of Service channel management accesses the service form and assigns it to a corresponding maintenance employee.



5.4 Weekly Tasks

This channel will present detailed information on assigned tasks for the current week.



5.5 Examples

This section provides some examples to better understand monitoring functionality.

Creating these example assignments allows us to see UPDATES on the monitored channels.

5.5.1 Example I - Task with an Incident

1- Preparing an Assignment

Form: fill in the form with the desired parameters, then insert a new assignment.


Monitor:

2- Confirming an Assignment

Form: Confirm the assignment using the button below. It will then be created and assigned.


Monitor:

3- The assignment is confirmed and created on the device after syncing.

The task is performed, and an issue has been detected while cleaning the room.

4- The task has been completed; during revision, a room issue or incident is spotted.

As a result, a service is automatically created in the service list. The manager will decide which maintenance employee should handle service.



5- After studying the availability of all maintenance employees, the manager will use the Service monitoring channel to assign a user to the service created.

Click the number link (underlined) to access the Service Form:


Set a Service Form user:


Monitor:

6- The service is processed, and will be created on the device after syncing.

The maintenance user is set and confirmed to execute the assignment.

7- The service has been completed and revised.

Monitor Ended:


Monitor Revised:


5.5.2 Example II - Task with No Issues

The first steps for assignment preparation and creation will be identical to the past example.

The assignment is confirmed, then created on the device after synchronization.

The task is performed.

The task has been completed and revised, and no incident has been spotted in the room.

To confirm room status as complete, an assignment for the supervisor will be created automatically.



The supervisor assignment is confirmed, then created on the device after synchronization.

The task is performed, and the room status is complete. No incidents were spotted.

The supervisor assignment has been completed and revised.

Monitoring Complete:


Monitoring Revised: