gemcap-be-common 1.2.72 → 1.2.74

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,176 @@
1
+ import Decimal from 'decimal.js';
2
+ import dayjs from 'dayjs';
3
+
4
+ import { getBBCDatesForPeriod } from '../../db/bbcDates.db';
5
+ import { getBBCSheetsByType } from '../../db/bbcSheets.db';
6
+ import { ECollaterals } from '../../enums/collaterals.enum';
7
+ import { getCollateralDocsByBBC } from '../../db/collaterals.db';
8
+ import { getAllUniqSKUInRangeNew } from '../../db/inventories';
9
+ import { IInventoryItem } from '../../models/InventoryItem.model';
10
+ import { IBBCDateDoc } from '../../models/BBCDate.model';
11
+ import { TQueryParams } from '../../models/QueryResult.model';
12
+ import { addHeaderToData } from '../../helpers/excel.helper';
13
+
14
+ interface IGroupedCollaterals extends IBBCDateDoc {
15
+ items: IInventoryItem[];
16
+ }
17
+
18
+ export const getInventoryTurnFull = async (params: TQueryParams) => {
19
+ const { borrowerId, startDate, endDate } = params;
20
+ const {
21
+ tableByUnit,
22
+ tableByValue,
23
+ } = await getInventoryTurn(borrowerId.toString(), startDate.toISOString(), endDate.toISOString());
24
+ const headerByUnit = getInventoryTurnHeader('byUnit');
25
+ const headerByValue = getInventoryTurnHeader('byValue');
26
+
27
+ const tableByUnitFull = addHeaderToData(headerByUnit, tableByUnit);
28
+ const tableByValueFull = addHeaderToData(headerByValue, tableByValue);
29
+
30
+ return {
31
+ 'by unit': tableByUnitFull, 'by value': tableByValueFull,
32
+ };
33
+ };
34
+
35
+ export const getInventoryTurn = async (borrowerId: string, startDate: string, endDate: string) => {
36
+ const bbcDates = await getBBCDatesForPeriod(borrowerId, new Date(startDate), new Date(endDate));
37
+ const bbcIds = bbcDates.map((bbc) => bbc._id.toString());
38
+ const bbcSheets = await getBBCSheetsByType(bbcIds, ECollaterals.INVENTORY);
39
+ const skuGroup = (await getAllUniqSKUInRangeNew(bbcSheets.map((bbcSheet) => bbcSheet._id.toString()))).pop();
40
+ const BBCs: IGroupedCollaterals[] = await getCollateralDocsByBBC(bbcIds, ECollaterals.INVENTORY);
41
+ return getDifference(skuGroup ? skuGroup.skus.sort() : [], BBCs);
42
+ };
43
+
44
+ const getDifference = (uniqSKUs: string[], BBCs: IGroupedCollaterals[]) => {
45
+ if (uniqSKUs) {
46
+ const groupedBbc = uniqSKUs.map((sku) => {
47
+ let minUnitCost = 0;
48
+ const totalSum = BBCs.map((bbc) => {
49
+ const skuItems = bbc.items.filter((item) => item.sku === sku);
50
+ const unitCosts = skuItems.map((item) => item.qty === 0 ? 0 : new Decimal(item.value).div(item.qty).toNumber());
51
+ if (unitCosts.length) {
52
+ minUnitCost = Math.min(...unitCosts);
53
+ }
54
+ const sum = skuItems.reduce((acc, item) => new Decimal(acc).add(item.qty).toNumber(), 0);
55
+ return { bbc: bbc.bbcDate, sum };
56
+ });
57
+ return { sku, totalSum, minUnitCost };
58
+ });
59
+ const groupedBbcWithDifferences = groupedBbc.map((group) => {
60
+ const differences = [];
61
+ group.totalSum.forEach((sumGroup, index) => {
62
+ if (index > 0) {
63
+ const firstDate = dayjs(group.totalSum[index - 1].bbc);
64
+ const lastDate = dayjs(sumGroup.bbc);
65
+ const diffDays = lastDate.diff(firstDate, 'day');
66
+ const diff = new Decimal(group.totalSum[index - 1].sum).sub(sumGroup.sum).toNumber();
67
+ const diffPerDay = diffDays > 0 ? new Decimal(diff).div(diffDays).toNumber() : 0;
68
+ differences.push({
69
+ bbc: sumGroup.bbc,
70
+ diff,
71
+ diffDays,
72
+ decreasePerDay: diffPerDay > 0 ? diffPerDay : 0,
73
+ increasePerDay: diffPerDay < 0 ? diffPerDay : 0,
74
+ });
75
+ }
76
+ });
77
+ return { ...group, differences };
78
+ });
79
+ const tableByUnit = [];
80
+ groupedBbcWithDifferences.forEach((group) => {
81
+ const totalDifference = group.differences.reduce((acc, group) => {
82
+ if (group.diff < 0) {
83
+ const diff = new Decimal(acc.increasesOverPeriod).add(group.diff).toNumber();
84
+ return { ...acc, increasesOverPeriod: diff };
85
+ } else {
86
+ const diff = new Decimal(acc.decreasesOverPeriod).add(Math.abs(group.diff)).toNumber();
87
+ return { ...acc, decreasesOverPeriod: diff };
88
+ }
89
+ }, { increasesOverPeriod: 0, decreasesOverPeriod: 0 });
90
+ const { increasesOverPeriod, decreasesOverPeriod } = totalDifference;
91
+ const current = group.totalSum[group.totalSum.length - 1].sum;
92
+ const firstDate = dayjs(group.totalSum[0].bbc);
93
+ const lastDate = dayjs(group.totalSum[group.totalSum.length - 1].bbc);
94
+ const dayInRange = lastDate.diff(firstDate, 'day');
95
+ const averageIncreasesPerDay = new Decimal(increasesOverPeriod).div(dayInRange).toNumber();
96
+ const averageDecreasesPerDay = new Decimal(decreasesOverPeriod).div(dayInRange).toNumber();
97
+ // const increaseDiffs = group.differences.filter((diff) => diff.increasePerDay < 0);
98
+ // const decreaseDiffs = group.differences.filter((diff) => diff.decreasePerDay > 0);
99
+ // const averageIncreasePerDay_test = increaseDiffs.length > 0
100
+ // ? new Decimal(increaseDiffs.reduce((acc, diff) => new Decimal(diff.increasePerDay).add(acc).toNumber(), 0)).div(decreaseDiffs.length).toNumber()
101
+ // : 0;
102
+ // const averageDecreasesPerDay_test = decreaseDiffs.length > 0
103
+ // ? new Decimal(decreaseDiffs.reduce((acc, diff) => new Decimal(diff.decreasePerDay).add(acc).toNumber(), 0)).div(decreaseDiffs.length).toNumber()
104
+ // : 0;
105
+ const daysToClear = averageDecreasesPerDay === 0
106
+ ? 0
107
+ : new Decimal(current).div(averageDecreasesPerDay).toDP().toNumber();
108
+ const ranking = averageDecreasesPerDay === 0
109
+ ? Math.round(averageIncreasesPerDay)
110
+ : new Decimal(averageIncreasesPerDay).div(averageDecreasesPerDay).toDP().toNumber();
111
+ tableByUnit.push({
112
+ sku: group.sku,
113
+ current,
114
+ minUnitCost: group.minUnitCost,
115
+ increasesOverPeriod,
116
+ decreasesOverPeriod,
117
+ averageIncreasesPerDay,
118
+ averageDecreasesPerDay,
119
+ daysToClear,
120
+ ranking,
121
+ });
122
+ });
123
+ tableByUnit.sort((a, b) => a.ranking > b.ranking ? -1 : 0);
124
+ const tableByValue = [];
125
+ tableByUnit.forEach((unit) => {
126
+ const minUnitCost = unit.minUnitCost;
127
+ const current = new Decimal(unit.current).mul(minUnitCost).toNumber();
128
+ const increasesOverPeriod = new Decimal(unit.increasesOverPeriod).mul(minUnitCost).toNumber();
129
+ const decreasesOverPeriod = new Decimal(unit.decreasesOverPeriod).mul(minUnitCost).toNumber();
130
+ const averageIncreasesPerDay = new Decimal(unit.averageIncreasesPerDay).mul(minUnitCost).toNumber();
131
+ const averageDecreasesPerDay = new Decimal(unit.averageDecreasesPerDay).mul(minUnitCost).toNumber();
132
+ const daysToClear = Math.round(new Decimal(unit.daysToClear).mul(minUnitCost).toNumber());
133
+ const ranking = Math.round(new Decimal(unit.ranking).mul(minUnitCost).toNumber());
134
+ tableByValue.push({
135
+ sku: unit.sku,
136
+ minUnitCost,
137
+ current,
138
+ increasesOverPeriod,
139
+ decreasesOverPeriod,
140
+ averageIncreasesPerDay,
141
+ averageDecreasesPerDay,
142
+ daysToClear,
143
+ ranking,
144
+ });
145
+ });
146
+ return { tableByUnit, tableByValue };
147
+ }
148
+ return { tableByUnit: [], tableByValue: [] };
149
+ };
150
+
151
+ const getInventoryTurnHeader = (type: 'byUnit' | 'byValue') => {
152
+ const headerMap = {
153
+ 'byUnit': {
154
+ sku: 'SKU',
155
+ current: 'Current number of units',
156
+ increasesOverPeriod: 'Increases in units over period',
157
+ decreasesOverPeriod: 'Decreases in units over period',
158
+ averageIncreasesPerDay: 'Average increases in units per day',
159
+ averageDecreasesPerDay: 'Average decreases in units per day',
160
+ daysToClear: 'Days to clear',
161
+ ranking: 'Ranking',
162
+ },
163
+ 'byValue': {
164
+ sku: 'SKU',
165
+ current: 'Current value',
166
+ minUnitCost: 'Min unit cost',
167
+ increasesOverPeriod: 'Increases over in value period',
168
+ decreasesOverPeriod: 'Decreases over in value period',
169
+ averageIncreasesPerDay: 'Average value increases per day',
170
+ averageDecreasesPerDay: 'Average value decreases per day',
171
+ daysToClear: 'Days to clear',
172
+ ranking: 'Ranking',
173
+ },
174
+ };
175
+ return headerMap[type];
176
+ };
@@ -1,4 +1,5 @@
1
1
  import { TQueryParams } from '../../models/QueryResult.model';
