@things-factory/worksheet-base 5.0.0-alpha.38 → 5.0.0-alpha.40

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 (50) hide show
  1. package/dist-server/constants/template.js +1 -0
  2. package/dist-server/constants/template.js.map +1 -1
  3. package/dist-server/controllers/ecommerce/sellercraft-controller.js +9 -3
  4. package/dist-server/controllers/ecommerce/sellercraft-controller.js.map +1 -1
  5. package/dist-server/controllers/inbound/unloading-worksheet-controller.js +9 -3
  6. package/dist-server/controllers/inbound/unloading-worksheet-controller.js.map +1 -1
  7. package/dist-server/controllers/index.js +2 -0
  8. package/dist-server/controllers/index.js.map +1 -1
  9. package/dist-server/controllers/render-fm-grn.js +229 -0
  10. package/dist-server/controllers/render-fm-grn.js.map +1 -0
  11. package/dist-server/controllers/render-grn.js +18 -18
  12. package/dist-server/controllers/render-po.js +147 -0
  13. package/dist-server/controllers/render-po.js.map +1 -0
  14. package/dist-server/graphql/resolvers/worksheet/cycle-count-adjustment.js +10 -3
  15. package/dist-server/graphql/resolvers/worksheet/cycle-count-adjustment.js.map +1 -1
  16. package/dist-server/graphql/resolvers/worksheet/loading/complete-loading.js +13 -3
  17. package/dist-server/graphql/resolvers/worksheet/loading/complete-loading.js.map +1 -1
  18. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js +6 -2
  19. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js.map +1 -1
  20. package/dist-server/graphql/resolvers/worksheet/picking/picking-assignment-status-by-user.js +49 -55
  21. package/dist-server/graphql/resolvers/worksheet/picking/picking-assignment-status-by-user.js.map +1 -1
  22. package/dist-server/graphql/resolvers/worksheet/worksheets.js +18 -0
  23. package/dist-server/graphql/resolvers/worksheet/worksheets.js.map +1 -1
  24. package/dist-server/graphql/types/worksheet/index.js +3 -2
  25. package/dist-server/graphql/types/worksheet/index.js.map +1 -1
  26. package/dist-server/graphql/types/worksheet/picking-assignment-status.js +2 -2
  27. package/dist-server/graphql/types/worksheet/worksheet-patch.js +1 -0
  28. package/dist-server/graphql/types/worksheet/worksheet-patch.js.map +1 -1
  29. package/dist-server/index.js +1 -0
  30. package/dist-server/index.js.map +1 -1
  31. package/dist-server/routes.js +12 -0
  32. package/dist-server/routes.js.map +1 -1
  33. package/package.json +17 -17
  34. package/server/constants/template.ts +1 -0
  35. package/server/controllers/ecommerce/sellercraft-controller.ts +10 -3
  36. package/server/controllers/inbound/unloading-worksheet-controller.ts +14 -3
  37. package/server/controllers/index.ts +3 -0
  38. package/server/controllers/render-fm-grn.ts +266 -0
  39. package/server/controllers/render-grn.ts +18 -18
  40. package/server/controllers/render-po.ts +170 -0
  41. package/server/graphql/resolvers/worksheet/cycle-count-adjustment.ts +13 -4
  42. package/server/graphql/resolvers/worksheet/loading/complete-loading.ts +19 -5
  43. package/server/graphql/resolvers/worksheet/picking/complete-picking.ts +5 -2
  44. package/server/graphql/resolvers/worksheet/picking/picking-assignment-status-by-user.ts +61 -58
  45. package/server/graphql/resolvers/worksheet/worksheets.ts +26 -0
  46. package/server/graphql/types/worksheet/index.ts +3 -2
  47. package/server/graphql/types/worksheet/picking-assignment-status.ts +2 -2
  48. package/server/graphql/types/worksheet/worksheet-patch.ts +1 -0
  49. package/server/index.ts +1 -0
  50. package/server/routes.ts +17 -0
