@things-factory/quotation 6.0.46

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 (98) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/assets/images/hatiolab-logo.png +0 -0
  3. package/client/actions/main.ts +1 -0
  4. package/client/activities/activity-quotation-edit.ts +90 -0
  5. package/client/activities/activity-quotation-view.ts +90 -0
  6. package/client/bootstrap.ts +8 -0
  7. package/client/index.ts +1 -0
  8. package/client/pages/main.ts +25 -0
  9. package/client/pages/quotation/quotation-importer.ts +97 -0
  10. package/client/pages/quotation/quotation-list-page.ts +348 -0
  11. package/client/reducers/main.ts +17 -0
  12. package/client/route.ts +11 -0
  13. package/client/tsconfig.json +11 -0
  14. package/dist-client/actions/main.d.ts +1 -0
  15. package/dist-client/actions/main.js +2 -0
  16. package/dist-client/actions/main.js.map +1 -0
  17. package/dist-client/activities/activity-quotation-edit.d.ts +14 -0
  18. package/dist-client/activities/activity-quotation-edit.js +87 -0
  19. package/dist-client/activities/activity-quotation-edit.js.map +1 -0
  20. package/dist-client/activities/activity-quotation-view.d.ts +14 -0
  21. package/dist-client/activities/activity-quotation-view.js +87 -0
  22. package/dist-client/activities/activity-quotation-view.js.map +1 -0
  23. package/dist-client/bootstrap.d.ts +1 -0
  24. package/dist-client/bootstrap.js +8 -0
  25. package/dist-client/bootstrap.js.map +1 -0
  26. package/dist-client/index.d.ts +1 -0
  27. package/dist-client/index.js +2 -0
  28. package/dist-client/index.js.map +1 -0
  29. package/dist-client/pages/main.d.ts +1 -0
  30. package/dist-client/pages/main.js +27 -0
  31. package/dist-client/pages/main.js.map +1 -0
  32. package/dist-client/pages/quotation/quotation-importer.d.ts +22 -0
  33. package/dist-client/pages/quotation/quotation-importer.js +100 -0
  34. package/dist-client/pages/quotation/quotation-importer.js.map +1 -0
  35. package/dist-client/pages/quotation/quotation-list-page.d.ts +62 -0
  36. package/dist-client/pages/quotation/quotation-list-page.js +326 -0
  37. package/dist-client/pages/quotation/quotation-list-page.js.map +1 -0
  38. package/dist-client/reducers/main.d.ts +6 -0
  39. package/dist-client/reducers/main.js +14 -0
  40. package/dist-client/reducers/main.js.map +1 -0
  41. package/dist-client/route.d.ts +1 -0
  42. package/dist-client/route.js +11 -0
  43. package/dist-client/route.js.map +1 -0
  44. package/dist-client/tsconfig.tsbuildinfo +1 -0
  45. package/dist-server/activities/activity-quotation.js +113 -0
  46. package/dist-server/activities/activity-quotation.js.map +1 -0
  47. package/dist-server/activities/index.js +17 -0
  48. package/dist-server/activities/index.js.map +1 -0
  49. package/dist-server/controllers/index.js +1 -0
  50. package/dist-server/controllers/index.js.map +1 -0
  51. package/dist-server/index.js +7 -0
  52. package/dist-server/index.js.map +1 -0
  53. package/dist-server/middlewares/index.js +8 -0
  54. package/dist-server/middlewares/index.js.map +1 -0
  55. package/dist-server/migrations/index.js +12 -0
  56. package/dist-server/migrations/index.js.map +1 -0
  57. package/dist-server/routes.js +25 -0
  58. package/dist-server/routes.js.map +1 -0
  59. package/dist-server/service/index.js +23 -0
  60. package/dist-server/service/index.js.map +1 -0
  61. package/dist-server/service/quotation/event-subscriber.js +21 -0
  62. package/dist-server/service/quotation/event-subscriber.js.map +1 -0
  63. package/dist-server/service/quotation/index.js +12 -0
  64. package/dist-server/service/quotation/index.js.map +1 -0
  65. package/dist-server/service/quotation/quotation-history.js +123 -0
  66. package/dist-server/service/quotation/quotation-history.js.map +1 -0
  67. package/dist-server/service/quotation/quotation-mutation.js +168 -0
  68. package/dist-server/service/quotation/quotation-mutation.js.map +1 -0
  69. package/dist-server/service/quotation/quotation-query.js +97 -0
  70. package/dist-server/service/quotation/quotation-query.js.map +1 -0
  71. package/dist-server/service/quotation/quotation-type.js +86 -0
  72. package/dist-server/service/quotation/quotation-type.js.map +1 -0
  73. package/dist-server/service/quotation/quotation.js +110 -0
  74. package/dist-server/service/quotation/quotation.js.map +1 -0
  75. package/dist-server/tsconfig.tsbuildinfo +1 -0
  76. package/helps/quotation/quotation.md +160 -0
  77. package/package.json +36 -0
  78. package/server/activities/activity-quotation.ts +112 -0
  79. package/server/activities/index.ts +17 -0
  80. package/server/controllers/index.ts +0 -0
  81. package/server/index.ts +4 -0
  82. package/server/middlewares/index.ts +3 -0
  83. package/server/migrations/index.ts +9 -0
  84. package/server/routes.ts +28 -0
  85. package/server/service/index.ts +22 -0
  86. package/server/service/quotation/event-subscriber.ts +17 -0
  87. package/server/service/quotation/index.ts +9 -0
  88. package/server/service/quotation/quotation-history.ts +110 -0
  89. package/server/service/quotation/quotation-mutation.ts +198 -0
  90. package/server/service/quotation/quotation-query.ts +62 -0
  91. package/server/service/quotation/quotation-type.ts +61 -0
  92. package/server/service/quotation/quotation.ts +95 -0
  93. package/server/tsconfig.json +10 -0
  94. package/things-factory.config.js +11 -0
  95. package/translations/en.json +1 -0
  96. package/translations/ko.json +1 -0
  97. package/translations/ms.json +1 -0
  98. package/translations/zh.json +1 -0
