Merged in feature/2021-07-30 (pull request #158)

feature/2021-07-30

Approved-by: Patrick Fic
This commit is contained in:
Patrick Fic
2021-08-03 18:46:24 +00:00
22 changed files with 777 additions and 49 deletions

View File

@@ -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
@@ -799,6 +799,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>reminder</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>scheduledfor</name> <name>scheduledfor</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -7033,6 +7054,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>tt_allow_post_to_invoiced</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>use_fippa</name> <name>use_fippa</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -14305,6 +14347,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>sms</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>
<folder_node> <folder_node>
<name>sub_status</name> <name>sub_status</name>
<children> <children>
@@ -16904,6 +16967,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>markasexported</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>markpstexempt</name> <name>markpstexempt</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -17114,6 +17198,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>uninvoice</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>unvoid</name> <name>unvoid</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -21454,6 +21559,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>adminwarning</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>allocations</name> <name>allocations</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -22398,6 +22524,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>deletedelivery</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>deleteintake</name> <name>deleteintake</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>

View File

@@ -1,26 +1,50 @@
import { Button, Divider, Popover, Space } from "antd";
import { AlertFilled } from "@ant-design/icons"; import { AlertFilled } from "@ant-design/icons";
import {
Button,
Divider,
Dropdown,
Menu,
notification,
Popover,
Space,
} from "antd";
import parsePhoneNumber from "libphonenumber-js";
import moment from "moment";
import queryString from "query-string";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { Link, useHistory, useLocation } from "react-router-dom"; import { Link, useHistory, useLocation } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import {
openChatByPhone,
setMessage,
} from "../../redux/messaging/messaging.actions";
import { setModalContext } from "../../redux/modals/modals.actions"; import { setModalContext } from "../../redux/modals/modals.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter"; import CurrencyFormatter from "../../utils/CurrencyFormatter";
import PhoneFormatter from "../../utils/PhoneFormatter";
import { GenerateDocument } from "../../utils/RenderTemplate"; import { GenerateDocument } from "../../utils/RenderTemplate";
import { TemplateList } from "../../utils/TemplateConstants"; import { TemplateList } from "../../utils/TemplateConstants";
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
import DataLabel from "../data-label/data-label.component"; import DataLabel from "../data-label/data-label.component";
import ScheduleAtChange from "./job-at-change.component"; import ScheduleAtChange from "./job-at-change.component";
import ScheduleEventColor from "./schedule-event.color.component"; import ScheduleEventColor from "./schedule-event.color.component";
import queryString from "query-string";
import ScheduleEventNote from "./schedule-event.note.component"; import ScheduleEventNote from "./schedule-event.note.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
setScheduleContext: (context) => setScheduleContext: (context) =>
dispatch(setModalContext({ context: context, modal: "schedule" })), dispatch(setModalContext({ context: context, modal: "schedule" })),
openChatByPhone: (phone) => dispatch(openChatByPhone(phone)),
setMessage: (text) => dispatch(setMessage(text)),
}); });
export function ScheduleEventComponent({ export function ScheduleEventComponent({
bodyshop,
setMessage,
openChatByPhone,
event, event,
refetch, refetch,
handleCancel, handleCancel,
@@ -77,9 +101,10 @@ export function ScheduleEventComponent({
{(event.job && event.job.ownr_ea) || ""} {(event.job && event.job.ownr_ea) || ""}
</DataLabel> </DataLabel>
<DataLabel label={t("jobs.fields.ownr_ph1")}> <DataLabel label={t("jobs.fields.ownr_ph1")}>
<PhoneFormatter> <ChatOpenButton
{(event.job && event.job.ownr_ph1) || ""} phone={event.job && event.job.ownr_ph1}
</PhoneFormatter> jobid={event.job.id}
/>
</DataLabel> </DataLabel>
<DataLabel label={t("jobs.fields.alt_transport")}> <DataLabel label={t("jobs.fields.alt_transport")}>
{(event.job && event.job.alt_transport) || ""} {(event.job && event.job.alt_transport) || ""}
@@ -109,23 +134,62 @@ export function ScheduleEventComponent({
{t("appointments.actions.preview")} {t("appointments.actions.preview")}
</Button> </Button>
) : null} ) : null}
<Button
onClick={() => { <Dropdown
const Template = TemplateList("job").appointment_reminder; overlay={
GenerateDocument( <Menu>
{ <Menu.Item
name: Template.key, onClick={() => {
variables: { id: event.job.id }, const Template = TemplateList("job").appointment_reminder;
}, GenerateDocument(
{ to: event.job && event.job.ownr_ea, subject: Template.subject }, {
"e", name: Template.key,
event.job && event.job.id variables: { id: event.job.id },
); },
}} {
disabled={event.arrived} to: event.job && event.job.ownr_ea,
subject: Template.subject,
},
"e",
event.job && event.job.id
);
}}
disabled={event.arrived}
>
{t("general.labels.email")}
</Menu.Item>
<Menu.Item
onClick={() => {
const p = parsePhoneNumber(event.job.ownr_ph1, "CA");
if (p && p.isValid()) {
openChatByPhone({
phone_num: p.formatInternational(),
jobid: event.job.id,
});
setMessage(
t("appointments.labels.reminder", {
shopname: bodyshop.shopname,
date: moment(event.start).format("MM/DD/YYYY"),
time: moment(event.start).format("HH:MM a"),
})
);
setVisible(false);
} else {
notification["error"]({
message: t("messaging.error.invalidphone"),
});
}
}}
disabled={event.arrived || !bodyshop.messagingservicesid}
>
{t("general.labels.sms")}
</Menu.Item>
</Menu>
}
> >
{t("appointments.actions.sendreminder")} <Button>{t("appointments.actions.sendreminder")}</Button>
</Button> </Dropdown>
<Button onClick={() => handleCancel(event.id)} disabled={event.arrived}> <Button onClick={() => handleCancel(event.id)} disabled={event.arrived}>
{t("appointments.actions.cancel")} {t("appointments.actions.cancel")}
</Button> </Button>
@@ -206,4 +270,7 @@ export function ScheduleEventComponent({
</Popover> </Popover>
); );
} }
export default connect(null, mapDispatchToProps)(ScheduleEventComponent); export default connect(
mapStateToProps,
mapDispatchToProps
)(ScheduleEventComponent);

View File

@@ -15,6 +15,7 @@ const JobSearchSelect = (
{ {
disabled, disabled,
convertedOnly = false, convertedOnly = false,
notInvoiced = false,
notExported = true, notExported = true,
clm_no = false, clm_no = false,
...restProps ...restProps
@@ -30,6 +31,7 @@ const JobSearchSelect = (
variables: { variables: {
...(convertedOnly ? { isConverted: true } : {}), ...(convertedOnly ? { isConverted: true } : {}),
...(notExported ? { notExported: true } : {}), ...(notExported ? { notExported: true } : {}),
...(notInvoiced ? { notInvoiced: true } : {}),
}, },
} }
: {}), : {}),

View File

@@ -6,8 +6,8 @@ import { useTranslation } from "react-i18next";
export default function JobAdminDeleteIntake({ job }) { export default function JobAdminDeleteIntake({ job }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [updateJob] = useMutation(gql` const [deleteIntake] = useMutation(gql`
mutation UPDATE_JOB($jobId: uuid!) { mutation DELETE_INTAKE($jobId: uuid!) {
update_jobs_by_pk( update_jobs_by_pk(
pk_columns: { id: $jobId } pk_columns: { id: $jobId }
_set: { intakechecklist: null } _set: { intakechecklist: null }
@@ -18,9 +18,39 @@ export default function JobAdminDeleteIntake({ job }) {
} }
`); `);
const [DELETE_DELIVERY] = useMutation(gql`
mutation DELETE_DELIVERY($jobId: uuid!) {
update_jobs_by_pk(
pk_columns: { id: $jobId }
_set: { deliverychecklist: null }
) {
id
deliverychecklist
}
}
`);
const handleDelete = async (values) => { const handleDelete = async (values) => {
setLoading(true); setLoading(true);
const result = await updateJob({ const result = await deleteIntake({
variables: { jobId: job.id },
});
if (!!!result.errors) {
notification["success"]({ message: t("jobs.successes.save") });
} else {
notification["error"]({
message: t("jobs.errors.saving", {
error: JSON.stringify(result.errors),
}),
});
}
setLoading(false);
};
const handleDeleteDelivery = async (values) => {
setLoading(true);
const result = await DELETE_DELIVERY({
variables: { jobId: job.id }, variables: { jobId: job.id },
}); });
@@ -34,12 +64,16 @@ export default function JobAdminDeleteIntake({ job }) {
}); });
} }
setLoading(false); setLoading(false);
//Get the owner details, populate it all back into the job.
}; };
return ( return (
<Button loading={loading} onClick={handleDelete}> <>
{t("jobs.labels.deleteintake")} <Button loading={loading} onClick={handleDelete}>
</Button> {t("jobs.labels.deleteintake")}
</Button>
<Button loading={loading} onClick={handleDeleteDelivery}>
{t("jobs.labels.deletedelivery")}
</Button>
</>
); );
} }

