OA system 24: leave approval 5: background logic of [approval pop-up box after clicking "approval"; (Dao layer and Service layer logic for submitting approval results)

The main contents of this blog are as follows: after clicking "confirm submission" in the [leave approval embedded page] and [approval pop-up box], the background logic: mainly the background logic of Dao layer and Service layer;

Description:

(1) At present, in order to realize a certain function, [a better programming logic and implementation process] is much more important than [actually knock the code to realize]!)  

(2.1) the parameters of the underlying SQL statement, updata and insert statement are generally an entity class object. Pay attention to this habit (or commonly used strategy);

(2.2) Moreover, in order to update some data, the general strategy first queries the data to be changed and uses an entity class object to carry it; Then, modify the entity class object, and then call the update method (the parameter of updata is the modified entity class object), which has achieved the purpose of updating these data;

(2.3) as can be seen from the example in 2.2, we try to write those general SQL statements in Mapper xml, or SQL statements that can complete a "universal" function; In this way, when we need to complete a specific business logic, we can call these SQL statements with "generality and universality" function to complete a specific business logic! This thought is very important!!!

catalogue

1: [approval] process and logic analysis

(1) If the leave time > = 72 hours: it needs to be approved by department manager and general manager

(2) If the leave time is less than 72 hours: it needs to be approved by department manager and general manager

2: Through the analysis in [I: [approval] process and logical analysis], conceive the implementation branch and structure of specific coding

3: Specific implementation

 1. Step 1: whether the approval result is approved or rejected, the current task status changes to complete;

(1.1) first, in process_ flow. Writing SQL statements in XML

(1.2) then, in ProcessFlowDao, write the above_ flow. Method declaration of two SQL statements declared in XML

(1.3) then, in LeaveFormService, write and implement [change the current task status to complete;] Business logic of

 2. Step 2: if the current task is the last node, it represents the end of the process and updates leave_ The status of the leave form in the form table is the corresponding approved or rejected

(1) First, in leave_ form. Add two SQL statements to XML;

(2) Then, write the definition of the method in LeaveFormDao

(3) then, in LeaveFormService, the Dao layer method is invoked to achieve the logic of this step.

3. Step 3: if the current task is not the last node, if it is approved, the status of the next node will be changed from ready to process

4. Step 4: if the current task is not the last node and the approval is rejected, the status of all subsequent tasks will change to cancel and leave will be updated at the same time_ The status of the leave form in the form table is returned

5. The last setting, because the whole operation does not need to return a value, so return null;

4: Testing

(1) Test data

(2) write test cases

(3) Actual running test cases

1: [approval] process and logic analysis

(1) If the leave time > = 72 hours: it needs to be approved by department manager and general manager

As above, the current approval phase is department manager approval.

(case 1: the intermediate node is approved:)

● if approved by the Department Manager:

Then, the [general manager] approves: the general manager approves: the general manager may or may not approve

(case 2: the intermediate node fails to pass the approval:)

● if the department manager fails to pass the examination and approval: then the leave does not need the examination and approval of the general manager, and the general manager does not agree directly.

(2) If the leave time is less than 72 hours: it needs to be approved by department manager and general manager

(case 3: the current node is the last node:)

That is, the approval process and logic can be extracted into three different situations: case 1: the current approval is an intermediate node and has passed the approval; Case 2: the current approval is an intermediate node, but the approval fails; Case 3: current approval is the last node;

2: Through the analysis in [I: [approval] process and logical analysis], conceive the implementation branch and structure of specific coding

Through the analysis in [I: [approval] process and logic analysis], the actual coding logic can be sorted as follows:

1. Whether the approval result is approved or rejected, the current task status changes to complete; (that is, as long as the current phase is approved, whether it is approved or rejected, the status of the current phase needs to be changed to complete after the current approval phase is approved)

2. If the current task is the last node, it represents the end of the process and updates leave_ The status of the leave form in the form table is the corresponding approved or rejected

3. If the current task is not the last node, if it is approved, the status of the next node will be changed from ready to process

4. If the current task is not the last node and the approval is rejected, the status of all subsequent tasks will change to cancel and leave will be updated at the same time_ The status of the leave form in the form table is returned

