Subversion Repositories SmartDukaan

Rev

Rev 37584 | Rev 37750 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 37584 Rev 37586
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">&rsaquo;</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">&nbsp;</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">&rsaquo;</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">&rsaquo;</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">&nbsp;</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)">&#x21B3; ' + 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">&rsaquo;</td>');
-
 
2955
          tr.push('</tr>');
-
 
2956
          html.push(tr.join(""));
2814
        });
2957
        });
2815
        tr.push('<td class="chev">&rsaquo;</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
    }