View File

@@ -7,6 +7,7 @@ import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import moment from "moment";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
}); });
@@ -21,8 +22,8 @@ export default connect(
export function JobAdminMarkReexport({ bodyshop, job }) { export function JobAdminMarkReexport({ bodyshop, job }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [updateJob] = useMutation(gql` const [markJobForReexport] = useMutation(gql`
mutation UPDATE_JOB($jobId: uuid!) { mutation MARK_JOB_FOR_REEXPORT($jobId: uuid!) {
update_jobs_by_pk( update_jobs_by_pk(
pk_columns: { id: $jobId } pk_columns: { id: $jobId }
_set: { date_exported: null _set: { date_exported: null
@@ -30,14 +31,84 @@ export function JobAdminMarkReexport({ bodyshop, job }) {
} }
) { ) {
id id
intakechecklist date_exported
status
date_invoiced
} }
} }
`); `);
const handleUpdate = async (values) => { const [markJobExported] = useMutation(gql`
mutation MARK_JOB_AS_EXPORTED($jobId: uuid!, $date_exported: timestamptz!) {
update_jobs_by_pk(
pk_columns: { id: $jobId }
_set: { date_exported: $date_exported
status: "${bodyshop.md_ro_statuses.default_exported}"
}
) {
id
date_exported
date_invoiced
status
}
}
`);
const [markJobUninvoiced] = useMutation(gql`
mutation MARK_JOB_AS_UNINVOICED($jobId: uuid!, ) {
update_jobs_by_pk(
pk_columns: { id: $jobId }
_set: { date_exported: null
date_invoiced: null
status: "${bodyshop.md_ro_statuses.default_delivered}"
}
) {
id
date_exported
date_invoiced
status
}
}
`);
const handleMarkForExport = async () => {
setLoading(true); setLoading(true);
const result = await updateJob({ const result = await markJobForReexport({
variables: { jobId: job.id },
});
if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") });
} else {
notification["error"]({
message: t("jobs.errors.saving", {
error: JSON.stringify(result.errors),
}),
});
}
setLoading(false);
};
const handleMarkExported = async () => {
setLoading(true);
const result = await markJobExported({
variables: { jobId: job.id, date_exported: moment() },
});
if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") });
} else {
notification["error"]({
message: t("jobs.errors.saving", {
error: JSON.stringify(result.errors),
}),
});
}
setLoading(false);
};
const handleUninvoice = async () => {
setLoading(true);
const result = await markJobUninvoiced({
variables: { jobId: job.id }, variables: { jobId: job.id },
}); });
@@ -51,16 +122,31 @@ export function JobAdminMarkReexport({ bodyshop, job }) {
}); });
} }
setLoading(false); setLoading(false);
//Get the owner details, populate it all back into the job.
}; };
return ( return (
<Button <>
loading={loading} <Button
disabled={!job.date_exported} loading={loading}
onClick={handleUpdate} disabled={!job.date_exported}
> onClick={handleMarkForExport}
{t("jobs.labels.markforreexport")} >
</Button> {t("jobs.labels.markforreexport")}
</Button>
<Button
loading={loading}
disabled={job.date_exported}
onClick={handleMarkExported}
>
{t("jobs.actions.markasexported")}
</Button>
<Button
loading={loading}
disabled={!job.date_invoiced || job.date_exported}
onClick={handleUninvoice}
>
{t("jobs.actions.uninvoice")}
</Button>
</>
); );
} }

