@simitgroup/simpleapp-generator 1.6.3-alpha → 1.6.4-alpha
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.
- package/dist/buildinschemas/branch.d.ts.map +1 -1
- package/dist/buildinschemas/branch.js +1 -0
- package/dist/buildinschemas/branch.js.map +1 -1
- package/dist/buildinschemas/changehistories.d.ts +3 -0
- package/dist/buildinschemas/changehistories.d.ts.map +1 -0
- package/dist/buildinschemas/changehistories.js +36 -0
- package/dist/buildinschemas/changehistories.js.map +1 -0
- package/dist/buildinschemas/index.d.ts +1 -0
- package/dist/buildinschemas/index.d.ts.map +1 -1
- package/dist/buildinschemas/index.js +3 -1
- package/dist/buildinschemas/index.js.map +1 -1
- package/dist/buildinschemas/organization.js +2 -2
- package/dist/buildinschemas/organization.js.map +1 -1
- package/dist/buildinschemas/user.d.ts.map +1 -1
- package/dist/buildinschemas/user.js +5 -1
- package/dist/buildinschemas/user.js.map +1 -1
- package/dist/buildinschemas/webhook.d.ts +3 -0
- package/dist/buildinschemas/webhook.d.ts.map +1 -0
- package/dist/buildinschemas/webhook.js +33 -0
- package/dist/buildinschemas/webhook.js.map +1 -0
- package/dist/framework.d.ts.map +1 -1
- package/dist/framework.js +3 -2
- package/dist/framework.js.map +1 -1
- package/dist/generate.js +30 -11
- package/dist/generate.js.map +1 -1
- package/dist/processors/jsonschemabuilder.d.ts.map +1 -1
- package/dist/processors/jsonschemabuilder.js +10 -2
- package/dist/processors/jsonschemabuilder.js.map +1 -1
- package/dist/type.d.ts +2 -0
- package/dist/type.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/buildinschemas/branch.ts +1 -0
- package/src/buildinschemas/changehistories.ts +33 -0
- package/src/buildinschemas/index.ts +2 -1
- package/src/buildinschemas/organization.ts +2 -2
- package/src/buildinschemas/user.ts +5 -1
- package/src/buildinschemas/webhook.ts +31 -0
- package/src/framework.ts +3 -2
- package/src/generate.ts +35 -15
- package/src/processors/jsonschemabuilder.ts +10 -2
- package/src/type.ts +2 -0
- package/templates/basic/nest/controller.ts.eta +23 -2
- package/templates/basic/nest/model.ts.eta +9 -1
- package/templates/basic/nest/resolver.ts.eta +2 -2
- package/templates/basic/nuxt/pages.[id].vue.eta +7 -7
- package/templates/basic/nuxt/pages.form.vue.eta +1 -4
- package/templates/basic/nuxt/pages.landing.vue.eta +1 -20
- package/templates/basic/nuxt/simpleapp.generate.client.ts.eta +8 -1
- package/templates/nest/src/simpleapp/generate/apischemas/simpleapp.apischema.ts.eta +2 -0
- package/templates/nest/src/simpleapp/generate/commons/dicts/documents.ts.eta +9 -2
- package/templates/nest/src/simpleapp/generate/commons/roles/roles.enum.ts.eta +5 -10
- package/templates/nest/src/simpleapp/generate/commons/roles/roles.group.ts.eta +1 -0
- package/templates/nest/src/simpleapp/generate/commons/runwebhook.service.ts.eta +50 -0
- package/templates/nest/src/simpleapp/generate/commons/user.context.ts.eta +13 -3
- package/templates/nest/src/simpleapp/generate/controllers/simpleapp.controller.ts.eta +9 -1
- package/templates/nest/src/simpleapp/generate/processors/branch.processor.ts.eta +12 -6
- package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +120 -19
- package/templates/nest/src/simpleapp/generate/types/schema.type.ts.eta +3 -1
- package/templates/nest/src/simpleapp/generate/types/simpleapp.type.ts.eta +1 -0
- package/templates/nest/src/simpleapp/profile/profile.controller.ts.eta +19 -0
- package/templates/nest/src/simpleapp/profile/profile.service.ts.eta +30 -8
- package/templates/nest/src/simpleapp/simpleapp.module.ts.eta +2 -1
- package/templates/nuxt/assets/css/calendar.css._eta +3 -0
- package/templates/nuxt/assets/css/style.css._eta +1 -1
- package/templates/nuxt/assets/images/unknown.png.eta +0 -0
- package/templates/nuxt/assets/primevue/passthrough.ts._eta +6 -1
- package/templates/nuxt/components/button/ButtonAction.vue._eta +40 -39
- package/templates/nuxt/components/button/ButtonDanger.vue._eta +11 -3
- package/templates/nuxt/components/button/ButtonDefault.vue._eta +11 -3
- package/templates/nuxt/components/button/ButtonPrimary.vue._eta +9 -3
- package/templates/nuxt/components/button/ButtonSecondary.vue._eta +33 -0
- package/templates/nuxt/components/button/ButtonText.vue._eta +9 -5
- package/templates/nuxt/components/button/ButtonWarning.vue._eta +11 -3
- package/templates/nuxt/components/calendar/CalendarInput.vue.eta +4 -3
- package/templates/nuxt/components/calendar/CalendarSmall.vue.eta +33 -16
- package/templates/nuxt/components/chart/card.vue._eta +1 -1
- package/templates/nuxt/components/debug/DebugDocumentData.vue.eta +36 -26
- package/templates/nuxt/components/event/EventDocumentViewer.vue._eta +36 -13
- package/templates/nuxt/components/form/FormBranch.vue._eta +52 -5
- package/templates/nuxt/components/form/FormDocnoformat.vue.eta +14 -10
- package/templates/nuxt/components/form/FormUser.vue._eta +1 -1
- package/templates/nuxt/components/form/user/FormUserPermission.vue.eta +77 -59
- package/templates/nuxt/components/header/HeaderSelectBranch.vue.eta +42 -35
- package/templates/nuxt/components/image/ImageAvatar.vue.eta._vue +30 -0
- package/templates/nuxt/components/image/ImageOrganization.vue.eta.vue +7 -5
- package/templates/nuxt/components/image/ImageToBase64Uploader.vue.eta.vue +67 -50
- package/templates/nuxt/components/list/ListDocumentTable.vue.eta +20 -12
- package/templates/nuxt/components/list/ListView.vue.eta +64 -35
- package/templates/nuxt/components/overlay/OverlayPanelWithToolBar.vue.eta +5 -4
- package/templates/nuxt/components/overlay/OverlayViewer.vue.eta +8 -8
- package/templates/nuxt/components/page/PageDocList.vue.eta +36 -13
- package/templates/nuxt/components/renderer/RendererDate.vue.eta +8 -2
- package/templates/nuxt/components/renderer/RendererDateTime.vue.eta +7 -1
- package/templates/nuxt/components/renderer/RendererDocHistories.vue.eta +56 -0
- package/templates/nuxt/components/renderer/RendererForeignKey.vue.eta +9 -8
- package/templates/nuxt/components/renderer/RendererLink.vue.eta +7 -4
- package/templates/nuxt/components/renderer/RendererMoney.vue.eta +25 -17
- package/templates/nuxt/components/renderer/RendererTime.vue.eta +7 -1
- package/templates/nuxt/components/renderer/RendererViewer.vue.eta +19 -9
- package/templates/nuxt/components/select/SelectTemplate.vue.eta +47 -21
- package/templates/nuxt/components/session/SessionBlock.vue.eta +44 -46
- package/templates/nuxt/components/simpleApp/SimpleAppAutocomplete.vue.eta +24 -15
- package/templates/nuxt/components/simpleApp/SimpleAppCalendarInput.vue.eta +64 -0
- package/templates/nuxt/components/simpleApp/SimpleAppChildrenList.vue.eta +16 -8
- package/templates/nuxt/components/simpleApp/SimpleAppDocumentNo.vue.eta +8 -8
- package/templates/nuxt/components/simpleApp/SimpleAppFieldContainer.vue.eta +1 -1
- package/templates/nuxt/components/simpleApp/SimpleAppFormToolBar.vue._eta +66 -22
- package/templates/nuxt/components/simpleApp/SimpleAppInput.vue.eta +89 -168
- package/templates/nuxt/components/simpleApp/SimpleAppInputTable.vue.eta +43 -40
- package/templates/nuxt/components/simpleApp/SimpleAppUserPicker.vue.eta +387 -0
- package/templates/nuxt/components/text/TextDocStatus.vue._eta +22 -0
- package/templates/nuxt/components/user/UserButtonCreateTenant.vue._eta +13 -15
- package/templates/nuxt/components/user/UserButtonPermissionInfo.vue.eta +127 -93
- package/templates/nuxt/components/user/UserTenantPicker.vue.eta +1 -1
- package/templates/nuxt/composables/date.generate.ts.eta +105 -8
- package/templates/nuxt/composables/getDocument.generate.ts.eta +8 -6
- package/templates/nuxt/composables/getOpenApi.generate.ts.eta +58 -10
- package/templates/nuxt/composables/getUserStore.generate.ts.eta +37 -5
- package/templates/nuxt/composables/goTo.generate.ts.eta +14 -1
- package/templates/nuxt/composables/graphquery.generate.ts.eta +20 -2
- package/templates/nuxt/composables/recently.generate.ts.eta +16 -0
- package/templates/nuxt/composables/roles.generate.ts.eta +8 -13
- package/templates/nuxt/composables/stringHelper.generate.ts.eta +52 -0
- package/templates/nuxt/composables/sysmessage.generate.ts.eta +1 -1
- package/templates/nuxt/pages/[xorg]/{organization.vue.eta → organization.vue._eta} +38 -9
- package/templates/nuxt/pages/[xorg]/user.vue.eta +12 -9
- package/templates/nuxt/pages/login.vue._eta +4 -1
- package/templates/nuxt/plugins/20.simpleapp-userstore.ts.eta +45 -26
- package/templates/nuxt/plugins/70.recently.ts.eta +55 -0
- package/templates/nuxt/providers/my-provider.ts.eta +22 -0
- package/templates/nuxt/server/api/[xorg]/{[...].ts.eta → [...].ts._eta} +47 -21
- package/templates/nuxt/simpleapp/generate/clients/SimpleAppClient.ts.eta +44 -3
- package/templates/nuxt/types/events.ts.eta +3 -2
- package/templates/nuxt/types/others.ts.eta +11 -1
- package/templates/nuxt/types/schema.ts.eta +3 -1
- package/templates/nuxt/types/simpleappinput.ts.eta +1 -1
- package/templates/nuxt/types/user.ts.eta +8 -7
- package/templates/project/jsonschemas/branch.json._eta +1 -0
- package/templates/project/jsonschemas/invoice.json._eta +4 -3
- package/templates/project/jsonschemas/organization.json._eta +2 -2
- package/templates/project/lang/default._json +3 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/templates/nuxt/components/image/ImageAvatar.vue.eta.vue +0 -38
- /package/templates/nuxt/pages/[xorg]/mobile/docnoformat/{index.vue.eta → index.vue.etaxxx} +0 -0
- /package/templates/nuxt/pages/[xorg]/mobile/{index.vue._eta → index.vue._etaxxx} +0 -0
- /package/templates/nuxt/pages/[xorg]/mobile/organization/{[id].vue._eta → [id].vue._etaxxx} +0 -0
- /package/templates/nuxt/pages/[xorg]/mobile/{pickgroup.vue._eta → pickgroup.vue._etaxxx} +0 -0
- /package/templates/nuxt/pages/[xorg]/mobile/user/{index.vue.eta → index.vue.etaxxx} +0 -0
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { UserContext } from '../commons/user.context';
|
|
8
8
|
import * as sharelibs from '../sharelibs';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
Injectable,
|
|
11
|
+
Inject,
|
|
12
|
+
InternalServerErrorException,
|
|
13
|
+
} from '@nestjs/common';
|
|
10
14
|
import { InjectModel } from '@nestjs/mongoose';
|
|
11
15
|
import * as jsonpath from 'jsonpath';
|
|
12
16
|
import { Model } from 'mongoose';
|
|
@@ -17,7 +21,7 @@ import { DocNumberFormatGenerator } from '../commons/docnogenerator.service';
|
|
|
17
21
|
import { AutoincreamentService } from '../../services/autoinc.service';
|
|
18
22
|
import { alldocuments } from '../commons/dicts/documents';
|
|
19
23
|
import { Docnoformat, DocnoformatService } from '../../services/docno.service';
|
|
20
|
-
import { BranchOrganization, Branch,BranchHooks } from '../types/branch.type';
|
|
24
|
+
import { BranchOrganization, Branch, BranchHooks } from '../types/branch.type';
|
|
21
25
|
import {
|
|
22
26
|
DefaultBranchOrganization,
|
|
23
27
|
DefaultBranch,
|
|
@@ -32,9 +36,11 @@ export class BranchProcessor extends SimpleAppService<Branch> {
|
|
|
32
36
|
protected strictIsolation = false;
|
|
33
37
|
protected documentIdentityCode = 'branchCode';
|
|
34
38
|
protected documentIdentityLabel = 'branchName';
|
|
35
|
-
protected hooks: BranchHooks = {
|
|
36
|
-
beforeCreate: async (appuser: UserContext, data: Branch) =>
|
|
37
|
-
|
|
39
|
+
protected hooks: BranchHooks = {
|
|
40
|
+
beforeCreate: async (appuser: UserContext, data: Branch) =>
|
|
41
|
+
await this.branchBeforeCreate(appuser, data),
|
|
42
|
+
afterCreate: async (appuser: UserContext, data: Branch) =>
|
|
43
|
+
await this.branchAfterCreate(appuser, data),
|
|
38
44
|
};
|
|
39
45
|
protected foreignkeys = { organization: ['$.organization._id'] };
|
|
40
46
|
constructor(mydoc: Model<Branch>) {
|
|
@@ -74,7 +80,7 @@ export class BranchProcessor extends SimpleAppService<Branch> {
|
|
|
74
80
|
const docformats = alldocuments.filter((item) => item.docNumber);
|
|
75
81
|
for (let i = 0; i < docformats.length; i++) {
|
|
76
82
|
const doc = docformats[i];
|
|
77
|
-
const pattern =
|
|
83
|
+
const pattern = doc.docNoPattern.replace('@BranchCode',branchCode);
|
|
78
84
|
const formatdata: Docnoformat = {
|
|
79
85
|
_id: crypto.randomUUID(),
|
|
80
86
|
docNoFormatNo: `${doc.docType}-${branchCode}`,
|
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
WorkflowName,
|
|
44
44
|
} from '../types';
|
|
45
45
|
@Injectable()
|
|
46
|
-
export class SimpleAppService<T extends { _id?: string
|
|
46
|
+
export class SimpleAppService<T extends { _id?: string; __v?: number }> {
|
|
47
47
|
@Inject(EventEmitter2)
|
|
48
48
|
protected eventEmitter: EventEmitter2;
|
|
49
49
|
@Inject(CloudApiService)
|
|
@@ -53,7 +53,12 @@ export class SimpleAppService<T extends { _id?: string, __v?:number }> {
|
|
|
53
53
|
protected hooks: DefaultHooks<T> = {};
|
|
54
54
|
protected logger = new Logger();
|
|
55
55
|
protected strictIsolation = true;
|
|
56
|
-
protected jsonschema
|
|
56
|
+
protected jsonschema: any = {
|
|
57
|
+
type: 'object',
|
|
58
|
+
'x-simpleapp-config': {},
|
|
59
|
+
properties: {},
|
|
60
|
+
required: [],
|
|
61
|
+
};
|
|
57
62
|
protected documentIdentityCode = 'code';
|
|
58
63
|
protected documentIdentityLabel = 'label';
|
|
59
64
|
protected documentName = '-unknowndocname-';
|
|
@@ -97,6 +102,7 @@ export class SimpleAppService<T extends { _id?: string, __v?:number }> {
|
|
|
97
102
|
getRecordId = (): string => this.data._id;
|
|
98
103
|
setSchema = (newschema) => (this.jsonschema = newschema);
|
|
99
104
|
getSchema = () => this.doc.schema.obj;
|
|
105
|
+
getJsonSchema = () => this.jsonschema;
|
|
100
106
|
getHooks = () => this.hooks;
|
|
101
107
|
getData = () => {
|
|
102
108
|
//console.log('thisdata', this.data);
|
|
@@ -225,7 +231,9 @@ export class SimpleAppService<T extends { _id?: string, __v?:number }> {
|
|
|
225
231
|
|
|
226
232
|
Object.assign(pipeline[0]['$match'], isolationFilter);
|
|
227
233
|
//console.log("final agg",pipeline)
|
|
228
|
-
return await this.doc.aggregate(pipeline
|
|
234
|
+
return await this.doc.aggregate(pipeline, {
|
|
235
|
+
session: appuser.getDBSession(),
|
|
236
|
+
});
|
|
229
237
|
} catch (err) {
|
|
230
238
|
throw new InternalServerErrorException(err);
|
|
231
239
|
}
|
|
@@ -238,8 +246,9 @@ export class SimpleAppService<T extends { _id?: string, __v?:number }> {
|
|
|
238
246
|
async search(
|
|
239
247
|
appuser: UserContext,
|
|
240
248
|
filters: FilterQuery<T>,
|
|
241
|
-
projection:
|
|
249
|
+
projection: string[] = undefined,
|
|
242
250
|
sort: any = undefined,
|
|
251
|
+
lookup: { [key: string]: string } = undefined,
|
|
243
252
|
) {
|
|
244
253
|
try {
|
|
245
254
|
const isolationFilter = { ...this.getIsolationFilter(appuser) };
|
|
@@ -252,24 +261,47 @@ export class SimpleAppService<T extends { _id?: string, __v?:number }> {
|
|
|
252
261
|
await this.hooks.beforeSearch(appuser, newfilters);
|
|
253
262
|
// console.log("before _find",newfilters)
|
|
254
263
|
// console.log("this.doc",this.doc)
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
.
|
|
258
|
-
|
|
259
|
-
|
|
264
|
+
let searchResults: T[] = [];
|
|
265
|
+
if (lookup === undefined) {
|
|
266
|
+
this.logger.debug('after search', newfilters);
|
|
267
|
+
searchResults = await this.doc
|
|
268
|
+
.find(newfilters, projection, { session: appuser.getDBSession() })
|
|
269
|
+
.sort(sort);
|
|
270
|
+
} else {
|
|
271
|
+
const pipelines = this.searchToAggregate(
|
|
272
|
+
filters,
|
|
273
|
+
projection,
|
|
274
|
+
sort,
|
|
275
|
+
lookup,
|
|
276
|
+
);
|
|
277
|
+
this.logger.debug('after aggregate', pipelines);
|
|
278
|
+
|
|
279
|
+
searchResults = await this.aggregate(appuser, pipelines);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const list: T[] = searchResults.map((p: T) => {
|
|
260
283
|
return p;
|
|
261
284
|
});
|
|
262
285
|
// console.log("after map",productlist)
|
|
263
|
-
if (this.hooks.afterSearch)
|
|
264
|
-
await this.hooks.afterSearch(appuser, productlist);
|
|
286
|
+
if (this.hooks.afterSearch) await this.hooks.afterSearch(appuser, list);
|
|
265
287
|
|
|
266
288
|
// console.log(products);
|
|
267
|
-
return
|
|
289
|
+
return list;
|
|
268
290
|
} catch (err) {
|
|
269
291
|
throw new BadRequestException(err.message);
|
|
270
292
|
}
|
|
271
293
|
// return this;
|
|
272
294
|
}
|
|
295
|
+
|
|
296
|
+
async fullTextSearch(appuser: UserContext, keyword: string) {
|
|
297
|
+
const isolationFilter = { ...this.getIsolationFilter(appuser) };
|
|
298
|
+
this.polishIsolationFilter(isolationFilter);
|
|
299
|
+
|
|
300
|
+
const filters = { $text: { $search: keyword } };
|
|
301
|
+
const newfilters: FilterQuery<T> = { ...filters, ...isolationFilter };
|
|
302
|
+
|
|
303
|
+
return await this.doc.find(newfilters);
|
|
304
|
+
}
|
|
273
305
|
async findById(appuser: UserContext, id: string) {
|
|
274
306
|
if (this.hooks.beforeFetchRecord)
|
|
275
307
|
await this.hooks.beforeFetchRecord(appuser, id);
|
|
@@ -364,6 +396,7 @@ export class SimpleAppService<T extends { _id?: string, __v?:number }> {
|
|
|
364
396
|
// result = await newdoc.save()
|
|
365
397
|
try {
|
|
366
398
|
if (this.hooks.afterCreate) await this.hooks.afterCreate(appuser, result);
|
|
399
|
+
this.callWebhook(appuser, 'create', result);
|
|
367
400
|
return result as T;
|
|
368
401
|
} catch (err) {
|
|
369
402
|
throw new InternalServerErrorException(
|
|
@@ -416,6 +449,7 @@ export class SimpleAppService<T extends { _id?: string, __v?:number }> {
|
|
|
416
449
|
ajv.addFormat('text', /.*$/);
|
|
417
450
|
ajv.addFormat('html', /.*$/);
|
|
418
451
|
ajv.addFormat('documentno', /.*$/);
|
|
452
|
+
ajv.addFormat('money', /.*$/);
|
|
419
453
|
|
|
420
454
|
ajv.addKeyword({ keyword: 'x-foreignkey', schemaType: 'string' });
|
|
421
455
|
ajv.addKeyword({ keyword: 'x-simpleapp-config', schemaType: 'object' });
|
|
@@ -524,6 +558,7 @@ export class SimpleAppService<T extends { _id?: string, __v?:number }> {
|
|
|
524
558
|
if (this.hooks.afterDelete)
|
|
525
559
|
await this.hooks.afterDelete(appuser, deleteresult, id);
|
|
526
560
|
//this.doc.findByIdAndDelete(id);
|
|
561
|
+
this.callWebhook(appuser, 'delete', deletedata);
|
|
527
562
|
return deleteresult;
|
|
528
563
|
} else {
|
|
529
564
|
this.logger.debug('reject query', dependency);
|
|
@@ -544,11 +579,13 @@ export class SimpleAppService<T extends { _id?: string, __v?:number }> {
|
|
|
544
579
|
const existingdata = await this.findById(appuser, id);
|
|
545
580
|
|
|
546
581
|
//version exists, need ensure different only 1
|
|
547
|
-
if(typeof data.__v=='number' && data.__v != existingdata.__v
|
|
548
|
-
throw new BadRequestException(
|
|
582
|
+
if (typeof data.__v == 'number' && data.__v != existingdata.__v) {
|
|
583
|
+
throw new BadRequestException(
|
|
584
|
+
`You submit older version data "v${data.__v}"" but latest version = "v${existingdata.__v}"`,
|
|
585
|
+
);
|
|
549
586
|
}
|
|
550
587
|
|
|
551
|
-
data.__v = existingdata.__v+1
|
|
588
|
+
data.__v = existingdata.__v + 1;
|
|
552
589
|
if (!existingdata) {
|
|
553
590
|
throw new NotFoundException(`${id} not found`, 'not found');
|
|
554
591
|
}
|
|
@@ -582,6 +619,7 @@ export class SimpleAppService<T extends { _id?: string, __v?:number }> {
|
|
|
582
619
|
appuser.addUpdatedRecordId(this.documentName, data._id);
|
|
583
620
|
if (this.hooks.afterUpdate)
|
|
584
621
|
await this.hooks.afterUpdate(appuser, id, existingdata, result);
|
|
622
|
+
this.callWebhook(appuser, 'update', result);
|
|
585
623
|
return result; // await this.findById(appuser, id);
|
|
586
624
|
} catch (err) {
|
|
587
625
|
this.logger.error(err);
|
|
@@ -599,12 +637,13 @@ export class SimpleAppService<T extends { _id?: string, __v?:number }> {
|
|
|
599
637
|
if (!existingdata) {
|
|
600
638
|
throw new NotFoundException(`${id} not found`, 'not found');
|
|
601
639
|
}
|
|
602
|
-
if(typeof data.__v=='number' && data.__v != existingdata.__v
|
|
603
|
-
throw new BadRequestException(
|
|
640
|
+
if (typeof data.__v == 'number' && data.__v != existingdata.__v) {
|
|
641
|
+
throw new BadRequestException(
|
|
642
|
+
`You submit older version data "v${data.__v}"" but latest version = "v${existingdata.__v}"`,
|
|
643
|
+
);
|
|
604
644
|
}
|
|
605
645
|
|
|
606
|
-
data.__v = existingdata.__v+1
|
|
607
|
-
|
|
646
|
+
data.__v = existingdata.__v + 1;
|
|
608
647
|
|
|
609
648
|
if (this.hooks.beforeUpdate)
|
|
610
649
|
await this.hooks.beforeUpdate(appuser, id, data, existingdata);
|
|
@@ -641,6 +680,7 @@ export class SimpleAppService<T extends { _id?: string, __v?:number }> {
|
|
|
641
680
|
|
|
642
681
|
if (this.hooks.afterUpdate)
|
|
643
682
|
await this.hooks.afterUpdate(appuser, id, existingdata, result);
|
|
683
|
+
this.callWebhook(appuser, 'update', result);
|
|
644
684
|
return result; //await this.findById(appuser, id);
|
|
645
685
|
} catch (err) {
|
|
646
686
|
throw new InternalServerErrorException(err.message);
|
|
@@ -744,6 +784,7 @@ export class SimpleAppService<T extends { _id?: string, __v?:number }> {
|
|
|
744
784
|
if (this.hooks.afterSetStatus)
|
|
745
785
|
await this.hooks.afterSetStatus(appuser, docstatus, finaldata);
|
|
746
786
|
|
|
787
|
+
this.callWebhook(appuser, docstatus, finaldata);
|
|
747
788
|
return updateresult;
|
|
748
789
|
}
|
|
749
790
|
}
|
|
@@ -928,4 +969,64 @@ export class SimpleAppService<T extends { _id?: string, __v?:number }> {
|
|
|
928
969
|
const pdfresult = await this.printapi.getBase64Pdf(appuser, formatid, id);
|
|
929
970
|
return pdfresult;
|
|
930
971
|
}
|
|
972
|
+
|
|
973
|
+
searchToAggregate(
|
|
974
|
+
filter: FilterQuery<T>,
|
|
975
|
+
columns: string[],
|
|
976
|
+
sort: string[][],
|
|
977
|
+
lookup: { [key: string]: string },
|
|
978
|
+
) {
|
|
979
|
+
const pipelines: PipelineStage[] = [];
|
|
980
|
+
const projection = {};
|
|
981
|
+
// console.log('sortsort', sort);
|
|
982
|
+
|
|
983
|
+
pipelines.push({ $match: filter });
|
|
984
|
+
if (Array.isArray(columns) && columns.length > 0) {
|
|
985
|
+
columns.forEach((col) => {
|
|
986
|
+
projection[col] = 1;
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
const collections = Object.keys(lookup);
|
|
991
|
+
collections.forEach((tokey: string) => {
|
|
992
|
+
const toarr = tokey.split('.');
|
|
993
|
+
const to = toarr[0];
|
|
994
|
+
const foreignField = toarr[1] ?? '_id';
|
|
995
|
+
pipelines.push({
|
|
996
|
+
$lookup: {
|
|
997
|
+
from: to,
|
|
998
|
+
as: '_' + to,
|
|
999
|
+
localField: lookup[tokey],
|
|
1000
|
+
foreignField: foreignField,
|
|
1001
|
+
},
|
|
1002
|
+
});
|
|
1003
|
+
pipelines.push({ $unwind: '$_' + to });
|
|
1004
|
+
|
|
1005
|
+
if (Object.keys(projection).length > 0) projection['_' + to] = 1;
|
|
1006
|
+
});
|
|
1007
|
+
|
|
1008
|
+
if (Object.keys(projection).length > 0)
|
|
1009
|
+
pipelines.push({ $project: projection });
|
|
1010
|
+
|
|
1011
|
+
if (Array.isArray(sort) && sort.length > 0) {
|
|
1012
|
+
const sortobj = {};
|
|
1013
|
+
sort.forEach((item) => {
|
|
1014
|
+
sortobj[item[0]] = item[1].toLowerCase() == 'asc' ? 1 : -1;
|
|
1015
|
+
});
|
|
1016
|
+
pipelines.push({ $sort: sortobj });
|
|
1017
|
+
}
|
|
1018
|
+
// console.log('pipelinespipelinespipelines', pipelines);
|
|
1019
|
+
|
|
1020
|
+
return pipelines;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
callWebhook(appuser: UserContext, actionName: string, data: any) {
|
|
1024
|
+
this.eventEmitter.emit(
|
|
1025
|
+
'webhook',
|
|
1026
|
+
appuser,
|
|
1027
|
+
this.documentName,
|
|
1028
|
+
actionName,
|
|
1029
|
+
data,
|
|
1030
|
+
);
|
|
1031
|
+
}
|
|
931
1032
|
}
|
|
@@ -30,17 +30,19 @@ export type DocumentStatus = {
|
|
|
30
30
|
formula:string //example "jslib.getDocumentSubTotal(@F{$.details})"
|
|
31
31
|
}
|
|
32
32
|
export type SchemaConfig = {
|
|
33
|
-
isolationType:
|
|
33
|
+
isolationType: string
|
|
34
34
|
requiredRoles?:string[]
|
|
35
35
|
pageType?: string
|
|
36
36
|
uniqueKey?:string
|
|
37
37
|
uniqueKeys?:string[][]
|
|
38
38
|
documentTitle?:string
|
|
39
39
|
generateDocumentNumber?:boolean
|
|
40
|
+
docNoPattern?:string
|
|
40
41
|
documentDate?:string
|
|
41
42
|
allStatus?:DocumentStatus[]
|
|
42
43
|
additionalApis?:DocumentApi[]
|
|
43
44
|
additionalAutoCompleteFields ?: string[]
|
|
45
|
+
search?:string[]
|
|
44
46
|
// libs?:ImportLibs[] // both process class and frontend client class will import same lib
|
|
45
47
|
formulas?: Formula[]
|
|
46
48
|
documentType: string
|
|
@@ -160,4 +160,23 @@ export class ProfileController {
|
|
|
160
160
|
throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
|
+
@Post('/tour-complete/:guidename')
|
|
164
|
+
@Roles(Role.User)
|
|
165
|
+
@ApiOperation({
|
|
166
|
+
operationId: 'runTourComplete',
|
|
167
|
+
description: 'complete specific tour guide',
|
|
168
|
+
})
|
|
169
|
+
@ApiResponse({ status: 201, type: Object, description: 'Success' })
|
|
170
|
+
async runTourComplete(
|
|
171
|
+
@AppUser() appuser: UserContext,
|
|
172
|
+
@Param('guidename') guidename: string,
|
|
173
|
+
|
|
174
|
+
) {
|
|
175
|
+
const result = await this.profileservice.runTourComplete(appuser,guidename,);
|
|
176
|
+
if (result) {
|
|
177
|
+
return result;
|
|
178
|
+
} else {
|
|
179
|
+
throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
163
182
|
}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* Author: Ks Tan
|
|
6
6
|
*/
|
|
7
7
|
import { UserService, User } from './../services/user.service';
|
|
8
|
-
import countrytimezone from 'countries-and-timezones'
|
|
9
|
-
import countryToCurrency, { Currencies, Countries } from
|
|
8
|
+
import countrytimezone from 'countries-and-timezones';
|
|
9
|
+
import countryToCurrency, { Currencies, Countries } from 'country-to-currency';
|
|
10
10
|
import {
|
|
11
11
|
Injectable,
|
|
12
12
|
Scope,
|
|
@@ -91,14 +91,14 @@ export class ProfileService {
|
|
|
91
91
|
appuser: UserContext,
|
|
92
92
|
tenantName: string,
|
|
93
93
|
timeZone: string,
|
|
94
|
-
utcOffset: number
|
|
94
|
+
utcOffset: number,
|
|
95
95
|
) {
|
|
96
96
|
// try{
|
|
97
|
-
const timezonedata = countrytimezone.getCountriesForTimezone(timeZone)[0]
|
|
98
|
-
const countryCode
|
|
99
|
-
const countryName
|
|
100
|
-
const currencyCode = countryToCurrency[countryCode]
|
|
101
|
-
|
|
97
|
+
const timezonedata = countrytimezone.getCountriesForTimezone(timeZone)[0];
|
|
98
|
+
const countryCode = timezonedata['id'];
|
|
99
|
+
const countryName = timezonedata['name'];
|
|
100
|
+
const currencyCode = countryToCurrency[countryCode];
|
|
101
|
+
|
|
102
102
|
appuser.getDBSession().startTransaction();
|
|
103
103
|
const tenantdata: Tenant = {
|
|
104
104
|
tenantId: 1,
|
|
@@ -245,4 +245,26 @@ export class ProfileService {
|
|
|
245
245
|
async getSession(appuser: UserContext) {
|
|
246
246
|
return 'OK';
|
|
247
247
|
}
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
async runTourComplete(appuser: UserContext, guideName: string) {
|
|
251
|
+
if (!guideName || guideName == '')
|
|
252
|
+
throw new BadRequestException('undefine guideName');
|
|
253
|
+
|
|
254
|
+
const user = await this.usersvc.findById(
|
|
255
|
+
appuser,
|
|
256
|
+
appuser.getId(),
|
|
257
|
+
);
|
|
258
|
+
if(!Array.isArray(user.completedTours)){
|
|
259
|
+
user.completedTours=[]
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (!user.completedTours.includes(guideName)) {
|
|
263
|
+
|
|
264
|
+
user.completedTours.push(guideName);
|
|
265
|
+
const res = await this.usersvc.findIdThenUpdate(appuser, user._id, user);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return 'ok';
|
|
269
|
+
}
|
|
248
270
|
}
|
|
@@ -10,7 +10,7 @@ import {DocNumberFormatGenerator} from './generate/commons/docnogenerator.servic
|
|
|
10
10
|
import { AuditTrail } from './generate/commons/audittrail.service';
|
|
11
11
|
import { CloudapiModule } from 'src/cloudapi/cloudapi.module';
|
|
12
12
|
import { PrintapiModule } from 'src/printapi/printapi.module';
|
|
13
|
-
|
|
13
|
+
import { RunWebhookService } from 'src/simpleapp/generate/commons/runwebhook.service'
|
|
14
14
|
import { UserResolverService } from './services/userresolver.service';
|
|
15
15
|
// auto import modules
|
|
16
16
|
<% for(let i=0;i<it.modules.length; i++){ %>
|
|
@@ -53,6 +53,7 @@ import { <%=capitalizeFirstLetter(bpmn)%>ListenerService } from 'src/simpleapp/w
|
|
|
53
53
|
controllers: [<% for(let i=0;i<it.modules.length; i++){ %><%= it.modules[i].docname %>Controller,<%}%> ProfileController,WorkflowController],
|
|
54
54
|
providers: [
|
|
55
55
|
SimpleAppRobotUserService,
|
|
56
|
+
RunWebhookService,
|
|
56
57
|
AuditTrail,DocNumberFormatGenerator,<% for(let i=0;i<it.modules.length; i++){ %>
|
|
57
58
|
<%= it.modules[i].docname %>Service,
|
|
58
59
|
<%= it.modules[i].docname %>Resolver,
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
@apply bg-gray-100 dark:bg-slate-800 dark:text-gray-300
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
[disabled=true],input[disabled] ,input[readonly] ,textarea[readonly]{
|
|
12
|
+
[disabled=true],input[disabled] ,input[readonly] ,textarea[readonly], .p-dropdown[readonly]{
|
|
13
13
|
@apply bg-gray-300 dark:bg-gray-600
|
|
14
14
|
}
|
|
15
15
|
|
|
Binary file
|
|
@@ -24,7 +24,12 @@ const CustomTailwind = usePassThrough(
|
|
|
24
24
|
root:{class:'bg-white dark:bg-gray-800 shadow p-2 rounded-2xl'},
|
|
25
25
|
// title:{class:''},
|
|
26
26
|
// header:{class:''}
|
|
27
|
-
},
|
|
27
|
+
},
|
|
28
|
+
fieldset:{
|
|
29
|
+
root:{class:'border p-2 mt-1'},
|
|
30
|
+
legend:{class:''},
|
|
31
|
+
content:{class:'p-2'}
|
|
32
|
+
},
|
|
28
33
|
// tabview:{
|
|
29
34
|
// tabpanel:{
|
|
30
35
|
// headeraction:{class:'p-tabview-nav-link p-tabview-header-action items-center cursor-pointer flex overflow-hidden relative select-none text-decoration-none select-none border-b-2 p-5 font-bold rounded-t-md transition-shadow duration-200 m-0 transition-colors duration-200 bg-white border-blue-500 text-blue-500 dark:bg-gray-600 dark:border-blue-300 dark:text-blue-300'}
|
|
@@ -1,66 +1,67 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<ButtonDefault v-if="!actionName" :animate="animate">
|
|
3
|
-
<i :class="getIcon()"/><slot></slot>def</ButtonDefault
|
|
3
|
+
<i :class="getIcon()" /><slot></slot>def</ButtonDefault
|
|
4
4
|
>
|
|
5
5
|
<ButtonPrimary
|
|
6
|
-
v-else-if="['create', 'update','confirm'].includes(actionName)"
|
|
6
|
+
v-else-if="['create', 'update', 'confirm'].includes(actionName)"
|
|
7
7
|
:animate="animate"
|
|
8
|
-
|
|
9
|
-
<i :class="getIcon()"/>
|
|
8
|
+
>
|
|
9
|
+
<i :class="getIcon()" />
|
|
10
10
|
<slot></slot
|
|
11
11
|
></ButtonPrimary>
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
<ButtonDanger
|
|
14
14
|
v-else-if="['delete', 'void'].includes(actionName)"
|
|
15
15
|
:animate="animate"
|
|
16
|
-
|
|
17
|
-
<i :class="getIcon()"/>
|
|
16
|
+
>
|
|
17
|
+
<i :class="getIcon()" />
|
|
18
18
|
<slot></slot>
|
|
19
19
|
</ButtonDanger>
|
|
20
20
|
<ButtonWarning v-else-if="['draft'].includes(actionName)" :animate="animate">
|
|
21
|
-
<i :class="getIcon()"/>
|
|
21
|
+
<i :class="getIcon()" />
|
|
22
22
|
<slot></slot>
|
|
23
|
-
</ButtonWarning>
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
</ButtonWarning>
|
|
24
|
+
<ButtonSecondary v-else-if="actionName == 'print'">
|
|
25
|
+
<i :class="getIcon()" />
|
|
26
|
+
<slot></slot
|
|
27
|
+
></ButtonSecondary>
|
|
28
|
+
<ButtonDefault v-else :animate="animate">
|
|
29
|
+
<i :class="getIcon()" />
|
|
29
30
|
<slot></slot
|
|
30
31
|
></ButtonDefault>
|
|
31
32
|
</template>
|
|
32
33
|
<script setup lang="ts">
|
|
33
34
|
/**
|
|
34
35
|
* This file was automatically generated by simpleapp generator during initialization. It is changable.
|
|
36
|
+
* --remove-this-line-to-prevent-override--
|
|
35
37
|
* last change 2024-03-01
|
|
36
38
|
* author: Ks Tan
|
|
37
39
|
*/
|
|
38
40
|
|
|
39
41
|
const props = defineProps<{ actionName?: string; animate?: boolean }>();
|
|
40
|
-
const getIcon = ()=>{
|
|
41
|
-
let cssname=
|
|
42
|
-
switch(props.actionName){
|
|
43
|
-
case
|
|
44
|
-
case
|
|
45
|
-
cssname+=
|
|
46
|
-
|
|
47
|
-
case
|
|
48
|
-
cssname+=
|
|
49
|
-
|
|
50
|
-
case
|
|
51
|
-
cssname+=
|
|
52
|
-
|
|
53
|
-
case
|
|
54
|
-
cssname+=
|
|
55
|
-
|
|
56
|
-
case
|
|
57
|
-
cssname+=
|
|
58
|
-
|
|
59
|
-
case
|
|
60
|
-
cssname+=
|
|
61
|
-
|
|
42
|
+
const getIcon = () => {
|
|
43
|
+
let cssname = "mr-1 pi ";
|
|
44
|
+
switch (props.actionName) {
|
|
45
|
+
case "create":
|
|
46
|
+
case "update":
|
|
47
|
+
cssname += "pi-save";
|
|
48
|
+
break;
|
|
49
|
+
case "delete":
|
|
50
|
+
cssname += "pi-trash";
|
|
51
|
+
break;
|
|
52
|
+
case "print":
|
|
53
|
+
cssname += "pi-file-pdf";
|
|
54
|
+
break;
|
|
55
|
+
case "confirm":
|
|
56
|
+
cssname += "pi-check";
|
|
57
|
+
break;
|
|
58
|
+
case "void":
|
|
59
|
+
cssname += "pi-file-excel";
|
|
60
|
+
break;
|
|
61
|
+
case "draft":
|
|
62
|
+
cssname += "pi-file-edit";
|
|
63
|
+
break;
|
|
62
64
|
}
|
|
63
|
-
return cssname
|
|
64
|
-
}
|
|
65
|
-
|
|
65
|
+
return cssname;
|
|
66
|
+
};
|
|
66
67
|
</script>
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Button
|
|
3
3
|
v-if="isMobile()"
|
|
4
|
-
|
|
4
|
+
severity="danger"
|
|
5
|
+
:class="`w-full rounded-full text-center block ${
|
|
6
|
+
animate ? 'animate-bounce' : ''
|
|
7
|
+
}`"
|
|
5
8
|
@click="onActivate"
|
|
6
9
|
>
|
|
7
10
|
<slot></slot>
|
|
8
11
|
</Button>
|
|
9
|
-
<Button
|
|
12
|
+
<Button
|
|
13
|
+
v-else
|
|
14
|
+
severity="danger"
|
|
15
|
+
:class="`${animate ? 'animate-bounce' : ''}`"
|
|
16
|
+
@click="onActivate"
|
|
17
|
+
>
|
|
10
18
|
<slot></slot>
|
|
11
19
|
</Button>
|
|
12
20
|
</template>
|
|
@@ -18,7 +26,7 @@
|
|
|
18
26
|
* author: Ks Tan
|
|
19
27
|
*/
|
|
20
28
|
const emits = defineEmits(["click"]);
|
|
21
|
-
const props = defineProps<{animate?:boolean}>()
|
|
29
|
+
const props = defineProps<{ animate?: boolean }>();
|
|
22
30
|
const onActivate = (e: Event) => {
|
|
23
31
|
emits("click", e);
|
|
24
32
|
};
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Button
|
|
3
3
|
v-if="isMobile()"
|
|
4
|
-
|
|
4
|
+
severity="secondary"
|
|
5
|
+
:class="`w-full rounded-full text-center block ${
|
|
6
|
+
animate ? 'animate-bounce' : ''
|
|
7
|
+
}`"
|
|
5
8
|
@click="onActivate"
|
|
6
9
|
>
|
|
7
10
|
<slot></slot>
|
|
8
11
|
</Button>
|
|
9
|
-
<Button
|
|
12
|
+
<Button
|
|
13
|
+
v-else
|
|
14
|
+
severity="secondary"
|
|
15
|
+
:class="`${animate ? 'animate-bounce' : ''}`"
|
|
16
|
+
@click="onActivate"
|
|
17
|
+
>
|
|
10
18
|
<slot></slot>
|
|
11
19
|
</Button>
|
|
12
20
|
</template>
|
|
@@ -18,7 +26,7 @@
|
|
|
18
26
|
* author: Ks Tan
|
|
19
27
|
*/
|
|
20
28
|
const emits = defineEmits(["click"]);
|
|
21
|
-
const props = defineProps<{animate?:boolean}>()
|
|
29
|
+
const props = defineProps<{ animate?: boolean }>();
|
|
22
30
|
const onActivate = (e: Event) => {
|
|
23
31
|
emits("click", e);
|
|
24
32
|
};
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Button
|
|
3
3
|
v-if="isMobile()"
|
|
4
|
-
:class="`w-full rounded-full text-center block dark:bg-primary-600 bg-primary-600 active:dark:bg-primary-400 text-white ${
|
|
4
|
+
:class="`w-full rounded-full text-center block dark:bg-primary-600 bg-primary-600 active:dark:bg-primary-400 text-white ${
|
|
5
|
+
animate ? 'animate-bounce' : ''
|
|
6
|
+
}`"
|
|
5
7
|
@click="onActivate"
|
|
6
8
|
>
|
|
7
9
|
<slot></slot>
|
|
8
10
|
</Button>
|
|
9
|
-
<Button
|
|
11
|
+
<Button
|
|
12
|
+
v-else
|
|
13
|
+
:class="`btn-primary ${animate ? 'animate-bounce' : ''}`"
|
|
14
|
+
@click="onActivate"
|
|
15
|
+
>
|
|
10
16
|
<slot></slot>
|
|
11
17
|
</Button>
|
|
12
18
|
</template>
|
|
@@ -18,7 +24,7 @@
|
|
|
18
24
|
* author: Ks Tan
|
|
19
25
|
*/
|
|
20
26
|
const emits = defineEmits(["click"]);
|
|
21
|
-
const props = defineProps<{animate?:boolean}>()
|
|
27
|
+
const props = defineProps<{ animate?: boolean }>();
|
|
22
28
|
const onActivate = (e: Event) => {
|
|
23
29
|
emits("click", e);
|
|
24
30
|
};
|