6 Customisation

1. Workflow outsend data

Sometime, after workflow approved or ended, data need to update to 3rd party system

  1. Outsend type -> URL

  2. Outsend address -> the php file path

  1. Reimbursement workflow complete, generate finance voucher in accouting system

  2. Leave application completed, update leave days in HR system

Here is an example to outsend data for license generate

<?php
/**
 * Send data to external system demo
 * Outsend data to url address example: http://127.0.0.1:8010/eoffice/server/ext/data_out/data_outsend.php
 * @author Weaver International
 * @Date 06/12/2023
 */

// $_REQUEST Workflow outsend data,the data structure example in POST
/*
{
    // Database table id
    "id": "2",
    // Workflow id, unicode
    "run_id": "2313",
    // Format: DATA_(number)  mean the form control data, DATA_(Number) means control id
    "DATA_1": "Sysadmin",
    "DATA_2": "IT Department",
    "DATA_3": "Meeting title",
    "DATA_4": "",
    "DATA_5": "",
    "DATA_6": "2018-03-15",
    "DATA_7": "00:00",
    "DATA_8": "2018-03-16",
    "DATA_9": "00:00",
    // Control type: user selector, value is user id concat string
    "DATA_10": "WV00000009,WV00000002,WV00000001",
    // DATA_10 Control corresponding user name string, match with user id
    "DATA_10_TEXT": "Mike Tan,Sheily Wong,John David",
    "DATA_14": "Approval",
    // Countersign control, each element is a countersign content
    "DATA_15": [
        {
            // countersign_id
            "countersign_id": "384",
            // Content
            "countersign_content": "<p>Approve</p>",
            // countersign_user_id
            "countersign_user_id": "admin",
            // countersign_user complete information, user_id and username
            "countersign_user": {
                "user_id": "admin",
                "user_name": "System admin"
            },
            // countersign_time
            "countersign_time": "2018-03-15 14:49:33",
            // Workflow id
            "run_id": "2313",
            // Step id
            "process_id": "1",
            // Node id
            "flow_process": "709",
            // countersign_control_id
            "countersign_control_id": "DATA_15"
        }
    ],
    //Workflow name
    "run_name": "cesi-copy-Meeting application(system intetration)(2018-03-15 14:49:33:System admin)",
    // workflow id
    "flow_id": "3131",
    // Form id
    "form_id": "2008",
    // workflow node name
    "process_name": "Meeting application",
    // Current user information
    "userInfo": {
        // user id
        "user_id": "admin",
        // username
        "user_name": "System admin",
        // Account
        "user_accounts": "admin",
        // Department
        "dept_name": "IT Department",
        // Department id
        "dept_id": "25",
        // Role name, if multiple role, split by comma
        "role_name": "[OA Admin,Accounting]",
        // Role id,if multiple role, split by comma
        "role_id": "[1,37]"
    }
}
*/

/**
 * Default method,import laravel related environment, the path is relevant path, adjust base on actual case
 * __DIR__ value example: D:\e-office11\www\eoffice\server\ext\data_out
 * Complete path: D:\e-office11\www\eoffice\server\bootstrap\app.php
 */
require __DIR__ . '/../../bootstrap/app.php';
// Default, import database
use Illuminate\Support\Facades\DB;

// Via $_REQUEST method to get relevant data
$data = (isset($_REQUEST) && !empty($_REQUEST)) ? $_REQUEST : [];
// log file path: D:\e-office11\www\eoffice\server\storage\logs\
$logDir = base_path('/storage/') . 'logs/';
if(empty($data)) {
    // If there is not data, record error message in D:\e-office11\www\eoffice\server\storage\logs\licenseDownQuery_log.txt 
    file_put_contents($logDir."licenseDownQuery_log.txt","Data error, outsend failed",FILE_APPEND);
    exit();
}
// Get outsend data example
// workflow id
$run_id    = isset($data["run_id"]) ? $data["run_id"] : "";
// Workflow current node
$flow_prcs = isset($data["node_id"]) ? $data["node_id"] : "";
// Workflow step id
$prcs_id   = isset($data["process_id"]) ? $data["process_id"] : "";

