| Line 527... |
Line 527... |
| 527 |
font-size: 11.5px;
|
527 |
font-size: 11.5px;
|
| 528 |
color: var(--muted);
|
528 |
color: var(--muted);
|
| 529 |
font-weight: 600
|
529 |
font-weight: 600
|
| 530 |
}
|
530 |
}
|
| 531 |
|
531 |
|
| - |
|
532 |
/* Top-level "All RBMs" collapsed row */
|
| - |
|
533 |
#rdrrGrid tr.top-parent {
|
| - |
|
534 |
cursor: pointer;
|
| - |
|
535 |
background: linear-gradient(180deg, #eef2fb, #dfe6f5);
|
| - |
|
536 |
font-weight: 700
|
| - |
|
537 |
}
|
| - |
|
538 |
|
| - |
|
539 |
#rdrrGrid tr.top-parent:hover {
|
| - |
|
540 |
background: linear-gradient(180deg, #dfe6f5, #cfd9ee)
|
| - |
|
541 |
}
|
| - |
|
542 |
|
| - |
|
543 |
#rdrrGrid tr.top-parent td {
|
| - |
|
544 |
border-top: 2px solid var(--brand);
|
| - |
|
545 |
border-bottom: 2px solid var(--brand)
|
| - |
|
546 |
}
|
| - |
|
547 |
|
| - |
|
548 |
#rdrrGrid tr.top-parent .top-toggle {
|
| - |
|
549 |
display: inline-block;
|
| - |
|
550 |
transition: transform .15s ease;
|
| - |
|
551 |
font-weight: 800;
|
| - |
|
552 |
color: var(--brand);
|
| - |
|
553 |
margin-right: 4px;
|
| - |
|
554 |
font-size: 15px
|
| - |
|
555 |
}
|
| - |
|
556 |
|
| - |
|
557 |
#rdrrGrid tr.top-parent .cell-val {
|
| - |
|
558 |
font-weight: 800;
|
| - |
|
559 |
color: var(--brand)
|
| - |
|
560 |
}
|
| - |
|
561 |
|
| - |
|
562 |
/* Multi-warehouse collapse — RBM-level parent row */
|
| - |
|
563 |
#rdrrGrid tr.grp-parent {
|
| - |
|
564 |
cursor: pointer;
|
| - |
|
565 |
background: #fafbfe
|
| - |
|
566 |
}
|
| - |
|
567 |
|
| - |
|
568 |
#rdrrGrid tr.grp-parent:hover {
|
| - |
|
569 |
background: #eef2fb
|
| - |
|
570 |
}
|
| - |
|
571 |
|
| - |
|
572 |
#rdrrGrid tr.grp-parent .grp-toggle {
|
| - |
|
573 |
display: inline-block;
|
| - |
|
574 |
transition: transform .15s ease;
|
| - |
|
575 |
font-weight: 700;
|
| - |
|
576 |
color: var(--brand);
|
| - |
|
577 |
margin-right: 2px
|
| - |
|
578 |
}
|
| - |
|
579 |
|
| - |
|
580 |
#rdrrGrid tr.grp-child td {
|
| - |
|
581 |
background: #fdfdff
|
| - |
|
582 |
}
|
| - |
|
583 |
|
| 532 |
.cell-val {
|
584 |
.cell-val {
|
| 533 |
font-variant-numeric: tabular-nums;
|
585 |
font-variant-numeric: tabular-nums;
|
| 534 |
font-weight: 650;
|
586 |
font-weight: 650;
|
| 535 |
color: var(--ink);
|
587 |
color: var(--ink);
|
| 536 |
white-space: nowrap
|
588 |
white-space: nowrap
|
| Line 2803... |
Line 2855... |
| 2803 |
html.push('<th class="num g-' + b.key + '">' + b.label + '<br><small style="color:var(--soft);font-weight:600">ACH / TGT</small></th>');
|
2855 |
html.push('<th class="num g-' + b.key + '">' + b.label + '<br><small style="color:var(--soft);font-weight:600">ACH / TGT</small></th>');
|
| 2804 |
html.push('<th class="num g-' + b.key + '">%</th>');
|
2856 |
html.push('<th class="num g-' + b.key + '">%</th>');
|
| 2805 |
});
|
2857 |
});
|
| 2806 |
html.push('<th></th></tr></thead><tbody>');
|
2858 |
html.push('<th></th></tr></thead><tbody>');
|
| 2807 |
|
2859 |
|
| - |
|
2860 |
// Two-level collapse:
|
| - |
|
2861 |
// Level 1 — one "All RBMs (N)" row at the top, shows the grand-total.
|
| - |
|
2862 |
// Click → reveal per-RBM rows below.
|
| - |
|
2863 |
// Level 2 — per-RBM rows. Single-warehouse RBMs are directly clickable
|
| - |
|
2864 |
// (→ drill-down). Multi-warehouse RBMs collapse into a
|
| - |
|
2865 |
// group-parent showing summed totals; click → reveal
|
| - |
|
2866 |
// per-warehouse child rows.
|
| - |
|
2867 |
// Level 3 — per-warehouse rows (only under multi-warehouse RBMs).
|
| - |
|
2868 |
// Click → drill-down for that RBM × warehouse.
|
| - |
|
2869 |
// Default state on render: only the "All RBMs" row visible.
|
| - |
|
2870 |
var topRow = ['<tr class="top-parent">'];
|
| - |
|
2871 |
topRow.push('<td><div class="rbm-cell">' +
|
| - |
|
2872 |
'<span class="rn">' +
|
| - |
|
2873 |
'<span class="top-toggle">›</span> All RBMs' +
|
| - |
|
2874 |
'</span>' +
|
| - |
|
2875 |
'<span class="wh">' + rows.length + ' rows (click to expand)</span>' +
|
| - |
|
2876 |
'</div></td>');
|
| - |
|
2877 |
topRow.push(cellPair(t.totalAch, t.totalTgt));
|
| - |
|
2878 |
buckets.forEach(function (b) {
|
| - |
|
2879 |
topRow.push(cellPair(t[b.key + "Ach"], t[b.key + "Tgt"]));
|
| - |
|
2880 |
});
|
| - |
|
2881 |
topRow.push('<td class="chev"> </td>');
|
| - |
|
2882 |
topRow.push('</tr>');
|
| - |
|
2883 |
html.push(topRow.join(""));
|
| - |
|
2884 |
|
| - |
|
2885 |
// Group rows per person (authId).
|
| - |
|
2886 |
var groups = new Map();
|
| - |
|
2887 |
var groupOrder = [];
|
| 2808 |
rows.forEach(function (r) {
|
2888 |
rows.forEach(function (r) {
|
| - |
|
2889 |
var key = String(r.authId);
|
| - |
|
2890 |
if (!groups.has(key)) {
|
| - |
|
2891 |
groups.set(key, {authId: r.authId, name: r.rbmName, children: []});
|
| - |
|
2892 |
groupOrder.push(key);
|
| - |
|
2893 |
}
|
| - |
|
2894 |
groups.get(key).children.push(r);
|
| - |
|
2895 |
});
|
| - |
|
2896 |
|
| - |
|
2897 |
var groupCounter = 0;
|
| - |
|
2898 |
groupOrder.forEach(function (key) {
|
| - |
|
2899 |
var g = groups.get(key);
|
| - |
|
2900 |
if (g.children.length === 1) {
|
| - |
|
2901 |
// Single-warehouse person → RBM-tier row, directly clickable for drill-down.
|
| - |
|
2902 |
var r = g.children[0];
|
| 2809 |
var tr = ['<tr class="clickable" data-authid="' + r.authId + '" data-warehouseid="' + r.warehouseId + '" data-rbmname="' + escapeHtml(r.rbmName) + '" data-warehousename="' + escapeHtml(r.warehouseName) + '">'];
|
2903 |
var tr = ['<tr class="clickable tier-rbm" style="display:none" data-authid="' + r.authId + '" data-warehouseid="' + r.warehouseId + '" data-rbmname="' + escapeHtml(r.rbmName) + '" data-warehousename="' + escapeHtml(r.warehouseName) + '">'];
|
| 2810 |
tr.push('<td><div class="rbm-cell"><span class="rn">' + escapeHtml(r.rbmName) + '</span><span class="wh">' + escapeHtml(r.warehouseName) + '</span></div></td>');
|
2904 |
tr.push('<td><div class="rbm-cell"><span class="rn">' + escapeHtml(r.rbmName) + '</span><span class="wh">' + escapeHtml(r.warehouseName) + '</span></div></td>');
|
| 2811 |
tr.push(cellPair(r.totalAch, r.totalTgt));
|
2905 |
tr.push(cellPair(r.totalAch, r.totalTgt));
|
| - |
|
2906 |
buckets.forEach(function (b) {
|
| - |
|
2907 |
tr.push(cellPair(r[b.key + "Ach"], r[b.key + "Tgt"]));
|
| - |
|
2908 |
});
|
| - |
|
2909 |
tr.push('<td class="chev">›</td>');
|
| - |
|
2910 |
tr.push('</tr>');
|
| - |
|
2911 |
html.push(tr.join(""));
|
| - |
|
2912 |
return;
|
| - |
|
2913 |
}
|
| - |
|
2914 |
|
| - |
|
2915 |
// Multi-warehouse person → RBM-tier collapsed parent + hidden per-warehouse children.
|
| - |
|
2916 |
var gid = "g" + (groupCounter++);
|
| - |
|
2917 |
var sum = {totalAch: 0, totalTgt: 0};
|
| 2812 |
buckets.forEach(function (b) {
|
2918 |
buckets.forEach(function (b) {
|
| - |
|
2919 |
sum[b.key + "Ach"] = 0;
|
| - |
|
2920 |
sum[b.key + "Tgt"] = 0;
|
| - |
|
2921 |
});
|
| - |
|
2922 |
g.children.forEach(function (r) {
|
| - |
|
2923 |
sum.totalAch += Number(r.totalAch) || 0;
|
| - |
|
2924 |
sum.totalTgt += Number(r.totalTgt) || 0;
|
| - |
|
2925 |
buckets.forEach(function (b) {
|
| - |
|
2926 |
sum[b.key + "Ach"] += Number(r[b.key + "Ach"]) || 0;
|
| - |
|
2927 |
sum[b.key + "Tgt"] += Number(r[b.key + "Tgt"]) || 0;
|
| - |
|
2928 |
});
|
| - |
|
2929 |
});
|
| - |
|
2930 |
|
| - |
|
2931 |
var parent = ['<tr class="grp-parent tier-rbm" style="display:none" data-gid="' + gid + '">'];
|
| - |
|
2932 |
parent.push('<td><div class="rbm-cell">' +
|
| - |
|
2933 |
'<span class="rn">' + escapeHtml(g.name) + '</span>' +
|
| - |
|
2934 |
'<span class="wh"><span class="grp-toggle">›</span> ' +
|
| - |
|
2935 |
g.children.length + ' warehouses (click to expand)</span>' +
|
| - |
|
2936 |
'</div></td>');
|
| - |
|
2937 |
parent.push(cellPair(sum.totalAch, sum.totalTgt));
|
| - |
|
2938 |
buckets.forEach(function (b) {
|
| - |
|
2939 |
parent.push(cellPair(sum[b.key + "Ach"], sum[b.key + "Tgt"]));
|
| - |
|
2940 |
});
|
| - |
|
2941 |
parent.push('<td class="chev"> </td>');
|
| - |
|
2942 |
parent.push('</tr>');
|
| - |
|
2943 |
html.push(parent.join(""));
|
| - |
|
2944 |
|
| - |
|
2945 |
g.children.forEach(function (r) {
|
| - |
|
2946 |
var tr = ['<tr class="clickable grp-child grp-' + gid + '" style="display:none" data-authid="' + r.authId + '" data-warehouseid="' + r.warehouseId + '" data-rbmname="' + escapeHtml(r.rbmName) + '" data-warehousename="' + escapeHtml(r.warehouseName) + '">'];
|
| - |
|
2947 |
tr.push('<td><div class="rbm-cell" style="padding-left:22px">' +
|
| - |
|
2948 |
'<span class="rn" style="font-weight:500;color:var(--soft)">↳ ' + escapeHtml(r.warehouseName) + '</span>' +
|
| - |
|
2949 |
'</div></td>');
|
| - |
|
2950 |
tr.push(cellPair(r.totalAch, r.totalTgt));
|
| - |
|
2951 |
buckets.forEach(function (b) {
|
| 2813 |
tr.push(cellPair(r[b.key + "Ach"], r[b.key + "Tgt"]));
|
2952 |
tr.push(cellPair(r[b.key + "Ach"], r[b.key + "Tgt"]));
|
| - |
|
2953 |
});
|
| - |
|
2954 |
tr.push('<td class="chev">›</td>');
|
| - |
|
2955 |
tr.push('</tr>');
|
| - |
|
2956 |
html.push(tr.join(""));
|
| 2814 |
});
|
2957 |
});
|
| 2815 |
tr.push('<td class="chev">›</td>');
|
- |
|
| 2816 |
tr.push('</tr>');
|
- |
|
| 2817 |
html.push(tr.join(""));
|
- |
|
| 2818 |
});
|
2958 |
});
|
| 2819 |
|
2959 |
|
| 2820 |
// totals row
|
2960 |
// totals row
|
| 2821 |
var totTr = ['<tr class="totalrow"><td><strong>Total</strong></td>'];
|
2961 |
var totTr = ['<tr class="totalrow"><td><strong>Total</strong></td>'];
|
| 2822 |
totTr.push(cellPair(t.totalAch, t.totalTgt, true));
|
2962 |
totTr.push(cellPair(t.totalAch, t.totalTgt, true));
|
| Line 2841... |
Line 2981... |
| 2841 |
$("#rdrrGrid tbody tr.clickable").on("click", function () {
|
2981 |
$("#rdrrGrid tbody tr.clickable").on("click", function () {
|
| 2842 |
var d = this.dataset;
|
2982 |
var d = this.dataset;
|
| 2843 |
var cached = $(this).data("cached");
|
2983 |
var cached = $(this).data("cached");
|
| 2844 |
openDrilldown(+d.authid, +d.warehouseid, d.rbmname, d.warehousename, cached);
|
2984 |
openDrilldown(+d.authid, +d.warehouseid, d.rbmname, d.warehousename, cached);
|
| 2845 |
});
|
2985 |
});
|
| - |
|
2986 |
|
| - |
|
2987 |
// Toggle collapsed groups: click parent row → show/hide the per-warehouse child rows.
|
| - |
|
2988 |
// Variable names deliberately avoid leading '$' — Velocity would try to parse them.
|
| - |
|
2989 |
$("#rdrrGrid tbody tr.grp-parent").on("click", function () {
|
| - |
|
2990 |
var gid = this.dataset.gid;
|
| - |
|
2991 |
var childRows = $("#rdrrGrid tbody tr.grp-" + gid);
|
| - |
|
2992 |
var isOpen = childRows.filter(":visible").length > 0;
|
| - |
|
2993 |
childRows.toggle(isOpen ? false : true);
|
| - |
|
2994 |
var toggleEl = $(this).find(".grp-toggle");
|
| - |
|
2995 |
toggleEl.css("transform", isOpen ? "rotate(0deg)" : "rotate(90deg)");
|
| - |
|
2996 |
toggleEl.css("display", "inline-block");
|
| - |
|
2997 |
});
|
| - |
|
2998 |
|
| - |
|
2999 |
// Top-level "All RBMs" collapse: click → show/hide every RBM-tier row.
|
| - |
|
3000 |
// When collapsing, also force-hide any expanded warehouse child rows.
|
| - |
|
3001 |
$("#rdrrGrid tbody tr.top-parent").on("click", function () {
|
| - |
|
3002 |
var rbmRows = $("#rdrrGrid tbody tr.tier-rbm");
|
| - |
|
3003 |
var isOpen = rbmRows.filter(":visible").length > 0;
|
| - |
|
3004 |
rbmRows.toggle(isOpen ? false : true);
|
| - |
|
3005 |
if (isOpen) {
|
| - |
|
3006 |
// Collapsing → also hide any expanded warehouse children + reset their chevrons.
|
| - |
|
3007 |
$("#rdrrGrid tbody tr.grp-child").hide();
|
| - |
|
3008 |
$("#rdrrGrid tbody tr.grp-parent .grp-toggle").css("transform", "rotate(0deg)");
|
| - |
|
3009 |
}
|
| - |
|
3010 |
var topToggle = $(this).find(".top-toggle");
|
| - |
|
3011 |
topToggle.css("transform", isOpen ? "rotate(0deg)" : "rotate(90deg)");
|
| - |
|
3012 |
topToggle.css("display", "inline-block");
|
| - |
|
3013 |
});
|
| 2846 |
}
|
3014 |
}
|
| 2847 |
|
3015 |
|
| 2848 |
function cellPair(ach, tgt, isTotal) {
|
3016 |
function cellPair(ach, tgt, isTotal) {
|
| 2849 |
var p = pctLabel(ach, tgt);
|
3017 |
var p = pctLabel(ach, tgt);
|
| 2850 |
var vhtml = '<td class="num"><div class="cell-val">' + fmtLakh(ach) + ' <small>/ ' + fmtLakh(tgt) + '</small></div></td>';
|
3018 |
var vhtml = '<td class="num"><div class="cell-val">' + fmtLakh(ach) + ' <small>/ ' + fmtLakh(tgt) + '</small></div></td>';
|
| Line 2897... |
Line 3065... |
| 2897 |
// Map buying values by status for O(1) lookup.
|
3065 |
// Map buying values by status for O(1) lookup.
|
| 2898 |
var buyMap = {};
|
3066 |
var buyMap = {};
|
| 2899 |
buying.forEach(function (b) {
|
3067 |
buying.forEach(function (b) {
|
| 2900 |
buyMap[b.status] = Number(b.value) || 0;
|
3068 |
buyMap[b.status] = Number(b.value) || 0;
|
| 2901 |
});
|
3069 |
});
|
| - |
|
3070 |
// TEMP-DISABLED: opening-balance addition. Re-enable alongside the
|
| - |
|
3071 |
// controller block. Uncomment these two lines and swap the "Coverage"
|
| - |
|
3072 |
// computation below to (sell / (open + buy)).
|
| - |
|
3073 |
// var opening = (data && data.opening) || [];
|
| - |
|
3074 |
// var openMap = {}; opening.forEach(function (o) { openMap[o.status] = Number(o.value) || 0; });
|
| 2902 |
var labels = {HID: "HID", FASTMOVING: "FAST", RUNNING: "RUN", SLOWMOVING: "SLOW", OTHER: "OTHER"};
|
3075 |
var labels = {HID: "HID", FASTMOVING: "FAST", RUNNING: "RUN", SLOWMOVING: "SLOW", OTHER: "OTHER"};
|
| 2903 |
var order = ["HID", "FASTMOVING", "RUNNING", "SLOWMOVING", "OTHER"];
|
3076 |
var order = ["HID", "FASTMOVING", "RUNNING", "SLOWMOVING", "OTHER"];
|
| 2904 |
// Selling per bucket from the cached grid row (already has ACH per bucket).
|
3077 |
// Selling per bucket from the cached grid row (already has ACH per bucket).
|
| 2905 |
var sellMap = {
|
3078 |
var sellMap = {
|
| 2906 |
HID: row ? Number(row.hidAch) || 0 : 0,
|
3079 |
HID: row ? Number(row.hidAch) || 0 : 0,
|
| Line 3281... |
Line 3454... |
| 3281 |
if (v > max) max = v;
|
3454 |
if (v > max) max = v;
|
| 3282 |
});
|
3455 |
});
|
| 3283 |
brandMax[b.name] = max;
|
3456 |
brandMax[b.name] = max;
|
| 3284 |
});
|
3457 |
});
|
| 3285 |
|
3458 |
|
| - |
|
3459 |
// The source fragment doesn't set a partner count on the "All RBMs" TOTAL
|
| - |
|
3460 |
// cell (grandTotal in MonitorController.getTodayPoTableFragment only sums
|
| - |
|
3461 |
// billed/PO/POBilled, not partiesBilled). Fill it in client-side by
|
| - |
|
3462 |
// summing each RBM's own TOTAL partner count — that column is the
|
| - |
|
3463 |
// distinct-across-brands count per RBM, so this sum is the most useful
|
| - |
|
3464 |
// aggregate available without a new backend query. Small risk of double-
|
| - |
|
3465 |
// counting if the same partner is served by two RBMs (rare, region-based).
|
| - |
|
3466 |
if (totalRow && totalRow.cells["TOTAL"]) {
|
| - |
|
3467 |
var sumTotalPartners = 0;
|
| - |
|
3468 |
rowOrder.forEach(function (name) {
|
| - |
|
3469 |
var r = rowsMap[name];
|
| - |
|
3470 |
if (r.isTotal) return;
|
| - |
|
3471 |
sumTotalPartners += ((r.cells["TOTAL"] || {}).count || 0);
|
| - |
|
3472 |
});
|
| - |
|
3473 |
if (sumTotalPartners > 0) {
|
| - |
|
3474 |
totalRow.cells["TOTAL"].count = sumTotalPartners;
|
| - |
|
3475 |
}
|
| - |
|
3476 |
}
|
| - |
|
3477 |
|
| 3286 |
var rows = rowOrder.map(function (n) {
|
3478 |
var rows = rowOrder.map(function (n) {
|
| 3287 |
return rowsMap[n];
|
3479 |
return rowsMap[n];
|
| 3288 |
});
|
3480 |
});
|
| 3289 |
return {brands: brandOrder, rows: rows, brandMax: brandMax};
|
3481 |
return {brands: brandOrder, rows: rows, brandMax: brandMax};
|
| 3290 |
}
|
3482 |
}
|