IO-1186 Export customer data.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
<babeledit_project be_version="2.7.1" version="1.2">
|
<babeledit_project version="1.2" be_version="2.7.1">
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
BabelEdit project file
|
BabelEdit project file
|
||||||
@@ -16285,6 +16285,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>exportcustdata</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>
|
<concept_node>
|
||||||
<name>exportselected</name>
|
<name>exportselected</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
import AddToProduction from "./jobs-detail-header-actions.addtoproduction.util";
|
import AddToProduction from "./jobs-detail-header-actions.addtoproduction.util";
|
||||||
import JobsDetaiLheaderCsi from "./jobs-detail-header-actions.csi.component";
|
import JobsDetaiLheaderCsi from "./jobs-detail-header-actions.csi.component";
|
||||||
import DuplicateJob from "./jobs-detail-header-actions.duplicate.util";
|
import DuplicateJob from "./jobs-detail-header-actions.duplicate.util";
|
||||||
|
import JobsDetailHeaderActionsExportcustdataComponent from "./jobs-detail-header-actions.exportcustdata.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -316,6 +317,7 @@ export function JobsDetailHeaderActions({
|
|||||||
{t("menus.jobsactions.admin")}
|
{t("menus.jobsactions.admin")}
|
||||||
</Link>
|
</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
<JobsDetailHeaderActionsExportcustdataComponent job={job} />
|
||||||
<JobsDetaiLheaderCsi job={job} />
|
<JobsDetaiLheaderCsi job={job} />
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="jobcosting"
|
key="jobcosting"
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
import { Menu, notification } from "antd";
|
||||||
|
import axios from "axios";
|
||||||
|
import React from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { auth, logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
|
});
|
||||||
|
const mapDispatchToProps = (dispatch) => ({});
|
||||||
|
|
||||||
|
export function JobsDetailHeaderActionexportCustomerData({
|
||||||
|
bodyshop,
|
||||||
|
job,
|
||||||
|
...props
|
||||||
|
}) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const handleExportCustData = async (e) => {
|
||||||
|
logImEXEvent("job_export_cust_data");
|
||||||
|
let QbXmlResponse;
|
||||||
|
try {
|
||||||
|
QbXmlResponse = await axios.post(
|
||||||
|
"/accounting/qbxml/receivables",
|
||||||
|
{ jobIds: [job.id], custDataOnly: true },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
console.log("handle -> XML", QbXmlResponse);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error getting QBXML from Server.", error);
|
||||||
|
notification["error"]({
|
||||||
|
message: t("jobs.errors.exporting", {
|
||||||
|
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let PartnerResponse;
|
||||||
|
try {
|
||||||
|
PartnerResponse = await axios.post(
|
||||||
|
"http://localhost:1337/qb/",
|
||||||
|
QbXmlResponse.data,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error connecting to quickbooks or partner.", error);
|
||||||
|
notification["error"]({
|
||||||
|
message: t("jobs.errors.exporting-partner"),
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Check to see if any of them failed. If they didn't don't execute the update.
|
||||||
|
const failedTransactions = PartnerResponse.data.filter((r) => !r.success);
|
||||||
|
if (failedTransactions.length > 0) {
|
||||||
|
//Uh oh. At least one was no good.
|
||||||
|
failedTransactions.forEach((ft) => {
|
||||||
|
//insert failed export log
|
||||||
|
notification.open({
|
||||||
|
// key: "failedexports",
|
||||||
|
type: "error",
|
||||||
|
message: t("jobs.errors.exporting", {
|
||||||
|
error: ft.errorMessage || "",
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//Handle Failures.
|
||||||
|
} else {
|
||||||
|
//Insert success export log.
|
||||||
|
|
||||||
|
notification.open({
|
||||||
|
type: "success",
|
||||||
|
key: "jobsuccessexport",
|
||||||
|
message: t("jobs.successes.exported"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Menu.Item
|
||||||
|
{...props}
|
||||||
|
onClick={handleExportCustData}
|
||||||
|
key="exportcustdata"
|
||||||
|
disabled={!job.converted}
|
||||||
|
>
|
||||||
|
{t("jobs.actions.exportcustdata")}
|
||||||
|
</Menu.Item>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(JobsDetailHeaderActionexportCustomerData);
|
||||||
@@ -50,8 +50,8 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
width: "25%",
|
width: "25%",
|
||||||
//sortOrder: sortcolumn === "ownr_ln" && sortorder,
|
//sortOrder: sortcolumn === "ownr_ln" && sortorder,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.owner ? (
|
return record.ownerid ? (
|
||||||
<Link to={"/manage/owners/" + record.owner.id}>
|
<Link to={"/manage/owners/" + record.ownerid}>
|
||||||
{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
||||||
record.ownr_co_nm || ""
|
record.ownr_co_nm || ""
|
||||||
}`}
|
}`}
|
||||||
|
|||||||
@@ -1611,6 +1611,7 @@ export const QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED = gql`
|
|||||||
) {
|
) {
|
||||||
ownr_fn
|
ownr_fn
|
||||||
ownr_ln
|
ownr_ln
|
||||||
|
ownerid
|
||||||
ownr_ph1
|
ownr_ph1
|
||||||
ownr_ea
|
ownr_ea
|
||||||
plate_no
|
plate_no
|
||||||
|
|||||||
@@ -1023,6 +1023,7 @@
|
|||||||
"convert": "Convert",
|
"convert": "Convert",
|
||||||
"deliver": "Deliver",
|
"deliver": "Deliver",
|
||||||
"export": "Export",
|
"export": "Export",
|
||||||
|
"exportcustdata": "Export Customer Data",
|
||||||
"exportselected": "Export Selected",
|
"exportselected": "Export Selected",
|
||||||
"filterpartsonly": "Filter Parts Only",
|
"filterpartsonly": "Filter Parts Only",
|
||||||
"generatecsi": "Generate CSI & Copy Link",
|
"generatecsi": "Generate CSI & Copy Link",
|
||||||
|
|||||||
@@ -1023,6 +1023,7 @@
|
|||||||
"convert": "Convertir",
|
"convert": "Convertir",
|
||||||
"deliver": "",
|
"deliver": "",
|
||||||
"export": "",
|
"export": "",
|
||||||
|
"exportcustdata": "",
|
||||||
"exportselected": "",
|
"exportselected": "",
|
||||||
"filterpartsonly": "",
|
"filterpartsonly": "",
|
||||||
"generatecsi": "",
|
"generatecsi": "",
|
||||||
|
|||||||
@@ -1023,6 +1023,7 @@
|
|||||||
"convert": "Convertir",
|
"convert": "Convertir",
|
||||||
"deliver": "",
|
"deliver": "",
|
||||||
"export": "",
|
"export": "",
|
||||||
|
"exportcustdata": "",
|
||||||
"exportselected": "",
|
"exportselected": "",
|
||||||
"filterpartsonly": "",
|
"filterpartsonly": "",
|
||||||
"generatecsi": "",
|
"generatecsi": "",
|
||||||
|
|||||||
@@ -75,17 +75,20 @@ exports.default = async (req, res) => {
|
|||||||
twoTierPref
|
twoTierPref
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
//Generate the actual invoice.
|
|
||||||
QbXmlToExecute.push({
|
if (!req.body.custDataOnly) {
|
||||||
id: jobs_by_pk.id,
|
//Generate the actual invoice.
|
||||||
okStatusCodes: ["0"],
|
QbXmlToExecute.push({
|
||||||
qbxml: generateInvoiceQbxml(
|
id: jobs_by_pk.id,
|
||||||
jobs_by_pk,
|
okStatusCodes: ["0"],
|
||||||
bodyshop,
|
qbxml: generateInvoiceQbxml(
|
||||||
isThreeTier,
|
jobs_by_pk,
|
||||||
twoTierPref
|
bodyshop,
|
||||||
),
|
isThreeTier,
|
||||||
});
|
twoTierPref
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
res.status(200).json(QbXmlToExecute);
|
res.status(200).json(QbXmlToExecute);
|
||||||
|
|||||||
Reference in New Issue
Block a user