Compare commits

...

55 Commits

Author SHA1 Message Date
Allan Carr
6cac0f9594 IO-3010 Task Table UI refactor
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-10-30 17:38:09 -07:00
Dave Richer
9b67148522 Merged in release/2024-11-01 (pull request #1866)
Release/2024-11-01 into master-AIO - IO-2979 - Misc Logger related fixes
2024-10-29 20:10:02 +00:00
Dave Richer
6b501e4619 release/2024-11-01 - Misc fixes
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-29 11:02:08 -07:00
Dave Richer
42f1d6fa13 release/2024-11-01 - Misc fixes
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-29 10:53:09 -07:00
Dave Richer
3f247a9227 release/2024-11-01 - Misc fixes
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-29 09:54:45 -07:00
Dave Richer
63b914731b release/2024-11-01 - Misc fixes
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-29 08:25:54 -07:00
Dave Richer
23f8f69bbe release/2024-11-01 - Misc fixes
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-29 08:19:58 -07:00
Dave Richer
fc3ea2bdf8 release/2024-11-01 - Misc fixes
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-29 07:37:40 -07:00
Dave Richer
96e970faf7 release/2024-11-01 - Misc fixes
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-28 18:16:48 -07:00
Dave Richer
c133195607 release/2024-11-01 - Misc fixes
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-28 17:48:43 -07:00
Dave Richer
d75ea2b1a6 release/2024-11-01 - Misc fixes
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-28 17:38:46 -07:00
Dave Richer
ec0fd840e4 Merged in feature/IO-2979-DST (pull request #1856)
IO-2979-DST into release/2024-11-01 - DST Related Fixes
2024-10-28 21:05:57 +00:00
Dave Richer
971a81fc27 feature/IO-2979-DST - Finish DST Stuff
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-28 14:04:14 -07:00
Dave Richer
19050d31f7 Merged in release/2024-11-01 (pull request #1853)
Release/2024-11-01 into master-AIO  - Fix Logging Issues
2024-10-28 20:39:28 +00:00
Dave Richer
e605433379 Merge remote-tracking branch 'origin/release/2024-11-01' into feature/IO-2979-DST 2024-10-28 13:10:08 -07:00
Dave Richer
b9ebb70b7a release/2024-11-01 - Remove Trace Log Level
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-28 13:06:47 -07:00
Dave Richer
79ed6f2388 release/2024-11-01 - Remove Trace Log Level
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-28 12:24:40 -07:00
Dave Richer
785449a986 release/2024-11-01 - Remove Trace Log Level
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-28 12:03:48 -07:00
Dave Richer
0b7d469e0e feature/IO-2979-DST - Finish DST
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-28 11:55:13 -07:00
Dave Richer
a57156756e feature/IO-2979-DST - Normalize usages of dayjs to dayjs not day, move locale hook
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-28 11:03:30 -07:00
Dave Richer
c4c30d98d4 release/2024-11-01 - Adjust hostname check
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-28 10:07:10 -07:00
Dave Richer
d4e8803b13 release/2024-11-01 - Adjust client body buffer size
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-28 09:47:27 -07:00
Dave Richer
1f2786ddec release/2024-11-01 - Fix some log things
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-28 09:31:37 -07:00
Dave Richer
e90cda07e4 Merged in release/2024-10-25 (pull request #1848)
Release/2024-10-25 - IO-2921, IO-2966, IO-2973, IO-2974, IO-2978, IO-2992, IO-2996, IO-2998
2024-10-26 04:48:05 +00:00
Dave Richer
9793daa04c release/2024-10-25 - Add The local email viewer to the reference folder.
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-25 11:58:50 -07:00
Allan Carr
117ced8fe7 Merged in feature/IO-2973-Created-By-Tasks (pull request #1846)
IO-2973 Created By Tasks

Approved-by: Dave Richer
2024-10-25 18:53:11 +00:00
Dave Richer
e7909205d1 feature/IO-2973-Created-By-Tasks - Merge in release, fix conflicts
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-25 11:50:11 -07:00
Dave Richer
18028a70ab feature/IO-2973-Created-By-Tasks - Merge in release, fix conflicts
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-25 11:22:59 -07:00
Dave Richer
eeb8d8d26f release/2024-10-25 - Clean up referenceDocuments
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-25 11:21:10 -07:00
Allan Carr
23659fc412 IO-2973 Created By Tasks
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-10-25 11:19:40 -07:00
Patrick Fic
ba65057782 Merged in feature/IO-2974-add-comment-to-schedule (pull request #1842)
IO-2974 add comment to schedule.

Approved-by: Dave Richer
2024-10-25 17:03:06 +00:00
Dave Richer
60a859cac8 Merged in feature/IO-2998-enhanced-api-logging (pull request #1843)
feature/IO-2998-enhanced-api-logging - Missing package
2024-10-25 15:38:46 +00:00
Dave Richer
0cfe26093c feature/IO-2998-enhanced-api-logging - Missing package
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-25 08:37:56 -07:00
Patrick Fic
d085a9c7c9 IO-2974 add comment to schedule. 2024-10-25 08:33:17 -07:00
Dave Richer
ec518a0593 Merged in feature/IO-2998-enhanced-api-logging (pull request #1840)
feature/IO-2998-enhanced-api-logging - Missing package
2024-10-25 15:30:26 +00:00
Dave Richer
1cd64ab6f1 feature/IO-2998-enhanced-api-logging - Missing package
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-25 08:29:51 -07:00
Dave Richer
26836f662a Merged in feature/IO-2998-enhanced-api-logging (pull request #1838)
feature/IO-2998-enhanced-api-logging - Finish
2024-10-25 15:12:24 +00:00
Dave Richer
111f280674 feature/IO-2998-enhanced-api-logging - Finish
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-25 08:11:33 -07:00
Dave Richer
6e88faa9d8 Merged in feature/IO-2998-enhanced-api-logging (pull request #1836)
Feature/IO-2998 into Release/2024-10-25
2024-10-25 14:11:26 +00:00
Dave Richer
1ca8b2a78d feature/IO-2998-enhanced-api-logging - Finish
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-24 14:36:35 -07:00
Dave Richer
cd2a7cad7f feature/IO-2998-enhanced-api-logging - Finish
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-10-24 14:21:35 -07:00
Dave Richer
ed16156957 Merge remote-tracking branch 'origin/release/2024-10-25' into feature/IO-2998-enhanced-api-logging 2024-10-24 13:18:21 -07:00
Patrick Fic
8dc1f7e08f IO-2998 remove graylog and additional erroneous console logs. 2024-10-24 12:18:39 -07:00
Patrick Fic
2d3c13c587 IO-2998 Add winston and replace logger.js 2024-10-24 11:50:54 -07:00
Allan Carr
5486907639 Merged in feature/IO-2978-Production-not-in-Production-Status (pull request #1834)
IO-2978 Production not in Production Status

Approved-by: Dave Richer
2024-10-24 16:49:59 +00:00
Allan Carr
9233cef23a IO-2978 Production not in Production Status
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-10-23 17:02:45 -07:00
Dave Richer
c16eafe892 Merged in feature/IO-2996-Package-Updates-Docker-Debugging (pull request #1832)
feature/IO-2996-Package-Updates-Docker-Debugging - Maintenance
2024-10-23 17:03:44 +00:00
Allan Carr
4201f61548 Merged in feature/IO-2966-Contract-Create-Page-Leave-Warning (pull request #1831)
IO-2966 Contract Create Page Leave Warning

Approved-by: Dave Richer
2024-10-23 14:58:22 +00:00
Allan Carr
d04fc76840 IO-2966 Contract Create Page Leave Warning
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-10-22 17:48:40 -07:00
Allan Carr
0f84adc752 IO-2966 Contract Create Page Leave Warning
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-10-22 17:35:54 -07:00
Allan Carr
fbefd80959 Merged in feature/IO-2921-CARSTAR-Canada-Chatter-Integration (pull request #1830)
IO-2921 CHATTER correct secertmanager call from undefined variable to string

Approved-by: Dave Richer
2024-10-22 15:08:11 +00:00
Allan Carr
6a691b54c8 Merged in feature/IO-2992-Bill-Line-UI-Table (pull request #1829)
IO-2992 Bill Line column Width with Word Breaks

Approved-by: Dave Richer
2024-10-22 15:07:43 +00:00
Allan Carr
fc75717d32 IO-2921 CHATTER correct secertmanager call from undefined variable to string
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-10-21 12:43:20 -07:00
Allan Carr
1459c6e993 Merge branch 'master-AIO' into feature/IO-2921-CARSTAR-Canada-Chatter-Integration
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-10-21 12:42:45 -07:00
Allan Carr
f50292f9bf IO-2992 Bill Line column Width with Word Breaks
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-10-21 10:53:32 -07:00
97 changed files with 6340 additions and 3992 deletions

View File

@@ -1 +1,2 @@
client_max_body_size 50M; client_max_body_size 50M;
client_body_buffer_size 5M;

View File

@@ -0,0 +1 @@
node_modules

View File

@@ -0,0 +1,7 @@
This will connect to your dockers local stack session and render the email in HTML.
```shell
node index.js
```
http://localhost:3334

View File

@@ -0,0 +1,116 @@
// index.js
import express from 'express';
import fetch from 'node-fetch';
import {simpleParser} from 'mailparser';
const app = express();
const PORT = 3334;
app.get('/', async (req, res) => {
try {
const response = await fetch('http://localhost:4566/_aws/ses');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
const messagesHtml = await parseMessages(data.messages);
res.send(renderHtml(messagesHtml));
} catch (error) {
console.error('Error fetching messages:', error);
res.status(500).send('Error fetching messages');
}
});
async function parseMessages(messages) {
const parsedMessages = await Promise.all(
messages.map(async (message, index) => {
try {
const parsed = await simpleParser(message.RawData);
return `
<div class="shadow-md rounded-lg p-4 mb-6" style="background-color: lightgray">
<div class="shadow-md rounded-lg p-4 mb-6" style="background-color: white">
<div class="mb-2">
<span class="font-bold text-lg">Message ${index + 1}</span>
</div>
<div class="mb-2">
<span class="font-semibold">From:</span> ${message.Source}
</div>
<div class="mb-2">
<span class="font-semibold">Region:</span> ${message.Region}
</div>
<div class="mb-2">
<span class="font-semibold">Timestamp:</span> ${message.Timestamp}
</div>
</div>
<div class="prose">
${parsed.html || parsed.textAsHtml || 'No HTML content available'}
</div>
</div>
`;
} catch (error) {
console.error('Error parsing email:', error);
return `
<div class="bg-white shadow-md rounded-lg p-4 mb-6">
<div class="mb-2">
<span class="font-bold text-lg">Message ${index + 1}</span>
</div>
<div class="mb-2">
<span class="font-semibold">From:</span> ${message.Source}
</div>
<div class="mb-2">
<span class="font-semibold">Region:</span> ${message.Region}
</div>
<div class="mb-2">
<span class="font-semibold">Timestamp:</span> ${message.Timestamp}
</div>
<div class="text-red-500">
Error parsing email content
</div>
</div>
`;
}
})
);
return parsedMessages.join('');
}
function renderHtml(messagesHtml) {
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Email Messages Viewer</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
background-color: #f3f4f6;
font-family: Arial, sans-serif;
}
.container {
max-width: 800px;
margin: 50px auto;
padding: 20px;
}
.prose {
line-height: 1.6;
}
</style>
</head>
<body>
<div class="container bg-white shadow-lg rounded-lg p-6">
<h1 class="text-2xl font-bold text-center mb-6">Email Messages Viewer</h1>
<div id="messages-container">
${messagesHtml}
</div>
</div>
</body>
</html>
`;
}
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
{
"name": "localemailviewer",
"version": "1.0.0",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"express": "^4.21.1",
"mailparser": "^3.7.1",
"node-fetch": "^3.3.2"
}
}

View File

@@ -2,8 +2,6 @@ import { ApolloProvider } from "@apollo/client";
import { SplitFactoryProvider, SplitSdk } from "@splitsoftware/splitio-react"; import { SplitFactoryProvider, SplitSdk } from "@splitsoftware/splitio-react";
import { ConfigProvider } from "antd"; import { ConfigProvider } from "antd";
import enLocale from "antd/es/locale/en_US"; import enLocale from "antd/es/locale/en_US";
import dayjs from "../utils/day";
import "dayjs/locale/en";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component"; import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component";
@@ -19,8 +17,6 @@ if (import.meta.env.DEV) {
Userpilot.initialize("NX-69145f08"); Userpilot.initialize("NX-69145f08");
} }
dayjs.locale("en");
const config = { const config = {
core: { core: {
authorizationKey: import.meta.env.VITE_APP_SPLIT_API, authorizationKey: import.meta.env.VITE_APP_SPLIT_API,

View File

@@ -7,10 +7,10 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import CiecaSelect from "../../utils/Ciecaselect"; import CiecaSelect from "../../utils/Ciecaselect";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
import BillLineSearchSelect from "../bill-line-search-select/bill-line-search-select.component"; import BillLineSearchSelect from "../bill-line-search-select/bill-line-search-select.component";
import BilllineAddInventory from "../billline-add-inventory/billline-add-inventory.component"; import BilllineAddInventory from "../billline-add-inventory/billline-add-inventory.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.component"; import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser //currentUser: selectCurrentUser
@@ -72,7 +72,14 @@ export function BillEnterModalLinesComponent({
<BillLineSearchSelect <BillLineSearchSelect
disabled={disabled} disabled={disabled}
options={lineData} options={lineData}
style={{ width: "100%", minWidth: "10rem" }} style={{
width: "20rem",
maxWidth: "20rem",
minWidth: "10rem",
whiteSpace: "normal",
height: "auto",
minHeight: "32px" // default height of Ant Design inputs
}}
allowRemoved={form.getFieldValue("is_credit_memo") || false} allowRemoved={form.getFieldValue("is_credit_memo") || false}
onSelect={(value, opt) => { onSelect={(value, opt) => {
setFieldsValue({ setFieldsValue({
@@ -105,7 +112,7 @@ export function BillEnterModalLinesComponent({
title: t("billlines.fields.line_desc"), title: t("billlines.fields.line_desc"),
dataIndex: "line_desc", dataIndex: "line_desc",
editable: true, editable: true,
width: "20rem",
formItemProps: (field) => { formItemProps: (field) => {
return { return {
key: `${field.index}line_desc`, key: `${field.index}line_desc`,
@@ -119,7 +126,7 @@ export function BillEnterModalLinesComponent({
] ]
}; };
}, },
formInput: (record, index) => <Input disabled={disabled} /> formInput: (record, index) => <Input.TextArea disabled={disabled} autoSize />
}, },
{ {
title: t("billlines.fields.quantity"), title: t("billlines.fields.quantity"),

View File

@@ -11,7 +11,7 @@ const BillLineSearchSelect = ({ options, disabled, allowRemoved, ...restProps },
disabled={disabled} disabled={disabled}
ref={ref} ref={ref}
showSearch showSearch
popupMatchSelectWidth={false} popupMatchSelectWidth={true}
optionLabelProp={"name"} optionLabelProp={"name"}
// optionFilterProp="line_desc" // optionFilterProp="line_desc"
filterOption={(inputValue, option) => { filterOption={(inputValue, option) => {
@@ -43,7 +43,7 @@ const BillLineSearchSelect = ({ options, disabled, allowRemoved, ...restProps },
item.oem_partno ? ` - ${item.oem_partno}` : "" item.oem_partno ? ` - ${item.oem_partno}` : ""
}${item.alt_partno ? ` (${item.alt_partno})` : ""}`.trim(), }${item.alt_partno ? ` (${item.alt_partno})` : ""}`.trim(),
label: ( label: (
<> <div style={{ whiteSpace: 'normal', wordBreak: 'break-word' }}>
<span> <span>
{`${item.removed ? `(REMOVED) ` : ""}${item.line_desc}${ {`${item.removed ? `(REMOVED) ` : ""}${item.line_desc}${
item.oem_partno ? ` - ${item.oem_partno}` : "" item.oem_partno ? ` - ${item.oem_partno}` : ""
@@ -57,7 +57,7 @@ const BillLineSearchSelect = ({ options, disabled, allowRemoved, ...restProps },
<span style={{ float: "right", paddingleft: "1rem" }}> <span style={{ float: "right", paddingleft: "1rem" }}>
{item.act_price ? `$${item.act_price && item.act_price.toFixed(2)}` : ``} {item.act_price ? `$${item.act_price && item.act_price.toFixed(2)}` : ``}
</span> </span>
</> </div>
) )
})) }))
]} ]}

View File

@@ -1,15 +1,17 @@
import { WarningFilled } from "@ant-design/icons"; import { WarningFilled } from "@ant-design/icons";
import { Form, Input, InputNumber, Space } from "antd"; import { Form, Input, InputNumber, Space } from "antd";
import dayjs from "../../utils/day";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { DateFormatter } from "../../utils/DateFormatter"; import { DateFormatter } from "../../utils/DateFormatter";
import dayjs from "../../utils/day";
//import ContractLicenseDecodeButton from "../contract-license-decode-button/contract-license-decode-button.component"; //import ContractLicenseDecodeButton from "../contract-license-decode-button/contract-license-decode-button.component";
import ContractStatusSelector from "../contract-status-select/contract-status-select.component"; import ContractStatusSelector from "../contract-status-select/contract-status-select.component";
import ContractsRatesChangeButton from "../contracts-rates-change-button/contracts-rates-change-button.component"; import ContractsRatesChangeButton from "../contracts-rates-change-button/contracts-rates-change-button.component";
import CourtesyCarFuelSlider from "../courtesy-car-fuel-select/courtesy-car-fuel-select.component"; import CourtesyCarFuelSlider from "../courtesy-car-fuel-select/courtesy-car-fuel-select.component";
import FormDateTimePicker from "../form-date-time-picker/form-date-time-picker.component"; import {
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component"; default as DateTimePicker,
default as FormDateTimePicker
} from "../form-date-time-picker/form-date-time-picker.component";
import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component"; import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
import InputPhone, { PhoneItemFormatterValidation } from "../form-items-formatted/phone-form-item.component"; import InputPhone, { PhoneItemFormatterValidation } from "../form-items-formatted/phone-form-item.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import LayoutFormRow from "../layout-form-row/layout-form-row.component";
@@ -18,10 +20,10 @@ import ContractFormJobPrefill from "./contract-form-job-prefill.component";
export default function ContractFormComponent({ form, create = false, selectedJobState, selectedCar }) { export default function ContractFormComponent({ form, create = false, selectedJobState, selectedCar }) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div> <>
<FormFieldsChanged form={form} /> {!create && <FormFieldsChanged form={form} />}
<LayoutFormRow> <LayoutFormRow>
{create ? null : ( {!create && (
<Form.Item <Form.Item
label={t("contracts.fields.status")} label={t("contracts.fields.status")}
name="status" name="status"
@@ -50,7 +52,7 @@ export default function ContractFormComponent({ form, create = false, selectedJo
<Form.Item label={t("contracts.fields.scheduledreturn")} name="scheduledreturn"> <Form.Item label={t("contracts.fields.scheduledreturn")} name="scheduledreturn">
<FormDateTimePicker /> <FormDateTimePicker />
</Form.Item> </Form.Item>
{create ? null : ( {!create && (
<Form.Item label={t("contracts.fields.actualreturn")} name="actualreturn"> <Form.Item label={t("contracts.fields.actualreturn")} name="actualreturn">
<FormDateTimePicker /> <FormDateTimePicker />
</Form.Item> </Form.Item>
@@ -122,7 +124,7 @@ export default function ContractFormComponent({ form, create = false, selectedJo
}} }}
</Form.Item> </Form.Item>
)} )}
{create ? null : ( {!create && (
<Form.Item label={t("contracts.fields.kmend")} name="kmend"> <Form.Item label={t("contracts.fields.kmend")} name="kmend">
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
@@ -145,25 +147,21 @@ export default function ContractFormComponent({ form, create = false, selectedJo
> >
<CourtesyCarFuelSlider /> <CourtesyCarFuelSlider />
</Form.Item> </Form.Item>
{create ? null : ( {!create && (
<Form.Item label={t("contracts.fields.fuelin")} name="fuelin" span={8}> <Form.Item label={t("contracts.fields.fuelin")} name="fuelin" span={8}>
<CourtesyCarFuelSlider /> <CourtesyCarFuelSlider />
</Form.Item> </Form.Item>
)} )}
</LayoutFormRow> </LayoutFormRow>
<div>
<Space wrap>
{selectedJobState && (
<div>
<ContractFormJobPrefill jobId={selectedJobState && selectedJobState[0]} form={form} />
</div>
)}
{
//<ContractLicenseDecodeButton form={form} />
}
</Space>
</div>
<LayoutFormRow header={t("contracts.labels.driverinformation")}> <LayoutFormRow header={t("contracts.labels.driverinformation")}>
<Space wrap>
{create && selectedJobState && (
<ContractFormJobPrefill jobId={selectedJobState && selectedJobState[0]} form={form} />
)}
{/* {<ContractLicenseDecodeButton form={form} />} */}
</Space>
</LayoutFormRow>
<LayoutFormRow noDivider={true}>
<Form.Item <Form.Item
label={t("contracts.fields.driver_dlnumber")} label={t("contracts.fields.driver_dlnumber")}
name="driver_dlnumber" name="driver_dlnumber"
@@ -183,9 +181,8 @@ export default function ContractFormComponent({ form, create = false, selectedJo
const dlExpiresBeforeReturn = dayjs(form.getFieldValue("driver_dlexpiry")).isBefore( const dlExpiresBeforeReturn = dayjs(form.getFieldValue("driver_dlexpiry")).isBefore(
dayjs(form.getFieldValue("scheduledreturn")) dayjs(form.getFieldValue("scheduledreturn"))
); );
return ( return (
<div> <>
<Form.Item <Form.Item
label={t("contracts.fields.driver_dlexpiry")} label={t("contracts.fields.driver_dlexpiry")}
name="driver_dlexpiry" name="driver_dlexpiry"
@@ -204,11 +201,10 @@ export default function ContractFormComponent({ form, create = false, selectedJo
<span>{t("contracts.labels.dlexpirebeforereturn")}</span> <span>{t("contracts.labels.dlexpirebeforereturn")}</span>
</Space> </Space>
)} )}
</div> </>
); );
}} }}
</Form.Item> </Form.Item>
<Form.Item label={t("contracts.fields.driver_dlst")} name="driver_dlst"> <Form.Item label={t("contracts.fields.driver_dlst")} name="driver_dlst">
<Input /> <Input />
</Form.Item> </Form.Item>
@@ -315,6 +311,6 @@ export default function ContractFormComponent({ form, create = false, selectedJo
<InputNumber precision={2} /> <InputNumber precision={2} />
</Form.Item> </Form.Item>
</LayoutFormRow> </LayoutFormRow>
</div> </>
); );
} }

View File

@@ -40,8 +40,6 @@ export function DmsLogEvents({ socket, logs, bodyshop }) {
function LogLevelHierarchy(level) { function LogLevelHierarchy(level) {
switch (level) { switch (level) {
case "TRACE":
return "pink";
case "DEBUG": case "DEBUG":
return "orange"; return "orange";
case "INFO": case "INFO":

View File

@@ -8,7 +8,7 @@ import { INSERT_EULA_ACCEPTANCE } from "../../graphql/user.queries";
import { useMutation } from "@apollo/client"; import { useMutation } from "@apollo/client";
import { acceptEula } from "../../redux/user/user.actions"; import { acceptEula } from "../../redux/user/user.actions";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import day from "../../utils/day"; import dayjs from "../../utils/day";
import "./eula.styles.scss"; import "./eula.styles.scss";
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx"; import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx";
@@ -208,7 +208,7 @@ const EulaFormComponent = ({ form, handleChange, onFinish, t }) => (
{ {
required: true, required: true,
validator: (_, value) => { validator: (_, value) => {
if (day(value).isSame(day(), "day")) { if (dayjs(value).isSame(dayjs(), "day")) {
return Promise.resolve(); return Promise.resolve();
} }
return Promise.reject(new Error(t("eula.messages.date_accepted"))); return Promise.reject(new Error(t("eula.messages.date_accepted")));

View File

@@ -4,19 +4,37 @@ import React, { useCallback, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import dayjs from "../../utils/day"; import dayjs from "../../utils/day";
import { fuzzyMatchDate } from "./formats.js"; import { fuzzyMatchDate } from "./formats.js";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors.js";
import { connect } from "react-redux";
const DateTimePicker = ({ value, onChange, onBlur, id, onlyFuture, onlyToday, isDateOnly = false, ...restProps }) => { const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop
});
const DateTimePicker = ({
value,
onChange,
onBlur,
id,
onlyFuture,
onlyToday,
isDateOnly = false,
bodyshop,
...restProps
}) => {
const [isManualInput, setIsManualInput] = useState(false); const [isManualInput, setIsManualInput] = useState(false);
const { t } = useTranslation(); const { t } = useTranslation();
const handleChange = useCallback( const handleChange = useCallback(
(newDate) => { (newDate) => {
if (!newDate) return;
if (onChange) { if (onChange) {
onChange(newDate || null); onChange(bodyshop?.timezone ? dayjs(newDate).tz(bodyshop.timezone, true) : newDate);
} }
setIsManualInput(false); setIsManualInput(false);
}, },
[onChange] [onChange, bodyshop?.timezone]
); );
const handleBlur = useCallback( const handleBlur = useCallback(
@@ -102,4 +120,4 @@ DateTimePicker.propTypes = {
isDateOnly: PropTypes.bool isDateOnly: PropTypes.bool
}; };
export default React.memo(DateTimePicker); export default connect(mapStateToProps, null)(DateTimePicker);

View File

@@ -116,18 +116,15 @@ function Header({
const { t } = useTranslation(); const { t } = useTranslation();
const deleteBetaCookie = () => { // const deleteBetaCookie = () => {
const cookieExists = document.cookie.split("; ").some((row) => row.startsWith(`betaSwitchImex=`)); // const cookieExists = document.cookie.split("; ").some((row) => row.startsWith(`betaSwitchImex=`));
if (cookieExists) { // if (cookieExists) {
const domain = window.location.hostname.split(".").slice(-2).join("."); // const domain = window.location.hostname.split(".").slice(-2).join(".");
document.cookie = `betaSwitchImex=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${domain}`; // document.cookie = `betaSwitchImex=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${domain}`;
console.log(`betaSwitchImex cookie deleted`); // }
} else { // };
console.log(`betaSwitchImex cookie does not exist`); //
} // deleteBetaCookie();
};
deleteBetaCookie();
const accountingChildren = []; const accountingChildren = [];

View File

@@ -23,6 +23,7 @@ import ScheduleEventColor from "./schedule-event.color.component";
import ScheduleEventNote from "./schedule-event.note.component"; import ScheduleEventNote from "./schedule-event.note.component";
import { useMutation } from "@apollo/client"; import { useMutation } from "@apollo/client";
import { UPDATE_APPOINTMENT } from "../../graphql/appointments.queries"; import { UPDATE_APPOINTMENT } from "../../graphql/appointments.queries";
import ProductionListColumnComment from "../production-list-columns/production-list-columns.comment.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop bodyshop: selectBodyshop
@@ -127,6 +128,9 @@ export function ScheduleEventComponent({
{(event.job && event.job.alt_transport) || ""} {(event.job && event.job.alt_transport) || ""}
<ScheduleAtChange job={event && event.job} /> <ScheduleAtChange job={event && event.job} />
</DataLabel> </DataLabel>
<DataLabel label={t("jobs.fields.comment")} valueStyle={{ overflow: "hidden", textOverflow: "ellipsis" }}>
<ProductionListColumnComment record={event && event.job} />
</DataLabel>
<ScheduleEventNote event={event} /> <ScheduleEventNote event={event} />
</div> </div>
) : ( ) : (
@@ -316,6 +320,7 @@ export function ScheduleEventComponent({
})`} })`}
{event.job && event.job.alt_transport && <div style={{ margin: ".1rem" }}>{event.job.alt_transport}</div>} {event.job && event.job.alt_transport && <div style={{ margin: ".1rem" }}>{event.job.alt_transport}</div>}
{event?.job?.comment && `C: ${event.job.comment}`}
</Space> </Space>
) : ( ) : (
<div <div

View File

@@ -1,5 +1,5 @@
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
import day from "../../utils/day"; import dayjs from "../../utils/day";
import axios from "axios"; import axios from "axios";
import { Badge, Card, Space, Table, Tag } from "antd"; import { Badge, Card, Space, Table, Tag } from "antd";
import { gql, useQuery } from "@apollo/client"; import { gql, useQuery } from "@apollo/client";
@@ -72,7 +72,7 @@ export function JobLifecycleComponent({ job, statuses, ...rest }) {
dataIndex: "start", dataIndex: "start",
key: "start", key: "start",
render: (text) => DateTimeFormatterFunction(text), render: (text) => DateTimeFormatterFunction(text),
sorter: (a, b) => day(a.start).unix() - day(b.start).unix() sorter: (a, b) => dayjs(a.start).unix() - dayjs(b.start).unix()
}, },
{ {
title: t("job_lifecycle.columns.relative_start"), title: t("job_lifecycle.columns.relative_start"),
@@ -90,7 +90,7 @@ export function JobLifecycleComponent({ job, statuses, ...rest }) {
} }
return isEmpty(a.end) ? 1 : -1; return isEmpty(a.end) ? 1 : -1;
} }
return day(a.end).unix() - day(b.end).unix(); return dayjs(a.end).unix() - dayjs(b.end).unix();
}, },
render: (text) => (isEmpty(text) ? t("job_lifecycle.content.not_available") : DateTimeFormatterFunction(text)) render: (text) => (isEmpty(text) ? t("job_lifecycle.content.not_available") : DateTimeFormatterFunction(text))
}, },

View File

@@ -2,7 +2,7 @@ import React, { useState } from "react";
import { useMutation } from "@apollo/client"; import { useMutation } from "@apollo/client";
import { Button, Form, notification, Popover, Select, Space } from "antd"; import { Button, Form, notification, Popover, Select, Space } from "antd";
import day from "../../utils/day"; import dayjs from "../../utils/day";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
@@ -48,7 +48,7 @@ export function JobLineDispatchButton({
const result = await dispatchLines({ const result = await dispatchLines({
variables: { variables: {
partsDispatch: { partsDispatch: {
dispatched_at: day(), dispatched_at: dayjs(),
employeeid: values.employeeid, employeeid: values.employeeid,
jobid: job.id, jobid: job.id,
dispatched_by: currentUser.email, dispatched_by: currentUser.email,
@@ -138,7 +138,11 @@ export function JobLineDispatchButton({
return ( return (
<Popover open={visible} content={popMenu}> <Popover open={visible} content={popMenu}>
<Button disabled={selectedLines.length === 0 || jobRO || disabled} loading={loading} onClick={() => setVisible(true)}> <Button
disabled={selectedLines.length === 0 || jobRO || disabled}
loading={loading}
onClick={() => setVisible(true)}
>
{t("joblines.actions.dispatchparts", { count: selectedLines.length })} {t("joblines.actions.dispatchparts", { count: selectedLines.length })}
</Button> </Button>
</Popover> </Popover>

View File

@@ -1,6 +1,6 @@
import { useMutation } from "@apollo/client"; import { useMutation } from "@apollo/client";
import { Button, Card, Col, notification, Row, Table } from "antd"; import { Button, Card, Col, notification, Row, Table } from "antd";
import day from "../../utils/day"; import dayjs from "../../utils/day";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { UPDATE_PARTS_DISPATCH_LINE } from "../../graphql/parts-dispatch.queries"; import { UPDATE_PARTS_DISPATCH_LINE } from "../../graphql/parts-dispatch.queries";
@@ -11,7 +11,7 @@ export default function PartsDispatchExpander({ dispatch, job }) {
const [updateDispatchLine] = useMutation(UPDATE_PARTS_DISPATCH_LINE); const [updateDispatchLine] = useMutation(UPDATE_PARTS_DISPATCH_LINE);
const handleAccept = async ({ partsDispatchLineId }) => { const handleAccept = async ({ partsDispatchLineId }) => {
const accepted_at = day(); const accepted_at = dayjs();
const result = await updateDispatchLine({ const result = await updateDispatchLine({
variables: { id: partsDispatchLineId, line: { accepted_at } }, variables: { id: partsDispatchLineId, line: { accepted_at } },
optimisticResponse: { optimisticResponse: {

View File

@@ -1,12 +1,14 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { useApolloClient } from "@apollo/client";
import Board from "./trello-board/index";
import { Button, notification, Skeleton, Space } from "antd";
import { PageHeader } from "@ant-design/pro-layout"; import { PageHeader } from "@ant-design/pro-layout";
import { useApolloClient } from "@apollo/client";
import { Button, notification, Skeleton, Space } from "antd";
import cloneDeep from "lodash/cloneDeep";
import isEqual from "lodash/isEqual";
import React, { useCallback, useEffect, useMemo, useState } from "react"; import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import NoteUpsertModal from "../../components/note-upsert-modal/note-upsert-modal.container";
import { logImEXEvent } from "../../firebase/firebase.utils"; import { logImEXEvent } from "../../firebase/firebase.utils";
import { generate_UPDATE_JOB_KANBAN } from "../../graphql/jobs.queries"; import { generate_UPDATE_JOB_KANBAN } from "../../graphql/jobs.queries";
import { insertAuditTrail } from "../../redux/application/application.actions"; import { insertAuditTrail } from "../../redux/application/application.actions";
@@ -15,14 +17,13 @@ import AuditTrailMapping from "../../utils/AuditTrailMappings";
import IndefiniteLoading from "../indefinite-loading/indefinite-loading.component"; import IndefiniteLoading from "../indefinite-loading/indefinite-loading.component";
import ProductionBoardFilters from "../production-board-filters/production-board-filters.component"; import ProductionBoardFilters from "../production-board-filters/production-board-filters.component";
import ProductionListDetailComponent from "../production-list-detail/production-list-detail.component"; import ProductionListDetailComponent from "../production-list-detail/production-list-detail.component";
import ProductionListPrint from "../production-list-table/production-list-print.component.jsx";
import CardColorLegend from "./production-board-kanban-card-color-legend.component.jsx"; import CardColorLegend from "./production-board-kanban-card-color-legend.component.jsx";
import "./production-board-kanban.styles.scss"; import "./production-board-kanban.styles.scss";
import { createBoardData } from "./production-board-kanban.utils.js"; import { createBoardData } from "./production-board-kanban.utils.js";
import ProductionBoardKanbanSettings from "./settings/production-board-kanban.settings.component.jsx";
import cloneDeep from "lodash/cloneDeep";
import isEqual from "lodash/isEqual";
import { defaultFilters, mergeWithDefaults } from "./settings/defaultKanbanSettings.js"; import { defaultFilters, mergeWithDefaults } from "./settings/defaultKanbanSettings.js";
import NoteUpsertModal from "../../components/note-upsert-modal/note-upsert-modal.container"; import ProductionBoardKanbanSettings from "./settings/production-board-kanban.settings.component.jsx";
import Board from "./trello-board/index";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop bodyshop: selectBodyshop
@@ -214,6 +215,7 @@ function ProductionBoardKanbanComponent({ data, bodyshop, refetch, insertAuditTr
bodyshop={bodyshop} bodyshop={bodyshop}
data={data} data={data}
/> />
<ProductionListPrint />
</Space> </Space>
} }
/> />

View File

@@ -77,7 +77,7 @@ export function ProductionListTable({ loading, data, refetch, bodyshop, technici
const matchingColumnConfig = useMemo(() => { const matchingColumnConfig = useMemo(() => {
return bodyshop?.production_config?.find((p) => p.name === defaultView); return bodyshop?.production_config?.find((p) => p.name === defaultView);
}, [bodyshop.production_config]); }, [bodyshop.production_config, defaultView]);
useEffect(() => { useEffect(() => {
const newColumns = const newColumns =

View File

@@ -120,14 +120,6 @@ var formats = {
}; };
const localizer = (dayjsLib) => { const localizer = (dayjsLib) => {
// load dayjs plugins
dayjsLib.extend(isBetween);
dayjsLib.extend(isSameOrAfter);
dayjsLib.extend(isSameOrBefore);
dayjsLib.extend(localeData);
dayjsLib.extend(localizedFormat);
dayjsLib.extend(minMax);
dayjsLib.extend(utc);
var locale = function locale(dj, c) { var locale = function locale(dj, c) {
return c ? dj.locale(c) : dj; return c ? dj.locale(c) : dj;
}; };
@@ -136,7 +128,8 @@ const localizer = (dayjsLib) => {
// then use the timezone aware version // then use the timezone aware version
//TODO This was the issue entirely... //TODO This was the issue entirely...
// var dayjs = dayjsLib.tz ? dayjsLib.tz : dayjsLib; // var dayjs = dayjsLib.tz ? dayjsLib.tz : dayjsLib;
var dayjs = dayjsLib; var dayjs = dayjsLib;
function getTimezoneOffset(date) { function getTimezoneOffset(date) {

View File

@@ -20,6 +20,7 @@ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
problemJobs: selectProblemJobs problemJobs: selectProblemJobs
}); });
const localizer = local(dayjs); const localizer = local(dayjs);
export function ScheduleCalendarWrapperComponent({ export function ScheduleCalendarWrapperComponent({

View File

@@ -1,10 +1,3 @@
import { Button, Card, Space, Switch, Table } from "antd";
import queryString from "query-string";
import React, { useCallback, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { pageLimit } from "../../utils/config";
import dayjs from "../../utils/day";
import { import {
CheckCircleFilled, CheckCircleFilled,
CheckCircleOutlined, CheckCircleOutlined,
@@ -15,9 +8,16 @@ import {
PlusCircleFilled, PlusCircleFilled,
SyncOutlined SyncOutlined
} from "@ant-design/icons"; } from "@ant-design/icons";
import { DateFormatter, DateTimeFormatter } from "../../utils/DateFormatter.jsx"; import { Button, Card, Space, Switch, Table } from "antd";
import queryString from "query-string";
import React, { useCallback, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { setModalContext } from "../../redux/modals/modals.actions"; import { setModalContext } from "../../redux/modals/modals.actions";
import { pageLimit } from "../../utils/config";
import { DateFormatter, DateTimeFormatter } from "../../utils/DateFormatter.jsx";
import dayjs from "../../utils/day";
/** /**
* Task List Component * Task List Component
@@ -140,6 +140,17 @@ function TaskListComponent({
render: (text, record) => <DateTimeFormatter>{record.created_at}</DateTimeFormatter> render: (text, record) => <DateTimeFormatter>{record.created_at}</DateTimeFormatter>
}); });
columns.push({
title: t("tasks.fields.created_by"),
dataIndex: "created_by",
key: "created_by",
width: "8%",
defaultSortOrder: "descend",
sorter: true,
sortOrder: sortcolumn === "created_by" && sortorder,
render: (text, record) => record.created_by
});
if (!onlyMine) { if (!onlyMine) {
columns.push({ columns.push({
title: t("tasks.fields.assigned_to"), title: t("tasks.fields.assigned_to"),
@@ -155,65 +166,70 @@ function TaskListComponent({
}); });
} }
if (showRo) { columns.push({
columns.push({ title: t("tasks.fields.related_items"),
title: t("tasks.fields.job.ro_number"), key: "related_items",
dataIndex: ["job", "ro_number"], width: "12%",
key: "job.ro_number", render: (text, record) => {
width: "8%", const items = [];
render: (text, record) =>
record.job ? ( // Job
<Link to={`/manage/jobs/${record.job.id}?tab=tasks`}>{record.job.ro_number || t("general.labels.na")}</Link> if (showRo && record.job) {
) : ( items.push(
t("general.labels.na") <Link key="job" to={`/manage/jobs/${record.job.id}?tab=tasks`}>
) {t("tasks.fields.job.ro_number")}: {record.job.ro_number}
}); </Link>
} );
}
if (showRo && !record.job) {
items.push(`${t("tasks.fields.job.ro_number")}: ${t("general.labels.na")}`);
}
// Jobline
if (record.jobline?.line_desc) {
items.push(
<span key="jobline">
{t("tasks.fields.jobline")}: {record.jobline.line_desc}
</span>
);
}
// Parts Order
if (record.parts_order) {
const { order_number, vendor } = record.parts_order;
const partsOrderText =
order_number && vendor?.name ? `${order_number} - ${vendor.name}` : t("general.labels.na");
items.push(
<Link
key="parts_order"
to={`/manage/jobs/${record.job.id}?partsorderid=${record.parts_order.id}&tab=partssublet`}
>
{t("tasks.fields.parts_order")}: {partsOrderText}
</Link>
);
}
// Bill
if (record.bill) {
const { invoice_number, vendor } = record.bill;
const billText = invoice_number && vendor?.name ? `${invoice_number} - ${vendor.name}` : t("general.labels.na");
items.push(
<Link key="bill" to={`/manage/jobs/${record.job.id}?billid=${record.bill.id}&tab=partssublet`}>
{t("tasks.fields.bill")}: {billText}
</Link>
);
}
return items.length > 0 ? <Space direction="vertical">{items}</Space> : null;
}
});
columns.push( columns.push(
{
title: t("tasks.fields.jobline"),
dataIndex: ["jobline", "id"],
key: "jobline.id",
width: "8%",
render: (text, record) => record?.jobline?.line_desc || ""
},
{
title: t("tasks.fields.parts_order"),
dataIndex: ["parts_order", "id"],
key: "part_order.id",
width: "8%",
render: (text, record) =>
record.parts_order ? (
<Link to={`/manage/jobs/${record.job.id}?partsorderid=${record.parts_order.id}&tab=partssublet`}>
{record.parts_order.order_number && record.parts_order.vendor && record.parts_order.vendor.name
? `${record.parts_order.order_number} - ${record.parts_order.vendor.name}`
: t("general.labels.na")}
</Link>
) : (
""
)
},
{
title: t("tasks.fields.bill"),
dataIndex: ["bill", "id"],
key: "bill.id",
width: "10%",
render: (text, record) =>
record.bill ? (
<Link to={`/manage/jobs/${record.job.id}?billid=${record.bill.id}&tab=partssublet`}>
{record.bill.invoice_number && record.bill.vendor && record.bill.vendor.name
? `${record.bill.invoice_number} - ${record.bill.vendor.name}`
: t("general.labels.na")}
</Link>
) : (
""
)
},
{ {
title: t("tasks.fields.title"), title: t("tasks.fields.title"),
dataIndex: "title", dataIndex: "title",
key: "title", key: "title",
minWidth: "20%",
sorter: true, sorter: true,
sortOrder: sortcolumn === "title" && sortorder sortOrder: sortcolumn === "title" && sortorder
}, },
@@ -247,7 +263,7 @@ function TaskListComponent({
{ {
title: t("tasks.fields.actions"), title: t("tasks.fields.actions"),
key: "toggleCompleted", key: "toggleCompleted",
width: "5%", width: "8%",
render: (text, record) => ( render: (text, record) => (
<Space direction="horizontal"> <Space direction="horizontal">
<Button <Button

View File

@@ -1,6 +1,6 @@
import { useMutation } from "@apollo/client"; import { useMutation } from "@apollo/client";
import { Button, notification } from "antd"; import { Button, notification } from "antd";
import day from "../../utils/day"; import dayjs from "../../utils/day";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -29,7 +29,7 @@ export function TimeTicketsCommit({ bodyshop, currentUser, timeticket, disabled,
? { commited_by: null, committed_at: null } ? { commited_by: null, committed_at: null }
: { : {
commited_by: currentUser.email, commited_by: currentUser.email,
committed_at: day() committed_at: dayjs()
}; };
const result = await updateTimeTicket({ const result = await updateTimeTicket({

View File

@@ -1,6 +1,6 @@
import { useMutation } from "@apollo/client"; import { useMutation } from "@apollo/client";
import { Button, notification } from "antd"; import { Button, notification } from "antd";
import day from "../../utils/day"; import dayjs from "../../utils/day";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -34,7 +34,7 @@ export function TimeTicketsCommit({
timeticketIds: timetickets.map((ticket) => ticket.id), timeticketIds: timetickets.map((ticket) => ticket.id),
timeticket: { timeticket: {
commited_by: currentUser.email, commited_by: currentUser.email,
committed_at: day() committed_at: dayjs()
} }
}, },
update(cache) { update(cache) {
@@ -47,7 +47,7 @@ export function TimeTicketsCommit({
return { return {
...ticket, ...ticket,
commited_by: currentUser.email, commited_by: currentUser.email,
committed_at: day() committed_at: dayjs()
}; };
} }
return ticket; return ticket;

View File

@@ -1,7 +1,7 @@
import { useApolloClient } from "@apollo/client"; import { useApolloClient } from "@apollo/client";
import { Button, notification } from "antd"; import { Button, notification } from "antd";
import _ from "lodash"; import _ from "lodash";
import day from "../../utils/day"; import dayjs from "../../utils/day";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -49,7 +49,7 @@ export function TtApproveButton({
})), })),
approvalIds: selectedTickets, approvalIds: selectedTickets,
approvalUpdate: { approvalUpdate: {
approved_at: day(), approved_at: dayjs(),
approved_by: currentUser.email approved_by: currentUser.email
} }
} }

View File

@@ -48,6 +48,7 @@ export const QUERY_ALL_ACTIVE_APPOINTMENTS = gql`
v_model_desc v_model_desc
est_ct_fn est_ct_fn
est_ct_ln est_ct_ln
comment
labhrs: joblines_aggregate(where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }) { labhrs: joblines_aggregate(where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }) {
aggregate { aggregate {
sum { sum {

View File

@@ -123,7 +123,6 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
socket.emit("set-log-level", value); socket.emit("set-log-level", value);
}} }}
> >
<Select.Option key="TRACE">TRACE</Select.Option>
<Select.Option key="DEBUG">DEBUG</Select.Option> <Select.Option key="DEBUG">DEBUG</Select.Option>
<Select.Option key="INFO">INFO</Select.Option> <Select.Option key="INFO">INFO</Select.Option>
<Select.Option key="WARNING">WARNING</Select.Option> <Select.Option key="WARNING">WARNING</Select.Option>

View File

@@ -173,7 +173,6 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, inse
socket.emit("set-log-level", value); socket.emit("set-log-level", value);
}} }}
> >
<Select.Option key="TRACE">TRACE</Select.Option>
<Select.Option key="DEBUG">DEBUG</Select.Option> <Select.Option key="DEBUG">DEBUG</Select.Option>
<Select.Option key="INFO">INFO</Select.Option> <Select.Option key="INFO">INFO</Select.Option>
<Select.Option key="WARNING">WARNING</Select.Option> <Select.Option key="WARNING">WARNING</Select.Option>

View File

@@ -28,7 +28,7 @@ import {
} from "../../firebase/firebase.utils"; } from "../../firebase/firebase.utils";
import { QUERY_EULA } from "../../graphql/bodyshop.queries"; import { QUERY_EULA } from "../../graphql/bodyshop.queries";
import client from "../../utils/GraphQLClient"; import client from "../../utils/GraphQLClient";
import day from "../../utils/day"; import dayjs from "../../utils/day";
import InstanceRenderManager from "../../utils/instanceRenderMgr"; import InstanceRenderManager from "../../utils/instanceRenderMgr";
import { import {
checkInstanceId, checkInstanceId,
@@ -96,7 +96,7 @@ export function* isUserAuthenticated() {
const eulaQuery = yield client.query({ const eulaQuery = yield client.query({
query: QUERY_EULA, query: QUERY_EULA,
variables: { variables: {
now: day() now: dayjs()
} }
}); });
@@ -314,8 +314,7 @@ export function* SetAuthLevelFromShopDetails({ payload }) {
try { try {
const userEmail = yield select((state) => state.user.currentUser.email); const userEmail = yield select((state) => state.user.currentUser.email);
try { try {
console.log("Setting shop timezone."); dayjs.tz.setDefault(payload.timezone);
day.tz.setDefault(payload.timezone);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }

View File

@@ -3044,6 +3044,7 @@
"production_by_target_date": "Production by Target Date", "production_by_target_date": "Production by Target Date",
"production_by_technician": "Production by Technician", "production_by_technician": "Production by Technician",
"production_by_technician_one": "Production filtered by Technician", "production_by_technician_one": "Production filtered by Technician",
"production_not_production_status": "Production not in Production Status",
"production_over_time": "Production Level over Time", "production_over_time": "Production Level over Time",
"psr_by_make": "Percent of Sales by Vehicle Make", "psr_by_make": "Percent of Sales by Vehicle Make",
"purchase_return_ratio_grouped_by_vendor_detail": "Purchase & Return Ratio by Vendor (Detail)", "purchase_return_ratio_grouped_by_vendor_detail": "Purchase & Return Ratio by Vendor (Detail)",
@@ -3186,6 +3187,7 @@
"billid": "Bill", "billid": "Bill",
"completed": "Completed", "completed": "Completed",
"created_at": "Created At", "created_at": "Created At",
"created_by": "Created By",
"description": "Description", "description": "Description",
"due_date": "Due Date", "due_date": "Due Date",
"job": { "job": {
@@ -3202,6 +3204,7 @@
"medium": "Medium" "medium": "Medium"
}, },
"priority": "Priority", "priority": "Priority",
"related_items": "Related Items",
"remind_at": "Remind At", "remind_at": "Remind At",
"title": "Title" "title": "Title"
}, },

View File

@@ -3044,6 +3044,7 @@
"production_by_target_date": "", "production_by_target_date": "",
"production_by_technician": "", "production_by_technician": "",
"production_by_technician_one": "", "production_by_technician_one": "",
"production_not_production_status": "",
"production_over_time": "", "production_over_time": "",
"psr_by_make": "", "psr_by_make": "",
"purchase_return_ratio_grouped_by_vendor_detail": "", "purchase_return_ratio_grouped_by_vendor_detail": "",
@@ -3186,6 +3187,7 @@
"billid": "", "billid": "",
"completed": "", "completed": "",
"created_at": "", "created_at": "",
"created_by": "",
"description": "", "description": "",
"due_date": "", "due_date": "",
"job": { "job": {
@@ -3202,6 +3204,7 @@
"medium": "" "medium": ""
}, },
"priority": "", "priority": "",
"related_items": "",
"remind_at": "", "remind_at": "",
"title": "" "title": ""
}, },

File diff suppressed because it is too large Load Diff

View File

@@ -2333,6 +2333,14 @@ export const TemplateList = (type, context) => {
key: "production_by_technician", key: "production_by_technician",
//idtype: "vendor", //idtype: "vendor",
disabled: false disabled: false
},
production_not_production_status: {
title: i18n.t("reportcenter.templates.production_not_production_status"),
description: "",
subject: i18n.t("reportcenter.templates.production_not_production_status"),
key: "production_not_production_status",
//idtype: "vendor",
disabled: false
} }
} }
: {}), : {}),

View File

@@ -1,5 +1,6 @@
import dayjs from "dayjs"; import dayjs from "dayjs";
import "dayjs/locale/en";
import dayjsBusinessDays from "dayjs-business-days2"; import dayjsBusinessDays from "dayjs-business-days2";
import isSameOrAfter from "dayjs/plugin/isSameOrAfter"; import isSameOrAfter from "dayjs/plugin/isSameOrAfter";
import updateLocale from "dayjs/plugin/updateLocale"; import updateLocale from "dayjs/plugin/updateLocale";
@@ -64,4 +65,6 @@ dayjs.extend(minMax);
dayjs.extend(isBetween); dayjs.extend(isBetween);
dayjs.extend(dayjsBusinessDays); dayjs.extend(dayjsBusinessDays);
dayjs.locale("en");
export default dayjs; export default dayjs;

View File

@@ -74,7 +74,7 @@ services:
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
environment: environment:
- SERVICES=ses,secretsmanager - SERVICES=ses,secretsmanager,cloudwatch,logs
- DEBUG=0 - DEBUG=0
- AWS_ACCESS_KEY_ID=test - AWS_ACCESS_KEY_ID=test
- AWS_SECRET_ACCESS_KEY=test - AWS_SECRET_ACCESS_KEY=test
@@ -115,6 +115,7 @@ services:
aws --endpoint-url=http://localstack:4566 ses verify-domain-identity --domain imex.online --region ca-central-1 aws --endpoint-url=http://localstack:4566 ses verify-domain-identity --domain imex.online --region ca-central-1
aws --endpoint-url=http://localstack:4566 ses verify-email-identity --email-address noreply@imex.online --region ca-central-1 aws --endpoint-url=http://localstack:4566 ses verify-email-identity --email-address noreply@imex.online --region ca-central-1
aws --endpoint-url=http://localstack:4566 secretsmanager create-secret --name CHATTER_PRIVATE_KEY --secret-string file:///tmp/certs/id_rsa aws --endpoint-url=http://localstack:4566 secretsmanager create-secret --name CHATTER_PRIVATE_KEY --secret-string file:///tmp/certs/id_rsa
aws --endpoint-url=http://localstack:4566 logs create-log-group --log-group-name development --region ca-central-1
" "
# Node App: The Main IMEX API # Node App: The Main IMEX API
node-app: node-app:

816
package-lock.json generated
View File

@@ -9,6 +9,7 @@
"version": "0.2.0", "version": "0.2.0",
"license": "UNLICENSED", "license": "UNLICENSED",
"dependencies": { "dependencies": {
"@aws-sdk/client-cloudwatch-logs": "^3.679.0",
"@aws-sdk/client-elasticache": "^3.675.0", "@aws-sdk/client-elasticache": "^3.675.0",
"@aws-sdk/client-secrets-manager": "^3.675.0", "@aws-sdk/client-secrets-manager": "^3.675.0",
"@aws-sdk/client-ses": "^3.675.0", "@aws-sdk/client-ses": "^3.675.0",
@@ -34,7 +35,6 @@
"firebase-admin": "^12.6.0", "firebase-admin": "^12.6.0",
"graphql": "^16.9.0", "graphql": "^16.9.0",
"graphql-request": "^6.1.0", "graphql-request": "^6.1.0",
"graylog2": "^0.2.1",
"inline-css": "^4.0.2", "inline-css": "^4.0.2",
"intuit-oauth": "^4.1.2", "intuit-oauth": "^4.1.2",
"ioredis": "^5.4.1", "ioredis": "^5.4.1",
@@ -56,6 +56,8 @@
"ssh2-sftp-client": "^10.0.3", "ssh2-sftp-client": "^10.0.3",
"twilio": "^4.23.0", "twilio": "^4.23.0",
"uuid": "^10.0.0", "uuid": "^10.0.0",
"winston": "^3.15.0",
"winston-cloudwatch": "^6.3.0",
"xml2js": "^0.6.2", "xml2js": "^0.6.2",
"xmlbuilder2": "^3.1.1" "xmlbuilder2": "^3.1.1"
}, },
@@ -70,6 +72,20 @@
"npm": ">=8.0.0" "npm": ">=8.0.0"
} }
}, },
"node_modules/@aws-crypto/crc32": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz",
"integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/util": "^5.2.0",
"@aws-sdk/types": "^3.222.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-crypto/sha256-browser": { "node_modules/@aws-crypto/sha256-browser": {
"version": "5.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz",
@@ -185,6 +201,554 @@
"node": ">=14.0.0" "node": ">=14.0.0"
} }
}, },
"node_modules/@aws-sdk/client-cloudwatch-logs": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.679.0.tgz",
"integrity": "sha512-A1qTVNX8KdpqvXgULd4Suo88uuNWPa8DiuBL8Qkw/WefYT7TSWsOpwuVK0oFkMpCfB0rQN9fXZh2DBiaz8YmZg==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
"@aws-sdk/client-sso-oidc": "3.679.0",
"@aws-sdk/client-sts": "3.679.0",
"@aws-sdk/core": "3.679.0",
"@aws-sdk/credential-provider-node": "3.679.0",
"@aws-sdk/middleware-host-header": "3.679.0",
"@aws-sdk/middleware-logger": "3.679.0",
"@aws-sdk/middleware-recursion-detection": "3.679.0",
"@aws-sdk/middleware-user-agent": "3.679.0",
"@aws-sdk/region-config-resolver": "3.679.0",
"@aws-sdk/types": "3.679.0",
"@aws-sdk/util-endpoints": "3.679.0",
"@aws-sdk/util-user-agent-browser": "3.679.0",
"@aws-sdk/util-user-agent-node": "3.679.0",
"@smithy/config-resolver": "^3.0.9",
"@smithy/core": "^2.4.8",
"@smithy/eventstream-serde-browser": "^3.0.10",
"@smithy/eventstream-serde-config-resolver": "^3.0.7",
"@smithy/eventstream-serde-node": "^3.0.9",
"@smithy/fetch-http-handler": "^3.2.9",
"@smithy/hash-node": "^3.0.7",
"@smithy/invalid-dependency": "^3.0.7",
"@smithy/middleware-content-length": "^3.0.9",
"@smithy/middleware-endpoint": "^3.1.4",
"@smithy/middleware-retry": "^3.0.23",
"@smithy/middleware-serde": "^3.0.7",
"@smithy/middleware-stack": "^3.0.7",
"@smithy/node-config-provider": "^3.1.8",
"@smithy/node-http-handler": "^3.2.4",
"@smithy/protocol-http": "^4.1.4",
"@smithy/smithy-client": "^3.4.0",
"@smithy/types": "^3.5.0",
"@smithy/url-parser": "^3.0.7",
"@smithy/util-base64": "^3.0.0",
"@smithy/util-body-length-browser": "^3.0.0",
"@smithy/util-body-length-node": "^3.0.0",
"@smithy/util-defaults-mode-browser": "^3.0.23",
"@smithy/util-defaults-mode-node": "^3.0.23",
"@smithy/util-endpoints": "^2.1.3",
"@smithy/util-middleware": "^3.0.7",
"@smithy/util-retry": "^3.0.7",
"@smithy/util-utf8": "^3.0.0",
"@types/uuid": "^9.0.1",
"tslib": "^2.6.2",
"uuid": "^9.0.1"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/client-sso": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.679.0.tgz",
"integrity": "sha512-/0cAvYnpOZTo/Y961F1kx2fhDDLUYZ0SQQ5/75gh3xVImLj7Zw+vp74ieqFbqWLYGMaq8z1Arr9A8zG95mbLdg==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
"@aws-sdk/core": "3.679.0",
"@aws-sdk/middleware-host-header": "3.679.0",
"@aws-sdk/middleware-logger": "3.679.0",
"@aws-sdk/middleware-recursion-detection": "3.679.0",
"@aws-sdk/middleware-user-agent": "3.679.0",
"@aws-sdk/region-config-resolver": "3.679.0",
"@aws-sdk/types": "3.679.0",
"@aws-sdk/util-endpoints": "3.679.0",
"@aws-sdk/util-user-agent-browser": "3.679.0",
"@aws-sdk/util-user-agent-node": "3.679.0",
"@smithy/config-resolver": "^3.0.9",
"@smithy/core": "^2.4.8",
"@smithy/fetch-http-handler": "^3.2.9",
"@smithy/hash-node": "^3.0.7",
"@smithy/invalid-dependency": "^3.0.7",
"@smithy/middleware-content-length": "^3.0.9",
"@smithy/middleware-endpoint": "^3.1.4",
"@smithy/middleware-retry": "^3.0.23",
"@smithy/middleware-serde": "^3.0.7",
"@smithy/middleware-stack": "^3.0.7",
"@smithy/node-config-provider": "^3.1.8",
"@smithy/node-http-handler": "^3.2.4",
"@smithy/protocol-http": "^4.1.4",
"@smithy/smithy-client": "^3.4.0",
"@smithy/types": "^3.5.0",
"@smithy/url-parser": "^3.0.7",
"@smithy/util-base64": "^3.0.0",
"@smithy/util-body-length-browser": "^3.0.0",
"@smithy/util-body-length-node": "^3.0.0",
"@smithy/util-defaults-mode-browser": "^3.0.23",
"@smithy/util-defaults-mode-node": "^3.0.23",
"@smithy/util-endpoints": "^2.1.3",
"@smithy/util-middleware": "^3.0.7",
"@smithy/util-retry": "^3.0.7",
"@smithy/util-utf8": "^3.0.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/client-sso-oidc": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.679.0.tgz",
"integrity": "sha512-/dBYWcCwbA/id4sFCIVZvf0UsvzHCC68SryxeNQk/PDkY9N4n5yRcMUkZDaEyQCjowc3kY4JOXp2AdUP037nhA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
"@aws-sdk/core": "3.679.0",
"@aws-sdk/credential-provider-node": "3.679.0",
"@aws-sdk/middleware-host-header": "3.679.0",
"@aws-sdk/middleware-logger": "3.679.0",
"@aws-sdk/middleware-recursion-detection": "3.679.0",
"@aws-sdk/middleware-user-agent": "3.679.0",
"@aws-sdk/region-config-resolver": "3.679.0",
"@aws-sdk/types": "3.679.0",
"@aws-sdk/util-endpoints": "3.679.0",
"@aws-sdk/util-user-agent-browser": "3.679.0",
"@aws-sdk/util-user-agent-node": "3.679.0",
"@smithy/config-resolver": "^3.0.9",
"@smithy/core": "^2.4.8",
"@smithy/fetch-http-handler": "^3.2.9",
"@smithy/hash-node": "^3.0.7",
"@smithy/invalid-dependency": "^3.0.7",
"@smithy/middleware-content-length": "^3.0.9",
"@smithy/middleware-endpoint": "^3.1.4",
"@smithy/middleware-retry": "^3.0.23",
"@smithy/middleware-serde": "^3.0.7",
"@smithy/middleware-stack": "^3.0.7",
"@smithy/node-config-provider": "^3.1.8",
"@smithy/node-http-handler": "^3.2.4",
"@smithy/protocol-http": "^4.1.4",
"@smithy/smithy-client": "^3.4.0",
"@smithy/types": "^3.5.0",
"@smithy/url-parser": "^3.0.7",
"@smithy/util-base64": "^3.0.0",
"@smithy/util-body-length-browser": "^3.0.0",
"@smithy/util-body-length-node": "^3.0.0",
"@smithy/util-defaults-mode-browser": "^3.0.23",
"@smithy/util-defaults-mode-node": "^3.0.23",
"@smithy/util-endpoints": "^2.1.3",
"@smithy/util-middleware": "^3.0.7",
"@smithy/util-retry": "^3.0.7",
"@smithy/util-utf8": "^3.0.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
},
"peerDependencies": {
"@aws-sdk/client-sts": "^3.679.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/client-sts": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.679.0.tgz",
"integrity": "sha512-3CvrT8w1RjFu1g8vKA5Azfr5V83r2/b68Ock43WE003Bq/5Y38mwmYX7vk0fPHzC3qejt4YMAWk/C3fSKOy25g==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
"@aws-sdk/client-sso-oidc": "3.679.0",
"@aws-sdk/core": "3.679.0",
"@aws-sdk/credential-provider-node": "3.679.0",
"@aws-sdk/middleware-host-header": "3.679.0",
"@aws-sdk/middleware-logger": "3.679.0",
"@aws-sdk/middleware-recursion-detection": "3.679.0",
"@aws-sdk/middleware-user-agent": "3.679.0",
"@aws-sdk/region-config-resolver": "3.679.0",
"@aws-sdk/types": "3.679.0",
"@aws-sdk/util-endpoints": "3.679.0",
"@aws-sdk/util-user-agent-browser": "3.679.0",
"@aws-sdk/util-user-agent-node": "3.679.0",
"@smithy/config-resolver": "^3.0.9",
"@smithy/core": "^2.4.8",
"@smithy/fetch-http-handler": "^3.2.9",
"@smithy/hash-node": "^3.0.7",
"@smithy/invalid-dependency": "^3.0.7",
"@smithy/middleware-content-length": "^3.0.9",
"@smithy/middleware-endpoint": "^3.1.4",
"@smithy/middleware-retry": "^3.0.23",
"@smithy/middleware-serde": "^3.0.7",
"@smithy/middleware-stack": "^3.0.7",
"@smithy/node-config-provider": "^3.1.8",
"@smithy/node-http-handler": "^3.2.4",
"@smithy/protocol-http": "^4.1.4",
"@smithy/smithy-client": "^3.4.0",
"@smithy/types": "^3.5.0",
"@smithy/url-parser": "^3.0.7",
"@smithy/util-base64": "^3.0.0",
"@smithy/util-body-length-browser": "^3.0.0",
"@smithy/util-body-length-node": "^3.0.0",
"@smithy/util-defaults-mode-browser": "^3.0.23",
"@smithy/util-defaults-mode-node": "^3.0.23",
"@smithy/util-endpoints": "^2.1.3",
"@smithy/util-middleware": "^3.0.7",
"@smithy/util-retry": "^3.0.7",
"@smithy/util-utf8": "^3.0.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/core": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.679.0.tgz",
"integrity": "sha512-CS6PWGX8l4v/xyvX8RtXnBisdCa5+URzKd0L6GvHChype9qKUVxO/Gg6N/y43Hvg7MNWJt9FBPNWIxUB+byJwg==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "3.679.0",
"@smithy/core": "^2.4.8",
"@smithy/node-config-provider": "^3.1.8",
"@smithy/property-provider": "^3.1.7",
"@smithy/protocol-http": "^4.1.4",
"@smithy/signature-v4": "^4.2.0",
"@smithy/smithy-client": "^3.4.0",
"@smithy/types": "^3.5.0",
"@smithy/util-middleware": "^3.0.7",
"fast-xml-parser": "4.4.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/credential-provider-env": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.679.0.tgz",
"integrity": "sha512-EdlTYbzMm3G7VUNAMxr9S1nC1qUNqhKlAxFU8E7cKsAe8Bp29CD5HAs3POc56AVo9GC4yRIS+/mtlZSmrckzUA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "3.679.0",
"@aws-sdk/types": "3.679.0",
"@smithy/property-provider": "^3.1.7",
"@smithy/types": "^3.5.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/credential-provider-http": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.679.0.tgz",
"integrity": "sha512-ZoKLubW5DqqV1/2a3TSn+9sSKg0T8SsYMt1JeirnuLJF0mCoYFUaWMyvxxKuxPoqvUsaycxKru4GkpJ10ltNBw==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "3.679.0",
"@aws-sdk/types": "3.679.0",
"@smithy/fetch-http-handler": "^3.2.9",
"@smithy/node-http-handler": "^3.2.4",
"@smithy/property-provider": "^3.1.7",
"@smithy/protocol-http": "^4.1.4",
"@smithy/smithy-client": "^3.4.0",
"@smithy/types": "^3.5.0",
"@smithy/util-stream": "^3.1.9",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/credential-provider-ini": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.679.0.tgz",
"integrity": "sha512-Rg7t8RwUzKcumpipG4neZqaeJ6DF+Bco1+FHn5BZB68jpvwvjBjcQUuWkxj18B6ctYHr1fkunnzeKEn/+vy7+w==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "3.679.0",
"@aws-sdk/credential-provider-env": "3.679.0",
"@aws-sdk/credential-provider-http": "3.679.0",
"@aws-sdk/credential-provider-process": "3.679.0",
"@aws-sdk/credential-provider-sso": "3.679.0",
"@aws-sdk/credential-provider-web-identity": "3.679.0",
"@aws-sdk/types": "3.679.0",
"@smithy/credential-provider-imds": "^3.2.4",
"@smithy/property-provider": "^3.1.7",
"@smithy/shared-ini-file-loader": "^3.1.8",
"@smithy/types": "^3.5.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
},
"peerDependencies": {
"@aws-sdk/client-sts": "^3.679.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/credential-provider-node": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.679.0.tgz",
"integrity": "sha512-E3lBtaqCte8tWs6Rkssc8sLzvGoJ10TLGvpkijOlz43wPd6xCRh1YLwg6zolf9fVFtEyUs/GsgymiASOyxhFtw==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/credential-provider-env": "3.679.0",
"@aws-sdk/credential-provider-http": "3.679.0",
"@aws-sdk/credential-provider-ini": "3.679.0",
"@aws-sdk/credential-provider-process": "3.679.0",
"@aws-sdk/credential-provider-sso": "3.679.0",
"@aws-sdk/credential-provider-web-identity": "3.679.0",
"@aws-sdk/types": "3.679.0",
"@smithy/credential-provider-imds": "^3.2.4",
"@smithy/property-provider": "^3.1.7",
"@smithy/shared-ini-file-loader": "^3.1.8",
"@smithy/types": "^3.5.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/credential-provider-process": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.679.0.tgz",
"integrity": "sha512-u/p4TV8kQ0zJWDdZD4+vdQFTMhkDEJFws040Gm113VHa/Xo1SYOjbpvqeuFoz6VmM0bLvoOWjxB9MxnSQbwKpQ==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "3.679.0",
"@aws-sdk/types": "3.679.0",
"@smithy/property-provider": "^3.1.7",
"@smithy/shared-ini-file-loader": "^3.1.8",
"@smithy/types": "^3.5.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/credential-provider-sso": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.679.0.tgz",
"integrity": "sha512-SAtWonhi9asxn0ukEbcE81jkyanKgqpsrtskvYPpO9Z9KOednM4Cqt6h1bfcS9zaHjN2zu815Gv8O7WiV+F/DQ==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/client-sso": "3.679.0",
"@aws-sdk/core": "3.679.0",
"@aws-sdk/token-providers": "3.679.0",
"@aws-sdk/types": "3.679.0",
"@smithy/property-provider": "^3.1.7",
"@smithy/shared-ini-file-loader": "^3.1.8",
"@smithy/types": "^3.5.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/credential-provider-web-identity": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.679.0.tgz",
"integrity": "sha512-a74tLccVznXCaBefWPSysUcLXYJiSkeUmQGtalNgJ1vGkE36W5l/8czFiiowdWdKWz7+x6xf0w+Kjkjlj42Ung==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "3.679.0",
"@aws-sdk/types": "3.679.0",
"@smithy/property-provider": "^3.1.7",
"@smithy/types": "^3.5.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
},
"peerDependencies": {
"@aws-sdk/client-sts": "^3.679.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/middleware-host-header": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.679.0.tgz",
"integrity": "sha512-y176HuQ8JRY3hGX8rQzHDSbCl9P5Ny9l16z4xmaiLo+Qfte7ee4Yr3yaAKd7GFoJ3/Mhud2XZ37fR015MfYl2w==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "3.679.0",
"@smithy/protocol-http": "^4.1.4",
"@smithy/types": "^3.5.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/middleware-logger": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.679.0.tgz",
"integrity": "sha512-0vet8InEj7nvIvGKk+ch7bEF5SyZ7Us9U7YTEgXPrBNStKeRUsgwRm0ijPWWd0a3oz2okaEwXsFl7G/vI0XiEA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "3.679.0",
"@smithy/types": "^3.5.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/middleware-recursion-detection": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.679.0.tgz",
"integrity": "sha512-sQoAZFsQiW/LL3DfKMYwBoGjYDEnMbA9WslWN8xneCmBAwKo6IcSksvYs23PP8XMIoBGe2I2J9BSr654XWygTQ==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "3.679.0",
"@smithy/protocol-http": "^4.1.4",
"@smithy/types": "^3.5.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/middleware-user-agent": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.679.0.tgz",
"integrity": "sha512-4hdeXhPDURPqQLPd9jCpUEo9fQITXl3NM3W1MwcJpE0gdUM36uXkQOYsTPeeU/IRCLVjK8Htlh2oCaM9iJrLCA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "3.679.0",
"@aws-sdk/types": "3.679.0",
"@aws-sdk/util-endpoints": "3.679.0",
"@smithy/core": "^2.4.8",
"@smithy/protocol-http": "^4.1.4",
"@smithy/types": "^3.5.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/region-config-resolver": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.679.0.tgz",
"integrity": "sha512-Ybx54P8Tg6KKq5ck7uwdjiKif7n/8g1x+V0V9uTjBjRWqaIgiqzXwKWoPj6NCNkE7tJNtqI4JrNxp/3S3HvmRw==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "3.679.0",
"@smithy/node-config-provider": "^3.1.8",
"@smithy/types": "^3.5.0",
"@smithy/util-config-provider": "^3.0.0",
"@smithy/util-middleware": "^3.0.7",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/token-providers": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.679.0.tgz",
"integrity": "sha512-1/+Zso/x2jqgutKixYFQEGli0FELTgah6bm7aB+m2FAWH4Hz7+iMUsazg6nSWm714sG9G3h5u42Dmpvi9X6/hA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "3.679.0",
"@smithy/property-provider": "^3.1.7",
"@smithy/shared-ini-file-loader": "^3.1.8",
"@smithy/types": "^3.5.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
},
"peerDependencies": {
"@aws-sdk/client-sso-oidc": "^3.679.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/types": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.679.0.tgz",
"integrity": "sha512-NwVq8YvInxQdJ47+zz4fH3BRRLC6lL+WLkvr242PVBbUOLRyK/lkwHlfiKUoeVIMyK5NF+up6TRg71t/8Bny6Q==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.5.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/util-endpoints": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.679.0.tgz",
"integrity": "sha512-YL6s4Y/1zC45OvddvgE139fjeWSKKPgLlnfrvhVL7alNyY9n7beR4uhoDpNrt5mI6sn9qiBF17790o+xLAXjjg==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "3.679.0",
"@smithy/types": "^3.5.0",
"@smithy/util-endpoints": "^2.1.3",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/util-user-agent-browser": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.679.0.tgz",
"integrity": "sha512-CusSm2bTBG1kFypcsqU8COhnYc6zltobsqs3nRrvYqYaOqtMnuE46K4XTWpnzKgwDejgZGOE+WYyprtAxrPvmQ==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "3.679.0",
"@smithy/types": "^3.5.0",
"bowser": "^2.11.0",
"tslib": "^2.6.2"
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/util-user-agent-node": {
"version": "3.679.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.679.0.tgz",
"integrity": "sha512-Bw4uXZ+NU5ed6TNfo4tBbhBSW+2eQxXYjYBGl5gLUNUpg2pDFToQAP6rXBFiwcG52V2ny5oLGiD82SoYuYkAVg==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/middleware-user-agent": "3.679.0",
"@aws-sdk/types": "3.679.0",
"@smithy/node-config-provider": "^3.1.8",
"@smithy/types": "^3.5.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
},
"peerDependencies": {
"aws-crt": ">=1.0.0"
},
"peerDependenciesMeta": {
"aws-crt": {
"optional": true
}
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/@aws-sdk/client-elasticache": { "node_modules/@aws-sdk/client-elasticache": {
"version": "3.675.0", "version": "3.675.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-elasticache/-/client-elasticache-3.675.0.tgz", "resolved": "https://registry.npmjs.org/@aws-sdk/client-elasticache/-/client-elasticache-3.675.0.tgz",
@@ -1245,6 +1809,7 @@
"version": "1.6.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
"integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
"license": "MIT",
"engines": { "engines": {
"node": ">=0.1.90" "node": ">=0.1.90"
} }
@@ -1960,6 +2525,73 @@
"node": ">=16.0.0" "node": ">=16.0.0"
} }
}, },
"node_modules/@smithy/eventstream-codec": {
"version": "3.1.7",
"resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.7.tgz",
"integrity": "sha512-kVSXScIiRN7q+s1x7BrQtZ1Aa9hvvP9FeCqCdBxv37GimIHgBCOnZ5Ip80HLt0DhnAKpiobFdGqTFgbaJNrazA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/crc32": "5.2.0",
"@smithy/types": "^3.6.0",
"@smithy/util-hex-encoding": "^3.0.0",
"tslib": "^2.6.2"
}
},
"node_modules/@smithy/eventstream-serde-browser": {
"version": "3.0.11",
"resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.11.tgz",
"integrity": "sha512-Pd1Wnq3CQ/v2SxRifDUihvpXzirJYbbtXfEnnLV/z0OGCTx/btVX74P86IgrZkjOydOASBGXdPpupYQI+iO/6A==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/eventstream-serde-universal": "^3.0.10",
"@smithy/types": "^3.6.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@smithy/eventstream-serde-config-resolver": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.8.tgz",
"integrity": "sha512-zkFIG2i1BLbfoGQnf1qEeMqX0h5qAznzaZmMVNnvPZz9J5AWBPkOMckZWPedGUPcVITacwIdQXoPcdIQq5FRcg==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.6.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@smithy/eventstream-serde-node": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.10.tgz",
"integrity": "sha512-hjpU1tIsJ9qpcoZq9zGHBJPBOeBGYt+n8vfhDwnITPhEre6APrvqq/y3XMDEGUT2cWQ4ramNqBPRbx3qn55rhw==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/eventstream-serde-universal": "^3.0.10",
"@smithy/types": "^3.6.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@smithy/eventstream-serde-universal": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.10.tgz",
"integrity": "sha512-ewG1GHbbqsFZ4asaq40KmxCmXO+AFSM1b+DcO2C03dyJj/ZH71CiTg853FSE/3SHK9q3jiYQIFjlGSwfxQ9kww==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/eventstream-codec": "^3.1.7",
"@smithy/types": "^3.6.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@smithy/fetch-http-handler": { "node_modules/@smithy/fetch-http-handler": {
"version": "3.2.9", "version": "3.2.9",
"resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.9.tgz", "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.9.tgz",
@@ -2698,7 +3330,8 @@
"node_modules/@types/triple-beam": { "node_modules/@types/triple-beam": {
"version": "1.3.5", "version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
"integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==",
"license": "MIT"
}, },
"node_modules/@types/uuid": { "node_modules/@types/uuid": {
"version": "9.0.8", "version": "9.0.8",
@@ -2731,7 +3364,6 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
"optional": true,
"dependencies": { "dependencies": {
"event-target-shim": "^5.0.0" "event-target-shim": "^5.0.0"
}, },
@@ -2944,8 +3576,7 @@
"type": "consulting", "type": "consulting",
"url": "https://feross.org/support" "url": "https://feross.org/support"
} }
], ]
"optional": true
}, },
"node_modules/base64id": { "node_modules/base64id": {
"version": "2.0.0", "version": "2.0.0",
@@ -3083,6 +3714,30 @@
"node": ">= 0.4.0" "node": ">= 0.4.0"
} }
}, },
"node_modules/buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT",
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"node_modules/buffer-equal-constant-time": { "node_modules/buffer-equal-constant-time": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
@@ -3158,7 +3813,6 @@
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"dependencies": { "dependencies": {
"ansi-styles": "^4.1.0", "ansi-styles": "^4.1.0",
"supports-color": "^7.1.0" "supports-color": "^7.1.0"
@@ -3174,7 +3828,6 @@
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"dependencies": { "dependencies": {
"has-flag": "^4.0.0" "has-flag": "^4.0.0"
}, },
@@ -4161,11 +4814,19 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
"optional": true,
"engines": { "engines": {
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/events": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
"license": "MIT",
"engines": {
"node": ">=0.8.x"
}
},
"node_modules/express": { "node_modules/express": {
"version": "4.21.1", "version": "4.21.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
@@ -4326,7 +4987,8 @@
"node_modules/fecha": { "node_modules/fecha": {
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
"integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==",
"license": "MIT"
}, },
"node_modules/file-uri-to-path": { "node_modules/file-uri-to-path": {
"version": "2.0.0", "version": "2.0.0",
@@ -4862,14 +5524,6 @@
"graphql": "14 - 16" "graphql": "14 - 16"
} }
}, },
"node_modules/graylog2": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/graylog2/-/graylog2-0.2.1.tgz",
"integrity": "sha512-vjysakwOhrAqMeIvSK0WZcmzKvkpxY6pCfT9QqtdSVAidPFIynuin7adqbdFp9MCCTbTE402WIxvg8cph5OWTA==",
"engines": {
"node": ">=0.6.11"
}
},
"node_modules/gtoken": { "node_modules/gtoken": {
"version": "7.0.1", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.0.1.tgz", "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.0.1.tgz",
@@ -4902,7 +5556,6 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
@@ -5058,6 +5711,26 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "BSD-3-Clause"
},
"node_modules/inflight": { "node_modules/inflight": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -5468,6 +6141,12 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
}, },
"node_modules/lodash.assign": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
"integrity": "sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw==",
"license": "MIT"
},
"node_modules/lodash.camelcase": { "node_modules/lodash.camelcase": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
@@ -5485,6 +6164,12 @@
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/lodash.find": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz",
"integrity": "sha512-yaRZoAV3Xq28F1iafWN1+a0rflOej93l1DQUejs3SZ41h2O9UJBoS9aueGjPDgAl4B6tPC0NuuchLKaDQQ3Isg==",
"license": "MIT"
},
"node_modules/lodash.includes": { "node_modules/lodash.includes": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -5501,6 +6186,18 @@
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
}, },
"node_modules/lodash.isempty": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
"integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==",
"license": "MIT"
},
"node_modules/lodash.iserror": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lodash.iserror/-/lodash.iserror-3.1.1.tgz",
"integrity": "sha512-eT/VeNns9hS7vAj1NKW/rRX6b+C3UX3/IAAqEE7aC4Oo2C0iD82NaP5IS4bSlQsammTii4qBJ8G1zd1LTL8hCw==",
"license": "MIT"
},
"node_modules/lodash.isinteger": { "node_modules/lodash.isinteger": {
"version": "4.0.4", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
@@ -5527,9 +6224,10 @@
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
}, },
"node_modules/logform": { "node_modules/logform": {
"version": "2.6.0", "version": "2.6.1",
"resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.1.tgz",
"integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", "integrity": "sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==",
"license": "MIT",
"dependencies": { "dependencies": {
"@colors/colors": "1.6.0", "@colors/colors": "1.6.0",
"@types/triple-beam": "^1.3.2", "@types/triple-beam": "^1.3.2",
@@ -6193,6 +6891,15 @@
"url": "https://github.com/prettier/prettier?sponsor=1" "url": "https://github.com/prettier/prettier?sponsor=1"
} }
}, },
"node_modules/process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
"license": "MIT",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/process-nextick-args": { "node_modules/process-nextick-args": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -6536,9 +7243,10 @@
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
}, },
"node_modules/safe-stable-stringify": { "node_modules/safe-stable-stringify": {
"version": "2.4.3", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
"integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
"license": "MIT",
"engines": { "engines": {
"node": ">=10" "node": ">=10"
} }
@@ -7510,6 +8218,7 @@
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
"integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==",
"license": "MIT",
"engines": { "engines": {
"node": ">= 14.0.0" "node": ">= 14.0.0"
} }
@@ -7749,39 +8458,76 @@
} }
}, },
"node_modules/winston": { "node_modules/winston": {
"version": "3.11.0", "version": "3.15.0",
"resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz", "resolved": "https://registry.npmjs.org/winston/-/winston-3.15.0.tgz",
"integrity": "sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==", "integrity": "sha512-RhruH2Cj0bV0WgNL+lOfoUBI4DVfdUNjVnJGVovWZmrcKtrFTTRzgXYK2O9cymSGjrERCtaAeHwMNnUWXlwZow==",
"license": "MIT",
"dependencies": { "dependencies": {
"@colors/colors": "^1.6.0", "@colors/colors": "^1.6.0",
"@dabh/diagnostics": "^2.0.2", "@dabh/diagnostics": "^2.0.2",
"async": "^3.2.3", "async": "^3.2.3",
"is-stream": "^2.0.0", "is-stream": "^2.0.0",
"logform": "^2.4.0", "logform": "^2.6.0",
"one-time": "^1.0.0", "one-time": "^1.0.0",
"readable-stream": "^3.4.0", "readable-stream": "^3.4.0",
"safe-stable-stringify": "^2.3.1", "safe-stable-stringify": "^2.3.1",
"stack-trace": "0.0.x", "stack-trace": "0.0.x",
"triple-beam": "^1.3.0", "triple-beam": "^1.3.0",
"winston-transport": "^4.5.0" "winston-transport": "^4.7.0"
}, },
"engines": { "engines": {
"node": ">= 12.0.0" "node": ">= 12.0.0"
} }
}, },
"node_modules/winston-transport": { "node_modules/winston-cloudwatch": {
"version": "4.6.0", "version": "6.3.0",
"resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.6.0.tgz", "resolved": "https://registry.npmjs.org/winston-cloudwatch/-/winston-cloudwatch-6.3.0.tgz",
"integrity": "sha512-wbBA9PbPAHxKiygo7ub7BYRiKxms0tpfU2ljtWzb3SjRjv5yl6Ozuy/TkXf00HTAt+Uylo3gSkNwzc4ME0wiIg==", "integrity": "sha512-ffLMBUtas4qCpAyNfA6yUjZUQPepl6XduwHjukxRtI8hSWE4dKmy1k1lcLpyYiglrsgZop+OQYAV/iJJ+7Z94g==",
"license": "MIT",
"dependencies": { "dependencies": {
"logform": "^2.3.2", "async": "^3.1.0",
"readable-stream": "^3.6.0", "chalk": "^4.0.0",
"fast-safe-stringify": "^2.0.7",
"lodash.assign": "^4.2.0",
"lodash.find": "^4.6.0",
"lodash.isempty": "^4.4.0",
"lodash.iserror": "^3.1.1"
},
"peerDependencies": {
"@aws-sdk/client-cloudwatch-logs": "^3.0.0",
"winston": "^3.0.0"
}
},
"node_modules/winston-transport": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.8.0.tgz",
"integrity": "sha512-qxSTKswC6llEMZKgCQdaWgDuMJQnhuvF5f2Nk3SNXc4byfQ+voo2mX1Px9dkNOuR8p0KAjfPG29PuYUSIb+vSA==",
"license": "MIT",
"dependencies": {
"logform": "^2.6.1",
"readable-stream": "^4.5.2",
"triple-beam": "^1.3.0" "triple-beam": "^1.3.0"
}, },
"engines": { "engines": {
"node": ">= 12.0.0" "node": ">= 12.0.0"
} }
}, },
"node_modules/winston-transport/node_modules/readable-stream": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
"integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
"license": "MIT",
"dependencies": {
"abort-controller": "^3.0.0",
"buffer": "^6.0.3",
"events": "^3.3.0",
"process": "^0.11.10",
"string_decoder": "^1.3.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/word-wrap": { "node_modules/word-wrap": {
"version": "1.2.5", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",

View File

@@ -19,6 +19,7 @@
"makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\"" "makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\""
}, },
"dependencies": { "dependencies": {
"@aws-sdk/client-cloudwatch-logs": "^3.679.0",
"@aws-sdk/client-elasticache": "^3.675.0", "@aws-sdk/client-elasticache": "^3.675.0",
"@aws-sdk/client-secrets-manager": "^3.675.0", "@aws-sdk/client-secrets-manager": "^3.675.0",
"@aws-sdk/client-ses": "^3.675.0", "@aws-sdk/client-ses": "^3.675.0",
@@ -44,7 +45,6 @@
"firebase-admin": "^12.6.0", "firebase-admin": "^12.6.0",
"graphql": "^16.9.0", "graphql": "^16.9.0",
"graphql-request": "^6.1.0", "graphql-request": "^6.1.0",
"graylog2": "^0.2.1",
"inline-css": "^4.0.2", "inline-css": "^4.0.2",
"intuit-oauth": "^4.1.2", "intuit-oauth": "^4.1.2",
"ioredis": "^5.4.1", "ioredis": "^5.4.1",
@@ -66,6 +66,8 @@
"ssh2-sftp-client": "^10.0.3", "ssh2-sftp-client": "^10.0.3",
"twilio": "^4.23.0", "twilio": "^4.23.0",
"uuid": "^10.0.0", "uuid": "^10.0.0",
"winston": "^3.15.0",
"winston-cloudwatch": "^6.3.0",
"xml2js": "^0.6.2", "xml2js": "^0.6.2",
"xmlbuilder2": "^3.1.1" "xmlbuilder2": "^3.1.1"
}, },

View File

@@ -1,5 +1,10 @@
const cors = require("cors"); // Load environment variables THIS MUST BE AT THE TOP
const path = require("path"); const path = require("path");
require("dotenv").config({
path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`)
});
const cors = require("cors");
const http = require("http"); const http = require("http");
const Redis = require("ioredis"); const Redis = require("ioredis");
const express = require("express"); const express = require("express");
@@ -18,11 +23,6 @@ const { redisSocketEvents } = require("./server/web-sockets/redisSocketEvents");
const { ElastiCacheClient, DescribeCacheClustersCommand } = require("@aws-sdk/client-elasticache"); const { ElastiCacheClient, DescribeCacheClustersCommand } = require("@aws-sdk/client-elasticache");
const { default: InstanceManager } = require("./server/utils/instanceMgr"); const { default: InstanceManager } = require("./server/utils/instanceMgr");
// Load environment variables
require("dotenv").config({
path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`)
});
const CLUSTER_RETRY_BASE_DELAY = 100; const CLUSTER_RETRY_BASE_DELAY = 100;
const CLUSTER_RETRY_MAX_DELAY = 5000; const CLUSTER_RETRY_MAX_DELAY = 5000;
const CLUSTER_RETRY_JITTER = 100; const CLUSTER_RETRY_JITTER = 100;
@@ -153,18 +153,13 @@ const connectToRedisCluster = async () => {
} else { } else {
// Use the Dockerized Redis cluster in development // Use the Dockerized Redis cluster in development
if (isEmpty(process.env?.REDIS_URL) || !isString(process.env?.REDIS_URL)) { if (isEmpty(process.env?.REDIS_URL) || !isString(process.env?.REDIS_URL)) {
logger.log(`[${process.env.NODE_ENV}] No or Malformed REDIS_URL present.`, "ERROR", "redis", "api"); logger.log(`No or Malformed REDIS_URL present.`, "ERROR", "redis", "api");
process.exit(1); process.exit(1);
} }
try { try {
redisServers = JSON.parse(process.env.REDIS_URL); redisServers = JSON.parse(process.env.REDIS_URL);
} catch (error) { } catch (error) {
logger.log( logger.log(`Failed to parse REDIS_URL: ${error.message}. Exiting...`, "ERROR", "redis", "api");
`[${process.env.NODE_ENV}] Failed to parse REDIS_URL: ${error.message}. Exiting...`,
"ERROR",
"redis",
"api"
);
process.exit(1); process.exit(1);
} }
} }
@@ -172,12 +167,7 @@ const connectToRedisCluster = async () => {
const clusterRetryStrategy = (times) => { const clusterRetryStrategy = (times) => {
const delay = const delay =
Math.min(CLUSTER_RETRY_BASE_DELAY + times * 50, CLUSTER_RETRY_MAX_DELAY) + Math.random() * CLUSTER_RETRY_JITTER; Math.min(CLUSTER_RETRY_BASE_DELAY + times * 50, CLUSTER_RETRY_MAX_DELAY) + Math.random() * CLUSTER_RETRY_JITTER;
logger.log( logger.log(`Redis cluster not yet ready. Retrying in ${delay.toFixed(2)}ms`, "WARN", "redis", "api");
`[${process.env.NODE_ENV}] Redis cluster not yet ready. Retrying in ${delay.toFixed(2)}ms`,
"ERROR",
"redis",
"api"
);
return delay; return delay;
}; };
@@ -194,12 +184,12 @@ const connectToRedisCluster = async () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
redisCluster.on("ready", () => { redisCluster.on("ready", () => {
logger.log(`[${process.env.NODE_ENV}] Redis cluster connection established.`, "INFO", "redis", "api"); logger.log(`Redis cluster connection established.`, "INFO", "redis", "api");
resolve(redisCluster); resolve(redisCluster);
}); });
redisCluster.on("error", (err) => { redisCluster.on("error", (err) => {
logger.log(`[${process.env.NODE_ENV}] Redis cluster connection failed: ${err.message}`, "ERROR", "redis", "api"); logger.log(`Redis cluster connection failed: ${err.message}`, "ERROR", "redis", "api");
reject(err); reject(err);
}); });
}); });
@@ -215,7 +205,7 @@ const applySocketIO = async ({ server, app }) => {
// Handle errors // Handle errors
redisCluster.on("error", (err) => { redisCluster.on("error", (err) => {
logger.log(`[${process.env.NODE_ENV}] Redis ERROR`, "ERROR", "redis", "api"); logger.log(`Redis ERROR`, "ERROR", "redis", "api");
}); });
const pubClient = redisCluster; const pubClient = redisCluster;
@@ -249,7 +239,7 @@ const applySocketIO = async ({ server, app }) => {
}); });
if (isString(process.env.REDIS_ADMIN_PASS) && !isEmpty(process.env.REDIS_ADMIN_PASS)) { if (isString(process.env.REDIS_ADMIN_PASS) && !isEmpty(process.env.REDIS_ADMIN_PASS)) {
logger.log(`[${process.env.NODE_ENV}] Initializing Redis Admin UI....`, "INFO", "redis", "api"); logger.log(`Initializing Redis Admin UI....`, "INFO", "redis", "api");
instrument(ioRedis, { instrument(ioRedis, {
auth: { auth: {
type: "basic", type: "basic",
@@ -312,9 +302,9 @@ const main = async () => {
try { try {
await server.listen(port); await server.listen(port);
logger.log(`[${process.env.NODE_ENV}] Server started on port ${port}`, "INFO", "api"); logger.log(`Server started on port ${port}`, "INFO", "api");
} catch (error) { } catch (error) {
logger.log(`[${process.env.NODE_ENV}] Server failed to start on port ${port}`, "ERROR", "api", error); logger.log(`Server failed to start on port ${port}`, "ERROR", "api", error);
} }
}; };

View File

@@ -24,9 +24,9 @@ axios.interceptors.request.use((x) => {
const printable = `${new Date()} | Request: ${x.method.toUpperCase()} | ${ const printable = `${new Date()} | Request: ${x.method.toUpperCase()} | ${
x.url x.url
} | ${JSON.stringify(x.data)} | ${JSON.stringify(headers)}`; } | ${JSON.stringify(x.data)} | ${JSON.stringify(headers)}`;
console.log(printable); //console.log(printable);
CdkBase.createJsonEvent(socket, "TRACE", `Raw Request: ${printable}`, x.data); CdkBase.createJsonEvent(socket, "SILLY", `Raw Request: ${printable}`, x.data);
return x; return x;
}); });
@@ -35,8 +35,8 @@ axios.interceptors.response.use((x) => {
const socket = x.config.socket; const socket = x.config.socket;
const printable = `${new Date()} | Response: ${x.status} | ${JSON.stringify(x.data)}`; const printable = `${new Date()} | Response: ${x.status} | ${JSON.stringify(x.data)}`;
console.log(printable); //console.log(printable);
CdkBase.createJsonEvent(socket, "TRACE", `Raw Response: ${printable}`, x.data); CdkBase.createJsonEvent(socket, "SILLY", `Raw Response: ${printable}`, x.data);
return x; return x;
}); });
@@ -181,7 +181,7 @@ async function QueryBillData(socket, billids) {
const result = await client const result = await client
.setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` }) .setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` })
.request(queries.GET_PBS_AP_ALLOCATIONS, { billids: billids }); .request(queries.GET_PBS_AP_ALLOCATIONS, { billids: billids });
CdkBase.createLogEvent(socket, "TRACE", `Bill data query result ${JSON.stringify(result, null, 2)}`); CdkBase.createLogEvent(socket, "SILLY", `Bill data query result ${JSON.stringify(result, null, 2)}`);
return result; return result;
} }

