diff --git a/client/src/components/production-board-kanban/production-board-kanban.container.jsx b/client/src/components/production-board-kanban/production-board-kanban.container.jsx
index a0b8cc984..364ee2d53 100644
--- a/client/src/components/production-board-kanban/production-board-kanban.container.jsx
+++ b/client/src/components/production-board-kanban/production-board-kanban.container.jsx
@@ -2,7 +2,11 @@ import React, { useEffect, useMemo } from "react";
import { useQuery, useSubscription } from "@apollo/client";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
-import { QUERY_JOBS_IN_PRODUCTION, SUBSCRIPTION_JOBS_IN_PRODUCTION } from "../../graphql/jobs.queries";
+import {
+ QUERY_JOBS_IN_PRODUCTION,
+ SUBSCRIPTION_JOBS_IN_PRODUCTION,
+ SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW
+} from "../../graphql/jobs.queries";
import { QUERY_KANBAN_SETTINGS } from "../../graphql/user.queries";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
import ProductionBoardKanbanComponent from "./production-board-kanban.component";
@@ -12,7 +16,7 @@ const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser
});
-function ProductionBoardKanbanContainer({ bodyshop, currentUser }) {
+function ProductionBoardKanbanContainer({ bodyshop, currentUser, subscriptionType = "direct" }) {
const combinedStatuses = useMemo(
() => [
...bodyshop.md_ro_statuses.production_statuses,
@@ -28,9 +32,12 @@ function ProductionBoardKanbanContainer({ bodyshop, currentUser }) {
onError: (error) => console.error(`Error fetching jobs in production: ${error.message}`)
});
- const { data: updatedJobs } = useSubscription(SUBSCRIPTION_JOBS_IN_PRODUCTION, {
- onError: (error) => console.error(`Error subscribing to jobs in production: ${error.message}`)
- });
+ const { data: updatedJobs } = useSubscription(
+ subscriptionType !== "view" ? SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW : SUBSCRIPTION_JOBS_IN_PRODUCTION,
+ {
+ onError: (error) => console.error(`Error subscribing to jobs in production: ${error.message}`)
+ }
+ );
const { loading: associationSettingsLoading, data: associationSettings } = useQuery(QUERY_KANBAN_SETTINGS, {
variables: { email: currentUser.email },
diff --git a/client/src/components/production-list-table/production-list-table.container.jsx b/client/src/components/production-list-table/production-list-table.container.jsx
index 29ddf015a..153089ddb 100644
--- a/client/src/components/production-list-table/production-list-table.container.jsx
+++ b/client/src/components/production-list-table/production-list-table.container.jsx
@@ -4,12 +4,13 @@ import {
QUERY_EXACT_JOB_IN_PRODUCTION,
QUERY_EXACT_JOBS_IN_PRODUCTION,
QUERY_JOBS_IN_PRODUCTION,
- SUBSCRIPTION_JOBS_IN_PRODUCTION
+ SUBSCRIPTION_JOBS_IN_PRODUCTION,
+ SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW
} from "../../graphql/jobs.queries";
import ProductionListTable from "./production-list-table.component";
import _ from "lodash";
-export default function ProductionListTableContainer() {
+export default function ProductionListTableContainer({ subscriptionType = "direct" }) {
const { refetch, loading, data } = useQuery(QUERY_JOBS_IN_PRODUCTION, {
pollInterval: 3600000,
fetchPolicy: "network-only",
@@ -17,7 +18,9 @@ export default function ProductionListTableContainer() {
});
const client = useApolloClient();
const [joblist, setJoblist] = useState([]);
- const { data: updatedJobs } = useSubscription(SUBSCRIPTION_JOBS_IN_PRODUCTION);
+ const { data: updatedJobs } = useSubscription(
+ subscriptionType !== "view" ? SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW : SUBSCRIPTION_JOBS_IN_PRODUCTION
+ );
useEffect(() => {
if (!(data && data.jobs)) return;
diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js
index 90169eccc..03a1800d3 100644
--- a/client/src/graphql/jobs.queries.js
+++ b/client/src/graphql/jobs.queries.js
@@ -2461,6 +2461,14 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql`
}
}
`;
+export const SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW = gql`
+ subscription SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW {
+ jobs: jobs_inproduction {
+ id
+ updated_at
+ }
+ }
+`;
export const QUERY_JOBS_IN_PRODUCTION = gql`
query QUERY_JOBS_IN_PRODUCTION {
@@ -2543,3 +2551,85 @@ export const QUERY_JOBS_IN_PRODUCTION = gql`
}
}
`;
+
+export const QUERY_JOBS_IN_PRODUCTION_VIEW = gql`
+ query QUERY_JOBS_IN_PRODUCTION {
+ jobs: jobs_inproduction {
+ tasks_aggregate(where: { completed: { _eq: false }, deleted: { _eq: false } }) {
+ aggregate {
+ count
+ }
+ }
+ id
+ updated_at
+ comment
+ status
+ category
+ iouparent
+ ro_number
+ ownerid
+ ownr_fn
+ ownr_ln
+ ownr_co_nm
+ v_model_yr
+ v_model_desc
+ clm_no
+ v_make_desc
+ v_color
+ vehicleid
+ plate_no
+ actual_in
+ scheduled_completion
+ scheduled_delivery
+ date_last_contacted
+ date_next_contact
+ ins_co_nm
+ clm_total
+ ownr_ph1
+ ownr_ph2
+ special_coverage_policy
+ owner_owing
+ production_vars
+ kanbanparent
+ alt_transport
+ employee_body
+ employee_refinish
+ employee_prep
+ employee_csr
+ est_ct_fn
+ est_ct_ln
+ suspended
+ job_totals
+ date_repairstarted
+ joblines_status {
+ part_type
+ status
+ count
+ }
+ labhrs: joblines_aggregate(where: { _and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }] }) {
+ aggregate {
+ sum {
+ mod_lb_hrs
+ }
+ }
+ }
+ larhrs: joblines_aggregate(where: { _and: [{ mod_lbr_ty: { _eq: "LAR" } }, { removed: { _eq: false } }] }) {
+ aggregate {
+ sum {
+ mod_lb_hrs
+ }
+ }
+ }
+ subletLines: joblines(
+ where: { _and: { part_type: { _in: ["PAS", "PASL"] }, removed: { _eq: false } } }
+ order_by: { line_no: asc }
+ ) {
+ id
+ line_desc
+ sublet_ignored
+ sublet_completed
+ jobid
+ }
+ }
+ }
+`;
diff --git a/client/src/pages/production-board/production-board.component.jsx b/client/src/pages/production-board/production-board.component.jsx
index 9b69da414..e5dfe7dff 100644
--- a/client/src/pages/production-board/production-board.component.jsx
+++ b/client/src/pages/production-board/production-board.component.jsx
@@ -1,6 +1,26 @@
import React from "react";
import ProductionBoardKanbanContainer from "../../components/production-board-kanban/production-board-kanban.container";
+import { connect } from "react-redux";
+import { createStructuredSelector } from "reselect";
+import { selectBodyshop } from "../../redux/user/user.selectors";
+import { useSplitTreatments } from "@splitsoftware/splitio-react";
+const mapStateToProps = createStructuredSelector({
+ //currentUser: selectCurrentUser
+ bodyshop: selectBodyshop
+});
+const mapDispatchToProps = (dispatch) => ({
+ //setUserLanguage: language => dispatch(setUserLanguage(language))
+});
+export default connect(mapStateToProps, mapDispatchToProps)(ProductionBoardComponent);
-export default function ProductionBoardComponent() {
- return ;
+export function ProductionBoardComponent({ bodyshop }) {
+ const {
+ treatments: { Production_Use_View }
+ } = useSplitTreatments({
+ attributes: {},
+ names: ["Production_Use_View"],
+ splitKey: bodyshop && bodyshop.imexshopid
+ });
+
+ return ;
}
diff --git a/client/src/pages/production-list/production-list.component.jsx b/client/src/pages/production-list/production-list.component.jsx
index 01dd29d51..177108f6d 100644
--- a/client/src/pages/production-list/production-list.component.jsx
+++ b/client/src/pages/production-list/production-list.component.jsx
@@ -2,11 +2,31 @@ import React from "react";
import NoteUpsertModal from "../../components/note-upsert-modal/note-upsert-modal.container";
import ProductionListTable from "../../components/production-list-table/production-list-table.container";
-export default function ProductionListComponent() {
+import { connect } from "react-redux";
+import { createStructuredSelector } from "reselect";
+import { selectBodyshop } from "../../redux/user/user.selectors";
+import { useSplitTreatments } from "@splitsoftware/splitio-react";
+const mapStateToProps = createStructuredSelector({
+ bodyshop: selectBodyshop
+});
+const mapDispatchToProps = (dispatch) => ({
+ //setUserLanguage: language => dispatch(setUserLanguage(language))
+});
+export default connect(mapStateToProps, mapDispatchToProps)(ProductionListComponent);
+
+export function ProductionListComponent({ bodyshop }) {
+ const {
+ treatments: { Production_Use_View }
+ } = useSplitTreatments({
+ attributes: {},
+ names: ["Production_Use_View"],
+ splitKey: bodyshop && bodyshop.imexshopid
+ });
+
return (
<>
-
+
>
);
}
diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml
index 7ab9621df..70be46ad0 100644
--- a/hasura/metadata/tables.yaml
+++ b/hasura/metadata/tables.yaml
@@ -918,6 +918,7 @@
- bill_tax_rates
- cdk_configuration
- cdk_dealerid
+ - chatterid
- city
- claimscorpid
- convenient_company
@@ -939,6 +940,7 @@
- inhousevendorid
- insurance_vendor_id
- intakechecklist
+ - intellipay_config
- jc_hourly_rates
- jobsizelimit
- last_name_first
@@ -1040,6 +1042,7 @@
- inhousevendorid
- insurance_vendor_id
- intakechecklist
+ - intellipay_config
- jc_hourly_rates
- last_name_first
- localmediaserverhttp
@@ -4240,6 +4243,63 @@
- active:
_eq: true
event_triggers:
+ - name: job_modified
+ definition:
+ enable_manual: false
+ update:
+ columns:
+ - clm_no
+ - v_make_desc
+ - date_next_contact
+ - status
+ - employee_csr
+ - employee_prep
+ - clm_total
+ - suspended
+ - employee_body
+ - ro_number
+ - actual_in
+ - ownr_co_nm
+ - v_model_yr
+ - comment
+ - job_totals
+ - v_vin
+ - ownr_fn
+ - scheduled_completion
+ - special_coverage_policy
+ - v_color
+ - ca_gst_registrant
+ - scheduled_delivery
+ - actual_delivery
+ - actual_completion
+ - kanbanparent
+ - est_ct_fn
+ - employee_refinish
+ - ownr_ph1
+ - date_last_contacted
+ - alt_transport
+ - inproduction
+ - est_ct_ln
+ - production_vars
+ - category
+ - v_model_desc
+ - date_invoiced
+ - est_co_nm
+ - ownr_ln
+ retry_conf:
+ interval_sec: 10
+ num_retries: 0
+ timeout_sec: 60
+ webhook_from_env: HASURA_API_URL
+ headers:
+ - name: event-secret
+ value_from_env: EVENT_SECRET
+ request_transform:
+ method: POST
+ query_params: {}
+ template_engine: Kriti
+ url: '{{$base_url}}/job/job-updated'
+ version: 2
- name: job_status_transition
definition:
enable_manual: true
@@ -4299,6 +4359,35 @@
template_engine: Kriti
url: '{{$base_url}}/opensearch'
version: 2
+- table:
+ name: jobs_inproduction
+ schema: public
+ object_relationships:
+ - name: bodyshop
+ using:
+ manual_configuration:
+ column_mapping:
+ shopid: id
+ insertion_order: null
+ remote_table:
+ name: bodyshops
+ schema: public
+ select_permissions:
+ - role: user
+ permission:
+ columns:
+ - id
+ - shopid
+ - updated_at
+ filter:
+ bodyshop:
+ associations:
+ _and:
+ - user:
+ authid:
+ _eq: X-Hasura-User-Id
+ - active:
+ _eq: true
- table:
name: masterdata
schema: public
diff --git a/hasura/migrations/1726773072213_run_sql_migration/down.sql b/hasura/migrations/1726773072213_run_sql_migration/down.sql
new file mode 100644
index 000000000..4f5681185
--- /dev/null
+++ b/hasura/migrations/1726773072213_run_sql_migration/down.sql
@@ -0,0 +1,11 @@
+-- Could not auto-generate a down migration.
+-- Please write an appropriate down migration for the SQL below:
+-- CREATE
+-- OR REPLACE VIEW "public"."jobs_inproduction" AS
+-- SELECT
+-- j.id,
+-- j.updated_at
+-- FROM
+-- jobs j
+-- WHERE
+-- j.inproduction=true;
diff --git a/hasura/migrations/1726773072213_run_sql_migration/up.sql b/hasura/migrations/1726773072213_run_sql_migration/up.sql
new file mode 100644
index 000000000..317afef83
--- /dev/null
+++ b/hasura/migrations/1726773072213_run_sql_migration/up.sql
@@ -0,0 +1,9 @@
+CREATE
+OR REPLACE VIEW "public"."jobs_inproduction" AS
+SELECT
+ j.id,
+ j.updated_at
+FROM
+ jobs j
+WHERE
+j.inproduction=true;
diff --git a/hasura/migrations/1726773316245_run_sql_migration/down.sql b/hasura/migrations/1726773316245_run_sql_migration/down.sql
new file mode 100644
index 000000000..153bb816b
--- /dev/null
+++ b/hasura/migrations/1726773316245_run_sql_migration/down.sql
@@ -0,0 +1,8 @@
+-- Could not auto-generate a down migration.
+-- Please write an appropriate down migration for the SQL below:
+-- CREATE OR REPLACE VIEW "public"."jobs_inproduction" AS
+-- SELECT j.id,
+-- j.updated_at,
+-- j.shopid
+-- FROM jobs j
+-- WHERE (j.inproduction = true);
diff --git a/hasura/migrations/1726773316245_run_sql_migration/up.sql b/hasura/migrations/1726773316245_run_sql_migration/up.sql
new file mode 100644
index 000000000..8bc73f558
--- /dev/null
+++ b/hasura/migrations/1726773316245_run_sql_migration/up.sql
@@ -0,0 +1,6 @@
+CREATE OR REPLACE VIEW "public"."jobs_inproduction" AS
+ SELECT j.id,
+ j.updated_at,
+ j.shopid
+ FROM jobs j
+ WHERE (j.inproduction = true);
diff --git a/hasura/migrations/1726773326353_run_sql_migration/down.sql b/hasura/migrations/1726773326353_run_sql_migration/down.sql
new file mode 100644
index 000000000..153bb816b
--- /dev/null
+++ b/hasura/migrations/1726773326353_run_sql_migration/down.sql
@@ -0,0 +1,8 @@
+-- Could not auto-generate a down migration.
+-- Please write an appropriate down migration for the SQL below:
+-- CREATE OR REPLACE VIEW "public"."jobs_inproduction" AS
+-- SELECT j.id,
+-- j.updated_at,
+-- j.shopid
+-- FROM jobs j
+-- WHERE (j.inproduction = true);
diff --git a/hasura/migrations/1726773326353_run_sql_migration/up.sql b/hasura/migrations/1726773326353_run_sql_migration/up.sql
new file mode 100644
index 000000000..8bc73f558
--- /dev/null
+++ b/hasura/migrations/1726773326353_run_sql_migration/up.sql
@@ -0,0 +1,6 @@
+CREATE OR REPLACE VIEW "public"."jobs_inproduction" AS
+ SELECT j.id,
+ j.updated_at,
+ j.shopid
+ FROM jobs j
+ WHERE (j.inproduction = true);
diff --git a/hasura/migrations/1726775434726_run_sql_migration/down.sql b/hasura/migrations/1726775434726_run_sql_migration/down.sql
new file mode 100644
index 000000000..16ca01c42
--- /dev/null
+++ b/hasura/migrations/1726775434726_run_sql_migration/down.sql
@@ -0,0 +1,3 @@
+-- Could not auto-generate a down migration.
+-- Please write an appropriate down migration for the SQL below:
+-- CREATE INDEX idx_jobs_inproduction_true_cast ON jobs(inproduction) WHERE inproduction = ('true') :: boolean;
diff --git a/hasura/migrations/1726775434726_run_sql_migration/up.sql b/hasura/migrations/1726775434726_run_sql_migration/up.sql
new file mode 100644
index 000000000..a6f352908
--- /dev/null
+++ b/hasura/migrations/1726775434726_run_sql_migration/up.sql
@@ -0,0 +1 @@
+CREATE INDEX idx_jobs_inproduction_true_cast ON jobs(inproduction) WHERE inproduction = ('true') :: boolean;
diff --git a/hasura/migrations/1726775487038_drop_index_idx_jobs_inproduction_true_cast/down.sql b/hasura/migrations/1726775487038_drop_index_idx_jobs_inproduction_true_cast/down.sql
new file mode 100644
index 000000000..a5f6e49ae
--- /dev/null
+++ b/hasura/migrations/1726775487038_drop_index_idx_jobs_inproduction_true_cast/down.sql
@@ -0,0 +1,2 @@
+CREATE INDEX "idx_jobs_inproduction_true_cast" on
+ "public"."jobs" using btree ("inproduction");
diff --git a/hasura/migrations/1726775487038_drop_index_idx_jobs_inproduction_true_cast/up.sql b/hasura/migrations/1726775487038_drop_index_idx_jobs_inproduction_true_cast/up.sql
new file mode 100644
index 000000000..d0163192a
--- /dev/null
+++ b/hasura/migrations/1726775487038_drop_index_idx_jobs_inproduction_true_cast/up.sql
@@ -0,0 +1 @@
+DROP INDEX IF EXISTS "public"."idx_jobs_inproduction_true_cast";