statewise-chart-processor 1.0.0 → 1.0.1

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