@things-factory/operato-hub 4.3.162 → 4.3.165

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 (61) hide show
  1. package/dist-server/entities/email-attachment.js +77 -0
  2. package/dist-server/entities/email-attachment.js.map +1 -0
  3. package/dist-server/entities/email-recipient.js +69 -0
  4. package/dist-server/entities/email-recipient.js.map +1 -0
  5. package/dist-server/entities/email.js +90 -0
  6. package/dist-server/entities/email.js.map +1 -0
  7. package/dist-server/entities/index.js +10 -0
  8. package/dist-server/entities/index.js.map +1 -1
  9. package/dist-server/graphql/resolvers/email/index.js +6 -0
  10. package/dist-server/graphql/resolvers/email/index.js.map +1 -0
  11. package/dist-server/graphql/resolvers/email/send-emails.js +194 -0
  12. package/dist-server/graphql/resolvers/email/send-emails.js.map +1 -0
  13. package/dist-server/graphql/resolvers/index.js +4 -2
  14. package/dist-server/graphql/resolvers/index.js.map +1 -1
  15. package/dist-server/graphql/resolvers/reports/inbound-order-details-report.js +200 -0
  16. package/dist-server/graphql/resolvers/reports/inbound-order-details-report.js.map +1 -0
  17. package/dist-server/graphql/resolvers/reports/index.js +7 -0
  18. package/dist-server/graphql/resolvers/reports/index.js.map +1 -0
  19. package/dist-server/graphql/resolvers/reports/outbound-order-details-report.js +231 -0
  20. package/dist-server/graphql/resolvers/reports/outbound-order-details-report.js.map +1 -0
  21. package/dist-server/graphql/types/index.js +3 -2
  22. package/dist-server/graphql/types/index.js.map +1 -1
  23. package/dist-server/graphql/types/reports/inbound-order-details-report-list.js +14 -0
  24. package/dist-server/graphql/types/reports/inbound-order-details-report-list.js.map +1 -0
  25. package/dist-server/graphql/types/reports/inbound-order-details-report.js +59 -0
  26. package/dist-server/graphql/types/reports/inbound-order-details-report.js.map +1 -0
  27. package/dist-server/graphql/types/reports/index.js +13 -0
  28. package/dist-server/graphql/types/reports/index.js.map +1 -0
  29. package/dist-server/graphql/types/reports/outbound-order-details-report-list.js +14 -0
  30. package/dist-server/graphql/types/reports/outbound-order-details-report-list.js.map +1 -0
  31. package/dist-server/graphql/types/reports/outbound-order-details-report.js +76 -0
  32. package/dist-server/graphql/types/reports/outbound-order-details-report.js.map +1 -0
  33. package/dist-server/graphql/types/synchronization/index.js +1 -0
  34. package/dist-server/graphql/types/synchronization/index.js.map +1 -1
  35. package/dist-server/index.js +1 -0
  36. package/dist-server/index.js.map +1 -1
  37. package/dist-server/utils/index.js +1 -0
  38. package/dist-server/utils/index.js.map +1 -1
  39. package/dist-server/utils/report-query-util.js +42 -0
  40. package/dist-server/utils/report-query-util.js.map +1 -0
  41. package/package.json +29 -28
  42. package/server/entities/email-attachment.ts +49 -0
  43. package/server/entities/email-recipient.ts +51 -0
  44. package/server/entities/email.ts +68 -0
  45. package/server/entities/index.ts +7 -0
  46. package/server/graphql/resolvers/email/index.ts +5 -0
  47. package/server/graphql/resolvers/email/send-emails.ts +196 -0
  48. package/server/graphql/resolvers/index.ts +4 -2
  49. package/server/graphql/resolvers/reports/inbound-order-details-report.ts +218 -0
  50. package/server/graphql/resolvers/reports/index.ts +7 -0
  51. package/server/graphql/resolvers/reports/outbound-order-details-report.ts +251 -0
  52. package/server/graphql/types/index.ts +3 -2
  53. package/server/graphql/types/reports/inbound-order-details-report-list.ts +8 -0
  54. package/server/graphql/types/reports/inbound-order-details-report.ts +53 -0
  55. package/server/graphql/types/reports/index.ts +11 -0
  56. package/server/graphql/types/reports/outbound-order-details-report-list.ts +8 -0
  57. package/server/graphql/types/reports/outbound-order-details-report.ts +70 -0
  58. package/server/graphql/types/synchronization/index.ts +1 -0
  59. package/server/index.ts +1 -0
  60. package/server/utils/index.ts +1 -0
  61. package/server/utils/report-query-util.ts +47 -0
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.OutboundOrderDetailsReport = void 0;
7
+ const graphql_tag_1 = __importDefault(require("graphql-tag"));
8
+ exports.OutboundOrderDetailsReport = (0, graphql_tag_1.default) `
9
+ type OutboundOrderDetailsReport {
10
+ bizplace: Bizplace
11
+ doNo: String
12
+ doDeliveryDate: String
13
+ deliveryAddress: String
14
+ manifestNo: String
15
+ roNo: String
16
+ roType: String
17
+ status: String
18
+ refNo1: String
19
+ refNo2: String
20
+ refNo3: String
21
+ exportOption: Boolean
22
+ containerNo: String
23
+ containerSize: String
24
+ transportOption: String
25
+ vehicleNo: String
26
+ driverName: String
27
+ palletQty: Int
28
+ acceptedBy: String
29
+ acceptedAt: String
30
+ orderCreatedBy: String
31
+ orderCreatedAt: String
32
+ pickingStart: String
33
+ pickingComplete: String
34
+ packingStart: String
35
+ packingComplete: String
36
+ sortingStart: String
37
+ sortingComplete: String
38
+ loadingStart: String
39
+ loadingComplete: String
40
+ orderLineItem: Int
41
+ product: Product
42
+ packType: String
43
+ packSize: Int
44
+ qty: Int
45
+ uomValue: Float
46
+ returnToLocationQty: Int
47
+ returnToLocationUomValue: Float
48
+ uom: String
49
+ unitCost: Float
50
+ unitVolume: Float
51
+ totalVolume: Float
52
+ unitNettWeight: Float
53
+ totalUnitNettWeight: Float
54
+ unitGrossWeight: Float
55
+ totalUnitGrossWeight: Float
56
+ weightUnit: String
57
+ palletId: String
58
+ cartonId: String
59
+ batchId: String
60
+ batchIdRef: String
61
+ expirationDate: String
62
+ manufactureDate: String
63
+ pickedAt: String
64
+ pickedBy: String
65
+ packedAt: String
66
+ packedBy: String
67
+ checkedRemarkBy: String
68
+ checkedRemarkAt: String
69
+ loadedAt: String
70
+ loadedBy: String
71
+ manifestedAt: String
72
+ manifestedBy: String
73
+ dispatchedAt: String
74
+ }
75
+ `;
76
+ //# sourceMappingURL=outbound-order-details-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbound-order-details-report.js","sourceRoot":"","sources":["../../../../server/graphql/types/reports/outbound-order-details-report.ts"],"names":[],"mappings":";;;;;;AAAA,8DAA6B;AAEhB,QAAA,0BAA0B,GAAG,IAAA,qBAAG,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmE5C,CAAA"}
@@ -20,6 +20,7 @@ exports.Mutation = `
20
20
  sellercraftPackMarketplaceOrder: Boolean @transaction
21
21
  createDatShipments: Boolean @transaction
22
22
  autoUpdateAllMarketplaceProductVariationQuantity(companyDomainId: String, warehouseId: String): Boolean @transaction
23
+ sendEmails: Boolean @transaction
23
24
  `;
