From 756d97a9cb988c16a6ac66421fda60f77c608f91 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Wed, 19 Jul 2023 16:42:11 -0700 Subject: [PATCH] Prevent previously claimed tasks. --- ...or-allocations-table.payroll.component.jsx | 2 +- .../time-ticket-task-modal.component.jsx | 66 +++++++++++-------- .../time-ticket-task-modal.container.jsx | 38 ++++++++++- client/src/graphql/jobs.queries.js | 9 +++ server/graphql-client/queries.js | 1 + server/payroll/claim-task.js | 7 ++ 6 files changed, 91 insertions(+), 32 deletions(-) diff --git a/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx b/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx index 16d23beec..44d4233ab 100644 --- a/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx +++ b/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx @@ -235,7 +235,7 @@ export function PayrollLaborAllocationsTable({ > `${record.cost_center} ${record.mod_lbr_ty}`} + rowKey={(record) => `${record.employeeid} ${record.mod_lbr_ty}`} pagination={false} onChange={handleTableChange} dataSource={totals} diff --git a/client/src/components/time-ticket-task-modal/time-ticket-task-modal.component.jsx b/client/src/components/time-ticket-task-modal/time-ticket-task-modal.component.jsx index 3cacf667a..09617993b 100644 --- a/client/src/components/time-ticket-task-modal/time-ticket-task-modal.component.jsx +++ b/client/src/components/time-ticket-task-modal/time-ticket-task-modal.component.jsx @@ -1,14 +1,12 @@ import { Alert, - Checkbox, Col, Form, Radio, Row, - Select, Skeleton, Space, - Table, + Spin, Typography, } from "antd"; import React from "react"; @@ -16,10 +14,8 @@ import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; -import EmployeeTeamSearchSelectComponent from "../employee-team-search-select/employee-team-search-select.component"; -import JobSearchSelectComponent from "../job-search-select/job-search-select.component"; import ReadOnlyFormItemComponent from "../form-items-formatted/read-only-form-item.component"; -import LayoutFormRow from "../layout-form-row/layout-form-row.component"; +import JobSearchSelectComponent from "../job-search-select/job-search-select.component"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -33,7 +29,12 @@ export default connect( mapDispatchToProps )(TimeTicketTaskModalComponent); -export function TimeTicketTaskModalComponent({ bodyshop, form, loading }) { +export function TimeTicketTaskModalComponent({ + bodyshop, + form, + loading, + completedTasks, +}) { const { t } = useTranslation(); return ( @@ -57,13 +58,18 @@ export function TimeTicketTaskModalComponent({ bodyshop, form, loading }) { - ({ - value: preset.name, - label: preset.name, - }))} - /> + {loading ? ( + + ) : ( + ({ + value: preset.name, + label: preset.name, + disabled: completedTasks.includes(preset.name), + }))} + /> + )} {() => { @@ -75,20 +81,24 @@ export function TimeTicketTaskModalComponent({ bodyshop, form, loading }) { if (!task) return null; return (
- - - - - - - - - - - - + + + + + + + + + + + + + +
{t("bodyshop.fields.md_tasks_presets.percent")}{`${theTaskPreset.percent || 0}%`}
{t("bodyshop.fields.md_tasks_presets.hourstype")}{theTaskPreset.hourstype.join(", ")}
- {t("bodyshop.fields.md_tasks_presets.nextstatus")} - {theTaskPreset.nextstatus}
{t("bodyshop.fields.md_tasks_presets.percent")}{`${theTaskPreset.percent || 0}%`}
+ {t("bodyshop.fields.md_tasks_presets.hourstype")} + {theTaskPreset.hourstype.join(", ")}
+ {t("bodyshop.fields.md_tasks_presets.nextstatus")} + {theTaskPreset.nextstatus}
); }} diff --git a/client/src/components/time-ticket-task-modal/time-ticket-task-modal.container.jsx b/client/src/components/time-ticket-task-modal/time-ticket-task-modal.container.jsx index fa77fa6a1..9bb1fb009 100644 --- a/client/src/components/time-ticket-task-modal/time-ticket-task-modal.container.jsx +++ b/client/src/components/time-ticket-task-modal/time-ticket-task-modal.container.jsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useCallback, useEffect, useState } from "react"; import { Form, Modal, notification } from "antd"; import axios from "axios"; @@ -9,6 +9,8 @@ import { toggleModalVisible } from "../../redux/modals/modals.actions"; import { selectTimeTicketTasks } from "../../redux/modals/modals.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors"; import TimeTicketTaskModalComponent from "./time-ticket-task-modal.component"; +import { useApolloClient } from "@apollo/client"; +import { QUERY_COMPLETED_TASKS } from "../../graphql/jobs.queries"; const mapStateToProps = createStructuredSelector({ timeTicketTasksModal: selectTimeTicketTasks, @@ -29,15 +31,41 @@ export function TimeTickeTaskModalContainer({ }) { const [form] = Form.useForm(); const { context, visible } = timeTicketTasksModal; - + const [completedTasks, setCompletedTasks] = useState([]); const { t } = useTranslation(); const [loading, setLoading] = useState(false); + const client = useApolloClient(); async function handleFinish(values) { calculateTickets({ values, handleFinish: true }); } + const getCompletedTasks = useCallback( + async (jobid) => { + setLoading(true); + + const { data } = await client.query({ + query: QUERY_COMPLETED_TASKS, + variables: { jobid }, + }); + + setCompletedTasks(data.jobs_by_pk.completed_tasks || []); + setLoading(false); + }, + [client] + ); + useEffect(() => { + if (visible) { + form.setFieldsValue({ ...context, task: null, timetickets: null }); + if (context.jobid) { + getCompletedTasks(context.jobid); + } + } + }, [context.jobid, visible, getCompletedTasks, form, context]); async function handleValueChange(changedValues, allValues) { + if (changedValues.jobid) { + getCompletedTasks(changedValues.jobid); + } if (allValues.jobid && allValues.task) { calculateTickets({ values: allValues, handleFinish: false }); } @@ -93,7 +121,11 @@ export function TimeTickeTaskModalContainer({ initialValues={context} onValuesChange={handleValueChange} > - + ); diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js index 6509b74e6..47f93bfd7 100644 --- a/client/src/graphql/jobs.queries.js +++ b/client/src/graphql/jobs.queries.js @@ -2196,3 +2196,12 @@ export const GET_JOB_LINE_ORDERS = gql` } } `; + +export const QUERY_COMPLETED_TASKS = gql` + query QUERY_COMPLETED_TASKS($jobid: uuid!) { + jobs_by_pk(id: $jobid) { + id + completed_tasks + } + } +`; diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index 99567fa42..08335694c 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -1881,6 +1881,7 @@ exports.QUERY_JOB_PAYROLL_DATA = `query QUERY_JOB_PAYROLL_DATA($id: uuid!) { rate_matd status materials + completed_tasks joblines(where: { removed: { _eq: false } }){ id line_no diff --git a/server/payroll/claim-task.js b/server/payroll/claim-task.js index fd3efb2b7..6b5ddf5b8 100644 --- a/server/payroll/claim-task.js +++ b/server/payroll/claim-task.js @@ -76,6 +76,13 @@ exports.claimtask = async function (req, res) { (ticket) => ticket.productivehrs !== 0 ), }); + const updateResult = await client.request(queries.UPDATE_JOB, { + jobId: job.id, + job: { + completed_tasks: [...job.completed_tasks, task], + }, + }); + console.log("🚀 ~ file: claim-task.js:85 ~ updateResult:", updateResult) } res.json(ticketsToInsert); } catch (error) {