Merge branch 'master' into feature/america

This commit is contained in:
Patrick Fic
2023-08-30 08:04:57 -07:00
43 changed files with 1812 additions and 11735 deletions

View File

@@ -1,4 +1,4 @@
<babeledit_project version="1.2" be_version="2.7.1">
<babeledit_project be_version="2.7.1" version="1.2">
<!--
BabelEdit project file
@@ -1009,27 +1009,6 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>smspaymentreminder</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>suggesteddates</name>
<definition_loaded>false</definition_loaded>
@@ -16312,6 +16291,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>copied</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>copylink</name>
<definition_loaded>false</definition_loaded>
@@ -16648,6 +16648,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>sendbysms</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>senderrortosupport</name>
<definition_loaded>false</definition_loaded>
@@ -19360,6 +19381,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>openingip</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>title</name>
<definition_loaded>false</definition_loaded>
@@ -33131,27 +33173,6 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>paymentremindersms</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>phonebook</name>
<definition_loaded>false</definition_loaded>
@@ -37601,6 +37622,32 @@
<folder_node>
<name>payments</name>
<children>
<folder_node>
<name>actions</name>
<children>
<concept_node>
<name>generatepaymentlink</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
<name>errors</name>
<children>
@@ -38118,6 +38165,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>smspaymentreminder</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>title</name>
<definition_loaded>false</definition_loaded>

View File

