Time Ticket Task Improvmenets.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
<babeledit_project version="1.2" be_version="2.7.1">
|
<babeledit_project be_version="2.7.1" version="1.2">
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
BabelEdit project file
|
BabelEdit project file
|
||||||
@@ -5608,6 +5608,27 @@
|
|||||||
<folder_node>
|
<folder_node>
|
||||||
<name>md_tasks_presets</name>
|
<name>md_tasks_presets</name>
|
||||||
<children>
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>enable_tasks</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>hourstype</name>
|
<name>hourstype</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -5692,6 +5713,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>use_approvals</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>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
@@ -8389,6 +8431,27 @@
|
|||||||
<folder_node>
|
<folder_node>
|
||||||
<name>ssbuckets</name>
|
<name>ssbuckets</name>
|
||||||
<children>
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>color</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>gte</name>
|
<name>gte</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -40461,6 +40524,27 @@
|
|||||||
</folder_node>
|
</folder_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>cardcolor</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>cardsettings</name>
|
<name>cardsettings</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -40671,6 +40755,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>legend</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>note</name>
|
<name>note</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -47825,6 +47930,53 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>labels</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>approval_queue_in_use</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>
|
||||||
|
<name>calculate</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>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
|
|||||||
@@ -246,11 +246,13 @@ function Header({
|
|||||||
{t("menus.header.timetickets")}
|
{t("menus.header.timetickets")}
|
||||||
</Link>
|
</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item key="ttapprovals" icon={<FieldTimeOutlined />}>
|
{bodyshop?.md_tasks_presets?.use_approvals && (
|
||||||
<Link to="/manage/ttapprovals">
|
<Menu.Item key="ttapprovals" icon={<FieldTimeOutlined />}>
|
||||||
{t("menus.header.ttapprovals")}
|
<Link to="/manage/ttapprovals">
|
||||||
</Link>
|
{t("menus.header.ttapprovals")}
|
||||||
</Menu.Item>
|
</Link>
|
||||||
|
</Menu.Item>
|
||||||
|
)}
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="entertimetickets"
|
key="entertimetickets"
|
||||||
icon={<Icon component={GiPlayerTime} />}
|
icon={<Icon component={GiPlayerTime} />}
|
||||||
|
|||||||
@@ -247,21 +247,24 @@ export function JobsDetailHeaderActions({
|
|||||||
>
|
>
|
||||||
{t("timetickets.actions.enter")}
|
{t("timetickets.actions.enter")}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item
|
{bodyshop.md_tasks_presets.enable_tasks && (
|
||||||
key="claimtimetickettasks"
|
<Menu.Item
|
||||||
disabled={
|
key="claimtimetickettasks"
|
||||||
!job.converted ||
|
disabled={
|
||||||
(!bodyshop.tt_allow_post_to_invoiced && job.date_invoiced)
|
!job.converted ||
|
||||||
}
|
(!bodyshop.tt_allow_post_to_invoiced && job.date_invoiced)
|
||||||
onClick={() => {
|
}
|
||||||
setTimeTicketTaskContext({
|
onClick={() => {
|
||||||
actions: {},
|
setTimeTicketTaskContext({
|
||||||
context: { jobid: job.id },
|
actions: {},
|
||||||
});
|
context: { jobid: job.id },
|
||||||
}}
|
});
|
||||||
>
|
}}
|
||||||
{t("timetickets.actions.claimtasks")}
|
>
|
||||||
</Menu.Item>
|
{t("timetickets.actions.claimtasks")}
|
||||||
|
</Menu.Item>
|
||||||
|
)}
|
||||||
|
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="enterpayments"
|
key="enterpayments"
|
||||||
disabled={!job.converted}
|
disabled={!job.converted}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
InputNumber,
|
InputNumber,
|
||||||
Row,
|
Row,
|
||||||
Space,
|
Space,
|
||||||
|
Switch,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -18,127 +19,146 @@ export default function ShopInfoTaskPresets({ form }) {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LayoutFormRow header={t("bodyshop.labels.md_tasks_presets")}>
|
<>
|
||||||
<Form.List name={["md_tasks_presets", "presets"]}>
|
<LayoutFormRow noDivider>
|
||||||
{(fields, { add, remove, move }) => {
|
<Form.Item
|
||||||
return (
|
label={t("bodyshop.fields.md_tasks_presets.enable_tasks")}
|
||||||
<div>
|
valuePropName="checked"
|
||||||
{fields.map((field, index) => (
|
name={["md_tasks_presets", "enable_tasks"]}
|
||||||
<Form.Item key={field.key}>
|
>
|
||||||
<LayoutFormRow noDivider>
|
<Switch />
|
||||||
<Form.Item
|
</Form.Item>
|
||||||
label={t("bodyshop.fields.md_tasks_presets.name")}
|
<Form.Item
|
||||||
key={`${index}name`}
|
label={t("bodyshop.fields.md_tasks_presets.use_approvals")}
|
||||||
name={[field.name, "name"]}
|
valuePropName="checked"
|
||||||
rules={[
|
name={["md_tasks_presets", "use_approvals"]}
|
||||||
{
|
>
|
||||||
required: true,
|
<Switch />
|
||||||
//message: t("general.validation.required"),
|
</Form.Item>
|
||||||
},
|
</LayoutFormRow>
|
||||||
]}
|
|
||||||
>
|
<LayoutFormRow header={t("bodyshop.labels.md_tasks_presets")}>
|
||||||
<Input />
|
<Form.List name={["md_tasks_presets", "presets"]}>
|
||||||
</Form.Item>
|
{(fields, { add, remove, move }) => {
|
||||||
<Form.Item
|
return (
|
||||||
label={t("bodyshop.fields.md_tasks_presets.hourstype")}
|
<div>
|
||||||
key={`${index}hourstype`}
|
{fields.map((field, index) => (
|
||||||
name={[field.name, "hourstype"]}
|
<Form.Item key={field.key}>
|
||||||
rules={[
|
<LayoutFormRow noDivider>
|
||||||
{
|
<Form.Item
|
||||||
required: true,
|
label={t("bodyshop.fields.md_tasks_presets.name")}
|
||||||
//message: t("general.validation.required"),
|
key={`${index}name`}
|
||||||
},
|
name={[field.name, "name"]}
|
||||||
]}
|
rules={[
|
||||||
>
|
{
|
||||||
<Checkbox.Group>
|
required: true,
|
||||||
<Row>
|
//message: t("general.validation.required"),
|
||||||
<Col span={8}>
|
},
|
||||||
<Checkbox
|
]}
|
||||||
value="LAB"
|
>
|
||||||
style={{ lineHeight: "32px" }}
|
<Input />
|
||||||
>
|
</Form.Item>
|
||||||
{t("joblines.fields.lbr_types.LAB")}
|
<Form.Item
|
||||||
</Checkbox>
|
label={t("bodyshop.fields.md_tasks_presets.hourstype")}
|
||||||
</Col>
|
key={`${index}hourstype`}
|
||||||
<Col span={8}>
|
name={[field.name, "hourstype"]}
|
||||||
<Checkbox
|
rules={[
|
||||||
value="LAR"
|
{
|
||||||
style={{ lineHeight: "32px" }}
|
required: true,
|
||||||
>
|
//message: t("general.validation.required"),
|
||||||
{t("joblines.fields.lbr_types.LAR")}
|
},
|
||||||
</Checkbox>
|
]}
|
||||||
</Col>
|
>
|
||||||
<Col span={8}>
|
<Checkbox.Group>
|
||||||
<Checkbox
|
<Row>
|
||||||
value="LAM"
|
<Col span={8}>
|
||||||
style={{ lineHeight: "32px" }}
|
<Checkbox
|
||||||
>
|
value="LAB"
|
||||||
{t("joblines.fields.lbr_types.LAM")}
|
style={{ lineHeight: "32px" }}
|
||||||
</Checkbox>
|
>
|
||||||
</Col>
|
{t("joblines.fields.lbr_types.LAB")}
|
||||||
<Col span={8}>
|
</Checkbox>
|
||||||
<Checkbox
|
</Col>
|
||||||
value="LAF"
|
<Col span={8}>
|
||||||
style={{ lineHeight: "32px" }}
|
<Checkbox
|
||||||
>
|
value="LAR"
|
||||||
{t("joblines.fields.lbr_types.LAF")}
|
style={{ lineHeight: "32px" }}
|
||||||
</Checkbox>
|
>
|
||||||
</Col>
|
{t("joblines.fields.lbr_types.LAR")}
|
||||||
<Col span={8}>
|
</Checkbox>
|
||||||
<Checkbox
|
</Col>
|
||||||
value="LAG"
|
<Col span={8}>
|
||||||
style={{ lineHeight: "32px" }}
|
<Checkbox
|
||||||
>
|
value="LAM"
|
||||||
{t("joblines.fields.lbr_types.LAG")}
|
style={{ lineHeight: "32px" }}
|
||||||
</Checkbox>
|
>
|
||||||
</Col>
|
{t("joblines.fields.lbr_types.LAM")}
|
||||||
</Row>
|
</Checkbox>
|
||||||
</Checkbox.Group>
|
</Col>
|
||||||
</Form.Item>
|
<Col span={8}>
|
||||||
<Form.Item
|
<Checkbox
|
||||||
label={t("bodyshop.fields.md_tasks_presets.percent")}
|
value="LAF"
|
||||||
key={`${index}percent`}
|
style={{ lineHeight: "32px" }}
|
||||||
name={[field.name, "percent"]}
|
>
|
||||||
>
|
{t("joblines.fields.lbr_types.LAF")}
|
||||||
<InputNumber min={0} max={100} />
|
</Checkbox>
|
||||||
</Form.Item>
|
</Col>
|
||||||
<Form.Item
|
<Col span={8}>
|
||||||
label={t("bodyshop.fields.md_tasks_presets.memo")}
|
<Checkbox
|
||||||
key={`${index}memo`}
|
value="LAG"
|
||||||
name={[field.name, "memo"]}
|
style={{ lineHeight: "32px" }}
|
||||||
>
|
>
|
||||||
<Input />
|
{t("joblines.fields.lbr_types.LAG")}
|
||||||
</Form.Item>
|
</Checkbox>
|
||||||
<Space wrap>
|
</Col>
|
||||||
<DeleteFilled
|
</Row>
|
||||||
onClick={() => {
|
</Checkbox.Group>
|
||||||
remove(field.name);
|
</Form.Item>
|
||||||
}}
|
<Form.Item
|
||||||
/>
|
label={t("bodyshop.fields.md_tasks_presets.percent")}
|
||||||
<FormListMoveArrows
|
key={`${index}percent`}
|
||||||
move={move}
|
name={[field.name, "percent"]}
|
||||||
index={index}
|
>
|
||||||
total={fields.length}
|
<InputNumber min={0} max={100} />
|
||||||
/>
|
</Form.Item>
|
||||||
</Space>
|
<Form.Item
|
||||||
</LayoutFormRow>
|
label={t("bodyshop.fields.md_tasks_presets.memo")}
|
||||||
|
key={`${index}memo`}
|
||||||
|
name={[field.name, "memo"]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Space wrap>
|
||||||
|
<DeleteFilled
|
||||||
|
onClick={() => {
|
||||||
|
remove(field.name);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<FormListMoveArrows
|
||||||
|
move={move}
|
||||||
|
index={index}
|
||||||
|
total={fields.length}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
</LayoutFormRow>
|
||||||
|
</Form.Item>
|
||||||
|
))}
|
||||||
|
<Form.Item>
|
||||||
|
<Button
|
||||||
|
type="dashed"
|
||||||
|
onClick={() => {
|
||||||
|
add();
|
||||||
|
}}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
>
|
||||||
|
{t("bodyshop.actions.add_task_preset")}
|
||||||
|
</Button>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
))}
|
</div>
|
||||||
<Form.Item>
|
);
|
||||||
<Button
|
}}
|
||||||
type="dashed"
|
</Form.List>
|
||||||
onClick={() => {
|
</LayoutFormRow>
|
||||||
add();
|
</>
|
||||||
}}
|
|
||||||
style={{ width: "100%" }}
|
|
||||||
>
|
|
||||||
{t("bodyshop.actions.add_task_preset")}
|
|
||||||
</Button>
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Form.List>
|
|
||||||
</LayoutFormRow>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,16 +205,15 @@ export function TimeTicketList({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
title: "Pay",
|
// title: "Pay",
|
||||||
dataIndex: "pay",
|
// dataIndex: "pay",
|
||||||
key: "pay",
|
// key: "pay",
|
||||||
render: (text, record) =>
|
// render: (text, record) =>
|
||||||
Dinero({ amount: Math.round(record.rate * 100) })
|
// Dinero({ amount: Math.round(record.rate * 100) })
|
||||||
.multiply(record.flat_rate ? record.productivehrs : record.actualhrs)
|
// .multiply(record.flat_rate ? record.productivehrs : record.actualhrs)
|
||||||
.toFormat("$0.00"),
|
// .toFormat("$0.00"),
|
||||||
},
|
// },
|
||||||
|
|
||||||
{
|
{
|
||||||
title: t("general.labels.actions"),
|
title: t("general.labels.actions"),
|
||||||
dataIndex: "actions",
|
dataIndex: "actions",
|
||||||
@@ -282,16 +281,18 @@ export function TimeTicketList({
|
|||||||
// context={{ jobId: jobId }}
|
// context={{ jobId: jobId }}
|
||||||
// />
|
// />
|
||||||
}
|
}
|
||||||
<Button
|
{bodyshop.md_tasks_presets.enable_tasks && (
|
||||||
onClick={() => {
|
<Button
|
||||||
setTimeTicketTaskContext({
|
onClick={() => {
|
||||||
actions: {},
|
setTimeTicketTaskContext({
|
||||||
context: { jobid: jobId },
|
actions: {},
|
||||||
});
|
context: { jobid: jobId },
|
||||||
}}
|
});
|
||||||
>
|
}}
|
||||||
{t("timetickets.actions.claimtasks")}
|
>
|
||||||
</Button>
|
{t("timetickets.actions.claimtasks")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
{jobId &&
|
{jobId &&
|
||||||
(techConsole ? null : (
|
(techConsole ? null : (
|
||||||
<TimeTicketEnterButton
|
<TimeTicketEnterButton
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import JobSearchSelectComponent from "../job-search-select/job-search-select.com
|
|||||||
import { CalculateAllocationsTotals } from "../labor-allocations-table/labor-allocations-table.utility";
|
import { CalculateAllocationsTotals } from "../labor-allocations-table/labor-allocations-table.utility";
|
||||||
import { LaborAllocationContainer } from "../time-ticket-modal/time-ticket-modal.component";
|
import { LaborAllocationContainer } from "../time-ticket-modal/time-ticket-modal.component";
|
||||||
import TimeTicketsTasksPresets from "../time-ticket-tasks-presets/time-ticket-tasks-presets.component";
|
import TimeTicketsTasksPresets from "../time-ticket-tasks-presets/time-ticket-tasks-presets.component";
|
||||||
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
//currentUser: selectCurrentUser
|
||||||
@@ -54,7 +55,12 @@ export function TimeTicketTaskModalComponent({
|
|||||||
calculateTimeTickets={calculateTimeTickets}
|
calculateTimeTickets={calculateTimeTickets}
|
||||||
/>
|
/>
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
<Col lg={12} md={24}>
|
{bodyshop?.md_tasks_presets?.use_approvals && (
|
||||||
|
<Col span={24}>
|
||||||
|
<Alert message={t(".tt_approvals.labels.approval_queue_in_use")} />
|
||||||
|
</Col>
|
||||||
|
)}
|
||||||
|
<Col xl={12} lg={24}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="jobid"
|
name="jobid"
|
||||||
label={t("timetickets.fields.ro_number")}
|
label={t("timetickets.fields.ro_number")}
|
||||||
@@ -77,37 +83,37 @@ export function TimeTicketTaskModalComponent({
|
|||||||
>
|
>
|
||||||
<EmployeeTeamSearchSelectComponent />
|
<EmployeeTeamSearchSelectComponent />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Space wrap>
|
|
||||||
<Form.Item
|
|
||||||
name="hourstype"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Checkbox.Group>
|
|
||||||
<Space wrap>
|
|
||||||
<Checkbox value="LAB" style={{ display: "flex" }}>
|
|
||||||
Body
|
|
||||||
</Checkbox>
|
|
||||||
<Checkbox value="LAR" style={{ display: "flex" }}>
|
|
||||||
Refinish
|
|
||||||
</Checkbox>
|
|
||||||
<Checkbox value="LAM" style={{ display: "flex" }}>
|
|
||||||
Mechanical
|
|
||||||
</Checkbox>
|
|
||||||
<Checkbox value="LAF" style={{ display: "flex" }}>
|
|
||||||
Frame
|
|
||||||
</Checkbox>
|
|
||||||
<Checkbox value="LAG" style={{ display: "flex" }}>
|
|
||||||
Glass
|
|
||||||
</Checkbox>
|
|
||||||
</Space>
|
|
||||||
</Checkbox.Group>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="hourstype"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Checkbox.Group>
|
||||||
|
<Space wrap>
|
||||||
|
<Checkbox value="LAB" style={{ display: "flex" }}>
|
||||||
|
{t("jobs.fields.lab")}
|
||||||
|
</Checkbox>
|
||||||
|
<Checkbox value="LAR" style={{ display: "flex" }}>
|
||||||
|
{t("jobs.fields.lar")}
|
||||||
|
</Checkbox>
|
||||||
|
<Checkbox value="LAM" style={{ display: "flex" }}>
|
||||||
|
{t("jobs.fields.lam")}
|
||||||
|
</Checkbox>
|
||||||
|
<Checkbox value="LAF" style={{ display: "flex" }}>
|
||||||
|
{t("jobs.fields.laf")}
|
||||||
|
</Checkbox>
|
||||||
|
<Checkbox value="LAG" style={{ display: "flex" }}>
|
||||||
|
{t("jobs.fields.lag")}
|
||||||
|
</Checkbox>
|
||||||
|
</Space>
|
||||||
|
</Checkbox.Group>
|
||||||
|
</Form.Item>
|
||||||
|
<Space wrap align="start">
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="percent"
|
name="percent"
|
||||||
rules={[
|
rules={[
|
||||||
@@ -119,10 +125,13 @@ export function TimeTicketTaskModalComponent({
|
|||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={1} addonAfter="%" />
|
<InputNumber min={0} max={100} precision={1} addonAfter="%" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
|
<Button onClick={calculateTimeTickets}>
|
||||||
|
{t("tt_approvals.labels.calculate")}
|
||||||
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
<Button onClick={calculateTimeTickets}>Calculate</Button>
|
|
||||||
</Col>
|
</Col>
|
||||||
<Col lg={12} md={24}>
|
<Col xl={12} lg={24}>
|
||||||
<Form.Item shouldUpdate>
|
<Form.Item shouldUpdate>
|
||||||
{() => {
|
{() => {
|
||||||
const data = form.getFieldValue("timetickets");
|
const data = form.getFieldValue("timetickets");
|
||||||
@@ -167,11 +176,11 @@ export function TimeTicketTaskModalComponent({
|
|||||||
dataIndex: "rate",
|
dataIndex: "rate",
|
||||||
key: "rate",
|
key: "rate",
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
title: "Pay",
|
// title: "Pay",
|
||||||
dataIndex: "pay",
|
// dataIndex: "pay",
|
||||||
key: "pay",
|
// key: "pay",
|
||||||
},
|
// },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -231,11 +240,9 @@ export function TimeTicketTaskModalComponent({
|
|||||||
<Alert key={idx} message={e} />
|
<Alert key={idx} message={e} />
|
||||||
))}
|
))}
|
||||||
<div
|
<div
|
||||||
style={
|
style={{
|
||||||
{
|
display: "none",
|
||||||
//display: "none"
|
}}
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{fields.map((field, index) => (
|
{fields.map((field, index) => (
|
||||||
<Form.Item
|
<Form.Item
|
||||||
|
|||||||
@@ -52,12 +52,8 @@ export function TimeTickeTaskModalContainer({
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function handleFinish(values) {
|
async function handleFinish(values) {
|
||||||
console.log(
|
|
||||||
"🚀 ~ file: time-ticket-task-modal.container.jsx:55 ~ handleFinish ~ values:",
|
|
||||||
values
|
|
||||||
);
|
|
||||||
try {
|
try {
|
||||||
if (true) {
|
if (bodyshop.md_tasks_presets.use_approvals) {
|
||||||
const result = await insertTimeTicketApproval({
|
const result = await insertTimeTicketApproval({
|
||||||
variables: {
|
variables: {
|
||||||
timeTicketInput: values.timetickets.map((ticket) => ({
|
timeTicketInput: values.timetickets.map((ticket) => ({
|
||||||
@@ -88,6 +84,7 @@ export function TimeTickeTaskModalContainer({
|
|||||||
_.omit(ticket, "pay")
|
_.omit(ticket, "pay")
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
refetchQueries: ["GET_LINE_TICKET_BY_PK"]
|
||||||
});
|
});
|
||||||
if (result.errors) {
|
if (result.errors) {
|
||||||
notification.open({
|
notification.open({
|
||||||
@@ -105,6 +102,13 @@ export function TimeTickeTaskModalContainer({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log("🚀 ~ file: time-ticket-task-modal.container.jsx:104 ~ handleFinish ~ error:", error)
|
||||||
|
notification.open({
|
||||||
|
type: "error",
|
||||||
|
message: t("timetickets.errors.creating", {
|
||||||
|
message: JSON.stringify(error),
|
||||||
|
}),
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,16 @@ import { createStructuredSelector } from "reselect";
|
|||||||
import { INSERT_TIME_TICKET_AND_APPROVE } from "../../graphql/timetickets.queries";
|
import { INSERT_TIME_TICKET_AND_APPROVE } from "../../graphql/timetickets.queries";
|
||||||
import { QUERY_TT_APPROVALS_BY_IDS } from "../../graphql/tt-approvals.queries";
|
import { QUERY_TT_APPROVALS_BY_IDS } from "../../graphql/tt-approvals.queries";
|
||||||
import {
|
import {
|
||||||
|
selectAuthLevel,
|
||||||
selectBodyshop,
|
selectBodyshop,
|
||||||
selectCurrentUser,
|
selectCurrentUser,
|
||||||
} from "../../redux/user/user.selectors";
|
} from "../../redux/user/user.selectors";
|
||||||
|
import { HasRbacAccess } from "../rbac-wrapper/rbac-wrapper.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
currentUser: selectCurrentUser,
|
currentUser: selectCurrentUser,
|
||||||
|
authLevel: selectAuthLevel,
|
||||||
});
|
});
|
||||||
|
|
||||||
export function TtApproveButton({
|
export function TtApproveButton({
|
||||||
@@ -23,6 +26,7 @@ export function TtApproveButton({
|
|||||||
currentUser,
|
currentUser,
|
||||||
selectedTickets,
|
selectedTickets,
|
||||||
disabled,
|
disabled,
|
||||||
|
authLevel,
|
||||||
loadingCallback,
|
loadingCallback,
|
||||||
completedCallback,
|
completedCallback,
|
||||||
refetch,
|
refetch,
|
||||||
@@ -83,7 +87,14 @@ export function TtApproveButton({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button onClick={handleQbxml} loading={loading} disabled={disabled}>
|
<Button
|
||||||
|
onClick={handleQbxml}
|
||||||
|
loading={loading}
|
||||||
|
disabled={
|
||||||
|
disabled ||
|
||||||
|
!HasRbacAccess({ bodyshop, authLevel, action: "ttapprovals:approve" })
|
||||||
|
}
|
||||||
|
>
|
||||||
{t("tt_approvals.actions.approveselected")}
|
{t("tt_approvals.actions.approveselected")}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -46,9 +46,12 @@ export function ShopPage({ bodyshop, setSelectedHeader, setBreadcrumbs }) {
|
|||||||
<Tabs.TabPane tab={t("bodyshop.labels.employees")} key="employees">
|
<Tabs.TabPane tab={t("bodyshop.labels.employees")} key="employees">
|
||||||
<ShopEmployeesContainer />
|
<ShopEmployeesContainer />
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane tab={t("bodyshop.labels.employee_teams")} key="teams">
|
{
|
||||||
<ShopTeamsContainer />
|
bodyshop.md_tasks_presets.enable_tasks &&
|
||||||
</Tabs.TabPane>
|
<Tabs.TabPane tab={t("bodyshop.labels.employee_teams")} key="teams">
|
||||||
|
<ShopTeamsContainer />
|
||||||
|
</Tabs.TabPane>
|
||||||
|
}
|
||||||
<Tabs.TabPane tab={t("bodyshop.labels.licensing")} key="licensing">
|
<Tabs.TabPane tab={t("bodyshop.labels.licensing")} key="licensing">
|
||||||
<ShopInfoUsersComponent />
|
<ShopInfoUsersComponent />
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
|
|||||||
@@ -341,10 +341,12 @@
|
|||||||
"md_payment_types": "Payment Types",
|
"md_payment_types": "Payment Types",
|
||||||
"md_referral_sources": "Referral Sources",
|
"md_referral_sources": "Referral Sources",
|
||||||
"md_tasks_presets": {
|
"md_tasks_presets": {
|
||||||
|
"enable_tasks": "Enable Task Claiming",
|
||||||
"hourstype": "Hour Types",
|
"hourstype": "Hour Types",
|
||||||
"memo": "Time Ticket Memo",
|
"memo": "Time Ticket Memo",
|
||||||
"name": "Preset Name",
|
"name": "Preset Name",
|
||||||
"percent": "Percent"
|
"percent": "Percent",
|
||||||
|
"use_approvals": "Use Time Ticket Approval Queue"
|
||||||
},
|
},
|
||||||
"messaginglabel": "Messaging Preset Label",
|
"messaginglabel": "Messaging Preset Label",
|
||||||
"messagingtext": "Messaging Preset Text",
|
"messagingtext": "Messaging Preset Text",
|
||||||
@@ -521,12 +523,12 @@
|
|||||||
"dailyhrslimit": "Daily Incoming Hours Limit"
|
"dailyhrslimit": "Daily Incoming Hours Limit"
|
||||||
},
|
},
|
||||||
"ssbuckets": {
|
"ssbuckets": {
|
||||||
|
"color": "Job Color",
|
||||||
"gte": "Greater Than/Equal to (hrs)",
|
"gte": "Greater Than/Equal to (hrs)",
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
"label": "Label",
|
"label": "Label",
|
||||||
"lt": "Less than (hrs)",
|
"lt": "Less than (hrs)",
|
||||||
"target": "Target (count)",
|
"target": "Target (count)"
|
||||||
"color": "Job Color"
|
|
||||||
},
|
},
|
||||||
"state": "Province/State",
|
"state": "Province/State",
|
||||||
"state_tax_id": "Provincial/State Tax ID (PST, QST)",
|
"state_tax_id": "Provincial/State Tax ID (PST, QST)",
|
||||||
@@ -2399,6 +2401,7 @@
|
|||||||
"qbo_usa": "QBO USA"
|
"qbo_usa": "QBO USA"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"cardcolor": "Card Colors",
|
||||||
"cardsettings": "Card Settings",
|
"cardsettings": "Card Settings",
|
||||||
"clm_no": "Claim Number",
|
"clm_no": "Claim Number",
|
||||||
"comment": "Comment",
|
"comment": "Comment",
|
||||||
@@ -2409,6 +2412,7 @@
|
|||||||
"ins_co_nm": "Insurance Company Name",
|
"ins_co_nm": "Insurance Company Name",
|
||||||
"jobdetail": "Job Details",
|
"jobdetail": "Job Details",
|
||||||
"laborhrs": "Labor Hours",
|
"laborhrs": "Labor Hours",
|
||||||
|
"legend": "Legend:",
|
||||||
"note": "Production Note",
|
"note": "Production Note",
|
||||||
"ownr_nm": "Owner Name",
|
"ownr_nm": "Owner Name",
|
||||||
"paintpriority": "P/P",
|
"paintpriority": "P/P",
|
||||||
@@ -2421,9 +2425,7 @@
|
|||||||
"sublets": "Sublets",
|
"sublets": "Sublets",
|
||||||
"totalhours": "Total Hrs ",
|
"totalhours": "Total Hrs ",
|
||||||
"touchtime": "T/T",
|
"touchtime": "T/T",
|
||||||
"viewname": "View Name",
|
"viewname": "View Name"
|
||||||
"legend": "Legend:",
|
|
||||||
"cardcolor": "Card Colors"
|
|
||||||
},
|
},
|
||||||
"successes": {
|
"successes": {
|
||||||
"removed": "Job removed from production."
|
"removed": "Job removed from production."
|
||||||
@@ -2815,6 +2817,10 @@
|
|||||||
"tt_approvals": {
|
"tt_approvals": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"approveselected": "Approve Selected"
|
"approveselected": "Approve Selected"
|
||||||
|
},
|
||||||
|
"labels": {
|
||||||
|
"approval_queue_in_use": "Time tickets will be added to the approval queue.",
|
||||||
|
"calculate": "Calculate"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
|
|||||||
@@ -341,10 +341,12 @@
|
|||||||
"md_payment_types": "",
|
"md_payment_types": "",
|
||||||
"md_referral_sources": "",
|
"md_referral_sources": "",
|
||||||
"md_tasks_presets": {
|
"md_tasks_presets": {
|
||||||
|
"enable_tasks": "",
|
||||||
"hourstype": "",
|
"hourstype": "",
|
||||||
"memo": "",
|
"memo": "",
|
||||||
"name": "",
|
"name": "",
|
||||||
"percent": ""
|
"percent": "",
|
||||||
|
"use_approvals": ""
|
||||||
},
|
},
|
||||||
"messaginglabel": "",
|
"messaginglabel": "",
|
||||||
"messagingtext": "",
|
"messagingtext": "",
|
||||||
@@ -521,6 +523,7 @@
|
|||||||
"dailyhrslimit": ""
|
"dailyhrslimit": ""
|
||||||
},
|
},
|
||||||
"ssbuckets": {
|
"ssbuckets": {
|
||||||
|
"color": "",
|
||||||
"gte": "",
|
"gte": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"label": "",
|
"label": "",
|
||||||
@@ -2398,6 +2401,7 @@
|
|||||||
"qbo_usa": ""
|
"qbo_usa": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"cardcolor": "",
|
||||||
"cardsettings": "",
|
"cardsettings": "",
|
||||||
"clm_no": "",
|
"clm_no": "",
|
||||||
"comment": "",
|
"comment": "",
|
||||||
@@ -2408,6 +2412,7 @@
|
|||||||
"ins_co_nm": "",
|
"ins_co_nm": "",
|
||||||
"jobdetail": "",
|
"jobdetail": "",
|
||||||
"laborhrs": "",
|
"laborhrs": "",
|
||||||
|
"legend": "",
|
||||||
"note": "",
|
"note": "",
|
||||||
"ownr_nm": "",
|
"ownr_nm": "",
|
||||||
"paintpriority": "",
|
"paintpriority": "",
|
||||||
@@ -2812,6 +2817,10 @@
|
|||||||
"tt_approvals": {
|
"tt_approvals": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"approveselected": ""
|
"approveselected": ""
|
||||||
|
},
|
||||||
|
"labels": {
|
||||||
|
"approval_queue_in_use": "",
|
||||||
|
"calculate": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
|
|||||||
@@ -341,10 +341,12 @@
|
|||||||
"md_payment_types": "",
|
"md_payment_types": "",
|
||||||
"md_referral_sources": "",
|
"md_referral_sources": "",
|
||||||
"md_tasks_presets": {
|
"md_tasks_presets": {
|
||||||
|
"enable_tasks": "",
|
||||||
"hourstype": "",
|
"hourstype": "",
|
||||||
"memo": "",
|
"memo": "",
|
||||||
"name": "",
|
"name": "",
|
||||||
"percent": ""
|
"percent": "",
|
||||||
|
"use_approvals": ""
|
||||||
},
|
},
|
||||||
"messaginglabel": "",
|
"messaginglabel": "",
|
||||||
"messagingtext": "",
|
"messagingtext": "",
|
||||||
@@ -521,6 +523,7 @@
|
|||||||
"dailyhrslimit": ""
|
"dailyhrslimit": ""
|
||||||
},
|
},
|
||||||
"ssbuckets": {
|
"ssbuckets": {
|
||||||
|
"color": "",
|
||||||
"gte": "",
|
"gte": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"label": "",
|
"label": "",
|
||||||
@@ -2398,6 +2401,7 @@
|
|||||||
"qbo_usa": ""
|
"qbo_usa": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"cardcolor": "",
|
||||||
"cardsettings": "",
|
"cardsettings": "",
|
||||||
"clm_no": "",
|
"clm_no": "",
|
||||||
"comment": "",
|
"comment": "",
|
||||||
@@ -2408,6 +2412,7 @@
|
|||||||
"ins_co_nm": "",
|
"ins_co_nm": "",
|
||||||
"jobdetail": "",
|
"jobdetail": "",
|
||||||
"laborhrs": "",
|
"laborhrs": "",
|
||||||
|
"legend": "",
|
||||||
"note": "",
|
"note": "",
|
||||||
"ownr_nm": "",
|
"ownr_nm": "",
|
||||||
"paintpriority": "",
|
"paintpriority": "",
|
||||||
@@ -2812,6 +2817,10 @@
|
|||||||
"tt_approvals": {
|
"tt_approvals": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"approveselected": ""
|
"approveselected": ""
|
||||||
|
},
|
||||||
|
"labels": {
|
||||||
|
"approval_queue_in_use": "",
|
||||||
|
"calculate": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
|
|||||||
Reference in New Issue
Block a user