@things-factory/worksheet-base 4.3.0-alpha.1 → 4.3.0

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 (133) hide show
  1. package/dist-server/constants/index.js +1 -5
  2. package/dist-server/constants/index.js.map +1 -1
  3. package/dist-server/controllers/ecommerce/index.js +1 -5
  4. package/dist-server/controllers/ecommerce/index.js.map +1 -1
  5. package/dist-server/controllers/inbound/index.js +1 -5
  6. package/dist-server/controllers/inbound/index.js.map +1 -1
  7. package/dist-server/controllers/inbound/unloading-worksheet-controller.js +9 -3
  8. package/dist-server/controllers/inbound/unloading-worksheet-controller.js.map +1 -1
  9. package/dist-server/controllers/index.js +2 -5
  10. package/dist-server/controllers/index.js.map +1 -1
  11. package/dist-server/controllers/inspect/index.js +1 -5
  12. package/dist-server/controllers/inspect/index.js.map +1 -1
  13. package/dist-server/controllers/outbound/index.js +1 -5
  14. package/dist-server/controllers/outbound/index.js.map +1 -1
  15. package/dist-server/controllers/outbound/loading-worksheet-controller.js +47 -10
  16. package/dist-server/controllers/outbound/loading-worksheet-controller.js.map +1 -1
  17. package/dist-server/controllers/outbound/picking-worksheet-controller.js +142 -5
  18. package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
  19. package/dist-server/controllers/outbound/sorting-worksheet-controller.js +116 -20
  20. package/dist-server/controllers/outbound/sorting-worksheet-controller.js.map +1 -1
  21. package/dist-server/controllers/render-fm-grn.js +229 -0
  22. package/dist-server/controllers/render-fm-grn.js.map +1 -0
  23. package/dist-server/controllers/render-grn.js +18 -18
  24. package/dist-server/controllers/vas/index.js +1 -5
  25. package/dist-server/controllers/vas/index.js.map +1 -1
  26. package/dist-server/graphql/index.js +1 -5
  27. package/dist-server/graphql/index.js.map +1 -1
  28. package/dist-server/graphql/resolvers/index.js +1 -5
  29. package/dist-server/graphql/resolvers/index.js.map +1 -1
  30. package/dist-server/graphql/resolvers/worksheet/batch-picking-worksheet.js +14 -1
  31. package/dist-server/graphql/resolvers/worksheet/batch-picking-worksheet.js.map +1 -1
  32. package/dist-server/graphql/resolvers/worksheet/loading/loading.js +3 -10
  33. package/dist-server/graphql/resolvers/worksheet/loading/loading.js.map +1 -1
  34. package/dist-server/graphql/resolvers/worksheet/loading-worksheet.js +55 -21
  35. package/dist-server/graphql/resolvers/worksheet/loading-worksheet.js.map +1 -1
  36. package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js +1 -0
  37. package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js.map +1 -1
  38. package/dist-server/graphql/resolvers/worksheet/picking/complete-batch-picking.js +1 -1
  39. package/dist-server/graphql/resolvers/worksheet/picking/complete-batch-picking.js.map +1 -1
  40. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js +8 -6
  41. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js.map +1 -1
  42. package/dist-server/graphql/resolvers/worksheet/picking/index.js +2 -1
  43. package/dist-server/graphql/resolvers/worksheet/picking/index.js.map +1 -1
  44. package/dist-server/graphql/resolvers/worksheet/picking/picking.js +4 -4
  45. package/dist-server/graphql/resolvers/worksheet/picking/picking.js.map +1 -1
  46. package/dist-server/graphql/resolvers/worksheet/picking/scan-product-picking.js +4 -4
  47. package/dist-server/graphql/resolvers/worksheet/picking/scan-product-picking.js.map +1 -1
  48. package/dist-server/graphql/resolvers/worksheet/picking/seal-tote.js +15 -0
  49. package/dist-server/graphql/resolvers/worksheet/picking/seal-tote.js.map +1 -0
  50. package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js +10 -1
  51. package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js.map +1 -1
  52. package/dist-server/graphql/resolvers/worksheet/sorting/complete-order-sorting.js +11 -6
  53. package/dist-server/graphql/resolvers/worksheet/sorting/complete-order-sorting.js.map +1 -1
  54. package/dist-server/graphql/resolvers/worksheet/sorting/scan-product-sorting.js +4 -4
  55. package/dist-server/graphql/resolvers/worksheet/sorting/scan-product-sorting.js.map +1 -1
  56. package/dist-server/graphql/resolvers/worksheet/sorting/sorting-product.js +4 -4
  57. package/dist-server/graphql/resolvers/worksheet/sorting/sorting-product.js.map +1 -1
  58. package/dist-server/graphql/resolvers/worksheet/vas-transactions/index.js +1 -5
  59. package/dist-server/graphql/resolvers/worksheet/vas-transactions/index.js.map +1 -1
  60. package/dist-server/graphql/resolvers/worksheet/vas-transactions/interfaces/index.js +1 -5
  61. package/dist-server/graphql/resolvers/worksheet/vas-transactions/interfaces/index.js.map +1 -1
  62. package/dist-server/graphql/resolvers/worksheet/vas-transactions/relabeling/index.js +1 -5
  63. package/dist-server/graphql/resolvers/worksheet/vas-transactions/relabeling/index.js.map +1 -1
  64. package/dist-server/graphql/resolvers/worksheet/vas-transactions/repackaging/index.js +1 -5
  65. package/dist-server/graphql/resolvers/worksheet/vas-transactions/repackaging/index.js.map +1 -1
  66. package/dist-server/graphql/resolvers/worksheet/vas-transactions/repalletizing/index.js +1 -5
  67. package/dist-server/graphql/resolvers/worksheet/vas-transactions/repalletizing/index.js.map +1 -1
  68. package/dist-server/graphql/resolvers/worksheet/vas-transactions/unpacking/index.js +1 -5
  69. package/dist-server/graphql/resolvers/worksheet/vas-transactions/unpacking/index.js.map +1 -1
  70. package/dist-server/graphql/resolvers/worksheet/worksheet.js +2 -0
  71. package/dist-server/graphql/resolvers/worksheet/worksheet.js.map +1 -1
  72. package/dist-server/graphql/resolvers/worksheet/worksheets.js +17 -2
  73. package/dist-server/graphql/resolvers/worksheet/worksheets.js.map +1 -1
  74. package/dist-server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details-by-bulk.js +5 -3
  75. package/dist-server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details-by-bulk.js.map +1 -1
  76. package/dist-server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details.js +15 -4
  77. package/dist-server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details.js.map +1 -1
  78. package/dist-server/graphql/resolvers/worksheet-detail/generate-picking-worksheet-details.js +4 -1
  79. package/dist-server/graphql/resolvers/worksheet-detail/generate-picking-worksheet-details.js.map +1 -1
  80. package/dist-server/graphql/resolvers/worksheet-detail/generate-release-good-worksheet-details.js +6 -2
  81. package/dist-server/graphql/resolvers/worksheet-detail/generate-release-good-worksheet-details.js.map +1 -1
  82. package/dist-server/graphql/types/index.js +1 -5
  83. package/dist-server/graphql/types/index.js.map +1 -1
  84. package/dist-server/graphql/types/worksheet/index.js +10 -0
  85. package/dist-server/graphql/types/worksheet/index.js.map +1 -1
  86. package/dist-server/graphql/types/worksheet/loaded-worksheet-detail.js +1 -0
  87. package/dist-server/graphql/types/worksheet/loaded-worksheet-detail.js.map +1 -1
  88. package/dist-server/graphql/types/worksheet/worksheet-detail-info.js +2 -0
  89. package/dist-server/graphql/types/worksheet/worksheet-detail-info.js.map +1 -1
  90. package/dist-server/graphql/types/worksheet/worksheet-info.js +2 -0
  91. package/dist-server/graphql/types/worksheet/worksheet-info.js.map +1 -1
  92. package/dist-server/graphql/types/worksheet/worksheet.js +1 -0
  93. package/dist-server/graphql/types/worksheet/worksheet.js.map +1 -1
  94. package/dist-server/index.js +1 -5
  95. package/dist-server/index.js.map +1 -1
  96. package/dist-server/routes.js +4 -0
  97. package/dist-server/routes.js.map +1 -1
  98. package/dist-server/utils/index.js +1 -5
  99. package/dist-server/utils/index.js.map +1 -1
  100. package/package.json +17 -17
  101. package/server/controllers/inbound/unloading-worksheet-controller.ts +14 -3
  102. package/server/controllers/index.ts +1 -0
  103. package/server/controllers/outbound/loading-worksheet-controller.ts +83 -17
  104. package/server/controllers/outbound/picking-worksheet-controller.ts +178 -7
  105. package/server/controllers/outbound/sorting-worksheet-controller.ts +167 -27
  106. package/server/controllers/render-fm-grn.ts +266 -0
  107. package/server/controllers/render-grn.ts +18 -18
  108. package/server/graphql/resolvers/worksheet/batch-picking-worksheet.ts +14 -0
  109. package/server/graphql/resolvers/worksheet/loading/loading.ts +5 -12
  110. package/server/graphql/resolvers/worksheet/loading-worksheet.ts +66 -13
  111. package/server/graphql/resolvers/worksheet/packing-worksheet.ts +1 -1
  112. package/server/graphql/resolvers/worksheet/picking/complete-batch-picking.ts +1 -1
  113. package/server/graphql/resolvers/worksheet/picking/complete-picking.ts +13 -11
  114. package/server/graphql/resolvers/worksheet/picking/index.ts +3 -1
  115. package/server/graphql/resolvers/worksheet/picking/picking.ts +30 -4
  116. package/server/graphql/resolvers/worksheet/picking/scan-product-picking.ts +7 -4
  117. package/server/graphql/resolvers/worksheet/picking/seal-tote.ts +25 -0
  118. package/server/graphql/resolvers/worksheet/picking-worksheet.ts +13 -2
  119. package/server/graphql/resolvers/worksheet/sorting/complete-order-sorting.ts +13 -9
  120. package/server/graphql/resolvers/worksheet/sorting/scan-product-sorting.ts +5 -4
  121. package/server/graphql/resolvers/worksheet/sorting/sorting-product.ts +5 -4
  122. package/server/graphql/resolvers/worksheet/worksheet.ts +2 -0
  123. package/server/graphql/resolvers/worksheet/worksheets.ts +26 -2
  124. package/server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details-by-bulk.ts +12 -3
  125. package/server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details.ts +22 -7
  126. package/server/graphql/resolvers/worksheet-detail/generate-picking-worksheet-details.ts +6 -2
  127. package/server/graphql/resolvers/worksheet-detail/generate-release-good-worksheet-details.ts +7 -1
  128. package/server/graphql/types/worksheet/index.ts +10 -0
  129. package/server/graphql/types/worksheet/loaded-worksheet-detail.ts +1 -0
  130. package/server/graphql/types/worksheet/worksheet-detail-info.ts +2 -0
  131. package/server/graphql/types/worksheet/worksheet-info.ts +2 -0
  132. package/server/graphql/types/worksheet/worksheet.ts +1 -0
  133. package/server/routes.ts +5 -0
