statewise-chart-processor 1.0.0 → 1.0.2

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.
Files changed (2) hide show
  1. package/index.js +602 -1
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1,3 +1,275 @@
1
+ function processStateChartData(chartData, reportHeader, tableHeaders, areaType) {
2
+ if (!chartData || !chartData.length) return null;
3
+ const finalData = { State: {} };
4
+ chartData.forEach(value => {
5
+ if (value.district && value.district !== '(NULL)') {
6
+ if (!finalData.State[value.state]) {
7
+ finalData.State[value.state] = { State: value.state };
8
+ }
9
+ if (!finalData.State[value.state][value.district]) {
10
+ finalData.State[value.state][value.district] = { district: value.district };
11
+ }
12
+ if (!finalData.State[value.state][value.district][value.area_type]) {
13
+ finalData.State[value.state][value.district][value.area_type] = { report_header: [] };
14
+ }
15
+ // Fill report_header for this area_type
16
+ Object.entries(reportHeader).forEach(([colname, headerName]) => {
17
+ finalData.State[value.state][value.district][value.area_type].report_header.push({
18
+ name: headerName,
19
+ total: value[colname]
20
+ });
21
+ });
22
+ // Fill missing area types with zeroes
23
+ areaType.forEach(type => {
24
+ if (!finalData.State[value.state][value.district][type]) {
25
+ finalData.State[value.state][value.district][type] = { report_header: [] };
26
+ Object.entries(reportHeader).forEach(([colname, headerName]) => {
27
+ finalData.State[value.state][value.district][type].report_header.push({
28
+ name: headerName,
29
+ total: 0
30
+ });
31
+ });
32
+ }
33
+ });
34
+ }
35
+ });
36
+ return finalData;
37
+ }
38
+ async function workersChartData(parameterData, chartData, tablewiseChartData) {
39
+ chartData = chartData[0];
40
+ tablewiseChartData = tablewiseChartData[0];
41
+
42
+ // Initialize result structure
43
+ const result = {
44
+ tableheaders: [],
45
+ areatype: [],
46
+ finaldata: {},
47
+ grandtotal: { grandTotal: {} }
48
+ };
49
+
50
+ // Process chartData if exists
51
+ if (chartData && chartData.length > 0) {
52
+ // Get report headers with order
53
+ const reportHeaderMap = {};
54
+ chartData.forEach(item => {
55
+ if (item.report_header && item.report_order != null) {
56
+ reportHeaderMap[item.report_order] = item.report_header;
57
+ }
58
+ });
59
+ // Sort by numeric keys and get values
60
+ const sortedReportHeaders = Object.keys(reportHeaderMap)
61
+ .sort((a, b) => parseInt(a) - parseInt(b))
62
+ .map(key => reportHeaderMap[key]);
63
+ result.tableheaders = sortedReportHeaders;
64
+ // Get unique area_type values
65
+ const areaTypeSet = new Set();
66
+ chartData.forEach(item => {
67
+ if (item.area_type) {
68
+ areaTypeSet.add(item.area_type);
69
+ }
70
+ });
71
+ // Convert to array and sort
72
+ let areatype = Array.from(areaTypeSet)
73
+ .filter(type => type !== null && type !== undefined && type !== '')
74
+ .sort((a, b) => {
75
+ const numA = parseInt(a);
76
+ const numB = parseInt(b);
77
+ if (!isNaN(numA) && !isNaN(numB)) {
78
+ return numA - numB;
79
+ }
80
+ return String(a).localeCompare(String(b));
81
+ });
82
+ const areaarray = ['rural', 'urban', 'combined'];
83
+ // Check if all areatype values are in areaarray and we have more than 1
84
+ const intersection = areatype.filter(type => areaarray.includes(type));
85
+ if (intersection.length === areatype.length && areatype.length > 1) {
86
+ areatype = areaarray; // Use the predefined order
87
+ }
88
+ result.areatype = areatype;
89
+ // Process data for specific flags
90
+ if ((parameterData.flag == 153 || parameterData.flag == 400 || parameterData.flag == 101)) {
91
+ const finaldata = { State: {} };
92
+ const grandtotal = { grandTotal: {} };
93
+ // First pass: Process chartData
94
+ chartData.forEach(value => {
95
+ if (value.disttName !== '(NULL)' && sortedReportHeaders.includes(value.report_header)) {
96
+ const state = 'name';
97
+ //const state = value.State;
98
+ const district = value.disttName;
99
+ const area = value.area_type;
100
+ // Initialize state data if needed
101
+ if (!finaldata.State[state]) {
102
+ finaldata.State[state] = {
103
+ State: state,
104
+ disttName: district
105
+ };
106
+ }
107
+ // Initialize district data if needed
108
+ if (!finaldata.State[state][district]) {
109
+ finaldata.State[state][district] = {
110
+ disttName: district,
111
+ grandTotal: 0
112
+ };
113
+ }
114
+ // Initialize area type data if needed
115
+ if (!finaldata.State[state][district][area]) {
116
+ finaldata.State[state][district][area] = {
117
+ report_header: []
118
+ };
119
+ }
120
+ // Add report header data
121
+ finaldata.State[state][district][area].report_header.push({
122
+ name: value.report_header,
123
+ total: value.total
124
+ });
125
+ // Process grand totals for area types
126
+ if (!grandtotal.grandTotal[area]) {
127
+ grandtotal.grandTotal[area] = {};
128
+ }
129
+ if (!grandtotal.grandTotal[area][value.report_header]) {
130
+ grandtotal.grandTotal[area][value.report_header] = { total: 0 };
131
+ }
132
+ grandtotal.grandTotal[area][value.report_header].total += Number(value.total);
133
+ // Process final total
134
+ if (!grandtotal.grandTotal.finaltotal) {
135
+ grandtotal.grandTotal.finaltotal = 0;
136
+ }
137
+ grandtotal.grandTotal.finaltotal += Number(value.total);
138
+ // Update district grand total
139
+ finaldata.State[state][district].grandTotal += Number(value.total);
140
+ }
141
+ });
142
+ // Merge grandtotal into finaldata
143
+ Object.assign(finaldata, grandtotal);
144
+ // Remove specific area types from grandTotal
145
+ if (areatype.length > 0) {
146
+ delete finaldata.grandTotal[areatype[0]];
147
+ if (areatype.length > 1) {
148
+ delete finaldata.grandTotal[areatype[1]];
149
+ }
150
+ }
151
+ // Reset finaltotal
152
+ finaldata.grandTotal.finaltotal = 0;
153
+ // Second pass: Reorganize data by area types
154
+ Object.entries(finaldata.State).forEach(([stateKey, stateValue]) => {
155
+ if (typeof stateValue === 'object') {
156
+ Object.entries(stateValue).forEach(([districtKey, districtValue]) => {
157
+ if (typeof districtValue === 'object' && districtKey !== 'State' && districtKey !== 'disttName') {
158
+ // Process each area type
159
+ areatype.forEach((area, index) => {
160
+ if (districtValue[area]) {
161
+ // Create map of existing totals for this area
162
+ const areaTotals = {};
163
+ districtValue[area].report_header.forEach(item => {
164
+ areaTotals[item.name] = Number(item.total);
165
+ });
166
+ // Clear and rebuild with tableheaders order
167
+ delete districtValue[area].report_header;
168
+ districtValue[area].report_header = [];
169
+ districtValue[area].areatotal = 0;
170
+ // Initialize grandTotal for this area if needed
171
+ if (!finaldata.grandTotal[area]) {
172
+ finaldata.grandTotal[area] = {};
173
+ }
174
+ sortedReportHeaders.forEach(headername => {
175
+ // Initialize grand total for this header
176
+ if (!finaldata.grandTotal[area][headername]) {
177
+ finaldata.grandTotal[area][headername] = { total: 0 };
178
+ }
179
+ if (!finaldata.grandTotal.combined) {
180
+ finaldata.grandTotal.combined = {};
181
+ }
182
+ if (!finaldata.grandTotal.combined[headername]) {
183
+ finaldata.grandTotal.combined[headername] = { total: 0 };
184
+ }
185
+ const total = areaTotals[headername] || 0;
186
+ districtValue[area].report_header.push({
187
+ name: headername,
188
+ total: total
189
+ });
190
+ districtValue[area].areatotal += Number(total);
191
+ // Update grand totals
192
+ finaldata.grandTotal[area][headername].total += Number(total);
193
+ finaldata.grandTotal.finaltotal += Number(total);
194
+ // Update area total in grandTotal
195
+ if (!finaldata.grandTotal[area].areatotal) {
196
+ finaldata.grandTotal[area].areatotal = 0;
197
+ }
198
+ finaldata.grandTotal[area].areatotal += Number(total);
199
+ // Update combined if multiple areas
200
+ if (areatype.length > 1 && index === 0) {
201
+ finaldata.grandTotal.combined[headername].total += total;
202
+ }
203
+ // Update district grand total
204
+ districtValue.grandTotal += total;
205
+ });
206
+ } else {
207
+ // No data for this area - create empty entries
208
+ districtValue[area] = {
209
+ report_header: [],
210
+ areatotal: 0
211
+ };
212
+ sortedReportHeaders.forEach(headername => {
213
+ districtValue[area].report_header.push({
214
+ name: headername,
215
+ total: 0
216
+ });
217
+ });
218
+ }
219
+ });
220
+ // Handle combined area for multiple area types
221
+ if (areatype.length > 1) {
222
+ const combinedArea = 'combined';
223
+ districtValue[combinedArea] = { report_header: [] };
224
+ sortedReportHeaders.forEach(headername => {
225
+ const ruralTotal = districtValue[areatype[0]]?.report_header?.find(item => item.name === headername)?.total || 0;
226
+ const urbanTotal = districtValue[areatype[1]]?.report_header?.find(item => item.name === headername)?.total || 0;
227
+ const combinedTotal = ruralTotal + urbanTotal;
228
+ districtValue[combinedArea].report_header.push({
229
+ name: headername,
230
+ total: combinedTotal
231
+ });
232
+ });
233
+ }
234
+ }
235
+ });
236
+ }
237
+ });
238
+ result.finaldata = finaldata;
239
+ // Process tablewiseChartData if available
240
+ if (tablewiseChartData && tablewiseChartData.length > 0) {
241
+ const tableReportHeader = [...new Set(tablewiseChartData
242
+ .filter(item => item.report_header && item.report_order != null)
243
+ .map(item => item.report_header)
244
+ )];
245
+ finaldata.tabledata = {};
246
+ tablewiseChartData.forEach(value => {
247
+ if (value.disttName !== '(NULL)' && tableReportHeader.includes(value.report_header)) {
248
+ const state = value.State;
249
+ const district = value.disttName;
250
+ const table = value.tableName;
251
+ // Initialize structure
252
+ if (!finaldata.tabledata[state]) {
253
+ finaldata.tabledata[state] = {};
254
+ }
255
+ if (!finaldata.tabledata[state][district]) {
256
+ finaldata.tabledata[state][district] = {};
257
+ }
258
+ if (!finaldata.tabledata[state][district][table]) {
259
+ finaldata.tabledata[state][district][table] = { report_header: [] };
260
+ }
261
+ // Add data
262
+ finaldata.tabledata[state][district][table].report_header.push({
263
+ name: value.report_header,
264
+ total: value.total
265
+ });
266
+ }
267
+ });
268
+ }
269
+ }
270
+ }
271
+ return result;
272
+ }
1
273
  async function processstatewisechart(parameterData, chartData, tablewiseChartData) {
2
274
  // ...your function code here...
3
275
  if (!chartData || chartData.length === 0) return {};
@@ -209,4 +481,333 @@ async function processstatewisechart(parameterData, chartData, tablewiseChartDat
209
481
  return { ...finaldata, ...grandtotal };
210
482
  }
211
483
 
212
- module.exports = { processstatewisechart };
484
+ async function processChartData(chartData, tablewiseChartData = null, tableheaders, reportHeader, areatype) {
485
+ let finaldata = { State: {} };
486
+ let grandtotal = { grandTotal: {} };
487
+
488
+ // -----------------------------
489
+ // FIRST PASS → STATE & GRAND TOTALS
490
+ // -----------------------------
491
+ for (const row of chartData) {
492
+ if (!row.state) continue;
493
+ if (!reportHeader.includes(row.report_header)) continue;
494
+
495
+ const state = row.state;
496
+ const area = row.area_type;
497
+ const header = row.report_header;
498
+ const total = row.total;
499
+
500
+ // Create state entry
501
+ if (!finaldata.State[state]) finaldata.State[state] = {};
502
+
503
+ // remarks only if flag=63
504
+ if (row.flag == 63) {
505
+ finaldata.State[state].State = state;
506
+ finaldata.State[state].remarks = row.remarks;
507
+ } else {
508
+ finaldata.State[state].State = state;
509
+ }
510
+
511
+ // Create area holder
512
+ if (!finaldata.State[state][area])
513
+ finaldata.State[state][area] = { report_header: [] };
514
+
515
+ // Push header → total
516
+ finaldata.State[state][area].report_header.push({
517
+ name: header,
518
+ total: total
519
+ });
520
+
521
+ // GRAND TOTAL by area + header
522
+ if (!grandtotal.grandTotal[area])
523
+ grandtotal.grandTotal[area] = {};
524
+
525
+ if (!grandtotal.grandTotal[area][header])
526
+ grandtotal.grandTotal[area][header] = { total: 0 };
527
+
528
+ grandtotal.grandTotal[area][header].total += total;
529
+
530
+ // GLOBAL final total
531
+ if (!grandtotal.grandTotal.finaltotal)
532
+ grandtotal.grandTotal.finaltotal = 0;
533
+
534
+ grandtotal.grandTotal.finaltotal += total;
535
+ }
536
+
537
+ finaldata = { ...finaldata, ...grandtotal };
538
+
539
+ // remove unwanted grand totals
540
+ if(areatype && areatype.length>0){
541
+ delete finaldata.grandTotal[areatype[0]];
542
+ }
543
+
544
+ finaldata.grandTotal.finaltotal = 0;
545
+ if (areatype.length > 1) delete finaldata.grandTotal[areatype[1]];
546
+
547
+ // -----------------------------
548
+ // SECOND PASS → RESHAPE BY HEADER
549
+ // -----------------------------
550
+ for (const stateKey in finaldata.State) {
551
+ const stateBlock = finaldata.State[stateKey];
552
+
553
+ // RURAL
554
+ if (stateBlock[areatype[0]]) {
555
+ let ruralTotals = Object.fromEntries(
556
+ stateBlock[areatype[0]].report_header.map(h => [h.name, h.total])
557
+ );
558
+
559
+ stateBlock[areatype[0]].report_header = [];
560
+ stateBlock[areatype[0]].areatotal = 0;
561
+
562
+ for (let header of tableheaders) {
563
+ let total = ruralTotals[header] || 0;
564
+
565
+ stateBlock[areatype[0]].report_header.push({
566
+ name: header,
567
+ total
568
+ });
569
+
570
+ stateBlock[areatype[0]].areatotal += total;
571
+
572
+ // init grandTotal rural for this header
573
+ if (!finaldata.grandTotal[areatype[0]])
574
+ finaldata.grandTotal[areatype[0]] = {};
575
+
576
+ if (!finaldata.grandTotal[areatype[0]][header])
577
+ finaldata.grandTotal[areatype[0]][header] = { total: 0 };
578
+
579
+ finaldata.grandTotal[areatype[0]][header].total += total;
580
+ finaldata.grandTotal.finaltotal += total;
581
+ }
582
+ } else {
583
+ // fill zero rural
584
+ stateBlock[areatype[0]] = { report_header: [], areatotal: 0 };
585
+ for (let header of tableheaders) {
586
+ stateBlock[areatype[0]].report_header.push({ name: header, total: 0 });
587
+ }
588
+ }
589
+
590
+ // URBAN + COMBINED
591
+ if (areatype.length > 1) {
592
+ if (stateBlock[areatype[1]]) {
593
+ let urbanTotals = Object.fromEntries(
594
+ stateBlock[areatype[1]].report_header.map(h => [h.name, h.total])
595
+ );
596
+
597
+ stateBlock[areatype[1]].report_header = [];
598
+ stateBlock[areatype[1]].areatotal = 0;
599
+ stateBlock.combined = { report_header: [] };
600
+
601
+ for (let header of tableheaders) {
602
+ let urban = urbanTotals[header] || 0;
603
+ let rural =
604
+ stateBlock[areatype[0]].report_header.find(h => h.name === header)?.total || 0;
605
+
606
+ let combined = rural + urban;
607
+
608
+ stateBlock[areatype[1]].report_header.push({
609
+ name: header,
610
+ total: urban
611
+ });
612
+
613
+ stateBlock[areatype[1]].areatotal += urban;
614
+
615
+ stateBlock.combined.report_header.push({
616
+ name: header,
617
+ total: combined
618
+ });
619
+
620
+ // grand totals
621
+ if (!finaldata.grandTotal[areatype[1]])
622
+ finaldata.grandTotal[areatype[1]] = {};
623
+
624
+ if (!finaldata.grandTotal[areatype[1]][header])
625
+ finaldata.grandTotal[areatype[1]][header] = { total: 0 };
626
+
627
+ finaldata.grandTotal[areatype[1]][header].total += urban;
628
+
629
+ if (!finaldata.grandTotal.combined)
630
+ finaldata.grandTotal.combined = {};
631
+
632
+ if (!finaldata.grandTotal.combined[header])
633
+ finaldata.grandTotal.combined[header] = { total: 0 };
634
+
635
+ finaldata.grandTotal.combined[header].total += combined;
636
+
637
+ finaldata.grandTotal.finaltotal += urban;
638
+ }
639
+ } else {
640
+ // NO URBAN → combined = rural
641
+ stateBlock[areatype[1]] = { report_header: [], areatotal: 0 };
642
+ stateBlock.combined = { report_header: [] };
643
+
644
+ for (let header of tableheaders) {
645
+ let rural =
646
+ stateBlock[areatype[0]].report_header.find(h => h.name === header)?.total || 0;
647
+
648
+ stateBlock[areatype[1]].report_header.push({ name: header, total: 0 });
649
+
650
+ stateBlock.combined.report_header.push({
651
+ name: header,
652
+ total: rural
653
+ });
654
+ }
655
+ }
656
+ }
657
+ }
658
+
659
+ // -----------------------------
660
+ // THIRD PASS → TABLE WISE DATA
661
+ // -----------------------------
662
+ if (tablewiseChartData && tablewiseChartData.length > 0) {
663
+ let tableHeadersObj = {};
664
+
665
+ tablewiseChartData.forEach(row => {
666
+ tableHeadersObj[row.report_order] = row.report_header;
667
+ });
668
+
669
+ let tHeaders = Object.values(
670
+ Object.keys(tableHeadersObj)
671
+ .sort((a, b) => a - b)
672
+ .map(key => tableHeadersObj[key])
673
+ );
674
+
675
+ for (let row of tablewiseChartData) {
676
+ if (!tHeaders.includes(row.report_header)) continue;
677
+
678
+ const state = row.state;
679
+ const tableName = row.tableName;
680
+
681
+ if (!finaldata.tabledata) finaldata.tabledata = {};
682
+ if (!finaldata.tabledata[state]) finaldata.tabledata[state] = {};
683
+ if (!finaldata.tabledata[state][tableName])
684
+ finaldata.tabledata[state][tableName] = { report_header: [] };
685
+
686
+ finaldata.tabledata[state][tableName].report_header.push({
687
+ name: row.report_header,
688
+ total: row.total
689
+ });
690
+ }
691
+ }
692
+
693
+ return finaldata;
694
+ }
695
+
696
+ async function processCentralChartData(chartData, tablewiseChartData = null, tableheaders, reportHeader, areatype) {
697
+ const output = {
698
+ State: {},
699
+ grandTotal: {
700
+ rural: {},
701
+ urban: {},
702
+ combined: {},
703
+ finaltotal: 0
704
+ },
705
+ tabledata: {}
706
+ };
707
+
708
+ const AREAS = ["rural", "urban"];
709
+ const toNumber = v => Number(v || 0);
710
+
711
+ // ---------- INIT GRAND TOTAL ----------
712
+ for (const area of AREAS) {
713
+ output.grandTotal[area] = { areatotal: 0 };
714
+ for (const h of tableheaders) {
715
+ output.grandTotal[area][h] = { total: 0 };
716
+ }
717
+ }
718
+
719
+ output.grandTotal.combined = {};
720
+ for (const h of tableheaders) {
721
+ output.grandTotal.combined[h] = { total: 0 };
722
+ }
723
+
724
+ // ---------- GROUP RAW DATA ----------
725
+ for (const row of chartData) {
726
+ const { state, area_type, report_header } = row;
727
+ const total = toNumber(row.total);
728
+
729
+ if (!output.State[state]) {
730
+ output.State[state] = {
731
+ State: state,
732
+ rural: { report_header: [], areatotal: 0 },
733
+ urban: { report_header: [], areatotal: 0 },
734
+ combined: { report_header: [] },
735
+ grandTotal: 0
736
+ };
737
+ }
738
+
739
+ const stateObj = output.State[state];
740
+ stateObj[area_type][report_header] =
741
+ (stateObj[area_type][report_header] || 0) + total;
742
+ }
743
+
744
+ // ---------- NORMALIZE HEADERS + TOTALS ----------
745
+ for (const state in output.State) {
746
+ const stateObj = output.State[state];
747
+
748
+ for (const area of AREAS) {
749
+ for (const h of tableheaders) {
750
+ const val = toNumber(stateObj[area][h]);
751
+
752
+ stateObj[area].report_header.push({
753
+ name: h,
754
+ total: String(val)
755
+ });
756
+
757
+ stateObj[area].areatotal += val;
758
+ output.grandTotal[area][h].total += val;
759
+ output.grandTotal[area].areatotal += val;
760
+ output.grandTotal.finaltotal += val;
761
+ }
762
+ }
763
+
764
+ // ---------- COMBINED ----------
765
+ for (const h of tableheaders) {
766
+ const ruralVal = toNumber(
767
+ stateObj.rural.report_header.find(x => x.name === h)?.total
768
+ );
769
+ const urbanVal = toNumber(
770
+ stateObj.urban.report_header.find(x => x.name === h)?.total
771
+ );
772
+
773
+ const combined = ruralVal + urbanVal;
774
+
775
+ stateObj.combined.report_header.push({
776
+ name: h,
777
+ total: combined
778
+ });
779
+
780
+ output.grandTotal.combined[h].total += combined;
781
+ stateObj.grandTotal += combined;
782
+ }
783
+ }
784
+
785
+ // ---------- TABLEDATA (SAFE DEFAULT) ----------
786
+ for (const row of tablewiseChartData) {
787
+ const { State, tableName, report_header, total } = row;
788
+
789
+ if (!output.tabledata[State]) {
790
+ output.tabledata[State] = {};
791
+ }
792
+
793
+ if (!output.tabledata[State][tableName]) {
794
+ output.tabledata[State][tableName] = { report_header: [] };
795
+ }
796
+
797
+ output.tabledata[State][tableName].report_header.push({
798
+ name: report_header,
799
+ total: String(total)
800
+ });
801
+ }
802
+
803
+ return output;
804
+ }
805
+
806
+
807
+ module.exports = {
808
+ workersChartData,
809
+ processstatewisechart,
810
+ processChartData,
811
+ processCentralChartData,
812
+ processStateChartData
813
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "statewise-chart-processor",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Processes statewise chart data for census reports.",
5
5
  "main": "index.js",
6
6
  "keywords": ["census", "statewise", "chart", "data", "processor"],