This example shows the creation of an RF form to draw quantities from an item series corresponding to a stock movement.

The RF form accesses the movement, which displays the first item to be moved, the location code and the quantity to be extracted; using a scanner, the location code is captured to confirm extraction, after which the information of the next item to be extracted is displayed to follow the same steps. Finally the stock of the bin and the status of the movement is updated. This form must validate each field before moving on to the next or displaying an error message, and it must revert the changes if the extraction process is not completed.

1 Execute stock movement with a task

The user extracts the items that correspond to a stock movement, one by one until the end..

1.1 Analysis

1.1.1 Process flow

The flow that the task will follow is shown below.

1.1.2 Low-level mockup

This is the low level mockup of the form:

1.2 Form definition

1.2.1 RF Form

The following defines the data required for the form.

Field name Content
form_name devtest_galmmov
form_desc Extraction movement

JS Client Initial Code: The variable "var_codubi" is defined, whose value will be obtained during the code execution of the " codart " field and will be used in the validation of the " codubi " field, the initial value of the variable " var_cabid " is also defined.
JS Form Server Rollback: The reversal code for lines with status changed in the process is defined. This code is activated when the process execution is interrupted or after 60 seconds of not pressing any key.

Copy
form.set("var_codubi", "");
form.set("var_cabid", 0);
Copy
if (fields.var_cabid > 0) {
    //Reverse line status
    Ax.db.update("devtest_galmmovl",
        {
            estmov : 0
        },
        {
            cabid : fields.var_cabid
        }
    );
}



1.2.2 Fields

The following defines the fields required for the form.

field_order field_name field_type field_scale field_noentry field_desc field_title field_required
2 cabid Integer 0 0 (NO) Identifier Movement identifier 1 (YES)
4 desmov String Uppercase (String) 0 1 (YES) Description Movement description 0 (NO)
6 codart String Uppercase (String) 0 0 (NO) Item code Item code 1 (YES)
8 nomart String Uppercase (String) 0 1 (YES) Item name Item name 0 (NO)
10 codubi String Uppercase (String) 0 0 (NO) Loc. code Location code 1 (YES)
12 canmov Integer 0 1 (YES) Quantity Quantity of movement 0 (NO)
14 confirm String Uppercase (String) 1 0 (NO) Confirm Confirm movement 1 (YES)

In the " confirm " field, the size of text entered is restricted to one letter by the value of field_scale . This field must receive the values "Y" or "N".

a) The " cabid " field has the following logic:

Server: Obtains the movement data, if it exists, display its data in the field " desmov " (having a field called " desmov ", equal to the property of the object used, the field automatically adopts this value without the need to assign it), otherwise, returns an error message in the variable " errmsg " (returning the object " result " with a property called " errmsg ", automatically creates or updates a variable with this name and value).
Client: Checks if there is any message in the variable " errmsg ", if there is, it displays the message and positions itself in the same field (preventing advancing until a correct value is entered). The movement identifier is stored in the " var_cabid " variable (used from the ROLLBACK section) by adopting the value of the property of the "result" object with the same name and the RF Terminal advances to the next field where data can be entered.

For this example it is not necessary to define any code in the "BEFORE SERVER CODE" section or in "BEFORE CLIENT CODE".

Copy
var result = {
    desmov : "",
    errmsg : ""
};

var mObjGalmmovh = Ax.db.executeQuery(`
        SELECT *
        FROM devtest_galmmovh
        WHERE 
            cabid   = ?  AND 
            coduser = ?  AND 
            codalm  = ?  AND 
            estado  = 'V'`, fields.cabid, config.USER, config.CODALM).toOne();

if (mObjGalmmovh.cabid != null){
    result.desmov = `Mov >> ${mObjGalmmovh.cabid}. Warehouse [${mObjGalmmovh.codalm}]`;
    result.var_cabid = mObjGalmmovh.cabid;
} else {
    result.errmsg = "No movement or not correspond!";
}

return result;
Copy
if (errmsg != "") {
    form.setFocus("cabid", errmsg);
}



b) The " desmov " field is descriptive only, so it has no execution code.





c) The " codart " field has the following logic:

Server: Moving to this field automatically retrieves the data of the first item (" codart ", " nomart ", " codubi " and " canmov ") of the movement, whose status is 0, without requiring data entry; it then moves to the " codubi " field to confirm the location of the extracted item or to the " confirm " field in case there are no more items to be extracted.
This is achieved by executing the code in the BEFORE SERVER CODE section.
Client: In this process, the data of the item location is saved in the variable " var_codubi ", declared in the form, to be used during the validation of the " codubi " field during the execution of the code in section BEFORE CLIENT CODE .

For this example it is not necessary to define any code in the "AFTER SERVER CODE" section or in "AFTER CLIENT CODE".

Copy
var result = {
    codubi : "",
    errmsg : ""
};

var mIntCabid = fields.cabid;

if (mIntCabid > 0) {
    var mObjGalmmovl = Ax.db.executeQuery(`
        SELECT 
            FIRST 1    
            devtest_galmmovl.seqno,
            devtest_galmmovl.codart,
            devtest_garticul.nomart,
            devtest_galmmovl.codubi,
            devtest_galmmovl.canmov
        FROM devtest_galmmovl
            JOIN devtest_garticul
                ON devtest_galmmovl.codart = devtest_garticul.codigo
        WHERE 
           cabid = ? AND estmov = 0`, mIntCabid).toOne();
    
    if (mObjGalmmovl.seqno != null) {
        result.codart       = mObjGalmmovl.codart;
        result.nomart       = `Loc.[${mObjGalmmovl.codubi}]. Article: ${mObjGalmmovl.nomart}`;
        result.var_codubi   = mObjGalmmovl.codubi;
        result.canmov       = mObjGalmmovl.canmov;

        Ax.db.update("devtest_galmmovl",
            {
                estmov : 1
            },
            {
                seqno : mObjGalmmovl.seqno
            }
        );
    } else {
        result.codart = "-"
        result.nomart = "Extracted articles!"
    }
}