24
25
  exports.Types = [
25
26
  sync_product_set_1.SyncProductSet,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../server/graphql/types/synchronization/index.ts"],"names":[],"mappings":";;;AAAA,2DAAqD;AACrD,yDAAoE;AACpE,2DAAqD;AACrD,yDAAmD;AACnD,yEAAkE;AAClE,uEAAiF;AAEpE,QAAA,KAAK,GAAiB;;;;CAIlC,CAAA;AAEY,QAAA,QAAQ,GAAiB;;;;;;;;CAQrC,CAAA;AAEY,QAAA,KAAK,GAAG;IACnB,iCAAc;IACd,mCAAe;IACf,8CAAoB;IACpB,gDAAqB;IACrB,GAAG,+BAAM;IACT,iCAAc;IACd,mCAAe;IACf,GAAG,wBAAM;CACV,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../server/graphql/types/synchronization/index.ts"],"names":[],"mappings":";;;AAAA,2DAAqD;AACrD,yDAAoE;AACpE,2DAAqD;AACrD,yDAAmD;AACnD,yEAAkE;AAClE,uEAAiF;AAEpE,QAAA,KAAK,GAAiB;;;;CAIlC,CAAA;AAEY,QAAA,QAAQ,GAAiB;;;;;;;;;CASrC,CAAA;AAEY,QAAA,KAAK,GAAG;IACnB,iCAAc;IACd,mCAAe;IACf,8CAAoB;IACpB,gDAAqB;IACrB,GAAG,+BAAM;IACT,iCAAc;IACd,mCAAe;IACf,GAAG,wBAAM;CACV,CAAA"}
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./graphql"), exports);
18
18
  __exportStar(require("./middlewares"), exports);
19
19
  __exportStar(require("./migrations"), exports);
20
+ __exportStar(require("./entities"), exports);
20
21
  const biz_base_1 = require("@things-factory/biz-base");
21
22
  const typeorm_1 = require("typeorm");
22
23
  require("./routers/api");
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAAyB;AACzB,gDAA6B;AAC7B,+CAA4B;AAG5B,uDAAmD;AAEnD,qCAAuC;AACvC,yBAAsB;AACtB,oBAAiB;AAUjB,OAAO,CAAC,EAAE,CAAC,wBAA+B,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAO,EAAE,EAAE;IACjF,OAAO,CAAC,gBAAgB,GAAG,KAAK,EAAE,MAAc,EAAE,IAAU,EAAoB,EAAE;QAChF,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE;YACpB,OAAO,KAAK,CAAA;SACb;QAED,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE;YAChC,OAAO,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE,CAAA;SAChC;aAAM;YACL,MAAM,EAAE,OAAO,EAAE,GAAa,MAAM,IAAA,uBAAa,EAAC,mBAAQ,CAAC,CAAC,OAAO,CAAC;gBAClE,KAAK,EAAE,EAAE,MAAM,EAAE;gBACjB,SAAS,EAAE,CAAC,SAAS,EAAE,gBAAgB,CAAC;aACzC,CAAC,CAAA;YACF,MAAM,aAAa,GAAW,OAAO,CAAC,MAAM,CAAA;YAC5C,OAAO,aAAa,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE,CAAA;SACvC;IACH,CAAC,CAAA;AACH,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAAyB;AACzB,gDAA6B;AAC7B,+CAA4B;AAC5B,6CAA0B;AAG1B,uDAAmD;AAEnD,qCAAuC;AACvC,yBAAsB;AACtB,oBAAiB;AAUjB,OAAO,CAAC,EAAE,CAAC,wBAA+B,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAO,EAAE,EAAE;IACjF,OAAO,CAAC,gBAAgB,GAAG,KAAK,EAAE,MAAc,EAAE,IAAU,EAAoB,EAAE;QAChF,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE;YACpB,OAAO,KAAK,CAAA;SACb;QAED,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE;YAChC,OAAO,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE,CAAA;SAChC;aAAM;YACL,MAAM,EAAE,OAAO,EAAE,GAAa,MAAM,IAAA,uBAAa,EAAC,mBAAQ,CAAC,CAAC,OAAO,CAAC;gBAClE,KAAK,EAAE,EAAE,MAAM,EAAE;gBACjB,SAAS,EAAE,CAAC,SAAS,EAAE,gBAAgB,CAAC;aACzC,CAAC,CAAA;YACF,MAAM,aAAa,GAAW,OAAO,CAAC,MAAM,CAAA;YAC5C,OAAO,aAAa,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE,CAAA;SACvC;IACH,CAAC,CAAA;AACH,CAAC,CAAC,CAAA"}
@@ -17,4 +17,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./build-map"), exports);
18
18
  __exportStar(require("./get-warehouses"), exports);
19
19
  __exportStar(require("./order-no-generator"), exports);
20
+ __exportStar(require("./report-query-util"), exports);
20
21
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA2B;AAC3B,mDAAgC;AAChC,uDAAoC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA2B;AAC3B,mDAAgC;AAChC,uDAAoC;AACpC,sDAAmC"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.rawProductsQuery = void 0;
4
+ async function rawProductsQuery(tx, params, bizplace) {
5
+ let product = params.filters.find(data => data.name === 'product');
6
+ let productDesc = params.filters.find(data => data.name === 'productDescription');
7
+ let productQuery = '';
8
+ if (product) {
9
+ let productValue = product.value
10
+ .toLowerCase()
11
+ .split(',')
12
+ .map(prod => {
13
+ return "'%" + prod.trim().replace(/'/g, "''") + "%'";
14
+ })
15
+ .join(',');
16
+ productQuery = `AND (
17
+ Lower(prd.name) LIKE ANY(ARRAY[${productValue}])
18
+ OR Lower(prd.sku) LIKE ANY(ARRAY[${productValue}])
19
+ OR Lower(prd.description) LIKE ANY(ARRAY[${productValue}])
20
+ OR Lower(prd.brand) LIKE ANY(ARRAY[${productValue}])
21
+ OR Lower(prd.brand_sku) LIKE ANY(ARRAY[${productValue}])
22
+ )`;
23
+ }
24
+ let productDescQuery = '';
25
+ if (productDesc) {
26
+ productDescQuery = "AND Lower(description) LIKE '%" + productDesc.value.toLowerCase() + "%'";
27
+ }
28
+ await tx.query(`
29
+ create temp table temp_products on commit drop AS
30
+ (
31
+ select prd.id, prd.sku, prd.name, prd.description, prd.type, prd.id::varchar as product_id, prd.brand, prd.brand_sku
32
+ from products prd
33
+ inner join bizplaces b on b.id = prd.bizplace_id
34
+ inner join companies c on c.domain_id = b.domain_id
35
+ inner join bizplaces b2 on b2.company_id = c.id
36
+ where b2.id = $1
37
+ ${productQuery}
38
+ GROUP BY prd.id, prd.sku, prd.name, prd.description, prd.brand, prd.brand_sku
39
+ )`, [bizplace.id]);
40
+ }
41
+ exports.rawProductsQuery = rawProductsQuery;
42
+ //# sourceMappingURL=report-query-util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-query-util.js","sourceRoot":"","sources":["../../server/utils/report-query-util.ts"],"names":[],"mappings":";;;AAIO,KAAK,UAAU,gBAAgB,CAAC,EAAiB,EAAE,MAAiB,EAAE,QAAkB;IAC7F,IAAI,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAA;IAClE,IAAI,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,oBAAoB,CAAC,CAAA;IAEjF,IAAI,YAAY,GAAG,EAAE,CAAA;IACrB,IAAI,OAAO,EAAE;QACX,IAAI,YAAY,GAAG,OAAO,CAAC,KAAK;aAC7B,WAAW,EAAE;aACb,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,IAAI,CAAC,EAAE;YACV,OAAO,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,IAAI,CAAA;QACtD,CAAC,CAAC;aACD,IAAI,CAAC,GAAG,CAAC,CAAA;QACZ,YAAY,GAAG;uCACoB,YAAY;yCACV,YAAY;iDACJ,YAAY;2CAClB,YAAY;+CACR,YAAY;MACrD,CAAA;KACH;IAED,IAAI,gBAAgB,GAAG,EAAE,CAAA;IACzB,IAAI,WAAW,EAAE;QACf,gBAAgB,GAAG,gCAAgC,GAAG,WAAW,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,IAAI,CAAA;KAC7F;IAED,MAAM,EAAE,CAAC,KAAK,CACZ;;;;;;;;;QASI,YAAY;;MAEd,EACF,CAAC,QAAQ,CAAC,EAAE,CAAC,CACd,CAAA;AACH,CAAC;AA1CD,4CA0CC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/operato-hub",
3
- "version": "4.3.162",
3
+ "version": "4.3.165",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "client/index.js",
6
6
  "things-factory": true,
@@ -55,42 +55,42 @@
55
55
  "@operato/scene-tab": "^0.1.8",
56
56
  "@operato/scene-table": "^0.1.8",
57
57
  "@operato/scene-wheel-sorter": "^0.1.8",
58
- "@things-factory/api": "^4.3.159",
58
+ "@things-factory/api": "^4.3.163",
59
59
  "@things-factory/apptool-ui": "^4.3.159",
60
- "@things-factory/attachment-base": "^4.3.159",
61
- "@things-factory/auth-base": "^4.3.159",
62
- "@things-factory/auth-ui": "^4.3.159",
63
- "@things-factory/biz-base": "^4.3.159",
64
- "@things-factory/biz-ui": "^4.3.159",
65
- "@things-factory/board-service": "^4.3.159",
66
- "@things-factory/board-ui": "^4.3.159",
67
- "@things-factory/code-ui": "^4.3.159",
60
+ "@things-factory/attachment-base": "^4.3.163",
61
+ "@things-factory/auth-base": "^4.3.163",
62
+ "@things-factory/auth-ui": "^4.3.163",
63
+ "@things-factory/biz-base": "^4.3.163",
64
+ "@things-factory/biz-ui": "^4.3.163",
65
+ "@things-factory/board-service": "^4.3.163",
66
+ "@things-factory/board-ui": "^4.3.163",
67
+ "@things-factory/code-ui": "^4.3.163",
68
68
  "@things-factory/component-ui": "^4.3.159",
69
69
  "@things-factory/context-ui": "^4.3.159",
70
- "@things-factory/document-template-ui": "^4.3.159",
70
+ "@things-factory/document-template-ui": "^4.3.163",
71
71
  "@things-factory/export-ui": "^4.3.159",
72
72
  "@things-factory/export-ui-csv": "^4.3.159",
73
73
  "@things-factory/export-ui-excel": "^4.3.159",
74
- "@things-factory/geography": "^4.3.159",
74
+ "@things-factory/geography": "^4.3.163",
75
75
  "@things-factory/grist-ui": "^4.3.159",
76
76
  "@things-factory/help": "^4.3.159",
77
77
  "@things-factory/i18n-base": "^4.3.159",
78
78
  "@things-factory/import-ui": "^4.3.159",
79
79
  "@things-factory/import-ui-excel": "^4.3.159",
80
- "@things-factory/integration-accounting": "^4.3.162",
81
- "@things-factory/integration-fulfillment": "^4.3.159",
82
- "@things-factory/integration-lmd": "^4.3.159",
83
- "@things-factory/integration-marketplace": "^4.3.159",
84
- "@things-factory/integration-pos": "^4.3.159",
85
- "@things-factory/integration-sellercraft": "^4.3.159",
86
- "@things-factory/integration-sftp": "^4.3.159",
87
- "@things-factory/lite-menu": "^4.3.159",
80
+ "@things-factory/integration-accounting": "^4.3.165",
81
+ "@things-factory/integration-fulfillment": "^4.3.163",
82
+ "@things-factory/integration-lmd": "^4.3.163",
83
+ "@things-factory/integration-marketplace": "^4.3.163",
84
+ "@things-factory/integration-pos": "^4.3.163",
85
+ "@things-factory/integration-sellercraft": "^4.3.163",
86
+ "@things-factory/integration-sftp": "^4.3.163",
87
+ "@things-factory/lite-menu": "^4.3.163",
88
88
  "@things-factory/more-ui": "^4.3.159",
89
- "@things-factory/notification": "^4.3.159",
89
+ "@things-factory/notification": "^4.3.163",
90
90
  "@things-factory/pdf": "^4.3.159",
91
- "@things-factory/product-ui": "^4.3.161",
92
- "@things-factory/resource-ui": "^4.3.159",
93
- "@things-factory/sales-base": "^4.3.162",
91
+ "@things-factory/product-ui": "^4.3.165",
92
+ "@things-factory/resource-ui": "^4.3.163",
93
+ "@things-factory/sales-base": "^4.3.165",
94
94
  "@things-factory/scene-data-transform": "^4.3.159",
95
95
  "@things-factory/scene-excel": "^4.3.159",
96
96
  "@things-factory/scene-firebase": "^4.3.159",
@@ -102,11 +102,12 @@
102
102
  "@things-factory/scene-mqtt": "^4.3.159",
103
103
  "@things-factory/scene-restful": "^4.3.159",
104
104
  "@things-factory/scene-visualizer": "^4.3.159",
105
- "@things-factory/setting-ui": "^4.3.159",
105
+ "@things-factory/setting-ui": "^4.3.163",
106
106
  "@things-factory/shell": "^4.3.159",
107
107
  "@things-factory/system-ui": "^4.3.159",
108
- "@things-factory/warehouse-base": "^4.3.162",
109
- "@things-factory/worksheet-base": "^4.3.162",
108
+ "@things-factory/warehouse-base": "^4.3.165",
109
+ "@things-factory/worksheet-base": "^4.3.165",
110
+ "cron-parser": "^4.7.0",
110
111
  "koa2-swagger-ui": "^5.0.2",
111
112
  "swagger-jsdoc": "^5.0.0",
112
113
  "yamljs": "^0.3.0"
@@ -117,5 +118,5 @@
117
118
  "resolutions": {
118
119
  "core-js": "^3.16.0"
119
120
  },
120
- "gitHead": "c933f88307fc147abcfa0cf6cf5c9b62db187f24"
121
+ "gitHead": "92f67631971ac0fa8358d9f1a7c865893d1ae0bd"
121
122
  }
@@ -0,0 +1,49 @@
1
+ import { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
2
+
3
+ import { User } from '@things-factory/auth-base'
4
+ import { Domain } from '@things-factory/shell'
5
+ import { Email } from './email'
6
+
7
+ @Entity()
8
+ @Index('ix_email_attachment_0', (emailAttachment: EmailAttachment) => [emailAttachment.domain, emailAttachment.name])
9
+ export class EmailAttachment {
10
+ @PrimaryGeneratedColumn('uuid')
11
+ id: string
12
+
13
+ @ManyToOne(type => Domain)
14
+ domain: Domain
15
+
16
+ @Column()
17
+ name: string
18
+
19
+ @Column()
20
+ gqlString: string
21
+
22
+ @Column()
23
+ headers: string
24
+
25
+ @Column({ nullable: true })
26
+ variables: string
27
+
28
+ @Column({ nullable: true })
29
+ mappingFunction: string
30
+
31
+ @ManyToOne(type => Email, email => email.emailAttachments)
32
+ email: Email
33
+
34
+ @CreateDateColumn()
35
+ createdAt: Date
36
+
37
+ @UpdateDateColumn()
38
+ updatedAt: Date
39
+
40
+ @ManyToOne(type => User, {
41
+ nullable: true
42
+ })
43
+ creator: User
44
+
45
+ @ManyToOne(type => User, {
46
+ nullable: true
47
+ })
48
+ updater: User
49
+ }
@@ -0,0 +1,51 @@
1
+ import {
2
+ Column,
3
+ CreateDateColumn,
4
+ Entity,
5
+ Index,
6
+ ManyToOne,
7
+ PrimaryGeneratedColumn,
8
+ UpdateDateColumn
9
+ } from 'typeorm'
10
+
11
+ import { User } from '@things-factory/auth-base'
12
+ import { Domain } from '@things-factory/shell'
13
+ import { Email } from './email'
14
+
15
+ @Entity()
16
+ @Index('ix_email_recipient_0', (emailRecipient: EmailRecipient) => [emailRecipient.domain, emailRecipient.name])
17
+ export class EmailRecipient {
18
+ @PrimaryGeneratedColumn('uuid')
19
+ id: string
20
+
21
+ @ManyToOne(type => Domain)
22
+ domain: Domain
23
+
24
+ @Column()
25
+ name: string
26
+
27
+ @Column()
28
+ emailAddress: string
29
+
30
+ @Column()
31
+ type: string
32
+
33
+ @ManyToOne(type => Email, email => email.emailRecipients)
34
+ email: Email
35
+
36
+ @CreateDateColumn()
37
+ createdAt: Date
38
+
39
+ @UpdateDateColumn()
40
+ updatedAt: Date
41
+
42
+ @ManyToOne(type => User, {
43
+ nullable: true
44
+ })
45
+ creator: User
46
+
47
+ @ManyToOne(type => User, {
48
+ nullable: true
49
+ })
50
+ updater: User
51
+ }
@@ -0,0 +1,68 @@
1
+ import {
2
+ Column,
3
+ CreateDateColumn,
4
+ Entity,
5
+ Index,
6
+ ManyToOne,
7
+ OneToMany,
8
+ PrimaryGeneratedColumn,
9
+ UpdateDateColumn
10
+ } from 'typeorm'
11
+
12
+ import { User } from '@things-factory/auth-base'
13
+ import { Domain } from '@things-factory/shell'
14
+ import { EmailRecipient } from './email-recipient'
15
+ import { EmailAttachment } from './email-attachment'
16
+
17
+ @Entity()
18
+ @Index('ix_email_0', (email: Email) => [email.domain, email.name], { unique: true })
19
+ export class Email {
20
+ @PrimaryGeneratedColumn('uuid')
21
+ id: string
22
+
23
+ @ManyToOne(type => Domain)
24
+ domain: Domain
25
+
26
+ @Column()
27
+ name: string
28
+
29
+ @Column()
30
+ schedule: string
31
+
32
+ @Column()
33
+ subject: string
34
+
35
+ @Column({ nullable: true })
36
+ content: string
37
+
38
+ @Column({ default: true })
39
+ active: boolean
40
+
41
+ @Column({ nullable: true })
42
+ timezoneOffset: number
43
+
44
+ @Column({ nullable: true })
45
+ partnerBlackList: string
46
+
47
+ @OneToMany(type => EmailRecipient, emailRecipient => emailRecipient.email)
48
+ emailRecipients: EmailRecipient[]
49
+
50
+ @OneToMany(type => EmailAttachment, emailAttachment => emailAttachment.email)
51
+ emailAttachments: EmailAttachment[]
52
+
53
+ @CreateDateColumn()
54
+ createdAt: Date
55
+
56
+ @UpdateDateColumn()
57
+ updatedAt: Date
58
+
59
+ @ManyToOne(type => User, {
60
+ nullable: true
61
+ })
62
+ creator: User
63
+
64
+ @ManyToOne(type => User, {
65
+ nullable: true
66
+ })
67
+ updater: User
68
+ }
@@ -0,0 +1,7 @@
1
+ import { Email } from './email'
2
+ import { EmailRecipient } from './email-recipient'
3
+ import { EmailAttachment } from './email-attachment'
4
+
5
+ export const entities = [Email, EmailRecipient, EmailAttachment ]
6
+
7
+ export { Email, EmailRecipient, EmailAttachment }
@@ -0,0 +1,5 @@
1
+ import { sendEmailsResolver } from './send-emails'
2
+
3
+ export const Mutation = {
4
+ ...sendEmailsResolver
5
+ }
@@ -0,0 +1,196 @@
1
+ import * as cronParser from 'cron-parser'
2
+ import gql from 'graphql-tag'
3
+ import { getRepository, In, Not } from 'typeorm'
4
+
5
+ import { Partner, User } from '@things-factory/auth-base'
6
+ import { Bizplace } from '@things-factory/biz-base'
7
+ import { objDataToExcel, sendEmailSes } from '@things-factory/email-base'
8
+ import { logger } from '@things-factory/env'
9
+ import { GraphqlLocalClient } from '@things-factory/shell'
10
+
11
+ import { Email } from '../../../entities'
12
+
13
+ export const sendEmailsResolver = {
14
+ async sendEmails(_: any, {}, context: any) {
15
+ const emails: Email[] = await getRepository(Email).find({
16
+ where: { active: true },
17
+ relations: ['domain', 'creator', 'creator.domains', 'emailRecipients', 'emailAttachments']
18
+ })
19
+
20
+ try {
21
+ for (let email of emails) {
22
+ // parse cron job format (i.e. * * * * *)
23
+ let interval: any = cronParser.parseExpression(email.schedule)
24
+ let now: any = new Date()
25
+ let thirtyMinsAgo: any = new Date(now - 30 * 60000)
26
+ let dag: any = new Date(interval.prev()) // get the most recent schedule
27
+ let startDate: any = new Date(interval.prev())
28
+
29
+ if (dag < now && dag > thirtyMinsAgo) {
30
+ try {
31
+ processEmailCronJob(email, startDate.toISOString(), now.toISOString()) // removed await
32
+ } catch (e) {
33
+ logger.error(`[auto_email_log_by_id(${email.id})] ${e}`)
34
+ }
35
+ }
36
+ }
37
+ } catch (e) {
38
+ logger.error(`[auto_email_log] ${e}`)
39
+ }
40
+
41
+ return true
42
+ }
43
+ }
44
+
45
+ function replaceValues(variablesString: string, values: any = []) {
46
+ for (let obj of values) {
47
+ variablesString = variablesString.replace(obj.name, obj.value)
48
+ }
49
+ return JSON.parse(variablesString)
50
+ }
51
+
52
+ // NOTE: might show unused because of usage in eval function
53
+ function flattenObject(obj, delimiter = '|') {
54
+ var objResult = {}
55
+ for (var items in obj) {
56
+ if (!Object.hasOwnProperty.bind(obj)(items)) continue
57
+
58
+ if (!!obj[items] && typeof obj[items] == 'object') {
59
+ var flatObject = flattenObject(obj[items], delimiter)
60
+ for (var x in flatObject) {
61
+ if (!Object.hasOwnProperty.bind(flatObject)(x)) continue
62
+
63
+ objResult[items + delimiter + x] = flatObject[x]
64
+ }
65
+ } else {
66
+ objResult[items] = obj[items]
67
+ }
68
+ }
69
+ return objResult
70
+ }
71
+
72
+ async function processEmailCronJob(email, fromDate, toDate) {
73
+ let attachments: any = []
74
+ // black list filtration
75
+ let partnerBlackList = JSON.parse(email.partnerBlackList) || []
76
+ //
77
+
78
+ const partners: Partner[] = await getRepository(Partner).find({
79
+ where: { domain: email.domain, id: Not(In(partnerBlackList)) },
80
+ relations: ['partnerDomain']
81
+ })
82
+
83
+ // retrieve and process xlsx attachmennts
84
+ for (let attachment of email.emailAttachments) {
85
+ let client = GraphqlLocalClient.client
86
+
87
+ for (let partner of partners) {
88
+ const bizplace: Bizplace = await getRepository(Bizplace).findOne({
89
+ where: { domain: partner.partnerDomain }
90
+ })
91
+
92
+ // date params processing
93
+ // let dateValue = new Date()
94
+ // let yesterday = dateValue.getDate() - 1
95
+ // let yesterdayBegin: any = new Date(dateValue.setDate(yesterday))
96
+ // let yesterdayEnd: any = new Date(dateValue.setDate(yesterday))
97
+
98
+ // yesterdayBegin.setHours(0, 0, 0, 0)
99
+ // yesterdayEnd.setHours(23, 59, 59, 999)
100
+
101
+ let timezoneOffset = email?.timezoneOffset || 0
102
+
103
+ let curDate = new Date()
104
+
105
+ let prevMonth = curDate.getMonth() - 1
106
+ let prevMonthBegin: any = new Date(curDate.setDate(prevMonth))
107
+ prevMonthBegin.setHours(0, 0, 0, 0)
108
+ let prevMonthBeginDateTime = new Date(prevMonthBegin - timezoneOffset * 60000).toISOString()
109
+
110
+ let prevWeek = curDate.getDate() - 7 // subtract 1 week
111
+ let prevWeekBegin: any = new Date(curDate.setDate(prevWeek))
112
+ prevWeekBegin.setHours(0, 0, 0, 0)
113
+ let prevWeekBeginDateTime = new Date(prevWeekBegin - timezoneOffset * 60000).toISOString()
114
+
115
+ let prevDay = curDate.getDate() - 1 // subtract 1 day
116
+ let prevDayBegin: any = new Date(curDate.setDate(prevDay))
117
+ prevDayBegin.setHours(0, 0, 0, 0)
118
+ let prevDayBeginDateTime = new Date(prevDayBegin - timezoneOffset * 60000).toISOString()
119
+
120
+ let endDate: any = curDate
121
+ endDate.setHours(23, 59, 59, 999)
122
+ let endDateTime = new Date(endDate - timezoneOffset * 60000).toISOString()
123
+
124
+ // let fromDate = new Date(yesterdayBegin - timezoneOffset * 60000).toISOString()
125
+ // let toDate = new Date(yesterdayEnd - timezoneOffset * 60000).toISOString()
126
+
127
+ // to trace UTC conversion in production
128
+ logger.info(`[email_utc_conversion] fromDate: ${fromDate}, toDate: ${toDate}`)
129
+
130
+ let variables = replaceValues(attachment.variables, [
131
+ { name: '{{bizplaceId}}', value: `"${bizplace.id}"` },
132
+ { name: '{{timezoneOffset}}', value: `${timezoneOffset}` },
133
+ { name: '{{lastRunDateTime}}', value: `"${fromDate}"` },
134
+ { name: '{{toDateTime}}', value: `"${endDateTime}"` },
135
+ { name: '{{prevMonthBeginDateTime}}', value: `"${prevMonthBeginDateTime}"` },
136
+ { name: '{{prevWeekBeginDateTime}}', value: `"${prevWeekBeginDateTime}"` },
137
+ { name: '{{prevDayBeginDateTime}}', value: `"${prevDayBeginDateTime}"` }
138
+ ])
139
+
140
+ let user: User = email.creator
141
+ delete user.creatorId
142
+ delete user.updaterId
143
+
144
+ // might show unused because of usage in eval
145
+ const response = await client.query({
146
+ query: gql`
147
+ ${attachment.gqlString}
148
+ `,
149
+ variables: variables || {},
150
+ context: { state: { domain: email.domain, user } }
151
+ } as any)
152
+
153
+ let mappedResponse = eval(attachment.mappingFunction)
154
+
155
+ let header = JSON.parse(attachment.headers)
156
+
157
+ let excelResponse = await objDataToExcel({ name: 'name', data: { header, data: mappedResponse } })
158
+
159
+ attachments.push({
160
+ filename: `${bizplace.name} - ${attachment.name}.xlsx`,
161
+ content: excelResponse,
162
+ contentType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
163
+ })
164
+ }
165
+ }
166
+
167
+ // modify content and subject
168
+ let bizplace: Bizplace = await getRepository(Bizplace).findOne({
169
+ where: { domain: email.domain },
170
+ relations: ['company']
171
+ })
172
+
173
+ let modifiedContent = email.content.replace('{{companyName}}', bizplace.company.name)
174
+
175
+ let modifiedSubject = email.subject.replace('{{warehouseName}}', email.domain.name)
176
+ modifiedSubject = modifiedSubject.replace('{{reportDate}}', new Date().toLocaleDateString('en-GB'))
177
+ //
178
+
179
+ let res = await sendEmailSes({
180
+ attachments,
181
+ subject: modifiedSubject,
182
+ content: modifiedContent,
183
+ toMailList:
184
+ email.emailRecipients
185
+ .filter(er => er.type == 'to')
186
+ .map(er => {
187
+ return er.emailAddress
188
+ }) || [],
189
+ ccMailList:
190
+ email.emailRecipients
191
+ .filter(er => er.type == 'cc')
192
+ .map(er => {
193
+ return er.emailAddress
194
+ }) || []
195
+ })
196
+ }
@@ -2,7 +2,9 @@ import * as Generators from './generators'
2
2
  import * as Oauth2 from './oauth2'
3
3
  import * as Invitations from './invitations'
4
4
  import * as Synchronization from './synchronization'
5
+ import * as Email from './email'
6
+ import * as Reports from './reports'
5
7
 
6
- export const queries = [Synchronization.Query, Oauth2.Query]
8
+ export const queries = [Synchronization.Query, Oauth2.Query, Reports.Query]
7
9
 
8
- export const mutations = [Generators.Mutation, Invitations.Mutation, Synchronization.Mutation]
10
+ export const mutations = [Generators.Mutation, Invitations.Mutation, Synchronization.Mutation, Email.Mutation]