{
  "$schema": "https://www.modernedi.com/docs/scenarios/schemas/scenario-binding-v1.schema.json",
  "apiVersion": "modernedi.com/scenario-binding-authoring/v1",
  "kind": "ScenarioBinding",
  "metadata": {
    "id": "supplierPartialFulfillment",
    "name": "Supplier partial shipments and backorders"
  },
  "spec": {
    "regressionCases": [
      {
        "id": "backorder-fulfilled-in-two-shipments",
        "name": "backorder fulfilled in two shipments",
        "parameters": {},
        "observations": [
          {
            "stepId": "purchaseOrder",
            "mappingCaseId": "purchase-order-example",
            "observedAfterSeconds": 0
          },
          {
            "stepId": "purchaseOrderAcknowledgment",
            "mappingCaseId": "acknowledgment",
            "observedAfterSeconds": 60
          },
          {
            "stepId": "advanceShipNotice",
            "mappingCaseId": "shipment-first",
            "observedAfterSeconds": 86400
          },
          {
            "stepId": "invoice",
            "mappingCaseId": "invoice-first",
            "observedAfterSeconds": 90000
          },
          {
            "stepId": "advanceShipNotice",
            "mappingCaseId": "shipment-remainder",
            "observedAfterSeconds": 518400
          },
          {
            "stepId": "invoice",
            "mappingCaseId": "invoice-remainder",
            "observedAfterSeconds": 522000
          }
        ],
        "evaluatedAfterSeconds": 522060,
        "closeSteps": [
          "advanceShipNotice",
          "invoice"
        ],
        "expected": {
          "outcome": "PASSED",
          "checks": []
        }
      },
      {
        "id": "first-shipment-leaves-backorder-open",
        "name": "first shipment leaves backorder open",
        "parameters": {},
        "observations": [
          {
            "stepId": "purchaseOrder",
            "mappingCaseId": "purchase-order-example",
            "observedAfterSeconds": 0
          },
          {
            "stepId": "purchaseOrderAcknowledgment",
            "mappingCaseId": "acknowledgment",
            "observedAfterSeconds": 60
          },
          {
            "stepId": "advanceShipNotice",
            "mappingCaseId": "shipment-first",
            "observedAfterSeconds": 86400
          },
          {
            "stepId": "invoice",
            "mappingCaseId": "invoice-first",
            "observedAfterSeconds": 90000
          }
        ],
        "evaluatedAfterSeconds": 90060,
        "closeSteps": [],
        "expected": {
          "outcome": "PENDING",
          "checks": []
        }
      },
      {
        "id": "arrived-out-of-order-attachments",
        "name": "arrived out of order attachments",
        "parameters": {},
        "observations": [
          {
            "stepId": "invoice",
            "mappingCaseId": "invoice-remainder",
            "observedAfterSeconds": 522000
          },
          {
            "stepId": "advanceShipNotice",
            "mappingCaseId": "shipment-remainder",
            "observedAfterSeconds": 518400
          },
          {
            "stepId": "invoice",
            "mappingCaseId": "invoice-first",
            "observedAfterSeconds": 90000
          },
          {
            "stepId": "advanceShipNotice",
            "mappingCaseId": "shipment-first",
            "observedAfterSeconds": 86400
          },
          {
            "stepId": "purchaseOrderAcknowledgment",
            "mappingCaseId": "acknowledgment",
            "observedAfterSeconds": 60
          },
          {
            "stepId": "purchaseOrder",
            "mappingCaseId": "purchase-order-example",
            "observedAfterSeconds": 0
          }
        ],
        "evaluatedAfterSeconds": 522060,
        "closeSteps": [
          "advanceShipNotice",
          "invoice"
        ],
        "expected": {
          "outcome": "PASSED",
          "checks": []
        }
      },
      {
        "id": "explicit-early-close-does-not-forgive-backorder",
        "name": "explicit early close does not forgive backorder",
        "parameters": {},
        "observations": [
          {
            "stepId": "purchaseOrder",
            "mappingCaseId": "purchase-order-example",
            "observedAfterSeconds": 0
          },
          {
            "stepId": "purchaseOrderAcknowledgment",
            "mappingCaseId": "acknowledgment",
            "observedAfterSeconds": 60
          },
          {
            "stepId": "advanceShipNotice",
            "mappingCaseId": "shipment-first",
            "observedAfterSeconds": 86400
          },
          {
            "stepId": "invoice",
            "mappingCaseId": "invoice-first",
            "observedAfterSeconds": 90000
          }
        ],
        "evaluatedAfterSeconds": 90060,
        "closeSteps": [
          "advanceShipNotice",
          "invoice"
        ],
        "expected": {
          "outcome": "FAILED",
          "checks": [
            {
              "id": "assertion:advanceShipNoticeQuantitiesMatchOrder",
              "outcome": "FAILED",
              "code": "KEYED_SUM_MISMATCH"
            }
          ]
        }
      }
    ],
    "definition": {
      "namespace": "example",
      "key": "supplier-partial-fulfillment",
      "version": "1.0.0",
      "contentSha256": "6941bb901539d9bc62c9883a7892e44126c4cd6c152daffc67645e2532779ffe"
    },
    "environment": "test",
    "actors": [
      {
        "actorId": "retailer",
        "endpoint": {
          "kind": "partner",
          "partnerId": 42
        }
      },
      {
        "actorId": "supplier",
        "endpoint": {
          "kind": "workspace"
        }
      }
    ],
    "steps": [
      {
        "stepId": "purchaseOrder",
        "syntaxTree": {
          "x12Version": "004010",
          "transactionSet": "850"
        },
        "target": {
          "kind": "runtime-mapping",
          "runtimeMappingId": 101
        },
        "factSources": [
          {
            "fact": "purchaseOrderNumber",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "ST->BEG(03)"
            }
          },
          {
            "fact": "lineKeys",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "forEach(line in orderBy(line in ST->PO1 => toJson([trim(line(07)[0]), trim(line(03)[0])])) => toJson([trim(line(07)[0]), trim(line(03)[0])]))"
            }
          },
          {
            "fact": "quantities",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "forEach(line in orderBy(line in ST->PO1 => toJson([trim(line(07)[0]), trim(line(03)[0])])) => line(02))"
            }
          },
          {
            "fact": "linesValid",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "countOf(line in ST->PO1) > 0 && allOf(line in ST->PO1 : line(06) == \"VN\" && !isEmpty(trim(line(07)[0])) && !isEmpty(trim(line(03)[0])) && toNumber(line(02)) > 0 && toNumber(line(04)) >= 0)"
            }
          },
          {
            "fact": "unitPrices",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "forEach(line in orderBy(line in ST->PO1 => toJson([trim(line(07)[0]), trim(line(03)[0])])) => line(04))"
            }
          },
          {
            "fact": "orderTotal",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "sumOf(line in ST->PO1 => round(toNumber(line(02)) * toNumber(line(04)), 2))"
            }
          },
          {
            "fact": "currency",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "ST->CUR(02)"
            }
          }
        ]
      },
      {
        "stepId": "purchaseOrderAcknowledgment",
        "syntaxTree": {
          "x12Version": "004010",
          "transactionSet": "855"
        },
        "target": {
          "kind": "runtime-mapping",
          "runtimeMappingId": 102
        },
        "factSources": [
          {
            "fact": "purchaseOrderNumber",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "ST->BAK(03)"
            }
          },
          {
            "fact": "acknowledgmentCode",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "ST->BAK(02)"
            }
          },
          {
            "fact": "lineKeys",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "forEach(line in orderBy(line in ST->PO1 => toJson([trim(line(07)[0]), trim(line(03)[0])])) => toJson([trim(line(07)[0]), trim(line(03)[0])]))"
            }
          },
          {
            "fact": "unitPrices",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "forEach(line in orderBy(line in ST->PO1 => toJson([trim(line(07)[0]), trim(line(03)[0])])) => line(04))"
            }
          },
          {
            "fact": "quantities",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "forEach(line in orderBy(line in ST->PO1 => toJson([trim(line(07)[0]), trim(line(03)[0])])) => line->ACK(02))"
            }
          },
          {
            "fact": "linesValid",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "countOf(line in ST->PO1) > 0 && allOf(line in ST->PO1 : line(06) == \"VN\" && !isEmpty(trim(line(07)[0])) && !isEmpty(trim(line(03)[0])) && toNumber(line(02)) > 0 && toNumber(line(04)) >= 0 && countOf(ack in line->ACK) == 1 && allOf(ack in line->ACK : (ack(01) == \"IA\" || ack(01) == \"IB\") && toNumber(ack(02)) == toNumber(line(02)) && ack(03) == line(03)))"
            }
          },
          {
            "fact": "hasBackorder",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "countOf(line in ST->PO1 : line->ACK(01) == \"IB\") > 0"
            }
          },
          {
            "fact": "backorderedQuantity",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "sumOf(line in ST->PO1 : line->ACK(01) == \"IB\" => toNumber(line->ACK(02)))"
            }
          }
        ]
      },
      {
        "stepId": "advanceShipNotice",
        "syntaxTree": {
          "x12Version": "004010",
          "transactionSet": "856"
        },
        "target": {
          "kind": "runtime-mapping",
          "runtimeMappingId": 103
        },
        "factSources": [
          {
            "fact": "purchaseOrderNumber",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "ST->HL[03 == \"O\"]->PRF(01)"
            }
          },
          {
            "fact": "shipmentId",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "ST->BSN(02)"
            }
          },
          {
            "fact": "lineKeys",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "forEach(line in orderBy(line in ST->HL[03 == \"I\"] => toJson([trim(line->LIN(03)[0]), trim(line->SN1(03)[0])])) => toJson([trim(line->LIN(03)[0]), trim(line->SN1(03)[0])]))"
            }
          },
          {
            "fact": "quantities",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "forEach(line in orderBy(line in ST->HL[03 == \"I\"] => toJson([trim(line->LIN(03)[0]), trim(line->SN1(03)[0])])) => line->SN1(02))"
            }
          },
          {
            "fact": "linesValid",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "countOf(line in ST->HL[03 == \"O\"]) == 1 && countOf(line in ST->HL[03 == \"I\"]) > 0 && allOf(line in ST->HL[03 == \"I\"] : line->LIN(02) == \"VN\" && !isEmpty(trim(line->LIN(03)[0])) && !isEmpty(trim(line->SN1(03)[0])) && toNumber(line->SN1(02)) > 0)"
            }
          }
        ]
      },
      {
        "stepId": "invoice",
        "syntaxTree": {
          "x12Version": "004010",
          "transactionSet": "810"
        },
        "target": {
          "kind": "runtime-mapping",
          "runtimeMappingId": 104
        },
        "factSources": [
          {
            "fact": "purchaseOrderNumber",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "ST->BIG(04)"
            }
          },
          {
            "fact": "shipmentId",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "ST->REF[01 == \"SI\"](02)"
            }
          },
          {
            "fact": "lineKeys",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "forEach(line in orderBy(line in ST->IT1 => toJson([trim(line(07)[0]), trim(line(03)[0])])) => toJson([trim(line(07)[0]), trim(line(03)[0])]))"
            }
          },
          {
            "fact": "quantities",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "forEach(line in orderBy(line in ST->IT1 => toJson([trim(line(07)[0]), trim(line(03)[0])])) => line(02))"
            }
          },
          {
            "fact": "linesValid",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "countOf(line in ST->IT1) > 0 && allOf(line in ST->IT1 : line(06) == \"VN\" && !isEmpty(trim(line(07)[0])) && !isEmpty(trim(line(03)[0])) && toNumber(line(02)) > 0 && toNumber(line(04)) >= 0)"
            }
          },
          {
            "fact": "unitPrices",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "forEach(line in orderBy(line in ST->IT1 => toJson([trim(line(07)[0]), trim(line(03)[0])])) => line(04))"
            }
          },
          {
            "fact": "lineTotal",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "sumOf(line in ST->IT1 => round(toNumber(line(02)) * toNumber(line(04)), 2))"
            }
          },
          {
            "fact": "invoiceTotal",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "toNumber(ST->TDS(01)) / 100"
            }
          },
          {
            "fact": "currency",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "ST->CUR(02)"
            }
          },
          {
            "fact": "invoiceNumber",
            "source": {
              "kind": "x12-mapper-expression",
              "expression": "ST->BIG(02)"
            }
          }
        ]
      }
    ]
  }
}
