Skip to content

Validate an Item's Sizes and Colors Grid ​

These two Groovy scripts check the Sizes and Colors grid of an Item when it is saved. The first refuses a size or color code that appears with two different names. The second refuses two lines marked Default for the same size and color.

Recommended pattern

These scripts are not tied to any customer's setup. You can paste them as they are; they take no parameters.

Class namesEAPreventDifferentNamesForSameSizeOrColor (names) and EAPreventDuplicateDefaultSizeAndColor (defaults)
ScriptsEAPreventDifferentNamesForSameSizeOrColor.groovy, EAPreventDuplicateDefaultSizeAndColor.groovy
Runs onItem, on the Validate On Save event
UsesNo parameters. Leave Parameter 1 empty.
Shipped asSource to paste. It is not built into the system.

When to use it ​

A clothing item can carry dozens of lines in its Sizes and Colors grid, one per barcode: size S in red, size S in blue, size M in red, and so on. Each line repeats the size's code and name and the color's code and name. With that much repetition, typing mistakes are common, and the system accepts them:

  • Size S is called Small on one line and Short on another, so anything that shows the size name disagrees with itself.
  • Two lines for size S in RED are both ticked Default, so there is no single default barcode for that combination.

These validations catch both mistakes at the moment the item is saved, and name the lines involved.

How it works ​

Names script. It goes through the grid and remembers the first name it meets for each size code under Size | Code, and for each color code under Color | Code. When a later line uses the same code with a different name, the save is refused. Lines with no size code, or no color code, are skipped for that check.

Defaults script. It goes through the lines ticked Default and groups them by size and color. When a second default line appears for the same pair, the save is refused, naming the barcode Code of both lines. A line with no size or no color is grouped with the others that lack the same value.

Both scripts report every problem they find, not only the first, and neither changes the item.

Setting it up ​

  1. Open Administration → Display Customization → Entity Flow and create a new flow.
  2. Set Target Type to Item and Target Action to Validate On Save.
  3. Add a line to the Details grid for each script you need. Paste the whole script into Groovy Script and leave Class Name empty: it is filled in when you save.
  4. Save the flow.
ParameterTitle shown after savingWhat to enter
Parameter 1Not used - leave emptyNothing.

Example ​

An item is saved with these lines:

CodeSize codeSize nameColor codeColor nameDefault
SZ1-S-REDSSmallREDRed✓
SZ1-S-RED-2SSmallREDRed✓
SZ1-S-BLUESShortBLUEBlue

The save is refused with two messages:

Size S is used with different names: Small and Short
More than one default barcode for size S and color RED: SZ1-S-RED and SZ1-S-RED-2

Renaming the third line's size to Small and unticking Default on the second line lets the item save.

Messages you may see ​

Each message appears under the usual heading of a failed flow, Error while running entity flow {0} for entity {1} - {2}:- — «خطأ أثناء تشغيل مسار الكيان {0} للسجل {1} - {2}:-». The scripts' own messages have no Arabic translation, so they appear in English on Arabic screens as well.

MessageWhyWhat to do
{0} {1} is used with different names: {2} and {3}{0} is Size or Color, {1} the code, {2} the first name met for it and {3} the different one.Give every line with that code the same name.
More than one default barcode for size {0} and color {1}: {2} and {3}Two lines for the same size and color are both ticked Default. {2} and {3} are their codes; an empty value shows as -.Untick Default on all but one of them.

The script ​

The names script:

groovy
package com.namasoft.modules.supplychain.domain.utils.plugnplay.groovy

import com.namasoft.common.utilities.ObjectChecker
import com.namasoft.infra.domainbase.datafields.LongTextDF
import com.namasoft.infra.domainbase.entity.base.EntityAction
import com.namasoft.infra.domainbase.util.Result
import com.namasoft.modules.supplychain.domain.details.SizesAndColors
import com.namasoft.modules.supplychain.domain.entities.InvItem