return result;
Copy
if (errmsg != "") {
    form.setFocus("codart", errmsg);
} else if (codart == "-") {
    form.setFocus("confirm", "");
} else {
    form.setFocus("codubi", "");
}




d) The " nomart " field is descriptive only, so it has no execution code.





e) The " codubi " field has the following logic:

Server: Validates that the location entered is equal to the value of the variable " var_codubi ", otherwise, it displays an error message.

For this example it is not necessary to define any code in the "BEFORE SERVER CODE" section, "BEFORE CLIENT CODE" or in "AFTER SERVER CODE".

AFTER CLIENT CODE

Copy
if (var_codubi != codubi) {
    form.setFocus("codubi", "Location does not correspond!");
} else {
    form.setFocus("codart", "");
}




f) The " canmov " field is descriptive only, so it has no execution code.





g) The " confirm " field has the following logic:

Server: Validates that the value is Y (Yes) or N (No), otherwise it displays an error message.
In case it is Y (movement confirmation), the list of items with movement status 1 is obtained to discount the stock of each one in the corresponding location, then the movement status is updated and the form fields are reset.
In the case of N (movement cancellation), a "STOP" message is sent.
Client: Checks if there is any message in the variable " errmsg ", if there is, it displays the message and positions itself in the same field (preventing advancing until a correct value is entered), otherwise, it resets the variables " var_codubi " and " var_cabid " and the RF Terminal returns to the initial field.

For this example it is not necessary to define any code in the "BEFORE SERVER CODE" section or in "BEFORE CLIENT CODE".

Copy
var result = {
    errmsg  : ""
};

var mStrConfirm = fields.confirm,
    mIntCabid   = fields.cabid;

if (mStrConfirm == "y" || mStrConfirm == "Y") {
    var mRsGalmmovl = Ax.db.executeQuery(`
            SELECT
                devtest_galmmovl.codart,
                devtest_galmmovl.codubi,
                devtest_galmmovl.canmov,
                devtest_galmstku.stkact
            FROM devtest_galmmovl
                JOIN devtest_galmstku
                    ON  (devtest_galmmovl.codart = devtest_galmstku.codart)
                    AND (devtest_galmmovl.codubi = devtest_galmstku.codubi)
            WHERE cabid = ? AND estmov = 1`, mIntCabid).toMemory();

    mRsGalmmovl.forEach(function(mRow){
        //Reduce stock at origin location
        Ax.db.update("devtest_galmstku",
            {
                stkact : mRow.stkact - mRow.canmov
            },
            {
                codart : mRow.codart,
                codubi : mRow.codubi
            }
        );
    });

    //Movement status update
    Ax.db.update("devtest_galmmovh",
        {
            estado : "F"
        },
        {
            cabid : mIntCabid,
        }
    );

    //Field cleaning
    result.cabid    =  0;
    result.desmov   = "";
    result.codart   = "";
    result.nomart   = "";
    result.codubi   = "";
    result.canmov   =  0;
    result.confirm  = "";
    
    //Reset variables
    result.var_codubi =  "";
    result.var_cabid  =  0;

} else if (mStrConfirm == "n" || mStrConfirm == "N") {
    result.errmsg = "STOP";
    
    if (mIntCabid > 0) {
        //Reverse line status
        Ax.db.update("devtest_galmmovl",
            {
                estmov : 0
            },
            {
                cabid : mIntCabid
            }
        );
    }
} else {
    result.errmsg = "Incorrect value (Y/N)";
}

return result;
Copy
if (errmsg == "STOP") {
    form.stop()
} else if (errmsg != "") {
    form.setFocus("confirm", errmsg);
}

1.2.3 Nest form to menu

The created form is nested to a menu, which in this case is TEST_STOCK.

1.3 Process RF

Starts the execution of the program RF2020 Terminal. In particular, verify that the elements corresponding to config and form have been correctly reported.

Copy
-config login_test
-menu TEST_STOCK

1.3.1 Case 1

Extract the items reported in movement number 1.
User: USER1
Warehouse: D1

RF Terminal

a) RF Terminal (login): Log in with the indicated data



b) RF Terminal : Access the " Execute stock movement with a task (devtest_galmmov) " form through the menu.



c) RF Terminal Identifier (cabid) : Enter the movement identifier. If there is a controlled error, the following message is displayed.

Incorrect value:



Correct value:

The first item to be moved will be displayed



d) RF Terminal Loc. Code (codubi) : Enter the location code. If there is a controlled error, the following message is displayed.

Incorrect value:



Correct value:



After entering the correct value for the location, the second item to be moved will be displayed



After entering the correct value for the location, the third and last item to be moved will be displayed



After entering the correct value for the location, if there are no more items, it displays a message in the " Item name (nomart) " field and is positioned in the confirmation field.



e) RF Terminal Confirm (confirm) : Enter the confirmation code (Y/N). If there is a controlled error, the following message is displayed.

Incorrect value:



Correct value:



1.4 After example

Important

If the form created is only an example:

  • Delete the form reference in the menu.
  • Delete form fields
  • Delete the form
  • Delete the SoftReference (if it is related only to the created form).
  • Delete created tables.