// Concat parameter base on business requirements
// license identification code, relevant control id DATA_100, other control is the same
$serverCode = isset($data["DATA_100"]) ? $data["DATA_100"] : "";
$serverCode = trim($serverCode);
// Get customer id
$customerId = isset($data["DATA_101"]) ? $data["DATA_101"] : "";
// Based on customer id,get customer information in customer table
$customerInfo = DB::select("select * from customer where customer_id = '".$customerId."'");
$customerInfo = json_decode(json_encode($customerInfo),true);
if(count($customerInfo) && !empty($customerInfo[0])) {
    $customerInfo = $customerInfo[0];
}
// Customer name
$customerName = isset($customerInfo["customer_name"]) ? $customerInfo["customer_name"] : "";
if($customerName == "") {
    // Exception, record error message
    file_put_contents($logDir."licenseDownQuery_log.txt","Customer name is black,outsend faild;workflow id:".$run_id."。",FILE_APPEND);
    exit();
}
// Server name with customer name
$serverName = $customerName;
// license file end date
$expireDate = isset($data["DATA_102"]) ? $data["DATA_102"] : "";
if(!$expireDate || $expireDate == "")
    $expireDate = "2115-05-25";
// Server address
$serverIp = isset($data["DATA_103"]) ? $data["DATA_103"] : "";
// port
$serverPort = isset($data["DATA_104"]) ? $data["DATA_104"] : "";
// Server key word eoffice
$serverKey = "Weaver eoffice";
// license Mobile concurrent uer license
$maxUserOnlineCount = "";
// license user license
$maxUserCount = isset($data["DATA_105"]) ? $data["DATA_105"] : "";
$maxUserCount = trim($maxUserCount);
if(!$maxUserCount || $maxUserCount == "")
    $maxUserCount = "0";
// other parameter
$isuseplate = 0;
// Mobile relevant product
$pluginType = "1";
// Whether control concurrent
$concurrentFlag = "0";
// Client type--iphone,ipad,android,webclient
$clients = "iphone,ipad,android,webclient";
// Module, default value
$modules = "1,2,3,4,5,6,7,8,9,10,11,13";
// generate business logical url
$licenseUrl = "http://127.0.0.1:1000/server/createLicense.do?serverCode=".$serverCode."&serverName=".implode(",",unpack('c*', $serverName))."&customerName=".implode(",",unpack('c*', $customerName))."&expireDate=".$expireDate."&serverIp=".implode(",",unpack('c*', $serverIp))."&serverPort=".implode(",",unpack('c*', $serverPort))."&serverKey=".implode(",",unpack('c*', $serverKey))."&maxUserOnlineCount=".$maxUserOnlineCount."&maxUserCount=".$maxUserCount."&isuseplate=".$isuseplate."&pluginType=".$pluginType."&concurrentFlag=".$concurrentFlag."&clients=".$clients."&modules=".$modules."";
// Write url in log
file_put_contents($logDir."licenseDownQuery_log.txt",$licenseUrl."@*@",FILE_APPEND);
// get data from url, can change to http request
$licenseReturnString = file_get_contents($licenseUrl);
// Return result to log
file_put_contents($logDir."licenseDownQuery_log.txt",$licenseReturnString."@*@",FILE_APPEND);
// Check return result
$licenseReturnArray = explode(";", $licenseReturnString);
if(count($licenseReturnArray) > 0 && $licenseReturnArray[0] == "true") {
    // get licenseId
    $licenseId = $licenseReturnArray[1];
    // Generate feedback
    $feedbackInfo = [
        "content"      => '<a href="http://127.0.0.1/server/getLicense.do?id='.$licenseId.'" style="font-family: Arial; line-height: 12px; white-space: normal;" target="_blank">Succeefully, please click to download license</a>',
        "flow_process" => $flow_prcs,
        "process_id"   => $prcs_id,
        "run_id"       => $run_id,
        "user_id"      => $user_id,
    ];
    // Logs
    file_put_contents($logDir."licenseDownQuery_log.txt",json_encode($feedbackInfo)."\r\n",FILE_APPEND);
    // Call service : FlowService ,inser feedback data
    app('App\EofficeApp\Flow\Services\FlowService')->createFlowFeedbackService($feedbackInfo);
}

?>

2 Salary item from file

2.1 Original Requirements:

Calculate lunch allowance, night shift allowance, and weekend holiday lunch meals.

2.2 Requirement details :

  1. Monday to Sunday, mid-shift : 16:00 to 0:00, work for 3 consecutive hours, then the allowance is 15 yuan (17:00 to 19:00 is also counted as 15 yuan, because there is a meal time);

  2. Monday to weekend, night shift: 0:00 to 8:30, work for 3 consecutive hours, then the subsidy is 20 yuan;

  3. weekend, noon: 9:30 to 12:30, work 3 hours, then the subsidy of 20 yuan;

  4. production synthesis department shift system, day shift: 8:30 to 20:30 (15 yuan). This if it is Saturday and Sunday overtime (9:30-12:30), lunch 20 yuan is to be given. That is: Monday to Friday day shift: 8:30 to 20:30 ($15), Saturday and Sunday day shift: 8:30 to 20:30 ($15+20=35).

2.3 Remarks:

  1. overtime clocking problems, cell phone and time machine clocking in and out signing in at the latest time to start counting, signing out at the earliest time to start counting.

