@things-factory/sales-base 8.0.0-beta.1 → 8.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/package.json +13 -13
  2. package/server/constants/attachment-type.ts +0 -9
  3. package/server/constants/index.ts +0 -7
  4. package/server/constants/load-type.ts +0 -4
  5. package/server/constants/order.ts +0 -203
  6. package/server/constants/product-group-type.ts +0 -4
  7. package/server/constants/release-good.ts +0 -9
  8. package/server/constants/transfer-order-type.ts +0 -6
  9. package/server/constants/validation-error-code.ts +0 -3
  10. package/server/constants/vas-target-type.ts +0 -25
  11. package/server/controllers/ecommerce/ecommerce-controller.ts +0 -122
  12. package/server/controllers/ecommerce/index.ts +0 -2
  13. package/server/controllers/ecommerce/sellercraft-controller.ts +0 -182
  14. package/server/controllers/index.ts +0 -2
  15. package/server/controllers/order-controller.ts +0 -296
  16. package/server/errors/index.ts +0 -1
  17. package/server/errors/validation-error.ts +0 -25
  18. package/server/index.ts +0 -5
  19. package/server/migrations/index.ts +0 -9
  20. package/server/service/arrival-notice/arrival-notice-mutation.ts +0 -1152
  21. package/server/service/arrival-notice/arrival-notice-query.ts +0 -549
  22. package/server/service/arrival-notice/arrival-notice-types.ts +0 -310
  23. package/server/service/arrival-notice/arrival-notice.ts +0 -202
  24. package/server/service/arrival-notice/index.ts +0 -9
  25. package/server/service/claim/claim-mutation.ts +0 -308
  26. package/server/service/claim/claim-query.ts +0 -122
  27. package/server/service/claim/claim-types.ts +0 -130
  28. package/server/service/claim/claim.ts +0 -140
  29. package/server/service/claim/index.ts +0 -9
  30. package/server/service/claim-detail/claim-detail-mutation.ts +0 -102
  31. package/server/service/claim-detail/claim-detail-query.ts +0 -55
  32. package/server/service/claim-detail/claim-detail-types.ts +0 -47
  33. package/server/service/claim-detail/claim-detail.ts +0 -69
  34. package/server/service/claim-detail/index.ts +0 -9
  35. package/server/service/claim-order/claim-order-mutation.ts +0 -101
  36. package/server/service/claim-order/claim-order-query.ts +0 -47
  37. package/server/service/claim-order/claim-order-types.ts +0 -35
  38. package/server/service/claim-order/claim-order.ts +0 -81
  39. package/server/service/claim-order/index.ts +0 -9
  40. package/server/service/collection-order/collection-order-mutation.ts +0 -245
  41. package/server/service/collection-order/collection-order-query.ts +0 -97
  42. package/server/service/collection-order/collection-order-types.ts +0 -165
  43. package/server/service/collection-order/collection-order.ts +0 -135
  44. package/server/service/collection-order/index.ts +0 -9
  45. package/server/service/delivery-order/delivery-order-mutation.ts +0 -967
  46. package/server/service/delivery-order/delivery-order-query.ts +0 -631
  47. package/server/service/delivery-order/delivery-order-types.ts +0 -268
  48. package/server/service/delivery-order/delivery-order.ts +0 -258
  49. package/server/service/delivery-order/index.ts +0 -9
  50. package/server/service/draft-release-good/draft-release-good-mutation.ts +0 -765
  51. package/server/service/draft-release-good/draft-release-good-query.ts +0 -354
  52. package/server/service/draft-release-good/draft-release-good-type.ts +0 -261
  53. package/server/service/draft-release-good/draft-release-good.ts +0 -284
  54. package/server/service/draft-release-good/index.ts +0 -9
  55. package/server/service/goods-receival-note/goods-receival-note-mutation.ts +0 -129
  56. package/server/service/goods-receival-note/goods-receival-note-query.ts +0 -280
  57. package/server/service/goods-receival-note/goods-receival-note-types.ts +0 -105
  58. package/server/service/goods-receival-note/goods-receival-note.ts +0 -127
  59. package/server/service/goods-receival-note/index.ts +0 -9
  60. package/server/service/index.ts +0 -238
  61. package/server/service/inventory-check/index.ts +0 -9
  62. package/server/service/inventory-check/inventory-check-mutation.ts +0 -149
  63. package/server/service/inventory-check/inventory-check-query.ts +0 -48
  64. package/server/service/inventory-check/inventory-check-types.ts +0 -48
  65. package/server/service/inventory-check/inventory-check.ts +0 -90
  66. package/server/service/invoice/index.ts +0 -9
  67. package/server/service/invoice/invoice-mutation.ts +0 -95
  68. package/server/service/invoice/invoice-query.ts +0 -53
  69. package/server/service/invoice/invoice-types.ts +0 -279
  70. package/server/service/invoice/invoice.ts +0 -230
  71. package/server/service/invoice-product/index.ts +0 -9
  72. package/server/service/invoice-product/invoice-product-mutation.ts +0 -54
  73. package/server/service/invoice-product/invoice-product-query.ts +0 -54
  74. package/server/service/invoice-product/invoice-product-types.ts +0 -84
  75. package/server/service/invoice-product/invoice-product.ts +0 -92
  76. package/server/service/job-sheet/index.ts +0 -9
  77. package/server/service/job-sheet/job-sheet-mutation.ts +0 -92
  78. package/server/service/job-sheet/job-sheet-query.ts +0 -112
  79. package/server/service/job-sheet/job-sheet-types.ts +0 -78
  80. package/server/service/job-sheet/job-sheet.ts +0 -102
  81. package/server/service/manifest/index.ts +0 -6
  82. package/server/service/manifest/manifest-mutation.ts +0 -190
  83. package/server/service/manifest/manifest-query.ts +0 -149
  84. package/server/service/manifest/manifest-type.ts +0 -84
  85. package/server/service/manifest/manifest.ts +0 -114
  86. package/server/service/order-inventory/index.ts +0 -9
  87. package/server/service/order-inventory/order-inventory-mutation.ts +0 -54
  88. package/server/service/order-inventory/order-inventory-query.ts +0 -722
  89. package/server/service/order-inventory/order-inventory-types.ts +0 -238
  90. package/server/service/order-inventory/order-inventory.ts +0 -401
  91. package/server/service/order-product/index.ts +0 -9
  92. package/server/service/order-product/order-product-mutation.ts +0 -48
  93. package/server/service/order-product/order-product-query.ts +0 -89
  94. package/server/service/order-product/order-product-types.ts +0 -335
  95. package/server/service/order-product/order-product.ts +0 -362
  96. package/server/service/order-tote/index.ts +0 -9
  97. package/server/service/order-tote/order-tote-mutation.ts +0 -31
  98. package/server/service/order-tote/order-tote-query.ts +0 -112
  99. package/server/service/order-tote/order-tote-types.ts +0 -47
  100. package/server/service/order-tote/order-tote.ts +0 -73
  101. package/server/service/order-tote-item/index.ts +0 -9
  102. package/server/service/order-tote-item/order-tote-item-mutation.ts +0 -31
  103. package/server/service/order-tote-item/order-tote-item-query.ts +0 -82
  104. package/server/service/order-tote-item/order-tote-item-types.ts +0 -56
  105. package/server/service/order-tote-item/order-tote-item.ts +0 -72
  106. package/server/service/order-tote-seal/index.ts +0 -9
  107. package/server/service/order-tote-seal/order-tote-seal-mutation.ts +0 -31
  108. package/server/service/order-tote-seal/order-tote-seal-query.ts +0 -59
  109. package/server/service/order-tote-seal/order-tote-seal-types.ts +0 -41
  110. package/server/service/order-tote-seal/order-tote-seal.ts +0 -46
  111. package/server/service/order-vas/index.ts +0 -9
  112. package/server/service/order-vas/order-vas-mutation.ts +0 -20
  113. package/server/service/order-vas/order-vas-query.ts +0 -72
  114. package/server/service/order-vas/order-vas-types.ts +0 -159
  115. package/server/service/order-vas/order-vas.ts +0 -207
  116. package/server/service/others/index.ts +0 -5
  117. package/server/service/others/other-query.ts +0 -563
  118. package/server/service/others/other-types.ts +0 -115
  119. package/server/service/purchase-order/index.ts +0 -9
  120. package/server/service/purchase-order/purchase-order-mutation.ts +0 -458
  121. package/server/service/purchase-order/purchase-order-query.ts +0 -90
  122. package/server/service/purchase-order/purchase-order-types.ts +0 -154
  123. package/server/service/purchase-order/purchase-order.ts +0 -172
  124. package/server/service/purchase-order-other-charge/index.ts +0 -9
  125. package/server/service/purchase-order-other-charge/purchase-order-other-charge-mutation.ts +0 -31
  126. package/server/service/purchase-order-other-charge/purchase-order-other-charge-query.ts +0 -52
  127. package/server/service/purchase-order-other-charge/purchase-order-other-charge-types.ts +0 -44
  128. package/server/service/purchase-order-other-charge/purchase-order-other-charge.ts +0 -68
  129. package/server/service/release-good/index.ts +0 -9
  130. package/server/service/release-good/release-good-mutation.ts +0 -1686
  131. package/server/service/release-good/release-good-query.ts +0 -980
  132. package/server/service/release-good/release-good-types.ts +0 -662
  133. package/server/service/release-good/release-good.ts +0 -490
  134. package/server/service/retail-replenishment-order/index.ts +0 -9
  135. package/server/service/retail-replenishment-order/retail-replenishment-order-mutation.ts +0 -382
  136. package/server/service/retail-replenishment-order/retail-replenishment-order-query.ts +0 -54
  137. package/server/service/retail-replenishment-order/retail-replenishment-order-types.ts +0 -101
  138. package/server/service/retail-replenishment-order/retail-replenishment-order.ts +0 -115
  139. package/server/service/return-order/index.ts +0 -9
  140. package/server/service/return-order/return-order-mutation.ts +0 -516
  141. package/server/service/return-order/return-order-query.ts +0 -226
  142. package/server/service/return-order/return-order-types.ts +0 -196
  143. package/server/service/return-order/return-order.ts +0 -127
  144. package/server/service/reverse-kitting-order/index.ts +0 -9
  145. package/server/service/reverse-kitting-order/reverse-kitting-order-mutation.ts +0 -500
  146. package/server/service/reverse-kitting-order/reverse-kitting-order-query.ts +0 -197
  147. package/server/service/reverse-kitting-order/reverse-kitting-order-type.ts +0 -173
  148. package/server/service/reverse-kitting-order/reverse-kitting-order.ts +0 -121
  149. package/server/service/reverse-kitting-order-inventory/index.ts +0 -9
  150. package/server/service/reverse-kitting-order-inventory/reverse-kitting-order-inventory-mutation.ts +0 -129
  151. package/server/service/reverse-kitting-order-inventory/reverse-kitting-order-inventory-query.ts +0 -52
  152. package/server/service/reverse-kitting-order-inventory/reverse-kitting-order-inventory-type.ts +0 -95
  153. package/server/service/reverse-kitting-order-inventory/reverse-kitting-order-inventory.ts +0 -143
  154. package/server/service/shipping-order/index.ts +0 -9
  155. package/server/service/shipping-order/shipping-order-mutation.ts +0 -61
  156. package/server/service/shipping-order/shipping-order-query.ts +0 -61
  157. package/server/service/shipping-order/shipping-order-types.ts +0 -89
  158. package/server/service/shipping-order/shipping-order.ts +0 -129
  159. package/server/service/transfer-order/index.ts +0 -9
  160. package/server/service/transfer-order/transfer-order-mutation.ts +0 -309
  161. package/server/service/transfer-order/transfer-order-query.ts +0 -66
  162. package/server/service/transfer-order/transfer-order-types.ts +0 -97
  163. package/server/service/transfer-order/transfer-order.ts +0 -117
  164. package/server/service/vas/index.ts +0 -9
  165. package/server/service/vas/vas-mutation.ts +0 -106
  166. package/server/service/vas/vas-query.ts +0 -60
  167. package/server/service/vas/vas-types.ts +0 -71
  168. package/server/service/vas/vas.ts +0 -77
  169. package/server/service/vas-order/index.ts +0 -9
  170. package/server/service/vas-order/vas-order-mutation.ts +0 -259
  171. package/server/service/vas-order/vas-order-query.ts +0 -119
  172. package/server/service/vas-order/vas-order-types.ts +0 -49
  173. package/server/service/vas-order/vas-order.ts +0 -81
  174. package/server/utils/datetime-util.ts +0 -54
  175. package/server/utils/index.ts +0 -3
  176. package/server/utils/inventory-util.ts +0 -1155
  177. 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
- }