2
+ export declare const getUnitCostDifferenceFull: (params: TQueryParams) => Promise<{}[]>;
2
3
  export declare const getUnitCostDifference: (params: TQueryParams) => Promise<{
3
4
  SKU: string;
4
5
  CURRENT_UNIT_COST: number;
@@ -8,12 +9,3 @@ export declare const getUnitCostDifference: (params: TQueryParams) => Promise<{
8
9
  CURRENT_QTY: number;
9
10
  VALUE_CHANGE: number;
10
11
  }[]>;
11
- export declare const getUnitCostDifferenceHeader: () => {
12
- SKU: string;
13
- CURRENT_QTY: string;
14
- CURRENT_UNIT_COST: string;
15
- LOWEST_UNIT_COST: string;
16
- LOWEST_UNIT_COST_DATE: string;
17
- DIFFERENCE: string;
18
- VALUE_CHANGE: string;
19
- };
@@ -3,12 +3,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getUnitCostDifferenceHeader = exports.getUnitCostDifference = void 0;
6
+ exports.getUnitCostDifference = exports.getUnitCostDifferenceFull = void 0;
7
7
  const mongoose_1 = __importDefault(require("mongoose"));
8
8
  const decimal_js_1 = __importDefault(require("decimal.js"));
9
9
  const collaterals_db_1 = require("../../db/collaterals.db");
10
10
  const collaterals_enum_1 = require("../../enums/collaterals.enum");
11
11
  const inventories_1 = require("../../db/inventories");
12
+ const excel_helper_1 = require("../../helpers/excel.helper");
13
+ const getUnitCostDifferenceFull = async (params) => {
14
+ const data = await (0, exports.getUnitCostDifference)(params);
15
+ const header = getUnitCostDifferenceHeader();
16
+ return (0, excel_helper_1.addHeaderToData)(header, data);
17
+ };
18
+ exports.getUnitCostDifferenceFull = getUnitCostDifferenceFull;
12
19
  const getUnitCostDifference = async (params) => {
13
20
  const { borrowerId } = params;
14
21
  const bbcGroups = await (0, collaterals_db_1.findCollateralsWithSheets)(borrowerId.toString(), [collaterals_enum_1.ECollaterals.INVENTORY]);
@@ -42,4 +49,3 @@ const getUnitCostDifferenceHeader = () => {
42
49
  VALUE_CHANGE: 'Value change',
43
50
  };
44
51
  };
45
- exports.getUnitCostDifferenceHeader = getUnitCostDifferenceHeader;
@@ -5,6 +5,13 @@ import { findCollateralsWithSheets } from '../../db/collaterals.db';
5
5
  import { ECollaterals } from '../../enums/collaterals.enum';
6
6
  import { getSKUUnitCostForAllDates } from '../../db/inventories';
7
7
  import { TQueryParams } from '../../models/QueryResult.model';
8
+ import { addHeaderToData } from '../../helpers/excel.helper';
9
+
10
+ export const getUnitCostDifferenceFull = async (params: TQueryParams) => {
11
+ const data = await getUnitCostDifference(params);
12
+ const header = getUnitCostDifferenceHeader();
13
+ return addHeaderToData(header, data);
14
+ };
8
15
 
9
16
  export const getUnitCostDifference = async (params: TQueryParams) => {
10
17
  const { borrowerId } = params;
@@ -28,7 +35,7 @@ export const getUnitCostDifference = async (params: TQueryParams) => {
28
35
  .sort((a, b) => a.VALUE_CHANGE > b.VALUE_CHANGE ? -1 : 0);
29
36
  };
30
37
 
31
- export const getUnitCostDifferenceHeader = () => {
38
+ const getUnitCostDifferenceHeader = () => {
32
39
  return {
33
40
  SKU: 'SKU',
34
41
  CURRENT_QTY: 'qty',