<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://izara.io/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sven+the+Barbarian</id>
	<title>Izara Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://izara.io/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sven+the+Barbarian"/>
	<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php/Special:Contributions/Sven_the_Barbarian"/>
	<updated>2026-08-26T05:23:16Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Per_Service_Schemas&amp;diff=4624</id>
		<title>Per Service Schemas</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Per_Service_Schemas&amp;diff=4624"/>
		<updated>2026-08-25T14:07:23Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Each service manages a schema of object/resources that it is responsible for, this schema is available to other services and frontends. The schema includes a list of fields available for each object.&lt;br /&gt;
&lt;br /&gt;
= File Structure =&lt;br /&gt;
&lt;br /&gt;
* see [[Repository structure#schemas|Repository structure]]&lt;br /&gt;
&lt;br /&gt;
= ObjectSchema | ObjectFieldSchema.js =&lt;br /&gt;
&lt;br /&gt;
== Not extendObjType ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;xx&amp;quot;,&lt;br /&gt;
	shortNameObjectType:&amp;quot;x&amp;quot;, // optional, use when generate code create lambda role with long name&lt;br /&gt;
	canDelete: false, // whether any fields can be deleted // default = false&lt;br /&gt;
	belongTo: { &lt;br /&gt;
		serviceTag:&amp;quot;iii&amp;quot;,&lt;br /&gt;
		objectType:&amp;quot;jjj&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
    // how is the object created&lt;br /&gt;
    // userGenerated there will be generated endpoints for api or sqs (used in importBatchMain) to create object&lt;br /&gt;
    // systemGenerated must be created by flow/s&lt;br /&gt;
    // searchResultGenerated see separate notes below&lt;br /&gt;
    generatedBy: &amp;quot;xx&amp;quot;, // &amp;quot;user&amp;quot;|&amp;quot;systemNoUserId&amp;quot;|&amp;quot;systemWithUserId&amp;quot;|&amp;quot;searchResultGenerated&amp;quot; // required&lt;br /&gt;
    searchResultGeneratedFlowType: {}, // for generatedBy = searchResultGenerated&lt;br /&gt;
	addOnDataStructure: [ // optional, add for additional setting to objectType&lt;br /&gt;
		{&lt;br /&gt;
			// all fields that a user can edit must be in versionedData, and all fields in versionedData must be editable by user&lt;br /&gt;
			type:&amp;quot;versionedData&amp;quot;,&lt;br /&gt;
			versionedDataLabel: &amp;quot;xx&amp;quot;, // versionedData label name&lt;br /&gt;
			storageResourceTag : &amp;quot;xx&amp;quot;, // ref to storegeResourceTag&lt;br /&gt;
			fieldNames: { // fieldName in versionedData cannot have in in main objectSchema.fieldNames&lt;br /&gt;
				&amp;quot;aaa&amp;quot;:{ // fieldName&lt;br /&gt;
					type: &amp;quot;xx&amp;quot;, // string|integer|number|timestamp|currency|currencyValue|float|special|object|boolean|arrayMixed|arrayNumeric|arrayString&lt;br /&gt;
					requiredOnCreate: false, // default = false&lt;br /&gt;
					optionalOnCreate: false, // default = false,&lt;br /&gt;
					validation: {&lt;br /&gt;
                      itemValidation:{} // for validate item in array&lt;br /&gt;
                    },&lt;br /&gt;
                    // probably impossible to have fromObjType, because data can be changed by user here&lt;br /&gt;
					fromObjType:{&lt;br /&gt;
						serviceTag: &amp;quot;xxx&amp;quot;, &lt;br /&gt;
						objectType: &amp;quot;xxx&amp;quot; &lt;br /&gt;
					},&lt;br /&gt;
				},&lt;br /&gt;
				// ...&lt;br /&gt;
			}&lt;br /&gt;
        },&lt;br /&gt;
        { // can have multiple addOn of type attributeTree&lt;br /&gt;
          type:&amp;quot;attributeTree&amp;quot;,           &lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;translation&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;propertyValue&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;mediaLink&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;rbac&amp;quot;,&lt;br /&gt;
          billalble:true // true || false , required&lt;br /&gt;
        },&lt;br /&gt;
		// ...&lt;br /&gt;
	],&lt;br /&gt;
	plugInTags: [&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;], // plugIns that can be connected to this objType&lt;br /&gt;
	storageResources:{&lt;br /&gt;
		&amp;quot;xxx&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // graph			&lt;br /&gt;
			graphServerTag: &amp;quot;xx&amp;quot;, // setting for storageType graph&lt;br /&gt;
            additionalGraphIndexes:[[&#039;fieldName1&#039;, &#039;fieldName2&#039;, ...], [...]]  // will make graph index with specific fieldName &lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;zzz&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // dynamoDB&lt;br /&gt;
			// setting for storageType dynamoDB&lt;br /&gt;
			tableName: &amp;quot;xx&amp;quot;,&lt;br /&gt;
			groupByPartitionKeyField: &amp;quot;xx&amp;quot;, // use groupByPartitionKeyField as partition key and not have sort key in dynamoDB, if have multiple identifiers will concat it. And use it as partitionKey.&lt;br /&gt;
            serviceTag:&amp;quot;zz&amp;quot;// default own service.&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	fieldNames: {&lt;br /&gt;
		xxx: { // fieldName&lt;br /&gt;
			type: &amp;quot;xx&amp;quot;,  // string|integer|number|timestamp|currency|currencyValue|float|special|object|boolean|arrayMixed|arrayNumeric|arrayString&lt;br /&gt;
            randomOnCreate: false,   // default = false , can set true in fieldName that part of identifiers and identifiers have single identifierFieldname&lt;br /&gt;
			requiredOnCreate: false, // default = false&lt;br /&gt;
			optionalOnCreate: false, // default = false&lt;br /&gt;
			canUpdate: true, // default = true (only system/flows can edit, no history of changes unless flow manually adds)&lt;br /&gt;
			validation: {&lt;br /&gt;
			  itemValidation:{}  // for validate item in array&lt;br /&gt;
            }, // maybe ajv syntax&lt;br /&gt;
			storageResourceTags: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // reference to storageResources property&lt;br /&gt;
		    fromObjType:{&lt;br /&gt;
			  serviceTag: &amp;quot;xxx&amp;quot;, &lt;br /&gt;
			  objectType: &amp;quot;xxx&amp;quot; &lt;br /&gt;
			},&lt;br /&gt;
            hashOnCreate: [&amp;quot;xx&amp;quot;, &amp;quot;yy&amp;quot;], // reference to other fieldName, &lt;br /&gt;
            statusField: true, // use for objectSchema inside flowSchema, identify which field is statusField &lt;br /&gt;
&lt;br /&gt;
			// comes from requiredOnCreate relationships&lt;br /&gt;
			fromRequiredOnCreate: { &lt;br /&gt;
				relType: {&lt;br /&gt;
					serviceTag:&amp;quot;aa&amp;quot;,&lt;br /&gt;
					relationshipTag:&amp;quot;bb&amp;quot;&lt;br /&gt;
				},&lt;br /&gt;
				// or&lt;br /&gt;
				belongToObjType: true, // if set to true use the belongTo relationship to belongTo objType&lt;br /&gt;
&lt;br /&gt;
				fieldName:&amp;quot;&amp;quot; // optional default= same field name eg: now default == xxx if not defined(use fieldname of object inside link when create)&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
		// ...&lt;br /&gt;
	},&lt;br /&gt;
    compositeKeyDeliminator: &amp;quot;xx&amp;quot;, // join partitionKey and sortKey&lt;br /&gt;
	identifiers: [&lt;br /&gt;
    // for dynamoDB storageType &lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // composite partition keys in DynamoDB&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		name: &amp;quot;zz&amp;quot;, // name of field in database&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	},&lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // composite partition keys in DynamoDB&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		name: &amp;quot;zz&amp;quot;, // name of field in database&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	},&lt;br /&gt;
   &lt;br /&gt;
    // for graph storageType&lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;identifier&amp;quot;,&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // identifier field in graph or composite partition keys in DynamoDB&lt;br /&gt;
        name: &amp;quot;zzz&amp;quot;              // use when save in dynamoDB partitionKey&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;	&lt;br /&gt;
	},&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== extendObjType ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	// for objects stored in graph this will add another node label&lt;br /&gt;
	objectType: &amp;quot;xx&amp;quot;, // new label to add&lt;br /&gt;
	extendObjType: { // core object that this object extends&lt;br /&gt;
		serviceTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;xxx&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources:{ // these are the storageResources that carry the extended objects settings, &lt;br /&gt;
		// (see above)&lt;br /&gt;
	},&lt;br /&gt;
	fieldNames: {&lt;br /&gt;
		// (see above) &lt;br /&gt;
	},&lt;br /&gt;
	// canDelete/identifiers come from the core object&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== searchResultGenerated ==&lt;br /&gt;
&lt;br /&gt;
* must be created by flow&lt;br /&gt;
* eg: variantProduct&lt;br /&gt;
* not have any storageResources&lt;br /&gt;
* identifiers are automatically searchResultData identifiers&lt;br /&gt;
* a searchResult request for this object will enter the searchResultGeneratedFlowType flow which creates searchResultData that can then be queried/sorted&lt;br /&gt;
* all relationships must be storageType = lambda, eg translate from variantProduct to variant uses a translateId flow to query the variantProduct identifier (searchResultData) to find the variantId in it&#039;s requiredData results&lt;br /&gt;
* searchResultGeneratedFlowType takes over after creating searchResultMain record until processRequiredData&lt;br /&gt;
* if objectSchema defines any fieldnames, then they are found using a flow, maybe as hooks in per service findData&lt;br /&gt;
* when finding direct fieldname, will need to check if requireData already exists, if not enter flow/findData to create&lt;br /&gt;
* no fields can be edited, so can show in forms but no updates performed&lt;br /&gt;
&lt;br /&gt;
= Relationships Schema | ObjectRelationships.js =&lt;br /&gt;
&lt;br /&gt;
* stored in top level schemas folder&lt;br /&gt;
* parent/child determines relationship direction for graph relationships&lt;br /&gt;
* have one service that contains information of each relationship &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// relationship schema in responsible service&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;xxx&amp;quot;: { // relationshipTag - name of relationship type stored in graph&lt;br /&gt;
      generatedBy: &amp;quot;xx&amp;quot;, // &amp;quot;user&amp;quot;|&amp;quot;systemNoUserId&amp;quot;|&amp;quot;systemWithUserId&amp;quot;&lt;br /&gt;
      canChangeToRelTypes: [&lt;br /&gt;
		{&lt;br /&gt;
			relType: { // relType that this relType can change to &lt;br /&gt;
			  serviceTag:&amp;quot;xxx&amp;quot;,&lt;br /&gt;
			  relationshipTag: &amp;quot;yyy&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			changeBy: &amp;quot;xx&amp;quot;, // &amp;quot;user&amp;quot;|&amp;quot;systemNoUserId&amp;quot;|&amp;quot;systemWithUserId&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
        // another relType&lt;br /&gt;
      ],&lt;br /&gt;
      storageResources:{&lt;br /&gt;
		&amp;quot;xxx&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // dynamoDB | graph | lambda&lt;br /&gt;
		    // if storageType=&amp;quot;dynamoDB&amp;quot;  will not specify tableName in relationship schema&lt;br /&gt;
&lt;br /&gt;
			// setting for storageType graph&lt;br /&gt;
			graphServerTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
            additionalGraphIndexes:[[&#039;fieldName1&#039;, &#039;fieldName2&#039;, ...], [...]],  // will make graph index with specific fieldName &lt;br /&gt;
&lt;br /&gt;
			// setting for storageType lambda&lt;br /&gt;
			serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
			functionName: &amp;quot;xx&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
      },&lt;br /&gt;
      fieldNames: {&lt;br /&gt;
		&amp;quot;xxx&amp;quot;: { // relationship property name&lt;br /&gt;
			type: &amp;quot;string&amp;quot;, // &amp;quot;string&amp;quot; | &amp;quot;number&amp;quot; ...&lt;br /&gt;
			requiredOnCreate: false, // default=false&lt;br /&gt;
			optionalOnCreate: false, // default = false&lt;br /&gt;
			updateBy: &amp;quot;xx&amp;quot;, // &amp;quot;user&amp;quot;|&amp;quot;systemNoUserId&amp;quot;|&amp;quot;systemWithUserId&amp;quot;|&amp;quot;none&amp;quot;&lt;br /&gt;
			validation: {} // ajv syntax&lt;br /&gt;
		},&lt;br /&gt;
		//...other relationship properties&lt;br /&gt;
      },&lt;br /&gt;
      links: [&lt;br /&gt;
        {&lt;br /&gt;
          storageResourceTags: [&amp;quot;xxx&amp;quot;],   // reference from storageResources property&lt;br /&gt;
          canDelete: false                // default = false, if set true will allow delete relationship between 2 objType&lt;br /&gt;
          from: {&lt;br /&gt;
            objType: {&lt;br /&gt;
              serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
              objectType: &amp;quot;xx&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            requiredOnCreate: true, // if set true will create relationshipTag when create objType data, if both &amp;quot;from&amp;quot; and &amp;quot;to&amp;quot; linkType=&amp;quot;many&amp;quot; should not have requiredOnCreate, exists in &amp;quot;from&amp;quot; or &amp;quot;to&amp;quot; only&lt;br /&gt;
            linkType: &amp;quot;&amp;quot;,   // one | many&lt;br /&gt;
          //   moveBy: &amp;quot;xx&amp;quot;, // &amp;quot;user&amp;quot;|&amp;quot;systemNoUserId&amp;quot;|&amp;quot;systemWithUserId&amp;quot;|&amp;quot;none&amp;quot;&lt;br /&gt;
          // belongTo:true&lt;br /&gt;
          },&lt;br /&gt;
          to: {&lt;br /&gt;
            objType: {&lt;br /&gt;
              serviceTag: &amp;quot;yy&amp;quot;,&lt;br /&gt;
              objectType: &amp;quot;yy&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            linkType: &amp;quot;&amp;quot;,   // one | many&lt;br /&gt;
             // moveBy allows the relationship to be moved between 2 instances of the same objType only&lt;br /&gt;
	        moveBy: &amp;quot;xx&amp;quot;, // &amp;quot;user&amp;quot;|&amp;quot;systemNoUserId&amp;quot;|&amp;quot;systemWithUserId&amp;quot;|&amp;quot;none&amp;quot;&lt;br /&gt;
            belongTo:true, // false&lt;br /&gt;
          },&lt;br /&gt;
          requestProperties: {&lt;br /&gt;
            // if storageType is Lambda and translateIds/linkPath requires properties set them here (eg sellOffer&amp;gt;orderPrice)&lt;br /&gt;
            tag_deliverTo: {&lt;br /&gt;
              requestPropertyType: &amp;quot;objectIdentifier&amp;quot;,&lt;br /&gt;
              objType: {&lt;br /&gt;
                serviceTag: &amp;quot;Locations&amp;quot;,&lt;br /&gt;
                objectType: &amp;quot;locationNode&amp;quot; // deliversToLocationNode&lt;br /&gt;
              },&lt;br /&gt;
              identifiersFieldName: &amp;quot;locationNodeId&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            // ... other request properties&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        // ...other link&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Reference Relationships Schema | RefObjectRelationships.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// reference to relationshipTag in external service&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    objectType: &amp;quot;zz&amp;quot;,              // objectType in local service&lt;br /&gt;
    relationshipTag: &amp;quot;xxx&amp;quot;,        // name of relationshiptag of objType&lt;br /&gt;
    relationshipServiceTag: &amp;quot;xx&amp;quot;   // point to service tag that contain data of relationshipTag of objType&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Flow Schema | FlowSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  [&lt;br /&gt;
    {&lt;br /&gt;
      flowTag: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
      initiateBy: &amp;quot;xx&amp;quot;, // &amp;quot;user&amp;quot;|&amp;quot;systemNoUserId&amp;quot;|&amp;quot;systemWithUserId&amp;quot;&lt;br /&gt;
      handleObj: &amp;quot;one&amp;quot;,           // &amp;quot;one&amp;quot; | &amp;quot;multi&amp;quot;&lt;br /&gt;
      statusType: &amp;quot;statusField&amp;quot;,  // &amp;quot;statusField&amp;quot; | &amp;quot;storedCache&amp;quot; | &amp;quot;none&amp;quot; | &amp;quot;triggerCache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      // statusType=&amp;quot;triggerCache&amp;quot; setting &lt;br /&gt;
      triggerType: &amp;quot;storedCache&amp;quot;, // &amp;quot;storedCache&amp;quot; | &amp;quot;switch&amp;quot;&lt;br /&gt;
      triggerFlowTypes: [&lt;br /&gt;
        //... triggerFlowType&lt;br /&gt;
      ],&lt;br /&gt;
&lt;br /&gt;
      // statusType=&amp;quot;statusField&amp;quot; | &amp;quot;triggerCache&amp;quot; | &amp;quot;storedCache&amp;quot; setting:&lt;br /&gt;
      objType: {},&lt;br /&gt;
&lt;br /&gt;
      event: [&amp;quot;ownTopic&amp;quot;],  // &amp;quot;ownTopic&amp;quot; | &amp;quot;extTopic&amp;quot; | &amp;quot;s3&amp;quot; | &amp;quot;eventBridge&amp;quot; | &amp;quot;lambdaSyncInv&amp;quot; | &amp;quot;lambdaSyncApi&amp;quot; | &amp;quot;generatedCode&amp;quot; | &amp;quot;dsq&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      // event=&amp;quot;s3&amp;quot; setting&lt;br /&gt;
      bucketName: &amp;quot;xxx&amp;quot;, // bucket for s3 event&lt;br /&gt;
      createBucket: boolean, // if true will generate new bucket with bucketName if false will point to old bucket that already have &lt;br /&gt;
&lt;br /&gt;
      // event=&amp;quot;eventBridge&amp;quot; setting&lt;br /&gt;
      schedules: [&lt;br /&gt;
        {&lt;br /&gt;
          name: &#039;your-scheduled-rate-event-name&#039;,&lt;br /&gt;
          description: &#039;your scheduled rate event description&#039;,&lt;br /&gt;
          rate: [&amp;quot;rate(1 minute)&amp;quot;,],&lt;br /&gt;
          input: {}&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
&lt;br /&gt;
      outputTopic: boolean,&lt;br /&gt;
&lt;br /&gt;
      flowSteps: {&lt;br /&gt;
        inTag: { // will generate Topic serviceTag_stage_yyy_inTag&lt;br /&gt;
          properties: [], // reference to stepProperties key, the first lambda&#039;s input properties and messageAttributes are the flow&#039;s input properties and messageAttributes&lt;br /&gt;
          messageAttributes: [], // reference to stepProperties key&lt;br /&gt;
          plugInHooks: [&lt;br /&gt;
            {&lt;br /&gt;
              plugInHookTag: &amp;quot;&amp;quot;,&lt;br /&gt;
              objType: {}, // used to query connection dynamo for an object instance in current flow&lt;br /&gt;
            },&lt;br /&gt;
          ],&lt;br /&gt;
          returnValues: {&lt;br /&gt;
            properties: [], // reference to stepProperties key&lt;br /&gt;
            messageAttributes: [], // reference to stepProperties key, only for outputTopic=true&lt;br /&gt;
          },&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
        // another flow steps&lt;br /&gt;
        flowStep1: { // will generate Topic serviceTag_stage_yyy_Flow1&lt;br /&gt;
          properties: [], // reference to stepProperties key&lt;br /&gt;
          messageAttributes: [], // reference to stepProperties key&lt;br /&gt;
          event: [&amp;quot;ownTopic&amp;quot;],  // &amp;quot;ownTopic&amp;quot; | &amp;quot;extTopic&amp;quot; | &amp;quot;s3&amp;quot; | &amp;quot;eventBridge&amp;quot; | &amp;quot;lambdaSyncInv&amp;quot; | &amp;quot;lambdaSyncApi&amp;quot; | &amp;quot;generatedCode&amp;quot; | &amp;quot;dsq&amp;quot;&lt;br /&gt;
          // handle splitting logic into awaitingStep/awaitingMultipleSteps&lt;br /&gt;
          // handle splitting logic into paginated lambda&lt;br /&gt;
&lt;br /&gt;
          previousSteps: [&lt;br /&gt;
            {&lt;br /&gt;
              sourceType:&amp;quot;ownTopic&amp;quot;, // if from own flow&lt;br /&gt;
              stepName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
              sourceType: &amp;quot;extTopic&amp;quot;, // triggered by output from external service&lt;br /&gt;
              serviceTag: &amp;quot;InventoryService&amp;quot;,&lt;br /&gt;
              topic: &amp;quot;ReserveStock_In&amp;quot;,&lt;br /&gt;
              fromStepNames: [&amp;quot;xx&amp;quot;] // which step in this flow sent request to external flow, used to find awaitingStep prefix&lt;br /&gt;
            }            &lt;br /&gt;
          ],&lt;br /&gt;
          nextSteps: [&lt;br /&gt;
            {&lt;br /&gt;
              targetType:&amp;quot;ownTopic&amp;quot;, // if from own flow&lt;br /&gt;
              stepName: &amp;quot;yyy&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
              targetType: &amp;quot;extTopic&amp;quot;,&lt;br /&gt;
              serviceTag: &amp;quot;InventoryService&amp;quot;,&lt;br /&gt;
              topic: &amp;quot;ReserveStock_In&amp;quot;,&lt;br /&gt;
              toStepNames: [&amp;quot;xx&amp;quot;] // which step in this flow sent request to external flow, used to find awaitingStep prefix&lt;br /&gt;
            }&lt;br /&gt;
          ],&lt;br /&gt;
&lt;br /&gt;
          plugInHooks: [&lt;br /&gt;
            {&lt;br /&gt;
              plugInHookTag: &amp;quot;&amp;quot;,&lt;br /&gt;
              objType: {}, // used to query connection dynamo for an object instance in current flow&lt;br /&gt;
            },&lt;br /&gt;
          ],&lt;br /&gt;
          returnValues: { // the last lambda function returnValues are the flow&#039;s returnValues&lt;br /&gt;
            properties: [], // reference to stepProperties key&lt;br /&gt;
            messageAttributes: [], // reference to stepProperties key, only for outputTopic=true&lt;br /&gt;
          },&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
      },&lt;br /&gt;
&lt;br /&gt;
      stepProperties: { // normalized all stepProperties&lt;br /&gt;
        &amp;quot;uuid&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          type: &amp;quot;object&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          childProperties: [&amp;quot;uuid2&amp;quot;, &amp;quot;uuid3&amp;quot;]&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid2&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid3&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid4&amp;quot;: {&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          objectField: {&lt;br /&gt;
            objType: {},&lt;br /&gt;
            fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          overwritePropertyName: &amp;quot;xx&amp;quot; // optional, if have objectField and have overwritePropertyName will overwrite fieldName &lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
      stepMessageAttributes: { // normalized all stepMessageAttributes&lt;br /&gt;
        &amp;quot;uuid&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid2&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= System Text Schema | SystemTextSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
	{&lt;br /&gt;
		namespace: &amp;quot;xxx&amp;quot;, // groups files downloaded by frontend&lt;br /&gt;
		systemTextTag: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
	}&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Auto generated systemText and namespaces ==&lt;br /&gt;
&lt;br /&gt;
=== systemNotification names ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;sysNotification_{notificationGrouping}&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{notificationTag}&amp;quot;&lt;br /&gt;
* eg shown on notification settings page&lt;br /&gt;
&lt;br /&gt;
=== objType names ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;objTypes&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{serviceTag}_{objectType}&amp;quot;&lt;br /&gt;
* eg shown on config pages, eg pulldown list of object types&lt;br /&gt;
&lt;br /&gt;
=== objType field name descriptions ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;objType_fielddesc_{serviceTag}_{objectType}&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{fieldname}&amp;quot;&lt;br /&gt;
* eg shown on config pages, eg info box for each field name&lt;br /&gt;
&lt;br /&gt;
= System Notification Schema | SystemNotificationSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
	{&lt;br /&gt;
		notificationTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
		notificationGrouping: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
		weight: &amp;quot;##&amp;quot;,&lt;br /&gt;
	},&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Error Schema =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
	{&lt;br /&gt;
		errorTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
		errorAction: &amp;quot;xxx&amp;quot;, // &amp;quot;throw&amp;quot;|&amp;quot;return&amp;quot;&lt;br /&gt;
		sharedLibrary: true, // if true gets added to a generated npm library repository&lt;br /&gt;
	}&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* errorsFound is array of objects with properties errorType and details&lt;br /&gt;
* flow classifies each error according to whether it believes calling flow should throw (validation error) or pass back/save as errorsFound (conditional error)&lt;br /&gt;
* calling flow uses library to handle throw|return, but can overwrite how to handle specific errors&lt;br /&gt;
&lt;br /&gt;
= Generated S3 schema files =&lt;br /&gt;
&lt;br /&gt;
* generate multiple files for different uses, eg:&lt;br /&gt;
*# list of saved fieldNames for Create&lt;br /&gt;
*# list of saved+calculated for Update/Info pages&lt;br /&gt;
*# graphSchemas&lt;br /&gt;
*# relationships (used by Search/Sort Results)&lt;br /&gt;
&lt;br /&gt;
= Use Cases =&lt;br /&gt;
&lt;br /&gt;
== Find Deployed Service Name ==&lt;br /&gt;
&lt;br /&gt;
* other services can use fixed serviceTag to get deployed serviceName from serviceSchema on S3&lt;br /&gt;
* used to build resource names for external services&lt;br /&gt;
* eg when one service needs to send a message into an SNS belonging to a different service&lt;br /&gt;
&lt;br /&gt;
== Standard Create, Update, List, Delete pages ==&lt;br /&gt;
&lt;br /&gt;
* List and Delete are maybe not required, use table data system instead.&lt;br /&gt;
* object schema can add validation information that can be used on the frontend to check before sending to backend, and by the backend to validate the data before handling&lt;br /&gt;
&lt;br /&gt;
=== Create Object ===&lt;br /&gt;
&lt;br /&gt;
* can configure what fields are shown&lt;br /&gt;
* requiredOnCreate fields must be shown &lt;br /&gt;
&lt;br /&gt;
=== Edit Object ===&lt;br /&gt;
&lt;br /&gt;
* users setup any number of pages for object types with configurable fields shown&lt;br /&gt;
* fields can be either display only or edit&lt;br /&gt;
* each field can adjust it&#039;s display properties (perhaps via cssStyles)&lt;br /&gt;
&lt;br /&gt;
== Menu Config ==&lt;br /&gt;
&lt;br /&gt;
When adding menu items can add links to create, update, list, delete objects, user chooses the service then from that service&#039;s list of objects and what action is being performed. For update/delete perhaps links to a standard page that asks for the identifier before presenting the page.&lt;br /&gt;
&lt;br /&gt;
== Tabled Data ==&lt;br /&gt;
&lt;br /&gt;
When viewing tabled data the frontend pulls the tableId&#039;s config from backend, then when requesting the data also requests the serviceTag &amp;gt; objectType schema for use when displaying the data.&lt;br /&gt;
&lt;br /&gt;
== Code Standardization ==&lt;br /&gt;
&lt;br /&gt;
Code such as middleware validation schema and saving data to databases can be standardized.&lt;br /&gt;
&lt;br /&gt;
== Code Generation ==&lt;br /&gt;
&lt;br /&gt;
Endpoints per object for actions such as Create/Delete/Update can be automatically generated from objectSchema.&lt;br /&gt;
&lt;br /&gt;
=== Code Generation Structure ===&lt;br /&gt;
&lt;br /&gt;
* npm for generic code generation, can be used in any project, includes functions for generating Source files from templates and developer files&lt;br /&gt;
* npm for per project specific files, eg templates for the project (Create/Update/.. code)&lt;br /&gt;
* Empty Service Template has GenerateCode.js script file in root dir that is run to generate code, it invokes a generation function from generic npm with param that points to per project npm&#039;s templates&lt;br /&gt;
* generated Source retains hook tags (and any developer added code), so if developer wants to update developer&#039;s file with updated template code they can generate code and simply copy generated Source to src folder&lt;br /&gt;
&lt;br /&gt;
= Graph Server Config =&lt;br /&gt;
&lt;br /&gt;
* S3 has a list of graphServerTag&#039;s linking to the GraphHandler serviceTag responsible for the graph&lt;br /&gt;
* multiple graphServerTags can point to one GraphHandler, combining graphs into one server&lt;br /&gt;
* when creating each GraphHandler&#039;s graph schemas, for each field split out the fields into each GraphHandler using the graphServerTag, if multiple graphServerTags for a field point to the same GraphHandler combine the fields to create GraphHandler&#039;s graph schema&lt;br /&gt;
* every GraphHandler an object is saved into will require it&#039;s identifiers&lt;br /&gt;
* when eg updating fields for an object separate the fields per GraphHandler before sending the request to update each graph&lt;br /&gt;
&lt;br /&gt;
= Extended Object Types =&lt;br /&gt;
&lt;br /&gt;
* Allows for one graph node to have multiple labels&lt;br /&gt;
* graph schema is created for both the core object and the extended object&lt;br /&gt;
* eg Media Manager&#039;s has a node schema for &amp;quot;media&amp;quot; object type, and Image service has a node schema for &amp;quot;image&amp;quot; object type&lt;br /&gt;
* the extended object builds it&#039;s schema by combining core + extended settings&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - Per Service Schemas|Per Service Schemas]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Standard_Data_Structures&amp;diff=4623</id>
		<title>Standard Data Structures</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Standard_Data_Structures&amp;diff=4623"/>
		<updated>2026-08-25T14:04:07Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
Standard structure and definitions.&lt;br /&gt;
&lt;br /&gt;
= Definition =&lt;br /&gt;
&lt;br /&gt;
== objType ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	serviceTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
	objectType: &amp;quot;yyy&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
use to identify which serviceTag that object schema located&lt;br /&gt;
* serviceTag: service tag that stored object schema&lt;br /&gt;
* objectType: name of object schema&lt;br /&gt;
&lt;br /&gt;
== objTypeConcat ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;serviceTag&amp;gt;_&amp;lt;objectType&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* objTypeConcat: &amp;quot;serviceTag&amp;quot; + &amp;quot;_&amp;quot; + &amp;quot;objectType&amp;quot;&lt;br /&gt;
* now use as the name of node label in graph database&lt;br /&gt;
&lt;br /&gt;
== objTypeId ==&lt;br /&gt;
* hash of objType object&lt;br /&gt;
&lt;br /&gt;
== relType ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	serviceTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
	relationshipTag: &amp;quot;yyy&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
use to identify which serviceTag that relationship schema  located&lt;br /&gt;
* serviceTag: service tag that stored object schema&lt;br /&gt;
* relationshipTag: name of relationship schema&lt;br /&gt;
&lt;br /&gt;
== relTypeConcat ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;serviceTag&amp;gt;_&amp;lt;relationshipTag&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* relTypeConcat: &amp;quot;serviceTag&amp;quot; + &amp;quot;_&amp;quot; + &amp;quot;relationshipTag&amp;quot;&lt;br /&gt;
* now use as the name of relationshipType in graph database&lt;br /&gt;
&lt;br /&gt;
== relTypeId ==&lt;br /&gt;
* hash of relType object&lt;br /&gt;
&lt;br /&gt;
== relTypeAndDirection ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	relType: {&lt;br /&gt;
		serviceTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
		relationshipTag: &amp;quot;yyy&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	relationshipDirection: &amp;quot;to&amp;quot;, // &amp;quot;from&amp;quot; || &amp;quot;to&amp;quot;&lt;br /&gt;
    relationshipProperties: {}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== objectLinks ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    base:{&lt;br /&gt;
      objType:{&lt;br /&gt;
        serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
        objectType: &amp;quot;yy&amp;quot;,&lt;br /&gt;
      },&lt;br /&gt;
      requiredOnCreate:true,&lt;br /&gt;
      linkType:&amp;quot;one&amp;quot;,&lt;br /&gt;
      direction:&amp;quot;to&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    other:{&lt;br /&gt;
      objType:{&lt;br /&gt;
        serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
        objectType: &amp;quot;yy&amp;quot;,&lt;br /&gt;
      },&lt;br /&gt;
      requiredOnCreate:false,&lt;br /&gt;
      linkType:&amp;quot;one&amp;quot;,&lt;br /&gt;
      direction:&amp;quot;from&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    relType:{&lt;br /&gt;
      serviceTag:&amp;quot;xx&amp;quot;&lt;br /&gt;
      relationshipTag:&amp;quot;xx&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  // ... another objectLinks&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* This format will receive it when use function getObjectLinks and base objType use it own objType.&lt;br /&gt;
* It show all link that connect with that objType.&lt;br /&gt;
&lt;br /&gt;
== objectLink ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  base:{&lt;br /&gt;
    objType:{&lt;br /&gt;
      serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
      objectType: &amp;quot;yy&amp;quot;,&lt;br /&gt;
    },&lt;br /&gt;
    requiredOnCreate:true,&lt;br /&gt;
    linkType:&amp;quot;one&amp;quot;,&lt;br /&gt;
    direction:&amp;quot;to&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  other:{&lt;br /&gt;
    objType:{&lt;br /&gt;
      serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
      objectType: &amp;quot;yy&amp;quot;,&lt;br /&gt;
    },&lt;br /&gt;
    requiredOnCreate:false,&lt;br /&gt;
    linkType:&amp;quot;one&amp;quot;,&lt;br /&gt;
    direction:&amp;quot;from&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  relType:{&lt;br /&gt;
    serviceTag:&amp;quot;xx&amp;quot;&lt;br /&gt;
    relationshipTag:&amp;quot;xx&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Object structure of one objectLink&lt;br /&gt;
&lt;br /&gt;
== linkConfig ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  from: {&lt;br /&gt;
    serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
    objectType: &amp;quot;yy&amp;quot;,&lt;br /&gt;
  },&lt;br /&gt;
  to: {&lt;br /&gt;
    serviceTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
    objectType: &amp;quot;yyy&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  relType: {&lt;br /&gt;
    serviceTag: &amp;quot;xxxx&amp;quot;,&lt;br /&gt;
    relationshipTag: &amp;quot;yyyy&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  relationshipDirection: &amp;quot;to&amp;quot;, // &amp;quot;from&amp;quot; || &amp;quot;to&amp;quot;&lt;br /&gt;
  requestProperties: {&lt;br /&gt;
    // to calculate orderPrices we need one identifier for each of the below objTypes&lt;br /&gt;
    tag_deliverTo: {&lt;br /&gt;
      requestPropertyType: &amp;quot;objectIdentifier&amp;quot;,&lt;br /&gt;
      objType: {&lt;br /&gt;
        serviceTag: &amp;quot;Locations&amp;quot;,&lt;br /&gt;
        objectType: &amp;quot;locationNode&amp;quot; // deliversToLocationNode&lt;br /&gt;
      },&lt;br /&gt;
      identifiersFieldName: &amp;quot;locationNodeId&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    // ... other request properties&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
config of each link between 2 objType&lt;br /&gt;
&lt;br /&gt;
== linkType ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  firstObjType: {&lt;br /&gt;
    serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
    objectType: &amp;quot;yy&amp;quot;,&lt;br /&gt;
  },&lt;br /&gt;
  secondObjType: {&lt;br /&gt;
    serviceTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
    objectType: &amp;quot;yyy&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
&lt;br /&gt;
  relType: {&lt;br /&gt;
    serviceTag: &amp;quot;xxxx&amp;quot;,&lt;br /&gt;
    relationshipTag: &amp;quot;yyyy&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  relationshipDirection: &amp;quot;to&amp;quot; // &amp;quot;from&amp;quot; || &amp;quot;to&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
use to identify relationship between 2 objectSchema&lt;br /&gt;
&lt;br /&gt;
== linkTypeId ==&lt;br /&gt;
create hash id from linkType&lt;br /&gt;
&lt;br /&gt;
== pathLinkType ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  objType: {&lt;br /&gt;
    serviceTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
    objectType: &amp;quot;yyy&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  relType: {&lt;br /&gt;
    serviceTag: &amp;quot;xxxx&amp;quot;,&lt;br /&gt;
    relationshipTag: &amp;quot;yyyy&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  relationshipDirection: &amp;quot;to&amp;quot; // &amp;quot;from&amp;quot; || &amp;quot;to&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* pathLinkType is used at each step of traversal/path&lt;br /&gt;
* when joined with the previous objType/baseObjType can be used to create linkType (and request linkConfig)&lt;br /&gt;
&lt;br /&gt;
== pathLinkTypeId ==&lt;br /&gt;
* create hash id from pathLinkType&lt;br /&gt;
&lt;br /&gt;
== flowType ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	serviceTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
	flowTag: &amp;quot;yyy&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
use to identify which serviceTag that flow schema is located&lt;br /&gt;
&lt;br /&gt;
== systemTextType ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	namespace: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
	systemTextTag: &amp;quot;yyy&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
identify a system text&lt;br /&gt;
&lt;br /&gt;
== notificationType ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	serviceTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
	notificationTag: &amp;quot;yyy&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
identify a system notification&lt;br /&gt;
&lt;br /&gt;
== notificationTypeId ==&lt;br /&gt;
&lt;br /&gt;
* hash of notificationType object&lt;br /&gt;
&lt;br /&gt;
== identifiers ==&lt;br /&gt;
An object that has fieldName’s identifiers inside&lt;br /&gt;
=== example identifiers ===&lt;br /&gt;
* example identifiers inside objectSchema&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
identifiers:[&lt;br /&gt;
  {    &lt;br /&gt;
    type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
    fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;],&lt;br /&gt;
    name: &amp;quot;zz&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* example identifiers object&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{    &lt;br /&gt;
  xx:&amp;quot;xx value&amp;quot;,&lt;br /&gt;
  yy:&amp;quot;yy value&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The example above identifiers is the value of fieldNames that part of identifiers &lt;br /&gt;
&lt;br /&gt;
== identifiersBase ==&lt;br /&gt;
concatenated identifiers object &lt;br /&gt;
=== example identifiersBase ===&lt;br /&gt;
* example identifiers inside objectSchema&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
identifiers:[&lt;br /&gt;
  {    &lt;br /&gt;
    type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
    fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;],&lt;br /&gt;
    name: &amp;quot;zz&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* example identifiersBase object&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{    &lt;br /&gt;
  zz:&amp;quot;xxValue_yyValue&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The example above identifiersBase is the value of each identifier of objectSchema &lt;br /&gt;
&lt;br /&gt;
== identifiersId ==&lt;br /&gt;
hash of identifiers object &lt;br /&gt;
&lt;br /&gt;
== identifiersConcat ==&lt;br /&gt;
string that concatenate all identifiers&lt;br /&gt;
* Note!: Will ordered concatenate value by objectSchema.identifiers array &lt;br /&gt;
&lt;br /&gt;
== objInstanceBase ==&lt;br /&gt;
result from dynamoDB that contains relevant and not relevant data of objectSchema &lt;br /&gt;
* identifiers from in objInstanceBase will concatenated or not concatenated depending on objectSchema&lt;br /&gt;
* izContext field not relevant with objectSchema but it contains inside objInstanceBase&lt;br /&gt;
&lt;br /&gt;
== objInstance ==&lt;br /&gt;
similar objInstanceBase but split concatenateIdentifier to each fieldName&lt;br /&gt;
&lt;br /&gt;
== objInstanceFull ==&lt;br /&gt;
object that separated fields and identifiers and identifiers cannot concatenated&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{    &lt;br /&gt;
  identifiers:{&lt;br /&gt;
    //... identifiers fieldName of objectSchema&lt;br /&gt;
  }, &lt;br /&gt;
  fields:{&lt;br /&gt;
    //.. data of objectSchema&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* identifiers: contains identifiers data&lt;br /&gt;
* fields: another data except  &lt;br /&gt;
&lt;br /&gt;
== errorType ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	serviceTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
	errorTag: &amp;quot;yyy&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== example data  ==&lt;br /&gt;
=== example objectSchema ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
// example objectSchema&lt;br /&gt;
{    &lt;br /&gt;
  fieldNames:{&lt;br /&gt;
    id:{&lt;br /&gt;
      type:”string”,&lt;br /&gt;
      // … another fieldName settings&lt;br /&gt;
    },&lt;br /&gt;
    createTime: {},     //  filedName settings&lt;br /&gt;
    location: {},       //  filedName settings&lt;br /&gt;
    value: {},          //  filedName settings&lt;br /&gt;
  },&lt;br /&gt;
  identifiers:[&lt;br /&gt;
    {&lt;br /&gt;
      type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
      fieldNames: [&amp;quot;id&amp;quot;,&amp;quot;createTime&amp;quot;],   // composite partition keys in DynamoDB&lt;br /&gt;
      deliminator: &amp;quot;_&amp;quot;,                  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
      name: &amp;quot;createId&amp;quot;                   // name of field in database&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
      fieldName: “location”&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== objInstanceBase ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
// example objInstanceBase data&lt;br /&gt;
{&lt;br /&gt;
  createId:&amp;quot;id_createTime&amp;quot;,&lt;br /&gt;
  location:&amp;quot;cnx&amp;quot;,&lt;br /&gt;
  value:199,&lt;br /&gt;
  errorsFound:[],&lt;br /&gt;
  izContext:{&lt;br /&gt;
  // ...izContext&lt;br /&gt;
  },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Normally objInstanceBase is the result from dynamoDB and it will include data that is not relevant to objectSchema. In example above errorsFound and izContext not contain in objectSchema.&lt;br /&gt;
&lt;br /&gt;
=== objInstance ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
// example objInstance data&lt;br /&gt;
{&lt;br /&gt;
  id:&amp;quot;id&amp;quot;,&lt;br /&gt;
  createTime:&amp;quot;createTime&amp;quot;&lt;br /&gt;
  location:&amp;quot;cnx&amp;quot;,&lt;br /&gt;
  value:199,&lt;br /&gt;
  errorsFound:[],&lt;br /&gt;
  izContext:{&lt;br /&gt;
  // ...izContext&lt;br /&gt;
  },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
objInstance is object that already refactored identifiers but another fields same as objInstanceBase &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== objInstanceFull ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
// example objInstanceFull data&lt;br /&gt;
{    &lt;br /&gt;
  identifiers:{&lt;br /&gt;
    id:&amp;quot;id&amp;quot;,&lt;br /&gt;
    createTime:&amp;quot;createTime&amp;quot;&lt;br /&gt;
    location:&amp;quot;cnx&amp;quot;,&lt;br /&gt;
  }, &lt;br /&gt;
  fields:{&lt;br /&gt;
    value:199,&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== identifiersBase ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
// example identifiersBase data&lt;br /&gt;
{&lt;br /&gt;
  createId:&amp;quot;id_createTime&amp;quot;,&lt;br /&gt;
  location:&amp;quot;cnx&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== identifiers ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
// example identifiers data&lt;br /&gt;
{&lt;br /&gt;
  id: &amp;quot;id&amp;quot;,&lt;br /&gt;
  createTime: &amp;quot;createTime&amp;quot;,&lt;br /&gt;
  location: &amp;quot;cnx&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - Standard Data Structures| Standard Data Structures]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=User_Data_Handling&amp;diff=4622</id>
		<title>User Data Handling</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=User_Data_Handling&amp;diff=4622"/>
		<updated>2026-08-25T13:49:32Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
submittedByUserId and targetIdentifiers for permissions/account limits/resource use, and for creating automatic data such as createdBy and belongTo relationships in graph database.&lt;br /&gt;
&lt;br /&gt;
= Structure =&lt;br /&gt;
&lt;br /&gt;
* baseUserId can stay in iz_Context because it should not change during processing&lt;br /&gt;
* targetUserId maybe no longer needed, moves to targetIdentifiers for flows where objType is user or belongsTo user&lt;br /&gt;
* maybe change baseUserId to submittedByUserId to be more clear, but see baseUserId reason for name below&lt;br /&gt;
* however consider if future flows will handle many submittedByUserIds, eg automated tasks that handle many submitted tasks, if that is common it might be better to allow generated code to pass the submittedByUserId as a flow input param&lt;br /&gt;
* targetId change to identifer object {fieldname: fieldValue} named targetIdentifiers&lt;br /&gt;
* generated code can where possible add this automatically when initializing flows, and can check received valid identifiers according to flowSchema&lt;br /&gt;
&lt;br /&gt;
= Graph =&lt;br /&gt;
&lt;br /&gt;
* automatically adds createdBy/versionData updatedBy relationships for objects created/updated by user&lt;br /&gt;
* automatically adds createdBy/updatedBy for relationships created/updated by user, relationshipSchema specifies which node to connect this history to&lt;br /&gt;
* automatically adds belongTo relationship when creating a node connecting to targetIdentifiers instance of belongTo objType&lt;br /&gt;
* relationshipSchema sets which side is belongTo node, that node must have belongTo relationship (ie that node must have belongTo or rbac addOnDataStructure)&lt;br /&gt;
&lt;br /&gt;
= RBAC =&lt;br /&gt;
&lt;br /&gt;
* RBAC actions are fixed to flowTypes&lt;br /&gt;
* RBAC is only checked on initiated by user|systemWithUserId flows&lt;br /&gt;
* target/targetIdentifiers are required according to flowTypes base objType (using either that objTypes rbac addOnDataStructure or if that objType has belongTo following that)&lt;br /&gt;
* flows that are initiated by user|systemWithUserId but do not have belongTo/rbac check thier permissions from projectLevel RBAC&lt;br /&gt;
* flows that are initiated by user|systemWithUserId and have belongTo/rbac check thier permissions from objectLevel RBAC according to target&lt;br /&gt;
* generated code automatically validates submittedByUserId and targetIdentifiers, passing permissionHandler/RBAC and AccountLimits&lt;br /&gt;
&lt;br /&gt;
== Project level RBAC service ==&lt;br /&gt;
&lt;br /&gt;
* previously called appLevel&lt;br /&gt;
* each user has projectLevel roles, eg basicUser, verifiedUser, AdminUser, restrictedUser&lt;br /&gt;
* when a new user is created automatically gets assigned a role/s, eg: basicUser&lt;br /&gt;
* roles set in projectLevel RBAC are also used by projectLevel AccountLimits&lt;br /&gt;
&lt;br /&gt;
== Object level RBAC ==&lt;br /&gt;
&lt;br /&gt;
* any objType that has addOnDataStructure rbac setting automatically creates rbac resources/endpoints in that objType&#039;s service&lt;br /&gt;
* when entering a flow generated code checks if the flow has objType that belongsTo/has rbac and sends to the target objType service rbac endpoint&lt;br /&gt;
* when a user creates an object instance of objType with objectLevel rbac, an admin role is automatically created with allow permission for all actions associated with that objType and all objTypes that belongTo it, and the creating user is given that role&lt;br /&gt;
* mayb need to create an S3 schema per rbac objType with all flows that point to it&lt;br /&gt;
&lt;br /&gt;
= Account Limits =&lt;br /&gt;
&lt;br /&gt;
* standardize checking of accountLimits so generated code can check per flow&lt;br /&gt;
* probably allow for additional developer added accountLimits to be checked anywhere in code&lt;br /&gt;
&lt;br /&gt;
== Project level Account Limits ==&lt;br /&gt;
&lt;br /&gt;
* uses roles from projectLevel rbac&lt;br /&gt;
* defines limits for that users actions, eg for their own account&lt;br /&gt;
* if target is user objType and targetIdentifiers matches submittedBy userid, only check accountLimits target limit (same as submittedBy user)&lt;br /&gt;
&lt;br /&gt;
== Object level Account Limits ==&lt;br /&gt;
&lt;br /&gt;
== Generating code ==&lt;br /&gt;
&lt;br /&gt;
* Can generate AccountLimit tags automatically for each flow&lt;br /&gt;
* if flow objType has belongTo or rbac addOnDataStructure always check AccountLimit, eg createOrder number of orders allowed to create&lt;br /&gt;
* some flows accept multiple objType, eg createObject, if only generated flows are like this then we could hardcode request to AccountLimit from objType param, but if developer made flows also are like this we could add a setting to the flow, eg: multipleObjTypes = true, if true then could standardize param name and generate request to AccountLimit&lt;br /&gt;
* if flow is event S3 can generate AccountLimit request for size of file&lt;br /&gt;
&lt;br /&gt;
== Add increase/decrease effect ==&lt;br /&gt;
&lt;br /&gt;
* currently account limits will find the highest limit of all roles attached to a customer&lt;br /&gt;
* if some roles are limiting, eg restrictedUser, want to be able to limit account limit&lt;br /&gt;
* could add increase/decrease action to each limit&lt;br /&gt;
* if action is increase find the highest limit&lt;br /&gt;
* if any limit has decrease action force limit to equal the lowest decrease limit, ignoring increase limits&lt;br /&gt;
* might need to do a check that the highest increase limit is lower than the lowest decrease limit, return the lowest of the two&lt;br /&gt;
&lt;br /&gt;
= Resource use =&lt;br /&gt;
&lt;br /&gt;
* is used for billing&lt;br /&gt;
* if apply resource use to target does not work for non-billable objects like deliveryMethod&lt;br /&gt;
* if apply to submitted user does not work for billable objects like business/organization/operation&lt;br /&gt;
* consider having a setting in object schema for addOnDataStructure rbac whether object is billable object&lt;br /&gt;
* any flow with objType have belongTo/rbac and billable set true, resource use attaches to target&lt;br /&gt;
* any flow objType not set billable and initiated by user|systemWithUserId, resource use attaches to submittedBy user&lt;br /&gt;
* any flow not have objType but initiated by user|systemWithUserId resource use is charged to submittedBy user&lt;br /&gt;
&lt;br /&gt;
= Creating objects =&lt;br /&gt;
&lt;br /&gt;
* creating objects that have belongTo must check RBAC and AccountLimits for target&lt;br /&gt;
* creating objects that have addOnDataStructure rbac must check projectLevel RBAC and AccountLimits for submittedBy userid&lt;br /&gt;
* creating objects that not have belongTo and not have addOnDataStructure rbac must check projectLevel RBAC and AccountLimits for submittedBy userid&lt;br /&gt;
&lt;br /&gt;
= Example Flow handling =&lt;br /&gt;
&lt;br /&gt;
== userId, belongTo rbac, billable ==&lt;br /&gt;
&lt;br /&gt;
* check projectLevel rbac for target&lt;br /&gt;
* check objectLevel rbac for target+user (unless target objType is user)&lt;br /&gt;
* check projectLevel account limit for target&lt;br /&gt;
* check objectLevel account limit for target+user (unless target objType is user)&lt;br /&gt;
* resource use to target&lt;br /&gt;
&lt;br /&gt;
== systemNoUserId, belongTo rbac, billable ==&lt;br /&gt;
&lt;br /&gt;
* no rbac&lt;br /&gt;
* no account limit&lt;br /&gt;
* resource use to target&lt;br /&gt;
&lt;br /&gt;
== userId, no belongTo ==&lt;br /&gt;
&lt;br /&gt;
* check projectLevel rbac for user&lt;br /&gt;
* check projectLevel account limit for user&lt;br /&gt;
* resource use to user&lt;br /&gt;
&lt;br /&gt;
== systemNoUserId, no belongTo ==&lt;br /&gt;
&lt;br /&gt;
* no rbac&lt;br /&gt;
* no account limit&lt;br /&gt;
* no resource use&lt;br /&gt;
&lt;br /&gt;
== userId, belongTo rbac, not billable ==&lt;br /&gt;
&lt;br /&gt;
* check projectLevel rbac for target&lt;br /&gt;
* check objectLevel rbac for target+user (unless target objType is user)&lt;br /&gt;
* check projectLevel account limit for target&lt;br /&gt;
* check objectLevel account limit for target+user (unless target objType is user)&lt;br /&gt;
* resource use to user&lt;br /&gt;
&lt;br /&gt;
== systemNoUserId, belongTo rbac, not billable ==&lt;br /&gt;
&lt;br /&gt;
* no rbac&lt;br /&gt;
* no account limit&lt;br /&gt;
* no resource use&lt;br /&gt;
&lt;br /&gt;
== userId, no belongTo ==&lt;br /&gt;
&lt;br /&gt;
* check projectLevel rbac for user&lt;br /&gt;
* check projectLevel account limit for user&lt;br /&gt;
* resource use to user&lt;br /&gt;
&lt;br /&gt;
== systemNoUserId, no belongTo ==&lt;br /&gt;
&lt;br /&gt;
* no rbac&lt;br /&gt;
* no account limit&lt;br /&gt;
* no resource use&lt;br /&gt;
&lt;br /&gt;
= Considerations =&lt;br /&gt;
&lt;br /&gt;
== userLevel rbac ==&lt;br /&gt;
&lt;br /&gt;
* connected to user objType&lt;br /&gt;
* no admin role with permissions is created automatically when create new user, unlike other objTypes with addOnDataStructure rbac&lt;br /&gt;
* if submittedUserId matches targetIdentifers not need to check objectLevel RBAC/objectLevel AccountLimits&lt;br /&gt;
&lt;br /&gt;
= Ideas =&lt;br /&gt;
&lt;br /&gt;
== Remove RBAC ==&lt;br /&gt;
&lt;br /&gt;
* We could mimic RBAC functionality in AccountLimits&lt;br /&gt;
* set action limit to 0 for no permission&lt;br /&gt;
* unable to do this yet because rbac includes flow param filters, allowing permissions to limit to eg specific object instances&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - User Data Handling| User Data Handling]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=User_Data_Handling&amp;diff=4619</id>
		<title>User Data Handling</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=User_Data_Handling&amp;diff=4619"/>
		<updated>2026-08-23T10:24:31Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
submittedByUserId and targetIdentifiers for permissions/account limits/resource use, and for creating automatic data such as createdBy and belongTo relationships in graph database.&lt;br /&gt;
&lt;br /&gt;
= Structure =&lt;br /&gt;
&lt;br /&gt;
* baseUserId can stay in iz_Context because it should not change during processing&lt;br /&gt;
* targetUserId maybe no longer needed, moves to targetIdentifiers for flows where objType is user or belongsTo user&lt;br /&gt;
* maybe change baseUserId to submittedByUserId to be more clear, but see baseUserId reason for name below&lt;br /&gt;
* however consider if future flows will handle many submittedByUserIds, eg automated tasks that handle many submitted tasks, if that is common it might be better to allow generated code to pass the submittedByUserId as a flow input param&lt;br /&gt;
* targetId change to identifer object {fieldname: fieldValue} named targetIdentifiers&lt;br /&gt;
* generated code can where possible add this automatically when initializing flows, and can check received valid identifiers according to flowSchema&lt;br /&gt;
&lt;br /&gt;
= Graph =&lt;br /&gt;
&lt;br /&gt;
* automatically adds createdBy/versionData updatedBy relationships for objects created/updated by user&lt;br /&gt;
* automatically adds createdBy/updatedBy for relationships created/updated by user, relationshipSchema specifies which node to connect this history to&lt;br /&gt;
* automatically adds belongTo relationship when creating a node connecting to targetIdentifiers instance of belongTo objType&lt;br /&gt;
* relationshipSchema sets which side is belongTo node, that node must have belongTo relationship (ie that node must have belongTo or rbac addOnDataStructure)&lt;br /&gt;
&lt;br /&gt;
= RBAC =&lt;br /&gt;
&lt;br /&gt;
* RBAC actions are fixed to flowTypes&lt;br /&gt;
* RBAC is only checked on initiated by user|systemWithUserId flows&lt;br /&gt;
* target/targetIdentifiers are required according to flowTypes base objType (using either that objTypes rbac addOnDataStructure or if that objType has belongTo following that)&lt;br /&gt;
* flows that are initiated by user|systemWithUserId but do not have belongTo/rbac check thier permissions from projectLevel RBAC&lt;br /&gt;
* flows that are initiated by user|systemWithUserId and have belongTo/rbac check thier permissions from objectLevel RBAC according to target&lt;br /&gt;
* generated code automatically validates submittedByUserId and targetIdentifiers, passing permissionHandler/RBAC and AccountLimits&lt;br /&gt;
&lt;br /&gt;
== Project level RBAC service ==&lt;br /&gt;
&lt;br /&gt;
* previously called appLevel&lt;br /&gt;
* each user has projectLevel roles, eg basicUser, verifiedUser, AdminUser, restrictedUser&lt;br /&gt;
* when a new user is created automatically gets assigned a role/s, eg: basicUser&lt;br /&gt;
* roles set in projectLevel RBAC are also used by projectLevel AccountLimits&lt;br /&gt;
&lt;br /&gt;
== Object level RBAC ==&lt;br /&gt;
&lt;br /&gt;
* any objType that has addOnDataStructure rbac setting automatically creates rbac resources/endpoints in that objType&#039;s service&lt;br /&gt;
* when entering a flow generated code checks if the flow has objType that belongsTo/has rbac and sends to the target objType service rbac endpoint&lt;br /&gt;
* when a user creates an object instance of objType with objectLevel rbac, an admin role is automatically created with allow permission for all actions associated with that objType and all objTypes that belongTo it, and the creating user is given that role&lt;br /&gt;
* mayb need to create an S3 schema per rbac objType with all flows that point to it&lt;br /&gt;
&lt;br /&gt;
= Account Limits =&lt;br /&gt;
&lt;br /&gt;
* standardize checking of accountLimits so generated code can check per flow&lt;br /&gt;
* probably allow for additional developer added accountLimits to be checked anywhere in code&lt;br /&gt;
&lt;br /&gt;
== Project level Account Limits ==&lt;br /&gt;
&lt;br /&gt;
* uses roles from projectLevel rbac&lt;br /&gt;
* defines limits for that users actions, eg for their own account&lt;br /&gt;
* if target is user objType and targetIdentifiers matches submittedBy userid, only check accountLimits target limit (same as submittedBy user)&lt;br /&gt;
&lt;br /&gt;
== Object level Account Limits ==&lt;br /&gt;
&lt;br /&gt;
== Add increase/decrease action =&lt;br /&gt;
&lt;br /&gt;
* currently account limits will find the highest limit of all roles attached to a customer&lt;br /&gt;
* if some roles are limiting, eg restrictedUser, want to be able to limit account limit&lt;br /&gt;
* could add increase/decrease action to each limit&lt;br /&gt;
* if action is increase find the highest limit&lt;br /&gt;
* if any limit has decrease action force limit to equal the lowest decrease limit, ignoring increase limits&lt;br /&gt;
* might need to do a check that the highest increase limit is lower than the lowest decrease limit, return the lowest of the two&lt;br /&gt;
&lt;br /&gt;
= Resource use =&lt;br /&gt;
&lt;br /&gt;
* is used for billing&lt;br /&gt;
* if apply resource use to target does not work for non-billable objects like deliveryMethod&lt;br /&gt;
* if apply to submitted user does not work for billable objects like business/organization/operation&lt;br /&gt;
* consider having a setting in object schema for addOnDataStructure rbac whether object is billable object&lt;br /&gt;
* any flow with objType have belongTo/rbac and billable set true, resource use attaches to target&lt;br /&gt;
* any flow objType not set billable and initiated by user|systemWithUserId, resource use attaches to submittedBy user&lt;br /&gt;
* any flow not have objType but initiated by user|systemWithUserId resource use is charged to submittedBy user&lt;br /&gt;
&lt;br /&gt;
= Creating objects =&lt;br /&gt;
&lt;br /&gt;
* creating objects that have belongTo must check RBAC and AccountLimits for target&lt;br /&gt;
* creating objects that have addOnDataStructure rbac must check projectLevel RBAC and AccountLimits for submittedBy userid&lt;br /&gt;
* creating objects that not have belongTo and not have addOnDataStructure rbac must check projectLevel RBAC and AccountLimits for submittedBy userid&lt;br /&gt;
&lt;br /&gt;
= Example Flow handling =&lt;br /&gt;
&lt;br /&gt;
== userId, belongTo rbac, billable ==&lt;br /&gt;
&lt;br /&gt;
* check projectLevel rbac for target&lt;br /&gt;
* check objectLevel rbac for target+user (unless target objType is user)&lt;br /&gt;
* check projectLevel account limit for target&lt;br /&gt;
* check objectLevel account limit for target+user (unless target objType is user)&lt;br /&gt;
* resource use to target&lt;br /&gt;
&lt;br /&gt;
== systemNoUserId, belongTo rbac, billable ==&lt;br /&gt;
&lt;br /&gt;
* no rbac&lt;br /&gt;
* no account limit&lt;br /&gt;
* resource use to target&lt;br /&gt;
&lt;br /&gt;
== userId, no belongTo ==&lt;br /&gt;
&lt;br /&gt;
* check projectLevel rbac for user&lt;br /&gt;
* check projectLevel account limit for user&lt;br /&gt;
* resource use to user&lt;br /&gt;
&lt;br /&gt;
== systemNoUserId, no belongTo ==&lt;br /&gt;
&lt;br /&gt;
* no rbac&lt;br /&gt;
* no account limit&lt;br /&gt;
* no resource use&lt;br /&gt;
&lt;br /&gt;
== userId, belongTo rbac, not billable ==&lt;br /&gt;
&lt;br /&gt;
* check projectLevel rbac for target&lt;br /&gt;
* check objectLevel rbac for target+user (unless target objType is user)&lt;br /&gt;
* check projectLevel account limit for target&lt;br /&gt;
* check objectLevel account limit for target+user (unless target objType is user)&lt;br /&gt;
* resource use to user&lt;br /&gt;
&lt;br /&gt;
== systemNoUserId, belongTo rbac, not billable ==&lt;br /&gt;
&lt;br /&gt;
* no rbac&lt;br /&gt;
* no account limit&lt;br /&gt;
* no resource use&lt;br /&gt;
&lt;br /&gt;
== userId, no belongTo ==&lt;br /&gt;
&lt;br /&gt;
* check projectLevel rbac for user&lt;br /&gt;
* check projectLevel account limit for user&lt;br /&gt;
* resource use to user&lt;br /&gt;
&lt;br /&gt;
== systemNoUserId, no belongTo ==&lt;br /&gt;
&lt;br /&gt;
* no rbac&lt;br /&gt;
* no account limit&lt;br /&gt;
* no resource use&lt;br /&gt;
&lt;br /&gt;
= Considerations =&lt;br /&gt;
&lt;br /&gt;
== userLevel rbac ==&lt;br /&gt;
&lt;br /&gt;
* connected to user objType&lt;br /&gt;
* no admin role with permissions is created automatically when create new user, unlike other objTypes with addOnDataStructure rbac&lt;br /&gt;
* if submittedUserId matches targetIdentifers not need to check objectLevel RBAC/objectLevel AccountLimits&lt;br /&gt;
&lt;br /&gt;
= Ideas =&lt;br /&gt;
&lt;br /&gt;
== Remove RBAC ==&lt;br /&gt;
&lt;br /&gt;
* We could mimic RBAC functionality in AccountLimits&lt;br /&gt;
* set action limit to 0 for no permission&lt;br /&gt;
* unable to do this yet because rbac includes flow param filters, allowing permissions to limit to eg specific object instances&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - User Data Handling| User Data Handling]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Per_Service_Schemas&amp;diff=4618</id>
		<title>Per Service Schemas</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Per_Service_Schemas&amp;diff=4618"/>
		<updated>2026-08-23T09:54:16Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Each service manages a schema of object/resources that it is responsible for, this schema is available to other services and frontends. The schema includes a list of fields available for each object.&lt;br /&gt;
&lt;br /&gt;
= File Structure =&lt;br /&gt;
&lt;br /&gt;
* see [[Repository structure#schemas|Repository structure]]&lt;br /&gt;
&lt;br /&gt;
= ObjectSchema | ObjectFieldSchema.js =&lt;br /&gt;
&lt;br /&gt;
== Not extendObjType ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;xx&amp;quot;,&lt;br /&gt;
	shortNameObjectType:&amp;quot;x&amp;quot;, // optional, use when generate code create lambda role with long name&lt;br /&gt;
	canDelete: false, // whether any fields can be deleted // default = false&lt;br /&gt;
	belongTo: { &lt;br /&gt;
		serviceTag:&amp;quot;iii&amp;quot;,&lt;br /&gt;
		objectType:&amp;quot;jjj&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
    // how is the object created&lt;br /&gt;
    // userGenerated there will be generated endpoints for api or sqs (used in importBatchMain) to create object&lt;br /&gt;
    // systemGenerated must be created by flow/s&lt;br /&gt;
    // searchResultGenerated see separate notes below&lt;br /&gt;
    generatedBy: &amp;quot;xx&amp;quot;, // &amp;quot;user&amp;quot;|&amp;quot;systemNoUserId&amp;quot;|&amp;quot;systemWithUserId&amp;quot;|&amp;quot;searchResultGenerated&amp;quot; // required&lt;br /&gt;
    searchResultGeneratedFlowType: {}, // for generatedBy = searchResultGenerated&lt;br /&gt;
	addOnDataStructure: [ // optional, add for additional setting to objectType&lt;br /&gt;
		{&lt;br /&gt;
			// all fields that a user can edit must be in versionedData, and all fields in versionedData must be editable by user&lt;br /&gt;
			type:&amp;quot;versionedData&amp;quot;,&lt;br /&gt;
			versionedDataLabel: &amp;quot;xx&amp;quot;, // versionedData label name&lt;br /&gt;
			storageResourceTag : &amp;quot;xx&amp;quot;, // ref to storegeResourceTag&lt;br /&gt;
			fieldNames: { // fieldName in versionedData cannot have in in main objectSchema.fieldNames&lt;br /&gt;
				&amp;quot;aaa&amp;quot;:{ // fieldName&lt;br /&gt;
					type: &amp;quot;xx&amp;quot;, // string|integer|number|timestamp|currency|currencyValue|float|special|object|boolean|arrayMixed|arrayNumeric|arrayString&lt;br /&gt;
					requiredOnCreate: false, // default = false&lt;br /&gt;
					optionalOnCreate: false, // default = false,&lt;br /&gt;
					validation: {&lt;br /&gt;
                      itemValidation:{} // for validate item in array&lt;br /&gt;
                    },&lt;br /&gt;
                    // probably impossible to have fromObjType, because data can be changed by user here&lt;br /&gt;
					fromObjType:{&lt;br /&gt;
						serviceTag: &amp;quot;xxx&amp;quot;, &lt;br /&gt;
						objectType: &amp;quot;xxx&amp;quot; &lt;br /&gt;
					},&lt;br /&gt;
				},&lt;br /&gt;
				// ...&lt;br /&gt;
			}&lt;br /&gt;
        },&lt;br /&gt;
        { // can have multiple addOn of type attributeTree&lt;br /&gt;
          type:&amp;quot;attributeTree&amp;quot;,           &lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;translation&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;propertyValue&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;mediaLink&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;rbac&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
		// ...&lt;br /&gt;
	],&lt;br /&gt;
	plugInTags: [&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;], // plugIns that can be connected to this objType&lt;br /&gt;
	storageResources:{&lt;br /&gt;
		&amp;quot;xxx&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // graph			&lt;br /&gt;
			graphServerTag: &amp;quot;xx&amp;quot;, // setting for storageType graph&lt;br /&gt;
            additionalGraphIndexes:[[&#039;fieldName1&#039;, &#039;fieldName2&#039;, ...], [...]]  // will make graph index with specific fieldName &lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;zzz&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // dynamoDB&lt;br /&gt;
			// setting for storageType dynamoDB&lt;br /&gt;
			tableName: &amp;quot;xx&amp;quot;,&lt;br /&gt;
			groupByPartitionKeyField: &amp;quot;xx&amp;quot;, // use groupByPartitionKeyField as partition key and not have sort key in dynamoDB, if have multiple identifiers will concat it. And use it as partitionKey.&lt;br /&gt;
            serviceTag:&amp;quot;zz&amp;quot;// default own service.&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	fieldNames: {&lt;br /&gt;
		xxx: { // fieldName&lt;br /&gt;
			type: &amp;quot;xx&amp;quot;,  // string|integer|number|timestamp|currency|currencyValue|float|special|object|boolean|arrayMixed|arrayNumeric|arrayString&lt;br /&gt;
            randomOnCreate: false,   // default = false , can set true in fieldName that part of identifiers and identifiers have single identifierFieldname&lt;br /&gt;
			requiredOnCreate: false, // default = false&lt;br /&gt;
			optionalOnCreate: false, // default = false&lt;br /&gt;
			canUpdate: true, // default = true (only system/flows can edit, no history of changes unless flow manually adds)&lt;br /&gt;
			validation: {&lt;br /&gt;
			  itemValidation:{}  // for validate item in array&lt;br /&gt;
            }, // maybe ajv syntax&lt;br /&gt;
			storageResourceTags: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // reference to storageResources property&lt;br /&gt;
		    fromObjType:{&lt;br /&gt;
			  serviceTag: &amp;quot;xxx&amp;quot;, &lt;br /&gt;
			  objectType: &amp;quot;xxx&amp;quot; &lt;br /&gt;
			},&lt;br /&gt;
            hashOnCreate: [&amp;quot;xx&amp;quot;, &amp;quot;yy&amp;quot;], // reference to other fieldName, &lt;br /&gt;
            statusField: true, // use for objectSchema inside flowSchema, identify which field is statusField &lt;br /&gt;
&lt;br /&gt;
			// comes from requiredOnCreate relationships&lt;br /&gt;
			fromRequiredOnCreate: { &lt;br /&gt;
				relType: {&lt;br /&gt;
					serviceTag:&amp;quot;aa&amp;quot;,&lt;br /&gt;
					relationshipTag:&amp;quot;bb&amp;quot;&lt;br /&gt;
				},&lt;br /&gt;
				// or&lt;br /&gt;
				belongToObjType: true, // if set to true use the belongTo relationship to belongTo objType&lt;br /&gt;
&lt;br /&gt;
				fieldName:&amp;quot;&amp;quot; // optional default= same field name eg: now default == xxx if not defined(use fieldname of object inside link when create)&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
		// ...&lt;br /&gt;
	},&lt;br /&gt;
    compositeKeyDeliminator: &amp;quot;xx&amp;quot;, // join partitionKey and sortKey&lt;br /&gt;
	identifiers: [&lt;br /&gt;
    // for dynamoDB storageType &lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // composite partition keys in DynamoDB&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		name: &amp;quot;zz&amp;quot;, // name of field in database&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	},&lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // composite partition keys in DynamoDB&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		name: &amp;quot;zz&amp;quot;, // name of field in database&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	},&lt;br /&gt;
   &lt;br /&gt;
    // for graph storageType&lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;identifier&amp;quot;,&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // identifier field in graph or composite partition keys in DynamoDB&lt;br /&gt;
        name: &amp;quot;zzz&amp;quot;              // use when save in dynamoDB partitionKey&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;	&lt;br /&gt;
	},&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== extendObjType ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	// for objects stored in graph this will add another node label&lt;br /&gt;
	objectType: &amp;quot;xx&amp;quot;, // new label to add&lt;br /&gt;
	extendObjType: { // core object that this object extends&lt;br /&gt;
		serviceTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;xxx&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources:{ // these are the storageResources that carry the extended objects settings, &lt;br /&gt;
		// (see above)&lt;br /&gt;
	},&lt;br /&gt;
	fieldNames: {&lt;br /&gt;
		// (see above) &lt;br /&gt;
	},&lt;br /&gt;
	// canDelete/identifiers come from the core object&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== searchResultGenerated ==&lt;br /&gt;
&lt;br /&gt;
* must be created by flow&lt;br /&gt;
* eg: variantProduct&lt;br /&gt;
* not have any storageResources&lt;br /&gt;
* identifiers are automatically searchResultData identifiers&lt;br /&gt;
* a searchResult request for this object will enter the searchResultGeneratedFlowType flow which creates searchResultData that can then be queried/sorted&lt;br /&gt;
* all relationships must be storageType = lambda, eg translate from variantProduct to variant uses a translateId flow to query the variantProduct identifier (searchResultData) to find the variantId in it&#039;s requiredData results&lt;br /&gt;
* searchResultGeneratedFlowType takes over after creating searchResultMain record until processRequiredData&lt;br /&gt;
* if objectSchema defines any fieldnames, then they are found using a flow, maybe as hooks in per service findData&lt;br /&gt;
* when finding direct fieldname, will need to check if requireData already exists, if not enter flow/findData to create&lt;br /&gt;
* no fields can be edited, so can show in forms but no updates performed&lt;br /&gt;
&lt;br /&gt;
= Relationships Schema | ObjectRelationships.js =&lt;br /&gt;
&lt;br /&gt;
* stored in top level schemas folder&lt;br /&gt;
* parent/child determines relationship direction for graph relationships&lt;br /&gt;
* have one service that contains information of each relationship &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// relationship schema in responsible service&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;xxx&amp;quot;: { // relationshipTag - name of relationship type stored in graph&lt;br /&gt;
      generatedBy: &amp;quot;xx&amp;quot;, // &amp;quot;user&amp;quot;|&amp;quot;systemNoUserId&amp;quot;|&amp;quot;systemWithUserId&amp;quot;&lt;br /&gt;
      canChangeToRelTypes: [&lt;br /&gt;
		{&lt;br /&gt;
			relType: { // relType that this relType can change to &lt;br /&gt;
			  serviceTag:&amp;quot;xxx&amp;quot;,&lt;br /&gt;
			  relationshipTag: &amp;quot;yyy&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			changeBy: &amp;quot;xx&amp;quot;, // &amp;quot;user&amp;quot;|&amp;quot;systemNoUserId&amp;quot;|&amp;quot;systemWithUserId&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
        // another relType&lt;br /&gt;
      ],&lt;br /&gt;
      storageResources:{&lt;br /&gt;
		&amp;quot;xxx&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // dynamoDB | graph | lambda&lt;br /&gt;
		    // if storageType=&amp;quot;dynamoDB&amp;quot;  will not specify tableName in relationship schema&lt;br /&gt;
&lt;br /&gt;
			// setting for storageType graph&lt;br /&gt;
			graphServerTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
            additionalGraphIndexes:[[&#039;fieldName1&#039;, &#039;fieldName2&#039;, ...], [...]],  // will make graph index with specific fieldName &lt;br /&gt;
&lt;br /&gt;
			// setting for storageType lambda&lt;br /&gt;
			serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
			functionName: &amp;quot;xx&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
      },&lt;br /&gt;
      fieldNames: {&lt;br /&gt;
		&amp;quot;xxx&amp;quot;: { // relationship property name&lt;br /&gt;
			type: &amp;quot;string&amp;quot;, // &amp;quot;string&amp;quot; | &amp;quot;number&amp;quot; ...&lt;br /&gt;
			requiredOnCreate: false, // default=false&lt;br /&gt;
			optionalOnCreate: false, // default = false&lt;br /&gt;
			updateBy: &amp;quot;xx&amp;quot;, // &amp;quot;user&amp;quot;|&amp;quot;systemNoUserId&amp;quot;|&amp;quot;systemWithUserId&amp;quot;|&amp;quot;none&amp;quot;&lt;br /&gt;
			validation: {} // ajv syntax&lt;br /&gt;
		},&lt;br /&gt;
		//...other relationship properties&lt;br /&gt;
      },&lt;br /&gt;
      links: [&lt;br /&gt;
        {&lt;br /&gt;
          storageResourceTags: [&amp;quot;xxx&amp;quot;],   // reference from storageResources property&lt;br /&gt;
          canDelete: false                // default = false, if set true will allow delete relationship between 2 objType&lt;br /&gt;
          from: {&lt;br /&gt;
            objType: {&lt;br /&gt;
              serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
              objectType: &amp;quot;xx&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            requiredOnCreate: true, // if set true will create relationshipTag when create objType data, if both &amp;quot;from&amp;quot; and &amp;quot;to&amp;quot; linkType=&amp;quot;many&amp;quot; should not have requiredOnCreate, exists in &amp;quot;from&amp;quot; or &amp;quot;to&amp;quot; only&lt;br /&gt;
            linkType: &amp;quot;&amp;quot;,   // one | many&lt;br /&gt;
          //   moveBy: &amp;quot;xx&amp;quot;, // &amp;quot;user&amp;quot;|&amp;quot;systemNoUserId&amp;quot;|&amp;quot;systemWithUserId&amp;quot;|&amp;quot;none&amp;quot;&lt;br /&gt;
          // belongTo:true&lt;br /&gt;
          },&lt;br /&gt;
          to: {&lt;br /&gt;
            objType: {&lt;br /&gt;
              serviceTag: &amp;quot;yy&amp;quot;,&lt;br /&gt;
              objectType: &amp;quot;yy&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            linkType: &amp;quot;&amp;quot;,   // one | many&lt;br /&gt;
             // moveBy allows the relationship to be moved between 2 instances of the same objType only&lt;br /&gt;
	        moveBy: &amp;quot;xx&amp;quot;, // &amp;quot;user&amp;quot;|&amp;quot;systemNoUserId&amp;quot;|&amp;quot;systemWithUserId&amp;quot;|&amp;quot;none&amp;quot;&lt;br /&gt;
            belongTo:true, // false&lt;br /&gt;
          },&lt;br /&gt;
          requestProperties: {&lt;br /&gt;
            // if storageType is Lambda and translateIds/linkPath requires properties set them here (eg sellOffer&amp;gt;orderPrice)&lt;br /&gt;
            tag_deliverTo: {&lt;br /&gt;
              requestPropertyType: &amp;quot;objectIdentifier&amp;quot;,&lt;br /&gt;
              objType: {&lt;br /&gt;
                serviceTag: &amp;quot;Locations&amp;quot;,&lt;br /&gt;
                objectType: &amp;quot;locationNode&amp;quot; // deliversToLocationNode&lt;br /&gt;
              },&lt;br /&gt;
              identifiersFieldName: &amp;quot;locationNodeId&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            // ... other request properties&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        // ...other link&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Reference Relationships Schema | RefObjectRelationships.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// reference to relationshipTag in external service&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    objectType: &amp;quot;zz&amp;quot;,              // objectType in local service&lt;br /&gt;
    relationshipTag: &amp;quot;xxx&amp;quot;,        // name of relationshiptag of objType&lt;br /&gt;
    relationshipServiceTag: &amp;quot;xx&amp;quot;   // point to service tag that contain data of relationshipTag of objType&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Flow Schema | FlowSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  [&lt;br /&gt;
    {&lt;br /&gt;
      flowTag: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
      initiateBy: &amp;quot;xx&amp;quot;, // &amp;quot;user&amp;quot;|&amp;quot;systemNoUserId&amp;quot;|&amp;quot;systemWithUserId&amp;quot;&lt;br /&gt;
      handleObj: &amp;quot;one&amp;quot;,           // &amp;quot;one&amp;quot; | &amp;quot;multi&amp;quot;&lt;br /&gt;
      statusType: &amp;quot;statusField&amp;quot;,  // &amp;quot;statusField&amp;quot; | &amp;quot;storedCache&amp;quot; | &amp;quot;none&amp;quot; | &amp;quot;triggerCache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      // statusType=&amp;quot;triggerCache&amp;quot; setting &lt;br /&gt;
      triggerType: &amp;quot;storedCache&amp;quot;, // &amp;quot;storedCache&amp;quot; | &amp;quot;switch&amp;quot;&lt;br /&gt;
      triggerFlowTypes: [&lt;br /&gt;
        //... triggerFlowType&lt;br /&gt;
      ],&lt;br /&gt;
&lt;br /&gt;
      // statusType=&amp;quot;statusField&amp;quot; | &amp;quot;triggerCache&amp;quot; | &amp;quot;storedCache&amp;quot; setting:&lt;br /&gt;
      objType: {},&lt;br /&gt;
&lt;br /&gt;
      event: [&amp;quot;ownTopic&amp;quot;],  // &amp;quot;ownTopic&amp;quot; | &amp;quot;extTopic&amp;quot; | &amp;quot;s3&amp;quot; | &amp;quot;eventBridge&amp;quot; | &amp;quot;lambdaSyncInv&amp;quot; | &amp;quot;lambdaSyncApi&amp;quot; | &amp;quot;generatedCode&amp;quot; | &amp;quot;dsq&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      // event=&amp;quot;s3&amp;quot; setting&lt;br /&gt;
      bucketName: &amp;quot;xxx&amp;quot;, // bucket for s3 event&lt;br /&gt;
      createBucket: boolean, // if true will generate new bucket with bucketName if false will point to old bucket that already have &lt;br /&gt;
&lt;br /&gt;
      // event=&amp;quot;eventBridge&amp;quot; setting&lt;br /&gt;
      schedules: [&lt;br /&gt;
        {&lt;br /&gt;
          name: &#039;your-scheduled-rate-event-name&#039;,&lt;br /&gt;
          description: &#039;your scheduled rate event description&#039;,&lt;br /&gt;
          rate: [&amp;quot;rate(1 minute)&amp;quot;,],&lt;br /&gt;
          input: {}&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
&lt;br /&gt;
      outputTopic: boolean,&lt;br /&gt;
&lt;br /&gt;
      flowSteps: {&lt;br /&gt;
        inTag: { // will generate Topic serviceTag_stage_yyy_inTag&lt;br /&gt;
          properties: [], // reference to stepProperties key, the first lambda&#039;s input properties and messageAttributes are the flow&#039;s input properties and messageAttributes&lt;br /&gt;
          messageAttributes: [], // reference to stepProperties key&lt;br /&gt;
          plugInHooks: [&lt;br /&gt;
            {&lt;br /&gt;
              plugInHookTag: &amp;quot;&amp;quot;,&lt;br /&gt;
              objType: {}, // used to query connection dynamo for an object instance in current flow&lt;br /&gt;
            },&lt;br /&gt;
          ],&lt;br /&gt;
          returnValues: {&lt;br /&gt;
            properties: [], // reference to stepProperties key&lt;br /&gt;
            messageAttributes: [], // reference to stepProperties key, only for outputTopic=true&lt;br /&gt;
          },&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
        // another flow steps&lt;br /&gt;
        flowStep1: { // will generate Topic serviceTag_stage_yyy_Flow1&lt;br /&gt;
          properties: [], // reference to stepProperties key&lt;br /&gt;
          messageAttributes: [], // reference to stepProperties key&lt;br /&gt;
          event: [&amp;quot;ownTopic&amp;quot;],  // &amp;quot;ownTopic&amp;quot; | &amp;quot;extTopic&amp;quot; | &amp;quot;s3&amp;quot; | &amp;quot;eventBridge&amp;quot; | &amp;quot;lambdaSyncInv&amp;quot; | &amp;quot;lambdaSyncApi&amp;quot; | &amp;quot;generatedCode&amp;quot; | &amp;quot;dsq&amp;quot;&lt;br /&gt;
          // handle splitting logic into awaitingStep/awaitingMultipleSteps&lt;br /&gt;
          // handle splitting logic into paginated lambda&lt;br /&gt;
&lt;br /&gt;
          previousSteps: [&lt;br /&gt;
            {&lt;br /&gt;
              sourceType:&amp;quot;ownTopic&amp;quot;, // if from own flow&lt;br /&gt;
              stepName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
              sourceType: &amp;quot;extTopic&amp;quot;, // triggered by output from external service&lt;br /&gt;
              serviceTag: &amp;quot;InventoryService&amp;quot;,&lt;br /&gt;
              topic: &amp;quot;ReserveStock_In&amp;quot;,&lt;br /&gt;
              fromStepNames: [&amp;quot;xx&amp;quot;] // which step in this flow sent request to external flow, used to find awaitingStep prefix&lt;br /&gt;
            }            &lt;br /&gt;
          ],&lt;br /&gt;
          nextSteps: [&lt;br /&gt;
            {&lt;br /&gt;
              targetType:&amp;quot;ownTopic&amp;quot;, // if from own flow&lt;br /&gt;
              stepName: &amp;quot;yyy&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
              targetType: &amp;quot;extTopic&amp;quot;,&lt;br /&gt;
              serviceTag: &amp;quot;InventoryService&amp;quot;,&lt;br /&gt;
              topic: &amp;quot;ReserveStock_In&amp;quot;,&lt;br /&gt;
              toStepNames: [&amp;quot;xx&amp;quot;] // which step in this flow sent request to external flow, used to find awaitingStep prefix&lt;br /&gt;
            }&lt;br /&gt;
          ],&lt;br /&gt;
&lt;br /&gt;
          plugInHooks: [&lt;br /&gt;
            {&lt;br /&gt;
              plugInHookTag: &amp;quot;&amp;quot;,&lt;br /&gt;
              objType: {}, // used to query connection dynamo for an object instance in current flow&lt;br /&gt;
            },&lt;br /&gt;
          ],&lt;br /&gt;
          returnValues: { // the last lambda function returnValues are the flow&#039;s returnValues&lt;br /&gt;
            properties: [], // reference to stepProperties key&lt;br /&gt;
            messageAttributes: [], // reference to stepProperties key, only for outputTopic=true&lt;br /&gt;
          },&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
      },&lt;br /&gt;
&lt;br /&gt;
      stepProperties: { // normalized all stepProperties&lt;br /&gt;
        &amp;quot;uuid&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          type: &amp;quot;object&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          childProperties: [&amp;quot;uuid2&amp;quot;, &amp;quot;uuid3&amp;quot;]&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid2&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid3&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid4&amp;quot;: {&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          objectField: {&lt;br /&gt;
            objType: {},&lt;br /&gt;
            fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          overwritePropertyName: &amp;quot;xx&amp;quot; // optional, if have objectField and have overwritePropertyName will overwrite fieldName &lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
      stepMessageAttributes: { // normalized all stepMessageAttributes&lt;br /&gt;
        &amp;quot;uuid&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid2&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= System Text Schema | SystemTextSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
	{&lt;br /&gt;
		namespace: &amp;quot;xxx&amp;quot;, // groups files downloaded by frontend&lt;br /&gt;
		systemTextTag: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
	}&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Auto generated systemText and namespaces ==&lt;br /&gt;
&lt;br /&gt;
=== systemNotification names ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;sysNotification_{notificationGrouping}&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{notificationTag}&amp;quot;&lt;br /&gt;
* eg shown on notification settings page&lt;br /&gt;
&lt;br /&gt;
=== objType names ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;objTypes&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{serviceTag}_{objectType}&amp;quot;&lt;br /&gt;
* eg shown on config pages, eg pulldown list of object types&lt;br /&gt;
&lt;br /&gt;
=== objType field name descriptions ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;objType_fielddesc_{serviceTag}_{objectType}&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{fieldname}&amp;quot;&lt;br /&gt;
* eg shown on config pages, eg info box for each field name&lt;br /&gt;
&lt;br /&gt;
= System Notification Schema | SystemNotificationSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
	{&lt;br /&gt;
		notificationTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
		notificationGrouping: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
		weight: &amp;quot;##&amp;quot;,&lt;br /&gt;
	},&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Generated S3 files =&lt;br /&gt;
&lt;br /&gt;
* generate multiple files for different uses, eg:&lt;br /&gt;
*# list of saved fieldNames for Create&lt;br /&gt;
*# list of saved+calculated for Update/Info pages&lt;br /&gt;
*# graphSchemas&lt;br /&gt;
*# relationships (used by Search/Sort Results)&lt;br /&gt;
&lt;br /&gt;
= Use Cases =&lt;br /&gt;
&lt;br /&gt;
== Find Deployed Service Name ==&lt;br /&gt;
&lt;br /&gt;
* other services can use fixed serviceTag to get deployed serviceName from serviceSchema on S3&lt;br /&gt;
* used to build resource names for external services&lt;br /&gt;
* eg when one service needs to send a message into an SNS belonging to a different service&lt;br /&gt;
&lt;br /&gt;
== Standard Create, Update, List, Delete pages ==&lt;br /&gt;
&lt;br /&gt;
* List and Delete are maybe not required, use table data system instead.&lt;br /&gt;
* object schema can add validation information that can be used on the frontend to check before sending to backend, and by the backend to validate the data before handling&lt;br /&gt;
&lt;br /&gt;
=== Create Object ===&lt;br /&gt;
&lt;br /&gt;
* can configure what fields are shown&lt;br /&gt;
* requiredOnCreate fields must be shown &lt;br /&gt;
&lt;br /&gt;
=== Edit Object ===&lt;br /&gt;
&lt;br /&gt;
* users setup any number of pages for object types with configurable fields shown&lt;br /&gt;
* fields can be either display only or edit&lt;br /&gt;
* each field can adjust it&#039;s display properties (perhaps via cssStyles)&lt;br /&gt;
&lt;br /&gt;
== Menu Config ==&lt;br /&gt;
&lt;br /&gt;
When adding menu items can add links to create, update, list, delete objects, user chooses the service then from that service&#039;s list of objects and what action is being performed. For update/delete perhaps links to a standard page that asks for the identifier before presenting the page.&lt;br /&gt;
&lt;br /&gt;
== Tabled Data ==&lt;br /&gt;
&lt;br /&gt;
When viewing tabled data the frontend pulls the tableId&#039;s config from backend, then when requesting the data also requests the serviceTag &amp;gt; objectType schema for use when displaying the data.&lt;br /&gt;
&lt;br /&gt;
== Code Standardization ==&lt;br /&gt;
&lt;br /&gt;
Code such as middleware validation schema and saving data to databases can be standardized.&lt;br /&gt;
&lt;br /&gt;
== Code Generation ==&lt;br /&gt;
&lt;br /&gt;
Endpoints per object for actions such as Create/Delete/Update can be automatically generated from objectSchema.&lt;br /&gt;
&lt;br /&gt;
=== Code Generation Structure ===&lt;br /&gt;
&lt;br /&gt;
* npm for generic code generation, can be used in any project, includes functions for generating Source files from templates and developer files&lt;br /&gt;
* npm for per project specific files, eg templates for the project (Create/Update/.. code)&lt;br /&gt;
* Empty Service Template has GenerateCode.js script file in root dir that is run to generate code, it invokes a generation function from generic npm with param that points to per project npm&#039;s templates&lt;br /&gt;
* generated Source retains hook tags (and any developer added code), so if developer wants to update developer&#039;s file with updated template code they can generate code and simply copy generated Source to src folder&lt;br /&gt;
&lt;br /&gt;
= Graph Server Config =&lt;br /&gt;
&lt;br /&gt;
* S3 has a list of graphServerTag&#039;s linking to the GraphHandler serviceTag responsible for the graph&lt;br /&gt;
* multiple graphServerTags can point to one GraphHandler, combining graphs into one server&lt;br /&gt;
* when creating each GraphHandler&#039;s graph schemas, for each field split out the fields into each GraphHandler using the graphServerTag, if multiple graphServerTags for a field point to the same GraphHandler combine the fields to create GraphHandler&#039;s graph schema&lt;br /&gt;
* every GraphHandler an object is saved into will require it&#039;s identifiers&lt;br /&gt;
* when eg updating fields for an object separate the fields per GraphHandler before sending the request to update each graph&lt;br /&gt;
&lt;br /&gt;
= Extended Object Types =&lt;br /&gt;
&lt;br /&gt;
* Allows for one graph node to have multiple labels&lt;br /&gt;
* graph schema is created for both the core object and the extended object&lt;br /&gt;
* eg Media Manager&#039;s has a node schema for &amp;quot;media&amp;quot; object type, and Image service has a node schema for &amp;quot;image&amp;quot; object type&lt;br /&gt;
* the extended object builds it&#039;s schema by combining core + extended settings&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - Per Service Schemas|Per Service Schemas]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Design_concepts&amp;diff=4617</id>
		<title>Design concepts</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Design_concepts&amp;diff=4617"/>
		<updated>2026-08-23T05:43:49Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Projects =&lt;br /&gt;
&lt;br /&gt;
* [[Development - Izara Core]]&lt;br /&gt;
* [[Development - Izara Market]]&lt;br /&gt;
* [[Development - Izara Supply]]&lt;br /&gt;
* [[Development - Izara Video Feed]]&lt;br /&gt;
* [[Development - Izara Commerce]]&lt;br /&gt;
* [[Development - Izara Accounting]]&lt;br /&gt;
* [[Development - Izara IoT]]&lt;br /&gt;
* [[Development - Izara Currency]]&lt;br /&gt;
&lt;br /&gt;
= Linker Projects =&lt;br /&gt;
&lt;br /&gt;
* [[Development - Izara Commerce to Accounting]]&lt;br /&gt;
* [[Development - Izara Supply to VideoFeed]]&lt;br /&gt;
&lt;br /&gt;
= Backend =&lt;br /&gt;
&lt;br /&gt;
== Backend services ==&lt;br /&gt;
&lt;br /&gt;
[[:Category:Backend services|see all Backend services]]&lt;br /&gt;
&lt;br /&gt;
== NPM modules ==&lt;br /&gt;
&lt;br /&gt;
[[:Category:NPM modules|see all NPM modules]]&lt;br /&gt;
&lt;br /&gt;
== Deploy instructions ==&lt;br /&gt;
&lt;br /&gt;
[[:Category:Deploy instructions|see all Deploy instructions]]&lt;br /&gt;
&lt;br /&gt;
== Testing and developing ==&lt;br /&gt;
&lt;br /&gt;
* [[Repository structure]]&lt;br /&gt;
*: Standard file and directory structure of repositories&lt;br /&gt;
* [[Development environment]]&lt;br /&gt;
* [[Test environment overview]]&lt;br /&gt;
* [[Using Postman]]&lt;br /&gt;
* [[Git development]]&lt;br /&gt;
* [[Syntax - Backend services]]&lt;br /&gt;
* [[Remote repository and workspace structure]]&lt;br /&gt;
* [[Developer guide for making Integration Tests]]&lt;br /&gt;
* [[Diagrams service]]&lt;br /&gt;
&lt;br /&gt;
== Misc concepts ==&lt;br /&gt;
&lt;br /&gt;
* [[Communication between services]]&lt;br /&gt;
* [[Lambda handler functions]]&lt;br /&gt;
* [[Idempotence and Race Conditions]]&lt;br /&gt;
* [[Per Service Schemas]]&lt;br /&gt;
* [[Standard Data Structures]]&lt;br /&gt;
* [[User Data Handling]]&lt;br /&gt;
* [[Standard LogicalResults Per Service]]&lt;br /&gt;
* [[Standard FindData Per Service]]&lt;br /&gt;
* [[Stored Cache]] and [[Triggered Cache]]&lt;br /&gt;
* [[Calling Flow]]&lt;br /&gt;
* [[Standard WebSocketTask Per Service]]&lt;br /&gt;
* [[Error Handling Multi Thread Processing]]&lt;br /&gt;
* [[Copying large Dynamo data from to another service table]]&lt;br /&gt;
&lt;br /&gt;
= Frontend =&lt;br /&gt;
&lt;br /&gt;
== Testing and developing ==&lt;br /&gt;
&lt;br /&gt;
* [[Syntax - Frontend services]]&lt;br /&gt;
&lt;br /&gt;
== Concepts ==&lt;br /&gt;
&lt;br /&gt;
* [[Frontend Application Structure]]&lt;br /&gt;
* [[Frontend Authentication]]&lt;br /&gt;
&lt;br /&gt;
== Testing and developing ==&lt;br /&gt;
&lt;br /&gt;
* [[Local Development Environment]]&lt;br /&gt;
&lt;br /&gt;
= This wiki =&lt;br /&gt;
&lt;br /&gt;
* [[How to contribute]]&lt;br /&gt;
* [[Standard formatting rules]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=2022-11-09_-_Multi_Thread_Invocation&amp;diff=4616</id>
		<title>2022-11-09 - Multi Thread Invocation</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=2022-11-09_-_Multi_Thread_Invocation&amp;diff=4616"/>
		<updated>2026-08-23T05:43:03Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;NOT YET USING&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Chose not to use this concept yet because no simple way of splitting sets of records queried from Dynamo into sets, eg: thread#1 process Dynamo pagination 1/6/11.., thread#2 process pagination 2/7/12..&lt;br /&gt;
&lt;br /&gt;
Reason is because to paginate Dynamo results we need the last evaluated key, but how do we find this? Each time we skip some records we need to query all records up to where we skip to, to get the last evaluated key.&lt;br /&gt;
&lt;br /&gt;
Alternatives are:&lt;br /&gt;
* Query just the keys up to the last record, then query the full items&lt;br /&gt;
* Do one full iteration of all records and cache the start keys per page&lt;br /&gt;
* If we insert records consecutively we could cache the start keys as we insert&lt;br /&gt;
* Have a Global Secondary Index which is an increment value 1,2,3.., this could be directly queried to get page results&lt;br /&gt;
&lt;br /&gt;
All the above add additional resources and complexity, need to weigh this against the gains of multithread processing which is primarily completing the tasks faster. I decided that most tasks will not justify the costs.&lt;br /&gt;
&lt;br /&gt;
Perhaps tasks that are time consuming the additional cost would be worth it, but most tasks that are time consuming are async and the multi thread part affects the first step only.&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Manages processing multiple sets of one data set at the same time, including a maximum number of threads per data set. Each invocation for each thread processes a set number of records.&lt;br /&gt;
&lt;br /&gt;
= Process =&lt;br /&gt;
&lt;br /&gt;
* originating function calculates the number of threads needed using the total count of records, max number of threads, and records processed per invocation&lt;br /&gt;
* each thread can paginate through the data set&lt;br /&gt;
* LastEvaluatedKey is required for pagination, thread#1 initially does not require this as starts from 0, but all other threads need to find the appropriate LastEvaluatedKey for where they begin&lt;br /&gt;
* Each invocation checks if there are additional pages it needs to process using total count of records and records processed per invocation&lt;br /&gt;
* Initial calling function saves AwaitingMultipleSteps for each thread&lt;br /&gt;
* as each thread detects there are no remaining pages to process it clears it&#039;s AwaitingMultipleStep and checks if any awaiting steps remain, if not it continues the work flow&lt;br /&gt;
&lt;br /&gt;
[[Category:Working documents| 2022-11-09]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=2022-11-09_-_Multi_Thread_Invocation&amp;diff=4615</id>
		<title>2022-11-09 - Multi Thread Invocation</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=2022-11-09_-_Multi_Thread_Invocation&amp;diff=4615"/>
		<updated>2026-08-23T05:42:54Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;NOT YET USING&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Chose not to use this concept yet because no simple way of splitting sets of records queried from Dynamo into sets, eg: thread#1 process Dynamo pagination 1/6/11.., thread#2 process pagination 2/7/12..&lt;br /&gt;
&lt;br /&gt;
Reason is because to paginate Dynamo results we need the last evaluated key, but how do we find this? Each time we skip some records we need to query all records up to where we skip to, to get the last evaluated key.&lt;br /&gt;
&lt;br /&gt;
Alternatives are:&lt;br /&gt;
* Query just the keys up to the last record, then query the full items&lt;br /&gt;
* Do one full iteration of all records and cache the start keys per page&lt;br /&gt;
* If we insert records consecutively we could cache the start keys as we insert&lt;br /&gt;
* Have a Global Secondary Index which is an increment value 1,2,3.., this could be directly queried to get page results&lt;br /&gt;
&lt;br /&gt;
All the above add additional resources and complexity, need to weigh this against the gains of multithread processing which is primarily completing the tasks faster. I decided that most tasks will not justify the costs.&lt;br /&gt;
&lt;br /&gt;
Perhaps tasks that are time consuming the additional cost would be worth it, but most tasks that are time consuming are async and the multi thread part affects the first step only.&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Manages processing multiple sets of one data set at the same time, including a maximum number of threads per data set. Each invocation for each thread processes a set number of records.&lt;br /&gt;
&lt;br /&gt;
= Process =&lt;br /&gt;
&lt;br /&gt;
* originating function calculates the number of threads needed using the total count of records, max number of threads, and records processed per invocation&lt;br /&gt;
* each thread can paginate through the data set&lt;br /&gt;
* LastEvaluatedKey is required for pagination, thread#1 initially does not require this as starts from 0, but all other threads need to find the appropriate LastEvaluatedKey for where they begin&lt;br /&gt;
* Each invocation checks if there are additional pages it needs to process using total count of records and records processed per invocation&lt;br /&gt;
* Initial calling function saves AwaitingMultipleSteps for each thread&lt;br /&gt;
* as each thread detects there are no remaining pages to process it clears it&#039;s AwaitingMultipleStep and checks if any awaiting steps remain, if not it continues the work flow&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Multi_Thread_Invocation&amp;diff=4614</id>
		<title>Multi Thread Invocation</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Multi_Thread_Invocation&amp;diff=4614"/>
		<updated>2026-08-23T05:41:52Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: Sven the Barbarian moved page Multi Thread Invocation to 2022-11-09 - Multi Thread Invocation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[2022-11-09 - Multi Thread Invocation]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=2022-11-09_-_Multi_Thread_Invocation&amp;diff=4613</id>
		<title>2022-11-09 - Multi Thread Invocation</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=2022-11-09_-_Multi_Thread_Invocation&amp;diff=4613"/>
		<updated>2026-08-23T05:41:50Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: Sven the Barbarian moved page Multi Thread Invocation to 2022-11-09 - Multi Thread Invocation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;NOT YET USING&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Chose not to use this concept yet because no simple way of splitting sets of records queried from Dynamo into sets, eg: thread#1 process Dynamo pagination 1/6/11.., thread#2 process pagination 2/7/12..&lt;br /&gt;
&lt;br /&gt;
Reason is because to paginate Dynamo results we need the last evaluated key, but how do we find this? Each time we skip some records we need to query all records up to where we skip to, to get the last evaluated key.&lt;br /&gt;
&lt;br /&gt;
Alternatives are:&lt;br /&gt;
* Query just the keys up to the last record, then query the full items&lt;br /&gt;
* Do one full iteration of all records and cache the start keys per page&lt;br /&gt;
* If we insert records consecutively we could cache the start keys as we insert&lt;br /&gt;
* Have a Global Secondary Index which is an increment value 1,2,3.., this could be directly queried to get page results&lt;br /&gt;
&lt;br /&gt;
All the above add additional resources and complexity, need to weigh this against the gains of multithread processing which is primarily completing the tasks faster. I decided that most tasks will not justify the costs.&lt;br /&gt;
&lt;br /&gt;
Perhaps tasks that are time consuming the additional cost would be worth it, but most tasks that are time consuming are async and the multi thread part affects the first step only.&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Manages processing multiple sets of one data set at the same time, including a maximum number of threads per data set. Each invocation for each thread processes a set number of records.&lt;br /&gt;
&lt;br /&gt;
= Process =&lt;br /&gt;
&lt;br /&gt;
* originating function calculates the number of threads needed using the total count of records, max number of threads, and records processed per invocation&lt;br /&gt;
* each thread can paginate through the data set&lt;br /&gt;
* LastEvaluatedKey is required for pagination, thread#1 initially does not require this as starts from 0, but all other threads need to find the appropriate LastEvaluatedKey for where they begin&lt;br /&gt;
* Each invocation checks if there are additional pages it needs to process using total count of records and records processed per invocation&lt;br /&gt;
* Initial calling function saves AwaitingMultipleSteps for each thread&lt;br /&gt;
* as each thread detects there are no remaining pages to process it clears it&#039;s AwaitingMultipleStep and checks if any awaiting steps remain, if not it continues the work flow&lt;br /&gt;
&lt;br /&gt;
[[Category:Working documents| 2022-11-09]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=2022-11-09_-_Multi_Thread_Invocation&amp;diff=4612</id>
		<title>2022-11-09 - Multi Thread Invocation</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=2022-11-09_-_Multi_Thread_Invocation&amp;diff=4612"/>
		<updated>2026-08-23T05:39:55Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;NOT YET USING&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Chose not to use this concept yet because no simple way of splitting sets of records queried from Dynamo into sets, eg: thread#1 process Dynamo pagination 1/6/11.., thread#2 process pagination 2/7/12..&lt;br /&gt;
&lt;br /&gt;
Reason is because to paginate Dynamo results we need the last evaluated key, but how do we find this? Each time we skip some records we need to query all records up to where we skip to, to get the last evaluated key.&lt;br /&gt;
&lt;br /&gt;
Alternatives are:&lt;br /&gt;
* Query just the keys up to the last record, then query the full items&lt;br /&gt;
* Do one full iteration of all records and cache the start keys per page&lt;br /&gt;
* If we insert records consecutively we could cache the start keys as we insert&lt;br /&gt;
* Have a Global Secondary Index which is an increment value 1,2,3.., this could be directly queried to get page results&lt;br /&gt;
&lt;br /&gt;
All the above add additional resources and complexity, need to weigh this against the gains of multithread processing which is primarily completing the tasks faster. I decided that most tasks will not justify the costs.&lt;br /&gt;
&lt;br /&gt;
Perhaps tasks that are time consuming the additional cost would be worth it, but most tasks that are time consuming are async and the multi thread part affects the first step only.&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Manages processing multiple sets of one data set at the same time, including a maximum number of threads per data set. Each invocation for each thread processes a set number of records.&lt;br /&gt;
&lt;br /&gt;
= Process =&lt;br /&gt;
&lt;br /&gt;
* originating function calculates the number of threads needed using the total count of records, max number of threads, and records processed per invocation&lt;br /&gt;
* each thread can paginate through the data set&lt;br /&gt;
* LastEvaluatedKey is required for pagination, thread#1 initially does not require this as starts from 0, but all other threads need to find the appropriate LastEvaluatedKey for where they begin&lt;br /&gt;
* Each invocation checks if there are additional pages it needs to process using total count of records and records processed per invocation&lt;br /&gt;
* Initial calling function saves AwaitingMultipleSteps for each thread&lt;br /&gt;
* as each thread detects there are no remaining pages to process it clears it&#039;s AwaitingMultipleStep and checks if any awaiting steps remain, if not it continues the work flow&lt;br /&gt;
&lt;br /&gt;
[[Category:Working documents| 2022-11-09]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Remote_repository_and_workspace_structure&amp;diff=4611</id>
		<title>Remote repository and workspace structure</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Remote_repository_and_workspace_structure&amp;diff=4611"/>
		<updated>2026-08-23T05:34:33Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Repository Design (Forgejo) =&lt;br /&gt;
* One organization per stack&lt;br /&gt;
&lt;br /&gt;
= Core Stacks =&lt;br /&gt;
&lt;br /&gt;
== Izara Core - Libraries ==&lt;br /&gt;
* npm modules that can be used by any web service&lt;br /&gt;
* one project per subject or grouping of functions&lt;br /&gt;
&lt;br /&gt;
== Izara Core - xxxx ==&lt;br /&gt;
* Any stacks that can be used by multiple web services prefixed by Izara Core&lt;br /&gt;
* eg: Media&lt;br /&gt;
&lt;br /&gt;
== Izara Frontend - Core ==&lt;br /&gt;
* Group all frontends for to core services in this workspace&lt;br /&gt;
* Separate projects for each stack&lt;br /&gt;
* Izara Frontends - Core project is for foundation microfrontends like rootConfig and auth&lt;br /&gt;
&lt;br /&gt;
== Izara Frontend - xxxx ==&lt;br /&gt;
* can split groupings of frontends into workspaces&lt;br /&gt;
* eg all Market frontends are in Izara Frontend - Market, one project per stack&lt;br /&gt;
&lt;br /&gt;
== Izara xxx - yyy ==&lt;br /&gt;
* Each stack has its own workspace&lt;br /&gt;
* prefixed by the web service&#039;s name, then the stack, eg: Izara Market - Products&lt;br /&gt;
&lt;br /&gt;
= Developers = &lt;br /&gt;
* When working on a repository developer creates a fork with the same name suffixed with their name in brackets&lt;br /&gt;
* If multiple developers working on the same repositories, only one person forks and names that repository, others fork/PR or push to developers fork&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Test_environment_overview&amp;diff=4610</id>
		<title>Test environment overview</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Test_environment_overview&amp;diff=4610"/>
		<updated>2026-08-23T05:30:26Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Test environments =&lt;br /&gt;
&lt;br /&gt;
* Old notes, now primarily use AI to check local developer code without mock AWS resources, [[Service - Integration Testing]] in AWS test environment, non-destructive tests in production environment could be implemented in the future&lt;br /&gt;
&lt;br /&gt;
There are three test environments to plan for:&lt;br /&gt;
&lt;br /&gt;
== [[Local test environment|Local]] ==&lt;br /&gt;
&lt;br /&gt;
For example when a developer clones one repository to their local computer and wishes to test code within that one repository.&lt;br /&gt;
&lt;br /&gt;
* Self contained environment per service/repository&lt;br /&gt;
* Does not have the AWS environment available&lt;br /&gt;
* Can use mock responses and environments if mocking modules function well&lt;br /&gt;
* Modules that emulate AWS offline are often lacking matching functionality/buggy&lt;br /&gt;
* DynamoDB / APIGateway / Lambda local mocking modules work well&lt;br /&gt;
* Mainly unit tests and basic integration tests that don’t involve queues, invoking other lambda functions, etc..&lt;br /&gt;
&lt;br /&gt;
== [[Test environment deployed on AWS]] ==&lt;br /&gt;
&lt;br /&gt;
Can have multiple deployed test environments, eg one that refreshes seed data and runs automated tests, one as a sandbox where data can be manipulated as a sandbox environment.&lt;br /&gt;
&lt;br /&gt;
* Replicates the final development environment&lt;br /&gt;
* Requires all services used in tested code to be deployed&lt;br /&gt;
&lt;br /&gt;
== [[Production environment deployed on AWS]] ==&lt;br /&gt;
&lt;br /&gt;
This is the final live production service, tests that do not harm live data/state can be periodically executed to make sure production environment is functioning as expected.&lt;br /&gt;
&lt;br /&gt;
* Can hook into live workflows (eg using selective/random requests set by middleware to debug or test) and for example check the flow passes through all steps&lt;br /&gt;
&lt;br /&gt;
= Sharing tests across environments =&lt;br /&gt;
&lt;br /&gt;
Unit tests used in the local environment could be extended to be steps within deployed integration tests across services, if we break up the multi-step integration steps into each services components, those components could be the unit tests for each service. The expected data that passes between services during integration tests would become the mock responses, inputs, and expected outputs for the unit tests.&lt;br /&gt;
&lt;br /&gt;
Doing this would allow us to code tests once, primarily for integration test, and have the same test design applied to each services unit tests. Single test designs used in multiple environments.&lt;br /&gt;
&lt;br /&gt;
Increasing the number of unit tests is optimal because local unit tests will be the most often invoked and the first line of testing, more unit tests will mean faster detection of bugs and less resources used moving to deployed integration tests.&lt;br /&gt;
&lt;br /&gt;
* [[Service - Integration Test Config]]&lt;br /&gt;
* [[Service - Integration Testing]]&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
&lt;br /&gt;
* [[2019-01-01 - Hexagonal Architecture pattern]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Local_test_environment&amp;diff=4609</id>
		<title>Local test environment</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Local_test_environment&amp;diff=4609"/>
		<updated>2026-08-23T05:26:46Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
* No longer used *&lt;br /&gt;
&lt;br /&gt;
Each repository is a micro-service that performs has responsibility for one part of the {{ProjectNameLong}}, although each is meant to be used as part of a network of interconnected micro-services when a single repository is cloned the first level of testing is at the self contained local level.&lt;br /&gt;
&lt;br /&gt;
= Unit tests =&lt;br /&gt;
&lt;br /&gt;
Most local tests will be unit tests, these tests are built in two ways:&lt;br /&gt;
&lt;br /&gt;
# created in the __test__/unit directory for each serverless project in the repository&lt;br /&gt;
# generated from integration tests defined in the [[Service - Integration Test Config|Integration Test Config]] service&lt;br /&gt;
&lt;br /&gt;
= Serverless Local =&lt;br /&gt;
&lt;br /&gt;
sets up a local api gateway and lambda functions&lt;br /&gt;
adds environment variable IS_OFFLINE into Lambda functions&lt;br /&gt;
&lt;br /&gt;
lambdas deployed to a local serverless offline environment are invoked by sending REST request to local API Gateway endpoint&lt;br /&gt;
good for testing API Gateway config&lt;br /&gt;
bad: cannot setup test environment (eg mocks) in the Jest code because is a separate environment to the serverless offline environment&lt;br /&gt;
cannot test individual functions that are not API Gateway triggered&lt;br /&gt;
&lt;br /&gt;
add to app serverless.yml below code&lt;br /&gt;
only needed where functions and api gateway are deployed&lt;br /&gt;
not needed in resource (if using sns/sqs offline they might need it)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;YAML&amp;quot;&amp;gt;&lt;br /&gt;
plugins:&lt;br /&gt;
  - serverless-offline&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= DynamoDB Local =&lt;br /&gt;
&lt;br /&gt;
* https://www.npmjs.com/package/serverless-dynamodb-local&lt;br /&gt;
* have setting in powertools dynamo client, if IS_LOCAL (set by serverless offline running) then will add connection settings below&lt;br /&gt;
DynamoDB local connection settings are hardcoded, if need to change things like port maybe we can find some hack like local environment variable, rather than polluting serverless.yml etc..&lt;br /&gt;
* Serverless have a small module to work with this, we could copy its code if needed:&lt;br /&gt;
* https://github.com/99xt/serverless-dynamodb-client/blob/master/index.js&lt;br /&gt;
&lt;br /&gt;
* thinking if starting multiple services together on local can use the same dynamodb local database, just placing multiple tables in it&lt;br /&gt;
&lt;br /&gt;
* default is to store data in memory, which gets destroyed each time we stop, if this becomes unmanageable or if we want to maintain state it is possible to save to file&lt;br /&gt;
&lt;br /&gt;
* to install into a project, in resource dir:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;npm install --save-dev serverless-dynamodb-local&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* all resource serverless.yml have below code, used only for DynamoDB local&lt;br /&gt;
* (not sure) we do not migrate or seed here because we want to do that per service (eg in a script), and might have different seeds for different situations&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
custom:&lt;br /&gt;
 dynamodb:&lt;br /&gt;
 # If you only want to use DynamoDB Local in some stages, declare them here&lt;br /&gt;
   stages:&lt;br /&gt;
     - Dev&lt;br /&gt;
   start:&lt;br /&gt;
     port: 8000&lt;br /&gt;
     inMemory: true&lt;br /&gt;
     heapInitial: 200m #not sure correct setting, can leave off&lt;br /&gt;
     heapMax: 1g #not sure correct setting, can leave off&lt;br /&gt;
     migrate: true&lt;br /&gt;
     seed: true&lt;br /&gt;
   seed:&lt;br /&gt;
     default:&lt;br /&gt;
       sources:&lt;br /&gt;
         - table: ${self:custom.resourcePrefix}Config&lt;br /&gt;
           sources: [../app/__test__/dynamodb_seed_data/default/Config.json]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== One Time Setup ==&lt;br /&gt;
&lt;br /&gt;
=== DynamoDB Local===&lt;br /&gt;
&lt;br /&gt;
* install DynamoDB Local in one services resource dir, this only has to be done once then can be used by all services&lt;br /&gt;
this downloads dynamodb-local from aws and sets up&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;sls dynamodb install&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* requires JDK/JRE, eg: sudo apt-get install openjdk-{version}-jdk&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
* DynamoDB local java executable appears to be saved into repositories /.dynamodb folder&lt;br /&gt;
* If have trouble the downloaded dynamodb file might be no good, can download from https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.DownloadingAndRunning.html&lt;br /&gt;
* Copy into repositories /.dynamodb folder&lt;br /&gt;
* Might need to change permissions to eg: 777&lt;br /&gt;
&lt;br /&gt;
== Per Session / Per Reboot ==&lt;br /&gt;
&lt;br /&gt;
=== Start an empty instance of DynamoDB ===&lt;br /&gt;
&lt;br /&gt;
* can by in any services resource dir:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
sls dynamodb start&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* this will also migrate and seed this service&lt;br /&gt;
&lt;br /&gt;
=== DynamoDB (if working on multiple services) ===&lt;br /&gt;
&lt;br /&gt;
* Can seed multiple services into the local DynamoDB instance&lt;br /&gt;
* resource dir of additional services:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
sls dynamodb migrate&lt;br /&gt;
sls dynamodb seed&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple Dynamo Seed groups ===&lt;br /&gt;
&lt;br /&gt;
* if service has multiple seed groups, to only seed the default group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
sls dynamodb start --seed:default&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working documents - Local test environment|Working documents - Local test environment]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=2026-08-18_-_Plug_In_Service_between_SupplyChian_and_VideoFeed&amp;diff=4605</id>
		<title>2026-08-18 - Plug In Service between SupplyChian and VideoFeed</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=2026-08-18_-_Plug_In_Service_between_SupplyChian_and_VideoFeed&amp;diff=4605"/>
		<updated>2026-08-18T15:51:05Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: Created page with &amp;quot;= Overview =  Move connection between monitor service and eg IzaraVideoFeed into a plugIn service  = notes =  * move monitor links (location/transformUnits/StageAdjust) to plugin * maybe not need monitor services anymore in SupplyChain, plugins create and configure the links, SupplyChain focuses on changes to units * location/transformUnits/StageAdjust links in plugin have properties that can in the future be used to create history video of a unit (eg high quality or spe...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Move connection between monitor service and eg IzaraVideoFeed into a plugIn service&lt;br /&gt;
&lt;br /&gt;
= notes =&lt;br /&gt;
&lt;br /&gt;
* move monitor links (location/transformUnits/StageAdjust) to plugin&lt;br /&gt;
* maybe not need monitor services anymore in SupplyChain, plugins create and configure the links, SupplyChain focuses on changes to units&lt;br /&gt;
* location/transformUnits/StageAdjust links in plugin have properties that can in the future be used to create history video of a unit (eg high quality or speed up video during markers)&lt;br /&gt;
* maybe not have a database entry for each transform/adjust, instead have per config (transformConfigId/stageAdjustmentId) links to videoFeed(s?)  - videoFeeds maybe validate are children of location&#039;s monitorIzaraVideoFeedGroup, but perhaps not need this so user has more freedom&lt;br /&gt;
- if user changes the transformConfigId/stageAdjustmentId &amp;gt; videoFeed link old links will no longer work, warn that they should create a new transform/stageAdjust if they want to keep history&lt;br /&gt;
&lt;br /&gt;
= old notes = &lt;br /&gt;
&lt;br /&gt;
* location points to monitorIzaraVideoFeedGroup (need to change on wiki) object which is one set of videoFeeds in an Operation, eg a warehouse with many videoFeeds&lt;br /&gt;
* transform or stage points to a marker which is a string that is passed to the monitor service, for videoFeeds this can be a tag that we add to videoFeeds, specifying which feed/s are focused during that stage/transform&lt;br /&gt;
* maybe can add properties to feeds and tag a specific property name, or maybe handle in supVid plugin&lt;br /&gt;
&lt;br /&gt;
[[Category:Working documents| 2026-08-18]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Per_Service_Schemas&amp;diff=4604</id>
		<title>Per Service Schemas</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Per_Service_Schemas&amp;diff=4604"/>
		<updated>2026-08-18T15:01:49Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: generatedCodeConfig removed, previously for eg Issue which would create a topic auto when making, but now use importBatch O&amp;gt;O&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Each service manages a schema of object/resources that it is responsible for, this schema is available to other services and frontends. The schema includes a list of fields available for each object.&lt;br /&gt;
&lt;br /&gt;
= File Structure =&lt;br /&gt;
&lt;br /&gt;
* see [[Repository structure#schemas|Repository structure]]&lt;br /&gt;
&lt;br /&gt;
= ObjectSchema | ObjectFieldSchema.js =&lt;br /&gt;
&lt;br /&gt;
== Not extendObjType ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;xx&amp;quot;,&lt;br /&gt;
	shortNameObjectType:&amp;quot;x&amp;quot;, // optional, use when generate code create lambda role with long name&lt;br /&gt;
	canDelete: false, // whether any fields can be deleted // default = false&lt;br /&gt;
	belongTo: { &lt;br /&gt;
		serviceTag:&amp;quot;iii&amp;quot;,&lt;br /&gt;
		objectType:&amp;quot;jjj&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
    // how is the object created&lt;br /&gt;
    // userGenerated there will be generated endpoints for api or sqs (used in importBatchMain) to create object&lt;br /&gt;
    // systemGenerated must be created by flow/s&lt;br /&gt;
    // searchResultGenerated see separate notes below&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot; || &amp;quot;systemGenerated&amp;quot; || &amp;quot;searchResultGenerated&amp;quot; // required&lt;br /&gt;
    searchResultGeneratedFlowType: {}, // for generatedBy = searchResultGenerated&lt;br /&gt;
	addOnDataStructure: [ // optional, add for additional setting to objectType&lt;br /&gt;
		{&lt;br /&gt;
			// all fields that a user can edit must be in versionedData, and all fields in versionedData must be editable by user&lt;br /&gt;
			type:&amp;quot;versionedData&amp;quot;,&lt;br /&gt;
			versionedDataLabel: &amp;quot;xx&amp;quot;, // versionedData label name&lt;br /&gt;
			storageResourceTag : &amp;quot;xx&amp;quot;, // ref to storegeResourceTag&lt;br /&gt;
			fieldNames: { // fieldName in versionedData cannot have in in main objectSchema.fieldNames&lt;br /&gt;
				&amp;quot;aaa&amp;quot;:{ // fieldName&lt;br /&gt;
					type: &amp;quot;xx&amp;quot;, // string|integer|number|timestamp|currency|currencyValue|float|special|object|boolean|arrayMixed|arrayNumeric|arrayString&lt;br /&gt;
					requiredOnCreate: false, // default = false&lt;br /&gt;
					optionalOnCreate: false, // default = false,&lt;br /&gt;
					validation: {&lt;br /&gt;
                      itemValidation:{} // for validate item in array&lt;br /&gt;
                    },&lt;br /&gt;
                    // probably impossible to have fromObjType, because data can be changed by user here&lt;br /&gt;
					fromObjType:{&lt;br /&gt;
						serviceTag: &amp;quot;xxx&amp;quot;, &lt;br /&gt;
						objectType: &amp;quot;xxx&amp;quot; &lt;br /&gt;
					},&lt;br /&gt;
				},&lt;br /&gt;
				// ...&lt;br /&gt;
			}&lt;br /&gt;
        },&lt;br /&gt;
        { // can have multiple addOn of type attributeTree&lt;br /&gt;
          type:&amp;quot;attributeTree&amp;quot;,           &lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;translation&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;propertyValue&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;mediaLink&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;rbac&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
		// ...&lt;br /&gt;
	],&lt;br /&gt;
	plugInTags: [&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;], // plugIns that can be connected to this objType&lt;br /&gt;
	storageResources:{&lt;br /&gt;
		&amp;quot;xxx&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // graph			&lt;br /&gt;
			graphServerTag: &amp;quot;xx&amp;quot;, // setting for storageType graph&lt;br /&gt;
            additionalGraphIndexes:[[&#039;fieldName1&#039;, &#039;fieldName2&#039;, ...], [...]]  // will make graph index with specific fieldName &lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;zzz&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // dynamoDB&lt;br /&gt;
			// setting for storageType dynamoDB&lt;br /&gt;
			tableName: &amp;quot;xx&amp;quot;,&lt;br /&gt;
			groupByPartitionKeyField: &amp;quot;xx&amp;quot;, // use groupByPartitionKeyField as partition key and not have sort key in dynamoDB, if have multiple identifiers will concat it. And use it as partitionKey.&lt;br /&gt;
            serviceTag:&amp;quot;zz&amp;quot;// default own service.&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	fieldNames: {&lt;br /&gt;
		xxx: { // fieldName&lt;br /&gt;
			type: &amp;quot;xx&amp;quot;,  // string|integer|number|timestamp|currency|currencyValue|float|special|object|boolean|arrayMixed|arrayNumeric|arrayString&lt;br /&gt;
            randomOnCreate: false,   // default = false , can set true in fieldName that part of identifiers and identifiers have single identifierFieldname&lt;br /&gt;
			requiredOnCreate: false, // default = false&lt;br /&gt;
			optionalOnCreate: false, // default = false&lt;br /&gt;
			canUpdate: true, // default = true (only system/flows can edit, no history of changes unless flow manually adds)&lt;br /&gt;
			validation: {&lt;br /&gt;
			  itemValidation:{}  // for validate item in array&lt;br /&gt;
            }, // maybe ajv syntax&lt;br /&gt;
			storageResourceTags: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // reference to storageResources property&lt;br /&gt;
		    fromObjType:{&lt;br /&gt;
			  serviceTag: &amp;quot;xxx&amp;quot;, &lt;br /&gt;
			  objectType: &amp;quot;xxx&amp;quot; &lt;br /&gt;
			},&lt;br /&gt;
            hashOnCreate: [&amp;quot;xx&amp;quot;, &amp;quot;yy&amp;quot;], // reference to other fieldName, &lt;br /&gt;
            statusField: true, // use for objectSchema inside flowSchema, identify which field is statusField &lt;br /&gt;
&lt;br /&gt;
			// comes from requiredOnCreate relationships&lt;br /&gt;
			fromRequiredOnCreate: { &lt;br /&gt;
				relType: {&lt;br /&gt;
					serviceTag:&amp;quot;aa&amp;quot;,&lt;br /&gt;
					relationshipTag:&amp;quot;bb&amp;quot;&lt;br /&gt;
				},&lt;br /&gt;
				// or&lt;br /&gt;
				belongToObjType: true, // if set to true use the belongTo relationship to belongTo objType&lt;br /&gt;
&lt;br /&gt;
				fieldName:&amp;quot;&amp;quot; // optional default= same field name eg: now default == xxx if not defined(use fieldname of object inside link when create)&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
		// ...&lt;br /&gt;
	},&lt;br /&gt;
    compositeKeyDeliminator: &amp;quot;xx&amp;quot;, // join partitionKey and sortKey&lt;br /&gt;
	identifiers: [&lt;br /&gt;
    // for dynamoDB storageType &lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // composite partition keys in DynamoDB&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		name: &amp;quot;zz&amp;quot;, // name of field in database&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	},&lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // composite partition keys in DynamoDB&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		name: &amp;quot;zz&amp;quot;, // name of field in database&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	},&lt;br /&gt;
   &lt;br /&gt;
    // for graph storageType&lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;identifier&amp;quot;,&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // identifier field in graph or composite partition keys in DynamoDB&lt;br /&gt;
        name: &amp;quot;zzz&amp;quot;              // use when save in dynamoDB partitionKey&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;	&lt;br /&gt;
	},&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== extendObjType ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	// for objects stored in graph this will add another node label&lt;br /&gt;
	objectType: &amp;quot;xx&amp;quot;, // new label to add&lt;br /&gt;
	extendObjType: { // core object that this object extends&lt;br /&gt;
		serviceTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;xxx&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources:{ // these are the storageResources that carry the extended objects settings, &lt;br /&gt;
		// (see above)&lt;br /&gt;
	},&lt;br /&gt;
	fieldNames: {&lt;br /&gt;
		// (see above) &lt;br /&gt;
	},&lt;br /&gt;
	// canDelete/identifiers come from the core object&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== searchResultGenerated ==&lt;br /&gt;
&lt;br /&gt;
* must be created by flow&lt;br /&gt;
* eg: variantProduct&lt;br /&gt;
* not have any storageResources&lt;br /&gt;
* identifiers are automatically searchResultData identifiers&lt;br /&gt;
* a searchResult request for this object will enter the searchResultGeneratedFlowType flow which creates searchResultData that can then be queried/sorted&lt;br /&gt;
* all relationships must be storageType = lambda, eg translate from variantProduct to variant uses a translateId flow to query the variantProduct identifier (searchResultData) to find the variantId in it&#039;s requiredData results&lt;br /&gt;
* searchResultGeneratedFlowType takes over after creating searchResultMain record until processRequiredData&lt;br /&gt;
* if objectSchema defines any fieldnames, then they are found using a flow, maybe as hooks in per service findData&lt;br /&gt;
* when finding direct fieldname, will need to check if requireData already exists, if not enter flow/findData to create&lt;br /&gt;
* no fields can be edited, so can show in forms but no updates performed&lt;br /&gt;
&lt;br /&gt;
= Relationships Schema | ObjectRelationships.js =&lt;br /&gt;
&lt;br /&gt;
* stored in top level schemas folder&lt;br /&gt;
* parent/child determines relationship direction for graph relationships&lt;br /&gt;
* have one service that contains information of each relationship &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// relationship schema in responsible service&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;xxx&amp;quot;: { // relationshipTag - name of relationship type stored in graph&lt;br /&gt;
      generatedBy: &amp;quot;userGenerated&amp;quot; || &amp;quot;systemGenerated&amp;quot; // default=&amp;quot;userGenerated&amp;quot;&lt;br /&gt;
      canChangeToRelTypes: [&lt;br /&gt;
		{&lt;br /&gt;
			relType: { // relType that this relType can change to &lt;br /&gt;
			  serviceTag:&amp;quot;xxx&amp;quot;,&lt;br /&gt;
			  relationshipTag: &amp;quot;yyy&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			changeBy: &amp;quot;user&amp;quot; // &amp;quot;systemNoUserId&amp;quot; | &amp;quot;systemWithUserId&amp;quot; | &amp;quot;user&amp;quot;, default=&amp;quot;user&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
        // another relType&lt;br /&gt;
      ],&lt;br /&gt;
      storageResources:{&lt;br /&gt;
		&amp;quot;xxx&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // dynamoDB | graph | lambda&lt;br /&gt;
		    // if storageType=&amp;quot;dynamoDB&amp;quot;  will not specify tableName in relationship schema&lt;br /&gt;
&lt;br /&gt;
			// setting for storageType graph&lt;br /&gt;
			graphServerTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
            additionalGraphIndexes:[[&#039;fieldName1&#039;, &#039;fieldName2&#039;, ...], [...]],  // will make graph index with specific fieldName &lt;br /&gt;
&lt;br /&gt;
			// setting for storageType lambda&lt;br /&gt;
			serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
			functionName: &amp;quot;xx&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
      },&lt;br /&gt;
      fieldNames: {&lt;br /&gt;
		&amp;quot;xxx&amp;quot;: { // relationship property name&lt;br /&gt;
			type: &amp;quot;string&amp;quot;, // &amp;quot;string&amp;quot; | &amp;quot;number&amp;quot; ...&lt;br /&gt;
			requiredOnCreate: false, // default=false&lt;br /&gt;
			optionalOnCreate: false, // default = false&lt;br /&gt;
			updateBy: &amp;quot;user&amp;quot; // &amp;quot;systemNoUserId&amp;quot; | &amp;quot;systemWithUserId&amp;quot; | &amp;quot;user&amp;quot; | &amp;quot;none&amp;quot;, default=&amp;quot;user&amp;quot;&lt;br /&gt;
			validation: {} // ajv syntax&lt;br /&gt;
		},&lt;br /&gt;
		//...other relationship properties&lt;br /&gt;
      },&lt;br /&gt;
      links: [&lt;br /&gt;
        {&lt;br /&gt;
          storageResourceTags: [&amp;quot;xxx&amp;quot;],   // reference from storageResources property&lt;br /&gt;
          canDelete: false                // default = false, if set true will allow delete relationship between 2 objType&lt;br /&gt;
          from: {&lt;br /&gt;
            objType: {&lt;br /&gt;
              serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
              objectType: &amp;quot;xx&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            requiredOnCreate: true, // if set true will create relationshipTag when create objType data, if both &amp;quot;from&amp;quot; and &amp;quot;to&amp;quot; linkType=&amp;quot;many&amp;quot; should not have requiredOnCreate, exists in &amp;quot;from&amp;quot; or &amp;quot;to&amp;quot; only&lt;br /&gt;
            linkType: &amp;quot;&amp;quot;,   // one | many&lt;br /&gt;
          //   moveBy: &amp;quot;none&amp;quot;, // &amp;quot;systemNoUserId&amp;quot; | &amp;quot;systemWithUserId&amp;quot; | &amp;quot;user&amp;quot; | &amp;quot;none&amp;quot;, default=&amp;quot;none&amp;quot;&lt;br /&gt;
          // belongTo:true&lt;br /&gt;
          },&lt;br /&gt;
          to: {&lt;br /&gt;
            objType: {&lt;br /&gt;
              serviceTag: &amp;quot;yy&amp;quot;,&lt;br /&gt;
              objectType: &amp;quot;yy&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            linkType: &amp;quot;&amp;quot;,   // one | many&lt;br /&gt;
             // moveBy allows the relationship to be moved between 2 instances of the same objType only&lt;br /&gt;
	        moveBy: &amp;quot;none&amp;quot;, // &amp;quot;systemNoUserId&amp;quot; | &amp;quot;systemWithUserId&amp;quot; | &amp;quot;user&amp;quot; | &amp;quot;none&amp;quot;, default=&amp;quot;none&amp;quot;&lt;br /&gt;
            belongTo:true, // false&lt;br /&gt;
          },&lt;br /&gt;
          requestProperties: {&lt;br /&gt;
            // if storageType is Lambda and translateIds/linkPath requires properties set them here (eg sellOffer&amp;gt;orderPrice)&lt;br /&gt;
            tag_deliverTo: {&lt;br /&gt;
              requestPropertyType: &amp;quot;objectIdentifier&amp;quot;,&lt;br /&gt;
              objType: {&lt;br /&gt;
                serviceTag: &amp;quot;Locations&amp;quot;,&lt;br /&gt;
                objectType: &amp;quot;locationNode&amp;quot; // deliversToLocationNode&lt;br /&gt;
              },&lt;br /&gt;
              identifiersFieldName: &amp;quot;locationNodeId&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            // ... other request properties&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        // ...other link&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Reference Relationships Schema | RefObjectRelationships.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// reference to relationshipTag in external service&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    objectType: &amp;quot;zz&amp;quot;,              // objectType in local service&lt;br /&gt;
    relationshipTag: &amp;quot;xxx&amp;quot;,        // name of relationshiptag of objType&lt;br /&gt;
    relationshipServiceTag: &amp;quot;xx&amp;quot;   // point to service tag that contain data of relationshipTag of objType&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Flow Schema | FlowSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  [&lt;br /&gt;
    {&lt;br /&gt;
      flowTag: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
      initiateBy: &amp;quot;user&amp;quot;,         // &amp;quot;user&amp;quot; | &amp;quot;system&amp;quot; -- if receive plugin should be user &lt;br /&gt;
      handleObj: &amp;quot;one&amp;quot;,           // &amp;quot;one&amp;quot; | &amp;quot;multi&amp;quot;&lt;br /&gt;
      statusType: &amp;quot;statusField&amp;quot;,  // &amp;quot;statusField&amp;quot; | &amp;quot;storedCache&amp;quot; | &amp;quot;none&amp;quot; | &amp;quot;triggerCache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      // statusType=&amp;quot;triggerCache&amp;quot; setting &lt;br /&gt;
      triggerType: &amp;quot;storedCache&amp;quot;, // &amp;quot;storedCache&amp;quot; | &amp;quot;switch&amp;quot;&lt;br /&gt;
      triggerFlowTypes: [&lt;br /&gt;
        //... triggerFlowType&lt;br /&gt;
      ],&lt;br /&gt;
&lt;br /&gt;
      // statusType=&amp;quot;statusField&amp;quot; | &amp;quot;triggerCache&amp;quot; | &amp;quot;storedCache&amp;quot; setting:&lt;br /&gt;
      objType: {},&lt;br /&gt;
&lt;br /&gt;
      event: [&amp;quot;ownTopic&amp;quot;],  // &amp;quot;ownTopic&amp;quot; | &amp;quot;extTopic&amp;quot; | &amp;quot;s3&amp;quot; | &amp;quot;eventBridge&amp;quot; | &amp;quot;lambdaSyncInv&amp;quot; | &amp;quot;lambdaSyncApi&amp;quot; | &amp;quot;generatedCode&amp;quot; | &amp;quot;dsq&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      // event=&amp;quot;s3&amp;quot; setting&lt;br /&gt;
      bucketName: &amp;quot;xxx&amp;quot;, // bucket for s3 event&lt;br /&gt;
      createBucket: boolean, // if true will generate new bucket with bucketName if false will point to old bucket that already have &lt;br /&gt;
&lt;br /&gt;
      // event=&amp;quot;eventBridge&amp;quot; setting&lt;br /&gt;
      schedules: [&lt;br /&gt;
        {&lt;br /&gt;
          name: &#039;your-scheduled-rate-event-name&#039;,&lt;br /&gt;
          description: &#039;your scheduled rate event description&#039;,&lt;br /&gt;
          rate: [&amp;quot;rate(1 minute)&amp;quot;,],&lt;br /&gt;
          input: {}&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
&lt;br /&gt;
      outputTopic: boolean,&lt;br /&gt;
&lt;br /&gt;
      flowSteps: {&lt;br /&gt;
        inTag: { // will generate Topic serviceTag_stage_yyy_inTag&lt;br /&gt;
          properties: [], // reference to stepProperties key, the first lambda&#039;s input properties and messageAttributes are the flow&#039;s input properties and messageAttributes&lt;br /&gt;
          messageAttributes: [], // reference to stepProperties key&lt;br /&gt;
          plugInHooks: [&lt;br /&gt;
            {&lt;br /&gt;
              plugInHookTag: &amp;quot;&amp;quot;,&lt;br /&gt;
              objType: {}, // used to query connection dynamo for an object instance in current flow&lt;br /&gt;
            },&lt;br /&gt;
          ],&lt;br /&gt;
          returnValues: {&lt;br /&gt;
            properties: [], // reference to stepProperties key&lt;br /&gt;
            messageAttributes: [], // reference to stepProperties key, only for outputTopic=true&lt;br /&gt;
          },&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
        // another flow steps&lt;br /&gt;
        flowStep1: { // will generate Topic serviceTag_stage_yyy_Flow1&lt;br /&gt;
          properties: [], // reference to stepProperties key&lt;br /&gt;
          messageAttributes: [], // reference to stepProperties key&lt;br /&gt;
          event: [&amp;quot;ownTopic&amp;quot;],  // &amp;quot;ownTopic&amp;quot; | &amp;quot;extTopic&amp;quot; | &amp;quot;s3&amp;quot; | &amp;quot;eventBridge&amp;quot; | &amp;quot;lambdaSyncInv&amp;quot; | &amp;quot;lambdaSyncApi&amp;quot; | &amp;quot;generatedCode&amp;quot; | &amp;quot;dsq&amp;quot;&lt;br /&gt;
          // handle splitting logic into awaitingStep/awaitingMultipleSteps&lt;br /&gt;
          // handle splitting logic into paginated lambda&lt;br /&gt;
&lt;br /&gt;
          previousSteps: [&lt;br /&gt;
            {&lt;br /&gt;
              sourceType:&amp;quot;ownTopic&amp;quot;, // if from own flow&lt;br /&gt;
              stepName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
              sourceType: &amp;quot;extTopic&amp;quot;, // triggered by output from external service&lt;br /&gt;
              serviceTag: &amp;quot;InventoryService&amp;quot;,&lt;br /&gt;
              topic: &amp;quot;ReserveStock_In&amp;quot;,&lt;br /&gt;
              fromStepNames: [&amp;quot;xx&amp;quot;] // which step in this flow sent request to external flow, used to find awaitingStep prefix&lt;br /&gt;
            }            &lt;br /&gt;
          ],&lt;br /&gt;
          nextSteps: [&lt;br /&gt;
            {&lt;br /&gt;
              targetType:&amp;quot;ownTopic&amp;quot;, // if from own flow&lt;br /&gt;
              stepName: &amp;quot;yyy&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
              targetType: &amp;quot;extTopic&amp;quot;,&lt;br /&gt;
              serviceTag: &amp;quot;InventoryService&amp;quot;,&lt;br /&gt;
              topic: &amp;quot;ReserveStock_In&amp;quot;,&lt;br /&gt;
              toStepNames: [&amp;quot;xx&amp;quot;] // which step in this flow sent request to external flow, used to find awaitingStep prefix&lt;br /&gt;
            }&lt;br /&gt;
          ],&lt;br /&gt;
&lt;br /&gt;
          plugInHooks: [&lt;br /&gt;
            {&lt;br /&gt;
              plugInHookTag: &amp;quot;&amp;quot;,&lt;br /&gt;
              objType: {}, // used to query connection dynamo for an object instance in current flow&lt;br /&gt;
            },&lt;br /&gt;
          ],&lt;br /&gt;
          returnValues: { // the last lambda function returnValues are the flow&#039;s returnValues&lt;br /&gt;
            properties: [], // reference to stepProperties key&lt;br /&gt;
            messageAttributes: [], // reference to stepProperties key, only for outputTopic=true&lt;br /&gt;
          },&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
      },&lt;br /&gt;
&lt;br /&gt;
      stepProperties: { // normalized all stepProperties&lt;br /&gt;
        &amp;quot;uuid&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          type: &amp;quot;object&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          childProperties: [&amp;quot;uuid2&amp;quot;, &amp;quot;uuid3&amp;quot;]&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid2&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid3&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid4&amp;quot;: {&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          objectField: {&lt;br /&gt;
            objType: {},&lt;br /&gt;
            fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          overwritePropertyName: &amp;quot;xx&amp;quot; // optional, if have objectField and have overwritePropertyName will overwrite fieldName &lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
      stepMessageAttributes: { // normalized all stepMessageAttributes&lt;br /&gt;
        &amp;quot;uuid&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid2&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= System Text Schema | SystemTextSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
	{&lt;br /&gt;
		namespace: &amp;quot;xxx&amp;quot;, // groups files downloaded by frontend&lt;br /&gt;
		systemTextTag: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
	}&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Auto generated systemText and namespaces ==&lt;br /&gt;
&lt;br /&gt;
=== systemNotification names ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;sysNotification_{notificationGrouping}&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{notificationTag}&amp;quot;&lt;br /&gt;
* eg shown on notification settings page&lt;br /&gt;
&lt;br /&gt;
=== objType names ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;objTypes&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{serviceTag}_{objectType}&amp;quot;&lt;br /&gt;
* eg shown on config pages, eg pulldown list of object types&lt;br /&gt;
&lt;br /&gt;
=== objType field name descriptions ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;objType_fielddesc_{serviceTag}_{objectType}&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{fieldname}&amp;quot;&lt;br /&gt;
* eg shown on config pages, eg info box for each field name&lt;br /&gt;
&lt;br /&gt;
= System Notification Schema | SystemNotificationSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
	{&lt;br /&gt;
		notificationTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
		notificationGrouping: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
		weight: &amp;quot;##&amp;quot;,&lt;br /&gt;
	},&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Generated S3 files =&lt;br /&gt;
&lt;br /&gt;
* generate multiple files for different uses, eg:&lt;br /&gt;
*# list of saved fieldNames for Create&lt;br /&gt;
*# list of saved+calculated for Update/Info pages&lt;br /&gt;
*# graphSchemas&lt;br /&gt;
*# relationships (used by Search/Sort Results)&lt;br /&gt;
&lt;br /&gt;
= Use Cases =&lt;br /&gt;
&lt;br /&gt;
== Find Deployed Service Name ==&lt;br /&gt;
&lt;br /&gt;
* other services can use fixed serviceTag to get deployed serviceName from serviceSchema on S3&lt;br /&gt;
* used to build resource names for external services&lt;br /&gt;
* eg when one service needs to send a message into an SNS belonging to a different service&lt;br /&gt;
&lt;br /&gt;
== Standard Create, Update, List, Delete pages ==&lt;br /&gt;
&lt;br /&gt;
* List and Delete are maybe not required, use table data system instead.&lt;br /&gt;
* object schema can add validation information that can be used on the frontend to check before sending to backend, and by the backend to validate the data before handling&lt;br /&gt;
&lt;br /&gt;
=== Create Object ===&lt;br /&gt;
&lt;br /&gt;
* can configure what fields are shown&lt;br /&gt;
* requiredOnCreate fields must be shown &lt;br /&gt;
&lt;br /&gt;
=== Edit Object ===&lt;br /&gt;
&lt;br /&gt;
* users setup any number of pages for object types with configurable fields shown&lt;br /&gt;
* fields can be either display only or edit&lt;br /&gt;
* each field can adjust it&#039;s display properties (perhaps via cssStyles)&lt;br /&gt;
&lt;br /&gt;
== Menu Config ==&lt;br /&gt;
&lt;br /&gt;
When adding menu items can add links to create, update, list, delete objects, user chooses the service then from that service&#039;s list of objects and what action is being performed. For update/delete perhaps links to a standard page that asks for the identifier before presenting the page.&lt;br /&gt;
&lt;br /&gt;
== Tabled Data ==&lt;br /&gt;
&lt;br /&gt;
When viewing tabled data the frontend pulls the tableId&#039;s config from backend, then when requesting the data also requests the serviceTag &amp;gt; objectType schema for use when displaying the data.&lt;br /&gt;
&lt;br /&gt;
== Code Standardization ==&lt;br /&gt;
&lt;br /&gt;
Code such as middleware validation schema and saving data to databases can be standardized.&lt;br /&gt;
&lt;br /&gt;
== Code Generation ==&lt;br /&gt;
&lt;br /&gt;
Endpoints per object for actions such as Create/Delete/Update can be automatically generated from objectSchema.&lt;br /&gt;
&lt;br /&gt;
=== Code Generation Structure ===&lt;br /&gt;
&lt;br /&gt;
* npm for generic code generation, can be used in any project, includes functions for generating Source files from templates and developer files&lt;br /&gt;
* npm for per project specific files, eg templates for the project (Create/Update/.. code)&lt;br /&gt;
* Empty Service Template has GenerateCode.js script file in root dir that is run to generate code, it invokes a generation function from generic npm with param that points to per project npm&#039;s templates&lt;br /&gt;
* generated Source retains hook tags (and any developer added code), so if developer wants to update developer&#039;s file with updated template code they can generate code and simply copy generated Source to src folder&lt;br /&gt;
&lt;br /&gt;
= Graph Server Config =&lt;br /&gt;
&lt;br /&gt;
* S3 has a list of graphServerTag&#039;s linking to the GraphHandler serviceTag responsible for the graph&lt;br /&gt;
* multiple graphServerTags can point to one GraphHandler, combining graphs into one server&lt;br /&gt;
* when creating each GraphHandler&#039;s graph schemas, for each field split out the fields into each GraphHandler using the graphServerTag, if multiple graphServerTags for a field point to the same GraphHandler combine the fields to create GraphHandler&#039;s graph schema&lt;br /&gt;
* every GraphHandler an object is saved into will require it&#039;s identifiers&lt;br /&gt;
* when eg updating fields for an object separate the fields per GraphHandler before sending the request to update each graph&lt;br /&gt;
&lt;br /&gt;
= Extended Object Types =&lt;br /&gt;
&lt;br /&gt;
* Allows for one graph node to have multiple labels&lt;br /&gt;
* graph schema is created for both the core object and the extended object&lt;br /&gt;
* eg Media Manager&#039;s has a node schema for &amp;quot;media&amp;quot; object type, and Image service has a node schema for &amp;quot;image&amp;quot; object type&lt;br /&gt;
* the extended object builds it&#039;s schema by combining core + extended settings&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - Per Service Schemas|Per Service Schemas]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_SupplyVideoFeed_Location&amp;diff=4602</id>
		<title>Service - SupplyVideoFeed Location</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_SupplyVideoFeed_Location&amp;diff=4602"/>
		<updated>2026-08-18T02:48:51Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Links Location objects to VideoFeed structures.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== supVidLocationLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;supVidLocationLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;SupplyVideoFeedLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;supVidLinkBySupplyNetwork&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;supVidLocationLink&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
       &amp;quot;myGraph&amp;quot;: {&lt;br /&gt;
            &amp;quot;storageType&amp;quot;: &amp;quot;graph&amp;quot;,&lt;br /&gt;
            &amp;quot;graphServerTag&amp;quot;: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// supplyNetworkId&lt;br /&gt;
		// operationId&lt;br /&gt;
		// supplyLocationId&lt;br /&gt;
		// feedGroupId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;supplyNetworkId&amp;quot;, &amp;quot;operationId&amp;quot;, &amp;quot;supplyLocationId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;supVidLinkSupLocId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;feedGroupId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* one supplyLocationId can link to multiple feedGroupIds&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= flowSchemas =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - SupplyVideoFeed Location| SupplyVideoFeed Location]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| SupplyVideoFeed Location]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_SupplyVideoFeed_Stage_Adjustment&amp;diff=4601</id>
		<title>Service - SupplyVideoFeed Stage Adjustment</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_SupplyVideoFeed_Stage_Adjustment&amp;diff=4601"/>
		<updated>2026-08-18T02:46:18Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: Created page with &amp;quot; = Overview =  Links Stage Adjust objects to VideoFeed structures.  = Repository =  ...  = Object Schemas = ; Additional Information: Per Service Schemas  == supVidStageAdjustLink ==  &amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt; { 	objectType: &amp;quot;supVidStageAdjustLink&amp;quot;,     generatedBy: &amp;quot;userGenerated&amp;quot;, 	canDelete: false, 	belongTo: { 		serviceTag: &amp;quot;SupplyVideoFeedLink&amp;quot;, 		objectType: &amp;quot;supVidLinkBySupplyNetwork&amp;quot; 	}, 	addOnDataStructure: [], 	storageResources: { 		&amp;quot;dynamo&amp;quot;: {...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Links Stage Adjust objects to VideoFeed structures.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== supVidStageAdjustLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;supVidStageAdjustLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;SupplyVideoFeedLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;supVidLinkBySupplyNetwork&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;supVidStageAdjustLink&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
       &amp;quot;myGraph&amp;quot;: {&lt;br /&gt;
            &amp;quot;storageType&amp;quot;: &amp;quot;graph&amp;quot;,&lt;br /&gt;
            &amp;quot;graphServerTag&amp;quot;: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// supplyNetworkId&lt;br /&gt;
		// operationId&lt;br /&gt;
		// stageAdjustmentId&lt;br /&gt;
		// videoFeedId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;supplyNetworkId&amp;quot;, &amp;quot;operationId&amp;quot;, &amp;quot;stageAdjustmentId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;supVidLinkStagAdjId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;videoFeedId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* one transformConfigId can link to multiple videoFeedIds&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= flowSchemas =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - SupplyVideoFeed Stage Adjustment| SupplyVideoFeed Stage Adjustment]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| SupplyVideoFeed Stage Adjustment]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_SupplyVideoFeed_Transform_Units&amp;diff=4600</id>
		<title>Service - SupplyVideoFeed Transform Units</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_SupplyVideoFeed_Transform_Units&amp;diff=4600"/>
		<updated>2026-08-18T02:44:46Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: Created page with &amp;quot;= Overview =  Links Transform Unit objects to VideoFeed structures.  = Repository =  ...  = Object Schemas = ; Additional Information: Per Service Schemas  == supVidTransformUnitLink ==  &amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt; { 	objectType: &amp;quot;supVidTransformUnitLink&amp;quot;,     generatedBy: &amp;quot;userGenerated&amp;quot;, 	canDelete: false, 	belongTo: { 		serviceTag: &amp;quot;SupplyVideoFeedLink&amp;quot;, 		objectType: &amp;quot;supVidLinkBySupplyNetwork&amp;quot; 	}, 	addOnDataStructure: [], 	storageResources: { 		&amp;quot;dynamo&amp;quot;:...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Links Transform Unit objects to VideoFeed structures.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== supVidTransformUnitLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;supVidTransformUnitLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;SupplyVideoFeedLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;supVidLinkBySupplyNetwork&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;supVidTransformUnitLink&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
       &amp;quot;myGraph&amp;quot;: {&lt;br /&gt;
            &amp;quot;storageType&amp;quot;: &amp;quot;graph&amp;quot;,&lt;br /&gt;
            &amp;quot;graphServerTag&amp;quot;: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// supplyNetworkId&lt;br /&gt;
		// operationId&lt;br /&gt;
		// transformConfigId&lt;br /&gt;
		// videoFeedId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;supplyNetworkId&amp;quot;, &amp;quot;operationId&amp;quot;, &amp;quot;transformConfigId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;supVidLinkTranConfId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;videoFeedId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* one transformConfigId can link to multiple videoFeedIds&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= flowSchemas =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - SupplyVideoFeed Transform Units| SupplyVideoFeed Transform Units]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| SupplyVideoFeed Transform Units]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_Stack_-_SupplyVideoFeed_Markers&amp;diff=4599</id>
		<title>Service Stack - SupplyVideoFeed Markers</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_Stack_-_SupplyVideoFeed_Markers&amp;diff=4599"/>
		<updated>2026-08-18T02:41:30Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Services that manage markers (transformUnits/StageAdjust) links to videoFeeds.&lt;br /&gt;
&lt;br /&gt;
= Services =&lt;br /&gt;
&lt;br /&gt;
== Markers ==&lt;br /&gt;
&lt;br /&gt;
* [[Service - SupplyVideoFeed Transform Units]]&lt;br /&gt;
* [[Service - SupplyVideoFeed Stage Adjustment]]&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - Service Stack - SupplyVideoFeed Markers| Service Stack - SupplyVideoFeed Markers]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_Stack_-_SupplyVideoFeed_Markers&amp;diff=4598</id>
		<title>Service Stack - SupplyVideoFeed Markers</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_Stack_-_SupplyVideoFeed_Markers&amp;diff=4598"/>
		<updated>2026-08-18T02:41:08Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: Created page with &amp;quot;= Overview =  Services that manage markers (transformUnits/StageAdjust) links to videoFeeds.  = Services =  == Markers ==  * Service - SupplyVideoFeed Transform Units  = Working documents =   Service Stack - SupplyVideoFeed Markers&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Services that manage markers (transformUnits/StageAdjust) links to videoFeeds.&lt;br /&gt;
&lt;br /&gt;
= Services =&lt;br /&gt;
&lt;br /&gt;
== Markers ==&lt;br /&gt;
&lt;br /&gt;
* [[Service - SupplyVideoFeed Transform Units]]&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - Service Stack - SupplyVideoFeed Markers| Service Stack - SupplyVideoFeed Markers]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_SupplyVideoFeed_Location&amp;diff=4597</id>
		<title>Service - SupplyVideoFeed Location</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_SupplyVideoFeed_Location&amp;diff=4597"/>
		<updated>2026-08-18T02:39:10Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: Created page with &amp;quot;= Overview =  Links Location objects to VideoFeed structures.  = Repository =  ...  = Object Schemas = ; Additional Information: Per Service Schemas  == supVidLocationLink ==  &amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt; { 	objectType: &amp;quot;supVidLocationLink&amp;quot;,     generatedBy: &amp;quot;userGenerated&amp;quot;, 	canDelete: false, 	belongTo: { 		serviceTag: &amp;quot;SupplyVideoFeedLink&amp;quot;, 		objectType: &amp;quot;supVidLinkBySupplyNetwork&amp;quot; 	}, 	addOnDataStructure: [], 	storageResources: { 		&amp;quot;dynamo&amp;quot;: { 			&amp;quot;storageTy...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Links Location objects to VideoFeed structures.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== supVidLocationLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;supVidLocationLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;SupplyVideoFeedLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;supVidLinkBySupplyNetwork&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;supVidLocationLink&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
       &amp;quot;myGraph&amp;quot;: {&lt;br /&gt;
            &amp;quot;storageType&amp;quot;: &amp;quot;graph&amp;quot;,&lt;br /&gt;
            &amp;quot;graphServerTag&amp;quot;: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// supplyNetworkId&lt;br /&gt;
		// operationId&lt;br /&gt;
		// supplyLocationId&lt;br /&gt;
		// feedGroupId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;supplyNetworkId&amp;quot;, &amp;quot;operationId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;supVidLinkId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;supplyLocationId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= flowSchemas =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - SupplyVideoFeed Location| SupplyVideoFeed Location]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| SupplyVideoFeed Location]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_SupplyVideoFeed_Link&amp;diff=4596</id>
		<title>Service - SupplyVideoFeed Link</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_SupplyVideoFeed_Link&amp;diff=4596"/>
		<updated>2026-08-18T02:36:35Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Configures the link between a Supply Network in Izara Supply and an Operation in Izara VideoFeed.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== supVidLinkBySupplyNetwork ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;supVidLinkBySupplyNetwork&amp;quot;,&lt;br /&gt;
	generatedBy: &amp;quot;systemGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	addOnDataStructure: [&lt;br /&gt;
		{&lt;br /&gt;
			type:&amp;quot;rbac&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
        &amp;quot;myGraph&amp;quot;:{&lt;br /&gt;
            &amp;quot;storageType&amp;quot;: &amp;quot;graph&amp;quot;,&lt;br /&gt;
            &amp;quot;graphServerTag&amp;quot;: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccLinkByBusiness&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// supplyNetworkId&lt;br /&gt;
		// operationId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			// supplyNetworkId: [supplyNetworkId,operationId]&lt;br /&gt;
		}&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== comAccLinkByOperation ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccLinkByOperation&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccLinkByOperation&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// operationId&lt;br /&gt;
		// supplyNetworkId		&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			// operationId&lt;br /&gt;
		}&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - SupplyVideoFeed Link| SupplyVideoFeed Link]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| SupplyVideoFeed Link]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_Stack_-_SupplyVideoFeed_Location&amp;diff=4595</id>
		<title>Service Stack - SupplyVideoFeed Location</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_Stack_-_SupplyVideoFeed_Location&amp;diff=4595"/>
		<updated>2026-08-18T02:24:30Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: Created page with &amp;quot;= Overview =  Services that manage location links to videoFeeds.  = Services =  == Locations ==  * Service - SupplyVideoFeed Location  = Working documents =   Service Stack - SupplyVideoFeed Location&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Services that manage location links to videoFeeds.&lt;br /&gt;
&lt;br /&gt;
= Services =&lt;br /&gt;
&lt;br /&gt;
== Locations ==&lt;br /&gt;
&lt;br /&gt;
* [[Service - SupplyVideoFeed Location]]&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - Service Stack - SupplyVideoFeed Location| Service Stack - SupplyVideoFeed Location]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Development_-_Izara_Supply_to_VideoFeed&amp;diff=4594</id>
		<title>Development - Izara Supply to VideoFeed</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Development_-_Izara_Supply_to_VideoFeed&amp;diff=4594"/>
		<updated>2026-08-18T02:23:30Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Backend =&lt;br /&gt;
&lt;br /&gt;
== Backend services ==&lt;br /&gt;
&lt;br /&gt;
* [[Service Stack - SupplyVideoFeed Link]]&lt;br /&gt;
&lt;br /&gt;
* [[Service Stack - SupplyVideoFeed Location]]&lt;br /&gt;
* [[Service Stack - SupplyVideoFeed Markers]]&lt;br /&gt;
&lt;br /&gt;
== NPM modules ==&lt;br /&gt;
&lt;br /&gt;
* ..&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Development_-_Izara_Supply_to_VideoFeed&amp;diff=4593</id>
		<title>Development - Izara Supply to VideoFeed</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Development_-_Izara_Supply_to_VideoFeed&amp;diff=4593"/>
		<updated>2026-08-18T02:21:57Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Backend =&lt;br /&gt;
&lt;br /&gt;
== Backend services ==&lt;br /&gt;
&lt;br /&gt;
* [[Service Stack - SupplyVideoFeed Link]]&lt;br /&gt;
&lt;br /&gt;
* [[Service Stack - SupplyVideoFeed Location]]&lt;br /&gt;
* [[Service Stack - SupplyVideoFeed Transform Units]]&lt;br /&gt;
* [[Service Stack - SupplyVideoFeed Stage_Adjustment]]&lt;br /&gt;
&lt;br /&gt;
== NPM modules ==&lt;br /&gt;
&lt;br /&gt;
* ..&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=2026-08-18_Backend_User_and_RBAC_Data&amp;diff=4592</id>
		<title>2026-08-18 Backend User and RBAC Data</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=2026-08-18_Backend_User_and_RBAC_Data&amp;diff=4592"/>
		<updated>2026-08-18T01:38:41Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: Sven the Barbarian moved page 2026-08-18 Backend User and RBAC Data to 2026-08-18 - Backend User and RBAC Data&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[2026-08-18 - Backend User and RBAC Data]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=2026-08-18_-_Backend_User_and_RBAC_Data&amp;diff=4591</id>
		<title>2026-08-18 - Backend User and RBAC Data</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=2026-08-18_-_Backend_User_and_RBAC_Data&amp;diff=4591"/>
		<updated>2026-08-18T01:38:41Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: Sven the Barbarian moved page 2026-08-18 Backend User and RBAC Data to 2026-08-18 - Backend User and RBAC Data&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[User Data Handling]]&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
How to pass around userId and targetIdentifiers for permissions/account limits/resource use, and for creating automatic data such as createdBy and belongTo relationships in graph database.&lt;br /&gt;
&lt;br /&gt;
= updated idea =&lt;br /&gt;
&lt;br /&gt;
* baseUserId can stay in iz_Context because it should not change during processing&lt;br /&gt;
* maybe change baseUserId to submittedByUserId to be more clear, but see baseUserId reason for name below&lt;br /&gt;
* however consider if future flows will handle many submittedByUserIds, eg automated tasks that handle many submitted tasks, if that is common it might be better to allow generated code to pass the submittedByUserId as a flow input param&lt;br /&gt;
* targetId change to identifer object {fieldname: fieldValue} named targetIdentifiers&lt;br /&gt;
* generated code can where possible add this automatically when initializing flows, and can check received valid identifiers according to flowSchema&lt;br /&gt;
&lt;br /&gt;
== RBAC ==&lt;br /&gt;
&lt;br /&gt;
* RBAC actions are basically list of flows, with target coming from the flows base objType (using either that objTypes rbac additional addOnDataStructure or if that objType has belongTo following that)&lt;br /&gt;
* generated code automatically validates submittedByUserId and targetIdentifiers, sends to permissionHandler/RBAC&lt;br /&gt;
&lt;br /&gt;
== Account Limits ==&lt;br /&gt;
&lt;br /&gt;
* standardize checking of accountLimits so generated code can check per flow&lt;br /&gt;
* probably allow for additional developer added accountLimits to be checked anywhere in code&lt;br /&gt;
&lt;br /&gt;
== Resource use ==&lt;br /&gt;
&lt;br /&gt;
* ? connected to target user if belongTo = user, but if not connect to submittedByUserId&lt;br /&gt;
&lt;br /&gt;
= old attempts =&lt;br /&gt;
&lt;br /&gt;
== First design ==&lt;br /&gt;
&lt;br /&gt;
* url paths sent from frontend had the service/resource/action and targetId in the url path, extracted by API Gateway&lt;br /&gt;
* submittedBy userId was extracted/confirmed from the Cognito token/sub&lt;br /&gt;
* RBAC was handled by a Lambda authorizer that used the above extracted variables&lt;br /&gt;
* submittedBy and targetIds were saved into iz_Context and automatically passed to proceeding logic&lt;br /&gt;
&lt;br /&gt;
=== limitations ===&lt;br /&gt;
&lt;br /&gt;
* requests must pass API Gateway to extract values&lt;br /&gt;
* Lambda authorizers can have limitations that complicated processing&lt;br /&gt;
&lt;br /&gt;
== Second design ==&lt;br /&gt;
&lt;br /&gt;
* using schemas and generated code&lt;br /&gt;
* RBAC moved out of authorizers and implemented inside handler lambdas&lt;br /&gt;
* still in iz_Context&lt;br /&gt;
* variable name is baseUserId, because accountLimits/resourceUse are connected to target userId if belong to User, but baseUserId if not&lt;br /&gt;
&lt;br /&gt;
=== limitations ===&lt;br /&gt;
&lt;br /&gt;
* targetId is a concat string for composite identifiers, want all handling of identifiers to be an object, only change to concat when required (eg save to database that requires single string)&lt;br /&gt;
* some flows might need to adjust target according to steps, eg importBatch submission belongTo user but each pending element may have different belongTo objType/instances, this complicates targetId management in iz_Context&lt;br /&gt;
&lt;br /&gt;
[[Category:Working_documents - User Data Handling| 2026-08-18]]&lt;br /&gt;
[[Category:Working documents| 2026-08-18]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=User_Data_Handling&amp;diff=4590</id>
		<title>User Data Handling</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=User_Data_Handling&amp;diff=4590"/>
		<updated>2026-08-18T01:18:16Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
submittedByUserId, targetUserId and targetIdentifiers for permissions/account limits/resource use, and for creating automatic data such as createdBy and belongTo relationships in graph database.&lt;br /&gt;
&lt;br /&gt;
= Structure =&lt;br /&gt;
&lt;br /&gt;
* baseUserId can stay in iz_Context because it should not change during processing&lt;br /&gt;
* maybe change baseUserId to submittedByUserId to be more clear, but see baseUserId reason for name below&lt;br /&gt;
* however consider if future flows will handle many submittedByUserIds, eg automated tasks that handle many submitted tasks, if that is common it might be better to allow generated code to pass the submittedByUserId as a flow input param&lt;br /&gt;
* targetId change to identifer object {fieldname: fieldValue} named targetIdentifiers&lt;br /&gt;
* generated code can where possible add this automatically when initializing flows, and can check received valid identifiers according to flowSchema&lt;br /&gt;
&lt;br /&gt;
== Graph ==&lt;br /&gt;
&lt;br /&gt;
* automatically adds createdBy/versionData updatedBy relationships for objects created/updated by user&lt;br /&gt;
* automatically adds createdBy/updatedBy for relationships created/updated by user, relationshipSchema specifies which node to connect this history to&lt;br /&gt;
* automatically adds belongTo relationship when creating a node connecting to targetIdentifiers instance of belongTo objType&lt;br /&gt;
* relationshipSchema sets which side is belongTo node, that node must have belongTo relationship (ie that node must have belongTo or rbac addOnDataStructure)&lt;br /&gt;
&lt;br /&gt;
== RBAC ==&lt;br /&gt;
&lt;br /&gt;
* RBAC actions are basically list of flows, with target coming from the flows base objType (using either that objTypes rbac addOnDataStructure or if that objType has belongTo following that)&lt;br /&gt;
* generated code automatically validates submittedByUserId and targetIdentifiers, sends to permissionHandler/RBAC&lt;br /&gt;
&lt;br /&gt;
== Account Limits ==&lt;br /&gt;
&lt;br /&gt;
* standardize checking of accountLimits so generated code can check per flow&lt;br /&gt;
* probably allow for additional developer added accountLimits to be checked anywhere in code&lt;br /&gt;
&lt;br /&gt;
== Resource use ==&lt;br /&gt;
&lt;br /&gt;
* ? connected to target user if belongTo = user, but if not connect to submittedByUserId&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - User Data Handling| User Data Handling]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=User_Data_Handling&amp;diff=4589</id>
		<title>User Data Handling</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=User_Data_Handling&amp;diff=4589"/>
		<updated>2026-08-18T01:08:23Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: Created page with &amp;quot;= Overview =  submittedByUserId, targetUserId and targetIdentifiers for permissions/account limits/resource use, and for creating automatic data such as createdBy and belongTo relationships in graph database.  = Structure =  * baseUserId can stay in iz_Context because it should not change during processing * maybe change baseUserId to submittedByUserId to be more clear, but see baseUserId reason for name below * however consider if future flows will handle many submitted...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
submittedByUserId, targetUserId and targetIdentifiers for permissions/account limits/resource use, and for creating automatic data such as createdBy and belongTo relationships in graph database.&lt;br /&gt;
&lt;br /&gt;
= Structure =&lt;br /&gt;
&lt;br /&gt;
* baseUserId can stay in iz_Context because it should not change during processing&lt;br /&gt;
* maybe change baseUserId to submittedByUserId to be more clear, but see baseUserId reason for name below&lt;br /&gt;
* however consider if future flows will handle many submittedByUserIds, eg automated tasks that handle many submitted tasks, if that is common it might be better to allow generated code to pass the submittedByUserId as a flow input param&lt;br /&gt;
* targetId change to identifer object {fieldname: fieldValue} named targetIdentifiers&lt;br /&gt;
* generated code can where possible add this automatically when initializing flows, and can check received valid identifiers according to flowSchema&lt;br /&gt;
&lt;br /&gt;
== RBAC ==&lt;br /&gt;
&lt;br /&gt;
* RBAC actions are basically list of flows, with target coming from the flows base objType (using either that objTypes rbac additional addOnDataStructure or if that objType has belongTo following that)&lt;br /&gt;
* generated code automatically validates submittedByUserId and targetIdentifiers, sends to permissionHandler/RBAC&lt;br /&gt;
&lt;br /&gt;
== Account Limits ==&lt;br /&gt;
&lt;br /&gt;
* standardize checking of accountLimits so generated code can check per flow&lt;br /&gt;
* probably allow for additional developer added accountLimits to be checked anywhere in code&lt;br /&gt;
&lt;br /&gt;
== Resource use ==&lt;br /&gt;
&lt;br /&gt;
* ? connected to target user if belongTo = user, but if not connect to submittedByUserId&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - User Data Handling| User Data Handling]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=2026-08-18_-_Backend_User_and_RBAC_Data&amp;diff=4588</id>
		<title>2026-08-18 - Backend User and RBAC Data</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=2026-08-18_-_Backend_User_and_RBAC_Data&amp;diff=4588"/>
		<updated>2026-08-18T01:07:12Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: Created page with &amp;quot;User Data Handling  = Overview =  How to pass around userId and targetIdentifiers for permissions/account limits/resource use, and for creating automatic data such as createdBy and belongTo relationships in graph database.  = updated idea =  * baseUserId can stay in iz_Context because it should not change during processing * maybe change baseUserId to submittedByUserId to be more clear, but see baseUserId reason for name below * however consider if future flows will...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[User Data Handling]]&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
How to pass around userId and targetIdentifiers for permissions/account limits/resource use, and for creating automatic data such as createdBy and belongTo relationships in graph database.&lt;br /&gt;
&lt;br /&gt;
= updated idea =&lt;br /&gt;
&lt;br /&gt;
* baseUserId can stay in iz_Context because it should not change during processing&lt;br /&gt;
* maybe change baseUserId to submittedByUserId to be more clear, but see baseUserId reason for name below&lt;br /&gt;
* however consider if future flows will handle many submittedByUserIds, eg automated tasks that handle many submitted tasks, if that is common it might be better to allow generated code to pass the submittedByUserId as a flow input param&lt;br /&gt;
* targetId change to identifer object {fieldname: fieldValue} named targetIdentifiers&lt;br /&gt;
* generated code can where possible add this automatically when initializing flows, and can check received valid identifiers according to flowSchema&lt;br /&gt;
&lt;br /&gt;
== RBAC ==&lt;br /&gt;
&lt;br /&gt;
* RBAC actions are basically list of flows, with target coming from the flows base objType (using either that objTypes rbac additional addOnDataStructure or if that objType has belongTo following that)&lt;br /&gt;
* generated code automatically validates submittedByUserId and targetIdentifiers, sends to permissionHandler/RBAC&lt;br /&gt;
&lt;br /&gt;
== Account Limits ==&lt;br /&gt;
&lt;br /&gt;
* standardize checking of accountLimits so generated code can check per flow&lt;br /&gt;
* probably allow for additional developer added accountLimits to be checked anywhere in code&lt;br /&gt;
&lt;br /&gt;
== Resource use ==&lt;br /&gt;
&lt;br /&gt;
* ? connected to target user if belongTo = user, but if not connect to submittedByUserId&lt;br /&gt;
&lt;br /&gt;
= old attempts =&lt;br /&gt;
&lt;br /&gt;
== First design ==&lt;br /&gt;
&lt;br /&gt;
* url paths sent from frontend had the service/resource/action and targetId in the url path, extracted by API Gateway&lt;br /&gt;
* submittedBy userId was extracted/confirmed from the Cognito token/sub&lt;br /&gt;
* RBAC was handled by a Lambda authorizer that used the above extracted variables&lt;br /&gt;
* submittedBy and targetIds were saved into iz_Context and automatically passed to proceeding logic&lt;br /&gt;
&lt;br /&gt;
=== limitations ===&lt;br /&gt;
&lt;br /&gt;
* requests must pass API Gateway to extract values&lt;br /&gt;
* Lambda authorizers can have limitations that complicated processing&lt;br /&gt;
&lt;br /&gt;
== Second design ==&lt;br /&gt;
&lt;br /&gt;
* using schemas and generated code&lt;br /&gt;
* RBAC moved out of authorizers and implemented inside handler lambdas&lt;br /&gt;
* still in iz_Context&lt;br /&gt;
* variable name is baseUserId, because accountLimits/resourceUse are connected to target userId if belong to User, but baseUserId if not&lt;br /&gt;
&lt;br /&gt;
=== limitations ===&lt;br /&gt;
&lt;br /&gt;
* targetId is a concat string for composite identifiers, want all handling of identifiers to be an object, only change to concat when required (eg save to database that requires single string)&lt;br /&gt;
* some flows might need to adjust target according to steps, eg importBatch submission belongTo user but each pending element may have different belongTo objType/instances, this complicates targetId management in iz_Context&lt;br /&gt;
&lt;br /&gt;
[[Category:Working_documents - User Data Handling| 2026-08-18]]&lt;br /&gt;
[[Category:Working documents| 2026-08-18]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Per_Service_Schemas&amp;diff=4587</id>
		<title>Per Service Schemas</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Per_Service_Schemas&amp;diff=4587"/>
		<updated>2026-08-18T00:59:39Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: /* Not extendObjType */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Each service manages a schema of object/resources that it is responsible for, this schema is available to other services and frontends. The schema includes a list of fields available for each object.&lt;br /&gt;
&lt;br /&gt;
= File Structure =&lt;br /&gt;
&lt;br /&gt;
* see [[Repository structure#schemas|Repository structure]]&lt;br /&gt;
&lt;br /&gt;
= ObjectSchema | ObjectFieldSchema.js =&lt;br /&gt;
&lt;br /&gt;
== Not extendObjType ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;xx&amp;quot;,&lt;br /&gt;
	shortNameObjectType:&amp;quot;x&amp;quot;, // optional, use when generate code create lambda role with long name&lt;br /&gt;
	canDelete: false, // whether any fields can be deleted // default = false&lt;br /&gt;
	belongTo: { &lt;br /&gt;
		serviceTag:&amp;quot;iii&amp;quot;,&lt;br /&gt;
		objectType:&amp;quot;jjj&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
    // how is the object created&lt;br /&gt;
    // userGenerated there will be generated endpoints for api or sqs (used in importBatchMain) to create object&lt;br /&gt;
    // systemGenerated must be created by flow/s&lt;br /&gt;
    // searchResultGenerated see separate notes below&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot; || &amp;quot;systemGenerated&amp;quot; || &amp;quot;searchResultGenerated&amp;quot; // required&lt;br /&gt;
    searchResultGeneratedFlowType: {}, // for generatedBy = searchResultGenerated&lt;br /&gt;
	addOnDataStructure: [ // optional, add for additional setting to objectType&lt;br /&gt;
		{&lt;br /&gt;
			// all fields that a user can edit must be in versionedData, and all fields in versionedData must be editable by user&lt;br /&gt;
			type:&amp;quot;versionedData&amp;quot;,&lt;br /&gt;
			versionedDataLabel: &amp;quot;xx&amp;quot;, // versionedData label name&lt;br /&gt;
			storageResourceTag : &amp;quot;xx&amp;quot;, // ref to storegeResourceTag&lt;br /&gt;
			fieldNames: { // fieldName in versionedData cannot have in in main objectSchema.fieldNames&lt;br /&gt;
				&amp;quot;aaa&amp;quot;:{ // fieldName&lt;br /&gt;
					type: &amp;quot;xx&amp;quot;, // string|integer|number|timestamp|currency|currencyValue|float|special|object|boolean|arrayMixed|arrayNumeric|arrayString&lt;br /&gt;
					requiredOnCreate: false, // default = false&lt;br /&gt;
					optionalOnCreate: false, // default = false,&lt;br /&gt;
					validation: {&lt;br /&gt;
                      itemValidation:{} // for validate item in array&lt;br /&gt;
                    },&lt;br /&gt;
                    // probably impossible to have fromObjType, because data can be changed by user here&lt;br /&gt;
					fromObjType:{&lt;br /&gt;
						serviceTag: &amp;quot;xxx&amp;quot;, &lt;br /&gt;
						objectType: &amp;quot;xxx&amp;quot; &lt;br /&gt;
					},&lt;br /&gt;
				},&lt;br /&gt;
				// ...&lt;br /&gt;
			}&lt;br /&gt;
        },&lt;br /&gt;
        { // can have multiple addOn of type attributeTree&lt;br /&gt;
          type:&amp;quot;attributeTree&amp;quot;,           &lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;translation&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;propertyValue&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;mediaLink&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;rbac&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
		// ...&lt;br /&gt;
	],&lt;br /&gt;
	plugInTags: [&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;], // plugIns that can be connected to this objType&lt;br /&gt;
	storageResources:{&lt;br /&gt;
		&amp;quot;xxx&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // graph			&lt;br /&gt;
			graphServerTag: &amp;quot;xx&amp;quot;, // setting for storageType graph&lt;br /&gt;
            additionalGraphIndexes:[[&#039;fieldName1&#039;, &#039;fieldName2&#039;, ...], [...]]  // will make graph index with specific fieldName &lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;zzz&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // dynamoDB&lt;br /&gt;
			// setting for storageType dynamoDB&lt;br /&gt;
			tableName: &amp;quot;xx&amp;quot;,&lt;br /&gt;
			groupByPartitionKeyField: &amp;quot;xx&amp;quot;, // use groupByPartitionKeyField as partition key and not have sort key in dynamoDB, if have multiple identifiers will concat it. And use it as partitionKey.&lt;br /&gt;
            serviceTag:&amp;quot;zz&amp;quot;// default own service.&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	fieldNames: {&lt;br /&gt;
		xxx: { // fieldName&lt;br /&gt;
			type: &amp;quot;xx&amp;quot;,  // string|integer|number|timestamp|currency|currencyValue|float|special|object|boolean|arrayMixed|arrayNumeric|arrayString&lt;br /&gt;
            randomOnCreate: false,   // default = false , can set true in fieldName that part of identifiers and identifiers have single identifierFieldname&lt;br /&gt;
			requiredOnCreate: false, // default = false&lt;br /&gt;
			optionalOnCreate: false, // default = false&lt;br /&gt;
			canUpdate: true, // default = true (only system/flows can edit, no history of changes unless flow manually adds)&lt;br /&gt;
			validation: {&lt;br /&gt;
			  itemValidation:{}  // for validate item in array&lt;br /&gt;
            }, // maybe ajv syntax&lt;br /&gt;
			storageResourceTags: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // reference to storageResources property&lt;br /&gt;
		    fromObjType:{&lt;br /&gt;
			  serviceTag: &amp;quot;xxx&amp;quot;, &lt;br /&gt;
			  objectType: &amp;quot;xxx&amp;quot; &lt;br /&gt;
			},&lt;br /&gt;
            hashOnCreate: [&amp;quot;xx&amp;quot;, &amp;quot;yy&amp;quot;], // reference to other fieldName, &lt;br /&gt;
            statusField: true, // use for objectSchema inside flowSchema, identify which field is statusField &lt;br /&gt;
&lt;br /&gt;
			// comes from requiredOnCreate relationships&lt;br /&gt;
			fromRequiredOnCreate: { &lt;br /&gt;
				relType: {&lt;br /&gt;
					serviceTag:&amp;quot;aa&amp;quot;,&lt;br /&gt;
					relationshipTag:&amp;quot;bb&amp;quot;&lt;br /&gt;
				},&lt;br /&gt;
				// or&lt;br /&gt;
				belongToObjType: true, // if set to true use the belongTo relationship to belongTo objType&lt;br /&gt;
&lt;br /&gt;
				fieldName:&amp;quot;&amp;quot; // optional default= same field name eg: now default == xxx if not defined(use fieldname of object inside link when create)&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
		// ...&lt;br /&gt;
	},&lt;br /&gt;
    compositeKeyDeliminator: &amp;quot;xx&amp;quot;, // join partitionKey and sortKey&lt;br /&gt;
	identifiers: [&lt;br /&gt;
    // for dynamoDB storageType &lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // composite partition keys in DynamoDB&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		name: &amp;quot;zz&amp;quot;, // name of field in database&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	},&lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // composite partition keys in DynamoDB&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		name: &amp;quot;zz&amp;quot;, // name of field in database&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	},&lt;br /&gt;
   &lt;br /&gt;
    // for graph storageType&lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;identifier&amp;quot;,&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // identifier field in graph or composite partition keys in DynamoDB&lt;br /&gt;
        name: &amp;quot;zzz&amp;quot;              // use when save in dynamoDB partitionKey&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;	&lt;br /&gt;
	},&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== extendObjType ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	// for objects stored in graph this will add another node label&lt;br /&gt;
	objectType: &amp;quot;xx&amp;quot;, // new label to add&lt;br /&gt;
	extendObjType: { // core object that this object extends&lt;br /&gt;
		serviceTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;xxx&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources:{ // these are the storageResources that carry the extended objects settings, &lt;br /&gt;
		// (see above)&lt;br /&gt;
	},&lt;br /&gt;
	fieldNames: {&lt;br /&gt;
		// (see above) &lt;br /&gt;
	},&lt;br /&gt;
	// canDelete/identifiers come from the core object&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== searchResultGenerated ==&lt;br /&gt;
&lt;br /&gt;
* must be created by flow&lt;br /&gt;
* eg: variantProduct&lt;br /&gt;
* not have any storageResources&lt;br /&gt;
* identifiers are automatically searchResultData identifiers&lt;br /&gt;
* a searchResult request for this object will enter the searchResultGeneratedFlowType flow which creates searchResultData that can then be queried/sorted&lt;br /&gt;
* all relationships must be storageType = lambda, eg translate from variantProduct to variant uses a translateId flow to query the variantProduct identifier (searchResultData) to find the variantId in it&#039;s requiredData results&lt;br /&gt;
* searchResultGeneratedFlowType takes over after creating searchResultMain record until processRequiredData&lt;br /&gt;
* if objectSchema defines any fieldnames, then they are found using a flow, maybe as hooks in per service findData&lt;br /&gt;
* when finding direct fieldname, will need to check if requireData already exists, if not enter flow/findData to create&lt;br /&gt;
* no fields can be edited, so can show in forms but no updates performed&lt;br /&gt;
&lt;br /&gt;
= Relationships Schema | ObjectRelationships.js =&lt;br /&gt;
&lt;br /&gt;
* stored in top level schemas folder&lt;br /&gt;
* parent/child determines relationship direction for graph relationships&lt;br /&gt;
* have one service that contains information of each relationship &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// relationship schema in responsible service&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;xxx&amp;quot;: { // relationshipTag - name of relationship type stored in graph&lt;br /&gt;
      generatedBy: &amp;quot;userGenerated&amp;quot; || &amp;quot;systemGenerated&amp;quot; // default=&amp;quot;userGenerated&amp;quot;&lt;br /&gt;
      canChangeToRelTypes: [&lt;br /&gt;
		{&lt;br /&gt;
			relType: { // relType that this relType can change to &lt;br /&gt;
			  serviceTag:&amp;quot;xxx&amp;quot;,&lt;br /&gt;
			  relationshipTag: &amp;quot;yyy&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			changeBy: &amp;quot;user&amp;quot; // &amp;quot;systemNoUserId&amp;quot; | &amp;quot;systemWithUserId&amp;quot; | &amp;quot;user&amp;quot;, default=&amp;quot;user&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
        // another relType&lt;br /&gt;
      ],&lt;br /&gt;
      storageResources:{&lt;br /&gt;
		&amp;quot;xxx&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // dynamoDB | graph | lambda&lt;br /&gt;
		    // if storageType=&amp;quot;dynamoDB&amp;quot;  will not specify tableName in relationship schema&lt;br /&gt;
&lt;br /&gt;
			// setting for storageType graph&lt;br /&gt;
			graphServerTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
            additionalGraphIndexes:[[&#039;fieldName1&#039;, &#039;fieldName2&#039;, ...], [...]],  // will make graph index with specific fieldName &lt;br /&gt;
&lt;br /&gt;
			// setting for storageType lambda&lt;br /&gt;
			serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
			functionName: &amp;quot;xx&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
      },&lt;br /&gt;
      fieldNames: {&lt;br /&gt;
		&amp;quot;xxx&amp;quot;: { // relationship property name&lt;br /&gt;
			type: &amp;quot;string&amp;quot;, // &amp;quot;string&amp;quot; | &amp;quot;number&amp;quot; ...&lt;br /&gt;
			requiredOnCreate: false, // default=false&lt;br /&gt;
			optionalOnCreate: false, // default = false&lt;br /&gt;
			updateBy: &amp;quot;user&amp;quot; // &amp;quot;systemNoUserId&amp;quot; | &amp;quot;systemWithUserId&amp;quot; | &amp;quot;user&amp;quot; | &amp;quot;none&amp;quot;, default=&amp;quot;user&amp;quot;&lt;br /&gt;
			validation: {} // ajv syntax&lt;br /&gt;
		},&lt;br /&gt;
		//...other relationship properties&lt;br /&gt;
      },&lt;br /&gt;
      links: [&lt;br /&gt;
        {&lt;br /&gt;
          storageResourceTags: [&amp;quot;xxx&amp;quot;],   // reference from storageResources property&lt;br /&gt;
          canDelete: false                // default = false, if set true will allow delete relationship between 2 objType&lt;br /&gt;
          from: {&lt;br /&gt;
            objType: {&lt;br /&gt;
              serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
              objectType: &amp;quot;xx&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            requiredOnCreate: true, // if set true will create relationshipTag when create objType data, if both &amp;quot;from&amp;quot; and &amp;quot;to&amp;quot; linkType=&amp;quot;many&amp;quot; should not have requiredOnCreate, exists in &amp;quot;from&amp;quot; or &amp;quot;to&amp;quot; only&lt;br /&gt;
            linkType: &amp;quot;&amp;quot;,   // one | many&lt;br /&gt;
          //   moveBy: &amp;quot;none&amp;quot;, // &amp;quot;systemNoUserId&amp;quot; | &amp;quot;systemWithUserId&amp;quot; | &amp;quot;user&amp;quot; | &amp;quot;none&amp;quot;, default=&amp;quot;none&amp;quot;&lt;br /&gt;
          // belongTo:true&lt;br /&gt;
          },&lt;br /&gt;
          to: {&lt;br /&gt;
            objType: {&lt;br /&gt;
              serviceTag: &amp;quot;yy&amp;quot;,&lt;br /&gt;
              objectType: &amp;quot;yy&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            linkType: &amp;quot;&amp;quot;,   // one | many&lt;br /&gt;
             // moveBy allows the relationship to be moved between 2 instances of the same objType only&lt;br /&gt;
	        moveBy: &amp;quot;none&amp;quot;, // &amp;quot;systemNoUserId&amp;quot; | &amp;quot;systemWithUserId&amp;quot; | &amp;quot;user&amp;quot; | &amp;quot;none&amp;quot;, default=&amp;quot;none&amp;quot;&lt;br /&gt;
            belongTo:true, // false&lt;br /&gt;
          },&lt;br /&gt;
          requestProperties: {&lt;br /&gt;
            // if storageType is Lambda and translateIds/linkPath requires properties set them here (eg sellOffer&amp;gt;orderPrice)&lt;br /&gt;
            tag_deliverTo: {&lt;br /&gt;
              requestPropertyType: &amp;quot;objectIdentifier&amp;quot;,&lt;br /&gt;
              objType: {&lt;br /&gt;
                serviceTag: &amp;quot;Locations&amp;quot;,&lt;br /&gt;
                objectType: &amp;quot;locationNode&amp;quot; // deliversToLocationNode&lt;br /&gt;
              },&lt;br /&gt;
              identifiersFieldName: &amp;quot;locationNodeId&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            // ... other request properties&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        // ...other link&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Reference Relationships Schema | RefObjectRelationships.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// reference to relationshipTag in external service&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    objectType: &amp;quot;zz&amp;quot;,              // objectType in local service&lt;br /&gt;
    relationshipTag: &amp;quot;xxx&amp;quot;,        // name of relationshiptag of objType&lt;br /&gt;
    relationshipServiceTag: &amp;quot;xx&amp;quot;   // point to service tag that contain data of relationshipTag of objType&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Flow Schema | FlowSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  [&lt;br /&gt;
    {&lt;br /&gt;
      flowTag: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
      initiateBy: &amp;quot;user&amp;quot;,         // &amp;quot;user&amp;quot; | &amp;quot;system&amp;quot; -- if receive plugin should be user &lt;br /&gt;
      handleObj: &amp;quot;one&amp;quot;,           // &amp;quot;one&amp;quot; | &amp;quot;multi&amp;quot;&lt;br /&gt;
      statusType: &amp;quot;statusField&amp;quot;,  // &amp;quot;statusField&amp;quot; | &amp;quot;storedCache&amp;quot; | &amp;quot;none&amp;quot; | &amp;quot;triggerCache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      // statusType=&amp;quot;triggerCache&amp;quot; setting &lt;br /&gt;
      triggerType: &amp;quot;storedCache&amp;quot;, // &amp;quot;storedCache&amp;quot; | &amp;quot;switch&amp;quot;&lt;br /&gt;
      triggerFlowTypes: [&lt;br /&gt;
        //... triggerFlowType&lt;br /&gt;
      ],&lt;br /&gt;
&lt;br /&gt;
      // statusType=&amp;quot;statusField&amp;quot; | &amp;quot;triggerCache&amp;quot; | &amp;quot;storedCache&amp;quot; setting:&lt;br /&gt;
      objType: {},&lt;br /&gt;
&lt;br /&gt;
      event: [&amp;quot;ownTopic&amp;quot;],  // &amp;quot;ownTopic&amp;quot; | &amp;quot;extTopic&amp;quot; | &amp;quot;s3&amp;quot; | &amp;quot;eventBridge&amp;quot; | &amp;quot;lambdaSyncInv&amp;quot; | &amp;quot;lambdaSyncApi&amp;quot; | &amp;quot;generatedCode&amp;quot; | &amp;quot;dsq&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      // event=&amp;quot;s3&amp;quot; setting&lt;br /&gt;
      bucketName: &amp;quot;xxx&amp;quot;, // bucket for s3 event&lt;br /&gt;
      createBucket: boolean, // if true will generate new bucket with bucketName if false will point to old bucket that already have &lt;br /&gt;
&lt;br /&gt;
      // event=&amp;quot;eventBridge&amp;quot; setting&lt;br /&gt;
      schedules: [&lt;br /&gt;
        {&lt;br /&gt;
          name: &#039;your-scheduled-rate-event-name&#039;,&lt;br /&gt;
          description: &#039;your scheduled rate event description&#039;,&lt;br /&gt;
          rate: [&amp;quot;rate(1 minute)&amp;quot;,],&lt;br /&gt;
          input: {}&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
&lt;br /&gt;
      // event=&amp;quot;generatedCode&amp;quot; setting&lt;br /&gt;
      generatedCodeConfig: {&lt;br /&gt;
        generatedCodeTag: &amp;quot;create&amp;quot;, // tag for generated code, eg &amp;quot;create&amp;quot; | &amp;quot;update&amp;quot; | &amp;quot;delete&amp;quot;&lt;br /&gt;
        codeHookTag: &amp;quot;xx&amp;quot;, // which codeHook to initiate flow from&lt;br /&gt;
        // maybe validate: invocationType must exist in &amp;quot;event&amp;quot; array, so don&#039;t need to check 2 places when eg creating sns topic&lt;br /&gt;
        invocationType: &amp;quot;ownTopic&amp;quot;, // &amp;quot;ownTopic&amp;quot; | &amp;quot;lambdaSyncInv&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        objType: {}, // which cases in the generated code trigger the flow&lt;br /&gt;
        // .. other settings depending on generated code&lt;br /&gt;
      },&lt;br /&gt;
&lt;br /&gt;
      outputTopic: boolean,&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      flowSteps: {&lt;br /&gt;
        inTag: { // will generate Topic serviceTag_stage_yyy_inTag&lt;br /&gt;
          properties: [], // reference to stepProperties key, the first lambda&#039;s input properties and messageAttributes are the flow&#039;s input properties and messageAttributes&lt;br /&gt;
          messageAttributes: [], // reference to stepProperties key&lt;br /&gt;
          plugInHooks: [&lt;br /&gt;
            {&lt;br /&gt;
              plugInHookTag: &amp;quot;&amp;quot;,&lt;br /&gt;
              objType: {}, // used to query connection dynamo for an object instance in current flow&lt;br /&gt;
            },&lt;br /&gt;
          ],&lt;br /&gt;
          returnValues: {&lt;br /&gt;
            properties: [], // reference to stepProperties key&lt;br /&gt;
            messageAttributes: [], // reference to stepProperties key, only for outputTopic=true&lt;br /&gt;
          },&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
        // another flow steps&lt;br /&gt;
        flowStep1: { // will generate Topic serviceTag_stage_yyy_Flow1&lt;br /&gt;
          properties: [], // reference to stepProperties key&lt;br /&gt;
          messageAttributes: [], // reference to stepProperties key&lt;br /&gt;
          event: [&amp;quot;ownTopic&amp;quot;],  // &amp;quot;ownTopic&amp;quot; | &amp;quot;extTopic&amp;quot; | &amp;quot;s3&amp;quot; | &amp;quot;eventBridge&amp;quot; | &amp;quot;lambdaSyncInv&amp;quot; | &amp;quot;lambdaSyncApi&amp;quot; | &amp;quot;generatedCode&amp;quot; | &amp;quot;dsq&amp;quot;&lt;br /&gt;
          // handle splitting logic into awaitingStep/awaitingMultipleSteps&lt;br /&gt;
          // handle splitting logic into paginated lambda&lt;br /&gt;
&lt;br /&gt;
          previousSteps: [&lt;br /&gt;
            {&lt;br /&gt;
              sourceType:&amp;quot;ownTopic&amp;quot;, // if from own flow&lt;br /&gt;
              stepName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
              sourceType: &amp;quot;extTopic&amp;quot;, // triggered by output from external service&lt;br /&gt;
              serviceTag: &amp;quot;InventoryService&amp;quot;,&lt;br /&gt;
              topic: &amp;quot;ReserveStock_In&amp;quot;,&lt;br /&gt;
              fromStepNames: [&amp;quot;xx&amp;quot;] // which step in this flow sent request to external flow, used to find awaitingStep prefix&lt;br /&gt;
            }            &lt;br /&gt;
          ],&lt;br /&gt;
          nextSteps: [&lt;br /&gt;
            {&lt;br /&gt;
              targetType:&amp;quot;ownTopic&amp;quot;, // if from own flow&lt;br /&gt;
              stepName: &amp;quot;yyy&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
              targetType: &amp;quot;extTopic&amp;quot;,&lt;br /&gt;
              serviceTag: &amp;quot;InventoryService&amp;quot;,&lt;br /&gt;
              topic: &amp;quot;ReserveStock_In&amp;quot;,&lt;br /&gt;
              toStepNames: [&amp;quot;xx&amp;quot;] // which step in this flow sent request to external flow, used to find awaitingStep prefix&lt;br /&gt;
            }&lt;br /&gt;
          ],&lt;br /&gt;
&lt;br /&gt;
          plugInHooks: [&lt;br /&gt;
            {&lt;br /&gt;
              plugInHookTag: &amp;quot;&amp;quot;,&lt;br /&gt;
              objType: {}, // used to query connection dynamo for an object instance in current flow&lt;br /&gt;
            },&lt;br /&gt;
          ],&lt;br /&gt;
          returnValues: { // the last lambda function returnValues are the flow&#039;s returnValues&lt;br /&gt;
            properties: [], // reference to stepProperties key&lt;br /&gt;
            messageAttributes: [], // reference to stepProperties key, only for outputTopic=true&lt;br /&gt;
          },&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
      },&lt;br /&gt;
&lt;br /&gt;
      stepProperties: { // normalized all stepProperties&lt;br /&gt;
        &amp;quot;uuid&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          type: &amp;quot;object&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          childProperties: [&amp;quot;uuid2&amp;quot;, &amp;quot;uuid3&amp;quot;]&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid2&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid3&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid4&amp;quot;: {&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          objectField: {&lt;br /&gt;
            objType: {},&lt;br /&gt;
            fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          overwritePropertyName: &amp;quot;xx&amp;quot; // optional, if have objectField and have overwritePropertyName will overwrite fieldName &lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
      stepMessageAttributes: { // normalized all stepMessageAttributes&lt;br /&gt;
        &amp;quot;uuid&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid2&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= System Text Schema | SystemTextSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
	{&lt;br /&gt;
		namespace: &amp;quot;xxx&amp;quot;, // groups files downloaded by frontend&lt;br /&gt;
		systemTextTag: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
	}&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Auto generated systemText and namespaces ==&lt;br /&gt;
&lt;br /&gt;
=== systemNotification names ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;sysNotification_{notificationGrouping}&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{notificationTag}&amp;quot;&lt;br /&gt;
* eg shown on notification settings page&lt;br /&gt;
&lt;br /&gt;
=== objType names ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;objTypes&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{serviceTag}_{objectType}&amp;quot;&lt;br /&gt;
* eg shown on config pages, eg pulldown list of object types&lt;br /&gt;
&lt;br /&gt;
=== objType field name descriptions ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;objType_fielddesc_{serviceTag}_{objectType}&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{fieldname}&amp;quot;&lt;br /&gt;
* eg shown on config pages, eg info box for each field name&lt;br /&gt;
&lt;br /&gt;
= System Notification Schema | SystemNotificationSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
	{&lt;br /&gt;
		notificationTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
		notificationGrouping: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
		weight: &amp;quot;##&amp;quot;,&lt;br /&gt;
	},&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Generated S3 files =&lt;br /&gt;
&lt;br /&gt;
* generate multiple files for different uses, eg:&lt;br /&gt;
*# list of saved fieldNames for Create&lt;br /&gt;
*# list of saved+calculated for Update/Info pages&lt;br /&gt;
*# graphSchemas&lt;br /&gt;
*# relationships (used by Search/Sort Results)&lt;br /&gt;
&lt;br /&gt;
= Use Cases =&lt;br /&gt;
&lt;br /&gt;
== Find Deployed Service Name ==&lt;br /&gt;
&lt;br /&gt;
* other services can use fixed serviceTag to get deployed serviceName from serviceSchema on S3&lt;br /&gt;
* used to build resource names for external services&lt;br /&gt;
* eg when one service needs to send a message into an SNS belonging to a different service&lt;br /&gt;
&lt;br /&gt;
== Standard Create, Update, List, Delete pages ==&lt;br /&gt;
&lt;br /&gt;
* List and Delete are maybe not required, use table data system instead.&lt;br /&gt;
* object schema can add validation information that can be used on the frontend to check before sending to backend, and by the backend to validate the data before handling&lt;br /&gt;
&lt;br /&gt;
=== Create Object ===&lt;br /&gt;
&lt;br /&gt;
* can configure what fields are shown&lt;br /&gt;
* requiredOnCreate fields must be shown &lt;br /&gt;
&lt;br /&gt;
=== Edit Object ===&lt;br /&gt;
&lt;br /&gt;
* users setup any number of pages for object types with configurable fields shown&lt;br /&gt;
* fields can be either display only or edit&lt;br /&gt;
* each field can adjust it&#039;s display properties (perhaps via cssStyles)&lt;br /&gt;
&lt;br /&gt;
== Menu Config ==&lt;br /&gt;
&lt;br /&gt;
When adding menu items can add links to create, update, list, delete objects, user chooses the service then from that service&#039;s list of objects and what action is being performed. For update/delete perhaps links to a standard page that asks for the identifier before presenting the page.&lt;br /&gt;
&lt;br /&gt;
== Tabled Data ==&lt;br /&gt;
&lt;br /&gt;
When viewing tabled data the frontend pulls the tableId&#039;s config from backend, then when requesting the data also requests the serviceTag &amp;gt; objectType schema for use when displaying the data.&lt;br /&gt;
&lt;br /&gt;
== Code Standardization ==&lt;br /&gt;
&lt;br /&gt;
Code such as middleware validation schema and saving data to databases can be standardized.&lt;br /&gt;
&lt;br /&gt;
== Code Generation ==&lt;br /&gt;
&lt;br /&gt;
Endpoints per object for actions such as Create/Delete/Update can be automatically generated from objectSchema.&lt;br /&gt;
&lt;br /&gt;
=== Code Generation Structure ===&lt;br /&gt;
&lt;br /&gt;
* npm for generic code generation, can be used in any project, includes functions for generating Source files from templates and developer files&lt;br /&gt;
* npm for per project specific files, eg templates for the project (Create/Update/.. code)&lt;br /&gt;
* Empty Service Template has GenerateCode.js script file in root dir that is run to generate code, it invokes a generation function from generic npm with param that points to per project npm&#039;s templates&lt;br /&gt;
* generated Source retains hook tags (and any developer added code), so if developer wants to update developer&#039;s file with updated template code they can generate code and simply copy generated Source to src folder&lt;br /&gt;
&lt;br /&gt;
= Graph Server Config =&lt;br /&gt;
&lt;br /&gt;
* S3 has a list of graphServerTag&#039;s linking to the GraphHandler serviceTag responsible for the graph&lt;br /&gt;
* multiple graphServerTags can point to one GraphHandler, combining graphs into one server&lt;br /&gt;
* when creating each GraphHandler&#039;s graph schemas, for each field split out the fields into each GraphHandler using the graphServerTag, if multiple graphServerTags for a field point to the same GraphHandler combine the fields to create GraphHandler&#039;s graph schema&lt;br /&gt;
* every GraphHandler an object is saved into will require it&#039;s identifiers&lt;br /&gt;
* when eg updating fields for an object separate the fields per GraphHandler before sending the request to update each graph&lt;br /&gt;
&lt;br /&gt;
= Extended Object Types =&lt;br /&gt;
&lt;br /&gt;
* Allows for one graph node to have multiple labels&lt;br /&gt;
* graph schema is created for both the core object and the extended object&lt;br /&gt;
* eg Media Manager&#039;s has a node schema for &amp;quot;media&amp;quot; object type, and Image service has a node schema for &amp;quot;image&amp;quot; object type&lt;br /&gt;
* the extended object builds it&#039;s schema by combining core + extended settings&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - Per Service Schemas|Per Service Schemas]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Design_concepts&amp;diff=4586</id>
		<title>Design concepts</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Design_concepts&amp;diff=4586"/>
		<updated>2026-08-18T00:32:43Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Projects =&lt;br /&gt;
&lt;br /&gt;
* [[Development - Izara Core]]&lt;br /&gt;
* [[Development - Izara Market]]&lt;br /&gt;
* [[Development - Izara Supply]]&lt;br /&gt;
* [[Development - Izara Video Feed]]&lt;br /&gt;
* [[Development - Izara Commerce]]&lt;br /&gt;
* [[Development - Izara Accounting]]&lt;br /&gt;
* [[Development - Izara IoT]]&lt;br /&gt;
* [[Development - Izara Currency]]&lt;br /&gt;
&lt;br /&gt;
= Linker Projects =&lt;br /&gt;
&lt;br /&gt;
* [[Development - Izara Commerce to Accounting]]&lt;br /&gt;
* [[Development - Izara Supply to VideoFeed]]&lt;br /&gt;
&lt;br /&gt;
= Backend =&lt;br /&gt;
&lt;br /&gt;
== Backend services ==&lt;br /&gt;
&lt;br /&gt;
[[:Category:Backend services|see all Backend services]]&lt;br /&gt;
&lt;br /&gt;
== NPM modules ==&lt;br /&gt;
&lt;br /&gt;
[[:Category:NPM modules|see all NPM modules]]&lt;br /&gt;
&lt;br /&gt;
== Deploy instructions ==&lt;br /&gt;
&lt;br /&gt;
[[:Category:Deploy instructions|see all Deploy instructions]]&lt;br /&gt;
&lt;br /&gt;
== Testing and developing ==&lt;br /&gt;
&lt;br /&gt;
* [[Repository structure]]&lt;br /&gt;
*: Standard file and directory structure of repositories&lt;br /&gt;
* [[Development environment]]&lt;br /&gt;
* [[Test environment overview]]&lt;br /&gt;
* [[Local test environment]]&lt;br /&gt;
* [[Using Postman]]&lt;br /&gt;
* [[Git development]]&lt;br /&gt;
* [[Syntax - Backend services]]&lt;br /&gt;
* [[Remote repository and workspace structure]]&lt;br /&gt;
* [[Developer guide for making Integration Tests]]&lt;br /&gt;
* [[Diagrams service]]&lt;br /&gt;
&lt;br /&gt;
== Misc concepts ==&lt;br /&gt;
&lt;br /&gt;
* [[Communication between services]]&lt;br /&gt;
* [[Lambda handler functions]]&lt;br /&gt;
* [[Idempotence and Race Conditions]]&lt;br /&gt;
* [[Per Service Schemas]]&lt;br /&gt;
* [[Standard Data Structures]]&lt;br /&gt;
* [[Standard Config Table Per Service]]&lt;br /&gt;
* [[User Data Handling]]&lt;br /&gt;
*: (maybe removing)&lt;br /&gt;
* [[Standard LogicalResults Per Service]]&lt;br /&gt;
* [[Standard FindData Per Service]]&lt;br /&gt;
* [[Stored Cache]] and [[Triggered Cache]]&lt;br /&gt;
* [[Calling Flow]]&lt;br /&gt;
* [[Standard WebSocketTask Per Service]]&lt;br /&gt;
* [[Error Handling Multi Thread Processing]]&lt;br /&gt;
* [[Multi Thread Invocation]]&lt;br /&gt;
* [[Copying large Dynamo data from to another service table]]&lt;br /&gt;
&lt;br /&gt;
= Frontend =&lt;br /&gt;
&lt;br /&gt;
== Testing and developing ==&lt;br /&gt;
&lt;br /&gt;
* [[Syntax - Frontend services]]&lt;br /&gt;
&lt;br /&gt;
== Concepts ==&lt;br /&gt;
&lt;br /&gt;
* [[Frontend Application Structure]]&lt;br /&gt;
* [[Frontend Authentication]]&lt;br /&gt;
&lt;br /&gt;
== Testing and developing ==&lt;br /&gt;
&lt;br /&gt;
* [[Local Development Environment]]&lt;br /&gt;
&lt;br /&gt;
= This wiki =&lt;br /&gt;
&lt;br /&gt;
* [[How to contribute]]&lt;br /&gt;
* [[Standard formatting rules]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Per_Service_Schemas&amp;diff=4577</id>
		<title>Per Service Schemas</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Per_Service_Schemas&amp;diff=4577"/>
		<updated>2026-08-11T14:19:59Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: /* Flow Schema | FlowSchemas.js */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Each service manages a schema of object/resources that it is responsible for, this schema is available to other services and frontends. The schema includes a list of fields available for each object.&lt;br /&gt;
&lt;br /&gt;
= File Structure =&lt;br /&gt;
&lt;br /&gt;
* see [[Repository structure#schemas|Repository structure]]&lt;br /&gt;
&lt;br /&gt;
= ObjectSchema | ObjectFieldSchema.js =&lt;br /&gt;
&lt;br /&gt;
== Not extendObjType ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;xx&amp;quot;,&lt;br /&gt;
	shortNameObjectType:&amp;quot;x&amp;quot;, // optional, use when generate code create lambda role with long name&lt;br /&gt;
	canDelete: false, // whether any fields can be deleted // default = false&lt;br /&gt;
	    belongTo: { &lt;br /&gt;
		serviceTag:&amp;quot;iii&amp;quot;,&lt;br /&gt;
		objectType:&amp;quot;jjj&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
    // how is the object created&lt;br /&gt;
    // userGenerated there will be generated endpoints for api or sqs (used in importBatchMain) to create object&lt;br /&gt;
    // systemGenerated must be created by flow/s&lt;br /&gt;
    // searchResultGenerated see separate notes below&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot; || &amp;quot;systemGenerated&amp;quot; || &amp;quot;searchResultGenerated&amp;quot; // required&lt;br /&gt;
    searchResultGeneratedFlowType: {}, // for generatedBy = searchResultGenerated&lt;br /&gt;
	addOnDataStructure: [ // optional, add for additional setting to objectType&lt;br /&gt;
		{&lt;br /&gt;
			// all fields that a user can edit must be in versionedData, and all fields in versionedData must be editable by user&lt;br /&gt;
			type:&amp;quot;versionedData&amp;quot;,&lt;br /&gt;
			versionedDataLabel: &amp;quot;xx&amp;quot;, // versionedData label name&lt;br /&gt;
			storageResourceTag : &amp;quot;xx&amp;quot;, // ref to storegeResourceTag&lt;br /&gt;
			fieldNames: { // fieldName in versionedData cannot have in in main objectSchema.fieldNames&lt;br /&gt;
				&amp;quot;aaa&amp;quot;:{ // fieldName&lt;br /&gt;
					type: &amp;quot;xx&amp;quot;, // string|integer|number|timestamp|currency|currencyValue|float|special|object|boolean|arrayMixed|arrayNumeric|arrayString&lt;br /&gt;
					requiredOnCreate: false, // default = false&lt;br /&gt;
					optionalOnCreate: false, // default = false,&lt;br /&gt;
					validation: {&lt;br /&gt;
                      itemValidation:{} // for validate item in array&lt;br /&gt;
                    },&lt;br /&gt;
                    // probably impossible to have fromObjType, because data can be changed by user here&lt;br /&gt;
					fromObjType:{&lt;br /&gt;
						serviceTag: &amp;quot;xxx&amp;quot;, &lt;br /&gt;
						objectType: &amp;quot;xxx&amp;quot; &lt;br /&gt;
					},&lt;br /&gt;
				},&lt;br /&gt;
				// ...&lt;br /&gt;
			}&lt;br /&gt;
        },&lt;br /&gt;
        { // can have multiple addOn of type attributeTree&lt;br /&gt;
          type:&amp;quot;attributeTree&amp;quot;,           &lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;translation&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;propertyValue&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;mediaLink&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          type:&amp;quot;rbac&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
		// ...&lt;br /&gt;
	],&lt;br /&gt;
	plugInTags: [&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;], // plugIns that can be connected to this objType&lt;br /&gt;
	storageResources:{&lt;br /&gt;
		&amp;quot;xxx&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // graph			&lt;br /&gt;
			graphServerTag: &amp;quot;xx&amp;quot;, // setting for storageType graph&lt;br /&gt;
            additionalGraphIndexes:[[&#039;fieldName1&#039;, &#039;fieldName2&#039;, ...], [...]]  // will make graph index with specific fieldName &lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;zzz&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // dynamoDB&lt;br /&gt;
			// setting for storageType dynamoDB&lt;br /&gt;
			tableName: &amp;quot;xx&amp;quot;,&lt;br /&gt;
			groupByPartitionKeyField: &amp;quot;xx&amp;quot;, // use groupByPartitionKeyField as partition key and not have sort key in dynamoDB, if have multiple identifiers will concat it. And use it as partitionKey.&lt;br /&gt;
            serviceTag:&amp;quot;zz&amp;quot;// default own service.&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	fieldNames: {&lt;br /&gt;
		xxx: { // fieldName&lt;br /&gt;
			type: &amp;quot;xx&amp;quot;,  // string|integer|number|timestamp|currency|currencyValue|float|special|object|boolean|arrayMixed|arrayNumeric|arrayString&lt;br /&gt;
            randomOnCreate: false,   // default = false , can set true in fieldName that part of identifiers and identifiers have single identifierFieldname&lt;br /&gt;
			requiredOnCreate: false, // default = false&lt;br /&gt;
			optionalOnCreate: false, // default = false&lt;br /&gt;
			canUpdate: true, // default = true (only system/flows can edit, no history of changes unless flow manually adds)&lt;br /&gt;
			validation: {&lt;br /&gt;
			  itemValidation:{}  // for validate item in array&lt;br /&gt;
            }, // maybe ajv syntax&lt;br /&gt;
			storageResourceTags: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // reference to storageResources property&lt;br /&gt;
		    fromObjType:{&lt;br /&gt;
			  serviceTag: &amp;quot;xxx&amp;quot;, &lt;br /&gt;
			  objectType: &amp;quot;xxx&amp;quot; &lt;br /&gt;
			},&lt;br /&gt;
            hashOnCreate: [&amp;quot;xx&amp;quot;, &amp;quot;yy&amp;quot;], // reference to other fieldName, &lt;br /&gt;
            statusField: true, // use for objectSchema inside flowSchema, identify which field is statusField &lt;br /&gt;
&lt;br /&gt;
			// comes from requiredOnCreate relationships&lt;br /&gt;
			fromRequiredOnCreate: { &lt;br /&gt;
				relType: {&lt;br /&gt;
					serviceTag:&amp;quot;aa&amp;quot;,&lt;br /&gt;
					relationshipTag:&amp;quot;bb&amp;quot;&lt;br /&gt;
				},&lt;br /&gt;
				// or&lt;br /&gt;
				belongToObjType: true, // if set to true use the belongTo relationship to belongTo objType&lt;br /&gt;
&lt;br /&gt;
				fieldName:&amp;quot;&amp;quot; // optional default= same field name eg: now default == xxx if not defined(use fieldname of object inside link when create)&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
		// ...&lt;br /&gt;
	},&lt;br /&gt;
    compositeKeyDeliminator: &amp;quot;xx&amp;quot;, // join partitionKey and sortKey&lt;br /&gt;
	identifiers: [&lt;br /&gt;
    // for dynamoDB storageType &lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // composite partition keys in DynamoDB&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		name: &amp;quot;zz&amp;quot;, // name of field in database&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	},&lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // composite partition keys in DynamoDB&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		name: &amp;quot;zz&amp;quot;, // name of field in database&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	},&lt;br /&gt;
   &lt;br /&gt;
    // for graph storageType&lt;br /&gt;
	{&lt;br /&gt;
		type: &amp;quot;identifier&amp;quot;,&lt;br /&gt;
		fieldNames: [&amp;quot;xx&amp;quot;,&amp;quot;yy&amp;quot;], // identifier field in graph or composite partition keys in DynamoDB&lt;br /&gt;
        name: &amp;quot;zzz&amp;quot;              // use when save in dynamoDB partitionKey&lt;br /&gt;
		deliminator: &amp;quot;xx&amp;quot;,  // optional, defaults to &amp;quot;_&amp;quot;&lt;br /&gt;
		// or&lt;br /&gt;
		fieldName: &amp;quot;xx&amp;quot;	&lt;br /&gt;
	},&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== extendObjType ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	// for objects stored in graph this will add another node label&lt;br /&gt;
	objectType: &amp;quot;xx&amp;quot;, // new label to add&lt;br /&gt;
	extendObjType: { // core object that this object extends&lt;br /&gt;
		serviceTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;xxx&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources:{ // these are the storageResources that carry the extended objects settings, &lt;br /&gt;
		// (see above)&lt;br /&gt;
	},&lt;br /&gt;
	fieldNames: {&lt;br /&gt;
		// (see above) &lt;br /&gt;
	},&lt;br /&gt;
	// canDelete/identifiers come from the core object&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== searchResultGenerated ==&lt;br /&gt;
&lt;br /&gt;
* must be created by flow&lt;br /&gt;
* eg: variantProduct&lt;br /&gt;
* not have any storageResources&lt;br /&gt;
* identifiers are automatically searchResultData identifiers&lt;br /&gt;
* a searchResult request for this object will enter the searchResultGeneratedFlowType flow which creates searchResultData that can then be queried/sorted&lt;br /&gt;
* all relationships must be storageType = lambda, eg translate from variantProduct to variant uses a translateId flow to query the variantProduct identifier (searchResultData) to find the variantId in it&#039;s requiredData results&lt;br /&gt;
* searchResultGeneratedFlowType takes over after creating searchResultMain record until processRequiredData&lt;br /&gt;
* if objectSchema defines any fieldnames, then they are found using a flow, maybe as hooks in per service findData&lt;br /&gt;
* when finding direct fieldname, will need to check if requireData already exists, if not enter flow/findData to create&lt;br /&gt;
* no fields can be edited, so can show in forms but no updates performed&lt;br /&gt;
&lt;br /&gt;
= Relationships Schema | ObjectRelationships.js =&lt;br /&gt;
&lt;br /&gt;
* stored in top level schemas folder&lt;br /&gt;
* parent/child determines relationship direction for graph relationships&lt;br /&gt;
* have one service that contains information of each relationship &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// relationship schema in responsible service&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;xxx&amp;quot;: { // relationshipTag - name of relationship type stored in graph&lt;br /&gt;
      generatedBy: &amp;quot;userGenerated&amp;quot; || &amp;quot;systemGenerated&amp;quot; // default=&amp;quot;userGenerated&amp;quot;&lt;br /&gt;
      canChangeToRelTypes: [&lt;br /&gt;
		{&lt;br /&gt;
			relType: { // relType that this relType can change to &lt;br /&gt;
			  serviceTag:&amp;quot;xxx&amp;quot;,&lt;br /&gt;
			  relationshipTag: &amp;quot;yyy&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			changeBy: &amp;quot;user&amp;quot; // &amp;quot;systemNoUserId&amp;quot; | &amp;quot;systemWithUserId&amp;quot; | &amp;quot;user&amp;quot;, default=&amp;quot;user&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
        // another relType&lt;br /&gt;
      ],&lt;br /&gt;
      storageResources:{&lt;br /&gt;
		&amp;quot;xxx&amp;quot;:{ // storageResourceTag&lt;br /&gt;
			storageType: &amp;quot;xx&amp;quot;, // dynamoDB | graph | lambda&lt;br /&gt;
		    // if storageType=&amp;quot;dynamoDB&amp;quot;  will not specify tableName in relationship schema&lt;br /&gt;
&lt;br /&gt;
			// setting for storageType graph&lt;br /&gt;
			graphServerTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
            additionalGraphIndexes:[[&#039;fieldName1&#039;, &#039;fieldName2&#039;, ...], [...]],  // will make graph index with specific fieldName &lt;br /&gt;
&lt;br /&gt;
			// setting for storageType lambda&lt;br /&gt;
			serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
			functionName: &amp;quot;xx&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
      },&lt;br /&gt;
      fieldNames: {&lt;br /&gt;
		&amp;quot;xxx&amp;quot;: { // relationship property name&lt;br /&gt;
			type: &amp;quot;string&amp;quot;, // &amp;quot;string&amp;quot; | &amp;quot;number&amp;quot; ...&lt;br /&gt;
			requiredOnCreate: false, // default=false&lt;br /&gt;
			optionalOnCreate: false, // default = false&lt;br /&gt;
			updateBy: &amp;quot;user&amp;quot; // &amp;quot;systemNoUserId&amp;quot; | &amp;quot;systemWithUserId&amp;quot; | &amp;quot;user&amp;quot; | &amp;quot;none&amp;quot;, default=&amp;quot;user&amp;quot;&lt;br /&gt;
			validation: {} // ajv syntax&lt;br /&gt;
		},&lt;br /&gt;
		//...other relationship properties&lt;br /&gt;
      },&lt;br /&gt;
      links: [&lt;br /&gt;
        {&lt;br /&gt;
          storageResourceTags: [&amp;quot;xxx&amp;quot;],   // reference from storageResources property&lt;br /&gt;
          canDelete: false                // default = false, if set true will allow delete relationship between 2 objType&lt;br /&gt;
          from: {&lt;br /&gt;
            objType: {&lt;br /&gt;
              serviceTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
              objectType: &amp;quot;xx&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            requiredOnCreate: true, // if set true will create relationshipTag when create objType data, if both &amp;quot;from&amp;quot; and &amp;quot;to&amp;quot; linkType=&amp;quot;many&amp;quot; should not have requiredOnCreate, exists in &amp;quot;from&amp;quot; or &amp;quot;to&amp;quot; only&lt;br /&gt;
            linkType: &amp;quot;&amp;quot;,   // one | many&lt;br /&gt;
          //   moveBy: &amp;quot;none&amp;quot;, // &amp;quot;systemNoUserId&amp;quot; | &amp;quot;systemWithUserId&amp;quot; | &amp;quot;user&amp;quot; | &amp;quot;none&amp;quot;, default=&amp;quot;none&amp;quot;&lt;br /&gt;
          // belongTo:true&lt;br /&gt;
          },&lt;br /&gt;
          to: {&lt;br /&gt;
            objType: {&lt;br /&gt;
              serviceTag: &amp;quot;yy&amp;quot;,&lt;br /&gt;
              objectType: &amp;quot;yy&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            linkType: &amp;quot;&amp;quot;,   // one | many&lt;br /&gt;
             // moveBy allows the relationship to be moved between 2 instances of the same objType only&lt;br /&gt;
	        moveBy: &amp;quot;none&amp;quot;, // &amp;quot;systemNoUserId&amp;quot; | &amp;quot;systemWithUserId&amp;quot; | &amp;quot;user&amp;quot; | &amp;quot;none&amp;quot;, default=&amp;quot;none&amp;quot;&lt;br /&gt;
            belongTo:true, // false&lt;br /&gt;
          },&lt;br /&gt;
          requestProperties: {&lt;br /&gt;
            // if storageType is Lambda and translateIds/linkPath requires properties set them here (eg sellOffer&amp;gt;orderPrice)&lt;br /&gt;
            tag_deliverTo: {&lt;br /&gt;
              requestPropertyType: &amp;quot;objectIdentifier&amp;quot;,&lt;br /&gt;
              objType: {&lt;br /&gt;
                serviceTag: &amp;quot;Locations&amp;quot;,&lt;br /&gt;
                objectType: &amp;quot;locationNode&amp;quot; // deliversToLocationNode&lt;br /&gt;
              },&lt;br /&gt;
              identifiersFieldName: &amp;quot;locationNodeId&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            // ... other request properties&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        // ...other link&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Reference Relationships Schema | RefObjectRelationships.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// reference to relationshipTag in external service&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    objectType: &amp;quot;zz&amp;quot;,              // objectType in local service&lt;br /&gt;
    relationshipTag: &amp;quot;xxx&amp;quot;,        // name of relationshiptag of objType&lt;br /&gt;
    relationshipServiceTag: &amp;quot;xx&amp;quot;   // point to service tag that contain data of relationshipTag of objType&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Flow Schema | FlowSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  [&lt;br /&gt;
    {&lt;br /&gt;
      flowTag: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
      initiateBy: &amp;quot;user&amp;quot;,         // &amp;quot;user&amp;quot; | &amp;quot;system&amp;quot; -- if receive plugin should be user &lt;br /&gt;
      handleObj: &amp;quot;one&amp;quot;,           // &amp;quot;one&amp;quot; | &amp;quot;multi&amp;quot;&lt;br /&gt;
      statusType: &amp;quot;statusField&amp;quot;,  // &amp;quot;statusField&amp;quot; | &amp;quot;storedCache&amp;quot; | &amp;quot;none&amp;quot; | &amp;quot;triggerCache&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      // statusType=&amp;quot;triggerCache&amp;quot; setting &lt;br /&gt;
      triggerType: &amp;quot;storedCache&amp;quot;, // &amp;quot;storedCache&amp;quot; | &amp;quot;switch&amp;quot;&lt;br /&gt;
      triggerFlowTypes: [&lt;br /&gt;
        //... triggerFlowType&lt;br /&gt;
      ],&lt;br /&gt;
&lt;br /&gt;
      // statusType=&amp;quot;statusField&amp;quot; | &amp;quot;triggerCache&amp;quot; | &amp;quot;storedCache&amp;quot; setting:&lt;br /&gt;
      objType: {},&lt;br /&gt;
&lt;br /&gt;
      event: [&amp;quot;ownTopic&amp;quot;],  // &amp;quot;ownTopic&amp;quot; | &amp;quot;extTopic&amp;quot; | &amp;quot;s3&amp;quot; | &amp;quot;eventBridge&amp;quot; | &amp;quot;lambdaSyncInv&amp;quot; | &amp;quot;lambdaSyncApi&amp;quot; | &amp;quot;generatedCode&amp;quot; | &amp;quot;dsq&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      // event=&amp;quot;s3&amp;quot; setting&lt;br /&gt;
      bucketName: &amp;quot;xxx&amp;quot;, // bucket for s3 event&lt;br /&gt;
      createBucket: boolean, // if true will generate new bucket with bucketName if false will point to old bucket that already have &lt;br /&gt;
&lt;br /&gt;
      // event=&amp;quot;eventBridge&amp;quot; setting&lt;br /&gt;
      schedules: [&lt;br /&gt;
        {&lt;br /&gt;
          name: &#039;your-scheduled-rate-event-name&#039;,&lt;br /&gt;
          description: &#039;your scheduled rate event description&#039;,&lt;br /&gt;
          rate: [&amp;quot;rate(1 minute)&amp;quot;,],&lt;br /&gt;
          input: {}&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
&lt;br /&gt;
      // event=&amp;quot;generatedCode&amp;quot; setting&lt;br /&gt;
      generatedCodeConfig: {&lt;br /&gt;
        generatedCodeTag: &amp;quot;create&amp;quot;, // tag for generated code, eg &amp;quot;create&amp;quot; | &amp;quot;update&amp;quot; | &amp;quot;delete&amp;quot;&lt;br /&gt;
        codeHookTag: &amp;quot;xx&amp;quot;, // which codeHook to initiate flow from&lt;br /&gt;
        // maybe validate: invocationType must exist in &amp;quot;event&amp;quot; array, so don&#039;t need to check 2 places when eg creating sns topic&lt;br /&gt;
        invocationType: &amp;quot;ownTopic&amp;quot;, // &amp;quot;ownTopic&amp;quot; | &amp;quot;lambdaSyncInv&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        objType: {}, // which cases in the generated code trigger the flow&lt;br /&gt;
        // .. other settings depending on generated code&lt;br /&gt;
      },&lt;br /&gt;
&lt;br /&gt;
      outputTopic: boolean,&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      flowSteps: {&lt;br /&gt;
        inTag: { // will generate Topic serviceTag_stage_yyy_inTag&lt;br /&gt;
          properties: [], // reference to stepProperties key, the first lambda&#039;s input properties and messageAttributes are the flow&#039;s input properties and messageAttributes&lt;br /&gt;
          messageAttributes: [], // reference to stepProperties key&lt;br /&gt;
          plugInHooks: [&lt;br /&gt;
            {&lt;br /&gt;
              plugInHookTag: &amp;quot;&amp;quot;,&lt;br /&gt;
              objType: {}, // used to query connection dynamo for an object instance in current flow&lt;br /&gt;
            },&lt;br /&gt;
          ],&lt;br /&gt;
          returnValues: {&lt;br /&gt;
            properties: [], // reference to stepProperties key&lt;br /&gt;
            messageAttributes: [], // reference to stepProperties key, only for outputTopic=true&lt;br /&gt;
          },&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
        // another flow steps&lt;br /&gt;
        flowStep1: { // will generate Topic serviceTag_stage_yyy_Flow1&lt;br /&gt;
          properties: [], // reference to stepProperties key&lt;br /&gt;
          messageAttributes: [], // reference to stepProperties key&lt;br /&gt;
          event: [&amp;quot;ownTopic&amp;quot;],  // &amp;quot;ownTopic&amp;quot; | &amp;quot;extTopic&amp;quot; | &amp;quot;s3&amp;quot; | &amp;quot;eventBridge&amp;quot; | &amp;quot;lambdaSyncInv&amp;quot; | &amp;quot;lambdaSyncApi&amp;quot; | &amp;quot;generatedCode&amp;quot; | &amp;quot;dsq&amp;quot;&lt;br /&gt;
          // handle splitting logic into awaitingStep/awaitingMultipleSteps&lt;br /&gt;
          // handle splitting logic into paginated lambda&lt;br /&gt;
&lt;br /&gt;
          previousSteps: [&lt;br /&gt;
            {&lt;br /&gt;
              stepName: &amp;quot;xxx&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
              sourceType: &amp;quot;extTopic&amp;quot;, // triggered by output from external service&lt;br /&gt;
              serviceTag: &amp;quot;InventoryService&amp;quot;,&lt;br /&gt;
              topic: &amp;quot;ReserveStock_In&amp;quot;,&lt;br /&gt;
              fromStepName: &amp;quot;xx&amp;quot; // which step in this flow sent request to external flow, used to find awaitingStep prefix&lt;br /&gt;
            }            &lt;br /&gt;
          ],&lt;br /&gt;
          nextSteps: [&lt;br /&gt;
            {&lt;br /&gt;
              stepName: &amp;quot;yyy&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
              targetType: &amp;quot;extTopic&amp;quot;,&lt;br /&gt;
              serviceTag: &amp;quot;InventoryService&amp;quot;,&lt;br /&gt;
              topic: &amp;quot;ReserveStock_In&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          ],&lt;br /&gt;
&lt;br /&gt;
          plugInHooks: [&lt;br /&gt;
            {&lt;br /&gt;
              plugInHookTag: &amp;quot;&amp;quot;,&lt;br /&gt;
              objType: {}, // used to query connection dynamo for an object instance in current flow&lt;br /&gt;
            },&lt;br /&gt;
          ],&lt;br /&gt;
          returnValues: { // the last lambda function returnValues are the flow&#039;s returnValues&lt;br /&gt;
            properties: [], // reference to stepProperties key&lt;br /&gt;
            messageAttributes: [], // reference to stepProperties key, only for outputTopic=true&lt;br /&gt;
          },&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
      },&lt;br /&gt;
&lt;br /&gt;
      stepProperties: { // normalized all stepProperties&lt;br /&gt;
        &amp;quot;uuid&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          type: &amp;quot;object&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          childProperties: [&amp;quot;uuid2&amp;quot;, &amp;quot;uuid3&amp;quot;]&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid2&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid3&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid4&amp;quot;: {&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          objectField: {&lt;br /&gt;
            objType: {},&lt;br /&gt;
            fieldName: &amp;quot;xx&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          overwritePropertyName: &amp;quot;xx&amp;quot; // optional, if have objectField and have overwritePropertyName will overwrite fieldName &lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
      stepMessageAttributes: { // normalized all stepMessageAttributes&lt;br /&gt;
        &amp;quot;uuid&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid2&amp;quot;: {&lt;br /&gt;
          propertyName: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
          required: false,  // true | false default=false &lt;br /&gt;
          type: &amp;quot;string&amp;quot;,&lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= System Text Schema | SystemTextSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
	{&lt;br /&gt;
		namespace: &amp;quot;xxx&amp;quot;, // groups files downloaded by frontend&lt;br /&gt;
		systemTextTag: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
	}&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Auto generated systemText and namespaces ==&lt;br /&gt;
&lt;br /&gt;
=== systemNotification names ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;sysNotification_{notificationGrouping}&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{notificationTag}&amp;quot;&lt;br /&gt;
* eg shown on notification settings page&lt;br /&gt;
&lt;br /&gt;
=== objType names ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;objTypes&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{serviceTag}_{objectType}&amp;quot;&lt;br /&gt;
* eg shown on config pages, eg pulldown list of object types&lt;br /&gt;
&lt;br /&gt;
=== objType field name descriptions ===&lt;br /&gt;
&lt;br /&gt;
* namespace: &amp;quot;objType_fielddesc_{serviceTag}_{objectType}&amp;quot;&lt;br /&gt;
* systemTextTag: &amp;quot;{fieldname}&amp;quot;&lt;br /&gt;
* eg shown on config pages, eg info box for each field name&lt;br /&gt;
&lt;br /&gt;
= System Notification Schema | SystemNotificationSchemas.js =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
	{&lt;br /&gt;
		notificationTag: &amp;quot;xxx&amp;quot;,&lt;br /&gt;
		notificationGrouping: &amp;quot;yyy&amp;quot;,&lt;br /&gt;
		weight: &amp;quot;##&amp;quot;,&lt;br /&gt;
	},&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Generated S3 files =&lt;br /&gt;
&lt;br /&gt;
* generate multiple files for different uses, eg:&lt;br /&gt;
*# list of saved fieldNames for Create&lt;br /&gt;
*# list of saved+calculated for Update/Info pages&lt;br /&gt;
*# graphSchemas&lt;br /&gt;
*# relationships (used by Search/Sort Results)&lt;br /&gt;
&lt;br /&gt;
= Use Cases =&lt;br /&gt;
&lt;br /&gt;
== Find Deployed Service Name ==&lt;br /&gt;
&lt;br /&gt;
* other services can use fixed serviceTag to get deployed serviceName from serviceSchema on S3&lt;br /&gt;
* used to build resource names for external services&lt;br /&gt;
* eg when one service needs to send a message into an SNS belonging to a different service&lt;br /&gt;
&lt;br /&gt;
== Standard Create, Update, List, Delete pages ==&lt;br /&gt;
&lt;br /&gt;
* List and Delete are maybe not required, use table data system instead.&lt;br /&gt;
* object schema can add validation information that can be used on the frontend to check before sending to backend, and by the backend to validate the data before handling&lt;br /&gt;
&lt;br /&gt;
=== Create Object ===&lt;br /&gt;
&lt;br /&gt;
* can configure what fields are shown&lt;br /&gt;
* requiredOnCreate fields must be shown &lt;br /&gt;
&lt;br /&gt;
=== Edit Object ===&lt;br /&gt;
&lt;br /&gt;
* users setup any number of pages for object types with configurable fields shown&lt;br /&gt;
* fields can be either display only or edit&lt;br /&gt;
* each field can adjust it&#039;s display properties (perhaps via cssStyles)&lt;br /&gt;
&lt;br /&gt;
== Menu Config ==&lt;br /&gt;
&lt;br /&gt;
When adding menu items can add links to create, update, list, delete objects, user chooses the service then from that service&#039;s list of objects and what action is being performed. For update/delete perhaps links to a standard page that asks for the identifier before presenting the page.&lt;br /&gt;
&lt;br /&gt;
== Tabled Data ==&lt;br /&gt;
&lt;br /&gt;
When viewing tabled data the frontend pulls the tableId&#039;s config from backend, then when requesting the data also requests the serviceTag &amp;gt; objectType schema for use when displaying the data.&lt;br /&gt;
&lt;br /&gt;
== Code Standardization ==&lt;br /&gt;
&lt;br /&gt;
Code such as middleware validation schema and saving data to databases can be standardized.&lt;br /&gt;
&lt;br /&gt;
== Code Generation ==&lt;br /&gt;
&lt;br /&gt;
Endpoints per object for actions such as Create/Delete/Update can be automatically generated from objectSchema.&lt;br /&gt;
&lt;br /&gt;
=== Code Generation Structure ===&lt;br /&gt;
&lt;br /&gt;
* npm for generic code generation, can be used in any project, includes functions for generating Source files from templates and developer files&lt;br /&gt;
* npm for per project specific files, eg templates for the project (Create/Update/.. code)&lt;br /&gt;
* Empty Service Template has GenerateCode.js script file in root dir that is run to generate code, it invokes a generation function from generic npm with param that points to per project npm&#039;s templates&lt;br /&gt;
* generated Source retains hook tags (and any developer added code), so if developer wants to update developer&#039;s file with updated template code they can generate code and simply copy generated Source to src folder&lt;br /&gt;
&lt;br /&gt;
= Graph Server Config =&lt;br /&gt;
&lt;br /&gt;
* S3 has a list of graphServerTag&#039;s linking to the GraphHandler serviceTag responsible for the graph&lt;br /&gt;
* multiple graphServerTags can point to one GraphHandler, combining graphs into one server&lt;br /&gt;
* when creating each GraphHandler&#039;s graph schemas, for each field split out the fields into each GraphHandler using the graphServerTag, if multiple graphServerTags for a field point to the same GraphHandler combine the fields to create GraphHandler&#039;s graph schema&lt;br /&gt;
* every GraphHandler an object is saved into will require it&#039;s identifiers&lt;br /&gt;
* when eg updating fields for an object separate the fields per GraphHandler before sending the request to update each graph&lt;br /&gt;
&lt;br /&gt;
= Extended Object Types =&lt;br /&gt;
&lt;br /&gt;
* Allows for one graph node to have multiple labels&lt;br /&gt;
* graph schema is created for both the core object and the extended object&lt;br /&gt;
* eg Media Manager&#039;s has a node schema for &amp;quot;media&amp;quot; object type, and Image service has a node schema for &amp;quot;image&amp;quot; object type&lt;br /&gt;
* the extended object builds it&#039;s schema by combining core + extended settings&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - Per Service Schemas|Per Service Schemas]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=2025-11-20_IntegrationTest&amp;diff=4576</id>
		<title>2025-11-20 IntegrationTest</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=2025-11-20_IntegrationTest&amp;diff=4576"/>
		<updated>2026-08-11T13:08:42Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: /* graphSeedDataTags */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Reference:&lt;br /&gt;
&lt;br /&gt;
*[[2020-10-01 - Integration Test Config - Functions|IntegrationtestConfig]]&lt;br /&gt;
*[[2020-10-01 - Integration Testing - Lambda Functions|Integrationtesting]]&lt;br /&gt;
*[[2025-02-20 - Integration Test examples|Example]]&lt;br /&gt;
&lt;br /&gt;
= File extension =&lt;br /&gt;
&lt;br /&gt;
uploadS3: &amp;quot;.json&amp;quot;&lt;br /&gt;
integrationtestConfig: &amp;quot;.js&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=TestRecord=&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JSON&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    integrationTestTag: &amp;quot;Integrationtest_xx&amp;quot;,&lt;br /&gt;
    testStartedTimestamp: 111111111, // start time&lt;br /&gt;
    bucketName: &amp;quot;integrationtest-config-us-east-2&amp;quot;,&lt;br /&gt;
    lastUpdateUniqueRequestId: &amp;quot;sssss&amp;quot;, //_izContext.uniqueRequestId protacts race coditionn dynamodb&lt;br /&gt;
    testStatus: &amp;quot;passed&amp;quot;,//failed,processing,passed&lt;br /&gt;
    testCompleteTimestamp: 1111113, // all test finish&lt;br /&gt;
    stages: [&lt;br /&gt;
      {&lt;br /&gt;
        stageConfig: {&lt;br /&gt;
          //straight copy of this stage from integration test config&lt;br /&gt;
          inputEventTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
          inputEventConfig: {//event input&lt;br /&gt;
          },&lt;br /&gt;
          outputEventTag: &amp;quot;output_xx&amp;quot;,&lt;br /&gt;
          outputEventConfig: {//event out put&lt;br /&gt;
          },&lt;br /&gt;
          resourceName: &amp;quot;ComplexfilterTestProcessComplexfilter&amp;quot;,// function name&lt;br /&gt;
          resourceType: &amp;quot;Lambda&amp;quot;, // function name&lt;br /&gt;
          serviceTag: &amp;quot;Complexfilter&amp;quot;,// (initeate sqs)&lt;br /&gt;
          snsServiceName: &amp;quot;Complexfilter&amp;quot;,// (initeate sqs)&lt;br /&gt;
          snsTopic: &amp;quot;PorcessComplexfilter_In&amp;quot;// (initeate sqs)&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
        stageStatus: &amp;quot;waiting&amp;quot;, //waiting|passed|failed,&lt;br /&gt;
        stageFinishedTimestamp: 111111111,// time that all tests finished and testRecord.stages.{stageKey}.stageStatus updated&lt;br /&gt;
        stageResults: {&lt;br /&gt;
          //results at the point of entering the resource (eg a Lambda function is invoked)&lt;br /&gt;
          inputResult: {&lt;br /&gt;
            resultTimestamp: 111111111,//{time result saved},&lt;br /&gt;
            resultStatus: &amp;quot;passed&amp;quot;,//passed|failed,&lt;br /&gt;
            requestParams: {//event input&lt;br /&gt;
            }&lt;br /&gt;
          },&lt;br /&gt;
          //results at the point of returning from the resource (eg a Lambda function returns)&lt;br /&gt;
          outputResult: {&lt;br /&gt;
            resultTimestamp: 111111111,//{time result saved},&lt;br /&gt;
            resultStatus: &amp;quot;passed&amp;quot;,//passed|failed,&lt;br /&gt;
            requestParams: {//event input&lt;br /&gt;
            }&lt;br /&gt;
          },&lt;br /&gt;
          //results at the point of invoking an external resource (eg the tested Lambda function is invoking another Lambda function)&lt;br /&gt;
          invokes: {&lt;br /&gt;
            &amp;quot;serviceName_resourceType_resourceName_inputEventTag &amp;quot;: {&lt;br /&gt;
              invokeTimestamp: 111111111,//{ time result saved },&lt;br /&gt;
              resultTimestamp: 111111112,//{ time result saved },&lt;br /&gt;
              resultStatus: &amp;quot;passed&amp;quot;,//passed | failed,&lt;br /&gt;
              invokeParams: {},//{event invoke input config }&lt;br /&gt;
              requestParams: {}// event invoke input request&lt;br /&gt;
            },&lt;br /&gt;
          },&lt;br /&gt;
          dynamodbResults: [&lt;br /&gt;
            {&lt;br /&gt;
              indexOfDynamodbOutput: 0,&lt;br /&gt;
              requestParams,&lt;br /&gt;
              resultStatus: &amp;quot;passed&amp;quot;,//&lt;br /&gt;
              resultTimestamp: 22222&lt;br /&gt;
            }]&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
        stageErrors: [&lt;br /&gt;
          //misc errors encountered&lt;br /&gt;
        ]&lt;br /&gt;
      }]&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Seed Data=&lt;br /&gt;
integrationtest manager seed date 2 process&lt;br /&gt;
&lt;br /&gt;
=== Main Seed Data===&lt;br /&gt;
:Save file in s3 (in &#039;&#039;&#039;buckname&#039;&#039;&#039; :integrationtest-config-us-east-2, &#039;&#039;&#039;folder&#039;&#039;&#039;:seedData_integrationTest).For other dev use service,If a developer wants to add more for other important testing purposes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;How to use:&#039;&#039;&#039;&lt;br /&gt;
#Add it from the s3 bucket at this point&lt;br /&gt;
#Run batch refreshSeedData [[Developer guide for making Integration Tests#Bash script|batch RefreshSeedData]]&lt;br /&gt;
&#039;&#039;&#039;Logic&#039;&#039;&#039;:Process by storage resouse (graph or dynamodb)&lt;br /&gt;
:To clean up the seed data in the table after it creates seed data form service deploy and pulls seed data from s3.&lt;br /&gt;
&lt;br /&gt;
=== Refresh Seed Data ===&lt;br /&gt;
:ProcessRefreshSeedData use seedDataTag for create data environment of &#039;&#039;&#039;test&#039;&#039;&#039; and can be refresh seeddata re-test agian.&lt;br /&gt;
:&#039;&#039;&#039;canbe share&#039;&#039;&#039; seed data for other test by seed data tag.&lt;br /&gt;
&#039;&#039;&#039;How to use:&#039;&#039;&#039;&lt;br /&gt;
:Save file in s3 (for other dav keep in floder dev name) or testConfig/seedData_config(for admin)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Folder&#039;&#039;&#039;&lt;br /&gt;
*dynamoDBSeedDataTags.json&lt;br /&gt;
*graphSeedDataTags.json&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example&#039;&#039;&#039;&lt;br /&gt;
==== dynamoDBSeedDataTags ====&lt;br /&gt;
:If set tag in this setting integrationtest is generate seed data. in storage resource dynammodb.&lt;br /&gt;
Example&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;seedDynamodb_abc_ver2&amp;quot;: [ // seedDataTag&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;tableName&amp;quot;: &amp;quot;DelivMethodSTDTestLogicalResultsData&amp;quot;,  // servcieTag+stage+tablename&lt;br /&gt;
      &amp;quot;partitionKey&amp;quot;: &amp;quot;logicalResultId&amp;quot;,&lt;br /&gt;
      &amp;quot;sortKey&amp;quot;: &amp;quot;identifiersId&amp;quot;,&lt;br /&gt;
      &amp;quot;datas&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          logicalResultId: {&lt;br /&gt;
            value: &amp;quot;eeeeeeeeee4&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          identifiersId: {&lt;br /&gt;
            value: &amp;quot;lllll123456&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          processLogicalResultExpiryTimestamp: {&lt;br /&gt;
            calcType: &amp;quot;currentTimestampAdjustment&amp;quot;, // can add other types of calculated data in future&lt;br /&gt;
            action: &amp;quot;subtract&amp;quot;, // add|subtract&lt;br /&gt;
            adjustment: &amp;quot;2 days&amp;quot;, // Human-Readable Relative Format&lt;br /&gt;
          }&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          logicalResultId: {&lt;br /&gt;
            value: &amp;quot;eeeeeeeeee4&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;identifiersId&amp;quot;: {&lt;br /&gt;
            value: &amp;quot;lllll777777&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          processLogicalResultExpiryTimestamp: {&lt;br /&gt;
            calcType: &amp;quot;currentTimestampAdjustment&amp;quot;, // can add other types of calculated data in future&lt;br /&gt;
            action: &amp;quot;add&amp;quot;, // add|subtract&lt;br /&gt;
            adjustment: &amp;quot;2 days&amp;quot;, // Human-Readable Relative Format&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;tableName&amp;quot;: &amp;quot;MLocationsTestFloatingRelationships&amp;quot;,// servcieTag+stage+tablename&lt;br /&gt;
      &amp;quot;partitionKey&amp;quot;: &amp;quot;importBatchId&amp;quot;,&lt;br /&gt;
      &amp;quot;sortKey&amp;quot;: &amp;quot;identifierRelationshipsId&amp;quot;,&lt;br /&gt;
      &amp;quot;datas&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;importBatchId&amp;quot;: &amp;quot;2-uuuuuuuuuuuuuu&amp;quot;,&lt;br /&gt;
          &amp;quot;identifierRelationshipsId&amp;quot;: &amp;quot;lllll123456&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;importBatchId&amp;quot;: &amp;quot;2-uuuuuuuuuuuuuu&amp;quot;,&lt;br /&gt;
          &amp;quot;identifierRelationshipsId&amp;quot;: &amp;quot;lllll777777&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;importBatchId&amp;quot;: &amp;quot;2-uuuuuuuuuuuuuu&amp;quot;,&lt;br /&gt;
          &amp;quot;identifierRelationshipsId&amp;quot;: &amp;quot;lllll99999999&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;tableName&amp;quot;: &amp;quot;MLocationsTestFindDataMain&amp;quot;,&lt;br /&gt;
      &amp;quot;partitionKey&amp;quot;: &amp;quot;findDataId&amp;quot;,&lt;br /&gt;
      &amp;quot;datas&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;findDataId&amp;quot;: &amp;quot;111111&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;findDataId&amp;quot;: &amp;quot;22222&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;findDataId&amp;quot;: &amp;quot;333333&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== graphSeedDataTags ====&lt;br /&gt;
:If set tag in this setting integrationtest is generate seed data. in storage resource graphHanler.&lt;br /&gt;
Example&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;seedData_testTag_GG&amp;quot;: [ // seedDataTag&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;nodes&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;nodeLabels&amp;quot;: [&lt;br /&gt;
            &amp;quot;SellOfferPlan_sellOfferPlanDeliveryMethodLink&amp;quot;&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;objectDetail&amp;quot;: {&lt;br /&gt;
            &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
              &amp;quot;sellOfferPlanDeliveryMethodLinkId&amp;quot;: {&lt;br /&gt;
                &amp;quot;value&amp;quot;: &amp;quot;minttestrefreshSeedData_01&amp;quot;,&lt;br /&gt;
              },&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;fields&amp;quot;: {&lt;br /&gt;
              &amp;quot;productId&amp;quot;: {&lt;br /&gt;
                &amp;quot;value&amp;quot;: &amp;quot;ddddd&amp;quot;,&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;price&amp;quot;: {&lt;br /&gt;
                &amp;quot;value&amp;quot;: 9999&lt;br /&gt;
              },&lt;br /&gt;
              exampleTimestamp: {&lt;br /&gt;
                calcType: &amp;quot;currentTimestampAdjustment&amp;quot;, // can add other types of calculated data in future&lt;br /&gt;
                action: &amp;quot;subtract&amp;quot;, // add|subtract&lt;br /&gt;
                adjustment: &amp;quot;2 days&amp;quot;, // Human-Readable Relative Format&lt;br /&gt;
              }&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;nodeLabels&amp;quot;: [&lt;br /&gt;
            &amp;quot;servcieMintTest_shoppingMall&amp;quot;&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;objectDetail&amp;quot;: {&lt;br /&gt;
            &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
              &amp;quot;shoppingMallId&amp;quot;: &amp;quot;minttestrefreshSeedData_shoppingMallId&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;fields&amp;quot;: {&lt;br /&gt;
              &amp;quot;name&amp;quot;: &amp;quot;hotpot-man&amp;quot;,&lt;br /&gt;
              &amp;quot;totalPrice&amp;quot;: 500&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;nodeLabels&amp;quot;: [&lt;br /&gt;
            &amp;quot;servcieMintTest_shoppingMallCalculateSetting&amp;quot;&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;objectDetail&amp;quot;: {&lt;br /&gt;
            &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
              &amp;quot;versionedDataId&amp;quot;: &amp;quot;minttestrefreshSeedData_versionedDataId&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;fields&amp;quot;: {&lt;br /&gt;
              &amp;quot;addToCalculatedValuePerOrder&amp;quot;: 10,&lt;br /&gt;
              &amp;quot;addToRateTableValuePerOrder&amp;quot;: 77&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;relationships&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;fromObject&amp;quot;: {&lt;br /&gt;
            &amp;quot;nodeLabel&amp;quot;: &amp;quot;SellOfferPlan_sellOfferPlanDeliveryMethodLink&amp;quot;,&lt;br /&gt;
            &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
              &amp;quot;sellOfferPlanDeliveryMethodLinkId&amp;quot;: &amp;quot;minttestrefreshSeedData_01&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;toObject&amp;quot;: {&lt;br /&gt;
            &amp;quot;nodeLabel&amp;quot;: &amp;quot;servcieMintTest_shoppingMall&amp;quot;,&lt;br /&gt;
            &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
              &amp;quot;shoppingMallId&amp;quot;: &amp;quot;minttestrefreshSeedData_shoppingMallId&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;relationships&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;relTypeConcat&amp;quot;: &amp;quot;SellOfferPlan_hasCCCCCCC&amp;quot;,&lt;br /&gt;
              &amp;quot;relId&amp;quot;: &amp;quot;uuid-4s56df74s9df79w-w6de4f5w689ef&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          ]&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;fromObject&amp;quot;: {&lt;br /&gt;
            &amp;quot;nodeLabel&amp;quot;: &amp;quot;servcieMintTest_shoppingMall&amp;quot;,&lt;br /&gt;
            &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
              &amp;quot;shoppingMallId&amp;quot;: &amp;quot;minttestrefreshSeedData_shoppingMallId&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;toObject&amp;quot;: {&lt;br /&gt;
            &amp;quot;nodeLabel&amp;quot;: &amp;quot;servcieMintTest_shoppingMallCalculateSetting&amp;quot;,&lt;br /&gt;
            &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
              &amp;quot;versionedDataId&amp;quot;: &amp;quot;minttestrefreshSeedData_versionedDataId&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;relationships&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;relTypeConcat&amp;quot;: &amp;quot;servcieMintTest_shoppingMall_currentShoppingMallCalculateSetting&amp;quot;,&lt;br /&gt;
              &amp;quot;relId&amp;quot;: &amp;quot;uuid-s122df5-s21df&amp;quot;,&lt;br /&gt;
              &amp;quot;relationshipProperty&amp;quot;: {&lt;br /&gt;
                &amp;quot;timeStamp&amp;quot;: 1234567879,&lt;br /&gt;
                &amp;quot;statusName&amp;quot;: true&lt;br /&gt;
              }&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;relTypeConcat&amp;quot;: &amp;quot;servcieMintTest_shoppingMall_hasShoppingMallCalculateSetting&amp;quot;,&lt;br /&gt;
              &amp;quot;relId&amp;quot;: &amp;quot;uuid-77777-99999&amp;quot;,&lt;br /&gt;
              &amp;quot;relationshipProperties&amp;quot;: {&lt;br /&gt;
                &amp;quot;statusName&amp;quot;: {&lt;br /&gt;
                  &amp;quot;value&amp;quot;: true&lt;br /&gt;
                },&lt;br /&gt;
                exampleTimestamp: {&lt;br /&gt;
                  calcType: &amp;quot;currentTimestampAdjustment&amp;quot;, // can add other types of calculated data in future&lt;br /&gt;
                  action: &amp;quot;subtract&amp;quot;, // add|subtract&lt;br /&gt;
                  adjustment: &amp;quot;2 days&amp;quot;, // Human-Readable Relative Format&lt;br /&gt;
                }&lt;br /&gt;
              }&lt;br /&gt;
            }&lt;br /&gt;
          ]&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;seedData_testTag_ABC&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;objType&amp;quot;: {&lt;br /&gt;
        &amp;quot;objectType&amp;quot;: &amp;quot;productAttributeLink&amp;quot;,&lt;br /&gt;
        &amp;quot;serviceTag&amp;quot;: &amp;quot;ProductAttribute&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;objInstanceFull&amp;quot;: {&lt;br /&gt;
        &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
          &amp;quot;productAttributeLinkId&amp;quot;: &amp;quot;f90b57ca8b2fe1a83459d57da038cf50fb6d40e6&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;fields&amp;quot;: {}&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;relationships&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;relType&amp;quot;: {&lt;br /&gt;
            &amp;quot;serviceTag&amp;quot;: &amp;quot;ProductAttribute&amp;quot;,&lt;br /&gt;
            &amp;quot;relationshipTag&amp;quot;: &amp;quot;hasProductAttributeLink&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;relationshipDirection&amp;quot;: &amp;quot;to&amp;quot;,&lt;br /&gt;
          &amp;quot;targetObjType&amp;quot;: {&lt;br /&gt;
            &amp;quot;serviceTag&amp;quot;: &amp;quot;ProductStandard&amp;quot;,&lt;br /&gt;
            &amp;quot;objectType&amp;quot;: &amp;quot;productStandard&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;targetIdentifiers&amp;quot;: {&lt;br /&gt;
            &amp;quot;productId&amp;quot;: &amp;quot;f526a367a2b66cb0f37ca61b6c43f419929f521d&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;relationshipProperties&amp;quot;: {}&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;relType&amp;quot;: {&lt;br /&gt;
            &amp;quot;serviceTag&amp;quot;: &amp;quot;ProductAttribute&amp;quot;,&lt;br /&gt;
            &amp;quot;relationshipTag&amp;quot;: &amp;quot;isProductAttribute&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;relationshipDirection&amp;quot;: &amp;quot;from&amp;quot;,&lt;br /&gt;
          &amp;quot;targetObjType&amp;quot;: {&lt;br /&gt;
            &amp;quot;serviceTag&amp;quot;: &amp;quot;ProductAttribute&amp;quot;,&lt;br /&gt;
            &amp;quot;objectType&amp;quot;: &amp;quot;productAttribute&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;targetIdentifiers&amp;quot;: {&lt;br /&gt;
            &amp;quot;productAttributeId&amp;quot;: &amp;quot;f4bf7a078071d54036656df544197ba638bc3a68&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;relationshipProperties&amp;quot;: {}&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;objType&amp;quot;: {&lt;br /&gt;
        &amp;quot;objectType&amp;quot;: &amp;quot;productAttributeLink&amp;quot;,&lt;br /&gt;
        &amp;quot;serviceTag&amp;quot;: &amp;quot;ProductAttribute&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;objInstanceFull&amp;quot;: {&lt;br /&gt;
        &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
          &amp;quot;productAttributeLinkId&amp;quot;: &amp;quot;f90b57ca8b2fe1a83459d57da038cf50fb6d40e6&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;fields&amp;quot;: {}&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;relationships&amp;quot;: []&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;seedData_testTag_LL&amp;quot;: []&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cleaning Seed Data ===&lt;br /&gt;
:Delete seed data for set environment of &#039;&#039;&#039;test&#039;&#039;&#039;.&lt;br /&gt;
*cleaningeDynamoOneRecordsTags.json&lt;br /&gt;
*cleaningeDynamoManyRecordsTags.json&lt;br /&gt;
&lt;br /&gt;
====cleaningeDynamoOneRecordsTags====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;cleaningSeed_TestFindData_and_Education_case_invalid01&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;tableName&amp;quot;: &amp;quot;MLocationsTestFindDataMain&amp;quot;,&lt;br /&gt;
      &amp;quot;primaryKeys&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;findDataId&amp;quot;: &amp;quot;cleaning-1&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;findDataId&amp;quot;: &amp;quot;cleaning-2&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;tableName&amp;quot;: &amp;quot;MLocationsTestEducation&amp;quot;,&lt;br /&gt;
      &amp;quot;primaryKeys&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;studentId&amp;quot;: &amp;quot;cleaning-AA&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;studentId&amp;quot;: &amp;quot;cleaning-BB&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;studentId&amp;quot;: &amp;quot;cleaning-CC&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;cleaningSeed_TestMemberPersonnel_case_invalid01&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;tableName&amp;quot;: &amp;quot;MLocationsTestMemberPersonnel&amp;quot;,&lt;br /&gt;
      &amp;quot;primaryKeys&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;userId&amp;quot;: &amp;quot;namtan&amp;quot;,&lt;br /&gt;
          &amp;quot;passwordId&amp;quot;: &amp;quot;qqqww&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;userId&amp;quot;: &amp;quot;jack&amp;quot;,&lt;br /&gt;
          &amp;quot;passwordId&amp;quot;: &amp;quot;q1&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;userId&amp;quot;: &amp;quot;Momay&amp;quot;,&lt;br /&gt;
          &amp;quot;passwordId&amp;quot;: &amp;quot;ttr&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== cleaningeDynamoManyRecordsTags ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;cleaningSeed_manyData_partitionKey_only_miss_sort&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;tableName&amp;quot;: &amp;quot;MLocationsTestMemberPersonnel&amp;quot;,&lt;br /&gt;
      &amp;quot;primaryKeys&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;userId&amp;quot;: &amp;quot;many-data&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*logic query table MLocationsTestMemberPersonnel use primary Keys &amp;quot;userId&amp;quot; and then delete all data from primary Keys.&lt;br /&gt;
&lt;br /&gt;
=resources=&lt;br /&gt;
syntax is object&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{ &lt;br /&gt;
	&amp;quot;Lambda&amp;quot;:{&lt;br /&gt;
		&amp;quot;{FunctionNameHdrSqs}&amp;quot;:{ // FunctionNameHdrSqs is match resourceName in file tests&lt;br /&gt;
			&amp;quot;localLacation&amp;quot;:&amp;quot;/src/FunctionNameHdrSqs.js&amp;quot;,&lt;br /&gt;
			&amp;quot;localHandler&amp;quot;:&amp;quot;main&amp;quot;, &lt;br /&gt;
			&amp;quot;functionName&amp;quot;:&amp;quot;FunctionNameHdrSqs&amp;quot;	// FunctionName is function name match key of function.yml of servcie.&lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;ProcessComplexFilterHdrSqs&amp;quot;:{ &lt;br /&gt;
			&amp;quot;localLacation&amp;quot;:&amp;quot;/src/ProcessComplexFilterHdrSqs.js&amp;quot;, &lt;br /&gt;
			&amp;quot;localHandler&amp;quot;:&amp;quot;main&amp;quot;, &lt;br /&gt;
			&amp;quot;functionName&amp;quot;:&amp;quot;ProcessComplexFilterHdrSqs&amp;quot; &lt;br /&gt;
		},&lt;br /&gt;
		... &lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;Dynamodb&amp;quot;: {&lt;br /&gt;
		&amp;quot;filterMain&amp;quot;:{ // match resourceName in file tests(dynamodbOutputEventIdentifiers)&lt;br /&gt;
			&amp;quot;tableName&amp;quot;:&amp;quot;filterMain&amp;quot; &lt;br /&gt;
		}, &lt;br /&gt;
		&amp;quot;tableNameBB&amp;quot;:{ &lt;br /&gt;
			&amp;quot;tableName&amp;quot;:&amp;quot;tableNameBB&amp;quot; &lt;br /&gt;
		},&lt;br /&gt;
		... &lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=events=&lt;br /&gt;
Syntax is object&lt;br /&gt;
==Syntax Name==&lt;br /&gt;
===FileName===&lt;br /&gt;
::Event_{inputEventTag}&lt;br /&gt;
&lt;br /&gt;
===eventTag===&lt;br /&gt;
#inputEventTag&lt;br /&gt;
#outputEventTag&lt;br /&gt;
#dynamodbTag&lt;br /&gt;
&lt;br /&gt;
*file events.js is have eventTag  (inputEventTag,outputEventTag,dynamodbTag)&lt;br /&gt;
**How to create name eventTag&lt;br /&gt;
***Example case : &amp;quot;test in service complexFilter functionname ProcessComplexFilter case element type is logical basic&amp;quot;.&lt;br /&gt;
::*&#039;&#039;&#039;inputEventTag&#039;&#039;&#039;&lt;br /&gt;
::::{serviceName}_{functionName}_{caseTest}&lt;br /&gt;
&#039;&#039;Conplexfilter_ProcessComplexFilter_Typelogical_basic&#039;&#039;&lt;br /&gt;
::*&#039;&#039;&#039;outputEventTag&#039;&#039;&#039;&lt;br /&gt;
::::output_{inputEventTag}&lt;br /&gt;
&#039;&#039;output_Conplexfilter_ProcessComplexFilter_Typelogical_basic&#039;&#039;&lt;br /&gt;
::*&#039;&#039;&#039;dynamodbTag&#039;&#039;&#039;&lt;br /&gt;
::::{inputEventTag}__Dynamodb__{&#039;&#039;&#039;action*&#039;&#039;&#039;}_{tableName} &lt;br /&gt;
&#039;&#039;Conplexfilter_ProcessComplexFilter_Typelogical_basic___Dynamodb__putItem_filterMain&#039;&#039;&lt;br /&gt;
: &amp;lt;u&amp;gt;&#039;&#039;&#039;{action}&#039;&#039;&#039; is only &#039;&#039;put&#039;&#039; or &#039;&#039;update&#039;&#039;, and in case of &#039;&#039;update&#039;&#039; must only test the last step of update &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Syntax event===&lt;br /&gt;
====initiate by handlerServcie====&lt;br /&gt;
=====Sqs=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
// An example input and output event of Sns&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;LambdaFunctionHdrSqs_input__pass&amp;quot;:{&lt;br /&gt;
      &amp;quot;properties&amp;quot;:{&lt;br /&gt;
         &amp;quot;propertyA&amp;quot;:{&lt;br /&gt;
            &amp;quot;value&amp;quot;:&amp;quot;valueProperty1&amp;quot;&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;propertyB&amp;quot;:{&lt;br /&gt;
            &amp;quot;properties&amp;quot;:{&lt;br /&gt;
               &amp;quot;propertyB1&amp;quot;:{&lt;br /&gt;
                  &amp;quot;value&amp;quot;:&amp;quot;valuePropertyB1&amp;quot;&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;propertyC&amp;quot;:{&lt;br /&gt;
            &amp;quot;eventValue&amp;quot;:[&lt;br /&gt;
               &amp;quot;valuePropertyC1&amp;quot;,&lt;br /&gt;
               &amp;quot;valuePropertyC2&amp;quot;,&lt;br /&gt;
               &amp;quot;valuePropertyC3&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;snsSqsTrigger&amp;quot;:true,&lt;br /&gt;
      &amp;quot;messageAttributes&amp;quot;:{&lt;br /&gt;
            &amp;quot;msgTag&amp;quot;:{&lt;br /&gt;
               &amp;quot;value&amp;quot;:&amp;quot;msgTag&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;propertyD&amp;quot;:{&lt;br /&gt;
               &amp;quot;value&amp;quot;:&amp;quot;valuePropertyD&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      &amp;quot;output_LambdaFunctionHdrSqs_pass&amp;quot;:{&lt;br /&gt;
         &amp;quot;properties&amp;quot;:{&lt;br /&gt;
            &amp;quot;propertyA&amp;quot;:{&lt;br /&gt;
               &amp;quot;value&amp;quot;:&amp;quot;valueProperty1&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot; linein&amp;gt;&lt;br /&gt;
&amp;quot;snsSqsTrigger&amp;quot;:true&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Dsq=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
// An example input and output event of Direct Sqs&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;LambdaFunctionHdrDsq_input__pass&amp;quot;:{&lt;br /&gt;
      &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
      &amp;quot;properties&amp;quot;:{&lt;br /&gt;
         &amp;quot;propertyA&amp;quot;:{&lt;br /&gt;
            &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
            &amp;quot;value&amp;quot;:&amp;quot;valueProperty1&amp;quot;&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;propertyB&amp;quot;:{&lt;br /&gt;
            &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
            &amp;quot;properties&amp;quot;:{&lt;br /&gt;
               &amp;quot;propertyB1&amp;quot;:{&lt;br /&gt;
                  &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
                  &amp;quot;value&amp;quot;:&amp;quot;valuePropertyB1&amp;quot;&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;propertyC&amp;quot;:{&lt;br /&gt;
            &amp;quot;eventValue&amp;quot;:[&lt;br /&gt;
               &amp;quot;valuePropertyC1&amp;quot;,&lt;br /&gt;
               &amp;quot;valuePropertyC2&amp;quot;,&lt;br /&gt;
               &amp;quot;valuePropertyC3&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;DirectSqs&amp;quot;:true,&lt;br /&gt;
      &amp;quot;messageAttributes&amp;quot;:{&lt;br /&gt;
         &amp;quot;msgTag&amp;quot;:{&lt;br /&gt;
           &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
           &amp;quot;value&amp;quot;:&amp;quot;msgTag&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;propertyD&amp;quot;:{&lt;br /&gt;
           &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
           &amp;quot;value&amp;quot;:&amp;quot;valuePropertyD&amp;quot;&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      &amp;quot;output_LambdaFunctionHdrDsq_pass&amp;quot;:{&lt;br /&gt;
         &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
         &amp;quot;properties&amp;quot;:{&lt;br /&gt;
            &amp;quot;propertyA&amp;quot;:{&lt;br /&gt;
               &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
               &amp;quot;value&amp;quot;:&amp;quot;valueProperty1&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* DirectSqs = true &lt;br /&gt;
:: for initialStage of Dsq&lt;br /&gt;
* messageAttributes is optional&lt;br /&gt;
&lt;br /&gt;
=====Inv=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;LambdaFunctionHdrInv_input__pass&amp;quot;:{&lt;br /&gt;
     &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
     &amp;quot;properties&amp;quot;:{&lt;br /&gt;
        &amp;quot;propertyA&amp;quot;:{&lt;br /&gt;
           &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
           &amp;quot;value&amp;quot;:&amp;quot;valueProperty1&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;propertyB&amp;quot;:{&lt;br /&gt;
           &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
           &amp;quot;properties&amp;quot;:{&lt;br /&gt;
              &amp;quot;propertyB1&amp;quot;:{&lt;br /&gt;
                 &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
                 &amp;quot;value&amp;quot;:&amp;quot;valuePropertyB1&amp;quot;&lt;br /&gt;
              }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;output_LambdaFunctionHdrInv_pass&amp;quot;:{&lt;br /&gt;
           &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
           &amp;quot;properties&amp;quot;:{&lt;br /&gt;
              &amp;quot;propertyA&amp;quot;:{&lt;br /&gt;
                 &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
                 &amp;quot;value&amp;quot;:&amp;quot;valueProperty1&amp;quot;&lt;br /&gt;
              }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Api=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
// An example input and output event of API&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;LambdaFunctionHdrApi_input__pass_notTestAuthorizer&amp;quot;: { &lt;br /&gt;
		&amp;quot;forstageMatvhing&amp;quot;: true, &lt;br /&gt;
		&amp;quot;properties&amp;quot;: { &lt;br /&gt;
			&amp;quot;body&amp;quot;: { &lt;br /&gt;
				&amp;quot;properties&amp;quot;: { &lt;br /&gt;
					&amp;quot;propertyA&amp;quot;: { &lt;br /&gt;
						&amp;quot;testValueMatches&amp;quot;: false, &lt;br /&gt;
						&amp;quot;value&amp;quot;: &amp;quot;valueProperty1&amp;quot;, &lt;br /&gt;
					}, &lt;br /&gt;
					&amp;quot;propertyB&amp;quot;: { &lt;br /&gt;
						&amp;quot;properties&amp;quot;: { &lt;br /&gt;
							&amp;quot;propertyB1&amp;quot;: { &lt;br /&gt;
								&amp;quot;value&amp;quot;: &amp;quot;valuePropertyB1&amp;quot;, &lt;br /&gt;
							} &lt;br /&gt;
						} &lt;br /&gt;
					}, &lt;br /&gt;
					&amp;quot;propertyC&amp;quot;: { &lt;br /&gt;
						&amp;quot;eventValue&amp;quot;: [ &lt;br /&gt;
							&amp;quot;valuePropertyC1&amp;quot;, &lt;br /&gt;
							&amp;quot;valuePropertyC2&amp;quot;, &lt;br /&gt;
							&amp;quot;valuePropertyC3&amp;quot;, &lt;br /&gt;
						] &lt;br /&gt;
					},&lt;br /&gt;
					... &lt;br /&gt;
				} &lt;br /&gt;
			} &lt;br /&gt;
		}&lt;br /&gt;
	}, &lt;br /&gt;
	&amp;quot;Output_LambdaFunctionHdrApi_input__pass_notTestAuthorizer&amp;quot;: { &lt;br /&gt;
		&amp;quot;properties&amp;quot;: { &lt;br /&gt;
			&amp;quot;body&amp;quot;: { &lt;br /&gt;
				&amp;quot;properties&amp;quot;: { &lt;br /&gt;
					&amp;quot;propertyA&amp;quot;: { &lt;br /&gt;
						&amp;quot;testValueMatches&amp;quot;: false, &lt;br /&gt;
						&amp;quot;value&amp;quot;: &amp;quot;valueProperty1&amp;quot;&lt;br /&gt;
					}, &lt;br /&gt;
					...&lt;br /&gt;
				} &lt;br /&gt;
			} &lt;br /&gt;
		}  &lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====S3=====&lt;br /&gt;
&lt;br /&gt;
====dynamodb====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
// An example event of Dynamodb //optional &lt;br /&gt;
{&lt;br /&gt;
	{inputEventTag}__dynamodb_{action}_{tablename}: { // eg. &amp;quot;Complexfilter_ProcessComplexfilter_logical_basic__dynamodb_update_FilterMain&amp;quot;&lt;br /&gt;
	&amp;quot;forStageMatching&amp;quot;: true,&lt;br /&gt;
     &amp;quot;properties&amp;quot;: {&lt;br /&gt;
        &amp;quot;filterMainUniqueRequestId&amp;quot;: {&lt;br /&gt;
          &amp;quot;testValueMatches&amp;quot;: fase,&lt;br /&gt;
          &amp;quot;value&amp;quot;: &amp;quot;bbc4f4a9-2032-4dec-9129-8c7d169fecc5&amp;quot;&lt;br /&gt;
         },&lt;br /&gt;
        &amp;quot;filterObject&amp;quot;: {&lt;br /&gt;
        &amp;quot;forStageMatching&amp;quot;: true,&lt;br /&gt;
        &amp;quot;properties&amp;quot;: {&lt;br /&gt;
          &amp;quot;logicalType&amp;quot;: {&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;partitionKey&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;comparison&amp;quot;: {&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;equals&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;type&amp;quot;: {&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;logical&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;partitionKey&amp;quot;: {&lt;br /&gt;
            &amp;quot;forStageMatching&amp;quot;: true,&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;mockIntegratioTestCPF&amp;quot;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;filterMainExpiryTime&amp;quot;: {&lt;br /&gt;
        &amp;quot;testValueMatches&amp;quot;: fase,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1731980802858&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;filterMainStatus&amp;quot;: {&lt;br /&gt;
       &amp;quot;forStageMatching&amp;quot;: true,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;processing&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;createTime&amp;quot;: {&lt;br /&gt;
        &amp;quot;testValueMatches&amp;quot;: fase,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1731894402678&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;objType&amp;quot;: {&lt;br /&gt;
        &amp;quot;forStageMatching&amp;quot;: true,&lt;br /&gt;
        &amp;quot;properties&amp;quot;: {&lt;br /&gt;
          &amp;quot;serviceTag&amp;quot;: {&lt;br /&gt;
            &amp;quot;forStageMatching&amp;quot;: true,&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;IntTesting&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;objectType&amp;quot;: {&lt;br /&gt;
            &amp;quot;forStageMatching&amp;quot;: true,&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;TestRecord&amp;quot;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;keyValues&amp;quot;: {&lt;br /&gt;
      &amp;quot;filterMainId&amp;quot;: &amp;quot;4865d2451a621cb7f71225cfabf2df4f98e20801&amp;quot;,&lt;br /&gt;
      &amp;quot;objTypeId&amp;quot;: &amp;quot;cdb170690571df7522b3850920fce02507c077ee&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
	} &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* partition key: filterMainId&lt;br /&gt;
* sort key: objTypeId&lt;br /&gt;
&lt;br /&gt;
[[2021-01-15 - Integration Testing - Adding DynamoDB result tests]]&lt;br /&gt;
&lt;br /&gt;
===Type paramiter===&lt;br /&gt;
use for evnet and dyanmodb event&lt;br /&gt;
====Normal====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 object: {&lt;br /&gt;
  forStageMatching: true,&lt;br /&gt;
  properties: {&lt;br /&gt;
    name:{&lt;br /&gt;
     forStageMatching: true,&lt;br /&gt;
     value:&amp;quot;Tom&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
   }&lt;br /&gt;
 },&lt;br /&gt;
 array: {&lt;br /&gt;
  forStageMatching: true,&lt;br /&gt;
  useIsEqual: true,&lt;br /&gt;
  eventValue: [&lt;br /&gt;
   {&lt;br /&gt;
     &amp;quot;relTypeAndDirection&amp;quot;: {&lt;br /&gt;
       &amp;quot;relType&amp;quot;: {&lt;br /&gt;
         &amp;quot;serviceTag&amp;quot;: &amp;quot;maxxCart2&amp;quot;,&lt;br /&gt;
         &amp;quot;relationshipTag&amp;quot;: &amp;quot;hasCartOrder&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;relationshipDirection&amp;quot;: &amp;quot;from&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;targetObjects&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;objType&amp;quot;: {&lt;br /&gt;
           &amp;quot;serviceTag&amp;quot;: &amp;quot;maxxCart2&amp;quot;,&lt;br /&gt;
           &amp;quot;objectType&amp;quot;: &amp;quot;cartOrder&amp;quot;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
 },&lt;br /&gt;
 number: {&lt;br /&gt;
  forStageMatching: true,&lt;br /&gt;
  value: 1111&lt;br /&gt;
 },&lt;br /&gt;
 string: {&lt;br /&gt;
  forStageMatching: true,&lt;br /&gt;
  value: &amp;quot;hi&amp;quot;&lt;br /&gt;
 },&lt;br /&gt;
 boolean: {&lt;br /&gt;
  forStageMatching: true,&lt;br /&gt;
  value: true&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
 forStageMatching: true&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
::set true for check match value,It is not necessary to set every value&lt;br /&gt;
:::use in test importent paramiter&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
testValueMatches:false&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
::setting paramiter require on create but can not test random value eg: identifier or timeStamp or uuid&lt;br /&gt;
&lt;br /&gt;
====Empty====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
 EmptyString:{&lt;br /&gt;
forStageMatching: true,&lt;br /&gt;
  value:&amp;quot;&amp;quot;&lt;br /&gt;
 },&lt;br /&gt;
 EmptyArray:{&lt;br /&gt;
   forStageMatching: true,&lt;br /&gt;
   useIsEqual: true,&lt;br /&gt;
   eventValue: []&lt;br /&gt;
 },&lt;br /&gt;
 EmptyObject:{&lt;br /&gt;
  forStageMatching: true,&lt;br /&gt;
  value:{}&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Error====&lt;br /&gt;
can test noRetryError&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;quot;errorMessage&amp;quot;: {&lt;br /&gt;
    forStageMatching: true,&lt;br /&gt;
    &amp;quot;value&amp;quot;: &amp;quot;Not found schema of {serviceTag:TestGraphHandler, objectType:notFoundObjType}&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Paramiter random====&lt;br /&gt;
Can not test case random numbber or uuid.&lt;br /&gt;
But requriOnCreate mush be set &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
testValueMatches:false&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
or set&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
forStageMatching:false&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=tests=&lt;br /&gt;
Syntax is array of object&lt;br /&gt;
==Syntax name== &lt;br /&gt;
===Testtag name ===&lt;br /&gt;
*{integrationTestTag}&lt;br /&gt;
#Test Own servcie or not a lot stage&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
Test_{inputEventTag}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#Mix multiple servcie and multiple stage&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt; &lt;br /&gt;
IntegrationTest_{inputEventTag}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===File name ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt; &lt;br /&gt;
{integrationTestTag}.json&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Setting of test==&lt;br /&gt;
[[Service - Integration Test Config#tests.js Syntax|syntax test]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
            integrationTestTag: {integrationTestTag},&lt;br /&gt;
            productionSafe: true|false, //default false&lt;br /&gt;
            noInitialStage: true, // default false, if set to true, no error when no foundInitialStages found&lt;br /&gt;
            errorIfStageUndefined: true|false, //default false&lt;br /&gt;
            errorIfInvokeUndefined: true|false, //default false,&lt;br /&gt;
            dynamoDBSeedDataTags:[&amp;quot;seedDataDB_test_case_xx&amp;quot;], //[seedDataTag] optional if have seed data for test&lt;br /&gt;
            graphSeedDataTags:[&amp;quot;seedDataGraph_test_case_xx&amp;quot;], //[seedDataTag] optional if have seed data for test&lt;br /&gt;
            cleaningeDynamoOneRecordsTags: [&amp;quot;cleaningSeed_partitionKey_sortKey_normol&amp;quot;], //optional&lt;br /&gt;
            cleaningeDynamoManyRecordsTags: [], // optional&lt;br /&gt;
            stages:[&lt;br /&gt;
               ...&lt;br /&gt;
            ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*[[2025-11-20 IntegrationTest#dynamoDBSeedDataTags|dynamoDBSeedDataTags]]&lt;br /&gt;
*[[2025-11-20 IntegrationTest#graphSeedDataTags|graphSeedDataTags]]&lt;br /&gt;
*[[2025-11-20 IntegrationTest#cleaningeDynamoOneRecordsTags|cleaningeDynamoOneRecordsTags]]&lt;br /&gt;
*[[2025-11-20 IntegrationTest#cleaningeDynamoManyRecordsTags|cleaningeDynamoManyRecordsTags]]&lt;br /&gt;
&lt;br /&gt;
==Stages==&lt;br /&gt;
====Initiate stage====&lt;br /&gt;
:&#039;&#039;&#039;&amp;quot;initialStage&amp;quot;:true&#039;&#039;&#039;&lt;br /&gt;
[[Service_-_Integration_Test_Config#tests.js Syntax|detail property of test]]&lt;br /&gt;
=====HandlerService=====&lt;br /&gt;
======Sqs======&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;stages&amp;quot;:[&lt;br /&gt;
         {&lt;br /&gt;
            &amp;quot;initialStage&amp;quot;:true,&lt;br /&gt;
            &amp;quot;inputEventTag&amp;quot;:&amp;quot;Locations_ProcessLocationNodeSomting_casenotHaveData&amp;quot;,&lt;br /&gt;
            &amp;quot;serviceName&amp;quot;:&amp;quot;Locations&amp;quot;,&lt;br /&gt;
            &amp;quot;resourceType&amp;quot;:&amp;quot;Lambda&amp;quot;,&lt;br /&gt;
            &amp;quot;resourceName&amp;quot;:&amp;quot;ProcessLocationNodeSomtingHdrDsq&amp;quot;,&lt;br /&gt;
            &amp;quot;outputEventTag&amp;quot;:&amp;quot;Output_Locations_ProcessLocationNodeSomting_casenotHaveData&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
      ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
======Dsq======&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
stages: [&lt;br /&gt;
        {&lt;br /&gt;
          initialStage: true,&lt;br /&gt;
          inputEventTag: &#039;LambdaFunctionHdrDsq_input_singleStage_directSqs__pass&#039;,&lt;br /&gt;
          serviceName: &#039;ServiceTemplate&#039;,&lt;br /&gt;
          resourceType: &#039;Lambda&#039;,&lt;br /&gt;
          resourceName: &#039;LambdaFunctionHdrDsq&#039;,&lt;br /&gt;
          outputEventTag: &#039;LambdaFunctionHdrDsq_output__returnvalue_pass&#039;,&lt;br /&gt;
          // **** not set snsServiceName and snsTopic&lt;br /&gt;
          // can be test dynamodbOutput&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
======Api======&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;stages&amp;quot;:[&lt;br /&gt;
    {&lt;br /&gt;
       &amp;quot;initialStage&amp;quot;:true,&lt;br /&gt;
       &amp;quot;inputEventTag&amp;quot;:&amp;quot;LambdaFunctionHdrApi_input__pass&amp;quot;,&lt;br /&gt;
       &amp;quot;serviceName&amp;quot;:&amp;quot;ServiceTemplate&amp;quot;,&lt;br /&gt;
       &amp;quot;resourceType&amp;quot;:&amp;quot;Lambda&amp;quot;,&lt;br /&gt;
       &amp;quot;resourceName&amp;quot;:&amp;quot;LambdaFunctionHdrApi&amp;quot;,&lt;br /&gt;
       &amp;quot;outputEventTag&amp;quot;:&amp;quot;LambdaFunctionHdrApi_output__pass&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
======Inv======&lt;br /&gt;
*&#039;&#039;&#039;single stage&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
[{&lt;br /&gt;
   &amp;quot;integrationTestTag&amp;quot;:&amp;quot;LambdaFunctionHdrInv__pass&amp;quot;,&lt;br /&gt;
   &amp;quot;productionSafe&amp;quot;:false,&lt;br /&gt;
   &amp;quot;errorIfStageUndefined&amp;quot;:false,&lt;br /&gt;
   &amp;quot;errorIfInvokeUndefined&amp;quot;:false,&lt;br /&gt;
   &amp;quot;dynamoDBSeedDataTags&amp;quot;:[&amp;quot;seedDataDB_test_case_xx&amp;quot;], //[seedDataTag] optional if have seed data for test&lt;br /&gt;
   &amp;quot;graphSeedDataTags&amp;quot;:[&amp;quot;seedDataGraph_test_case_xx&amp;quot;], //[seedDataTag] optional if have seed data for test&lt;br /&gt;
   &amp;quot;cleaningeDynamoOneRecordsTags&amp;quot;: [&amp;quot;cleaningSeed_partitionKey_sortKey_normol&amp;quot;], //optional&lt;br /&gt;
   &amp;quot;cleaningeDynamoManyRecordsTags&amp;quot;: []&lt;br /&gt;
   &amp;quot;stages&amp;quot;:[&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;initialStage&amp;quot;:true,&lt;br /&gt;
         &amp;quot;inputEventTag&amp;quot;:&amp;quot;LambdaFunctionHdrInv_input__pass&amp;quot;,&lt;br /&gt;
         &amp;quot;serviceName&amp;quot;:&amp;quot;ServiceTemplate&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceType&amp;quot;:&amp;quot;Lambda&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceName&amp;quot;:&amp;quot;LambdaFunctionHdrInv&amp;quot;,&lt;br /&gt;
         &amp;quot;outputEventTag&amp;quot;:&amp;quot;LambdaFunctionHdrInv_output__pass&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;invoke multiple stage&#039;&#039;&#039; &lt;br /&gt;
:*Each stage test can invoke multiple lambda by use &amp;quot;eventStage Tag&amp;quot; point to stage for test integration test.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
[{&lt;br /&gt;
   &amp;quot;integrationTestTag&amp;quot;:&amp;quot;LambdaFunctionHdrInv_invokes__pass&amp;quot;,&lt;br /&gt;
   &amp;quot;productionSafe&amp;quot;:false,&lt;br /&gt;
   &amp;quot;errorIfStageUndefined&amp;quot;:false,&lt;br /&gt;
   &amp;quot;errorIfInvokeUndefined&amp;quot;:false,&lt;br /&gt;
   &amp;quot;dynamoDBSeedDataTags&amp;quot;:[], //[seedDataTag] optional if have seed data for test&lt;br /&gt;
   &amp;quot;graphSeedDataTags&amp;quot;:[], //[seedDataTag] optional if have seed data for test&lt;br /&gt;
   &amp;quot;cleaningeDynamoOneRecordsTags&amp;quot;: [], //optional&lt;br /&gt;
   &amp;quot;cleaningeDynamoManyRecordsTags&amp;quot;: [], // optional&lt;br /&gt;
   &amp;quot;stages&amp;quot;:[&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;initialStage&amp;quot;:true,&lt;br /&gt;
         &amp;quot;inputEventTag&amp;quot;:&amp;quot;LambdaFunctionHdrInv_input__pass&amp;quot;,&lt;br /&gt;
         &amp;quot;serviceName&amp;quot;:&amp;quot;ServiceTemplate&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceType&amp;quot;:&amp;quot;Lambda&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceName&amp;quot;:&amp;quot;LambdaFunctionHdrInv&amp;quot;,&lt;br /&gt;
         &amp;quot;outputEventTag&amp;quot;:&amp;quot;LambdaFunctionHdrInv_output__pass&amp;quot;,&lt;br /&gt;
         &amp;quot;invokes&amp;quot;:[&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;eventStageTag&amp;quot;:&amp;quot;service_invokesB__pass&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;eventStageTag&amp;quot;:&amp;quot;service_invokesD__pass&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
         ]&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;eventStageTag&amp;quot;:&amp;quot;service_invokesB__pass&amp;quot;,&lt;br /&gt;
         &amp;quot;inputEventTag&amp;quot;:&amp;quot;input_service_invokes__pass&amp;quot;,&lt;br /&gt;
         &amp;quot;serviceName&amp;quot;:&amp;quot;ServiceTemplate_B&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceType&amp;quot;:&amp;quot;Lambda&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceName&amp;quot;:&amp;quot;LambdaFunction_B_HdrInv&amp;quot;,&lt;br /&gt;
         &amp;quot;outputEventTag&amp;quot;:&amp;quot;output_service_invokes__pass&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;eventStageTag&amp;quot;:&amp;quot;service_invokesD__pass&amp;quot;,&lt;br /&gt;
         &amp;quot;inputEventTag&amp;quot;:&amp;quot;input_service_invokesD__pass&amp;quot;,&lt;br /&gt;
         &amp;quot;serviceName&amp;quot;:&amp;quot;ServiceTemplate_D&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceType&amp;quot;:&amp;quot;Lambda&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceName&amp;quot;:&amp;quot;LambdaFunction_D_HdrInv&amp;quot;,&lt;br /&gt;
         &amp;quot;outputEventTag&amp;quot;:&amp;quot;output_service_invokesD__pass&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
======S3======&lt;br /&gt;
======Batch======&lt;br /&gt;
&lt;br /&gt;
====GeneratedSeedData====&lt;br /&gt;
*Integrationtest must be delete identifier every time before test.&lt;br /&gt;
*Set &#039;generatedSeedData&#039; in file tests.json case by case of stage eg: stages[0] create identifier is randomOnCreate will set &#039;generatedSeedData&#039; and stages[1] create relationship is randomOnCreate(It is usually random, except in the case of relationship version) set generatedSeedData this stages[1].&lt;br /&gt;
*How to delete case identifier rendomOnCreate?: set in stage use setting generateSeedData &amp;quot;randomOnCreateIdentifier&amp;quot;&lt;br /&gt;
#randomOnCreateIdentifier&lt;br /&gt;
#notRandomOnIdentifier&lt;br /&gt;
#relationships&lt;br /&gt;
=====randomOnCreateIdentifier=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;stages&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;initialStage&amp;quot;: true,&lt;br /&gt;
        &amp;quot;inputEventTag&amp;quot;: &amp;quot;MLocation_CreateHdrSqs__case_NodeVersionData_Jaya&amp;quot;,&lt;br /&gt;
        &amp;quot;serviceTag&amp;quot;: &amp;quot;MLocations&amp;quot;,&lt;br /&gt;
        &amp;quot;resourceType&amp;quot;: &amp;quot;Lambda&amp;quot;,&lt;br /&gt;
        &amp;quot;resourceName&amp;quot;: &amp;quot;CreateHdrSqs&amp;quot;,&lt;br /&gt;
        &amp;quot;snsServiceName&amp;quot;: &amp;quot;MLocations&amp;quot;,&lt;br /&gt;
        &amp;quot;snsTopic&amp;quot;: &amp;quot;Create_In&amp;quot;,&lt;br /&gt;
        &amp;quot;generatedSeedData&amp;quot;: {&lt;br /&gt;
          &amp;quot;randomOnCreateIdentifier&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;objType&amp;quot;: {&lt;br /&gt;
                &amp;quot;serviceTag&amp;quot;: &amp;quot;MLocations&amp;quot;,&lt;br /&gt;
                &amp;quot;objectType&amp;quot;: &amp;quot;Member&amp;quot;&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;identifierValue&amp;quot;: &amp;quot;Jaya-member-001&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          ]&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=====notRandomOnIdentifier=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;quot;stages&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;initialStage&amp;quot;: true,&lt;br /&gt;
        &amp;quot;inputEventTag&amp;quot;: &amp;quot;MLocation_CreateHdrSqs__case_NodeVersionData_Jaya&amp;quot;,&lt;br /&gt;
        &amp;quot;serviceTag&amp;quot;: &amp;quot;MLocations&amp;quot;,&lt;br /&gt;
        &amp;quot;resourceType&amp;quot;: &amp;quot;Lambda&amp;quot;,&lt;br /&gt;
        &amp;quot;resourceName&amp;quot;: &amp;quot;CreateHdrSqs&amp;quot;,&lt;br /&gt;
        &amp;quot;snsServiceName&amp;quot;: &amp;quot;MLocations&amp;quot;,&lt;br /&gt;
        &amp;quot;snsTopic&amp;quot;: &amp;quot;Create_In&amp;quot;,&lt;br /&gt;
        &amp;quot;generatedSeedData&amp;quot;: {&lt;br /&gt;
          &amp;quot;notRandomOnIdentifier&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;objType&amp;quot;: {&lt;br /&gt;
                &amp;quot;serviceTag&amp;quot;: &amp;quot;gggg&amp;quot;,&lt;br /&gt;
                &amp;quot;objectType&amp;quot;: &amp;quot;ssssss&amp;quot;&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
                &amp;quot;topId&amp;quot;: &amp;quot;123456&amp;quot;&lt;br /&gt;
              }&lt;br /&gt;
            }&lt;br /&gt;
          ]&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=====relationships=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;quot;stages&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;initialStage&amp;quot;: true,&lt;br /&gt;
        &amp;quot;inputEventTag&amp;quot;: &amp;quot;MLocation_CreateHdrSqs__case_NodeVersionData_Jaya&amp;quot;,&lt;br /&gt;
        &amp;quot;serviceTag&amp;quot;: &amp;quot;MLocations&amp;quot;,&lt;br /&gt;
        &amp;quot;resourceType&amp;quot;: &amp;quot;Lambda&amp;quot;,&lt;br /&gt;
        &amp;quot;resourceName&amp;quot;: &amp;quot;CreateHdrSqs&amp;quot;,&lt;br /&gt;
        &amp;quot;snsServiceName&amp;quot;: &amp;quot;MLocations&amp;quot;,&lt;br /&gt;
        &amp;quot;snsTopic&amp;quot;: &amp;quot;Create_In&amp;quot;,&lt;br /&gt;
        &amp;quot;generatedSeedData&amp;quot;: {&lt;br /&gt;
         &amp;quot;relationships&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;relType&amp;quot;: {&lt;br /&gt;
                &amp;quot;serviceTag&amp;quot;: &amp;quot;PaymentMethodGeneric&amp;quot;,&lt;br /&gt;
                &amp;quot;relationshipTag&amp;quot;: &amp;quot;disabledPaymentMethodGenericPropertyValue&amp;quot;&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;relId&amp;quot;: &amp;quot;f4f73de7-647c-4b3b-8043-87cc002f361a&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          ]&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Dynamodb==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
stages: [&lt;br /&gt;
        {&lt;br /&gt;
          initialStage: true,&lt;br /&gt;
          inputEventTag: &#039;Locations_LambdaFunctionHdrDsq_singleStage_directSqs__pass&#039;,&lt;br /&gt;
          serviceName: &#039;ServiceTemplate&#039;,&lt;br /&gt;
          resourceType: &#039;Lambda&#039;,&lt;br /&gt;
          resourceName: &#039;LambdaFunctionHdrDsq&#039;,&lt;br /&gt;
          outputEventTag: &#039;output_Locations_LambdaFunctionHdrDsq_singleStage_directSqs__pass&#039;,&lt;br /&gt;
          dynamodbOutputEventIdentifiers: [&lt;br /&gt;
			{&lt;br /&gt;
              serviceName: {tableName}, //service that deployed the DynamoDB table, so can build table&#039;s full resource name&lt;br /&gt;
              resourceName: {resourceName}, //DynamoDB resourceName&lt;br /&gt;
              eventTag: {eventTagDynamoDB}&lt;br /&gt;
		    }&lt;br /&gt;
          ],&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Result of integrationtest =&lt;br /&gt;
Data have 2 table &amp;quot;TestRecord&amp;quot; and &amp;quot;TestUnit&amp;quot;.&lt;br /&gt;
:- TestRecord is table all unti of stage inside eg input output invokes and dynamodb&lt;br /&gt;
:- TestUnit is store status each unit &lt;br /&gt;
each unit save in table TestUnit&lt;br /&gt;
testRecordId is  name of test concat with testTime.&lt;br /&gt;
testUnitId is point to position of unti instage.&lt;br /&gt;
resultStatus is status of unit.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
eg:&lt;br /&gt;
input_0 = stages index 0 result &#039;&#039;&#039;input&#039;&#039;&#039;&lt;br /&gt;
output_1 = stages index 1 result &#039;&#039;&#039;output&#039;&#039;&#039;&lt;br /&gt;
invokeInput_0_1 = stages index 0 result &#039;&#039;&#039;invokes&#039;&#039;&#039; index 1 position input &lt;br /&gt;
invokeOutput_0_1 = stages index 0 result &#039;&#039;&#039;invokes&#039;&#039;&#039; index 1 position output&lt;br /&gt;
dynamodb_0_1 =  stages index 0 result &#039;&#039;&#039;dynamodb&#039;&#039;&#039; index 1.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
after all TestUnit finish (check  by awaitingMultiplestep penditnStep is integrationtestTag awaitingStepId is each TestUnit )&lt;br /&gt;
check all awaitingStep finish send message to ultimateIntegrationtest for sumla all test is status&lt;br /&gt;
&lt;br /&gt;
== Summary of test status == &lt;br /&gt;
:1.testStatus is &amp;quot;passed&amp;quot; all unit passed.&lt;br /&gt;
:2.testStatus is &amp;quot;failed&amp;quot;  have some is failed.&lt;br /&gt;
:3.testStatus is &amp;quot;processing&amp;quot; have some is have status processing after check all awaiting step is finish.&lt;br /&gt;
:4.testStatus is &amp;quot;failed&amp;quot; have record &amp;quot;errorsTest&amp;quot; in case &amp;quot;not match stage invoke&amp;quot;, &#039;found multiple matchingInvokes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*[[2025-02-20 - Integration Test examples#tests.js Syntax|Syntax Dynamodb]]&lt;br /&gt;
&lt;br /&gt;
=How to test integrationtest s3=&lt;br /&gt;
[[Developer guide for making Integration Tests]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Working documents| 2025-11-20]]&lt;br /&gt;
[[Category:Working documents - Integration Testing| 2025-11-20]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=2025-11-20_IntegrationTest&amp;diff=4575</id>
		<title>2025-11-20 IntegrationTest</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=2025-11-20_IntegrationTest&amp;diff=4575"/>
		<updated>2026-08-11T13:07:48Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: /* dynamoDBSeedDataTags */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Reference:&lt;br /&gt;
&lt;br /&gt;
*[[2020-10-01 - Integration Test Config - Functions|IntegrationtestConfig]]&lt;br /&gt;
*[[2020-10-01 - Integration Testing - Lambda Functions|Integrationtesting]]&lt;br /&gt;
*[[2025-02-20 - Integration Test examples|Example]]&lt;br /&gt;
&lt;br /&gt;
= File extension =&lt;br /&gt;
&lt;br /&gt;
uploadS3: &amp;quot;.json&amp;quot;&lt;br /&gt;
integrationtestConfig: &amp;quot;.js&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=TestRecord=&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JSON&amp;quot;&amp;gt;&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    integrationTestTag: &amp;quot;Integrationtest_xx&amp;quot;,&lt;br /&gt;
    testStartedTimestamp: 111111111, // start time&lt;br /&gt;
    bucketName: &amp;quot;integrationtest-config-us-east-2&amp;quot;,&lt;br /&gt;
    lastUpdateUniqueRequestId: &amp;quot;sssss&amp;quot;, //_izContext.uniqueRequestId protacts race coditionn dynamodb&lt;br /&gt;
    testStatus: &amp;quot;passed&amp;quot;,//failed,processing,passed&lt;br /&gt;
    testCompleteTimestamp: 1111113, // all test finish&lt;br /&gt;
    stages: [&lt;br /&gt;
      {&lt;br /&gt;
        stageConfig: {&lt;br /&gt;
          //straight copy of this stage from integration test config&lt;br /&gt;
          inputEventTag: &amp;quot;xx&amp;quot;,&lt;br /&gt;
          inputEventConfig: {//event input&lt;br /&gt;
          },&lt;br /&gt;
          outputEventTag: &amp;quot;output_xx&amp;quot;,&lt;br /&gt;
          outputEventConfig: {//event out put&lt;br /&gt;
          },&lt;br /&gt;
          resourceName: &amp;quot;ComplexfilterTestProcessComplexfilter&amp;quot;,// function name&lt;br /&gt;
          resourceType: &amp;quot;Lambda&amp;quot;, // function name&lt;br /&gt;
          serviceTag: &amp;quot;Complexfilter&amp;quot;,// (initeate sqs)&lt;br /&gt;
          snsServiceName: &amp;quot;Complexfilter&amp;quot;,// (initeate sqs)&lt;br /&gt;
          snsTopic: &amp;quot;PorcessComplexfilter_In&amp;quot;// (initeate sqs)&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
        stageStatus: &amp;quot;waiting&amp;quot;, //waiting|passed|failed,&lt;br /&gt;
        stageFinishedTimestamp: 111111111,// time that all tests finished and testRecord.stages.{stageKey}.stageStatus updated&lt;br /&gt;
        stageResults: {&lt;br /&gt;
          //results at the point of entering the resource (eg a Lambda function is invoked)&lt;br /&gt;
          inputResult: {&lt;br /&gt;
            resultTimestamp: 111111111,//{time result saved},&lt;br /&gt;
            resultStatus: &amp;quot;passed&amp;quot;,//passed|failed,&lt;br /&gt;
            requestParams: {//event input&lt;br /&gt;
            }&lt;br /&gt;
          },&lt;br /&gt;
          //results at the point of returning from the resource (eg a Lambda function returns)&lt;br /&gt;
          outputResult: {&lt;br /&gt;
            resultTimestamp: 111111111,//{time result saved},&lt;br /&gt;
            resultStatus: &amp;quot;passed&amp;quot;,//passed|failed,&lt;br /&gt;
            requestParams: {//event input&lt;br /&gt;
            }&lt;br /&gt;
          },&lt;br /&gt;
          //results at the point of invoking an external resource (eg the tested Lambda function is invoking another Lambda function)&lt;br /&gt;
          invokes: {&lt;br /&gt;
            &amp;quot;serviceName_resourceType_resourceName_inputEventTag &amp;quot;: {&lt;br /&gt;
              invokeTimestamp: 111111111,//{ time result saved },&lt;br /&gt;
              resultTimestamp: 111111112,//{ time result saved },&lt;br /&gt;
              resultStatus: &amp;quot;passed&amp;quot;,//passed | failed,&lt;br /&gt;
              invokeParams: {},//{event invoke input config }&lt;br /&gt;
              requestParams: {}// event invoke input request&lt;br /&gt;
            },&lt;br /&gt;
          },&lt;br /&gt;
          dynamodbResults: [&lt;br /&gt;
            {&lt;br /&gt;
              indexOfDynamodbOutput: 0,&lt;br /&gt;
              requestParams,&lt;br /&gt;
              resultStatus: &amp;quot;passed&amp;quot;,//&lt;br /&gt;
              resultTimestamp: 22222&lt;br /&gt;
            }]&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
        stageErrors: [&lt;br /&gt;
          //misc errors encountered&lt;br /&gt;
        ]&lt;br /&gt;
      }]&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Seed Data=&lt;br /&gt;
integrationtest manager seed date 2 process&lt;br /&gt;
&lt;br /&gt;
=== Main Seed Data===&lt;br /&gt;
:Save file in s3 (in &#039;&#039;&#039;buckname&#039;&#039;&#039; :integrationtest-config-us-east-2, &#039;&#039;&#039;folder&#039;&#039;&#039;:seedData_integrationTest).For other dev use service,If a developer wants to add more for other important testing purposes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;How to use:&#039;&#039;&#039;&lt;br /&gt;
#Add it from the s3 bucket at this point&lt;br /&gt;
#Run batch refreshSeedData [[Developer guide for making Integration Tests#Bash script|batch RefreshSeedData]]&lt;br /&gt;
&#039;&#039;&#039;Logic&#039;&#039;&#039;:Process by storage resouse (graph or dynamodb)&lt;br /&gt;
:To clean up the seed data in the table after it creates seed data form service deploy and pulls seed data from s3.&lt;br /&gt;
&lt;br /&gt;
=== Refresh Seed Data ===&lt;br /&gt;
:ProcessRefreshSeedData use seedDataTag for create data environment of &#039;&#039;&#039;test&#039;&#039;&#039; and can be refresh seeddata re-test agian.&lt;br /&gt;
:&#039;&#039;&#039;canbe share&#039;&#039;&#039; seed data for other test by seed data tag.&lt;br /&gt;
&#039;&#039;&#039;How to use:&#039;&#039;&#039;&lt;br /&gt;
:Save file in s3 (for other dav keep in floder dev name) or testConfig/seedData_config(for admin)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Folder&#039;&#039;&#039;&lt;br /&gt;
*dynamoDBSeedDataTags.json&lt;br /&gt;
*graphSeedDataTags.json&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example&#039;&#039;&#039;&lt;br /&gt;
==== dynamoDBSeedDataTags ====&lt;br /&gt;
:If set tag in this setting integrationtest is generate seed data. in storage resource dynammodb.&lt;br /&gt;
Example&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;seedDynamodb_abc_ver2&amp;quot;: [ // seedDataTag&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;tableName&amp;quot;: &amp;quot;DelivMethodSTDTestLogicalResultsData&amp;quot;,  // servcieTag+stage+tablename&lt;br /&gt;
      &amp;quot;partitionKey&amp;quot;: &amp;quot;logicalResultId&amp;quot;,&lt;br /&gt;
      &amp;quot;sortKey&amp;quot;: &amp;quot;identifiersId&amp;quot;,&lt;br /&gt;
      &amp;quot;datas&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          logicalResultId: {&lt;br /&gt;
            value: &amp;quot;eeeeeeeeee4&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          identifiersId: {&lt;br /&gt;
            value: &amp;quot;lllll123456&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          processLogicalResultExpiryTimestamp: {&lt;br /&gt;
            calcType: &amp;quot;currentTimestampAdjustment&amp;quot;, // can add other types of calculated data in future&lt;br /&gt;
            action: &amp;quot;subtract&amp;quot;, // add|subtract&lt;br /&gt;
            adjustment: &amp;quot;2 days&amp;quot;, // Human-Readable Relative Format&lt;br /&gt;
          }&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          logicalResultId: {&lt;br /&gt;
            value: &amp;quot;eeeeeeeeee4&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;identifiersId&amp;quot;: {&lt;br /&gt;
            value: &amp;quot;lllll777777&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          processLogicalResultExpiryTimestamp: {&lt;br /&gt;
            calcType: &amp;quot;currentTimestampAdjustment&amp;quot;, // can add other types of calculated data in future&lt;br /&gt;
            action: &amp;quot;add&amp;quot;, // add|subtract&lt;br /&gt;
            adjustment: &amp;quot;2 days&amp;quot;, // Human-Readable Relative Format&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;tableName&amp;quot;: &amp;quot;MLocationsTestFloatingRelationships&amp;quot;,// servcieTag+stage+tablename&lt;br /&gt;
      &amp;quot;partitionKey&amp;quot;: &amp;quot;importBatchId&amp;quot;,&lt;br /&gt;
      &amp;quot;sortKey&amp;quot;: &amp;quot;identifierRelationshipsId&amp;quot;,&lt;br /&gt;
      &amp;quot;datas&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;importBatchId&amp;quot;: &amp;quot;2-uuuuuuuuuuuuuu&amp;quot;,&lt;br /&gt;
          &amp;quot;identifierRelationshipsId&amp;quot;: &amp;quot;lllll123456&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;importBatchId&amp;quot;: &amp;quot;2-uuuuuuuuuuuuuu&amp;quot;,&lt;br /&gt;
          &amp;quot;identifierRelationshipsId&amp;quot;: &amp;quot;lllll777777&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;importBatchId&amp;quot;: &amp;quot;2-uuuuuuuuuuuuuu&amp;quot;,&lt;br /&gt;
          &amp;quot;identifierRelationshipsId&amp;quot;: &amp;quot;lllll99999999&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;tableName&amp;quot;: &amp;quot;MLocationsTestFindDataMain&amp;quot;,&lt;br /&gt;
      &amp;quot;partitionKey&amp;quot;: &amp;quot;findDataId&amp;quot;,&lt;br /&gt;
      &amp;quot;datas&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;findDataId&amp;quot;: &amp;quot;111111&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;findDataId&amp;quot;: &amp;quot;22222&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;findDataId&amp;quot;: &amp;quot;333333&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== graphSeedDataTags ====&lt;br /&gt;
:If set tag in this setting integrationtest is generate seed data. in storage resource graphHanler.&lt;br /&gt;
Example&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;seedData_testTag_GG&amp;quot;: [ // seedDataTag&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;nodes&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;nodeLabels&amp;quot;: [&lt;br /&gt;
            &amp;quot;SellOfferPlan_sellOfferPlanDeliveryMethodLink&amp;quot;&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;objectDetail&amp;quot;: {&lt;br /&gt;
            &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
              &amp;quot;sellOfferPlanDeliveryMethodLinkId&amp;quot;: {&lt;br /&gt;
				        &amp;quot;value&amp;quot;: &amp;quot;minttestrefreshSeedData_01&amp;quot;,&lt;br /&gt;
		      		},&lt;br /&gt;
			      },&lt;br /&gt;
            &amp;quot;fields&amp;quot;: {&lt;br /&gt;
              &amp;quot;productId&amp;quot;: {&lt;br /&gt;
				        &amp;quot;value&amp;quot;: &amp;quot;ddddd&amp;quot;,&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;price&amp;quot;: {&lt;br /&gt;
				        &amp;quot;value&amp;quot;: 9999&lt;br /&gt;
              },&lt;br /&gt;
              exampleTimestamp:{&lt;br /&gt;
                calcType: &amp;quot;currentTimestampAdjustment&amp;quot;, // can add other types of calculated data in future&lt;br /&gt;
                action: &amp;quot;subtract&amp;quot;, // add|subtract&lt;br /&gt;
                adjustment: &amp;quot;2 days&amp;quot;, // Human-Readable Relative Format&lt;br /&gt;
              }&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;nodeLabels&amp;quot;: [&lt;br /&gt;
            &amp;quot;servcieMintTest_shoppingMall&amp;quot;&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;objectDetail&amp;quot;: {&lt;br /&gt;
            &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
              &amp;quot;shoppingMallId&amp;quot;: &amp;quot;minttestrefreshSeedData_shoppingMallId&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;fields&amp;quot;: {&lt;br /&gt;
              &amp;quot;name&amp;quot;: &amp;quot;hotpot-man&amp;quot;,&lt;br /&gt;
              &amp;quot;totalPrice&amp;quot;: 500&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;nodeLabels&amp;quot;: [&lt;br /&gt;
            &amp;quot;servcieMintTest_shoppingMallCalculateSetting&amp;quot;&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;objectDetail&amp;quot;: {&lt;br /&gt;
            &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
              &amp;quot;versionedDataId&amp;quot;: &amp;quot;minttestrefreshSeedData_versionedDataId&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;fields&amp;quot;: {&lt;br /&gt;
              &amp;quot;addToCalculatedValuePerOrder&amp;quot;: 10,&lt;br /&gt;
              &amp;quot;addToRateTableValuePerOrder&amp;quot;: 77&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;relationships&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;fromObject&amp;quot;: {&lt;br /&gt;
            &amp;quot;nodeLabel&amp;quot;: &amp;quot;SellOfferPlan_sellOfferPlanDeliveryMethodLink&amp;quot;,&lt;br /&gt;
            &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
              &amp;quot;sellOfferPlanDeliveryMethodLinkId&amp;quot;: &amp;quot;minttestrefreshSeedData_01&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;toObject&amp;quot;: {&lt;br /&gt;
            &amp;quot;nodeLabel&amp;quot;: &amp;quot;servcieMintTest_shoppingMall&amp;quot;,&lt;br /&gt;
            &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
              &amp;quot;shoppingMallId&amp;quot;: &amp;quot;minttestrefreshSeedData_shoppingMallId&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;relationships&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;relTypeConcat&amp;quot;: &amp;quot;SellOfferPlan_hasCCCCCCC&amp;quot;,&lt;br /&gt;
              &amp;quot;relId&amp;quot;: &amp;quot;uuid-4s56df74s9df79w-w6de4f5w689ef&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          ]&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;fromObject&amp;quot;: {&lt;br /&gt;
            &amp;quot;nodeLabel&amp;quot;: &amp;quot;servcieMintTest_shoppingMall&amp;quot;,&lt;br /&gt;
            &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
              &amp;quot;shoppingMallId&amp;quot;: &amp;quot;minttestrefreshSeedData_shoppingMallId&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;toObject&amp;quot;: {&lt;br /&gt;
            &amp;quot;nodeLabel&amp;quot;: &amp;quot;servcieMintTest_shoppingMallCalculateSetting&amp;quot;,&lt;br /&gt;
            &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
              &amp;quot;versionedDataId&amp;quot;: &amp;quot;minttestrefreshSeedData_versionedDataId&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;relationships&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;relTypeConcat&amp;quot;: &amp;quot;servcieMintTest_shoppingMall_currentShoppingMallCalculateSetting&amp;quot;,&lt;br /&gt;
              &amp;quot;relId&amp;quot;: &amp;quot;uuid-s122df5-s21df&amp;quot;,&lt;br /&gt;
              &amp;quot;relationshipProperty&amp;quot;: {&lt;br /&gt;
                &amp;quot;timeStamp&amp;quot;: 1234567879,&lt;br /&gt;
                &amp;quot;statusName&amp;quot;: true&lt;br /&gt;
              }&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;relTypeConcat&amp;quot;: &amp;quot;servcieMintTest_shoppingMall_hasShoppingMallCalculateSetting&amp;quot;,&lt;br /&gt;
              &amp;quot;relId&amp;quot;: &amp;quot;uuid-77777-99999&amp;quot;,&lt;br /&gt;
              &amp;quot;relationshipProperties&amp;quot;: {&lt;br /&gt;
                &amp;quot;statusName&amp;quot;: {&lt;br /&gt;
                  &amp;quot;value&amp;quot;: true&lt;br /&gt;
                },&lt;br /&gt;
                exampleTimestamp:{&lt;br /&gt;
                  calcType: &amp;quot;currentTimestampAdjustment&amp;quot;, // can add other types of calculated data in future&lt;br /&gt;
                  action: &amp;quot;subtract&amp;quot;, // add|subtract&lt;br /&gt;
                  adjustment: &amp;quot;2 days&amp;quot;, // Human-Readable Relative Format&lt;br /&gt;
                }                &lt;br /&gt;
              }&lt;br /&gt;
            }&lt;br /&gt;
          ]&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;seedData_testTag_ABC&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;objType&amp;quot;: {&lt;br /&gt;
        &amp;quot;objectType&amp;quot;: &amp;quot;productAttributeLink&amp;quot;,&lt;br /&gt;
        &amp;quot;serviceTag&amp;quot;: &amp;quot;ProductAttribute&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;objInstanceFull&amp;quot;: {&lt;br /&gt;
        &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
          &amp;quot;productAttributeLinkId&amp;quot;: &amp;quot;f90b57ca8b2fe1a83459d57da038cf50fb6d40e6&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;fields&amp;quot;: {}&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;relationships&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;relType&amp;quot;: {&lt;br /&gt;
            &amp;quot;serviceTag&amp;quot;: &amp;quot;ProductAttribute&amp;quot;,&lt;br /&gt;
            &amp;quot;relationshipTag&amp;quot;: &amp;quot;hasProductAttributeLink&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;relationshipDirection&amp;quot;: &amp;quot;to&amp;quot;,&lt;br /&gt;
          &amp;quot;targetObjType&amp;quot;: {&lt;br /&gt;
            &amp;quot;serviceTag&amp;quot;: &amp;quot;ProductStandard&amp;quot;,&lt;br /&gt;
            &amp;quot;objectType&amp;quot;: &amp;quot;productStandard&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;targetIdentifiers&amp;quot;: {&lt;br /&gt;
            &amp;quot;productId&amp;quot;: &amp;quot;f526a367a2b66cb0f37ca61b6c43f419929f521d&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;relationshipProperties&amp;quot;: {}&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;relType&amp;quot;: {&lt;br /&gt;
            &amp;quot;serviceTag&amp;quot;: &amp;quot;ProductAttribute&amp;quot;,&lt;br /&gt;
            &amp;quot;relationshipTag&amp;quot;: &amp;quot;isProductAttribute&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;relationshipDirection&amp;quot;: &amp;quot;from&amp;quot;,&lt;br /&gt;
          &amp;quot;targetObjType&amp;quot;: {&lt;br /&gt;
            &amp;quot;serviceTag&amp;quot;: &amp;quot;ProductAttribute&amp;quot;,&lt;br /&gt;
            &amp;quot;objectType&amp;quot;: &amp;quot;productAttribute&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;targetIdentifiers&amp;quot;: {&lt;br /&gt;
            &amp;quot;productAttributeId&amp;quot;: &amp;quot;f4bf7a078071d54036656df544197ba638bc3a68&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;relationshipProperties&amp;quot;: {}&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;objType&amp;quot;: {&lt;br /&gt;
        &amp;quot;objectType&amp;quot;: &amp;quot;productAttributeLink&amp;quot;,&lt;br /&gt;
        &amp;quot;serviceTag&amp;quot;: &amp;quot;ProductAttribute&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;objInstanceFull&amp;quot;: {&lt;br /&gt;
        &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
          &amp;quot;productAttributeLinkId&amp;quot;: &amp;quot;f90b57ca8b2fe1a83459d57da038cf50fb6d40e6&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;fields&amp;quot;: {}&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;relationships&amp;quot;: []&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;seedData_testTag_LL&amp;quot;: []&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cleaning Seed Data ===&lt;br /&gt;
:Delete seed data for set environment of &#039;&#039;&#039;test&#039;&#039;&#039;.&lt;br /&gt;
*cleaningeDynamoOneRecordsTags.json&lt;br /&gt;
*cleaningeDynamoManyRecordsTags.json&lt;br /&gt;
&lt;br /&gt;
====cleaningeDynamoOneRecordsTags====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;cleaningSeed_TestFindData_and_Education_case_invalid01&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;tableName&amp;quot;: &amp;quot;MLocationsTestFindDataMain&amp;quot;,&lt;br /&gt;
      &amp;quot;primaryKeys&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;findDataId&amp;quot;: &amp;quot;cleaning-1&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;findDataId&amp;quot;: &amp;quot;cleaning-2&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;tableName&amp;quot;: &amp;quot;MLocationsTestEducation&amp;quot;,&lt;br /&gt;
      &amp;quot;primaryKeys&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;studentId&amp;quot;: &amp;quot;cleaning-AA&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;studentId&amp;quot;: &amp;quot;cleaning-BB&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;studentId&amp;quot;: &amp;quot;cleaning-CC&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;cleaningSeed_TestMemberPersonnel_case_invalid01&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;tableName&amp;quot;: &amp;quot;MLocationsTestMemberPersonnel&amp;quot;,&lt;br /&gt;
      &amp;quot;primaryKeys&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;userId&amp;quot;: &amp;quot;namtan&amp;quot;,&lt;br /&gt;
          &amp;quot;passwordId&amp;quot;: &amp;quot;qqqww&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;userId&amp;quot;: &amp;quot;jack&amp;quot;,&lt;br /&gt;
          &amp;quot;passwordId&amp;quot;: &amp;quot;q1&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;userId&amp;quot;: &amp;quot;Momay&amp;quot;,&lt;br /&gt;
          &amp;quot;passwordId&amp;quot;: &amp;quot;ttr&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== cleaningeDynamoManyRecordsTags ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;cleaningSeed_manyData_partitionKey_only_miss_sort&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;tableName&amp;quot;: &amp;quot;MLocationsTestMemberPersonnel&amp;quot;,&lt;br /&gt;
      &amp;quot;primaryKeys&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;userId&amp;quot;: &amp;quot;many-data&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*logic query table MLocationsTestMemberPersonnel use primary Keys &amp;quot;userId&amp;quot; and then delete all data from primary Keys.&lt;br /&gt;
&lt;br /&gt;
=resources=&lt;br /&gt;
syntax is object&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{ &lt;br /&gt;
	&amp;quot;Lambda&amp;quot;:{&lt;br /&gt;
		&amp;quot;{FunctionNameHdrSqs}&amp;quot;:{ // FunctionNameHdrSqs is match resourceName in file tests&lt;br /&gt;
			&amp;quot;localLacation&amp;quot;:&amp;quot;/src/FunctionNameHdrSqs.js&amp;quot;,&lt;br /&gt;
			&amp;quot;localHandler&amp;quot;:&amp;quot;main&amp;quot;, &lt;br /&gt;
			&amp;quot;functionName&amp;quot;:&amp;quot;FunctionNameHdrSqs&amp;quot;	// FunctionName is function name match key of function.yml of servcie.&lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;ProcessComplexFilterHdrSqs&amp;quot;:{ &lt;br /&gt;
			&amp;quot;localLacation&amp;quot;:&amp;quot;/src/ProcessComplexFilterHdrSqs.js&amp;quot;, &lt;br /&gt;
			&amp;quot;localHandler&amp;quot;:&amp;quot;main&amp;quot;, &lt;br /&gt;
			&amp;quot;functionName&amp;quot;:&amp;quot;ProcessComplexFilterHdrSqs&amp;quot; &lt;br /&gt;
		},&lt;br /&gt;
		... &lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;Dynamodb&amp;quot;: {&lt;br /&gt;
		&amp;quot;filterMain&amp;quot;:{ // match resourceName in file tests(dynamodbOutputEventIdentifiers)&lt;br /&gt;
			&amp;quot;tableName&amp;quot;:&amp;quot;filterMain&amp;quot; &lt;br /&gt;
		}, &lt;br /&gt;
		&amp;quot;tableNameBB&amp;quot;:{ &lt;br /&gt;
			&amp;quot;tableName&amp;quot;:&amp;quot;tableNameBB&amp;quot; &lt;br /&gt;
		},&lt;br /&gt;
		... &lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=events=&lt;br /&gt;
Syntax is object&lt;br /&gt;
==Syntax Name==&lt;br /&gt;
===FileName===&lt;br /&gt;
::Event_{inputEventTag}&lt;br /&gt;
&lt;br /&gt;
===eventTag===&lt;br /&gt;
#inputEventTag&lt;br /&gt;
#outputEventTag&lt;br /&gt;
#dynamodbTag&lt;br /&gt;
&lt;br /&gt;
*file events.js is have eventTag  (inputEventTag,outputEventTag,dynamodbTag)&lt;br /&gt;
**How to create name eventTag&lt;br /&gt;
***Example case : &amp;quot;test in service complexFilter functionname ProcessComplexFilter case element type is logical basic&amp;quot;.&lt;br /&gt;
::*&#039;&#039;&#039;inputEventTag&#039;&#039;&#039;&lt;br /&gt;
::::{serviceName}_{functionName}_{caseTest}&lt;br /&gt;
&#039;&#039;Conplexfilter_ProcessComplexFilter_Typelogical_basic&#039;&#039;&lt;br /&gt;
::*&#039;&#039;&#039;outputEventTag&#039;&#039;&#039;&lt;br /&gt;
::::output_{inputEventTag}&lt;br /&gt;
&#039;&#039;output_Conplexfilter_ProcessComplexFilter_Typelogical_basic&#039;&#039;&lt;br /&gt;
::*&#039;&#039;&#039;dynamodbTag&#039;&#039;&#039;&lt;br /&gt;
::::{inputEventTag}__Dynamodb__{&#039;&#039;&#039;action*&#039;&#039;&#039;}_{tableName} &lt;br /&gt;
&#039;&#039;Conplexfilter_ProcessComplexFilter_Typelogical_basic___Dynamodb__putItem_filterMain&#039;&#039;&lt;br /&gt;
: &amp;lt;u&amp;gt;&#039;&#039;&#039;{action}&#039;&#039;&#039; is only &#039;&#039;put&#039;&#039; or &#039;&#039;update&#039;&#039;, and in case of &#039;&#039;update&#039;&#039; must only test the last step of update &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Syntax event===&lt;br /&gt;
====initiate by handlerServcie====&lt;br /&gt;
=====Sqs=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
// An example input and output event of Sns&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;LambdaFunctionHdrSqs_input__pass&amp;quot;:{&lt;br /&gt;
      &amp;quot;properties&amp;quot;:{&lt;br /&gt;
         &amp;quot;propertyA&amp;quot;:{&lt;br /&gt;
            &amp;quot;value&amp;quot;:&amp;quot;valueProperty1&amp;quot;&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;propertyB&amp;quot;:{&lt;br /&gt;
            &amp;quot;properties&amp;quot;:{&lt;br /&gt;
               &amp;quot;propertyB1&amp;quot;:{&lt;br /&gt;
                  &amp;quot;value&amp;quot;:&amp;quot;valuePropertyB1&amp;quot;&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;propertyC&amp;quot;:{&lt;br /&gt;
            &amp;quot;eventValue&amp;quot;:[&lt;br /&gt;
               &amp;quot;valuePropertyC1&amp;quot;,&lt;br /&gt;
               &amp;quot;valuePropertyC2&amp;quot;,&lt;br /&gt;
               &amp;quot;valuePropertyC3&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;snsSqsTrigger&amp;quot;:true,&lt;br /&gt;
      &amp;quot;messageAttributes&amp;quot;:{&lt;br /&gt;
            &amp;quot;msgTag&amp;quot;:{&lt;br /&gt;
               &amp;quot;value&amp;quot;:&amp;quot;msgTag&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;propertyD&amp;quot;:{&lt;br /&gt;
               &amp;quot;value&amp;quot;:&amp;quot;valuePropertyD&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
      }&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      &amp;quot;output_LambdaFunctionHdrSqs_pass&amp;quot;:{&lt;br /&gt;
         &amp;quot;properties&amp;quot;:{&lt;br /&gt;
            &amp;quot;propertyA&amp;quot;:{&lt;br /&gt;
               &amp;quot;value&amp;quot;:&amp;quot;valueProperty1&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot; linein&amp;gt;&lt;br /&gt;
&amp;quot;snsSqsTrigger&amp;quot;:true&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Dsq=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
// An example input and output event of Direct Sqs&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;LambdaFunctionHdrDsq_input__pass&amp;quot;:{&lt;br /&gt;
      &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
      &amp;quot;properties&amp;quot;:{&lt;br /&gt;
         &amp;quot;propertyA&amp;quot;:{&lt;br /&gt;
            &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
            &amp;quot;value&amp;quot;:&amp;quot;valueProperty1&amp;quot;&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;propertyB&amp;quot;:{&lt;br /&gt;
            &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
            &amp;quot;properties&amp;quot;:{&lt;br /&gt;
               &amp;quot;propertyB1&amp;quot;:{&lt;br /&gt;
                  &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
                  &amp;quot;value&amp;quot;:&amp;quot;valuePropertyB1&amp;quot;&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;propertyC&amp;quot;:{&lt;br /&gt;
            &amp;quot;eventValue&amp;quot;:[&lt;br /&gt;
               &amp;quot;valuePropertyC1&amp;quot;,&lt;br /&gt;
               &amp;quot;valuePropertyC2&amp;quot;,&lt;br /&gt;
               &amp;quot;valuePropertyC3&amp;quot;&lt;br /&gt;
            ]&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;DirectSqs&amp;quot;:true,&lt;br /&gt;
      &amp;quot;messageAttributes&amp;quot;:{&lt;br /&gt;
         &amp;quot;msgTag&amp;quot;:{&lt;br /&gt;
           &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
           &amp;quot;value&amp;quot;:&amp;quot;msgTag&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;propertyD&amp;quot;:{&lt;br /&gt;
           &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
           &amp;quot;value&amp;quot;:&amp;quot;valuePropertyD&amp;quot;&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      &amp;quot;output_LambdaFunctionHdrDsq_pass&amp;quot;:{&lt;br /&gt;
         &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
         &amp;quot;properties&amp;quot;:{&lt;br /&gt;
            &amp;quot;propertyA&amp;quot;:{&lt;br /&gt;
               &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
               &amp;quot;value&amp;quot;:&amp;quot;valueProperty1&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* DirectSqs = true &lt;br /&gt;
:: for initialStage of Dsq&lt;br /&gt;
* messageAttributes is optional&lt;br /&gt;
&lt;br /&gt;
=====Inv=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;LambdaFunctionHdrInv_input__pass&amp;quot;:{&lt;br /&gt;
     &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
     &amp;quot;properties&amp;quot;:{&lt;br /&gt;
        &amp;quot;propertyA&amp;quot;:{&lt;br /&gt;
           &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
           &amp;quot;value&amp;quot;:&amp;quot;valueProperty1&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;propertyB&amp;quot;:{&lt;br /&gt;
           &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
           &amp;quot;properties&amp;quot;:{&lt;br /&gt;
              &amp;quot;propertyB1&amp;quot;:{&lt;br /&gt;
                 &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
                 &amp;quot;value&amp;quot;:&amp;quot;valuePropertyB1&amp;quot;&lt;br /&gt;
              }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;output_LambdaFunctionHdrInv_pass&amp;quot;:{&lt;br /&gt;
           &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
           &amp;quot;properties&amp;quot;:{&lt;br /&gt;
              &amp;quot;propertyA&amp;quot;:{&lt;br /&gt;
                 &amp;quot;forStageMatching&amp;quot;:true,&lt;br /&gt;
                 &amp;quot;value&amp;quot;:&amp;quot;valueProperty1&amp;quot;&lt;br /&gt;
              }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Api=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
// An example input and output event of API&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;LambdaFunctionHdrApi_input__pass_notTestAuthorizer&amp;quot;: { &lt;br /&gt;
		&amp;quot;forstageMatvhing&amp;quot;: true, &lt;br /&gt;
		&amp;quot;properties&amp;quot;: { &lt;br /&gt;
			&amp;quot;body&amp;quot;: { &lt;br /&gt;
				&amp;quot;properties&amp;quot;: { &lt;br /&gt;
					&amp;quot;propertyA&amp;quot;: { &lt;br /&gt;
						&amp;quot;testValueMatches&amp;quot;: false, &lt;br /&gt;
						&amp;quot;value&amp;quot;: &amp;quot;valueProperty1&amp;quot;, &lt;br /&gt;
					}, &lt;br /&gt;
					&amp;quot;propertyB&amp;quot;: { &lt;br /&gt;
						&amp;quot;properties&amp;quot;: { &lt;br /&gt;
							&amp;quot;propertyB1&amp;quot;: { &lt;br /&gt;
								&amp;quot;value&amp;quot;: &amp;quot;valuePropertyB1&amp;quot;, &lt;br /&gt;
							} &lt;br /&gt;
						} &lt;br /&gt;
					}, &lt;br /&gt;
					&amp;quot;propertyC&amp;quot;: { &lt;br /&gt;
						&amp;quot;eventValue&amp;quot;: [ &lt;br /&gt;
							&amp;quot;valuePropertyC1&amp;quot;, &lt;br /&gt;
							&amp;quot;valuePropertyC2&amp;quot;, &lt;br /&gt;
							&amp;quot;valuePropertyC3&amp;quot;, &lt;br /&gt;
						] &lt;br /&gt;
					},&lt;br /&gt;
					... &lt;br /&gt;
				} &lt;br /&gt;
			} &lt;br /&gt;
		}&lt;br /&gt;
	}, &lt;br /&gt;
	&amp;quot;Output_LambdaFunctionHdrApi_input__pass_notTestAuthorizer&amp;quot;: { &lt;br /&gt;
		&amp;quot;properties&amp;quot;: { &lt;br /&gt;
			&amp;quot;body&amp;quot;: { &lt;br /&gt;
				&amp;quot;properties&amp;quot;: { &lt;br /&gt;
					&amp;quot;propertyA&amp;quot;: { &lt;br /&gt;
						&amp;quot;testValueMatches&amp;quot;: false, &lt;br /&gt;
						&amp;quot;value&amp;quot;: &amp;quot;valueProperty1&amp;quot;&lt;br /&gt;
					}, &lt;br /&gt;
					...&lt;br /&gt;
				} &lt;br /&gt;
			} &lt;br /&gt;
		}  &lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====S3=====&lt;br /&gt;
&lt;br /&gt;
====dynamodb====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
// An example event of Dynamodb //optional &lt;br /&gt;
{&lt;br /&gt;
	{inputEventTag}__dynamodb_{action}_{tablename}: { // eg. &amp;quot;Complexfilter_ProcessComplexfilter_logical_basic__dynamodb_update_FilterMain&amp;quot;&lt;br /&gt;
	&amp;quot;forStageMatching&amp;quot;: true,&lt;br /&gt;
     &amp;quot;properties&amp;quot;: {&lt;br /&gt;
        &amp;quot;filterMainUniqueRequestId&amp;quot;: {&lt;br /&gt;
          &amp;quot;testValueMatches&amp;quot;: fase,&lt;br /&gt;
          &amp;quot;value&amp;quot;: &amp;quot;bbc4f4a9-2032-4dec-9129-8c7d169fecc5&amp;quot;&lt;br /&gt;
         },&lt;br /&gt;
        &amp;quot;filterObject&amp;quot;: {&lt;br /&gt;
        &amp;quot;forStageMatching&amp;quot;: true,&lt;br /&gt;
        &amp;quot;properties&amp;quot;: {&lt;br /&gt;
          &amp;quot;logicalType&amp;quot;: {&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;partitionKey&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;comparison&amp;quot;: {&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;equals&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;type&amp;quot;: {&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;logical&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;partitionKey&amp;quot;: {&lt;br /&gt;
            &amp;quot;forStageMatching&amp;quot;: true,&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;mockIntegratioTestCPF&amp;quot;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;filterMainExpiryTime&amp;quot;: {&lt;br /&gt;
        &amp;quot;testValueMatches&amp;quot;: fase,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1731980802858&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;filterMainStatus&amp;quot;: {&lt;br /&gt;
       &amp;quot;forStageMatching&amp;quot;: true,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;processing&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;createTime&amp;quot;: {&lt;br /&gt;
        &amp;quot;testValueMatches&amp;quot;: fase,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1731894402678&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;objType&amp;quot;: {&lt;br /&gt;
        &amp;quot;forStageMatching&amp;quot;: true,&lt;br /&gt;
        &amp;quot;properties&amp;quot;: {&lt;br /&gt;
          &amp;quot;serviceTag&amp;quot;: {&lt;br /&gt;
            &amp;quot;forStageMatching&amp;quot;: true,&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;IntTesting&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;objectType&amp;quot;: {&lt;br /&gt;
            &amp;quot;forStageMatching&amp;quot;: true,&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;TestRecord&amp;quot;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;keyValues&amp;quot;: {&lt;br /&gt;
      &amp;quot;filterMainId&amp;quot;: &amp;quot;4865d2451a621cb7f71225cfabf2df4f98e20801&amp;quot;,&lt;br /&gt;
      &amp;quot;objTypeId&amp;quot;: &amp;quot;cdb170690571df7522b3850920fce02507c077ee&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
	} &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* partition key: filterMainId&lt;br /&gt;
* sort key: objTypeId&lt;br /&gt;
&lt;br /&gt;
[[2021-01-15 - Integration Testing - Adding DynamoDB result tests]]&lt;br /&gt;
&lt;br /&gt;
===Type paramiter===&lt;br /&gt;
use for evnet and dyanmodb event&lt;br /&gt;
====Normal====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 object: {&lt;br /&gt;
  forStageMatching: true,&lt;br /&gt;
  properties: {&lt;br /&gt;
    name:{&lt;br /&gt;
     forStageMatching: true,&lt;br /&gt;
     value:&amp;quot;Tom&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
   }&lt;br /&gt;
 },&lt;br /&gt;
 array: {&lt;br /&gt;
  forStageMatching: true,&lt;br /&gt;
  useIsEqual: true,&lt;br /&gt;
  eventValue: [&lt;br /&gt;
   {&lt;br /&gt;
     &amp;quot;relTypeAndDirection&amp;quot;: {&lt;br /&gt;
       &amp;quot;relType&amp;quot;: {&lt;br /&gt;
         &amp;quot;serviceTag&amp;quot;: &amp;quot;maxxCart2&amp;quot;,&lt;br /&gt;
         &amp;quot;relationshipTag&amp;quot;: &amp;quot;hasCartOrder&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;relationshipDirection&amp;quot;: &amp;quot;from&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;targetObjects&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;objType&amp;quot;: {&lt;br /&gt;
           &amp;quot;serviceTag&amp;quot;: &amp;quot;maxxCart2&amp;quot;,&lt;br /&gt;
           &amp;quot;objectType&amp;quot;: &amp;quot;cartOrder&amp;quot;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
 },&lt;br /&gt;
 number: {&lt;br /&gt;
  forStageMatching: true,&lt;br /&gt;
  value: 1111&lt;br /&gt;
 },&lt;br /&gt;
 string: {&lt;br /&gt;
  forStageMatching: true,&lt;br /&gt;
  value: &amp;quot;hi&amp;quot;&lt;br /&gt;
 },&lt;br /&gt;
 boolean: {&lt;br /&gt;
  forStageMatching: true,&lt;br /&gt;
  value: true&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
 forStageMatching: true&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
::set true for check match value,It is not necessary to set every value&lt;br /&gt;
:::use in test importent paramiter&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
testValueMatches:false&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
::setting paramiter require on create but can not test random value eg: identifier or timeStamp or uuid&lt;br /&gt;
&lt;br /&gt;
====Empty====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
 EmptyString:{&lt;br /&gt;
forStageMatching: true,&lt;br /&gt;
  value:&amp;quot;&amp;quot;&lt;br /&gt;
 },&lt;br /&gt;
 EmptyArray:{&lt;br /&gt;
   forStageMatching: true,&lt;br /&gt;
   useIsEqual: true,&lt;br /&gt;
   eventValue: []&lt;br /&gt;
 },&lt;br /&gt;
 EmptyObject:{&lt;br /&gt;
  forStageMatching: true,&lt;br /&gt;
  value:{}&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Error====&lt;br /&gt;
can test noRetryError&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;quot;errorMessage&amp;quot;: {&lt;br /&gt;
    forStageMatching: true,&lt;br /&gt;
    &amp;quot;value&amp;quot;: &amp;quot;Not found schema of {serviceTag:TestGraphHandler, objectType:notFoundObjType}&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Paramiter random====&lt;br /&gt;
Can not test case random numbber or uuid.&lt;br /&gt;
But requriOnCreate mush be set &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
testValueMatches:false&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
or set&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
forStageMatching:false&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=tests=&lt;br /&gt;
Syntax is array of object&lt;br /&gt;
==Syntax name== &lt;br /&gt;
===Testtag name ===&lt;br /&gt;
*{integrationTestTag}&lt;br /&gt;
#Test Own servcie or not a lot stage&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
Test_{inputEventTag}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#Mix multiple servcie and multiple stage&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt; &lt;br /&gt;
IntegrationTest_{inputEventTag}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===File name ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt; &lt;br /&gt;
{integrationTestTag}.json&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Setting of test==&lt;br /&gt;
[[Service - Integration Test Config#tests.js Syntax|syntax test]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
            integrationTestTag: {integrationTestTag},&lt;br /&gt;
            productionSafe: true|false, //default false&lt;br /&gt;
            noInitialStage: true, // default false, if set to true, no error when no foundInitialStages found&lt;br /&gt;
            errorIfStageUndefined: true|false, //default false&lt;br /&gt;
            errorIfInvokeUndefined: true|false, //default false,&lt;br /&gt;
            dynamoDBSeedDataTags:[&amp;quot;seedDataDB_test_case_xx&amp;quot;], //[seedDataTag] optional if have seed data for test&lt;br /&gt;
            graphSeedDataTags:[&amp;quot;seedDataGraph_test_case_xx&amp;quot;], //[seedDataTag] optional if have seed data for test&lt;br /&gt;
            cleaningeDynamoOneRecordsTags: [&amp;quot;cleaningSeed_partitionKey_sortKey_normol&amp;quot;], //optional&lt;br /&gt;
            cleaningeDynamoManyRecordsTags: [], // optional&lt;br /&gt;
            stages:[&lt;br /&gt;
               ...&lt;br /&gt;
            ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*[[2025-11-20 IntegrationTest#dynamoDBSeedDataTags|dynamoDBSeedDataTags]]&lt;br /&gt;
*[[2025-11-20 IntegrationTest#graphSeedDataTags|graphSeedDataTags]]&lt;br /&gt;
*[[2025-11-20 IntegrationTest#cleaningeDynamoOneRecordsTags|cleaningeDynamoOneRecordsTags]]&lt;br /&gt;
*[[2025-11-20 IntegrationTest#cleaningeDynamoManyRecordsTags|cleaningeDynamoManyRecordsTags]]&lt;br /&gt;
&lt;br /&gt;
==Stages==&lt;br /&gt;
====Initiate stage====&lt;br /&gt;
:&#039;&#039;&#039;&amp;quot;initialStage&amp;quot;:true&#039;&#039;&#039;&lt;br /&gt;
[[Service_-_Integration_Test_Config#tests.js Syntax|detail property of test]]&lt;br /&gt;
=====HandlerService=====&lt;br /&gt;
======Sqs======&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;stages&amp;quot;:[&lt;br /&gt;
         {&lt;br /&gt;
            &amp;quot;initialStage&amp;quot;:true,&lt;br /&gt;
            &amp;quot;inputEventTag&amp;quot;:&amp;quot;Locations_ProcessLocationNodeSomting_casenotHaveData&amp;quot;,&lt;br /&gt;
            &amp;quot;serviceName&amp;quot;:&amp;quot;Locations&amp;quot;,&lt;br /&gt;
            &amp;quot;resourceType&amp;quot;:&amp;quot;Lambda&amp;quot;,&lt;br /&gt;
            &amp;quot;resourceName&amp;quot;:&amp;quot;ProcessLocationNodeSomtingHdrDsq&amp;quot;,&lt;br /&gt;
            &amp;quot;outputEventTag&amp;quot;:&amp;quot;Output_Locations_ProcessLocationNodeSomting_casenotHaveData&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
      ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
======Dsq======&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
stages: [&lt;br /&gt;
        {&lt;br /&gt;
          initialStage: true,&lt;br /&gt;
          inputEventTag: &#039;LambdaFunctionHdrDsq_input_singleStage_directSqs__pass&#039;,&lt;br /&gt;
          serviceName: &#039;ServiceTemplate&#039;,&lt;br /&gt;
          resourceType: &#039;Lambda&#039;,&lt;br /&gt;
          resourceName: &#039;LambdaFunctionHdrDsq&#039;,&lt;br /&gt;
          outputEventTag: &#039;LambdaFunctionHdrDsq_output__returnvalue_pass&#039;,&lt;br /&gt;
          // **** not set snsServiceName and snsTopic&lt;br /&gt;
          // can be test dynamodbOutput&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
======Api======&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;stages&amp;quot;:[&lt;br /&gt;
    {&lt;br /&gt;
       &amp;quot;initialStage&amp;quot;:true,&lt;br /&gt;
       &amp;quot;inputEventTag&amp;quot;:&amp;quot;LambdaFunctionHdrApi_input__pass&amp;quot;,&lt;br /&gt;
       &amp;quot;serviceName&amp;quot;:&amp;quot;ServiceTemplate&amp;quot;,&lt;br /&gt;
       &amp;quot;resourceType&amp;quot;:&amp;quot;Lambda&amp;quot;,&lt;br /&gt;
       &amp;quot;resourceName&amp;quot;:&amp;quot;LambdaFunctionHdrApi&amp;quot;,&lt;br /&gt;
       &amp;quot;outputEventTag&amp;quot;:&amp;quot;LambdaFunctionHdrApi_output__pass&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
======Inv======&lt;br /&gt;
*&#039;&#039;&#039;single stage&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
[{&lt;br /&gt;
   &amp;quot;integrationTestTag&amp;quot;:&amp;quot;LambdaFunctionHdrInv__pass&amp;quot;,&lt;br /&gt;
   &amp;quot;productionSafe&amp;quot;:false,&lt;br /&gt;
   &amp;quot;errorIfStageUndefined&amp;quot;:false,&lt;br /&gt;
   &amp;quot;errorIfInvokeUndefined&amp;quot;:false,&lt;br /&gt;
   &amp;quot;dynamoDBSeedDataTags&amp;quot;:[&amp;quot;seedDataDB_test_case_xx&amp;quot;], //[seedDataTag] optional if have seed data for test&lt;br /&gt;
   &amp;quot;graphSeedDataTags&amp;quot;:[&amp;quot;seedDataGraph_test_case_xx&amp;quot;], //[seedDataTag] optional if have seed data for test&lt;br /&gt;
   &amp;quot;cleaningeDynamoOneRecordsTags&amp;quot;: [&amp;quot;cleaningSeed_partitionKey_sortKey_normol&amp;quot;], //optional&lt;br /&gt;
   &amp;quot;cleaningeDynamoManyRecordsTags&amp;quot;: []&lt;br /&gt;
   &amp;quot;stages&amp;quot;:[&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;initialStage&amp;quot;:true,&lt;br /&gt;
         &amp;quot;inputEventTag&amp;quot;:&amp;quot;LambdaFunctionHdrInv_input__pass&amp;quot;,&lt;br /&gt;
         &amp;quot;serviceName&amp;quot;:&amp;quot;ServiceTemplate&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceType&amp;quot;:&amp;quot;Lambda&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceName&amp;quot;:&amp;quot;LambdaFunctionHdrInv&amp;quot;,&lt;br /&gt;
         &amp;quot;outputEventTag&amp;quot;:&amp;quot;LambdaFunctionHdrInv_output__pass&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;invoke multiple stage&#039;&#039;&#039; &lt;br /&gt;
:*Each stage test can invoke multiple lambda by use &amp;quot;eventStage Tag&amp;quot; point to stage for test integration test.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
[{&lt;br /&gt;
   &amp;quot;integrationTestTag&amp;quot;:&amp;quot;LambdaFunctionHdrInv_invokes__pass&amp;quot;,&lt;br /&gt;
   &amp;quot;productionSafe&amp;quot;:false,&lt;br /&gt;
   &amp;quot;errorIfStageUndefined&amp;quot;:false,&lt;br /&gt;
   &amp;quot;errorIfInvokeUndefined&amp;quot;:false,&lt;br /&gt;
   &amp;quot;dynamoDBSeedDataTags&amp;quot;:[], //[seedDataTag] optional if have seed data for test&lt;br /&gt;
   &amp;quot;graphSeedDataTags&amp;quot;:[], //[seedDataTag] optional if have seed data for test&lt;br /&gt;
   &amp;quot;cleaningeDynamoOneRecordsTags&amp;quot;: [], //optional&lt;br /&gt;
   &amp;quot;cleaningeDynamoManyRecordsTags&amp;quot;: [], // optional&lt;br /&gt;
   &amp;quot;stages&amp;quot;:[&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;initialStage&amp;quot;:true,&lt;br /&gt;
         &amp;quot;inputEventTag&amp;quot;:&amp;quot;LambdaFunctionHdrInv_input__pass&amp;quot;,&lt;br /&gt;
         &amp;quot;serviceName&amp;quot;:&amp;quot;ServiceTemplate&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceType&amp;quot;:&amp;quot;Lambda&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceName&amp;quot;:&amp;quot;LambdaFunctionHdrInv&amp;quot;,&lt;br /&gt;
         &amp;quot;outputEventTag&amp;quot;:&amp;quot;LambdaFunctionHdrInv_output__pass&amp;quot;,&lt;br /&gt;
         &amp;quot;invokes&amp;quot;:[&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;eventStageTag&amp;quot;:&amp;quot;service_invokesB__pass&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;eventStageTag&amp;quot;:&amp;quot;service_invokesD__pass&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
         ]&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;eventStageTag&amp;quot;:&amp;quot;service_invokesB__pass&amp;quot;,&lt;br /&gt;
         &amp;quot;inputEventTag&amp;quot;:&amp;quot;input_service_invokes__pass&amp;quot;,&lt;br /&gt;
         &amp;quot;serviceName&amp;quot;:&amp;quot;ServiceTemplate_B&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceType&amp;quot;:&amp;quot;Lambda&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceName&amp;quot;:&amp;quot;LambdaFunction_B_HdrInv&amp;quot;,&lt;br /&gt;
         &amp;quot;outputEventTag&amp;quot;:&amp;quot;output_service_invokes__pass&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;eventStageTag&amp;quot;:&amp;quot;service_invokesD__pass&amp;quot;,&lt;br /&gt;
         &amp;quot;inputEventTag&amp;quot;:&amp;quot;input_service_invokesD__pass&amp;quot;,&lt;br /&gt;
         &amp;quot;serviceName&amp;quot;:&amp;quot;ServiceTemplate_D&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceType&amp;quot;:&amp;quot;Lambda&amp;quot;,&lt;br /&gt;
         &amp;quot;resourceName&amp;quot;:&amp;quot;LambdaFunction_D_HdrInv&amp;quot;,&lt;br /&gt;
         &amp;quot;outputEventTag&amp;quot;:&amp;quot;output_service_invokesD__pass&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
======S3======&lt;br /&gt;
======Batch======&lt;br /&gt;
&lt;br /&gt;
====GeneratedSeedData====&lt;br /&gt;
*Integrationtest must be delete identifier every time before test.&lt;br /&gt;
*Set &#039;generatedSeedData&#039; in file tests.json case by case of stage eg: stages[0] create identifier is randomOnCreate will set &#039;generatedSeedData&#039; and stages[1] create relationship is randomOnCreate(It is usually random, except in the case of relationship version) set generatedSeedData this stages[1].&lt;br /&gt;
*How to delete case identifier rendomOnCreate?: set in stage use setting generateSeedData &amp;quot;randomOnCreateIdentifier&amp;quot;&lt;br /&gt;
#randomOnCreateIdentifier&lt;br /&gt;
#notRandomOnIdentifier&lt;br /&gt;
#relationships&lt;br /&gt;
=====randomOnCreateIdentifier=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;stages&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;initialStage&amp;quot;: true,&lt;br /&gt;
        &amp;quot;inputEventTag&amp;quot;: &amp;quot;MLocation_CreateHdrSqs__case_NodeVersionData_Jaya&amp;quot;,&lt;br /&gt;
        &amp;quot;serviceTag&amp;quot;: &amp;quot;MLocations&amp;quot;,&lt;br /&gt;
        &amp;quot;resourceType&amp;quot;: &amp;quot;Lambda&amp;quot;,&lt;br /&gt;
        &amp;quot;resourceName&amp;quot;: &amp;quot;CreateHdrSqs&amp;quot;,&lt;br /&gt;
        &amp;quot;snsServiceName&amp;quot;: &amp;quot;MLocations&amp;quot;,&lt;br /&gt;
        &amp;quot;snsTopic&amp;quot;: &amp;quot;Create_In&amp;quot;,&lt;br /&gt;
        &amp;quot;generatedSeedData&amp;quot;: {&lt;br /&gt;
          &amp;quot;randomOnCreateIdentifier&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;objType&amp;quot;: {&lt;br /&gt;
                &amp;quot;serviceTag&amp;quot;: &amp;quot;MLocations&amp;quot;,&lt;br /&gt;
                &amp;quot;objectType&amp;quot;: &amp;quot;Member&amp;quot;&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;identifierValue&amp;quot;: &amp;quot;Jaya-member-001&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          ]&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=====notRandomOnIdentifier=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;quot;stages&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;initialStage&amp;quot;: true,&lt;br /&gt;
        &amp;quot;inputEventTag&amp;quot;: &amp;quot;MLocation_CreateHdrSqs__case_NodeVersionData_Jaya&amp;quot;,&lt;br /&gt;
        &amp;quot;serviceTag&amp;quot;: &amp;quot;MLocations&amp;quot;,&lt;br /&gt;
        &amp;quot;resourceType&amp;quot;: &amp;quot;Lambda&amp;quot;,&lt;br /&gt;
        &amp;quot;resourceName&amp;quot;: &amp;quot;CreateHdrSqs&amp;quot;,&lt;br /&gt;
        &amp;quot;snsServiceName&amp;quot;: &amp;quot;MLocations&amp;quot;,&lt;br /&gt;
        &amp;quot;snsTopic&amp;quot;: &amp;quot;Create_In&amp;quot;,&lt;br /&gt;
        &amp;quot;generatedSeedData&amp;quot;: {&lt;br /&gt;
          &amp;quot;notRandomOnIdentifier&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;objType&amp;quot;: {&lt;br /&gt;
                &amp;quot;serviceTag&amp;quot;: &amp;quot;gggg&amp;quot;,&lt;br /&gt;
                &amp;quot;objectType&amp;quot;: &amp;quot;ssssss&amp;quot;&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;identifiers&amp;quot;: {&lt;br /&gt;
                &amp;quot;topId&amp;quot;: &amp;quot;123456&amp;quot;&lt;br /&gt;
              }&lt;br /&gt;
            }&lt;br /&gt;
          ]&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=====relationships=====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;quot;stages&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;initialStage&amp;quot;: true,&lt;br /&gt;
        &amp;quot;inputEventTag&amp;quot;: &amp;quot;MLocation_CreateHdrSqs__case_NodeVersionData_Jaya&amp;quot;,&lt;br /&gt;
        &amp;quot;serviceTag&amp;quot;: &amp;quot;MLocations&amp;quot;,&lt;br /&gt;
        &amp;quot;resourceType&amp;quot;: &amp;quot;Lambda&amp;quot;,&lt;br /&gt;
        &amp;quot;resourceName&amp;quot;: &amp;quot;CreateHdrSqs&amp;quot;,&lt;br /&gt;
        &amp;quot;snsServiceName&amp;quot;: &amp;quot;MLocations&amp;quot;,&lt;br /&gt;
        &amp;quot;snsTopic&amp;quot;: &amp;quot;Create_In&amp;quot;,&lt;br /&gt;
        &amp;quot;generatedSeedData&amp;quot;: {&lt;br /&gt;
         &amp;quot;relationships&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;relType&amp;quot;: {&lt;br /&gt;
                &amp;quot;serviceTag&amp;quot;: &amp;quot;PaymentMethodGeneric&amp;quot;,&lt;br /&gt;
                &amp;quot;relationshipTag&amp;quot;: &amp;quot;disabledPaymentMethodGenericPropertyValue&amp;quot;&lt;br /&gt;
              },&lt;br /&gt;
              &amp;quot;relId&amp;quot;: &amp;quot;f4f73de7-647c-4b3b-8043-87cc002f361a&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
          ]&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Dynamodb==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
stages: [&lt;br /&gt;
        {&lt;br /&gt;
          initialStage: true,&lt;br /&gt;
          inputEventTag: &#039;Locations_LambdaFunctionHdrDsq_singleStage_directSqs__pass&#039;,&lt;br /&gt;
          serviceName: &#039;ServiceTemplate&#039;,&lt;br /&gt;
          resourceType: &#039;Lambda&#039;,&lt;br /&gt;
          resourceName: &#039;LambdaFunctionHdrDsq&#039;,&lt;br /&gt;
          outputEventTag: &#039;output_Locations_LambdaFunctionHdrDsq_singleStage_directSqs__pass&#039;,&lt;br /&gt;
          dynamodbOutputEventIdentifiers: [&lt;br /&gt;
			{&lt;br /&gt;
              serviceName: {tableName}, //service that deployed the DynamoDB table, so can build table&#039;s full resource name&lt;br /&gt;
              resourceName: {resourceName}, //DynamoDB resourceName&lt;br /&gt;
              eventTag: {eventTagDynamoDB}&lt;br /&gt;
		    }&lt;br /&gt;
          ],&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Result of integrationtest =&lt;br /&gt;
Data have 2 table &amp;quot;TestRecord&amp;quot; and &amp;quot;TestUnit&amp;quot;.&lt;br /&gt;
:- TestRecord is table all unti of stage inside eg input output invokes and dynamodb&lt;br /&gt;
:- TestUnit is store status each unit &lt;br /&gt;
each unit save in table TestUnit&lt;br /&gt;
testRecordId is  name of test concat with testTime.&lt;br /&gt;
testUnitId is point to position of unti instage.&lt;br /&gt;
resultStatus is status of unit.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
eg:&lt;br /&gt;
input_0 = stages index 0 result &#039;&#039;&#039;input&#039;&#039;&#039;&lt;br /&gt;
output_1 = stages index 1 result &#039;&#039;&#039;output&#039;&#039;&#039;&lt;br /&gt;
invokeInput_0_1 = stages index 0 result &#039;&#039;&#039;invokes&#039;&#039;&#039; index 1 position input &lt;br /&gt;
invokeOutput_0_1 = stages index 0 result &#039;&#039;&#039;invokes&#039;&#039;&#039; index 1 position output&lt;br /&gt;
dynamodb_0_1 =  stages index 0 result &#039;&#039;&#039;dynamodb&#039;&#039;&#039; index 1.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
after all TestUnit finish (check  by awaitingMultiplestep penditnStep is integrationtestTag awaitingStepId is each TestUnit )&lt;br /&gt;
check all awaitingStep finish send message to ultimateIntegrationtest for sumla all test is status&lt;br /&gt;
&lt;br /&gt;
== Summary of test status == &lt;br /&gt;
:1.testStatus is &amp;quot;passed&amp;quot; all unit passed.&lt;br /&gt;
:2.testStatus is &amp;quot;failed&amp;quot;  have some is failed.&lt;br /&gt;
:3.testStatus is &amp;quot;processing&amp;quot; have some is have status processing after check all awaiting step is finish.&lt;br /&gt;
:4.testStatus is &amp;quot;failed&amp;quot; have record &amp;quot;errorsTest&amp;quot; in case &amp;quot;not match stage invoke&amp;quot;, &#039;found multiple matchingInvokes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*[[2025-02-20 - Integration Test examples#tests.js Syntax|Syntax Dynamodb]]&lt;br /&gt;
&lt;br /&gt;
=How to test integrationtest s3=&lt;br /&gt;
[[Developer guide for making Integration Tests]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Working documents| 2025-11-20]]&lt;br /&gt;
[[Category:Working documents - Integration Testing| 2025-11-20]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Sale&amp;diff=4569</id>
		<title>Service - CommerceAccounting Sale</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Sale&amp;diff=4569"/>
		<updated>2026-08-11T04:51:47Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: /* comAccSaleLink */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Handle sales in one service because some Accounting entries include the full amount, some break up according to saleLineItems.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== comAccSaleLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccSaleLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
        &amp;quot;myGraph&amp;quot;:{&lt;br /&gt;
          &amp;quot;storageType&amp;quot;: &amp;quot;graph&amp;quot;,&lt;br /&gt;
          &amp;quot;graphServerTag&amp;quot;: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccSaleLink&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		businessId:{&lt;br /&gt;
			fromObjType:{&lt;br /&gt;
			  serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
			  objectType: &amp;quot;comAccLinkByBusiness&amp;quot; &lt;br /&gt;
			},&lt;br /&gt;
        },&lt;br /&gt;
		organizationId: {&lt;br /&gt;
			fromObjType:{&lt;br /&gt;
			  serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
			  objectType: &amp;quot;comAccLinkByOrganization&amp;quot; &lt;br /&gt;
			},&lt;br /&gt;
		},&lt;br /&gt;
        accountLinkTag:{   // type of link: ..&lt;br /&gt;
            type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			requriedOnCreate: true,&lt;br /&gt;
			storageResourceTags: [&#039;myGraph&#039;, &#039;dynamo&#039;]&lt;br /&gt;
        }		&lt;br /&gt;
        accountId:{&lt;br /&gt;
            type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			requriedOnCreate: true,&lt;br /&gt;
			storageResourceTags: [&#039;myGraph&#039;, &#039;dynamo&#039;]&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountLinkTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* sets which Accounting accountId journal entries are added to&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccSale&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;systemGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccSale&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
        &amp;quot;myGraph&amp;quot;: {&lt;br /&gt;
            &amp;quot;storageType&amp;quot;: &amp;quot;graph&amp;quot;,&lt;br /&gt;
            &amp;quot;graphServerTag&amp;quot;: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId,&lt;br /&gt;
		// organizationId,&lt;br /&gt;
		// saleId,&lt;br /&gt;
&lt;br /&gt;
		// record lock eg: prefix: &amp;quot;updateSale&amp;quot;&lt;br /&gt;
		// updateSale_status: {requiredOnCreate: true}, // open|lock, &lt;br /&gt;
		// updateSale_uniqueRequestId: {requiredOnCreate: true},&lt;br /&gt;
		// updateSale_timestamp: {requiredOnCreate: true},&lt;br /&gt;
&lt;br /&gt;
		saleValueJournalId: {&lt;br /&gt;
			type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			optionalOnCreate: true,&lt;br /&gt;
			canUpdate: true,&lt;br /&gt;
			storageResourceTags: [&amp;quot;dynamo&amp;quot;],&lt;br /&gt;
		},&lt;br /&gt;
		inventoryAdjustJournalId: {&lt;br /&gt;
			type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			optionalOnCreate: true,&lt;br /&gt;
			canUpdate: true,&lt;br /&gt;
			storageResourceTags: [&amp;quot;dynamo&amp;quot;],&lt;br /&gt;
		},&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;saleId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* one saleId links to two journalIds, sale value and inventory adjustment entries&lt;br /&gt;
* maintains a link between saleId and journalIds, so can adjust if changes made to sale&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= flowSchemas =&lt;br /&gt;
&lt;br /&gt;
== saleCommitted ==&lt;br /&gt;
&lt;br /&gt;
* when creating a sale, iterate saleLineItems to decide which journal entries are created&lt;br /&gt;
* accountsReceivable accountId will need to come from [[Service - CommerceAccounting Customer]]&lt;br /&gt;
&lt;br /&gt;
=== Sale Value ===&lt;br /&gt;
&lt;br /&gt;
* the total sale value has journal entry for all the below:&lt;br /&gt;
*# (debit)accountsReceivable(Asset)&lt;br /&gt;
&lt;br /&gt;
* The other side (credit) is broken up depending on goods/service or assets&lt;br /&gt;
&lt;br /&gt;
* For goods value an entry is entered into the below&lt;br /&gt;
*# (credit)goodsSale/serviceSale(Revenue)&lt;br /&gt;
&lt;br /&gt;
* Assets have:&lt;br /&gt;
*# (credit)inventoryAsset(Asset)&lt;br /&gt;
*# (debit)accumulatedDepreciation(Asset)&lt;br /&gt;
*# (debit or credit)creditGainOnSale(Renenue)/debitLossOnSale(Expense)&lt;br /&gt;
&lt;br /&gt;
* Intangible Assets have:&lt;br /&gt;
*# (credit)inventoryIntangibleAsset(Asset)&lt;br /&gt;
*# (debit)accumulatedAmortization(Asset)&lt;br /&gt;
*# (debit or credit)creditGainOnSale(Renenue)/debitLossOnSale(Expense)&lt;br /&gt;
&lt;br /&gt;
* all credit side may have:&lt;br /&gt;
*# (credit)salesTaxPayable(Liability)&lt;br /&gt;
*# (credit)vatPayable(liability)&lt;br /&gt;
&lt;br /&gt;
=== Goods Sold ===&lt;br /&gt;
&lt;br /&gt;
* the total saleLineItem value for Inventory Goods has a journal entry for:&lt;br /&gt;
*# (debit)cogsGoods(Expense)&lt;br /&gt;
*# (credit)inventoryGoods(Asset)&lt;br /&gt;
&lt;br /&gt;
=== Raw Material Sold ===&lt;br /&gt;
&lt;br /&gt;
* the total saleLineItem value for Inventory Raw Materials has a journal entry for:&lt;br /&gt;
*# (debit)cogsRawMaterial(Expense)&lt;br /&gt;
*# (credit)inventoryRawMaterial(Asset)&lt;br /&gt;
&lt;br /&gt;
=== Assets Sold ===&lt;br /&gt;
&lt;br /&gt;
* might not have accumulatedDepreciation applied yet&lt;br /&gt;
* if sold for same amount as original value then not have creditGainOnSale/debitLossOnSale&lt;br /&gt;
* will need to query Accounting Assets service for depreciation amount&lt;br /&gt;
* may need to query ComAcc Inventory service to find link between Commerce Asset and Accounting Asset, so can find depreciation&lt;br /&gt;
&lt;br /&gt;
=== Services Sold ===&lt;br /&gt;
&lt;br /&gt;
* no additional entries required&lt;br /&gt;
&lt;br /&gt;
=== Intangible Goods Sold ===&lt;br /&gt;
&lt;br /&gt;
* no additional entries required&lt;br /&gt;
* entries same as physical Goods&lt;br /&gt;
&lt;br /&gt;
=== Intangible Assets ===&lt;br /&gt;
&lt;br /&gt;
* same as an Asset, except use the term Amortization instead of Depreciation, which are functionally the same&lt;br /&gt;
&lt;br /&gt;
== saleChange ==&lt;br /&gt;
&lt;br /&gt;
* make adjustment to journal entries when saleLineItemId changes&lt;br /&gt;
* perhaps handling removal of sale/journal entries, or creation of new entries&lt;br /&gt;
* basically re-calculate all entries and check against existing&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - CommerceAccounting Sale| CommerceAccounting Sale]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| CommerceAccounting Sale]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_Organization&amp;diff=4568</id>
		<title>Service - Organization</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_Organization&amp;diff=4568"/>
		<updated>2026-08-11T04:49:39Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: /* organization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
A user can have many organizations, each organization has it&#039;s independent accounting.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== organization ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;organization&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	addOnDataStructure: [&lt;br /&gt;
		{&lt;br /&gt;
			type:&amp;quot;rbac&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;propertyValue&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;versionedData&amp;quot;,&lt;br /&gt;
			versionedDataLabel: &amp;quot;Detail&amp;quot;,&lt;br /&gt;
			storageResourceTag : &amp;quot;myGraph&amp;quot;,&lt;br /&gt;
			fieldNames: {&lt;br /&gt;
				&amp;quot;organizationName&amp;quot;:{&lt;br /&gt;
					type: &amp;quot;string&amp;quot;,&lt;br /&gt;
					requiredOnCreate: true,&lt;br /&gt;
					canUpdate: true,&lt;br /&gt;
					userCanUpdate: true,&lt;br /&gt;
				},&lt;br /&gt;
				&amp;quot;dailyRateCurrencyTableId&amp;quot;:{&lt;br /&gt;
					type: &amp;quot;string&amp;quot;,&lt;br /&gt;
					requiredOnCreate: true,&lt;br /&gt;
					canUpdate: true,&lt;br /&gt;
					userCanUpdate: true,&lt;br /&gt;
				},&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
	],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		myGraph: {&lt;br /&gt;
			storageType: &amp;quot;graph&amp;quot;,&lt;br /&gt;
			graphServerTag: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		organizationId: {&lt;br /&gt;
			type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			randomOnCreate: true,&lt;br /&gt;
			storageResourceTags: [&#039;myGraph&#039;]&lt;br /&gt;
		},&lt;br /&gt;
		functionalCurrency: {&lt;br /&gt;
			type: &amp;quot;currency&amp;quot;,&lt;br /&gt;
			requiredOnCreate: true,&lt;br /&gt;
			canUpdate: false,&lt;br /&gt;
			userCanUpdate: false,&lt;br /&gt;
			storageResourceTags: [&#039;myGraph&#039;]&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
      precision: {&lt;br /&gt;
        type: &amp;quot;integer&amp;quot;,&lt;br /&gt;
        randomOnCreate: false,  &lt;br /&gt;
        optionalOnCreate: true,&lt;br /&gt;
        requiredOnCreate: false, &lt;br /&gt;
        validation: {&lt;br /&gt;
          pattern: pattern&lt;br /&gt;
        },&lt;br /&gt;
        storageResourceTags: [&#039;graph&#039;],&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;identifier&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;organizationId&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
=== hasOrganization ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	hasOrganization: {&lt;br /&gt;
		storageResources: {&lt;br /&gt;
			myGraph: {&lt;br /&gt;
				storageType: &amp;quot;graph&amp;quot;,&lt;br /&gt;
				graphServerTag: &amp;quot;GraphHandler&amp;quot;			&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
		canChangeToRelTypes: [&lt;br /&gt;
			{&lt;br /&gt;
				serviceTag: &amp;quot;Organization&amp;quot;,&lt;br /&gt;
				relationshipTag: &amp;quot;removedOrganization&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
		],		&lt;br /&gt;
		links: [&lt;br /&gt;
			{&lt;br /&gt;
				storageResourceTags: [&amp;quot;myGraph&amp;quot;],&lt;br /&gt;
				from: {&lt;br /&gt;
					objType: {&lt;br /&gt;
						serviceTag: &amp;quot;User&amp;quot;,&lt;br /&gt;
						objectType: &amp;quot;user&amp;quot;&lt;br /&gt;
					},&lt;br /&gt;
					linkType: &amp;quot;one&amp;quot;,&lt;br /&gt;
				},&lt;br /&gt;
				to: {&lt;br /&gt;
					objType: {&lt;br /&gt;
						serviceTag: &amp;quot;Organization&amp;quot;,&lt;br /&gt;
						objectType: &amp;quot;organization&amp;quot;&lt;br /&gt;
					},&lt;br /&gt;
					linkType: &amp;quot;many&amp;quot;&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
		]&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== removedOrganization ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	removedOrganization: {&lt;br /&gt;
		storageResources: {&lt;br /&gt;
			myGraph: {&lt;br /&gt;
				storageType: &amp;quot;graph&amp;quot;,&lt;br /&gt;
				graphServerTag: &amp;quot;GraphHandler&amp;quot;			&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
		canChangeToRelTypes: [&lt;br /&gt;
			{&lt;br /&gt;
				serviceTag: &amp;quot;Organization&amp;quot;,&lt;br /&gt;
				relationshipTag: &amp;quot;hasOrganization&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
		],		&lt;br /&gt;
		links: [&lt;br /&gt;
			{&lt;br /&gt;
				storageResourceTags: [&amp;quot;myGraph&amp;quot;],&lt;br /&gt;
				from: {&lt;br /&gt;
					objType: {&lt;br /&gt;
						serviceTag: &amp;quot;User&amp;quot;,&lt;br /&gt;
						objectType: &amp;quot;user&amp;quot;&lt;br /&gt;
					},&lt;br /&gt;
					linkType: &amp;quot;one&amp;quot;,&lt;br /&gt;
				},&lt;br /&gt;
				to: {&lt;br /&gt;
					objType: {&lt;br /&gt;
						serviceTag: &amp;quot;Organization&amp;quot;,&lt;br /&gt;
						objectType: &amp;quot;organization&amp;quot;&lt;br /&gt;
					},&lt;br /&gt;
					linkType: &amp;quot;many&amp;quot;&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
		]&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* links a user to the organization they manage&lt;br /&gt;
* does not convey ownership, each organization is a standalone organization that has it&#039;s own RBAC&lt;br /&gt;
* this allows for simple transfer of ownership of data&lt;br /&gt;
&lt;br /&gt;
= Addresses =&lt;br /&gt;
&lt;br /&gt;
* use same structure as users in Izara Market&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - Organization| Organization]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| Organization]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_Business&amp;diff=4567</id>
		<title>Service - Business</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_Business&amp;diff=4567"/>
		<updated>2026-08-11T04:49:27Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: /* Object Schemas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
A user can have many businesses, each business has it&#039;s independent set of data.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== business ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;business&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	addOnDataStructure: [&lt;br /&gt;
		{&lt;br /&gt;
			type:&amp;quot;rbac&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;propertyValue&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type:&amp;quot;versionedData&amp;quot;,&lt;br /&gt;
			versionedDataLabel: &amp;quot;Detail&amp;quot;,&lt;br /&gt;
			storageResourceTag : &amp;quot;myGraph&amp;quot;,&lt;br /&gt;
			fieldNames: {&lt;br /&gt;
				&amp;quot;businessName&amp;quot;:{&lt;br /&gt;
					type: &amp;quot;string&amp;quot;,&lt;br /&gt;
					requiredOnCreate: true,&lt;br /&gt;
				},&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
	],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		myGraph: {&lt;br /&gt;
			storageType: &amp;quot;graph&amp;quot;,&lt;br /&gt;
			graphServerTag: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		businessId: {&lt;br /&gt;
			type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			randomOnCreate: true,&lt;br /&gt;
			canUpdate: false,&lt;br /&gt;
			userCanUpdate: false,&lt;br /&gt;
			storageResourceTags: [&#039;myGraph&#039;]&lt;br /&gt;
		},&lt;br /&gt;
		functionalCurrency: {&lt;br /&gt;
			type: &amp;quot;currency&amp;quot;,&lt;br /&gt;
			requiredOnCreate: true,&lt;br /&gt;
			canUpdate: false,&lt;br /&gt;
			userCanUpdate: false,&lt;br /&gt;
			storageResourceTags: [&#039;myGraph&#039;]&lt;br /&gt;
		},&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;identifier&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;businessId&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RelationshipSchemas ==&lt;br /&gt;
&lt;br /&gt;
=== hasBusiness ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	hasBusiness: {&lt;br /&gt;
		storageResources: {&lt;br /&gt;
			myGraph: {&lt;br /&gt;
				storageType: &amp;quot;graph&amp;quot;,&lt;br /&gt;
				graphServerTag: &amp;quot;GraphHandler&amp;quot;			&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
		canChangeToRelTypes: [&lt;br /&gt;
			{&lt;br /&gt;
				serviceTag:&amp;quot;Business&amp;quot;,&lt;br /&gt;
				relationshipTag: &amp;quot;removedBusiness&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
		],		&lt;br /&gt;
		links: [&lt;br /&gt;
			{&lt;br /&gt;
				storageResourceTags: [&amp;quot;myGraph&amp;quot;],&lt;br /&gt;
				from: {&lt;br /&gt;
					objType: {&lt;br /&gt;
						serviceTag: &amp;quot;User&amp;quot;,&lt;br /&gt;
						objectType: &amp;quot;user&amp;quot;&lt;br /&gt;
					},&lt;br /&gt;
					linkType: &amp;quot;one&amp;quot;,&lt;br /&gt;
				},&lt;br /&gt;
				to: {&lt;br /&gt;
					objType: {&lt;br /&gt;
						serviceTag: &amp;quot;Business&amp;quot;,&lt;br /&gt;
						objectType: &amp;quot;business&amp;quot;&lt;br /&gt;
					},&lt;br /&gt;
					linkType: &amp;quot;many&amp;quot;&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
		]&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== removedBusiness ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	removedBusiness: {&lt;br /&gt;
		storageResources: {&lt;br /&gt;
			myGraph: {&lt;br /&gt;
				storageType: &amp;quot;graph&amp;quot;,&lt;br /&gt;
				graphServerTag: &amp;quot;GraphHandler&amp;quot;			&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
		canChangeToRelTypes: [&lt;br /&gt;
			{&lt;br /&gt;
				serviceTag:&amp;quot;Business&amp;quot;,&lt;br /&gt;
				relationshipTag: &amp;quot;hasBusiness&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
		],		&lt;br /&gt;
		links: [&lt;br /&gt;
			{&lt;br /&gt;
				storageResourceTags: [&amp;quot;myGraph&amp;quot;],&lt;br /&gt;
				from: {&lt;br /&gt;
					objType: {&lt;br /&gt;
						serviceTag: &amp;quot;User&amp;quot;,&lt;br /&gt;
						objectType: &amp;quot;user&amp;quot;&lt;br /&gt;
					},&lt;br /&gt;
					linkType: &amp;quot;one&amp;quot;,&lt;br /&gt;
				},&lt;br /&gt;
				to: {&lt;br /&gt;
					objType: {&lt;br /&gt;
						serviceTag: &amp;quot;Business&amp;quot;,&lt;br /&gt;
						objectType: &amp;quot;business&amp;quot;&lt;br /&gt;
					},&lt;br /&gt;
					linkType: &amp;quot;many&amp;quot;&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
		]&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* links a user to the businesses they manage&lt;br /&gt;
* does not convey ownership, each business is a standalone organization that has it&#039;s own RBAC (allowing for simple transfer of ownership of data)&lt;br /&gt;
* user can link themselves to any businesses so ui can present list of connected businesses&lt;br /&gt;
&lt;br /&gt;
= Addresses =&lt;br /&gt;
&lt;br /&gt;
* use same structure as users in Izara Market&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - Business| Business]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| Business]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Link&amp;diff=4566</id>
		<title>Service - CommerceAccounting Link</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Link&amp;diff=4566"/>
		<updated>2026-08-10T13:37:40Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Configures the link between a Business in Izara Commerce and an organization in Izara Accounting.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== comAccLinkByBusiness ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccLinkByBusiness&amp;quot;,&lt;br /&gt;
	generatedBy: &amp;quot;systemGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	addOnDataStructure: [&lt;br /&gt;
		{&lt;br /&gt;
			type:&amp;quot;rbac&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
        &amp;quot;myGraph&amp;quot;:{&lt;br /&gt;
            &amp;quot;storageType&amp;quot;: &amp;quot;graph&amp;quot;,&lt;br /&gt;
            &amp;quot;graphServerTag&amp;quot;: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccLinkByBusiness&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		 businessId:{&lt;br /&gt;
            type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			requriedOnCreate: true,&lt;br /&gt;
			storageResourceTags: [&#039;myGraph&#039;,&#039;dynamo&#039;]&lt;br /&gt;
         },		&lt;br /&gt;
		 organizationId:{&lt;br /&gt;
            type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			requriedOnCreate: true,&lt;br /&gt;
			storageResourceTags: [&#039;myGraph&#039;,&#039;dynamo&#039;]&lt;br /&gt;
         }		&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;businessId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;organizationId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== comAccLinkByOrganization ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccLinkByOrganization&amp;quot;,&lt;br /&gt;
	generatedBy: &amp;quot;systemGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccLinkByOrganization&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// organizationId&lt;br /&gt;
		// businessId		&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;organizationId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;businessId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== comAccAccountLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccAccountLink&amp;quot;,&lt;br /&gt;
	generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: true,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccAccountLink&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		businessId: {&lt;br /&gt;
			fromObjType:{&lt;br /&gt;
			  serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
			  objectType: &amp;quot;comAccLinkByBusiness&amp;quot; &lt;br /&gt;
			},&lt;br /&gt;
		},&lt;br /&gt;
		organizationId: {&lt;br /&gt;
			fromObjType:{&lt;br /&gt;
			  serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
			  objectType: &amp;quot;comAccLinkByOrganization&amp;quot; &lt;br /&gt;
			},&lt;br /&gt;
		},&lt;br /&gt;
		accountTag: { // this is the granular accounting classification that actions need to add entries to&lt;br /&gt;
			type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			requiredOnCreate: true,&lt;br /&gt;
			canUpdate: false,&lt;br /&gt;
			userCanUpdate: false,&lt;br /&gt;
			storageResourceTags: [&amp;quot;dynamo&amp;quot;],&lt;br /&gt;
		},&lt;br /&gt;
		accountId: { // accountId from Izara Accounting&lt;br /&gt;
			type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			requiredOnCreate: true,&lt;br /&gt;
			canUpdate: true,&lt;br /&gt;
			userCanUpdate: true,&lt;br /&gt;
			storageResourceTags: [&amp;quot;dynamo&amp;quot;],&lt;br /&gt;
		},&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* sets up which Accounting Accounts are used for different connection tasks&lt;br /&gt;
* example: which Accounting Account is adjusted when stock increases/decreases&lt;br /&gt;
* will need to have a plugIn level shared const lib of all accountTags&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - CommerceAccounting Link| CommerceAccounting Link]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| CommerceAccounting Link]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Inventory&amp;diff=4565</id>
		<title>Service - CommerceAccounting Inventory</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Inventory&amp;diff=4565"/>
		<updated>2026-08-10T12:18:43Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Links Inventory objects to Accounting structures.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== comAccInventoryLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccInventoryLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccInventoryLink&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
       &amp;quot;myGraph&amp;quot;: {&lt;br /&gt;
            &amp;quot;storageType&amp;quot;: &amp;quot;graph&amp;quot;,&lt;br /&gt;
            &amp;quot;graphServerTag&amp;quot;: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId&lt;br /&gt;
		// organizationId&lt;br /&gt;
		// inventoryId&lt;br /&gt;
		// accountLinkTag // type of link: purchaseLineItem|..&lt;br /&gt;
		// accountId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;, &amp;quot;inventoryId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkInvId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountLinkTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== comAccInventoryLocationLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccInventoryLocationLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccInventoryLocationLink&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
        &amp;quot;myGraph&amp;quot;: {&lt;br /&gt;
            &amp;quot;storageType&amp;quot;: &amp;quot;graph&amp;quot;,&lt;br /&gt;
            &amp;quot;graphServerTag&amp;quot;: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId&lt;br /&gt;
		// organizationId&lt;br /&gt;
		// inventoryLocationId&lt;br /&gt;
		// accountLinkTag // type of link: purchaseLineItem|..&lt;br /&gt;
		// accountId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;, &amp;quot;inventoryLocationId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkInvLocId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountLinkTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== comAccInventoryTemplateLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccInventoryTemplateLink&amp;quot;,&lt;br /&gt;
	generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccInventoryTemplateLink&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
       &amp;quot;myGraph&amp;quot;: {&lt;br /&gt;
            &amp;quot;storageType&amp;quot;: &amp;quot;graph&amp;quot;,&lt;br /&gt;
            &amp;quot;graphServerTag&amp;quot;: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId&lt;br /&gt;
		// organizationId&lt;br /&gt;
		// inventoryTemplateId&lt;br /&gt;
		// accountLinkTag // type of link: purchaseLineItem|..&lt;br /&gt;
		// accountId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;, &amp;quot;inventoryTemplateId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkInvTemId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountLinkTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== comAccInventoryTypeLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccInventoryTypeLink&amp;quot;,&lt;br /&gt;
	generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccInventoryTypeLink&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
       &amp;quot;myGraph&amp;quot;: {&lt;br /&gt;
            &amp;quot;storageType&amp;quot;: &amp;quot;graph&amp;quot;,&lt;br /&gt;
            &amp;quot;graphServerTag&amp;quot;: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId&lt;br /&gt;
		// organizationId&lt;br /&gt;
		// inventoryType // goods|intangibleGoods|rawMaterial|asset|intangibleAsset&lt;br /&gt;
		// accountLinkTag // type of link: purchaseLineItem|..&lt;br /&gt;
		// accountId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;, &amp;quot;inventoryType&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkInvTypId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountLinkTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= flowSchemas =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - CommerceAccounting Inventory| CommerceAccounting Inventory]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| CommerceAccounting Inventory]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Purchase&amp;diff=4548</id>
		<title>Service - CommerceAccounting Purchase</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Purchase&amp;diff=4548"/>
		<updated>2026-08-09T13:51:07Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: /* comAccPurchase */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Handle links between purchases and Accounting records.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== comAccPurchaseLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccPurchaseLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
        &amp;quot;myGraph&amp;quot;:{&lt;br /&gt;
          &amp;quot;storageType&amp;quot;: &amp;quot;graph&amp;quot;,&lt;br /&gt;
          &amp;quot;graphServerTag&amp;quot;: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccPurchaseLink&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		businessId:{&lt;br /&gt;
			fromObjType:{&lt;br /&gt;
			  serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
			  objectType: &amp;quot;comAccLinkByBusiness&amp;quot; &lt;br /&gt;
			},&lt;br /&gt;
        },&lt;br /&gt;
		organizationId: {&lt;br /&gt;
			fromObjType:{&lt;br /&gt;
			  serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
			  objectType: &amp;quot;comAccLinkByOrganization&amp;quot; &lt;br /&gt;
			},&lt;br /&gt;
		},&lt;br /&gt;
        accountLinkTag:{   // type of link: inputVAT|salesTax|vatTax..&lt;br /&gt;
            type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			requriedOnCreate: true,&lt;br /&gt;
			storageResourceTags: [&#039;myGraph&#039;,&#039;dynamo&#039;]&lt;br /&gt;
        }		&lt;br /&gt;
        accountId:{&lt;br /&gt;
            type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			requriedOnCreate: true,&lt;br /&gt;
			storageResourceTags: [&#039;myGraph&#039;,&#039;dynamo&#039;]&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountLinkTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* sets which Accounting accountId journal entries are added to&lt;br /&gt;
&lt;br /&gt;
== comAccPurchase ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccPurchase&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;systemGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
    addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccPurchase&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId,&lt;br /&gt;
		// organizationId,&lt;br /&gt;
		// purchaseId,&lt;br /&gt;
&lt;br /&gt;
		// record lock eg: prefix: &amp;quot;updatePurchase&amp;quot;&lt;br /&gt;
		// updatePurchase_status: {requiredOnCreate: true}, // open|lock, &lt;br /&gt;
		// updatePurchase_uniqueRequestId: {requiredOnCreate: true},&lt;br /&gt;
		// updatePurchase_timestamp: {requiredOnCreate: true},&lt;br /&gt;
&lt;br /&gt;
		journalId: {&lt;br /&gt;
			type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			optionalOnCreate: true,&lt;br /&gt;
			canUpdate: true,&lt;br /&gt;
			storageResourceTags: [&amp;quot;dynamo&amp;quot;],&lt;br /&gt;
		},&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;purchaseId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== comAccPurchaseLineItem ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccPurchaseLineItem&amp;quot;,&lt;br /&gt;
	generatedBy: &amp;quot;systemGenerated&amp;quot;,&lt;br /&gt;
    canDelete: false,&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccPurchaseLineItem&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId&lt;br /&gt;
		// organizationId&lt;br /&gt;
		// purchaseId,&lt;br /&gt;
		// purchaseLineItemId,&lt;br /&gt;
		// accountId&lt;br /&gt;
		// lineItemQuantity&lt;br /&gt;
		// lineItemUnitPricelineItemUnitPrice&lt;br /&gt;
		// entryId // not sure want to record because multiple lineItems might be in the same entryId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;, &amp;quot;purchaseId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkPurchaseId&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;purchaseLineItemId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* This table might not be needed because we do not create a journal entry per line item, we make a compound journal entry per purchase&lt;br /&gt;
* Keep it for now so we can reconcile Commerce data matches ComAcc data&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= flowSchemas =&lt;br /&gt;
&lt;br /&gt;
== createPurchase ==&lt;br /&gt;
&lt;br /&gt;
* when creating a purchase, iterate purchaseLineItems to decide which journal entries are created&lt;br /&gt;
* accountsPayable accountId comes from [[Service - CommerceAccounting Vendor]]&lt;br /&gt;
* each purchaseLineItem checks it&#039;s type then finds accountId from coresponding comAcc service&lt;br /&gt;
&lt;br /&gt;
=== Example request param from Commerce ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	belongToIdentifiers: {&lt;br /&gt;
	  businessId: &amp;quot;xxx&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	purchaseId: &amp;quot;&amp;quot;,&lt;br /&gt;
	vendorId: &amp;quot;&amp;quot;,&lt;br /&gt;
    timestamp: 1111111,&lt;br /&gt;
	purchaseCurrencyId: &amp;quot;&amp;quot;,&lt;br /&gt;
	inventoryLocationId: &amp;quot;&amp;quot;, // required if have any inventory/?assets&lt;br /&gt;
	purchaseLineItems: {&lt;br /&gt;
		{purchaseLineItemId}: {&lt;br /&gt;
&lt;br /&gt;
            inventoryId: &amp;quot;&amp;quot;,&lt;br /&gt;
            inventoryTemplateId: &amp;quot;&amp;quot;,&lt;br /&gt;
            // or&lt;br /&gt;
            expenseId: &amp;quot;&amp;quot;,&lt;br /&gt;
            // or&lt;br /&gt;
            servicesId: &amp;quot;&amp;quot;,&lt;br /&gt;
            servicesTemplateId: &amp;quot;&amp;quot;,&lt;br /&gt;
            // or&lt;br /&gt;
            freightInId: &amp;quot;&amp;quot;,&lt;br /&gt;
            // or&lt;br /&gt;
&lt;br /&gt;
            otherPurchaseItemId: &amp;quot;&amp;quot;,&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
			type: &amp;quot;&amp;quot;, // inventory|expense|services|freight|salesTax|vatTax|other&lt;br /&gt;
			subType: &amp;quot;&amp;quot;, // inventory: goods|intangibleGoods|rawMaterial|asset|intangibleAsset, expense: pointInTime|overTime, services: pointInTime|overTime, freight: standard, other: standard&lt;br /&gt;
&lt;br /&gt;
			lineItemQuantity: 1,&lt;br /&gt;
			lineItemUnitPrice: &amp;quot;2.00&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		//...&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== updatePurchase ==&lt;br /&gt;
&lt;br /&gt;
* make adjustment to journal entries when purchaseLineItemId changes&lt;br /&gt;
* handle removal of purchase/journal entries, or creation of new entries&lt;br /&gt;
* basically re-calculate all entries and check against existing&lt;br /&gt;
* each journalId must check Accounting that it&#039;s period/s are not locked, if locked return error, cannot make update&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - CommerceAccounting Purchase| CommerceAccounting Purchase]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| CommerceAccounting Purchase]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Other_Purchase_Item&amp;diff=4547</id>
		<title>Service - CommerceAccounting Other Purchase Item</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Other_Purchase_Item&amp;diff=4547"/>
		<updated>2026-08-08T10:06:52Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Links Other Purchase Item objects to Accounting structures.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== comAccOtherPurchaseItemLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccOtherPurchaseItemLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccOtherPurchaseItemLink&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId&lt;br /&gt;
		// organizationId&lt;br /&gt;
		// otherPurchaseItemId&lt;br /&gt;
		// accountLinkTag // type of link: purchaseLineItem|..&lt;br /&gt;
		// accountId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;, &amp;quot;otherPurchaseItemId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkOthPurId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountLinkTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== comAccOtherPurchaseItemTypeLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccOtherPurchaseItemTypeLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccOtherPurchaseItemTypeLink&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId&lt;br /&gt;
		// organizationId&lt;br /&gt;
		// otherPurchaseItemType // standard&lt;br /&gt;
		// accountLinkTag // type of link: purchaseLineItem|..&lt;br /&gt;
		// accountId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;, &amp;quot;otherPurchaseItemType&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkOthPurTypId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountLinkTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= flowSchemas =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - CommerceAccounting Other Purchase Item| CommerceAccounting Other Purchase Item]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| CommerceAccounting Other Purchase Item]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Freight_In&amp;diff=4546</id>
		<title>Service - CommerceAccounting Freight In</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Freight_In&amp;diff=4546"/>
		<updated>2026-08-08T10:03:02Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Links Freight In objects to Accounting structures.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== comAccFreightInLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccFreightInLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccFreightInLink&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId&lt;br /&gt;
		// organizationId&lt;br /&gt;
		// freightInId&lt;br /&gt;
		// accountLinkTag // type of link: purchaseLineItem&lt;br /&gt;
		// accountId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;, &amp;quot;freightInId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkFreInId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountLinkTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== comAccFreightInTypeLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccFreightInTypeLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccFreightInTypeLink&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId&lt;br /&gt;
		// organizationId&lt;br /&gt;
		// freightInType // standard|..&lt;br /&gt;
		// accountLinkTag // type of link: purchaseLineItem|..&lt;br /&gt;
		// accountId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;, &amp;quot;freightInType&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkFreInTypId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountLinkTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= flowSchemas =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - CommerceAccounting Freight In| CommerceAccounting Freight In]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| CommerceAccounting Freight In]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Vendor_Payment&amp;diff=4545</id>
		<title>Service - CommerceAccounting Vendor Payment</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Vendor_Payment&amp;diff=4545"/>
		<updated>2026-08-08T09:59:56Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Handle payments to vendors.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== comAccVendorPayment ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccVendorPayment&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;systemGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
    addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccVendorPayment&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId,&lt;br /&gt;
		// organizationId,&lt;br /&gt;
		// vendorPaymentId,&lt;br /&gt;
&lt;br /&gt;
		// record lock eg: prefix: &amp;quot;updateVendorPayment&amp;quot;&lt;br /&gt;
		// updateVendorPayment_status: {requiredOnCreate: true}, // open|lock, &lt;br /&gt;
		// updateVendorPayment_uniqueRequestId: {requiredOnCreate: true},&lt;br /&gt;
		// updateVendorPayment_timestamp: {requiredOnCreate: true},&lt;br /&gt;
&lt;br /&gt;
		journalId: {&lt;br /&gt;
			type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			optionalOnCreate: true,&lt;br /&gt;
			canUpdate: true,&lt;br /&gt;
			storageResourceTags: [&amp;quot;dynamo&amp;quot;],&lt;br /&gt;
		},&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;vendorPaymentId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* maintains a link between vendorPaymentId and journalIds, so can adjust if changes made to payment&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= flowSchemas =&lt;br /&gt;
&lt;br /&gt;
== vendorPaymentCreated ==&lt;br /&gt;
&lt;br /&gt;
* when creating a vendor payment add journal entries&lt;br /&gt;
&lt;br /&gt;
== vendorPaymentChange ==&lt;br /&gt;
&lt;br /&gt;
* make adjustment to journal entries&lt;br /&gt;
* need to check for locked records&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - CommerceAccounting Vendor Payment| CommerceAccounting Vendor Payment]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| CommerceAccounting Vendor Payment]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Customer_Payment&amp;diff=4544</id>
		<title>Service - CommerceAccounting Customer Payment</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Customer_Payment&amp;diff=4544"/>
		<updated>2026-08-08T09:58:15Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Handle payments by customers.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== comAccCustomerPayment ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccCustomerPayment&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;systemGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
    addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccCustomerPayment&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId,&lt;br /&gt;
		// organizationId,&lt;br /&gt;
		// customerPaymentId,&lt;br /&gt;
&lt;br /&gt;
		// record lock eg: prefix: &amp;quot;updateCustomerPayment&amp;quot;&lt;br /&gt;
		// updateCustomerPayment_status: {requiredOnCreate: true}, // open|lock, &lt;br /&gt;
		// updateCustomerPayment_uniqueRequestId: {requiredOnCreate: true},&lt;br /&gt;
		// updateCustomerPayment_timestamp: {requiredOnCreate: true},&lt;br /&gt;
&lt;br /&gt;
		journalId: {&lt;br /&gt;
			type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			optionalOnCreate: true,&lt;br /&gt;
			canUpdate: true,&lt;br /&gt;
			storageResourceTags: [&amp;quot;dynamo&amp;quot;],&lt;br /&gt;
		},&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;customerPaymentId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* maintains a link between customerPaymentId and journalIds, so can adjust if changes made to payment&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= flowSchemas =&lt;br /&gt;
&lt;br /&gt;
== customerPaymentCreated ==&lt;br /&gt;
&lt;br /&gt;
* when creating a customer payment add journal entries&lt;br /&gt;
&lt;br /&gt;
== customerPaymentChange ==&lt;br /&gt;
&lt;br /&gt;
* make adjustment to journal entries&lt;br /&gt;
* need to check for locked records&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - CommerceAccounting Customer Payment| CommerceAccounting Customer Payment]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| CommerceAccounting Customer Payment]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Customer_Payment&amp;diff=4543</id>
		<title>Service - CommerceAccounting Customer Payment</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Customer_Payment&amp;diff=4543"/>
		<updated>2026-08-08T09:56:53Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Handle payments by customers.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccCustomerPaymentLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccCustomerPaymentLink&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId&lt;br /&gt;
		// organizationId&lt;br /&gt;
		// customerId&lt;br /&gt;
		// accountLinkTag // type of link: ..&lt;br /&gt;
		// accountId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;, &amp;quot;customerId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkExpId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountLinkTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== comAccCustomerPayment ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccCustomerPayment&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;systemGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
    addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccCustomerPayment&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId,&lt;br /&gt;
		// organizationId,&lt;br /&gt;
		// customerPaymentId,&lt;br /&gt;
&lt;br /&gt;
		// record lock eg: prefix: &amp;quot;updateCustomerPayment&amp;quot;&lt;br /&gt;
		// updateCustomerPayment_status: {requiredOnCreate: true}, // open|lock, &lt;br /&gt;
		// updateCustomerPayment_uniqueRequestId: {requiredOnCreate: true},&lt;br /&gt;
		// updateCustomerPayment_timestamp: {requiredOnCreate: true},&lt;br /&gt;
&lt;br /&gt;
		journalId: {&lt;br /&gt;
			type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			optionalOnCreate: true,&lt;br /&gt;
			canUpdate: true,&lt;br /&gt;
			storageResourceTags: [&amp;quot;dynamo&amp;quot;],&lt;br /&gt;
		},&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;customerPaymentId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* maintains a link between customerPaymentId and journalIds, so can adjust if changes made to payment&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= flowSchemas =&lt;br /&gt;
&lt;br /&gt;
== customerPaymentCreated ==&lt;br /&gt;
&lt;br /&gt;
* when creating a customer payment add journal entries&lt;br /&gt;
&lt;br /&gt;
== customerPaymentChange ==&lt;br /&gt;
&lt;br /&gt;
* make adjustment to journal entries&lt;br /&gt;
* need to check for locked records&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - CommerceAccounting Customer Payment| CommerceAccounting Customer Payment]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| CommerceAccounting Customer Payment]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Manufacture&amp;diff=4542</id>
		<title>Service - CommerceAccounting Manufacture</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Manufacture&amp;diff=4542"/>
		<updated>2026-08-08T09:51:14Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Connects each manufacture operation to their Accounting accounts, such as moving stock out of work in progress account to inventory asset account.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccManufacture&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;systemGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccWorkInProgressAccountLink&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId,&lt;br /&gt;
		// organizationId,&lt;br /&gt;
		// workInProgressId,&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;workInProgressId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= flowSchemas =&lt;br /&gt;
&lt;br /&gt;
== workInProgressAdded ==&lt;br /&gt;
&lt;br /&gt;
* creates journal entry for inventory/raw material out, workInProgress in&lt;br /&gt;
&lt;br /&gt;
== workInProgressRemoved ==&lt;br /&gt;
&lt;br /&gt;
* creates journal entry for workInProgress out, inventory/raw material in&lt;br /&gt;
&lt;br /&gt;
== workInProgressComplete ==&lt;br /&gt;
&lt;br /&gt;
* creates journal entry for workInProgress out, inventory/raw material in&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - CommerceAccounting Manufacture| CommerceAccounting Manufacture]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| CommerceAccounting Manufacture]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Expense&amp;diff=4541</id>
		<title>Service - CommerceAccounting Expense</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Expense&amp;diff=4541"/>
		<updated>2026-08-08T09:51:10Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Links Expense objects to Accounting structures.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== comAccExpenseLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccExpenseLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccExpenseLink&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId&lt;br /&gt;
		// organizationId&lt;br /&gt;
		// expenseId&lt;br /&gt;
		// accountLinkTag // type of link: ..&lt;br /&gt;
		// accountId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;, &amp;quot;expenseId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkExpId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountLinkTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== comAccExpenseTypeLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccExpenseTypeLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccExpenseTypeLink&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId&lt;br /&gt;
		// organizationId&lt;br /&gt;
		// expenseType // pointInTime|overTime&lt;br /&gt;
		// accountLinkTag // type of link: purchaseLineItem|..&lt;br /&gt;
		// accountId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;, &amp;quot;expenseType&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkExpTypId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountLinkTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RelationshipSchemas ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - CommerceAccounting Expenses|CommerceAccounting Expenses]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| CommerceAccounting Expenses]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
	<entry>
		<id>https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Purchase&amp;diff=4540</id>
		<title>Service - CommerceAccounting Purchase</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=Service_-_CommerceAccounting_Purchase&amp;diff=4540"/>
		<updated>2026-08-08T09:46:28Z</updated>

		<summary type="html">&lt;p&gt;Sven the Barbarian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
Handle links between purchases and Accounting records.&lt;br /&gt;
&lt;br /&gt;
= Repository =&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= Object Schemas =&lt;br /&gt;
; Additional Information: [[Per Service Schemas]]&lt;br /&gt;
&lt;br /&gt;
== comAccPurchaseLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccPurchaseLink&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;userGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
	belongTo: {&lt;br /&gt;
		serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
		objectType: &amp;quot;comAccLinkByBusiness&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
        &amp;quot;myGraph&amp;quot;:{&lt;br /&gt;
          &amp;quot;storageType&amp;quot;: &amp;quot;graph&amp;quot;,&lt;br /&gt;
          &amp;quot;graphServerTag&amp;quot;: &amp;quot;GraphHandler&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccPurchaseLink&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		businessId:{&lt;br /&gt;
			fromObjType:{&lt;br /&gt;
			  serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
			  objectType: &amp;quot;comAccLinkByBusiness&amp;quot; &lt;br /&gt;
			},&lt;br /&gt;
        },&lt;br /&gt;
		organizationId: {&lt;br /&gt;
			fromObjType:{&lt;br /&gt;
			  serviceTag: &amp;quot;CommerceAccountingLink&amp;quot;,&lt;br /&gt;
			  objectType: &amp;quot;comAccLinkByOrganization&amp;quot; &lt;br /&gt;
			},&lt;br /&gt;
		},&lt;br /&gt;
        accountLinkTag:{   // type of link: inputVAT|salesTax|vatTax..&lt;br /&gt;
            type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			requriedOnCreate: true,&lt;br /&gt;
			storageResourceTags: [&#039;myGraph&#039;,&#039;dynamo&#039;]&lt;br /&gt;
        }		&lt;br /&gt;
        accountId:{&lt;br /&gt;
            type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			requriedOnCreate: true,&lt;br /&gt;
			storageResourceTags: [&#039;myGraph&#039;,&#039;dynamo&#039;]&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;accountLinkTag&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* sets which Accounting accountId journal entries are added to&lt;br /&gt;
&lt;br /&gt;
== comAccPurchase ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccPurchase&amp;quot;,&lt;br /&gt;
    generatedBy: &amp;quot;systemGenerated&amp;quot;,&lt;br /&gt;
	canDelete: false,&lt;br /&gt;
    addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccPurchase&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId,&lt;br /&gt;
		// organizationId,&lt;br /&gt;
		// purchaseId,&lt;br /&gt;
&lt;br /&gt;
		// record lock eg: prefix: &amp;quot;updatePurchase&amp;quot;&lt;br /&gt;
		// updatePurchase_status: {requiredOnCreate: true}, // open|lock, &lt;br /&gt;
		// updatePurchase_uniqueRequestId: {requiredOnCreate: true},&lt;br /&gt;
		// updatePurchase_timestamp: {requiredOnCreate: true},&lt;br /&gt;
&lt;br /&gt;
		purchseValueJournalId: {&lt;br /&gt;
			type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			optionalOnCreate: true,&lt;br /&gt;
			canUpdate: true,&lt;br /&gt;
			storageResourceTags: [&amp;quot;dynamo&amp;quot;],&lt;br /&gt;
		},&lt;br /&gt;
		inventoryAdjustJournalId: {&lt;br /&gt;
			type: &amp;quot;string&amp;quot;,&lt;br /&gt;
			optionalOnCreate: true,&lt;br /&gt;
			canUpdate: true,&lt;br /&gt;
			storageResourceTags: [&amp;quot;dynamo&amp;quot;],&lt;br /&gt;
		},&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkId&amp;quot;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;purchaseId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== comAccPurchaseLineItem ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	objectType: &amp;quot;comAccPurchaseLineItem&amp;quot;,&lt;br /&gt;
	generatedBy: &amp;quot;systemGenerated&amp;quot;,&lt;br /&gt;
    canDelete: false,&lt;br /&gt;
	addOnDataStructure: [],&lt;br /&gt;
	storageResources: {&lt;br /&gt;
		&amp;quot;dynamo&amp;quot;: {&lt;br /&gt;
			&amp;quot;storageType&amp;quot;: &amp;quot;dynamoDB&amp;quot;,&lt;br /&gt;
			&amp;quot;tableName&amp;quot;: &amp;quot;comAccPurchaseLineItem&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
    },&lt;br /&gt;
    fieldNames: {&lt;br /&gt;
		// businessId&lt;br /&gt;
		// organizationId&lt;br /&gt;
		// purchaseId,&lt;br /&gt;
		// purchaseLineItemId,&lt;br /&gt;
		// accountId&lt;br /&gt;
		// lineItemQuantity&lt;br /&gt;
		// lineItemUnitPricelineItemUnitPrice&lt;br /&gt;
		// entryId // not sure want to record because multiple lineItems might be in the same entryId&lt;br /&gt;
    },&lt;br /&gt;
    identifiers: [&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;partitionKey&amp;quot;,&lt;br /&gt;
			fieldNames: [&amp;quot;businessId&amp;quot;, &amp;quot;organizationId&amp;quot;, &amp;quot;purchaseId&amp;quot;],&lt;br /&gt;
			name: &amp;quot;comAccLinkPurchaseId&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			type: &amp;quot;sortKey&amp;quot;,&lt;br /&gt;
			fieldName: &amp;quot;purchaseLineItemId&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* This table might not be needed because we do not create a journal entry per line item, we make a compound journal entry per purchase&lt;br /&gt;
* Keep it for now so we can reconcile Commerce data matches ComAcc data&lt;br /&gt;
&lt;br /&gt;
== Relationships ==&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
= flowSchemas =&lt;br /&gt;
&lt;br /&gt;
== createPurchase ==&lt;br /&gt;
&lt;br /&gt;
* when creating a purchase, iterate purchaseLineItems to decide which journal entries are created&lt;br /&gt;
* accountsPayable accountId comes from [[Service - CommerceAccounting Vendor]]&lt;br /&gt;
* each purchaseLineItem checks it&#039;s type then finds accountId from coresponding comAcc service&lt;br /&gt;
&lt;br /&gt;
=== Example request param from Commerce ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	belongToIdentifiers: {&lt;br /&gt;
	  businessId: &amp;quot;xxx&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	purchaseId: &amp;quot;&amp;quot;,&lt;br /&gt;
	vendorId: &amp;quot;&amp;quot;,&lt;br /&gt;
    timestamp: 1111111,&lt;br /&gt;
	purchaseCurrencyId: &amp;quot;&amp;quot;,&lt;br /&gt;
	inventoryLocationId: &amp;quot;&amp;quot;, // required if have any inventory/?assets&lt;br /&gt;
	purchaseLineItems: {&lt;br /&gt;
		{purchaseLineItemId}: {&lt;br /&gt;
&lt;br /&gt;
            inventoryId: &amp;quot;&amp;quot;,&lt;br /&gt;
            inventoryTemplateId: &amp;quot;&amp;quot;,&lt;br /&gt;
            // or&lt;br /&gt;
            expenseId: &amp;quot;&amp;quot;,&lt;br /&gt;
            // or&lt;br /&gt;
            servicesId: &amp;quot;&amp;quot;,&lt;br /&gt;
            servicesTemplateId: &amp;quot;&amp;quot;,&lt;br /&gt;
            // or&lt;br /&gt;
            freightInId: &amp;quot;&amp;quot;,&lt;br /&gt;
            // or&lt;br /&gt;
&lt;br /&gt;
            otherPurchaseItemId: &amp;quot;&amp;quot;,&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
			type: &amp;quot;&amp;quot;, // inventory|expense|services|freight|salesTax|vatTax|other&lt;br /&gt;
			subType: &amp;quot;&amp;quot;, // inventory: goods|intangibleGoods|rawMaterial|asset|intangibleAsset, expense: pointInTime|overTime, services: pointInTime|overTime, freight: standard, other: standard&lt;br /&gt;
&lt;br /&gt;
			lineItemQuantity: 1,&lt;br /&gt;
			lineItemUnitPrice: &amp;quot;2.00&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		//...&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== updatePurchase ==&lt;br /&gt;
&lt;br /&gt;
* make adjustment to journal entries when purchaseLineItemId changes&lt;br /&gt;
* handle removal of purchase/journal entries, or creation of new entries&lt;br /&gt;
* basically re-calculate all entries and check against existing&lt;br /&gt;
* each journalId must check Accounting that it&#039;s period/s are not locked, if locked return error, cannot make update&lt;br /&gt;
&lt;br /&gt;
= Working documents =&lt;br /&gt;
&lt;br /&gt;
[[:Category:Working_documents - CommerceAccounting Purchase| CommerceAccounting Purchase]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Backend services| CommerceAccounting Purchase]]&lt;/div&gt;</summary>
		<author><name>Sven the Barbarian</name></author>
	</entry>
</feed>