Merge master into feature/local-images
This commit is contained in:
@@ -8927,6 +8927,48 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>md_to_emails</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>md_to_emails_emails</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>messagingpresets</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -14017,6 +14059,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>external_id</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>first_name</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -36695,6 +36758,32 @@
|
||||
</concept_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
<name>special</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>attendance_detail_csv</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>subjects</name>
|
||||
<children>
|
||||
|
||||
@@ -28,7 +28,7 @@ export default connect(
|
||||
mapDispatchToProps
|
||||
)(AccountingPayablesTableComponent);
|
||||
|
||||
export function AccountingPayablesTableComponent({ bodyshop, loading, bills }) {
|
||||
export function AccountingPayablesTableComponent({ bodyshop, loading, bills, refetch }) {
|
||||
const { t } = useTranslation();
|
||||
const [selectedBills, setSelectedBills] = useState([]);
|
||||
const [transInProgress, setTransInProgress] = useState(false);
|
||||
@@ -149,6 +149,7 @@ export function AccountingPayablesTableComponent({ bodyshop, loading, bills }) {
|
||||
disabled={transInProgress || !!record.exported}
|
||||
loadingCallback={setTransInProgress}
|
||||
setSelectedBills={setSelectedBills}
|
||||
refetch={refetch}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
@@ -181,6 +182,7 @@ export function AccountingPayablesTableComponent({ bodyshop, loading, bills }) {
|
||||
disabled={transInProgress || selectedBills.length === 0}
|
||||
loadingCallback={setTransInProgress}
|
||||
completedCallback={setSelectedBills}
|
||||
refetch={refetch}
|
||||
/>
|
||||
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && (
|
||||
<QboAuthorizeComponent />
|
||||
|
||||
@@ -32,6 +32,7 @@ export function AccountingPayablesTableComponent({
|
||||
bodyshop,
|
||||
loading,
|
||||
payments,
|
||||
refetch,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [selectedPayments, setSelectedPayments] = useState([]);
|
||||
@@ -147,6 +148,7 @@ export function AccountingPayablesTableComponent({
|
||||
disabled={transInProgress || !!record.exportedat}
|
||||
loadingCallback={setTransInProgress}
|
||||
setSelectedPayments={setSelectedPayments}
|
||||
refetch={refetch}
|
||||
/>
|
||||
),
|
||||
},
|
||||
@@ -187,6 +189,7 @@ export function AccountingPayablesTableComponent({
|
||||
disabled={transInProgress || selectedPayments.length === 0}
|
||||
loadingCallback={setTransInProgress}
|
||||
completedCallback={setSelectedPayments}
|
||||
refetch={refetch}
|
||||
/>
|
||||
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && (
|
||||
<QboAuthorizeComponent />
|
||||
|
||||
@@ -31,6 +31,7 @@ export function AccountingReceivablesTableComponent({
|
||||
bodyshop,
|
||||
loading,
|
||||
jobs,
|
||||
refetch,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [selectedJobs, setSelectedJobs] = useState([]);
|
||||
@@ -155,6 +156,7 @@ export function AccountingReceivablesTableComponent({
|
||||
jobId={record.id}
|
||||
disabled={!!record.date_exported}
|
||||
setSelectedJobs={setSelectedJobs}
|
||||
refetch={refetch}
|
||||
/>
|
||||
<Link to={`/manage/jobs/${record.id}/close`}>
|
||||
<Button>{t("jobs.labels.viewallocations")}</Button>
|
||||
@@ -205,6 +207,7 @@ export function AccountingReceivablesTableComponent({
|
||||
disabled={transInProgress || selectedJobs.length === 0}
|
||||
loadingCallback={setTransInProgress}
|
||||
completedCallback={setSelectedJobs}
|
||||
refetch={refetch}
|
||||
/>
|
||||
)}
|
||||
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && (
|
||||
|
||||
@@ -42,7 +42,12 @@ export function EmailOverlayComponent({
|
||||
const { t } = useTranslation();
|
||||
const handleClick = ({ item, key, keyPath }) => {
|
||||
const email = item.props.value;
|
||||
form.setFieldsValue({ to: _.uniq([...form.getFieldValue("to"), email]) });
|
||||
form.setFieldsValue({
|
||||
to: _.uniq([
|
||||
...form.getFieldValue("to"),
|
||||
...(typeof email === "string" ? [email] : email),
|
||||
]),
|
||||
});
|
||||
};
|
||||
|
||||
const menu = (
|
||||
@@ -55,6 +60,11 @@ export function EmailOverlayComponent({
|
||||
{`${e.first_name} ${e.last_name}`}
|
||||
</Menu.Item>
|
||||
))}
|
||||
{bodyshop.md_to_emails.map((e, idx) => (
|
||||
<Menu.Item value={e.emails} key={idx + "group"}>
|
||||
{e.label}
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -15,7 +15,6 @@ 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,
|
||||
currentUser: selectCurrentUser,
|
||||
@@ -27,6 +26,7 @@ export function JobsCloseExportButton({
|
||||
jobId,
|
||||
disabled,
|
||||
setSelectedJobs,
|
||||
refetch,
|
||||
}) {
|
||||
const history = useHistory();
|
||||
const { t } = useTranslation();
|
||||
@@ -46,13 +46,10 @@ export function JobsCloseExportButton({
|
||||
//Check if it's a QBO Setup.
|
||||
let PartnerResponse;
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
||||
PartnerResponse = await axios.post(
|
||||
`/qbo/receivables`,
|
||||
{
|
||||
jobIds: [jobId],
|
||||
},
|
||||
|
||||
);
|
||||
PartnerResponse = await axios.post(`/qbo/receivables`, {
|
||||
jobIds: [jobId],
|
||||
elgen: true,
|
||||
});
|
||||
} else {
|
||||
//Default is QBD
|
||||
|
||||
@@ -117,58 +114,64 @@ export function JobsCloseExportButton({
|
||||
});
|
||||
});
|
||||
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
jobid: jobId,
|
||||
successful: false,
|
||||
message: JSON.stringify(
|
||||
failedTransactions.map((ft) => ft.errorMessage)
|
||||
),
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
|
||||
//QBO Logs are handled server side.
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
jobid: jobId,
|
||||
successful: false,
|
||||
message: JSON.stringify(
|
||||
failedTransactions.map((ft) => ft.errorMessage)
|
||||
),
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
//Insert success export log.
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
jobid: jobId,
|
||||
successful: true,
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const jobUpdateResponse = await updateJob({
|
||||
variables: {
|
||||
jobId: jobId,
|
||||
job: {
|
||||
status: bodyshop.md_ro_statuses.default_exported || "Exported*",
|
||||
date_exported: new Date(),
|
||||
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
|
||||
//QBO Logs are handled server side.
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
jobid: jobId,
|
||||
successful: true,
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
if (!jobUpdateResponse.errors) {
|
||||
notification.open({
|
||||
type: "success",
|
||||
key: "jobsuccessexport",
|
||||
message: t("jobs.successes.exported"),
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.exporting", {
|
||||
error: JSON.stringify(jobUpdateResponse.error),
|
||||
}),
|
||||
const jobUpdateResponse = await updateJob({
|
||||
variables: {
|
||||
jobId: jobId,
|
||||
job: {
|
||||
status: bodyshop.md_ro_statuses.default_exported || "Exported*",
|
||||
date_exported: new Date(),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!jobUpdateResponse.errors) {
|
||||
notification.open({
|
||||
type: "success",
|
||||
key: "jobsuccessexport",
|
||||
message: t("jobs.successes.exported"),
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.exporting", {
|
||||
error: JSON.stringify(jobUpdateResponse.error),
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
if (setSelectedJobs) {
|
||||
setSelectedJobs((selectedJobs) => {
|
||||
@@ -176,7 +179,7 @@ export function JobsCloseExportButton({
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ export function JobsExportAllButton({
|
||||
disabled,
|
||||
loadingCallback,
|
||||
completedCallback,
|
||||
refetch,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [updateJob] = useMutation(UPDATE_JOBS);
|
||||
@@ -39,6 +40,7 @@ export function JobsExportAllButton({
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
||||
PartnerResponse = await axios.post(`/qbo/receivables`, {
|
||||
jobIds: jobIds,
|
||||
elgen: true,
|
||||
});
|
||||
} else {
|
||||
let QbXmlResponse;
|
||||
@@ -83,6 +85,7 @@ export function JobsExportAllButton({
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("PartnerResponse", PartnerResponse);
|
||||
const groupedData = _.groupBy(
|
||||
PartnerResponse.data,
|
||||
@@ -106,61 +109,70 @@ export function JobsExportAllButton({
|
||||
});
|
||||
//Call is not awaited as it is not critical to finish before proceeding.
|
||||
});
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
jobid: key,
|
||||
successful: false,
|
||||
message: JSON.stringify(
|
||||
failedTransactions.map((ft) => ft.errorMessage)
|
||||
),
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
jobid: key,
|
||||
successful: true,
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const jobUpdateResponse = await updateJob({
|
||||
variables: {
|
||||
jobIds: [key],
|
||||
fields: {
|
||||
status: bodyshop.md_ro_statuses.default_exported || "Exported*",
|
||||
date_exported: new Date(),
|
||||
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
|
||||
//QBO Logs are handled server side.
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
jobid: key,
|
||||
successful: false,
|
||||
message: JSON.stringify(
|
||||
failedTransactions.map((ft) => ft.errorMessage)
|
||||
),
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
|
||||
//QBO Logs are handled server side.
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
jobid: key,
|
||||
successful: true,
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
if (!jobUpdateResponse.errors) {
|
||||
notification.open({
|
||||
type: "success",
|
||||
key: "jobsuccessexport",
|
||||
message: t("jobs.successes.exported"),
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.exporting", {
|
||||
error: JSON.stringify(jobUpdateResponse.error),
|
||||
}),
|
||||
const jobUpdateResponse = await updateJob({
|
||||
variables: {
|
||||
jobIds: [key],
|
||||
fields: {
|
||||
status:
|
||||
bodyshop.md_ro_statuses.default_exported || "Exported*",
|
||||
date_exported: new Date(),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!jobUpdateResponse.errors) {
|
||||
notification.open({
|
||||
type: "success",
|
||||
key: "jobsuccessexport",
|
||||
message: t("jobs.successes.exported"),
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.exporting", {
|
||||
error: JSON.stringify(jobUpdateResponse.error),
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
|
||||
|
||||
if (!!completedCallback) completedCallback([]);
|
||||
if (!!loadingCallback) loadingCallback(false);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import React from "react";
|
||||
import { Button, Popconfirm } from "antd";
|
||||
import { DeleteFilled } from "@ant-design/icons";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { DELETE_PARTS_ORDER_LINE } from "../../graphql/parts-orders.queries";
|
||||
import { useMutation } from "@apollo/client";
|
||||
|
||||
export default function PartsOrderDeleteLine({
|
||||
disabled,
|
||||
partsLineId,
|
||||
partsOrderId,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [deletePartsOrderLine] = useMutation(DELETE_PARTS_ORDER_LINE);
|
||||
return (
|
||||
<Popconfirm
|
||||
title={t("parts_orders.labels.confirmdelete")}
|
||||
disabled={disabled}
|
||||
onConfirm={async () => {
|
||||
//Delete the parts return.!
|
||||
|
||||
await deletePartsOrderLine({
|
||||
variables: { partsOrderLineId: partsLineId },
|
||||
update(cache) {
|
||||
cache.modify({
|
||||
id: cache.identify({
|
||||
__typename: "parts_orders",
|
||||
id: partsOrderId,
|
||||
}),
|
||||
fields: {
|
||||
parts_order_lines(cached, { readField }) {
|
||||
return cached.filter((c) => {
|
||||
return readField("id", c) !== partsLineId;
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Button disabled={disabled}>
|
||||
<DeleteFilled />
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
);
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import { TemplateList } from "../../utils/TemplateConstants";
|
||||
import DataLabel from "../data-label/data-label.component";
|
||||
import PartsOrderBackorderEta from "../parts-order-backorder-eta/parts-order-backorder-eta.component";
|
||||
import PartsOrderCmReceived from "../parts-order-cm-received/parts-order-cm-received.component";
|
||||
import PartsOrderDeleteLine from "../parts-order-delete-line/parts-order-delete-line.component";
|
||||
import PartsOrderLineBackorderButton from "../parts-order-line-backorder-button/parts-order-line-backorder-button.component";
|
||||
import PartsReceiveModalContainer from "../parts-receive-modal/parts-receive-modal.container";
|
||||
import PrintWrapper from "../print-wrapper/print-wrapper.component";
|
||||
@@ -391,12 +392,21 @@ export function PartsOrderListTableComponent({
|
||||
dataIndex: "actions",
|
||||
key: "actions",
|
||||
render: (text, record) => (
|
||||
<PartsOrderLineBackorderButton
|
||||
disabled={jobRO}
|
||||
partsOrderStatus={record.status}
|
||||
partsLineId={record.id}
|
||||
jobLineId={record.job_line_id}
|
||||
/>
|
||||
<Space wrap>
|
||||
<PartsOrderDeleteLine
|
||||
disabled={jobRO}
|
||||
partsOrderStatus={record.status}
|
||||
partsLineId={record.id}
|
||||
partsOrderId={selectedpartsorder}
|
||||
jobLineId={record.job_line_id}
|
||||
/>
|
||||
<PartsOrderLineBackorderButton
|
||||
disabled={jobRO}
|
||||
partsOrderStatus={record.status}
|
||||
partsLineId={record.id}
|
||||
jobLineId={record.job_line_id}
|
||||
/>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -27,6 +27,7 @@ export function PayableExportAll({
|
||||
disabled,
|
||||
loadingCallback,
|
||||
completedCallback,
|
||||
refetch,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [updateBill] = useMutation(UPDATE_BILLS);
|
||||
@@ -42,6 +43,7 @@ export function PayableExportAll({
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
||||
PartnerResponse = await axios.post(`/qbo/payables`, {
|
||||
bills: billids,
|
||||
elgen: true,
|
||||
});
|
||||
} else {
|
||||
let QbXmlResponse;
|
||||
@@ -104,57 +106,62 @@ export function PayableExportAll({
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
billid: key,
|
||||
successful: false,
|
||||
message: JSON.stringify(
|
||||
failedTransactions.map((ft) => ft.errorMessage)
|
||||
),
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
billid: key,
|
||||
successful: true,
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const billUpdateResponse = await updateBill({
|
||||
variables: {
|
||||
billIdList: [key],
|
||||
bill: {
|
||||
exported: true,
|
||||
exported_at: new Date(),
|
||||
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
|
||||
//QBO Logs are handled server side.
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
billid: key,
|
||||
successful: false,
|
||||
message: JSON.stringify(
|
||||
failedTransactions.map((ft) => ft.errorMessage)
|
||||
),
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!!!billUpdateResponse.errors) {
|
||||
notification.open({
|
||||
type: "success",
|
||||
key: "billsuccessexport",
|
||||
message: t("bills.successes.exported"),
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("bills.errors.exporting", {
|
||||
error: JSON.stringify(billUpdateResponse.error),
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
|
||||
//QBO Logs are handled server side.
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
billid: key,
|
||||
successful: true,
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const billUpdateResponse = await updateBill({
|
||||
variables: {
|
||||
billIdList: [key],
|
||||
bill: {
|
||||
exported: true,
|
||||
exported_at: new Date(),
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!!!billUpdateResponse.errors) {
|
||||
notification.open({
|
||||
type: "success",
|
||||
key: "billsuccessexport",
|
||||
message: t("bills.successes.exported"),
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("bills.errors.exporting", {
|
||||
error: JSON.stringify(billUpdateResponse.error),
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})()
|
||||
@@ -164,6 +171,8 @@ export function PayableExportAll({
|
||||
await Promise.all(proms);
|
||||
if (!!completedCallback) completedCallback([]);
|
||||
if (!!loadingCallback) loadingCallback(false);
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ export function PayableExportButton({
|
||||
disabled,
|
||||
loadingCallback,
|
||||
setSelectedBills,
|
||||
refetch,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [updateBill] = useMutation(UPDATE_BILLS);
|
||||
@@ -43,6 +44,7 @@ export function PayableExportButton({
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
||||
PartnerResponse = await axios.post(`/qbo/payables`, {
|
||||
bills: [billId],
|
||||
elgen: true,
|
||||
});
|
||||
} else {
|
||||
//Default is QBD
|
||||
@@ -100,64 +102,72 @@ export function PayableExportButton({
|
||||
}),
|
||||
})
|
||||
);
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
billid: billId,
|
||||
successful: false,
|
||||
message: JSON.stringify(
|
||||
failedTransactions.map((ft) => ft.errorMessage)
|
||||
),
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
if (successfulTransactions.length > 0) {
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
billid: billId,
|
||||
successful: true,
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const billUpdateResponse = await updateBill({
|
||||
variables: {
|
||||
billIdList: successfulTransactions.map(
|
||||
(st) =>
|
||||
st[
|
||||
bodyshop.accountingconfig && bodyshop.accountingconfig.qbo
|
||||
? "billid"
|
||||
: "id"
|
||||
]
|
||||
),
|
||||
bill: {
|
||||
exported: true,
|
||||
exported_at: new Date(),
|
||||
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
|
||||
//QBO Logs are handled server side.
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
billid: billId,
|
||||
successful: false,
|
||||
message: JSON.stringify(
|
||||
failedTransactions.map((ft) => ft.errorMessage)
|
||||
),
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!!!billUpdateResponse.errors) {
|
||||
notification.open({
|
||||
type: "success",
|
||||
key: "billsuccessexport",
|
||||
message: t("bills.successes.exported"),
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("bills.errors.exporting", {
|
||||
error: JSON.stringify(billUpdateResponse.error),
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
if (successfulTransactions.length > 0) {
|
||||
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
|
||||
//QBO Logs are handled server side.
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
billid: billId,
|
||||
successful: true,
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const billUpdateResponse = await updateBill({
|
||||
variables: {
|
||||
billIdList: successfulTransactions.map(
|
||||
(st) =>
|
||||
st[
|
||||
bodyshop.accountingconfig && bodyshop.accountingconfig.qbo
|
||||
? "billid"
|
||||
: "id"
|
||||
]
|
||||
),
|
||||
bill: {
|
||||
exported: true,
|
||||
exported_at: new Date(),
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!!!billUpdateResponse.errors) {
|
||||
notification.open({
|
||||
type: "success",
|
||||
key: "billsuccessexport",
|
||||
message: t("bills.successes.exported"),
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("bills.errors.exporting", {
|
||||
error: JSON.stringify(billUpdateResponse.error),
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
|
||||
|
||||
if (setSelectedBills) {
|
||||
setSelectedBills((selectedBills) => {
|
||||
return selectedBills.filter((i) => i !== billId);
|
||||
|
||||
@@ -26,6 +26,7 @@ export function PaymentExportButton({
|
||||
disabled,
|
||||
loadingCallback,
|
||||
setSelectedPayments,
|
||||
refetch,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [updatePayment] = useMutation(UPDATE_PAYMENTS);
|
||||
@@ -40,6 +41,7 @@ export function PaymentExportButton({
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
||||
PartnerResponse = await axios.post(`/qbo/payments`, {
|
||||
payments: [paymentId],
|
||||
elgen: true,
|
||||
});
|
||||
} else {
|
||||
//Default is QBD
|
||||
@@ -100,63 +102,68 @@ export function PaymentExportButton({
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
paymentid: paymentId,
|
||||
successful: false,
|
||||
message: JSON.stringify(
|
||||
failedTransactions.map((ft) => ft.errorMessage)
|
||||
),
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
paymentid: paymentId,
|
||||
successful: true,
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const paymentUpdateResponse = await updatePayment({
|
||||
variables: {
|
||||
paymentIdList: successfulTransactions.map(
|
||||
(st) =>
|
||||
st[
|
||||
bodyshop.accountingconfig && bodyshop.accountingconfig.qbo
|
||||
? "paymentid"
|
||||
: "id"
|
||||
]
|
||||
),
|
||||
payment: {
|
||||
exportedat: new Date(),
|
||||
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
|
||||
//QBO Logs are handled server side.
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
paymentid: paymentId,
|
||||
successful: false,
|
||||
message: JSON.stringify(
|
||||
failedTransactions.map((ft) => ft.errorMessage)
|
||||
),
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!!!paymentUpdateResponse.errors) {
|
||||
notification.open({
|
||||
type: "success",
|
||||
key: "paymentsuccessexport",
|
||||
message: t("payments.successes.exported"),
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("payments.errors.exporting", {
|
||||
error: JSON.stringify(paymentUpdateResponse.error),
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
|
||||
//QBO Logs are handled server side.
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
paymentid: paymentId,
|
||||
successful: true,
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const paymentUpdateResponse = await updatePayment({
|
||||
variables: {
|
||||
paymentIdList: successfulTransactions.map(
|
||||
(st) =>
|
||||
st[
|
||||
bodyshop.accountingconfig && bodyshop.accountingconfig.qbo
|
||||
? "paymentid"
|
||||
: "id"
|
||||
]
|
||||
),
|
||||
payment: {
|
||||
exportedat: new Date(),
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!!!paymentUpdateResponse.errors) {
|
||||
notification.open({
|
||||
type: "success",
|
||||
key: "paymentsuccessexport",
|
||||
message: t("payments.successes.exported"),
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("payments.errors.exporting", {
|
||||
error: JSON.stringify(paymentUpdateResponse.error),
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (setSelectedPayments) {
|
||||
@@ -165,7 +172,7 @@ export function PaymentExportButton({
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
|
||||
if (!!loadingCallback) loadingCallback(false);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
@@ -25,6 +25,7 @@ export function PaymentsExportAllButton({
|
||||
disabled,
|
||||
loadingCallback,
|
||||
completedCallback,
|
||||
refetch
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [updatePayments] = useMutation(UPDATE_PAYMENTS);
|
||||
@@ -38,6 +39,7 @@ export function PaymentsExportAllButton({
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
||||
PartnerResponse = await axios.post(`/qbo/payments`, {
|
||||
payments: paymentIds,
|
||||
elgen: true,
|
||||
});
|
||||
} else {
|
||||
let QbXmlResponse;
|
||||
@@ -92,54 +94,61 @@ export function PaymentsExportAllButton({
|
||||
}),
|
||||
})
|
||||
);
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
paymentid: key,
|
||||
successful: false,
|
||||
message: JSON.stringify(
|
||||
failedTransactions.map((ft) => ft.errorMessage)
|
||||
),
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
paymentid: key,
|
||||
successful: true,
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const paymentUpdateResponse = await updatePayments({
|
||||
variables: {
|
||||
paymentIdList: [key],
|
||||
payment: {
|
||||
exportedat: new Date(),
|
||||
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
|
||||
//QBO Logs are handled server side.
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
paymentid: key,
|
||||
successful: false,
|
||||
message: JSON.stringify(
|
||||
failedTransactions.map((ft) => ft.errorMessage)
|
||||
),
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!!!paymentUpdateResponse.errors) {
|
||||
notification.open({
|
||||
type: "success",
|
||||
key: "paymentsuccessexport",
|
||||
message: t("payments.successes.exported"),
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("payments.errors.exporting", {
|
||||
error: JSON.stringify(paymentUpdateResponse.error),
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
if (!(bodyshop.accountingconfig && bodyshop.accountingconfig.qbo)) {
|
||||
//QBO Logs are handled server side.
|
||||
|
||||
await insertExportLog({
|
||||
variables: {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
paymentid: key,
|
||||
successful: true,
|
||||
useremail: currentUser.email,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const paymentUpdateResponse = await updatePayments({
|
||||
variables: {
|
||||
paymentIdList: [key],
|
||||
payment: {
|
||||
exportedat: new Date(),
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!!!paymentUpdateResponse.errors) {
|
||||
notification.open({
|
||||
type: "success",
|
||||
key: "paymentsuccessexport",
|
||||
message: t("payments.successes.exported"),
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("payments.errors.exporting", {
|
||||
error: JSON.stringify(paymentUpdateResponse.error),
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})()
|
||||
@@ -148,6 +157,7 @@ export function PaymentsExportAllButton({
|
||||
await Promise.all(proms);
|
||||
if (!!completedCallback) completedCallback([]);
|
||||
if (!!loadingCallback) loadingCallback(false);
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) refetch();
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
|
||||
@@ -328,6 +328,12 @@ export function ShopEmployeesFormComponent({ bodyshop }) {
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("employees.fields.external_id")}
|
||||
name="external_id"
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<Form.List name={["rates"]}>
|
||||
{(fields, { add, remove, move }) => {
|
||||
|
||||
@@ -1393,6 +1393,60 @@ export default function ShopInfoGeneral({ form }) {
|
||||
}}
|
||||
</Form.List>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow grow header={t("bodyshop.labels.md_to_emails")}>
|
||||
<Form.List name={["md_to_emails"]}>
|
||||
{(fields, { add, remove, move }) => {
|
||||
return (
|
||||
<div>
|
||||
{fields.map((field, index) => (
|
||||
<Form.Item key={field.key}>
|
||||
<LayoutFormRow noDivider>
|
||||
<Form.Item
|
||||
label={t("general.labels.label")}
|
||||
key={`${index}label`}
|
||||
name={[field.name, "label"]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("bodyshop.labels.md_to_emails_emails")}
|
||||
key={`${index}emails`}
|
||||
name={[field.name, "emails"]}
|
||||
>
|
||||
<Select mode="tags" tokenSeparators={[",", ";"]} />
|
||||
</Form.Item>
|
||||
|
||||
<Space>
|
||||
<DeleteFilled
|
||||
onClick={() => {
|
||||
remove(field.name);
|
||||
}}
|
||||
/>
|
||||
<FormListMoveArrows
|
||||
move={move}
|
||||
index={index}
|
||||
total={fields.length}
|
||||
/>
|
||||
</Space>
|
||||
</LayoutFormRow>
|
||||
</Form.Item>
|
||||
))}
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => {
|
||||
add();
|
||||
}}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
{t("general.actions.add")}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</Form.List>
|
||||
</LayoutFormRow>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -237,7 +237,11 @@ export function TimeTicketModalComponent({
|
||||
return Promise.reject(
|
||||
t("timetickets.validation.clockoffwithoutclockon")
|
||||
);
|
||||
if (value && !value.isSameOrAfter(clockon))
|
||||
if (
|
||||
value &&
|
||||
value.isSameOrAfter &&
|
||||
!value.isSameOrAfter(clockon)
|
||||
)
|
||||
return Promise.reject(
|
||||
t("timetickets.validation.clockoffmustbeafterclockon")
|
||||
);
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { Button } from "antd";
|
||||
import queryString from "query-string";
|
||||
import React, { useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { GenerateDocument } from "../../utils/RenderTemplate";
|
||||
import { TemplateList } from "../../utils/TemplateConstants";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import moment from "moment";
|
||||
const AttendanceCsv = TemplateList("special").attendance_detail_csv;
|
||||
|
||||
export default function TimeTicketsAttendanceTable() {
|
||||
const searchParams = queryString.parse(useLocation().search);
|
||||
const { start, end } = searchParams;
|
||||
const { t } = useTranslation();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleClick = async () => {
|
||||
setLoading(true);
|
||||
|
||||
await GenerateDocument(
|
||||
{
|
||||
name: AttendanceCsv.key,
|
||||
variables: {
|
||||
start: start
|
||||
? start
|
||||
: moment().startOf("week").subtract(7, "days").format("YYYY-MM-DD"),
|
||||
end: end ? end : moment().endOf("week").format("YYYY-MM-DD"),
|
||||
},
|
||||
},
|
||||
{},
|
||||
"text"
|
||||
);
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Button loading={loading} onClick={handleClick}>
|
||||
{t("printcenter.special.attendance_detail_csv")}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
@@ -106,6 +106,7 @@ export const QUERY_BODYSHOP = gql`
|
||||
last_name_first
|
||||
md_parts_order_comment
|
||||
bill_allow_post_to_closed
|
||||
md_to_emails
|
||||
employees {
|
||||
user_email
|
||||
id
|
||||
@@ -114,6 +115,7 @@ export const QUERY_BODYSHOP = gql`
|
||||
last_name
|
||||
employee_number
|
||||
rates
|
||||
external_id
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,6 +211,7 @@ export const UPDATE_SHOP = gql`
|
||||
last_name_first
|
||||
md_parts_order_comment
|
||||
bill_allow_post_to_closed
|
||||
md_to_emails
|
||||
employees {
|
||||
id
|
||||
first_name
|
||||
@@ -217,6 +220,7 @@ export const UPDATE_SHOP = gql`
|
||||
employee_number
|
||||
rates
|
||||
user_email
|
||||
external_id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ export const QUERY_EMPLOYEE_BY_ID = gql`
|
||||
rates
|
||||
pin
|
||||
user_email
|
||||
external_id
|
||||
employee_vacations(order_by: { start: desc }) {
|
||||
id
|
||||
start
|
||||
|
||||
@@ -292,6 +292,14 @@ export const DELETE_PARTS_ORDER = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export const DELETE_PARTS_ORDER_LINE = gql`
|
||||
mutation DELETE_PARTS_ORDER_LINE($partsOrderLineId: uuid!) {
|
||||
delete_parts_order_lines_by_pk(id: $partsOrderLineId) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const MUTATION_UPDATE_PO_CM_REECEIVED = gql`
|
||||
mutation MUTATION_UPDATE_PO_CM_REECEIVED(
|
||||
$partsLineId: uuid!
|
||||
|
||||
@@ -45,7 +45,7 @@ export function AccountingPayablesContainer({
|
||||
checkPartnerStatus(bodyshop, true);
|
||||
}, [t, setBreadcrumbs, setSelectedHeader, bodyshop]);
|
||||
|
||||
const { loading, error, data } = useQuery(QUERY_BILLS_FOR_EXPORT, {
|
||||
const { loading, error, data, refetch } = useQuery(QUERY_BILLS_FOR_EXPORT, {
|
||||
fetchPolicy: "network-only",
|
||||
nextFetchPolicy: "network-only",
|
||||
});
|
||||
@@ -73,6 +73,7 @@ export function AccountingPayablesContainer({
|
||||
<AccountingPayablesTable
|
||||
loadaing={loading}
|
||||
bills={data ? data.bills : []}
|
||||
refetch={refetch}
|
||||
/>
|
||||
</RbacWrapper>
|
||||
</div>
|
||||
|
||||
@@ -44,10 +44,13 @@ export function AccountingPaymentsContainer({
|
||||
checkPartnerStatus(bodyshop, true);
|
||||
}, [t, setBreadcrumbs, setSelectedHeader, bodyshop]);
|
||||
|
||||
const { loading, error, data } = useQuery(QUERY_PAYMENTS_FOR_EXPORT, {
|
||||
fetchPolicy: "network-only",
|
||||
nextFetchPolicy: "network-only",
|
||||
});
|
||||
const { loading, error, data, refetch } = useQuery(
|
||||
QUERY_PAYMENTS_FOR_EXPORT,
|
||||
{
|
||||
fetchPolicy: "network-only",
|
||||
nextFetchPolicy: "network-only",
|
||||
}
|
||||
);
|
||||
|
||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||
const noPath =
|
||||
@@ -70,6 +73,7 @@ export function AccountingPaymentsContainer({
|
||||
<AccountingPaymentsTable
|
||||
loadaing={loading}
|
||||
payments={data ? data.payments : []}
|
||||
refetch={refetch}
|
||||
/>
|
||||
</RbacWrapper>
|
||||
</div>
|
||||
|
||||
@@ -44,7 +44,7 @@ export function AccountingReceivablesContainer({
|
||||
checkPartnerStatus(bodyshop, true);
|
||||
}, [t, setBreadcrumbs, setSelectedHeader, bodyshop]);
|
||||
|
||||
const { loading, error, data } = useQuery(QUERY_JOBS_FOR_EXPORT, {
|
||||
const { loading, error, data, refetch } = useQuery(QUERY_JOBS_FOR_EXPORT, {
|
||||
variables: {
|
||||
invoicedStatus: bodyshop.md_ro_statuses.default_invoiced || "Invoiced*",
|
||||
},
|
||||
@@ -75,6 +75,7 @@ export function AccountingReceivablesContainer({
|
||||
<AccountingReceivablesTable
|
||||
loadaing={loading}
|
||||
jobs={data ? data.jobs : []}
|
||||
refetch={refetch}
|
||||
/>
|
||||
</RbacWrapper>
|
||||
</div>
|
||||
|
||||
@@ -14,6 +14,7 @@ import TimeTicketList from "../../components/time-ticket-list/time-ticket-list.c
|
||||
import TimeTicketsPayrollTable from "../../components/time-tickets-payroll-table/time-tickets-payroll-table.component";
|
||||
import TimeTicketsSummaryEmployees from "../../components/time-tickets-summary-employees/time-tickets-summary-employees.component";
|
||||
import { QUERY_TIME_TICKETS_IN_RANGE } from "../../graphql/timetickets.queries";
|
||||
import TimeTicketsAttendanceTable from "../../components/time-tickets-attendance-table/time-tickets-attendance-table.component";
|
||||
import {
|
||||
setBreadcrumbs,
|
||||
setSelectedHeader,
|
||||
@@ -71,6 +72,7 @@ export function TimeTicketsContainer({
|
||||
timetickets={data ? data.timetickets : []}
|
||||
extra={
|
||||
<Space wrap>
|
||||
<TimeTicketsAttendanceTable />
|
||||
<TimeTicketsPayrollTable />
|
||||
<TimeTicketsDatesSelector />
|
||||
</Space>
|
||||
|
||||
@@ -544,6 +544,8 @@
|
||||
"jobstatuses": "Job Statuses",
|
||||
"laborrates": "Labor Rates",
|
||||
"licensing": "Licensing",
|
||||
"md_to_emails": "Preset To Emails",
|
||||
"md_to_emails_emails": "Emails",
|
||||
"messagingpresets": "Messaging Presets",
|
||||
"notemplatesavailable": "No templates available to add.",
|
||||
"notespresets": "Notes Presets",
|
||||
@@ -878,6 +880,7 @@
|
||||
"base_rate": "Base Rate",
|
||||
"cost_center": "Cost Center",
|
||||
"employee_number": "Employee Number",
|
||||
"external_id": "External Employee ID",
|
||||
"first_name": "First Name",
|
||||
"flat_rate": "Flat Rate (Disabled is Straight Time)",
|
||||
"hire_date": "Hire Date",
|
||||
@@ -2172,6 +2175,9 @@
|
||||
"ca_bc_etf_table": "ICBC ETF Table",
|
||||
"exported_payroll": "Payroll Table"
|
||||
},
|
||||
"special": {
|
||||
"attendance_detail_csv": "Attendance Table"
|
||||
},
|
||||
"subjects": {
|
||||
"jobs": {
|
||||
"parts_order": "Parts Order PO: {{ro_number}} - {{name}}"
|
||||
|
||||
@@ -544,6 +544,8 @@
|
||||
"jobstatuses": "",
|
||||
"laborrates": "",
|
||||
"licensing": "",
|
||||
"md_to_emails": "",
|
||||
"md_to_emails_emails": "",
|
||||
"messagingpresets": "",
|
||||
"notemplatesavailable": "",
|
||||
"notespresets": "",
|
||||
@@ -878,6 +880,7 @@
|
||||
"base_rate": "Tasa básica",
|
||||
"cost_center": "Centro de costos",
|
||||
"employee_number": "Numero de empleado",
|
||||
"external_id": "",
|
||||
"first_name": "Nombre de pila",
|
||||
"flat_rate": "Tarifa plana (deshabilitado es tiempo recto)",
|
||||
"hire_date": "Fecha de contratación",
|
||||
@@ -2172,6 +2175,9 @@
|
||||
"ca_bc_etf_table": "",
|
||||
"exported_payroll": ""
|
||||
},
|
||||
"special": {
|
||||
"attendance_detail_csv": ""
|
||||
},
|
||||
"subjects": {
|
||||
"jobs": {
|
||||
"parts_order": ""
|
||||
|
||||
@@ -544,6 +544,8 @@
|
||||
"jobstatuses": "",
|
||||
"laborrates": "",
|
||||
"licensing": "",
|
||||
"md_to_emails": "",
|
||||
"md_to_emails_emails": "",
|
||||
"messagingpresets": "",
|
||||
"notemplatesavailable": "",
|
||||
"notespresets": "",
|
||||
@@ -878,6 +880,7 @@
|
||||
"base_rate": "Taux de base",
|
||||
"cost_center": "Centre de coûts",
|
||||
"employee_number": "Numéro d'employé",
|
||||
"external_id": "",
|
||||
"first_name": "Prénom",
|
||||
"flat_rate": "Taux fixe (désactivé est le temps normal)",
|
||||
"hire_date": "Date d'embauche",
|
||||
@@ -2172,6 +2175,9 @@
|
||||
"ca_bc_etf_table": "",
|
||||
"exported_payroll": ""
|
||||
},
|
||||
"special": {
|
||||
"attendance_detail_csv": ""
|
||||
},
|
||||
"subjects": {
|
||||
"jobs": {
|
||||
"parts_order": ""
|
||||
|
||||
@@ -18,7 +18,8 @@ export default async function RenderTemplate(
|
||||
templateObject,
|
||||
bodyshop,
|
||||
renderAsHtml = false,
|
||||
renderAsExcel = false
|
||||
renderAsExcel = false,
|
||||
renderAsText = false
|
||||
) {
|
||||
//Query assets that match the template name. Must be in format <<templateName>>.query
|
||||
let { contextData, useShopSpecificTemplate } = await fetchContextData(
|
||||
@@ -54,6 +55,7 @@ export default async function RenderTemplate(
|
||||
}),
|
||||
}),
|
||||
...(renderAsExcel ? { recipe: "html-to-xlsx" } : {}),
|
||||
...(renderAsText ? { recipe: "text" } : {}),
|
||||
},
|
||||
data: {
|
||||
...contextData,
|
||||
@@ -254,6 +256,8 @@ export const GenerateDocument = async (
|
||||
} else if (sendType === "x") {
|
||||
console.log("excel");
|
||||
await RenderTemplate(template, bodyshop, false, true);
|
||||
} else if (sendType === "text") {
|
||||
await RenderTemplate(template, bodyshop, false, false, true);
|
||||
} else {
|
||||
await RenderTemplate(template, bodyshop);
|
||||
}
|
||||
|
||||
@@ -1668,6 +1668,13 @@ export const TemplateList = (type, context) => {
|
||||
key: "exported_payroll",
|
||||
disabled: false,
|
||||
},
|
||||
attendance_detail_csv: {
|
||||
title: i18n.t("printcenter.special.attendance_detail_csv"),
|
||||
description: "Est Detail",
|
||||
subject: i18n.t("printcenter.special.attendance_detail_csv"),
|
||||
key: "attendance_detail_csv",
|
||||
disabled: false,
|
||||
},
|
||||
production_by_technician_one: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.production_by_technician_one"
|
||||
|
||||
@@ -858,6 +858,7 @@
|
||||
- md_referral_sources
|
||||
- md_responsibility_centers
|
||||
- md_ro_statuses
|
||||
- md_to_emails
|
||||
- messagingservicesid
|
||||
- pbs_configuration
|
||||
- pbs_serialnumber
|
||||
@@ -944,6 +945,7 @@
|
||||
- md_referral_sources
|
||||
- md_responsibility_centers
|
||||
- md_ro_statuses
|
||||
- md_to_emails
|
||||
- pbs_configuration
|
||||
- phone
|
||||
- prodtargethrs
|
||||
@@ -1953,6 +1955,7 @@
|
||||
- active
|
||||
- created_at
|
||||
- employee_number
|
||||
- external_id
|
||||
- first_name
|
||||
- flat_rate
|
||||
- hire_date
|
||||
@@ -1971,6 +1974,7 @@
|
||||
- active
|
||||
- created_at
|
||||
- employee_number
|
||||
- external_id
|
||||
- first_name
|
||||
- flat_rate
|
||||
- hire_date
|
||||
@@ -1999,6 +2003,7 @@
|
||||
- active
|
||||
- created_at
|
||||
- employee_number
|
||||
- external_id
|
||||
- first_name
|
||||
- flat_rate
|
||||
- hire_date
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Could not auto-generate a down migration.
|
||||
-- Please write an appropriate down migration for the SQL below:
|
||||
-- alter table "public"."bodyshops" add column "md_to_emails" jsonb
|
||||
-- null default jsonb_build_array();
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."bodyshops" add column "md_to_emails" jsonb
|
||||
null default jsonb_build_array();
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Could not auto-generate a down migration.
|
||||
-- Please write an appropriate down migration for the SQL below:
|
||||
-- alter table "public"."employees" add column "external_id" text
|
||||
-- null;
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."employees" add column "external_id" text
|
||||
null;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -71,7 +71,7 @@ exports.default = async (req, res) => {
|
||||
|
||||
exports.refresh = async (oauthClient, req) => {
|
||||
try {
|
||||
logger.log("qbo-token-refresh", "DEBUG", req.user.email, null, null);
|
||||
// logger.log("qbo-token-refresh", "DEBUG", req.user.email, null, null);
|
||||
const authResponse = await oauthClient.refresh();
|
||||
await client.request(queries.SET_QBO_AUTH, {
|
||||
email: req.user.email,
|
||||
@@ -85,7 +85,7 @@ exports.refresh = async (oauthClient, req) => {
|
||||
};
|
||||
|
||||
exports.setNewRefreshToken = async (email, apiResponse) => {
|
||||
logger.log("qbo-token-updated", "DEBUG", email, null, null);
|
||||
//logger.log("qbo-token-updated", "DEBUG", email, null, null);
|
||||
|
||||
await client.request(queries.SET_QBO_AUTH, {
|
||||
email,
|
||||
|
||||
@@ -45,7 +45,7 @@ exports.default = async (req, res) => {
|
||||
await refreshOauthToken(oauthClient, req);
|
||||
|
||||
const BearerToken = req.headers.authorization;
|
||||
const { bills: billsToQuery } = req.body;
|
||||
const { bills: billsToQuery, elgen } = req.body;
|
||||
//Query Job Info
|
||||
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {
|
||||
headers: {
|
||||
@@ -59,8 +59,9 @@ exports.default = async (req, res) => {
|
||||
bills: billsToQuery,
|
||||
});
|
||||
|
||||
const { bills } = result;
|
||||
const { bills, bodyshops } = result;
|
||||
const ret = [];
|
||||
const bodyshop = bodyshops[0];
|
||||
|
||||
for (const bill of bills) {
|
||||
try {
|
||||
@@ -86,9 +87,31 @@ exports.default = async (req, res) => {
|
||||
qbo_realmId,
|
||||
req,
|
||||
bill,
|
||||
vendorRecord
|
||||
vendorRecord,
|
||||
bodyshop
|
||||
);
|
||||
|
||||
// //No error. Mark the job exported & insert export log.
|
||||
if (elgen) {
|
||||
const result = await client
|
||||
.setHeaders({ Authorization: BearerToken })
|
||||
.request(queries.QBO_MARK_BILL_EXPORTED, {
|
||||
billId: bill.id,
|
||||
bill: {
|
||||
exported: true,
|
||||
exported_at: moment().tz(bodyshop.timezone),
|
||||
},
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
billid: bill.id,
|
||||
successful: true,
|
||||
useremail: req.user.email,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
ret.push({ billid: bill.id, success: true });
|
||||
} catch (error) {
|
||||
ret.push({
|
||||
@@ -98,6 +121,26 @@ exports.default = async (req, res) => {
|
||||
(error && error.authResponse && error.authResponse.body) ||
|
||||
(error && error.message),
|
||||
});
|
||||
|
||||
//Add the export log error.
|
||||
if (elgen) {
|
||||
const result = await client
|
||||
.setHeaders({ Authorization: BearerToken })
|
||||
.request(queries.INSERT_EXPORT_LOG, {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
billid: bill.id,
|
||||
successful: false,
|
||||
message: JSON.stringify([
|
||||
(error && error.authResponse && error.authResponse.body) ||
|
||||
(error && error.message),
|
||||
]),
|
||||
useremail: req.user.email,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +210,14 @@ async function InsertVendorRecord(oauthClient, qbo_realmId, req, bill) {
|
||||
}
|
||||
}
|
||||
|
||||
async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor) {
|
||||
async function InsertBill(
|
||||
oauthClient,
|
||||
qbo_realmId,
|
||||
req,
|
||||
bill,
|
||||
vendor,
|
||||
bodyshop
|
||||
) {
|
||||
const { accounts, taxCodes, classes } = await QueryMetaData(
|
||||
oauthClient,
|
||||
qbo_realmId,
|
||||
@@ -179,20 +229,20 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor) {
|
||||
il,
|
||||
accounts,
|
||||
bill.job.class,
|
||||
bill.job.bodyshop.md_responsibility_centers.sales_tax_codes,
|
||||
bodyshop.md_responsibility_centers.sales_tax_codes,
|
||||
classes,
|
||||
taxCodes,
|
||||
bill.job.bodyshop.md_responsibility_centers.costs
|
||||
bodyshop.md_responsibility_centers.costs
|
||||
)
|
||||
);
|
||||
|
||||
//QB USA with GST
|
||||
//This was required for the No. 1 Collision Group.
|
||||
if (
|
||||
bill.job.bodyshop.accountingconfig &&
|
||||
bill.job.bodyshop.accountingconfig.qbo &&
|
||||
bill.job.bodyshop.accountingconfig.qbo_usa &&
|
||||
bill.job.bodyshop.region_config.includes("CA_")
|
||||
bodyshop.accountingconfig &&
|
||||
bodyshop.accountingconfig.qbo &&
|
||||
bodyshop.accountingconfig.qbo_usa &&
|
||||
bodyshop.region_config.includes("CA_")
|
||||
) {
|
||||
lines.push({
|
||||
DetailType: "AccountBasedExpenseLineDetail",
|
||||
@@ -204,8 +254,7 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor) {
|
||||
AccountRef: {
|
||||
value:
|
||||
accounts[
|
||||
bill.job.bodyshop.md_responsibility_centers.taxes.federal
|
||||
.accountdesc
|
||||
bodyshop.md_responsibility_centers.taxes.federal.accountdesc
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -239,7 +288,18 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor) {
|
||||
}),
|
||||
DocNumber: bill.invoice_number,
|
||||
//...(bill.job.class ? { ClassRef: { Id: classes[bill.job.class] } } : {}),
|
||||
|
||||
...(!(
|
||||
bodyshop.accountingconfig &&
|
||||
bodyshop.accountingconfig.qbo &&
|
||||
bodyshop.accountingconfig.qbo_usa &&
|
||||
bodyshop.region_config.includes("CA_")
|
||||
)
|
||||
? { GlobalTaxCalculation: "TaxExcluded" }
|
||||
: {}),
|
||||
...(bodyshop.accountingconfig.qbo_departmentid &&
|
||||
bodyshop.accountingconfig.qbo_departmentid.trim() !== "" && {
|
||||
DepartmentRef: { value: bodyshop.accountingconfig.qbo_departmentid },
|
||||
}),
|
||||
PrivateNote: `RO ${bill.job.ro_number || ""}`,
|
||||
Line: lines,
|
||||
};
|
||||
|
||||
@@ -52,7 +52,7 @@ exports.default = async (req, res) => {
|
||||
await refreshOauthToken(oauthClient, req);
|
||||
|
||||
const BearerToken = req.headers.authorization;
|
||||
const { payments: paymentsToQuery } = req.body;
|
||||
const { payments: paymentsToQuery, elgen } = req.body;
|
||||
//Query Job Info
|
||||
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {
|
||||
headers: {
|
||||
@@ -155,6 +155,27 @@ exports.default = async (req, res) => {
|
||||
bodyshop
|
||||
);
|
||||
}
|
||||
|
||||
// //No error. Mark the payment exported & insert export log.
|
||||
if (elgen) {
|
||||
const result = await client
|
||||
.setHeaders({ Authorization: BearerToken })
|
||||
.request(queries.QBO_MARK_PAYMENT_EXPORTED, {
|
||||
paymentId: payment.id,
|
||||
payment: {
|
||||
exportedat: moment().tz(bodyshop.timezone),
|
||||
},
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
paymentid: payment.id,
|
||||
successful: true,
|
||||
useremail: req.user.email,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
ret.push({ paymentid: payment.id, success: true });
|
||||
} catch (error) {
|
||||
logger.log("qbo-payment-create-error", "ERROR", req.user.email, {
|
||||
@@ -162,6 +183,25 @@ exports.default = async (req, res) => {
|
||||
(error && error.authResponse && error.authResponse.body) ||
|
||||
(error && error.message),
|
||||
});
|
||||
//Add the export log error.
|
||||
if (elgen) {
|
||||
const result = await client
|
||||
.setHeaders({ Authorization: BearerToken })
|
||||
.request(queries.INSERT_EXPORT_LOG, {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
paymentid: payment.id,
|
||||
successful: false,
|
||||
message: JSON.stringify([
|
||||
(error && error.authResponse && error.authResponse.body) ||
|
||||
(error && error.message),
|
||||
]),
|
||||
useremail: req.user.email,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
ret.push({
|
||||
paymentid: payment.id,
|
||||
|
||||
@@ -46,7 +46,7 @@ exports.default = async (req, res) => {
|
||||
await refreshOauthToken(oauthClient, req);
|
||||
|
||||
const BearerToken = req.headers.authorization;
|
||||
const { jobIds } = req.body;
|
||||
const { jobIds, elgen } = req.body;
|
||||
//Query Job Info
|
||||
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {
|
||||
headers: {
|
||||
@@ -139,6 +139,28 @@ exports.default = async (req, res) => {
|
||||
bodyshop,
|
||||
jobTier
|
||||
);
|
||||
|
||||
// //No error. Mark the job exported & insert export log.
|
||||
if (elgen) {
|
||||
const result = await client
|
||||
.setHeaders({ Authorization: BearerToken })
|
||||
.request(queries.QBO_MARK_JOB_EXPORTED, {
|
||||
jobId: job.id,
|
||||
job: {
|
||||
status:
|
||||
bodyshop.md_ro_statuses.default_exported || "Exported*",
|
||||
date_exported: moment().tz(bodyshop.timezone),
|
||||
},
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
jobid: job.id,
|
||||
successful: true,
|
||||
useremail: req.user.email,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
ret.push({ jobid: job.id, success: true });
|
||||
} catch (error) {
|
||||
@@ -149,6 +171,25 @@ exports.default = async (req, res) => {
|
||||
(error && error.authResponse && error.authResponse.body) ||
|
||||
(error && error.message),
|
||||
});
|
||||
//Add the export log error.
|
||||
if (elgen) {
|
||||
const result = await client
|
||||
.setHeaders({ Authorization: BearerToken })
|
||||
.request(queries.INSERT_EXPORT_LOG, {
|
||||
logs: [
|
||||
{
|
||||
bodyshopid: bodyshop.id,
|
||||
jobid: job.id,
|
||||
successful: false,
|
||||
message: JSON.stringify([
|
||||
(error && error.authResponse && error.authResponse.body) ||
|
||||
(error && error.message),
|
||||
]),
|
||||
useremail: req.user.email,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,6 +239,7 @@ async function InsertInsuranceCo(oauthClient, qbo_realmId, req, job, bodyshop) {
|
||||
|
||||
const Customer = {
|
||||
DisplayName: job.ins_co_nm,
|
||||
BillWithParent: true,
|
||||
BillAddr: {
|
||||
City: job.ownr_city,
|
||||
Line1: insCo.street1,
|
||||
@@ -261,6 +303,7 @@ async function InsertOwner(
|
||||
const ownerName = generateOwnerTier(job, true, null);
|
||||
const Customer = {
|
||||
DisplayName: ownerName,
|
||||
BillWithParent: true,
|
||||
BillAddr: {
|
||||
City: job.ownr_city,
|
||||
Line1: job.ownr_addr1,
|
||||
@@ -321,6 +364,7 @@ exports.QueryJob = QueryJob;
|
||||
async function InsertJob(oauthClient, qbo_realmId, req, job, parentTierRef) {
|
||||
const Customer = {
|
||||
DisplayName: job.ro_number,
|
||||
BillWithParent: true,
|
||||
BillAddr: {
|
||||
City: job.ownr_city,
|
||||
Line1: job.ownr_addr1,
|
||||
|
||||
@@ -37,14 +37,15 @@ exports.default = async (req, res) => {
|
||||
.request(queries.QUERY_BILLS_FOR_PAYABLES_EXPORT, {
|
||||
bills: billsToQuery,
|
||||
});
|
||||
const { bills } = result;
|
||||
const { bills, bodyshops } = result;
|
||||
const bodyshop = bodyshops[0];
|
||||
|
||||
const QbXmlToExecute = [];
|
||||
bills.map((i) => {
|
||||
QbXmlToExecute.push({
|
||||
id: i.id,
|
||||
okStatusCodes: ["0"],
|
||||
qbxml: generateBill(i),
|
||||
qbxml: generateBill(i, bodyshop),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -62,7 +63,7 @@ exports.default = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
const generateBill = (bill) => {
|
||||
const generateBill = (bill, bodyshop) => {
|
||||
const billQbxmlObj = {
|
||||
QBXML: {
|
||||
QBXMLMsgsRq: {
|
||||
@@ -87,7 +88,7 @@ const generateBill = (bill) => {
|
||||
ExpenseLineAdd: bill.billlines.map((il) =>
|
||||
generateBillLine(
|
||||
il,
|
||||
bill.job.bodyshop.md_responsibility_centers,
|
||||
bodyshop.md_responsibility_centers,
|
||||
bill.job.class
|
||||
)
|
||||
),
|
||||
|
||||
@@ -217,6 +217,7 @@ query QUERY_JOBS_FOR_RECEIVABLES_EXPORT($ids: [uuid!]!) {
|
||||
accountingconfig
|
||||
md_ins_cos
|
||||
timezone
|
||||
md_ro_statuses
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -408,6 +409,13 @@ query QUERY_JOBS_FOR_PBS_EXPORT($id: uuid!) {
|
||||
|
||||
exports.QUERY_BILLS_FOR_PAYABLES_EXPORT = `
|
||||
query QUERY_BILLS_FOR_PAYABLES_EXPORT($bills: [uuid!]!) {
|
||||
bodyshops(where: {associations: {active: {_eq: true}}}) {
|
||||
id
|
||||
md_responsibility_centers
|
||||
timezone
|
||||
region_config
|
||||
accountingconfig
|
||||
}
|
||||
bills(where: {id: {_in: $bills}}) {
|
||||
id
|
||||
date
|
||||
@@ -424,12 +432,6 @@ query QUERY_BILLS_FOR_PAYABLES_EXPORT($bills: [uuid!]!) {
|
||||
ownr_ln
|
||||
ownr_co_nm
|
||||
class
|
||||
bodyshop{
|
||||
md_responsibility_centers
|
||||
timezone
|
||||
region_config
|
||||
accountingconfig
|
||||
}
|
||||
}
|
||||
billlines{
|
||||
id
|
||||
@@ -1482,6 +1484,7 @@ mutation MARK_JOB_EXPORTED($jobId: uuid!, $job: jobs_set_input!, $log: exportlog
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
exports.INSERT_EXPORT_LOG = `
|
||||
mutation INSERT_EXPORT_LOG($log: exportlog_insert_input!) {
|
||||
insert_exportlog_one(object: $log) {
|
||||
@@ -1534,4 +1537,52 @@ exports.QUERY_JOB_ID_MIXDATA = `query QUERY_JOB_ID_MIXDATA($roNumbers: [String!]
|
||||
}
|
||||
}
|
||||
|
||||
`;
|
||||
`;
|
||||
|
||||
exports.QBO_MARK_JOB_EXPORTED = `
|
||||
mutation QBO_MARK_JOB_EXPORTED($jobId: uuid!, $job: jobs_set_input!, $logs: [exportlog_insert_input!]!) {
|
||||
insert_exportlog(objects: $logs) {
|
||||
affected_rows
|
||||
}
|
||||
update_jobs(where: {id: {_eq: $jobId}}, _set: $job) {
|
||||
returning {
|
||||
id
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
`;
|
||||
exports.QBO_MARK_BILL_EXPORTED = `
|
||||
mutation QBO_MARK_BILL_EXPORTED($billId: uuid!, $bill: bills_set_input!, $logs: [exportlog_insert_input!]!) {
|
||||
insert_exportlog(objects: $logs) {
|
||||
affected_rows
|
||||
}
|
||||
update_bills(where: { id: { _eq: $billId } }, _set: $bill) {
|
||||
returning {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
`;
|
||||
|
||||
exports.QBO_MARK_PAYMENT_EXPORTED = `
|
||||
mutation QBO_MARK_PAYMENT_EXPORTED($paymentId: uuid!, $payment: payments_set_input!, $logs: [exportlog_insert_input!]!) {
|
||||
insert_exportlog(objects: $logs) {
|
||||
affected_rows
|
||||
}
|
||||
update_payments(where: {id: {_eq: $paymentId}}, _set: $payment) {
|
||||
returning {
|
||||
id
|
||||
}
|
||||
}
|
||||
}`;
|
||||
|
||||
exports.INSERT_EXPORT_LOG = `
|
||||
mutation INSERT_EXPORT_LOG($logs: [exportlog_insert_input!]!) {
|
||||
insert_exportlog(objects: $logs) {
|
||||
affected_rows
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user