@things-factory/integration-accounting 8.0.0-beta.9 → 8.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist-server/tsconfig.tsbuildinfo +1 -1
  2. package/package.json +14 -14
  3. package/server/controllers/accounting-api/decorators.ts +47 -0
  4. package/server/controllers/accounting-api/index.ts +72 -0
  5. package/server/controllers/index.ts +3 -0
  6. package/server/controllers/xero/apis/contact/get-contact.ts +38 -0
  7. package/server/controllers/xero/apis/contact/get-contacts.ts +16 -0
  8. package/server/controllers/xero/apis/contact/index.ts +2 -0
  9. package/server/controllers/xero/apis/index.ts +4 -0
  10. package/server/controllers/xero/apis/invoice/create-invoice.ts +12 -0
  11. package/server/controllers/xero/apis/invoice/get-invoice.ts +14 -0
  12. package/server/controllers/xero/apis/invoice/get-invoices.ts +76 -0
  13. package/server/controllers/xero/apis/invoice/index.ts +4 -0
  14. package/server/controllers/xero/apis/invoice/update-invoice.ts +12 -0
  15. package/server/controllers/xero/apis/item/create-item.ts +37 -0
  16. package/server/controllers/xero/apis/item/delete-item.ts +19 -0
  17. package/server/controllers/xero/apis/item/get-item.ts +41 -0
  18. package/server/controllers/xero/apis/item/get-items.ts +41 -0
  19. package/server/controllers/xero/apis/item/index.ts +6 -0
  20. package/server/controllers/xero/apis/item/update-item.ts +35 -0
  21. package/server/controllers/xero/apis/item/update-items.ts +43 -0
  22. package/server/controllers/xero/apis/purchase-order/get-purchase-orders.ts +61 -0
  23. package/server/controllers/xero/apis/purchase-order/index.ts +1 -0
  24. package/server/controllers/xero/index.ts +8 -0
  25. package/server/controllers/xero/platform-action.ts +53 -0
  26. package/server/controllers/xero/xero.ts +215 -0
  27. package/server/engine/connector/accounting-connector.ts +33 -0
  28. package/server/engine/connector/index.ts +1 -0
  29. package/server/engine/index.ts +2 -0
  30. package/server/engine/task/accounting-api.ts +64 -0
  31. package/server/engine/task/index.ts +1 -0
  32. package/server/entities/account.ts +86 -0
  33. package/server/entities/index.ts +5 -0
  34. package/server/graphql/index.ts +7 -0
  35. package/server/graphql/resolvers/accounting/account.ts +14 -0
  36. package/server/graphql/resolvers/accounting/accounts.ts +15 -0
  37. package/server/graphql/resolvers/accounting/create-account.ts +18 -0
  38. package/server/graphql/resolvers/accounting/delete-account.ts +20 -0
  39. package/server/graphql/resolvers/accounting/delete-accounts.ts +25 -0
  40. package/server/graphql/resolvers/accounting/index.ts +25 -0
  41. package/server/graphql/resolvers/accounting/update-account.ts +18 -0
  42. package/server/graphql/resolvers/accounting/update-multiple-accounts.ts +44 -0
  43. package/server/graphql/resolvers/accounting/xero/deactivate-xero-account.ts +57 -0
  44. package/server/graphql/resolvers/accounting/xero/get-xero-auth-url.ts +32 -0
  45. package/server/graphql/resolvers/accounting/xero/index.ts +13 -0
  46. package/server/graphql/resolvers/accounting/xero/refresh-xero-access-token.ts +67 -0
  47. package/server/graphql/resolvers/accounting-api/accounting-invoice.ts +36 -0
  48. package/server/graphql/resolvers/accounting-api/accounting-item.ts +42 -0
  49. package/server/graphql/resolvers/accounting-api/accounting-purchase-order.ts +14 -0
  50. package/server/graphql/resolvers/accounting-api/index.ts +14 -0
  51. package/server/graphql/resolvers/index.ts +5 -0
  52. package/server/graphql/types/accounting/account-list.ts +8 -0
  53. package/server/graphql/types/accounting/account-patch.ts +14 -0
  54. package/server/graphql/types/accounting/account.ts +25 -0
  55. package/server/graphql/types/accounting/index.ts +44 -0
  56. package/server/graphql/types/accounting/new-account.ts +12 -0
  57. package/server/graphql/types/accounting-api/invoice.ts +65 -0
  58. package/server/graphql/types/accounting-api/item.ts +64 -0
  59. package/server/graphql/types/accounting-api/purchase-order.ts +30 -0
  60. package/server/graphql/types/index.ts +10 -0
  61. package/server/index.ts +9 -0
  62. package/server/migrations/index.ts +9 -0
  63. package/server/routers/xero-private-router.ts +24 -0
  64. package/server/routers/xero-router.ts +154 -0
  65. package/server/routes.ts +10 -0