View File

@@ -444,6 +444,13 @@ export default function ShopInfoGeneral({ form }) {
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
<Form.Item
name={["tt_allow_post_to_invoiced"]}
label={t("bodyshop.fields.tt_allow_post_to_invoiced")}
valuePropName="checked"
>
<Switch />
</Form.Item>
</LayoutFormRow> </LayoutFormRow>
<LayoutFormRow grow header={t("bodyshop.labels.messagingpresets")}> <LayoutFormRow grow header={t("bodyshop.labels.messagingpresets")}>
<Form.List name={["md_messaging_presets"]}> <Form.List name={["md_messaging_presets"]}>

View File

@@ -30,7 +30,10 @@ export function TechClockInComponent({ form, bodyshop, technician }) {
}, },
]} ]}
> >
<JobSearchSelect /> <JobSearchSelect
convertedOnly={!bodyshop.tt_allow_post_to_invoiced}
notExported={!bodyshop.tt_allow_post_to_invoiced}
/>
</Form.Item> </Form.Item>
<Form.Item <Form.Item

View File

@@ -82,7 +82,10 @@ export function TimeTicketModalComponent({
}, },
]} ]}
> >
<JobSearchSelect convertedOnly notExported={false} /> <JobSearchSelect
convertedOnly={!bodyshop.tt_allow_post_to_invoiced}
notExported={!bodyshop.tt_allow_post_to_invoiced}
/>
</Form.Item> </Form.Item>
)} )}
</Form.Item> </Form.Item>