2.4 Demand analysis:

  1. Use the "payroll items from the file", in the two-open file, according to the personnel attendance data, statistics out of the "need for meal allowances / allowances" and return;

  2. Calculate the "number of allowances" by the "amount of allowance" using the formula to get the value of the allowance.

2.5 Salary item confirmation

Salary itemSettingValue

Weekend allowance rate

{Fix value}

20

Mid-shift allowance rate

{Fix value}

15

Night shift allowance rate

{Fix value}

20

Weekend allowance times

{From file}

Mid-shift allowance times

{From file}

Night shift allowance times

{From file}

Weekend allowance

Weekend allowance rate * Weekend allowance time

Mid-shift allowance

Mid-shift allowance rate * Mid-shift allowance times

Night shift allowance

Night shift allowance rate * Night shift allowance times

<?php
// attend.php
//author: Weaver internationa;
//date: 06/12/2023
class Attendance
{
    private $year;
    private $month;
    private $userId;
    //Department ID
    private $deptId = 2;
    //Statistic type
    private $type;
    private $data = [
        //Weekend
        'weekend' => 0,
        //Day shift
        'day' => 0,
        //Night shift
        'night' => 0
    ];

    private $userRepository;
    private $attendanceRecordsRepository;

    public function __construct()
    {
        $this->userRepository = 'App\EofficeApp\User\Repositories\UserRepository';
        $this->attendanceRecordsRepository = 'App\EofficeApp\Attendance\Repositories\AttendanceRecordsRepository';

        if (!$request = Utils::bindRequest('year', 'month', 'user_id', 'type')) {
            return $this->response();
        }
        list($this->year, $this->month, $this->userId, $this->type) = $request;
    }

    public function run()
    {
        $userDeptId = $this->getUserDeptId();
        if (!$userDeptId) {
            return $this->response();
        }
        list($startDate, $endDate) = Utils::getMonthStartEnd($this->year, $this->month);
        $parsms = ['sign_date' => [[$startDate, $endDate], 'between'], 'user_id' => [$this->userId]];
        $records = app($this->attendanceRecordsRepository)->getRecords($parsms)->toArray();
        if (!$records) {
            return $this->response();
        }
        $dateGroup = array();
        foreach ($records as $record) {
            $signDate = Utils::has($record, 'sign_date');
            $signIn = Utils::has($record, 'sign_in_time');
            $signOut = Utils::has($record, 'sign_out_time');
            if ($signDate && $signIn && $signOut) {
                $dateGroup[$signDate] = [$signIn, $signOut];
            }
        }
        if (!$dateGroup) {
            return $this->response();
        }
        $ruleType = $userDeptId == $this->deptId ? 'dept' : 'common';
        foreach ($dateGroup as $date => $sign) {
            $rules = $this->getRules($date, $ruleType);
            list($signIn, $signOut) = $sign;
            $isWeekEnd = Utils::isWeekEnd($date);
            foreach ($rules as $type => $rule) {
                foreach ($rule as $item) {
                    $needWeekend = $item['weekend'];//Whether for weekend only
                    $hour = $item['hour'];//Allowance hours
                    $time = $item['time']; //Allowance time
                    $secords = Utils::getIntersetTime($signIn, $signOut, $time[0], $time[1]);
                    if ($secords < $hour * 3600) {
                        continue;
                    }
                    if (!$needWeekend || ($needWeekend && $isWeekEnd)) {
                        $this->data[$type]++;
                        break;
                    };
                }
            }
        }
        return $this->response();
    }

    public function response()
    {
        echo $this->data[$this->type] ?? 0;
        exit();
    }


    private function getUserDeptId()
    {
        return app($this->userRepository)->getUserDeptIdAndRoleIdByUserId($this->userId)['dept_id'] ?? null;
    }

    private function getRules($date, $type)
    {
        $nextDate = Utils::getNextDate($date);
        $rules = [
            'common' => [
                'day' => [
                    ['weekend' => false, 'hour' => 3, 'time' => [$date . ' 16:00:00', $nextDate . ' 00:00:00']],
                    ['weekend' => false, 'hour' => 2, 'time' => [$date . ' 17:00:00', $date . ' 19:00:00']]
                ],
                'night' => [
                    ['weekend' => false, 'hour' => 3, 'time' => [$date . ' 00:00:00', $date . ' 08:30:00']]
                ],
                'weekend' => [
                    ['weekend' => true, 'hour' => 3, 'time' => [$date . ' 09:30:00', $date . ' 12:30:00']]
                ]
            ],
            'dept' => [
                'day' => [
                    ['weekend' => false, 'hour' => 12, 'time' => [$date . ' 08:30:00', $date . ' 20:30:00']]
                ],
                'weekend' => [
                    ['weekend' => true, 'hour' => 3, 'time' => [$date . ' 09:30:00', $date . ' 12:30:00']]
                ]
            ]
        ];
        return $rules[$type];
    }
}