@@ -1,21 +1,38 @@
import React, { useCallback, useEffect } from "react";
import axios from "axios";
import { useTranslation } from "react-i18next";
import { Button, Card, Form, Input, InputNumber, Row, Select } from "antd";
import moment from "moment";
import { useMutation, useQuery } from "@apollo/client";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import JobSearchSelectComponent from "../job-search-select/job-search-select.component";
import { INSERT_NEW_PAYMENT } from "../../graphql/payments.queries";
import {
Button,
Card,
Form,
Input,
InputNumber,
Row,
Spin,
notification,
} from "antd";
import axios from "axios";
import moment from "moment";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import {
INSERT_PAYMENT_RESPONSE,
QUERY_RO_AND_OWNER_BY_JOB_PK,
} from "../../graphql/payment_response.queries";
import DataLabel from "../data-label/data-label.component";
import { INSERT_NEW_PAYMENT } from "../../graphql/payments.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import { connect } from "react-redux";
import { toggleModalVisible } from "../../redux/modals/modals.actions";
import { selectCardPayment } from "../../redux/modals/modals.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import DataLabel from "../data-label/data-label.component";
import JobSearchSelectComponent from "../job-search-select/job-search-select.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
const mapStateToProps = createStructuredSelector({
cardPaymentModal: selectCardPayment,
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
insertAuditTrail: ({ jobid, operation }) =>
@@ -25,24 +42,39 @@ const mapDispatchToProps = (dispatch) => ({
const CardPaymentModalComponent = ({
bodyshop,
context,
cardPaymentModal,
toggleModalVisible,
insertAuditTrail,
}) => {
const { context } = cardPaymentModal;
const [form] = Form.useForm();
const amount = Form.useWatch("amount", form);
const payer = Form.useWatch("payer", form);
const jobid = Form.useWatch("jobid", form);
const [loading, setLoading] = useState(false);
const [insertPayment] = useMutation(INSERT_NEW_PAYMENT);
const [insertPaymentResponse] = useMutation(INSERT_PAYMENT_RESPONSE);
const { t } = useTranslation();
const { data, refetch } = useQuery(QUERY_RO_AND_OWNER_BY_JOB_PK, {
variables: { jobid: context?.jobid ?? "" },
skip: !context?.jobid,
});
const nonApproval = useCallback(
async (response) => {
//Initialize the intellipay window.
const SetIntellipayCallbackFunctions = () => {
console.log("*** Set IntelliPay callback functions.");
window.intellipay.runOnClose(() => {
//window.intellipay.initialize();
});
window.intellipay.runOnApproval(async function (response) {
console.warn("*** Running On Approval Script ***");
form.setFieldValue("paymentResponse", response);
form.submit();
});
window.intellipay.runOnNonApproval(async function (response) {
// Mutate unsuccessful payment
await insertPaymentResponse({
variables: {
@@ -57,221 +89,193 @@ const CardPaymentModalComponent = ({
},
},
});
// Insert failed payment to audit trail
insertAuditTrail({
jobid: jobid || context?.jobid,
operation: AuditTrailMapping.failedpayment(),
});
},
[bodyshop, context, insertAuditTrail, insertPaymentResponse, jobid]
);
const initIntellipayFunctions = useCallback(() => {
if (window.intellipay !== undefined && typeof jobid !== "undefined") {
console.log("intellipay init functions");
window.intellipay.runOnClose(() => {
window.intellipay.initialize();
});
window.intellipay.runOnApproval(async function (response) {
form.setFieldValue("paymentResponse", response);
form.submit();
toggleModalVisible();
});
window.intellipay.runOnNonApproval(nonApproval);
}
}, [form, jobid, nonApproval, toggleModalVisible]);
const initJobId = useCallback(() => {
if (context?.jobid) {
form.setFieldValue("jobid", context.jobid);
}
form.setFieldValue("payer", t("payments.labels.customer"));
}, [context?.jobid, form, t]);
useEffect(() => {
initJobId();
axios
.post("/intellipay/lightbox_credentials", { bodyshop })
.then((response) => {
var rg = document.createRange();
let node = rg.createContextualFragment(response.data);
document.documentElement.appendChild(node);
window.intellipay.initialize();
initIntellipayFunctions();
});
function handleEvents(...props) {
const operation = props[0].data.operation;
if (operation === "updateform") {
props[0].stopImmediatePropagation();
}
}
window.addEventListener("message", handleEvents, false);
return () => window.removeEventListener("message", handleEvents, false);
}, [bodyshop, initJobId, initIntellipayFunctions]);
});
};
const handleFinish = async (values) => {
const paymentResult = await insertPayment({
variables: {
paymentInput: {
amount: values.amount,
transactionid: values.paymentResponse.receiptelements.transid,
payer: values.payer,
type: values.paymentResponse.cardType,
jobid: values.jobid,
date: moment(Date.now()),
},
},
update(cache, { data }) {
cache.modify({
id: cache.identify({ id: jobid, __typename: "jobs" }),
fields: {
payments(payments) {
return [...data.insert_payments.returning, ...payments];
},
try {
const paymentResult = await insertPayment({
variables: {
paymentInput: {
amount: values.amount,
transactionid: (values.paymentResponse.paymentid || "").toString(),
payer: t("payments.labels.customer"),
type: values.paymentResponse.cardbrand,
jobid: values.jobid,
date: moment(Date.now()),
},
});
},
});
await insertPaymentResponse({
variables: {
paymentResponse: {
amount: values.amount,
bodyshopid: bodyshop.id,
paymentid: paymentResult.data.insert_payments.returning[0].id,
jobid: values.jobid,
declinereason: values.paymentResponse.declinereason,
ext_paymentid: values.paymentResponse.paymentid.toString(),
successful: true,
response: values.paymentResponse,
},
},
});
refetchQueries: ["GET_JOB_BY_PK"],
update(cache, { data }) {
cache.modify({
id: cache.identify({ id: values.jobid, __typename: "jobs" }),
fields: {
payments(cachedPayments) {
return [...data.insert_payments.returning, ...cachedPayments];
},
},
});
},
});
await insertPaymentResponse({
variables: {
paymentResponse: {
amount: values.amount,
bodyshopid: bodyshop.id,
paymentid: paymentResult.data.insert_payments.returning[0].id,
jobid: values.jobid,
declinereason: values.paymentResponse.declinereason,
ext_paymentid: values.paymentResponse.paymentid.toString(),
successful: true,
response: values.paymentResponse,
},
},
});
toggleModalVisible();
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
};
const handleIntelliPayCharge = async () => {
setLoading(true);
try {
console.warn("*** Window.Intellipay", !!window.intellipay);
const response = await axios.post("/intellipay/lightbox_credentials", {
bodyshop,
refresh: !!window.intellipay,
});
if (window.intellipay) {
// eslint-disable-next-line no-eval
eval(response.data);
SetIntellipayCallbackFunctions();
window.intellipay.autoOpen();
} else {
var rg = document.createRange();
let node = rg.createContextualFragment(response.data);
document.documentElement.appendChild(node);
SetIntellipayCallbackFunctions();
window.intellipay.isAutoOpen = true;
window.intellipay.initialize();
}
} catch (error) {
notification.open({
type: "error",
message: t("job_payments.notifications.error.openingip"),
});
setLoading(false);
}
};
return (
<Card title="Card Payment">
<Form onFinish={handleFinish} form={form}>
<LayoutFormRow grow>
<Form.Item
name="jobid"
label={t("bills.fields.ro_number")}
rules={[
{
required: true,
// message: t("general.validation.required"),
},
]}
>
<JobSearchSelectComponent
disabled={context?.jobid}
notExported={false}
clm_no
onChange={(e) => {
refetch({ jobid: e });
}}
/>
</Form.Item>
</LayoutFormRow>
{/* Lighbox Input amount needs to be hidden */}
<Input
className="ipayfield"
data-ipayname="amount"
type="hidden"
value={amount}
hidden
/>
<Input
className="ipayfield"
data-ipayname="account"
type="hidden"
value={data?.jobs_by_pk.ro_number}
hidden
/>
<Input
className="ipayfield"
data-ipayname="email"
type="hidden"
value={data?.jobs_by_pk.owner.ownr_ea}
hidden
/>
{/* Lightbox payment response when it is completed */}
<Form.Item name="paymentResponse" hidden>
<Input type="hidden" value={amount} />
</Form.Item>
<LayoutFormRow grow>
<Form.Item
label={t("payments.fields.payer")}
name="payer"
rules={[
{
required: true,
// message: t("general.validation.required"),
},
]}
>
<Select>
<Select.Option value={t("payments.labels.customer")}>
{t("payments.labels.customer")}
</Select.Option>
<Select.Option value={t("payments.labels.insurance")}>
{t("payments.labels.insurance")}
</Select.Option>
</Select>
</Form.Item>
<Form.Item
label="Amount"
name="amount"
rules={[
{
required: true,
// message: t("general.validation.required"),
},
]}
>
<InputNumber />
</Form.Item>
<Row justify="space-around">
<Button
type="primary"
data-ipayname="submit"
className="ipayfield"
disabled={!amount || !payer || !jobid}
<Spin spinning={loading}>
<Form
onFinish={handleFinish}
form={form}
initialValues={{ jobid: context?.jobid }}
>
<LayoutFormRow grow noDivider>
<Form.Item
name="jobid"
label={t("bills.fields.ro_number")}
rules={[
{
required: true,
// message: t("general.validation.required"),
},
]}
>
{t("job_payments.buttons.proceedtopayment")}
</Button>
{context?.balance && (
<DataLabel
valueStyle={{
color: context?.balance.getAmount() !== 0 ? "red" : "green",
<JobSearchSelectComponent
disabled={context?.jobid}
notExported={false}
clm_no
onChange={(e) => {
refetch({ jobid: e });
}}
label={t("payments.labels.balance")}
/>
</Form.Item>
</LayoutFormRow>
{/* Lighbox Input amount needs to be hidden */}
<Input
className="ipayfield"
data-ipayname="amount"
type="hidden"
value={amount}
hidden
/>
<Input
className="ipayfield"
data-ipayname="account"
type="hidden"
value={data?.jobs_by_pk.ro_number}
hidden
/>
<Input
className="ipayfield"
data-ipayname="email"
type="hidden"
value={data?.jobs_by_pk.owner.ownr_ea}
hidden
/>
{/* Lightbox payment response when it is completed */}
<Form.Item name="paymentResponse" hidden>
<Input type="hidden" value={amount} />
</Form.Item>
<LayoutFormRow grow>
<Form.Item
label="Amount"
name="amount"
rules={[
{
required: true,
// message: t("general.validation.required"),
},
]}
>
<InputNumber />
</Form.Item>
<Row justify="space-around">
<Button
type="primary"
// data-ipayname="submit"
className="ipayfield"
disabled={!amount || !jobid}
onClick={handleIntelliPayCharge}
>
{context?.balance.toFormat()}
</DataLabel>
)}
</Row>
</LayoutFormRow>
</Form>
{t("job_payments.buttons.proceedtopayment")}
</Button>
{context?.balance && (
<DataLabel
valueStyle={{
color: context?.balance.getAmount() !== 0 ? "red" : "green",
}}
label={t("payments.labels.balance")}
>
{context?.balance.toFormat()}
</DataLabel>
)}
</Row>
</LayoutFormRow>
</Form>
</Spin>
</Card>
);
};
export default connect(null, mapDispatchToProps)(CardPaymentModalComponent);
export default connect(
mapStateToProps,
mapDispatchToProps
)(CardPaymentModalComponent);

View File

@@ -22,7 +22,7 @@ function CardPaymentModalContainer({
toggleModalVisible,
bodyshop,
}) {
const { context, visible } = cardPaymentModal;
const { visible } = cardPaymentModal;
const { t } = useTranslation();
const handleCancel = () => {
@@ -35,7 +35,7 @@ function CardPaymentModalContainer({
return (
<Modal
visible={visible}
open={visible}
onOk={handleOK}
onCancel={handleCancel}
footer={[
@@ -46,7 +46,7 @@ function CardPaymentModalContainer({
width="60%"
destroyOnClose
>
<CardPaymentModalComponent bodyshop={bodyshop} context={context} />
<CardPaymentModalComponent />
</Modal>
);
}

View File

@@ -23,36 +23,40 @@ export default function DashboardScheduledInToday({ data, ...cardProps }) {
const appt = []; // Flatten Data
data.scheduled_in_today.forEach((item) => {
var i = {
canceled: item.canceled,
id: item.id,
alt_transport: item.job.alt_transport,
clm_no: item.job.clm_no,
jobid: item.job.jobid,
ins_co_nm: item.job.ins_co_nm,
iouparent: item.job.iouparent,
ownerid: item.job.ownerid,
ownr_co_nm: item.job.ownr_co_nm,
ownr_ea: item.job.ownr_ea,
ownr_fn: item.job.ownr_fn,
ownr_ln: item.job.ownr_ln,
ownr_ph1: item.job.ownr_ph1,
ownr_ph2: item.job.ownr_ph2,
production_vars: item.job.production_vars,
ro_number: item.job.ro_number,
suspended: item.job.suspended,
v_make_desc: item.job.v_make_desc,
v_model_desc: item.job.v_model_desc,
v_model_yr: item.job.v_model_yr,
v_vin: item.job.v_vin,
vehicleid: item.job.vehicleid,
note: item.note,
start: moment(item.start).format("hh:mm a"),
title: item.title,
};
appt.push(i);
if (item.job) {
var i = {
canceled: item.canceled,
id: item.id,
alt_transport: item.job.alt_transport,
clm_no: item.job.clm_no,
jobid: item.job.jobid,
ins_co_nm: item.job.ins_co_nm,
iouparent: item.job.iouparent,
ownerid: item.job.ownerid,
ownr_co_nm: item.job.ownr_co_nm,
ownr_ea: item.job.ownr_ea,
ownr_fn: item.job.ownr_fn,
ownr_ln: item.job.ownr_ln,
ownr_ph1: item.job.ownr_ph1,
ownr_ph2: item.job.ownr_ph2,
production_vars: item.job.production_vars,
ro_number: item.job.ro_number,
suspended: item.job.suspended,
v_make_desc: item.job.v_make_desc,
v_model_desc: item.job.v_model_desc,
v_model_yr: item.job.v_model_yr,
v_vin: item.job.v_vin,
vehicleid: item.job.vehicleid,
note: item.note,
start: moment(item.start).format("hh:mm a"),
title: item.title,
};
appt.push(i);
}
});
appt.sort(function (a, b) {
return new moment(a.start) - new moment(b.start);
});
appt.sort ( function (a, b) { return new Date(a.start) - new Date(b.start); });
const columns = [
{
@@ -182,7 +186,12 @@ export default function DashboardScheduledInToday({ data, ...cardProps }) {
};
return (
<Card title={t("dashboard.titles.scheduledintoday", {date: moment().startOf("day").format("MM/DD/YYYY")})} {...cardProps}>
<Card
title={t("dashboard.titles.scheduledintoday", {
date: moment().startOf("day").format("MM/DD/YYYY"),
})}
{...cardProps}
>
<div style={{ height: "100%" }}>
<Table
onChange={handleTableChange}

View File

@@ -18,7 +18,7 @@ export default function DataLabel({
<div {...props} style={{ display: "flex" }}>
<div
style={{
flex: 2,
// flex: 2,
marginRight: ".2rem",
}}
>

View File

@@ -97,6 +97,11 @@ function Header({
{},
bodyshop && bodyshop.imexshopid
);
const { ImEXPay } = useTreatments(
["ImEXPay"],
{},
bodyshop && bodyshop.imexshopid
);
const { t } = useTranslation();
@@ -243,19 +248,20 @@ function Header({
>
{t("menus.header.enterpayment")}
</Menu.Item>
{/* TODO: Enter Card Payment */}
<Menu.Item
key="entercardpayments"
onClick={() => {
setCardPaymentContext({
actions: {},
context: null,
});
}}
icon={<Icon component={FaCreditCard} />}
>
{t("menus.header.entercardpayment")}
</Menu.Item>
{ImEXPay.treatment === "on" && (
<Menu.Item
key="entercardpayments"
onClick={() => {
setCardPaymentContext({
actions: {},
context: null,
});
}}
icon={<Icon component={FaCreditCard} />}
>
{t("menus.header.entercardpayment")}
</Menu.Item>
)}
<Menu.Divider key="div5" />
<Menu.Item key="timetickets" icon={<FieldTimeOutlined />}>
<Link to="/manage/timetickets">

View File

@@ -5,6 +5,7 @@ import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { SEARCH_VENDOR_AUTOCOMPLETE_WITH_ADDR } from "../../graphql/vendors.queries";
import { selectTechnician } from "../../redux/tech/tech.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { GenerateDocument } from "../../utils/RenderTemplate";
import { TemplateList } from "../../utils/TemplateConstants";
@@ -13,13 +14,14 @@ import VendorSearchSelect from "../vendor-search-select/vendor-search-select.com
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
technician: selectTechnician,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(mapStateToProps, mapDispatchToProps)(Jobd3RdPartyModal);
export function Jobd3RdPartyModal({ bodyshop, jobId, job }) {
export function Jobd3RdPartyModal({ bodyshop, jobId, job, technician }) {
const [isModalVisible, setIsModalVisible] = useState(false);
const { t } = useTranslation();
const [form] = Form.useForm();
@@ -212,7 +214,9 @@ export function Jobd3RdPartyModal({ bodyshop, jobId, job }) {
]}
>
<Radio.Group>
<Radio value={"e"}>{t("parts_orders.labels.email")}</Radio>
{!technician ? (
<Radio value={"e"}>{t("parts_orders.labels.email")}</Radio>
) : null}
<Radio value={"p"}>{t("parts_orders.labels.print")}</Radio>
</Radio.Group>
</Form.Item>

View File

@@ -29,11 +29,11 @@ import { GenerateDocument } from "../../utils/RenderTemplate";
import { TemplateList } from "../../utils/TemplateConstants";
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
import DataLabel from "../data-label/data-label.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import ScheduleManualEvent from "../schedule-manual-event/schedule-manual-event.component";
import ScheduleAtChange from "./job-at-change.component";
import ScheduleEventColor from "./schedule-event.color.component";
import ScheduleEventNote from "./schedule-event.note.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -208,46 +208,56 @@ export function ScheduleEventComponent({
<Button>{t("appointments.actions.sendreminder")}</Button>
</Dropdown>
) : null}
<Popover
trigger="click"
disabled={event.arrived}
content={
<Form
layout="vertical"
onFinish={({ lost_sale_reason }) => {
handleCancel({ id: event.id, lost_sale_reason });
}}
>
<Form.Item
name="lost_sale_reason"
label={t("jobs.fields.lost_sale_reason")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<Select
options={bodyshop.md_lost_sale_reasons.map((lsr) => ({
label: lsr,
value: lsr,
}))}
/>
</Form.Item>
<Button htmlType="submit">
{t("appointments.actions.cancel")}
</Button>
</Form>
}
>
{event.arrived ? (
<Button
// onClick={() => handleCancel(event.id)}
disabled={event.arrived}
>
{t("appointments.actions.cancel")}
</Button>
</Popover>
) : (
<Popover
trigger="click"
disabled={event.arrived}
content={
<Form
layout="vertical"
onFinish={({ lost_sale_reason }) => {
handleCancel({ id: event.id, lost_sale_reason });
}}
>
<Form.Item
name="lost_sale_reason"
label={t("jobs.fields.lost_sale_reason")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<Select
options={bodyshop.md_lost_sale_reasons.map((lsr) => ({
label: lsr,
value: lsr,
}))}
/>
</Form.Item>
<Button htmlType="submit">
{t("appointments.actions.cancel")}
</Button>
</Form>
}
>
<Button
// onClick={() => handleCancel(event.id)}
disabled={event.arrived}
>
{t("appointments.actions.cancel")}
</Button>
</Popover>
)}
{event.isintake ? (
<Button
disabled={event.arrived}

View File

@@ -1,26 +1,26 @@
import { Button, Card, Space, Table } from "antd";
import { EditFilled } from "@ant-design/icons";
import { Button, Card, Space, Table } from "antd";
import Dinero from "dinero.js";
import React, { useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
import {
openChatByPhone,
setMessage,
} from "../../redux/messaging/messaging.actions";
import { setModalContext } from "../../redux/modals/modals.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateFormatter } from "../../utils/DateFormatter";
import { alphaSort, dateSort } from "../../utils/sorters";
import { TemplateList } from "../../utils/TemplateConstants";
import { alphaSort, dateSort } from "../../utils/sorters";
import DataLabel from "../data-label/data-label.component";
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
import PaymentExpandedRowComponent from "../payment-expanded-row/payment-expanded-row.component";
import {
setMessage,
openChatByPhone,
} from "../../redux/messaging/messaging.actions";
import { parsePhoneNumber } from "libphonenumber-js";
import axios from "axios";
import PaymentsGenerateLink from "../payments-generate-link/payments-generate-link.component";
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
import { useTreatments } from "@splitsoftware/splitio-react";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -46,12 +46,17 @@ export function JobPayments({
setCardPaymentContext,
refetch,
}) {
const { ImEXPay } = useTreatments(
["ImEXPay"],
{},
bodyshop && bodyshop.imexshopid
);
const { t } = useTranslation();
const [state, setState] = useState({
sortedInfo: {},
filteredInfo: {},
});
const [generatingURL, setGeneratingtURL] = useState(false);
const columns = [
{
@@ -165,39 +170,21 @@ export function JobPayments({
title={t("payments.labels.title")}
extra={
<Space wrap>
<Button
disabled={!job.converted}
loading={generatingURL}
onClick={async () => {
const p = parsePhoneNumber(job.ownr_ph1, "CA");
setGeneratingtURL(true);
const response = await axios.post(
"/intellipay/generate_payment_url",
{
bodyshop,
amount: balance.getAmount(),
account: job.ro_number,
{ImEXPay.treatment === "on" && (
<>
<Button
onClick={() =>
setCardPaymentContext({
actions: { refetch },
context: { jobid: job.id, balance },
})
}
);
setGeneratingtURL(false);
console.log("SMS", response);
openChatByPhone({
phone_num: p.formatInternational(),
jobid: job.id,
});
setMessage(
t("appointments.labels.smspaymentreminder", {
shopname: bodyshop.shopname,
amount: balance.toFormat(),
payment_link: response.data.shorUrl,
})
);
}}
>
{t("menus.header.paymentremindersms")}
</Button>
>
{t("menus.header.entercardpayment")}
</Button>
<PaymentsGenerateLink job={job} />
</>
)}
<Button
disabled={!job.converted}
onClick={() =>
@@ -209,16 +196,7 @@ export function JobPayments({
>
{t("menus.header.enterpayment")}
</Button>
<Button
onClick={() =>
setCardPaymentContext({
actions: { refetch },
context: { jobid: job.id, balance },
})
}
>
{t("menus.header.entercardpayment")}
</Button>
<DataLabel
valueStyle={{ color: balance.getAmount() !== 0 ? "red" : "green" }}
label={t("payments.labels.balance")}

View File

@@ -4,16 +4,15 @@ import axios from "axios";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useHistory } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { auth } from "../../firebase/firebase.utils";
import { auth, logImEXEvent } from "../../firebase/firebase.utils";
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
import { UPDATE_JOB } from "../../graphql/jobs.queries";
import {
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
import { useHistory } from "react-router-dom";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -173,6 +172,13 @@ export function JobsCloseExportButton({
});
}
}
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
notification.open({
type: "success",
key: "jobsuccessexport",
message: t("jobs.successes.exported"),
});
}
if (setSelectedJobs) {
setSelectedJobs((selectedJobs) => {
return selectedJobs.filter((i) => i !== jobId);

View File

@@ -143,63 +143,67 @@ export function JobsDetailHeaderActions({
<Menu.Item
disabled={job.status !== bodyshop.md_ro_statuses.default_scheduled}
>
<Popover
trigger="click"
disabled={job.status !== bodyshop.md_ro_statuses.default_scheduled}
content={
<Form
layout="vertical"
onFinish={async ({ lost_sale_reason }) => {
const jobUpdate = await cancelAllAppointments({
variables: {
jobid: job.id,
job: {
date_scheduled: null,
scheduled_in: null,
scheduled_completion: null,
lost_sale_reason,
status: bodyshop.md_ro_statuses.default_imported,
{job.status !== bodyshop.md_ro_statuses.default_scheduled ? (
t("menus.jobsactions.cancelallappointments")
) : (
<Popover
trigger="click"
disabled={job.status !== bodyshop.md_ro_statuses.default_scheduled}
content={
<Form
layout="vertical"
onFinish={async ({ lost_sale_reason }) => {
const jobUpdate = await cancelAllAppointments({
variables: {
jobid: job.id,
job: {
date_scheduled: null,
scheduled_in: null,
scheduled_completion: null,
lost_sale_reason,
status: bodyshop.md_ro_statuses.default_imported,
},
},
},
});
if (!jobUpdate.errors) {
notification["success"]({
message: t("appointments.successes.canceled"),
});
return;
}
}}
>
<Form.Item
name="lost_sale_reason"
label={t("jobs.fields.lost_sale_reason")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
if (!jobUpdate.errors) {
notification["success"]({
message: t("appointments.successes.canceled"),
});
return;
}
}}
>
<Select
options={bodyshop.md_lost_sale_reasons.map((lsr) => ({
label: lsr,
value: lsr,
}))}
/>
</Form.Item>
<Button
htmlType="submit"
disabled={
job.status !== bodyshop.md_ro_statuses.default_scheduled
}
>
{t("appointments.actions.cancel")}
</Button>
</Form>
}
>
{t("menus.jobsactions.cancelallappointments")}
</Popover>
<Form.Item
name="lost_sale_reason"
label={t("jobs.fields.lost_sale_reason")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<Select
options={bodyshop.md_lost_sale_reasons.map((lsr) => ({
label: lsr,
value: lsr,
}))}
/>
</Form.Item>
<Button
htmlType="submit"
disabled={
job.status !== bodyshop.md_ro_statuses.default_scheduled
}
>
{t("appointments.actions.cancel")}
</Button>
</Form>
}
>
{t("menus.jobsactions.cancelallappointments")}
</Popover>
)}
</Menu.Item>
<Menu.Item
disabled={
@@ -245,7 +249,12 @@ export function JobsDetailHeaderActions({
setTimeTicketContext({
actions: {},
context: { jobId: job.id },
context: {
jobId: job.id,
created_by: currentUser.displayName
? currentUser.email.concat(" | ", currentUser.displayName)
: currentUser.email,
},
});
}}
>

View File

@@ -169,14 +169,20 @@ export function JobsExportAllButton({
});
}
}
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
notification.open({
type: "success",
key: "jobsuccessexport",
message: t("jobs.successes.exported"),
});
}
}
})
);
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
if (!!completedCallback) completedCallback([]);
if (!!loadingCallback) loadingCallback(false);
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
setLoading(false);
};

View File

@@ -6,6 +6,7 @@ import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { alphaSort, statusSort } from "../../utils/sorters";
import OwnerDetailUpdateJobsComponent from "../owner-detail-update-jobs/owner-detail-update-jobs.component";
const mapStateToProps = createStructuredSelector({
@@ -15,6 +16,15 @@ const mapStateToProps = createStructuredSelector({
function OwnerDetailJobsComponent({ bodyshop, owner }) {
const { t } = useTranslation();
const [selectedJobs, setSelectedJobs] = useState([]);
const [state, setState] = useState({
sortedInfo: {},
filteredInfo: { text: "" },
});
const handleTableChange = (pagination, filters, sorter) => {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
};
const columns = [
{
title: t("jobs.fields.ro_number"),
@@ -26,6 +36,9 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
{record.ro_number || t("general.labels.na")}
</Link>
),
sorter: (a, b) => alphaSort(a.ro_number, b.ro_number),
sortOrder:
state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order,
},
{
title: t("jobs.fields.vehicle"),
@@ -46,11 +59,17 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
title: t("jobs.fields.clm_no"),
dataIndex: "clm_no",
key: "clm_no",
sorter: (a, b) => alphaSort(a.clm_no, b.clm_no),
sortOrder:
state.sortedInfo.columnKey === "clm_no" && state.sortedInfo.order,
},
{
title: t("jobs.fields.status"),
dataIndex: "status",
key: "status",
sorter: (a, b) => statusSort(a.status, b.status, bodyshop.md_ro_statuses.statuses),
sortOrder:
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
},
{
@@ -60,6 +79,9 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
render: (text, record) => (
<CurrencyFormatter>{record.clm_total}</CurrencyFormatter>
),
sorter: (a, b) => a.clm_total - b.clm_total,
sortOrder:
state.sortedInfo.columnKey === "clm_total" && state.sortedInfo.order,
},
];
@@ -80,6 +102,7 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
scroll={{ x: true }}
rowKey="id"
dataSource={owner.jobs}
onChange={handleTableChange}
rowSelection={{
onSelect: (record, selected, selectedRows) => {
setSelectedJobs(selectedRows ? selectedRows.map((i) => i.id) : []);

View File

@@ -113,6 +113,8 @@ export function PartsOrderListTableComponent({
id: pol.id,
line_desc: pol.line_desc,
quantity: pol.quantity,
act_price: pol.act_price,
oem_partno: pol.oem_partno,
};
}),
},

View File

@@ -79,6 +79,20 @@ export function PartsReceiveModalComponent({ bodyshop, form }) {
>
<Input />
</Form.Item>
<Form.Item
label={t("joblines.fields.oem_partno")}
key={`${index}oem_partno`}
name={[field.name, "oem_partno"]}
>
<Input disabled />
</Form.Item>
<Form.Item
label={t("joblines.fields.act_price")}
key={`${index}act_price`}
name={[field.name, "act_price"]}
>
<Input disabled />
</Form.Item>
<Form.Item
label={t("joblines.fields.location")}
key={`${index}location`}

View File

@@ -1,20 +1,19 @@
import { useMutation } from "@apollo/client";
import { Button, notification } from "antd";
import axios from "axios";
import _ from "lodash";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { auth } from "../../firebase/firebase.utils";
import { auth, logImEXEvent } from "../../firebase/firebase.utils";
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
import { UPDATE_BILLS } from "../../graphql/bills.queries";
import {
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
import { logImEXEvent } from "../../firebase/firebase.utils";
import _ from "lodash";
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
import { Link } from "react-router-dom";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -164,6 +163,13 @@ export function PayableExportAll({
});
}
}
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
notification.open({
type: "success",
key: "billsuccessexport",
message: t("bills.successes.exported"),
});
}
}
})()
);
@@ -173,7 +179,6 @@ export function PayableExportAll({
if (!!completedCallback) completedCallback([]);
if (!!loadingCallback) loadingCallback(false);
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
setLoading(false);
};

View File

@@ -4,16 +4,15 @@ import axios from "axios";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { auth } from "../../firebase/firebase.utils";
import { auth, logImEXEvent } from "../../firebase/firebase.utils";
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
import { UPDATE_BILLS } from "../../graphql/bills.queries";
import {
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
import { Link } from "react-router-dom";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -167,7 +166,13 @@ export function PayableExportButton({
});
}
}
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
notification.open({
type: "success",
key: "billsuccessexport",
message: t("bills.successes.exported"),
});
}
if (setSelectedBills) {
setSelectedBills((selectedBills) => {
@@ -177,6 +182,7 @@ export function PayableExportButton({
}
if (!!loadingCallback) loadingCallback(false);
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
setLoading(false);
};

View File

@@ -172,8 +172,15 @@ export function PaymentExportButton({
});
}
}
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
notification.open({
type: "success",
key: "paymentsuccessexport",
message: t("payments.successes.exported"),
});
}
if (!!loadingCallback) loadingCallback(false);
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
setLoading(false);
};

View File

@@ -25,7 +25,7 @@ export function PaymentsExportAllButton({
disabled,
loadingCallback,
completedCallback,
refetch
refetch,
}) {
const { t } = useTranslation();
const [updatePayments] = useMutation(UPDATE_PAYMENTS);
@@ -150,6 +150,13 @@ export function PaymentsExportAllButton({
});
}
}
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
notification.open({
type: "success",
key: "paymentsuccessexport",
message: t("payments.successes.exported"),
});
}
}
})()
);

View File

@@ -0,0 +1,156 @@
import { CopyFilled } from "@ant-design/icons";
import { Button, Form, Popover, Space, message } from "antd";
import axios from "axios";
import Dinero from "dinero.js";
import { parsePhoneNumber } from "libphonenumber-js";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import {
openChatByPhone,
setMessage,
} from "../../redux/messaging/messaging.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormItemComponent from "../form-items-formatted/currency-form-item.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
openChatByPhone: (phone) => dispatch(openChatByPhone(phone)),
setMessage: (text) => dispatch(setMessage(text)),
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(PaymentsGenerateLink);
export function PaymentsGenerateLink({
bodyshop,
callback,
job,
openChatByPhone,
setMessage,
}) {
const { t } = useTranslation();
const [form] = Form.useForm();
const [visible, setVisible] = useState(false);
const [loading, setLoading] = useState(false);
const [paymentLink, setPaymentLink] = useState(null);
const handleFinish = async ({ amount }) => {
setLoading(true);
const p = parsePhoneNumber(job.ownr_ph1, "CA");
setLoading(true);
const response = await axios.post("/intellipay/generate_payment_url", {
bodyshop,
amount: amount,
account: job.ro_number,
invoice: job.id,
});
setLoading(false);
setPaymentLink(response.data.shorUrl);
openChatByPhone({
phone_num: p.formatInternational(),
jobid: job.id,
});
setMessage(
t("payments.labels.smspaymentreminder", {
shopname: bodyshop.shopname,
amount: amount,
payment_link: response.data.shorUrl,
})
);
//Add in confirmation & errors.
if (callback) callback();
// setVisible(false);
setLoading(false);
};
const popContent = (
<div>
<Form onFinish={handleFinish} layout="vertical" form={form}>
<Form.Item
label={t("payments.fields.amount")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
name="amount"
>
<CurrencyFormItemComponent />
</Form.Item>
{paymentLink && (
<Space direction="vertical">
<Space
style={{ cursor: "pointer" }}
onClick={() => {
navigator.clipboard.writeText(paymentLink);
message.success(t("general.actions.copied"));
}}
>
<div
onClick={() => {
//Copy the link.
}}
>
{paymentLink}
</div>{" "}
<CopyFilled />
</Space>
<Button
onClick={() => {
const p = parsePhoneNumber(job.ownr_ph1, "CA");
openChatByPhone({
phone_num: p.formatInternational(),
jobid: job.id,
});
setMessage(
t("payments.labels.smspaymentreminder", {
shopname: bodyshop.shopname,
amount: Dinero({
amount: Math.round(form.getFieldValue("amount") * 100),
}).toFormat(),
payment_link: paymentLink,
})
);
}}
>
{t("general.actions.sendbysms")}
</Button>
</Space>
)}
</Form>
<Space>
<Button type="primary" onClick={() => form.submit()}>
{t("general.actions.submit")}
</Button>
<Button
onClick={() => {
form.resetFields();
setPaymentLink(null);
setVisible(false);
}}
>
{t("general.actions.cancel")}
</Button>
</Space>
</div>
);
return (
<Popover content={popContent} visible={visible}>
<Button onClick={() => setVisible(true)} loading={loading}>
{t("payments.actions.generatepaymentlink")}
</Button>
</Popover>
);
}

View File

@@ -5,11 +5,13 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { setEmailOptions } from "../../redux/email/email.actions";
import { selectPrintCenter } from "../../redux/modals/modals.selectors";
import { selectTechnician } from "../../redux/tech/tech.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { GenerateDocument } from "../../utils/RenderTemplate";
const mapStateToProps = createStructuredSelector({
printCenterModal: selectPrintCenter,
bodyshop: selectBodyshop,
technician: selectTechnician,
});
const mapDispatchToProps = (dispatch) => ({
setEmailOptions: (e) => dispatch(setEmailOptions(e)),
@@ -22,6 +24,7 @@ export function PrintCenterItemComponent({
id,
bodyshop,
disabled,
technician,
}) {
const [loading, setLoading] = useState(false);
const { context } = printCenterModal;
@@ -44,19 +47,24 @@ export function PrintCenterItemComponent({
<Space wrap>
{item.title}
<PrinterOutlined onClick={renderToNewWindow} />
<MailOutlined
onClick={() => {
GenerateDocument(
{
name: item.key,
variables: { id: id },
},
{ to: context.job && context.job.ownr_ea, subject: item.subject },
"e",
id
);
}}
/>
{!technician ? (
<MailOutlined
onClick={() => {
GenerateDocument(
{
name: item.key,
variables: { id: id },
},
{
to: context.job && context.job.ownr_ea,
subject: item.subject,
},
"e",
id
);
}}
/>
) : null}
{loading && <Spin />}
</Space>
</li>

View File

@@ -1,31 +1,33 @@
import { PrinterFilled } from "@ant-design/icons";
import { useQuery } from "@apollo/client";
import { Descriptions, Drawer, Space, PageHeader, Button } from "antd";
import { Button, Descriptions, Drawer, PageHeader, Space } from "antd";
import queryString from "query-string";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useHistory, useLocation } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { QUERY_JOB_CARD_DETAILS } from "../../graphql/jobs.queries";
import { setModalContext } from "../../redux/modals/modals.actions";
import { selectTechnician } from "../../redux/tech/tech.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateFormatter } from "../../utils/DateFormatter";
import AlertComponent from "../alert/alert.component";
import StartChatButton from "../chat-open-button/chat-open-button.component";
import JobAtChange from "../job-at-change/job-at-change.component";
import JobDetailCardsDocumentsComponent from "../job-detail-cards/job-detail-cards.documents.component";
import JobDetailCardsNotesComponent from "../job-detail-cards/job-detail-cards.notes.component";
import JobDetailCardsPartsComponent from "../job-detail-cards/job-detail-cards.parts.component";
import JobEmployeeAssignments from "../job-employee-assignments/job-employee-assignments.container";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
import ProductionRemoveButton from "../production-remove-button/production-remove-button.component";
import JobAtChange from "../job-at-change/job-at-change.component";
import { PrinterFilled } from "@ant-design/icons";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { setModalContext } from "../../redux/modals/modals.actions";
import ScoreboardAddButton from "../job-scoreboard-add-button/job-scoreboard-add-button.component";
import { selectBodyshop } from "../../redux/user/user.selectors";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import ProductionRemoveButton from "../production-remove-button/production-remove-button.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
technician: selectTechnician,
});
const mapDispatchToProps = (dispatch) => ({
setPrintCenterContext: (context) =>
@@ -40,6 +42,7 @@ export function ProductionListDetail({
bodyshop,
jobs,
setPrintCenterContext,
technician,
}) {
const search = queryString.parse(useLocation().search);
const history = useHistory();
@@ -66,7 +69,9 @@ export function ProductionListDetail({
title={theJob.ro_number}
extra={
<Space wrap>
<ProductionRemoveButton jobId={theJob.id} />{" "}
{!technician ? (
<ProductionRemoveButton jobId={theJob.id} />
) : null}
<Button
onClick={() => {
setPrintCenterContext({
@@ -82,7 +87,9 @@ export function ProductionListDetail({
<PrinterFilled />
{t("jobs.actions.printCenter")}
</Button>
<ScoreboardAddButton job={data ? data.jobs_by_pk : {}} />
{!technician ? (
<ScoreboardAddButton job={data ? data.jobs_by_pk : {}} />
) : null}
</Space>
}
/>

View File

@@ -59,11 +59,12 @@ export function ScheduleManualEvent({ bodyshop, event }) {
refetchQueries: ["QUERY_ALL_ACTIVE_APPOINTMENTS"],
});
}
form.resetFields();
setVisibility(false);
} catch (error) {
console.log(error);
} finally {
setLoading(false);
setVisibility(false);
}
};

View File

@@ -130,7 +130,7 @@ export function TechClockInContainer({
>
{t("timetickets.actions.enter")}
</Button>
<TechJobPrintTickets />
<TechJobPrintTickets attendacePrint={false} />
<Button
type="primary"
onClick={() => form.submit()}

View File

@@ -1,4 +1,4 @@
import { Button, Card, DatePicker, Form, Popover, Space } from "antd";
import { Button, Card, DatePicker, Form, Popover, Radio, Space } from "antd";
import moment from "moment";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
@@ -21,12 +21,13 @@ export default connect(
mapDispatchToProps
)(TechJobPrintTickets);
export function TechJobPrintTickets({ technician, event }) {
export function TechJobPrintTickets({ technician, event, attendacePrint }) {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [form] = Form.useForm();
const [visibility, setVisibility] = useState(false);
const Templates = TemplateList("report_center");
useEffect(() => {
if (visibility && event) {
@@ -44,7 +45,10 @@ export function TechJobPrintTickets({ technician, event }) {
try {
await GenerateDocument(
{
name: TemplateList().timetickets_employee.key,
name:
attendacePrint === true
? Templates.attendance_employee.key
: Templates.timetickets_employee.key,
variables: {
...(start
? { start: moment(start).startOf("day").format("YYYY-MM-DD") }
@@ -60,9 +64,12 @@ export function TechJobPrintTickets({ technician, event }) {
},
{
to: technician.email,
subject: TemplateList().timetickets_employee.subject,
subject:
attendacePrint === true
? Templates.attendance_employee.subject
: Templates.timetickets_employee.subject,
},
"p"
values.sendby // === "email" ? "e" : "p"
);
} catch (error) {
console.log(error);
@@ -92,10 +99,25 @@ export function TechJobPrintTickets({ technician, event }) {
format={"MM/DD/YYYY"}
/>
</Form.Item>
<Form.Item dependencies={["dates"]}>
{() => {
return (
<Form.Item
label={t("general.labels.sendby")}
name="sendby"
initialValue="p"
>
<Radio.Group>
<Radio value="e">{t("general.labels.email")}</Radio>
<Radio value="p">{t("general.labels.print")}</Radio>
</Radio.Group>
</Form.Item>
);
}}
</Form.Item>
<Space wrap>
<Button type="primary" onClick={() => form.submit()}>
{t("general.actions.print")}
{t("reportcenter.actions.generate")}
</Button>
<Button
onClick={() => {
@@ -118,7 +140,7 @@ export function TechJobPrintTickets({ technician, event }) {
return (
<Popover content={overlay} visible={visibility}>
<Button loading={loading} onClick={handleClick}>
{t("general.actions.print")}
{t("general.labels.reports")}
</Button>
</Popover>
);

View File

@@ -4,48 +4,67 @@ import { useTranslation } from "react-i18next";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import DataLabel from "../data-label/data-label.component";
import TechClockOffButton from "../tech-job-clock-out-button/tech-job-clock-out-button.component";
import TechJobPrintTickets from "../tech-job-print-tickets/tech-job-print-tickets.component";
export default function TimeTicketShiftActive({ timetickets, refetch }) {
export default function TimeTicketShiftActive({
timetickets,
refetch,
isTechConsole,
}) {
const { t } = useTranslation();
return (
<div>
{timetickets.length > 0 ? (
<div>
<Typography.Title level={2}>
{t("timetickets.labels.shiftalreadyclockedon")}
</Typography.Title>
<List
grid={{
gutter: 32,
xs: 1,
sm: 2,
md: 3,
lg: 4,
xl: 5,
xxl: 6,
}}
dataSource={timetickets || []}
renderItem={(ticket) => (
<List.Item>
<Card
title={t(ticket.memo)}
actions={[
<TechClockOffButton
jobId={ticket.jobid}
timeTicketId={ticket.id}
completedCallback={refetch}
isShiftTicket
/>,
]}
>
<DataLabel label={t("timetickets.fields.clockon")}>
<DateTimeFormatter>{ticket.clockon}</DateTimeFormatter>
</DataLabel>
</Card>
</List.Item>
)}
></List>
<div
style={{
display: "flex",
justifyContent: "space-between",
flexDirection: "column",
height: "100%",
}}
>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<Typography.Title level={2}>
{t("timetickets.labels.shiftalreadyclockedon")}
</Typography.Title>
{isTechConsole ? (
<TechJobPrintTickets attendacePrint={true} />
) : null}
</div>
<div style={{ flexGrow: 1 }}>
<List
grid={{
gutter: 32,
xs: 1,
sm: 2,
md: 3,
lg: 4,
xl: 5,
xxl: 6,
}}
dataSource={timetickets || []}
renderItem={(ticket) => (
<List.Item>
<Card
title={t(ticket.memo)}
actions={[
<TechClockOffButton
jobId={ticket.jobid}
timeTicketId={ticket.id}
completedCallback={refetch}
isShiftTicket
/>,
]}
>
<DataLabel label={t("timetickets.fields.clockon")}>
<DateTimeFormatter>{ticket.clockon}</DateTimeFormatter>
</DataLabel>
</Card>
</List.Item>
)}
></List>
</div>
</div>
) : null}
</div>

View File

@@ -1,5 +1,5 @@
import { useMutation } from "@apollo/client";
import { Button, Form, notification } from "antd";
import { Button, Form, Space, notification } from "antd";
import axios from "axios";
import moment from "moment";
import React, { useMemo, useState } from "react";
@@ -12,6 +12,7 @@ import {
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
import TechJobPrintTickets from "../tech-job-print-tickets/tech-job-print-tickets.component";
import TimeTicektShiftComponent from "./time-ticket-shift-form.component";
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
@@ -29,6 +30,10 @@ export function TimeTicektShiftContainer({
isTechConsole,
checkIfAlreadyClocked,
}) {
console.log(
"🚀 ~ file: time-ticket-shift-form.container.jsx:28 ~ technician:",
technician
);
const [form] = Form.useForm();
const [insertTimeTicket] = useMutation(INSERT_NEW_TIME_TICKET);
const { t } = useTranslation();
@@ -113,9 +118,14 @@ export function TimeTicektShiftContainer({
initialValues={{ cost_center: t("timetickets.labels.shift") }}
>
<TimeTicektShiftComponent form={form} />
<Button htmlType="submit" loading={loading}>
{t("timetickets.actions.clockin")}
</Button>
<Space wrap>
<Button htmlType="submit" loading={loading} type="primary">
{t("timetickets.actions.clockin")}
</Button>
{isTechConsole === true ? (
<TechJobPrintTickets attendacePrint={true} />
) : null}
</Space>
</Form>
</div>
);

View File

@@ -76,6 +76,7 @@ export function TimeTicketShiftContainer({
<TimeTicketShiftActive
timetickets={data ? data.timetickets : []}
refetch={refetch}
isTechConsole={isTechConsole}
/>
) : (
<TimeTicketShiftFormContainer

View File

@@ -6,8 +6,9 @@ import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import VehicleDetailUpdateJobsComponent from "../vehicle-detail-update-jobs/vehicle-detail-update-jobs.component";
import { alphaSort, statusSort } from "../../utils/sorters";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import VehicleDetailUpdateJobsComponent from "../vehicle-detail-update-jobs/vehicle-detail-update-jobs.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -16,6 +17,14 @@ const mapStateToProps = createStructuredSelector({
export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
const { t } = useTranslation();
const [selectedJobs, setSelectedJobs] = useState([]);
const [state, setState] = useState({
sortedInfo: {},
filteredInfo: { text: "" },
});
const handleTableChange = (pagination, filters, sorter) => {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
};
const columns = [
{
@@ -28,6 +37,9 @@ export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
{record.ro_number || t("general.labels.na")}
</Link>
),
sorter: (a, b) => alphaSort(a.ro_number, b.ro_number),
sortOrder:
state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order,
},
{
title: t("jobs.fields.owner"),
@@ -43,11 +55,17 @@ export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
title: t("jobs.fields.clm_no"),
dataIndex: "clm_no",
key: "clm_no",
sorter: (a, b) => alphaSort(a.clm_no, b.clm_no),
sortOrder:
state.sortedInfo.columnKey === "clm_no" && state.sortedInfo.order,
},
{
title: t("jobs.fields.status"),
dataIndex: "status",
key: "status",
sorter: (a, b) => statusSort(a.status, b.status, bodyshop.md_ro_statuses.statuses),
sortOrder:
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
},
{
@@ -57,6 +75,9 @@ export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
render: (text, record) => (
<CurrencyFormatter>{record.clm_total}</CurrencyFormatter>
),
sorter: (a, b) => a.clm_total - b.clm_total,
sortOrder:
state.sortedInfo.columnKey === "clm_total" && state.sortedInfo.order,
},
];
@@ -76,6 +97,7 @@ export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
rowKey="id"
scroll={{ x: true }}
dataSource={vehicle.jobs}
onChange={handleTableChange}
rowSelection={{
onSelect: (record, selected, selectedRows) => {
setSelectedJobs(selectedRows ? selectedRows.map((i) => i.id) : []);

View File

@@ -757,7 +757,6 @@ export const GET_JOB_BY_PK = gql`
amount
payer
created_at
stripeid
transactionid
memo
date

View File

@@ -69,7 +69,7 @@ export const QUERY_OWNER_BY_ID = gql`
preferred_contact
note
tax_number
jobs {
jobs(order_by: { date_open: desc }) {
id
ro_number
clm_no

View File

@@ -5,6 +5,15 @@ export const INSERT_NEW_PAYMENT = gql`
insert_payments(objects: $paymentInput) {
returning {
id
jobid
amount
payer
created_at
transactionid
memo
date
type
exportedat
}
}
}

View File

@@ -28,11 +28,10 @@ export const QUERY_VEHICLE_BY_ID = gql`
updated_at
trim_color
notes
jobs {
jobs(order_by: { date_open: desc }) {
id
ro_number
ownr_fn
ownr_ln
owner {
id

View File

@@ -1,23 +1,26 @@
import { BackTop, Layout } from "antd";
import React, { lazy, Suspense, useEffect } from "react";
import React, { Suspense, lazy, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Redirect, Route, Switch } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import ErrorBoundary from "../../components/error-boundary/error-boundary.component";
import FeatureWrapper from "../../components/feature-wrapper/feature-wrapper.component";
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
import TechHeader from "../../components/tech-header/tech-header.component";
import TechSider from "../../components/tech-sider/tech-sider.component";
import { selectTechnician } from "../../redux/tech/tech.selectors";
import FeatureWrapper from "../../components/feature-wrapper/feature-wrapper.component";
import "./tech.page.styles.scss";
import TechLookupJobsDrawer from "../../components/tech-lookup-jobs-drawer/tech-lookup-jobs-drawer.component";
import TechSider from "../../components/tech-sider/tech-sider.component";
import UpdateAlert from "../../components/update-alert/update-alert.component";
import { selectTechnician } from "../../redux/tech/tech.selectors";
import "./tech.page.styles.scss";
import "./tech.page.styles.scss";
const TimeTicketModalContainer = lazy(() =>
import("../../components/time-ticket-modal/time-ticket-modal.container")
);
const EmailOverlayContainer = lazy(() =>
import("../../components/email-overlay/email-overlay.container.jsx")
);
const PrintCenterModalContainer = lazy(() =>
import("../../components/print-center-modal/print-center-modal.container")
);
@@ -44,7 +47,8 @@ const TimeTicketModalTask = lazy(() =>
);
const TechAssignedProdJobs = lazy(() =>
import("../tech-assigned-prod-jobs/tech-assigned-prod-jobs.component")
);const TechDispatchedParts = lazy(() =>
);
const TechDispatchedParts = lazy(() =>
import("../tech-dispatched-parts/tech-dispatched-parts.page")
);
@@ -81,6 +85,7 @@ export function TechPage({ technician, match }) {
>
<FeatureWrapper featureName="tech-console">
<TimeTicketModalContainer />
<EmailOverlayContainer />
<PrintCenterModalContainer />
<TimeTicketModalTask />
<Switch>

View File

@@ -1020,6 +1020,7 @@
"cancel": "Cancel",
"clear": "Clear",
"close": "Close",
"copied": "Copied!",
"copylink": "Copy Link",
"create": "Create",
"delete": "Delete",
@@ -1036,6 +1037,7 @@
"saveandnew": "Save and New",
"selectall": "Select All",
"send": "Send",
"sendbysms": "Send by SMS",
"senderrortosupport": "Send Error to Support",
"submit": "Submit",
"tryagain": "Try Again",
@@ -1097,6 +1099,7 @@
"passwordsdonotmatch": "The passwords you have entered do not match.",
"print": "Print",
"refresh": "Refresh",
"reports": "Reports",
"required": "Required",
"saturday": "Saturday",
"search": "Search...",
@@ -1196,24 +1199,25 @@
},
"job_payments": {
"buttons": {
"goback": "Cancel",
"goback": "Go Back",
"proceedtopayment": "Proceed to Payment",
"refundpayment": "Refund Payment"
},
"notifications": {
"error": {
"description": "Please try again. Make sure the refund amount does not exceeds the payment amount.",
"title": "Error Refunding Payment"
"openingip": "Error connecting to IntelliPay service.",
"title": "Error placing refund"
}
},
"titles": {
"amount": "Amount",
"dateOfPayment": "Date",
"descriptions": "Description",
"dateOfPayment": "Date of Payment",
"descriptions": "Payment Details",
"payer": "Payer",
"payername": "Payer Name",
"paymentid": "Payment ID",
"paymenttype": "Type",
"paymentid": "Payment Reference ID",
"paymenttype": "Payment Type",
"refundamount": "Refund Amount",
"transactionid": "Transaction ID"
}
@@ -1934,7 +1938,7 @@
"customers": "Customers",
"dashboard": "Dashboard",
"enterbills": "Enter Bills",
"entercardpayment": "Enter Card Payments",
"entercardpayment": "New Card Charge",
"enterpayment": "Enter Payments",
"entertimeticket": "Enter Time Tickets",
"export": "Export",
@@ -1946,7 +1950,6 @@
"newjob": "Create New Job",
"owners": "Owners",
"parts-queue": "Parts Queue",
"paymentremindersms": "Send Payment Reminder via SMS",
"phonebook": "Phonebook",
"productionboard": "Production Board - Visual",
"productionlist": "Production Board - List",
@@ -2232,6 +2235,9 @@
}
},
"payments": {
"actions": {
"generatepaymentlink": "Generate Payment Link"
},
"errors": {
"exporting": "Error exporting payment(s). {{error}}",
"exporting-partner": "Error exporting to partner. Please check the partner interaction log for more errors."
@@ -2261,6 +2267,7 @@
"markforreexport": "Mark for Re-export",
"new": "New Payment",
"signup": "Please contact support to sign up for electronic payments.",
"smspaymentreminder": "This is {{shopname}} reminding you about your balance of {{amount}}. To pay, click the following link {{payment_link}}.",
"title": "Payments",
"totalpayments": "Total Payments"
},

View File

@@ -63,7 +63,6 @@
"scheduledfor": "Cita programada para:",
"severalerrorsfound": "",
"smartscheduling": "",
"smspaymentreminder": "",
"suggesteddates": ""
},
"successes": {
@@ -1020,6 +1019,7 @@
"cancel": "",
"clear": "",
"close": "",
"copied": "",
"copylink": "",
"create": "",
"delete": "Borrar",
@@ -1036,6 +1036,7 @@
"saveandnew": "",
"selectall": "",
"send": "",
"sendbysms": "",
"senderrortosupport": "",
"submit": "",
"tryagain": "",
@@ -1097,6 +1098,7 @@
"passwordsdonotmatch": "",
"print": "",
"refresh": "",
"reports": "",
"required": "",
"saturday": "",
"search": "Buscar...",
@@ -1203,6 +1205,7 @@
"notifications": {
"error": {
"description": "",
"openingip": "",
"title": ""
}
},
@@ -1946,7 +1949,6 @@
"newjob": "",
"owners": "propietarios",
"parts-queue": "",
"paymentremindersms": "",
"phonebook": "",
"productionboard": "",
"productionlist": "",
@@ -2232,6 +2234,9 @@
}
},
"payments": {
"actions": {
"generatepaymentlink": ""
},
"errors": {
"exporting": "",
"exporting-partner": ""
@@ -2261,6 +2266,7 @@
"markforreexport": "",
"new": "",
"signup": "",
"smspaymentreminder": "",
"title": "",
"totalpayments": ""
},

View File

@@ -63,7 +63,6 @@
"scheduledfor": "Rendez-vous prévu pour:",
"severalerrorsfound": "",
"smartscheduling": "",
"smspaymentreminder": "",
"suggesteddates": ""
},
"successes": {
@@ -1020,6 +1019,7 @@
"cancel": "",
"clear": "",
"close": "",
"copied": "",
"copylink": "",
"create": "",
"delete": "Effacer",
@@ -1036,6 +1036,7 @@
"saveandnew": "",
"selectall": "",
"send": "",
"sendbysms": "",
"senderrortosupport": "",
"submit": "",
"tryagain": "",
@@ -1097,6 +1098,7 @@
"passwordsdonotmatch": "",
"print": "",
"refresh": "",
"reports": "",
"required": "",
"saturday": "",
"search": "Chercher...",
@@ -1203,6 +1205,7 @@
"notifications": {
"error": {
"description": "",
"openingip": "",
"title": ""
}
},
@@ -1946,7 +1949,6 @@
"newjob": "",
"owners": "Propriétaires",
"parts-queue": "",
"paymentremindersms": "",
"phonebook": "",
"productionboard": "",
"productionlist": "",
@@ -2232,6 +2234,9 @@
}
},
"payments": {
"actions": {
"generatepaymentlink": ""
},
"errors": {
"exporting": "",
"exporting-partner": ""
@@ -2261,6 +2266,7 @@
"markforreexport": "",
"new": "",
"signup": "",
"smspaymentreminder": "",
"title": "",
"totalpayments": ""
},

11095
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -17,6 +17,7 @@
"start": "node server.js"
},
"dependencies": {
"@aws-sdk/client-secrets-manager": "^3.388.0",
"@aws-sdk/credential-provider-node": "^3.319.0",
"@opensearch-project/opensearch": "^2.2.1",
"aws-sdk": "^2.1326.0",

View File

@@ -643,6 +643,7 @@ async function InsertAccountPostingData(socket) {
wips.push(item);
});
socket.transWips = wips;
const { data: AccountPostingChange } = await axios.post(
PBS_ENDPOINTS.AccountingPostingChange,
@@ -697,6 +698,7 @@ async function MarkJobExported(socket, jobid) {
jobid: jobid,
successful: true,
useremail: socket.user.email,
metadata: socket.transWips,
},
bill: {
exported: true,

View File

@@ -992,6 +992,7 @@ exports.GET_JOB_BY_PK = `query GET_JOB_BY_PK($id: uuid!) {
ins_ph1
est_co_nm
est_ct_fn
shopid
est_ct_ln
vehicle{
id

View File

@@ -4,6 +4,9 @@ const queries = require("../graphql-client/queries");
const Dinero = require("dinero.js");
const qs = require("query-string");
const axios = require("axios");
const moment = require("moment");
const logger = require("../utils/logger");
require("dotenv").config({
path: path.resolve(
process.cwd(),
@@ -12,7 +15,15 @@ require("dotenv").config({
});
const domain = process.env.NODE_ENV ? "secure" : "test";
const SecretsManager = require("./aws-secrets-manager");
const {
SecretsManagerClient,
GetSecretValueCommand,
} = require("@aws-sdk/client-secrets-manager");
const client = new SecretsManagerClient({
region: "ca-central-1",
});
const gqlClient = require("../graphql-client/graphql-client").client;
@@ -20,38 +31,55 @@ const getShopCredentials = async (bodyshop) => {
// Development only
if (process.env.NODE_ENV === undefined) {
return {
merchantkey: process.env.DEV_INTELLIPAY_MERCHANTKEY,
apikey: process.env.DEV_INTELLIPAY_APIKEY,
merchantkey: process.env.INTELLIPAY_MERCHANTKEY,
apikey: process.env.INTELLIPAY_APIKEY,
};
}
// Production code
if (bodyshop?.imexshopid) {
const secret = await SecretsManager.getSecret(
`intellipay-credentials-${bodyshop.imexshopid}`,
process.env.REGION
);
return JSON.parse(secret);
try {
const secret = await client.send(
new GetSecretValueCommand({
SecretId: `intellipay-credentials-${bodyshop.imexshopid}`,
VersionStage: "AWSCURRENT", // VersionStage defaults to AWSCURRENT if unspecified
})
);
return JSON.parse(secret.SecretString);
} catch (error) {
return {
error: error.message,
};
}
}
};
exports.lightbox_credentials = async (req, res) => {
logger.log(
"intellipay-lightbox-credentials",
"DEBUG",
req.user?.email,
null,
null
);
const shopCredentials = await getShopCredentials(req.body.bodyshop);
if (shopCredentials.error) {
res.json(shopCredentials);
return;
}
try {
const options = {
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" },
//TODO: Move these to environment variables/database.
data: qs.stringify({
...shopCredentials,
operatingenv:
process.env.NODE_ENV === undefined
? process.env.NODE_ENV
: "businessattended",
operatingenv: "businessattended",
}),
url: `https://${domain}.cpteller.com/api/custapi.cfc?method=autoterminal`,
url: `https://${domain}.cpteller.com/api/custapi.cfc?method=autoterminal${
req.body.refresh ? "_refresh" : ""
}`, //autoterminal_refresh
};
const response = await axios(options);
@@ -59,11 +87,20 @@ exports.lightbox_credentials = async (req, res) => {
res.send(response.data);
} catch (error) {
console.log(error);
logger.log(
"intellipay-lightbox-credentials-error",
"ERROR",
req.user?.email,
null,
{ error: JSON.stringify(error) }
);
res.json({ error });
}
};
exports.payment_refund = async (req, res) => {
logger.log("intellipay-refund", "DEBUG", req.user?.email, null, null);
const shopCredentials = await getShopCredentials(req.body.bodyshop);
try {
@@ -85,11 +122,15 @@ exports.payment_refund = async (req, res) => {
res.send(response.data);
} catch (error) {
console.log(error);
logger.log("intellipay-refund-error", "ERROR", req.user?.email, null, {
error: JSON.stringify(error),
});
res.json({ error });
}
};
exports.generate_payment_url = async (req, res) => {
logger.log("intellipay-payment-url", "DEBUG", req.user?.email, null, null);
const shopCredentials = await getShopCredentials(req.body.bodyshop);
try {
const options = {
@@ -100,6 +141,7 @@ exports.generate_payment_url = async (req, res) => {
...shopCredentials,
...req.body,
createshorturl: true,
//The postback URL is set at the CP teller global terminal settings page.
}),
url: `https://${domain}.cpteller.com/api/custapi.cfc?method=generate_lightbox_url`,
};
@@ -109,76 +151,58 @@ exports.generate_payment_url = async (req, res) => {
res.send(response.data);
} catch (error) {
console.log(error);
logger.log("intellipay-payment-url-error", "ERROR", req.user?.email, null, {
error: JSON.stringify(error),
});
res.json({ error });
}
};
exports.postback = async (req, res) => {
console.log("postback as", req.body);
logger.log("intellipay-postback", "ERROR", req.user?.email, null, req.body);
const { body: values } = req;
if (!values.invoice) {
res.sendStatus(200);
return;
}
// TODO query job by account name
const job = await gqlClient.request(queries.GET_JOB_BY_RO_NUMBER, {
ro_number: values.account,
const job = await gqlClient.request(queries.GET_JOB_BY_PK, {
id: values.invoice,
});
// TODO add mutation to database
const paymentResult = await gqlClient.request(queries.INSERT_NEW_PAYMENT, {
paymentInput: {
amount: values.total,
transactionid: `C00 ${values.authcode}`,
payer: "Customer",
type: values.cardtype,
jobid: job.jobs[0].id,
date: moment(Date.now()),
},
});
try {
const paymentResult = await gqlClient.request(queries.INSERT_NEW_PAYMENT, {
paymentInput: {
amount: values.total,
transactionid: `C00 ${values.authcode}`,
payer: "Customer",
type: values.cardtype,
jobid: values.invoice,
date: moment(Date.now()),
},
});
await gqlClient.request(queries.INSERT_PAYMENT_RESPONSE, {
paymentResponse: {
amount: values.total,
bodyshopid: job.jobs[0].bodyshop.id,
paymentid: paymentResult.id,
jobid: job.jobs[0].id,
declinereason: "Approved",
ext_paymentid: values.paymentid,
successful: true,
response: values,
},
});
await gqlClient.request(queries.INSERT_PAYMENT_RESPONSE, {
paymentResponse: {
amount: values.total,
bodyshopid: job.jobs_by_pk.shopid,
paymentid: paymentResult.id,
jobid: values.invoice,
declinereason: "Approved",
ext_paymentid: values.paymentid,
successful: true,
response: values,
},
});
res.send({ message: "Postback Successful" });
res.send({ message: "Postback Successful" });
} catch (error) {
logger.log("intellipay-postback-error", "ERROR", req.user?.email, null, {
error: JSON.stringify(error),
body: req.body,
});
res.status(400).json({ succesful: false, error: error.message });
}
};
`{
ipaddress: '136.158.34.242',
firstname: 'JC',
notes: '',
city: '',
fee: ' 0.00',
origin: 'OneLink',
total: '5061.36',
avsdata: 'N',
arglist: '""',
state: ' ',
cardtype: 'Visa',
department: '',
email: '',
timestamp: "{ts '2023-03-23 09:52:23'}",
op: 'Kh6Pa6AT9keg',
amount: '5061.36',
method: 'CARD',
address2: '',
address1: '',
lastname: 'Tolentino',
zipcode: '1742 ',
authcode: '367885',
phone: '',
merchantid: '7114',
paymentid: '24205435',
customerid: '19610104',
comment: '',
invoice: '',
account: 'QBD241'
}`;

703
yarn.lock
View File

@@ -2,6 +2,15 @@
# yarn lockfile v1
"@aws-crypto/crc32@3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-3.0.0.tgz#07300eca214409c33e3ff769cd5697b57fdd38fa"
integrity sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==
dependencies:
"@aws-crypto/util" "^3.0.0"
"@aws-sdk/types" "^3.222.0"
tslib "^1.11.1"
"@aws-crypto/ie11-detection@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz#640ae66b4ec3395cee6a8e94ebcd9f80c24cd688"
@@ -56,6 +65,49 @@
"@aws-sdk/types" "3.310.0"
tslib "^2.5.0"
"@aws-sdk/client-secrets-manager@^3.388.0":
version "3.388.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.388.0.tgz#284429ebc9376a167c3197075a848ea00b49bea9"
integrity sha512-XOf7FXz2Xn6tbykx/79rDLWysMLX5hQNciuCdbaHhKiflyTSYFNOpe5NQoq7jTzA64NW4dUxJUNwsBdo5M/i3g==
dependencies:
"@aws-crypto/sha256-browser" "3.0.0"
"@aws-crypto/sha256-js" "3.0.0"
"@aws-sdk/client-sts" "3.388.0"
"@aws-sdk/credential-provider-node" "3.388.0"
"@aws-sdk/middleware-host-header" "3.387.0"
"@aws-sdk/middleware-logger" "3.387.0"
"@aws-sdk/middleware-recursion-detection" "3.387.0"
"@aws-sdk/middleware-signing" "3.387.0"
"@aws-sdk/middleware-user-agent" "3.387.0"
"@aws-sdk/types" "3.387.0"
"@aws-sdk/util-endpoints" "3.387.0"
"@aws-sdk/util-user-agent-browser" "3.387.0"
"@aws-sdk/util-user-agent-node" "3.387.0"
"@smithy/config-resolver" "^2.0.2"
"@smithy/fetch-http-handler" "^2.0.2"
"@smithy/hash-node" "^2.0.2"
"@smithy/invalid-dependency" "^2.0.2"
"@smithy/middleware-content-length" "^2.0.2"
"@smithy/middleware-endpoint" "^2.0.2"
"@smithy/middleware-retry" "^2.0.2"
"@smithy/middleware-serde" "^2.0.2"
"@smithy/middleware-stack" "^2.0.0"
"@smithy/node-config-provider" "^2.0.2"
"@smithy/node-http-handler" "^2.0.2"
"@smithy/protocol-http" "^2.0.2"
"@smithy/smithy-client" "^2.0.2"
"@smithy/types" "^2.1.0"
"@smithy/url-parser" "^2.0.2"
"@smithy/util-base64" "^2.0.0"
"@smithy/util-body-length-browser" "^2.0.0"
"@smithy/util-body-length-node" "^2.0.0"
"@smithy/util-defaults-mode-browser" "^2.0.2"
"@smithy/util-defaults-mode-node" "^2.0.2"
"@smithy/util-retry" "^2.0.0"
"@smithy/util-utf8" "^2.0.0"
tslib "^2.5.0"
uuid "^8.3.2"
"@aws-sdk/client-sso-oidc@3.319.0":
version "3.319.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.319.0.tgz#d9c1045ac3e1c55b719590f2a47e825a803fd6ed"
@@ -132,6 +184,88 @@
"@aws-sdk/util-utf8" "3.310.0"
tslib "^2.5.0"
"@aws-sdk/client-sso@3.387.0":
version "3.387.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.387.0.tgz#d2182c09ad8d75a1a8896c2765e6f8729118660f"
integrity sha512-E7uKSvbA0XMKSN5KLInf52hmMpe9/OKo6N9OPffGXdn3fNEQlvyQq3meUkqG7Is0ldgsQMz5EUBNtNybXzr3tQ==
dependencies:
"@aws-crypto/sha256-browser" "3.0.0"
"@aws-crypto/sha256-js" "3.0.0"
"@aws-sdk/middleware-host-header" "3.387.0"
"@aws-sdk/middleware-logger" "3.387.0"
"@aws-sdk/middleware-recursion-detection" "3.387.0"
"@aws-sdk/middleware-user-agent" "3.387.0"
"@aws-sdk/types" "3.387.0"
"@aws-sdk/util-endpoints" "3.387.0"
"@aws-sdk/util-user-agent-browser" "3.387.0"
"@aws-sdk/util-user-agent-node" "3.387.0"
"@smithy/config-resolver" "^2.0.2"
"@smithy/fetch-http-handler" "^2.0.2"
"@smithy/hash-node" "^2.0.2"
"@smithy/invalid-dependency" "^2.0.2"
"@smithy/middleware-content-length" "^2.0.2"
"@smithy/middleware-endpoint" "^2.0.2"
"@smithy/middleware-retry" "^2.0.2"
"@smithy/middleware-serde" "^2.0.2"
"@smithy/middleware-stack" "^2.0.0"
"@smithy/node-config-provider" "^2.0.2"
"@smithy/node-http-handler" "^2.0.2"
"@smithy/protocol-http" "^2.0.2"
"@smithy/smithy-client" "^2.0.2"
"@smithy/types" "^2.1.0"
"@smithy/url-parser" "^2.0.2"
"@smithy/util-base64" "^2.0.0"
"@smithy/util-body-length-browser" "^2.0.0"
"@smithy/util-body-length-node" "^2.0.0"
"@smithy/util-defaults-mode-browser" "^2.0.2"
"@smithy/util-defaults-mode-node" "^2.0.2"
"@smithy/util-retry" "^2.0.0"
"@smithy/util-utf8" "^2.0.0"
tslib "^2.5.0"
"@aws-sdk/client-sts@3.388.0":
version "3.388.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.388.0.tgz#df4363f89de34bd02533056fc335ec8e785f788c"
integrity sha512-y9FAcAYHT8O6T/jqhgsIQUb4gLiSTKD3xtzudDvjmFi8gl0oRIY1npbeckSiK6k07VQugm2s64I0nDnDxtWsBg==
dependencies:
"@aws-crypto/sha256-browser" "3.0.0"
"@aws-crypto/sha256-js" "3.0.0"
"@aws-sdk/credential-provider-node" "3.388.0"
"@aws-sdk/middleware-host-header" "3.387.0"
"@aws-sdk/middleware-logger" "3.387.0"
"@aws-sdk/middleware-recursion-detection" "3.387.0"
"@aws-sdk/middleware-sdk-sts" "3.387.0"
"@aws-sdk/middleware-signing" "3.387.0"
"@aws-sdk/middleware-user-agent" "3.387.0"
"@aws-sdk/types" "3.387.0"
"@aws-sdk/util-endpoints" "3.387.0"
"@aws-sdk/util-user-agent-browser" "3.387.0"
"@aws-sdk/util-user-agent-node" "3.387.0"
"@smithy/config-resolver" "^2.0.2"
"@smithy/fetch-http-handler" "^2.0.2"
"@smithy/hash-node" "^2.0.2"
"@smithy/invalid-dependency" "^2.0.2"
"@smithy/middleware-content-length" "^2.0.2"
"@smithy/middleware-endpoint" "^2.0.2"
"@smithy/middleware-retry" "^2.0.2"
"@smithy/middleware-serde" "^2.0.2"
"@smithy/middleware-stack" "^2.0.0"
"@smithy/node-config-provider" "^2.0.2"
"@smithy/node-http-handler" "^2.0.2"
"@smithy/protocol-http" "^2.0.2"
"@smithy/smithy-client" "^2.0.2"
"@smithy/types" "^2.1.0"
"@smithy/url-parser" "^2.0.2"
"@smithy/util-base64" "^2.0.0"
"@smithy/util-body-length-browser" "^2.0.0"
"@smithy/util-body-length-node" "^2.0.0"
"@smithy/util-defaults-mode-browser" "^2.0.2"
"@smithy/util-defaults-mode-node" "^2.0.2"
"@smithy/util-retry" "^2.0.0"
"@smithy/util-utf8" "^2.0.0"
fast-xml-parser "4.2.5"
tslib "^2.5.0"
"@aws-sdk/config-resolver@3.310.0":
version "3.310.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.310.0.tgz#c02dce96546d5cd25551bc89907b27224e16ca7f"
@@ -151,6 +285,16 @@
"@aws-sdk/types" "3.310.0"
tslib "^2.5.0"
"@aws-sdk/credential-provider-env@3.387.0":
version "3.387.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.387.0.tgz#7323eada10228c0157195a922d10638cd65c293c"
integrity sha512-PVqNk7XPIYe5CMYNvELkcALtkl/pIM8/uPtqEtTg+mgnZBeL4fAmgXZiZMahQo1DxP5t/JaK384f6JG+A0qDjA==
dependencies:
"@aws-sdk/types" "3.387.0"
"@smithy/property-provider" "^2.0.0"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@aws-sdk/credential-provider-imds@3.310.0":
version "3.310.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.310.0.tgz#d8fb1223fee7e289a81e28177fe55dedf4d2745e"
@@ -177,6 +321,39 @@
"@aws-sdk/types" "3.310.0"
tslib "^2.5.0"
"@aws-sdk/credential-provider-ini@3.388.0":
version "3.388.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.388.0.tgz#284b6dd2da4f3f8f53b2fa1838085148a478b936"
integrity sha512-3dg3A8AiZ5vXkSAYyyI3V/AW3Eo6KQJyE/glA+Nr2M0oAjT4z3vHhS3pf2B+hfKGZBTuKKgxusrrhrQABd/Diw==
dependencies:
"@aws-sdk/credential-provider-env" "3.387.0"
"@aws-sdk/credential-provider-process" "3.387.0"
"@aws-sdk/credential-provider-sso" "3.388.0"
"@aws-sdk/credential-provider-web-identity" "3.387.0"
"@aws-sdk/types" "3.387.0"
"@smithy/credential-provider-imds" "^2.0.0"
"@smithy/property-provider" "^2.0.0"
"@smithy/shared-ini-file-loader" "^2.0.0"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@aws-sdk/credential-provider-node@3.388.0":
version "3.388.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.388.0.tgz#4c1599e2fdd94cff61f1d5568cade8e595cf4da2"
integrity sha512-BqWAkIG08gj/wevpesaZhAjALjfUNVjseHQRk+DNUoHIfyibW7Ahf3q/GIPs11dA2o8ECwR9/fo68Sq+sK799A==
dependencies:
"@aws-sdk/credential-provider-env" "3.387.0"
"@aws-sdk/credential-provider-ini" "3.388.0"
"@aws-sdk/credential-provider-process" "3.387.0"
"@aws-sdk/credential-provider-sso" "3.388.0"
"@aws-sdk/credential-provider-web-identity" "3.387.0"
"@aws-sdk/types" "3.387.0"
"@smithy/credential-provider-imds" "^2.0.0"
"@smithy/property-provider" "^2.0.0"
"@smithy/shared-ini-file-loader" "^2.0.0"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@aws-sdk/credential-provider-node@^3.319.0":
version "3.319.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.319.0.tgz#51c8cd9d676d5b3ef80e88282fc1925946b1aaaf"
@@ -203,6 +380,17 @@
"@aws-sdk/types" "3.310.0"
tslib "^2.5.0"
"@aws-sdk/credential-provider-process@3.387.0":
version "3.387.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.387.0.tgz#114acfbcf9bd289e549fb3fd48acc1a71d7c75b7"
integrity sha512-tQScLHmDlqkQN+mqw4s3cxepEUeHYDhFl5eH+J8puvPqWjXMYpCEdY79SAtWs6SZd4CWiZ0VLeYU6xQBZengbQ==
dependencies:
"@aws-sdk/types" "3.387.0"
"@smithy/property-provider" "^2.0.0"
"@smithy/shared-ini-file-loader" "^2.0.0"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@aws-sdk/credential-provider-sso@3.319.0":
version "3.319.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.319.0.tgz#c7bbea82e28bfbbafdb7d729239464c7ae38f7d0"
@@ -215,6 +403,19 @@
"@aws-sdk/types" "3.310.0"
tslib "^2.5.0"
"@aws-sdk/credential-provider-sso@3.388.0":
version "3.388.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.388.0.tgz#39868ebd160d24348287c8a8e57908f6a5d86046"
integrity sha512-RH02+rntaO0UhnSBr42n+7q8HOztc+Dets/hh6cWovf3Yi9s9ghLgYLN9FXpSosfot3XkmT/HOCa+CphAmGN9A==
dependencies:
"@aws-sdk/client-sso" "3.387.0"
"@aws-sdk/token-providers" "3.388.0"
"@aws-sdk/types" "3.387.0"
"@smithy/property-provider" "^2.0.0"
"@smithy/shared-ini-file-loader" "^2.0.0"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@aws-sdk/credential-provider-web-identity@3.310.0":
version "3.310.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.310.0.tgz#c9fa09b0068027e58d31178e3fa06bf4e9ae9d36"
@@ -224,6 +425,16 @@
"@aws-sdk/types" "3.310.0"
tslib "^2.5.0"
"@aws-sdk/credential-provider-web-identity@3.387.0":
version "3.387.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.387.0.tgz#f15431ce00dbfe4f937b4afc706254759a096396"
integrity sha512-6ueMPl+J3KWv6ZaAWF4Z138QCuBVFZRVAgwbtP3BNqWrrs4Q6TPksOQJ79lRDMpv0EUoyVl04B6lldNlhN8RdA==
dependencies:
"@aws-sdk/types" "3.387.0"
"@smithy/property-provider" "^2.0.0"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@aws-sdk/fetch-http-handler@3.310.0":
version "3.310.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.310.0.tgz#f31006b7b3103683d72e177cd27d80354f7a37c4"
@@ -289,6 +500,16 @@
"@aws-sdk/types" "3.310.0"
tslib "^2.5.0"
"@aws-sdk/middleware-host-header@3.387.0":
version "3.387.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.387.0.tgz#17c4948b83bb42ed04bdc2346fce4e4f980691e5"
integrity sha512-EWm9PXSr8dSp7hnRth1U7OfelXQp9dLf1yS1kUL+UhppYDJpjhdP7ql3NI4xJKw8e76sP2FuJYEuzWnJHuWoyQ==
dependencies:
"@aws-sdk/types" "3.387.0"
"@smithy/protocol-http" "^2.0.2"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@aws-sdk/middleware-logger@3.310.0":
version "3.310.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.310.0.tgz#8cc6381f49ef867cae1364b8517f939629e4dd9d"
@@ -297,6 +518,15 @@
"@aws-sdk/types" "3.310.0"
tslib "^2.5.0"
"@aws-sdk/middleware-logger@3.387.0":
version "3.387.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.387.0.tgz#bbc05eb087989d6addecc58f1baeb39334851e6e"
integrity sha512-FjAvJr1XyaInT81RxUwgifnbXoFJrRBFc64XeFJgFanGIQCWLYxRrK2HV9eBpao/AycbmuoHgLd/f0sa4hZFoQ==
dependencies:
"@aws-sdk/types" "3.387.0"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@aws-sdk/middleware-recursion-detection@3.310.0":
version "3.310.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.310.0.tgz#020c986ed8da751bd613fd84c8c8a805c89e0952"
@@ -306,6 +536,16 @@
"@aws-sdk/types" "3.310.0"
tslib "^2.5.0"
"@aws-sdk/middleware-recursion-detection@3.387.0":
version "3.387.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.387.0.tgz#34beba7dc436dcf13065f5ad99cc239f2f6175b9"
integrity sha512-ZF45T785ru8OwvYZw6awD9Z76OwSMM1eZzj2eY+FDz1cHfkpLjxEiti2iIH1FxbyK7n9ZqDUx29lVlCv238YyQ==
dependencies:
"@aws-sdk/types" "3.387.0"
"@smithy/protocol-http" "^2.0.2"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@aws-sdk/middleware-retry@3.310.0":
version "3.310.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-retry/-/middleware-retry-3.310.0.tgz#12e95e962875d44af4acbdebe02db337a1ad5c35"
@@ -319,6 +559,16 @@
tslib "^2.5.0"
uuid "^8.3.2"
"@aws-sdk/middleware-sdk-sts@3.387.0":
version "3.387.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.387.0.tgz#6bd1e4eb17acc7387fa4231da52378ef77e10b1b"
integrity sha512-7ZzRKOJ4V/JDQmKz9z+FjZqw59mrMATEMLR6ff0H0JHMX0Uk5IX8TQB058ss+ar14qeJ4UcteYzCqHNI0O1BHw==
dependencies:
"@aws-sdk/middleware-signing" "3.387.0"
"@aws-sdk/types" "3.387.0"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@aws-sdk/middleware-serde@3.310.0":
version "3.310.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-serde/-/middleware-serde-3.310.0.tgz#e334031b66a1a155375ec901478b26570fbe1783"
@@ -327,6 +577,19 @@
"@aws-sdk/types" "3.310.0"
tslib "^2.5.0"
"@aws-sdk/middleware-signing@3.387.0":
version "3.387.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.387.0.tgz#74bf5a9cf35239b5745a384a9d8f6f92afbd8328"
integrity sha512-oJXlE0MES8gxNLo137PPNNiOICQGOaETTvq3kBSJgb/gtEAxQajMIlaNT7s1wsjOAruFHt4975nCXuY4lpx7GQ==
dependencies:
"@aws-sdk/types" "3.387.0"
"@smithy/property-provider" "^2.0.0"
"@smithy/protocol-http" "^2.0.2"
"@smithy/signature-v4" "^2.0.0"
"@smithy/types" "^2.1.0"
"@smithy/util-middleware" "^2.0.0"
tslib "^2.5.0"
"@aws-sdk/middleware-stack@3.310.0":
version "3.310.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-stack/-/middleware-stack-3.310.0.tgz#06c83963998fbdc83e99b67a7a138529312a6224"
@@ -344,6 +607,17 @@
"@aws-sdk/util-endpoints" "3.319.0"
tslib "^2.5.0"
"@aws-sdk/middleware-user-agent@3.387.0":
version "3.387.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.387.0.tgz#aa5f9eb4f3cb4d6e0df879d8d84ccaf4f8baf8e5"
integrity sha512-hTfFTwDtp86xS98BKa+RFuLfcvGftxwzrbZeisZV8hdb4ZhvNXjSxnvM3vetW0GUEnY9xHPSGyp2ERRTinPKFQ==
dependencies:
"@aws-sdk/types" "3.387.0"
"@aws-sdk/util-endpoints" "3.387.0"
"@smithy/protocol-http" "^2.0.2"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@aws-sdk/node-config-provider@3.310.0":
version "3.310.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.310.0.tgz#ba8fb41af2db0316291ba9002267627553ec65ac"
@@ -431,6 +705,47 @@
"@aws-sdk/types" "3.310.0"
tslib "^2.5.0"
"@aws-sdk/token-providers@3.388.0":
version "3.388.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.388.0.tgz#50000f5ca32b58614542a6e25918bc32585535cb"
integrity sha512-2lo1gFJl624kfjo/YdU6zW+k6dEwhoqjNkDNbOZEFgS1KDofHe9GX8W4/ReKb0Ggho5/EcjzZ53/1CjkzUq4tA==
dependencies:
"@aws-crypto/sha256-browser" "3.0.0"
"@aws-crypto/sha256-js" "3.0.0"
"@aws-sdk/middleware-host-header" "3.387.0"
"@aws-sdk/middleware-logger" "3.387.0"
"@aws-sdk/middleware-recursion-detection" "3.387.0"
"@aws-sdk/middleware-user-agent" "3.387.0"
"@aws-sdk/types" "3.387.0"
"@aws-sdk/util-endpoints" "3.387.0"
"@aws-sdk/util-user-agent-browser" "3.387.0"
"@aws-sdk/util-user-agent-node" "3.387.0"
"@smithy/config-resolver" "^2.0.2"
"@smithy/fetch-http-handler" "^2.0.2"
"@smithy/hash-node" "^2.0.2"
"@smithy/invalid-dependency" "^2.0.2"
"@smithy/middleware-content-length" "^2.0.2"
"@smithy/middleware-endpoint" "^2.0.2"
"@smithy/middleware-retry" "^2.0.2"
"@smithy/middleware-serde" "^2.0.2"
"@smithy/middleware-stack" "^2.0.0"
"@smithy/node-config-provider" "^2.0.2"
"@smithy/node-http-handler" "^2.0.2"
"@smithy/property-provider" "^2.0.0"
"@smithy/protocol-http" "^2.0.2"
"@smithy/shared-ini-file-loader" "^2.0.0"
"@smithy/smithy-client" "^2.0.2"
"@smithy/types" "^2.1.0"
"@smithy/url-parser" "^2.0.2"
"@smithy/util-base64" "^2.0.0"
"@smithy/util-body-length-browser" "^2.0.0"
"@smithy/util-body-length-node" "^2.0.0"
"@smithy/util-defaults-mode-browser" "^2.0.2"
"@smithy/util-defaults-mode-node" "^2.0.2"
"@smithy/util-retry" "^2.0.0"
"@smithy/util-utf8" "^2.0.0"
tslib "^2.5.0"
"@aws-sdk/types@3.310.0", "@aws-sdk/types@^3.222.0":
version "3.310.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.310.0.tgz#b83a0580feb38b58417abb8b4ed3eae1a0cb7bc1"
@@ -438,6 +753,14 @@
dependencies:
tslib "^2.5.0"
"@aws-sdk/types@3.387.0":
version "3.387.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.387.0.tgz#15a968344956b2587dbab1224718d72329e050f4"
integrity sha512-YTjFabNwjTF+6yl88f0/tWff018qmmgMmjlw45s6sdVKueWxdxV68U7gepNLF2nhaQPZa6FDOBoA51NaviVs0Q==
dependencies:
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@aws-sdk/url-parser@3.310.0":
version "3.310.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/url-parser/-/url-parser-3.310.0.tgz#928c9eac2e3d74c3c5db4c6e364a1de00185dcaa"
@@ -514,6 +837,14 @@
"@aws-sdk/types" "3.310.0"
tslib "^2.5.0"
"@aws-sdk/util-endpoints@3.387.0":
version "3.387.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.387.0.tgz#86d7611527ce916c39dfc02641b8be6e0ad8f1f4"
integrity sha512-g7kvuCXehGXHHBw9PkSQdwVyDFmNUZLmfrRmqMyrMDG9QLQrxr4pyWcSaYgTE16yUzhQQOR+QSey+BL6W9/N6g==
dependencies:
"@aws-sdk/types" "3.387.0"
tslib "^2.5.0"
"@aws-sdk/util-locate-window@^3.0.0":
version "3.310.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz#b071baf050301adee89051032bd4139bba32cc40"
@@ -552,6 +883,16 @@
bowser "^2.11.0"
tslib "^2.5.0"
"@aws-sdk/util-user-agent-browser@3.387.0":
version "3.387.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.387.0.tgz#a59409a168a73a3ce08c0ac831593f864490078e"
integrity sha512-lpgSVvDqx+JjHZCTYs/yQSS7J71dPlJeAlvxc7bmx5m+vfwKe07HAnIs+929DngS0QbAp/VaXbTiMFsInLkO4Q==
dependencies:
"@aws-sdk/types" "3.387.0"
"@smithy/types" "^2.1.0"
bowser "^2.11.0"
tslib "^2.5.0"
"@aws-sdk/util-user-agent-node@3.310.0":
version "3.310.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.310.0.tgz#ebefbedc5a4759adc958885741628ec0de1ab197"
@@ -561,6 +902,16 @@
"@aws-sdk/types" "3.310.0"
tslib "^2.5.0"
"@aws-sdk/util-user-agent-node@3.387.0":
version "3.387.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.387.0.tgz#54ae2e17fb3738c018891bdb67ab4e4cce219e6f"
integrity sha512-r9OVkcWpRYatjLhJacuHFgvO2T5s/Nu5DDbScMrkUD8b4aGIIqsrdZji0vZy9FCjsUFQMM92t9nt4SejrGjChA==
dependencies:
"@aws-sdk/types" "3.387.0"
"@smithy/node-config-provider" "^2.0.2"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@aws-sdk/util-utf8-browser@^3.0.0":
version "3.259.0"
resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz#3275a6f5eb334f96ca76635b961d3c50259fd9ff"
@@ -841,6 +1192,346 @@
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
"@smithy/abort-controller@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-2.0.2.tgz#e2188247a1723b58d60b0803f3ba24b76a714413"
integrity sha512-ln5Cob0mksym62sLr7NiPOSqJ0jKao4qjfcNLDdgINM1lQI12hXrZBlKdPHbXJqpKhKiECDgonMoqCM8bigq4g==
dependencies:
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@smithy/config-resolver@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-2.0.2.tgz#64496d2f2f9f1482d2e982d3dc057dccc4ba97db"
integrity sha512-0kdsqBL6BdmSbdU6YaDkodVBMua5MuQQluC3nocJ7OJ6PnOuM7i2FEQHE46LBadLqT+CimlDSM+6j91uHNL1ng==
dependencies:
"@smithy/types" "^2.1.0"
"@smithy/util-config-provider" "^2.0.0"
"@smithy/util-middleware" "^2.0.0"
tslib "^2.5.0"
"@smithy/credential-provider-imds@^2.0.0", "@smithy/credential-provider-imds@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.2.tgz#9096ff1a2ceb235497a62d469ac70086b96022ad"
integrity sha512-mbWFYEZ00LBRDk3WvcXViwpdpkJQcfrM3seuKzFxZnF6wIBLMwrcWcsj+OUC/1L+86m8aQY9imXMAaQsAoGxow==
dependencies:
"@smithy/node-config-provider" "^2.0.2"
"@smithy/property-provider" "^2.0.2"
"@smithy/types" "^2.1.0"
"@smithy/url-parser" "^2.0.2"
tslib "^2.5.0"
"@smithy/eventstream-codec@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-2.0.2.tgz#9d81c8d081ac28ba098d98b06cbb39955af1e09b"
integrity sha512-PQZiKx7fMnNwx4zxcUCm82VjnqK6wV4MEHSmMy3taj5dKfXV782IjRGyaDT+8TsmNqVdZIkve5zLRAzh+7kOhA==
dependencies:
"@aws-crypto/crc32" "3.0.0"
"@smithy/types" "^2.1.0"
"@smithy/util-hex-encoding" "^2.0.0"
tslib "^2.5.0"
"@smithy/fetch-http-handler@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-2.0.2.tgz#dcc0e9d365efd8feef4a54dd96a264735a1446b7"
integrity sha512-Wo2m1RaiXNSLF4J3D62LpdSoj/YYb+6tn0H8is1tSrzr7eXAdiYVBc0wIa23N0wT4zmN0iG/yNY6gTCDQ6799A==
dependencies:
"@smithy/protocol-http" "^2.0.2"
"@smithy/querystring-builder" "^2.0.2"
"@smithy/types" "^2.1.0"
"@smithy/util-base64" "^2.0.0"
tslib "^2.5.0"
"@smithy/hash-node@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-2.0.2.tgz#e968a3e7ab7072bd12297063e3770ae6d9249dee"
integrity sha512-JKDzZ1YVR7JzOBaJoWy3ToJCE86OQE6D4kOBvvVsu93a3lcF9kv6KYTKBYEWAjwOn/CpK4NH7mKB01OQ8H+aiA==
dependencies:
"@smithy/types" "^2.1.0"
"@smithy/util-buffer-from" "^2.0.0"
"@smithy/util-utf8" "^2.0.0"
tslib "^2.5.0"
"@smithy/invalid-dependency@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-2.0.2.tgz#1f7b6a860395e9f11fcdbdf3ac22fb95ce863c69"
integrity sha512-inQZQ5gCO3WRWuXpsc1YJ4KBjsvj2qsoU32yTIKznBWTCQe/D5Dp+sSaysqBqxe0VTZ+8nFEHdUMWUX2BxQThw==
dependencies:
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@smithy/is-array-buffer@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz#8fa9b8040651e7ba0b2f6106e636a91354ff7d34"
integrity sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==
dependencies:
tslib "^2.5.0"
"@smithy/middleware-content-length@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-2.0.2.tgz#6167e8ca52cb5f2b06d3c76fa445080c45baaf25"
integrity sha512-FmHlNfuvYgDZE3fIx0G3rD/wLXfAmBYE4mVc/w6d7RllA7TygPzq2pfHL1iCMzWkWTdoAVnt3h4aavAZnhaxEQ==
dependencies:
"@smithy/protocol-http" "^2.0.2"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@smithy/middleware-endpoint@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-2.0.2.tgz#29f4c8ae799ffb0891f96148eb754f8d0a41a97c"
integrity sha512-ropE7/c+g22QeluZ+By/B/WvVep0UFreX+IeRMGIO7EbOUPgqtJRXpbJFdG6JKB1uC+CdaJLn4MnZnVBpcyjuA==
dependencies:
"@smithy/middleware-serde" "^2.0.2"
"@smithy/types" "^2.1.0"
"@smithy/url-parser" "^2.0.2"
"@smithy/util-middleware" "^2.0.0"
tslib "^2.5.0"
"@smithy/middleware-retry@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-2.0.2.tgz#0d6feb551a5d546c720106435d2a4e7878fd8ea2"
integrity sha512-wtBUXqtZVriiXppYaFkUrybAPhFVX7vebnW/yVPliLMWMcguOMS58qhOYPZe3t9Wki2+mASfyu+kO3An8lAg2A==
dependencies:
"@smithy/protocol-http" "^2.0.2"
"@smithy/service-error-classification" "^2.0.0"
"@smithy/types" "^2.1.0"
"@smithy/util-middleware" "^2.0.0"
"@smithy/util-retry" "^2.0.0"
tslib "^2.5.0"
uuid "^8.3.2"
"@smithy/middleware-serde@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-2.0.2.tgz#a59f74e981be8b76ef18e272d525e24e3974dc82"
integrity sha512-Kw9xLdlueIaivUWslKB67WZ/cCUg3QnzYVIA3t5KfgsseEEuU4UxXw8NSTvIt71gqQloY+Um8ugS+idgxrWWnw==
dependencies:
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@smithy/middleware-stack@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-2.0.0.tgz#cd9f442c2788b1ef0ea6b32236d80c76b3c342e9"
integrity sha512-31XC1xNF65nlbc16yuh3wwTudmqs6qy4EseQUGF8A/p2m/5wdd/cnXJqpniy/XvXVwkHPz/GwV36HqzHtIKATQ==
dependencies:
tslib "^2.5.0"
"@smithy/node-config-provider@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-2.0.2.tgz#a15f125f7011ff82610297d899826b7ef7889867"
integrity sha512-9wVJccASfuCctNWrzR0zrDkf0ox3HCHGEhFlWL2LBoghUYuK28pVRBbG69wvnkhlHnB8dDZHagxH+Nq9dm7eWw==
dependencies:
"@smithy/property-provider" "^2.0.2"
"@smithy/shared-ini-file-loader" "^2.0.2"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@smithy/node-http-handler@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-2.0.2.tgz#3c4d43352f5412cdb23ca075327ac997f5b03df2"
integrity sha512-lpZjmtmyZqSAtMPsbrLhb7XoAQ2kAHeuLY/csW6I2k+QyFvOk7cZeQsqEngWmZ9SJaeYiDCBINxAIM61i5WGLw==
dependencies:
"@smithy/abort-controller" "^2.0.2"
"@smithy/protocol-http" "^2.0.2"
"@smithy/querystring-builder" "^2.0.2"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@smithy/property-provider@^2.0.0", "@smithy/property-provider@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-2.0.2.tgz#abe091d1e7dc5b617e3418b63eaed11363c96f21"
integrity sha512-DfaZ8cO+d/mgnMzIllcXcU4OYP+omiOl2LYdn/fTGpw/EAQSVzscYV2muV3sDDnuPYQ/r014hUqIxnF+pzh+SQ==
dependencies:
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@smithy/protocol-http@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-2.0.2.tgz#ec3d45a650cb5554b6aba1c38768f51fc9cf79b5"
integrity sha512-qWu8g1FUy+m36KpO1sREJSF7BaLmjw9AqOuwxLVVSdYz+nUQjc9tFAZ9LB6jJXKdsZFSjfkjHJBbhD78QdE7Rw==
dependencies:
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@smithy/querystring-builder@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-2.0.2.tgz#67a1bb503037c4666b5df56ad4b9e10bc525f568"
integrity sha512-H99LOMWEssfwqkOoTs4Y12UiZ7CTGQSX5Nrx5UkYgRbUEpC1GnnaprHiYrqclC58/xr4K76aNchdPyioxewMzA==
dependencies:
"@smithy/types" "^2.1.0"
"@smithy/util-uri-escape" "^2.0.0"
tslib "^2.5.0"
"@smithy/querystring-parser@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-2.0.2.tgz#d6b2562e7ae29282b144939e5fd439b17bdf61dd"
integrity sha512-L4VtKQ8O4/aWPQJbiFymbhAmxdfLnEaROh/Vs0OstJ7jtOZeBl2QJmuWY2V7hjt64W7V+tEn2sv6vVvnxkm/xQ==
dependencies:
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@smithy/service-error-classification@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-2.0.0.tgz#bbce07c9c529d9333d40db881fd4a1795dd84892"
integrity sha512-2z5Nafy1O0cTf69wKyNjGW/sNVMiqDnb4jgwfMG8ye8KnFJ5qmJpDccwIbJNhXIfbsxTg9SEec2oe1cexhMJvw==
"@smithy/shared-ini-file-loader@^2.0.0", "@smithy/shared-ini-file-loader@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.0.2.tgz#49b9bf384ece821352f50c8f6cb989edc77d2dbf"
integrity sha512-2VkNOM/82u4vatVdK5nfusgGIlvR48Fkq6me17Oc+V1iyxfR/1x0pG6LzW0br1qlGtzBYFZKmDyviBRcPVFTVw==
dependencies:
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@smithy/signature-v4@^2.0.0":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-2.0.2.tgz#c1ec6d9485a72039060e9a8fe2c02e0afb9d7764"
integrity sha512-YMooDEw/UmGxcXY4qWnSXkbPFsRloluSvyXVT678YPDN/K2AS1GzKfRsvSU7fbccOB4WF8MHZf2UqcRGEltE3Q==
dependencies:
"@smithy/eventstream-codec" "^2.0.2"
"@smithy/is-array-buffer" "^2.0.0"
"@smithy/types" "^2.1.0"
"@smithy/util-hex-encoding" "^2.0.0"
"@smithy/util-middleware" "^2.0.0"
"@smithy/util-uri-escape" "^2.0.0"
"@smithy/util-utf8" "^2.0.0"
tslib "^2.5.0"
"@smithy/smithy-client@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-2.0.2.tgz#3364bfb4afa73d57712b95cb9319f7c8324a104e"
integrity sha512-mDfokI8WwLU5C0gcQ4ww/zJI/WLGSh2+vdIA42JRnjfYUjJNH/rKfX9YOnn2eBOxl3loATERVUqkHmKe+P8s2Q==
dependencies:
"@smithy/middleware-stack" "^2.0.0"
"@smithy/types" "^2.1.0"
"@smithy/util-stream" "^2.0.2"
tslib "^2.5.0"
"@smithy/types@^2.1.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@smithy/types/-/types-2.1.0.tgz#67fd47c25bbb0fd818951891bf7bcf19a8ee2fe6"
integrity sha512-KLsCsqxX0j2l99iP8s0f7LBlcsp7a7ceXGn0LPYPyVOsqmIKvSaPQajq0YevlL4T9Bm+DtcyXfBTbtBcLX1I7A==
dependencies:
tslib "^2.5.0"
"@smithy/url-parser@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-2.0.2.tgz#af50bd62298b209b1a16c80912a03460b7cb8994"
integrity sha512-X1mHCzrSVDlhVy7d3S7Vq+dTfYzwh4n7xGHhyJumu77nJqIss0lazVug85Pwo0DKIoO314wAOvMnBxNYDa+7wA==
dependencies:
"@smithy/querystring-parser" "^2.0.2"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@smithy/util-base64@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-2.0.0.tgz#1beeabfb155471d1d41c8d0603be1351f883c444"
integrity sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==
dependencies:
"@smithy/util-buffer-from" "^2.0.0"
tslib "^2.5.0"
"@smithy/util-body-length-browser@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz#5447853003b4c73da3bc5f3c5e82c21d592d1650"
integrity sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==
dependencies:
tslib "^2.5.0"
"@smithy/util-body-length-node@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-2.0.0.tgz#4870b71cb9ded0123d984898ce952ce56896bc53"
integrity sha512-ZV7Z/WHTMxHJe/xL/56qZwSUcl63/5aaPAGjkfynJm4poILjdD4GmFI+V+YWabh2WJIjwTKZ5PNsuvPQKt93Mg==
dependencies:
tslib "^2.5.0"
"@smithy/util-buffer-from@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz#7eb75d72288b6b3001bc5f75b48b711513091deb"
integrity sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==
dependencies:
"@smithy/is-array-buffer" "^2.0.0"
tslib "^2.5.0"
"@smithy/util-config-provider@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz#4dd6a793605559d94267312fd06d0f58784b4c38"
integrity sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==
dependencies:
tslib "^2.5.0"
"@smithy/util-defaults-mode-browser@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.2.tgz#fb3ad350573ddea0ff7222adc98e9ecc4155b0d3"
integrity sha512-c2tMMjb624XLuzmlRoZpnFOkejVxcgw3WQKdmgdGZYZapcLzXyC0H9JhnXMjQCt30GqLTlsILRNVBYwFRbw/4Q==
dependencies:
"@smithy/property-provider" "^2.0.2"
"@smithy/types" "^2.1.0"
bowser "^2.11.0"
tslib "^2.5.0"
"@smithy/util-defaults-mode-node@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.2.tgz#2e16e3eb57427c76604c255c38d9e1eacd385d7e"
integrity sha512-gt7m5LLqUtEKldJLyc14DE4kb85vxwomvt9AfEMEvWM4VwfWS1kGJqiStZFb5KNqnQPXw8vvpgLTi8NrWAOXqg==
dependencies:
"@smithy/config-resolver" "^2.0.2"
"@smithy/credential-provider-imds" "^2.0.2"
"@smithy/node-config-provider" "^2.0.2"
"@smithy/property-provider" "^2.0.2"
"@smithy/types" "^2.1.0"
tslib "^2.5.0"
"@smithy/util-hex-encoding@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz#0aa3515acd2b005c6d55675e377080a7c513b59e"
integrity sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==
dependencies:
tslib "^2.5.0"
"@smithy/util-middleware@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-2.0.0.tgz#706681d4a1686544a2275f68266304233f372c99"
integrity sha512-eCWX4ECuDHn1wuyyDdGdUWnT4OGyIzV0LN1xRttBFMPI9Ff/4heSHVxneyiMtOB//zpXWCha1/SWHJOZstG7kA==
dependencies:
tslib "^2.5.0"
"@smithy/util-retry@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-2.0.0.tgz#7ac5d5f12383a9d9b2a43f9ff25f3866c8727c24"
integrity sha512-/dvJ8afrElasuiiIttRJeoS2sy8YXpksQwiM/TcepqdRVp7u4ejd9C4IQURHNjlfPUT7Y6lCDSa2zQJbdHhVTg==
dependencies:
"@smithy/service-error-classification" "^2.0.0"
tslib "^2.5.0"
"@smithy/util-stream@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-2.0.2.tgz#cb4f3c4eca4253f77a780fd861630ed02d67b220"
integrity sha512-Mg9IJcKIu4YKlbzvpp1KLvh4JZLdcPgpxk+LICuDwzZCfxe47R9enVK8dNEiuyiIGK2ExbfvzCVT8IBru62vZw==
dependencies:
"@smithy/fetch-http-handler" "^2.0.2"
"@smithy/node-http-handler" "^2.0.2"
"@smithy/types" "^2.1.0"
"@smithy/util-base64" "^2.0.0"
"@smithy/util-buffer-from" "^2.0.0"
"@smithy/util-hex-encoding" "^2.0.0"
"@smithy/util-utf8" "^2.0.0"
tslib "^2.5.0"
"@smithy/util-uri-escape@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz#19955b1a0f517a87ae77ac729e0e411963dfda95"
integrity sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==
dependencies:
tslib "^2.5.0"
"@smithy/util-utf8@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.0.0.tgz#b4da87566ea7757435e153799df9da717262ad42"
integrity sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==
dependencies:
"@smithy/util-buffer-from" "^2.0.0"
tslib "^2.5.0"
"@socket.io/component-emitter@~3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553"
@@ -2136,6 +2827,13 @@ fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3:
resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz#0aa25f7f638222e3396d72bf936afcf1d42d6867"
integrity sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==
fast-xml-parser@4.2.5:
version "4.2.5"
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f"
integrity sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==
dependencies:
strnum "^1.0.5"
faye-websocket@0.11.4:
version "0.11.4"
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da"
@@ -4187,6 +4885,11 @@ stripe@^9.15.0:
"@types/node" ">=8.1.0"
qs "^6.10.3"
strnum@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db"
integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==
stubs@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b"