View File

@@ -92,6 +92,7 @@ export const QUERY_BODYSHOP = gql`
cdk_dealerid cdk_dealerid
features features
attach_pdf_to_email attach_pdf_to_email
tt_allow_post_to_invoiced
employees { employees {
id id
active active
@@ -180,6 +181,7 @@ export const UPDATE_SHOP = gql`
md_jobline_presets md_jobline_presets
cdk_dealerid cdk_dealerid
attach_pdf_to_email attach_pdf_to_email
tt_allow_post_to_invoiced
employees { employees {
id id
first_name first_name

View File

@@ -1025,6 +1025,7 @@ export const SEARCH_JOBS_FOR_AUTOCOMPLETE = gql`
$search: String $search: String
$isConverted: Boolean $isConverted: Boolean
$notExported: Boolean $notExported: Boolean
$notInvoiced: Boolean
) { ) {
search_jobs( search_jobs(
args: { search: $search } args: { search: $search }
@@ -1033,6 +1034,7 @@ export const SEARCH_JOBS_FOR_AUTOCOMPLETE = gql`
_and: { _and: {
converted: { _eq: $isConverted } converted: { _eq: $isConverted }
date_exported: { _is_null: $notExported } date_exported: { _is_null: $notExported }
date_invoiced: { _is_null: $notInvoiced }
} }
} }
) { ) {

View File

@@ -1,5 +1,5 @@
import { useQuery } from "@apollo/client"; import { useQuery } from "@apollo/client";
import { Card, Col, Result, Row, Space } from "antd"; import { Card, Col, Result, Row, Space, Typography } from "antd";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -84,6 +84,9 @@ export function JobsCloseContainer({ setBreadcrumbs, setSelectedHeader }) {
return ( return (
<RbacWrapper action="jobs:admin"> <RbacWrapper action="jobs:admin">
<Typography.Title level={4} style={{ color: "tomato" }}>
{t("jobs.labels.adminwarning")}
</Typography.Title>
<Row gutter={[16, 16]}> <Row gutter={[16, 16]}>
<Col {...colSpan}> <Col {...colSpan}>
<Card style={cardStyle}> <Card style={cardStyle}>

View File

@@ -53,6 +53,7 @@
"nocompletingjobs": "No jobs scheduled for completion.", "nocompletingjobs": "No jobs scheduled for completion.",
"nodateselected": "No date has been selected.", "nodateselected": "No date has been selected.",
"priorappointments": "Previous Appointments", "priorappointments": "Previous Appointments",
"reminder": "This is {{shopname}} reminding you about an appointment on {{date}} at {{time}}. Please let us know if you are not able to make the appointment. We look forward to seeing you soon. ",
"scheduledfor": "Scheduled appointment for: ", "scheduledfor": "Scheduled appointment for: ",
"smartscheduling": "Smart Scheduling", "smartscheduling": "Smart Scheduling",
"suggesteddates": "Suggested Dates" "suggesteddates": "Suggested Dates"
@@ -445,6 +446,7 @@
"production_statuses": "Production Statuses" "production_statuses": "Production Statuses"
}, },
"target_touchtime": "Target Touch Time", "target_touchtime": "Target Touch Time",
"tt_allow_post_to_invoiced": "Allow Time Tickets to be posted to Invoiced & Exported Jobs",
"use_fippa": "Use FIPPA for Names on Generated Documents?", "use_fippa": "Use FIPPA for Names on Generated Documents?",
"website": "Website", "website": "Website",
"zip_post": "Zip/Postal Code" "zip_post": "Zip/Postal Code"
@@ -897,6 +899,7 @@
"sendagain": "Send Again", "sendagain": "Send Again",
"sendby": "Send By", "sendby": "Send By",
"signin": "Sign In", "signin": "Sign In",
"sms": "SMS",
"sub_status": { "sub_status": {
"expired": "The subscription for this shop has expired. Please contact technical support to reactivate the subscription. " "expired": "The subscription for this shop has expired. Please contact technical support to reactivate the subscription. "
}, },
@@ -1056,6 +1059,7 @@
"intake": "Intake", "intake": "Intake",
"manualnew": "Create New Job Manually", "manualnew": "Create New Job Manually",
"mark": "Mark", "mark": "Mark",
"markasexported": "Mark as Exported",
"markpstexempt": "Mark Job PST Exempt", "markpstexempt": "Mark Job PST Exempt",
"markpstexemptconfirm": "Are you sure you want to do this? To undo this, you must manually update all PST rates.", "markpstexemptconfirm": "Are you sure you want to do this? To undo this, you must manually update all PST rates.",
"postbills": "Post Bills", "postbills": "Post Bills",
@@ -1066,6 +1070,7 @@
"schedule": "Schedule", "schedule": "Schedule",
"sendcsi": "Send CSI", "sendcsi": "Send CSI",
"sync": "Sync", "sync": "Sync",
"uninvoice": "Uninvoice",
"unvoid": "Unvoid Job", "unvoid": "Unvoid Job",
"viewchecklist": "View Checklists", "viewchecklist": "View Checklists",
"viewdetail": "View Details" "viewdetail": "View Details"
@@ -1285,6 +1290,7 @@
"additionaltotal": "Additional Total", "additionaltotal": "Additional Total",
"adjustmentrate": "Adjustment Rate", "adjustmentrate": "Adjustment Rate",
"adjustments": "Adjustments", "adjustments": "Adjustments",
"adminwarning": "Use the functionality on this page at your own risk. You are responsible for any and all changes to your data.",
"allocations": "Allocations", "allocations": "Allocations",
"alreadyclosed": "This job has already been closed.", "alreadyclosed": "This job has already been closed.",
"appointmentconfirmation": "Send confirmation to customer?", "appointmentconfirmation": "Send confirmation to customer?",
@@ -1337,7 +1343,8 @@
"waived": "Waived" "waived": "Waived"
}, },
"deleteconfirm": "Are you sure you want to delete this job? This cannot be undone. ", "deleteconfirm": "Are you sure you want to delete this job? This cannot be undone. ",
"deleteintake": "Delete Intake", "deletedelivery": "Delete Delivery Checklist",
"deleteintake": "Delete Intake Checklist",
"deliverchecklist": "Deliver Checklist", "deliverchecklist": "Deliver Checklist",
"difference": "Difference", "difference": "Difference",
"diskscan": "Scan Disk for Estimates", "diskscan": "Scan Disk for Estimates",

