Rev 34898 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
<meta charset="UTF-8"><link id="modal-bootstrap-css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"rel="stylesheet"/><style>.chart-wrapper {overflow: hidden;transition: all 0.3s ease;}.chart-content {display: flex;flex-wrap: nowrap;gap: 20px;align-items: flex-start;}.chart-container {flex: 0 0 550px;height: 320px;}.partner-income-container {flex: 1 1 auto;min-width: 300px;}.legend {background: #f8f9fa;padding: 15px;border-radius: 8px;margin-bottom: 30px;}.status-badge {display: inline-block;padding: 6px 12px;border-radius: 20px;font-size: 12px;font-weight: 600;text-transform: uppercase;letter-spacing: 0.5px;}.status-ok {background-color: #d4edda;color: #155724;border: 1px solid #c3e6cb;}.status-not-ok {background-color: #f8d7da;color: #721c24;border: 1px solid #f5c6cb;}.brand-card {background: white;border: 1px solid #e9ecef;border-radius: 12px;padding: 20px;margin-bottom: 15px;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);transition: transform 0.2s ease, box-shadow 0.2s ease;}.brand-card:hover {transform: translateY(-2px);box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);}.brand-name {font-size: 1.5rem;font-weight: 700;margin-bottom: 15px;color: #2c3e50;}.quantity-row {display: flex;justify-content: space-between;align-items: center;padding: 8px 0;border-bottom: 1px solid #f1f3f4;}.quantity-row:last-child {border-bottom: none;}.quantity-label {font-weight: 500;color: #6c757d;}.quantity-value {font-weight: 600;color: #2c3e50;}.left-panel {background: #f8f9fa;border-radius: 8px;padding: 20px;}.right-panel {background: white;border-radius: 8px;padding: 20px;border: 1px solid #e9ecef;}.chart-legend {max-height: 400px;overflow-y: auto;}.legend-item {transition: transform 0.2s ease;margin-bottom: 10px;}.legend-item:hover {transform: translateX(5px) scale(1.02); /* Scale instead of shift */z-index: 10; /* Bring hovered items to front */}.legend-color {width: 20px;height: 20px;border-radius: 6px;margin-right: 12px;flex-shrink: 0;}.legend-brand {font-weight: 750;color: #2d3748;font-size: 14px;}.legend-percentage {font-weight: 700;font-size: 14px;color: #4a5568;}@keyframes shimmer {0% {left: -100%;}100% {left: 100%;}}.brand-card {transition: all 0.2s ease;border: 1px solid #e9ecef;}.brand-card:hover {box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);transform: translateY(-1px);}.brand-logo {width: 80px;height: 80px;object-fit: contain;border-radius: 12px;background-color: #f8f9fa;padding: 2px;}.brand-name {font-size: 13px;font-weight: 700;color: #212529;margin-bottom: 8px;}.status-badge {font-size: 12px;font-weight: 600;padding: 8px 16px;border-radius: 25px;border: none;}.legend {background-color: #f8f9fa;border-radius: 8px;padding: 12px;margin-bottom: 24px;}.modal-backdrop.in {filter: alpha(opacity=50);opacity: 0.35;width: auto;height: auto;}.brandText {transform: rotate(270deg) !important;}.rounded-corner {border-top-left-radius: 30px !important;border-top-right-radius: 30px !important;}.bg-danger {background-color: #D3181F !important;}.fs-8 {font-size: 25px !important;}.table-bordered th {border: 1px solid rgba(255, 255, 255, 0.2);}.table-bordered td {border: 1px solid #dee2e6;vertical-align: middle;}.fs-5 {font-size: 1.2rem !important;}.brand-btn {transition: all 0.3s ease;font-weight: normal;border-radius: 25px;padding: 4px 10px;margin: 5px;border: 2px solid #666;}.brand-logo {height: 40px;object-fit: contain;}.curve {padding-left: 100px !important;border-radius: 40px 0 0 40px !important;width: 250px !important;}.stock-ribbon {position: relative;padding: 5px 15px;color: white;clip-path: polygon(0 0, 100% 0, 95% 100%, 0 100%);min-width: 220px;}.mandatory-ribbon {background-color: #D3181F !important;}.other-ribbon {background-color: #000;}.brand-item {display: flex;align-items: center;margin-bottom: 20px;}.category-header {font-size: 15px;font-weight: bold;margin: 20px 0;padding-left: 15px;}.mandatory-header {color: #d32f2f;}.other-header {color: #333;}.bg-orange {background-color: #FF6700 !important;color: white;}.bg-cryan {background-color: #004d51 !important;color: white;}.bg-dark-light {background-color: #3e3e3e !important;color: white;}.table-bordered td, .table-bordered th {border: 1px solid #dee2e6;}.brand-circle {width: 60px;height: 60px;object-fit: cover;border: 5px solid rgb(122, 116, 116);}.currency::before {content: "\20B9";}.table thead th {font-weight: 600;letter-spacing: 0.5px;}.table tbody td {font-weight: normal;}.fs-3, .fs-5 {font-weight: normal;}/* Only make specific elements bold when needed */.fw-bold {font-weight: bold !important;}.btn {font-weight: normal;}.payment-circle {width: 200px;height: 200px;border: 25px solid #e0dcdc;border-radius: 50%;display: flex;align-items: center;justify-content: center;transition: transform 0.3s ease;}.payment-content {text-align: center;color: white;padding: 20px;}.payment-amount {font-size: 18px;font-weight: 700;margin-bottom: 10px;text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);}.payment-label {font-size: 18px;line-height: 1.3;text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);}.table-border td {border: 1px solid black !important;}.table-border thead {border: 1px solid black;}.p-0 {padding: 0 !important;}</style><body style="background-color: rgb(247, 247, 247);zoom: 100%!important;"><div style="overflow-y:auto;max-height: 120vh; "><section id="ajaxSection" class="rounded"style="max-height: 120vh; overflow-y: auto;"><!-- Header Section --><div class="w-full bg-danger h-25 py-3 mb-4"><h1 class="text-center text-white " style="font-size: 30px !important; font-weight: 800">PendingTasks</h1></div><div class="container">##-----------------------------------------------GRN Pending -----------------------------------------------------<div class="container-fluid p-4">#if($grnPendingOrders.entrySet().size()>0)<!-- Section Header --><div class="row justify-content-center"><div class="col-10"><div class="bg-dark-light rounded-3 p-3 shadow rounded-corner"><h1 class="text-white text-center mb-0 fw-bold py-2 fs-8">GRN Pending</h1></div></div></div><!-- Responsive Table --><div class="table-responsive rounded-3 shadow p-5"><table id="grnTable" class="table table-bordered mb-0 table-border" style="width:100%"><!-- MANDATORY BRANDS SECTION --><thead><tr class="bg-danger text-white"><th class="ps-4 fs-5 fw-bold text-uppercase bg-danger text-white text-center"style="padding: 10px !important;">BRANDS</th><th class="fs-5 fw-bold text-uppercase bg-danger text-white text-center"style="padding: 10px !important;">QUANTITY</th><th class="pe-4 fs-5 fw-bold text-uppercase bg-danger text-white text-center"style="padding: 10px !important;">VALUE</th></tr></thead><tbody>## Define mandatory brands#set($mandatoryBrands = ["Vivo", "Oppo", "Samsung", "Realme"])## Process mandatory brands first#foreach($entry in $grnPendingOrders.entrySet())#set($brand = $entry.key)#set($details = $entry.value)## #if($mandatoryBrands.contains($brand))<tr class=""><td class="ps-4 text-center p-0"><div class="d-flex align-items-center justify-content-center"><div class="row align-items-center" style="width: 200px;"><div class="col-auto"><img src="$brandLogos.getOrDefault($brand,'https://static.vecteezy.com/system/resources/thumbnails/025/213/042/small_2x/mobile-phone-icon-in-black-circle-png.png')"alt="$brand logo"class="brand-logo rounded-circle"style="width:35px;height:35px"></div><div class="col text-start"><span class="fw-bold fs-5">$brand</span></div></div></div></td><td class="text-center align-middle fs-5 fw-semibold p-0">$details.quantity</td><td class="pe-4 text-center align-middle fs-5 fw-semibold currency p-0 ">$nf.format($details.mrp)</td></tr>#end## #end</tbody>####</table></div>#end</div>##-----------------------------------------------Unbilled Activated -----------------------------------------------------<div class="container-fluid p-4">#if($unbilledActivated.entrySet().size()>0)<!-- Section Header --><div class="row justify-content-center"><div class="col-10"><div class="bg-dark-light rounded-3 p-3 shadow rounded-corner"><h1 class="text-white text-center mb-0 py-2 fw-bold fs-8">Pending Billing</h1></div></div></div><!-- Responsive Table --><div class="table-responsive rounded-3 shadow p-5"><table id="unbilledTable" class="table table-bordered mb-0 table-border" style="width:100%"><!-- MANDATORY BRANDS SECTION --><thead><tr class="bg-danger text-white"><th class="ps-4 fs-5 fw-bold text-uppercase bg-danger text-white text-center p-0"style="padding: 10px !important;">BRANDS</th><th class="fs-5 fw-bold text-uppercase bg-danger text-white text-center p-0"style="padding: 10px !important;">QUANTITY</th><th class="pe-4 fs-5 fw-bold text-uppercase bg-danger text-white text-center p-0"style="padding: 10px !important;">VALUE</th></tr></thead><tbody>## Define mandatory brands#set($mandatoryBrands = ["Vivo", "Realme", "Oppo", "Samsung"])## Process mandatory brands first#foreach($entry in $unbilledActivated.entrySet())#set($brand = $entry.key)#set($details = $entry.value)## #if($mandatoryBrands.contains($brand))<tr><td class="ps-4 text-center p-0"><div class="d-flex align-items-center justify-content-center"><div class="row align-items-center" style="width: 200px;"><div class="col-auto"><img src="$brandLogos.getOrDefault($brand,'https://static.vecteezy.com/system/resources/thumbnails/025/213/042/small_2x/mobile-phone-icon-in-black-circle-png.png')"alt="$brand logo"class="brand-logo rounded-circle"style="width:35px;height:35px"></div><div class="col text-start"><span class="fw-bold fs-5">$brand</span></div></div></div></td><td class="text-center align-middle fs-5 fw-semibold p-0">$details.quantity</td><td class="pe-4 text-center align-middle p-0 currency fw-semibold fs-5">$nf.format( $details.mtd)</td></tr>#end</tbody></table></div>#end</div>##-----------------------------------------------Loan Amount -----------------------------------------------------<div class="container-fluid p-4"><!-- Section Header --><div class="row mb-5 justify-content-center"><div class="col-10"><div class="bg-dark-light rounded-3 p-3 shadow rounded-corner"><h1 class="text-white text-center mb-0 fw-bold py-2 fs-8">Loan </h1></div></div></div><div class="row justify-content-center"><!-- Default Payment --><div class="col-12 col-md-4 text-center "><div class="payment-circle shadow-lg shadow-dark mx-auto "style="background-color: #cc0000 !important;"><div class="payment-content"><div class="payment-amount currency"> $nf.format( $totalDefaultAmount) </div></div></div><h1 class="payment-label fw-bold mt-4" style="font-weight: 400 !important;">Default Payment<br>(Above30 days)</h1></div><!-- Due Payment --><div class="col-12 col-md-4 text-center"><div class="payment-circle shadow-lg mx-auto" style="background-color: #FF9433 !important;"><div class="payment-content"><div class="payment-amount currency"> $nf.format($totalOverdueAmount) </div></div></div><h1 class="payment-label fw-bold mt-4"style="font-size: 20px !important; font-weight: 400 !important;">Due Payment<br>(Above 15Days)</h1></div><!-- Other Payment --><div class="col-12 col-md-4 text-center"><div class="payment-circle shadow-lg mx-auto " style="background-color: #00B050 !important;"><div class="payment-content"><div class="payment-amount currency"> $nf.format($totalDueAmount) </div></div></div><h1 class="payment-label fw-bold mt-4"style="font-size: 20px !important; font-weight: 400 !important;">Other Loan<br>(Within 15Days)</h1></div><!-- Total Loan Value --><div class="mt-4 mx-5 " style="margin-top: 6rem !important;"><h1 class="text-center " style="font-size:30px !important;font-weight:300 !important;">TotalLoan Value :<span class="currency fw-bold"> $nf.format( $totalLoan )</span></h1></div></div></div></div>## Add this chart section after the loan circles<div class="w-full bg-danger h-25 py-3 my-4"><h1 class="text-center text-white fw-bold" style="font-size: 30px !important; font-weight: 800">My BusinessAnalysis</h1></div><div class="container-fluid p-5 mt-5"><!-- Chart Section Header --><div class="row mb-1 my-4 mx-3 justify-content-center"><div class="col-10"><div class="bg-dark-light rounded-3 p-3 shadow rounded-corner"><h1 class="text-white text-center mb-0 fw-bold py-2 fs-8">My Earning </h1></div></div></div><!-- Chart Container --><div class="container mt-4"><div class="chart-wrapper card shadow-lg rounded-5 p-2"><span class="text-danger fs-3 fw-bold text-end">** Click on the bar to see the details</span><div class="chart-content "><div class="chart-container"><canvas id="sixMonthChart"></canvas></div><div id="partner-income" class="partner-income-container"></div></div></div></div></div>## ----------------------------------------anyalysis---------------------------=//#set($marketShareData = [{"Brand": "Vivo", "MarketShare": "20%", "Quarter": "Q1 2025", "BgColor": "#2196F3", "Rank": "1"},{"Brand": "Samsung", "MarketShare": "18%", "Quarter": "Q1 2025", "BgColor": "#1428A0", "Rank": "2"},{"Brand": "Xiaomi", "MarketShare": "13%", "Quarter": "Q1 2025", "BgColor": "#FF6900", "Rank": "3"},{"Brand": "OPPO", "MarketShare": "12%", "Quarter": "Q1 2025", "BgColor": "#006B33", "Rank": "4"},{"Brand": "realme", "MarketShare": "11%", "Quarter": "Q1 2025", "BgColor": "#FFC915", "Rank": "5"},{"Brand": "Others", "MarketShare": "26%", "Quarter": "Q1 2025", "BgColor": "#6b7280", "Rank": "-"}])<div class="container-fluid p-5"><!-- Chart Section Header --><div class="row mb-1 my-4 mx-3 justify-content-center"><div class="col-10"><div class="bg-dark-light rounded-3 p-3 shadow rounded-corner"><h1 class="text-white text-center mb-0 fw-bold py-2 fs-8">Brand Analysis </h1></div></div></div>## ----------------------------------------stagged chart ------------------------------------------<div class="container d-flex "><div class="p-5" style=" height: 350px !important;width: 650px !important;"><div class="chart-title fs-2 text-center fw-bold">Brands Share Analysis (QTY)</div><canvas id="combinedStackedChart"></canvas></div><div class="" style="width: 400px!important;"><div class="right-panel"><h4 class="mb-4">Quantity Analysis</h4><div class="brand-analysis-container"><div class="table-responsive"><table class="table table-striped table-hover"><thead class="table-light table-bordered"><tr><th scope="col">Brand Name</th><th scope="col">Available Models</th><th scope="col">Required Models</th><th scope="col" class="text-center">Status</th></tr></thead><tbody class="table-bordered">#foreach($brandName in $targetBrands)#set($analysis = $brandAnalysisData.get($brandName))<tr><td><strong class="brand-name">${brandName}</strong></td><td><span class="quantity-value">${analysis.get('availableQuantity')}</span></td><td><span class="quantity-value">${analysis.get('requiredQuantity')}</span></td><td class="text-center"><span class="badge #if($analysis.get('isOK'))bg-success#else bg-danger#end">${analysis.get('status')}</span></td></tr>#end</tbody></table></div></div></div></div></div>## -----------------------------------------------Fast Selling & HID model ------------------------------------------------<div class="container-fluid py-3"><div class="card mb-4 p-5 "><div class="row justify-content-center "><div class="col-10"><div class="bg-dark-light rounded-3 p-3 shadow rounded-corner"><h3 class="text-white text-center mb-0 fw-bold py-2 fs-8">Fast Selling Models &HID </h3></div></div></div><div class="card-body card shadow-lg rounded-5 p-3"><!-- Dynamic Brand Filters --><div class="d-flex flex-wrap justify-content-center gap-2 p-1 border-bottom fs-5">#foreach($brand in $brands)<button class="brand-btn" data-brand="$brand.toLowerCase()">$brand</button>#end</div><div class="card-header text-center fw-bold "><h4>HID</h4></div><!-- Table Header --><div class="row mx-0 mt-4"><div class="col-3 text-center"><div class="p-1 py-3 rounded-top" style="background: #555; color: white;"><strong class="fs-4 fw-bold">Model </strong></div></div><div class="col-3 text-center"><div class="p-1 py-3 rounded-top" style="background: #d82c2c; color: white;"><strong class="fs-4 fw-bold">Suggested Qty</strong></div></div><div class="col-3 text-center"><div class="p-1 py-3 rounded-top" style="background: #555; color: white;"><strong class="fw-bold" style="font-size: 1.3rem !important;">My Stock + PendingIndent</strong></div></div><div class="col-3 text-center"><div class="p-1 py-3 rounded-top" style="background: #d82c2c; color: white;"><strong class="fs-4 fw-bold">Remarks</strong></div></div></div><!-- Data Rows -->#foreach($brand in $brands)#if($hidAllocationModelBrandMap.containsKey($brand) && !$hidAllocationModelBrandMap.get($brand).isEmpty())#foreach($model in $hidAllocationModelBrandMap.get($brand))<div class="brand-data" data-brand="$brand.toLowerCase()"><div class="row mx-0"><div class="col-3 text-center"><div class="p-4 border border-light fs-5 trim"style="background: #444; color: white;">$model.getModelNumber()</div></div><div class="col-3 text-center"><div class="p-4 border border-light fs-5"style="background: #b30606; color: white;">$model.getHidAllocation()</div></div><div class="col-3 text-center"><div class="p-4 border border-light fs-5"style="background: #444; color: white;"><strong>$model.getAvailableStock()</strong></div></div><div class="col-3 text-center"><div class="p-4 border border-light fs-5"style="background: #b30606; color: white;"><strong>#if($model.getAvailableStock() == 0)<span class="fw-bold p-4 w-full text-warning">Urgently Required</span>#elseif($model.getAvailableStock() < $model.getHidAllocation())<span class="fw-bold p-4 text-info ">Need to Order</span>#else<span class=" fw-bold p-4 text-success"style="color: rgb(61 251 163) !important;">Stock OK</span>#end</strong></div></div></div></div>#end#else<div class="brand-data" data-brand="$brand.toLowerCase()"><div class="row mx-0"><div class="col-12 text-center p-4 fs-5" style="background: #f8f9fa;">No Data Available</div></div></div>#end#end## -----------------------------------Fast Selling Modal-------------------------------<div class="card-header text-center fw-bold "><h4> Fast Selling Model</h4></div>#if($brandwiseFastmoving && $brandwiseFastmoving.entrySet().size() > 0)#foreach($brandEntry in $brandwiseFastmoving.entrySet())#foreach($model in $brandEntry.value)<div class="brand-data col-12" data-brand="$brandEntry.key.toLowerCase()"><div class="row mx-0 "><div class="col-3 text-center "><div class="p-4 border border-light fs-5 text-truncate"style="background: #444; color: white;"><strong>$model.modelNumber</strong></div></div><div class="col-3 text-center "><div class="p-4 border border-light fs-5"style="background: #b30606; color: white;"><strong> #set($suggestedQty = 2)$suggestedQty</strong></div></div><div class="col-3 text-center "><div class="p-4 border border-light fs-5 "style="background: #444; color: white;"><strong> $model.partnerCurrentQty#if($processingOrderCatalogQtyMap.get($model.getCatalogId()))+ $processingOrderCatalogQtyMap.get($model.getCatalogId())#end</strong></div></div>#set($processingQty = $processingOrderCatalogQtyMap.get($model.getCatalogId()))#if(!$processingQty)#set($processingQty = 0)#end#set($totalQty = $model.partnerCurrentQty + $processingQty)<div class="col-3 text-center "><div class="p-4 border border-light fs-5"style="background: #b30606; color: white;"><strong>#if($totalQty == 0)<span class="fw-bold p-4 w-full text-warning">Urgently Required</span>#elseif($totalQty < 2)<span class="fw-bold p-4 text-info ">Need to Order</span>#else<span class=" fw-bold p-4 text-success"style="color: rgb(61 251 163) !important;">Stock OK</span>#end</strong></div></div></div></div>#end#end#else<div class="brand-data"><div class="row mx-0"><div class="col-12 text-center p-4 fs-5" style="background: #f8f9fa;">No Data Available</div></div></div>#end</div></div></div>## -----------------------------------------------My Stock ------------------------------------------------<div class="row mb-1 my-4 justify-content-center"><div class="col-10"><div class=" bg-dark-light rounded-3 p-3 shadow rounded-corner"><h1 class="text-center mb-0 fw-bold py-2 text-white fs-8">My Stock</h1></div></div></div><div class="row px-5" style="margin-left: 10rem !important;"><!-- MANDATORY BRANDS COLUMN --><div class="col-md-6"><div class="category-header mandatory-header">MANDATORY BRANDS</div>#foreach($brandStockPrice in $brandStockPrices)#set($mandatoryBrands = ["Vivo", "Oppo", "Samsung", "Realme"])#if($mandatoryBrands.contains($brandStockPrice.getBrand()))<div class="brand-item"><!-- Brand Logo Circle --><div class="position-relative" style="z-index: 10"><img src="${brandStockPrice.getBrandUrl()}"class="brand-circle img-fluid rounded-circle shadow border border-danger"data-stockbrand="$brandStockPrice.getBrand()"alt="$brandStockPrice.getBrand()"></div><!-- Ribbon with Stock Info --><div class="stock-ribbon mandatory-ribbon ms-n3 position-absolute curve "><div class="d-flex d-flex mb-1"><span class="fw-bold text-start fs-5">QTY: </span><span class="fw-bold text-start fs-5">$brandStockPrice.getTotalQty()</span></div><div class="d-flex "><span class="fw-bold text-start fs-5">Value: </span><span class="currency fw-bold text-start fs-5"> $nf.format( $brandStockPrice.getTotalValue())</span></div>#if($brandStockPrice.getAgedValue() > 0)<div class="aged-stock mt-2 pt-2 border-top border-light border-opacity-25"><div class="d-flex justify-content-between"><span>Focus Stock:</span><span><span class="currency"> $nf.format($brandStockPrice.getAgedValue()) </span>/$brandStockPrice.getAgedQty()</span></div></div>#end</div></div>#end#end</div><!-- OTHER BRANDS COLUMN --><div class="col-md-6"><div class="category-header other-header">OTHER BRANDS</div>#set($mandatoryBrands = ["Vivo", "Oppo", "Samsung", "Realme"])#foreach($brandStockPrice in $brandStockPrices)#if(!$mandatoryBrands.contains($brandStockPrice.getBrand()))<div class="brand-item"><!-- Brand Logo Circle --><div class="position-relative " style="z-index: 10"><img src="${brandStockPrice.getBrandUrl()}"class="brand-circle img-fluid rounded-circle shadow border border-dark"data-stockbrand="$brandStockPrice.getBrand()"alt="$brandStockPrice.getBrand()"></div><!-- Ribbon with Stock Info --><div class="stock-ribbon other-ribbon ms-n3 position-absolute curve"><div class="d-flex d-flex mb-1"><span class="fw-bold text-start fs-5">QTY: </span><span class="fw-bold text-start fs-5">$brandStockPrice.getTotalQty()</span></div><div class="d-flex "><span class="fw-bold text-start fs-5">Value: </span><span class="currency fw-bold text-start fs-5"> $nf.format($brandStockPrice.getTotalValue())</span></div>#if($brandStockPrice.getAgedValue() > 0)<div class="aged-stock mt-2 pt-2 border-top border-light border-opacity-25"><div class="d-flex justify-content-between"><span>Focus Stock:</span><span><span class="currency"> $nf.format($brandStockPrice.getAgedValue())</span>/$brandStockPrice.getAgedQty()</span></div></div>#end</div></div>#end#end</div></div>## ------------------------------------my stock ageing---------------------------------<div class="card shadow-lg rounded-3"><div class="row mb-1 my-4 justify-content-center"><div class="col-10"><div class="bg-dark-light rounded-3 p-3 shadow rounded-corner"><h1 class="text-white text-center mb-0 fw-bold py-2 fs-8">My Stock Ageing</h1></div></div></div><div class="card-body"><!-- Controls for Volume/Value toggle --><div class="row mb-4"><div class="col-md-4"><div class="btn-group" role="group"><button type="button" class="btn btn-danger rounded-pill px-4 me-2 fs-5" id="btnVolume">Volume</button><button type="button" class="btn btn-danger rounded-pill px-4 fs-5" id="btnValue">Value</button></div></div></div><!-- Main stock aging grid --><div class="table-responsive rounded-5 p-5"><table class="table table-bordered rounded-4" id="stockAgingTable"><thead><tr class="text-center"><th></th><th class="align-middle bg-danger text-white fs-5 fw-bold" style="width: 180px;">Brands</th>#set($intervals = ["Less Than 15 Days", "16 - 30 Days", "31 - 45 Days","More Than 45 Days"])#set($bgColors = ["bg-success", "bg-cryan", "bg-orange", "bg-danger"])#set($textColors = ["text-white", "text-white", "text-white", "text-white"])#foreach($interval in $intervals)<th class="align-middle fs-5 fw-bold $bgColors.get($foreach.index) text-wrap"style="width: 180px;height: 55px !important; word-wrap: break-word; white-space: normal;"><span class="$textColors.get($foreach.index) text-wrap ">$interval</span></th>#end</tr></thead><tbody>#if(!$inventoryGroupedByBrand.isEmpty())#set($mandatoryBrands = ["vivo", "oppo", "samsung", "realme"])#set($otherBrands = [])## First process mandatory brands<tr><td class="align-middle bg-secondary text-center text-white fw-bold " rowspan="5"style="width: 60px !important; font-size: 10px !important;"><div class="brandText">MANDATORY BRANDS</div></td></tr>#foreach($brandKey in $mandatoryBrands)#set($found = false)#foreach($entry in $inventoryGroupedByBrand.entrySet())#if($entry.getKey().toLowerCase() == $brandKey)#set($found = true)<tr><td class="brand-cell text-start p-0"><div class="p-3 bg-danger #getBrandBgColor($entry.getKey())"style="height: 40px; display: flex; align-items: center; justify-content: start;"><span class="text-white fw-bold fs-5"><imgsrc="$brandLogos.getOrDefault($entry.getKey(),'https://static.vecteezy.com/system/resources/thumbnails/025/213/042/small_2x/mobile-phone-icon-in-black-circle-png.png')"alt="$entry.getKey() logo"class="brand-logo rounded-circle me-3"style="width:35px;height:35px">$entry.getKey()</span></div></td>#foreach($i in [0..3])<td class="align-middle text-center $bgColors.get($i)"style="opacity: 0.9;">#set($qty = 0)#set($value = 0)#foreach($item in $entry.getValue())#if($i < $item.getValues().size() && $item.getValues().get($i))#set($qty = $math.add($qty, $item.getValues().get($i).getQuantity()))#set($itemValue = $math.mul($item.getValues().get($i).getPrice(), $item.getValues().get($i).getQuantity()))#set($value = $math.add($value, $itemValue))#end#end<div class="volume-view fs-5 fw-bold text-white ">$qty</div><div class="value-view currency fs-5 fw-bold text-white"style="display: none;"> $nf.format( $value)</div></td>#end</tr>#end#end#if(!$found)<tr><td class="brand-cell text-center p-0"><div class="p-3 #getBrandBgColor($brandKey)"style="height: 40px; display: flex; align-items: center; justify-content: center;"><span class="text-white fw-bold">$brandKey</span></div></td>#foreach($i in [0..3])<td class="text-center align-middle $bgColors.get($i)"style="opacity: 0.9;"><div class="volume-view fs-5 fw-bold text-white">0</div><div class="value-view currency fs-5 fw-bold text-white"style="display: none;">0.00</div></td>#end</tr>#end#end## Process other brands<tr><td class="align-middle bg-dark-light text-center text-white fw-bold "rowspan="$inventoryGroupedByBrand.size()"style="width: 60px !important; font-size: 10px !important;"><div class="brandText">OTHER BRANDS</div></td></tr>#foreach($entry in $inventoryGroupedByBrand.entrySet())#set($isOtherBrand = true)#foreach($mandatoryBrand in $mandatoryBrands)#if($entry.getKey().toLowerCase() == $mandatoryBrand)#set($isOtherBrand = false)#break#end#end#if($isOtherBrand)<tr><td class="brand-cell text-start p-0"><div class="p-3 bg-secondary #getBrandBgColor($entry.getKey())"style="height: 40px; display: flex; align-items: center; justify-content: start;"><span class="text-white fw-bold fs-5 "><imgsrc="$brandLogos.getOrDefault($entry.getKey(),'https://static.vecteezy.com/system/resources/thumbnails/025/213/042/small_2x/mobile-phone-icon-in-black-circle-png.png')"alt="$entry.getKey() logo"class="brand-logo rounded-circle me-3"style="width:35px;height:35px">$entry.getKey()</span></div></td>#foreach($i in [0..3])<td class="text-center align-middle pb-4 $bgColors.get($i)"style="opacity: 0.9;">#set($qty = 0)#set($value = 0)#foreach($item in $entry.getValue())#if($i < $item.getValues().size() && $item.getValues().get($i))#set($qty = $math.add($qty, $item.getValues().get($i).getQuantity()))#set($itemValue = $math.mul($item.getValues().get($i).getPrice(), $item.getValues().get($i).getQuantity()))#set($value = $math.add($value, $itemValue))#end#end<div class="volume-view fs-5 fw-bold text-white">$qty</div><div class="value-view currency fs-5 fw-bold text-white"style="display: none;"> $nf.format($value)</div></td>#end</tr>#end#end#else<tr><td colspan="6" class="text-center">No inventory data available</td></tr>#end</tbody></table></div><div class="d-flex justify-content-center mt-5 "><button type="button" class="btn-sm btn-danger fs-2 fw-bold px-4" data-dismiss="modal">X CLOSE</button></div></div></div></section></div></body><script>var chart;const brandColors = {'vivo': '#2196F3','oppo': '#006b35','samsung': '#1428A0','realme': '#FFC107','xiaomi': '#FF5722','apple': '#666666','poco': '#FFD403','tecno': '#0064FE','lava': '#ED0F53'// Add other brands here...};function loadMonthDetails(monthIndex) {console.log(`Loading details for month: ${monthIndex}`);doGetAjaxRequestHandler(`${context}/monthWisePartnerIncome/${monthIndex}?partnerTask=true`, function (response) {$('.bootbox.modal .modal-body .bootbox-body').empty();$('#partner-income').html(response);const $section = $('#ajaxSection');});}$(document).on("click", ".pending-income", function () {lastMonthCreditIncome("main-content");});// Standard AJAX handler - assuming this already exists, but including for completenessfunction doGetAjaxRequestHandler(url, successCallback) {$.ajax({url: url,type: 'GET',success: successCallback,error: function (xhr, status, error) {console.error("AJAX request failed:", error);}});}$(function () {$('#reportrange').daterangepicker(getRangedDatePicker());});$(document).ready(function () {$("#btnVolume").addClass("active");$("#btnVolume").click(function () {$(this).addClass("active");$("#btnValue").removeClass("active");$(".volume-view").show();$(".value-view").hide();});$("#btnValue").click(function () {$(this).addClass("active");$("#btnVolume").removeClass("active");$(".volume-view").hide();$(".value-view").show();});});document.querySelectorAll('.brand-btn').forEach(button => {button.addEventListener('click', function () {const selectedBrand = this.getAttribute('data-brand');document.querySelectorAll('.brand-data').forEach(row => {row.style.display = (row.getAttribute('data-brand') === selectedBrand || selectedBrand === 'all') ? 'block' : 'none';});});});function initializeBrandButtons() {const brandButtons = document.querySelectorAll('.brand-btn');brandButtons.forEach(button => {const brand = button.dataset.brand; // Already lowercase from serverconst color = brandColors[brand] || '#666';// Apply initial stylesbutton.style.border = `2px solid ${color}`;button.style.color = color;button.style.backgroundColor = '#fff';});// Add click handlersbrandButtons.forEach(button => {button.addEventListener('click', function () {const selectedBrand = this.dataset.brand;// Reset all buttonsbrandButtons.forEach(btn => {const brandColor = brandColors[btn.dataset.brand] || '#666';btn.style.backgroundColor = '#fff';btn.style.color = brandColor;});// Activate clicked buttonthis.style.backgroundColor = brandColors[selectedBrand] || '#666';this.style.color = '#fff';// Filter rowsdocument.querySelectorAll('.brand-data').forEach(row => {row.style.display = row.dataset.brand === selectedBrand ? 'block' : 'none';});});});brandButtons[0]?.click();}initializeBrandButtons();</script><script>// Brand filtering functionalitydocument.querySelectorAll('.brand-btn').forEach(button => {button.addEventListener('click', function () {const brand = this.getAttribute('data-brand');// Update active buttondocument.querySelectorAll('.brand-btn').forEach(btn => {btn.style.backgroundColor = '';btn.style.color = '';});this.style.backgroundColor = '#006b35';this.style.color = 'white';// Show selected brand datadocument.querySelectorAll('.brand-data').forEach(item => {item.style.display = item.getAttribute('data-brand') === brand ? 'block' : 'none';});});});// Activate first brand by defaultdocument.querySelector('.brand-btn')?.click();</script>##-------------------------------------------------------------------My Earning chart -----------------------------------------<script>$(document).ready(function () {// loadMonthDetails(0);const monthData = [#foreach( $item in $summaryList ){month: "$!item.monthValueMap[$item.monthIndex]",monthIndex: "$item.monthIndex",total: $item.get('totalIncome'),credited: $item.get('creditedIncome'),pending: $item.get('pendingIncome')}#if($foreach.hasNext),#end#end].reverse();// Simple formatting with roundingconst formatIndianCurrency = (amount) => {const rounded = Math.round(amount);return rounded.toLocaleString('en-IN');};// Apply formatting when displayingmonthData.forEach(item => {item.totalFormatted = formatIndianCurrency(item.total);item.creditedFormatted = formatIndianCurrency(item.credited);item.pendingFormatted = formatIndianCurrency(item.pending);});chart = new Chart(document.getElementById('sixMonthChart'), {type: 'bar',data: {labels: monthData.map(d => d.month),datasets: [// Bar: Credited Income{label: 'Credited Income',data: monthData.map(d => Math.round(d.credited)),backgroundColor: '#aadcb4',borderColor: '#aadcb4',borderWidth: 1,barThickness: 30,hitRadius: 30,order: 1,yAxisID: 'y',hoverBorderWidth: 3,hoverBorderColor: '#aadcb4'},// Bar: Pending Income{label: 'Pending Income',data: monthData.map(d => Math.round(d.pending)),backgroundColor: 'rgba(255,0,0,0.7)',borderColor: 'rgba(255,0,0,1)',borderWidth: 1,barThickness: 30,order: 2,hitRadius: 0,yAxisID: 'y',hoverBorderWidth: 3,hoverBorderColor: '#ff0000'},// Line: Total Income{label: 'Total Income',data: monthData.map(d => Math.round(d.total)),borderColor: '#4bc0c0',backgroundColor: 'rgba(75, 192, 192, 0.1)',borderWidth: 4,type: 'line',order: 3,pointRadius: 6,pointHoverRadius: 0,pointHitRadius: 0,pointBackgroundColor: '#4bc0c0',pointBorderColor: '#ffffff',pointBorderWidth: 2,yAxisID: 'y',tension: 0.3}]},options: {responsive: true,maintainAspectRatio: true,interaction: {mode: 'point',intersect: true,},plugins: {datalabels: {formatter: function (value) {return Math.round(value).toLocaleString('en-IN');},color: '#fff',backgroundColor: '#333',borderRadius: 4,padding: 4,font: {weight: 'bold'},display: function (context) {const rawValue = context.dataset.data[context.dataIndex];return context.datasetIndex < 3 && rawValue != null && rawValue !== 0;},},tooltip: {mode: 'index',intersect: false,backgroundColor: 'rgba(0, 0, 0, 0.9)',titleColor: '#ffffff',bodyColor: '#ffffff',borderColor: '#4bc0c0',borderWidth: 2,displayColors: true,padding: 12,boxWidth: 15,boxHeight: 15,cornerRadius: 8,usePointStyle: true,bodyFont: {size: 14,weight: 'bold' // Make body text bold},titleFont: {size: 16,weight: 'bold'},footerFont: {size: 12,weight: 'bold' // Make footer bold too},callbacks: {title: function (context) {return `Month: ${context[0].label}`;},label: function (context) {const value = context.parsed.y;// Round the value first, then format with currency symbolconst roundedValue = Math.round(value);const formattedValue = roundedValue.toLocaleString('en-IN');// Format with proper spacing and bold stylingconst label = context.dataset.label;return `${label}: ${formattedValue}`;},footer: function (tooltipItems) {// Calculate and show percentage for credited vs totalconst credited = tooltipItems.find(item => item.dataset.label === 'Credited Income')?.parsed.y || 0;const total = tooltipItems.find(item => item.dataset.label === 'Total Income')?.parsed.y || 0;if (total > 0) {const percentage = ((credited / total) * 100).toFixed(1);return `Credited: ${percentage}% of total income`;}return '';},labelColor: function (context) {return {borderColor: 'transparent',backgroundColor: context.dataset.borderColor,borderRadius: 4,borderWidth: 2};},labelTextColor: function (context) {return '#ffffff'; // Ensure text is white and visible}}},legend: {display: true,position: 'top',labels: {usePointStyle: true,padding: 20,font: {size: 14,weight: 'bold'},color: '#333',boxWidth: 15,boxHeight: 15}}},scales: {x: {ticks: {autoSkip: false,font: {size: 12,weight: 'bold'},color: '#333',padding: 10}},y: {type: 'linear',display: true,position: 'left',stacked: false,beginAtZero: true,grid: {color: 'rgba(0, 0, 0, 0.1)',lineWidth: 1},ticks: {callback: function (value) {// Round the value first, then formatconst roundedValue = Math.round(value);return roundedValue.toLocaleString('en-IN');},font: {size: 12,weight: 'bold'},color: '#333'}}},elements: {bar: {borderRadius: 4,categoryPercentage: 0.8,barPercentage: 0.9},line: {borderJoinStyle: 'round'},point: {hoverBorderWidth: 1}},onHover: function (event, elements) {event.native.target.style.cursor = elements.length > 0 ? 'pointer' : 'default';},onClick: function (event, elements) {if (elements && elements.length > 0) {const clickedIndex = elements[0].index;const clickedData = monthData[clickedIndex];// Visual feedbackevent.chart.canvas.style.cursor = 'wait';console.log(`Loading details for month: ${clickedData.monthIndex} (${clickedData.month})`);loadMonthDetails(clickedData.monthIndex);// Smooth scroll to resultssetTimeout(() => {document.getElementById('partner-income').scrollIntoView({behavior: 'smooth',block: 'start'});event.chart.canvas.style.cursor = 'pointer';}, 300);}}}});})</script>##-----------------------------------------------------------------------Stagged CHart ---------------------------------<script>$(document).ready(function () {// Define major brands to keep separateconst MAJOR_BRANDS = ['vivo', 'samsung', 'oppo', 'realme', 'xiaomi'];// Prepare market dataconst marketSegments = [];const otherMarketData = {brand: "Others",marketShare: 0,color: '#6b7280'};// Prepare stock dataconst stockSegments = [];const otherStockData = {brand: "Others",quantity: 0,value: 0};// Process market share data#foreach($entry in $marketShareData)var marketBrandName = '$entry.Brand'.toLowerCase();if (MAJOR_BRANDS.includes(marketBrandName)) {marketSegments.push({brand: marketBrandName,marketShare: ${entry.MarketShare.replace('%', '')},color: '$entry.BgColor'});} else {otherMarketData.marketShare += ${entry.MarketShare.replace('%', '')};}#end// Process stock data#foreach($brandStockPrice in $brandStockPrices)var stockBrandName = "$brandStockPrice.getBrand()".toLowerCase();if (MAJOR_BRANDS.includes(stockBrandName)) {stockSegments.push({brand: stockBrandName,quantity: $brandStockPrice.getTotalQty(),value: $brandStockPrice.getTotalValue()});} else {otherStockData.quantity += $brandStockPrice.getTotalQty();otherStockData.value += $brandStockPrice.getTotalValue();}#end// Add Others categories if they have dataif (otherMarketData.marketShare > 0) {marketSegments.push(otherMarketData);}if (otherStockData.quantity > 0) {stockSegments.push(otherStockData);}// Combine dataconst combinedSegments = [];const allBrands = [...new Set([...marketSegments.map(d => d.brand),...stockSegments.map(d => d.brand)])];allBrands.forEach(brand => {const marketInfo = marketSegments.find(m => m.brand === brand) || {};const stockInfo = stockSegments.find(s => s.brand === brand) || {};combinedSegments.push({brand: brand.charAt(0).toUpperCase() + brand.slice(1),marketShare: marketInfo.marketShare || 0,stockQuantity: stockInfo.quantity || 0,stockValue: stockInfo.value || 0,color: marketInfo.color || brandColors[brand] || '#95a5a6'});});// Calculate total stock quantityconst totalStockQuantity = stockSegments.reduce((sum, b) => sum + b.quantity, 0);// Create stacked bar chartconst ctx4 = document.getElementById('combinedStackedChart').getContext('2d');const staggedChart = new Chart(ctx4, {type: 'bar',data: {labels: combinedSegments.map(item => item.brand),datasets: [{label: 'Brand Market Share (%)',data: combinedSegments.map(item => item.marketShare),backgroundColor: combinedSegments.map(item => item.color + '80'),borderColor: combinedSegments.map(item => item.color),borderWidth: 2},{label: 'Your Brand Share (%)',data: combinedSegments.map(item => ((item.stockQuantity / totalStockQuantity) * 100).toFixed(1)),backgroundColor: combinedSegments.map(item => item.color + '40'),borderColor: combinedSegments.map(item => item.color),borderWidth: 1}]},options: {responsive: true,scales: {x: {stacked: true},y: {stacked: true,beginAtZero: true,title: {display: true,text: 'Percentage (%)'}}},plugins: {tooltip: {callbacks: {label: function (context) {const segment = combinedSegments[context.dataIndex];if (context.datasetIndex === 0) {return `Market Share: ${segment.marketShare}%`;} else {return [`Stock Quantity: ${segment.stockQuantity}`,`Percentage: ${((segment.stockQuantity / totalStockQuantity) * 100).toFixed(1)}%`];}}}}}}});});</script>