@things-factory/sales-base 8.0.3 → 8.0.5

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 (178) hide show
  1. package/dist-server/tsconfig.tsbuildinfo +1 -1
  2. package/package.json +12 -12
  3. package/server/constants/attachment-type.ts +0 -9
  4. package/server/constants/index.ts +0 -7
  5. package/server/constants/load-type.ts +0 -4
  6. package/server/constants/order.ts +0 -203
  7. package/server/constants/product-group-type.ts +0 -4
  8. package/server/constants/release-good.ts +0 -9
  9. package/server/constants/transfer-order-type.ts +0 -6
  10. package/server/constants/validation-error-code.ts +0 -3
  11. package/server/constants/vas-target-type.ts +0 -25
  12. package/server/controllers/ecommerce/ecommerce-controller.ts +0 -122
  13. package/server/controllers/ecommerce/index.ts +0 -2
  14. package/server/controllers/ecommerce/sellercraft-controller.ts +0 -182
  15. package/server/controllers/index.ts +0 -2
  16. package/server/controllers/order-controller.ts +0 -296
  17. package/server/errors/index.ts +0 -1
  18. package/server/errors/validation-error.ts +0 -25
  19. package/server/index.ts +0 -5
  20. package/server/migrations/index.ts +0 -9
  21. package/server/service/arrival-notice/arrival-notice-mutation.ts +0 -1152
  22. package/server/service/arrival-notice/arrival-notice-query.ts +0 -549
  23. package/server/service/arrival-notice/arrival-notice-types.ts +0 -310
  24. package/server/service/arrival-notice/arrival-notice.ts +0 -202
  25. package/server/service/arrival-notice/index.ts +0 -9
  26. package/server/service/claim/claim-mutation.ts +0 -308
  27. package/server/service/claim/claim-query.ts +0 -122
  28. package/server/service/claim/claim-types.ts +0 -130
  29. package/server/service/claim/claim.ts +0 -140
  30. package/server/service/claim/index.ts +0 -9
  31. package/server/service/claim-detail/claim-detail-mutation.ts +0 -102
  32. package/server/service/claim-detail/claim-detail-query.ts +0 -55
  33. package/server/service/claim-detail/claim-detail-types.ts +0 -47
  34. package/server/service/claim-detail/claim-detail.ts +0 -69
  35. package/server/service/claim-detail/index.ts +0 -9
  36. package/server/service/claim-order/claim-order-mutation.ts +0 -101
  37. package/server/service/claim-order/claim-order-query.ts +0 -47
  38. package/server/service/claim-order/claim-order-types.ts +0 -35
  39. package/server/service/claim-order/claim-order.ts +0 -81
  40. package/server/service/claim-order/index.ts +0 -9
  41. package/server/service/collection-order/collection-order-mutation.ts +0 -245
  42. package/server/service/collection-order/collection-order-query.ts +0 -97
  43. package/server/service/collection-order/collection-order-types.ts +0 -165
  44. package/server/service/collection-order/collection-order.ts +0 -135
  45. package/server/service/collection-order/index.ts +0 -9
  46. package/server/service/delivery-order/delivery-order-mutation.ts +0 -967
  47. package/server/service/delivery-order/delivery-order-query.ts +0 -631
  48. package/server/service/delivery-order/delivery-order-types.ts +0 -268
  49. package/server/service/delivery-order/delivery-order.ts +0 -258
  50. package/server/service/delivery-order/index.ts +0 -9
  51. package/server/service/draft-release-good/draft-release-good-mutation.ts +0 -765
  52. package/server/service/draft-release-good/draft-release-good-query.ts +0 -354
  53. package/server/service/draft-release-good/draft-release-good-type.ts +0 -261
  54. package/server/service/draft-release-good/draft-release-good.ts +0 -284
  55. package/server/service/draft-release-good/index.ts +0 -9
  56. package/server/service/goods-receival-note/goods-receival-note-mutation.ts +0 -129
  57. package/server/service/goods-receival-note/goods-receival-note-query.ts +0 -280
  58. package/server/service/goods-receival-note/goods-receival-note-types.ts +0 -105
  59. package/server/service/goods-receival-note/goods-receival-note.ts +0 -127
  60. package/server/service/goods-receival-note/index.ts +0 -9
  61. package/server/service/index.ts +0 -238
  62. package/server/service/inventory-check/index.ts +0 -9
  63. package/server/service/inventory-check/inventory-check-mutation.ts +0 -149
  64. package/server/service/inventory-check/inventory-check-query.ts +0 -48
  65. package/server/service/inventory-check/inventory-check-types.ts +0 -48
  66. package/server/service/inventory-check/inventory-check.ts +0 -90
  67. package/server/service/invoice/index.ts +0 -9
  68. package/server/service/invoice/invoice-mutation.ts +0 -95
  69. package/server/service/invoice/invoice-query.ts +0 -53
  70. package/server/service/invoice/invoice-types.ts +0 -279
  71. package/server/service/invoice/invoice.ts +0 -230
  72. package/server/service/invoice-product/index.ts +0 -9
  73. package/server/service/invoice-product/invoice-product-mutation.ts +0 -54
  74. package/server/service/invoice-product/invoice-product-query.ts +0 -54
  75. package/server/service/invoice-product/invoice-product-types.ts +0 -84
  76. package/server/service/invoice-product/invoice-product.ts +0 -92
  77. package/server/service/job-sheet/index.ts +0 -9
  78. package/server/service/job-sheet/job-sheet-mutation.ts +0 -92
  79. package/server/service/job-sheet/job-sheet-query.ts +0 -112
  80. package/server/service/job-sheet/job-sheet-types.ts +0 -78
  81. package/server/service/job-sheet/job-sheet.ts +0 -102
  82. package/server/service/manifest/index.ts +0 -6
  83. package/server/service/manifest/manifest-mutation.ts +0 -190
  84. package/server/service/manifest/manifest-query.ts +0 -149
  85. package/server/service/manifest/manifest-type.ts +0 -84
  86. package/server/service/manifest/manifest.ts +0 -114
  87. package/server/service/order-inventory/index.ts +0 -9
  88. package/server/service/order-inventory/order-inventory-mutation.ts +0 -54
  89. package/server/service/order-inventory/order-inventory-query.ts +0 -722
  90. package/server/service/order-inventory/order-inventory-types.ts +0 -238
  91. package/server/service/order-inventory/order-inventory.ts +0 -401
  92. package/server/service/order-product/index.ts +0 -9
  93. package/server/service/order-product/order-product-mutation.ts +0 -48
  94. package/server/service/order-product/order-product-query.ts +0 -89
  95. package/server/service/order-product/order-product-types.ts +0 -335
  96. package/server/service/order-product/order-product.ts +0 -362
  97. package/server/service/order-tote/index.ts +0 -9
  98. package/server/service/order-tote/order-tote-mutation.ts +0 -31
  99. package/server/service/order-tote/order-tote-query.ts +0 -112
  100. package/server/service/order-tote/order-tote-types.ts +0 -47
  101. package/server/service/order-tote/order-tote.ts +0 -73
  102. package/server/service/order-tote-item/index.ts +0 -9
  103. package/server/service/order-tote-item/order-tote-item-mutation.ts +0 -31
  104. package/server/service/order-tote-item/order-tote-item-query.ts +0 -82
  105. package/server/service/order-tote-item/order-tote-item-types.ts +0 -56
  106. package/server/service/order-tote-item/order-tote-item.ts +0 -72
  107. package/server/service/order-tote-seal/index.ts +0 -9
  108. package/server/service/order-tote-seal/order-tote-seal-mutation.ts +0 -31
  109. package/server/service/order-tote-seal/order-tote-seal-query.ts +0 -59
  110. package/server/service/order-tote-seal/order-tote-seal-types.ts +0 -41
  111. package/server/service/order-tote-seal/order-tote-seal.ts +0 -46
  112. package/server/service/order-vas/index.ts +0 -9
  113. package/server/service/order-vas/order-vas-mutation.ts +0 -20
  114. package/server/service/order-vas/order-vas-query.ts +0 -72
  115. package/server/service/order-vas/order-vas-types.ts +0 -159
  116. package/server/service/order-vas/order-vas.ts +0 -207
  117. package/server/service/others/index.ts +0 -5
  118. package/server/service/others/other-query.ts +0 -563
  119. package/server/service/others/other-types.ts +0 -115
  120. package/server/service/purchase-order/index.ts +0 -9
  121. package/server/service/purchase-order/purchase-order-mutation.ts +0 -458
  122. package/server/service/purchase-order/purchase-order-query.ts +0 -90
  123. package/server/service/purchase-order/purchase-order-types.ts +0 -154
  124. package/server/service/purchase-order/purchase-order.ts +0 -172
  125. package/server/service/purchase-order-other-charge/index.ts +0 -9
  126. package/server/service/purchase-order-other-charge/purchase-order-other-charge-mutation.ts +0 -31
  127. package/server/service/purchase-order-other-charge/purchase-order-other-charge-query.ts +0 -52
  128. package/server/service/purchase-order-other-charge/purchase-order-other-charge-types.ts +0 -44
  129. package/server/service/purchase-order-other-charge/purchase-order-other-charge.ts +0 -68
  130. package/server/service/release-good/index.ts +0 -9
  131. package/server/service/release-good/release-good-mutation.ts +0 -1686
  132. package/server/service/release-good/release-good-query.ts +0 -980
  133. package/server/service/release-good/release-good-types.ts +0 -662
  134. package/server/service/release-good/release-good.ts +0 -490
  135. package/server/service/retail-replenishment-order/index.ts +0 -9
  136. package/server/service/retail-replenishment-order/retail-replenishment-order-mutation.ts +0 -382
  137. package/server/service/retail-replenishment-order/retail-replenishment-order-query.ts +0 -54
  138. package/server/service/retail-replenishment-order/retail-replenishment-order-types.ts +0 -101
  139. package/server/service/retail-replenishment-order/retail-replenishment-order.ts +0 -115
  140. package/server/service/return-order/index.ts +0 -9
  141. package/server/service/return-order/return-order-mutation.ts +0 -516
  142. package/server/service/return-order/return-order-query.ts +0 -226
  143. package/server/service/return-order/return-order-types.ts +0 -196
  144. package/server/service/return-order/return-order.ts +0 -127
  145. package/server/service/reverse-kitting-order/index.ts +0 -9
  146. package/server/service/reverse-kitting-order/reverse-kitting-order-mutation.ts +0 -500
  147. package/server/service/reverse-kitting-order/reverse-kitting-order-query.ts +0 -197
  148. package/server/service/reverse-kitting-order/reverse-kitting-order-type.ts +0 -173
  149. package/server/service/reverse-kitting-order/reverse-kitting-order.ts +0 -121
  150. package/server/service/reverse-kitting-order-inventory/index.ts +0 -9
  151. package/server/service/reverse-kitting-order-inventory/reverse-kitting-order-inventory-mutation.ts +0 -129
  152. package/server/service/reverse-kitting-order-inventory/reverse-kitting-order-inventory-query.ts +0 -52
  153. package/server/service/reverse-kitting-order-inventory/reverse-kitting-order-inventory-type.ts +0 -95
  154. package/server/service/reverse-kitting-order-inventory/reverse-kitting-order-inventory.ts +0 -143
  155. package/server/service/shipping-order/index.ts +0 -9
  156. package/server/service/shipping-order/shipping-order-mutation.ts +0 -61
  157. package/server/service/shipping-order/shipping-order-query.ts +0 -61
  158. package/server/service/shipping-order/shipping-order-types.ts +0 -89
  159. package/server/service/shipping-order/shipping-order.ts +0 -129
  160. package/server/service/transfer-order/index.ts +0 -9
  161. package/server/service/transfer-order/transfer-order-mutation.ts +0 -309
  162. package/server/service/transfer-order/transfer-order-query.ts +0 -66
  163. package/server/service/transfer-order/transfer-order-types.ts +0 -97
  164. package/server/service/transfer-order/transfer-order.ts +0 -117
  165. package/server/service/vas/index.ts +0 -9
  166. package/server/service/vas/vas-mutation.ts +0 -106
  167. package/server/service/vas/vas-query.ts +0 -60
  168. package/server/service/vas/vas-types.ts +0 -71
  169. package/server/service/vas/vas.ts +0 -77
  170. package/server/service/vas-order/index.ts +0 -9
  171. package/server/service/vas-order/vas-order-mutation.ts +0 -259
  172. package/server/service/vas-order/vas-order-query.ts +0 -119
  173. package/server/service/vas-order/vas-order-types.ts +0 -49
  174. package/server/service/vas-order/vas-order.ts +0 -81
  175. package/server/utils/datetime-util.ts +0 -54
  176. package/server/utils/index.ts +0 -3
  177. package/server/utils/inventory-util.ts +0 -1155
  178. package/server/utils/order-no-generator.ts +0 -146
