| 34813 |
aman |
1 |
<meta charset="UTF-8">
|
|
|
2 |
<link id="modal-bootstrap-css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
|
|
|
3 |
rel="stylesheet"/>
|
|
|
4 |
<style>
|
|
|
5 |
|
|
|
6 |
.chart-wrapper {
|
|
|
7 |
overflow: hidden;
|
|
|
8 |
transition: all 0.3s ease;
|
|
|
9 |
}
|
|
|
10 |
|
|
|
11 |
.chart-content {
|
|
|
12 |
display: flex;
|
|
|
13 |
flex-wrap: nowrap;
|
|
|
14 |
gap: 20px;
|
|
|
15 |
align-items: flex-start;
|
|
|
16 |
}
|
|
|
17 |
|
|
|
18 |
.chart-container {
|
|
|
19 |
flex: 0 0 550px;
|
|
|
20 |
height: 320px;
|
|
|
21 |
}
|
|
|
22 |
|
|
|
23 |
.partner-income-container {
|
|
|
24 |
flex: 1 1 auto;
|
|
|
25 |
min-width: 300px;
|
|
|
26 |
}
|
|
|
27 |
|
|
|
28 |
|
|
|
29 |
|
|
|
30 |
|
|
|
31 |
.status-ok {
|
|
|
32 |
color: #155724;
|
| 35001 |
aman |
33 |
font-weight: 700;
|
| 34813 |
aman |
34 |
}
|
|
|
35 |
|
|
|
36 |
.brand-name {
|
|
|
37 |
font-size: 1.5rem;
|
|
|
38 |
font-weight: 700;
|
|
|
39 |
margin-bottom: 15px;
|
|
|
40 |
color: #2c3e50;
|
|
|
41 |
}
|
|
|
42 |
|
|
|
43 |
|
|
|
44 |
|
|
|
45 |
.quantity-value {
|
|
|
46 |
font-weight: 600;
|
|
|
47 |
color: #2c3e50;
|
|
|
48 |
}
|
|
|
49 |
|
|
|
50 |
.right-panel {
|
|
|
51 |
background: white;
|
|
|
52 |
border-radius: 8px;
|
|
|
53 |
padding: 20px;
|
|
|
54 |
border: 1px solid #e9ecef;
|
|
|
55 |
}
|
|
|
56 |
|
|
|
57 |
|
|
|
58 |
@keyframes shimmer {
|
|
|
59 |
0% {
|
|
|
60 |
left: -100%;
|
|
|
61 |
}
|
|
|
62 |
100% {
|
|
|
63 |
left: 100%;
|
|
|
64 |
}
|
|
|
65 |
}
|
|
|
66 |
|
|
|
67 |
|
|
|
68 |
|
|
|
69 |
.brand-logo {
|
|
|
70 |
width: 80px;
|
|
|
71 |
height: 80px;
|
|
|
72 |
object-fit: contain;
|
|
|
73 |
border-radius: 12px;
|
|
|
74 |
background-color: #f8f9fa;
|
|
|
75 |
padding: 2px;
|
|
|
76 |
}
|
|
|
77 |
|
|
|
78 |
|
|
|
79 |
|
|
|
80 |
.modal-backdrop.in {
|
|
|
81 |
filter: alpha(opacity=50);
|
|
|
82 |
opacity: 0.35;
|
|
|
83 |
width: auto;
|
|
|
84 |
height: auto;
|
|
|
85 |
}
|
|
|
86 |
|
|
|
87 |
.brandText {
|
|
|
88 |
transform: rotate(270deg) !important;
|
|
|
89 |
}
|
|
|
90 |
|
|
|
91 |
.rounded-corner {
|
|
|
92 |
border-top-left-radius: 30px !important;
|
|
|
93 |
border-top-right-radius: 30px !important;
|
|
|
94 |
|
|
|
95 |
}
|
|
|
96 |
|
|
|
97 |
.bg-danger {
|
|
|
98 |
background-color: #D3181F !important;
|
|
|
99 |
}
|
|
|
100 |
|
|
|
101 |
.fs-8 {
|
|
|
102 |
font-size: 25px !important;
|
|
|
103 |
}
|
|
|
104 |
|
|
|
105 |
.table-bordered th {
|
|
|
106 |
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
|
107 |
}
|
|
|
108 |
|
|
|
109 |
.table-bordered td {
|
|
|
110 |
border: 1px solid #dee2e6;
|
|
|
111 |
vertical-align: middle;
|
|
|
112 |
}
|
|
|
113 |
|
|
|
114 |
.fs-5 {
|
|
|
115 |
font-size: 1.2rem !important;
|
|
|
116 |
}
|
|
|
117 |
.brand-btn {
|
| 35001 |
aman |
118 |
background: #444;
|
|
|
119 |
color: white;
|
|
|
120 |
border: none;
|
|
|
121 |
padding: 8px 16px;
|
|
|
122 |
border-radius: 20px;
|
|
|
123 |
cursor: pointer;
|
| 34813 |
aman |
124 |
transition: all 0.3s ease;
|
| 35001 |
aman |
125 |
margin: 2px;
|
| 34813 |
aman |
126 |
}
|
|
|
127 |
|
| 35001 |
aman |
128 |
.brand-btn:hover {
|
|
|
129 |
background: #666;
|
|
|
130 |
color: white;
|
| 34813 |
aman |
131 |
}
|
|
|
132 |
|
|
|
133 |
|
| 35001 |
aman |
134 |
.section-header {
|
|
|
135 |
background: #7a7a7a;
|
|
|
136 |
color: white;
|
|
|
137 |
padding: 15px;
|
|
|
138 |
margin: 20px 0 10px 0;
|
|
|
139 |
border-radius: 8px;
|
|
|
140 |
text-align: center;
|
|
|
141 |
font-weight: bold;
|
| 35119 |
aman |
142 |
font-size: 1.6rem;
|
| 35001 |
aman |
143 |
}
|
|
|
144 |
|
|
|
145 |
.table thead th {
|
|
|
146 |
background: #555;
|
|
|
147 |
color: white;
|
|
|
148 |
border: none;
|
|
|
149 |
font-weight: bold;
|
|
|
150 |
text-align: center;
|
|
|
151 |
vertical-align: middle;
|
|
|
152 |
padding: 15px 8px;
|
|
|
153 |
}
|
|
|
154 |
|
|
|
155 |
.table tbody td {
|
|
|
156 |
text-align: center;
|
|
|
157 |
vertical-align: middle;
|
|
|
158 |
padding: 12px 8px;
|
|
|
159 |
border: 1px solid #dee2e6;
|
|
|
160 |
}
|
|
|
161 |
|
|
|
162 |
|
|
|
163 |
.status-order {
|
|
|
164 |
color: #17a2b8 !important;
|
|
|
165 |
font-weight: bold;
|
|
|
166 |
}
|
|
|
167 |
|
|
|
168 |
|
|
|
169 |
.no-data-row {
|
|
|
170 |
background: #f8f9fa;
|
|
|
171 |
color: #6c757d;
|
|
|
172 |
font-style: italic;
|
|
|
173 |
}
|
|
|
174 |
|
| 34813 |
aman |
175 |
.curve {
|
|
|
176 |
padding-left: 100px !important;
|
|
|
177 |
border-radius: 40px 0 0 40px !important;
|
|
|
178 |
width: 250px !important;
|
|
|
179 |
}
|
|
|
180 |
|
|
|
181 |
|
|
|
182 |
.stock-ribbon {
|
|
|
183 |
position: relative;
|
|
|
184 |
padding: 5px 15px;
|
|
|
185 |
color: white;
|
|
|
186 |
clip-path: polygon(0 0, 100% 0, 95% 100%, 0 100%);
|
|
|
187 |
min-width: 220px;
|
|
|
188 |
}
|
|
|
189 |
|
|
|
190 |
.mandatory-ribbon {
|
|
|
191 |
background-color: #D3181F !important;
|
|
|
192 |
}
|
|
|
193 |
|
|
|
194 |
.other-ribbon {
|
|
|
195 |
background-color: #000;
|
|
|
196 |
}
|
|
|
197 |
|
|
|
198 |
.brand-item {
|
|
|
199 |
display: flex;
|
|
|
200 |
align-items: center;
|
|
|
201 |
margin-bottom: 20px;
|
|
|
202 |
}
|
|
|
203 |
|
|
|
204 |
.category-header {
|
|
|
205 |
font-size: 15px;
|
|
|
206 |
font-weight: bold;
|
|
|
207 |
margin: 20px 0;
|
|
|
208 |
padding-left: 15px;
|
|
|
209 |
}
|
|
|
210 |
|
|
|
211 |
.mandatory-header {
|
|
|
212 |
color: #d32f2f;
|
|
|
213 |
}
|
|
|
214 |
|
|
|
215 |
.other-header {
|
|
|
216 |
color: #333;
|
|
|
217 |
}
|
|
|
218 |
|
|
|
219 |
|
|
|
220 |
.bg-dark-light {
|
|
|
221 |
background-color: #3e3e3e !important;
|
|
|
222 |
color: white;
|
|
|
223 |
}
|
|
|
224 |
|
|
|
225 |
.table-bordered td, .table-bordered th {
|
|
|
226 |
border: 1px solid #dee2e6;
|
|
|
227 |
}
|
|
|
228 |
|
|
|
229 |
.brand-circle {
|
|
|
230 |
width: 60px;
|
|
|
231 |
height: 60px;
|
|
|
232 |
object-fit: cover;
|
|
|
233 |
border: 5px solid rgb(122, 116, 116);
|
|
|
234 |
}
|
|
|
235 |
|
|
|
236 |
|
|
|
237 |
.currency::before {
|
|
|
238 |
content: "\20B9";
|
|
|
239 |
}
|
|
|
240 |
|
|
|
241 |
.fs-3, .fs-5 {
|
|
|
242 |
font-weight: normal;
|
|
|
243 |
}
|
|
|
244 |
|
|
|
245 |
.fw-bold {
|
|
|
246 |
font-weight: bold !important;
|
|
|
247 |
}
|
|
|
248 |
|
|
|
249 |
.btn {
|
|
|
250 |
font-weight: normal;
|
|
|
251 |
}
|
|
|
252 |
|
|
|
253 |
.payment-circle {
|
|
|
254 |
width: 200px;
|
|
|
255 |
height: 200px;
|
|
|
256 |
border: 25px solid #e0dcdc;
|
|
|
257 |
border-radius: 50%;
|
|
|
258 |
display: flex;
|
|
|
259 |
align-items: center;
|
|
|
260 |
justify-content: center;
|
|
|
261 |
transition: transform 0.3s ease;
|
|
|
262 |
}
|
|
|
263 |
|
|
|
264 |
|
|
|
265 |
.payment-amount {
|
|
|
266 |
font-size: 18px;
|
|
|
267 |
font-weight: 700;
|
|
|
268 |
margin-bottom: 10px;
|
|
|
269 |
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);
|
| 35001 |
aman |
270 |
color: white;
|
| 34813 |
aman |
271 |
}
|
|
|
272 |
|
|
|
273 |
.payment-label {
|
|
|
274 |
font-size: 18px;
|
|
|
275 |
line-height: 1.3;
|
|
|
276 |
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
|
|
|
277 |
}
|
|
|
278 |
|
|
|
279 |
|
|
|
280 |
.table-border td {
|
|
|
281 |
border: 1px solid black !important;
|
|
|
282 |
}
|
|
|
283 |
|
|
|
284 |
.table-border thead {
|
|
|
285 |
border: 1px solid black;
|
|
|
286 |
}
|
|
|
287 |
|
|
|
288 |
.p-0 {
|
|
|
289 |
padding: 0 !important;
|
|
|
290 |
}
|
|
|
291 |
</style>
|
|
|
292 |
<body style="background-color: rgb(247, 247, 247);zoom: 100%!important;">
|
|
|
293 |
<div style="overflow-y:auto;max-height: 120vh; ">
|
|
|
294 |
<section id="ajaxSection" class="rounded"
|
|
|
295 |
style="max-height: 120vh; overflow-y: auto;">
|
|
|
296 |
<div class="w-full bg-danger h-25 py-3 mb-4">
|
|
|
297 |
<h1 class="text-center text-white " style="font-size: 30px !important; font-weight: 800">Pending
|
|
|
298 |
Tasks</h1>
|
|
|
299 |
</div>
|
|
|
300 |
<div class="container">
|
|
|
301 |
##-----------------------------------------------GRN Pending -----------------------------------------------------
|
|
|
302 |
<div class="container-fluid p-4">
|
|
|
303 |
#if($grnPendingOrders.entrySet().size()>0)
|
|
|
304 |
<div class="row justify-content-center">
|
|
|
305 |
<div class="col-10">
|
|
|
306 |
<div class="bg-dark-light rounded-3 p-3 shadow rounded-corner">
|
|
|
307 |
<h1 class="text-white text-center mb-0 fw-bold py-2 fs-8">GRN Pending</h1>
|
|
|
308 |
</div>
|
|
|
309 |
</div>
|
|
|
310 |
</div>
|
|
|
311 |
|
|
|
312 |
<div class="table-responsive rounded-3 shadow p-5">
|
|
|
313 |
<table id="grnTable" class="table table-bordered mb-0 table-border" style="width:100%">
|
|
|
314 |
<thead>
|
|
|
315 |
<tr class="bg-danger text-white">
|
|
|
316 |
<th class="ps-4 fs-5 fw-bold text-uppercase bg-danger text-white text-center"
|
|
|
317 |
style="padding: 10px !important;">BRANDS
|
|
|
318 |
</th>
|
|
|
319 |
<th class="fs-5 fw-bold text-uppercase bg-danger text-white text-center"
|
|
|
320 |
style="padding: 10px !important;">QUANTITY
|
|
|
321 |
</th>
|
|
|
322 |
<th class="pe-4 fs-5 fw-bold text-uppercase bg-danger text-white text-center"
|
|
|
323 |
style="padding: 10px !important;">VALUE
|
|
|
324 |
</th>
|
|
|
325 |
</tr>
|
|
|
326 |
</thead>
|
|
|
327 |
<tbody>
|
|
|
328 |
#set($mandatoryBrands = ["Vivo", "Oppo", "Samsung", "Realme"])
|
|
|
329 |
#foreach($entry in $grnPendingOrders.entrySet())
|
|
|
330 |
#set($brand = $entry.key)
|
|
|
331 |
#set($details = $entry.value)
|
|
|
332 |
<tr class="">
|
|
|
333 |
<td class="ps-4 text-center p-0">
|
|
|
334 |
<div class="d-flex align-items-center justify-content-center">
|
|
|
335 |
<div class="row align-items-center" style="width: 200px;">
|
|
|
336 |
<div class="col-auto">
|
|
|
337 |
<img src="$brandLogos.getOrDefault($brand,
|
|
|
338 |
'https://static.vecteezy.com/system/resources/thumbnails/025/213/042/small_2x/mobile-phone-icon-in-black-circle-png.png')"
|
|
|
339 |
alt="$brand logo"
|
|
|
340 |
class="brand-logo rounded-circle"
|
|
|
341 |
style="width:35px;height:35px">
|
|
|
342 |
</div>
|
|
|
343 |
<div class="col text-start">
|
|
|
344 |
<span class="fw-bold fs-5">$brand</span>
|
|
|
345 |
</div>
|
|
|
346 |
</div>
|
|
|
347 |
</div>
|
|
|
348 |
</td>
|
|
|
349 |
<td class="text-center align-middle fs-5 fw-semibold p-0">
|
|
|
350 |
$details.quantity
|
|
|
351 |
</td>
|
|
|
352 |
<td class="pe-4 text-center align-middle fs-5 fw-semibold currency p-0 ">
|
|
|
353 |
$nf.format($details.mrp)
|
|
|
354 |
</td>
|
|
|
355 |
</tr>
|
|
|
356 |
#end
|
|
|
357 |
</tbody>
|
|
|
358 |
</table>
|
|
|
359 |
</div>
|
|
|
360 |
#end
|
|
|
361 |
</div>
|
|
|
362 |
|
|
|
363 |
##-----------------------------------------------Unbilled Activated -----------------------------------------------------
|
|
|
364 |
|
|
|
365 |
<div class="container-fluid p-4">
|
|
|
366 |
#if($unbilledActivated.entrySet().size()>0)
|
|
|
367 |
<div class="row justify-content-center">
|
|
|
368 |
<div class="col-10">
|
|
|
369 |
<div class="bg-dark-light rounded-3 p-3 shadow rounded-corner">
|
|
|
370 |
<h1 class="text-white text-center mb-0 py-2 fw-bold fs-8">Pending Billing</h1>
|
|
|
371 |
</div>
|
|
|
372 |
</div>
|
|
|
373 |
</div>
|
|
|
374 |
|
|
|
375 |
<div class="table-responsive rounded-3 shadow p-5">
|
|
|
376 |
<table id="unbilledTable" class="table table-bordered mb-0 table-border" style="width:100%">
|
|
|
377 |
|
|
|
378 |
<thead>
|
|
|
379 |
<tr class="bg-danger text-white">
|
|
|
380 |
<th class="ps-4 fs-5 fw-bold text-uppercase bg-danger text-white text-center p-0"
|
|
|
381 |
style="padding: 10px !important;">BRANDS
|
|
|
382 |
</th>
|
|
|
383 |
<th class="fs-5 fw-bold text-uppercase bg-danger text-white text-center p-0"
|
|
|
384 |
style="padding: 10px !important;">QUANTITY
|
|
|
385 |
</th>
|
|
|
386 |
<th class="pe-4 fs-5 fw-bold text-uppercase bg-danger text-white text-center p-0"
|
|
|
387 |
style="padding: 10px !important;">VALUE
|
|
|
388 |
</th>
|
|
|
389 |
</tr>
|
|
|
390 |
</thead>
|
|
|
391 |
<tbody>
|
|
|
392 |
#set($mandatoryBrands = ["Vivo", "Realme", "Oppo", "Samsung"])
|
|
|
393 |
|
|
|
394 |
#foreach($entry in $unbilledActivated.entrySet())
|
|
|
395 |
#set($brand = $entry.key)
|
|
|
396 |
#set($details = $entry.value)
|
|
|
397 |
<tr>
|
|
|
398 |
<td class="ps-4 text-center p-0">
|
|
|
399 |
<div class="d-flex align-items-center justify-content-center">
|
|
|
400 |
<div class="row align-items-center" style="width: 200px;">
|
|
|
401 |
<div class="col-auto">
|
|
|
402 |
<img src="$brandLogos.getOrDefault($brand,
|
|
|
403 |
'https://static.vecteezy.com/system/resources/thumbnails/025/213/042/small_2x/mobile-phone-icon-in-black-circle-png.png')"
|
|
|
404 |
alt="$brand logo"
|
|
|
405 |
class="brand-logo rounded-circle"
|
|
|
406 |
style="width:35px;height:35px">
|
|
|
407 |
</div>
|
|
|
408 |
<div class="col text-start">
|
|
|
409 |
<span class="fw-bold fs-5">$brand</span>
|
|
|
410 |
</div>
|
|
|
411 |
</div>
|
|
|
412 |
</div>
|
|
|
413 |
</td>
|
|
|
414 |
<td class="text-center align-middle fs-5 fw-semibold p-0">
|
|
|
415 |
$details.quantity
|
|
|
416 |
</td>
|
|
|
417 |
<td class="pe-4 text-center align-middle p-0 currency fw-semibold fs-5">
|
|
|
418 |
$nf.format( $details.mtd)
|
|
|
419 |
</td>
|
|
|
420 |
</tr>
|
|
|
421 |
#end
|
|
|
422 |
</tbody>
|
|
|
423 |
</table>
|
|
|
424 |
</div>
|
|
|
425 |
#end
|
|
|
426 |
</div>
|
|
|
427 |
|
|
|
428 |
|
|
|
429 |
##-----------------------------------------------Loan Amount -----------------------------------------------------
|
| 34971 |
aman |
430 |
#if( $totalDefaultAmount != 0 || $totalOverdueAmount != 0 || $totalDueAmount != 0 || $totalLoan != 0 )
|
|
|
431 |
<div class="container-fluid p-4">
|
|
|
432 |
<div class="row mb-5 justify-content-center">
|
|
|
433 |
<div class="col-10">
|
|
|
434 |
<div class="bg-dark-light rounded-3 p-3 shadow rounded-corner">
|
|
|
435 |
<h1 class="text-white text-center mb-0 fw-bold py-2 fs-8">Loan </h1>
|
|
|
436 |
</div>
|
| 34813 |
aman |
437 |
</div>
|
|
|
438 |
</div>
|
| 34971 |
aman |
439 |
<div class="row justify-content-center">
|
|
|
440 |
<div class="col-12 col-md-4 text-center ">
|
|
|
441 |
<div class="payment-circle shadow-lg shadow-dark mx-auto "
|
|
|
442 |
style="background-color: #cc0000 !important;">
|
|
|
443 |
<div class="payment-content">
|
|
|
444 |
<div class="payment-amount currency"> $nf.format( $totalDefaultAmount) </div>
|
| 34813 |
aman |
445 |
|
| 34971 |
aman |
446 |
</div>
|
| 34813 |
aman |
447 |
</div>
|
| 34971 |
aman |
448 |
<h1 class="payment-label fw-bold mt-4" style="font-weight: 400 !important;">Default
|
|
|
449 |
Payment<br>(Above
|
|
|
450 |
30 days)</h1>
|
| 34813 |
aman |
451 |
</div>
|
|
|
452 |
|
| 34971 |
aman |
453 |
<div class="col-12 col-md-4 text-center">
|
|
|
454 |
<div class="payment-circle shadow-lg mx-auto" style="background-color: #FF9433 !important;">
|
|
|
455 |
<div class="payment-content">
|
|
|
456 |
<div class="payment-amount currency"> $nf.format($totalOverdueAmount) </div>
|
|
|
457 |
</div>
|
| 34813 |
aman |
458 |
</div>
|
| 34971 |
aman |
459 |
<h1 class="payment-label fw-bold mt-4"
|
|
|
460 |
style="font-size: 20px !important; font-weight: 400 !important;">Due Payment<br>(Above
|
|
|
461 |
15
|
|
|
462 |
Days)</h1>
|
|
|
463 |
|
| 34813 |
aman |
464 |
</div>
|
| 34971 |
aman |
465 |
<div class="col-12 col-md-4 text-center">
|
|
|
466 |
<div class="payment-circle shadow-lg mx-auto "
|
|
|
467 |
style="background-color: #00B050 !important;">
|
|
|
468 |
<div class="payment-content">
|
|
|
469 |
<div class="payment-amount currency"> $nf.format($totalDueAmount) </div>
|
|
|
470 |
</div>
|
| 34813 |
aman |
471 |
</div>
|
| 34971 |
aman |
472 |
<h1 class="payment-label fw-bold mt-4"
|
|
|
473 |
style="font-size: 20px !important; font-weight: 400 !important;">Other Loan<br>(Within
|
|
|
474 |
15
|
|
|
475 |
Days)</h1>
|
| 34813 |
aman |
476 |
</div>
|
|
|
477 |
|
|
|
478 |
|
| 34971 |
aman |
479 |
<div class="mt-4 mx-5 " style="margin-top: 6rem !important;">
|
|
|
480 |
<h1 class="text-center " style="font-size:30px !important;font-weight:300 !important;">Total
|
|
|
481 |
Loan Value :
|
|
|
482 |
<span class="currency fw-bold"> $nf.format( $totalLoan )</span>
|
|
|
483 |
</h1>
|
|
|
484 |
</div>
|
| 34813 |
aman |
485 |
</div>
|
|
|
486 |
</div>
|
| 34971 |
aman |
487 |
#end
|
| 34813 |
aman |
488 |
</div>
|
|
|
489 |
|
|
|
490 |
<div class="w-full bg-danger h-25 py-3 my-4">
|
|
|
491 |
<h1 class="text-center text-white fw-bold" style="font-size: 30px !important; font-weight: 800">My Business
|
|
|
492 |
Analysis</h1>
|
|
|
493 |
</div>
|
|
|
494 |
<div class="container-fluid p-5 mt-5">
|
|
|
495 |
|
|
|
496 |
<div class="row mb-1 my-4 mx-3 justify-content-center">
|
|
|
497 |
<div class="col-10">
|
|
|
498 |
<div class="bg-dark-light rounded-3 p-3 shadow rounded-corner">
|
|
|
499 |
<h1 class="text-white text-center mb-0 fw-bold py-2 fs-8">My Earning </h1>
|
|
|
500 |
</div>
|
|
|
501 |
</div>
|
|
|
502 |
</div>
|
|
|
503 |
|
|
|
504 |
<div class="container mt-4">
|
|
|
505 |
<div class="chart-wrapper card shadow-lg rounded-5 p-2">
|
|
|
506 |
<span class="text-danger fs-3 fw-bold text-end">** Click on the bar to see the details</span>
|
|
|
507 |
|
|
|
508 |
<div class="chart-content ">
|
|
|
509 |
<div class="chart-container">
|
|
|
510 |
<canvas id="sixMonthChart"></canvas>
|
|
|
511 |
</div>
|
|
|
512 |
<div id="partner-income" class="partner-income-container"></div>
|
|
|
513 |
</div>
|
|
|
514 |
</div>
|
|
|
515 |
</div>
|
|
|
516 |
|
|
|
517 |
</div>
|
|
|
518 |
## ----------------------------------------anyalysis---------------------------=//
|
|
|
519 |
#set($marketShareData = [
|
|
|
520 |
{"Brand": "Vivo", "MarketShare": "20%", "Quarter": "Q1 2025", "BgColor": "#2196F3", "Rank": "1"},
|
|
|
521 |
{"Brand": "Samsung", "MarketShare": "18%", "Quarter": "Q1 2025", "BgColor": "#1428A0", "Rank": "2"},
|
|
|
522 |
{"Brand": "Xiaomi", "MarketShare": "13%", "Quarter": "Q1 2025", "BgColor": "#FF6900", "Rank": "3"},
|
|
|
523 |
{"Brand": "OPPO", "MarketShare": "12%", "Quarter": "Q1 2025", "BgColor": "#006B33", "Rank": "4"},
|
|
|
524 |
{"Brand": "realme", "MarketShare": "11%", "Quarter": "Q1 2025", "BgColor": "#FFC915", "Rank": "5"},
|
|
|
525 |
{"Brand": "Others", "MarketShare": "26%", "Quarter": "Q1 2025", "BgColor": "#6b7280", "Rank": "-"}
|
|
|
526 |
])
|
|
|
527 |
|
|
|
528 |
<div class="container-fluid p-5">
|
|
|
529 |
<div class="row mb-1 my-4 mx-3 justify-content-center">
|
|
|
530 |
<div class="col-10">
|
|
|
531 |
<div class="bg-dark-light rounded-3 p-3 shadow rounded-corner">
|
|
|
532 |
<h1 class="text-white text-center mb-0 fw-bold py-2 fs-8">Brand Analysis </h1>
|
|
|
533 |
</div>
|
|
|
534 |
</div>
|
|
|
535 |
</div>
|
| 35119 |
aman |
536 |
<img src="https://images.smartdukaan.com/uploads/campaigns/image2025-10-03/brand-analysis-note-11759485977860.png"
|
|
|
537 |
class="w-75 p-2 d-block mx-auto"
|
|
|
538 |
alt="note">
|
| 34813 |
aman |
539 |
## ----------------------------------------stagged chart ------------------------------------------
|
|
|
540 |
<div class="container d-flex ">
|
|
|
541 |
<div class="p-5" style=" height: 350px !important;width: 650px !important;">
|
|
|
542 |
<div class="chart-title fs-2 text-center fw-bold">Brands Share Analysis (QTY)</div>
|
|
|
543 |
<canvas id="combinedStackedChart"></canvas>
|
|
|
544 |
</div>
|
|
|
545 |
<div class="" style="width: 400px!important;">
|
|
|
546 |
<div class="right-panel">
|
|
|
547 |
<h4 class="mb-4">Quantity Analysis</h4>
|
|
|
548 |
|
|
|
549 |
<div class="brand-analysis-container">
|
|
|
550 |
<div class="table-responsive">
|
|
|
551 |
<table class="table table-striped table-hover">
|
|
|
552 |
<thead class="table-light table-bordered">
|
|
|
553 |
<tr>
|
|
|
554 |
<th scope="col">Brand Name</th>
|
|
|
555 |
<th scope="col">Available Models</th>
|
|
|
556 |
<th scope="col">Required Models</th>
|
|
|
557 |
<th scope="col" class="text-center">Status</th>
|
|
|
558 |
</tr>
|
|
|
559 |
</thead>
|
|
|
560 |
<tbody class="table-bordered">
|
|
|
561 |
#foreach($brandName in $targetBrands)
|
|
|
562 |
#set($analysis = $brandAnalysisData.get($brandName))
|
|
|
563 |
<tr>
|
|
|
564 |
<td>
|
|
|
565 |
<strong class="brand-name">${brandName}</strong>
|
|
|
566 |
</td>
|
|
|
567 |
<td>
|
|
|
568 |
<span class="quantity-value">${analysis.get('availableQuantity')}</span>
|
|
|
569 |
</td>
|
|
|
570 |
<td>
|
|
|
571 |
<span class="quantity-value">${analysis.get('requiredQuantity')}</span>
|
|
|
572 |
</td>
|
|
|
573 |
<td class="text-center">
|
|
|
574 |
<span class="badge #if($analysis.get('isOK'))bg-success#else bg-danger#end">
|
|
|
575 |
${analysis.get('status')}
|
|
|
576 |
</span>
|
|
|
577 |
</td>
|
|
|
578 |
</tr>
|
|
|
579 |
#end
|
|
|
580 |
</tbody>
|
|
|
581 |
</table>
|
|
|
582 |
</div>
|
|
|
583 |
</div>
|
|
|
584 |
</div>
|
|
|
585 |
</div>
|
|
|
586 |
</div>
|
|
|
587 |
|
|
|
588 |
|
|
|
589 |
## -----------------------------------------------Fast Selling & HID model ------------------------------------------------
|
| 35001 |
aman |
590 |
<div id="brand-table-section">
|
| 34813 |
aman |
591 |
<div class="container-fluid py-3">
|
| 35001 |
aman |
592 |
<div class="card mb-4 p-4">
|
|
|
593 |
<!-- Main Header -->
|
|
|
594 |
<div class="row justify-content-center">
|
| 34813 |
aman |
595 |
<div class="col-10">
|
|
|
596 |
<div class="bg-dark-light rounded-3 p-3 shadow rounded-corner">
|
|
|
597 |
<h3 class="text-white text-center mb-0 fw-bold py-2 fs-8">Fast Selling Models &
|
|
|
598 |
HID </h3>
|
|
|
599 |
</div>
|
|
|
600 |
</div>
|
|
|
601 |
</div>
|
|
|
602 |
|
| 35001 |
aman |
603 |
<div class="card-body">
|
|
|
604 |
<!-- Brand Filter Buttons -->
|
|
|
605 |
<div class="d-flex flex-wrap justify-content-center gap-2 p-3 border-bottom mb-4">
|
|
|
606 |
<!-- Velocity Template Loop for Brands -->
|
| 34813 |
aman |
607 |
#foreach($brand in $brands)
|
| 35001 |
aman |
608 |
<button class="brand-btn" data-brand="$brand.toLowerCase()">$brand</button>
|
| 34813 |
aman |
609 |
#end
|
|
|
610 |
</div>
|
|
|
611 |
|
| 35001 |
aman |
612 |
<!-- HID Section -->
|
|
|
613 |
<div class="section-header">HID</div>
|
| 34813 |
aman |
614 |
|
| 35001 |
aman |
615 |
<div class="table-responsive">
|
|
|
616 |
<table class="table ">
|
|
|
617 |
<thead>
|
|
|
618 |
<tr>
|
|
|
619 |
<th class="w-25">Model</th>
|
|
|
620 |
<th class=" w-25">Suggested Qty</th>
|
|
|
621 |
<th class="w-25">My Stock + Pending Indent</th>
|
|
|
622 |
<th class="w-25">Remarks</th>
|
|
|
623 |
</tr>
|
|
|
624 |
</thead>
|
|
|
625 |
<tbody>
|
|
|
626 |
<!-- Velocity Template Loop for HID Data -->
|
|
|
627 |
#foreach($brand in $brands)
|
|
|
628 |
#if($hidAllocationModelBrandMap.containsKey($brand) && !$hidAllocationModelBrandMap.get($brand).isEmpty())
|
|
|
629 |
#foreach($model in $hidAllocationModelBrandMap.get($brand))
|
|
|
630 |
<tr class="brand-data" data-brand="$brand.toLowerCase()">
|
|
|
631 |
<td><strong>$model.getModelNumber()</strong></td>
|
|
|
632 |
<td class="w-25"><strong>$model.getHidAllocation()</strong></td>
|
|
|
633 |
<td><strong>$model.getAvailableStock()</strong></td>
|
|
|
634 |
<td class="w-25">
|
|
|
635 |
#if($model.getAvailableStock() == 0)
|
|
|
636 |
<span class="text-danger fw-bold">Urgently Required</span>
|
| 34813 |
aman |
637 |
#elseif($model.getAvailableStock() < $model.getHidAllocation())
|
| 35001 |
aman |
638 |
<span class="status-order">Need to Order</span>
|
| 34813 |
aman |
639 |
#else
|
| 35001 |
aman |
640 |
<span class="status-ok fw-bold">Stock OK</span>
|
|
|
641 |
#end
|
|
|
642 |
</td>
|
|
|
643 |
</tr>
|
|
|
644 |
#end
|
|
|
645 |
#else
|
|
|
646 |
<tr class="brand-data no-data-row" data-brand="$brand.toLowerCase()">
|
|
|
647 |
<td colspan="4">No Data Available</td>
|
|
|
648 |
</tr>
|
|
|
649 |
#end
|
|
|
650 |
#end
|
|
|
651 |
</tbody>
|
|
|
652 |
</table>
|
| 34813 |
aman |
653 |
</div>
|
|
|
654 |
|
| 35001 |
aman |
655 |
<!-- Fast Selling Models Section -->
|
|
|
656 |
<div class="section-header">Fast Selling Model</div>
|
| 34813 |
aman |
657 |
|
| 35001 |
aman |
658 |
<div class="table-responsive">
|
|
|
659 |
<table class="table ">
|
|
|
660 |
<tbody>
|
|
|
661 |
<!-- Velocity Template Loop for Fast Selling Data -->
|
|
|
662 |
#if($brandwiseFastmoving && $brandwiseFastmoving.entrySet().size() > 0)
|
|
|
663 |
#foreach($brandEntry in $brandwiseFastmoving.entrySet())
|
|
|
664 |
#foreach($model in $brandEntry.value)
|
|
|
665 |
#set($processingQty = $processingOrderCatalogQtyMap.get($model.getCatalogId()))
|
|
|
666 |
#if(!$processingQty)
|
|
|
667 |
#set($processingQty = 0)
|
|
|
668 |
#end
|
|
|
669 |
#set($totalQty = $model.partnerCurrentQty + $processingQty)
|
|
|
670 |
#set($suggestedQty = 2)
|
| 34813 |
aman |
671 |
|
| 35001 |
aman |
672 |
<tr class="brand-data" data-brand="$brandEntry.key.toLowerCase()">
|
|
|
673 |
<td class="w-25"><strong>$model.modelNumber</strong></td>
|
|
|
674 |
<td class="suggested-qty-col w-25"><strong>$suggestedQty</strong></td>
|
|
|
675 |
<td class="w-25">
|
|
|
676 |
<strong>
|
|
|
677 |
$model.partnerCurrentQty
|
| 34813 |
aman |
678 |
#if($processingOrderCatalogQtyMap.get($model.getCatalogId()))
|
| 35001 |
aman |
679 |
+ $processingOrderCatalogQtyMap.get($model.getCatalogId())
|
| 34813 |
aman |
680 |
#end
|
|
|
681 |
</strong>
|
| 35001 |
aman |
682 |
</td>
|
|
|
683 |
<td class="remarks-col w-25">
|
|
|
684 |
#if($totalQty == 0)
|
|
|
685 |
<span class="text-danger fw-bold">Urgently Required</span>
|
| 34813 |
aman |
686 |
#elseif($totalQty < 2)
|
| 35001 |
aman |
687 |
<span class="status-order">Need to Order</span>
|
| 34813 |
aman |
688 |
#else
|
| 35001 |
aman |
689 |
<span class="status-ok fw-bold">Stock OK</span>
|
|
|
690 |
#end
|
|
|
691 |
</td>
|
|
|
692 |
</tr>
|
|
|
693 |
#end
|
|
|
694 |
#end
|
|
|
695 |
#else
|
|
|
696 |
<tr class="brand-data no-data-row">
|
|
|
697 |
<td colspan="4">No Data Available</td>
|
|
|
698 |
</tr>
|
|
|
699 |
#end
|
|
|
700 |
</tbody>
|
|
|
701 |
</table>
|
|
|
702 |
</div>
|
| 35119 |
aman |
703 |
<div class="section-header">Running Model</div>
|
|
|
704 |
|
|
|
705 |
<div class="table-responsive">
|
|
|
706 |
<table class="table ">
|
|
|
707 |
<tbody>
|
|
|
708 |
<!-- Velocity Template Loop for Fast Selling Data -->
|
|
|
709 |
#if($brandwiseRunningmoving && $brandwiseRunningmoving.entrySet().size() > 0)
|
|
|
710 |
#foreach($brandEntry in $brandwiseRunningmoving.entrySet())
|
|
|
711 |
#foreach($model in $brandEntry.value)
|
|
|
712 |
#set($processingQty = $processingOrderCatalogQtyMap.get($model.getCatalogId()))
|
|
|
713 |
#if(!$processingQty)
|
|
|
714 |
#set($processingQty = 0)
|
|
|
715 |
#end
|
|
|
716 |
#set($totalQty = $model.partnerCurrentQty + $processingQty)
|
|
|
717 |
#set($suggestedQty = 2)
|
|
|
718 |
|
|
|
719 |
<tr class="brand-data" data-brand="$brandEntry.key.toLowerCase()">
|
|
|
720 |
<td class="w-25"><strong>$model.modelNumber</strong></td>
|
|
|
721 |
<td class="suggested-qty-col w-25"><strong>$suggestedQty</strong></td>
|
|
|
722 |
<td class="w-25">
|
|
|
723 |
<strong>
|
|
|
724 |
$model.partnerCurrentQty
|
|
|
725 |
#if($processingOrderCatalogQtyMap.get($model.getCatalogId()))
|
|
|
726 |
+ $processingOrderCatalogQtyMap.get($model.getCatalogId())
|
|
|
727 |
#end
|
|
|
728 |
</strong>
|
|
|
729 |
</td>
|
|
|
730 |
<td class="remarks-col w-25">
|
|
|
731 |
#if($totalQty == 0)
|
|
|
732 |
<span class="text-danger fw-bold">Urgently Required</span>
|
|
|
733 |
#elseif($totalQty < 2)
|
|
|
734 |
<span class="status-order">Need to Order</span>
|
|
|
735 |
#else
|
|
|
736 |
<span class="status-ok fw-bold">Stock OK</span>
|
|
|
737 |
#end
|
|
|
738 |
</td>
|
|
|
739 |
</tr>
|
|
|
740 |
#end
|
|
|
741 |
#end
|
|
|
742 |
#else
|
|
|
743 |
<tr class="brand-data no-data-row">
|
|
|
744 |
<td colspan="4">No Data Available</td>
|
|
|
745 |
</tr>
|
|
|
746 |
#end
|
|
|
747 |
</tbody>
|
|
|
748 |
</table>
|
|
|
749 |
</div>
|
| 34813 |
aman |
750 |
</div>
|
|
|
751 |
</div>
|
|
|
752 |
</div>
|
| 35001 |
aman |
753 |
</div>
|
| 34813 |
aman |
754 |
## -----------------------------------------------My Stock ------------------------------------------------
|
|
|
755 |
<div class="row mb-1 my-4 justify-content-center">
|
|
|
756 |
<div class="col-10">
|
|
|
757 |
<div class=" bg-dark-light rounded-3 p-3 shadow rounded-corner">
|
|
|
758 |
<h1 class="text-center mb-0 fw-bold py-2 text-white fs-8">My Stock</h1>
|
|
|
759 |
</div>
|
|
|
760 |
</div>
|
|
|
761 |
</div>
|
|
|
762 |
|
|
|
763 |
<div class="row px-5" style="margin-left: 10rem !important;">
|
|
|
764 |
<div class="col-md-6">
|
|
|
765 |
<div class="category-header mandatory-header">MANDATORY BRANDS</div>
|
|
|
766 |
|
|
|
767 |
#foreach($brandStockPrice in $brandStockPrices)
|
|
|
768 |
#set($mandatoryBrands = ["Vivo", "Oppo", "Samsung", "Realme"])
|
|
|
769 |
#if($mandatoryBrands.contains($brandStockPrice.getBrand()))
|
|
|
770 |
<div class="brand-item">
|
|
|
771 |
<div class="position-relative" style="z-index: 10">
|
|
|
772 |
<img src="${brandStockPrice.getBrandUrl()}"
|
|
|
773 |
class="brand-circle img-fluid rounded-circle shadow border border-danger"
|
|
|
774 |
data-stockbrand="$brandStockPrice.getBrand()"
|
|
|
775 |
alt="$brandStockPrice.getBrand()">
|
|
|
776 |
</div>
|
|
|
777 |
|
|
|
778 |
<div class="stock-ribbon mandatory-ribbon ms-n3 position-absolute curve ">
|
|
|
779 |
<div class="d-flex d-flex mb-1">
|
|
|
780 |
<span class="fw-bold text-start fs-5">QTY: </span>
|
|
|
781 |
<span class="fw-bold text-start fs-5">$brandStockPrice.getTotalQty()</span>
|
|
|
782 |
</div>
|
|
|
783 |
<div class="d-flex ">
|
|
|
784 |
<span class="fw-bold text-start fs-5">Value: </span>
|
|
|
785 |
<span class="currency fw-bold text-start fs-5"> $nf.format( $brandStockPrice.getTotalValue())</span>
|
|
|
786 |
</div>
|
|
|
787 |
|
|
|
788 |
#if($brandStockPrice.getAgedValue() > 0)
|
|
|
789 |
<div class="aged-stock mt-2 pt-2 border-top border-light border-opacity-25">
|
|
|
790 |
<div class="d-flex justify-content-between">
|
|
|
791 |
<span>Focus Stock:</span>
|
|
|
792 |
<span>
|
|
|
793 |
<span class="currency"> $nf.format($brandStockPrice.getAgedValue()) </span>/
|
|
|
794 |
$brandStockPrice.getAgedQty()
|
|
|
795 |
</span>
|
|
|
796 |
</div>
|
|
|
797 |
</div>
|
|
|
798 |
#end
|
|
|
799 |
</div>
|
|
|
800 |
</div>
|
|
|
801 |
#end
|
|
|
802 |
#end
|
|
|
803 |
</div>
|
|
|
804 |
|
|
|
805 |
<div class="col-md-6">
|
|
|
806 |
<div class="category-header other-header">OTHER BRANDS</div>
|
|
|
807 |
#set($mandatoryBrands = ["Vivo", "Oppo", "Samsung", "Realme"])
|
|
|
808 |
|
|
|
809 |
#foreach($brandStockPrice in $brandStockPrices)
|
|
|
810 |
#if(!$mandatoryBrands.contains($brandStockPrice.getBrand()))
|
|
|
811 |
<div class="brand-item">
|
|
|
812 |
<div class="position-relative " style="z-index: 10">
|
|
|
813 |
<img src="${brandStockPrice.getBrandUrl()}"
|
|
|
814 |
class="brand-circle img-fluid rounded-circle shadow border border-dark"
|
|
|
815 |
data-stockbrand="$brandStockPrice.getBrand()"
|
|
|
816 |
alt="$brandStockPrice.getBrand()">
|
|
|
817 |
</div>
|
|
|
818 |
|
|
|
819 |
<div class="stock-ribbon other-ribbon ms-n3 position-absolute curve">
|
|
|
820 |
<div class="d-flex d-flex mb-1">
|
|
|
821 |
<span class="fw-bold text-start fs-5">QTY: </span>
|
|
|
822 |
<span class="fw-bold text-start fs-5">$brandStockPrice.getTotalQty()</span>
|
|
|
823 |
</div>
|
|
|
824 |
<div class="d-flex ">
|
|
|
825 |
<span class="fw-bold text-start fs-5">Value: </span>
|
|
|
826 |
<span class="currency fw-bold text-start fs-5"> $nf.format($brandStockPrice.getTotalValue())</span>
|
|
|
827 |
</div>
|
|
|
828 |
|
|
|
829 |
#if($brandStockPrice.getAgedValue() > 0)
|
|
|
830 |
<div class="aged-stock mt-2 pt-2 border-top border-light border-opacity-25">
|
|
|
831 |
<div class="d-flex justify-content-between">
|
|
|
832 |
<span>Focus Stock:</span>
|
|
|
833 |
<span>
|
|
|
834 |
<span class="currency"> $nf.format($brandStockPrice.getAgedValue())</span>/
|
|
|
835 |
$brandStockPrice.getAgedQty()
|
|
|
836 |
</span>
|
|
|
837 |
</div>
|
|
|
838 |
</div>
|
|
|
839 |
#end
|
|
|
840 |
</div>
|
|
|
841 |
</div>
|
|
|
842 |
#end
|
|
|
843 |
#end
|
|
|
844 |
</div>
|
|
|
845 |
</div>
|
|
|
846 |
|
|
|
847 |
## ------------------------------------my stock ageing---------------------------------
|
|
|
848 |
|
|
|
849 |
<div class="card shadow-lg rounded-3">
|
|
|
850 |
<div class="row mb-1 my-4 justify-content-center">
|
|
|
851 |
<div class="col-10">
|
|
|
852 |
<div class="bg-dark-light rounded-3 p-3 shadow rounded-corner">
|
|
|
853 |
<h1 class="text-white text-center mb-0 fw-bold py-2 fs-8">My Stock Ageing</h1>
|
|
|
854 |
</div>
|
|
|
855 |
</div>
|
|
|
856 |
</div>
|
|
|
857 |
<div class="card-body">
|
|
|
858 |
<div class="row mb-4">
|
|
|
859 |
<div class="col-md-4">
|
|
|
860 |
<div class="btn-group" role="group">
|
|
|
861 |
<button type="button" class="btn btn-danger rounded-pill px-4 me-2 fs-5" id="btnVolume">
|
|
|
862 |
Volume
|
|
|
863 |
</button>
|
|
|
864 |
<button type="button" class="btn btn-danger rounded-pill px-4 fs-5" id="btnValue">Value
|
|
|
865 |
</button>
|
|
|
866 |
</div>
|
|
|
867 |
</div>
|
|
|
868 |
</div>
|
|
|
869 |
|
|
|
870 |
<div class="table-responsive rounded-5 p-5">
|
|
|
871 |
<table class="table table-bordered rounded-4" id="stockAgingTable">
|
|
|
872 |
<thead>
|
| 35001 |
aman |
873 |
<tr class="text-center ">
|
| 34813 |
aman |
874 |
<th></th>
|
| 35001 |
aman |
875 |
<th class="align-middle text-white fs-5 fw-bold" style="width: 180px;">
|
| 34813 |
aman |
876 |
Brands
|
|
|
877 |
</th>
|
|
|
878 |
#set($intervals = ["Less Than 15 Days", "16 - 30 Days", "31 - 45 Days",
|
|
|
879 |
"More Than 45 Days"])
|
|
|
880 |
#foreach($interval in $intervals)
|
| 35001 |
aman |
881 |
<th class="align-middle fs-5 fw-bold text-wrap"
|
| 34813 |
aman |
882 |
style="width: 180px;height: 55px !important; word-wrap: break-word; white-space: normal;">
|
| 35001 |
aman |
883 |
<span class="text-white text-wrap ">$interval</span>
|
| 34813 |
aman |
884 |
</th>
|
|
|
885 |
#end
|
|
|
886 |
</tr>
|
|
|
887 |
</thead>
|
|
|
888 |
<tbody>
|
|
|
889 |
#if(!$inventoryGroupedByBrand.isEmpty())
|
|
|
890 |
#set($mandatoryBrands = ["vivo", "oppo", "samsung", "realme"])
|
|
|
891 |
#set($otherBrands = [])
|
|
|
892 |
|
|
|
893 |
<tr>
|
|
|
894 |
<td class="align-middle bg-secondary text-center text-white fw-bold " rowspan="5"
|
|
|
895 |
style="width: 60px !important; font-size: 10px !important;">
|
|
|
896 |
<div class="brandText">MANDATORY BRANDS</div>
|
|
|
897 |
</td>
|
|
|
898 |
</tr>
|
|
|
899 |
|
|
|
900 |
#foreach($brandKey in $mandatoryBrands)
|
|
|
901 |
#set($found = false)
|
|
|
902 |
#foreach($entry in $inventoryGroupedByBrand.entrySet())
|
|
|
903 |
#if($entry.getKey().toLowerCase() == $brandKey)
|
|
|
904 |
#set($found = true)
|
|
|
905 |
<tr>
|
|
|
906 |
<td class="brand-cell text-start p-0">
|
| 35001 |
aman |
907 |
<div class="p-3 bg-white #getBrandBgColor($entry.getKey())"
|
| 34813 |
aman |
908 |
style="height: 40px; display: flex; align-items: center; justify-content: start;">
|
| 35001 |
aman |
909 |
<span class="text-black fw-bold fs-5"><img
|
| 34813 |
aman |
910 |
src="$brandLogos.getOrDefault($entry.getKey(),
|
|
|
911 |
'https://static.vecteezy.com/system/resources/thumbnails/025/213/042/small_2x/mobile-phone-icon-in-black-circle-png.png')"
|
|
|
912 |
alt="$entry.getKey() logo"
|
|
|
913 |
class="brand-logo rounded-circle me-3"
|
|
|
914 |
style="width:35px;height:35px">$entry.getKey()</span>
|
|
|
915 |
</div>
|
|
|
916 |
</td>
|
|
|
917 |
#foreach($i in [0..3])
|
|
|
918 |
<td class="align-middle text-center $bgColors.get($i)"
|
|
|
919 |
style="opacity: 0.9;">
|
|
|
920 |
#set($qty = 0)
|
|
|
921 |
#set($value = 0)
|
|
|
922 |
#foreach($item in $entry.getValue())
|
|
|
923 |
#if($i < $item.getValues().size() && $item.getValues().get($i))
|
|
|
924 |
#set($qty = $math.add($qty, $item.getValues().get($i).getQuantity()))
|
|
|
925 |
#set($itemValue = $math.mul($item.getValues().get($i).getPrice(), $item.getValues().get($i).getQuantity()))
|
|
|
926 |
#set($value = $math.add($value, $itemValue))
|
|
|
927 |
#end
|
|
|
928 |
#end
|
| 35001 |
aman |
929 |
<div class="volume-view fs-5 fw-bold text-black ">$qty</div>
|
|
|
930 |
<div class="value-view currency fs-5 fw-bold text-black"
|
| 34813 |
aman |
931 |
style="display: none;"> $nf.format( $value)</div>
|
|
|
932 |
</td>
|
|
|
933 |
#end
|
|
|
934 |
</tr>
|
|
|
935 |
#end
|
|
|
936 |
#end
|
|
|
937 |
|
|
|
938 |
#if(!$found)
|
|
|
939 |
<tr>
|
|
|
940 |
<td class="brand-cell text-center p-0">
|
| 35001 |
aman |
941 |
<div class="p-3 bg-white"
|
| 34813 |
aman |
942 |
style="height: 40px; display: flex; align-items: center; justify-content: center;">
|
| 35001 |
aman |
943 |
<span class="text-black fw-bold">$brandKey</span>
|
| 34813 |
aman |
944 |
</div>
|
|
|
945 |
</td>
|
|
|
946 |
#foreach($i in [0..3])
|
|
|
947 |
<td class="text-center align-middle $bgColors.get($i)"
|
|
|
948 |
style="opacity: 0.9;">
|
| 35001 |
aman |
949 |
<div class="volume-view fs-5 fw-bold text-black">0</div>
|
|
|
950 |
<div class="value-view currency fs-5 fw-bold text-black"
|
| 34813 |
aman |
951 |
style="display: none;">0.00
|
|
|
952 |
</div>
|
|
|
953 |
</td>
|
|
|
954 |
#end
|
|
|
955 |
</tr>
|
|
|
956 |
#end
|
|
|
957 |
#end
|
|
|
958 |
|
|
|
959 |
<tr>
|
|
|
960 |
<td class="align-middle bg-dark-light text-center text-white fw-bold "
|
|
|
961 |
rowspan="$inventoryGroupedByBrand.size()"
|
|
|
962 |
style="width: 60px !important; font-size: 10px !important;">
|
|
|
963 |
<div class="brandText">OTHER BRANDS</div>
|
|
|
964 |
</td>
|
|
|
965 |
</tr>
|
|
|
966 |
|
|
|
967 |
#foreach($entry in $inventoryGroupedByBrand.entrySet())
|
|
|
968 |
#set($isOtherBrand = true)
|
|
|
969 |
#foreach($mandatoryBrand in $mandatoryBrands)
|
|
|
970 |
#if($entry.getKey().toLowerCase() == $mandatoryBrand)
|
|
|
971 |
#set($isOtherBrand = false)
|
|
|
972 |
#break
|
|
|
973 |
#end
|
|
|
974 |
#end
|
|
|
975 |
|
|
|
976 |
#if($isOtherBrand)
|
|
|
977 |
<tr>
|
|
|
978 |
<td class="brand-cell text-start p-0">
|
| 35001 |
aman |
979 |
<div class="p-3 text-black"
|
| 34813 |
aman |
980 |
style="height: 40px; display: flex; align-items: center; justify-content: start;">
|
| 35001 |
aman |
981 |
<span class="text-black fw-bold fs-5 "><img
|
| 34813 |
aman |
982 |
src="$brandLogos.getOrDefault($entry.getKey(),
|
|
|
983 |
'https://static.vecteezy.com/system/resources/thumbnails/025/213/042/small_2x/mobile-phone-icon-in-black-circle-png.png')"
|
|
|
984 |
alt="$entry.getKey() logo"
|
|
|
985 |
class="brand-logo rounded-circle me-3"
|
|
|
986 |
style="width:35px;height:35px">$entry.getKey()</span>
|
|
|
987 |
</div>
|
|
|
988 |
</td>
|
|
|
989 |
#foreach($i in [0..3])
|
|
|
990 |
<td class="text-center align-middle pb-4 $bgColors.get($i)"
|
|
|
991 |
style="opacity: 0.9;">
|
|
|
992 |
#set($qty = 0)
|
|
|
993 |
#set($value = 0)
|
|
|
994 |
#foreach($item in $entry.getValue())
|
|
|
995 |
#if($i < $item.getValues().size() && $item.getValues().get($i))
|
|
|
996 |
#set($qty = $math.add($qty, $item.getValues().get($i).getQuantity()))
|
|
|
997 |
#set($itemValue = $math.mul($item.getValues().get($i).getPrice(), $item.getValues().get($i).getQuantity()))
|
|
|
998 |
#set($value = $math.add($value, $itemValue))
|
|
|
999 |
#end
|
|
|
1000 |
#end
|
| 35001 |
aman |
1001 |
<div class="volume-view fs-5 fw-bold text-black">$qty</div>
|
|
|
1002 |
<div class="value-view currency fs-5 fw-bold text-black"
|
| 34813 |
aman |
1003 |
style="display: none;"> $nf.format($value)</div>
|
|
|
1004 |
</td>
|
|
|
1005 |
#end
|
|
|
1006 |
</tr>
|
|
|
1007 |
#end
|
|
|
1008 |
#end
|
|
|
1009 |
#else
|
|
|
1010 |
<tr>
|
|
|
1011 |
<td colspan="6" class="text-center">No inventory data available</td>
|
|
|
1012 |
</tr>
|
|
|
1013 |
#end
|
|
|
1014 |
</tbody>
|
|
|
1015 |
</table>
|
|
|
1016 |
</div>
|
|
|
1017 |
<div class="d-flex justify-content-center mt-5 ">
|
|
|
1018 |
<button type="button" class="btn-sm btn-danger fs-2 fw-bold px-4" data-dismiss="modal">X CLOSE
|
|
|
1019 |
</button>
|
|
|
1020 |
</div>
|
|
|
1021 |
</div>
|
|
|
1022 |
</div>
|
|
|
1023 |
</section>
|
|
|
1024 |
</div>
|
|
|
1025 |
</body>
|
|
|
1026 |
<script>
|
|
|
1027 |
var chart;
|
| 35001 |
aman |
1028 |
var brandColors = {
|
| 34813 |
aman |
1029 |
'vivo': '#2196F3',
|
|
|
1030 |
'oppo': '#006b35',
|
|
|
1031 |
'samsung': '#1428A0',
|
|
|
1032 |
'realme': '#FFC107',
|
|
|
1033 |
'xiaomi': '#FF5722',
|
|
|
1034 |
'apple': '#666666',
|
|
|
1035 |
'poco': '#FFD403',
|
|
|
1036 |
'tecno': '#0064FE',
|
|
|
1037 |
'lava': '#ED0F53'
|
|
|
1038 |
};
|
|
|
1039 |
|
|
|
1040 |
|
|
|
1041 |
function loadMonthDetails(monthIndex) {
|
|
|
1042 |
console.log(`Loading details for month: ${monthIndex}`);
|
|
|
1043 |
doGetAjaxRequestHandler(`${context}/monthWisePartnerIncome/${monthIndex}?partnerTask=true`, function (response) {
|
|
|
1044 |
$('.bootbox.modal .modal-body .bootbox-body').empty();
|
|
|
1045 |
$('#partner-income').html(response);
|
|
|
1046 |
const $section = $('#ajaxSection');
|
|
|
1047 |
});
|
|
|
1048 |
}
|
|
|
1049 |
|
|
|
1050 |
$(document).on("click", ".pending-income", function () {
|
|
|
1051 |
lastMonthCreditIncome("main-content");
|
|
|
1052 |
});
|
|
|
1053 |
|
|
|
1054 |
function doGetAjaxRequestHandler(url, successCallback) {
|
|
|
1055 |
$.ajax({
|
|
|
1056 |
url: url,
|
|
|
1057 |
type: 'GET',
|
|
|
1058 |
success: successCallback,
|
|
|
1059 |
error: function (xhr, status, error) {
|
|
|
1060 |
console.error("AJAX request failed:", error);
|
|
|
1061 |
}
|
|
|
1062 |
});
|
|
|
1063 |
}
|
|
|
1064 |
|
|
|
1065 |
$(function () {
|
|
|
1066 |
$('#reportrange').daterangepicker(getRangedDatePicker());
|
|
|
1067 |
});
|
|
|
1068 |
$(document).ready(function () {
|
|
|
1069 |
|
|
|
1070 |
$("#btnVolume").addClass("active");
|
|
|
1071 |
|
|
|
1072 |
$("#btnVolume").click(function () {
|
|
|
1073 |
$(this).addClass("active");
|
|
|
1074 |
$("#btnValue").removeClass("active");
|
|
|
1075 |
$(".volume-view").show();
|
|
|
1076 |
$(".value-view").hide();
|
|
|
1077 |
});
|
|
|
1078 |
|
|
|
1079 |
$("#btnValue").click(function () {
|
|
|
1080 |
$(this).addClass("active");
|
|
|
1081 |
$("#btnVolume").removeClass("active");
|
|
|
1082 |
$(".volume-view").hide();
|
|
|
1083 |
$(".value-view").show();
|
|
|
1084 |
});
|
|
|
1085 |
});
|
|
|
1086 |
document.querySelectorAll('.brand-btn').forEach(button => {
|
|
|
1087 |
button.addEventListener('click', function () {
|
| 35001 |
aman |
1088 |
const brand = this.getAttribute('data-brand');
|
|
|
1089 |
|
|
|
1090 |
document.querySelectorAll('.brand-btn').forEach(btn => {
|
|
|
1091 |
btn.style.backgroundColor = '';
|
|
|
1092 |
btn.style.color = '';
|
| 34813 |
aman |
1093 |
});
|
| 35001 |
aman |
1094 |
this.style.backgroundColor = '#006b35';
|
|
|
1095 |
this.style.color = 'white';
|
|
|
1096 |
|
|
|
1097 |
document.querySelectorAll('.brand-data').forEach(item => {
|
|
|
1098 |
item.style.display = item.getAttribute('data-brand') === brand ? 'table-row' : 'none';
|
|
|
1099 |
});
|
| 34813 |
aman |
1100 |
});
|
|
|
1101 |
});
|
| 35001 |
aman |
1102 |
document.querySelector('.brand-btn')?.click();
|
| 34813 |
aman |
1103 |
|
|
|
1104 |
function initializeBrandButtons() {
|
|
|
1105 |
const brandButtons = document.querySelectorAll('.brand-btn');
|
|
|
1106 |
|
|
|
1107 |
brandButtons.forEach(button => {
|
| 34898 |
aman |
1108 |
const brand = button.dataset.brand;
|
| 34813 |
aman |
1109 |
const color = brandColors[brand] || '#666';
|
|
|
1110 |
|
|
|
1111 |
button.style.border = `2px solid ${color}`;
|
|
|
1112 |
button.style.color = color;
|
|
|
1113 |
button.style.backgroundColor = '#fff';
|
|
|
1114 |
});
|
|
|
1115 |
|
|
|
1116 |
brandButtons.forEach(button => {
|
|
|
1117 |
button.addEventListener('click', function () {
|
|
|
1118 |
const selectedBrand = this.dataset.brand;
|
|
|
1119 |
|
|
|
1120 |
brandButtons.forEach(btn => {
|
|
|
1121 |
btn.style.backgroundColor = '#fff';
|
| 35001 |
aman |
1122 |
btn.style.color = '#666';
|
| 34813 |
aman |
1123 |
});
|
|
|
1124 |
|
|
|
1125 |
this.style.backgroundColor = brandColors[selectedBrand] || '#666';
|
|
|
1126 |
this.style.color = '#fff';
|
|
|
1127 |
|
|
|
1128 |
document.querySelectorAll('.brand-data').forEach(row => {
|
| 35001 |
aman |
1129 |
row.style.display = row.dataset.brand === selectedBrand ? 'inline-masonry' : 'none';
|
| 34813 |
aman |
1130 |
});
|
|
|
1131 |
});
|
|
|
1132 |
});
|
|
|
1133 |
brandButtons[0]?.click();
|
|
|
1134 |
}
|
|
|
1135 |
|
|
|
1136 |
initializeBrandButtons();
|
|
|
1137 |
|
|
|
1138 |
</script>
|
|
|
1139 |
<script>
|
|
|
1140 |
document.querySelectorAll('.brand-btn').forEach(button => {
|
|
|
1141 |
button.addEventListener('click', function () {
|
|
|
1142 |
const brand = this.getAttribute('data-brand');
|
|
|
1143 |
|
|
|
1144 |
document.querySelectorAll('.brand-btn').forEach(btn => {
|
|
|
1145 |
btn.style.backgroundColor = '';
|
|
|
1146 |
btn.style.color = '';
|
|
|
1147 |
});
|
|
|
1148 |
this.style.backgroundColor = '#006b35';
|
|
|
1149 |
this.style.color = 'white';
|
|
|
1150 |
|
|
|
1151 |
document.querySelectorAll('.brand-data').forEach(item => {
|
| 35001 |
aman |
1152 |
item.style.display = item.getAttribute('data-brand') === brand ? 'inline-masonry' : 'none';
|
| 34813 |
aman |
1153 |
});
|
|
|
1154 |
});
|
|
|
1155 |
});
|
|
|
1156 |
document.querySelector('.brand-btn')?.click();
|
|
|
1157 |
</script>
|
|
|
1158 |
|
|
|
1159 |
##-------------------------------------------------------------------My Earning chart -----------------------------------------
|
|
|
1160 |
<script>
|
|
|
1161 |
$(document).ready(function () {
|
|
|
1162 |
// loadMonthDetails(0);
|
|
|
1163 |
const monthData = [
|
|
|
1164 |
#foreach( $item in $summaryList )
|
|
|
1165 |
{
|
|
|
1166 |
month: "$!item.monthValueMap[$item.monthIndex]",
|
|
|
1167 |
monthIndex: "$item.monthIndex",
|
|
|
1168 |
total: $item.get('totalIncome'),
|
|
|
1169 |
credited: $item.get('creditedIncome'),
|
|
|
1170 |
pending: $item.get('pendingIncome')
|
|
|
1171 |
}
|
|
|
1172 |
#if($foreach.hasNext),#end
|
|
|
1173 |
#end
|
|
|
1174 |
].reverse();
|
|
|
1175 |
|
|
|
1176 |
const formatIndianCurrency = (amount) => {
|
|
|
1177 |
const rounded = Math.round(amount);
|
|
|
1178 |
return rounded.toLocaleString('en-IN');
|
|
|
1179 |
};
|
|
|
1180 |
|
|
|
1181 |
monthData.forEach(item => {
|
|
|
1182 |
item.totalFormatted = formatIndianCurrency(item.total);
|
|
|
1183 |
item.creditedFormatted = formatIndianCurrency(item.credited);
|
|
|
1184 |
item.pendingFormatted = formatIndianCurrency(item.pending);
|
|
|
1185 |
});
|
|
|
1186 |
chart = new Chart(document.getElementById('sixMonthChart'), {
|
|
|
1187 |
type: 'bar',
|
|
|
1188 |
data: {
|
|
|
1189 |
labels: monthData.map(d => d.month),
|
|
|
1190 |
datasets: [
|
|
|
1191 |
{
|
|
|
1192 |
label: 'Credited Income',
|
|
|
1193 |
data: monthData.map(d => Math.round(d.credited)),
|
|
|
1194 |
backgroundColor: '#aadcb4',
|
|
|
1195 |
borderColor: '#aadcb4',
|
|
|
1196 |
borderWidth: 1,
|
|
|
1197 |
barThickness: 30,
|
|
|
1198 |
hitRadius: 30,
|
|
|
1199 |
order: 1,
|
|
|
1200 |
yAxisID: 'y',
|
|
|
1201 |
hoverBorderWidth: 3,
|
|
|
1202 |
hoverBorderColor: '#aadcb4'
|
|
|
1203 |
},
|
|
|
1204 |
{
|
|
|
1205 |
label: 'Pending Income',
|
|
|
1206 |
data: monthData.map(d => Math.round(d.pending)),
|
|
|
1207 |
backgroundColor: 'rgba(255,0,0,0.7)',
|
|
|
1208 |
borderColor: 'rgba(255,0,0,1)',
|
|
|
1209 |
borderWidth: 1,
|
|
|
1210 |
barThickness: 30,
|
|
|
1211 |
order: 2,
|
|
|
1212 |
hitRadius: 0,
|
|
|
1213 |
yAxisID: 'y',
|
|
|
1214 |
hoverBorderWidth: 3,
|
|
|
1215 |
hoverBorderColor: '#ff0000'
|
|
|
1216 |
},
|
|
|
1217 |
{
|
|
|
1218 |
label: 'Total Income',
|
|
|
1219 |
data: monthData.map(d => Math.round(d.total)),
|
|
|
1220 |
borderColor: '#4bc0c0',
|
|
|
1221 |
backgroundColor: 'rgba(75, 192, 192, 0.1)',
|
|
|
1222 |
borderWidth: 4,
|
|
|
1223 |
type: 'line',
|
|
|
1224 |
order: 3,
|
|
|
1225 |
pointRadius: 6,
|
|
|
1226 |
pointHoverRadius: 0,
|
|
|
1227 |
pointHitRadius: 0,
|
|
|
1228 |
pointBackgroundColor: '#4bc0c0',
|
|
|
1229 |
pointBorderColor: '#ffffff',
|
|
|
1230 |
pointBorderWidth: 2,
|
|
|
1231 |
yAxisID: 'y',
|
|
|
1232 |
tension: 0.3
|
|
|
1233 |
}
|
|
|
1234 |
|
|
|
1235 |
]
|
|
|
1236 |
},
|
|
|
1237 |
options: {
|
|
|
1238 |
responsive: true,
|
|
|
1239 |
maintainAspectRatio: true,
|
|
|
1240 |
interaction: {
|
|
|
1241 |
mode: 'point',
|
|
|
1242 |
intersect: true,
|
|
|
1243 |
},
|
|
|
1244 |
plugins: {
|
|
|
1245 |
datalabels: {
|
|
|
1246 |
formatter: function (value) {
|
|
|
1247 |
return Math.round(value).toLocaleString('en-IN');
|
|
|
1248 |
},
|
|
|
1249 |
color: '#fff',
|
|
|
1250 |
backgroundColor: '#333',
|
|
|
1251 |
borderRadius: 4,
|
|
|
1252 |
padding: 4,
|
| 34898 |
aman |
1253 |
font: {weight: 'bold'},
|
| 34813 |
aman |
1254 |
display: function (context) {
|
| 34898 |
aman |
1255 |
const datasetLabel = context.dataset.label;
|
| 34813 |
aman |
1256 |
const rawValue = context.dataset.data[context.dataIndex];
|
| 34898 |
aman |
1257 |
if (!rawValue || rawValue === 0) return false;
|
|
|
1258 |
if (datasetLabel === 'Credited Income') {
|
|
|
1259 |
const total = context.chart.data.datasets
|
|
|
1260 |
.find(d => d.label === 'Total Income')
|
|
|
1261 |
.data[context.dataIndex];
|
|
|
1262 |
if (Math.round(total) === Math.round(rawValue)) return false;
|
|
|
1263 |
}
|
|
|
1264 |
return true;
|
|
|
1265 |
}
|
| 34813 |
aman |
1266 |
},
|
|
|
1267 |
tooltip: {
|
|
|
1268 |
mode: 'index',
|
|
|
1269 |
intersect: false,
|
|
|
1270 |
backgroundColor: 'rgba(0, 0, 0, 0.9)',
|
|
|
1271 |
titleColor: '#ffffff',
|
|
|
1272 |
bodyColor: '#ffffff',
|
|
|
1273 |
borderColor: '#4bc0c0',
|
|
|
1274 |
borderWidth: 2,
|
|
|
1275 |
displayColors: true,
|
|
|
1276 |
padding: 12,
|
|
|
1277 |
boxWidth: 15,
|
|
|
1278 |
boxHeight: 15,
|
|
|
1279 |
cornerRadius: 8,
|
|
|
1280 |
usePointStyle: true,
|
|
|
1281 |
bodyFont: {
|
|
|
1282 |
size: 14,
|
| 34898 |
aman |
1283 |
weight: 'bold'
|
| 34813 |
aman |
1284 |
},
|
|
|
1285 |
titleFont: {
|
|
|
1286 |
size: 16,
|
|
|
1287 |
weight: 'bold'
|
|
|
1288 |
},
|
|
|
1289 |
footerFont: {
|
|
|
1290 |
size: 12,
|
| 34898 |
aman |
1291 |
weight: 'bold'
|
| 34813 |
aman |
1292 |
},
|
|
|
1293 |
callbacks: {
|
|
|
1294 |
title: function (context) {
|
|
|
1295 |
return `Month: ${context[0].label}`;
|
|
|
1296 |
},
|
|
|
1297 |
label: function (context) {
|
|
|
1298 |
const value = context.parsed.y;
|
|
|
1299 |
const roundedValue = Math.round(value);
|
|
|
1300 |
const formattedValue = roundedValue.toLocaleString('en-IN');
|
|
|
1301 |
|
|
|
1302 |
const label = context.dataset.label;
|
|
|
1303 |
return `${label}: ${formattedValue}`;
|
|
|
1304 |
},
|
|
|
1305 |
footer: function (tooltipItems) {
|
|
|
1306 |
const credited = tooltipItems.find(item => item.dataset.label === 'Credited Income')?.parsed.y || 0;
|
|
|
1307 |
const total = tooltipItems.find(item => item.dataset.label === 'Total Income')?.parsed.y || 0;
|
|
|
1308 |
if (total > 0) {
|
|
|
1309 |
const percentage = ((credited / total) * 100).toFixed(1);
|
|
|
1310 |
return `Credited: ${percentage}% of total income`;
|
|
|
1311 |
}
|
|
|
1312 |
return '';
|
|
|
1313 |
},
|
|
|
1314 |
labelColor: function (context) {
|
|
|
1315 |
return {
|
|
|
1316 |
borderColor: 'transparent',
|
|
|
1317 |
backgroundColor: context.dataset.borderColor,
|
|
|
1318 |
borderRadius: 4,
|
|
|
1319 |
borderWidth: 2
|
|
|
1320 |
};
|
|
|
1321 |
},
|
|
|
1322 |
labelTextColor: function (context) {
|
| 34898 |
aman |
1323 |
return '#ffffff';
|
| 34813 |
aman |
1324 |
}
|
|
|
1325 |
}
|
|
|
1326 |
},
|
|
|
1327 |
legend: {
|
|
|
1328 |
display: true,
|
|
|
1329 |
position: 'top',
|
|
|
1330 |
labels: {
|
|
|
1331 |
usePointStyle: true,
|
|
|
1332 |
padding: 20,
|
|
|
1333 |
font: {
|
|
|
1334 |
size: 14,
|
|
|
1335 |
weight: 'bold'
|
|
|
1336 |
},
|
|
|
1337 |
color: '#333',
|
|
|
1338 |
boxWidth: 15,
|
|
|
1339 |
boxHeight: 15
|
|
|
1340 |
}
|
|
|
1341 |
}
|
|
|
1342 |
},
|
|
|
1343 |
scales: {
|
|
|
1344 |
x: {
|
|
|
1345 |
|
|
|
1346 |
ticks: {
|
|
|
1347 |
|
|
|
1348 |
autoSkip: false,
|
|
|
1349 |
font: {
|
|
|
1350 |
size: 12,
|
|
|
1351 |
weight: 'bold'
|
|
|
1352 |
},
|
|
|
1353 |
color: '#333',
|
|
|
1354 |
padding: 10
|
|
|
1355 |
}
|
|
|
1356 |
},
|
|
|
1357 |
y: {
|
|
|
1358 |
type: 'linear',
|
|
|
1359 |
display: true,
|
|
|
1360 |
position: 'left',
|
|
|
1361 |
stacked: false,
|
|
|
1362 |
beginAtZero: true,
|
|
|
1363 |
grid: {
|
|
|
1364 |
color: 'rgba(0, 0, 0, 0.1)',
|
|
|
1365 |
lineWidth: 1
|
|
|
1366 |
},
|
|
|
1367 |
ticks: {
|
|
|
1368 |
callback: function (value) {
|
|
|
1369 |
// Round the value first, then format
|
|
|
1370 |
const roundedValue = Math.round(value);
|
|
|
1371 |
return roundedValue.toLocaleString('en-IN');
|
|
|
1372 |
},
|
|
|
1373 |
font: {
|
|
|
1374 |
size: 12,
|
|
|
1375 |
weight: 'bold'
|
|
|
1376 |
},
|
|
|
1377 |
color: '#333'
|
|
|
1378 |
}
|
|
|
1379 |
}
|
|
|
1380 |
},
|
|
|
1381 |
elements: {
|
|
|
1382 |
bar: {
|
|
|
1383 |
borderRadius: 4,
|
|
|
1384 |
categoryPercentage: 0.8,
|
|
|
1385 |
barPercentage: 0.9
|
|
|
1386 |
},
|
|
|
1387 |
line: {
|
|
|
1388 |
borderJoinStyle: 'round'
|
|
|
1389 |
},
|
|
|
1390 |
point: {
|
|
|
1391 |
hoverBorderWidth: 1
|
|
|
1392 |
}
|
|
|
1393 |
},
|
|
|
1394 |
onHover: function (event, elements) {
|
|
|
1395 |
event.native.target.style.cursor = elements.length > 0 ? 'pointer' : 'default';
|
|
|
1396 |
},
|
|
|
1397 |
onClick: function (event, elements) {
|
|
|
1398 |
if (elements && elements.length > 0) {
|
|
|
1399 |
const clickedIndex = elements[0].index;
|
|
|
1400 |
const clickedData = monthData[clickedIndex];
|
|
|
1401 |
|
|
|
1402 |
event.chart.canvas.style.cursor = 'wait';
|
|
|
1403 |
|
|
|
1404 |
console.log(`Loading details for month: ${clickedData.monthIndex} (${clickedData.month})`);
|
|
|
1405 |
|
|
|
1406 |
loadMonthDetails(clickedData.monthIndex);
|
|
|
1407 |
|
|
|
1408 |
setTimeout(() => {
|
|
|
1409 |
document.getElementById('partner-income').scrollIntoView({
|
|
|
1410 |
behavior: 'smooth',
|
|
|
1411 |
block: 'start'
|
|
|
1412 |
});
|
|
|
1413 |
event.chart.canvas.style.cursor = 'pointer';
|
|
|
1414 |
}, 300);
|
|
|
1415 |
}
|
|
|
1416 |
}
|
|
|
1417 |
}
|
|
|
1418 |
});
|
|
|
1419 |
})
|
|
|
1420 |
</script>
|
|
|
1421 |
##-----------------------------------------------------------------------Stagged CHart ---------------------------------
|
|
|
1422 |
<script>
|
|
|
1423 |
$(document).ready(function () {
|
|
|
1424 |
const MAJOR_BRANDS = ['vivo', 'samsung', 'oppo', 'realme', 'xiaomi'];
|
|
|
1425 |
|
|
|
1426 |
const marketSegments = [];
|
|
|
1427 |
const otherMarketData = {
|
|
|
1428 |
brand: "Others",
|
|
|
1429 |
marketShare: 0,
|
|
|
1430 |
color: '#6b7280'
|
|
|
1431 |
};
|
|
|
1432 |
|
|
|
1433 |
const stockSegments = [];
|
|
|
1434 |
const otherStockData = {
|
|
|
1435 |
brand: "Others",
|
|
|
1436 |
quantity: 0,
|
|
|
1437 |
value: 0
|
|
|
1438 |
};
|
|
|
1439 |
|
|
|
1440 |
#foreach($entry in $marketShareData)
|
|
|
1441 |
var marketBrandName = '$entry.Brand'.toLowerCase();
|
|
|
1442 |
if (MAJOR_BRANDS.includes(marketBrandName)) {
|
|
|
1443 |
marketSegments.push({
|
|
|
1444 |
brand: marketBrandName,
|
|
|
1445 |
marketShare: ${entry.MarketShare.replace('%', '')},
|
|
|
1446 |
color: '$entry.BgColor'
|
|
|
1447 |
});
|
|
|
1448 |
} else {
|
|
|
1449 |
otherMarketData.marketShare += ${entry.MarketShare.replace('%', '')};
|
|
|
1450 |
}
|
|
|
1451 |
#end
|
|
|
1452 |
|
|
|
1453 |
#foreach($brandStockPrice in $brandStockPrices)
|
|
|
1454 |
var stockBrandName = "$brandStockPrice.getBrand()".toLowerCase();
|
|
|
1455 |
if (MAJOR_BRANDS.includes(stockBrandName)) {
|
|
|
1456 |
stockSegments.push({
|
|
|
1457 |
brand: stockBrandName,
|
|
|
1458 |
quantity: $brandStockPrice.getTotalQty(),
|
|
|
1459 |
value: $brandStockPrice.getTotalValue()
|
|
|
1460 |
});
|
|
|
1461 |
} else {
|
|
|
1462 |
otherStockData.quantity += $brandStockPrice.getTotalQty();
|
|
|
1463 |
otherStockData.value += $brandStockPrice.getTotalValue();
|
|
|
1464 |
}
|
|
|
1465 |
#end
|
|
|
1466 |
|
|
|
1467 |
if (otherMarketData.marketShare > 0) {
|
|
|
1468 |
marketSegments.push(otherMarketData);
|
|
|
1469 |
}
|
|
|
1470 |
if (otherStockData.quantity > 0) {
|
|
|
1471 |
stockSegments.push(otherStockData);
|
|
|
1472 |
}
|
|
|
1473 |
|
|
|
1474 |
const combinedSegments = [];
|
|
|
1475 |
const allBrands = [...new Set([
|
|
|
1476 |
...marketSegments.map(d => d.brand),
|
|
|
1477 |
...stockSegments.map(d => d.brand)
|
|
|
1478 |
])];
|
|
|
1479 |
|
|
|
1480 |
allBrands.forEach(brand => {
|
|
|
1481 |
const marketInfo = marketSegments.find(m => m.brand === brand) || {};
|
|
|
1482 |
const stockInfo = stockSegments.find(s => s.brand === brand) || {};
|
|
|
1483 |
|
|
|
1484 |
combinedSegments.push({
|
|
|
1485 |
brand: brand.charAt(0).toUpperCase() + brand.slice(1),
|
|
|
1486 |
marketShare: marketInfo.marketShare || 0,
|
|
|
1487 |
stockQuantity: stockInfo.quantity || 0,
|
|
|
1488 |
stockValue: stockInfo.value || 0,
|
|
|
1489 |
color: marketInfo.color || brandColors[brand] || '#95a5a6'
|
|
|
1490 |
});
|
|
|
1491 |
});
|
|
|
1492 |
|
|
|
1493 |
const totalStockQuantity = stockSegments.reduce((sum, b) => sum + b.quantity, 0);
|
|
|
1494 |
|
|
|
1495 |
const ctx4 = document.getElementById('combinedStackedChart').getContext('2d');
|
|
|
1496 |
const staggedChart = new Chart(ctx4, {
|
|
|
1497 |
type: 'bar',
|
|
|
1498 |
data: {
|
|
|
1499 |
labels: combinedSegments.map(item => item.brand),
|
|
|
1500 |
datasets: [
|
|
|
1501 |
{
|
| 35119 |
aman |
1502 |
label: 'Brand Market Share Percentage',
|
| 34813 |
aman |
1503 |
data: combinedSegments.map(item => item.marketShare),
|
|
|
1504 |
backgroundColor: combinedSegments.map(item => item.color + '80'),
|
|
|
1505 |
borderColor: combinedSegments.map(item => item.color),
|
|
|
1506 |
borderWidth: 2
|
|
|
1507 |
},
|
|
|
1508 |
{
|
| 35119 |
aman |
1509 |
label: 'Brand Share Percentage in your outlet',
|
| 34813 |
aman |
1510 |
data: combinedSegments.map(item => ((item.stockQuantity / totalStockQuantity) * 100).toFixed(1)),
|
|
|
1511 |
backgroundColor: combinedSegments.map(item => item.color + '40'),
|
|
|
1512 |
borderColor: combinedSegments.map(item => item.color),
|
|
|
1513 |
borderWidth: 1
|
|
|
1514 |
}
|
|
|
1515 |
]
|
|
|
1516 |
},
|
|
|
1517 |
options: {
|
|
|
1518 |
responsive: true,
|
|
|
1519 |
scales: {
|
|
|
1520 |
x: {
|
|
|
1521 |
stacked: true
|
|
|
1522 |
},
|
|
|
1523 |
y: {
|
|
|
1524 |
stacked: true,
|
|
|
1525 |
beginAtZero: true,
|
|
|
1526 |
title: {
|
|
|
1527 |
display: true,
|
|
|
1528 |
text: 'Percentage (%)'
|
|
|
1529 |
}
|
|
|
1530 |
}
|
|
|
1531 |
},
|
|
|
1532 |
plugins: {
|
|
|
1533 |
tooltip: {
|
|
|
1534 |
callbacks: {
|
|
|
1535 |
label: function (context) {
|
|
|
1536 |
const segment = combinedSegments[context.dataIndex];
|
|
|
1537 |
if (context.datasetIndex === 0) {
|
|
|
1538 |
return `Market Share: ${segment.marketShare}%`;
|
|
|
1539 |
} else {
|
|
|
1540 |
return [
|
|
|
1541 |
`Stock Quantity: ${segment.stockQuantity}`,
|
|
|
1542 |
`Percentage: ${((segment.stockQuantity / totalStockQuantity) * 100).toFixed(1)}%`
|
|
|
1543 |
];
|
|
|
1544 |
}
|
|
|
1545 |
}
|
|
|
1546 |
}
|
|
|
1547 |
}
|
|
|
1548 |
}
|
|
|
1549 |
}
|
|
|
1550 |
});
|
|
|
1551 |
});
|
|
|
1552 |
</script>
|