@@ -0,0 +1,198 @@
1
+ import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'
2
+ import { In } from 'typeorm'
3
+
4
+ import { createAttachment, deleteAttachmentsByRef } from '@things-factory/attachment-base'
5
+
6
+ import { Quotation } from './quotation'
7
+ import { NewQuotation, QuotationPatch } from './quotation-type'
8
+
9
+ @Resolver(Quotation)
10
+ export class QuotationMutation {
11
+ @Directive('@transaction')
12
+ @Mutation(returns => Quotation, { description: 'To create new Quotation' })
13
+ async createQuotation(@Arg('quotation') quotation: NewQuotation, @Ctx() context: ResolverContext): Promise<Quotation> {
14
+ const { domain, user, tx } = context.state
15
+
16
+ const result = await tx.getRepository(Quotation).save({
17
+ ...quotation,
18
+ domain,
19
+ creator: user,
20
+ updater: user
21
+ })
22
+
23
+ if (quotation.thumbnail) {
24
+ await createAttachment(
25
+ null,
26
+ {
27
+ attachment: {
28
+ file: quotation.thumbnail,
29
+ refType: Quotation.name,
30
+ refBy: result.id
31
+ }
32
+ },
33
+ context
34
+ )
35
+ }
36
+
37
+ return result
38
+ }
39
+
40
+ @Directive('@transaction')
41
+ @Mutation(returns => Quotation, { description: 'To modify Quotation information' })
42
+ async updateQuotation(
43
+ @Arg('id') id: string,
44
+ @Arg('patch') patch: QuotationPatch,
45
+ @Ctx() context: ResolverContext
46
+ ): Promise<Quotation> {
47
+ const { domain, user, tx } = context.state
48
+
49
+ const repository = tx.getRepository(Quotation)
50
+ const quotation = await repository.findOne({
51
+ where: { domain: { id: domain.id }, id }
52
+ })
53
+
54
+ const result = await repository.save({
55
+ ...quotation,
56
+ ...patch,
57
+ updater: user
58
+ })
59
+
60
+ if (patch.thumbnail) {
61
+ await deleteAttachmentsByRef(null, { refBys: [result.id] }, context)
62
+ await createAttachment(
63
+ null,
64
+ {
65
+ attachment: {
66
+ file: patch.thumbnail,
67
+ refType: Quotation.name,
68
+ refBy: result.id
69
+ }
70
+ },
71
+ context
72
+ )
73
+ }
74
+
75
+ return result
76
+ }
77
+
78
+ @Directive('@transaction')
79
+ @Mutation(returns => [Quotation], { description: "To modify multiple Quotations' information" })
80
+ async updateMultipleQuotation(
81
+ @Arg('patches', type => [QuotationPatch]) patches: QuotationPatch[],
82
+ @Ctx() context: ResolverContext
83
+ ): Promise<Quotation[]> {
84
+ const { domain, user, tx } = context.state
85
+
86
+ let results = []
87
+ const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
88
+ const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
89
+ const quotationRepo = tx.getRepository(Quotation)
90
+
91
+ if (_createRecords.length > 0) {
92
+ for (let i = 0; i < _createRecords.length; i++) {
93
+ const newRecord = _createRecords[i]
94
+
95
+ const result = await quotationRepo.save({
96
+ ...newRecord,
97
+ domain,
98
+ creator: user,
99
+ updater: user
100
+ })
101
+
102
+ if (newRecord.thumbnail) {
103
+ await createAttachment(
104
+ null,
105
+ {
106
+ attachment: {
107
+ file: newRecord.thumbnail,
108
+ refType: Quotation.name,
109
+ refBy: result.id
110
+ }
111
+ },
112
+ context
113
+ )
114
+ }
115
+
116
+ results.push({ ...result, cuFlag: '+' })
117
+ }
118
+ }
119
+
120
+ if (_updateRecords.length > 0) {
121
+ for (let i = 0; i < _updateRecords.length; i++) {
122
+ const updateRecord = _updateRecords[i]
123
+ const quotation = await quotationRepo.findOneBy({ id: updateRecord.id })
124
+
125
+ const result = await quotationRepo.save({
126
+ ...quotation,
127
+ ...updateRecord,
128
+ updater: user
129
+ })
130
+
131
+ if (updateRecord.thumbnail) {
132
+ await deleteAttachmentsByRef(null, { refBys: [result.id] }, context)
133
+ await createAttachment(
134
+ null,
135
+ {
136
+ attachment: {
137
+ file: updateRecord.thumbnail,
138
+ refType: Quotation.name,
139
+ refBy: result.id
140
+ }
141
+ },
142
+ context
143
+ )
144
+ }
145
+
146
+ results.push({ ...result, cuFlag: 'M' })
147
+ }
148
+ }
149
+
150
+ return results
151
+ }
152
+
153
+ @Directive('@transaction')
154
+ @Mutation(returns => Boolean, { description: 'To delete Quotation' })
155
+ async deleteQuotation(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
156
+ const { domain, tx } = context.state
157
+
158
+ await tx.getRepository(Quotation).delete({ domain: { id: domain.id }, id })
159
+ await deleteAttachmentsByRef(null, { refBys: [id] }, context)
160
+
161
+ return true
162
+ }
163
+
164
+ @Directive('@transaction')
165
+ @Mutation(returns => Boolean, { description: 'To delete multiple Quotations' })
166
+ async deleteQuotations(
167
+ @Arg('ids', type => [String]) ids: string[],
168
+ @Ctx() context: ResolverContext
169
+ ): Promise<boolean> {
170
+ const { domain, tx } = context.state
171
+
172
+ await tx.getRepository(Quotation).delete({
173
+ domain: { id: domain.id },
174
+ id: In(ids)
175
+ })
176
+
177
+ await deleteAttachmentsByRef(null, { refBys: ids }, context)
178
+
179
+ return true
180
+ }
181
+
182
+ @Directive('@transaction')
183
+ @Mutation(returns => Boolean, { description: 'To import multiple Quotations' })
184
+ async importQuotations(
185
+ @Arg('quotations', type => [QuotationPatch]) quotations: QuotationPatch[],
186
+ @Ctx() context: ResolverContext
187
+ ): Promise<boolean> {
188
+ const { domain, tx } = context.state
189
+
190
+ await Promise.all(
191
+ quotations.map(async (quotation: QuotationPatch) => {
192
+ const createdQuotation: Quotation = await tx.getRepository(Quotation).save({ domain, ...quotation })
193
+ })
194
+ )
195
+
196
+ return true
197
+ }
198
+ }
@@ -0,0 +1,62 @@
1
+ import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'
2
+ import { Attachment } from '@things-factory/attachment-base'
3
+ import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
4
+ import { User } from '@things-factory/auth-base'
5
+ import { Quotation } from './quotation'
6
+ import { QuotationList } from './quotation-type'
7
+
8
+ @Resolver(Quotation)
9
+ export class QuotationQuery {
10
+ @Query(returns => Quotation!, { nullable: true, description: 'To fetch a Quotation' })
11
+ async quotation(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Quotation> {
12
+ const { domain } = context.state
13
+
14
+ return await getRepository(Quotation).findOne({
15
+ where: { domain: { id: domain.id }, id }
16
+ })
17
+ }
18
+
19
+ @Query(returns => QuotationList, { description: 'To fetch multiple Quotations' })
20
+ async quotations(@Args() params: ListParam, @Ctx() context: ResolverContext): Promise<QuotationList> {
21
+ const { domain } = context.state
22
+
23
+ const queryBuilder = getQueryBuilderFromListParams({
24
+ domain,
25
+ params,
26
+ repository: await getRepository(Quotation),
27
+ searchables: ['name', 'description']
28
+ })
29
+
30
+ const [items, total] = await queryBuilder.getManyAndCount()
31
+
32
+ return { items, total }
33
+ }
34
+
35
+ @FieldResolver(type => String)
36
+ async thumbnail(@Root() quotation: Quotation): Promise<string | undefined> {
37
+ const attachment: Attachment = await getRepository(Attachment).findOne({
38
+ where: {
39
+ domain: { id: quotation.domainId },
40
+ refType: Quotation.name,
41
+ refBy: quotation.id
42
+ }
43
+ })
44
+
45
+ return attachment?.fullpath
46
+ }
47
+
48
+ @FieldResolver(type => Domain)
49
+ async domain(@Root() quotation: Quotation): Promise<Domain> {
50
+ return await getRepository(Domain).findOneBy({ id: quotation.domainId })
51
+ }
52
+
53
+ @FieldResolver(type => User)
54
+ async updater(@Root() quotation: Quotation): Promise<User> {
55
+ return await getRepository(User).findOneBy({ id: quotation.updaterId })
56
+ }
57
+
58
+ @FieldResolver(type => User)
59
+ async creator(@Root() quotation: Quotation): Promise<User> {
60
+ return await getRepository(User).findOneBy({ id: quotation.creatorId })
61
+ }
62
+ }
@@ -0,0 +1,61 @@
1
+ import type { FileUpload } from 'graphql-upload/GraphQLUpload.js'
2
+ import GraphQLUpload from 'graphql-upload/GraphQLUpload.js'
3
+ import { ObjectType, Field, InputType, Int, ID, registerEnumType } from 'type-graphql'
4
+
5
+ import { ObjectRef, ScalarObject } from '@things-factory/shell'
6
+
7
+ import { Quotation, QuotationStatus } from './quotation'
8
+
9
+ @InputType()
10
+ export class NewQuotation {
11
+ @Field()
12
+ name: string
13
+
14
+ @Field({ nullable: true })
15
+ description?: string
16
+
17
+ @Field(type => QuotationStatus, { nullable: true })
18
+ state?: QuotationStatus
19
+
20
+ @Field({ nullable: true })
21
+ active?: boolean
22
+
23
+ @Field({ nullable: true })
24
+ params?: string
25
+
26
+ @Field(type => GraphQLUpload, { nullable: true })
27
+ thumbnail?: FileUpload
28
+ }
29
+
30
+ @InputType()
31
+ export class QuotationPatch {
32
+ @Field(type => ID, { nullable: true })
33
+ id?: string
34
+
35
+ @Field({ nullable: true })
36
+ name?: string
37
+
38
+ @Field({ nullable: true })
39
+ description?: string
40
+
41
+ @Field(type => QuotationStatus, { nullable: true })
42
+ state?: QuotationStatus
43
+
44
+ @Field({ nullable: true })
45
+ active?: boolean
46
+
47
+ @Field(type => GraphQLUpload, { nullable: true })
48
+ thumbnail?: FileUpload
49
+
50
+ @Field({ nullable: true })
51
+ cuFlag?: string
52
+ }
53
+
54
+ @ObjectType()
55
+ export class QuotationList {
56
+ @Field(type => [Quotation])
57
+ items: Quotation[]
58
+
59
+ @Field(type => Int)
60
+ total: number
61
+ }
@@ -0,0 +1,95 @@
1
+ import {
2
+ CreateDateColumn,
3
+ UpdateDateColumn,
4
+ DeleteDateColumn,
5
+ Entity,
6
+ Index,
7
+ Column,
8
+ RelationId,
9
+ ManyToOne,
10
+ PrimaryGeneratedColumn,
11
+ VersionColumn
12
+ } from 'typeorm'
13
+ import { ObjectType, Field, Int, ID, registerEnumType } from 'type-graphql'
14
+
15
+ import { Domain } from '@things-factory/shell'
16
+ import { User } from '@things-factory/auth-base'
17
+
18
+ export enum QuotationStatus {
19
+ STATUS_A = 'STATUS_A',
20
+ STATUS_B = 'STATUS_B'
21
+ }
22
+
23
+ registerEnumType(QuotationStatus, {
24
+ name: 'QuotationStatus',
25
+ description: 'state enumeration of a quotation'
26
+ })
27
+
28
+ @Entity()
29
+ @Index('ix_quotation_0', (quotation: Quotation) => [quotation.domain, quotation.name, quotation.deletedAt], { unique: true })
30
+ @ObjectType({ description: 'Entity for Quotation' })
31
+ export class Quotation {
32
+ @PrimaryGeneratedColumn('uuid')
33
+ @Field(type => ID)
34
+ readonly id: string
35
+
36
+ @VersionColumn()
37
+ @Field({ nullable: true })
38
+ version?: number = 1
39
+
40
+ @ManyToOne(type => Domain)
41
+ @Field({ nullable: true })
42
+ domain?: Domain
43
+
44
+ @RelationId((quotation: Quotation) => quotation.domain)
45
+ domainId?: string
46
+
47
+ @Column()
48
+ @Field({ nullable: true })
49
+ name?: string
50
+
51
+ @Column({ nullable: true })
52
+ @Field({ nullable: true })
53
+ description?: string
54
+
55
+ @Column({ nullable: true })
56
+ @Field({ nullable: true })
57
+ active?: boolean
58
+
59
+ @Column({ nullable: true })
60
+ @Field({ nullable: true })
61
+ state?: QuotationStatus
62
+
63
+ @Column({ nullable: true })
64
+ @Field({ nullable: true })
65
+ params?: string
66
+
67
+ @CreateDateColumn()
68
+ @Field({ nullable: true })
69
+ createdAt?: Date
70
+
71
+ @UpdateDateColumn()
72
+ @Field({ nullable: true })
73
+ updatedAt?: Date
74
+
75
+ @DeleteDateColumn()
76
+ @Field({ nullable: true })
77
+ deletedAt?: Date
78
+
79
+ @ManyToOne(type => User, { nullable: true })
80
+ @Field(type => User, { nullable: true })
81
+ creator?: User
82
+
83
+ @RelationId((quotation: Quotation) => quotation.creator)
84
+ creatorId?: string
85
+
86
+ @ManyToOne(type => User, { nullable: true })
87
+ @Field(type => User, { nullable: true })
88
+ updater?: User
89
+
90
+ @RelationId((quotation: Quotation) => quotation.updater)
91
+ updaterId?: string
92
+
93
+ @Field(type => String, { nullable: true })
94
+ thumbnail?: string
95
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../../tsconfig-base.json",
3
+ "compilerOptions": {
4
+ "strict": false,
5
+ "module": "commonjs",
6
+ "outDir": "../dist-server",
7
+ "baseUrl": "./"
8
+ },
9
+ "include": ["./**/*"]
10
+ }
@@ -0,0 +1,11 @@
1
+ import route from './dist-client/route'
2
+ import bootstrap from './dist-client/bootstrap'
3
+
4
+ export default {
5
+ route,
6
+ routes: [
7
+ { tagname: 'quotation-main', page: 'quotation-main' },
8
+ { tagname: 'quotation-list-page', page: 'quotation-list' }
9
+ ],
10
+ bootstrap
11
+ }
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1 @@
1
+ {}