@@ -12932,6 +12932,32 @@
|
||||
</concept_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
<name>labels</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>attempts</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>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
@@ -35194,6 +35220,37 @@
|
||||
</folder_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
<name>scoredboard</name>
|
||||
<children>
|
||||
<folder_node>
|
||||
<name>successes</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>updated</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>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
<name>tech</name>
|
||||
<children>
|
||||
|
||||
@@ -109,6 +109,17 @@ export default function AccountingPayablesTableComponent({ loading, bills }) {
|
||||
<Checkbox disabled checked={record.is_credit_memo} />
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t("exportlogs.labels.attempts"),
|
||||
dataIndex: "attempts",
|
||||
key: "attempts",
|
||||
|
||||
render: (text, record) => {
|
||||
const success = record.exportlogs.filter((e) => e.successful).length;
|
||||
const attempts = record.exportlogs.length;
|
||||
return `${success}/${attempts}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t("general.labels.actions"),
|
||||
dataIndex: "actions",
|
||||
|
||||
@@ -108,7 +108,17 @@ export default function AccountingPayablesTableComponent({
|
||||
<DateTimeFormatter>{record.exportedat}</DateTimeFormatter>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t("exportlogs.labels.attempts"),
|
||||
dataIndex: "attempts",
|
||||
key: "attempts",
|
||||
|
||||
render: (text, record) => {
|
||||
const success = record.exportlogs.filter((e) => e.successful).length;
|
||||
const attempts = record.exportlogs.length;
|
||||
return `${success}/${attempts}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t("general.labels.actions"),
|
||||
dataIndex: "actions",
|
||||
|
||||
@@ -114,11 +114,21 @@ export default function AccountingReceivablesTableComponent({ loading, jobs }) {
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t("exportlogs.labels.attempts"),
|
||||
dataIndex: "attempts",
|
||||
key: "attempts",
|
||||
|
||||
render: (text, record) => {
|
||||
const success = record.exportlogs.filter((e) => e.successful).length;
|
||||
const attempts = record.exportlogs.length;
|
||||
return `${success}/${attempts}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t("general.labels.actions"),
|
||||
dataIndex: "actions",
|
||||
key: "actions",
|
||||
sorter: (a, b) => a.clm_total - b.clm_total,
|
||||
|
||||
render: (text, record) => (
|
||||
<Space wrap>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import Dinero from "dinero.js";
|
||||
|
||||
export const CalculateBillTotal = (invoice) => {
|
||||
const {
|
||||
total,
|
||||
billlines,
|
||||
federal_tax_rate,
|
||||
local_tax_rate,
|
||||
state_tax_rate,
|
||||
} = invoice;
|
||||
const { total, billlines, federal_tax_rate, local_tax_rate, state_tax_rate } =
|
||||
invoice;
|
||||
|
||||
//TODO Determine why this recalculates so many times.
|
||||
let subtotal = Dinero({ amount: 0 });
|
||||
@@ -20,8 +15,7 @@ export const CalculateBillTotal = (invoice) => {
|
||||
billlines.forEach((i) => {
|
||||
if (!!i) {
|
||||
const itemTotal = Dinero({
|
||||
amount:
|
||||
Math.round(((i.actual_cost || 0) * 100 + Number.EPSILON) * 100) / 100,
|
||||
amount: Math.round((i.actual_cost || 0) * 100),
|
||||
}).multiply(i.quantity || 1);
|
||||
|
||||
subtotal = subtotal.add(itemTotal);
|
||||
|
||||
@@ -72,7 +72,7 @@ export function JobLineStatusPopup({ bodyshop, jobline, disabled }) {
|
||||
);
|
||||
return (
|
||||
<div
|
||||
style={{ width: "100%", minHeight: "2rem", cursor: "pointer" }}
|
||||
style={{ width: "100%", minHeight: "1rem", cursor: "pointer" }}
|
||||
onClick={() => !disabled && setEditing(true)}
|
||||
>
|
||||
{jobline.status}
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
import { Col, notification, Row } from "antd";
|
||||
import Axios from "axios";
|
||||
import Dinero from "dinero.js";
|
||||
import _ from "lodash";
|
||||
import moment from "moment";
|
||||
import queryString from "query-string";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
@@ -187,7 +186,9 @@ export function JobsAvailableContainer({
|
||||
|
||||
setJobModalVisible(false);
|
||||
setInsertLoading(true);
|
||||
const estData = replaceEmpty(estDataRaw.data.available_jobs_by_pk);
|
||||
|
||||
const estData = estDataRaw.data.available_jobs_by_pk;
|
||||
|
||||
if (!(estData && estData.est_data)) {
|
||||
//We don't have the right data. Error!
|
||||
setInsertLoading(false);
|
||||
@@ -196,7 +197,7 @@ export function JobsAvailableContainer({
|
||||
});
|
||||
} else {
|
||||
//create upsert job
|
||||
let supp = _.cloneDeep(estData.est_data);
|
||||
let supp = replaceEmpty({ ...estData.est_data });
|
||||
|
||||
delete supp.owner;
|
||||
delete supp.vehicle;
|
||||
@@ -208,7 +209,7 @@ export function JobsAvailableContainer({
|
||||
let suppDelta = await GetSupplementDelta(
|
||||
client,
|
||||
selectedJob,
|
||||
estData.est_data.joblines.data
|
||||
supp.joblines.data
|
||||
);
|
||||
|
||||
delete supp.joblines;
|
||||
@@ -380,10 +381,10 @@ export default connect(
|
||||
)(JobsAvailableContainer);
|
||||
|
||||
function replaceEmpty(someObj, replaceValue = null) {
|
||||
const replacer = (key, value) => (value === "" ? replaceValue : value);
|
||||
const replacer = (key, value) =>
|
||||
value === "" ? replaceValue || null : value;
|
||||
//^ because you seem to want to replace (strings) "null" or "undefined" too
|
||||
console.log(someObj);
|
||||
const temp = JSON.stringify(someObj, replacer);
|
||||
console.log(`temp`, temp);
|
||||
console.log("Parsed", JSON.parse(temp));
|
||||
return JSON.parse(temp);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
|
||||
);
|
||||
};
|
||||
|
||||
const overlay = (
|
||||
const overlay = bodyshop.cdk_dealerid && (
|
||||
<Menu onClick={handleMenuClick}>
|
||||
{bodyshop.md_responsibility_centers.dms_defaults.map((mapping) => (
|
||||
<Menu.Item key={mapping.name}>{mapping.name}</Menu.Item>
|
||||
|
||||
@@ -150,7 +150,7 @@ export function JobsCloseExportButton({
|
||||
}
|
||||
if (setSelectedJobs) {
|
||||
setSelectedJobs((selectedJobs) => {
|
||||
return selectedJobs.filter((i) => i.id !== jobId);
|
||||
return selectedJobs.filter((i) => i !== jobId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { alphaSort } from "../../utils/sorters";
|
||||
import LaborAllocationsAdjustmentEdit from "../labor-allocations-adjustment-edit/labor-allocations-adjustment-edit.component";
|
||||
import "./labor-allocations-table.styles.scss";
|
||||
import { CalculateAllocationsTotals } from "./labor-allocations-table.utility";
|
||||
|
||||
import _ from "lodash";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
technician: selectTechnician,
|
||||
@@ -113,7 +113,7 @@ export function LaborAllocationsTable({
|
||||
color: record.difference >= 0 ? "green" : "red",
|
||||
}}
|
||||
>
|
||||
{record.difference}
|
||||
{_.round(record.difference, 1)}
|
||||
</strong>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -145,7 +145,7 @@ export function PayableExportButton({
|
||||
}
|
||||
if (setSelectedBills) {
|
||||
setSelectedBills((selectedBills) => {
|
||||
return selectedBills.filter((i) => i.id !== billId);
|
||||
return selectedBills.filter((i) => i !== billId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ export function PaymentExportButton({
|
||||
|
||||
if (setSelectedPayments) {
|
||||
setSelectedPayments((selectedBills) => {
|
||||
return selectedBills.filter((i) => i.id !== paymentId);
|
||||
return selectedBills.filter((i) => i !== paymentId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
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 mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
@@ -52,17 +52,22 @@ export function ScoreboardChart({ sbEntriesByDate, bodyshop }) {
|
||||
|
||||
const theValue = {
|
||||
date: moment(val).format("D dd"),
|
||||
paintHrs: dayhrs.painthrs,
|
||||
bodyHrs: dayhrs.bodyhrs,
|
||||
accTargetHrs: Utils.AsOfDateTargetHours(
|
||||
bodyshop.scoreboard_target.dailyBodyTarget +
|
||||
bodyshop.scoreboard_target.dailyPaintTarget,
|
||||
val
|
||||
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:
|
||||
accHrs: _.round(
|
||||
acc.length > 0
|
||||
? acc[acc.length - 1].accHrs + dayhrs.painthrs + dayhrs.bodyhrs
|
||||
: dayhrs.painthrs + dayhrs.bodyhrs,
|
||||
1
|
||||
),
|
||||
};
|
||||
|
||||
return [...acc, theValue];
|
||||
|
||||
@@ -40,17 +40,21 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
|
||||
|
||||
const [costOptions, setCostOptions] = useState(
|
||||
[
|
||||
...(form
|
||||
.getFieldValue(["md_responsibility_centers", "costs"])
|
||||
.map((i) => i && i.name) || []),
|
||||
...((form.getFieldValue(["md_responsibility_centers", "costs"]) &&
|
||||
form
|
||||
.getFieldValue(["md_responsibility_centers", "costs"])
|
||||
.map((i) => i && i.name)) ||
|
||||
[]),
|
||||
] || []
|
||||
);
|
||||
|
||||
const [profitOptions, setProfitOptions] = useState(
|
||||
[
|
||||
...(form
|
||||
.getFieldValue(["md_responsibility_centers", "profits"])
|
||||
.map((i) => i && i.name) || []),
|
||||
...((form.getFieldValue(["md_responsibility_centers", "profits"]) &&
|
||||
form
|
||||
.getFieldValue(["md_responsibility_centers", "profits"])
|
||||
.map((i) => i && i.name)) ||
|
||||
[]),
|
||||
] || []
|
||||
);
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Card, Space, Table } from "antd";
|
||||
import { EditFilled } from "@ant-design/icons";
|
||||
import { Card, Space, Table } from "antd";
|
||||
import moment from "moment";
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import {
|
||||
selectAuthLevel,
|
||||
@@ -16,8 +17,6 @@ import RbacWrapper, {
|
||||
HasRbacAccess,
|
||||
} from "../rbac-wrapper/rbac-wrapper.component";
|
||||
import TimeTicketEnterButton from "../time-ticket-enter-button/time-ticket-enter-button.component";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
authLevel: selectAuthLevel,
|
||||
@@ -268,8 +267,12 @@ export function TimeTicketList({
|
||||
<Table.Summary.Cell />
|
||||
<Table.Summary.Cell />
|
||||
<Table.Summary.Cell />
|
||||
<Table.Summary.Cell>{totals.productivehrs}</Table.Summary.Cell>
|
||||
<Table.Summary.Cell>{totals.actualhrs}</Table.Summary.Cell>
|
||||
<Table.Summary.Cell>
|
||||
{totals.productivehrs.toFixed(1)}
|
||||
</Table.Summary.Cell>
|
||||
<Table.Summary.Cell>
|
||||
{totals.actualhrs.toFixed(1)}
|
||||
</Table.Summary.Cell>
|
||||
<Table.Summary.Cell>
|
||||
{totals.actualhrs === 0 || !totals.actualhrs
|
||||
? "∞"
|
||||
|
||||
@@ -48,7 +48,9 @@ export function TimeTicketModalComponent({
|
||||
{emps &&
|
||||
emps.rates.map((item) => (
|
||||
<Select.Option key={item.cost_center}>
|
||||
{item.cost_center}
|
||||
{item.cost_center === "timetickets.labels.shift"
|
||||
? t(item.cost_center)
|
||||
: item.cost_center}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
|
||||
@@ -24,6 +24,10 @@ export const QUERY_JOBS_FOR_EXPORT = gql`
|
||||
clm_total
|
||||
clm_no
|
||||
ins_co_nm
|
||||
exportlogs {
|
||||
id
|
||||
successful
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -37,6 +41,10 @@ export const QUERY_BILLS_FOR_EXPORT = gql`
|
||||
invoice_number
|
||||
is_credit_memo
|
||||
total
|
||||
exportlogs {
|
||||
id
|
||||
successful
|
||||
}
|
||||
job {
|
||||
id
|
||||
ro_number
|
||||
@@ -73,6 +81,10 @@ export const QUERY_PAYMENTS_FOR_EXPORT = gql`
|
||||
transactionid
|
||||
paymentnum
|
||||
date
|
||||
exportlogs {
|
||||
id
|
||||
successful
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -2,7 +2,10 @@ import { gql } from "@apollo/client";
|
||||
|
||||
export const SUBSCRIPTION_SCOREBOARD = gql`
|
||||
subscription SUBSCRIPTION_SCOREBOARD($start: date!, $end: date!) {
|
||||
scoreboard(where: { _and: { date: { _gte: $start, _lte: $end } } }) {
|
||||
scoreboard(
|
||||
where: { _and: { date: { _gte: $start, _lte: $end } } }
|
||||
order_by: { date: asc }
|
||||
) {
|
||||
id
|
||||
painthrs
|
||||
bodyhrs
|
||||
|
||||
@@ -828,6 +828,9 @@
|
||||
"exportlogs": {
|
||||
"fields": {
|
||||
"createdat": "Created At"
|
||||
},
|
||||
"labels": {
|
||||
"attempts": "Export Attempts"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
@@ -2112,6 +2115,11 @@
|
||||
"updated": "Scoreboard updated."
|
||||
}
|
||||
},
|
||||
"scoredboard": {
|
||||
"successes": {
|
||||
"updated": "Scoreboard entry updated."
|
||||
}
|
||||
},
|
||||
"tech": {
|
||||
"fields": {
|
||||
"employeeid": "Employee ID",
|
||||
|
||||
@@ -828,6 +828,9 @@
|
||||
"exportlogs": {
|
||||
"fields": {
|
||||
"createdat": ""
|
||||
},
|
||||
"labels": {
|
||||
"attempts": ""
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
@@ -2112,6 +2115,11 @@
|
||||
"updated": ""
|
||||
}
|
||||
},
|
||||
"scoredboard": {
|
||||
"successes": {
|
||||
"updated": ""
|
||||
}
|
||||
},
|
||||
"tech": {
|
||||
"fields": {
|
||||
"employeeid": "",
|
||||
|
||||
@@ -828,6 +828,9 @@
|
||||
"exportlogs": {
|
||||
"fields": {
|
||||
"createdat": ""
|
||||
},
|
||||
"labels": {
|
||||
"attempts": ""
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
@@ -2112,6 +2115,11 @@
|
||||
"updated": ""
|
||||
}
|
||||
},
|
||||
"scoredboard": {
|
||||
"successes": {
|
||||
"updated": ""
|
||||
}
|
||||
},
|
||||
"tech": {
|
||||
"fields": {
|
||||
"employeeid": "",
|
||||
|
||||
@@ -605,7 +605,7 @@ const formatGpPercent = (gppercent) => {
|
||||
const getAdditionalCostCenter = (jl, profitCenters) => {
|
||||
console.log("Checking additional cost center", jl.line_desc);
|
||||
if (!jl.part_type && !jl.mod_lbr_ty) {
|
||||
const lineDesc = jl.line_desc.toLowerCase();
|
||||
const lineDesc = jl.line_desc ? jl.line_desc.toLowerCase() : "";
|
||||
//This logic is covered prior and assigned based on the labor type of the lines
|
||||
// if (lineDesc.includes("shop materials")) {
|
||||
// return profitCenters["MASH"];
|
||||
|
||||
Reference in New Issue
Block a user