Merged in test (pull request #184)

Merge WIP items back into CDK CErt.
This commit is contained in:
Patrick Fic
2021-08-20 16:37:44 +00:00
22 changed files with 182 additions and 46 deletions

View File

@@ -12932,6 +12932,32 @@
</concept_node> </concept_node>
</children> </children>
</folder_node> </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> </children>
</folder_node> </folder_node>
<folder_node> <folder_node>
@@ -35194,6 +35220,37 @@
</folder_node> </folder_node>
</children> </children>
</folder_node> </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> <folder_node>
<name>tech</name> <name>tech</name>
<children> <children>

View File

@@ -109,6 +109,17 @@ export default function AccountingPayablesTableComponent({ loading, bills }) {
<Checkbox disabled checked={record.is_credit_memo} /> <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"), title: t("general.labels.actions"),
dataIndex: "actions", dataIndex: "actions",

View File

@@ -108,7 +108,17 @@ export default function AccountingPayablesTableComponent({
<DateTimeFormatter>{record.exportedat}</DateTimeFormatter> <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"), title: t("general.labels.actions"),
dataIndex: "actions", dataIndex: "actions",

View File

@@ -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"), title: t("general.labels.actions"),
dataIndex: "actions", dataIndex: "actions",
key: "actions", key: "actions",
sorter: (a, b) => a.clm_total - b.clm_total,
render: (text, record) => ( render: (text, record) => (
<Space wrap> <Space wrap>

View File

@@ -1,13 +1,8 @@
import Dinero from "dinero.js"; import Dinero from "dinero.js";
export const CalculateBillTotal = (invoice) => { export const CalculateBillTotal = (invoice) => {
const { const { total, billlines, federal_tax_rate, local_tax_rate, state_tax_rate } =
total, invoice;
billlines,
federal_tax_rate,
local_tax_rate,
state_tax_rate,
} = invoice;
//TODO Determine why this recalculates so many times. //TODO Determine why this recalculates so many times.
let subtotal = Dinero({ amount: 0 }); let subtotal = Dinero({ amount: 0 });
@@ -20,8 +15,7 @@ export const CalculateBillTotal = (invoice) => {
billlines.forEach((i) => { billlines.forEach((i) => {
if (!!i) { if (!!i) {
const itemTotal = Dinero({ const itemTotal = Dinero({
amount: amount: Math.round((i.actual_cost || 0) * 100),
Math.round(((i.actual_cost || 0) * 100 + Number.EPSILON) * 100) / 100,
}).multiply(i.quantity || 1); }).multiply(i.quantity || 1);
subtotal = subtotal.add(itemTotal); subtotal = subtotal.add(itemTotal);

View File

@@ -72,7 +72,7 @@ export function JobLineStatusPopup({ bodyshop, jobline, disabled }) {
); );
return ( return (
<div <div
style={{ width: "100%", minHeight: "2rem", cursor: "pointer" }} style={{ width: "100%", minHeight: "1rem", cursor: "pointer" }}
onClick={() => !disabled && setEditing(true)} onClick={() => !disabled && setEditing(true)}
> >
{jobline.status} {jobline.status}

View File

@@ -8,7 +8,6 @@ import {
import { Col, notification, Row } from "antd"; import { Col, notification, Row } from "antd";
import Axios from "axios"; import Axios from "axios";
import Dinero from "dinero.js"; import Dinero from "dinero.js";
import _ from "lodash";
import moment from "moment"; import moment from "moment";
import queryString from "query-string"; import queryString from "query-string";
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
@@ -187,7 +186,9 @@ export function JobsAvailableContainer({
setJobModalVisible(false); setJobModalVisible(false);
setInsertLoading(true); setInsertLoading(true);
const estData = replaceEmpty(estDataRaw.data.available_jobs_by_pk);
const estData = estDataRaw.data.available_jobs_by_pk;
if (!(estData && estData.est_data)) { if (!(estData && estData.est_data)) {
//We don't have the right data. Error! //We don't have the right data. Error!
setInsertLoading(false); setInsertLoading(false);
@@ -196,7 +197,7 @@ export function JobsAvailableContainer({
}); });
} else { } else {
//create upsert job //create upsert job
let supp = _.cloneDeep(estData.est_data); let supp = replaceEmpty({ ...estData.est_data });
delete supp.owner; delete supp.owner;
delete supp.vehicle; delete supp.vehicle;
@@ -208,7 +209,7 @@ export function JobsAvailableContainer({
let suppDelta = await GetSupplementDelta( let suppDelta = await GetSupplementDelta(
client, client,
selectedJob, selectedJob,
estData.est_data.joblines.data supp.joblines.data
); );
delete supp.joblines; delete supp.joblines;
@@ -380,10 +381,10 @@ export default connect(
)(JobsAvailableContainer); )(JobsAvailableContainer);
function replaceEmpty(someObj, replaceValue = null) { 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 //^ because you seem to want to replace (strings) "null" or "undefined" too
console.log(someObj);
const temp = JSON.stringify(someObj, replacer); const temp = JSON.stringify(someObj, replacer);
console.log(`temp`, temp); console.log("Parsed", JSON.parse(temp));
return JSON.parse(temp); return JSON.parse(temp);
} }

View File

@@ -61,7 +61,7 @@ export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
); );
}; };
const overlay = ( const overlay = bodyshop.cdk_dealerid && (
<Menu onClick={handleMenuClick}> <Menu onClick={handleMenuClick}>
{bodyshop.md_responsibility_centers.dms_defaults.map((mapping) => ( {bodyshop.md_responsibility_centers.dms_defaults.map((mapping) => (
<Menu.Item key={mapping.name}>{mapping.name}</Menu.Item> <Menu.Item key={mapping.name}>{mapping.name}</Menu.Item>

View File

@@ -150,7 +150,7 @@ export function JobsCloseExportButton({
} }
if (setSelectedJobs) { if (setSelectedJobs) {
setSelectedJobs((selectedJobs) => { setSelectedJobs((selectedJobs) => {
return selectedJobs.filter((i) => i.id !== jobId); return selectedJobs.filter((i) => i !== jobId);
}); });
} }
} }

View File

@@ -10,7 +10,7 @@ import { alphaSort } from "../../utils/sorters";
import LaborAllocationsAdjustmentEdit from "../labor-allocations-adjustment-edit/labor-allocations-adjustment-edit.component"; import LaborAllocationsAdjustmentEdit from "../labor-allocations-adjustment-edit/labor-allocations-adjustment-edit.component";
import "./labor-allocations-table.styles.scss"; import "./labor-allocations-table.styles.scss";
import { CalculateAllocationsTotals } from "./labor-allocations-table.utility"; import { CalculateAllocationsTotals } from "./labor-allocations-table.utility";
import _ from "lodash";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
technician: selectTechnician, technician: selectTechnician,
@@ -113,7 +113,7 @@ export function LaborAllocationsTable({
color: record.difference >= 0 ? "green" : "red", color: record.difference >= 0 ? "green" : "red",
}} }}
> >
{record.difference} {_.round(record.difference, 1)}
</strong> </strong>
), ),
}, },

View File

@@ -145,7 +145,7 @@ export function PayableExportButton({
} }
if (setSelectedBills) { if (setSelectedBills) {
setSelectedBills((selectedBills) => { setSelectedBills((selectedBills) => {
return selectedBills.filter((i) => i.id !== billId); return selectedBills.filter((i) => i !== billId);
}); });
} }
} }

View File

@@ -145,7 +145,7 @@ export function PaymentExportButton({
if (setSelectedPayments) { if (setSelectedPayments) {
setSelectedPayments((selectedBills) => { setSelectedPayments((selectedBills) => {
return selectedBills.filter((i) => i.id !== paymentId); return selectedBills.filter((i) => i !== paymentId);
}); });
} }
} }

View File

@@ -17,7 +17,7 @@ import {
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import * as Utils from "../scoreboard-targets-table/scoreboard-targets-table.util"; import * as Utils from "../scoreboard-targets-table/scoreboard-targets-table.util";
import _ from "lodash";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
}); });
@@ -52,17 +52,22 @@ export function ScoreboardChart({ sbEntriesByDate, bodyshop }) {
const theValue = { const theValue = {
date: moment(val).format("D dd"), date: moment(val).format("D dd"),
paintHrs: dayhrs.painthrs, paintHrs: _.round(dayhrs.painthrs, 1),
bodyHrs: dayhrs.bodyhrs, bodyHrs: _.round(dayhrs.bodyhrs, 1),
accTargetHrs: Utils.AsOfDateTargetHours( accTargetHrs: _.round(
bodyshop.scoreboard_target.dailyBodyTarget + Utils.AsOfDateTargetHours(
bodyshop.scoreboard_target.dailyPaintTarget, bodyshop.scoreboard_target.dailyBodyTarget +
val bodyshop.scoreboard_target.dailyPaintTarget,
val
),
1
), ),
accHrs: accHrs: _.round(
acc.length > 0 acc.length > 0
? acc[acc.length - 1].accHrs + dayhrs.painthrs + dayhrs.bodyhrs ? acc[acc.length - 1].accHrs + dayhrs.painthrs + dayhrs.bodyhrs
: dayhrs.painthrs + dayhrs.bodyhrs, : dayhrs.painthrs + dayhrs.bodyhrs,
1
),
}; };
return [...acc, theValue]; return [...acc, theValue];

View File

@@ -40,17 +40,21 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
const [costOptions, setCostOptions] = useState( const [costOptions, setCostOptions] = useState(
[ [
...(form ...((form.getFieldValue(["md_responsibility_centers", "costs"]) &&
.getFieldValue(["md_responsibility_centers", "costs"]) form
.map((i) => i && i.name) || []), .getFieldValue(["md_responsibility_centers", "costs"])
.map((i) => i && i.name)) ||
[]),
] || [] ] || []
); );
const [profitOptions, setProfitOptions] = useState( const [profitOptions, setProfitOptions] = useState(
[ [
...(form ...((form.getFieldValue(["md_responsibility_centers", "profits"]) &&
.getFieldValue(["md_responsibility_centers", "profits"]) form
.map((i) => i && i.name) || []), .getFieldValue(["md_responsibility_centers", "profits"])
.map((i) => i && i.name)) ||
[]),
] || [] ] || []
); );

View File

@@ -1,9 +1,10 @@
import { Card, Space, Table } from "antd";
import { EditFilled } from "@ant-design/icons"; import { EditFilled } from "@ant-design/icons";
import { Card, Space, Table } from "antd";
import moment from "moment"; import moment from "moment";
import React, { useMemo, useState } from "react"; import React, { useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { import {
selectAuthLevel, selectAuthLevel,
@@ -16,8 +17,6 @@ import RbacWrapper, {
HasRbacAccess, HasRbacAccess,
} from "../rbac-wrapper/rbac-wrapper.component"; } from "../rbac-wrapper/rbac-wrapper.component";
import TimeTicketEnterButton from "../time-ticket-enter-button/time-ticket-enter-button.component"; import TimeTicketEnterButton from "../time-ticket-enter-button/time-ticket-enter-button.component";
import { Link } from "react-router-dom";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
authLevel: selectAuthLevel, authLevel: selectAuthLevel,
@@ -268,8 +267,12 @@ export function TimeTicketList({
<Table.Summary.Cell /> <Table.Summary.Cell />
<Table.Summary.Cell /> <Table.Summary.Cell />
<Table.Summary.Cell /> <Table.Summary.Cell />
<Table.Summary.Cell>{totals.productivehrs}</Table.Summary.Cell> <Table.Summary.Cell>
<Table.Summary.Cell>{totals.actualhrs}</Table.Summary.Cell> {totals.productivehrs.toFixed(1)}
</Table.Summary.Cell>
<Table.Summary.Cell>
{totals.actualhrs.toFixed(1)}
</Table.Summary.Cell>
<Table.Summary.Cell> <Table.Summary.Cell>
{totals.actualhrs === 0 || !totals.actualhrs {totals.actualhrs === 0 || !totals.actualhrs
? "∞" ? "∞"

View File

@@ -48,7 +48,9 @@ export function TimeTicketModalComponent({
{emps && {emps &&
emps.rates.map((item) => ( emps.rates.map((item) => (
<Select.Option key={item.cost_center}> <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.Option>
))} ))}
</Select> </Select>

View File

@@ -24,6 +24,10 @@ export const QUERY_JOBS_FOR_EXPORT = gql`
clm_total clm_total
clm_no clm_no
ins_co_nm ins_co_nm
exportlogs {
id
successful
}
} }
} }
`; `;
@@ -37,6 +41,10 @@ export const QUERY_BILLS_FOR_EXPORT = gql`
invoice_number invoice_number
is_credit_memo is_credit_memo
total total
exportlogs {
id
successful
}
job { job {
id id
ro_number ro_number
@@ -73,6 +81,10 @@ export const QUERY_PAYMENTS_FOR_EXPORT = gql`
transactionid transactionid
paymentnum paymentnum
date date
exportlogs {
id
successful
}
} }
} }
`; `;

View File

@@ -2,7 +2,10 @@ import { gql } from "@apollo/client";
export const SUBSCRIPTION_SCOREBOARD = gql` export const SUBSCRIPTION_SCOREBOARD = gql`
subscription SUBSCRIPTION_SCOREBOARD($start: date!, $end: date!) { 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 id
painthrs painthrs
bodyhrs bodyhrs

View File

@@ -828,6 +828,9 @@
"exportlogs": { "exportlogs": {
"fields": { "fields": {
"createdat": "Created At" "createdat": "Created At"
},
"labels": {
"attempts": "Export Attempts"
} }
}, },
"general": { "general": {
@@ -2112,6 +2115,11 @@
"updated": "Scoreboard updated." "updated": "Scoreboard updated."
} }
}, },
"scoredboard": {
"successes": {
"updated": "Scoreboard entry updated."
}
},
"tech": { "tech": {
"fields": { "fields": {
"employeeid": "Employee ID", "employeeid": "Employee ID",

View File

@@ -828,6 +828,9 @@
"exportlogs": { "exportlogs": {
"fields": { "fields": {
"createdat": "" "createdat": ""
},
"labels": {
"attempts": ""
} }
}, },
"general": { "general": {
@@ -2112,6 +2115,11 @@
"updated": "" "updated": ""
} }
}, },
"scoredboard": {
"successes": {
"updated": ""
}
},
"tech": { "tech": {
"fields": { "fields": {
"employeeid": "", "employeeid": "",

View File

@@ -828,6 +828,9 @@
"exportlogs": { "exportlogs": {
"fields": { "fields": {
"createdat": "" "createdat": ""
},
"labels": {
"attempts": ""
} }
}, },
"general": { "general": {
@@ -2112,6 +2115,11 @@
"updated": "" "updated": ""
} }
}, },
"scoredboard": {
"successes": {
"updated": ""
}
},
"tech": { "tech": {
"fields": { "fields": {
"employeeid": "", "employeeid": "",

View File

@@ -605,7 +605,7 @@ const formatGpPercent = (gppercent) => {
const getAdditionalCostCenter = (jl, profitCenters) => { const getAdditionalCostCenter = (jl, profitCenters) => {
console.log("Checking additional cost center", jl.line_desc); console.log("Checking additional cost center", jl.line_desc);
if (!jl.part_type && !jl.mod_lbr_ty) { 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 //This logic is covered prior and assigned based on the labor type of the lines
// if (lineDesc.includes("shop materials")) { // if (lineDesc.includes("shop materials")) {
// return profitCenters["MASH"]; // return profitCenters["MASH"];