import Dinero from "dinero.js"; import _ from "lodash"; import { all, call, put, select, takeLatest } from "redux-saga/effects"; import client from "../../graphql/GraphQLClient"; import { REPORTING_GET_JOBS } from "../../graphql/reporting.queries"; import ipcTypes from "../../ipc.types"; import { CalculateJobRpsDollars, CalculateJobRpsPc, } from "../../util/CalculateJobRps"; import GetJobTarget from "../../util/GetJobTarget"; import { calculateScorecard, setReportingData, setScoreCard, } from "./reporting.actions"; import ReportingApplicationTypes from "./reporting.types"; const { log, ipcRenderer } = window; export function* onQueryReportData() { yield takeLatest( ReportingApplicationTypes.QUERY_REPORTING_DATA, queryReportingData ); } export function* queryReportingData({ payload: { startDate, endDate } }) { const result = yield client.query({ query: REPORTING_GET_JOBS, variables: { startDate, endDate }, }); if (result.errors) { log.error("Error fetching report data.", result.errors); yield put(setReportingData(null)); } else { yield put(calculateScorecard(result.data.jobs)); } } export function* onSetReportData() { yield takeLatest( ReportingApplicationTypes.SET_REPORTING_DATA, handleSetReportData ); } export function* handleSetReportData({ payload: jobs }) { // yield put(calculateScorecard(jobs)); } export function* onCalculateScoreCard() { yield takeLatest( ReportingApplicationTypes.CALCULATE_SCORE_CARD, handleCalculateScoreCard ); } export function* handleCalculateScoreCard({ payload: jobs }) { try { ipcRenderer.send(ipcTypes.default.app.toMain.track, { event: "CALCULATE_SCORECARD", }); const targets = yield select((state) => state.user.bodyshop.targets); const groups = yield select((state) => state.user.bodyshop.groups); const scoreCard = { shopRpsTotalDollars: Dinero(), shopRpsExpectedDollars: Dinero(), varianceDollars: null, variancePc: 0, allJobsSumDbPrice: Dinero(), allJobsSumActPrice: Dinero(), currentRpsPc: 0, targetRpsPc: 0, scatterChart: _.sortBy( groups, [(group) => group.toLowerCase()], ["desc"] ).reduce((acc, val) => { return { ...acc, [val]: [] }; }, {}), }; //Get the RPS on a per job basis. jobs = jobs.map((job) => { const { actPriceSum, jobRpsDollars } = CalculateJobRpsDollars(job, true); const { dbPriceSum, jobRpsPc } = CalculateJobRpsPc( job, jobRpsDollars, true ); const jobTarget = GetJobTarget(job.group, job.v_age, targets); scoreCard.shopRpsTotalDollars = scoreCard.shopRpsTotalDollars.add( jobRpsDollars ); const expectedRpsDollars = dbPriceSum.percentage(jobTarget * 100); scoreCard.shopRpsExpectedDollars = scoreCard.shopRpsExpectedDollars.add( expectedRpsDollars ); scoreCard.allJobsSumDbPrice = scoreCard.allJobsSumDbPrice.add(dbPriceSum); scoreCard.allJobsSumActPrice = scoreCard.allJobsSumActPrice.add( actPriceSum ); const deviationPc = Math.round((jobRpsPc - jobTarget) * 1000) / 10; scoreCard.scatterChart[job.group].push({ deviationPc: isNaN(deviationPc) ? -100 : deviationPc, deviationDollars: ( jobRpsDollars.subtract(expectedRpsDollars).getAmount() / 100 ).toFixed(2), age: job.v_age, dbPriceSum, dbPriceSumAmt: dbPriceSum.getAmount() / 100, id: job.id, owner: `${job.ownr_fn} ${job.ownr_ln}`, vehicle: `${job.v_model_yr} ${job.v_makedesc} ${job.v_model} (${job.v_type}) - ${job.group}`, clm_no: job.clm_no, jobRpsDollars, jobRpsPc: isNaN(jobRpsPc) ? -1 : jobRpsPc, }); //sum db price * percentage expected. return { ...job, actPriceSum, jobRpsDollars, dbPriceSum, jobRpsPc, jobTarget, expectedRpsDollars, }; }); scoreCard.varianceDollars = scoreCard.shopRpsTotalDollars.subtract( scoreCard.shopRpsExpectedDollars ); scoreCard.currentRpsPc = scoreCard.shopRpsTotalDollars.getAmount() / scoreCard.allJobsSumDbPrice.getAmount(); scoreCard.targetRpsPc = scoreCard.shopRpsExpectedDollars.getAmount() / scoreCard.allJobsSumDbPrice.getAmount(); scoreCard.variancePc = scoreCard.currentRpsPc - scoreCard.targetRpsPc; //Set the data. yield put(setScoreCard(scoreCard)); yield put(setReportingData(jobs)); } catch (error) { ipcRenderer.send(ipcTypes.default.app.toMain.track, { event: "CALCULATE_SCORE_CARD_ERROR", error: error, }); } } export function* reportingSagas() { yield all([ call(onQueryReportData), call(onSetReportData), call(onCalculateScoreCard), ]); }