View File

@@ -26,9 +26,9 @@ axios.interceptors.request.use((x) => {
const printable = `${new Date()} | Request: ${x.method.toUpperCase()} | ${ const printable = `${new Date()} | Request: ${x.method.toUpperCase()} | ${
x.url x.url
} | ${JSON.stringify(x.data)} | ${JSON.stringify(headers)}`; } | ${JSON.stringify(x.data)} | ${JSON.stringify(headers)}`;
console.log(printable); //console.log(printable);
CdkBase.createJsonEvent(socket, "TRACE", `Raw Request: ${printable}`, x.data); CdkBase.createJsonEvent(socket, "SILLY", `Raw Request: ${printable}`, x.data);
return x; return x;
}); });
@@ -37,8 +37,8 @@ axios.interceptors.response.use((x) => {
const socket = x.config.socket; const socket = x.config.socket;
const printable = `${new Date()} | Response: ${x.status} | ${JSON.stringify(x.data)}`; const printable = `${new Date()} | Response: ${x.status} | ${JSON.stringify(x.data)}`;
console.log(printable); //console.log(printable);
CdkBase.createJsonEvent(socket, "TRACE", `Raw Response: ${printable}`, x.data); CdkBase.createJsonEvent(socket, "SILLY", `Raw Response: ${printable}`, x.data);
return x; return x;
}); });
@@ -118,7 +118,7 @@ async function CheckForErrors(socket, response) {
CdkBase.createLogEvent(socket, "DEBUG", `Successful response from DMS. ${response.Message || ""}`); CdkBase.createLogEvent(socket, "DEBUG", `Successful response from DMS. ${response.Message || ""}`);
} else { } else {
CdkBase.createLogEvent(socket, "ERROR", `Error received from DMS: ${response.Message}`); CdkBase.createLogEvent(socket, "ERROR", `Error received from DMS: ${response.Message}`);
CdkBase.createLogEvent(socket, "TRACE", `Error received from DMS: ${JSON.stringify(response)}`); CdkBase.createLogEvent(socket, "SILLY", `Error received from DMS: ${JSON.stringify(response)}`);
} }
} }
@@ -130,7 +130,7 @@ async function QueryJobData(socket, jobid) {
const result = await client const result = await client
.setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` }) .setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` })
.request(queries.QUERY_JOBS_FOR_PBS_EXPORT, { id: jobid }); .request(queries.QUERY_JOBS_FOR_PBS_EXPORT, { id: jobid });
CdkBase.createLogEvent(socket, "TRACE", `Job data query result ${JSON.stringify(result, null, 2)}`); CdkBase.createLogEvent(socket, "SILLY", `Job data query result ${JSON.stringify(result, null, 2)}`);
return result.jobs_by_pk; return result.jobs_by_pk;
} }

