Milestone configures for Approval & Reject Flows.

Certified Associate Developer

Hi All,

here i using Milestone for my App in Summary(view) interface, so based on status value the Milestone Bar should work. 

in table, "status" containing statuses: "Assigne", "Approved", "Return" and "Reject", which represent the different statuses of a request.

I have the requirement of a milestone where first step should always be "Addproduct",

then next possible steps shown are "Approved", by Manager and "Approved" by supplier it will complete.

but when shopmanager "Reject" show like.

  

similarly, Supplier too, 

  Discussion posts and replies are publicly visible

  • I'm not sure I completely understand the question here, but are you looking to dynamically change the milestone step display after rejections?  Such as when the Manager Rejects, the display changes from:

    (Addproduct>Manager's Approved>Supplier's Approved)

    To:

    (Addproduct>Reject>Supplier's Approved)

    Or something like that?  If so, why not send flags for manager/supplier rejects and use the ol' if() statement logic in the milestone rule?

    Or am I just in right field here..

  • 0
    Certified Associate Developer
    in reply to Chris

    Hi Chris,

    Yes, if the manager reject's step like (Addproduct>Rejected>Suppler's Approval)

  • Can you share what you've tried so far, and what isn't working?  Or if this is more of a general question, can you be most specific on what you need help with?

  • 0
    Certified Associate Developer
    in reply to Chris

    a!localVariables(
      local!steps: {
        "Add Product",
        "Manager's Approval",
        "Supplier's Approval"
      },
      local!Rejectstep: {
        a!map(
          id: 1,
          name: "Addproduct",
          color: "POSITIVE"
        ),
        a!map(
          id: - 1,
          name: "Reject by shopmanager",
          color: "NEGATIVE"
        ),
        
      },
      {
        if(
          not(ri!product.status = "Reject"),
          /* Approval flow milestone  */
          a!milestoneField(
            label: "Inventory Tracker",
            labelPosition: "ABOVE",
            instructions: "product ID " & ri!product.productid,
            steps: local!steps,
            active: {
              if(ri!product.status = {}, 1, {}),
              if(ri!product.status = "Approve", 2, - 1)
              
            }
          ),
          /* Reject or Return flow milestone  */
          a!milestoneField(
            active: - 1,
            steps: local!Rejectstep.name,
            color: local!Rejectstep.color[wherecontains( - 1, local!Rejectstep.id)]
          )
        ),
        a!sectionLayout(
          label: "Product Details",
          contents: {
            a!columnsLayout(
              columns: {
                a!columnLayout(
                  contents: {
                    a!textField(
                      label: "ProductName",
                      labelPosition: "ADJACENT",
                      value: ri!product.productname,
                      saveInto: {},
                      refreshAfter: "UNFOCUS",
                      readOnly: true(),
                      validations: {}
                    ),
                    a!textField(
                      label: "Productdetails",
                      labelPosition: "ADJACENT",
                      value: ri!product.productdetails,
                      saveInto: {},
                      refreshAfter: "UNFOCUS",
                      readOnly: true(),
                      validations: {}
                    ),
                    a!textField(
                      label: "Categorytype",
                      labelPosition: "ADJACENT",
                      value: ri!product.categorytype,
                      saveInto: {},
                      refreshAfter: "UNFOCUS",
                      readOnly: true(),
                      validations: {}
                    )
                  }
                ),
                a!columnLayout(
                  contents: {
                    a!paragraphField(
                      label: "Comments",
                      labelPosition: "ADJACENT",
                      value: ri!product.Comments,
                      saveInto: {},
                      refreshAfter: "UNFOCUS",
                      readOnly: true,
                      validations: {}
                    ),
                    a!textField(
                      label: "Status",
                      labelPosition: "ADJACENT",
                      value: ri!product.status,
                      saveInto: {},
                      refreshAfter: "UNFOCUS",
                      readOnly: true,
                      validations: {}
                    )
                  }
                )
              }
            ),
            a!gridField(
              label: "Supplier Details",
              labelPosition: "ABOVE",
              data: property(ri!product, "supplierDetails", null),
              columns: {
                a!gridColumn(
                  label: "Supplierid",
                  value: fv!row.supplierid
                ),
                a!gridColumn(
                  label: "Suppliername",
                  value: fv!row.suppliername
                ),
                a!gridColumn(label: "Location", value: fv!row.location),
                a!gridColumn(
                  label: "Phonenumber",
                  value: fv!row.phonenumber
                ),
                a!gridColumn(
                  label: "Productprice",
                  value: fv!row.productprice
                ),
                a!gridColumn(label: "Quantity", value: fv!row.quantity),
                a!gridColumn(
                  label: "image",
                  value: a!imageField(
                    images: a!documentImage(
                      document: if(
                        isnull(fv!row.image),
                        cons!IA_NoimageforProduct,
                        fv!row.image
                      )
                    ),
                    size: "GALLERY"
                  ),
                  align: "CENTER"
                )
              },
              validations: {}
            )
          }
        )
      }
    )

    here i use if conditionaly  to diplay the Milestone filed, and  in Active Parameter the way i coded is correct..? by using Multiple if conditions.

  • You can certainly use if() to display different milestone components, but don't forget about the showWhen parameter which can also be used for the same result and tends to be cleaner overall, in my experience.  Additionally, you can use 1 component and have the steps be dynamic based on what occurred in the process (as in the example below).

    As far as design, I typically do not change the Milestone component steps based on the history of the process, this can be confusing for reviewers.  You may be able to safely append the approval disposition, but I typically leave these as only the step names, and have a History section somewhere below to show what has occurred previously.

    Also to note, within the milestone components the active parameter is looking for a single integer value to determine which single step is active, it will not accept a list of values as in your example.

    a!localVariables(
      local!managerReject: true, /* logic to determine if the manager rejected */
      local!supplierReject: false, /* logic to determine if the supplier rejected */
      local!active: 1, /* which step is the process at */
      
    
      a!milestoneField(
        label: "Workflow",
        steps: {
          "Add Product",
          concat("Manager Approval",if(local!managerReject," (Rejected)","")),
          concat("Supplier Approval",if(local!supplierReject," (Rejected)","")),
        },
        active: local!active
      )
    )