public class EAPreventDifferentNamesForSameSizeOrColor implements EntityAction<InvItem> {
    @Override
    Result doAction(InvItem item, LongTextDF... parameters) {
        Result result = Result.createAccumulatingResult()
        validateSameValueHasSameName(item, result, "Size", { SizesAndColors line -> line.getSize() }, { SizesAndColors line -> line.getSizeName() })
        validateSameValueHasSameName(item, result, "Color", { SizesAndColors line -> line.getColor() }, { SizesAndColors line -> line.getColorName() })
        return result
    }

    private static void validateSameValueHasSameName(InvItem item, Result result, String fieldLabel, Closure valueOf, Closure nameOf) {
        Map<String, String> nameByValue = new HashMap<>()
        for (SizesAndColors line : item.getSizesAndColors()) {
            String value = ObjectChecker.toStringOrEmpty(valueOf(line))
            if (ObjectChecker.isEmptyOrNull(value))
                continue
            String name = ObjectChecker.toStringOrEmpty(nameOf(line))
            String previousName = nameByValue.putIfAbsent(value, name)
            if (previousName != null && ObjectChecker.areNotEqual(previousName, name))
                Result.createFailureResult("{0} {1} is used with different names: {2} and {3}", fieldLabel, value, previousName, name)
                        .addToAccumulatingResult(result)
        }
    }

    @Override
    String describe() {
        return "Item: refuses the save when the same size code, or the same color code, appears on more than one line of the " +
                "Sizes and Colors grid with different names. Attach it to the Validate On Save event of Item. Parameter 1 is not used."
    }

    @Override
    List<String> columnNames() {
        return Arrays.asList("Not used - leave empty")
    }
}

The defaults script:

groovy
package com.namasoft.modules.supplychain.domain.utils.plugnplay.groovy

import com.namasoft.common.utilities.ObjectChecker
import com.namasoft.infra.domainbase.datafields.BooleanDF
import com.namasoft.infra.domainbase.datafields.LongTextDF
import com.namasoft.infra.domainbase.entity.base.EntityAction
import com.namasoft.infra.domainbase.util.Result
import com.namasoft.modules.supplychain.domain.details.SizesAndColors
import com.namasoft.modules.supplychain.domain.entities.InvItem

public class EAPreventDuplicateDefaultSizeAndColor implements EntityAction<InvItem> {
    @Override
    Result doAction(InvItem item, LongTextDF... parameters) {
        Result result = Result.createAccumulatingResult()
        Map<String, SizesAndColors> defaultLineByCombination = new HashMap<>()
        for (SizesAndColors line : item.getSizesAndColors()) {
            if (BooleanDF.isFalse(line.getDefaultSizeAndColor()))
                continue
            String size = ObjectChecker.toStringOrEmpty(line.getSize())
            String color = ObjectChecker.toStringOrEmpty(line.getColor())
            SizesAndColors previousLine = defaultLineByCombination.putIfAbsent(size + " / " + color, line)
            if (previousLine != null)
                Result.createFailureResult("More than one default barcode for size {0} and color {1}: {2} and {3}",
                        emptyAsDash(size), emptyAsDash(color), codeOf(previousLine), codeOf(line))
                        .addToAccumulatingResult(result)
        }
        return result
    }

    private static String codeOf(SizesAndColors line) {
        return emptyAsDash(ObjectChecker.toStringOrEmpty(line.getCode()))
    }

    private static String emptyAsDash(String value) {
        return ObjectChecker.isEmptyOrNull(value) ? "-" : value
    }

    @Override
    String describe() {
        return "Item: refuses the save when more than one line of the Sizes and Colors grid is marked Default for the same " +
                "size and color combination. Attach it to the Validate On Save event of Item. Parameter 1 is not used."
    }

    @Override
    List<String> columnNames() {
        return Arrays.asList("Not used - leave empty")
    }
}