View File

@@ -53,6 +53,7 @@
"nocompletingjobs": "", "nocompletingjobs": "",
"nodateselected": "No se ha seleccionado ninguna fecha.", "nodateselected": "No se ha seleccionado ninguna fecha.",
"priorappointments": "Nombramientos previos", "priorappointments": "Nombramientos previos",
"reminder": "",
"scheduledfor": "Cita programada para:", "scheduledfor": "Cita programada para:",
"smartscheduling": "", "smartscheduling": "",
"suggesteddates": "" "suggesteddates": ""
@@ -445,6 +446,7 @@
"production_statuses": "" "production_statuses": ""
}, },
"target_touchtime": "", "target_touchtime": "",
"tt_allow_post_to_invoiced": "",
"use_fippa": "", "use_fippa": "",
"website": "", "website": "",
"zip_post": "" "zip_post": ""
@@ -897,6 +899,7 @@
"sendagain": "", "sendagain": "",
"sendby": "", "sendby": "",
"signin": "", "signin": "",
"sms": "",
"sub_status": { "sub_status": {
"expired": "" "expired": ""
}, },
@@ -1056,6 +1059,7 @@
"intake": "", "intake": "",
"manualnew": "", "manualnew": "",
"mark": "", "mark": "",
"markasexported": "",
"markpstexempt": "", "markpstexempt": "",
"markpstexemptconfirm": "", "markpstexemptconfirm": "",
"postbills": "Contabilizar facturas", "postbills": "Contabilizar facturas",
@@ -1066,6 +1070,7 @@
"schedule": "Programar", "schedule": "Programar",
"sendcsi": "", "sendcsi": "",
"sync": "", "sync": "",
"uninvoice": "",
"unvoid": "", "unvoid": "",
"viewchecklist": "", "viewchecklist": "",
"viewdetail": "" "viewdetail": ""
@@ -1285,6 +1290,7 @@
"additionaltotal": "", "additionaltotal": "",
"adjustmentrate": "", "adjustmentrate": "",
"adjustments": "", "adjustments": "",
"adminwarning": "",
"allocations": "", "allocations": "",
"alreadyclosed": "", "alreadyclosed": "",
"appointmentconfirmation": "¿Enviar confirmación al cliente?", "appointmentconfirmation": "¿Enviar confirmación al cliente?",
@@ -1337,6 +1343,7 @@
"waived": "" "waived": ""
}, },
"deleteconfirm": "", "deleteconfirm": "",
"deletedelivery": "",
"deleteintake": "", "deleteintake": "",
"deliverchecklist": "", "deliverchecklist": "",
"difference": "", "difference": "",

