UNPKG

@jigx/mdk

Version:

Jigx Mobile Development Kit - SDK for building Jigx applications

1,556 lines 189 kB
{ "name": "expenses-app-lukas", "title": "Expenses", "category": "field-services", "expressions": { "hasItems": "=function($items)\n{\n $type($items) = 'array' or $count($items) > 0\n} \n" }, "tabs": { "home": { "jigId": "home", "icon": "receipt-dollar", "label": { "id": "expenses" } } }, "onLoad": { "type": "action.execute-action", "options": { "action": "action-sync-data" } }, "databases": { "default": { "tables": { "weather-icons": null, "logged-time": null, "timesheets": null, "expenseItemIcons": null, "feature-settings": null }, "databaseId": "default" } }, "datasources": { "data-deleted-expense-receipts": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_LOCAL", "entities": [ "expense-receipts", "expense-receipts-not-deleted" ], "query": "SELECT id\nFROM [expense-receipts] AS p\nWHERE NOT EXISTS (\n SELECT 1\n FROM [expense-receipts-not-deleted] AS np\n WHERE p.id = np.id\n)\n" } }, "data-expense-receipt-max-modified": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_LOCAL", "entities": [ { "entity": "expense-receipts" } ], "query": "SELECT max(json_extract(data, '$.LastModifiedDateTime.value')) as LastModifiedDateTime FROM [expense-receipts]" } }, "data-global-expenses": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_LOCAL", "entities": [ "expense-receipts" ], "jsonProperties": [ "files" ], "query": "SELECT id, json_extract(data, '$.files') as files\nFROM [expense-receipts] WHERE json_array_length(files) > 0\n" } }, "data-loading-progress": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_LOCAL", "entities": [ { "entity": "progress" } ], "query": "SELECT \nid\n,'$.stage'\n,'$.percentage'\n,'$.step'\n,'$.max'\nFROM\nprogress\n" } }, "data-solution-features": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_DYNAMIC", "entities": [ "default/feature-settings" ], "query": "SELECT id, '$.CorporateCard', '$.CostCode', '$.Project' FROM [default/feature-settings] LIMIT 1" } }, "data-who-am-i": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_LOCAL", "entities": [ { "entity": "whoami" } ], "query": "SELECT \n '$.employeeID',\n '$.fullName'\nFROM \n [whoami]\n" } }, "errorqueue": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_LOCAL", "entities": [ { "entity": [ "_commandQueue" ] } ], "query": "SELECT\nid,\njson_extract(payload, '$.functionId') AS functionId,\njson_extract(payload, '$.data.id') AS appointmentLineItemId,\njson_extract(payload, '$.data.LineNbr') AS lineNbr,\njson_extract(payload, '$.correlationId') as correlationId,\njson_extract(payload, '$.entity') as entity,\njson_extract(payload, '$.data') as functionData,\n[payload],\n[type],\n[queue],\n[state],\n[error]\nFROM\n[_commandQueue]\nwhere state = 'failed' \nand error is not null\n" } }, "processqueue": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_LOCAL", "entities": [ { "entity": [ "_commandQueue" ] } ], "query": "SELECT\nid,\njson_extract(payload, '$.functionId') AS functionId,\njson_extract(payload, '$.data.id') AS appointmentLineItemId,\njson_extract(payload, '$.data.LineNbr') AS lineNbr,\njson_extract(payload, '$.correlationId') as correlationId,\njson_extract(payload, '$.entity') as entity,\njson_extract(payload, '$.data') as functionData,\n[payload],\n[type],\n[queue],\n[state],\n[error]\nFROM\n[_commandQueue]\nwhere state != 'failed' \n" } }, "user-roles": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_LOCAL", "entities": [ { "entity": "userRoles" } ], "query": "SELECT id, '$.roleName' FROM [userRoles]" } } }, "functions": { "rest-get-corp-cards": { "provider": "DATA_PROVIDER_REST", "method": "GET", "url": "https://{oDataBaseUrl}JIGXEmployeeCorpCard", "useLocalCall": true, "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "$format": { "location": "query", "type": "string", "value": "json", "required": false }, "oDataBaseUrl": { "type": "string", "location": "path", "required": true } }, "outputTransform": "$.value.{\n \"CorporateCardID\" : CorporateCardID,\n \"EmployeeID\" : $trim(EmployeeID),\n \"EmployeeName\" : EmployeeName,\n \"CardNumber\" : CardNumber\n }", "error": [ { "when": "=@ctx.response.status = 200 and @ctx.response.body = ''", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "No data returned from Acumatica", "table": "diff-sync-errors" }, { "when": "=@.response.status = 401", "title": "Unauthorized", "description": "Unauthorized", "notification": true, "retry": { "maxRetries": 3, "delay": 5000 } }, { "when": "=@ctx.response.status = 500", "icon": "on-error-sad", "title": "Something Went Wrong", "description": "\"It seems like something went wrong when trying to get your user information.\nPlease screenshot and email to markus@jigx.com\"\n", "details": "=@ctx.response.body", "notification": true }, { "when": "=@ctx.response.status = 503", "icon": "on-error-sad", "title": "Server is temporarily unavailable", "description": "\"The server is currently unavailable, please try again in a few minutes.\"\n", "details": "=@ctx.response.body", "notification": true }, { "when": "=@ctx.response.status = 504", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "504 Gateway Timeout", "table": "diff-sync-errors", "transform": "=$" } ] }, "rest-get-uploaded-files": { "provider": "DATA_PROVIDER_REST", "method": "GET", "url": "https://{oDataBaseUrlv4}PX_SM_UploadFileRevisionNoData", "useLocalCall": true, "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "$format": { "location": "query", "type": "string", "value": "json", "required": false }, "oDataBaseUrlv4": { "type": "string", "location": "path", "required": true } }, "outputTransform": "$.value", "error": [ { "when": "=@ctx.response.status = 200 and @ctx.response.body = ''", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "No data returned from Acumatica", "table": "diff-sync-errors" }, { "when": "=@.response.status = 401", "title": "Unauthorized", "description": "Unauthorized", "notification": true, "retry": { "maxRetries": 3, "delay": 5000 } }, { "when": "=@ctx.response.status = 500", "icon": "on-error-sad", "title": "Something Went Wrong", "description": "\"It seems like something went wrong when trying to get your user information.\nPlease screenshot and email to markus@jigx.com\"\n", "details": "=@ctx.response.body", "notification": true }, { "when": "=@ctx.response.status = 503", "icon": "on-error-sad", "title": "Server is temporarily unavailable", "description": "\"The server is currently unavailable, please try again in a few minutes.\"\n", "details": "=@ctx.response.body", "notification": true }, { "when": "=@ctx.response.status = 504", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "504 Gateway Timeout", "table": "diff-sync-errors", "transform": "=$" } ] }, "rest-get-user-roles": { "provider": "DATA_PROVIDER_REST", "method": "GET", "url": "https://{oDataBaseUrl}JIGXUserRoles", "useLocalCall": true, "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "$format": { "location": "query", "type": "string", "value": "json", "required": false }, "oDataBaseUrl": { "type": "string", "location": "path", "required": true } }, "outputTransform": "$.value.{\n \"login\" : Login,\n \"email\" : Email,\n \"employeeID\" : $trim(EmployeeID),\n \"roleName\" : RoleName\n }", "error": [ { "when": "=@ctx.response.status = 200 and @ctx.response.body = ''", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "No data returned from Acumatica", "table": "diff-sync-errors" }, { "when": "=@.response.status = 401", "title": "Unauthorized", "description": "Unauthorized", "notification": true, "retry": { "maxRetries": 3, "delay": 5000 } }, { "when": "=@ctx.response.status = 500", "icon": "on-error-sad", "title": "Something Went Wrong", "description": "\"It seems like something went wrong when trying to get your user information.\nPlease screenshot and email to markus@jigx.com\"\n", "details": "=@ctx.response.body", "notification": true }, { "when": "=@ctx.response.status = 503", "icon": "on-error-sad", "title": "Server is temporarily unavailable", "description": "\"The server is currently unavailable, please try again in a few minutes.\"\n", "details": "=@ctx.response.body", "notification": true }, { "when": "=@ctx.response.status = 504", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "504 Gateway Timeout", "table": "diff-sync-errors", "transform": "=$" } ] }, "rest-whoami": { "provider": "DATA_PROVIDER_REST", "method": "GET", "url": "https://{oDataBaseUrl}JIGXWhoAmI", "useLocalCall": true, "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "$format": { "location": "query", "type": "string", "value": "json", "required": false }, "oDataBaseUrl": { "type": "string", "location": "path", "required": true } }, "outputTransform": "$.value.{\n \"login\" : Login,\n \"email\" : Email,\n \"employeeID\" : $trim(EmployeeID),\n \"fullName\" : FullName\n }", "error": [ { "when": "=@ctx.response.status = 200 and @ctx.response.body = ''", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "No data returned from Acumatica", "table": "diff-sync-errors" }, { "when": "=@.response.status = 401", "title": "Unauthorized", "description": "Unauthorized", "notification": true, "retry": { "maxRetries": 3, "delay": 5000 } }, { "when": "=@ctx.response.status = 500", "icon": "on-error-sad", "title": "Something Went Wrong", "description": "\"It seems like something went wrong when trying to get your user information.\nPlease screenshot and email to markus@jigx.com\"\n", "details": "=@ctx.response.body", "notification": true }, { "when": "=@ctx.response.status = 503", "icon": "on-error-sad", "title": "Server is temporarily unavailable", "description": "\"The server is currently unavailable, please try again in a few minutes.\"\n", "details": "=@ctx.response.body", "notification": true }, { "when": "=@ctx.response.status = 504", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "504 Gateway Timeout", "table": "diff-sync-errors", "transform": "=$" } ] }, "rest-delete-expense": { "provider": "DATA_PROVIDER_REST", "url": "https://{acumaticaurl}ExpenseReceipt/{expId}", "method": "DELETE", "useLocalCall": true, "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "expId": { "type": "string", "location": "path", "required": true }, "acumaticaurl": { "type": "string", "location": "path", "required": true } }, "error": [ { "when": "=(@ctx.response.status = 400) or (@ctx.response.status = 404)", "title": "Bad Request", "description": "Please screenshot and email support at markus@jigx.com", "notification": true, "details": "=@ctx.response.body", "retry": { "maxRetries": 3, "delay": 5000 } }, { "when": "=@.response.status = 401", "title": "Unauthorized", "description": "Unauthorized", "notification": true, "retry": { "maxRetries": 3, "delay": 5000 } }, { "when": "=@.response.status = 500", "title": "Internal error", "description": "Internal error", "notification": false }, { "when": "=@ctx.response.status = 504", "title": "504 Retry error", "description": "Retry", "icon": "button-loop-1", "retry": { "delay": 16000, "maxRetries": 4 }, "notification": true }, { "when": "=@ctx.response.status = 503", "icon": "on-error-sad", "title": "Server is temporarily unavailable", "description": "\"The server is currently unavailable, please try again in a few minutes.\"\n", "details": "=@ctx.response.body", "notification": true, "retry": { "maxRetries": 3, "delay": 5000 } }, { "when": "=@ctx.response.status = 429", "retry": { "delay": 16000, "maxRetries": 4 }, "notification": true, "description": "Too many requests", "table": "diff-sync-errors", "transform": "=$" } ] }, "rest-get-expense-inventory-item": { "provider": "DATA_PROVIDER_REST", "method": "GET", "url": "https://{oDataBaseUrl}JIGXExpenseInventory?$format=json", "useLocalCall": true, "records": "=$.data", "outputTransform": "={\n \"top\": @ctx.parameters.\"$top\",\n \"skip\": @ctx.parameters.\"$skip\",\n \"data\" : @ctx.response.body ? $map(@ctx.response.body.value, function($item){$merge([$item, {\"id\": $item.InventoryID}])}) : []\n}", "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "$format": { "type": "string", "location": "query", "required": false, "value": "json" }, "oDataBaseUrl": { "type": "string", "location": "path", "required": true }, "$filter": { "type": "string", "location": "query", "required": false }, "$top": { "type": "number", "location": "query", "required": true, "value": 500 }, "$skip": { "type": "number", "location": "query", "required": true, "value": 0 } }, "continuation": { "when": "=$count(@ctx.output.data) = $number(@ctx.output.top)", "url": "https://{oDataBaseUrl}JIGXExpenseInventory?$format=json", "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "oDataBaseUrl": { "type": "string", "location": "path", "required": true }, "$top": { "type": "number", "location": "query", "required": true, "value": 500 }, "$skip": { "type": "number", "location": "query", "required": true, "value": "=$number(@ctx.output.skip) + 500" }, "$filter": { "type": "string", "location": "query", "required": false } } }, "error": [ { "when": "=@ctx.response.status = 200 and @ctx.response.body = ''", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "No data returned from Acumatica", "table": "diff-sync-errors", "transform": "=$" }, { "when": "=@ctx.response.status = 504", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "504 Gateway Timeout", "table": "diff-sync-errors", "transform": "=$" }, { "when": "=@.response.status = 401", "title": "Unauthorized", "description": "Unauthorized", "notification": true, "retry": { "maxRetries": 3, "delay": 5000 } } ] }, "rest-get-expense-projects": { "provider": "DATA_PROVIDER_REST", "method": "GET", "url": "https://{oDataBaseUrl}JIGXExpProjectDetails", "useLocalCall": true, "records": "=$.data", "outputTransform": "={\n \"top\": @ctx.parameters.\"$top\",\n \"skip\": @ctx.parameters.\"$skip\",\n \"data\" : @ctx.response.body.value\n}", "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "$format": { "type": "string", "location": "query", "required": false, "value": "json" }, "oDataBaseUrl": { "type": "string", "location": "path", "required": true }, "$filter": { "type": "string", "location": "query", "required": false }, "$top": { "type": "number", "location": "query", "required": true, "value": 1000 }, "$skip": { "type": "number", "location": "query", "required": true, "value": 0 } }, "continuation": { "when": "=$count(@ctx.output.data) = $number(@ctx.output.top)", "url": "https://{oDataBaseUrl}JIGXExpProjectDetails", "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "oDataBaseUrl": { "type": "string", "location": "path", "required": true }, "$top": { "type": "number", "location": "query", "required": true, "value": 1000 }, "$skip": { "type": "number", "location": "query", "required": true, "value": "=$number(@ctx.output.skip) + 1000" }, "$filter": { "type": "string", "location": "query", "required": false } } }, "error": [ { "when": "=@ctx.response.status = 200 and @ctx.response.body = ''", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "No data returned from Acumatica", "table": "diff-sync-errors", "transform": "=$" }, { "when": "=@ctx.response.status = 504", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "504 Gateway Timeout", "table": "diff-sync-errors", "transform": "=$" }, { "when": "=@.response.status = 401", "title": "Unauthorized", "description": "Unauthorized", "notification": true, "retry": { "maxRetries": 3, "delay": 5000 } } ] }, "rest-get-expense-receipt-check": { "provider": "DATA_PROVIDER_REST", "method": "GET", "useLocalCall": true, "url": "https://{acumaticaurl}ExpenseReceipt/{id}", "records": "=$.data", "forRowsWithMatchingIds": true, "outputTransform": "={\n \"top\": @ctx.parameters.\"$top\",\n \"skip\": @ctx.parameters.\"$skip\",\n \"data\" : @ctx.response.body ? $map(@ctx.response.body, function($item){$merge([$item, { \"Remote\": true }])}) : []\n}", "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "acumaticaurl": { "type": "string", "location": "path", "required": true }, "id": { "type": "string", "location": "path", "required": false } }, "error": [ { "when": "=$contains(@ctx.error.message, \"No credentials\")", "notification": true, "description": "No details for Acumatica oAuth credentials found.", "table": "diff-sync-errors", "transform": "=$", "title": "No credentials for Acumatica", "icon": "lock", "details": "Please ensure your secondary credentials under your profile are logged in and connected to Acumatica." }, { "when": "=@ctx.response.status = 200 and @ctx.response.body = ''", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "No data returned from Acumatica", "table": "diff-sync-errors", "transform": "=$" }, { "when": "=@ctx.response.status = 504", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "504 Gateway Timeout", "table": "diff-sync-errors", "transform": "=$" }, { "when": "=@.response.status = 401", "title": "Unauthorized", "description": "Unauthorized", "notification": true, "retry": { "maxRetries": 3, "delay": 5000 } } ] }, "rest-get-expense-receipt": { "provider": "DATA_PROVIDER_REST", "method": "GET", "useLocalCall": true, "url": "https://{acumaticaurl}ExpenseReceipt", "records": "=$.data", "forRowsWithMatchingIds": true, "outputTransform": "={\n \"top\": @ctx.parameters.\"$top\",\n \"skip\": @ctx.parameters.\"$skip\",\n \"data\" : @ctx.response.body ? $map(@ctx.response.body, function($item){$merge([$item, { \"Remote\": true }])}) : []\n}", "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "acumaticaurl": { "type": "string", "location": "path", "required": true }, "$top": { "type": "number", "location": "query", "required": true, "value": 500 }, "$skip": { "type": "number", "location": "query", "required": true, "value": 0 }, "$filter": { "type": "string", "location": "query", "required": false }, "$expand": { "type": "string", "location": "query", "required": false, "value": "ReceiptDetails,TaxDetails,Files" } }, "continuation": { "when": "=$count(@ctx.output.data) = $number(@ctx.output.top)", "url": "https://{acumaticaurl}ExpenseReceipt", "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "acumaticaurl": { "type": "string", "location": "path", "required": true }, "$top": { "type": "number", "location": "query", "required": true, "value": 500 }, "$skip": { "type": "number", "location": "query", "required": true, "value": "=$number(@ctx.output.skip) + 500" }, "$filter": { "type": "string", "location": "query", "required": false }, "$expand": { "type": "string", "location": "query", "required": false, "value": "ReceiptDetails,TaxDetails,Files" } } }, "error": [ { "when": "=$contains(@ctx.error.message, \"No credentials\")", "notification": true, "description": "No details for Acumatica oAuth credentials found.", "table": "diff-sync-errors", "transform": "=$", "title": "No credentials for Acumatica", "icon": "lock", "details": "Please ensure your secondary credentials under your profile are logged in and connected to Acumatica." }, { "when": "=@ctx.response.status = 200 and @ctx.response.body = ''", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "No data returned from Acumatica", "table": "diff-sync-errors", "transform": "=$" }, { "when": "=@ctx.response.status = 504", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "504 Gateway Timeout", "table": "diff-sync-errors", "transform": "=$" }, { "when": "=@.response.status = 401", "title": "Unauthorized", "description": "Unauthorized", "notification": true, "retry": { "maxRetries": 3, "delay": 5000 } } ] }, "rest-get-file-content-plural": { "provider": "DATA_PROVIDER_REST", "method": "GET", "url": "https://{acumaticaurl}/files/{id}", "useLocalCall": true, "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "id": { "type": "string", "location": "path", "required": true }, "filename": { "type": "string", "location": "path", "required": true }, "acumaticaurl": { "type": "string", "location": "path", "required": true } }, "format": "pdf", "conversions": [ { "property": "file", "from": "buffer", "to": "local-uri" } ], "outputTransform": "{\n \"id\" : $.inputs.id\n ,\"file\" : $.data\n ,\"filename\" : $substringAfter($.inputs.filename , '\\\\')\n}\n", "forRowsWithValues": { "id": "id" } }, "rest-get-not-deleted-expense-receipts": { "provider": "DATA_PROVIDER_REST", "method": "GET", "url": "https://{oDataBaseUrl}JIGXExpenseReceiptsDeleted", "useLocalCall": true, "records": "=$.data", "outputTransform": "={\n \"top\": @ctx.parameters.\"$top\",\n \"skip\": @ctx.parameters.\"$skip\",\n \"data\" : @ctx.response.body ? $map(@ctx.response.body.value, function($item){$merge([$item, {\"id\": $item.id}])}) : []\n}", "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "$format": { "type": "string", "location": "query", "required": false, "value": "json" }, "oDataBaseUrl": { "type": "string", "location": "path", "required": true }, "$filter": { "type": "string", "location": "query", "required": false }, "$top": { "type": "number", "location": "query", "required": true, "value": 500 }, "$skip": { "type": "number", "location": "query", "required": true, "value": 0 } }, "continuation": { "when": "=$count(@ctx.output.data) = $number(@ctx.output.top)", "url": "https://{oDataBaseUrl}JIGXExpenseReceiptsDeleted", "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "oDataBaseUrl": { "type": "string", "location": "path", "required": true }, "$top": { "type": "number", "location": "query", "required": true, "value": 500 }, "$skip": { "type": "number", "location": "query", "required": true, "value": "=$number(@ctx.output.skip) + 500" }, "$filter": { "type": "string", "location": "query", "required": false } } }, "error": [ { "when": "=@ctx.response.status = 200 and @ctx.response.body = ''", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "No data returned from Acumatica", "table": "diff-sync-errors", "transform": "=$" }, { "when": "=@ctx.response.status = 504", "retry": { "delay": 5000, "maxRetries": 4 }, "notification": false, "description": "504 Gateway Timeout", "table": "diff-sync-errors", "transform": "=$" }, { "when": "=@.response.status = 401", "title": "Unauthorized", "description": "Unauthorized", "notification": true, "retry": { "maxRetries": 3, "delay": 5000 } } ] }, "rest-put-expense-file": { "provider": "DATA_PROVIDER_REST", "url": "https://{acumaticaurl}files/PX.Objects.EP.ExpenseClaimDetailEntry/ClaimDetails/{expId}/{filename}", "method": "PUT", "useLocalCall": true, "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "expId": { "type": "string", "location": "path", "required": true }, "Content-Type": { "location": "header", "required": true, "type": "string", "value": "image/jpeg" }, "file": { "location": "body", "required": true, "type": "image" }, "filename": { "location": "path", "required": true, "type": "string" }, "acumaticaurl": { "type": "string", "location": "path", "required": true } }, "conversions": [ { "property": "file", "from": "local-uri", "to": "buffer" } ], "outputTransform": "={\n \"id\": $substringAfter(@ctx.response.headers.location, '/files/'),\n \"custId\": @ctx.parameters.custId\n}\n", "guard": { "function": "rest-get-expense-receipt-check", "parameters": { "accessToken": "acuerp", "acumaticaurl": "=@ctx.solution.settings.custom.acumaticaurl", "id": "=@ctx.parameters.expId" }, "onInitial": true, "result": "=@ctx.response.status = 200 ? false:true", "operations": [ { "type": "operation.execute-sql", "tables": [ "customerfiles" ], "statements": [ { "statement": "DELETE FROM customerfiles\nWHERE json_extract(data , '$.expId') = @expId\n", "parameters": { "expId": "=@ctx.parameters.expId" } } ] } ] }, "error": [ { "when": "=(@ctx.response.status = 400) or (@ctx.response.status = 404)", "title": "Bad Request", "description": "Please screenshot and email support at markus@jigx.com", "notification": true, "details": "=@ctx.response.body", "retry": { "maxRetries": 3, "delay": 5000 } }, { "when": "=@.response.status = 401", "title": "Unauthorized", "description": "Unauthorized", "notification": true, "retry": { "maxRetries": 3, "delay": 5000 } }, { "when": "=@ctx.response.status = 504", "title": "504 Retry error", "description": "Retry", "icon": "button-loop-1", "retry": { "delay": 16000, "maxRetries": 4 }, "notification": true }, { "when": "=@ctx.response.status = 503", "icon": "on-error-sad", "title": "Server is temporarily unavailable", "description": "\"The server is currently unavailable, please try again in a few minutes.\"\n", "details": "=@ctx.response.body", "notification": true, "retry": { "maxRetries": 3, "delay": 5000 } }, { "when": "=@ctx.response.status = 429", "retry": { "delay": 16000, "maxRetries": 4 }, "notification": true, "description": "Too many requests", "table": "diff-sync-errors", "transform": "=$" } ] }, "rest-save-expense-receipt": { "provider": "DATA_PROVIDER_REST", "method": "PUT", "url": "https://{acumaticaurl}ExpenseReceipt?$expand=ReceiptDetails,TaxDetails,Files", "forRowsWithMatchingIds": true, "useLocalCall": true, "parameters": { "accessToken": { "location": "header", "required": true, "type": "acuerp", "value": "acuerp" }, "acumaticaurl": { "type": "string", "location": "path", "required": true }, "msgBody": { "type": "string", "location": "body", "required": true } }, "inputTransform": "=$sift(@ctx.parameters.msgBody, function($v, $k) { $k != \"id\" })", "outputTransform": "=$merge([@ctx.response.body, { \"Remote\": true } ])", "error": [ { "when": "=@.response.status = 401", "title": "Unauthorized", "description": "Unauthorized", "notification": true, "retry": { "maxRetries": 3, "delay": 5000 } }, { "when": "=@ctx.response.status = 422", "title": "Missing or incorrect information", "description": "=\"Something went wrong when creating the Expense Receipt\"", "details": "=$utilities.extractErrors(@ctx.response.body)", "notification": true, "table": "=@ctx.entity & \"_error\"", "icon": "server-error-document", "transform": "=@ctx.response.body" }, { "when": "=@ctx.response.status = 504", "title": "504 Retry error", "description": "Retry", "icon": "button-loop-1", "retry": { "delay": 16000, "maxRetries": 4 }, "notification": false }, { "when": "=@ctx.response.status = 500", "icon": "on-error-sad", "title": "Something Went Wrong", "description": "\"It seems like something went wrong when trying to create expense receipt.\nPlease screenshot and email to markus@jigx.com\"\n", "details": "=@ctx.response.body", "notification": true }, { "when": "=@ctx.response.status = 503", "icon": "on-error-sad", "title": "Server is temporarily unavailable", "description": "\"The server is currently unavailable, please try again in a few minutes.\"\n", "details": "=@ctx.response.body", "notification": true } ] } }, "jigs": { "jig-add-expense-receipt": { "title": { "id": "add-new-expense" }, "type": "jig.default", "datasources": { "expense-receipts": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_LOCAL", "entities": [ "expense-receipts" ], "query": "SELECT id\nFROM [expense-receipts] ORDER BY timestamp DESC LIMIT 1\n" } }, "ExpenseItems": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_LOCAL", "entities": [ { "entity": "expense-inventory-items" } ], "query": "SELECT trim(id) as id, data FROM [expense-inventory-items] order by id", "jsonProperties": [ "data" ] } }, "ExpenseProjects": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_LOCAL", "entities": [ "expense-projects" ], "query": "SELECT DISTINCT \n trim(json_extract(data, '$.ProjectID')) AS ProjectID,\n trim(json_extract(data, '$.ProjectDescription')) AS ProjectDescription,\n trim(json_extract(data, '$.CustomerID')) AS CustomerID,\n trim(json_extract(data, '$.Customer_Description')) AS Customer_Description,\n trim(json_extract(data, '$.CustomerLocation')) AS CustomerLocation,\n trim(json_extract(data, '$.Location_Descripion')) AS Location_Descripion\nFROM [expense-projects]\nWHERE json_extract(data, '$.ProjectStatus') = 'Active'\nAND json_extract(data, '$.Type') = 'Contract'\nand (\n json_extract(data, '$.ProjectID') LIKE '%' || @search || '%' OR\n json_extract(data, '$.ProjectDescription') LIKE '%' || @search || '%' OR\n json_extract(data, '$.CustomerID') LIKE '%' || @search || '%' OR\n json_extract(data, '$.Customer_Description') LIKE '%' || @search || '%' OR\n @search = '' OR @search IS NULL\n )\nORDER BY '$.ProjectID'\n", "queryParameters": { "search": "=@ctx.components.component-expense-receipt.outputs.projectSearch" }, "jsonProperties": [ "data" ] } }, "projectTasks": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_LOCAL", "entities": [ { "entity": "expense-projects" } ], "query": "SELECT DISTINCT \n trim(json_extract(data, '$.TaskID')) AS TaskID,\n trim(json_extract(data, '$.TaskDescription')) AS TaskDescription\nFROM [expense-projects]\nWHERE trim(json_extract(data, '$.ProjectID')) = @projectID and TaskID IS NOT NULL\nORDER BY TaskID\n", "queryParameters": { "projectID": "=$trim(@ctx.components.component-expense-receipt.outputs.projectID)" }, "jsonProperties": [ "data" ] } }, "costCodes": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_LOCAL", "entities": [ { "entity": "expense-projects" } ], "query": "SELECT DISTINCT \n trim(json_extract(data, '$.CostCode')) AS CostCode,\n trim(json_extract(data, '$.CostCodeDescription')) AS CostCodeDescription\nFROM [expense-projects]\nWHERE trim(json_extract(data, '$.ProjectID')) = @projectID\nAND trim(json_extract(data, '$.TaskID')) = @taskID\nORDER BY CostCode\n", "queryParameters": { "projectID": "=$trim(@ctx.components.component-expense-receipt.outputs.projectID)", "taskID": "=$trim(@ctx.components.component-expense-receipt.outputs.projectTaskID)" }, "jsonProperties": [ "data" ] } }, "paidWith": { "type": "datasource.static", "options": { "data": [ { "id": 1, "title": "Personal Account" }, { "id": 2, "title": "Corporate Card, Company Expense" }, { "id": 3, "title": "Corporate Card, Personal Expense" } ] } }, "corpCard": { "type": "datasource.sqlite", "options": { "provider": "DATA_PROVIDER_LOCAL", "entities": [ { "entity": "corpCards" } ], "query": "SELECT id, '$.EmployeeID', '$.CorporateCardID','$.EmployeeName','$.CardNumber' FROM [corpCards] WHERE '$.EmployeeID' = @EmployeeID", "queryParameters": { "EmployeeID": "=$trim(@ctx.datasources.data-who-am-i.employeeID)" } } } }, "children": [ { "type": "component.custom-component", "componentId": "component-expense-receipt", "instanceId": "component-expense-receipt", "inputs": { "ExpenseItems": "=@ctx.datasources.ExpenseItems", "instanceId": "=@ctx.jig.instanceId", "expenseProjects": "=@ctx.datasources.ExpenseProjects", "projectTasks": "=@ctx.datasources.projectTasks", "costCodes": "=@ctx.datasources.costCodes", "newExpense": true, "paidWith": "=@ctx.datasources.paidWith", "corpCards": "=@ctx.datasources.corpCard" } } ], "actions": [ { "children": [ { "type": "action.action-list", "options": { "title": "Save Expense Receipt", "isSequential": true, "style": { "isDisabled": "=$not(@ctx.components.component-expense-receipt.outputs.errorState)" }, "actions": [ { "type": "action.set-state", "options": { "state": "=@ctx.solution.state.expenseFormRequired", "value": false } }, { "type": "action.execute-entity", "options": { "provider": "DATA_PROVIDER_REST", "entity": "expense-receipts", "method": "save", "function": "rest-save-expense-receipt", "queueOperation": "replace", "functionParameters": { "accessToken": "acuerp", "acumaticaurl": "=@ctx.solution.settings.custom.acumaticaurl", "msgBody": "=$expenses.generateExpenseReceiptJSON(@ctx.components.component-expense-receipt.outputs.expenseReceiptFormJSON)" }, "data": "=$expenses.generateExpenseReceiptJSON(@ctx.components.component-expense-receipt.outputs.expenseReceiptFormJSON)" } }, { "type": "action.execute-entities", "when": "=(@ctx.components.component-expense-receipt.outputs.expenseImage) ? true : false\n", "options": { "provider": "DATA_PROVIDER_REST", "entity": "customerfiles", "method": "save", "goBack": "stay", "queueOperation": "replace", "function": "rest-put-expense-file", "data": "=$map(@ctx.components.component-expense-receipt.outputs.expenseImage, function($v, $i, $a) {\n $.{\n \"expId\" : @ctx.datasources.expense-receipts.id,\n \"Content-Type\" : \"image/jpeg\",\n \"acumaticaurl\" : @ctx.solution.settings.custom.AcumaticaExpURL,\n \"accessToken\" : acuerp,\n \"filename\" : $split($v, \"/\")[-1],\n \"file\" : $v\n }})[]\n" } }, { "type": "action.go-back" } ] } } ] } ], "summary": { "children": { "type": "component.summary", "options": { "layout": "default", "leftIcon": { "element": "icon", "icon": "currency-dollar-circle", "isDuotone": true }, "title": { "text": "=@ctx.components.component-expense-receipt.outputs.expenseReceiptFormJSON.ClaimAmount", "format": { "numberStyle": "currency", "currency": "USD" } }, "subtitle": "Claim Amount" } } } }, "jig-edit-expense-receipt": { "title": { "id": "edit-expense" }, "type": "jig.default", "header": { "type": "component.jig-header", "options": { "height": "small", "actions": [ { "type": "action.confirm", "options": { "title": "Delete", "icon": "bin-1", "isHidden": "=@ctx.jig.inputs.status != 'Released' or $not($exists(@ctx.jig.inputs.status)) ? @ctx.solution.state.expenseReceiptEditModeDisabled = false ? true:false:true", "style": { "isDanger": true }, "isConfirmedAutomatically": false, "