Created
April 26, 2018 16:40
-
-
Save edmondop/91e96cdfd18aabe12b20e96e19917138 to your computer and use it in GitHub Desktop.
chart-data-parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {ChartData} from "chart.js"; | |
import {getDateOfISOWeek, getDateStringOfISOWeek, getWeekNumber} from "../../../commons/src"; | |
import {addMonths, addWeeks, differenceInCalendarMonths, differenceInCalendarWeeks, isPast, isFuture, addDays} from 'date-fns'; | |
import {range} from 'lodash'; | |
export interface IAdvanceSummaryData{ | |
Invoicer__c?: string; | |
paidBackOnTime: number; | |
paidBackLate: number; | |
notPaidBack: number; | |
toBePaidBackNotPostponed: number; | |
toBePaidBackPostponed: number; | |
} | |
interface IMonthlyDataIndex{ | |
year: number; | |
month: number; | |
} | |
interface IWeeklyDataIndex{ | |
year: number; | |
week: number; | |
} | |
export interface IMonthlyChartData extends IAdvanceSummaryData,IMonthlyDataIndex{ | |
} | |
export interface IWeeklyChartData extends IAdvanceSummaryData,IWeeklyDataIndex{ | |
} | |
export interface IChartDataResponse { | |
frequency: "MONTHLY" | "WEEKLY", | |
period: string, | |
data: IMonthlyChartData[] | IWeeklyChartData[] | |
} | |
interface IParsedData { | |
labels: string[]; | |
paidBackOnTime: number[]; | |
paidBackLate: number[]; | |
notPaidBack: number[]; | |
toBePaidBackNotPostponed: number[]; | |
toBePaidBackPostponed: number[]; | |
} | |
const monthsLabels = ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"]; | |
function addData(res:IParsedData, curr:IAdvanceSummaryData){ | |
res.notPaidBack.push(curr.notPaidBack); | |
res.paidBackLate.push(curr.paidBackLate); | |
res.paidBackOnTime.push(curr.paidBackOnTime); | |
res.toBePaidBackPostponed.push(curr.toBePaidBackPostponed); | |
res.toBePaidBackNotPostponed.push(curr.toBePaidBackNotPostponed); | |
} | |
function buildDataSet(parsedData:IParsedData){ | |
return { | |
labels: parsedData.labels, | |
datasets: [ | |
{ | |
label: 'Paid back on time', | |
backgroundColor: '#006600', | |
data: parsedData.paidBackOnTime | |
}, | |
{ | |
label: 'Paid back late', | |
backgroundColor: '#ff6e00', | |
data: parsedData.paidBackLate | |
}, | |
{ | |
label: 'Not paid back', | |
backgroundColor: '#660000', | |
data: parsedData.notPaidBack | |
}, | |
{ | |
label: 'To be paid back - non renegotiated', | |
backgroundColor: '#006600', | |
data: parsedData.toBePaidBackNotPostponed | |
}, | |
{ | |
label: 'To be paid back - renegotiated', | |
backgroundColor: '#ff6e00', | |
data: parsedData.toBePaidBackPostponed | |
} | |
] | |
}; | |
} | |
function initialParsedData(){ | |
return { | |
labels: [], | |
paidBackOnTime: [], | |
paidBackLate: [], | |
notPaidBack: [], | |
toBePaidBackNotPostponed: [], | |
toBePaidBackPostponed: [] | |
}; | |
} | |
function defaultEmptyDataSet(){ | |
return { | |
labels: [], | |
datasets: [ | |
{ | |
label: 'Amount', | |
backgroundColor: '#006600', | |
data: [] | |
} | |
] | |
} | |
} | |
function buildSlidingMonthlyWindow(period:string,data: IMonthlyChartData[]) { | |
let firstDate; | |
let lastDate; | |
if (period === 'ALL') { | |
firstDate = new Date(data[0].year!, data[0].month!); | |
lastDate = new Date(data[data.length - 1].year!, data[data.length - 1].month!); | |
} else { | |
firstDate = addMonths(new Date(), -period / 2); | |
lastDate = addMonths(new Date(), (+period / 2) + 1); | |
} | |
let firstMonth = firstDate.getMonth(); | |
let firstYear = firstDate.getFullYear(); | |
let difference = differenceInCalendarMonths(lastDate, firstDate); | |
let slidingWindow:Array<IMonthlyDataIndex> = range(0,difference).map( (item:number,index:number) => | |
{ | |
const yearIndex = Math.floor((firstMonth + index)/12); | |
return { | |
month : ((firstMonth + index) % 12) +1 , | |
year : firstYear + yearIndex | |
} | |
}); | |
console.log('Using monthly sliding window ' , slidingWindow); | |
return data.filter(d => slidingWindow.some(x => x.month === d.month && x.year === d.year)) | |
} | |
function buildWeeklySlidingWindow(period: string,data: IWeeklyChartData[]){ | |
let firstDate: Date; | |
let lastDate; | |
let firstWeek : number; | |
if (period === 'ALL') { | |
firstDate = getDateOfISOWeek(data[0].week!, data[0].year!); | |
lastDate = getDateOfISOWeek(data[data.length - 1].week!, data[data.length - 1].year!); | |
} else { | |
firstDate = addWeeks(new Date(), -period / 2); | |
lastDate = addWeeks(new Date(), (+period / 2) + 1); | |
} | |
firstWeek = getWeekNumber(firstDate); | |
let difference = differenceInCalendarWeeks(lastDate, firstDate); | |
let slidingWindow: Array<IWeeklyDataIndex> = range(0,difference).map( (item:number,index:number) => | |
{ | |
// TODO: 53 | |
const yearIndex = Math.floor((firstWeek+ index)/52); | |
return { | |
week : (firstWeek + index) % 53 === 0 ? 53 : (firstWeek + index) % 53 , | |
year : firstDate.getFullYear() + yearIndex | |
} | |
}); | |
console.log('Using weekly sliding window' , slidingWindow , 'for data ' , data); | |
return data.filter(d => slidingWindow.some(x => x.week === d.week && x.year === d.year)); | |
} | |
export function parseMonthlyChartData(data: IMonthlyChartData[], period: string): ChartData { | |
console.log('Parsing monthly data ' , data , ' for period ' , period); | |
if (data.length === 0) { | |
return defaultEmptyDataSet(); | |
} | |
const initialData: IParsedData = initialParsedData(); | |
const filteredData = buildSlidingMonthlyWindow(period,data); | |
const parsedData = filteredData.reduce((res: IParsedData, curr: IMonthlyChartData) => { | |
res.labels.push(`${monthsLabels[curr.month! - 1]} ${curr.year}`); | |
addData(res,curr); | |
return res; | |
}, initialData); | |
return buildDataSet(parsedData); | |
} | |
export function parseWeeklyChartData(data: IWeeklyChartData[], period: string): ChartData { | |
console.log('Parsing weekly data ' , data , ' for period ' , period); | |
if (data.length === 0) { | |
return defaultEmptyDataSet(); | |
} | |
const initialData: IParsedData = initialParsedData(); | |
const filteredData = buildWeeklySlidingWindow(period,data); | |
const parsedData = filteredData.reduce( (res: IParsedData, curr: IWeeklyChartData) => { | |
res.labels.push(`${getDateStringOfISOWeek(curr.week!, curr.year!)}`); | |
addData(res,curr); | |
return res; | |
}, initialData); | |
return buildDataSet(parsedData); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment