@things-factory/operato-hub 4.3.162 → 4.3.163

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 +177 -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 +173 -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.163",
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.163",
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.163",
92
+ "@things-factory/resource-ui": "^4.3.163",
93
+ "@things-factory/sales-base": "^4.3.163",
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.163",
109
+ "@things-factory/worksheet-base": "^4.3.163",
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": "082339ccf43992dc550c7078c605cc2794758c7f"
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,173 @@
1
+ import { getConnection, getRepository, In, Not } from 'typeorm'
2
+ import { Email, EmailRecipient, EmailAttachment } from '../../../entities'
3
+ import { Partner } from '@things-factory/auth-base'
4
+ import { Bizplace } from '@things-factory/biz-base'
5
+ import { GraphqlLocalClient } from '@things-factory/shell'
6
+ import gql from 'graphql-tag'
7
+ import { objDataToExcel, sendEmailSes } from '@things-factory/email-base'
8
+ import { User } from '@things-factory/auth-base'
9
+ import { logger } from '@things-factory/env'
10
+ import * as cronParser from 'cron-parser'
11
+
12
+ export const sendEmailsResolver = {
13
+ async sendEmails(_: any, {}, context: any) {
14
+ const emails: Email[] = await getRepository(Email).find({
15
+ where: { active: true },
16
+ relations: ['domain', 'creator', 'creator.domains', 'emailRecipients', 'emailAttachments']
17
+ })
18
+
19
+ try {
20
+ for (let email of emails) {
21
+ // parse cron job format (i.e. * * * * *)
22
+ let interval: any = cronParser.parseExpression(email.schedule)
23
+ let now: any = new Date()
24
+ let thirtyMinsAgo: any = new Date(now - 30 * 60000)
25
+ let dag: any = new Date(interval.prev()) // get the most recent schedule
26
+ let startDate: any = new Date(interval.prev())
27
+
28
+ if (dag < now && dag > thirtyMinsAgo) {
29
+ try {
30
+ processEmailCronJob(email, startDate.toISOString(), now.toISOString()) // removed await
31
+ } catch (e) {
32
+ logger.error(`[auto_email_log_by_id(${email.id})] ${e}`)
33
+ }
34
+ }
35
+ }
36
+ } catch (e) {
37
+ logger.error(`[auto_email_log] ${e}`)
38
+ }
39
+
40
+ return true
41
+ }
42
+ }
43
+
44
+ function replaceValues(variablesString: string, values: any = []) {
45
+ for (let obj of values) {
46
+ variablesString = variablesString.replace(obj.name, obj.value)
47
+ }
48
+ return JSON.parse(variablesString)
49
+ }
50
+
51
+ // NOTE: might show unused because of usage in eval function
52
+ function flattenObject(obj, delimiter = '|') {
53
+ var objResult = {}
54
+ for (var items in obj) {
55
+ if (!Object.hasOwnProperty.bind(obj)(items)) continue
56
+
57
+ if (!!obj[items] && typeof obj[items] == 'object') {
58
+ var flatObject = flattenObject(obj[items], delimiter)
59
+ for (var x in flatObject) {
60
+ if (!Object.hasOwnProperty.bind(flatObject)(x)) continue
61
+
62
+ objResult[items + delimiter + x] = flatObject[x]
63
+ }
64
+ } else {
65
+ objResult[items] = obj[items]
66
+ }
67
+ }
68
+ return objResult
69
+ }
70
+
71
+ async function processEmailCronJob(email, fromDate, toDate) {
72
+ let attachments: any = []
73
+ // black list filtration
74
+ let partnerBlackList = JSON.parse(email.partnerBlackList) || []
75
+ //
76
+
77
+ const partners: Partner[] = await getRepository(Partner).find({
78
+ where: { domain: email.domain, id: Not(In(partnerBlackList)) },
79
+ relations: ['partnerDomain']
80
+ })
81
+
82
+ // retrieve and process xlsx attachmennts
83
+ for (let attachment of email.emailAttachments) {
84
+ let client = GraphqlLocalClient.client
85
+
86
+ for (let partner of partners) {
87
+ const bizplace: Bizplace = await getRepository(Bizplace).findOne({
88
+ where: { domain: partner.partnerDomain }
89
+ })
90
+
91
+ // date params processing
92
+ // let dateValue = new Date()
93
+ // let yesterday = dateValue.getDate() - 1
94
+ // let yesterdayBegin: any = new Date(dateValue.setDate(yesterday))
95
+ // let yesterdayEnd: any = new Date(dateValue.setDate(yesterday))
96
+
97
+ // yesterdayBegin.setHours(0, 0, 0, 0)
98
+ // yesterdayEnd.setHours(23, 59, 59, 999)
99
+
100
+ let timezoneOffset = email?.timezoneOffset || 0
101
+
102
+ // let fromDate = new Date(yesterdayBegin - timezoneOffset * 60000).toISOString()
103
+ // let toDate = new Date(yesterdayEnd - timezoneOffset * 60000).toISOString()
104
+ //
105
+
106
+ // to trace UTC conversion in production
107
+ logger.info(`[email_utc_conversion] fromDate: ${fromDate}, toDate: ${toDate}`)
108
+ //
109
+
110
+ let variables = replaceValues(attachment.variables, [
111
+ { name: '{{bizplaceIdValue}}', value: `"${bizplace.id}"` },
112
+ { name: '{{timezoneOffsetValue}}', value: `${timezoneOffset}` },
113
+ { name: '{{fromDateValue}}', value: `"${fromDate}"` },
114
+ { name: '{{toDateValue}}', value: `"${toDate}"` }
115
+ ])
116
+
117
+ let user: User = email.creator
118
+ delete user.creatorId
119
+ delete user.updaterId
120
+
121
+ // might show unused because of usage in eval
122
+ const response = await client.query({
123
+ query: gql`
124
+ ${attachment.gqlString}
125
+ `,
126
+ variables: variables || {},
127
+ context: { state: { domain: email.domain, user } }
128
+ } as any)
129
+
130
+ let mappedResponse = eval(attachment.mappingFunction)
131
+
132
+ let header = JSON.parse(attachment.headers)
133
+
134
+ let excelResponse = await objDataToExcel({ name: 'name', data: { header, data: mappedResponse } })
135
+
136
+ attachments.push({
137
+ filename: `${bizplace.name} - ${attachment.name}.xlsx`,
138
+ content: excelResponse,
139
+ contentType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
140
+ })
141
+ }
142
+ }
143
+
144
+ // modify content and subject
145
+ let bizplace: Bizplace = await getRepository(Bizplace).findOne({
146
+ where: { domain: email.domain },
147
+ relations: ['company']
148
+ })
149
+
150
+ let modifiedContent = email.content.replace('{{companyName}}', bizplace.company.name)
151
+
152
+ let modifiedSubject = email.subject.replace('{{warehouseName}}', email.domain.name)
153
+ modifiedSubject = modifiedSubject.replace('{{reportDate}}', new Date().toLocaleDateString('en-GB'))
154
+ //
155
+
156
+ let res = await sendEmailSes({
157
+ attachments,
158
+ subject: modifiedSubject,
159
+ content: modifiedContent,
160
+ toMailList:
161
+ email.emailRecipients
162
+ .filter(er => er.type == 'to')
163
+ .map(er => {
164
+ return er.emailAddress
165
+ }) || [],
166
+ ccMailList:
167
+ email.emailRecipients
168
+ .filter(er => er.type == 'cc')
169
+ .map(er => {
170
+ return er.emailAddress
171
+ }) || []
172
+ })
173
+ }
@@ -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]