@@ -0,0 +1,266 @@
1
+ import FormData from 'form-data'
2
+ import _ from 'lodash'
3
+ import fetch from 'node-fetch'
4
+ import { getRepository, IsNull, Not } from 'typeorm'
5
+
6
+ import { Attachment, STORAGE } from '@things-factory/attachment-base'
7
+ import { Partner } from '@things-factory/auth-base'
8
+ import { Bizplace, ContactPoint } from '@things-factory/biz-base'
9
+ import { config } from '@things-factory/env'
10
+ import { ArrivalNotice, GoodsReceivalNote, ORDER_STATUS, OrderProduct } from '@things-factory/sales-base'
11
+ import { Domain } from '@things-factory/shell'
12
+ import { InventoryItem, ReducedInventoryHistory } from '@things-factory/warehouse-base'
13
+
14
+ import { TEMPLATE_TYPE, WORKSHEET_TYPE } from '../constants'
15
+ import { Worksheet } from '../entities'
16
+ import { DateTimeConverter } from '../utils/datetime-util'
17
+
18
+ const REPORT_API_URL = config.get('reportApiUrl', 'http://localhost:8888/rest/report/show_html')
19
+
20
+ export async function renderFmGRN({ grnNo, timezoneOffSet }, context: any) {
21
+ // 1. find domain
22
+ const domain: Domain = await getRepository(Domain).findOne({
23
+ where: { id: context.state.domain.id }
24
+ })
25
+
26
+ // 2. find grn
27
+ const foundGRN: GoodsReceivalNote = await getRepository(GoodsReceivalNote).findOne({
28
+ where: { domain, name: grnNo },
29
+ relations: ['domain', 'bizplace', 'bizplace.domain', 'bizplace.company', 'arrivalNotice']
30
+ })
31
+
32
+ // 3. find GAN
33
+ const foundGAN: ArrivalNotice = foundGRN.arrivalNotice
34
+ const ownRefNo = foundGAN.refNo
35
+
36
+ const foundInventoryItem: InventoryItem[] = await getRepository(InventoryItem).query(
37
+ `select row_number() over (partition by p.sku) as "seq",p.sku,p.brand_sku, ii.serial_number from inventory_items ii left join products p on ii.product_id = p.id where inbound_order_id = '${foundGAN.id}' group by p.sku,ii.serial_number,p.brand_sku`
38
+ )
39
+
40
+ // 4. find customer bizplace
41
+ const partnerBiz: Bizplace = foundGRN.bizplace
42
+
43
+ const partnerDomain: Partner = await getRepository(Partner).findOne({
44
+ where: { partnerDomain: partnerBiz.domain, domain },
45
+ relations: ['domain']
46
+ })
47
+
48
+ const domainOwner: Domain = partnerDomain.domain
49
+ const domainBizplace: Bizplace = await getRepository(Bizplace).findOne({
50
+ where: { domain: domainOwner },
51
+ relations: ['company']
52
+ })
53
+
54
+ const qbReducedInventory = getRepository(ReducedInventoryHistory)
55
+ .createQueryBuilder('ivh')
56
+ .select('product_id', 'productId')
57
+ .addSelect('batch_id', 'batchId')
58
+ .addSelect('reusable_pallet_id', 'reusablePalletId')
59
+ .addSelect('packing_type', 'packingType')
60
+ .addSelect('sum(qty)', 'qty')
61
+ .addSelect('sum(uom_value)', 'uomValue')
62
+ .addSelect('uom', 'uom')
63
+ .addSelect('expiration_date', 'expiryDate')
64
+ .addSelect('count(distinct pallet_id)', 'pallet')
65
+ .addSelect(`string_agg(distinct pallet_id::varchar,', ' order by pallet_id::varchar)`, 'palletId')
66
+ .where('ivh.domain_id = :domainId', { domainId: domain.id })
67
+ .andWhere('ivh.ref_order_id = :refOrderId', { refOrderId: foundGAN.id })
68
+ .andWhere(`ivh.transaction_type = 'UNLOADING'`)
69
+ .groupBy('reusable_pallet_id')
70
+ .addGroupBy('product_id')
71
+ .addGroupBy('batch_id')
72
+ .addGroupBy('packing_type')
73
+ .addGroupBy('uom')
74
+ .addGroupBy('expiration_date')
75
+ .getRawMany()
76
+
77
+ // 5. find domain contact point
78
+ const foundCP: ContactPoint = await getRepository(ContactPoint).findOne({
79
+ where: { domain, bizplace: domainBizplace }
80
+ })
81
+
82
+ // 5. find domain contact point
83
+ const foundPartnerCP: ContactPoint = await getRepository(ContactPoint).findOne({
84
+ where: { domain, bizplace: partnerBiz }
85
+ })
86
+
87
+ // 6. find unloading worksheet
88
+ const foundWS: Worksheet = await getRepository(Worksheet).findOne({
89
+ where: { domain, arrivalNotice: foundGAN, type: WORKSHEET_TYPE.UNLOADING, status: ORDER_STATUS.DONE },
90
+ relations: ['worksheetDetails', 'updater']
91
+ })
92
+
93
+ // find putaway worksheet
94
+ const foundPutawayWS: Worksheet = await getRepository(Worksheet).findOne({
95
+ where: { domain, arrivalNotice: foundGAN, type: WORKSHEET_TYPE.PUTAWAY, status: ORDER_STATUS.DONE },
96
+ relations: ['worksheetDetails', 'updater']
97
+ })
98
+
99
+ const targetProducts: OrderProduct[] = await getRepository(OrderProduct).find({
100
+ where: { domain, arrivalNotice: foundGAN, actualPalletQty: Not(IsNull()), actualPackQty: Not(IsNull()) },
101
+ relations: ['product']
102
+ })
103
+
104
+ // 7. find grn template based on category
105
+ const foundTemplate: Attachment = await getRepository(Attachment).findOne({
106
+ where: { domain, category: TEMPLATE_TYPE.GRN_TEMPLATE }
107
+ })
108
+
109
+ // 8. find grn logo
110
+ const foundLogo: Attachment = await getRepository(Attachment).findOne({
111
+ where: {
112
+ domain,
113
+ category: TEMPLATE_TYPE.LOGO
114
+ }
115
+ })
116
+
117
+ // 9. find signature
118
+ const foundSignature: Attachment = await getRepository(Attachment).findOne({
119
+ where: {
120
+ domain,
121
+ category: TEMPLATE_TYPE.SIGNATURE
122
+ }
123
+ })
124
+
125
+ const foundCop: Attachment = await getRepository(Attachment).findOne({
126
+ where: {
127
+ domain,
128
+ category: TEMPLATE_TYPE.COP
129
+ }
130
+ })
131
+
132
+ const inboundInventories: any[] = await qbReducedInventory
133
+
134
+ const template = await STORAGE.readFile(foundTemplate.path, 'utf-8')
135
+
136
+ let logo = null
137
+ if (foundLogo?.path) {
138
+ logo = 'data:' + foundLogo.mimetype + ';base64,' + (await STORAGE.readFile(foundLogo.path, 'base64'))
139
+ }
140
+
141
+ let signature = null
142
+ if (foundSignature?.path) {
143
+ signature = 'data:' + foundSignature.mimetype + ';base64,' + (await STORAGE.readFile(foundSignature.path, 'base64'))
144
+ }
145
+
146
+ let cop = null
147
+ if (foundCop?.path) {
148
+ cop = 'data:' + foundSignature.mimetype + ';base64,' + (await STORAGE.readFile(foundCop.path, 'base64'))
149
+ }
150
+
151
+ const filterInventoryItem = _.groupBy(foundInventoryItem, i => i.sku)
152
+
153
+ const tempIndexArr = []
154
+
155
+ const tempTotalQuantity = []
156
+
157
+ Object.keys(filterInventoryItem).forEach(k => {
158
+ const tempIndex = foundInventoryItem.findIndex(i => {
159
+ return i.sku == k
160
+ })
161
+
162
+ tempIndexArr.push(tempIndex)
163
+ })
164
+
165
+ Object.values(filterInventoryItem).forEach(k => {
166
+ const tempQuantity = k.length
167
+
168
+ tempTotalQuantity.push(tempQuantity)
169
+ })
170
+
171
+ tempIndexArr.forEach((t, index) => {
172
+ if (t >= 0) foundInventoryItem[t].totalQuantity = tempTotalQuantity[index]
173
+ })
174
+
175
+ const data = {
176
+ logo_url: logo,
177
+ sign_url: signature,
178
+ cop_url: cop,
179
+ customer_biz: partnerBiz.name,
180
+ customer_address: partnerBiz.address,
181
+ company_domain: domainBizplace.company.name,
182
+ company_phone: foundCP.phone,
183
+ company_email: foundCP.email,
184
+ company_brn: domainBizplace.company.brn,
185
+ company_address: domainBizplace.company.address,
186
+ warehouse_address: foundCP.address,
187
+ warehouse_address2: foundCP.address2,
188
+ warehouse_postcode: foundCP.postCode,
189
+ warehouse_city: foundCP.city,
190
+ warehouse_state: foundCP.state,
191
+ warehouse_phone: foundCP.phone,
192
+ warehouse_fax: foundCP.fax,
193
+ warehouse_email: foundCP.email,
194
+ order_no: foundGRN.name,
195
+ gan_no: foundGAN.name,
196
+ gan_accepted_at: foundGAN.acceptedAt ? DateTimeConverter.datetime(foundGAN.acceptedAt, timezoneOffSet) : '',
197
+ unload_date: DateTimeConverter.date(foundWS.endedAt),
198
+ ref_no: ownRefNo ? `${foundGAN.name} / ${foundGAN.refNo}` : `${foundGAN.name}`,
199
+ ref_no_only: ownRefNo ? ` ${foundGAN.refNo}` : '',
200
+ ref_no1: foundGAN.refNo2 ? `${foundGAN.refNo2}` : '',
201
+ ref_no2: foundGAN.refNo3 ? `${foundGAN.refNo3}` : '',
202
+ received_date: DateTimeConverter.date(foundWS.endedAt),
203
+ truck_no: foundGAN.truckNo || '',
204
+ container_no: foundGAN.containerNo || '',
205
+ container_size: foundGAN.containerSize || '',
206
+ delivery_order_no: foundGAN.deliveryOrderNo ? foundGAN.deliveryOrderNo : '',
207
+ account_no: foundPartnerCP ? foundPartnerCP.accountNo : '',
208
+ unloaded_by: foundWS ? foundWS.updater.name : '',
209
+ putaway_by: foundPutawayWS ? foundPutawayWS.updater.name : '',
210
+ product_list: targetProducts
211
+ .reduce((acc, item) => {
212
+ acc.push(
213
+ ...inboundInventories
214
+ .filter(
215
+ ih =>
216
+ ih.productId == item.product.id &&
217
+ ih.batchId == item.batchId &&
218
+ ih.packingType == item.packingType &&
219
+ ih.uom == item.uom
220
+ )
221
+ .map(unloadInvHistory => {
222
+ return {
223
+ product_sku: `${item.product.sku}`,
224
+ product_brand_sku: `${item.product.brandSku}`,
225
+ product_name: `${item.product.name}(${item.product.description})`,
226
+ product_desc: item.product.description,
227
+ product_nameOnly: item.product.name,
228
+ product_type: item.packingType,
229
+ product_size: item.packingSize,
230
+ product_batch: item.batchId,
231
+ batch_id_ref: item?.batchIdRef ? item.batchIdRef : '',
232
+ pallet_qty: item.actualPalletQty,
233
+ product_qty: unloadInvHistory.qty || item.actualPackQty,
234
+ product_pack_qty: item.packQty,
235
+ descrepancy_qty: (unloadInvHistory.qty || item.actualPackQty) - item.packQty,
236
+ product_unit_uom_value: `${Math.round(item.uomValue * 100) / 100}`,
237
+ product_total_uom_value: `${
238
+ Math.round((unloadInvHistory.uomValue || item.uomValue * item.actualPackQty) * 100) / 100
239
+ }`,
240
+ product_uom: `${unloadInvHistory.uom || item.uom}`,
241
+ product_gross_weight: item.product.grossWeight || null,
242
+ unit_price: item.unitPrice || null,
243
+ expiry_date: unloadInvHistory.expiryDate && unloadInvHistory.expiryDate != '' ? new Date(unloadInvHistory.expiryDate).toISOString().split('T')[0] : '',
244
+ manufacture_date: item.manufactureDate,
245
+ reusable_pallet_id: unloadInvHistory.reusablePalletId || '',
246
+ remark: (item.remark ? item.remark : '') + (item.issue ? ' [Issue]: ' + item.issue : '')
247
+ }
248
+ })
249
+ )
250
+ return acc
251
+ }, [])
252
+ .map((item, idx) => ({ list_no: idx + 1, ...item })),
253
+ serialNumber: foundInventoryItem
254
+ }
255
+
256
+ const formData = new FormData()
257
+ formData.append('template', template)
258
+ formData.append('jsonString', JSON.stringify(data))
259
+
260
+ const response = await fetch(REPORT_API_URL, {
261
+ method: 'POST',
262
+ body: formData
263
+ })
264
+
265
+ return await response.text()
266
+ }
@@ -52,25 +52,25 @@ export async function renderGRN({ grnNo, timezoneOffSet }, context: any) {
52
52
  })
