IO-1914 Update inventory insert queries.

This commit is contained in:
Patrick Fic
2022-06-01 16:32:24 -07:00
parent 62b1da0b64
commit 485b5d0866
7 changed files with 309 additions and 7 deletions

View File

@@ -36,6 +36,7 @@ export function BillEnterModalLinesComponent({
form,
responsibilityCenters,
billEdit,
billid,
}) {
const { t } = useTranslation();
const { setFieldsValue, getFieldsValue, getFieldValue } = form;

View File

@@ -7,11 +7,17 @@ import React, { useState } from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
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 queryString from "query-string";
import { useLocation } from "react-router-dom";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
currentUser: selectCurrentUser,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
@@ -21,8 +27,15 @@ export default connect(
mapDispatchToProps
)(BilllineAddInventory);
export function BilllineAddInventory({ bodyshop, billline, disabled, jobid }) {
export function BilllineAddInventory({
currentUser,
bodyshop,
billline,
disabled,
jobid,
}) {
const [loading, setLoading] = useState(false);
const { billid } = queryString.parse(useLocation().search);
const [insertInventoryLine] = useMutation(INSERT_INVENTORY_AND_CREDIT);
@@ -51,9 +64,9 @@ export function BilllineAddInventory({ bodyshop, billline, disabled, jobid }) {
cost_center: billline.cost_center,
deductedfromlbr: billline.deductedfromlbr,
applicable_taxes: {
local: billline.applicable_taxes.local,
state: billline.applicable_taxes.state,
federal: billline.applicable_taxes.federal,
local: false, //billline.applicable_taxes.local,
state: false, //billline.applicable_taxes.state,
federal: false, // billline.applicable_taxes.federal,
},
},
],
@@ -63,6 +76,8 @@ export function BilllineAddInventory({ bodyshop, billline, disabled, jobid }) {
const insertResult = await insertInventoryLine({
variables: {
joblineId: billline.joblineid,
joblineStatus: bodyshop.md_order_statuses.default_returned,
inv: {
shopid: bodyshop.id,
billlineid: billline.id,
@@ -72,6 +87,31 @@ export function BilllineAddInventory({ bodyshop, billline, disabled, jobid }) {
line_desc: billline.line_desc,
},
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"],
});
@@ -97,7 +137,7 @@ export function BilllineAddInventory({ bodyshop, billline, disabled, jobid }) {
<Tooltip title={t("inventory.actions.addtoinventory")}>
<Button
loading={loading}
disabled={disabled || billline.inventories.length > 0}
disabled={disabled || billline?.inventories?.length > 0}
onClick={addToInventory}
>
<FileAddFilled />

View File

@@ -47,3 +47,20 @@ export const ListOfDaysInCurrentMonth = () => {
days.push(dateEnd.format("YYYY-MM-DD"));
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;
};

View File

@@ -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>
);
}

View File

@@ -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.

View File

@@ -4,6 +4,9 @@ export const INSERT_INVENTORY_AND_CREDIT = gql`
mutation INSERT_INVENTORY_AND_CREDIT(
$inv: inventory_insert_input!
$cm: bills_insert_input!
$pol: parts_orders_insert_input!
$joblineId: uuid!
$joblineStatus: String
) {
insert_inventory_one(object: $inv) {
id
@@ -11,6 +14,16 @@ export const INSERT_INVENTORY_AND_CREDIT = gql`
insert_bills_one(object: $cm) {
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`

View File

@@ -1,3 +1,5 @@
import Icon from "@ant-design/icons";
import { Tabs } from "antd";
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
@@ -10,6 +12,8 @@ import {
setSelectedHeader,
} from "../../redux/application/application.actions";
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({
bodyshop: selectBodyshop,
@@ -37,7 +41,32 @@ export function ScoreboardContainer({ setBreadcrumbs, setSelectedHeader }) {
return (
<FeatureWrapper featureName="scoreboard">
<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>
</FeatureWrapper>
);