View File

@@ -53,6 +53,7 @@
"nocompletingjobs": "", "nocompletingjobs": "",
"nodateselected": "Aucune date n'a été sélectionnée.", "nodateselected": "Aucune date n'a été sélectionnée.",
"priorappointments": "Rendez-vous précédents", "priorappointments": "Rendez-vous précédents",
"reminder": "",
"scheduledfor": "Rendez-vous prévu pour:", "scheduledfor": "Rendez-vous prévu pour:",
"smartscheduling": "", "smartscheduling": "",
"suggesteddates": "" "suggesteddates": ""
@@ -445,6 +446,7 @@
"production_statuses": "" "production_statuses": ""
}, },
"target_touchtime": "", "target_touchtime": "",
"tt_allow_post_to_invoiced": "",
"use_fippa": "", "use_fippa": "",
"website": "", "website": "",
"zip_post": "" "zip_post": ""
@@ -897,6 +899,7 @@
"sendagain": "", "sendagain": "",
"sendby": "", "sendby": "",
"signin": "", "signin": "",
"sms": "",
"sub_status": { "sub_status": {
"expired": "" "expired": ""
}, },
@@ -1056,6 +1059,7 @@
"intake": "", "intake": "",
"manualnew": "", "manualnew": "",
"mark": "", "mark": "",
"markasexported": "",
"markpstexempt": "", "markpstexempt": "",
"markpstexemptconfirm": "", "markpstexemptconfirm": "",
"postbills": "Poster des factures", "postbills": "Poster des factures",
@@ -1066,6 +1070,7 @@
"schedule": "Programme", "schedule": "Programme",
"sendcsi": "", "sendcsi": "",
"sync": "", "sync": "",
"uninvoice": "",
"unvoid": "", "unvoid": "",
"viewchecklist": "", "viewchecklist": "",
"viewdetail": "" "viewdetail": ""
@@ -1285,6 +1290,7 @@
"additionaltotal": "", "additionaltotal": "",
"adjustmentrate": "", "adjustmentrate": "",
"adjustments": "", "adjustments": "",
"adminwarning": "",
"allocations": "", "allocations": "",
"alreadyclosed": "", "alreadyclosed": "",
"appointmentconfirmation": "Envoyer une confirmation au client?", "appointmentconfirmation": "Envoyer une confirmation au client?",
@@ -1337,6 +1343,7 @@
"waived": "" "waived": ""
}, },
"deleteconfirm": "", "deleteconfirm": "",
"deletedelivery": "",
"deleteintake": "", "deleteintake": "",
"deliverchecklist": "", "deliverchecklist": "",
"difference": "", "difference": "",