View File

@@ -63,7 +63,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes
); );
if (!account) { if (!account) {
logger.log("qbxml-receivables-no-account", "warn", null, jobline.id, null); logger.log("qbxml-receivables-no-account", "warn", null, jobline.id);
throw new Error( throw new Error(
`A matching account does not exist for the part allocation. Center: ${jobline.profitcenter_part}` `A matching account does not exist for the part allocation. Center: ${jobline.profitcenter_part}`
); );
@@ -207,7 +207,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes
}); });
if (!hasMapaLine && jobs_by_pk.job_totals.rates.mapa.total.amount > 0) { if (!hasMapaLine && jobs_by_pk.job_totals.rates.mapa.total.amount > 0) {
// console.log("Adding MAPA Line Manually."); // //console.log("Adding MAPA Line Manually.");
const mapaAccountName = responsibilityCenters.defaults.profits.MAPA; const mapaAccountName = responsibilityCenters.defaults.profits.MAPA;
const mapaAccount = responsibilityCenters.profits.find((c) => c.name === mapaAccountName); const mapaAccount = responsibilityCenters.profits.find((c) => c.name === mapaAccountName);
@@ -272,12 +272,12 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes
}); });
} }
} else { } else {
//console.log("NO MAPA ACCOUNT FOUND!!"); ////console.log("NO MAPA ACCOUNT FOUND!!");
} }
} }
if (!hasMashLine && jobs_by_pk.job_totals.rates.mash.total.amount > 0) { if (!hasMashLine && jobs_by_pk.job_totals.rates.mash.total.amount > 0) {
// console.log("Adding MASH Line Manually."); // //console.log("Adding MASH Line Manually.");
const mashAccountName = responsibilityCenters.defaults.profits.MASH; const mashAccountName = responsibilityCenters.defaults.profits.MASH;
@@ -341,7 +341,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes
}); });
} }
} else { } else {
// console.log("NO MASH ACCOUNT FOUND!!"); // //console.log("NO MASH ACCOUNT FOUND!!");
} }
} }
@@ -795,7 +795,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes
: taxCodes[taxAccountCode]; : taxCodes[taxAccountCode];
for (let tyCounter = 1; tyCounter <= 5; tyCounter++) { for (let tyCounter = 1; tyCounter <= 5; tyCounter++) {
const taxAmount = Dinero(job_totals.totals.us_sales_tax_breakdown[`ty${tyCounter}Tax`]); const taxAmount = Dinero(job_totals.totals.us_sales_tax_breakdown[`ty${tyCounter}Tax`]);
console.log(`Tax ${tyCounter}`, taxAmount.toFormat()); //console.log(`Tax ${tyCounter}`, taxAmount.toFormat());
if (taxAmount.getAmount() > 0) { if (taxAmount.getAmount() > 0) {
if (qbo) { if (qbo) {
InvoiceLineAdd.push({ InvoiceLineAdd.push({

View File

@@ -45,7 +45,7 @@ exports.default = async (req, res) => {
const BearerToken = req.BearerToken; const BearerToken = req.BearerToken;
const client = req.userGraphQLClient; const client = req.userGraphQLClient;
logger.log("qbo-payable-create", "DEBUG", req.user.email, billsToQuery); logger.log("qbo-payable-create", "DEBUG", req.user.email, null, { billsToQuery });
const result = await client const result = await client
.setHeaders({ Authorization: BearerToken }) .setHeaders({ Authorization: BearerToken })
@@ -91,6 +91,12 @@ exports.default = async (req, res) => {
ret.push({ billid: bill.id, success: true }); ret.push({ billid: bill.id, success: true });
} catch (error) { } catch (error) {
logger.log("qbo-paybles-create-error", "ERROR", req.user.email, null, {
error:
(error && error.authResponse && error.authResponse.body) ||
error.response?.data?.Fault?.Error.map((e) => e.Detail).join(", ") ||
(error && error.message)
});
ret.push({ ret.push({
billid: bill.id, billid: bill.id,
success: false, success: false,
@@ -121,8 +127,8 @@ exports.default = async (req, res) => {
res.status(200).json(ret); res.status(200).json(ret);
} catch (error) { } catch (error) {
console.log(error); //console.log(error);
logger.log("qbo-payable-create-error", "ERROR", req.user.email, { logger.log("qbo-payable-create-error", "ERROR", req.user.email, null, {
error: error.message, error: error.message,
stack: error.stack stack: error.stack
}); });

View File

@@ -49,7 +49,7 @@ exports.default = async (req, res) => {
const BearerToken = req.BearerToken; const BearerToken = req.BearerToken;
const client = req.userGraphQLClient; const client = req.userGraphQLClient;
logger.log("qbo-payment-create", "DEBUG", req.user.email, paymentsToQuery); logger.log("qbo-payment-create", "DEBUG", req.user.email, null, { paymentsToQuery });
const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.QUERY_PAYMENTS_FOR_EXPORT, { const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.QUERY_PAYMENTS_FOR_EXPORT, {
payments: paymentsToQuery payments: paymentsToQuery
@@ -152,7 +152,7 @@ exports.default = async (req, res) => {
ret.push({ paymentid: payment.id, success: true }); ret.push({ paymentid: payment.id, success: true });
} catch (error) { } catch (error) {
logger.log("qbo-payment-create-error", "ERROR", req.user.email, { logger.log("qbo-payment-create-error", "ERROR", req.user.email, null, {
error: (error && error.authResponse && error.authResponse.body) || (error && error.message) error: (error && error.authResponse && error.authResponse.body) || (error && error.message)
}); });
//Add the export log error. //Add the export log error.
@@ -182,8 +182,8 @@ exports.default = async (req, res) => {
res.status(200).json(ret); res.status(200).json(ret);
} catch (error) { } catch (error) {
console.log(error); //console.log(error);
logger.log("qbo-payment-create-error", "ERROR", req.user.email, { logger.log("qbo-payment-create-error", "ERROR", req.user.email, null, {
error: error.message, error: error.message,
stack: error.stack stack: error.stack
}); });

View File

@@ -185,7 +185,7 @@ exports.default = async (req, res) => {
error?.response?.data || error?.response?.data ||
error?.message error?.message
}); });
console.log(error); //console.log(error);
logger.log("qbo-receivable-create-error", "ERROR", req.user.email, { logger.log("qbo-receivable-create-error", "ERROR", req.user.email, {
error: error.message, error: error.message,
stack: error.stack stack: error.stack
@@ -211,7 +211,7 @@ exports.default = async (req, res) => {
res.status(200).json(ret); res.status(200).json(ret);
} catch (error) { } catch (error) {
console.log(error); //console.log(error);
logger.log("qbo-receivable-create-error", "ERROR", req.user.email, { logger.log("qbo-receivable-create-error", "ERROR", req.user.email, {
error: error.message, error: error.message,
stack: error.stack stack: error.stack

View File

@@ -42,9 +42,10 @@ exports.default = async (req, res) => {
//For each invoice. //For each invoice.
res.status(200).json(QbXmlToExecute); res.status(200).json(QbXmlToExecute);
} catch (error) { } catch (error) {
logger.log("qbxml-payable-error", "ERROR", req.user.email, req.body.billsToQuery, { logger.log("qbxml-payable-error", "ERROR", req?.user?.email, null, {
error: error.message, billsToQuery: req?.body?.billsToQuery,
stack: error.stack error: error?.message,
stack: error?.stack
}); });
res.status(400).send(JSON.stringify(error)); res.status(400).send(JSON.stringify(error));
} }

View File

@@ -21,7 +21,9 @@ exports.default = async (req, res) => {
const client = req.userGraphQLClient; const client = req.userGraphQLClient;
try { try {
logger.log("qbxml-payments-create", "DEBUG", req.user.email, req.body.paymentsToQuery, null); logger.log("qbxml-payments-create", "DEBUG", req?.user?.email, null, {
paymentsToQuery: req.body?.paymentsToQuery
});
const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.QUERY_PAYMENTS_FOR_EXPORT, { const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.QUERY_PAYMENTS_FOR_EXPORT, {
payments: paymentsToQuery payments: paymentsToQuery
@@ -62,7 +64,8 @@ exports.default = async (req, res) => {
res.status(200).json(QbXmlToExecute); res.status(200).json(QbXmlToExecute);
} catch (error) { } catch (error) {
logger.log("qbxml-payments-error", "error", req.user.email, req.body.paymentsToQuery, { logger.log("qbxml-payments-error", "error", req?.user?.email, null, {
paymentsToQuery: req.body?.paymentsToQuery,
error: error.message, error: error.message,
stack: error.stack stack: error.stack
}); });

View File

@@ -23,7 +23,9 @@ exports.default = async (req, res) => {
const client = req.userGraphQLClient; const client = req.userGraphQLClient;
try { try {
logger.log("qbxml-receivables-create", "DEBUG", req.user.email, req.body.jobIds, null); logger.log("qbxml-receivables-create", "DEBUG", req?.user?.email, null, {
jobIds: req?.body?.jobIds
});
const result = await client const result = await client
.setHeaders({ Authorization: BearerToken }) .setHeaders({ Authorization: BearerToken })
@@ -74,7 +76,8 @@ exports.default = async (req, res) => {
res.status(200).json(QbXmlToExecute); res.status(200).json(QbXmlToExecute);
} catch (error) { } catch (error) {
logger.log("qbxml-receivables-error", "error", req.user.email, req.body.jobIds, { logger.log("qbxml-receivables-error", "error", req?.user?.email, null, {
jobIds: req.body?.jobIds,
error: error.message, error: error.message,
stack: error.stack stack: error.stack
}); });

View File

@@ -9,7 +9,7 @@ require("dotenv").config({
const client = require("../graphql-client/graphql-client").client; const client = require("../graphql-client/graphql-client").client;
exports.createAssociation = async (req, res) => { exports.createAssociation = async (req, res) => {
logger.log("admin-create-association", "ADMIN", req.user.email, null, { logger.log("admin-create-association", "debug", req.user.email, null, {
request: req.body, request: req.body,
ioadmin: true ioadmin: true
}); });
@@ -31,7 +31,7 @@ exports.createAssociation = async (req, res) => {
res.json(result); res.json(result);
}; };
exports.createShop = async (req, res) => { exports.createShop = async (req, res) => {
logger.log("admin-create-shop", "ADMIN", req.user.email, null, { logger.log("admin-create-shop", "debug", req.user.email, null, {
request: req.body, request: req.body,
ioadmin: true ioadmin: true
}); });
@@ -64,7 +64,7 @@ exports.createShop = async (req, res) => {
} }
}; };
exports.updateCounter = async (req, res) => { exports.updateCounter = async (req, res) => {
logger.log("admin-update-counter", "ADMIN", req.user.email, null, { logger.log("admin-update-counter", "debug", req.user.email, null, {
request: req.body, request: req.body,
ioadmin: true ioadmin: true
}); });
@@ -91,7 +91,7 @@ exports.updateCounter = async (req, res) => {
} }
}; };
exports.updateShop = async (req, res) => { exports.updateShop = async (req, res) => {
logger.log("admin-update-shop", "ADMIN", req.user.email, null, { logger.log("admin-update-shop", "debug", req.user.email, null, {
request: req.body, request: req.body,
ioadmin: true ioadmin: true
}); });

View File

@@ -22,7 +22,7 @@ exports.defaultRoute = async function (req, res) {
const jobData = await QueryJobData(req, req.BearerToken, req.body.jobid); const jobData = await QueryJobData(req, req.BearerToken, req.body.jobid);
return res.status(200).json({ data: calculateAllocations(req, jobData) }); return res.status(200).json({ data: calculateAllocations(req, jobData) });
} catch (error) { } catch (error) {
console.log(error); ////console.log(error);
CdkBase.createLogEvent(req, "ERROR", `Error encountered in CdkCalculateAllocations. ${error}`); CdkBase.createLogEvent(req, "ERROR", `Error encountered in CdkCalculateAllocations. ${error}`);
res.status(500).json({ error: `Error encountered in CdkCalculateAllocations. ${error}` }); res.status(500).json({ error: `Error encountered in CdkCalculateAllocations. ${error}` });
} }
@@ -33,7 +33,7 @@ exports.default = async function (socket, jobid) {
const jobData = await QueryJobData(socket, "Bearer " + socket.handshake.auth.token, jobid); const jobData = await QueryJobData(socket, "Bearer " + socket.handshake.auth.token, jobid);
return calculateAllocations(socket, jobData); return calculateAllocations(socket, jobData);
} catch (error) { } catch (error) {
console.log(error); ////console.log(error);
CdkBase.createLogEvent(socket, "ERROR", `Error encountered in CdkCalculateAllocations. ${error}`); CdkBase.createLogEvent(socket, "ERROR", `Error encountered in CdkCalculateAllocations. ${error}`);
} }
}; };
@@ -42,7 +42,7 @@ async function QueryJobData(connectionData, token, jobid) {
CdkBase.createLogEvent(connectionData, "DEBUG", `Querying job data for id ${jobid}`); CdkBase.createLogEvent(connectionData, "DEBUG", `Querying job data for id ${jobid}`);
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {}); const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});
const result = await client.setHeaders({ Authorization: token }).request(queries.GET_CDK_ALLOCATIONS, { id: jobid }); const result = await client.setHeaders({ Authorization: token }).request(queries.GET_CDK_ALLOCATIONS, { id: jobid });
CdkBase.createLogEvent(connectionData, "TRACE", `Job data query result ${JSON.stringify(result, null, 2)}`); CdkBase.createLogEvent(connectionData, "SILLY", `Job data query result ${JSON.stringify(result, null, 2)}`);
return result.jobs_by_pk; return result.jobs_by_pk;
} }
@@ -212,7 +212,7 @@ function calculateAllocations(connectionData, job) {
}); });
if (!hasMapaLine && job.job_totals.rates.mapa.total.amount > 0) { if (!hasMapaLine && job.job_totals.rates.mapa.total.amount > 0) {
// console.log("Adding MAPA Line Manually."); // //console.log("Adding MAPA Line Manually.");
const mapaAccountName = selectedDmsAllocationConfig.profits.MAPA; const mapaAccountName = selectedDmsAllocationConfig.profits.MAPA;
const mapaAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === mapaAccountName); const mapaAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === mapaAccountName);
@@ -224,7 +224,7 @@ function calculateAllocations(connectionData, job) {
Dinero(job.job_totals.rates.mapa.total) Dinero(job.job_totals.rates.mapa.total)
); );
} else { } else {
//console.log("NO MAPA ACCOUNT FOUND!!"); ////console.log("NO MAPA ACCOUNT FOUND!!");
} }
} }
@@ -373,13 +373,19 @@ function calculateAllocations(connectionData, job) {
}); });
//profile level adjustments for labor and materials //profile level adjustments for labor and materials
Object.keys(job.job_totals.rates).forEach((key) => { Object.keys(job.job_totals.rates).forEach((key) => {
if (job.job_totals.rates[key] && job.job_totals.rates[key].adjustment && Dinero(job.job_totals.rates[key].adjustment).isZero() === false) { if (
job.job_totals.rates[key] &&
job.job_totals.rates[key].adjustment &&
Dinero(job.job_totals.rates[key].adjustment).isZero() === false
) {
const accountName = selectedDmsAllocationConfig.profits[key.toUpperCase()]; const accountName = selectedDmsAllocationConfig.profits[key.toUpperCase()];
const otherAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === accountName); const otherAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === accountName);
if (otherAccount) { if (otherAccount) {
if (!profitCenterHash[accountName]) profitCenterHash[accountName] = Dinero(); if (!profitCenterHash[accountName]) profitCenterHash[accountName] = Dinero();
profitCenterHash[accountName] = profitCenterHash[accountName].add(Dinero(job.job_totals.rates[key].adjustments)); profitCenterHash[accountName] = profitCenterHash[accountName].add(
Dinero(job.job_totals.rates[key].adjustments)
);
} else { } else {
CdkBase.createLogEvent( CdkBase.createLogEvent(
connectionData, connectionData,

View File

@@ -39,8 +39,8 @@ exports.default = async function ReloadCdkMakes(req, res) {
const deleteResult = await client const deleteResult = await client
.setHeaders({ Authorization: BearerToken }) .setHeaders({ Authorization: BearerToken })
.request(queries.DELETE_ALL_DMS_VEHICLES, {}); .request(queries.DELETE_ALL_DMS_VEHICLES, {});
console.log("🚀 ~ file: cdk-get-makes.js ~ line 53 ~ deleteResult", deleteResult);
// logger.logger.debug("🚀 ~ file: cdk-get-makes.js ~ line 53 ~ deleteResult", { deleteResult });
//Insert the new ones. //Insert the new ones.
const insertResult = await client.setHeaders({ Authorization: BearerToken }).request(queries.INSERT_DMS_VEHICLES, { const insertResult = await client.setHeaders({ Authorization: BearerToken }).request(queries.INSERT_DMS_VEHICLES, {
@@ -59,6 +59,7 @@ exports.default = async function ReloadCdkMakes(req, res) {
cdk_dealerid, cdk_dealerid,
count: newList.length count: newList.length
}); });
res.sendStatus(200); res.sendStatus(200);
} catch (error) { } catch (error) {
logger.log("cdk-replace-makes-models-error", "ERROR", req.user.email, null, { logger.log("cdk-replace-makes-models-error", "ERROR", req.user.email, null, {

View File

@@ -151,7 +151,7 @@ async function QueryJobData(socket, jobid) {
const result = await client const result = await client
.setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` }) .setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` })
.request(queries.QUERY_JOBS_FOR_CDK_EXPORT, { id: jobid }); .request(queries.QUERY_JOBS_FOR_CDK_EXPORT, { id: jobid });
CdkBase.createLogEvent(socket, "TRACE", `Job data query result ${JSON.stringify(result, null, 2)}`); CdkBase.createLogEvent(socket, "SILLY", `Job data query result ${JSON.stringify(result, null, 2)}`);
return result.jobs_by_pk; return result.jobs_by_pk;
} }
@@ -171,7 +171,7 @@ async function CalculateDmsVid(socket, JobData) {
CdkBase.createLogEvent( CdkBase.createLogEvent(
socket, socket,
"TRACE", "SILLY",
`soapClientVehicleInsertUpdate.getVehIdsAsync Result ${JSON.stringify(result, null, 2)}` `soapClientVehicleInsertUpdate.getVehIdsAsync Result ${JSON.stringify(result, null, 2)}`
); );
CheckCdkResponseForError(socket, soapResponseVehicleInsertUpdate); CheckCdkResponseForError(socket, soapResponseVehicleInsertUpdate);
@@ -214,7 +214,7 @@ async function QueryDmsVehicleById(socket, JobData, DMSVid) {
CdkBase.createLogEvent( CdkBase.createLogEvent(
socket, socket,
"TRACE", "SILLY",
`soapClientVehicleInsertUpdate.readAsync Result ${JSON.stringify(result, null, 2)}` `soapClientVehicleInsertUpdate.readAsync Result ${JSON.stringify(result, null, 2)}`
); );
CdkBase.createXmlEvent(socket, rawResponse, `soapClientVehicleInsertUpdate.readAsync response.`); CdkBase.createXmlEvent(socket, rawResponse, `soapClientVehicleInsertUpdate.readAsync response.`);
@@ -246,7 +246,7 @@ async function QueryDmsCustomerById(socket, JobData, CustomerId) {
CdkBase.createXmlEvent(socket, rawResponse, `soapClientCustomerInsertUpdate.readAsync response.`); CdkBase.createXmlEvent(socket, rawResponse, `soapClientCustomerInsertUpdate.readAsync response.`);
CdkBase.createLogEvent( CdkBase.createLogEvent(
socket, socket,
"TRACE", "SILLY",
`soapClientCustomerInsertUpdate.readAsync Result ${JSON.stringify(result, null, 2)}` `soapClientCustomerInsertUpdate.readAsync Result ${JSON.stringify(result, null, 2)}`
); );
CheckCdkResponseForError(socket, soapResponseCustomerInsertUpdate); CheckCdkResponseForError(socket, soapResponseCustomerInsertUpdate);
@@ -295,7 +295,7 @@ async function QueryDmsCustomerByName(socket, JobData) {
CdkBase.createLogEvent( CdkBase.createLogEvent(
socket, socket,
"TRACE", "SILLY",
`soapClientCustomerSearch.executeSearchBulkAsync Result ${JSON.stringify(result, null, 2)}` `soapClientCustomerSearch.executeSearchBulkAsync Result ${JSON.stringify(result, null, 2)}`
); );
CheckCdkResponseForError(socket, soapResponseCustomerSearch); CheckCdkResponseForError(socket, soapResponseCustomerSearch);
@@ -337,7 +337,7 @@ async function GenerateDmsCustomerNumber(socket) {
CdkBase.createLogEvent( CdkBase.createLogEvent(
socket, socket,
"TRACE", "SILLY",
`soapClientCustomerInsertUpdate.getCustomerNumberAsync Result ${JSON.stringify(result, null, 2)}` `soapClientCustomerInsertUpdate.getCustomerNumberAsync Result ${JSON.stringify(result, null, 2)}`
); );
CheckCdkResponseForError(socket, soapResponseCustomerInsertUpdate); CheckCdkResponseForError(socket, soapResponseCustomerInsertUpdate);
@@ -425,7 +425,7 @@ async function InsertDmsCustomer(socket, newCustomerNumber) {
CdkBase.createXmlEvent(socket, rawResponse, `soapClientCustomerInsertUpdate.insertAsync response.`); CdkBase.createXmlEvent(socket, rawResponse, `soapClientCustomerInsertUpdate.insertAsync response.`);
CdkBase.createLogEvent( CdkBase.createLogEvent(
socket, socket,
"TRACE", "SILLY",
`soapClientCustomerInsertUpdate.insertAsync Result ${JSON.stringify(result, null, 2)}` `soapClientCustomerInsertUpdate.insertAsync Result ${JSON.stringify(result, null, 2)}`
); );
CheckCdkResponseForError(socket, soapResponseCustomerInsertUpdate); CheckCdkResponseForError(socket, soapResponseCustomerInsertUpdate);
@@ -505,7 +505,7 @@ async function InsertDmsVehicle(socket) {
CdkBase.createLogEvent( CdkBase.createLogEvent(
socket, socket,
"TRACE", "SILLY",
`soapClientVehicleInsertUpdate.insertAsync Result ${JSON.stringify(result, null, 2)}` `soapClientVehicleInsertUpdate.insertAsync Result ${JSON.stringify(result, null, 2)}`
); );
CdkBase.createXmlEvent(socket, rawResponse, `soapClientVehicleInsertUpdate.insertAsync response.`); CdkBase.createXmlEvent(socket, rawResponse, `soapClientVehicleInsertUpdate.insertAsync response.`);
@@ -611,7 +611,7 @@ async function UpdateDmsVehicle(socket) {
CdkBase.createLogEvent( CdkBase.createLogEvent(
socket, socket,
"TRACE", "DEBUG",
`soapClientVehicleInsertUpdate.updateAsync Result ${JSON.stringify(result, null, 2)}` `soapClientVehicleInsertUpdate.updateAsync Result ${JSON.stringify(result, null, 2)}`
); );
CdkBase.createXmlEvent(socket, rawResponse, `soapClientVehicleInsertUpdate.updateAsync response.`); CdkBase.createXmlEvent(socket, rawResponse, `soapClientVehicleInsertUpdate.updateAsync response.`);
@@ -650,7 +650,7 @@ async function InsertServiceVehicleHistory(socket) {
CdkBase.createLogEvent( CdkBase.createLogEvent(
socket, socket,
"TRACE", "SILLY",
`soapClientServiceHistoryInsert.serviceHistoryHeaderInsert Result ${JSON.stringify(result, null, 2)}` `soapClientServiceHistoryInsert.serviceHistoryHeaderInsert Result ${JSON.stringify(result, null, 2)}`
); );
CdkBase.createXmlEvent(socket, rawResponse, `soapClientServiceHistoryInsert.serviceHistoryHeaderInsert response.`); CdkBase.createXmlEvent(socket, rawResponse, `soapClientServiceHistoryInsert.serviceHistoryHeaderInsert response.`);
@@ -690,7 +690,7 @@ async function InsertDmsStartWip(socket) {
CdkBase.createLogEvent( CdkBase.createLogEvent(
socket, socket,
"TRACE", "SILLY",
`soapClientAccountingGLInsertUpdate.doStartWIPAsync Result ${JSON.stringify(result, null, 2)}` `soapClientAccountingGLInsertUpdate.doStartWIPAsync Result ${JSON.stringify(result, null, 2)}`
); );
CdkBase.createXmlEvent(socket, rawResponse, `soapClientAccountingGLInsertUpdate.doStartWIPAsync response.`); CdkBase.createXmlEvent(socket, rawResponse, `soapClientAccountingGLInsertUpdate.doStartWIPAsync response.`);
@@ -721,7 +721,7 @@ async function InsertDmsBatchWip(socket) {
CdkBase.createLogEvent( CdkBase.createLogEvent(
socket, socket,
"TRACE", "SILLY",
`soapClientAccountingGLInsertUpdate.doTransBatchWIPAsync Result ${JSON.stringify(result, null, 2)}` `soapClientAccountingGLInsertUpdate.doTransBatchWIPAsync Result ${JSON.stringify(result, null, 2)}`
); );
CdkBase.createXmlEvent(socket, rawResponse, `soapClientAccountingGLInsertUpdate.doTransBatchWIPAsync response.`); CdkBase.createXmlEvent(socket, rawResponse, `soapClientAccountingGLInsertUpdate.doTransBatchWIPAsync response.`);
@@ -885,7 +885,7 @@ async function PostDmsBatchWip(socket) {
CdkBase.createLogEvent( CdkBase.createLogEvent(
socket, socket,
"TRACE", "SILLY",
`soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync Result ${JSON.stringify(result, null, 2)}` `soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync Result ${JSON.stringify(result, null, 2)}`
); );
CdkBase.createXmlEvent(socket, rawResponse, `soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync response.`); CdkBase.createXmlEvent(socket, rawResponse, `soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync response.`);
@@ -914,7 +914,7 @@ async function QueryDmsErrWip(socket) {
CdkBase.createLogEvent( CdkBase.createLogEvent(
socket, socket,
"TRACE", "DEBUG",
`soapClientAccountingGLInsertUpdate.doErrWIPAsync Result ${JSON.stringify(result, null, 2)}` `soapClientAccountingGLInsertUpdate.doErrWIPAsync Result ${JSON.stringify(result, null, 2)}`
); );
CdkBase.createXmlEvent(socket, rawResponse, `soapClientAccountingGLInsertUpdate.doErrWIPAsync response.`); CdkBase.createXmlEvent(socket, rawResponse, `soapClientAccountingGLInsertUpdate.doErrWIPAsync response.`);
@@ -945,7 +945,7 @@ async function DeleteDmsWip(socket) {
CdkBase.createLogEvent( CdkBase.createLogEvent(
socket, socket,
"TRACE", "SILLY",
`soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync Result ${JSON.stringify(result, null, 2)}` `soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync Result ${JSON.stringify(result, null, 2)}`
); );
CdkBase.createXmlEvent(socket, rawResponse, `soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync response.`); CdkBase.createXmlEvent(socket, rawResponse, `soapClientAccountingGLInsertUpdate.doPostBatchWIPAsync response.`);

View File

@@ -820,7 +820,7 @@ exports.default = async (req, res) => {
job: JSON.stringify({ id: job.id, ro_number: job.ro_number }), job: JSON.stringify({ id: job.id, ro_number: job.ro_number }),
error: error.message || JSON.stringify(error) error: error.message || JSON.stringify(error)
}); });
console.log(error); //console.log(error);
} }
} catch (error) { } catch (error) {
logger.log("arms-failed-job", "ERROR", "api", job.shopid, { logger.log("arms-failed-job", "ERROR", "api", job.shopid, {
@@ -886,7 +886,10 @@ exports.default = async (req, res) => {
const [result, rawResponse, , rawRequest] = entegralResponse; const [result, rawResponse, , rawRequest] = entegralResponse;
} catch (error) { } catch (error) {
fs.writeFileSync(`./logs/${xmlObj.filename}`, xmlObj.xml); fs.writeFileSync(`./logs/${xmlObj.filename}`, xmlObj.xml);
console.log(error); //console.log(error);
logger.log("arms-error-shop", "ERROR", "api", bodyshop.id, {
error
});
} }
} catch (error) { } catch (error) {
//Error at the shop level. //Error at the shop level.

View File

@@ -206,9 +206,6 @@ const CreateRepairOrderTag = (job, errorCallback) => {
const repairCosts = CreateCosts(job); const repairCosts = CreateCosts(job);
if (job.ro_number === "QBD209") {
console.log("Stop here");
}
//Calculate detail only lines. //Calculate detail only lines.
const detailAdjustments = job.joblines const detailAdjustments = job.joblines
.filter((jl) => jl.ah_detail_line && jl.mod_lbr_ty) .filter((jl) => jl.ah_detail_line && jl.mod_lbr_ty)

View File

@@ -154,7 +154,7 @@ exports.default = async (req, res) => {
async function getPrivateKey() { async function getPrivateKey() {
// Connect to AWS Secrets Manager // Connect to AWS Secrets Manager
const client = new SecretsManagerClient({ region: "ca-central-1" }); const client = new SecretsManagerClient({ region: "ca-central-1" });
const command = new GetSecretValueCommand({ SecretId: CHATTER_PRIVATE_KEY }); const command = new GetSecretValueCommand({ SecretId: "CHATTER_PRIVATE_KEY" });
logger.log("chatter-get-private-key", "DEBUG", "api", null, null); logger.log("chatter-get-private-key", "DEBUG", "api", null, null);
try { try {

View File

@@ -3,6 +3,7 @@ const { defaultProvider } = require("@aws-sdk/credential-provider-node");
const { default: InstanceManager } = require("../utils/instanceMgr"); const { default: InstanceManager } = require("../utils/instanceMgr");
const aws = require("@aws-sdk/client-ses"); const aws = require("@aws-sdk/client-ses");
const nodemailer = require("nodemailer"); const nodemailer = require("nodemailer");
const logger = require("../utils/logger");
const isLocal = isString(process.env?.LOCALSTACK_HOSTNAME) && !isEmpty(process.env?.LOCALSTACK_HOSTNAME); const isLocal = isString(process.env?.LOCALSTACK_HOSTNAME) && !isEmpty(process.env?.LOCALSTACK_HOSTNAME);
@@ -19,7 +20,7 @@ const sesConfig = {
if (isLocal) { if (isLocal) {
sesConfig.endpoint = `http://${process.env.LOCALSTACK_HOSTNAME}:4566`; sesConfig.endpoint = `http://${process.env.LOCALSTACK_HOSTNAME}:4566`;
console.log(`SES Mailer set to LocalStack end point: ${sesConfig.endpoint}`); logger.logger.debug(`SES Mailer set to LocalStack end point: ${sesConfig.endpoint}`);
} }
const ses = new aws.SES(sesConfig); const ses = new aws.SES(sesConfig);

View File

@@ -21,7 +21,7 @@ const getImage = async (imageUrl) => {
// Log the email in the database // Log the email in the database
const logEmail = async (req, email) => { const logEmail = async (req, email) => {
try { try {
const insertresult = await client.request(queries.INSERT_EMAIL_AUDIT, { await client.request(queries.INSERT_EMAIL_AUDIT, {
email: { email: {
to: email.to, to: email.to,
cc: email.cc, cc: email.cc,
@@ -34,13 +34,13 @@ const logEmail = async (req, email) => {
status: "Sent" status: "Sent"
} }
}); });
console.log(insertresult);
} catch (error) { } catch (error) {
logger.log("email-log-error", "error", req.user.email, null, { logger.log("email-log-error", "error", req?.user?.email, null, {
from: `${req.body.from.name} <${req.body.from.address}>`, from: `${req.body.from.name} <${req.body.from.address}>`,
to: req.body.to, to: req?.body?.to,
cc: req.body.cc, cc: req?.body?.cc,
subject: req.body.subject subject: req?.body?.subject,
email
// info, // info,
}); });
} }
@@ -70,12 +70,11 @@ const sendServerEmail = async ({ subject, text }) => {
} }
}, },
(err, info) => { (err, info) => {
console.log(err || info); logger.log("server-email-failure", err ? "error" : "debug", null, null, { message: err || info });
} }
); );
} catch (error) { } catch (error) {
console.log(error); logger.log("server-email-failure", "error", null, null, { error });
logger.log("server-email-failure", "error", null, null, error);
} }
}; };
@@ -88,8 +87,7 @@ const sendProManagerWelcomeEmail = async ({ to, subject, html }) => {
html html
}); });
} catch (error) { } catch (error) {
console.log(error); logger.log("server-email-failure", "error", null, null, { error });
logger.log("server-email-failure", "error", null, null, error);
} }
}; };
@@ -108,12 +106,12 @@ const sendTaskEmail = async ({ to, subject, type = "text", html, text, attachmen
attachments: attachments || null attachments: attachments || null
}, },
(err, info) => { (err, info) => {
console.log(err || info); // (message, type, user, record, meta
logger.log("server-email", err ? "error" : "debug", null, null, { message: err || info });
} }
); );
} catch (error) { } catch (error) {
console.log(error); logger.log("server-email-failure", "error", null, null, { error });
logger.log("server-email-failure", "error", null, null, error);
} }
}; };
@@ -184,9 +182,8 @@ const sendEmail = async (req, res) => {
} }
}, },
(err, info) => { (err, info) => {
console.log(err || info);
if (info) { if (info) {
logger.log("send-email-success", "DEBUG", req.user.email, null, { logger.log("send-email-success", "DEBUG", req?.user?.email, null, {
from: `${req.body.from.name} <${req.body.from.address}>`, from: `${req.body.from.name} <${req.body.from.address}>`,
replyTo: req.body.ReplyTo.Email, replyTo: req.body.ReplyTo.Email,
to: req.body.to, to: req.body.to,
@@ -205,7 +202,7 @@ const sendEmail = async (req, res) => {
success: true //response: info success: true //response: info
}); });
} else { } else {
logger.log("send-email-failure", "ERROR", req.user.email, null, { logger.log("send-email-failure", "ERROR", req?.user?.email, null, {
from: `${req.body.from.name} <${req.body.from.address}>`, from: `${req.body.from.name} <${req.body.from.address}>`,
replyTo: req.body.ReplyTo.Email, replyTo: req.body.ReplyTo.Email,
to: req.body.to, to: req.body.to,
@@ -290,7 +287,9 @@ ${body.bounce?.bouncedRecipients.map(
` `
}, },
(err, info) => { (err, info) => {
console.log("***", err || info); logger.log("sns-error", err ? "error" : "debug", "api", null, {
message: err ? JSON.stringify(error) : info
});
} }
); );
} }

View File

@@ -18,10 +18,10 @@ const tasksEmailQueue = taskEmailQueue();
const tasksEmailQueueCleanup = async () => { const tasksEmailQueueCleanup = async () => {
try { try {
// Example async operation // Example async operation
console.log("Performing Tasks Email Reminder process cleanup..."); // console.log("Performing Tasks Email Reminder process cleanup...");
await new Promise((resolve) => tasksEmailQueue.destroy(() => resolve())); await new Promise((resolve) => tasksEmailQueue.destroy(() => resolve()));
} catch (err) { } catch (err) {
console.error("Tasks Email Reminder process cleanup failed:", err); // console.error("Tasks Email Reminder process cleanup failed:", err);
} }
}; };
@@ -77,6 +77,7 @@ const formatPriority = (priority) => {
* @param priority * @param priority
* @param description * @param description
* @param dueDate * @param dueDate
* @param createdBy
* @param bodyshop * @param bodyshop
* @param job * @param job
* @param taskId * @param taskId
@@ -96,11 +97,11 @@ const getEndpoints = (bodyshop) =>
: "https://romeonline.io" : "https://romeonline.io"
}); });
const generateTemplateArgs = (title, priority, description, dueDate, bodyshop, job, taskId, dateLine) => { const generateTemplateArgs = (title, priority, description, dueDate, bodyshop, job, taskId, dateLine, createdBy) => {
const endPoints = getEndpoints(bodyshop); const endPoints = getEndpoints(bodyshop);
return { return {
header: title, header: title,
subHeader: `Body Shop: ${bodyshop.shopname} | Priority: ${formatPriority(priority)} ${formatDate(dueDate)}`, subHeader: `Body Shop: ${bodyshop.shopname} | Priority: ${formatPriority(priority)} ${formatDate(dueDate)} | Created By: ${createdBy || "N/A"}`,
body: `Reference: ${job.ro_number || "N/A"} | ${job.ownr_co_nm ? job.ownr_co_nm : `${job.ownr_fn || ""} ${job.ownr_ln || ""}`.trim()} | ${`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${job.v_model_desc || ""}`.trim()}<br>${description ? description.concat("<br>") : ""}<a href="${endPoints}/manage/tasks/alltasks?taskid=${taskId}">View this task.</a>`, body: `Reference: ${job.ro_number || "N/A"} | ${job.ownr_co_nm ? job.ownr_co_nm : `${job.ownr_fn || ""} ${job.ownr_ln || ""}`.trim()} | ${`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${job.v_model_desc || ""}`.trim()}<br>${description ? description.concat("<br>") : ""}<a href="${endPoints}/manage/tasks/alltasks?taskid=${taskId}">View this task.</a>`,
dateLine dateLine
}; };
@@ -181,7 +182,8 @@ const taskAssignedEmail = async (req, res) => {
tasks_by_pk.bodyshop, tasks_by_pk.bodyshop,
tasks_by_pk.job, tasks_by_pk.job,
newTask.id, newTask.id,
dateLine dateLine,
newTask.created_by
) )
), ),
null, null,
@@ -268,7 +270,8 @@ const tasksRemindEmail = async (req, res) => {
onlyTask.bodyshop, onlyTask.bodyshop,
onlyTask.job, onlyTask.job,
onlyTask.id, onlyTask.id,
dateLine dateLine,
onlyTask.created_by
) )
); );
} }

View File

@@ -10,8 +10,9 @@ const logger = require("../utils/logger");
const taskEmailQueue = () => const taskEmailQueue = () =>
new Queue( new Queue(
(taskIds, cb) => { (taskIds, cb) => {
console.log("Processing reminds for taskIds: ", taskIds.join(", ")); logger.log("Processing reminds for taskIds: ", "silly", null, null, {
taskIds: taskIds?.join(", ")
});
// Set the remind_at_sent to the current time. // Set the remind_at_sent to the current time.
const now = moment().toISOString(); const now = moment().toISOString();

View File

@@ -16,7 +16,7 @@ admin.initializeApp({
}); });
const createUser = async (req, res) => { const createUser = async (req, res) => {
logger.log("admin-create-user", "ADMIN", req.user.email, null, { logger.log("admin-create-user", "debug", req.user.email, null, {
request: req.body, request: req.body,
ioadmin: true ioadmin: true
}); });
@@ -97,7 +97,7 @@ const sendPromanagerWelcomeEmail = (req, res) => {
// Validate email before proceeding // Validate email before proceeding
if (!dbUser.validemail) { if (!dbUser.validemail) {
logger.log("admin-send-welcome-email-skip", "ADMIN", req.user.email, null, { logger.log("admin-send-welcome-email-skip", "debug", req.user.email, null, {
message: "User email is not valid, skipping email.", message: "User email is not valid, skipping email.",
email email
}); });
@@ -107,7 +107,7 @@ const sendPromanagerWelcomeEmail = (req, res) => {
// Check if the user's company is ProManager // Check if the user's company is ProManager
const convenientCompany = dbUser.associations?.[0]?.bodyshop?.convenient_company; const convenientCompany = dbUser.associations?.[0]?.bodyshop?.convenient_company;
if (convenientCompany !== "promanager") { if (convenientCompany !== "promanager") {
logger.log("admin-send-welcome-email-skip", "ADMIN", req.user.email, null, { logger.log("admin-send-welcome-email-skip", "debug", req.user.email, null, {
message: 'convenient_company is not "promanager", skipping email.', message: 'convenient_company is not "promanager", skipping email.',
convenientCompany convenientCompany
}); });
@@ -141,7 +141,7 @@ const sendPromanagerWelcomeEmail = (req, res) => {
}) })
.then(() => { .then(() => {
// Log success and return response // Log success and return response
logger.log("admin-send-welcome-email", "ADMIN", req.user.email, null, { logger.log("admin-send-welcome-email", "debug", req.user.email, null, {
request: req.body, request: req.body,
ioadmin: true, ioadmin: true,
emailSentTo: email emailSentTo: email
@@ -161,7 +161,7 @@ const sendPromanagerWelcomeEmail = (req, res) => {
}; };
const updateUser = (req, res) => { const updateUser = (req, res) => {
logger.log("admin-update-user", "ADMIN", req.user.email, null, { logger.log("admin-update-user", "debug", req.user.email, null, {
request: req.body, request: req.body,
ioadmin: true ioadmin: true
}); });
@@ -184,7 +184,7 @@ const updateUser = (req, res) => {
.then((userRecord) => { .then((userRecord) => {
// See the UserRecord reference doc for the contents of userRecord. // See the UserRecord reference doc for the contents of userRecord.
logger.log("admin-update-user-success", "ADMIN", req.user.email, null, { logger.log("admin-update-user-success", "debug", req.user.email, null, {
userRecord, userRecord,
ioadmin: true ioadmin: true
}); });
@@ -199,7 +199,7 @@ const updateUser = (req, res) => {
}; };
const getUser = (req, res) => { const getUser = (req, res) => {
logger.log("admin-get-user", "ADMIN", req.user.email, null, { logger.log("admin-get-user", "debug", req.user.email, null, {
request: req.body, request: req.body,
ioadmin: true ioadmin: true
}); });
@@ -269,10 +269,14 @@ const sendNotification = async (req, res) => {
}) })
.then((response) => { .then((response) => {
// Response is a message ID string. // Response is a message ID string.
console.log("Successfully sent message:", response); logger.log("Successfully sent message:", "debug", req?.user?.email, null, {
response
});
}) })
.catch((error) => { .catch((error) => {
console.log("Error sending message:", error); logger.log("Successfully sent message:", "error", req?.user?.email, null, {
error
});
}); });
res.sendStatus(200); res.sendStatus(200);
@@ -321,7 +325,7 @@ module.exports = {
// admin.auth().setCustomUserClaims(uid, { // admin.auth().setCustomUserClaims(uid, {
// ioadmin: true, // ioadmin: true,
// "https://hasura.io/jwt/claims": { // "https://hasura.io/jwt/claims": {
// "x-hasura-default-role": "admin", // "x-hasura-default-role": "debug",
// "x-hasura-allowed-roles": ["admin"], // "x-hasura-allowed-roles": ["admin"],
// "x-hasura-user-id": uid, // "x-hasura-user-id": uid,
// }, // },

View File

@@ -2506,6 +2506,7 @@ exports.QUERY_TASK_BY_ID = `
query QUERY_TASK_BY_ID($id: uuid!) { query QUERY_TASK_BY_ID($id: uuid!) {
tasks_by_pk(id: $id) { tasks_by_pk(id: $id) {
id id
created_by
assigned_to_employee{ assigned_to_employee{
id id
user_email user_email

View File

@@ -78,7 +78,7 @@ exports.lightbox_credentials = async (req, res) => {
res.send(response.data); res.send(response.data);
} catch (error) { } catch (error) {
console.log(error); //console.log(error);
logger.log("intellipay-lightbox-credentials-error", "ERROR", req.user?.email, null, { logger.log("intellipay-lightbox-credentials-error", "ERROR", req.user?.email, null, {
error: JSON.stringify(error) error: JSON.stringify(error)
}); });
@@ -109,7 +109,7 @@ exports.payment_refund = async (req, res) => {
res.send(response.data); res.send(response.data);
} catch (error) { } catch (error) {
console.log(error); //console.log(error);
logger.log("intellipay-refund-error", "ERROR", req.user?.email, null, { logger.log("intellipay-refund-error", "ERROR", req.user?.email, null, {
error: JSON.stringify(error) error: JSON.stringify(error)
}); });
@@ -143,7 +143,7 @@ exports.generate_payment_url = async (req, res) => {
res.send(response.data); res.send(response.data);
} catch (error) { } catch (error) {
console.log(error); //console.log(error);
logger.log("intellipay-payment-url-error", "ERROR", req.user?.email, null, { logger.log("intellipay-payment-url-error", "ERROR", req.user?.email, null, {
error: JSON.stringify(error) error: JSON.stringify(error)
}); });

View File

@@ -28,14 +28,14 @@ exports.default = async (req, res) => {
// } // }
// }); // });
ioRedis.to(getBodyshopRoom(bodyshopid)).emit("bodyshop-message", { // ioRedis.to(getBodyshopRoom(bodyshopid)).emit("bodyshop-message", {
operationName, // operationName,
useremail // useremail
}); // });
res.sendStatus(200); res.sendStatus(200);
} catch (error) { } catch (error) {
logger.log("ioevent-error", "trace", user, null, { logger.log("ioevent-error", "silly", user, null, {
operationname: operationName, operationname: operationName,
time, time,
dbevent, dbevent,

View File

@@ -19,7 +19,8 @@ async function JobCosting(req, res) {
const BearerToken = req.BearerToken; const BearerToken = req.BearerToken;
const client = req.userGraphQLClient; const client = req.userGraphQLClient;
logger.log("job-costing-start", "DEBUG", req.user.email, jobid, null); //Uncomment for further testing
// logger.log("job-costing-start", "DEBUG", req.user.email, jobid, null);
try { try {
const resp = await client.setHeaders({ Authorization: BearerToken }).request(queries.QUERY_JOB_COSTING_DETAILS, { const resp = await client.setHeaders({ Authorization: BearerToken }).request(queries.QUERY_JOB_COSTING_DETAILS, {
@@ -46,7 +47,10 @@ async function JobCostingMulti(req, res) {
const BearerToken = req.BearerToken; const BearerToken = req.BearerToken;
const client = req.userGraphQLClient; const client = req.userGraphQLClient;
logger.log("job-costing-multi-start", "DEBUG", req.user.email, jobids, null); //Uncomment for further testing
// logger.log("job-costing-multi-start", "DEBUG", req?.user?.email, null, {
// jobids
// });
try { try {
const resp = await client const resp = await client
@@ -244,7 +248,8 @@ async function JobCostingMulti(req, res) {
data: ret data: ret
}); });
} catch (error) { } catch (error) {
logger.log("job-costing-multi-error", "ERROR", req.user.email, [jobids], { logger.log("job-costing-multi-error", "ERROR", req?.user?.email, null, {
jobids,
message: error.message, message: error.message,
stack: error.stack stack: error.stack
}); });
@@ -282,7 +287,13 @@ function GenerateCostingData(job) {
if (val.mod_lbr_ty) { if (val.mod_lbr_ty) {
const laborProfitCenter = val.profitcenter_labor || defaultProfits[val.mod_lbr_ty] || "Unknown"; const laborProfitCenter = val.profitcenter_labor || defaultProfits[val.mod_lbr_ty] || "Unknown";
if (laborProfitCenter === "Unknown") console.log("Unknown type", val.line_desc, val.mod_lbr_ty); //Uncomment for further testing
// if (laborProfitCenter === "Unknown") {
// logger.log("job-costing unknown type", "debug", null, null, {
// line_desc: val.line_desc,
// mod_lbr_ty: val.mod_lbr_ty
// });
// }
const rateName = `rate_${(val.mod_lbr_ty || "").toLowerCase()}`; const rateName = `rate_${(val.mod_lbr_ty || "").toLowerCase()}`;
@@ -349,10 +360,22 @@ function GenerateCostingData(job) {
if (val.part_type && val.part_type !== "PAE" && val.part_type !== "PAS" && val.part_type !== "PASL") { if (val.part_type && val.part_type !== "PAE" && val.part_type !== "PAS" && val.part_type !== "PASL") {
const partsProfitCenter = val.profitcenter_part || defaultProfits[val.part_type] || "Unknown"; const partsProfitCenter = val.profitcenter_part || defaultProfits[val.part_type] || "Unknown";
if (partsProfitCenter === "Unknown") console.log("Unknown type", val.line_desc, val.part_type); //Uncomment for further testing
// if (partsProfitCenter === "Unknown" || !partsProfitCenter) {
// logger.log(
// partsProfitCenter === "Unknown"
// ? "job-costing unknown type"
// : "Unknown cost/profit center mapping for parts.",
// "debug",
// null,
// null,
// {
// line_desc: val.line_desc,
// part_type: val.part_type
// }
// );
// }
if (!partsProfitCenter)
console.log("Unknown cost/profit center mapping for parts.", val.line_desc, val.part_type);
let partsAmount = Dinero({ let partsAmount = Dinero({
amount: val.act_price_before_ppc amount: val.act_price_before_ppc
? Math.round(val.act_price_before_ppc * 100) ? Math.round(val.act_price_before_ppc * 100)
@@ -409,10 +432,22 @@ function GenerateCostingData(job) {
if (val.part_type && val.part_type !== "PAE" && (val.part_type === "PAS" || val.part_type === "PASL")) { if (val.part_type && val.part_type !== "PAE" && (val.part_type === "PAS" || val.part_type === "PASL")) {
const partsProfitCenter = val.profitcenter_part || defaultProfits[val.part_type] || "Unknown"; const partsProfitCenter = val.profitcenter_part || defaultProfits[val.part_type] || "Unknown";
if (partsProfitCenter === "Unknown") console.log("Unknown type", val.line_desc, val.part_type); //Uncomment for further testing
// if (partsProfitCenter === "Unknown" || !partsProfitCenter) {
// logger.log(
// partsProfitCenter === "Unknown"
// ? "job-costing unknown type"
// : "job-costing Unknown cost/profit center mapping for sublet",
// "debug",
// null,
// null,
// {
// line_desc: val.line_desc,
// part_type: val.part_type
// }
// );
// }
if (!partsProfitCenter)
console.log("Unknown cost/profit center mapping for sublet.", val.line_desc, val.part_type);
const partsAmount = Dinero({ const partsAmount = Dinero({
amount: Math.round((val.act_price || 0) * 100) amount: Math.round((val.act_price || 0) * 100)
}) })
@@ -443,9 +478,14 @@ function GenerateCostingData(job) {
//If so, use it, otherwise try to use the same from the auto-allocate logic in IO app jobs-close-auto-allocate. //If so, use it, otherwise try to use the same from the auto-allocate logic in IO app jobs-close-auto-allocate.
const partsProfitCenter = val.profitcenter_part || getAdditionalCostCenter(val, defaultProfits) || "Unknown"; const partsProfitCenter = val.profitcenter_part || getAdditionalCostCenter(val, defaultProfits) || "Unknown";
if (partsProfitCenter === "Unknown") { //Uncomment for further testing
console.log("Unknown type", val.line_desc, val.part_type); // if (partsProfitCenter === "Unknown") {
} // logger.log("job-costing unknown type", "debug", null, null, {
// line_desc: val.line_desc,
// part_type: val.part_type
// });
// }
const partsAmount = Dinero({ const partsAmount = Dinero({
amount: Math.round((val.act_price || 0) * 100) amount: Math.round((val.act_price || 0) * 100)
}) })
@@ -476,7 +516,7 @@ function GenerateCostingData(job) {
if (!hasMapaLine) { if (!hasMapaLine) {
if (!jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]]) if (!jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]])
jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]] = Dinero(); jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]] = Dinero();
jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]] = jobLineTotalsByProfitCenter.additional[ jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]] = jobLineTotalsByProfitCenter.additional[
defaultProfits["MAPA"] defaultProfits["MAPA"]
].add( ].add(

View File

@@ -26,7 +26,7 @@ exports.totalsSsu = async function (req, res) {
const BearerToken = req.BearerToken; const BearerToken = req.BearerToken;
const client = req.userGraphQLClient; const client = req.userGraphQLClient;
logger.log("job-totals-ssu-USA", "DEBUG", req.user.email, id, null); logger.log("job-totals-ssu-USA", "DEBUG", req?.user?.email, id);
try { try {
const job = await client.setHeaders({ Authorization: BearerToken }).request(queries.GET_JOB_BY_PK, { const job = await client.setHeaders({ Authorization: BearerToken }).request(queries.GET_JOB_BY_PK, {
@@ -47,7 +47,7 @@ exports.totalsSsu = async function (req, res) {
res.status(200).send(); res.status(200).send();
} catch (error) { } catch (error) {
logger.log("job-totals-ssu-USA-error", "ERROR", req.user.email, id, { logger.log("job-totals-ssu-USA-error", "ERROR", req?.user?.email, id, {
jobid: id, jobid: id,
error error
}); });
@@ -84,12 +84,10 @@ async function Totals(req, res) {
const logger = req.logger; const logger = req.logger;
const client = req.userGraphQLClient; const client = req.userGraphQLClient;
logger.log("job-totals-USA", "DEBUG", req.user.email, job.id, { logger.log("job-totals-ssu-USA", "DEBUG", req.user.email, job.id, {
jobid: job.id jobid: job.id
}); });
logger.log("job-totals-ssu-USA", "DEBUG", req.user.email, id, null);
await AutoAddAtsIfRequired({ job, client }); await AutoAddAtsIfRequired({ job, client });
try { try {
@@ -866,8 +864,8 @@ function CalculateTaxesTotals(job, otherTotals) {
} }
}); });
console.log("*** Taxable Amounts***"); // console.log("*** Taxable Amounts***");
console.table(JSON.parse(JSON.stringify(taxableAmounts))); // console.table(JSON.parse(JSON.stringify(taxableAmounts)));
//For the taxable amounts, figure out which tax type applies. //For the taxable amounts, figure out which tax type applies.
//Then sum up the total of that tax type and then calculate the thresholds. //Then sum up the total of that tax type and then calculate the thresholds.
@@ -961,7 +959,9 @@ function CalculateTaxesTotals(job, otherTotals) {
} }
} }
} catch (error) { } catch (error) {
console.error("Key with issue", key); logger.log("job-totals-USA Key with issue", "error", null, null, {
key
});
} }
}); });
@@ -979,8 +979,8 @@ function CalculateTaxesTotals(job, otherTotals) {
} }
const remainingTaxableAmounts = taxableAmountsByTier; const remainingTaxableAmounts = taxableAmountsByTier;
console.log("*** Taxable Amounts by Tier***"); // console.log("*** Taxable Amounts by Tier***");
console.table(JSON.parse(JSON.stringify(taxableAmountsByTier))); // console.table(JSON.parse(JSON.stringify(taxableAmountsByTier)));
Object.keys(taxableAmountsByTier).forEach((taxTierKey) => { Object.keys(taxableAmountsByTier).forEach((taxTierKey) => {
try { try {
@@ -1026,12 +1026,14 @@ function CalculateTaxesTotals(job, otherTotals) {
totalTaxByTier[taxTierKey] = totalTaxByTier[taxTierKey].add(taxAmountToAdd); totalTaxByTier[taxTierKey] = totalTaxByTier[taxTierKey].add(taxAmountToAdd);
} }
} catch (error) { } catch (error) {
console.error("PFP Calculation error", error); logger.log("job-totals-USA - PFP Calculation Error", "error", null, null, {
error
});
} }
}); });
console.log("*** Total Tax by Tier Amounts***"); // console.log("*** Total Tax by Tier Amounts***");
console.table(JSON.parse(JSON.stringify(totalTaxByTier))); // console.table(JSON.parse(JSON.stringify(totalTaxByTier)));
stateTax = stateTax stateTax = stateTax
.add(totalTaxByTier.ty1Tax) .add(totalTaxByTier.ty1Tax)

View File

@@ -182,7 +182,7 @@ async function AutoAddAtsIfRequired({ job, client }) {
job.joblines[atsLineIndex].act_price = atsAmount; job.joblines[atsLineIndex].act_price = atsAmount;
} }
console.log(job.jobLines); //console.log(job.jobLines);
} }
} }

View File

@@ -15,7 +15,7 @@ const jobUpdated = async (req, res) => {
}); });
} }
logger.log("job-update", "INFO", req.user?.email, null, { logger.log("job-update", "DEBUG", req.user?.email, null, {
message: `Job updated event received from Hasura`, message: `Job updated event received from Hasura`,
jobid: req?.body?.event?.data?.new?.id jobid: req?.body?.event?.data?.new?.id
}); });

View File

@@ -16,7 +16,11 @@ const validateFirebaseIdTokenMiddleware = async (req, res, next) => {
(!req.headers.authorization || !req.headers.authorization.startsWith("Bearer ")) && (!req.headers.authorization || !req.headers.authorization.startsWith("Bearer ")) &&
!(req.cookies && req.cookies.__session) !(req.cookies && req.cookies.__session)
) { ) {
console.error("Unauthorized attempt. No authorization provided."); logger.log("api-authorization-call", "warn", req?.user?.email, null, {
type: "unauthorized",
path: req.path,
body: req.body
});
return res.status(403).send("Unauthorized"); return res.status(403).send("Unauthorized");
} }
@@ -32,10 +36,10 @@ const validateFirebaseIdTokenMiddleware = async (req, res, next) => {
idToken = req.cookies.__session; idToken = req.cookies.__session;
} else { } else {
// No cookie // No cookie
console.error("Unauthorized attempt. No cookie provided."); logger.log("api-unauthorized-call", "warn", null, null, {
logger.log("api-unauthorized-call", "WARN", null, null, { type: "unauthorized",
req, path: req.path,
type: "no-cookie" body: req.body
}); });
return res.status(403).send("Unauthorized"); return res.status(403).send("Unauthorized");
@@ -47,11 +51,11 @@ const validateFirebaseIdTokenMiddleware = async (req, res, next) => {
req.user = decodedIdToken; req.user = decodedIdToken;
next(); next();
} catch (error) { } catch (error) {
logger.log("api-unauthorized-call", "WARN", null, null, { logger.log("api-unauthorized-call", "warn", null, null, {
path: req.path, path: req.path,
body: req.body, body: req.body,
type: "unauthroized", type: "unauthorized",
...error ...error
}); });

View File

@@ -9,11 +9,9 @@ require("dotenv").config({
}); });
exports.mixdataUpload = async (req, res) => { exports.mixdataUpload = async (req, res) => {
const { bodyshopid } = req.body;
const client = req.userGraphQLClient; const client = req.userGraphQLClient;
logger.log("job-mixdata-upload", "DEBUG", req.user.email, null, null); logger.log("job-mixdata-upload", "DEBUG", req?.user?.email, null, null);
try { try {
for (const element of req.files) { for (const element of req.files) {
@@ -23,7 +21,7 @@ exports.mixdataUpload = async (req, res) => {
explicitArray: false explicitArray: false
}); });
logger.log("job-mixdata-parse", "DEBUG", req.user.email, inboundRequest); logger.log("job-mixdata-parse", "DEBUG", req?.user?.email, null, { inboundRequest });
const ScaleType = DetermineScaleType(inboundRequest); const ScaleType = DetermineScaleType(inboundRequest);
const RoNumbersFromInboundRequest = GetListOfRos(inboundRequest, ScaleType); const RoNumbersFromInboundRequest = GetListOfRos(inboundRequest, ScaleType);
@@ -70,7 +68,7 @@ function DetermineScaleType(inboundRequest) {
const ret = { type: "", verson: 0 }; const ret = { type: "", verson: 0 };
//PPG Mix Data //PPG Mix Data
if (inboundRequest.PPG && inboundRequest.PPG.Header.Protocol.Name === "PPG") { if (inboundRequest?.PPG?.Header?.Protocol?.Name === "PPG") {
return { return {
type: inboundRequest.PPG.Header.Protocol.Name, type: inboundRequest.PPG.Header.Protocol.Name,
company: "PPG", company: "PPG",
@@ -80,13 +78,13 @@ function DetermineScaleType(inboundRequest) {
} }
function GetListOfRos(inboundRequest, ScaleType) { function GetListOfRos(inboundRequest, ScaleType) {
if (ScaleType.company === "PPG" && ScaleType.version === "1.3.0") { if (ScaleType?.company === "PPG" && ScaleType?.version === "1.3.0") {
return inboundRequest.PPG.MixDataInterface.ROData.RepairOrders.RO.map((r) => r.RONumber); return inboundRequest.PPG.MixDataInterface.ROData.RepairOrders.RO.map((r) => r.RONumber);
} }
} }
function GenerateMixDataArray(inboundRequest, ScaleType, jobHash) { function GenerateMixDataArray(inboundRequest, ScaleType, jobHash) {
if (ScaleType.company === "PPG" && ScaleType.version === "1.3.0") { if (ScaleType?.company === "PPG" && ScaleType?.version === "1.3.0") {
return inboundRequest.PPG.MixDataInterface.ROData.RepairOrders.RO.map((r) => { return inboundRequest.PPG.MixDataInterface.ROData.RepairOrders.RO.map((r) => {
return { return {
jobid: jobHash[r.RONumber]?.jobid, jobid: jobHash[r.RONumber]?.jobid,

View File

@@ -148,7 +148,7 @@ async function OpenSearchUpdateHandler(req, res) {
}; };
const response = await osClient.index(payload); const response = await osClient.index(payload);
console.log(response.body); //console.log(response.body);
res.status(200).json(response.body); res.status(200).json(response.body);
} }
} catch (error) { } catch (error) {
@@ -255,7 +255,7 @@ async function OpenSearchSearchHandler(req, res) {
res.json(body); res.json(body);
} catch (error) { } catch (error) {
console.log(error); //console.log(error);
logger.log("os-search-error", "ERROR", req.user.email, null, { logger.log("os-search-error", "ERROR", req.user.email, null, {
error: JSON.stringify(error) error: JSON.stringify(error)
}); });

View File

@@ -45,12 +45,12 @@ exports.payall = async function (req, res) {
const path = diffParser(diff); const path = diffParser(diff);
if (diff.op === "add") { if (diff.op === "add") {
console.log(Object.keys(diff.val)); // console.log(Object.keys(diff.val));
if (typeof diff.val === "object" && Object.keys(diff.val).length > 1) { if (typeof diff.val === "object" && Object.keys(diff.val).length > 1) {
//Multiple values to add. //Multiple values to add.
Object.keys(diff.val).forEach((key) => { Object.keys(diff.val).forEach((key) => {
console.log("Hours", diff.val[key][Object.keys(diff.val[key])[0]]); // console.log("Hours", diff.val[key][Object.keys(diff.val[key])[0]]);
console.log("Rate", Object.keys(diff.val[key])[0]); // console.log("Rate", Object.keys(diff.val[key])[0]);
ticketsToInsert.push({ ticketsToInsert.push({
task_name: "Pay All", task_name: "Pay All",
jobid: job.id, jobid: job.id,

View File

@@ -1,18 +1,19 @@
const { createCanvas } = require("canvas"); const { createCanvas } = require("canvas");
const Chart = require("chart.js/auto"); const Chart = require("chart.js/auto");
const logger = require("../utils/logger");
const { backgroundColors, borderColors } = require("./canvas-colors"); const { backgroundColors, borderColors } = require("./canvas-colors");
const { isObject, defaultsDeep, isNumber } = require("lodash"); const { isObject, defaultsDeep, isNumber } = require("lodash");
exports.canvastest = function (req, res) { exports.canvastest = function (req, res) {
console.log("Incoming test request.", req); //console.log("Incoming test request.", req);
res.status(200).send("OK"); res.status(200).send("OK");
}; };
exports.canvas = function (req, res) { exports.canvas = function (req, res) {
const { w, h, values, keys, override } = req.body; const { w, h, values, keys, override } = req.body;
console.log("Incoming Canvas Request:", w, h, values, keys, override); //console.log("Incoming Canvas Request:", w, h, values, keys, override);
logger.log("inbound-canvas-creation", "debug", "jsr", null, { w, h, values, keys, override });
// Gate required values // Gate required values
if (!values || !keys) { if (!values || !keys) {
res.status(400).send("Missing required data"); res.status(400).send("Missing required data");

View File

@@ -49,7 +49,7 @@ exports.job = async (req, res) => {
if (bucketId) { if (bucketId) {
load.productionTotal[bucketId].count = load.productionTotal[bucketId].count + 1; load.productionTotal[bucketId].count = load.productionTotal[bucketId].count + 1;
} else { } else {
console.log("Uh oh, this job doesn't fit in a bucket!", item); // console.log("Uh oh, this job doesn't fit in a bucket!", item);
} }
}); });
@@ -254,7 +254,7 @@ const CalculateLoad = (currentLoad, buckets, jobsIn, jobsOut) => {
if (bucketId) { if (bucketId) {
newLoad[bucketId].count = newLoad[bucketId].count + 1; newLoad[bucketId].count = newLoad[bucketId].count + 1;
} else { } else {
console.log("[Util Arr Job]Uh oh, this job doesn't fit in a bucket!", job); // console.log("[Util Arr Job]Uh oh, this job doesn't fit in a bucket!", job);
} }
}); });
@@ -263,10 +263,10 @@ const CalculateLoad = (currentLoad, buckets, jobsIn, jobsOut) => {
if (bucketId) { if (bucketId) {
newLoad[bucketId].count = newLoad[bucketId].count - 1; newLoad[bucketId].count = newLoad[bucketId].count - 1;
if (newLoad[bucketId].count < 0) { if (newLoad[bucketId].count < 0) {
console.log("***ERROR: NEGATIVE LOAD Bucket =>", bucketId, job); // console.log("***ERROR: NEGATIVE LOAD Bucket =>", bucketId, job);
} }
} else { } else {
console.log("[Util Out Job]Uh oh, this job doesn't fit in a bucket!", job); // console.log("[Util Out Job]Uh oh, this job doesn't fit in a bucket!", job);
} }
}); });

View File

@@ -47,7 +47,7 @@ exports.receive = async (req, res) => {
//Found a bodyshop - should always happen. //Found a bodyshop - should always happen.
if (response.bodyshops[0].conversations.length === 0) { if (response.bodyshops[0].conversations.length === 0) {
//No conversation Found, create one. //No conversation Found, create one.
console.log("[SMS Receive] No conversation found. Creating one."); //console.log("[SMS Receive] No conversation found. Creating one.");
newMessage.conversation = { newMessage.conversation = {
data: { data: {
bodyshopid: response.bodyshops[0].id, bodyshopid: response.bodyshops[0].id,
@@ -56,7 +56,7 @@ exports.receive = async (req, res) => {
}; };
} else if (response.bodyshops[0].conversations.length === 1) { } else if (response.bodyshops[0].conversations.length === 1) {
//Just add it to the conversation //Just add it to the conversation
console.log("[SMS Receive] Conversation found. Added ID."); //console.log("[SMS Receive] Conversation found. Added ID.");
newMessage.conversationid = response.bodyshops[0].conversations[0].id; newMessage.conversationid = response.bodyshops[0].conversations[0].id;
} else { } else {
//We should never get here. //We should never get here.
@@ -123,7 +123,14 @@ exports.receive = async (req, res) => {
} }
} }
} catch (e1) { } catch (e1) {
console.log("e1", e1); logger.log("sms-inbound-error", "ERROR", "api", null, {
msid: req.body.SmsMessageSid,
text: req.body.Body,
image: !!req.body.MediaUrl0,
image_path: generateMediaArray(req.body),
messagingServiceSid: req.body.MessagingServiceSid,
error: e1
});
res.sendStatus(500).json(e1); res.sendStatus(500).json(e1);
} }
} }

View File

@@ -39,7 +39,7 @@ const processor = async (req, res) => {
} }
}); });
} catch (error) { } catch (error) {
console.log("error", error); // console.log("error", error);
res.status(400).send(error); res.status(400).send(error);
} }
}; };

View File

@@ -6,10 +6,11 @@ const client = require("../graphql-client/graphql-client").client;
const emailer = require("../email/sendemail"); const emailer = require("../email/sendemail");
const moment = require("moment-timezone"); const moment = require("moment-timezone");
const converter = require("json-2-csv"); const converter = require("json-2-csv");
const logger = require("../utils/logger");
exports.taskHandler = async (req, res) => { exports.taskHandler = async (req, res) => {
try { try {
const { bodyshopid, query, variables, text, to, subject, timezone } = req.body; const { query, variables, text, to, subject, timezone } = req.body;
//Check the variables to see if they are an object. //Check the variables to see if they are an object.
Object.keys(variables).forEach((key) => { Object.keys(variables).forEach((key) => {
@@ -32,8 +33,10 @@ exports.taskHandler = async (req, res) => {
text, text,
attachments: [{ filename: "query.csv", content: csv }] attachments: [{ filename: "query.csv", content: csv }]
}) })
.catch((err) => { .catch((error) => {
console.error("Errors sending CSV Email."); logger.log("Tasks - Error sending CSV EMAIL", "error", req?.user?.email, null, {
error
});
}); });
return res.status(200).send(csv); return res.status(200).send(csv);

View File

@@ -1,25 +1,139 @@
const graylog2 = require("graylog2"); // Load environment variables THIS MUST BE AT THE TOP
const path = require("path");
const logger = new graylog2.graylog({ require("dotenv").config({
servers: [{ host: "logs.bodyshop.app", port: 12201 }] path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`)
}); });
function log(message, type, user, record, object) { const InstanceManager = require("../utils/instanceMgr").default;
if (type !== "ioevent") const winston = require("winston");
console.log(message, { const WinstonCloudWatch = require("winston-cloudwatch");
type, const { isString, isEmpty } = require("lodash");
env: process.env.NODE_ENV || "development", const { networkInterfaces, hostname } = require("node:os");
user,
record,
...object
});
logger.log(message, message, {
type,
env: process.env.NODE_ENV || "development",
user,
record,
...object
});
}
module.exports = { log }; const createLogger = () => {
try {
const isLocal = isString(process.env?.LOCALSTACK_HOSTNAME) && !isEmpty(process.env?.LOCALSTACK_HOSTNAME);
const logGroupName = isLocal ? "development" : process.env.CLOUDWATCH_LOG_GROUP;
const winstonCloudwatchTransportDefaults = {
logGroupName: logGroupName,
awsOptions: {
region: InstanceManager({
imex: "ca-central-1",
rome: "us-east-2"
})
},
jsonMessage: true
};
if (isLocal) {
winstonCloudwatchTransportDefaults.awsOptions.endpoint = `http://${process.env.LOCALSTACK_HOSTNAME}:4566`;
}
const levelFilter = (levels) => {
return winston.format((info) => {
if (Array.isArray(levels)) {
return levels.includes(info.level) ? info : false;
} else {
return info.level === levels ? info : false;
}
})();
};
const getHostNameOrIP = () => {
// Try to get the hostname first
const hostName = hostname();
if (hostName) return hostName;
const interfaces = networkInterfaces();
for (const name of Object.keys(interfaces)) {
for (const iface of interfaces[name]) {
if (iface.family === "IPv4" && !iface.internal) {
return iface.address;
}
}
}
return "127.0.0.1";
};
const createProductionTransport = (level, logStreamName, filters) => {
return new WinstonCloudWatch({
level,
logStreamName: logStreamName || level,
format: levelFilter(filters || level),
...winstonCloudwatchTransportDefaults
});
};
const internalHostname = process.env.HOSTNAME || getHostNameOrIP();
const getDevelopmentTransports = () => [
new winston.transports.Console({
level: "silly",
format: winston.format.combine(
winston.format.colorize(),
winston.format.timestamp(),
winston.format.printf(({ level, message, timestamp, user, record, meta }) => {
const hostnameColor = `\x1b[34m${internalHostname}\x1b[0m`; // Blue
const timestampColor = `\x1b[36m${timestamp}\x1b[0m`; // Cyan
const labelColor = "\x1b[33m"; // Yellow
const separatorColor = "\x1b[35m|\x1b[0m"; // Magenta for separators
return `${timestampColor} [${hostnameColor}] [${level}]: ${message} ${
user ? `${separatorColor} ${labelColor}user:\x1b[0m ${JSON.stringify(user)}` : ""
} ${record ? `${separatorColor} ${labelColor}record:\x1b[0m ${JSON.stringify(record)}` : ""}${
meta
? `\n${separatorColor} ${labelColor}meta:\x1b[0m ${JSON.stringify(meta, null, 2)} ${separatorColor}`
: ""
}`;
})
)
})
];
const getProductionTransports = () => [
createProductionTransport("error"),
createProductionTransport("warn"),
createProductionTransport("info"),
createProductionTransport("silly", "debug", ["http", "verbose", "debug", "silly"])
];
const winstonLogger = winston.createLogger({
format: winston.format.json(),
transports:
process.env.NODE_ENV === "production"
? getProductionTransports()
: [...getDevelopmentTransports(), ...getProductionTransports()]
});
if (isLocal) {
winstonLogger.debug(
`CloudWatch set to LocalStack end point: ${winstonCloudwatchTransportDefaults.awsOptions.endpoint}`
);
}
const log = (message, type, user, record, meta) => {
winstonLogger.log({
level: type.toLowerCase(),
message,
user,
record,
hostname: internalHostname,
meta
});
};
return {
log,
logger: winstonLogger
};
} catch (e) {
console.error("Error setting up enhanced Logger, defaulting to console.: " + e?.message || "");
return {
log: console.log,
logger: console.log
};
}
};
module.exports = createLogger();

View File

@@ -8,7 +8,6 @@ const redisSocketEvents = ({
}) => { }) => {
// Logging helper functions // Logging helper functions
const createLogEvent = (socket, level, message) => { const createLogEvent = (socket, level, message) => {
console.log(`[IOREDIS LOG EVENT] - ${socket?.user?.email} - ${socket.id} - ${message}`);
logger.log("ioredis-log-event", level, socket?.user?.email, null, { wsmessage: message }); logger.log("ioredis-log-event", level, socket?.user?.email, null, { wsmessage: message });
}; };
@@ -33,7 +32,6 @@ const redisSocketEvents = ({
next(new Error("Authentication error - no authorization token.")); next(new Error("Authentication error - no authorization token."));
} }
} catch (error) { } catch (error) {
console.log("Uncaught connection error:::", error);
logger.log("websocket-connection-error", "error", null, null, { logger.log("websocket-connection-error", "error", null, null, {
...error ...error
}); });
@@ -43,7 +41,8 @@ const redisSocketEvents = ({
// Register Socket Events // Register Socket Events
const registerSocketEvents = (socket) => { const registerSocketEvents = (socket) => {
createLogEvent(socket, "DEBUG", `Registering RedisIO Socket Events.`); // Uncomment for further testing
// createLogEvent(socket, "debug", `Registering RedisIO Socket Events.`);
// Token Update Events // Token Update Events
const registerUpdateEvents = (socket) => { const registerUpdateEvents = (socket) => {
@@ -56,18 +55,19 @@ const redisSocketEvents = ({
// If We ever want to persist user Data across workers // If We ever want to persist user Data across workers
// await setSessionData(socket.id, "user", user); // await setSessionData(socket.id, "user", user);
createLogEvent(socket, "INFO", "Token updated successfully"); // Uncomment for further testing
// createLogEvent(socket, "debug", "Token updated successfully");
socket.emit("token-updated", { success: true }); socket.emit("token-updated", { success: true });
} catch (error) { } catch (error) {
if (error.code === "auth/id-token-expired") { if (error.code === "auth/id-token-expired") {
createLogEvent(socket, "WARNING", "Stale token received, waiting for new token"); createLogEvent(socket, "warn", "Stale token received, waiting for new token");
socket.emit("token-updated", { socket.emit("token-updated", {
success: false, success: false,
error: "Stale token." error: "Stale token."
}); });
} else { } else {
createLogEvent(socket, "ERROR", `Token update failed: ${error.message}`); createLogEvent(socket, "error", `Token update failed: ${error.message}`);
socket.emit("token-updated", { success: false, error: error.message }); socket.emit("token-updated", { success: false, error: error.message });
// For any other errors, optionally disconnect the socket // For any other errors, optionally disconnect the socket
socket.disconnect(); socket.disconnect();
@@ -82,9 +82,9 @@ const redisSocketEvents = ({
try { try {
const room = getBodyshopRoom(bodyshopUUID); const room = getBodyshopRoom(bodyshopUUID);
socket.join(room); socket.join(room);
createLogEvent(socket, "DEBUG", `Client joined bodyshop room: ${room}`); // createLogEvent(socket, "debug", `Client joined bodyshop room: ${room}`);
} catch (error) { } catch (error) {
createLogEvent(socket, "ERROR", `Error joining room: ${error}`); createLogEvent(socket, "error", `Error joining room: ${error}`);
} }
}; };
@@ -92,9 +92,9 @@ const redisSocketEvents = ({
try { try {
const room = getBodyshopRoom(bodyshopUUID); const room = getBodyshopRoom(bodyshopUUID);
socket.leave(room); socket.leave(room);
createLogEvent(socket, "DEBUG", `Client left bodyshop room: ${room}`); createLogEvent(socket, "debug", `Client left bodyshop room: ${room}`);
} catch (error) { } catch (error) {
createLogEvent(socket, "ERROR", `Error joining room: ${error}`); createLogEvent(socket, "error", `Error joining room: ${error}`);
} }
}; };
@@ -102,9 +102,10 @@ const redisSocketEvents = ({
try { try {
const room = getBodyshopRoom(bodyshopUUID); const room = getBodyshopRoom(bodyshopUUID);
io.to(room).emit("bodyshop-message", message); io.to(room).emit("bodyshop-message", message);
createLogEvent(socket, "DEBUG", `Broadcast message to bodyshop ${room}`); // We do not need this as these can be debugged live
// createLogEvent(socket, "debug", `Broadcast message to bodyshop ${room}`);
} catch (error) { } catch (error) {
createLogEvent(socket, "ERROR", `Error getting room: ${error}`); createLogEvent(socket, "error", `Error getting room: ${error}`);
} }
}; };
@@ -115,7 +116,9 @@ const redisSocketEvents = ({
// Disconnect Events // Disconnect Events
const registerDisconnectEvents = (socket) => { const registerDisconnectEvents = (socket) => {
const disconnect = () => { const disconnect = () => {
createLogEvent(socket, "DEBUG", `User disconnected.`); // Uncomment for further testing
// createLogEvent(socket, "debug", `User disconnected.`);
const rooms = Array.from(socket.rooms).filter((room) => room !== socket.id); const rooms = Array.from(socket.rooms).filter((room) => room !== socket.id);
for (const room of rooms) { for (const room of rooms) {
socket.leave(room); socket.leave(room);

View File

@@ -31,7 +31,7 @@ io.use(function (socket, next) {
next(new Error("Authentication error - no authorization token.")); next(new Error("Authentication error - no authorization token."));
} }
} catch (error) { } catch (error) {
console.log("Uncaught connection error:::", error); //console.log("Uncaught connection error:::", error);
logger.log("websocket-connection-error", "error", null, null, { logger.log("websocket-connection-error", "error", null, null, {
token: socket.handshake.auth.token, token: socket.handshake.auth.token,
...error ...error
@@ -41,7 +41,7 @@ io.use(function (socket, next) {
}); });
io.on("connection", (socket) => { io.on("connection", (socket) => {
socket.log_level = "TRACE"; socket.log_level = "DEBUG";
createLogEvent(socket, "DEBUG", `Connected and Authenticated.`); createLogEvent(socket, "DEBUG", `Connected and Authenticated.`);
socket.on("set-log-level", (level) => { socket.on("set-log-level", (level) => {
@@ -75,7 +75,7 @@ io.on("connection", (socket) => {
socket.on("cdk-calculate-allocations", async (jobid, callback) => { socket.on("cdk-calculate-allocations", async (jobid, callback) => {
const allocations = await CdkCalculateAllocations(socket, jobid); const allocations = await CdkCalculateAllocations(socket, jobid);
createLogEvent(socket, "DEBUG", `Allocations calculated.`); createLogEvent(socket, "DEBUG", `Allocations calculated.`);
createLogEvent(socket, "TRACE", `Allocations calculated. ${JSON.stringify(allocations, null, 2)}`); createLogEvent(socket, "SILLY", `Allocations calculated. ${JSON.stringify(allocations, null, 2)}`);
callback(allocations); callback(allocations);
}); });
@@ -85,7 +85,7 @@ io.on("connection", (socket) => {
socket.on("pbs-calculate-allocations", async (jobid, callback) => { socket.on("pbs-calculate-allocations", async (jobid, callback) => {
const allocations = await CdkCalculateAllocations(socket, jobid); const allocations = await CdkCalculateAllocations(socket, jobid);
createLogEvent(socket, "DEBUG", `Allocations calculated.`); createLogEvent(socket, "DEBUG", `Allocations calculated.`);
createLogEvent(socket, "TRACE", `Allocations calculated. ${JSON.stringify(allocations, null, 2)}`); createLogEvent(socket, "SILLY", `Allocations calculated. ${JSON.stringify(allocations, null, 2)}`);
callback(allocations); callback(allocations);
}); });
@@ -103,7 +103,7 @@ io.on("connection", (socket) => {
socket.on("pbs-calculate-allocations-ap", async (billids, callback) => { socket.on("pbs-calculate-allocations-ap", async (billids, callback) => {
const allocations = await PbsCalculateAllocationsAp(socket, billids); const allocations = await PbsCalculateAllocationsAp(socket, billids);
createLogEvent(socket, "DEBUG", `AP Allocations calculated.`); createLogEvent(socket, "DEBUG", `AP Allocations calculated.`);
createLogEvent(socket, "TRACE", `Allocations calculated. ${JSON.stringify(allocations, null, 2)}`); createLogEvent(socket, "DEBUG", `Allocations calculated. ${JSON.stringify(allocations, null, 2)}`);
socket.apAllocations = allocations; socket.apAllocations = allocations;
callback(allocations); callback(allocations);
}); });
@@ -122,7 +122,7 @@ io.on("connection", (socket) => {
function createLogEvent(socket, level, message) { function createLogEvent(socket, level, message) {
if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy(level)) { if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy(level)) {
console.log(`[WS LOG EVENT] ${level} - ${new Date()} - ${socket.user.email} - ${socket.id} - ${message}`); // console.log(`[WS LOG EVENT] ${level} - ${new Date()} - ${socket.user.email} - ${socket.id} - ${message}`);
socket.emit("log-event", { socket.emit("log-event", {
timestamp: new Date(), timestamp: new Date(),
level, level,
@@ -148,7 +148,7 @@ function createLogEvent(socket, level, message) {
function createJsonEvent(socket, level, message, json) { function createJsonEvent(socket, level, message, json) {
if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy(level)) { if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy(level)) {
console.log(`[WS LOG EVENT] ${level} - ${new Date()} - ${socket.user.email} - ${socket.id} - ${message}`); //console.log(`[WS LOG EVENT] ${level} - ${new Date()} - ${socket.user.email} - ${socket.id} - ${message}`);
socket.emit("log-event", { socket.emit("log-event", {
timestamp: new Date(), timestamp: new Date(),
level, level,
@@ -173,17 +173,17 @@ function createJsonEvent(socket, level, message, json) {
} }
function createXmlEvent(socket, xml, message, isError = false) { function createXmlEvent(socket, xml, message, isError = false) {
if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy("TRACE")) { if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy("SILLY")) {
socket.emit("log-event", { socket.emit("log-event", {
timestamp: new Date(), timestamp: new Date(),
level: isError ? "ERROR" : "TRACE", level: isError ? "ERROR" : "SILLY",
message: `${message}: ${xml}` message: `${message}: ${xml}`
}); });
} }
logger.log( logger.log(
isError ? "ws-log-event-xml-error" : "ws-log-event-xml", isError ? "ws-log-event-xml-error" : "ws-log-event-xml",
isError ? "ERROR" : "TRACE", isError ? "ERROR" : "SILLY",
socket.user.email, socket.user.email,
socket.recordid, socket.recordid,
{ {
@@ -195,7 +195,7 @@ function createXmlEvent(socket, xml, message, isError = false) {
if (socket.logEvents && isArray(socket.logEvents)) { if (socket.logEvents && isArray(socket.logEvents)) {
socket.logEvents.push({ socket.logEvents.push({
timestamp: new Date(), timestamp: new Date(),
level: isError ? "ERROR" : "TRACE", level: isError ? "ERROR" : "SILLY",
message, message,
xml xml
}); });
@@ -206,7 +206,7 @@ function LogLevelHierarchy(level) {
switch (level) { switch (level) {
case "XML": case "XML":
return 5; return 5;
case "TRACE": case "SILLY":
return 5; return 5;
case "DEBUG": case "DEBUG":
return 4; return 4;