53
53
 
54
54
  const qbReducedInventory = getRepository(ReducedInventoryHistory)
55
- .createQueryBuilder(`ivh`)
56
- .select(`product_id`, `productId`)
57
- .addSelect(`batch_id`, `batchId`)
58
- .addSelect(`reusable_pallet_id`, `reusablePalletId`)
59
- .addSelect(`packing_type`, `packingType`)
60
- .addSelect(`sum(qty)`, `qty`)
61
- .addSelect(`sum(uom_value)`, `uomValue`)
62
- .addSelect(`uom`, `uom`)
63
- .addSelect(`count(distinct pallet_id)`, `pallet`)
64
- .addSelect(`string_agg(distinct expiration_date::varchar,', ' order by expiration_date::varchar)`, `expiryDate`)
65
- .addSelect(`string_agg(distinct pallet_id::varchar,', ' order by pallet_id::varchar)`, `palletId`)
66
- .where(`ivh.domain_id = :domainId`, { domainId: domain.id })
67
- .andWhere(`ivh.ref_order_id = :refOrderId`, { refOrderId: foundGAN.id })
55
+ .createQueryBuilder('ivh')
56
+ .select('product_id', 'productId')
57
+ .addSelect('batch_id', 'batchId')
58
+ .addSelect('reusable_pallet_id', 'reusablePalletId')
59
+ .addSelect('packing_type', 'packingType')
60
+ .addSelect('sum(qty)', 'qty')
61
+ .addSelect('sum(uom_value)', 'uomValue')
62
+ .addSelect('uom', 'uom')
63
+ .addSelect('count(distinct pallet_id)', 'pallet')
64
+ .addSelect(`string_agg(distinct expiration_date::varchar,', ' order by expiration_date::varchar)`, 'expiryDate')
65
+ .addSelect(`string_agg(distinct pallet_id::varchar,', ' order by pallet_id::varchar)`, 'palletId')
66
+ .where('ivh.domain_id = :domainId', { domainId: domain.id })
67
+ .andWhere('ivh.ref_order_id = :refOrderId', { refOrderId: foundGAN.id })
68
68
  .andWhere(`ivh.transaction_type = 'UNLOADING'`)
