2020-02-03 10:24:25 +01:00
|
|
|
import path from "path"
|
|
|
|
import {
|
|
|
|
getRecordApi,
|
|
|
|
getCollectionApi,
|
|
|
|
getIndexApi,
|
|
|
|
getActionsApi,
|
|
|
|
} from "../src"
|
|
|
|
import memory from "./memory"
|
|
|
|
import { setupDatastore } from "../src/appInitialise"
|
|
|
|
import {
|
|
|
|
configFolder,
|
|
|
|
fieldDefinitions,
|
|
|
|
templateDefinitions,
|
|
|
|
joinKey,
|
|
|
|
isSomething,
|
|
|
|
crypto as nodeCrypto,
|
|
|
|
} from "../src/common"
|
|
|
|
import { getNewIndexTemplate } from "../src/templateApi/createNodes"
|
|
|
|
import { indexTypes } from "../src/templateApi/indexes"
|
|
|
|
import getTemplateApi from "../src/templateApi"
|
|
|
|
import getAuthApi from "../src/authApi"
|
|
|
|
import { createEventAggregator } from "../src/appInitialise/eventAggregator"
|
|
|
|
import { filter, find } from "lodash/fp"
|
|
|
|
import { createBehaviourSources } from "../src/actionsApi/buildBehaviourSource"
|
|
|
|
import { createAction, createTrigger } from "../src/templateApi/createActions"
|
|
|
|
import { initialiseActions } from "../src/actionsApi/initialise"
|
2020-03-24 11:56:48 +01:00
|
|
|
import { setCleanupFunc } from "../src/transactions/setCleanupFunc"
|
2020-02-03 10:24:25 +01:00
|
|
|
import { permission } from "../src/authApi/permissions"
|
|
|
|
import { generateFullPermissions } from "../src/authApi/generateFullPermissions"
|
|
|
|
import { initialiseData } from "../src/appInitialise/initialiseData"
|
|
|
|
|
|
|
|
export const testFileArea = testNameArea =>
|
|
|
|
path.join("test", "fs_test_area", testNameArea)
|
|
|
|
export const testConfigFolder = testAreaName =>
|
|
|
|
path.join(testFileArea(testAreaName), configFolder)
|
|
|
|
export const testFieldDefinitionsPath = testAreaName =>
|
|
|
|
path.join(testFileArea(testAreaName), fieldDefinitions)
|
|
|
|
export const testTemplatesPath = testAreaName =>
|
|
|
|
path.join(testFileArea(testAreaName), templateDefinitions)
|
|
|
|
|
|
|
|
export const getMemoryStore = () => setupDatastore(memory({}))
|
2020-03-27 17:58:32 +01:00
|
|
|
export const getMemoryTemplateApi = store => {
|
2020-02-03 10:24:25 +01:00
|
|
|
const app = {
|
2020-03-24 11:56:48 +01:00
|
|
|
datastore: store || getMemoryStore(),
|
2020-04-14 10:49:10 +02:00
|
|
|
publish: () => { },
|
2020-02-03 10:24:25 +01:00
|
|
|
getEpochTime: async () => new Date().getTime(),
|
|
|
|
user: { name: "", permissions: [permission.writeTemplates.get()] },
|
|
|
|
}
|
|
|
|
app.removePermission = removePermission(app)
|
|
|
|
app.withOnlyThisPermission = withOnlyThisPermission(app)
|
|
|
|
app.withNoPermissions = withNoPermissions(app)
|
|
|
|
const templateApi = getTemplateApi(app)
|
|
|
|
templateApi._eventAggregator = createEventAggregator()
|
|
|
|
templateApi._storeHandle = app.datastore
|
|
|
|
return { templateApi, app }
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: subscribe actions
|
2020-02-03 10:24:25 +01:00
|
|
|
export const appFromTempalteApi = async (
|
|
|
|
templateApi,
|
|
|
|
disableCleanupTransactions = false
|
|
|
|
) => {
|
|
|
|
const appDef = await templateApi.getApplicationDefinition()
|
|
|
|
const app = {
|
|
|
|
hierarchy: appDef.hierarchy,
|
|
|
|
datastore: templateApi._storeHandle,
|
|
|
|
publish: templateApi._eventAggregator.publish,
|
|
|
|
_eventAggregator: templateApi._eventAggregator,
|
|
|
|
getEpochTime: async () => new Date().getTime(),
|
|
|
|
crypto: nodeCrypto,
|
|
|
|
user: { name: "bob", permissions: [] },
|
|
|
|
actions: {},
|
|
|
|
}
|
|
|
|
app.removePermission = removePermission(app)
|
|
|
|
app.withOnlyThisPermission = withOnlyThisPermission(app)
|
|
|
|
app.withNoPermissions = withNoPermissions(app)
|
|
|
|
|
|
|
|
const fullPermissions = generateFullPermissions(app)
|
|
|
|
app.user.permissions = fullPermissions
|
|
|
|
|
2020-04-14 10:49:10 +02:00
|
|
|
if (disableCleanupTransactions) setCleanupFunc(app, async () => { })
|
2020-03-24 11:56:48 +01:00
|
|
|
else setCleanupFunc(app)
|
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
return app
|
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
|
|
|
|
const removePermission = app => perm => {
|
2020-02-03 10:24:25 +01:00
|
|
|
app.user.permissions = filter(
|
|
|
|
p =>
|
|
|
|
p.type !== perm.type ||
|
|
|
|
(isSomething(perm.nodeKey) && perm.nodeKey !== p.nodeKey)
|
|
|
|
)(app.user.permissions)
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
const withOnlyThisPermission = app => perm => (app.user.permissions = [perm])
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
const withNoPermissions = app => () => (app.user.permissions = [])
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
export const getRecordApiFromTemplateApi = async (
|
|
|
|
templateApi,
|
|
|
|
disableCleanupTransactions = false
|
|
|
|
) => {
|
|
|
|
const app = await appFromTempalteApi(templateApi, disableCleanupTransactions)
|
2020-03-24 11:56:48 +01:00
|
|
|
const recordapi = getRecordApi(app)
|
2020-02-03 10:24:25 +01:00
|
|
|
recordapi._storeHandle = app.datastore
|
2020-03-24 11:56:48 +01:00
|
|
|
return recordapi
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
export const getCollectionApiFromTemplateApi = async (
|
|
|
|
templateApi,
|
|
|
|
disableCleanupTransactions = false
|
|
|
|
) =>
|
|
|
|
getCollectionApi(
|
|
|
|
await appFromTempalteApi(templateApi, disableCleanupTransactions)
|
|
|
|
)
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
export const getIndexApiFromTemplateApi = async (
|
|
|
|
templateApi,
|
|
|
|
disableCleanupTransactions = false
|
|
|
|
) =>
|
|
|
|
getIndexApi(await appFromTempalteApi(templateApi, disableCleanupTransactions))
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
export const getAuthApiFromTemplateApi = async (
|
|
|
|
templateApi,
|
|
|
|
disableCleanupTransactions = false
|
|
|
|
) =>
|
|
|
|
getAuthApi(await appFromTempalteApi(templateApi, disableCleanupTransactions))
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
export const findIndex = (parentNode, name) =>
|
|
|
|
find(i => i.name === name)(parentNode.indexes)
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
export const findCollectionDefaultIndex = recordCollectionNode =>
|
|
|
|
findIndex(recordCollectionNode.parent(), recordCollectionNode.name + "_index")
|
2019-07-15 08:12:52 +02:00
|
|
|
|
|
|
|
export const hierarchyFactory = (...additionalFeatures) => templateApi => {
|
2020-02-03 10:24:25 +01:00
|
|
|
const root = templateApi.getNewRootLevel()
|
|
|
|
|
|
|
|
const settingsRecord = templateApi.getNewSingleRecordTemplate(root)
|
|
|
|
settingsRecord.name = "settings"
|
|
|
|
|
2020-04-14 10:49:10 +02:00
|
|
|
const customerRecord = templateApi.getNewModelTemplate(root, "customer")
|
2020-02-03 10:24:25 +01:00
|
|
|
customerRecord.collectionName = "customers"
|
|
|
|
findCollectionDefaultIndex(customerRecord).map =
|
|
|
|
"return {surname:record.surname, isalive:record.isalive, partner:record.partner};"
|
|
|
|
|
2020-04-14 10:49:10 +02:00
|
|
|
const partnerRecord = templateApi.getNewModelTemplate(root, "partner")
|
2020-02-03 10:24:25 +01:00
|
|
|
partnerRecord.collectionName = "partners"
|
|
|
|
|
2020-04-14 10:49:10 +02:00
|
|
|
const partnerInvoiceRecord = templateApi.getNewModelTemplate(
|
2020-02-03 10:24:25 +01:00
|
|
|
partnerRecord,
|
|
|
|
"invoice"
|
|
|
|
)
|
|
|
|
partnerInvoiceRecord.collectionName = "invoices"
|
|
|
|
findCollectionDefaultIndex(partnerInvoiceRecord).name =
|
|
|
|
"partnerInvoices_index"
|
|
|
|
|
2020-04-14 10:49:10 +02:00
|
|
|
const invoiceRecord = templateApi.getNewModelTemplate(
|
2020-02-03 10:24:25 +01:00
|
|
|
customerRecord,
|
|
|
|
"invoice"
|
|
|
|
)
|
|
|
|
invoiceRecord.collectionName = "invoices"
|
|
|
|
findCollectionDefaultIndex(invoiceRecord).map =
|
|
|
|
"return {createdDate: record.createdDate, totalIncVat: record.totalIncVat};"
|
|
|
|
|
2020-04-14 10:49:10 +02:00
|
|
|
const chargeRecord = templateApi.getNewModelTemplate(invoiceRecord, "charge")
|
2020-02-03 10:24:25 +01:00
|
|
|
chargeRecord.collectionName = "charges"
|
|
|
|
|
|
|
|
const hierarchy = {
|
|
|
|
root,
|
|
|
|
customerRecord,
|
|
|
|
invoiceRecord,
|
|
|
|
partnerRecord,
|
|
|
|
partnerInvoiceRecord,
|
|
|
|
chargeRecord,
|
|
|
|
settingsRecord,
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let feature of additionalFeatures) {
|
|
|
|
feature(hierarchy, templateApi)
|
|
|
|
}
|
|
|
|
return hierarchy
|
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
|
|
|
|
export const basicAppHierarchyCreator = templateApis =>
|
2020-02-03 10:24:25 +01:00
|
|
|
hierarchyFactory()(templateApis)
|
2019-07-15 08:12:52 +02:00
|
|
|
|
|
|
|
export const withFields = (hierarchy, templateApi) => {
|
2020-02-03 10:24:25 +01:00
|
|
|
const {
|
|
|
|
customerRecord,
|
|
|
|
invoiceRecord,
|
|
|
|
partnerInvoiceRecord,
|
|
|
|
chargeRecord,
|
|
|
|
partnerRecord,
|
|
|
|
settingsRecord,
|
|
|
|
root,
|
|
|
|
} = hierarchy
|
|
|
|
|
|
|
|
getNewFieldAndAdd(templateApi, settingsRecord)("appName", "string", "")
|
|
|
|
|
|
|
|
const newCustomerField = getNewFieldAndAdd(templateApi, customerRecord)
|
|
|
|
|
|
|
|
const partnersReferenceIndex = templateApi.getNewIndexTemplate(root)
|
|
|
|
partnersReferenceIndex.name = "partnersReference"
|
|
|
|
partnersReferenceIndex.map =
|
|
|
|
"return {name:record.businessName, phone:record.phone};"
|
2020-04-14 11:19:14 +02:00
|
|
|
partnersReferenceIndex.allowedModelNodeIds = [partnerRecord.nodeId]
|
2020-02-03 10:24:25 +01:00
|
|
|
|
|
|
|
const partnerCustomersReverseIndex = templateApi.getNewIndexTemplate(
|
|
|
|
partnerRecord,
|
|
|
|
indexTypes.reference
|
|
|
|
)
|
|
|
|
partnerCustomersReverseIndex.name = "partnerCustomers"
|
|
|
|
partnerCustomersReverseIndex.map = "return {...record};"
|
|
|
|
partnerCustomersReverseIndex.filter = "record.isalive === true"
|
2020-04-14 11:19:14 +02:00
|
|
|
partnerCustomersReverseIndex.allowedModelNodeIds = [customerRecord.nodeId]
|
2020-02-03 10:24:25 +01:00
|
|
|
hierarchy.partnerCustomersReverseIndex = partnerCustomersReverseIndex
|
|
|
|
|
|
|
|
newCustomerField("surname", "string")
|
|
|
|
newCustomerField("isalive", "bool", "true")
|
|
|
|
newCustomerField("createddate", "datetime")
|
|
|
|
newCustomerField("age", "number")
|
|
|
|
newCustomerField("profilepic", "file")
|
|
|
|
newCustomerField("partner", "reference", undefined, {
|
|
|
|
indexNodeKey: "/partnersReference",
|
|
|
|
displayValue: "name",
|
|
|
|
reverseIndexNodeKeys: [
|
|
|
|
joinKey(partnerRecord.nodeKey(), "partnerCustomers"),
|
|
|
|
],
|
|
|
|
})
|
|
|
|
|
|
|
|
const referredToCustomersReverseIndex = templateApi.getNewIndexTemplate(
|
|
|
|
customerRecord,
|
|
|
|
indexTypes.reference
|
|
|
|
)
|
|
|
|
referredToCustomersReverseIndex.name = "referredToCustomers"
|
|
|
|
referredToCustomersReverseIndex.map = "return {...record};"
|
|
|
|
referredToCustomersReverseIndex.getShardName =
|
|
|
|
"return !record.surname ? 'null' : record.surname.substring(0,1);"
|
2020-04-14 11:19:14 +02:00
|
|
|
referredToCustomersReverseIndex.allowedModelNodeIds = [customerRecord.nodeId]
|
2020-02-03 10:24:25 +01:00
|
|
|
hierarchy.referredToCustomersReverseIndex = referredToCustomersReverseIndex
|
|
|
|
|
|
|
|
const customerReferredByField = newCustomerField(
|
|
|
|
"referredBy",
|
|
|
|
"reference",
|
|
|
|
undefined,
|
|
|
|
{
|
|
|
|
indexNodeKey: "/customer_index",
|
|
|
|
displayValue: "surname",
|
|
|
|
reverseIndexNodeKeys: [
|
|
|
|
joinKey(customerRecord.nodeKey(), "referredToCustomers"),
|
|
|
|
],
|
|
|
|
}
|
|
|
|
)
|
|
|
|
hierarchy.customerReferredByField = customerReferredByField
|
|
|
|
|
|
|
|
const newInvoiceField = getNewFieldAndAdd(templateApi, invoiceRecord)
|
|
|
|
|
|
|
|
const invoiceTotalIncVatField = newInvoiceField("totalIncVat", "number")
|
|
|
|
invoiceTotalIncVatField.typeOptions.decimalPlaces = 2
|
|
|
|
newInvoiceField("createdDate", "datetime")
|
|
|
|
newInvoiceField("paidAmount", "number")
|
|
|
|
newInvoiceField("invoiceType", "string")
|
|
|
|
newInvoiceField("isWrittenOff", "bool")
|
|
|
|
|
|
|
|
const newPartnerField = getNewFieldAndAdd(templateApi, partnerRecord)
|
|
|
|
newPartnerField("businessName", "string")
|
|
|
|
newPartnerField("phone", "string")
|
|
|
|
|
|
|
|
const newPartnerInvoiceField = getNewFieldAndAdd(
|
|
|
|
templateApi,
|
|
|
|
partnerInvoiceRecord
|
|
|
|
)
|
|
|
|
const partnerInvoiceTotalIncVatVield = newPartnerInvoiceField(
|
|
|
|
"totalIncVat",
|
|
|
|
"number"
|
|
|
|
)
|
|
|
|
partnerInvoiceTotalIncVatVield.typeOptions.decimalPlaces = 2
|
|
|
|
newPartnerInvoiceField("createdDate", "datetime")
|
|
|
|
newPartnerInvoiceField("paidAmount", "number")
|
|
|
|
|
|
|
|
const newChargeField = getNewFieldAndAdd(templateApi, chargeRecord)
|
|
|
|
newChargeField("amount", "number")
|
|
|
|
|
|
|
|
newChargeField("partnerInvoice", "reference", undefined, {
|
|
|
|
reverseIndexNodeKeys: [
|
|
|
|
joinKey(partnerInvoiceRecord.nodeKey(), "partnerCharges"),
|
|
|
|
],
|
|
|
|
displayValue: "createdDate",
|
|
|
|
indexNodeKey: joinKey(partnerRecord.nodeKey(), "partnerInvoices_index"),
|
|
|
|
})
|
|
|
|
|
|
|
|
const partnerChargesReverseIndex = templateApi.getNewIndexTemplate(
|
|
|
|
partnerInvoiceRecord,
|
|
|
|
indexTypes.reference
|
|
|
|
)
|
|
|
|
partnerChargesReverseIndex.name = "partnerCharges"
|
|
|
|
partnerChargesReverseIndex.map = "return {...record};"
|
2020-04-14 11:19:14 +02:00
|
|
|
partnerChargesReverseIndex.allowedModelNodeIds = [chargeRecord]
|
2020-02-03 10:24:25 +01:00
|
|
|
hierarchy.partnerChargesReverseIndex = partnerChargesReverseIndex
|
|
|
|
|
|
|
|
const customersReferenceIndex = templateApi.getNewIndexTemplate(
|
|
|
|
hierarchy.root
|
|
|
|
)
|
|
|
|
customersReferenceIndex.name = "customersReference"
|
|
|
|
customersReferenceIndex.map = "return {name:record.surname}"
|
|
|
|
customersReferenceIndex.filter = "record.isalive === true"
|
2020-04-14 11:19:14 +02:00
|
|
|
customersReferenceIndex.allowedModelNodeIds = [customerRecord.nodeId]
|
2020-02-03 10:24:25 +01:00
|
|
|
|
|
|
|
newInvoiceField("customer", "reference", undefined, {
|
|
|
|
indexNodeKey: "/customersReference",
|
|
|
|
reverseIndexNodeKeys: [findCollectionDefaultIndex(invoiceRecord).nodeKey()],
|
|
|
|
displayValue: "name",
|
|
|
|
})
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export const withIndexes = (hierarchy, templateApi) => {
|
2020-02-03 10:24:25 +01:00
|
|
|
const {
|
|
|
|
root,
|
|
|
|
customerRecord,
|
|
|
|
partnerInvoiceRecord,
|
|
|
|
invoiceRecord,
|
|
|
|
partnerRecord,
|
|
|
|
chargeRecord,
|
|
|
|
} = hierarchy
|
|
|
|
const deceasedCustomersIndex = getNewIndexTemplate(root)
|
|
|
|
deceasedCustomersIndex.name = "deceased"
|
|
|
|
deceasedCustomersIndex.map =
|
|
|
|
"return {surname: record.surname, age:record.age};"
|
|
|
|
deceasedCustomersIndex.filter = "record.isalive === false"
|
|
|
|
findCollectionDefaultIndex(customerRecord).map = "return record;"
|
2020-04-14 11:19:14 +02:00
|
|
|
deceasedCustomersIndex.allowedModelNodeIds = [customerRecord.nodeId]
|
2020-02-03 10:24:25 +01:00
|
|
|
|
2020-04-14 11:19:14 +02:00
|
|
|
findCollectionDefaultIndex(invoiceRecord).allowedModelNodeIds = [
|
2020-02-03 10:24:25 +01:00
|
|
|
invoiceRecord.nodeId,
|
|
|
|
]
|
2020-04-14 11:19:14 +02:00
|
|
|
findCollectionDefaultIndex(customerRecord).allowedModelNodeIds = [
|
2020-02-03 10:24:25 +01:00
|
|
|
customerRecord.nodeId,
|
|
|
|
]
|
2020-04-14 11:19:14 +02:00
|
|
|
findCollectionDefaultIndex(partnerRecord).allowedModelNodeIds = [
|
2020-02-03 10:24:25 +01:00
|
|
|
partnerRecord.nodeId,
|
|
|
|
]
|
2020-04-14 11:19:14 +02:00
|
|
|
findIndex(partnerRecord, "partnerInvoices_index").allowedModelNodeIds = [
|
2020-02-03 10:24:25 +01:00
|
|
|
partnerInvoiceRecord.nodeId,
|
|
|
|
]
|
2020-04-14 11:19:14 +02:00
|
|
|
findCollectionDefaultIndex(chargeRecord).allowedModelNodeIds = [
|
2020-02-03 10:24:25 +01:00
|
|
|
chargeRecord.nodeId,
|
|
|
|
]
|
|
|
|
|
|
|
|
const customerInvoicesIndex = getNewIndexTemplate(root)
|
|
|
|
customerInvoicesIndex.name = "customer_invoices"
|
|
|
|
customerInvoicesIndex.map = "return record;"
|
|
|
|
customerInvoicesIndex.filter = "record.type === 'invoice'"
|
2020-04-14 11:19:14 +02:00
|
|
|
customerInvoicesIndex.allowedModelNodeIds = [invoiceRecord.nodeId]
|
2020-02-03 10:24:25 +01:00
|
|
|
|
|
|
|
const outstandingInvoicesIndex = getNewIndexTemplate(root)
|
|
|
|
outstandingInvoicesIndex.name = "Outstanding Invoices"
|
|
|
|
outstandingInvoicesIndex.filter =
|
|
|
|
"record.type === 'invoice' && record.paidAmount < record.totalIncVat"
|
|
|
|
outstandingInvoicesIndex.map = "return {...record};"
|
2020-04-14 11:19:14 +02:00
|
|
|
outstandingInvoicesIndex.allowedModelNodeIds = [
|
2020-02-03 10:24:25 +01:00
|
|
|
invoiceRecord.nodeId,
|
|
|
|
partnerInvoiceRecord.nodeId,
|
|
|
|
]
|
|
|
|
|
|
|
|
const allInvoicesAggregateGroup = templateApi.getNewAggregateGroupTemplate(
|
|
|
|
outstandingInvoicesIndex
|
|
|
|
)
|
|
|
|
allInvoicesAggregateGroup.name = "all_invoices"
|
|
|
|
|
|
|
|
const allInvoicesByType = templateApi.getNewAggregateGroupTemplate(
|
|
|
|
outstandingInvoicesIndex
|
|
|
|
)
|
|
|
|
allInvoicesByType.groupBy = "return record.invoiceType"
|
|
|
|
allInvoicesByType.name = "all_invoices_by_type"
|
|
|
|
|
|
|
|
const allInvoicesTotalAmountAggregate = templateApi.getNewAggregateTemplate(
|
|
|
|
allInvoicesByType
|
|
|
|
)
|
|
|
|
allInvoicesTotalAmountAggregate.name = "totalIncVat"
|
|
|
|
allInvoicesTotalAmountAggregate.aggregatedValue = "return record.totalIncVat"
|
|
|
|
|
|
|
|
const allInvoicesPaidAmountAggregate = templateApi.getNewAggregateTemplate(
|
|
|
|
allInvoicesByType
|
|
|
|
)
|
|
|
|
allInvoicesPaidAmountAggregate.name = "paidAmount"
|
|
|
|
allInvoicesPaidAmountAggregate.aggregatedValue = "return record.paidAmount"
|
|
|
|
|
|
|
|
const writtenOffInvoicesByType = templateApi.getNewAggregateGroupTemplate(
|
|
|
|
outstandingInvoicesIndex
|
|
|
|
)
|
|
|
|
writtenOffInvoicesByType.groupBy = "return record.invoiceType"
|
|
|
|
writtenOffInvoicesByType.name = "written_off"
|
|
|
|
writtenOffInvoicesByType.condition = "record.isWrittenOff === true"
|
|
|
|
|
|
|
|
const writtenOffInvoicesTotalAmountAggregate = templateApi.getNewAggregateTemplate(
|
|
|
|
writtenOffInvoicesByType
|
|
|
|
)
|
|
|
|
writtenOffInvoicesTotalAmountAggregate.name = "totalIncVat"
|
|
|
|
writtenOffInvoicesTotalAmountAggregate.aggregatedValue =
|
|
|
|
"return record.totalIncVat"
|
|
|
|
|
|
|
|
const customersBySurnameIndex = templateApi.getNewIndexTemplate(root)
|
|
|
|
customersBySurnameIndex.name = "customersBySurname"
|
|
|
|
customersBySurnameIndex.map = "return {...record};"
|
|
|
|
customersBySurnameIndex.filter = ""
|
2020-04-14 11:19:14 +02:00
|
|
|
customersBySurnameIndex.allowedModelNodeIds = [customerRecord.nodeId]
|
2020-02-03 10:24:25 +01:00
|
|
|
customersBySurnameIndex.getShardName =
|
|
|
|
"return !record.surname ? 'null' : record.surname.substring(0,1);"
|
|
|
|
|
|
|
|
const customersDefaultIndex = findCollectionDefaultIndex(customerRecord)
|
|
|
|
const customersNoGroupaggregateGroup = templateApi.getNewAggregateGroupTemplate(
|
|
|
|
customersDefaultIndex
|
|
|
|
)
|
|
|
|
customersNoGroupaggregateGroup.name = "Customers Summary"
|
|
|
|
const allCustomersAgeFunctions = templateApi.getNewAggregateTemplate(
|
|
|
|
customersNoGroupaggregateGroup
|
|
|
|
)
|
|
|
|
allCustomersAgeFunctions.aggregatedValue = "return record.age"
|
|
|
|
allCustomersAgeFunctions.name = "all customers - age breakdown"
|
|
|
|
|
|
|
|
const invoicesByOutstandingIndex = templateApi.getNewIndexTemplate(
|
|
|
|
customerRecord
|
|
|
|
)
|
|
|
|
invoicesByOutstandingIndex.name = "invoicesByOutstanding"
|
|
|
|
invoicesByOutstandingIndex.map = "return {...record};"
|
|
|
|
invoicesByOutstandingIndex.filter = ""
|
|
|
|
invoicesByOutstandingIndex.getShardName =
|
|
|
|
"return (record.totalIncVat > record.paidAmount ? 'outstanding' : 'paid');"
|
2020-04-14 11:19:14 +02:00
|
|
|
invoicesByOutstandingIndex.allowedModelNodeIds = [
|
2020-02-03 10:24:25 +01:00
|
|
|
partnerInvoiceRecord.nodeId,
|
|
|
|
invoiceRecord.nodeId,
|
|
|
|
]
|
|
|
|
const allInvoicesByType_Sharded = templateApi.getNewAggregateGroupTemplate(
|
|
|
|
invoicesByOutstandingIndex
|
|
|
|
)
|
|
|
|
allInvoicesByType_Sharded.groupBy = "return record.invoiceType"
|
|
|
|
allInvoicesByType_Sharded.name = "all_invoices_by_type"
|
|
|
|
|
|
|
|
const allInvoicesTotalAmountAggregate_Sharded = templateApi.getNewAggregateTemplate(
|
|
|
|
allInvoicesByType_Sharded
|
|
|
|
)
|
|
|
|
allInvoicesTotalAmountAggregate_Sharded.name = "totalIncVat"
|
|
|
|
allInvoicesTotalAmountAggregate_Sharded.aggregatedValue =
|
|
|
|
"return record.totalIncVat"
|
|
|
|
|
|
|
|
hierarchy.allInvoicesByType = allInvoicesByType
|
|
|
|
hierarchy.allInvoicesTotalAmountAggregate = allInvoicesTotalAmountAggregate
|
|
|
|
hierarchy.allInvoicesPaidAmountAggregate = allInvoicesPaidAmountAggregate
|
|
|
|
hierarchy.customersDefaultIndex = customersDefaultIndex
|
|
|
|
hierarchy.allCustomersAgeFunctions = allCustomersAgeFunctions
|
|
|
|
hierarchy.customersNoGroupaggregateGroup = customersNoGroupaggregateGroup
|
|
|
|
hierarchy.invoicesByOutstandingIndex = invoicesByOutstandingIndex
|
|
|
|
hierarchy.customersBySurnameIndex = customersBySurnameIndex
|
|
|
|
hierarchy.outstandingInvoicesIndex = outstandingInvoicesIndex
|
|
|
|
hierarchy.deceasedCustomersIndex = deceasedCustomersIndex
|
|
|
|
hierarchy.customerInvoicesIndex = customerInvoicesIndex
|
|
|
|
}
|
|
|
|
|
|
|
|
export const basicAppHierarchyCreator_WithFields = templateApi =>
|
|
|
|
hierarchyFactory(withFields)(templateApi)
|
|
|
|
|
|
|
|
export const basicAppHierarchyCreator_WithFields_AndIndexes = templateApi =>
|
|
|
|
hierarchyFactory(withFields, withIndexes)(templateApi)
|
|
|
|
|
|
|
|
export const setupApphierarchy = async (
|
|
|
|
creator,
|
|
|
|
disableCleanupTransactions = false
|
|
|
|
) => {
|
|
|
|
const { templateApi } = getMemoryTemplateApi()
|
|
|
|
const hierarchy = creator(templateApi)
|
|
|
|
await initialiseData(templateApi._storeHandle, {
|
|
|
|
hierarchy: hierarchy.root,
|
|
|
|
actions: [],
|
|
|
|
triggers: [],
|
|
|
|
})
|
|
|
|
await templateApi.saveApplicationHierarchy(hierarchy.root)
|
|
|
|
const app = await appFromTempalteApi(templateApi, disableCleanupTransactions)
|
|
|
|
const collectionApi = getCollectionApi(app)
|
|
|
|
const indexApi = getIndexApi(app)
|
|
|
|
const authApi = getAuthApi(app)
|
|
|
|
const actionsApi = getActionsApi(app)
|
|
|
|
const recordApi = await getRecordApi(app)
|
|
|
|
recordApi._storeHandle = app.datastore
|
|
|
|
actionsApi._app = app
|
|
|
|
|
|
|
|
const apis = {
|
|
|
|
recordApi,
|
|
|
|
collectionApi,
|
|
|
|
templateApi,
|
|
|
|
indexApi,
|
|
|
|
authApi,
|
|
|
|
actionsApi,
|
|
|
|
appHierarchy: hierarchy,
|
|
|
|
subscribe: templateApi._eventAggregator.subscribe,
|
|
|
|
app,
|
|
|
|
}
|
|
|
|
|
|
|
|
return apis
|
|
|
|
}
|
|
|
|
|
|
|
|
export const getNewFieldAndAdd = (templateApi, record) => (
|
|
|
|
name,
|
|
|
|
type,
|
|
|
|
initial,
|
|
|
|
typeOptions
|
|
|
|
) => {
|
|
|
|
const field = templateApi.getNewField(type)
|
|
|
|
field.name = name
|
|
|
|
field.getInitialValue = !initial ? "default" : initial
|
|
|
|
if (typeOptions) field.typeOptions = typeOptions
|
|
|
|
templateApi.addField(record, field)
|
|
|
|
return field
|
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
|
|
|
|
export const stubEventHandler = () => {
|
2020-02-03 10:24:25 +01:00
|
|
|
const events = []
|
|
|
|
return {
|
|
|
|
handle: (name, context) => {
|
|
|
|
events.push({ name, context })
|
|
|
|
},
|
|
|
|
events,
|
|
|
|
getEvents: n => filter(e => e.name === n)(events),
|
|
|
|
}
|
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
|
|
|
|
export const createValidActionsAndTriggers = () => {
|
2020-02-03 10:24:25 +01:00
|
|
|
const logMessage = createAction()
|
|
|
|
logMessage.name = "logMessage"
|
|
|
|
logMessage.behaviourName = "log"
|
|
|
|
logMessage.behaviourSource = "budibase-behaviours"
|
|
|
|
|
|
|
|
const measureCallTime = createAction()
|
|
|
|
measureCallTime.name = "measureCallTime"
|
|
|
|
measureCallTime.behaviourName = "call_timer"
|
|
|
|
measureCallTime.behaviourSource = "budibase-behaviours"
|
|
|
|
|
|
|
|
const sendEmail = createAction()
|
|
|
|
sendEmail.name = "sendEmail"
|
|
|
|
sendEmail.behaviourName = "send_email"
|
|
|
|
sendEmail.behaviourSource = "my-custom-lib"
|
|
|
|
|
|
|
|
const logOnErrorTrigger = createTrigger()
|
|
|
|
logOnErrorTrigger.actionName = "logMessage"
|
|
|
|
logOnErrorTrigger.eventName = "recordApi:save:onError"
|
|
|
|
logOnErrorTrigger.optionsCreator = "return context.error.message;"
|
|
|
|
|
|
|
|
const timeCustomerSaveTrigger = createTrigger()
|
|
|
|
timeCustomerSaveTrigger.actionName = "measureCallTime"
|
|
|
|
timeCustomerSaveTrigger.eventName = "recordApi:save:onComplete"
|
|
|
|
timeCustomerSaveTrigger.optionsCreator = "return 999;"
|
|
|
|
timeCustomerSaveTrigger.condition = "context.record.type === 'customer'"
|
|
|
|
|
|
|
|
const allActions = [logMessage, measureCallTime, sendEmail]
|
|
|
|
const allTriggers = [logOnErrorTrigger, timeCustomerSaveTrigger]
|
|
|
|
|
|
|
|
const behaviourSources = createBehaviourSources()
|
|
|
|
const logs = []
|
|
|
|
const call_timers = []
|
|
|
|
const emails = []
|
|
|
|
behaviourSources.register("budibase-behaviours", {
|
|
|
|
log: message => logs.push(message),
|
|
|
|
call_timer: opts => call_timers.push(opts),
|
|
|
|
})
|
|
|
|
behaviourSources.register("my-custom-lib", {
|
|
|
|
send_email: em => emails.push(em),
|
|
|
|
})
|
|
|
|
|
|
|
|
return {
|
|
|
|
logMessage,
|
|
|
|
measureCallTime,
|
|
|
|
sendEmail,
|
|
|
|
logOnErrorTrigger,
|
|
|
|
timeCustomerSaveTrigger,
|
|
|
|
allActions,
|
|
|
|
allTriggers,
|
|
|
|
behaviourSources,
|
|
|
|
logs,
|
|
|
|
call_timers,
|
|
|
|
emails,
|
|
|
|
}
|
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
|
|
|
|
export const createAppDefinitionWithActionsAndTriggers = async () => {
|
2020-02-03 10:24:25 +01:00
|
|
|
const {
|
|
|
|
appHierarchy,
|
|
|
|
templateApi,
|
|
|
|
app,
|
|
|
|
actionsApi,
|
|
|
|
} = await setupApphierarchy(basicAppHierarchyCreator_WithFields)
|
|
|
|
|
|
|
|
// adding validation rule so it can fail when we save it
|
|
|
|
templateApi.addRecordValidationRule(appHierarchy.customerRecord)(
|
|
|
|
templateApi.commonRecordValidationRules.fieldNotEmpty("surname")
|
|
|
|
)
|
|
|
|
|
|
|
|
await templateApi.saveApplicationHierarchy(appHierarchy.root)
|
|
|
|
|
|
|
|
const actionsAndTriggers = createValidActionsAndTriggers()
|
|
|
|
const { allActions, allTriggers, behaviourSources } = actionsAndTriggers
|
|
|
|
await templateApi.saveActionsAndTriggers(allActions, allTriggers)
|
|
|
|
app.actions = initialiseActions(
|
|
|
|
templateApi._eventAggregator.subscribe,
|
|
|
|
behaviourSources,
|
|
|
|
allActions,
|
|
|
|
allTriggers
|
|
|
|
)
|
|
|
|
app.user.permissions = generateFullPermissions(app)
|
|
|
|
app.behaviourSources = behaviourSources
|
|
|
|
const appDefinition = await templateApi.getApplicationDefinition()
|
|
|
|
return {
|
|
|
|
templateApi,
|
|
|
|
appDefinition,
|
|
|
|
...actionsAndTriggers,
|
|
|
|
...appHierarchy,
|
|
|
|
app,
|
|
|
|
actionsApi,
|
|
|
|
}
|
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
export const validUser = async (
|
|
|
|
app,
|
|
|
|
authApi,
|
|
|
|
password,
|
|
|
|
enabled = true,
|
|
|
|
accessLevels = null
|
|
|
|
) => {
|
|
|
|
const access = await authApi.getNewAccessLevel(app)
|
|
|
|
access.name = "admin"
|
|
|
|
permission.setPassword.add(access)
|
|
|
|
|
|
|
|
const access2 = await authApi.getNewAccessLevel(app)
|
|
|
|
access2.name = "admin2"
|
|
|
|
permission.setPassword.add(access)
|
|
|
|
|
|
|
|
await authApi.saveAccessLevels({ version: 0, levels: [access, access2] })
|
|
|
|
|
|
|
|
const u = authApi.getNewUser(app)
|
|
|
|
u.name = "bob"
|
|
|
|
if (accessLevels === null) u.accessLevels = ["admin"]
|
|
|
|
else u.accessLevels = accessLevels
|
|
|
|
|
|
|
|
u.enabled = enabled
|
|
|
|
|
|
|
|
await authApi.createUser(u, password)
|
|
|
|
return u
|
|
|
|
}
|