View File

@@ -0,0 +1,5 @@
- args:
cascade: false
read_only: false
sql: ALTER TABLE "public"."bodyshops" DROP COLUMN "tt_allow_post_to_invoiced";
type: run_sql

View File

@@ -0,0 +1,6 @@
- args:
cascade: false
read_only: false
sql: ALTER TABLE "public"."bodyshops" ADD COLUMN "tt_allow_post_to_invoiced" boolean
NOT NULL DEFAULT false;
type: run_sql

View File

@@ -0,0 +1,88 @@
- args:
role: user
table:
name: bodyshops
schema: public
type: drop_select_permission
- args:
permission:
allow_aggregations: false
columns:
- accountingconfig
- address1
- address2
- appt_alt_transport
- appt_colors
- appt_length
- attach_pdf_to_email
- bill_tax_rates
- cdk_dealerid
- city
- country
- created_at
- default_adjustment_rate
- deliverchecklist
- email
- enforce_class
- enforce_referral
- features
- federal_tax_id
- id
- imexshopid
- inhousevendorid
- insurance_vendor_id
- intakechecklist
- jc_hourly_rates
- jobsizelimit
- logo_img_path
- md_categories
- md_ccc_rates
- md_classes
- md_hour_split
- md_ins_cos
- md_jobline_presets
- md_labor_rates
- md_messaging_presets
- md_notes_presets
- md_order_statuses
- md_parts_locations
- md_payment_types
- md_rbac
- md_referral_sources
- md_responsibility_centers
- md_ro_statuses
- messagingservicesid
- phone
- prodtargethrs
- production_config
- region_config
- schedule_end_time
- schedule_start_time
- scoreboard_target
- shopname
- shoprates
- speedprint
- ssbuckets
- state
- state_tax_id
- stripe_acct_id
- sub_status
- target_touchtime
- template_header
- textid
- updated_at
- use_fippa
- website
- workingdays
- zip_post
computed_fields: []
filter:
associations:
user:
authid:
_eq: X-Hasura-User-Id
role: user
table:
name: bodyshops
schema: public
type: create_select_permission

View File

@@ -0,0 +1,89 @@
- args:
role: user
table:
name: bodyshops
schema: public
type: drop_select_permission
- args:
permission:
allow_aggregations: false
columns:
- accountingconfig
- address1
- address2
- appt_alt_transport
- appt_colors
- appt_length
- attach_pdf_to_email
- bill_tax_rates
- cdk_dealerid
- city
- country
- created_at
- default_adjustment_rate
- deliverchecklist
- email
- enforce_class
- enforce_referral
- features
- federal_tax_id
- id
- imexshopid
- inhousevendorid
- insurance_vendor_id
- intakechecklist
- jc_hourly_rates
- jobsizelimit
- logo_img_path
- md_categories
- md_ccc_rates
- md_classes
- md_hour_split
- md_ins_cos
- md_jobline_presets
- md_labor_rates
- md_messaging_presets
- md_notes_presets
- md_order_statuses
- md_parts_locations
- md_payment_types
- md_rbac
- md_referral_sources
- md_responsibility_centers
- md_ro_statuses
- messagingservicesid
- phone
- prodtargethrs
- production_config
- region_config
- schedule_end_time
- schedule_start_time
- scoreboard_target
- shopname
- shoprates
- speedprint
- ssbuckets
- state
- state_tax_id
- stripe_acct_id
- sub_status
- target_touchtime
- template_header
- textid
- tt_allow_post_to_invoiced
- updated_at
- use_fippa
- website
- workingdays
- zip_post
computed_fields: []
filter:
associations:
user:
authid:
_eq: X-Hasura-User-Id
role: user
table:
name: bodyshops
schema: public
type: create_select_permission

