IO-1914 Update inventory insert queries.
This commit is contained in:
@@ -36,6 +36,7 @@ export function BillEnterModalLinesComponent({
|
||||
form,
|
||||
responsibilityCenters,
|
||||
billEdit,
|
||||
billid,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const { setFieldsValue, getFieldsValue, getFieldValue } = form;
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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(
|
||||
$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`
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user