diff --git a/client/src/App/App.styles.scss b/client/src/App/App.styles.scss index b57e94677..ddf87ac42 100644 --- a/client/src/App/App.styles.scss +++ b/client/src/App/App.styles.scss @@ -145,7 +145,7 @@ //Update row highlighting on production board. .ant-table-tbody > tr.ant-table-row:hover > td { - background: #eaeaea !important; + background: #e7f3ff !important; } .job-line-manual { diff --git a/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx b/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx index ffc087ae2..0642884c1 100644 --- a/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx +++ b/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx @@ -1,13 +1,18 @@ import { Badge, List, Tag } from "antd"; -import React, { useEffect } from "react"; +import React from "react"; import { connect } from "react-redux"; +import { + AutoSizer, + CellMeasurer, + CellMeasurerCache, + List as VirtualizedList, +} from "react-virtualized"; import { createStructuredSelector } from "reselect"; import { setSelectedConversation } from "../../redux/messaging/messaging.actions"; import { selectSelectedConversation } from "../../redux/messaging/messaging.selectors"; import { TimeAgoFormatter } from "../../utils/DateFormatter"; import PhoneFormatter from "../../utils/PhoneFormatter"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; -import { List as VirtualizedList, AutoSizer } from "react-virtualized"; import "./chat-conversation-list.styles.scss"; @@ -24,57 +29,66 @@ function ChatConversationListComponent({ conversationList, selectedConversation, setSelectedConversation, - subscribeToMoreConversations, loadMoreConversations, }) { - useEffect( - () => subscribeToMoreConversations(), - // eslint-disable-next-line react-hooks/exhaustive-deps - [] - ); + const cache = new CellMeasurerCache({ + fixedWidth: true, + defaultHeight: 60, + }); - const rowRenderer = ({ index, key, style }) => { + const rowRenderer = ({ index, key, style, parent }) => { const item = conversationList[index]; return ( - setSelectedConversation(item.id)} - className={`chat-list-item ${ - item.id === selectedConversation - ? "chat-list-selected-conversation" - : null - }`} - style={style} + cache={cache} + parent={parent} + columnIndex={0} + rowIndex={index} > -
- {item.label &&
{item.label}
} - {item.job_conversations.length > 0 ? ( -
- {item.job_conversations.map((j, idx) => ( -
- -
- ))} -
- ) : ( - {item.phone_num} - )} -
-
-
- {item.job_conversations.length > 0 - ? item.job_conversations.map((j, idx) => ( - - {j.job.ro_number} - - )) - : null} + setSelectedConversation(item.id)} + className={`chat-list-item ${ + item.id === selectedConversation + ? "chat-list-selected-conversation" + : null + }`} + style={style} + > +
+ {item.label &&
{item.label}
} + {item.job_conversations.length > 0 ? ( +
+ {item.job_conversations.map((j, idx) => ( +
+ +
+ ))} +
+ ) : ( + {item.phone_num} + )}
- {item.updated_at} -
- - +
+
+ {item.job_conversations.length > 0 + ? item.job_conversations.map((j, idx) => ( + + {j.job.ro_number} + + )) + : null} +
+ {item.updated_at} +
+ + + ); }; @@ -86,7 +100,7 @@ function ChatConversationListComponent({ height={height} width={width} rowCount={conversationList.length} - rowHeight={60} + rowHeight={cache.rowHeight} rowRenderer={rowRenderer} onScroll={({ scrollTop, scrollHeight, clientHeight }) => { if (scrollTop + clientHeight === scrollHeight) { diff --git a/client/src/components/chat-popup/chat-popup.component.jsx b/client/src/components/chat-popup/chat-popup.component.jsx index 1c80d7c4c..6d582bdab 100644 --- a/client/src/components/chat-popup/chat-popup.component.jsx +++ b/client/src/components/chat-popup/chat-popup.component.jsx @@ -4,7 +4,7 @@ import { ShrinkOutlined, SyncOutlined, } from "@ant-design/icons"; -import { useLazyQuery, useSubscription } from "@apollo/client"; +import { useLazyQuery, useQuery } from "@apollo/client"; import { Badge, Card, Col, Row, Space, Tag, Tooltip, Typography } from "antd"; import React, { useCallback, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; @@ -12,8 +12,7 @@ import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { CONVERSATION_LIST_QUERY, - CONVERSATION_LIST_SUBSCRIPTION, - UNREAD_CONVERSATION_COUNT_SUBSCRIPTION, + UNREAD_CONVERSATION_COUNT, } from "../../graphql/conversations.queries"; import { toggleChatVisible } from "../../redux/messaging/messaging.actions"; import { @@ -42,19 +41,20 @@ export function ChatPopupComponent({ const { t } = useTranslation(); const [pollInterval, setpollInterval] = useState(0); - const { data: unreadData } = useSubscription( - UNREAD_CONVERSATION_COUNT_SUBSCRIPTION - ); - - const [ - getConversations, - { loading, data, called, refetch, fetchMore, subscribeToMore }, - ] = useLazyQuery(CONVERSATION_LIST_QUERY, { + const { data: unreadData } = useQuery(UNREAD_CONVERSATION_COUNT, { fetchPolicy: "network-only", nextFetchPolicy: "network-only", - skip: !chatVisible, + ...(pollInterval > 0 ? { pollInterval } : {}), }); + const [getConversations, { loading, data, refetch, fetchMore }] = + useLazyQuery(CONVERSATION_LIST_QUERY, { + fetchPolicy: "network-only", + nextFetchPolicy: "network-only", + skip: !chatVisible, + ...(pollInterval > 0 ? { pollInterval } : {}), + }); + const fcmToken = sessionStorage.getItem("fcmtoken"); useEffect(() => { @@ -66,13 +66,13 @@ export function ChatPopupComponent({ }, [fcmToken]); useEffect(() => { - if (called && chatVisible) + if (chatVisible) getConversations({ variables: { offset: 0, }, }); - }, [chatVisible, called, getConversations]); + }, [chatVisible, getConversations]); const loadMoreConversations = useCallback(() => { if (data) @@ -119,43 +119,6 @@ export function ChatPopupComponent({ - subscribeToMore({ - document: CONVERSATION_LIST_SUBSCRIPTION, - variables: { offset: 0 }, - updateQuery: (prev, { subscriptionData }) => { - if ( - !subscriptionData.data || - subscriptionData.data.conversations.length === 0 - ) - return prev; - - let conversations = [...prev.conversations]; - const newConversations = - subscriptionData.data.conversations; - - for (const conversation of newConversations) { - const index = conversations.findIndex( - (prevConversation) => - prevConversation.id === conversation.id - ); - - if (index !== -1) { - conversations.splice(index, 1); - conversations.unshift(conversation); - - continue; - } - - conversations.unshift(conversation); - } - - return Object.assign({}, prev, { - conversations: conversations, - }); - }, - }) - } /> )} diff --git a/client/src/components/dms-allocations-summary-ap/dms-allocations-summary-ap.component.jsx b/client/src/components/dms-allocations-summary-ap/dms-allocations-summary-ap.component.jsx index 1da53e3ba..54651544d 100644 --- a/client/src/components/dms-allocations-summary-ap/dms-allocations-summary-ap.component.jsx +++ b/client/src/components/dms-allocations-summary-ap/dms-allocations-summary-ap.component.jsx @@ -66,7 +66,7 @@ export function DmsAllocationsSummaryAp({ socket, bodyshop, billids, title }) { key: "status", }, { - title: t("jobs.fields.ro_number"), + title: t("bills.fields.invoice_number"), dataIndex: ["Posting", "Reference"], key: "reference", }, diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx index ecb12a1a4..81f11c338 100644 --- a/client/src/components/header/header.component.jsx +++ b/client/src/components/header/header.component.jsx @@ -334,7 +334,9 @@ function Header({ icon={} > }> - {t("menus.header.shop_config")} + + {t("menus.header.shop_config")} + }> {t("menus.header.dashboard")} diff --git a/client/src/components/shop-info/shop-info.component.jsx b/client/src/components/shop-info/shop-info.component.jsx index 1cc44dc72..ac3be4bde 100644 --- a/client/src/components/shop-info/shop-info.component.jsx +++ b/client/src/components/shop-info/shop-info.component.jsx @@ -53,7 +53,9 @@ export function ShopInfoComponent({ bodyshop, form, saveLoading }) { - history.push({ search: `?tab=${search.tab}&subtab=${key}` }) + history.push({ + search: `?tab=${search.tab}&subtab=${key}`, + }) } > diff --git a/client/src/components/update-alert/update-alert.component.jsx b/client/src/components/update-alert/update-alert.component.jsx new file mode 100644 index 000000000..f0b11520e --- /dev/null +++ b/client/src/components/update-alert/update-alert.component.jsx @@ -0,0 +1,78 @@ +import { Alert, Button, Col, Row, Space } from "antd"; +import i18n from "i18next"; +import React from "react"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectUpdateAvailable } from "../../redux/application/application.selectors"; +import { AlertOutlined } from "@ant-design/icons"; +import { useTranslation } from "react-i18next"; +import { setUpdateAvailable } from "../../redux/application/application.actions"; +import { store } from "../../redux/store"; +import * as serviceWorkerRegistration from "../../serviceWorkerRegistration"; + +let globalRegistration; + +const mapStateToProps = createStructuredSelector({ + updateAvailable: selectUpdateAvailable, +}); +const mapDispatchToProps = (dispatch) => ({ + //setUserLanguage: language => dispatch(setUserLanguage(language)) +}); +export default connect(mapStateToProps, mapDispatchToProps)(UpdateAlert); + +export function UpdateAlert({ updateAvailable }) { + const { t } = useTranslation(); + if (!updateAvailable) return null; + return ( + } + description={ + + + {t("general.messages.newversionmessage")} + + + + + + + + + } + closable={false} + type="warning" + /> + ); +} + +const onServiceWorkerUpdate = (registration) => { + console.log("onServiceWorkerUpdate", registration); + globalRegistration = registration; + store.dispatch(setUpdateAvailable(true)); +}; + +serviceWorkerRegistration.register({ onUpdate: onServiceWorkerUpdate }); diff --git a/client/src/graphql/conversations.queries.js b/client/src/graphql/conversations.queries.js index f9feb3f2f..315ba1a5d 100644 --- a/client/src/graphql/conversations.queries.js +++ b/client/src/graphql/conversations.queries.js @@ -1,37 +1,5 @@ import { gql } from "@apollo/client"; -export const CONVERSATION_LIST_SUBSCRIPTION = gql` - subscription CONVERSATION_LIST_SUBSCRIPTION($offset: Int!) { - conversations( - order_by: { updated_at: desc } - limit: 1 - offset: $offset - where: { archived: { _eq: false } } - ) { - phone_num - id - updated_at - unreadcnt - messages_aggregate( - where: { read: { _eq: false }, isoutbound: { _eq: false } } - ) { - aggregate { - count - } - } - job_conversations { - job { - id - ro_number - ownr_fn - ownr_ln - ownr_co_nm - } - } - } - } -`; - export const UNREAD_CONVERSATION_COUNT = gql` query UNREAD_CONVERSATION_COUNT { messages_aggregate( @@ -44,18 +12,6 @@ export const UNREAD_CONVERSATION_COUNT = gql` } `; -export const UNREAD_CONVERSATION_COUNT_SUBSCRIPTION = gql` - subscription UNREAD_CONVERSATION_COUNT_SUBSCRIPTION { - messages_aggregate( - where: { read: { _eq: false }, isoutbound: { _eq: false } } - ) { - aggregate { - count - } - } - } -`; - export const CONVERSATION_LIST_QUERY = gql` query CONVERSATION_LIST_QUERY($offset: Int!) { conversations( diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx index 879b487bc..da52ac064 100644 --- a/client/src/pages/manage/manage.page.component.jsx +++ b/client/src/pages/manage/manage.page.component.jsx @@ -25,6 +25,7 @@ import { import * as Sentry from "@sentry/react"; import "./manage.page.styles.scss"; +import UpdateAlert from "../../components/update-alert/update-alert.component"; const ManageRootPage = lazy(() => import("../manage-root/manage-root.page.container") @@ -410,6 +411,7 @@ export function Manage({ match, conflict, bodyshop }) { <> + diff --git a/client/src/pages/manage/manage.page.container.jsx b/client/src/pages/manage/manage.page.container.jsx index 75f4da328..04505ce2a 100644 --- a/client/src/pages/manage/manage.page.container.jsx +++ b/client/src/pages/manage/manage.page.container.jsx @@ -6,7 +6,7 @@ import AlertComponent from "../../components/alert/alert.component"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; import { QUERY_BODYSHOP } from "../../graphql/bodyshop.queries"; import { setBodyshop } from "../../redux/user/user.actions"; -import "../../utils/RegisterSw"; +//import "../../utils/RegisterSw"; import ManagePage from "./manage.page.component"; const mapDispatchToProps = (dispatch) => ({ diff --git a/client/src/pages/shop/shop.page.component.jsx b/client/src/pages/shop/shop.page.component.jsx index 5f26142ce..e7987ee9e 100644 --- a/client/src/pages/shop/shop.page.component.jsx +++ b/client/src/pages/shop/shop.page.component.jsx @@ -42,6 +42,10 @@ export function ShopPage({ bodyshop, setSelectedHeader, setBreadcrumbs }) { ]); }, [t, setSelectedHeader, setBreadcrumbs, bodyshop.shopname]); + useEffect(() => { + if (!search.tab) history.push({ search: "?tab=info" }); + }, [history, search]); + return ( import("../../components/time-ticket-modal/time-ticket-modal.container") ); @@ -56,7 +57,9 @@ export function TechPage({ technician, match }) { {technician ? null : } + + ({ type: ApplicationActionTypes.SET_PROBLEM_JOBS, payload: problemJobs, }); + +export const setUpdateAvailable = (isUpdateAvailable) => ({ + type: ApplicationActionTypes.SET_UPDATE_AVAILABLE, + payload: isUpdateAvailable, +}); diff --git a/client/src/redux/application/application.reducer.js b/client/src/redux/application/application.reducer.js index 95579574a..0b428209b 100644 --- a/client/src/redux/application/application.reducer.js +++ b/client/src/redux/application/application.reducer.js @@ -3,6 +3,7 @@ import ApplicationActionTypes from "./application.types"; const INITIAL_STATE = { loading: false, online: true, + updateAvailable: false, breadcrumbs: [], recentItems: [], selectedHeader: "home", @@ -18,6 +19,11 @@ const INITIAL_STATE = { const applicationReducer = (state = INITIAL_STATE, action) => { switch (action.type) { + case ApplicationActionTypes.SET_UPDATE_AVAILABLE: + return { + ...state, + updateAvailable: action.payload, + }; case ApplicationActionTypes.SET_SELECTED_HEADER: return { ...state, diff --git a/client/src/redux/application/application.selectors.js b/client/src/redux/application/application.selectors.js index cb5e2c679..e9b293d62 100644 --- a/client/src/redux/application/application.selectors.js +++ b/client/src/redux/application/application.selectors.js @@ -48,3 +48,7 @@ export const selectProblemJobs = createSelector( [selectApplication], (application) => application.problemJobs ); +export const selectUpdateAvailable = createSelector( + [selectApplication], + (application) => application.updateAvailable +); diff --git a/client/src/redux/application/application.types.js b/client/src/redux/application/application.types.js index 1e047bb82..9b95dd6ee 100644 --- a/client/src/redux/application/application.types.js +++ b/client/src/redux/application/application.types.js @@ -12,5 +12,6 @@ const ApplicationActionTypes = { SET_ONLINE_STATUS: "SET_ONLINE_STATUS", INSERT_AUDIT_TRAIL: "INSERT_AUDIT_TRAIL", SET_PROBLEM_JOBS: "SET_PROBLEM_JOBS", + SET_UPDATE_AVAILABLE: "SET_UPDATE_AVAILABLE" }; export default ApplicationActionTypes; diff --git a/client/src/utils/RegisterSw.js b/client/src/utils/RegisterSw.js index 213e73552..3394ee0cf 100644 --- a/client/src/utils/RegisterSw.js +++ b/client/src/utils/RegisterSw.js @@ -3,6 +3,7 @@ import { Button, notification, Space } from "antd"; import i18n from "i18next"; import React from "react"; import * as serviceWorkerRegistration from "../serviceWorkerRegistration"; +import { store } from "../redux/store"; const onServiceWorkerUpdate = (registration) => { console.log("onServiceWorkerUpdate", registration); @@ -33,6 +34,9 @@ const onServiceWorkerUpdate = (registration) => { ); + + store.dispatch() + notification.open({ icon: , message: i18n.t("general.messages.newversiontitle"), diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml index b86dd17fb..111374fb5 100644 --- a/hasura/metadata/tables.yaml +++ b/hasura/metadata/tables.yaml @@ -2690,6 +2690,13 @@ table: name: inventory schema: public + - name: parts_dispatch_lines + using: + foreign_key_constraint_on: + column: joblineid + table: + name: parts_dispatch_lines + schema: public - name: parts_order_lines using: foreign_key_constraint_on: @@ -3131,6 +3138,13 @@ table: name: notes schema: public + - name: parts_dispatches + using: + foreign_key_constraint_on: + column: jobid + table: + name: parts_dispatch + schema: public - name: parts_orders using: foreign_key_constraint_on: @@ -4556,6 +4570,165 @@ template_engine: Kriti url: '{{$base_url}}/opensearch' version: 2 +- table: + name: parts_dispatch + schema: public + object_relationships: + - name: job + using: + foreign_key_constraint_on: jobid + array_relationships: + - name: parts_dispatch_lines + using: + foreign_key_constraint_on: + column: partsdispatchid + table: + name: parts_dispatch_lines + schema: public + insert_permissions: + - role: user + permission: + check: + job: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + columns: + - id + - created_at + - updated_at + - jobid + - number + - employeeid + - dispatched_at + - dispatched_by + select_permissions: + - role: user + permission: + columns: + - number + - dispatched_by + - created_at + - dispatched_at + - updated_at + - employeeid + - id + - jobid + filter: + job: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + update_permissions: + - role: user + permission: + columns: + - number + - dispatched_by + - created_at + - dispatched_at + - updated_at + - employeeid + - id + - jobid + filter: + job: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + check: null +- table: + name: parts_dispatch_lines + schema: public + object_relationships: + - name: jobline + using: + foreign_key_constraint_on: joblineid + - name: parts_dispatch + using: + foreign_key_constraint_on: partsdispatchid + insert_permissions: + - role: user + permission: + check: + parts_dispatch: + job: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + columns: + - id + - created_at + - updated_at + - partsdispatchid + - joblineid + - quantity + - accepted_at + select_permissions: + - role: user + permission: + columns: + - quantity + - accepted_at + - created_at + - updated_at + - id + - joblineid + - partsdispatchid + filter: + parts_dispatch: + job: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + update_permissions: + - role: user + permission: + columns: + - id + - created_at + - updated_at + - partsdispatchid + - joblineid + - quantity + - accepted_at + filter: + parts_dispatch: + job: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + check: null - table: name: parts_order_lines schema: public diff --git a/hasura/migrations/1685561607407_create_table_public_parts_dispatch/down.sql b/hasura/migrations/1685561607407_create_table_public_parts_dispatch/down.sql new file mode 100644 index 000000000..42325ddf5 --- /dev/null +++ b/hasura/migrations/1685561607407_create_table_public_parts_dispatch/down.sql @@ -0,0 +1 @@ +DROP TABLE "public"."parts_dispatch"; diff --git a/hasura/migrations/1685561607407_create_table_public_parts_dispatch/up.sql b/hasura/migrations/1685561607407_create_table_public_parts_dispatch/up.sql new file mode 100644 index 000000000..d8c7c2729 --- /dev/null +++ b/hasura/migrations/1685561607407_create_table_public_parts_dispatch/up.sql @@ -0,0 +1,18 @@ +CREATE TABLE "public"."parts_dispatch" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), "jobid" uuid NOT NULL, "number" serial NOT NULL, "employeeid" uuid NOT NULL, "dispatched_at" timestamptz NOT NULL, "dispatched_by" text NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("jobid") REFERENCES "public"."jobs"("id") ON UPDATE cascade ON DELETE cascade); +CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() +RETURNS TRIGGER AS $$ +DECLARE + _new record; +BEGIN + _new := NEW; + _new."updated_at" = NOW(); + RETURN _new; +END; +$$ LANGUAGE plpgsql; +CREATE TRIGGER "set_public_parts_dispatch_updated_at" +BEFORE UPDATE ON "public"."parts_dispatch" +FOR EACH ROW +EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); +COMMENT ON TRIGGER "set_public_parts_dispatch_updated_at" ON "public"."parts_dispatch" +IS 'trigger to set value of column "updated_at" to current timestamp on row update'; +CREATE EXTENSION IF NOT EXISTS pgcrypto; diff --git a/hasura/migrations/1685561715531_create_table_public_parts_dispatch_lines/down.sql b/hasura/migrations/1685561715531_create_table_public_parts_dispatch_lines/down.sql new file mode 100644 index 000000000..a12867253 --- /dev/null +++ b/hasura/migrations/1685561715531_create_table_public_parts_dispatch_lines/down.sql @@ -0,0 +1 @@ +DROP TABLE "public"."parts_dispatch_lines"; diff --git a/hasura/migrations/1685561715531_create_table_public_parts_dispatch_lines/up.sql b/hasura/migrations/1685561715531_create_table_public_parts_dispatch_lines/up.sql new file mode 100644 index 000000000..5146e2c7e --- /dev/null +++ b/hasura/migrations/1685561715531_create_table_public_parts_dispatch_lines/up.sql @@ -0,0 +1,18 @@ +CREATE TABLE "public"."parts_dispatch_lines" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), "partsdispatchid" UUID NOT NULL, "joblineid" uuid NOT NULL, "quantity" numeric NOT NULL DEFAULT 1, "accepted_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("joblineid") REFERENCES "public"."joblines"("id") ON UPDATE cascade ON DELETE cascade); +CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() +RETURNS TRIGGER AS $$ +DECLARE + _new record; +BEGIN + _new := NEW; + _new."updated_at" = NOW(); + RETURN _new; +END; +$$ LANGUAGE plpgsql; +CREATE TRIGGER "set_public_parts_dispatch_lines_updated_at" +BEFORE UPDATE ON "public"."parts_dispatch_lines" +FOR EACH ROW +EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); +COMMENT ON TRIGGER "set_public_parts_dispatch_lines_updated_at" ON "public"."parts_dispatch_lines" +IS 'trigger to set value of column "updated_at" to current timestamp on row update'; +CREATE EXTENSION IF NOT EXISTS pgcrypto; diff --git a/hasura/migrations/1686082869359_set_fk_public_parts_dispatch_lines_partsdispatchid/down.sql b/hasura/migrations/1686082869359_set_fk_public_parts_dispatch_lines_partsdispatchid/down.sql new file mode 100644 index 000000000..ce1f733b9 --- /dev/null +++ b/hasura/migrations/1686082869359_set_fk_public_parts_dispatch_lines_partsdispatchid/down.sql @@ -0,0 +1 @@ +alter table "public"."parts_dispatch_lines" drop constraint "parts_dispatch_lines_partsdispatchid_fkey"; diff --git a/hasura/migrations/1686082869359_set_fk_public_parts_dispatch_lines_partsdispatchid/up.sql b/hasura/migrations/1686082869359_set_fk_public_parts_dispatch_lines_partsdispatchid/up.sql new file mode 100644 index 000000000..b0503febb --- /dev/null +++ b/hasura/migrations/1686082869359_set_fk_public_parts_dispatch_lines_partsdispatchid/up.sql @@ -0,0 +1,5 @@ +alter table "public"."parts_dispatch_lines" + add constraint "parts_dispatch_lines_partsdispatchid_fkey" + foreign key ("partsdispatchid") + references "public"."parts_dispatch" + ("id") on update cascade on delete cascade; diff --git a/hasura/migrations/1686084082349_alter_table_public_parts_dispatch_lines_alter_column_accepted_at/down.sql b/hasura/migrations/1686084082349_alter_table_public_parts_dispatch_lines_alter_column_accepted_at/down.sql new file mode 100644 index 000000000..b88b44672 --- /dev/null +++ b/hasura/migrations/1686084082349_alter_table_public_parts_dispatch_lines_alter_column_accepted_at/down.sql @@ -0,0 +1 @@ +alter table "public"."parts_dispatch_lines" alter column "accepted_at" set not null; diff --git a/hasura/migrations/1686084082349_alter_table_public_parts_dispatch_lines_alter_column_accepted_at/up.sql b/hasura/migrations/1686084082349_alter_table_public_parts_dispatch_lines_alter_column_accepted_at/up.sql new file mode 100644 index 000000000..723108120 --- /dev/null +++ b/hasura/migrations/1686084082349_alter_table_public_parts_dispatch_lines_alter_column_accepted_at/up.sql @@ -0,0 +1 @@ +alter table "public"."parts_dispatch_lines" alter column "accepted_at" drop not null; diff --git a/hasura/migrations/1686335272144_set_fk_public_job_conversations_conversationid/down.sql b/hasura/migrations/1686335272144_set_fk_public_job_conversations_conversationid/down.sql new file mode 100644 index 000000000..1dfd23a52 --- /dev/null +++ b/hasura/migrations/1686335272144_set_fk_public_job_conversations_conversationid/down.sql @@ -0,0 +1,5 @@ +alter table "public"."job_conversations" drop constraint "job_conversations_conversationid_fkey", + add constraint "job_conversations_conversationid_fkey" + foreign key ("conversationid") + references "public"."conversations" + ("id") on update restrict on delete restrict; diff --git a/hasura/migrations/1686335272144_set_fk_public_job_conversations_conversationid/up.sql b/hasura/migrations/1686335272144_set_fk_public_job_conversations_conversationid/up.sql new file mode 100644 index 000000000..524d765ed --- /dev/null +++ b/hasura/migrations/1686335272144_set_fk_public_job_conversations_conversationid/up.sql @@ -0,0 +1,5 @@ +alter table "public"."job_conversations" drop constraint "job_conversations_conversationid_fkey", + add constraint "job_conversations_conversationid_fkey" + foreign key ("conversationid") + references "public"."conversations" + ("id") on update cascade on delete cascade; diff --git a/server/opensearch/os-handler.js b/server/opensearch/os-handler.js index 1266e6a6c..0bc72170c 100644 --- a/server/opensearch/os-handler.js +++ b/server/opensearch/os-handler.js @@ -86,6 +86,7 @@ async function OpenSearchUpdateHandler(req, res) { "v_model_yr", "v_make_desc", "v_model_desc", + "v_vin", ]); document.bodyshopid = req.body.event.data.new.shopid; break; @@ -139,7 +140,7 @@ async function OpenSearchUpdateHandler(req, res) { "exported_at", "invoice_number", "is_credit_memo", - "total" + "total", ]), ...bill.bills_by_pk, bodyshopid: bill.bills_by_pk.job.shopid, @@ -244,17 +245,54 @@ async function OpensearchSearchHandler(req, res) { bool: { must: [ { - multi_match: { - query: search, - type: "phrase_prefix", - //fields: ["*"], - // fuzziness: "5", - //prefix_length: 2, + match: { + bodyshopid: assocs.associations[0].shopid, }, }, { - match: { - bodyshopid: assocs.associations[0].shopid, + bool: { + should: [ + { + multi_match: { + query: search, + type: "cross_fields", + fields: ["*ownr_fn", "*ownr_ln"], + }, + }, + { + multi_match: { + query: search, + type: "most_fields", + fields: [ + "*v_model_yr", + "*v_make_desc^2", + "*v_model_desc^3", + ], + }, + }, + { + query_string: { + query: `*${search}*`, + + fields: [ + "*ro_number^20", + "*clm_no^14", + "*v_vin^12", + "*plate_no^12", + "*ownr_ln^10", + "transactionid^10", + "paymentnum^10", + "invoice_number^10", + "*ownr_fn^8", + "*ownr_co_nm^8", + "*ownr_ph1^8", + "*ownr_ph2^8", + "*", + ], + }, + }, + ], + minimum_should_match: 1, }, }, ],