diff --git a/client/src/components/bill-enter-modal/bill-enter-modal.container.jsx b/client/src/components/bill-enter-modal/bill-enter-modal.container.jsx
index 6fb7692a4..d2d0d928a 100644
--- a/client/src/components/bill-enter-modal/bill-enter-modal.container.jsx
+++ b/client/src/components/bill-enter-modal/bill-enter-modal.container.jsx
@@ -1,18 +1,18 @@
import { useApolloClient, useMutation } from "@apollo/client";
-import { Button, Checkbox, Form, Modal, notification, Space } from "antd";
+import { Button, Checkbox, Form, Modal, Space, notification } from "antd";
import _ from "lodash";
-import React, { useEffect, useState, useMemo } from "react";
+import React, { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { INSERT_NEW_BILL } from "../../graphql/bills.queries";
+import { UPDATE_INVENTORY_LINES } from "../../graphql/inventory.queries";
import { UPDATE_JOB_LINE } from "../../graphql/jobs-lines.queries";
import {
QUERY_JOB_LBR_ADJUSTMENTS,
UPDATE_JOB,
} from "../../graphql/jobs.queries";
import { MUTATION_MARK_RETURN_RECEIVED } from "../../graphql/parts-orders.queries";
-import { UPDATE_INVENTORY_LINES } from "../../graphql/inventory.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { toggleModalVisible } from "../../redux/modals/modals.actions";
import { selectBillEnterModal } from "../../redux/modals/modals.selectors";
@@ -20,15 +20,15 @@ import {
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
-import confirmDialog from "../../utils/asyncConfirm";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
-import BillFormContainer from "../bill-form/bill-form.container";
-import { CalculateBillTotal } from "../bill-form/bill-form.totals.utility";
-import { handleUpload } from "../documents-upload/documents-upload.utility";
-import { handleUpload as handleLocalUpload } from "../documents-local-upload/documents-local-upload.utility";
-import useLocalStorage from "../../utils/useLocalStorage";
import { GenerateDocument } from "../../utils/RenderTemplate";
import { TemplateList } from "../../utils/TemplateConstants";
+import confirmDialog from "../../utils/asyncConfirm";
+import useLocalStorage from "../../utils/useLocalStorage";
+import BillFormContainer from "../bill-form/bill-form.container";
+import { CalculateBillTotal } from "../bill-form/bill-form.totals.utility";
+import { handleUpload as handleLocalUpload } from "../documents-local-upload/documents-local-upload.utility";
+import { handleUpload } from "../documents-upload/documents-upload.utility";
const mapStateToProps = createStructuredSelector({
billEnterModal: selectBillEnterModal,
@@ -126,6 +126,17 @@ function BillEnterModalContainer({
deductedfromlbr: deductedfromlbr,
lbr_adjustment,
joblineid: i.joblineid === "noline" ? null : i.joblineid,
+ applicable_taxes: {
+ federal:
+ (i.applicable_taxes && i.applicable_taxes.federal) ||
+ false,
+ state:
+ (i.applicable_taxes && i.applicable_taxes.state) ||
+ false,
+ local:
+ (i.applicable_taxes && i.applicable_taxes.local) ||
+ false,
+ },
};
}),
},
diff --git a/client/src/components/dashboard-components/scheduled-in-today/scheduled-in-today.component.jsx b/client/src/components/dashboard-components/scheduled-in-today/scheduled-in-today.component.jsx
new file mode 100644
index 000000000..87d1980a1
--- /dev/null
+++ b/client/src/components/dashboard-components/scheduled-in-today/scheduled-in-today.component.jsx
@@ -0,0 +1,235 @@
+import {
+ BranchesOutlined,
+ ExclamationCircleFilled,
+ PauseCircleOutlined,
+} from "@ant-design/icons";
+import { Card, Space, Table, Tooltip } from "antd";
+import moment from "moment";
+import React, { useState } from "react";
+import { useTranslation } from "react-i18next";
+import { Link } from "react-router-dom";
+import ChatOpenButton from "../../chat-open-button/chat-open-button.component";
+import OwnerNameDisplay from "../../owner-name-display/owner-name-display.component";
+import DashboardRefreshRequired from "../refresh-required.component";
+
+export default function DashboardScheduledInToday({ data, ...cardProps }) {
+ const { t } = useTranslation();
+ const [state, setState] = useState({
+ sortedInfo: {},
+ });
+ if (!data) return null;
+ if (!data.scheduled_in_today)
+ return ;
+
+ const appt = []; // Flatten Data
+ data.scheduled_in_today.forEach((item) => {
+ var i = {
+ canceled: item.canceled,
+ id: item.id,
+ alt_transport: item.job.alt_transport,
+ clm_no: item.job.clm_no,
+ jobid: item.job.jobid,
+ ins_co_nm: item.job.ins_co_nm,
+ iouparent: item.job.iouparent,
+ ownerid: item.job.ownerid,
+ ownr_co_nm: item.job.ownr_co_nm,
+ ownr_ea: item.job.ownr_ea,
+ ownr_fn: item.job.ownr_fn,
+ ownr_ln: item.job.ownr_ln,
+ ownr_ph1: item.job.ownr_ph1,
+ ownr_ph2: item.job.ownr_ph2,
+ production_vars: item.job.production_vars,
+ ro_number: item.job.ro_number,
+ suspended: item.job.suspended,
+ v_make_desc: item.job.v_make_desc,
+ v_model_desc: item.job.v_model_desc,
+ v_model_yr: item.job.v_model_yr,
+ v_vin: item.job.v_vin,
+ vehicleid: item.job.vehicleid,
+ note: item.note,
+ start: moment(item.start).format("hh:mm a"),
+ title: item.title,
+ };
+ appt.push(i);
+ });
+ appt.sort ( function (a, b) { return new Date(a.start) - new Date(b.start); });
+
+ const columns = [
+ {
+ title: t("jobs.fields.ro_number"),
+ dataIndex: "ro_number",
+ key: "ro_number",
+ render: (text, record) => (
+ e.stopPropagation()}
+ >
+
+ {record.ro_number || t("general.labels.na")}
+ {record.production_vars && record.production_vars.alert ? (
+
+ ) : null}
+ {record.suspended && (
+
+ )}
+ {record.iouparent && (
+
+
+
+ )}
+
+
+ ),
+ },
+ {
+ title: t("jobs.fields.owner"),
+ dataIndex: "owner",
+ key: "owner",
+ ellipsis: true,
+ responsive: ["md"],
+ render: (text, record) => {
+ return record.ownerid ? (
+ e.stopPropagation()}
+ >
+
+
+ ) : (
+
+
+
+ );
+ },
+ },
+ {
+ title: t("jobs.fields.ownr_ph1"),
+ dataIndex: "ownr_ph1",
+ key: "ownr_ph1",
+ ellipsis: true,
+ responsive: ["md"],
+ render: (text, record) => (
+
+ ),
+ },
+ {
+ title: t("jobs.fields.ownr_ph2"),
+ dataIndex: "ownr_ph2",
+ key: "ownr_ph2",
+ ellipsis: true,
+ responsive: ["md"],
+ render: (text, record) => (
+
+ ),
+ },
+ {
+ title: t("jobs.fields.ownr_ea"),
+ dataIndex: "ownr_ea",
+ key: "ownr_ea",
+ ellipsis: true,
+ responsive: ["md"],
+ render: (text, record) => (
+
+ ),
+ },
+ {
+ title: t("jobs.fields.vehicle"),
+ dataIndex: "vehicle",
+ key: "vehicle",
+ ellipsis: true,
+ render: (text, record) => {
+ return record.vehicleid ? (
+ e.stopPropagation()}
+ >
+ {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${
+ record.v_model_desc || ""
+ }`}
+
+ ) : (
+ {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${
+ record.v_model_desc || ""
+ }`}
+ );
+ },
+ },
+ {
+ title: t("jobs.fields.ins_co_nm"),
+ dataIndex: "ins_co_nm",
+ key: "ins_co_nm",
+ ellipsis: true,
+ responsive: ["md"],
+ },
+ {
+ title: t("appointments.fields.time"),
+ dataIndex: "start",
+ key: "start",
+ ellipsis: true,
+ responsive: ["md"],
+ },
+ {
+ title: t("appointments.fields.alt_transport"),
+ dataIndex: "alt_transport",
+ key: "alt_transport",
+ ellipsis: true,
+ responsive: ["md"],
+ },
+ ];
+
+ const handleTableChange = (sorter) => {
+ setState({ ...state, sortedInfo: sorter });
+ };
+
+ return (
+
+
+
+ );
+}
+
+export const DashboardScheduledInTodayGql = `
+ scheduled_in_today: appointments(where: {start: {_gte: "${moment()
+ .startOf("day")
+ .toISOString()}", _lte: "${moment()
+ .endOf("day")
+ .toISOString()}"}, canceled: {_eq: false}, block: {_neq: true}}) {
+ canceled
+ id
+ job {
+ alt_transport
+ clm_no
+ jobid: id
+ ins_co_nm
+ iouparent
+ ownerid
+ ownr_co_nm
+ ownr_ea
+ ownr_fn
+ ownr_ln
+ ownr_ph1
+ ownr_ph2
+ production_vars
+ ro_number
+ suspended
+ v_make_desc
+ v_model_desc
+ v_model_yr
+ v_vin
+ vehicleid
+ }
+ note
+ start
+ title
+ }
+`;
diff --git a/client/src/components/dashboard-components/scheduled-out-today/scheduled-out-today.component.jsx b/client/src/components/dashboard-components/scheduled-out-today/scheduled-out-today.component.jsx
new file mode 100644
index 000000000..586e719ab
--- /dev/null
+++ b/client/src/components/dashboard-components/scheduled-out-today/scheduled-out-today.component.jsx
@@ -0,0 +1,210 @@
+import {
+ BranchesOutlined,
+ ExclamationCircleFilled,
+ PauseCircleOutlined,
+} from "@ant-design/icons";
+import { Card, Space, Table, Tooltip } from "antd";
+import moment from "moment";
+import React, { useState } from "react";
+import { useTranslation } from "react-i18next";
+import { Link } from "react-router-dom";
+import ChatOpenButton from "../../chat-open-button/chat-open-button.component";
+import OwnerNameDisplay from "../../owner-name-display/owner-name-display.component";
+import DashboardRefreshRequired from "../refresh-required.component";
+
+export default function DashboardScheduledOutToday({ data, ...cardProps }) {
+ const { t } = useTranslation();
+ const [state, setState] = useState({
+ sortedInfo: {},
+ });
+ if (!data) return null;
+ if (!data.scheduled_out_today)
+ return ;
+
+ data.scheduled_out_today.forEach((item) => {
+ item.scheduled_completion= moment(item.scheduled_completion).format("hh:mm a")
+ });
+ data.scheduled_out_today.sort(function (a, b) {
+ return new Date(a.scheduled_completion) - new Date(b.scheduled_completion);
+ });
+
+ const columns = [
+ {
+ title: t("jobs.fields.ro_number"),
+ dataIndex: "ro_number",
+ key: "ro_number",
+ render: (text, record) => (
+ e.stopPropagation()}
+ >
+
+ {record.ro_number || t("general.labels.na")}
+ {record.production_vars && record.production_vars.alert ? (
+
+ ) : null}
+ {record.suspended && (
+
+ )}
+ {record.iouparent && (
+
+
+
+ )}
+
+
+ ),
+ },
+ {
+ title: t("jobs.fields.owner"),
+ dataIndex: "owner",
+ key: "owner",
+ ellipsis: true,
+ responsive: ["md"],
+ render: (text, record) => {
+ return record.ownerid ? (
+ e.stopPropagation()}
+ >
+
+
+ ) : (
+
+
+
+ );
+ },
+ },
+ {
+ title: t("jobs.fields.ownr_ph1"),
+ dataIndex: "ownr_ph1",
+ key: "ownr_ph1",
+ ellipsis: true,
+ responsive: ["md"],
+ render: (text, record) => (
+
+ ),
+ },
+ {
+ title: t("jobs.fields.ownr_ph2"),
+ dataIndex: "ownr_ph2",
+ key: "ownr_ph2",
+ ellipsis: true,
+ responsive: ["md"],
+ render: (text, record) => (
+
+ ),
+ },
+ {
+ title: t("jobs.fields.ownr_ea"),
+ dataIndex: "ownr_ea",
+ key: "ownr_ea",
+ ellipsis: true,
+ responsive: ["md"],
+ render: (text, record) => (
+
+ ),
+ },
+ {
+ title: t("jobs.fields.vehicle"),
+ dataIndex: "vehicle",
+ key: "vehicle",
+ ellipsis: true,
+ render: (text, record) => {
+ return record.vehicleid ? (
+ e.stopPropagation()}
+ >
+ {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${
+ record.v_model_desc || ""
+ }`}
+
+ ) : (
+ {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${
+ record.v_model_desc || ""
+ }`}
+ );
+ },
+ },
+ {
+ title: t("jobs.fields.ins_co_nm"),
+ dataIndex: "ins_co_nm",
+ key: "ins_co_nm",
+ ellipsis: true,
+ responsive: ["md"],
+ },
+ {
+ title: t("jobs.fields.scheduled_completion"),
+ dataIndex: "scheduled_completion",
+ key: "scheduled_completion",
+ ellipsis: true,
+ responsive: ["md"],
+ },
+ {
+ title: t("appointments.fields.alt_transport"),
+ dataIndex: "alt_transport",
+ key: "alt_transport",
+ ellipsis: true,
+ responsive: ["md"],
+ },
+ ];
+
+ const handleTableChange = (sorter) => {
+ setState({ ...state, sortedInfo: sorter });
+ };
+
+ return (
+
+
+
+ );
+}
+
+export const DashboardScheduledOutTodayGql = `
+ scheduled_out_today: jobs(where: {
+ date_invoiced: {_is_null: true},
+ ro_number: {_is_null: false},
+ voided: {_eq: false},
+ scheduled_completion: {_gte: "${moment().startOf("day").toISOString()}",
+ _lte: "${moment().endOf("day").toISOString()}"}}) {
+ alt_transport
+ clm_no
+ jobid: id
+ ins_co_nm
+ iouparent
+ ownerid
+ ownr_co_nm
+ ownr_ea
+ ownr_fn
+ ownr_ln
+ ownr_ph1
+ ownr_ph2
+ production_vars
+ ro_number
+ scheduled_completion
+ suspended
+ v_make_desc
+ v_model_desc
+ v_model_yr
+ v_vin
+ vehicleid
+
+ }
+`;
diff --git a/client/src/components/dashboard-grid/dashboard-grid.component.jsx b/client/src/components/dashboard-grid/dashboard-grid.component.jsx
index 39a5432c2..d24dd5641 100644
--- a/client/src/components/dashboard-grid/dashboard-grid.component.jsx
+++ b/client/src/components/dashboard-grid/dashboard-grid.component.jsx
@@ -1,6 +1,6 @@
import Icon, { SyncOutlined } from "@ant-design/icons";
import { gql, useMutation, useQuery } from "@apollo/client";
-import { Button, Dropdown, Menu, notification, PageHeader, Space } from "antd";
+import { Button, Dropdown, Menu, PageHeader, Space, notification } from "antd";
import i18next from "i18next";
import _ from "lodash";
import moment from "moment";
@@ -37,6 +37,12 @@ import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
//Combination of the following:
// /node_modules/react-grid-layout/css/styles.css
// /node_modules/react-resizable/css/styles.css
+import DashboardScheduledInToday, {
+ DashboardScheduledInTodayGql,
+} from "../dashboard-components/scheduled-in-today/scheduled-in-today.component";
+import DashboardScheduledOutToday, {
+ DashboardScheduledOutTodayGql,
+} from "../dashboard-components/scheduled-out-today/scheduled-out-today.component";
import "./dashboard-grid.styles.scss";
import { GenerateDashboardData } from "./dashboard-grid.utils";
@@ -268,6 +274,28 @@ const componentList = {
w: 2,
h: 2,
},
+ ScheduleInToday: {
+ label: i18next.t("dashboard.titles.scheduledintoday", {
+ date: moment().startOf("day").format("MM/DD/YYYY"),
+ }),
+ component: DashboardScheduledInToday,
+ gqlFragment: DashboardScheduledInTodayGql,
+ minW: 10,
+ minH: 2,
+ w: 10,
+ h: 2,
+ },
+ ScheduleOutToday: {
+ label: i18next.t("dashboard.titles.scheduledouttoday", {
+ date: moment().startOf("day").format("MM/DD/YYYY"),
+ }),
+ component: DashboardScheduledOutToday,
+ gqlFragment: DashboardScheduledOutTodayGql,
+ minW: 10,
+ minH: 2,
+ w: 10,
+ h: 2,
+ },
};
const createDashboardQuery = (state) => {
@@ -283,8 +311,12 @@ const createDashboardQuery = (state) => {
monthly_sales: jobs(where: {_and: [
{ voided: {_eq: false}},
{date_invoiced: {_gte: "${moment()
- .startOf("month").startOf('day').toISOString()}"}}, {date_invoiced: {_lte: "${moment()
- .endOf("month").endOf('day').toISOString()}"}}]}) {
+ .startOf("month")
+ .startOf("day")
+ .toISOString()}"}}, {date_invoiced: {_lte: "${moment()
+ .endOf("month")
+ .endOf("day")
+ .toISOString()}"}}]}) {
id
ro_number
date_invoiced
diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json
index 9a1f09d9c..ad7662c82 100644
--- a/client/src/translations/en_us/common.json
+++ b/client/src/translations/en_us/common.json
@@ -858,7 +858,9 @@
"prodhrssummary": "Production Hours Summary",
"productiondollars": "Total dollars in Production",
"productionhours": "Total hours in Production",
- "projectedmonthlysales": "Projected Monthly Sales"
+ "projectedmonthlysales": "Projected Monthly Sales",
+ "scheduledintoday": "Sheduled In Today: {{date}}",
+ "scheduledouttoday": "Sheduled Out Today: {{date}}"
}
},
"dms": {
@@ -2568,6 +2570,7 @@
"job_costing_ro_ins_co": "Job Costing by RO Source",
"jobs_completed_not_invoiced": "Jobs Completed not Invoiced",
"jobs_invoiced_not_exported": "Jobs Invoiced not Exported",
+ "jobs_scheduled_completion": "Jobs Scheduled Completion",
"jobs_reconcile": "Parts/Sublet/Labor Reconciliation",
"lag_time": "Lag Time",
"open_orders": "Open Orders by Date",
diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json
index 52857b75f..662c3e005 100644
--- a/client/src/translations/es/common.json
+++ b/client/src/translations/es/common.json
@@ -858,7 +858,9 @@
"prodhrssummary": "",
"productiondollars": "",
"productionhours": "",
- "projectedmonthlysales": ""
+ "projectedmonthlysales": "",
+ "scheduledintoday": "",
+ "scheduledouttoday": ""
}
},
"dms": {
@@ -2565,6 +2567,7 @@
"job_costing_ro_ins_co": "",
"jobs_completed_not_invoiced": "",
"jobs_invoiced_not_exported": "",
+ "jobs_scheduled_completion": "",
"jobs_reconcile": "",
"lag_time": "",
"open_orders": "",
diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json
index 9105279ef..d93183bfc 100644
--- a/client/src/translations/fr/common.json
+++ b/client/src/translations/fr/common.json
@@ -858,7 +858,9 @@
"prodhrssummary": "",
"productiondollars": "",
"productionhours": "",
- "projectedmonthlysales": ""
+ "projectedmonthlysales": "",
+ "scheduledintoday": "",
+ "scheduledouttoday": ""
}
},
"dms": {
@@ -2565,6 +2567,7 @@
"job_costing_ro_ins_co": "",
"jobs_completed_not_invoiced": "",
"jobs_invoiced_not_exported": "",
+ "jobs_scheduled_completion": "",
"jobs_reconcile": "",
"lag_time": "",
"open_orders": "",
diff --git a/client/src/utils/TemplateConstants.js b/client/src/utils/TemplateConstants.js
index debbfc57e..c07e375fa 100644
--- a/client/src/utils/TemplateConstants.js
+++ b/client/src/utils/TemplateConstants.js
@@ -1897,6 +1897,18 @@ export const TemplateList = (type, context) => {
},
group: "sales",
},
+ jobs_scheduled_completion: {
+ title: i18n.t("reportcenter.templates.jobs_scheduled_completion"),
+ subject: i18n.t("reportcenter.templates.jobs_scheduled_completion"),
+ key: "jobs_scheduled_completion",
+ //idtype: "vendor",
+ disabled: false,
+ rangeFilter: {
+ object: i18n.t("reportcenter.labels.objects.jobs"),
+ field: i18n.t("jobs.fields.scheduled_completion"),
+ },
+ group: "jobs",
+ },
}
: {}),
...(!type || type === "courtesycarcontract"
diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml
index 111374fb5..1ce055244 100644
--- a/hasura/metadata/tables.yaml
+++ b/hasura/metadata/tables.yaml
@@ -2092,6 +2092,13 @@
table:
name: employee_team_members
schema: public
+ - name: joblines
+ using:
+ foreign_key_constraint_on:
+ column: assigned_team
+ table:
+ name: joblines
+ schema: public
insert_permissions:
- role: user
permission:
@@ -2665,6 +2672,9 @@
name: joblines
schema: public
object_relationships:
+ - name: employee_team
+ using:
+ foreign_key_constraint_on: assigned_team
- name: job
using:
foreign_key_constraint_on: jobid
@@ -2726,6 +2736,7 @@
- alt_part_i
- alt_partm
- alt_partno
+ - assigned_team
- bett_amt
- bett_pctg
- bett_tax
@@ -2734,6 +2745,7 @@
- convertedtolbr
- convertedtolbr_data
- created_at
+ - critical
- db_hrs
- db_price
- db_ref
@@ -2793,6 +2805,7 @@
- alt_part_i
- alt_partm
- alt_partno
+ - assigned_team
- bett_amt
- bett_pctg
- bett_tax
@@ -2872,6 +2885,7 @@
- alt_part_i
- alt_partm
- alt_partno
+ - assigned_team
- bett_amt
- bett_pctg
- bett_tax
diff --git a/hasura/migrations/1688674667178_alter_table_public_joblines_add_column_assigned_team/down.sql b/hasura/migrations/1688674667178_alter_table_public_joblines_add_column_assigned_team/down.sql
new file mode 100644
index 000000000..61af19807
--- /dev/null
+++ b/hasura/migrations/1688674667178_alter_table_public_joblines_add_column_assigned_team/down.sql
@@ -0,0 +1,4 @@
+-- Could not auto-generate a down migration.
+-- Please write an appropriate down migration for the SQL below:
+-- alter table "public"."joblines" add column "assigned_team" uuid
+-- null;
diff --git a/hasura/migrations/1688674667178_alter_table_public_joblines_add_column_assigned_team/up.sql b/hasura/migrations/1688674667178_alter_table_public_joblines_add_column_assigned_team/up.sql
new file mode 100644
index 000000000..0128442fe
--- /dev/null
+++ b/hasura/migrations/1688674667178_alter_table_public_joblines_add_column_assigned_team/up.sql
@@ -0,0 +1,2 @@
+alter table "public"."joblines" add column "assigned_team" uuid
+ null;
diff --git a/hasura/migrations/1688674763806_set_fk_public_joblines_assigned_team/down.sql b/hasura/migrations/1688674763806_set_fk_public_joblines_assigned_team/down.sql
new file mode 100644
index 000000000..651570671
--- /dev/null
+++ b/hasura/migrations/1688674763806_set_fk_public_joblines_assigned_team/down.sql
@@ -0,0 +1 @@
+alter table "public"."joblines" drop constraint "joblines_assigned_team_fkey";
diff --git a/hasura/migrations/1688674763806_set_fk_public_joblines_assigned_team/up.sql b/hasura/migrations/1688674763806_set_fk_public_joblines_assigned_team/up.sql
new file mode 100644
index 000000000..4740318f8
--- /dev/null
+++ b/hasura/migrations/1688674763806_set_fk_public_joblines_assigned_team/up.sql
@@ -0,0 +1,5 @@
+alter table "public"."joblines"
+ add constraint "joblines_assigned_team_fkey"
+ foreign key ("assigned_team")
+ references "public"."employee_teams"
+ ("id") on update restrict on delete restrict;
diff --git a/server/accounting/qbxml/qbxml-payables.js b/server/accounting/qbxml/qbxml-payables.js
index 5bc99cf5f..26f0f2d8a 100644
--- a/server/accounting/qbxml/qbxml-payables.js
+++ b/server/accounting/qbxml/qbxml-payables.js
@@ -133,7 +133,13 @@ const generateBillLine = (billLine, responsibilityCenters, jobClass) => {
const findTaxCode = (billLine, taxcode) => {
const {
applicable_taxes: { local, state, federal },
- } = billLine;
+ } =
+ billLine.applicable_taxes === null
+ ? {
+ ...billLine,
+ applicable_taxes: { local: false, state: false, federal: false },
+ }
+ : billLine;
const t = taxcode.filter(
(t) =>
!!t.local === !!local &&
diff --git a/server/accounting/qbxml/qbxml-receivables.js b/server/accounting/qbxml/qbxml-receivables.js
index e697e0985..5489f859e 100644
--- a/server/accounting/qbxml/qbxml-receivables.js
+++ b/server/accounting/qbxml/qbxml-receivables.js
@@ -262,10 +262,10 @@ const generateInvoiceQbxml = (
RefNumber: jobs_by_pk.ro_number,
BillAddress: {
Addr1: jobs_by_pk.ownr_co_nm
- ? jobs_by_pk.ownr_co_nm.substring(0, 30)
- : `${`${jobs_by_pk.ownr_ln || ""} ${
- jobs_by_pk.ownr_fn || ""
- }`.substring(0, 30)}`,
+ ? jobs_by_pk.ownr_co_nm.substring(0, 30).trim()
+ : `${`${jobs_by_pk.ownr_ln || ""} ${jobs_by_pk.ownr_fn || ""}`
+ .substring(0, 30)
+ .trim()}`,
Addr2: jobs_by_pk.ownr_addr1,
Addr3: jobs_by_pk.ownr_addr2,
City: jobs_by_pk.ownr_city,
@@ -274,10 +274,10 @@ const generateInvoiceQbxml = (
},
ShipAddress: {
Addr1: jobs_by_pk.ownr_co_nm
- ? jobs_by_pk.ownr_co_nm.substring(0, 30)
- : `${`${jobs_by_pk.ownr_ln || ""} ${
- jobs_by_pk.ownr_fn || ""
- }`.substring(0, 30)}`,
+ ? jobs_by_pk.ownr_co_nm.substring(0, 30).trim()
+ : `${`${jobs_by_pk.ownr_ln || ""} ${jobs_by_pk.ownr_fn || ""}`
+ .substring(0, 30)
+ .trim()}`,
Addr2: jobs_by_pk.ownr_addr1,
Addr3: jobs_by_pk.ownr_addr2,
City: jobs_by_pk.ownr_city,
diff --git a/server/accounting/qbxml/qbxml-utils.js b/server/accounting/qbxml/qbxml-utils.js
index af59b3cf7..8909cbb2a 100644
--- a/server/accounting/qbxml/qbxml-utils.js
+++ b/server/accounting/qbxml/qbxml-utils.js
@@ -21,9 +21,9 @@ exports.generateOwnerTier = (jobs_by_pk, isThreeTier, twotierpref) => {
? `${jobs_by_pk.ownr_co_nm.substring(0, 30)} #${
jobs_by_pk.owner.accountingid || ""
}`
- : `${`${jobs_by_pk.ownr_ln || ""} ${
- jobs_by_pk.ownr_fn || ""
- }`.substring(0, 30)} #${jobs_by_pk.owner.accountingid || ""}`
+ : `${`${jobs_by_pk.ownr_ln || ""} ${jobs_by_pk.ownr_fn || ""}`
+ .substring(0, 30)
+ .trim()} #${jobs_by_pk.owner.accountingid || ""}`
)
.trim()
.replace(":", " ");
@@ -39,9 +39,9 @@ exports.generateOwnerTier = (jobs_by_pk, isThreeTier, twotierpref) => {
? `${jobs_by_pk.ownr_co_nm.substring(0, 30)} #${
jobs_by_pk.owner.accountingid || ""
}`
- : `${`${jobs_by_pk.ownr_ln || ""} ${
- jobs_by_pk.ownr_fn || ""
- }`.substring(0, 30)} #${jobs_by_pk.owner.accountingid || ""}`
+ : `${`${jobs_by_pk.ownr_ln || ""} ${jobs_by_pk.ownr_fn || ""}`
+ .substring(0, 30)
+ .trim()} #${jobs_by_pk.owner.accountingid || ""}`
)
.trim()
.replace(":", " ");