View File

@@ -0,0 +1,80 @@
- args:
role: user
table:
name: bodyshops
schema: public
type: drop_update_permission
- args:
permission:
columns:
- accountingconfig
- address1
- address2
- appt_alt_transport
- appt_colors
- appt_length
- attach_pdf_to_email
- bill_tax_rates
- city
- country
- created_at
- default_adjustment_rate
- deliverchecklist
- email
- enforce_class
- enforce_referral
- federal_tax_id
- id
- inhousevendorid
- insurance_vendor_id
- intakechecklist
- jc_hourly_rates
- logo_img_path
- md_categories
- md_ccc_rates
- md_classes
- md_hour_split
- md_ins_cos
- md_jobline_presets
- md_labor_rates
- md_messaging_presets
- md_notes_presets
- md_order_statuses
- md_parts_locations
- md_payment_types
- md_rbac
- md_referral_sources
- md_responsibility_centers
- md_ro_statuses
- phone
- prodtargethrs
- production_config
- schedule_end_time
- schedule_start_time
- scoreboard_target
- shopname
- shoprates
- speedprint
- ssbuckets
- state
- state_tax_id
- target_touchtime
- updated_at
- use_fippa
- website
- workingdays
- zip_post
filter:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
set: {}
role: user
table:
name: bodyshops
schema: public
type: create_update_permission

View File

@@ -0,0 +1,81 @@
- args:
role: user
table:
name: bodyshops
schema: public
type: drop_update_permission
- args:
permission:
columns:
- accountingconfig
- address1
- address2
- appt_alt_transport
- appt_colors
- appt_length
- attach_pdf_to_email
- bill_tax_rates
- city
- country
- created_at
- default_adjustment_rate
- deliverchecklist
- email
- enforce_class
- enforce_referral
- federal_tax_id
- id
- inhousevendorid
- insurance_vendor_id
- intakechecklist
- jc_hourly_rates
- logo_img_path
- md_categories
- md_ccc_rates
- md_classes
- md_hour_split
- md_ins_cos
- md_jobline_presets
- md_labor_rates
- md_messaging_presets
- md_notes_presets
- md_order_statuses
- md_parts_locations
- md_payment_types
- md_rbac
- md_referral_sources
- md_responsibility_centers
- md_ro_statuses
- phone
- prodtargethrs
- production_config
- schedule_end_time
- schedule_start_time
- scoreboard_target
- shopname
- shoprates
- speedprint
- ssbuckets
- state
- state_tax_id
- target_touchtime
- tt_allow_post_to_invoiced
- updated_at
- use_fippa
- website
- workingdays
- zip_post
filter:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
set: {}
role: user
table:
name: bodyshops
schema: public
type: create_update_permission

View File

@@ -850,6 +850,7 @@ tables:
- target_touchtime - target_touchtime
- template_header - template_header
- textid - textid
- tt_allow_post_to_invoiced
- updated_at - updated_at
- use_fippa - use_fippa
- website - website
@@ -916,6 +917,7 @@ tables:
- state - state
- state_tax_id - state_tax_id
- target_touchtime - target_touchtime
- tt_allow_post_to_invoiced
- updated_at - updated_at
- use_fippa - use_fippa
- website - website

View File

@@ -76,7 +76,7 @@ exports.default = async (req, res) => {
allxmlsToUpload.push({ allxmlsToUpload.push({
xml: ret, xml: ret,
filename: `IM_${bodyshop.imexshopid}_${moment().format( filename: `IM_${bodyshop.autohouseid}_${moment().format(
"DDMMYYYY_HHMMSS" "DDMMYYYY_HHMMSS"
)}.xml`, )}.xml`,
}); });