class Utils
{
    public static function bindRequest(...$keys)
    {
        $array = array();
        foreach ($keys as $key) {
            if (!$v = static::has($_REQUEST, $key)) {
                return false;
            } else {
                $array[] = $v;
            }
        }
        return $array;
    }

    public static function has($array, $key)
    {
        return (isset($array[$key]) && !empty($array[$key])) ? $array[$key] : false;
    }

    public static function getMonthStartEnd($year, $month)
    {
        $date = $year . '-' . $month . '-01';
        $startDate = date('Y-m-01', strtotime($date));
        $endDate = date('Y-m-t', strtotime($date));
        return [$startDate, $endDate];
    }

    public static function getNextDate($date = false)
    {
        if ($date) {
            return date('Y-m-d', strtotime("+1 day", strtotime($date)));
        }
        return date('Y-m-d', strtotime("+1 day"));
    }

    public static function isWeekEnd($date)
    {
        if ((date('w', strtotime($date)) == 6) || (date('w', strtotime($date)) == 0)) {
            return true;
        } else {
            return false;
        }
    }

    public static function getIntersetTime($start1, $end1, $start2, $end2)
    {
        $intersetTime = 0;
        if ($end2 > $start1 && $start2 < $end1) {
            $beginTime = static::getBigData($start1, $start2);
            $endTime = static::getSmallData($end2, $end1);
            $intersetTime = strtotime($endTime) - strtotime($beginTime);
        }
        return $intersetTime;
    }

    protected static function getSmallData($one, $two)
    {
        return $one < $two ? $one : $two;
    }

    protected static function getBigData($one, $two)
    {
        return $one < $two ? $two : $one;
    }
}

require_once __DIR__ . '/../../bootstrap/app.php';
$attendance = new Attendance();
$attendance->run();
?>

3 Workflow data verification

<?php
/**
 * This example is limited to PHP development language, also supports external system interfaces, or interfaces developed in other languages, if you open the data validation file validation and configuration of the current file address, the process flow will run some of the parameters of the process and the form data are passed to the file, through the $_REQUEST can be exported to see all the incoming parameters.
 */
// Framework startup file for the framework of the startup and auto-load configuration, if the entire code logic is not used in the framework of the method, you do not need to introduce this file, the introduction of this file path needs to be adjusted according to the current location of the file stored, if it is in accordance with the current validation of the address of the path stored in the example, according to the example of the relative path can be.
require __DIR__ . '/../../bootstrap/app.php'; 
// If the code needs to operate the database, you can selectively introduce this facade, the specific operation of the database method see Laravel documentation: https://laravelacademy.org/post/22012; if the address is invalid, you can search for Laravel documentation to check.
use Illuminate\Support\Facades\DB; 

/**
 * Data Validation File Validation Address Configuration Example: /eoffice/server/ext/customer_name/data_validate_example.php?check_control_id=DATA_1
 * 1、File Address Path Note: The customer_name in the path is recommended to use the full spelling of the customer's name or abbreviation, or named according to the role of the demand, as far as possible to ensure that the folder name uniqueness, do not conflict with the name of the folder under the ext directory, to avoid subsequent upgrades to the system to cover or delete the folder.
 * 2、File address parameter description: address parameter configuration is optional, check_control_id here to provide an example of parameters, such as the current development of the file need to reuse different processes, different processes need to determine the form control ID or need to query the data table fields are different, you can configure the address parameter configuration passed in to achieve the file reuse.
 */

// Get the parameters configured on the file address
$checkControlId     = $_REQUEST['check_control_id'] ?? 'DATA_1'; // Parameters can be obtained if they are configured on the file address.

// Getting incoming data
$checkControlIdData = $_REQUEST[$checkControlId] ?? ''; // If you configure a parameter on the file address, get the ID of the configured form control or table name, table field, etc., and then use this parameter to get the corresponding data in the incoming parameter.
$checkControlIdData = $_REQUEST['DATA_1'] ?? ''; // Or get process form data directly.

// database operation example
$list = DB::table('xxx')->select('xxx')->where('xxx')->get();

// data process, code here base on real business requirement

// return result example
echo 1;exit; // pass
echo 'true';exit; // pass
echo 'xxx';exit; // Beside 1 and 'true',Returns all other content for the verification does not pass, if the data verification is not configured to prompt the content of the text, the content returned at this time will be used as a reminder of the information, if the data verification is configured to prompt the text of the configured text prompts.
?>

Last updated