IO-2261 Opensearch for Payments, Bills and All Jobs

This commit is contained in:
Allan Carr
2023-05-03 16:29:01 -07:00
parent 852fd9c388
commit 759a8ac58c
10 changed files with 198 additions and 86 deletions

View File

@@ -1,5 +1,6 @@
import { SyncOutlined } from "@ant-design/icons";
import { Button, Card, Input, Space, Table, Typography } from "antd";
import axios from "axios";
import _ from "lodash";
import queryString from "query-string";
import React, { useEffect, useState } from "react";
@@ -11,7 +12,6 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import StartChatButton from "../chat-open-button/chat-open-button.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import axios from "axios";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
bodyshop: selectBodyshop,
@@ -209,11 +209,11 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
search: value || search.search,
index: "jobs",
});
setOpenSearchResults(searchData.data.hits.hits.map((s) => s._source));
} catch (error) {
console.log("Error while fetching search results", error);
} finally {
//setLoading(false)
// setLoading(false);
}
}

View File

@@ -1,7 +1,8 @@
import { EditFilled, SyncOutlined } from "@ant-design/icons";
import { Button, Card, Input, Space, Table, Typography } from "antd";
import axios from "axios";
import queryString from "query-string";
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link, useHistory, useLocation } from "react-router-dom";
@@ -10,11 +11,11 @@ import { setModalContext } from "../../redux/modals/modals.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateFormatter, DateTimeFormatter } from "../../utils/DateFormatter";
import { alphaSort } from "../../utils/sorters";
import { TemplateList } from "../../utils/TemplateConstants";
import { alphaSort } from "../../utils/sorters";
import CaBcEtfTableModalContainer from "../ca-bc-etf-table-modal/ca-bc-etf-table-modal.container";
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
@@ -39,6 +40,7 @@ export function PaymentsListPaginated({
bodyshop,
}) {
const search = queryString.parse(useLocation().search);
const [openSearchResults, setOpenSearchResults] = useState([]);
const { page, sortcolumn, sortorder } = search;
const history = useHistory();
const [state, setState] = useState({
@@ -54,11 +56,15 @@ export function PaymentsListPaginated({
key: "ro_number",
sorter: (a, b) => alphaSort(a.job.ro_number, b.job.ro_number),
sortOrder: sortcolumn === "ro_number" && sortorder,
render: (text, record) => (
render: (text, record) => {
return record.job ? (
<Link to={"/manage/jobs/" + record.job.id}>
{record.job.ro_number || t("general.labels.na")}
</Link>
),
) : (
<span>{t("general.labels.na")}</span>
);
},
},
{
title: t("payments.fields.paymentnum"),
@@ -75,13 +81,13 @@ export function PaymentsListPaginated({
sorter: (a, b) => alphaSort(a.job.ownr_ln, b.job.ownr_ln),
sortOrder: sortcolumn === "owner" && sortorder,
render: (text, record) => {
return record.job.owner ? (
<Link to={"/manage/owners/" + record.job.owner.id}>
<OwnerNameDisplay ownerObject={record} />
return record.job?.owner ? (
<Link to={"/manage/owners/" + record.job?.owner?.id}>
<OwnerNameDisplay ownerObject={record.job} />
</Link>
) : (
<span>
<OwnerNameDisplay ownerObject={record} />
<OwnerNameDisplay ownerObject={record.job} />
</span>
);
},
@@ -177,6 +183,28 @@ export function PaymentsListPaginated({
history.push({ search: queryString.stringify(search) });
};
useEffect(() => {
if (search.search && search.search.trim() !== "") {
// setLoading(true);
searchPayments();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
async function searchPayments(value) {
try {
const searchData = await axios.post("/search", {
search: value || search.search,
index: "payments",
});
setOpenSearchResults(searchData.data.hits.hits.map((s) => s._source));
} catch (error) {
console.log("Error while fetching search results", error);
} finally {
// setLoading(false);
}
}
return (
<Card
extra={
@@ -212,6 +240,7 @@ export function PaymentsListPaginated({
onSearch={(value) => {
search.search = value;
history.push({ search: queryString.stringify(search) });
searchPayments(value);
}}
enterButton
/>
@@ -221,15 +250,20 @@ export function PaymentsListPaginated({
<Table
loading={loading}
scroll={{ x: true }}
pagination={{
pagination={
search?.search
? { pageSize: 25 }
: {
position: "top",
pageSize: 25,
current: parseInt(page || 1),
total: total,
}}
showSizeChanger: false,
}
}
columns={columns}
rowKey="id"
dataSource={payments}
dataSource={search?.search ? openSearchResults : payments}
onChange={handleTableChange}
/>
</Card>

View File

@@ -20,13 +20,11 @@ export const DELETE_BILL = gql`
export const QUERY_ALL_BILLS_PAGINATED = gql`
query QUERY_ALL_BILLS_PAGINATED(
$search: String
$offset: Int
$limit: Int
$order: [bills_order_by!]!
) {
search_bills(
args: { search: $search }
bills(
offset: $offset
limit: $limit
order_by: $order
@@ -51,7 +49,7 @@ export const QUERY_ALL_BILLS_PAGINATED = gql`
ro_number
}
}
search_bills_aggregate(args: { search: $search }) {
bills_aggregate {
aggregate {
count(distinct: true)
}

View File

@@ -12,13 +12,11 @@ export const INSERT_NEW_PAYMENT = gql`
export const QUERY_ALL_PAYMENTS_PAGINATED = gql`
query QUERY_ALL_PAYMENTS_PAGINATED(
$search: String
$offset: Int
$limit: Int
$order: [payments_order_by!]!
) {
search_payments(
args: { search: $search }
payments(
offset: $offset
limit: $limit
order_by: $order
@@ -31,9 +29,16 @@ export const QUERY_ALL_PAYMENTS_PAGINATED = gql`
job {
id
ro_number
ownerid
ownr_co_nm
ownr_fn
ownr_ln
owner {
id
ownr_co_nm
ownr_fn
ownr_ln
}
}
transactionid
memo
@@ -44,7 +49,7 @@ export const QUERY_ALL_PAYMENTS_PAGINATED = gql`
stripeid
payer
}
search_payments_aggregate(args: { search: $search }) {
payments_aggregate {
aggregate {
count(distinct: true)
}

View File

@@ -1,7 +1,8 @@
import { SyncOutlined, EditFilled } from "@ant-design/icons";
import { EditFilled, SyncOutlined } from "@ant-design/icons";
import { Button, Card, Checkbox, Input, Space, Table, Typography } from "antd";
import axios from "axios";
import queryString from "query-string";
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link, useHistory, useLocation } from "react-router-dom";
@@ -11,8 +12,8 @@ import PrintWrapperComponent from "../../components/print-wrapper/print-wrapper.
import { setModalContext } from "../../redux/modals/modals.actions";
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";
const mapDispatchToProps = (dispatch) => ({
setPartsOrderContext: (context) =>
@@ -29,15 +30,16 @@ export function BillsListPage({
setPartsOrderContext,
setBillEnterContext,
}) {
const { t } = useTranslation();
const search = queryString.parse(useLocation().search);
const [openSearchResults, setOpenSearchResults] = useState([]);
const { page } = search;
const history = useHistory();
const [state, setState] = useState({
sortedInfo: {},
filteredInfo: { text: "" },
});
const history = useHistory();
const search = queryString.parse(useLocation().search);
const { page } = search;
const Templates = TemplateList("bill");
const { t } = useTranslation();
const columns = [
{
title: t("bills.fields.vendorname"),
@@ -199,11 +201,32 @@ export function BillsListPage({
search.sortcolumn = sorter.order ? sorter.columnKey : null;
search.sortorder = sorter.order;
}
search.sort = JSON.stringify({ [sorter.columnKey]: sorter.order });
history.push({ search: queryString.stringify(search) });
};
useEffect(() => {
if (search.search && search.search.trim() !== "") {
// setLoading(true);
searchBills();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
async function searchBills(value) {
try {
const searchData = await axios.post("/search", {
search: value || search.search,
index: "bills",
});
setOpenSearchResults(searchData.data.hits.hits.map((s) => s._source));
} catch (error) {
console.log("Error while fetching search results", error);
} finally {
// setLoading(false);
}
}
return (
<Card
title={t("bills.labels.bills")}
@@ -243,7 +266,9 @@ export function BillsListPage({
onSearch={(value) => {
search.search = value;
history.push({ search: queryString.stringify(search) });
searchBills(value);
}}
enterButton
/>
</Space>
}
@@ -252,18 +277,24 @@ export function BillsListPage({
<Table
loading={loading}
scroll={{
x: "50%", // y: "40rem"
}}
pagination={{
// scroll={{
// x: "50%", // y: "40rem"
// }}
scroll={{ x: true }}
pagination={
search?.search
? { pageSize: 25 }
: {
position: "top",
pageSize: 25,
current: parseInt(page || 1),
total: total,
}}
showSizeChanger: false,
}
}
columns={columns}
rowKey="id"
dataSource={data}
dataSource={search?.search ? openSearchResults : data}
onChange={handleTableChange}
/>
</Card>

View File

@@ -1,6 +1,6 @@
import { useQuery } from "@apollo/client";
import queryString from "query-string";
import React, { useEffect } from "react";
import { useQuery } from "@apollo/client";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useLocation } from "react-router-dom";
@@ -22,7 +22,7 @@ const mapDispatchToProps = (dispatch) => ({
export function BillsPageContainer({ setBreadcrumbs, setSelectedHeader }) {
const { t } = useTranslation();
const searchParams = queryString.parse(useLocation().search);
const { page, sortcolumn, sortorder, search, searchObj } = searchParams;
const { page, sortcolumn, sortorder, searchObj } = searchParams;
useEffect(() => {
document.title = t("titles.bills-list");
@@ -38,7 +38,6 @@ export function BillsPageContainer({ setBreadcrumbs, setSelectedHeader }) {
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
variables: {
search: search || "",
offset: page ? (page - 1) * 25 : 0,
limit: 25,
order: [
@@ -61,10 +60,10 @@ export function BillsPageContainer({ setBreadcrumbs, setSelectedHeader }) {
<RbacWrapper action="bills:list">
<div>
<BillsPageComponent
data={data ? data.search_bills : []}
data={data ? data.bills : []}
loading={loading}
refetch={refetch}
total={data ? data.search_bills_aggregate.aggregate.count : 0}
total={data ? data.bills_aggregate.aggregate.count : 0}
/>
<BillDetailEditContainer />

View File

@@ -25,7 +25,7 @@ const mapDispatchToProps = (dispatch) => ({
export function AllJobs({ setBreadcrumbs, setSelectedHeader }) {
const searchParams = queryString.parse(useLocation().search);
const { page, sortcolumn, sortorder, search, statusFilters } = searchParams;
const { page, sortcolumn, sortorder, statusFilters } = searchParams;
const { loading, error, data, refetch } = useQuery(
QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED,

View File

@@ -26,7 +26,7 @@ const mapDispatchToProps = (dispatch) => ({
export function AllJobs({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
const searchParams = queryString.parse(useLocation().search);
const { page, sortcolumn, sortorder, search } = searchParams;
const { page, sortcolumn, sortorder, searchObj } = searchParams;
const { loading, error, data, refetch } = useQuery(
QUERY_ALL_PAYMENTS_PAGINATED,
@@ -34,11 +34,12 @@ export function AllJobs({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
variables: {
search: search || "",
offset: page ? (page - 1) * 25 : 0,
limit: 25,
order: [
{
searchObj
? JSON.parse(searchObj)
: {
[sortcolumn || "date"]: sortorder
? sortorder === "descend"
? "desc"
@@ -66,8 +67,8 @@ export function AllJobs({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
refetch={refetch}
loading={loading}
searchParams={searchParams}
total={data ? data.search_payments_aggregate.aggregate.count : 0}
payments={data ? data.search_payments : []}
total={data ? data.payments_aggregate.aggregate.count : 0}
payments={data ? data.payments : []}
/>
</RbacWrapper>
);

View File

@@ -74,12 +74,18 @@ async function OpenSearchUpdateHandler(req, res) {
const jobsData = await gqlclient.request(`query{jobs{
id
bodyshopid:shopid
ro_number
clm_no
clm_total
comment
ins_co_nm
ownr_co_nm
ownr_fn
ownr_ln
ownr_ph1
ownr_ph2
plate_no
ro_number
status
ownr_co_nm
v_model_yr
v_make_desc
v_model_desc
@@ -128,12 +134,12 @@ async function OpenSearchUpdateHandler(req, res) {
vehicles {
id
bodyshopid: shopid
plate_no
v_model_yr
v_model_desc
v_make_desc
v_color
v_vin
plate_no
}
}
`);
@@ -155,11 +161,25 @@ plate_no
payments {
id
amount
paymentnum
created_at
exportedat
memo
payer
paymentnum
transactionid
type
job {
id
ownerid
ownr_co_nm
ownr_fn
ownr_ln
owner {
id
ownr_co_nm
ownr_fn
ownr_ln
}
ro_number
bodyshopid: shopid
}
@@ -187,9 +207,11 @@ plate_no
const billsData = await gqlclient.request(`{
bills {
id
total
invoice_number
date
exported
invoice_number
is_credit_memo
total
vendor {
name
id
@@ -200,9 +222,7 @@ plate_no
bodyshopid: shopid
}
}
}
`);
}`);
for (let i = 0; i <= billsData.bills.length / batchSize; i++) {
const slicedArray = billsData.bills.slice(
i * batchSize,

View File

@@ -66,18 +66,21 @@ async function OpenSearchUpdateHandler(req, res) {
document = _.pick(req.body.event.data.new, [
"id",
"bodyshopid",
"ro_number",
"clm_no",
"clm_total",
"comment",
"ins_co_nm",
"ownr_co_nm",
"ownr_fn",
"ownr_ln",
"ownr_ph1",
"ownr_ph2",
"plate_no",
"ro_number",
"status",
"ownr_co_nm",
"v_model_yr",
"v_make_desc",
"v_model_desc",
"clm_total",
"plate_no",
"ownr_ph1",
]);
document.bodyshopid = req.body.event.data.new.shopid;
break;
@@ -127,8 +130,10 @@ async function OpenSearchUpdateHandler(req, res) {
document = {
..._.pick(req.body.event.data.new, [
"id",
"invoice_number",
"date",
"exported",
"invoice_number",
"is_credit_memo",
]),
...bill.bills_by_pk,
bodyshopid: bill.bills_by_pk.job.shopid,
@@ -145,15 +150,34 @@ async function OpenSearchUpdateHandler(req, res) {
id
ro_number
shopid
ownerid
ownr_co_nm
ownr_fn
ownr_ln
owner {
id
ownr_co_nm
ownr_fn
ownr_ln
}
}
}
}
`,
{ paymentId: req.body.event.data.new.id }
);
document = {
..._.pick(req.body.event.data.new, ["id", "invoice_number"]),
..._.pick(req.body.event.data.new, [
"id",
"amount",
"created_at",
"exportedat",
"memo",
"payer",
"paymentnum",
"transactionid",
"type",
]),
...payment.payments_by_pk,
bodyshopid: bill.payments_by_pk.job.shopid,
};