69
- .groupBy(`reusable_pallet_id`)
70
- .addGroupBy(`product_id`)
71
- .addGroupBy(`batch_id`)
72
- .addGroupBy(`packing_type`)
73
- .addGroupBy(`uom`)
69
+ .groupBy('reusable_pallet_id')
70
+ .addGroupBy('product_id')
71
+ .addGroupBy('batch_id')
72
+ .addGroupBy('packing_type')
73
+ .addGroupBy('uom')
74
74
  .getRawMany()
75
75
 
76
76
  // 5. find domain contact point
@@ -3,6 +3,7 @@ import { getRepository, SelectQueryBuilder } from 'typeorm'
3
3
  import { ORDER_INVENTORY_STATUS } from '@things-factory/sales-base'
4
4
  import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../../constants'
5
5
  import { Worksheet, WorksheetDetail } from '../../../entities'
6
+ import { InventoryChange } from '@things-factory/warehouse-base'
6
7
 
7
8
  export const batchPickingWorksheetResolver = {
8
9
  async batchPickingWorksheet(_: any, { taskNo, locationSortingRules }, context: any) {
@@ -42,6 +43,7 @@ export const batchPickingWorksheetResolver = {
42
43
  .addSelect('LOC.column', 'column')
43
44
  .addSelect('LOC.shelf', 'shelf')
44
45
  .addSelect('BIN_LOC.name', 'binLocationName')
46
+ .addSelect('WSD.status', 'status')
45
47
  .leftJoin('WSD.targetInventory', 'T_INV')
46
48
  .leftJoin('T_INV.inventory', 'INV')
47
49
  .leftJoin('T_INV.product', 'PROD')
@@ -70,6 +72,7 @@ export const batchPickingWorksheetResolver = {
70
72
  .addGroupBy('LOC.column')
71
73
  .addGroupBy('LOC.row')
72
74
  .addGroupBy('LOC.shelf')
75
+ .addGroupBy('WSD.status')
73
76
 
74
77
  if (locationSortingRules?.length > 0) {
75
78
  locationSortingRules.forEach((rule: { name: string; desc: boolean }) => {
@@ -86,6 +89,15 @@ export const batchPickingWorksheetResolver = {
86
89
  partnerDomainId: worksheet.bizplace?.domain.id
87
90
  },
88
91
  worksheetDetailInfos: items.map(async (item: any) => {
92
+ const inventoryChangesCount: number = await getRepository(InventoryChange).count({
93
+ where: {
94
+ inventory: item.inventoryId,
95
+ status: 'PENDING',
96
+ transactionType: 'MISSING'
97
+ },
98
+ relations: ['inventory', 'product']
99
+ })
100
+
89
101
  return {
90
102
  palletId: item?.palletId,
91
103
  cartonId: item?.cartonId,
@@ -98,6 +110,8 @@ export const batchPickingWorksheetResolver = {
98
110
  },
99
111
  qty: item?.qty,
100
112
  releaseQty: item.releaseQty,
113
+ hasMissingInventoryChanges: inventoryChangesCount > 0 ? true : false,
114
+ status: item.status,
101
115
  pickedQty: item.pickedQty,
102
116
  packingType: item?.packingType,
103
117
  packingSize: item?.packingSize,
@@ -9,7 +9,7 @@ import { WorksheetDetail } from '../../../../entities'
9
9
  export const loadingResolver = {
10
10
  async loading(_: any, { loadedWorksheetDetails, releaseGoodNo, orderInfo }, context: any) {
11
11
  const { tx, domain, user }: { tx: EntityManager; domain: Domain; user: User } = context.state
12
- await loading(tx, domain, user, loadedWorksheetDetails, releaseGoodNo)
12
+ const worksheetDetails = await loading(tx, domain, user, loadedWorksheetDetails, releaseGoodNo)
13
13
  const worksheetController: WorksheetController = new WorksheetController(tx, domain, user)
14
14
  const releaseGood: ReleaseGood = await worksheetController.findRefOrder(
15
15
  ReleaseGood,
@@ -18,14 +18,7 @@ export const loadingResolver = {
18
18
  )
19
19
 
20
20
  const loadingWorksheetController: LoadingWorksheetController = new LoadingWorksheetController(tx, domain, user)
21
- let targetInventories: OrderInventory[] = []
22
- for (let worksheetDetail of loadedWorksheetDetails) {
23
- worksheetDetail = await loadingWorksheetController.findWorksheetDetailByName(worksheetDetail.name, [
24
- 'targetInventory'
25
- ])
26
- const targetInventory = worksheetDetail.targetInventory
27
- targetInventories.push(targetInventory)
28
- }
21
+ let targetInventories: OrderInventory[] = worksheetDetails.map(itm => itm.targetInventory)
29
22
 
30
23
  const bizplace: Bizplace = releaseGood.bizplace
31
24
  orderInfo = {
@@ -41,9 +34,9 @@ export async function loading(
41
34
  tx: EntityManager,
42
35
  domain: Domain,
43
36
  user: User,
44
- worksheetDetails: Partial<WorksheetDetail & { loadedQty: number }>[],
37
+ worksheetDetails: Partial<WorksheetDetail & { loadedQty: number } & { toteName: string }>[],
45
38
  releaseGoodNo: string
46
- ): Promise<void> {
39
+ ): Promise<any> {
47
40
  const worksheetController: LoadingWorksheetController = new LoadingWorksheetController(tx, domain, user)
48
- await worksheetController.loading(releaseGoodNo, worksheetDetails)
41
+ return await worksheetController.loading(releaseGoodNo, worksheetDetails)
49
42
  }
@@ -1,6 +1,13 @@
1
1
  import { Equal, getRepository, In, Not, SelectQueryBuilder } from 'typeorm'
2
2
 
3
- import { ORDER_STATUS, ORDER_INVENTORY_STATUS, OrderInventory, ReleaseGood } from '@things-factory/sales-base'
3
+ import {
4
+ ORDER_STATUS,
5
+ ORDER_INVENTORY_STATUS,
6
+ OrderInventory,
7
+ ReleaseGood,
8
+ OrderTote,
9
+ OrderToteItem
10
+ } from '@things-factory/sales-base'
4
11
  import { Domain } from '@things-factory/shell'
5
12
  import { Inventory, Location } from '@things-factory/warehouse-base'
6
13
 
@@ -27,7 +34,9 @@ export const loadingWorksheetResolver = {
27
34
  .innerJoinAndSelect('releaseGood.bizplace', 'bizplace')
28
35
  .innerJoinAndSelect('bizplace.domain', 'domain')
29
36
  .where('orderInventory.domain_id = :domainId', { domainId: domain.id })
30
- .andWhere('orderInventory.status IN (:...orderInventoryStatus)', { orderInventoryStatus: [ORDER_INVENTORY_STATUS.LOADING, ORDER_INVENTORY_STATUS.LOADED] })
37
+ .andWhere('orderInventory.status IN (:...orderInventoryStatus)', {
38
+ orderInventoryStatus: [ORDER_INVENTORY_STATUS.LOADING, ORDER_INVENTORY_STATUS.LOADED]
39
+ })
31
40
  .andWhere('orderInventory.bin_location_id = :locationId', { locationId: binLocation.id })
32
41
  .andWhere('releaseGood.status = :status', { status: ORDER_STATUS.LOADING })
33
42
 
@@ -41,6 +50,10 @@ export const loadingWorksheetResolver = {
41
50
 
42
51
  if (!releaseGood) throw new Error(`Release good doesn't exists.`)
43
52
 
53
+ let [orderTotes, orderTotesTotal]: OrderTote = await getRepository(OrderTote).findAndCount({
54
+ where: { releaseGood: releaseGood.id }
55
+ })
56
+
44
57
  const foundWorksheet: Worksheet = await fetchExecutingWorksheet(
45
58
  domain,
46
59
  releaseGood.bizplace,
@@ -48,7 +61,7 @@ export const loadingWorksheetResolver = {
48
61
  WORKSHEET_TYPE.LOADING,
49
62
  releaseGood
50
63
  )
51
- const foundWSD: WorksheetDetail[] = await getRepository(WorksheetDetail).find({
64
+ let foundWSD: any[] = await getRepository(WorksheetDetail).find({
52
65
  where: {
53
66
  domain,
54
67
  worksheet: foundWorksheet,
@@ -57,21 +70,50 @@ export const loadingWorksheetResolver = {
57
70
  },
58
71
  relations: [
59
72
  'targetInventory',
73
+ 'targetInventory.orderProduct',
60
74
  'targetInventory.inventory',
61
75
  'targetInventory.inventory.location',
62
76
  'targetInventory.inventory.product'
63
77
  ]
64
78
  })
65
79
 
66
- return {
67
- worksheetInfo: {
68
- releaseGood,
69
- bizplaceName: releaseGood.bizplace.name,
70
- startedAt: foundWorksheet.startedAt,
71
- refNo: releaseGood.refNo,
72
- ownCollection: releaseGood.ownTransport
73
- },
74
- worksheetDetailInfos: foundWSD.map(async (loadingWSD: WorksheetDetail) => {
80
+ if (orderTotesTotal > 0) {
81
+ let [toteItems, toteItemsTotal]: OrderToteItem = await getRepository(OrderToteItem).findAndCount({
82
+ where: { orderTote: In(orderTotes.map(itm => itm.id)) },
83
+ relations: ['orderTote', 'orderInventory']
84
+ })
85
+
86
+ let toteWsd = []
87
+
88
+ for (let i = 0; i < toteItemsTotal; i++) {
89
+ let wsdIndex = foundWSD.findIndex(
90
+ itm => !itm?.toteName && itm.targetInventory.id == toteItems[i].orderInventory.id
91
+ )
92
+
93
+ if (wsdIndex >= 0) {
94
+ let filterWSD: any = JSON.parse(JSON.stringify(foundWSD[wsdIndex]))
95
+ let uomValue =
96
+ Math.round((filterWSD.targetInventory.releaseUomValue / filterWSD.targetInventory.releaseQty) * 100) / 100
97
+
98
+ foundWSD[wsdIndex].targetInventory.releaseQty -= toteItems[i].qty
99
+ foundWSD[wsdIndex].targetInventory.pickedQty -= toteItems[i].qty
100
+ foundWSD[wsdIndex].targetInventory.releaseUomValue = foundWSD[wsdIndex].targetInventory.releaseQty * uomValue
101
+
102
+ filterWSD.targetInventory.releaseQty = toteItems[i].qty
103
+ filterWSD.targetInventory.pickedQty = toteItems[i].qty
104
+ filterWSD.targetInventory.releaseUomValue = toteItems[i].qty * uomValue
105
+ filterWSD.toteName = toteItems[i].orderTote.name
106
+ toteWsd.push(filterWSD)
107
+ }
108
+ }
109
+
110
+ foundWSD = foundWSD.concat(toteWsd)
111
+ foundWSD.sort((a, b) => (a.toteName > b.toteName ? 1 : -1))
112
+ }
113
+
114
+ let worksheetDetailInfos = foundWSD
115
+ .filter(itm => itm.targetInventory.releaseQty > 0)
116
+ .map((loadingWSD: any) => {
75
117
  const targetInventory: OrderInventory = loadingWSD.targetInventory
76
118
  const inventory: Inventory = targetInventory.inventory
77
119
  return {
@@ -87,9 +129,20 @@ export const loadingWorksheetResolver = {
87
129
  targetName: targetInventory.name,
88
130
  packingType: inventory.packingType,
89
131
  packingSize: inventory.packingSize,
90
- inventory: targetInventory.inventory
132
+ inventory: targetInventory.inventory,
133
+ toteName: loadingWSD.toteName
91
134
  }
92
135
  })
136
+
137
+ return {
138
+ worksheetInfo: {
139
+ releaseGood,
140
+ bizplaceName: releaseGood.bizplace.name,
141
+ startedAt: foundWorksheet.startedAt,
142
+ refNo: releaseGood.refNo,
143
+ ownCollection: releaseGood.ownTransport
144
+ },
145
+ worksheetDetailInfos
93
146
  }
94
147
  }
95
148
  }
@@ -11,7 +11,6 @@ import {
11
11
  import { ORDER_INVENTORY_STATUS, ORDER_STATUS, OrderInventory, ReleaseGood } from '@things-factory/sales-base'
12
12
  import { Domain } from '@things-factory/shell'
13
13
  import { Inventory, Location } from '@things-factory/warehouse-base'
14
- import { ProductDetail } from '@things-factory/product-base'
15
14
 
16
15
  import { WORKSHEET_TYPE } from '../../../constants'
17
16
  import { SellercraftController } from '../../../controllers'
@@ -167,6 +166,7 @@ export const packingWorksheetResolver = {
167
166
  shippingProvider: shippingProvider ? shippingProvider : '',
168
167
  trackingNo: trackingNo ? trackingNo : '',
169
168
  airwayBill: releaseGood?.airwayBill,
169
+ checkedRemarkBy: releaseGood?.checkedRemarkBy,
170
170
  invoice: releaseGood?.invoice,
171
171
  platform: marketplaceOrder ? marketplaceOrder.marketplaceStore.platform : 'operato',
172
172
  marketplaceStoreId: marketplaceOrder ? marketplaceOrder.marketplaceStore.id : '',
@@ -42,7 +42,7 @@ export async function completeBatchPicking(
42
42
  const worksheet = await pickingWSCtrl.completeBatchPicking(taskNo)
43
43
 
44
44
  const worksheetDetails: WorksheetDetail[] = worksheet.worksheetDetails
45
- const targetInventories: OrderInventory[] = worksheetDetails.map((wsd: WorksheetDetail) => wsd.targetInventory)
45
+ const targetInventories: OrderInventory[] = worksheetDetails.filter(wsd=>wsd.status != 'MISSING').map((wsd: WorksheetDetail) => wsd.targetInventory)
46
46
 
47
47
  const sellercraft: Sellercraft = await tx
48
48
  .getRepository(Sellercraft)
@@ -248,18 +248,20 @@ export async function completePicking(
248
248
  })
249
249
 
250
250
  if (!existLoadingWorksheet && !releaseGood.courierOption && !releaseGood.packingOption) {
251
- const loadingWSCtrl: LoadingWorksheetController = new LoadingWorksheetController(tx, domain, user)
252
- let loadingWorksheet: Worksheet = await loadingWSCtrl.generateLoadingWorksheet(
253
- releaseGoodNo,
254
- pickedTargetInventories
255
- )
256
-
257
- if (!loadingWorksheet.worksheetDetails?.length) {
258
- loadingWorksheet = await pickingWSCtrl.findWorksheetById(loadingWorksheet.id)
251
+ if(pickedTargetInventories.length>0){
252
+ const loadingWSCtrl: LoadingWorksheetController = new LoadingWorksheetController(tx, domain, user)
253
+ let loadingWorksheet: Worksheet = await loadingWSCtrl.generateLoadingWorksheet(
254
+ releaseGoodNo,
255
+ pickedTargetInventories
256
+ )
257
+
258
+ if (!loadingWorksheet.worksheetDetails?.length) {
259
+ loadingWorksheet = await pickingWSCtrl.findWorksheetById(loadingWorksheet.id)
260
+ }
261
+
262
+ const loadingWorksheetDetails: WorksheetDetail[] = loadingWorksheet.worksheetDetails
263
+ await loadingWSCtrl.activateLoading(loadingWorksheet.name, loadingWorksheetDetails)
259
264
  }
260
-
261
- const loadingWorksheetDetails: WorksheetDetail[] = loadingWorksheet.worksheetDetails
262
- await loadingWSCtrl.activateLoading(loadingWorksheet.name, loadingWorksheetDetails)
263
265
  } else {
264
266
  const loadingWSCtrl: LoadingWorksheetController = new LoadingWorksheetController(tx, domain, user)
265
267
  let loadingWorksheet: Worksheet = await loadingWSCtrl.updateLoadingWorksheet(
@@ -11,6 +11,7 @@ import { scanProductPickingResolver } from './scan-product-picking'
11
11
  import { scanProductBatchPickingResolver } from './scan-product-batch-picking'
12
12
  import { undoPickingAssigmentResolver } from './undo-picking-assignment'
13
13
  import { undoSerialNumberPickingResolver } from './undo-serial-number-picking'
14
+ import { sealToteResolver } from './seal-tote'
14
15
 
15
16
  export const Mutations = {
16
17
  ...assignPickingInventoriesResolver,
@@ -25,5 +26,6 @@ export const Mutations = {
25
26
  ...completeBatchPickingResolver,
26
27
  ...assignPickingWorkerResolver,
27
28
  ...fetchAndAssignPickingTaskResolver,
28
- ...undoSerialNumberPickingResolver
29
+ ...undoSerialNumberPickingResolver,
30
+ ...sealToteResolver
29
31
  }
@@ -4,9 +4,25 @@ import { EntityManager } from 'typeorm'
4
4
  import { PickingWorksheetController } from '../../../../controllers'
5
5
 
6
6
  export const pickingResolver = {
7
- async picking(_: any, { worksheetDetailName, worksheetType, palletId, locationName, releaseQty, binLocation, serialNumber }, context: any) {
7
+ async picking(
8
+ _: any,
9
+ { worksheetDetailName, worksheetType, palletId, locationName, releaseQty, binLocation, serialNumber, toteNo },
10
+ context: any
11
+ ) {
8
12
  const { tx, domain, user }: { tx: EntityManager; domain: Domain; user: User } = context.state
9
- await picking(tx, domain, user, worksheetDetailName, worksheetType, palletId, locationName, releaseQty, binLocation, serialNumber)
13
+ await picking(
14
+ tx,
15
+ domain,
16
+ user,
17
+ worksheetDetailName,
18
+ worksheetType,
19
+ palletId,
20
+ locationName,
21
+ releaseQty,
22
+ binLocation,
23
+ serialNumber,
24
+ toteNo
25
+ )
10
26
  }
11
27
  }
12
28
 
@@ -20,8 +36,18 @@ export async function picking(
20
36
  locationName: string,
21
37
  releaseQty: number,
22
38
  binLocation?: string,
23
- serialNumber?: string
39
+ serialNumber?: string,
40
+ toteNo?: string
24
41
  ) {
25
42
  const worksheetController: PickingWorksheetController = new PickingWorksheetController(tx, domain, user)
26
- await worksheetController.picking(worksheetDetailName, worksheetType, palletId, locationName, releaseQty, binLocation, serialNumber)
43
+ await worksheetController.picking(
44
+ worksheetDetailName,
45
+ worksheetType,
46
+ palletId,
47
+ locationName,
48
+ releaseQty,
49
+ binLocation,
50
+ serialNumber,
51
+ toteNo
52
+ )
27
53
  }