@@ -1,1152 +0,0 @@
1
- import type { FileUpload } from 'graphql-upload/GraphQLUpload.js'
2
- import GraphQLUpload from 'graphql-upload/GraphQLUpload.js'
3
- import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
4
- import { EntityManager, getConnection, In, Repository } from 'typeorm'
5
-
6
- import { Attachment, createAttachments } from '@things-factory/attachment-base'
7
- import { Role, User } from '@things-factory/auth-base'
8
- import {
9
- Bizplace,
10
- ContactPoint,
11
- getDomainUsers,
12
- getMyBizplace,
13
- getOutletBizplace,
14
- getPermittedBizplaces
15
- } from '@things-factory/biz-base'
16
- import { generateId } from '@things-factory/id-rule-base'
17
- import { Product } from '@things-factory/product-base'
18
- import { PartnerSetting, Setting } from '@things-factory/setting-base'
19
- import { Domain, getRepository } from '@things-factory/shell'
20
-
21
- import {
22
- ORDER_NUMBER_RULE_TYPE,
23
- ORDER_NUMBER_SETTING_KEY,
24
- ORDER_PRODUCT_STATUS,
25
- ORDER_STATUS,
26
- ORDER_TYPES,
27
- ORDER_VAS_STATUS
28
- } from '../../constants'
29
- import { ATTACHMENT_TYPE } from '../../constants/attachment-type'
30
- import { ValidationError } from '../../errors'
31
- import { OrderNoGenerator } from '../../utils/order-no-generator'
32
- import { CollectionOrder } from '../collection-order/collection-order'
33
- import { JobSheet } from '../job-sheet/job-sheet'
34
- import { generateJobSheet } from '../job-sheet/job-sheet-mutation'
35
- import { OrderProduct } from '../order-product/order-product'
36
- import { NewOrderProduct, OrderProductPatch } from '../order-product/order-product-types'
37
- import { OrderVas } from '../order-vas/order-vas'
38
- import { ReleaseGood } from '../release-good/release-good'
39
- import { confirmReleaseGood, deleteReleaseGood, rejectReleaseGood } from '../release-good/release-good-mutation'
40
- import { Vas } from '../vas/vas'
41
- import { validateBulkArrivalNoticesFunction } from './'
42
- import { ArrivalNotice } from './arrival-notice'
43
- import { ArrivalNoticeList, ArrivalNoticePatch, NewArrivalNotice, RawArrivalNotice } from './arrival-notice-types'
44
-
45
- const debug = require('debug')('things-factory:operato-wms:addArrivalNotice')
46
-
47
- @Resolver(ArrivalNotice)
48
- export class ArrivalNoticeMutation {
49
- @Directive('@privilege(category: "order_customer", privilege: "mutation")')
50
- @Directive('@transaction')
51
- @Mutation(returns => Boolean)
52
- async deleteArrivalNotice(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<Boolean> {
53
- const { tx, user, domain } = context.state
54
-
55
- return await deleteArrivalNotice(tx, name, user, domain)
56
- }
57
-
58
- @Directive('@privilege(category: "order_customer", privilege: "mutation")')
59
- @Directive('@transaction')
60
- @Mutation(returns => ArrivalNotice)
61
- async generateArrivalNotice(
62
- @Ctx() context: ResolverContext,
63
- @Arg('arrivalNotice', type => NewArrivalNotice) arrivalNotice: NewArrivalNotice,
64
- @Arg('files', type => [GraphQLUpload], { nullable: true }) files?: FileUpload[]
65
- ): Promise<ArrivalNotice> {
66
- const { tx } = context.state
67
- const createdArrivalNotice: ArrivalNotice = await generateArrivalNoticeFunction(
68
- null,
69
- arrivalNotice,
70
- false,
71
- files,
72
- context,
73
- tx
74
- )
75
-
76
- return createdArrivalNotice
77
- }
78
-
79
- @Directive('@privilege(category: "order_customer", privilege: "mutation")')
80
- @Directive('@transaction')
81
- @Mutation(returns => ArrivalNotice)
82
- async confirmArrivalNotice(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<ArrivalNotice> {
83
- const { tx } = context.state
84
- const arrivalNotice: ArrivalNotice = await confirmArrivalNoticeFunction(name, context, tx)
85
-
86
- // If current GAN has cross docking
87
- if (arrivalNotice.crossDocking) {
88
- const { releaseGood } = await tx.getRepository(ArrivalNotice).findOne({
89
- where: { id: arrivalNotice.id },
90
- relations: ['releaseGood']
91
- })
92
-
93
- // If status of related RO is not equal to PENDING_RECEIVE (i.e. Wasn't confirmed yet.)
94
- if (releaseGood.status !== ORDER_STATUS.PENDING_RECEIVE) {
95
- await confirmReleaseGood(releaseGood.name, context)
96
- }
97
- }
98
-
99
- return arrivalNotice
100
- }
101
-
102
- @Directive('@privilege(category: "order_warehouse", privilege: "mutation")')
103
- @Directive('@transaction')
104
- @Mutation(returns => ArrivalNotice)
105
- async receiveArrivalNotice(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<ArrivalNotice> {
106
- const receiveArrivalNotice: ArrivalNotice = await receiveArrivalNoticeFunction(null, name, context)
107
-
108
- return receiveArrivalNotice
109
- }
110
-
111
- @Directive('@privilege(category: "order_warehouse", privilege: "mutation")')
112
- @Directive('@transaction')
113
- @Mutation(returns => ArrivalNotice)
114
- async checkArrivedNotice(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<ArrivalNotice> {
115
- const { tx } = context.state
116
-
117
- return await checkArrivedNoticeFunction(name, context, tx)
118
- }
119
-
120
- @Directive('@privilege(category: "order_warehouse", privilege: "mutation")')
121
- @Directive('@transaction')
122
- @Mutation(returns => ArrivalNotice)
123
- async rejectArrivalNotice(
124
- @Arg('name') name: string,
125
- @Arg('patch', type => ArrivalNoticePatch) patch: ArrivalNoticePatch,
126
- @Ctx() context: ResolverContext
127
- ): Promise<ArrivalNotice> {
128
- const { tx } = context.state
129
-
130
- const arrivalNotice: ArrivalNotice = await rejectArrivalNotice(tx, name, patch.remark, context)
131
-
132
- if (arrivalNotice.crossDocking) {
133
- const { releaseGood }: { releaseGood: ReleaseGood } = await tx.getRepository(ArrivalNotice).findOne({
134
- where: { id: arrivalNotice.id },
135
- relations: ['releaseGood']
136
- })
137
-
138
- if (releaseGood.status !== ORDER_STATUS.REJECTED) {
139
- await rejectReleaseGood(tx, context, releaseGood.name, patch.remark)
140
- }
141
- }
142
-
143
- return arrivalNotice
144
- }
145
-
146
- @Directive('@privilege(category: "order_warehouse", privilege: "mutation")')
147
- @Directive('@transaction')
148
- @Mutation(returns => Boolean)
149
- async addEditArrivalNoticeProducts(
150
- @Ctx() context: ResolverContext,
151
- @Arg('ganNo') ganNo: string,
152
- @Arg('newOrderProducts', type => [NewOrderProduct], { nullable: true }) newOrderProducts?: NewOrderProduct[],
153
- @Arg('existingOrderProducts', type => [OrderProductPatch], { nullable: true })
154
- existingOrderProducts?: OrderProductPatch[]
155
- ): Promise<Boolean> {
156
- const { user, domain, tx } = context.state
157
-
158
- let arrivalNotice: ArrivalNotice = await tx.getRepository(ArrivalNotice).findOne({
159
- where: { name: ganNo },
160
- relations: ['bizplace', 'orderProducts']
161
- })
162
-
163
- arrivalNotice.status = ORDER_STATUS.PENDING_APPROVAL
164
- arrivalNotice.updater = user
165
- arrivalNotice = await tx.getRepository(ArrivalNotice).save(arrivalNotice)
166
-
167
- debug('gan-new-order-products', ganNo, newOrderProducts)
168
- if (newOrderProducts?.length > 0) await addArrivalNoticeProducts(domain, arrivalNotice, newOrderProducts, user, tx)
169
-
170
- debug('gan-existing-order-products', ganNo, existingOrderProducts)
171
- if (existingOrderProducts?.length > 0) await editArrivalNoticeProducts(existingOrderProducts, user, tx)
172
-
173
- // notification logics
174
- const users: any[] = await getDomainUsers(arrivalNotice?.bizplace, tx)
175
- debug('users', users)
176
-
177
- if (users?.length && context.header?.referer) {
178
- const receivers: any[] = users.map(user => user.id)
179
- const msg = {
180
- title: `Products are added/edited for ${arrivalNotice.name}`,
181
- body: `Warehouse need your review for changes to be approved`,
182
- url: context.header.referer,
183
- data: { url: context.header.referer }
184
- }
185
- /**
186
- * @notes Temporary off sendNotification due to suspect of causing wms down
187
- */
188
-
189
- // await sendNotification({
190
- // receivers,
191
- // message: { ...msg }
192
- // })
193
- }
194
-
195
- return true
196
- }
197
-
198
- @Directive('@privilege(category: "order_customer", privilege: "mutation")')
199
- @Directive('@transaction')
200
- @Mutation(returns => ArrivalNotice)
201
- async addArrivalNotice(
202
- @Ctx() context: ResolverContext,
203
- @Arg('arrivalNotice', type => NewArrivalNotice) arrivalNotice: NewArrivalNotice,
204
- @Arg('file', type => GraphQLUpload, { nullable: true }) file?: FileUpload
205
- ): Promise<ArrivalNotice> {
206
- const { tx } = context.state
207
- const createdGAN: ArrivalNotice = await generateArrivalNoticeFunction(null, arrivalNotice, false, file, context, tx)
208
-
209
- debug('createdGAN', createdGAN)
210
-
211
- const confirmedGAN: ArrivalNotice = await confirmArrivalNoticeFunction(createdGAN.name, context, tx)
212
-
213
- debug('confirmedGAN', confirmedGAN)
214
-
215
- return confirmedGAN
216
- }
217
-
218
- @Directive('@privilege(category: "order_customer", privilege: "mutation")')
219
- @Directive('@transaction')
220
- @Mutation(returns => ArrivalNotice)
221
- async updateArrivalNoticeDetails(
222
- @Ctx() context: ResolverContext,
223
- @Arg('arrivalNotice', type => ArrivalNoticePatch) arrivalNotice: ArrivalNoticePatch
224
- ): Promise<ArrivalNotice> {
225
- const { domain, tx } = context.state
226
- let existingArrivalNotice = await tx
227
- .getRepository(ArrivalNotice)
228
- .findOne({ where: { name: arrivalNotice.name, domain: { id: domain.id } } })
229
-
230
- if (!existingArrivalNotice) {
231
- throw new Error('Existing Arrival Notice not found.')
232
- }
233
-
234
- await tx.getRepository(ArrivalNotice).update(existingArrivalNotice.id, arrivalNotice)
235
- return await tx.getRepository(ArrivalNotice).findOneBy({ id: existingArrivalNotice.id })
236
- }
237
-
238
- @Directive('@privilege(category: "order_customer", privilege: "mutation")')
239
- @Directive('@transaction')
240
- @Mutation(returns => ArrivalNoticeList)
241
- async bulkGenerateArrivalNotices(
242
- @Ctx() context: ResolverContext,
243
- @Arg('rawArrivalNotices', type => [NewArrivalNotice], { nullable: true }) rawArrivalNotices: NewArrivalNotice[],
244
- @Arg('bizplaceId', type => String) bizplaceId: string,
245
- @Arg('bufferLocation', type => String, { nullable: true }) bufferLocation: string
246
- ): Promise<ArrivalNoticeList> {
247
- const { domain, user, tx } = context.state
248
- let createdArrivalNoticeIds: string[] = [],
249
- createdOrderProductIds: string[] = [],
250
- errorsCaught: any[] = [],
251
- finalArrivalNoticeList: ArrivalNotice[] = []
252
- let opStatus = ORDER_PRODUCT_STATUS.PENDING_RECEIVE
253
- let anStatus = ORDER_STATUS.PENDING_RECEIVE
254
-
255
- const foundBizplace: Bizplace = await tx
256
- .getRepository(Bizplace)
257
- .findOne({ where: { id: bizplaceId }, relations: ['domain'] })
258
-
259
- if (!foundBizplace) throw new Error('company not found')
260
-
261
- // to check whether the raw data are valid
262
- const validatedArrivalNotices: RawArrivalNotice[] = await validateBulkArrivalNoticesFunction(
263
- rawArrivalNotices,
264
- bizplaceId,
265
- tx
266
- )
267
-
268
- // check for custom GAN order no setting
269
- const ganNoSetting: Setting = await tx.getRepository(Setting).findOne({
270
- where: {
271
- domain: { id: domain.id },
272
- name: ORDER_NUMBER_SETTING_KEY.GAN_NUMBER_RULE
273
- }
274
- })
275
-
276
- const ganProcessingSetting: Setting = await tx.getRepository(Setting).findOne({
277
- where: { domain: { id: domain.id }, category: 'id-rule', name: 'gan-order-processing' }
278
- })
279
-
280
- const partnerGanProcessingSetting: PartnerSetting = await tx.getRepository(PartnerSetting).findOne({
281
- where: {
282
- setting: { id: ganProcessingSetting.id },
283
- domain: { id: domain.id },
284
- partnerDomain: { id: foundBizplace.domain.id }
285
- }
286
- })
287
-
288
- // If status of GAN is PENDING_RECEIVE then directly to assign warehouse
289
- if (ganProcessingSetting) {
290
- let setting = !isNaN(Number(partnerGanProcessingSetting?.value))
291
- ? partnerGanProcessingSetting?.value
292
- : ganProcessingSetting.value
293
-
294
- // CONFIRM to assign if setting value is 1
295
- if (Number(setting) == 1) {
296
- opStatus = ORDER_PRODUCT_STATUS.ARRIVED
297
- anStatus = ORDER_STATUS.ARRIVED
298
- }
299
- }
300
-
301
- // extract rawArrivalNotices data into normal ArrivalNotice format
302
- let arrivalNotices: Partial<ArrivalNotice[]> = extractArrivalNotices(validatedArrivalNotices)
303
-
304
- for (let i = 0, l = arrivalNotices.length; i < l; i++) {
305
- try {
306
- await getConnection().transaction(async childTx => {
307
- // check for duplication
308
- const duplicatedArrivalNotice: ArrivalNotice = await childTx.getRepository(ArrivalNotice).findOne({
309
- where: {
310
- refNo: arrivalNotices[i].refNo,
311
- refNo2: arrivalNotices[i].refNo2,
312
- refNo3: arrivalNotices[i].refNo3,
313
- etaDate: arrivalNotices[i].etaDate,
314
- truckNo: arrivalNotices[i].truckNo,
315
- containerNo: arrivalNotices[i].containerNo,
316
- containerSize: arrivalNotices[i].containerSize,
317
- looseItem: arrivalNotices[i].looseItem,
318
- importCargo: arrivalNotices[i].importCargo
319
- }
320
- })
321
-
322
- if (duplicatedArrivalNotice) {
323
- throw new Error(`duplicated with ${duplicatedArrivalNotice.name}`)
324
- }
325
-
326
- // save new arrival notice
327
- const createdArrivalNotice: ArrivalNotice = await childTx.getRepository(ArrivalNotice).save({
328
- ...arrivalNotices[i],
329
- name: ganNoSetting
330
- ? await generateId({ domain, type: ORDER_NUMBER_RULE_TYPE.GAN_NUMBER, seed: {} })
331
- : OrderNoGenerator.arrivalNotice(),
332
- domain,
333
- bizplace: foundBizplace,
334
- status: ORDER_STATUS.PENDING,
335
- creator: user,
336
- updater: user
337
- })
338
-
339
- // save new order products
340
- let createdOrderProducts: OrderProduct[] = await Promise.all(
341
- arrivalNotices[i].orderProducts.map(async (op: OrderProduct) => {
342
- return {
343
- ...op,
344
- domain,
345
- bizplace: foundBizplace,
346
- name: OrderNoGenerator.orderProduct(),
347
- // product: await childTx.getRepository(Product).findOneBy({ id: op.product.id }),
348
- status: ORDER_PRODUCT_STATUS.PENDING,
349
- arrivalNotice: createdArrivalNotice,
350
- creator: user
351
- }
352
- })
353
- )
354
- createdOrderProducts = await childTx.getRepository(OrderProduct).save(createdOrderProducts)
355
-
356
- // generate new jobsheet
357
- await generateJobSheet(domain, user, createdArrivalNotice, childTx)
358
-
359
- // push arrivalNotice and orderProducts IDs if successfully saved
360
- createdArrivalNoticeIds.push(createdArrivalNotice.id)
361
- createdOrderProductIds.push(...createdOrderProducts.map(op => op.id))
362
- })
363
- } catch (error) {
364
- // collect the arrivalNotice details and its error
365
- let rawArrivalNotices: RawArrivalNotice[] = formRawArrivalNotices(arrivalNotices[i], error.message)
366
- errorsCaught.push(...rawArrivalNotices)
367
- }
368
- }
369
-
370
- if (createdArrivalNoticeIds.length && createdOrderProductIds.length) {
371
- await getConnection().transaction(async childTx => {
372
- // update arrivalNotices status to PENDING_RECEIVE
373
- await childTx
374
- .getRepository(ArrivalNotice)
375
- .update({ id: In(createdArrivalNoticeIds) }, { status: anStatus, updater: user })
376
-
377
- // update orderProducts status to PENDING_RECEIVE
378
- await childTx
379
- .getRepository(OrderProduct)
380
- .update({ id: In(createdOrderProductIds) }, { status: opStatus, updater: user })
381
-
382
- finalArrivalNoticeList = await childTx.getRepository(ArrivalNotice).find({
383
- where: { id: In(createdArrivalNoticeIds) },
384
- relations: ['orderProducts', 'orderProducts.product', 'bizplace']
385
- })
386
- })
387
- }
388
-
389
- if (errorsCaught.length) {
390
- // should return this error list in the grist so that user know which gan need to amend
391
- throw new ValidationError({
392
- ...ValidationError.ERROR_CODES.INVALID_DATA_FOUND,
393
- detail: { data: JSON.stringify(errorsCaught) }
394
- })
395
- }
396
-
397
- // return arrivalNotices with its orderProducts list
398
- return { items: finalArrivalNoticeList, total: 0 }
399
- }
400
- }
401
-
402
- export async function deleteArrivalNotice(
403
- tx: EntityManager,
404
- name: string,
405
- user: User,
406
- domain: Domain
407
- ): Promise<boolean> {
408
- let foundArrivalNotice: ArrivalNotice = await tx.getRepository(ArrivalNotice).findOne({
409
- where: { domain: { id: domain.id }, name },
410
- relations: ['bizplace', 'releaseGood', 'orderProducts', 'orderVass', 'collectionOrders', 'creator', 'updater']
411
- })
412
-
413
- if (!foundArrivalNotice) throw new Error(`Arrival notice doesn't exists.`)
414
-
415
- const foundJS: JobSheet = await tx.getRepository(JobSheet).findOne({
416
- where: {
417
- bizplace: { id: foundArrivalNotice.bizplace.id },
418
- arrivalNoticeRefNo: foundArrivalNotice.name
419
- }
420
- })
421
-
422
- if (foundJS) await tx.getRepository(JobSheet).delete({ arrivalNoticeRefNo: foundArrivalNotice.name })
423
-
424
- const foundOPs: OrderProduct[] = foundArrivalNotice.orderProducts
425
- const foundOVs: OrderVas[] = foundArrivalNotice.orderVass
426
-
427
- // 1. delete order products
428
- const productIds = foundOPs.map((product: OrderProduct) => product.id)
429
- if (productIds.length) {
430
- await tx.getRepository(OrderProduct).delete({ id: In(productIds) })
431
- }
432
-
433
- // 2. delete order vass
434
- const vasIds = foundOVs.map((vas: OrderVas) => vas.id)
435
- if (vasIds.length) {
436
- await tx.getRepository(OrderVas).delete({ id: In(vasIds) })
437
- }
438
-
439
- await tx.getRepository(ArrivalNotice).save({
440
- ...foundArrivalNotice,
441
- updater: user
442
- })
443
-
444
- // 4. Remove relation with RO if it's cross docking
445
- if (foundArrivalNotice.crossDocking && foundArrivalNotice.releaseGood?.id) {
446
- let releaseGood: ReleaseGood = foundArrivalNotice.releaseGood
447
- releaseGood.arrivalNotice = null
448
- releaseGood = await tx.getRepository(ReleaseGood).save(releaseGood)
449
-
450
- await tx.getRepository(ArrivalNotice).delete({ domain: { id: domain.id }, name })
451
- await deleteReleaseGood(tx, releaseGood.name, user, domain)
452
- } else {
453
- // 5. delete GAN
454
- await tx.getRepository(ArrivalNotice).delete({ domain: { id: domain.id }, name })
455
- }
456
- return true
457
- }
458
-
459
- export async function generateArrivalNoticeFunction(
460
- _: any,
461
- arrivalNotice: any,
462
- fromPo: Boolean,
463
- files: FileUpload[],
464
- context: any,
465
- tx?: EntityManager
466
- ): Promise<ArrivalNotice> {
467
- const { domain, user } = context.state
468
- let orderProducts: OrderProduct[] = arrivalNotice.orderProducts
469
- let orderVass: OrderVas[] = arrivalNotice.orderVass
470
- let myBizplace: Bizplace
471
- let orderNo: string = ''
472
-
473
- const settingRepo: Repository<Setting> = tx?.getRepository(Setting) || getRepository(Setting)
474
-
475
- if (arrivalNotice.bizplace) myBizplace = arrivalNotice.bizplace
476
- else if (arrivalNotice.customerBizplaceId) {
477
- const permittedBizplaces: Bizplace[] = await getPermittedBizplaces(domain, user)
478
- let foundPermittedBizplace: Bizplace = permittedBizplaces.find(biz => biz.id == arrivalNotice.customerBizplaceId)
479
-
480
- if (!foundPermittedBizplace) throw new Error(`This user does not permitted for this company`)
481
-
482
- myBizplace = arrivalNotice.customerBizplaceId
483
- } else if (arrivalNotice.partnerBizplaceId) {
484
- const permittedBizplaces: Bizplace[] = await getPermittedBizplaces(domain, user)
485
- let foundPermittedBizplace: Bizplace = permittedBizplaces.find(biz => biz.id == arrivalNotice.partnerBizplaceId)
486
-
487
- if (!foundPermittedBizplace) throw new Error(`This user does not permitted for this company`)
488
-
489
- myBizplace = arrivalNotice.partnerBizplaceId
490
- } else if (arrivalNotice.warehouseId) myBizplace = await getOutletBizplace(arrivalNotice.warehouseId)
491
- else myBizplace = await getMyBizplace(domain, user)
492
-
493
- if (arrivalNotice.supplier) {
494
- const supplier: ContactPoint = await tx.getRepository(ContactPoint).findOne({
495
- where: { id: arrivalNotice.supplier, domain: { id: domain.id } },
496
- relations: ['bizplace']
497
- })
498
-
499
- if (!supplier) throw new Error('contact point does not exist')
500
-
501
- arrivalNotice.supplier = supplier
502
- }
503
- // find GAN number rule setting
504
- const ganNoSetting: Setting = await settingRepo.findOne({
505
- where: {
506
- domain: { id: domain.id },
507
- name: ORDER_NUMBER_SETTING_KEY.GAN_NUMBER_RULE
508
- }
509
- })
510
-
511
- if (ganNoSetting) {
512
- orderNo = await generateId({ domain, type: ORDER_NUMBER_RULE_TYPE.GAN_NUMBER, seed: {} })
513
- } else {
514
- orderNo = OrderNoGenerator.arrivalNotice()
515
- }
516
-
517
- // 1. Create arrival notice
518
- const createdArrivalNotice: ArrivalNotice = await tx.getRepository(ArrivalNotice).save({
519
- ...arrivalNotice,
520
- name: orderNo,
521
- domain,
522
- bizplace: myBizplace,
523
- looseItem: arrivalNotice?.looseItem ? arrivalNotice.looseItem : false,
524
- status: fromPo ? ORDER_STATUS.INTRANSIT : ORDER_STATUS.PENDING,
525
- creator: user,
526
- updater: user
527
- })
528
-
529
- // 2. Create arrival notice product
530
- await addArrivalNoticeProducts(
531
- domain,
532
- createdArrivalNotice,
533
- orderProducts.map((op: OrderProduct) => {
534
- return { ...op, status: fromPo ? ORDER_PRODUCT_STATUS.INTRANSIT : ORDER_PRODUCT_STATUS.PENDING }
535
- }),
536
- user,
537
- tx
538
- )
539
-
540
- await generateJobSheet(domain, user, createdArrivalNotice, tx)
541
-
542
- // 3. Create arrival notice vas
543
- if (orderVass?.length) {
544
- orderVass = await Promise.all(
545
- orderVass.map(async (ov: OrderVas) => {
546
- if (ov.targetProduct) {
547
- ov.targetProduct = await tx.getRepository(Product).findOneBy({ id: ov.targetProduct.id })
548
- }
549
-
550
- return {
551
- ...ov,
552
- domain,
553
- bizplace: myBizplace,
554
- name: OrderNoGenerator.orderVas(),
555
- vas: await tx.getRepository(Vas).findOneBy({ domain: { id: domain.id }, id: ov.vas.id }),
556
- type: ORDER_TYPES.ARRIVAL_NOTICE,
557
- arrivalNotice: createdArrivalNotice,
558
- status: fromPo ? ORDER_VAS_STATUS.INTRANSIT : ORDER_VAS_STATUS.PENDING,
559
- creator: user,
560
- updater: user
561
- }
562
- })
563
- )
564
- await tx.getRepository(OrderVas).save(orderVass)
565
- }
566
-
567
- if (files?.length) {
568
- const attachments: Partial<Attachment>[] = files.map(attachment => {
569
- return {
570
- file: attachment,
571
- refType: ATTACHMENT_TYPE.GAN,
572
- refBy: createdArrivalNotice.id,
573
- category: ATTACHMENT_TYPE.GAN /* TODO use refType */
574
- }
575
- })
576
- await createAttachments(_, { attachments }, context)
577
- }
578
-
579
- return createdArrivalNotice
580
- }
581
-
582
- export async function confirmArrivalNoticeFunction(
583
- name: string,
584
- context: any,
585
- tx?: EntityManager
586
- ): Promise<ArrivalNotice> {
587
- const { user, domain } = context.state
588
-
589
- const foundArrivalNotice: ArrivalNotice = await tx.getRepository(ArrivalNotice).findOne({
590
- where: { domain: { id: domain.id }, name, status: ORDER_STATUS.PENDING },
591
- relations: [
592
- 'bizplace',
593
- 'bizplace.domain',
594
- 'releaseGood',
595
- 'orderProducts',
596
- 'orderProducts.product',
597
- 'orderVass',
598
- 'orderVass.vas',
599
- 'creator',
600
- 'updater'
601
- ]
602
- })
603
-
604
- let foundOPs: OrderProduct[] = foundArrivalNotice.orderProducts
605
- let foundOVs: OrderVas[] = foundArrivalNotice.orderVass
606
- let customerBizplace: Bizplace = foundArrivalNotice.bizplace
607
- let opStatus = ORDER_PRODUCT_STATUS.PENDING_RECEIVE
608
- let anStatus = ORDER_STATUS.PENDING_RECEIVE
609
- let ovStatus = ORDER_VAS_STATUS.PENDING_RECEIVE
610
- let acceptedByUser = null
611
- let acceptedTime = null
612
-
613
- const ganProcessingSetting: Setting = await tx.getRepository(Setting).findOne({
614
- where: { domain: { id: domain.id }, category: 'id-rule', name: 'gan-order-processing' }
615
- })
616
-
617
- // If status of GAN is PENDING_RECEIVE then directly to assign warehouse
618
- if (ganProcessingSetting) {
619
- const partnerGanProcessingSetting: PartnerSetting = await tx.getRepository(PartnerSetting).findOne({
620
- where: {
621
- setting: { id: ganProcessingSetting.id },
622
- domain: { id: domain.id },
623
- partnerDomain: { id: customerBizplace?.domain?.id }
624
- }
625
- })
626
-
627
- let setting = !isNaN(Number(partnerGanProcessingSetting?.value))
628
- ? partnerGanProcessingSetting?.value
629
- : ganProcessingSetting.value
630
-
631
- // CONFIRM to assign if setting value is 1
632
- if (Number(setting) == 1) {
633
- opStatus = ORDER_PRODUCT_STATUS.ARRIVED
634
- anStatus = ORDER_STATUS.ARRIVED
635
- ovStatus = ORDER_VAS_STATUS.ARRIVED
636
- acceptedByUser = user
637
- acceptedTime = new Date()
638
- }
639
- }
640
-
641
- if (!foundArrivalNotice) throw new Error(`Arrival notice doesn't exists.`)
642
-
643
- // 1. GAN Status change (PENDING => PENDING_RECEIVE)
644
- let arrivalNotice: ArrivalNotice = await tx.getRepository(ArrivalNotice).save({
645
- ...foundArrivalNotice,
646
- status: anStatus,
647
- updater: user,
648
- acceptedBy: acceptedByUser,
649
- acceptedAt: acceptedTime
650
- })
651
-
652
- foundOPs = foundOPs.map((op: OrderProduct) => {
653
- return { ...op, status: opStatus }
654
- })
655
- await tx.getRepository(OrderProduct).save(foundOPs)
656
-
657
- // 2. Update order vas status if it exists.
658
- if (foundOVs && foundOVs.length) {
659
- foundOVs = foundOVs.map((ov: OrderVas) => {
660
- return { ...ov, status: ovStatus }
661
- })
662
-
663
- await tx.getRepository(OrderVas).save(foundOVs)
664
- }
665
-
666
- // notification logics
667
- // get Office Admin Users
668
- if (context?.state?.type != 'api') {
669
- const users: any[] = await tx
670
- .getRepository('users_roles')
671
- .createQueryBuilder('ur')
672
- .select('ur.users_id', 'id')
673
- .where(qb => {
674
- const subQuery = qb
675
- .subQuery()
676
- .select('role.id')
677
- .from(Role, 'role')
678
- .where("role.name = 'Office Admin'")
679
- .andWhere('role.domain_id = :domain', { domain: domain.id })
680
- .getQuery()
681
- return 'ur.roles_id IN ' + subQuery
682
- })
683
- .getRawMany()
684
-
685
- // send notification to Office Admin Users
686
- if (users?.length && context.header?.referer) {
687
- const receivers: any[] = users.map(user => user.id)
688
- const msg = {
689
- title: `New Arrival Notice from ${customerBizplace.name}`,
690
- body: `New incoming order, ${foundArrivalNotice.name} is pending for receiving`,
691
- url: context.header.referer,
692
- data: { url: context.header.referer }
693
- }
694
-
695
- /**
696
- * @notes Temporary off sendNotification due to suspect of causing wms down
697
- */
698
-
699
- // await sendNotification({
700
- // receivers,
701
- // message: { ...msg }
702
- // })
703
- }
704
- }
705
-
706
- return arrivalNotice
707
- }
708
-
709
- export async function receiveArrivalNoticeFunction(
710
- _: any,
711
- name: string,
712
- context: ResolverContext
713
- ): Promise<ArrivalNotice> {
714
- const { user, domain, tx } = context.state
715
- try {
716
- const foundArrivalNotice: ArrivalNotice = await tx.getRepository(ArrivalNotice).findOne({
717
- where: { domain: { id: domain.id }, name, status: ORDER_STATUS.PENDING_RECEIVE },
718
- relations: ['bizplace', 'bizplace.domain', 'collectionOrders', 'orderProducts', 'orderVass']
719
- })
720
-
721
- let foundOPs: OrderProduct[] = foundArrivalNotice.orderProducts
722
- let foundOVs: OrderVas[] = foundArrivalNotice.orderVass
723
- let foundCOs: CollectionOrder[] = await tx.getRepository(CollectionOrder).find({
724
- where: { domain: { id: domain.id }, refNo: foundArrivalNotice.name }
725
- })
726
- let customerBizplace: Bizplace = foundArrivalNotice.bizplace
727
- let opStatus = ORDER_PRODUCT_STATUS.INTRANSIT
728
- let anStatus = ORDER_STATUS.INTRANSIT
729
- let ovStatus = ORDER_VAS_STATUS.INTRANSIT
730
- let coStatus = ORDER_STATUS.READY_TO_DISPATCH
731
-
732
- const ganProcessingSetting: Setting = await tx.getRepository(Setting).findOne({
733
- where: { domain: { id: domain.id }, category: 'id-rule', name: 'gan-order-processing' }
734
- })
735
-
736
- // If status of GAN is INTRANSIT then directly to assign warehouse
737
- if (ganProcessingSetting) {
738
- const partnerGanProcessingSetting: PartnerSetting = await tx.getRepository(PartnerSetting).findOne({
739
- where: {
740
- setting: { id: ganProcessingSetting.id },
741
- domain: { id: domain.id },
742
- partnerDomain: { id: customerBizplace?.domain?.id }
743
- }
744
- })
745
-
746
- let setting = !isNaN(Number(partnerGanProcessingSetting?.value))
747
- ? partnerGanProcessingSetting?.value
748
- : ganProcessingSetting.value
749
-
750
- // RECEIVE to assign if setting value is 2
751
- if (Number(setting) == 2) {
752
- opStatus = ORDER_PRODUCT_STATUS.ARRIVED
753
- anStatus = ORDER_STATUS.ARRIVED
754
- ovStatus = ORDER_VAS_STATUS.ARRIVED
755
- coStatus = ORDER_STATUS.READY_TO_DISPATCH
756
- }
757
- }
758
-
759
- if (!foundArrivalNotice) throw new Error(`Arrival notice doesn't exists.`)
760
-
761
- // 1. Update status of order products (PENDING_RECEIVE => INTRANSIT)
762
- foundOPs = foundOPs.map((op: OrderProduct) => {
763
- return {
764
- ...op,
765
- status: opStatus,
766
- updater: user
767
- }
768
- })
769
- await tx.getRepository(OrderProduct).save(foundOPs)
770
-
771
- // 2. Update status of order vass if it exists (PENDING_RECEIVE => INTRANSIT)
772
- if (foundOVs && foundOVs.length) {
773
- foundOVs = foundOVs.map((ov: OrderVas) => {
774
- return {
775
- ...ov,
776
- status: ovStatus,
777
- updater: user
778
- }
779
- })
780
- await tx.getRepository(OrderVas).save(foundOVs)
781
- }
782
-
783
- // 3. If there's collection order, update status of collection order (PENDING_RECEIVE => READY_TO_DISPATCH)
784
- if (foundCOs) {
785
- foundCOs = foundCOs.map((co: CollectionOrder) => {
786
- return {
787
- ...co,
788
- status: coStatus,
789
- updater: user
790
- }
791
- })
792
- }
793
-
794
- // notification logics
795
- const users: any[] = await getDomainUsers(foundArrivalNotice?.bizplace, tx)
796
-
797
- // send notification to Customer Users
798
- if (users?.length && context.header?.referer) {
799
- const receivers: any[] = users.map(user => user.id)
800
- const msg = {
801
- title: `Latest status for ${foundArrivalNotice.name}`,
802
- body: `Your GAN has been received and processed by ${domain.name}`,
803
- url: context.header.referer,
804
- data: { url: context.header.referer }
805
- }
806
-
807
- /**
808
- * @notes Temporary off sendNotification due to suspect of causing wms down
809
- */
810
-
811
- // await sendNotification({
812
- // receivers,
813
- // message: { ...msg }
814
- // })
815
- }
816
-
817
- // 4. Update status of arrival notice (PENDING_RECEIVE => INTRANSIT)
818
- let rcvArrivalNotice = await tx.getRepository(ArrivalNotice).save({
819
- ...foundArrivalNotice,
820
- status: anStatus,
821
- acceptedBy: user,
822
- acceptedAt: new Date(),
823
- updater: user
824
- })
825
-
826
- return foundArrivalNotice
827
- } catch (e) {
828
- throw e
829
- }
830
- }
831
-
832
- export async function checkArrivedNoticeFunction(
833
- name: string,
834
- context: any,
835
- tx?: EntityManager
836
- ): Promise<ArrivalNotice> {
837
- const { user, domain } = context.state
838
- try {
839
- const foundArrivalNotice: ArrivalNotice = await tx.getRepository(ArrivalNotice).findOne({
840
- where: { domain: { id: domain.id }, name, status: ORDER_STATUS.INTRANSIT },
841
- relations: ['bizplace', 'collectionOrders', 'orderProducts', 'orderVass']
842
- })
843
-
844
- debug('ganNo', name, foundArrivalNotice)
845
-
846
- if (!foundArrivalNotice) throw new Error(`Arrival notice doesn't exists.`)
847
-
848
- // 1. Check wheter related collection order is done or not
849
- const foundCOs: CollectionOrder[] = foundArrivalNotice.collectionOrders
850
- if (foundCOs && foundCOs.length) {
851
- foundCOs.map((co: CollectionOrder) => {
852
- if (co.status !== ORDER_STATUS.DONE) {
853
- throw new Error(`Collection Order: ${co.name} is not finished yet.`)
854
- }
855
- })
856
- }
857
-
858
- let foundOPs: OrderProduct[] = foundArrivalNotice.orderProducts
859
- let foundOVs: OrderVas[] = foundArrivalNotice.orderVass
860
-
861
- // 2. Update status of order products (INTRANSIT => ARRIVED)
862
- foundOPs = foundOPs.map((op: OrderProduct) => {
863
- return {
864
- ...op,
865
- status: ORDER_PRODUCT_STATUS.ARRIVED,
866
- updater: user
867
- }
868
- })
869
- await tx.getRepository(OrderProduct).save(foundOPs)
870
-
871
- // 3. Update status of order vass if it exists (INTRANSIT => ARRIVED)
872
- if (foundOVs && foundOVs.length) {
873
- foundOVs = foundOVs.map((ov: OrderVas) => {
874
- return {
875
- ...ov,
876
- status: ORDER_VAS_STATUS.ARRIVED,
877
- updater: user
878
- }
879
- })
880
- await tx.getRepository(OrderVas).save(foundOVs)
881
- }
882
-
883
- // 4. Update status of arrival notice (INTRANSIT => ARRIVED)
884
- await tx.getRepository(ArrivalNotice).save({
885
- ...foundArrivalNotice,
886
- status: ORDER_STATUS.ARRIVED,
887
- updater: user
888
- })
889
-
890
- // notification logics
891
- const users: any[] = await getDomainUsers(foundArrivalNotice?.bizplace, tx)
892
-
893
- if (users?.length && context.header?.referer) {
894
- const receivers: any[] = users.map(user => user.id)
895
- const msg = {
896
- title: `Latest status for ${foundArrivalNotice.name}`,
897
- body: `Your goods has safely arrived at ${domain.name}`,
898
- url: context.header.referer,
899
- data: { url: context.header.referer }
900
- }
901
-
902
- /**
903
- * @notes Temporary off sendNotification due to suspect of causing wms down
904
- */
905
-
906
- // await sendNotification({
907
- // receivers,
908
- // message: { ...msg }
909
- // })
910
- }
911
-
912
- return foundArrivalNotice
913
- } catch (e) {
914
- throw e
915
- }
916
- }
917
-
918
- export async function rejectArrivalNotice(
919
- tx: EntityManager,
920
- name: string,
921
- remark: string,
922
- context: any
923
- ): Promise<ArrivalNotice> {
924
- const { user, domain } = context.state
925
-
926
- const foundArrivalNotice: ArrivalNotice = await tx.getRepository(ArrivalNotice).findOne({
927
- where: { domain: { id: domain.id }, name, status: ORDER_STATUS.PENDING_RECEIVE },
928
- relations: ['bizplace', 'orderProducts', 'orderVass', 'collectionOrders']
929
- })
930
-
931
- if (!foundArrivalNotice) throw new Error(`Arrival notice doesn't exists.`)
932
- if (!remark) throw new Error('Remark is not exist.')
933
-
934
- let foundOPs: OrderProduct[] = foundArrivalNotice.orderProducts
935
- let foundOVs: OrderVas[] = foundArrivalNotice.orderVass
936
- let foundCOs: CollectionOrder[] = foundArrivalNotice.collectionOrders
937
-
938
- // 1. Update status of order products (PENDING_RECEIVE => REJECTED)
939
- foundOPs = foundOPs.map((op: OrderProduct) => {
940
- op.status = ORDER_PRODUCT_STATUS.REJECTED
941
- op.updater = user
942
- return op
943
- })
944
- await tx.getRepository(OrderProduct).save(foundOPs)
945
-
946
- // 2. Update status of order vass if it exists (PENDING_RECEIVE => REJECTED)
947
- if (foundOVs && foundOVs.length) {
948
- foundOVs = foundOVs.map((ov: OrderVas) => {
949
- ov.status = ORDER_VAS_STATUS.REJECTED
950
- ov.updater = user
951
- return ov
952
- })
953
- await tx.getRepository(OrderVas).save(foundOVs)
954
- }
955
-
956
- // 3. If there's collection order, update status of collection order (PENDING_RECEIVE => REJECTED)
957
- if (foundCOs) {
958
- foundCOs = foundCOs.map((co: CollectionOrder) => {
959
- co.status = ORDER_STATUS.REJECTED
960
- co.updater = user
961
- return co
962
- })
963
- await tx.getRepository(CollectionOrder).save(foundCOs)
964
- }
965
-
966
- foundArrivalNotice.remark = remark
967
- foundArrivalNotice.status = ORDER_STATUS.REJECTED
968
- foundArrivalNotice.updater = user
969
- await tx.getRepository(ArrivalNotice).save(foundArrivalNotice)
970
-
971
- // notification logics
972
- const users: any[] = await getDomainUsers(foundArrivalNotice?.bizplace, tx)
973
-
974
- // send notification to Customer Users
975
- if (users?.length && context.header?.referer) {
976
- const receivers: any[] = users.map(user => user.id)
977
- const msg = {
978
- title: `Latest status for ${foundArrivalNotice.name}`,
979
- body: `Your GAN has been rejected.`,
980
- url: context.header.referer,
981
- data: { url: context.header.referer }
982
- }
983
-
984
- /**
985
- * @notes Temporary off sendNotification due to suspect of causing wms down
986
- */
987
-
988
- // await sendNotification({
989
- // receivers,
990
- // message: { ...msg }
991
- // })
992
- }
993
-
994
- return foundArrivalNotice
995
- }
996
-
997
- export async function addArrivalNoticeProducts(
998
- domain: Domain,
999
- arrivalNotice: ArrivalNotice,
1000
- newOrderProducts: any[],
1001
- user: User,
1002
- tx?: EntityManager
1003
- ): Promise<void> {
1004
- const productRepo: Repository<Product> = tx?.getRepository(Product) || getRepository(Product)
1005
- const orderProductRepo: Repository<OrderProduct> = tx?.getRepository(OrderProduct) || getRepository(OrderProduct)
1006
-
1007
- if (!arrivalNotice?.bizplace || !arrivalNotice?.orderProducts?.length) {
1008
- arrivalNotice = await tx.getRepository(ArrivalNotice).findOne({
1009
- where: { domain: { id: domain.id }, name: arrivalNotice.name },
1010
- relations: ['bizplace', 'orderProducts']
1011
- })
1012
- }
1013
-
1014
- const createdOrderProducts: OrderProduct[] = await Promise.all(
1015
- newOrderProducts.map(async (op: OrderProduct) => {
1016
- return {
1017
- ...op,
1018
- domain,
1019
- bizplace: arrivalNotice.bizplace,
1020
- name: OrderNoGenerator.orderProduct(),
1021
- product: await productRepo.findOneBy({ id: op.product.id }),
1022
- arrivalNotice,
1023
- creator: user
1024
- }
1025
- })
1026
- )
1027
-
1028
- debug('gan-created-order-products', createdOrderProducts)
1029
- await orderProductRepo.save(createdOrderProducts)
1030
- }
1031
-
1032
- export async function editArrivalNoticeProducts(
1033
- existingOrderProducts: (OrderProduct | OrderProductPatch)[],
1034
- user: User,
1035
- tx?: EntityManager
1036
- ): Promise<void> {
1037
- const orderProductRepo: Repository<OrderProduct> = tx?.getRepository(OrderProduct) || getRepository(OrderProduct)
1038
-
1039
- const updatedOrderProducts: OrderProduct[] = await Promise.all(
1040
- existingOrderProducts.map(async (op: OrderProduct) => {
1041
- return {
1042
- ...op,
1043
- status: ORDER_PRODUCT_STATUS.EDITED,
1044
- updater: user
1045
- }
1046
- })
1047
- )
1048
-
1049
- debug('gan-updated-order-products', updatedOrderProducts)
1050
- await orderProductRepo.save(updatedOrderProducts)
1051
- }
1052
-
1053
- function extractArrivalNotices(rawArrivalNotices): Partial<ArrivalNotice[]> {
1054
- return rawArrivalNotices.reduce((arrivalNotices, raw) => {
1055
- // discard the item that has no productId or productDetailId
1056
- if (!raw.productId || !raw.productDetailId) return
1057
-
1058
- const idx: number = arrivalNotices.findIndex(an => {
1059
- // consider these attributes if they are exist in "item"
1060
- const comparison = [
1061
- 'refNo2',
1062
- 'refNo3',
1063
- 'truckNo',
1064
- 'ownTransport',
1065
- 'container',
1066
- 'containerNo',
1067
- 'containerSize',
1068
- 'looseItem',
1069
- 'importCargo'
1070
- ]
1071
-
1072
- let a: any = {},
1073
- b: any = {}
1074
-
1075
- comparison.forEach(cc => {
1076
- if (raw[cc] !== null) {
1077
- a[cc] = raw[cc]
1078
- b[cc] = an[cc]
1079
- }
1080
- })
1081
-
1082
- a = JSON.stringify(Object.fromEntries(Object.entries(a).sort()))
1083
- b = JSON.stringify(Object.fromEntries(Object.entries(b).sort()))
1084
-
1085
- return an.refNo == raw.refNo && an.etaDate == raw.etaDate && a === b
1086
- })
1087
-
1088
- const product: Product = Object.assign(new Product(), { id: raw.productId, sku: raw.sku })
1089
- const orderProduct: Partial<OrderProduct> = {
1090
- product,
1091
- batchId: raw.batchId,
1092
- batchIdRef: raw.batchIdRef,
1093
- packingType: raw.packingType,
1094
- packingSize: raw.packingSize,
1095
- packQty: raw.packQty,
1096
- uomValue: raw.uomValue,
1097
- uom: raw.uom,
1098
- totalUomValue: raw.totalUomValue,
1099
- palletQty: raw.palletQty,
1100
- unitPrice: raw.unitPrice,
1101
- manufactureDate: raw.manufactureDate
1102
- }
1103
-
1104
- if (idx >= 0) {
1105
- const duplicateSkuIdx: number = arrivalNotices[idx].orderProducts.findIndex(
1106
- op =>
1107
- op.sku === raw.sku &&
1108
- op.packingType === raw.packingType &&
1109
- op.packingSize === raw.packingSize &&
1110
- op.batchId === raw.batchId
1111
- )
1112
-
1113
- if (duplicateSkuIdx >= 0) arrivalNotices[idx].orderProducts[duplicateSkuIdx].packQty += raw.packQty
1114
- else arrivalNotices[idx].orderProducts.push(orderProduct)
1115
- } else {
1116
- arrivalNotices.push({
1117
- refNo: raw.refNo,
1118
- refNo2: raw.refNo2,
1119
- refNo3: raw.refNo3,
1120
- etaDate: raw.etaDate,
1121
- truckNo: raw.truckNo,
1122
- ownTransport: raw.ownTransport,
1123
- container: raw.container,
1124
- containerNo: raw.containerNo,
1125
- containerSize: raw.containerSize,
1126
- importCargo: raw.importCargo,
1127
- looseItem: raw.looseItem,
1128
- orderProducts: [orderProduct]
1129
- })
1130
- }
1131
-
1132
- return arrivalNotices
1133
- }, [])
1134
- }
1135
-
1136
- function formRawArrivalNotices(arrivalNotice, errorMsg) {
1137
- let rawArrivalNotices = []
1138
- for (let i = 0, l = arrivalNotice.orderProducts.length; i < l; i++) {
1139
- let rawArrivalNotice = {
1140
- ...arrivalNotice,
1141
- ...arrivalNotice.orderProducts[i],
1142
- sku: arrivalNotice.orderProducts[i].product.sku,
1143
- errorMsg
1144
- }
1145
-
1146
- delete rawArrivalNotice.orderProducts
1147
- delete rawArrivalNotice.product
1148
-
1149
- rawArrivalNotices.push(rawArrivalNotice)
1150
- }
1151
- return rawArrivalNotices
1152
- }