IO-1914 Update inventory insert queries.
This commit is contained in:
@@ -36,6 +36,7 @@ export function BillEnterModalLinesComponent({
|
|||||||
form,
|
form,
|
||||||
responsibilityCenters,
|
responsibilityCenters,
|
||||||
billEdit,
|
billEdit,
|
||||||
|
billid,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { setFieldsValue, getFieldsValue, getFieldValue } = form;
|
const { setFieldsValue, getFieldsValue, getFieldValue } = form;
|
||||||
|
|||||||
@@ -7,11 +7,17 @@ import React, { useState } from "react";
|
|||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { INSERT_INVENTORY_AND_CREDIT } from "../../graphql/inventory.queries";
|
import { INSERT_INVENTORY_AND_CREDIT } from "../../graphql/inventory.queries";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import {
|
||||||
|
selectBodyshop,
|
||||||
|
selectCurrentUser,
|
||||||
|
} from "../../redux/user/user.selectors";
|
||||||
import { CalculateBillTotal } from "../bill-form/bill-form.totals.utility";
|
import { CalculateBillTotal } from "../bill-form/bill-form.totals.utility";
|
||||||
|
import queryString from "query-string";
|
||||||
|
import { useLocation } from "react-router-dom";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
|
currentUser: selectCurrentUser,
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
@@ -21,8 +27,15 @@ export default connect(
|
|||||||
mapDispatchToProps
|
mapDispatchToProps
|
||||||
)(BilllineAddInventory);
|
)(BilllineAddInventory);
|
||||||
|
|
||||||
export function BilllineAddInventory({ bodyshop, billline, disabled, jobid }) {
|
export function BilllineAddInventory({
|
||||||
|
currentUser,
|
||||||
|
bodyshop,
|
||||||
|
billline,
|
||||||
|
disabled,
|
||||||
|
jobid,
|
||||||
|
}) {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const { billid } = queryString.parse(useLocation().search);
|
||||||
|
|
||||||
const [insertInventoryLine] = useMutation(INSERT_INVENTORY_AND_CREDIT);
|
const [insertInventoryLine] = useMutation(INSERT_INVENTORY_AND_CREDIT);
|
||||||
|
|
||||||
@@ -51,9 +64,9 @@ export function BilllineAddInventory({ bodyshop, billline, disabled, jobid }) {
|
|||||||
cost_center: billline.cost_center,
|
cost_center: billline.cost_center,
|
||||||
deductedfromlbr: billline.deductedfromlbr,
|
deductedfromlbr: billline.deductedfromlbr,
|
||||||
applicable_taxes: {
|
applicable_taxes: {
|
||||||
local: billline.applicable_taxes.local,
|
local: false, //billline.applicable_taxes.local,
|
||||||
state: billline.applicable_taxes.state,
|
state: false, //billline.applicable_taxes.state,
|
||||||
federal: billline.applicable_taxes.federal,
|
federal: false, // billline.applicable_taxes.federal,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -63,6 +76,8 @@ export function BilllineAddInventory({ bodyshop, billline, disabled, jobid }) {
|
|||||||
|
|
||||||
const insertResult = await insertInventoryLine({
|
const insertResult = await insertInventoryLine({
|
||||||
variables: {
|
variables: {
|
||||||
|
joblineId: billline.joblineid,
|
||||||
|
joblineStatus: bodyshop.md_order_statuses.default_returned,
|
||||||
inv: {
|
inv: {
|
||||||
shopid: bodyshop.id,
|
shopid: bodyshop.id,
|
||||||
billlineid: billline.id,
|
billlineid: billline.id,
|
||||||
@@ -72,6 +87,31 @@ export function BilllineAddInventory({ bodyshop, billline, disabled, jobid }) {
|
|||||||
line_desc: billline.line_desc,
|
line_desc: billline.line_desc,
|
||||||
},
|
},
|
||||||
cm: { ...cm, billlines: { data: cm.billlines } }, //Fix structure for apollo insert.
|
cm: { ...cm, billlines: { data: cm.billlines } }, //Fix structure for apollo insert.
|
||||||
|
pol: {
|
||||||
|
returnfrombill: billid,
|
||||||
|
vendorid: bodyshop.inhousevendorid,
|
||||||
|
deliver_by: moment().format("YYYY-MM-DD"),
|
||||||
|
parts_order_lines: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
line_desc: billline.line_desc,
|
||||||
|
|
||||||
|
act_price: billline.actual_price,
|
||||||
|
cost: billline.actual_cost,
|
||||||
|
quantity: billline.quantity,
|
||||||
|
job_line_id: billline.joblineid,
|
||||||
|
part_type: billline.jobline.part_type,
|
||||||
|
cm_received: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
order_date: "2022-06-01",
|
||||||
|
orderedby: currentUser.email,
|
||||||
|
jobid: jobid,
|
||||||
|
user_email: currentUser.email,
|
||||||
|
return: true,
|
||||||
|
status: "Ordered",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
refetchQueries: ["QUERY_BILL_BY_PK"],
|
refetchQueries: ["QUERY_BILL_BY_PK"],
|
||||||
});
|
});
|
||||||
@@ -97,7 +137,7 @@ export function BilllineAddInventory({ bodyshop, billline, disabled, jobid }) {
|
|||||||
<Tooltip title={t("inventory.actions.addtoinventory")}>
|
<Tooltip title={t("inventory.actions.addtoinventory")}>
|
||||||
<Button
|
<Button
|
||||||
loading={loading}
|
loading={loading}
|
||||||
disabled={disabled || billline.inventories.length > 0}
|
disabled={disabled || billline?.inventories?.length > 0}
|
||||||
onClick={addToInventory}
|
onClick={addToInventory}
|
||||||
>
|
>
|
||||||
<FileAddFilled />
|
<FileAddFilled />
|
||||||
|
|||||||
@@ -47,3 +47,20 @@ export const ListOfDaysInCurrentMonth = () => {
|
|||||||
days.push(dateEnd.format("YYYY-MM-DD"));
|
days.push(dateEnd.format("YYYY-MM-DD"));
|
||||||
return days;
|
return days;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const ListDaysBetween = ({ start, end }) => {
|
||||||
|
console.log(
|
||||||
|
"🚀 ~ file: scoreboard-targets-table.util.js ~ line 52 ~ start, end",
|
||||||
|
start,
|
||||||
|
end
|
||||||
|
);
|
||||||
|
const days = [];
|
||||||
|
const dateStart = moment(start);
|
||||||
|
const dateEnd = moment(end);
|
||||||
|
while (dateEnd.diff(dateStart, "days") > 0) {
|
||||||
|
days.push(dateStart.format("YYYY-MM-DD"));
|
||||||
|
dateStart.add(1, "days");
|
||||||
|
}
|
||||||
|
days.push(dateEnd.format("YYYY-MM-DD"));
|
||||||
|
return days;
|
||||||
|
};
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
import { Card } from "antd";
|
||||||
|
import moment from "moment";
|
||||||
|
import React, { useMemo } from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import {
|
||||||
|
Area,
|
||||||
|
Bar,
|
||||||
|
CartesianGrid,
|
||||||
|
ComposedChart,
|
||||||
|
Legend,
|
||||||
|
Line,
|
||||||
|
ResponsiveContainer,
|
||||||
|
Tooltip,
|
||||||
|
XAxis,
|
||||||
|
YAxis,
|
||||||
|
} from "recharts";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import * as Utils from "../scoreboard-targets-table/scoreboard-targets-table.util";
|
||||||
|
import _ from "lodash";
|
||||||
|
|
||||||
|
const graphProps = {
|
||||||
|
strokeWidth: 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
|
});
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
|
});
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(ScoreboardTicketsBar);
|
||||||
|
|
||||||
|
export function ScoreboardTicketsBar({ start, end, timetickets, bodyshop }) {
|
||||||
|
console.log(
|
||||||
|
"🚀 ~ file: scoreboard-timetickets.bar.component.jsx ~ line 39 ~ start, end,",
|
||||||
|
start,
|
||||||
|
end
|
||||||
|
);
|
||||||
|
const listOfBusDays = Utils.ListOfDaysInCurrentMonth();
|
||||||
|
|
||||||
|
const data = useMemo(() => {
|
||||||
|
const ticketsGroupedByDate = _.groupBy(timetickets, "date");
|
||||||
|
|
||||||
|
const listOfDays = Utils.ListDaysBetween({ start, end });
|
||||||
|
console.log(
|
||||||
|
"🚀 ~ file: scoreboard-timetickets.bar.component.jsx ~ line 45 ~ listOfDays",
|
||||||
|
listOfDays
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"🚀 ~ file: scoreboard-timetickets.bar.component.jsx ~ line 43 ~ groupedByDate",
|
||||||
|
ticketsGroupedByDate
|
||||||
|
);
|
||||||
|
|
||||||
|
const ret = [];
|
||||||
|
listOfDays.forEach((day) => {
|
||||||
|
const r = {
|
||||||
|
date: day,
|
||||||
|
total: 0,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}, [timetickets]);
|
||||||
|
// const data = listOfBusDays.reduce((acc, val) => {
|
||||||
|
// //Sum up the current day.
|
||||||
|
|
||||||
|
// const groupedbyDate = _.groupBy(data, "date");
|
||||||
|
// let dayhrs;
|
||||||
|
// if (!!sbEntriesByDate[val]) {
|
||||||
|
// dayhrs = sbEntriesByDate[val].reduce(
|
||||||
|
// (dayAcc, dayVal) => {
|
||||||
|
// return {
|
||||||
|
// bodyhrs: dayAcc.bodyhrs + dayVal.bodyhrs,
|
||||||
|
// painthrs: dayAcc.painthrs + dayVal.painthrs,
|
||||||
|
// };
|
||||||
|
// },
|
||||||
|
// { bodyhrs: 0, painthrs: 0 }
|
||||||
|
// );
|
||||||
|
// } else {
|
||||||
|
// dayhrs = {
|
||||||
|
// bodyhrs: 0,
|
||||||
|
// painthrs: 0,
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const theValue = {
|
||||||
|
// date: moment(val).format("D ddd"),
|
||||||
|
// paintHrs: _.round(dayhrs.painthrs, 1),
|
||||||
|
// bodyHrs: _.round(dayhrs.bodyhrs, 1),
|
||||||
|
// accTargetHrs: _.round(
|
||||||
|
// Utils.AsOfDateTargetHours(
|
||||||
|
// bodyshop.scoreboard_target.dailyBodyTarget +
|
||||||
|
// bodyshop.scoreboard_target.dailyPaintTarget,
|
||||||
|
// val
|
||||||
|
// ),
|
||||||
|
// 1
|
||||||
|
// ),
|
||||||
|
// accHrs: _.round(
|
||||||
|
// acc.length > 0
|
||||||
|
// ? acc[acc.length - 1].accHrs + dayhrs.painthrs + dayhrs.bodyhrs
|
||||||
|
// : dayhrs.painthrs + dayhrs.bodyhrs,
|
||||||
|
// 1
|
||||||
|
// ),
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return [...acc, theValue];
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<ResponsiveContainer width="100%" height={475}>
|
||||||
|
<ComposedChart
|
||||||
|
data={data}
|
||||||
|
margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
|
||||||
|
>
|
||||||
|
<CartesianGrid stroke="#f5f5f5" />
|
||||||
|
<XAxis dataKey="date" strokeWidth={graphProps.strokeWidth} />
|
||||||
|
<YAxis strokeWidth={graphProps.strokeWidth} />
|
||||||
|
<Tooltip />
|
||||||
|
<Legend />
|
||||||
|
<Area
|
||||||
|
type="monotone"
|
||||||
|
name="Accumulated Hours"
|
||||||
|
dataKey="accHrs"
|
||||||
|
fill="lightgreen"
|
||||||
|
stroke="green"
|
||||||
|
/>
|
||||||
|
<Bar
|
||||||
|
name="Body Hours"
|
||||||
|
dataKey="bodyHrs"
|
||||||
|
stackId="day"
|
||||||
|
barSize={20}
|
||||||
|
fill="darkblue"
|
||||||
|
/>
|
||||||
|
<Bar
|
||||||
|
name="Paint Hours"
|
||||||
|
dataKey="paintHrs"
|
||||||
|
stackId="day"
|
||||||
|
barSize={20}
|
||||||
|
fill="darkred"
|
||||||
|
/>
|
||||||
|
<Line
|
||||||
|
name="Target Hours"
|
||||||
|
type="monotone"
|
||||||
|
dataKey="accTargetHrs"
|
||||||
|
stroke="#ff7300"
|
||||||
|
strokeWidth={graphProps.strokeWidth}
|
||||||
|
/>
|
||||||
|
</ComposedChart>
|
||||||
|
</ResponsiveContainer>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { useLocation } from "react-router-dom";
|
||||||
|
import queryString from "query-string";
|
||||||
|
import moment from "moment";
|
||||||
|
import { useQuery } from "@apollo/client";
|
||||||
|
import { QUERY_TIME_TICKETS_IN_RANGE } from "../../graphql/timetickets.queries";
|
||||||
|
import AlertComponent from "../alert/alert.component";
|
||||||
|
import TimeTicketsDatesSelector from "../../components/ticket-tickets-dates-selector/time-tickets-dates-selector.component";
|
||||||
|
import ScoreboardTicketsBar from "./scoreboard-timetickets.bar.component";
|
||||||
|
|
||||||
|
export default function ScoreboardTimeTickets() {
|
||||||
|
const searchParams = queryString.parse(useLocation().search);
|
||||||
|
const { start, end } = searchParams;
|
||||||
|
const startDate = start
|
||||||
|
? moment(start)
|
||||||
|
: moment().startOf("week").subtract(7, "days");
|
||||||
|
const endDate = end ? moment(end) : moment().endOf("week");
|
||||||
|
const { loading, error, data } = useQuery(QUERY_TIME_TICKETS_IN_RANGE, {
|
||||||
|
variables: {
|
||||||
|
start: startDate,
|
||||||
|
end: endDate,
|
||||||
|
},
|
||||||
|
fetchPolicy: "network-only",
|
||||||
|
nextFetchPolicy: "network-only",
|
||||||
|
});
|
||||||
|
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<TimeTicketsDatesSelector />
|
||||||
|
<ScoreboardTicketsBar
|
||||||
|
start={startDate}
|
||||||
|
end={endDate}
|
||||||
|
timetickets={data ? data.timetickets : []}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Include a filter by employee.
|
||||||
|
|
||||||
|
//Hours produced today.
|
||||||
|
//Hours produced in last 7 days
|
||||||
|
//Hours produced for time period by day
|
||||||
|
//Hours produced by employee by day for time period.
|
||||||
@@ -4,6 +4,9 @@ export const INSERT_INVENTORY_AND_CREDIT = gql`
|
|||||||
mutation INSERT_INVENTORY_AND_CREDIT(
|
mutation INSERT_INVENTORY_AND_CREDIT(
|
||||||
$inv: inventory_insert_input!
|
$inv: inventory_insert_input!
|
||||||
$cm: bills_insert_input!
|
$cm: bills_insert_input!
|
||||||
|
$pol: parts_orders_insert_input!
|
||||||
|
$joblineId: uuid!
|
||||||
|
$joblineStatus: String
|
||||||
) {
|
) {
|
||||||
insert_inventory_one(object: $inv) {
|
insert_inventory_one(object: $inv) {
|
||||||
id
|
id
|
||||||
@@ -11,6 +14,16 @@ export const INSERT_INVENTORY_AND_CREDIT = gql`
|
|||||||
insert_bills_one(object: $cm) {
|
insert_bills_one(object: $cm) {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
insert_parts_orders_one(object: $pol) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
update_joblines_by_pk(
|
||||||
|
pk_columns: { id: $joblineId }
|
||||||
|
_set: { status: $joblineStatus }
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
status
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const UPDATE_INVENTORY_LINES = gql`
|
export const UPDATE_INVENTORY_LINES = gql`
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import Icon from "@ant-design/icons";
|
||||||
|
import { Tabs } 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";
|
||||||
@@ -10,6 +12,8 @@ import {
|
|||||||
setSelectedHeader,
|
setSelectedHeader,
|
||||||
} from "../../redux/application/application.actions";
|
} from "../../redux/application/application.actions";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import { FaHardHat, FaRegStickyNote, FaShieldAlt } from "react-icons/fa";
|
||||||
|
import ScoreboardTimeTickets from "../../components/scoreboard-timetickets/scoreboard-timetickets.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -37,7 +41,32 @@ export function ScoreboardContainer({ setBreadcrumbs, setSelectedHeader }) {
|
|||||||
return (
|
return (
|
||||||
<FeatureWrapper featureName="scoreboard">
|
<FeatureWrapper featureName="scoreboard">
|
||||||
<RbacWrapper action="scoreboard:view">
|
<RbacWrapper action="scoreboard:view">
|
||||||
<ScoreboardDisplay />
|
<Tabs>
|
||||||
|
<Tabs.TabPane
|
||||||
|
tab={
|
||||||
|
<span>
|
||||||
|
<Icon component={FaShieldAlt} />
|
||||||
|
{t("menus.jobsdetail.general")}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
destroyInactiveTabPane
|
||||||
|
key="sb"
|
||||||
|
>
|
||||||
|
<ScoreboardDisplay />
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane
|
||||||
|
tab={
|
||||||
|
<span>
|
||||||
|
<Icon component={FaShieldAlt} />
|
||||||
|
{t("menus.jobsdetail.general")}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
destroyInactiveTabPane
|
||||||
|
key="tickets"
|
||||||
|
>
|
||||||
|
<ScoreboardTimeTickets />
|
||||||
|
</Tabs.TabPane>
|
||||||
|
</Tabs>
|
||||||
</RbacWrapper>
|
</RbacWrapper>
|
||||||
</FeatureWrapper>
|
</FeatureWrapper>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user