@@ -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
@@ -0,0 +1,170 @@
1
+ import FormData from 'form-data'
2
+ import fetch from 'node-fetch'
3
+ import { getRepository, SelectQueryBuilder } from 'typeorm'
4
+
5
+ import { Attachment, STORAGE } from '@things-factory/attachment-base'
6
+ import { Bizplace } from '@things-factory/biz-base'
7
+ import { config } from '@things-factory/env'
8
+ import { InvoiceProduct, ReleaseGood, PurchaseOrder, PurchaseOrderOtherCharge, OrderProduct } from '@things-factory/sales-base'
9
+
10
+ import { Domain } from '@things-factory/shell'
11
+
12
+ import { TEMPLATE_TYPE } from '../constants'
13
+ import { DateTimeConverter } from '../utils/datetime-util'
14
+
15
+ const REPORT_API_URL = config.get('reportApiUrl', 'http://localhost:8888/rest/report/show_html')
16
+
17
+ export async function renderPO({ req, timezoneOffSet }, context: any) {
18
+ try {
19
+ const domain: Domain = await getRepository(Domain).findOne({
20
+ where: { id: context.state.domain.id }
21
+ })
22
+
23
+ let result = await Promise.all(
24
+ req.poIds.map(async poId => {
25
+ try {
26
+ const qb: SelectQueryBuilder<PurchaseOrder> = await getRepository(PurchaseOrder)
27
+ .createQueryBuilder('po')
28
+ .innerJoinAndSelect('po.domain', 'domain')
29
+ .innerJoinAndSelect('po.bizplace', 'bizplace')
30
+ .innerJoinAndSelect('bizplace.domain', 'bizplace_domain')
31
+ .innerJoinAndSelect('bizplace.company', 'company')
32
+ .innerJoinAndSelect('company.domain', 'company_domain')
33
+ .leftJoinAndSelect('contact_points', 'cp', 'po.supplier_id = cp.id')
34
+ .where('po.id = :poId')
35
+ .andWhere('po.domain = :domainId')
36
+ .setParameters({ poId, domainId: domain.id })
37
+
38
+ let record: any = await qb.getRawOne()
39
+
40
+ if (record) {
41
+ const partnerBiz: Partial<Bizplace> = {
42
+ id: record.bizplace_id,
43
+ name: record.bizplace_name,
44
+ address: record.bizplace_address,
45
+ domain: { id: record.bizplace_domain_id }
46
+ }
47
+
48
+ const foundTemplate: Attachment = await getRepository(Attachment).findOne({
49
+ where: { domain: partnerBiz.domain, category: TEMPLATE_TYPE.PO_TEMPLATE }
50
+ })
51
+
52
+ const foundLogo: Attachment = await getRepository(Attachment).findOne({
53
+ where: {
54
+ domain: partnerBiz.domain,
55
+ category: TEMPLATE_TYPE.LOGO
56
+ }
57
+ })
58
+
59
+ let logo = null
60
+ if (foundLogo?.path) {
61
+ logo = 'data:' + foundLogo.mimetype + ';base64,' + (await STORAGE.readFile(foundLogo.path, 'base64'))
62
+ }
63
+
64
+ const template = await STORAGE.readFile(foundTemplate.path, 'utf-8')
65
+
66
+ const poocQb: SelectQueryBuilder<PurchaseOrderOtherCharge> = await getRepository(PurchaseOrderOtherCharge)
67
+ .createQueryBuilder('pooc')
68
+ .where('pooc.purchase_order_id = :poId')
69
+ .andWhere('pooc.apply_in_items = false')
70
+ .setParameters({ poId })
71
+
72
+ let poOtherCharges: any[] = await poocQb.getRawMany()
73
+
74
+
75
+ const qb: SelectQueryBuilder<OrderProduct> = await getRepository(OrderProduct)
76
+ .createQueryBuilder('op')
77
+ .innerJoin('domains', 'd', 'op.domain_id = d.id')
78
+ .leftJoinAndSelect('purchase_orders', 'po', 'po.id = op.purchase_order_id')
79
+ .leftJoinAndSelect('products', 'p', 'op.product_id = p.id')
80
+ .where('op.purchase_order_id = :poId')
81
+ .andWhere('op.domain = :domainId')
82
+ .setParameters({ poId, domainId: domain.id })
83
+
84
+ let items: any[] = await qb.getRawMany()
85
+
86
+ const product_list = items.map((item, idx) => {
87
+ return {
88
+ list_no: idx + 1,
89
+ product_sku: item.p_sku,
90
+ product_name: item.p_name,
91
+ product_desc: item.p_description,
92
+ product_qty: item.op_pack_qty,
93
+ product_uom: item.op_uom,
94
+ product_other_charges: item.ip_other_charges,
95
+ product_unit_price: (item.op_unit_price).toFixed(2),
96
+ product_total_price: ((((item.op_unit_price || 0) * item.op_pack_qty) - (item.op_discount_amt || 0)) * (1 + (item.op_tax_rate / 100))).toFixed(2),
97
+ product_tax_rate: item.op_tax_rate,
98
+ product_disc_amt: item.op_discount_amt
99
+ }
100
+ })
101
+
102
+
103
+ let date = DateTimeConverter.date(new Date(record.po_created_at - timezoneOffSet))
104
+ let eta = DateTimeConverter.date(new Date(record.po_eta_date))
105
+
106
+ let subtotal = getRoundedValue(
107
+ product_list.reduce((init, item) => {
108
+ return (init += parseFloat(item.product_total_price))
109
+ }, 0) || 0
110
+ )
111
+
112
+ const data = {
113
+ logo_url: logo,
114
+ company_name: record.company_description,
115
+ company_address: record.company_address,
116
+ company_postal_code: record.company_postal_code,
117
+ po_number: record.po_name,
118
+ po_order_date: date,
119
+ po_delivery_date: eta,
120
+ ref_no: record.po_ref_no,
121
+ cp_company_name: record.cp_company_name,
122
+ cp_address: record.cp_address2 ? [record.cp_address, record.cp_address2].join(', ') : record.cp_address,
123
+ cp_contact_name: record.cp_name,
124
+ cp_email: record.cp_email,
125
+ cp_phone_number: record.cp_phone,
126
+ product_list,
127
+ charges_list: [
128
+ {
129
+ field: 'SUBTOTAL', value: subtotal.toFixed(2)
130
+ },
131
+ ...poOtherCharges.map(itm => { return { field: itm.pooc_name.toUpperCase(), value: itm.pooc_total_amt.toFixed(2) } }),
132
+ {
133
+ field: 'TOTAL', value: (poOtherCharges.reduce((init, item) => {
134
+ return init += (item.pooc_total_amt)
135
+ }, subtotal) || 0).toFixed(2),
136
+ },
137
+ ]
138
+ }
139
+
140
+ const formData = new FormData()
141
+ formData.append('template', template)
142
+ formData.append('jsonString', JSON.stringify(data))
143
+
144
+ const response = await fetch(REPORT_API_URL, {
145
+ method: 'POST',
146
+ body: formData
147
+ })
148
+
149
+ return await response.text()
150
+ }
151
+ return null
152
+ } catch (ex) {
153
+ return null
154
+ }
155
+ })
156
+ )
157
+
158
+ if (result.filter(x => x != null).length <= 0) {
159
+ throw Error('No purchase order found!')
160
+ }
161
+
162
+ return result.join()
163
+ } catch (ex) {
164
+ throw ex
165
+ }
166
+ }
167
+
168
+ function getRoundedValue(value = 0) {
169
+ return Math.round((value + Number.EPSILON) * 100) / 100
170
+ }
@@ -56,7 +56,9 @@ export async function cycleCountAdjustment(
56
56
  'targetInventory.inventory.product.productDetails',
57
57
  'targetInventory.inventory.product.productDetails.childProductDetail',
58
58
  'targetInventory.inventory.bizplace',
59
+ 'targetInventory.inventory.domain',
59
60
  'targetInventory.inventory.bizplace.domain',
61
+ 'targetInventory.inventory.warehouse',
60
62
  'targetInventory.inventory.location',
61
63
  'targetInventory.inspectedLocation',
62
64
  'targetInventory.inspectedLocation.warehouse'
@@ -67,8 +69,8 @@ export async function cycleCountAdjustment(
67
69
  const targetInventory: OrderInventory = worksheetDetail.targetInventory
68
70
  let inventory: Inventory = targetInventory.inventory
69
71
 
70
- const transactQty: number = targetInventory.inspectedQty - inventory.qty
71
- const transactUomValue: number = targetInventory.inspectedUomValue - inventory.uomValue
72
+ let transactQty: number = targetInventory.inspectedQty - inventory.qty
73
+ let transactUomValue: number = targetInventory.inspectedUomValue - inventory.uomValue
72
74
 
73
75
  const sellercraft: Sellercraft = await tx.getRepository(Sellercraft).findOne({
74
76
  where: { domain: inventory.bizplace.domain, status: SellercraftStatus.ACTIVE }
@@ -137,16 +139,23 @@ export async function cycleCountAdjustment(
137
139
 
138
140
  if (targetInventory.inspectedBatchNo !== inventory.batchId) {
139
141
  // generate TERMINATED, ADJUSTMENT history
142
+ const { qty, uomValue }: { qty: number; uomValue: number } = inventory
140
143
  inventory.status = INVENTORY_STATUS.TERMINATED
144
+ inventory.qty = 0
145
+ inventory.uomValue = 0
146
+
141
147
  await generateInventoryHistory(
142
148
  inventory,
143
149
  cycleCount,
144
150
  INVENTORY_TRANSACTION_TYPE.CC_ADJUSTMENT,
145
- -transactQty,
146
- -transactUomValue,
151
+ -qty,
152
+ -uomValue,
147
153
  user,
148
154
  tx
149
155
  )
156
+
157
+ transactQty = targetInventory.inspectedQty
158
+ transactUomValue = targetInventory.inspectedUomValue
150
159
  }
151
160
 
152
161
  inventory.batchId = targetInventory.inspectedBatchNo
@@ -1,11 +1,14 @@
1
+ import { EntityManager } from 'typeorm'
2
+
1
3
  import { User } from '@things-factory/auth-base'
2
- import { OrderInventory, ORDER_INVENTORY_STATUS, ORDER_STATUS, ReleaseGood } from '@things-factory/sales-base'
4
+ import { Sftp, SftpAPI } from '@things-factory/integration-sftp'
5
+ import { ORDER_INVENTORY_STATUS, ORDER_STATUS, OrderInventory, ReleaseGood } from '@things-factory/sales-base'
3
6
  import { Domain } from '@things-factory/shell'
4
- import { EntityManager } from 'typeorm'
7
+ import { InventoryItem } from '@things-factory/warehouse-base'
8
+
5
9
  import { WORKSHEET_TYPE } from '../../../../constants'
6
10
  import { LoadingWorksheetController, ReturningWorksheetController } from '../../../../controllers'
7
11
  import { Worksheet, WorksheetDetail } from '../../../../entities'
8
- import { Sftp, SftpAPI } from '@things-factory/integration-sftp'
9
12
 
10
13
  export const completeLoadingResolver = {
11
14
  async completeLoading(_: any, { releaseGoodNo }, context: any) {
@@ -46,12 +49,23 @@ export async function completeLoading(
46
49
  where: { domain: customerDomain }
47
50
  })
48
51
  if (customerAvailableSftp) {
49
- let result: Sftp = await SftpAPI.createShipment(customerAvailableSftp, {
52
+ let inventoryItems: InventoryItem[] = await tx.getRepository(InventoryItem).find({
53
+ where: { domain, outboundOrderId: releaseGood.id }
54
+ })
55
+
56
+ let shipmentResult: Sftp = await SftpAPI.createShipment(customerAvailableSftp, {
50
57
  releaseGood,
51
58
  orderInventories: targetInventories,
52
59
  sftp: customerAvailableSftp
53
60
  })
54
- customerAvailableSftp = await tx.getRepository(Sftp).save(result)
61
+ customerAvailableSftp = await tx.getRepository(Sftp).save(shipmentResult)
62
+
63
+ let snResult: Sftp = await SftpAPI.createSerialNumber(customerAvailableSftp, {
64
+ releaseGood,
65
+ inventoryItems,
66
+ sftp: customerAvailableSftp
67
+ })
68
+ customerAvailableSftp = await tx.getRepository(Sftp).save(snResult)
55
69
  }
56
70
 
57
71
  await worksheetController.completeLoading(releaseGoodNo)
@@ -205,8 +205,11 @@ export async function completePicking(
205
205
  }
206
206
  }
207
207
  } else {
208
- throw resp
209
- //Failed
208
+ if (resp?.AWBurl && resp?.TrackingNo)
209
+ await tx
210
+ .getRepository(MarketplaceOrderShipping)
211
+ .update({ id: marketplaceOrderShipping.id }, { airwayBill: resp.AWBurl, trackingNo: resp.TrackingNo })
212
+ else throw resp
210
213
  }
211
214
  }
212
215
  }
@@ -1,79 +1,82 @@
1
- import { getDomainUsers, User } from '@things-factory/auth-base'
2
- import { Domain } from '@things-factory/shell'
3
- import { FindManyOptions, getRepository, ILike, In } from 'typeorm'
1
+ import { getDomainUsers, User, Role } from '@things-factory/auth-base'
2
+ import { Domain, ListParam, buildQuery, Sorting} from '@things-factory/shell'
3
+ import { FindManyOptions, getRepository, ILike, In, EntityManager, getManager, SelectQueryBuilder } from 'typeorm'
4
4
  import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../../../constants'
5
5
  import { Worksheet } from '../../../../entities'
6
6
 
7
- type AssignmentStatusByUserType = { user: User; pending?: Worksheet[]; picking?: Worksheet[] }
7
+ type AssignmentStatusByUserType = { user: User; pending?: String; picking?: String }
8
8
 
9
9
  export const pickingAssignmentStatusByUsersResolver = {
10
10
  async pickingAssignmentStatusByUsers(
11
11
  _: void,
12
- { name, email }: { name?: string; email?: string },
12
+ params: ListParam,
13
13
  context: any
14
14
  ): Promise<AssignmentStatusByUserType[]> {
15
+
15
16
  const { domain }: { domain: Domain } = context.state
16
- const domainUsers: User[] = await getDomainUsers(domain)
17
17
 
18
- const domainUserIds: string[] = domainUsers
19
- .filter((user: User) => user.userType === 'user')
20
- .map((user: User) => user.id)
18
+ const nameFilter = params.filters.find(p=>{return p.name == "name"});
19
+ const emailFilter = params.filters.find(p=>{return p.name == "email"});
20
+ const roleFilter = params.filters.find(p=>{return p.name == 'roles'});
21
21
 
22
- const findOneOption: FindManyOptions<User> = { where: { id: In(domainUserIds) } }
23
- if (name) findOneOption.where.name = ILike(`%${name}%`)
24
- if (email) findOneOption.where.email = ILike(`%${email}%`)
22
+ const pendingSorter = params.sortings.find(p=>{return p.name == 'pending'});
23
+ const pickingSorter = params.sortings.find(p=>{return p.name == 'picking'});
25
24
 
26
- const users: User[] = await getRepository(User).find(findOneOption)
27
25
 
28
- const assignedPickingWorksheets: Worksheet[] = await getRepository(Worksheet).find({
29
- where: {
30
- type: In([WORKSHEET_TYPE.PICKING, WORKSHEET_TYPE.BATCH_PICKING]),
31
- status: In([WORKSHEET_STATUS.DEACTIVATED, WORKSHEET_STATUS.EXECUTING]),
32
- assignee: In(users.map((u: User) => u.id)),
33
- domain
34
- },
35
- relations: ['assignee']
36
- })
37
26
 
38
- const assignmentMap: Map<string, AssignmentStatusByUserType> = assignedPickingWorksheets.reduce(
39
- (assignmentMap: Map<string, AssignmentStatusByUserType>, worksheet: Worksheet) => {
40
- const assignee: User = worksheet.assignee
41
- const status: string = worksheet.status
27
+ const getUserInfoQb:SelectQueryBuilder<User> = await getRepository(User).createQueryBuilder('u')
42
28
 
43
- if (assignmentMap.has(assignee.id)) {
44
- const assignment: AssignmentStatusByUserType = assignmentMap.get(assignee.id)
45
- if (status === WORKSHEET_STATUS.DEACTIVATED) {
46
- assignment.pending.push(worksheet)
47
- } else if (status === WORKSHEET_STATUS.EXECUTING) {
48
- assignment.picking.push(worksheet)
49
- }
50
- } else {
51
- if (status === WORKSHEET_STATUS.DEACTIVATED) {
52
- assignmentMap.set(assignee.id, {
53
- user: assignee,
54
- pending: [worksheet],
55
- picking: []
56
- })
57
- } else if (status === WORKSHEET_STATUS.EXECUTING) {
58
- assignmentMap.set(assignee.id, {
59
- user: assignee,
60
- pending: [],
61
- picking: [worksheet]
62
- })
63
- }
64
- }
29
+ getUserInfoQb.select('u.id')
30
+ getUserInfoQb.addSelect('u.name')
31
+ getUserInfoQb.addSelect('u.email')
32
+ getUserInfoQb.addSelect("string_agg(r.name,', ') as roles")
33
+ getUserInfoQb.innerJoin('u.roles','r')
34
+ getUserInfoQb.where('r.domain_id = :domainId',{domainId:domain.id})
35
+ roleFilter? getUserInfoQb.andWhere('r.name ilike :userRole', { userRole: `%${roleFilter.value}%` }) :""
36
+ nameFilter? getUserInfoQb.andWhere('u.name ilike :userName', { userName: `%${nameFilter.value}%` }) :""
37
+ emailFilter? getUserInfoQb.andWhere('u.email ilike :userEmail', { userEmail: `%${emailFilter.value}%` }) :""
38
+ getUserInfoQb.andWhere('r.name not ilike :userR',{userR:`%CLIENT%`})
39
+ getUserInfoQb.andWhere('u.user_type = :userType',{userType:"user"})
40
+ getUserInfoQb.groupBy('u.id')
41
+ getUserInfoQb.addGroupBy('u.name')
42
+ getUserInfoQb.addGroupBy('u.email')
65
43
 
66
- return assignmentMap
67
- },
68
- new Map()
69
- )
44
+ const getAssignedWSQb = await getRepository(Worksheet).createQueryBuilder('ws')
70
45
 
71
- users.forEach((user: User) => {
72
- if (!assignmentMap.has(user.id)) {
73
- assignmentMap.set(user.id, { user, pending: [], picking: [] })
74
- }
75
- })
46
+ getAssignedWSQb.select('ws.assignee_id')
47
+ getAssignedWSQb.addSelect('u.name')
48
+ getAssignedWSQb.addSelect("sum(case when ws.status='EXECUTING' then 1 else 0 end) as picking")
49
+ getAssignedWSQb.addSelect("sum(case when ws.status='DEACTIVATED' then 1 else 0 end) as pending")
50
+ getAssignedWSQb.innerJoin('ws.assignee','u')
51
+ getAssignedWSQb.where('ws.domain_id = :id',{id:domain.id})
52
+ getAssignedWSQb.andWhere('ws.type IN (:...type)', {type: [WORKSHEET_TYPE.PICKING, WORKSHEET_TYPE.BATCH_PICKING]})
53
+ getAssignedWSQb.andWhere('ws.status IN (:...status)', {status: [WORKSHEET_STATUS.DEACTIVATED, WORKSHEET_STATUS.EXECUTING]})
54
+ getAssignedWSQb.groupBy('ws.assignee_id')
55
+ getAssignedWSQb.addGroupBy('u.name')
56
+ pendingSorter?.desc ? getAssignedWSQb.orderBy('pending','DESC') : ''
57
+ pickingSorter?.desc ? getAssignedWSQb.orderBy('picking','DESC') : ''
58
+ pickingSorter && Object.keys(pickingSorter).length == 1 ?getAssignedWSQb.orderBy('picking','ASC') : ''
59
+ pendingSorter && Object.keys(pendingSorter).length == 1 ? getAssignedWSQb.orderBy('pending','ASC') : ''
60
+
61
+
62
+ const parameter1= getUserInfoQb.getParameters()
63
+ const parameter2 = getAssignedWSQb.getParameters()
76
64
 
77
- return Array.from(assignmentMap.values())
65
+ const combineParams = Object.assign(parameter1, parameter2)
66
+
67
+ const combineQb = getManager().createQueryBuilder()
68
+
69
+ combineQb.select('u.*')
70
+ combineQb.addSelect('coalesce(ws.picking, 0) as picking')
71
+ combineQb.addSelect('coalesce(ws.pending, 0) as pending')
72
+ combineQb.from("(" + getUserInfoQb.getQuery() + ")","u")
73
+ combineQb.leftJoin("(" + getAssignedWSQb.getQuery() + ")","ws",' ws.assignee_id = u.u_id')
74
+ combineQb.setParameters(combineParams)
75
+
76
+ const combineInfo = await combineQb.getRawMany()
77
+
78
+ return combineInfo.map(itm => {
79
+ return { user: { id:itm.u_id,email:itm.u_email,name:itm.u_name, description: itm.roles },pending:itm.pending,picking:itm.picking }
80
+ })
78
81
  }
79
82
  }
@@ -99,6 +99,7 @@ export const worksheetsResolver = {
99
99
  const releaseGoodCrossDockingParam = params.filters.find(param => param.name === 'crossDocking')
100
100
  const releaseGoodCourierOptionParam = params.filters.find(param => param.name === 'courierOption')
101
101
  const releaseGoodPackingOptionParam = params.filters.find(param => param.name === 'packingOption')
102
+ const releaseGoodPickerOptionParam = params.filters.find(param => param.name === 'assignee')
102
103
  if (
103
104
  releaseGoodParam ||
104
105
  releaseGoodRefNoParam ||
@@ -252,6 +253,31 @@ export const worksheetsResolver = {
252
253
  }
253
254
  }
254
255
 
256
+ //find assignee
257
+
258
+ const assigneeParam = params.filters.find(param => param.name === 'assignee')
259
+ let assigneeFilter = []
260
+ if (assigneeParam) {
261
+ params.filters.splice(
262
+ params.filters.findIndex(item => item.name == 'assignee'),
263
+ 1
264
+ )
265
+ assigneeFilter.push({ ...assigneeParam, name: 'name' })
266
+
267
+ const foundAssignee: User[] = await getRepository(User).find({
268
+ ...convertListParams({ filters: assigneeFilter })
269
+ })
270
+
271
+ if (foundAssignee) {
272
+ params.filters.push({
273
+ name: 'assigneeId',
274
+ operator: 'in',
275
+ value: foundAssignee.map((foundIC: User) => foundIC.id),
276
+ relation: false
277
+ })
278
+ }
279
+ }
280
+
255
281
  ////Set default bizplace filter
256
282
  const bizplaceFilter = params.filters.find(param => param.name === 'bizplaceId')
257
283
  if (!bizplaceFilter && typeParam.value[0] !== WORKSHEET_TYPE.BATCH_PICKING) {
@@ -681,8 +681,9 @@ export const Query = /* GraphQL */ `
681
681
  ): [Inventory] @privilege(category: "worksheet", privilege: "query")
682
682
 
683
683
  pickingAssignmentStatusByUsers(
684
- name: String
685
- email: String
684
+ filters: [Filter],
685
+ pagination: Pagination,
686
+ sortings: [Sorting]
686
687
  ): [PickingAssignmentStatus] @privilege(category: "worksheet", privilege: "query")
687
688
 
688
689
  myPickingAssignmentStatus: MyPickingAssignmentStatus @privilege(category: "worksheet", privilege: "query")
@@ -3,7 +3,7 @@ import { gql } from 'apollo-server-koa'
3
3
  export const PickingAssignmentStatus = gql`
4
4
  type PickingAssignmentStatus {
5
5
  user: User
6
- pending: [Worksheet]
7
- picking: [Worksheet]
6
+ pending: String
7
+ picking: String
8
8
  }
9
9
  `
@@ -11,6 +11,7 @@ export const WorksheetPatch = gql`
11
11
  initialBatchId: String
12
12
  status: String
13
13
  truckNo: String
14
+ transportDriver: ObjectRef
14
15
  palletQty: String
15
16
  ownCollection: Boolean
16
17
  cuFlag: String
package/server/index.ts CHANGED
@@ -10,3 +10,4 @@ export * from './graphql/resolvers/worksheet-detail/generate-release-good-worksh
10
10
  export * from './graphql/resolvers/worksheet/unloading/activate-unloading'
11
11
  export * from './graphql/resolvers/worksheet/picking/activate-picking'
12
12
  export * from './migrations'
13
+ export * from './controllers'
package/server/routes.ts CHANGED
@@ -8,7 +8,10 @@ import { renderOrientageDO } from './controllers/render-orientage-do'
8
8
  import { renderOrientageGRN } from './controllers/render-orientage-grn'
9
9
  import { renderRODO } from './controllers/render-ro-do'
10
10
  import { renderSeebuuGRN } from './controllers/render-seebuu-grn'
11
+ import { renderFmGRN } from './controllers/render-fm-grn'
11
12
  import { renderInvoices } from './controllers/render-invoices'
13
+ import { renderPO } from './controllers/render-po'
14
+
12
15
 
13
16
  process.on('bootstrap-module-domain-private-route' as any, (app, routes) => {
14
17
  routes.get('/view_document_ro_do/:doNo', async (context, next) => {
@@ -43,6 +46,10 @@ process.on('bootstrap-module-domain-private-route' as any, (app, routes) => {
43
46
  context.body = await renderSeebuuGRN(context.params, context)
44
47
  })
45
48
 
49
+ routes.get('/view_fm_grn/:grnNo/:timezoneOffSet', async (context, next) => {
50
+ context.body = await renderFmGRN(context.params, context)
51
+ })
52
+
46
53
  routes.get('/view_job_sheet/:ganNo/:timezoneOffSet', async (context, next) => {
47
54
  context.body = await renderJobSheet(context.params, context)
48
55
  })
@@ -60,4 +67,14 @@ process.on('bootstrap-module-domain-private-route' as any, (app, routes) => {
60
67
  context.type = 'application/json'
61
68
  context.body = data
62
69
  })
70
+
71
+ routes.post('/view_purchase_orders/:timezoneOffSet', async (context, next) => {
72
+ let req = context.request.body || {}
73
+ let timezoneOffSet = context.params.timezoneOffSet || 0
74
+
75
+ let data = await renderPO({ req, timezoneOffSet }, context)
76
+
77
+ context.type = 'application/json'
78
+ context.body = data
79
+ })
63
80
  })