@@ -0,0 +1,53 @@
1
+ import { config, logger } from '@things-factory/env'
2
+
3
+ import { Xero } from './xero'
4
+
5
+ const xeroConfig = config.get('accountingIntegrationXero', {})
6
+ const { apiKey, apiSecret, callback } = xeroConfig
7
+
8
+ function substitute(path, obj) {
9
+ var props = []
10
+ var re = /{([^}]+)}/g
11
+ var text
12
+
13
+ while ((text = re.exec(path))) {
14
+ props.push(text[1])
15
+ }
16
+
17
+ var result = path
18
+ props.forEach(prop => {
19
+ let value = obj[prop.trim()]
20
+ result = result.replace(`{${prop}}`, value === undefined ? '' : value)
21
+ })
22
+
23
+ return result
24
+ }
25
+
26
+ async function _action({ accounting, method = 'get', path, request }) {
27
+ const client = new Xero({
28
+ apiKey,
29
+ apiSecret,
30
+ accessToken: accounting.accessToken,
31
+ tenantId: accounting.accountId,
32
+ callback
33
+ })
34
+
35
+ const { resource = {}, payload = {} } = request
36
+
37
+ path = substitute(path, resource)
38
+
39
+ return await client[method](path, payload)
40
+ }
41
+
42
+ export const action = async ({ accounting, method = 'get', path, request }) => {
43
+ try {
44
+ return await _action({ accounting, method, path, request })
45
+ } catch (ex) {
46
+ if (ex.status === 401) {
47
+ var refreshedAccounting = await Xero.refreshAccessToken(apiKey, apiSecret, accounting)
48
+ return await _action({ accounting: refreshedAccounting, method, path, request })
49
+ } else {
50
+ logger.error(`Xero: action: ${ex}`)
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,215 @@
1
+ import fetch from 'node-fetch'
2
+
3
+ import { getRepository } from '@things-factory/shell'
4
+ import { parseJwt } from '@things-factory/utils'
5
+
6
+ import { Account } from '../../entities/account'
7
+
8
+ const ENDPOINT = 'https://api.xero.com/api.xro/2.0'
9
+ const debug = require('debug')('things-factory:integration-accounting:xero')
10
+
11
+ export type XeroConfig = {
12
+ apiKey: string
13
+ apiSecret: string
14
+ accessToken?: string
15
+ tenantId?: string
16
+ callback?: string
17
+ }
18
+
19
+ export class Xero {
20
+ private config: XeroConfig
21
+
22
+ constructor(config: XeroConfig) {
23
+ this.config = {
24
+ ...config
25
+ }
26
+ }
27
+
28
+ buildAuthURL(nonce) {
29
+ const scopes = 'offline_access openid profile email accounting.transactions accounting.settings accounting.contacts'
30
+ const { apiKey, callback: redirectUrl } = this.config
31
+
32
+ return `https://login.xero.com/identity/connect/authorize?response_type=code&client_id=${apiKey}&scope=${scopes}&redirect_uri=${redirectUrl}&state=${nonce}`
33
+ }
34
+
35
+ async get(path: string, data: any) {
36
+ const { accessToken, tenantId } = this.config
37
+
38
+ const qs = Object.entries(data)
39
+ .map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`)
40
+ .join('&')
41
+
42
+ const endpoint = `${ENDPOINT}${path}${qs ? '?' + qs : ''}`
43
+ debug('endpoint', endpoint)
44
+
45
+ const response = await fetch(endpoint, {
46
+ method: 'get',
47
+ headers: {
48
+ accept: 'application/json',
49
+ 'Content-Type': 'application/json',
50
+ Authorization: `Bearer ${accessToken}`,
51
+ 'xero-tenant-id': tenantId
52
+ }
53
+ })
54
+
55
+ if (!response.ok) {
56
+ throw response
57
+ }
58
+
59
+ let result = await response.json()
60
+ debug('response result', result)
61
+ result = this.convertStatusCode(result)
62
+
63
+ return result
64
+ }
65
+
66
+ async post(path: string, data: any = {}) {
67
+ const { accessToken, tenantId } = this.config
68
+
69
+ debug('data', data)
70
+
71
+ const jsondata = JSON.stringify(data)
72
+
73
+ const endpoint = `${ENDPOINT}${path}`
74
+ debug('endpoint', endpoint)
75
+
76
+ const response = await fetch(endpoint, {
77
+ method: 'post',
78
+ headers: {
79
+ accept: 'application/json',
80
+ 'Content-Type': 'application/json',
81
+ Authorization: `Bearer ${accessToken}`,
82
+ 'xero-tenant-id': tenantId
83
+ },
84
+ body: jsondata
85
+ })
86
+
87
+ if (!response.ok) {
88
+ throw response
89
+ }
90
+
91
+ let result = await response.json()
92
+ debug('response result', result)
93
+ result = this.convertStatusCode(result)
94
+
95
+ return result
96
+ }
97
+
98
+ async put(path: string, data: any = {}) {
99
+ const { accessToken, tenantId } = this.config
100
+
101
+ debug('data', data)
102
+
103
+ const jsondata = JSON.stringify(data)
104
+
105
+ const endpoint = `${ENDPOINT}${path}`
106
+ debug('endpoint', endpoint)
107
+
108
+ const response = await fetch(endpoint, {
109
+ method: 'put',
110
+ headers: {
111
+ accept: 'application/json',
112
+ 'Content-Type': 'application/json',
113
+ Authorization: `Bearer ${accessToken}`,
114
+ 'xero-tenant-id': tenantId
115
+ },
116
+ body: jsondata
117
+ })
118
+
119
+ if (!response.ok) {
120
+ throw response
121
+ }
122
+
123
+ let result = await response.json()
124
+ debug('response result', result)
125
+ result = this.convertStatusCode(result)
126
+
127
+ return result
128
+ }
129
+
130
+ async delete(path: string, data: any = {}) {
131
+ const { accessToken, tenantId } = this.config
132
+
133
+ debug('data', data)
134
+
135
+ const jsondata = JSON.stringify(data)
136
+
137
+ const endpoint = `${ENDPOINT}${path}`
138
+ debug('endpoint', endpoint)
139
+
140
+ const response = await fetch(endpoint, {
141
+ method: 'delete',
142
+ headers: {
143
+ accept: 'application/json',
144
+ 'Content-Type': 'application/json',
145
+ Authorization: `Bearer ${accessToken}`,
146
+ 'xero-tenant-id': tenantId
147
+ },
148
+ body: jsondata
149
+ })
150
+
151
+ if (!response.ok) {
152
+ throw response
153
+ }
154
+
155
+ let result = await response.json()
156
+ debug('response result', result)
157
+ result = this.convertStatusCode(result)
158
+
159
+ return result
160
+ }
161
+
162
+ private convertStatusCode(result: Record<string, any>): Record<string, any> {
163
+ result.ok = result.Status.toLowerCase() === 'ok'
164
+ return result
165
+ }
166
+
167
+ public static async refreshAccessToken(apiKey, apiSecret, account) {
168
+ const refreshRequestData = {
169
+ grant_type: 'refresh_token',
170
+ refresh_token: account.refreshToken
171
+ }
172
+
173
+ const refreshResponse = await fetch(`https://identity.xero.com/connect/token`, {
174
+ method: 'post',
175
+ headers: {
176
+ Authorization: `Basic ${Buffer.from(apiKey + ':' + apiSecret).toString('base64')}`,
177
+ 'Content-Type': 'application/x-www-form-urlencoded'
178
+ },
179
+ body: Object.entries(refreshRequestData)
180
+ .map(([key, value]) => encodeURIComponent(key) + '=' + encodeURIComponent(value))
181
+ .join('&')
182
+ })
183
+
184
+ if (!refreshResponse.ok) {
185
+ throw new Error(`get account information failed: ${await refreshResponse.text()}`)
186
+ }
187
+
188
+ const body = await refreshResponse.json()
189
+ const {
190
+ access_token /* token used to call the API */,
191
+ id_token /* token containing user identity details (only returned if OpenID Connect scopes are requested) */,
192
+ expires_in /* amount of seconds until the access token expires */,
193
+ token_type: tokenType /* must be Bearer */,
194
+ refresh_token
195
+ /* token used to refresh the access token once it has expired (only returned if the offline_access scope is requested).
196
+ */
197
+ } = body
198
+
199
+ const { exp } = parseJwt(access_token)
200
+
201
+ var patch = {
202
+ accessToken: access_token,
203
+ refreshToken: refresh_token,
204
+ tokenType,
205
+ expiresIn: new Date(exp * 1000)
206
+ }
207
+
208
+ const repository = getRepository(Account)
209
+
210
+ return await repository.save({
211
+ ...account,
212
+ ...patch
213
+ })
214
+ }
215
+ }
@@ -0,0 +1,33 @@
1
+ import { ConnectionManager, Connector } from '@things-factory/integration-base'
2
+
3
+ export class AccountingConnector implements Connector {
4
+ async ready(connectionConfigs) {
5
+ await Promise.all(connectionConfigs.map(this.connect))
6
+
7
+ ConnectionManager.logger.info('accounting-connector connections are ready')
8
+ }
9
+
10
+ async connect(connection) {
11
+ const { domain, name, endpoint } = connection
12
+
13
+ ConnectionManager.addConnectionInstance(connection, { ...connection })
14
+
15
+ ConnectionManager.logger.info(`accounting-connector connection(${name}:${connection.endpoint}) is connected`)
16
+ }
17
+
18
+ async disconnect(connection) {
19
+ ConnectionManager.removeConnectionInstance(connection)
20
+
21
+ ConnectionManager.logger.info(`accounting-connector connection(${connection.name}) is disconnected`)
22
+ }
23
+
24
+ get parameterSpec() {
25
+ return []
26
+ }
27
+
28
+ get taskPrefixes() {
29
+ return ['accounting']
30
+ }
31
+ }
32
+
33
+ ConnectionManager.registerConnector('accounting-connector', new AccountingConnector())
@@ -0,0 +1 @@
1
+ import './accounting-connector'
@@ -0,0 +1,2 @@
1
+ import './connector'
2
+ import './task'
@@ -0,0 +1,64 @@
1
+ import { ConnectionManager, TaskRegistry } from '@things-factory/integration-base'
2
+ import { getRepository } from '@things-factory/shell'
3
+ import { access } from '@things-factory/utils'
4
+
5
+ import { AccountingAPI as API } from '../../controllers/accounting-api'
6
+ import { Account } from '../../entities'
7
+
8
+ async function AccountingAPI(step, { logger, data, domain }) {
9
+ var {
10
+ connection,
11
+ params: { account: name, api, accessor }
12
+ } = step
13
+
14
+ var client = ConnectionManager.getConnectionInstanceByName(domain, connection) || {}
15
+ if (!client) {
16
+ throw new Error(`no connection : ${connection}`)
17
+ }
18
+
19
+ if (!api) {
20
+ throw new Error(`no api defined`)
21
+ }
22
+
23
+ const repository = getRepository(Account)
24
+ const account: Account = await repository.findOne({
25
+ where: { domain: { id: domain.id }, name }
26
+ })
27
+
28
+ if (!account) {
29
+ throw new Error(`no account defined`)
30
+ }
31
+
32
+ var result = await API[api](account, accessor ? access(accessor, data) : {})
33
+
34
+ return {
35
+ data: result
36
+ }
37
+ }
38
+
39
+ AccountingAPI.parameterSpec = [
40
+ {
41
+ type: 'entity-selector',
42
+ name: 'account',
43
+ label: 'account',
44
+ property: {
45
+ queryName: 'accounts',
46
+ valueKey: 'name'
47
+ }
48
+ },
49
+ {
50
+ type: 'select',
51
+ name: 'api',
52
+ label: 'api',
53
+ property: {
54
+ options: ['', 'getAccountingInvoices']
55
+ }
56
+ },
57
+ {
58
+ type: 'string',
59
+ name: 'accessor',
60
+ label: 'accessor'
61
+ }
62
+ ]
63
+
64
+ TaskRegistry.registerTaskHandler('accounting-api', AccountingAPI)
@@ -0,0 +1 @@
1
+ import './accounting-api'
@@ -0,0 +1,86 @@
1
+ import { User } from '@things-factory/auth-base'
2
+ import { Domain } from '@things-factory/shell'
3
+ import { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
4
+
5
+ @Entity()
6
+ @Index('ix_account_0', (account: Account) => [account.domain, account.name], { unique: true })
7
+ export class Account {
8
+ @PrimaryGeneratedColumn('uuid')
9
+ id: string
10
+
11
+ @ManyToOne(type => Domain)
12
+ domain: Domain
13
+
14
+ @Column()
15
+ platform: string
16
+
17
+ @Column({
18
+ nullable: true
19
+ })
20
+ accountId: string
21
+
22
+ @Column()
23
+ countryCode: string
24
+
25
+ @Column({
26
+ nullable: true
27
+ })
28
+ status: string
29
+
30
+ @Column()
31
+ name: string
32
+
33
+ @Column({
34
+ nullable: true
35
+ })
36
+ accessInfo: string
37
+
38
+ @Column({
39
+ nullable: true
40
+ })
41
+ accessToken: string
42
+
43
+ @Column({ default: false, nullable: true })
44
+ trackedInventory: Boolean
45
+
46
+ @Column({
47
+ nullable: true
48
+ })
49
+ refreshToken: string
50
+
51
+ @Column({
52
+ nullable: true
53
+ })
54
+ expiresIn: Date
55
+
56
+ @Column({
57
+ nullable: true
58
+ })
59
+ tokenType: string
60
+
61
+ @Column({
62
+ nullable: true
63
+ })
64
+ accountInfo: string
65
+
66
+ @Column({
67
+ nullable: true
68
+ })
69
+ description: string
70
+
71
+ @CreateDateColumn()
72
+ createdAt: Date
73
+
74
+ @UpdateDateColumn()
75
+ updatedAt: Date
76
+
77
+ @ManyToOne(type => User, {
78
+ nullable: true
79
+ })
80
+ creator: User
81
+
82
+ @ManyToOne(type => User, {
83
+ nullable: true
84
+ })
85
+ updater: User
86
+ }
@@ -0,0 +1,5 @@
1
+ import { Account } from './account'
2
+
3
+ export const entities = [Account]
4
+
5
+ export { Account }
@@ -0,0 +1,7 @@
1
+ import * as typeDefs from './types'
2
+ import * as resolvers from './resolvers'
3
+
4
+ export const schema = {
5
+ typeDefs,
6
+ resolvers
7
+ }
@@ -0,0 +1,14 @@
1
+ import { getRepository } from '@things-factory/shell'
2
+
3
+ import { Account } from '../../../entities'
4
+
5
+ export const accountResolver = {
6
+ async account(_: any, { id }, context: ResolverContext) {
7
+ const repository = getRepository(Account)
8
+
9
+ return await getRepository(Account).findOne({
10
+ where: { domain: { id: context.state.domain.id }, id },
11
+ relations: ['domain', 'creator', 'updater']
12
+ })
13
+ }
14
+ }
@@ -0,0 +1,15 @@
1
+ import { convertListParams, getRepository, ListParam } from '@things-factory/shell'
2
+
3
+ import { Account } from '../../../entities'
4
+
5
+ export const accountsResolver = {
6
+ async accounts(_: any, params: ListParam, context: ResolverContext) {
7
+ const { domain } = context.state
8
+ const convertedParams = convertListParams(params, { domain })
9
+ const [items, total] = await getRepository(Account).findAndCount({
10
+ ...convertedParams,
11
+ relations: ['domain', 'creator', 'updater']
12
+ })
13
+ return { items, total }
14
+ }
15
+ }
@@ -0,0 +1,18 @@
1
+ import { getRepository } from '@things-factory/shell'
2
+
3
+ import { ACCOUNTING_STATUS } from '../../../controllers'
4
+ import { Account } from '../../../entities'
5
+
6
+ export const createAccount = {
7
+ async createAccount(_: any, { account }, context: ResolverContext) {
8
+ const { domain, user } = context.state
9
+
10
+ return await getRepository(Account).save({
11
+ status: ACCOUNTING_STATUS.INACTIVE,
12
+ ...account,
13
+ domain,
14
+ creator: user,
15
+ updater: user
16
+ })
17
+ }
18
+ }
@@ -0,0 +1,20 @@
1
+ import { getRepository } from '@things-factory/shell'
2
+
3
+ import { ACCOUNTING_STATUS } from '../../../controllers'
4
+ import { Account } from '../../../entities'
5
+
6
+ export const deleteAccount = {
7
+ async deleteAccount(_: any, { id }, context: ResolverContext) {
8
+ const foundAccount: Account = await getRepository(Account).findOne({
9
+ where: { domain: { id: context.state.domain.id }, id }
10
+ })
11
+
12
+ await getRepository(Account).save({
13
+ ...foundAccount,
14
+ status: ACCOUNTING_STATUS.TERMINATED,
15
+ updater: context.state.user
16
+ })
17
+
18
+ return true
19
+ }
20
+ }
@@ -0,0 +1,25 @@
1
+ import { In } from 'typeorm'
2
+
3
+ import { getRepository } from '@things-factory/shell'
4
+
5
+ import { ACCOUNTING_STATUS } from '../../../controllers'
6
+ import { Account } from '../../../entities'
7
+
8
+ export const deleteAccounts = {
9
+ async deleteAccounts(_: any, { ids }, context: ResolverContext) {
10
+ let foundAccounts: Account[] = await getRepository(Account).find({
11
+ where: { domain: { id: context.state.domain.id }, id: In(ids) }
12
+ })
13
+
14
+ const updatedAccount = foundAccounts.map((account: Account) => {
15
+ return {
16
+ ...account,
17
+ status: ACCOUNTING_STATUS.TERMINATED,
18
+ updater: context.state.user
19
+ }
20
+ })
21
+
22
+ await getRepository(Account).save(updatedAccount)
23
+ return true
24
+ }
25
+ }
@@ -0,0 +1,25 @@
1
+ import { accountResolver } from './account'
2
+ import { accountsResolver } from './accounts'
3
+
4
+ import { updateMultipleAccount } from './update-multiple-accounts'
5
+ import { updateAccount } from './update-account'
6
+ import { createAccount } from './create-account'
7
+ import { deleteAccount } from './delete-account'
8
+ import { deleteAccounts } from './delete-accounts'
9
+
10
+ import * as Xero from './xero'
11
+
12
+ export const Query = {
13
+ ...accountsResolver,
14
+ ...accountResolver,
15
+ ...Xero.Query
16
+ } as any
17
+
18
+ export const Mutation = {
19
+ ...updateAccount,
20
+ ...updateMultipleAccount,
21
+ ...createAccount,
22
+ ...deleteAccount,
23
+ ...deleteAccounts,
24
+ ...Xero.Mutation
25
+ }
@@ -0,0 +1,18 @@
1
+ import { getRepository } from '@things-factory/shell'
2
+
3
+ import { Account } from '../../../entities'
4
+
5
+ export const updateAccount = {
6
+ async updateAccount(_: any, { name, patch }, context: ResolverContext) {
7
+ const repository = getRepository(Account)
8
+ const account: any = await repository.findOne({
9
+ where: { domain: { id: context.state.domain.id }, name }
10
+ })
11
+
12
+ return await repository.save({
13
+ ...account,
14
+ ...patch,
15
+ updater: context.state.user
16
+ })
17
+ }
18
+ }
@@ -0,0 +1,44 @@
1
+ import { getRepository } from '@things-factory/shell'
2
+
3
+ import { Account } from '../../../entities'
4
+
5
+ export const updateMultipleAccount = {
6
+ async updateMultipleAccount(_: any, { patches }, context: ResolverContext) {
7
+ let results = []
8
+ const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
9
+ const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
10
+ const accountRepo = getRepository(Account)
11
+
12
+ if (_createRecords.length > 0) {
13
+ for (let i = 0; i < _createRecords.length; i++) {
14
+ const newRecord = _createRecords[i]
15
+
16
+ const result = await accountRepo.save({
17
+ ...newRecord,
18
+ domain: context.state.domain,
19
+ creator: context.state.user,
20
+ updater: context.state.user
21
+ })
22
+
23
+ results.push({ ...result, cuFlag: '+' })
24
+ }
25
+ }
26
+
27
+ if (_updateRecords.length > 0) {
28
+ for (let i = 0; i < _updateRecords.length; i++) {
29
+ const newRecord = _updateRecords[i]
30
+ const account: Account = await accountRepo.findOneBy({ id: newRecord.id })
31
+
32
+ const result = await accountRepo.save({
33
+ ...account,
34
+ ...newRecord,
35
+ updater: context.state.user
36
+ })
37
+
38
+ results.push({ ...result, cuFlag: 'M' })
39
+ }
40
+ }
41
+
42
+ return results
43
+ }
44
+ }