(PS: the ability of [to build a better code structure and logic in order to realize a function] needs to be improved slowly; indeed, at present, [to realize a function, a better programming logic and implementation process] is much more important than [actually knock code to realize]!)  

3: Specific implementation

 1. Step 1: whether the approval result is approved or rejected, the current task status changes to complete;

(1.1) first, in process_ flow. Writing SQL statements in XML

After thinking, it can be found that in order to realize the logic of this step, two underlying SQL operations are required: one is to query all approval links of the current form; Second, change a certain approval link;

(PS: the selectByFormId above is carelessly wrong, with an extra c.. Therefore, timely unit testing is very important!!)  

process_flow.xml: the code of the above new content

    <select id="selectByFormId" parameterType="Long" resultType="com.imooc.oa.entity.ProcessFlow">
        select * from adm_process_flow where form_id = #{value} order by order_no
    </select>

    <update id="update" parameterType="com.imooc.oa.entity.ProcessFlow">
      UPDATE adm_process_flow SET form_id = #{formId}, operator_id = #{operatorId}, action = #{action}, result = #{result}, reason = #{reason}, create_time = #{createTime}, audit_time = #{auditTime}, order_no = #{orderNo}, state = #{state}, is_last = #{isLast}
      WHERE process_id = #{processId}
    </update>

(1.2) then, in ProcessFlowDao, write the above_ flow. Method declaration of two SQL statements declared in XML

(1.3) then, in LeaveFormService, write and implement [change the current task status to complete;] Business logic of

[step 1: change the current task status to complete no matter whether the approval result is approved or rejected;] Code of:

    /**
     *
     * @param formId:The formId of this leave information (which can be transmitted from the front desk)
     * @param operatorId: Handler number (obtained from the current session object)
     * @param result: Approval results (which can be transferred from the front desk)
     * @param reason: Approval comments (which can be transmitted from the front desk)
     */
    public void audit(Long formId,Long operatorId,String result,String reason){
        MybatisUtils.executeUpdate(sqlSession -> {
            //1. Whether the approval result is approved or rejected, the current task status changes to complete
            //(1.1) first, obtain all process data of the current form;
            ProcessFlowDao processFlowDao = sqlSession.getMapper(ProcessFlowDao.class);
            List<ProcessFlow> processFlowList = processFlowDao.selectByFormId(formId);
            if (processFlowList.size() == 0) {  //if judgment, it is a fault-tolerant processing. if the queried process data is 0, an exception needs to be thrown;
                throw new BussinessException("PF001", "Invalid approval process");// This error code is user-defined;
            }
            //(1.2) obtain the data of the current approval phase
            //Get the current approval process: to determine whether an approval process is the current approval process, the following two conditions need to be met: first, the state of the current phase should be process; The second is the operator of the current link_ The ID should be the current login user.
            // Data filtering is done through the Stream stream of Lambda expression
            List<ProcessFlow> currentProcessFlowList = processFlowList.stream().filter(p -> p.getOperatorId() == operatorId && p.getState().equals("process")).collect(Collectors.toList());
            ProcessFlow processFlow = null;
            if (currentProcessFlowList.size() == 0) {  //If it is judged that a fault-tolerant processing is made, if it is not in process_ Find the current approval process in the flow table and throw an exception;
                throw new BussinessException("PF002", "Pending tasks not found");// This error code is user-defined;
            } else { //If the current approval process data is found, the approval process data will be extracted
                processFlow = currentProcessFlowList.get(0);
                processFlow.setState("complete");
                processFlow.setResult(result);
                processFlow.setReason(reason);
                processFlow.setAuditTime(new Date());
                processFlowDao.update(processFlow);
            }

            //2. If the current task is the last node, it represents the end of the process and updates leave_ The status of the leave form in the form table is the corresponding approved or rejected
            //3. If the current task is not the last node, if it is approved, the status of the next node will be changed from ready to process
            //4. If the current task is not the last node and the approval is rejected, the status of all subsequent tasks will change to cancel and leave will be updated at the same time_ The status of the leave form in the form table is returned
        })
    }

explain:

(1) Because all approval operations are either OK or not, the above code is written in [MybatisUtils.executeUpdate()]:

(2) First, get all process data of the current form; A fault-tolerant processing of judgment is added. If everything is normal, it should be obtained, but in case it cannot be obtained, a user-defined BussinessException exception will be thrown;

(3) Then, filter out the data of the current approval phase from all process data of the current form; A fault-tolerant processing of judgment is added. If everything is normal, it should be obtained, but in case it cannot be obtained, a user-defined BussinessException exception will be thrown; (because this rule is used when [leave data to be approved] is displayed in the front. However, if it cannot be found for some reason, an exception will be reported.)

The stream stream of Lambda expression is used here. If you forget, you can refer to Lambda expression 7: Stream 1: introduction to Stream And related articles nearby.

(4) Update the data of the current approval phase

 2. Step 2: if the current task is the last node, it represents the end of the process and updates leave_ The status of the leave form in the form table is the corresponding approved or rejected

(1) First, in leave_ form. Add two SQL statements to XML;

Because in order to realize the logic of the second step, the bottom layer needs two SQL supports: one is based on the form_id query form data; The second is to update the data of a form

(PS: the parameter in the update tag above is written incorrectly and becomes LeaveForm, which should actually be com.imooc.oa.entity.LeaveForm. This error also leads to the NoClassDefFoundError error error when running and publishing later, so that the system cannot log in. Therefore, timely unit testing is very important!!!)  

leave_ form. Add two SQL statement codes to XML:

    <select id="selectById" parameterType="Long" resultType="com.imooc.oa.entity.LeaveForm">
        select * from adm_leave_form where form_id = #{value}
    </select>

    <update id="update" parameterType="com.imooc.oa.entity.LeaveForm">
        UPDATE adm_leave_form SET employee_id = #{employeeId} , form_type = #{formType}, start_time = #{startTime}, end_time = #{endTime}, reason = #{reason}, state = #{state} ,create_time = #{createTime} WHERE form_id = #{formId}
    </update>

(2) Then, write the definition of the method in LeaveFormDao

(3) then, in LeaveFormService, the Dao layer method is invoked to achieve the logic of this step.

3. Step 3: if the current task is not the last node, if it is approved, the status of the next node will be changed from ready to process

It can be seen from here that when we write the underlying SQL statements, we write the SQL statements with "generality and universality" function. Therefore, in this step, we directly call those SQL statements with "generality and universality" function to complete the specific business logic of this step

4. Step 4: if the current task is not the last node and the approval is rejected, the status of all subsequent tasks will change to cancel and leave will be updated at the same time_ The status of the leave form in the form table is returned

It can be seen from here that when we write the underlying SQL statements, we write the SQL statements with "generality and universality" function. Therefore, in this step, we directly call those SQL statements with "generality and universality" function to complete the specific business logic of this step

5. The last setting, because the whole operation does not need to return a value, so return null;

4: Testing

(PS: I think in actual development, it's better to test a Service module or a Dao module before writing it. Don't wait until a function has been compiled and written.)

(1) Test data

As you can see, there are three test data, and their forms_ The IDs are 31, 32 and 33 in turn;

(2) write test cases

For this test, the following three test methods are written:

package com.imooc.oa.service;

import com.imooc.oa.entity.LeaveForm;
import org.junit.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import static org.junit.Assert.*;

public class LeaveFormServiceTest {
    LeaveFormService leaveFormService = new LeaveFormService();

    /**
     * Ask for leave for more than 3 days, which is approved by the Department Manager
     */
    @Test
    public void audit1(){
        leaveFormService.audit(31l,2l,"approved","I wish you a speedy recovery");
    }

    /**
     * If the leave is more than 3 days, the approval of the Department Manager shall be rejected
     */
    @Test
    public void audit2(){
        leaveFormService.audit(32l,2l,"refused","Tight construction period,Don't delay");
    }

    /**
     * The department manager asks for leave, which is approved by the general manager
     */
    @Test
    public void audit3(){
        leaveFormService.audit(33l,1l,"approved","agree");
    }

}

(3) Actual running test cases

Run audit1():

Run audit2():

Run audit3():

 

So far, it is OK to write the business logic part, and then write the Controller and foreground interface.  

Added by zabmilenko on Fri, 28 Jan 2022 16:30:17 +0200