Subversion Repositories SmartDukaan

Rev

Rev 37699 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
37697 amit 1
<style>
2
    /* Availability shown against the quantity box when moving stock between our own warehouses. */
3
    .mv-qty-cell { position: relative; }
4
    .mv-qty-cell .qty { padding-right: 26px; }
5
    .mv-avail-icon {
6
        position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
7
        width: 16px; height: 16px; line-height: 16px; border-radius: 50%;
8
        background: #5a6a7a; color: #fff; font-size: 11px; font-style: italic; font-weight: bold;
9
        text-align: center; cursor: pointer; user-select: none;
10
    }
11
    .mv-avail-icon.mv-part { background: #d58512; }
12
    .mv-avail-icon.mv-none { background: #c9302c; }
13
    .mv-qty-warn { color: #c9302c; font-size: 11px; margin-top: 2px; }
14
    .qty.mv-over { border-color: #c9302c; }
37699 amit 15
    /* Divs, not a table: Bootstrap's popover sanitizer drops table markup and everything inside it. */
16
    .popover .mv-avail { font-size: 12px; }
17
    .popover .mv-avail .mv-row { display: flex; justify-content: space-between; padding: 2px 0; }
18
    .popover .mv-avail .mv-val { padding-left: 12px; font-weight: bold; white-space: nowrap; }
19
    .popover .mv-avail .mv-po { padding-left: 10px; color: #777; }
20
    .popover .mv-avail .mv-po .mv-val { color: #777; font-weight: normal; }
21
    .popover .mv-avail .mv-total { border-top: 1px solid #ddd; margin-top: 2px; padding-top: 4px; }
37697 amit 22
    .popover .mv-note { margin-top: 6px; font-size: 11px; color: #777; }
23
</style>
24
 
32360 amit.gupta 25
<div class="row">
32145 tejbeer 26
 
32360 amit.gupta 27
    <div>
28
        <p style="font-size: 25px;text-align: center; font-weight: bold; text-decoration-line: underline;">
29
            From $warehouse to $vendor.getName() </p>
30
    </div>
32145 tejbeer 31
 
32360 amit.gupta 32
</div>
32145 tejbeer 33
 
34
 
32360 amit.gupta 35
<div class="row">
32145 tejbeer 36
 
32360 amit.gupta 37
    <div class="col-lg-1 form-group">
38
        <input class="form-control btn btn-primary addRowInPurchaseOrder" type="button" value="Add Item">
39
    </div>
40
 
36532 amit 41
    <div class="col-lg-2 form-group">
42
        <label class="btn btn-primary form-control" style="cursor:pointer;">
43
            Bulk Upload <input type="file" id="poItemsFile" accept=".xlsx,.xls" style="display:none;">
44
        </label>
45
    </div>
46
 
47
    <div class="col-lg-2 form-group">
36551 amit 48
        <a href="${rc.contextPath}/downloadPOItemsTemplate" class="btn btn-default form-control">Download Template</a>
36532 amit 49
    </div>
50
 
32360 amit.gupta 51
</div>
52
 
53
 
54
<div class="row">
55
    <div class="col-lg-12">
56
        <table class="table table-border table-condensed table-bordered" id="purchase-order-table" style="width:100%">
57
            <thead>
58
            <tr>
59
 
60
                <th>Product Name</th>
61
                <th>Qty</th>
62
                <th>Transfer Price</th>
63
                <th>Total Value</th>
64
 
65
            </tr>
66
            </thead>
67
            <tbody>
68
            </tbody>
69
        </table>
70
 
71
    </div>
72
</div>
73
 
74
<div class="row">
33727 ranu 75
    <div class="col-md-12 form-group">
36520 amit 76
        <p><b><span>Total Quantity</span></b> -: <b><span id="totalQuantity"></span></b> &nbsp;&nbsp;&nbsp; <b><span>Grand Total</span></b> -: <b><span id="grandTotal"></span></b></p>
33727 ranu 77
    </div>
32360 amit.gupta 78
    <div class="col-lg-2 form-group">
79
        <input class="form-control btn btn-primary createPurchaseOrder" type="button"
80
               value="Create and Save Purchase Order">
81
    </div>
82
 
83
    <div class="col-lg-2 form-group">
84
        <input class="form-control btn btn-primary createSendPurchaseOrder" type="button"
85
               value="Create and Send Purchase Order">
86
    </div>
87
 
88
</div>
89
 
90
<script type="text/javascript">
91
    $('.addRowInPurchaseOrder').ready(function () {
92
        $('.addRowInPurchaseOrder').click();
93
    });
37750 ranu 94
</script>
95
 
96
<!-- ═════════════════════════════════════════════════════════════════════════════
97
     Create-PO modal stack — replaces native confirm/prompt. Three modals fire
98
     in sequence: create-confirm → reason (only if approval needed) → approval-
99
     target confirm → actual create. All IDs are prefixed with `pmscp*` to
100
     avoid the global-jQuery delegated-handler collision problem.
101
     ═════════════════════════════════════════════════════════════════════════════ -->
102
 
103
<style>
104
    .pmscp-modal .modal-dialog {
105
        margin-top: 80px
106
    }
107
 
108
    .pmscp-modal .modal-content {
109
        border-radius: 12px;
110
        border: 0;
111
        box-shadow: 0 20px 60px rgba(20, 40, 90, .18)
112
    }
113
 
114
    .pmscp-modal .modal-header {
115
        border-bottom: 1px solid #eef1f5;
116
        padding: 18px 24px 14px;
117
        display: flex;
118
        align-items: center;
119
        gap: 12px
120
    }
121
 
122
    .pmscp-modal .modal-header .pmscp-icon {
123
        width: 40px;
124
        height: 40px;
125
        border-radius: 50%;
126
        background: #eef2fb;
127
        color: #3b5bdb;
128
        display: inline-flex;
129
        align-items: center;
130
        justify-content: center;
131
        font-size: 20px
132
    }
133
 
134
    .pmscp-modal .modal-header h4 {
135
        margin: 0;
136
        font-size: 17px;
137
        font-weight: 700;
138
        color: #1f2c4f
139
    }
140
 
141
    .pmscp-modal .modal-header .pmscp-sub {
142
        display: block;
143
        font-size: 12px;
144
        color: #7b8199;
145
        font-weight: 500;
146
        margin-top: 3px
147
    }
148
 
149
    .pmscp-modal .modal-body {
150
        padding: 20px 24px;
151
        font-size: 13.5px;
152
        color: #2a3352
153
    }
154
 
155
    .pmscp-modal .modal-footer {
156
        border-top: 1px solid #eef1f5;
157
        padding: 14px 24px
158
    }
159
 
160
    .pmscp-modal .btn {
161
        padding: 8px 18px;
162
        border-radius: 8px;
163
        font-weight: 600;
164
        font-size: 13px
165
    }
166
 
167
    .pmscp-modal .btn-cancel {
168
        background: #f2f4f8;
169
        color: #4a5170;
170
        border: 1px solid #dfe3ec
171
    }
172
 
173
    .pmscp-modal .btn-primary-cta {
174
        background: #3b5bdb;
175
        color: #fff;
176
        border: 1px solid #3b5bdb
177
    }
178
 
179
    .pmscp-modal .btn-primary-cta:hover {
180
        background: #2f4bbf
181
    }
182
 
183
    .pmscp-modal .btn-primary-cta:disabled {
184
        opacity: .5;
185
        cursor: not-allowed
186
    }
187
 
188
    .pmscp-modal .btn-warn-cta {
189
        background: #b78600;
190
        color: #fff;
191
        border: 1px solid #b78600
192
    }
193
 
194
    .pmscp-modal .btn-warn-cta:disabled {
195
        opacity: .5;
196
        cursor: not-allowed
197
    }
198
 
199
    .pmscp-summary {
200
        background: #f7f9fd;
201
        border: 1px solid #e6ebf5;
202
        border-radius: 10px;
203
        padding: 14px 16px;
204
        margin-top: 10px
205
    }
206
 
207
    .pmscp-summary .pmscp-row {
208
        display: flex;
209
        justify-content: space-between;
210
        font-size: 13px;
211
        padding: 4px 0
212
    }
213
 
214
    .pmscp-summary .pmscp-row .pmscp-lbl {
215
        color: #7b8199
216
    }
217
 
218
    .pmscp-summary .pmscp-row .pmscp-val {
219
        color: #1f2c4f;
220
        font-weight: 600
221
    }
222
 
223
    .pmscp-warn {
224
        background: #fff8e1;
225
        border: 1px solid #f1e0b0;
226
        border-left: 4px solid #b78600;
227
        color: #8a6d3b;
228
        padding: 12px 14px;
229
        border-radius: 8px;
230
        font-size: 12.5px;
231
        line-height: 1.5;
232
        margin-bottom: 14px
233
    }
234
 
235
    .pmscp-warn b {
236
        color: #6a5220
237
    }
238
 
239
    #pmscpReasonText {
240
        width: 100%;
241
        min-height: 120px;
242
        border: 1px solid #dfe3ec;
243
        border-radius: 8px;
244
        padding: 10px 12px;
245
        font-size: 13.5px;
246
        font-family: inherit;
247
        resize: vertical;
248
        outline: none;
249
        transition: border-color .12s
250
    }
251
 
252
    #pmscpReasonText:focus {
253
        border-color: #3b5bdb;
254
        box-shadow: 0 0 0 3px rgba(59, 91, 219, .12)
255
    }
256
 
257
    .pmscp-counter {
258
        font-size: 11.5px;
259
        color: #7b8199;
260
        margin-top: 6px;
261
        display: flex;
262
        gap: 8px;
263
        align-items: center
264
    }
265
 
266
    .pmscp-counter #pmscpReasonCount {
267
        font-weight: 700;
268
        color: #c62828
269
    }
270
 
271
    .pmscp-counter.pmscp-ok #pmscpReasonCount {
272
        color: #177a3a
273
    }
274
 
275
    .pmscp-counter .pmscp-short {
276
        color: #c62828;
277
        font-style: italic
278
    }
279
 
280
    .pmscp-counter.pmscp-ok .pmscp-short {
281
        display: none
282
    }
283
 
284
    .pmscp-counter.pmscp-ok::after {
285
        content: "✓ ready";
286
        color: #177a3a;
287
        font-weight: 600
288
    }
289
 
290
    .pmscp-approver {
291
        display: flex;
292
        gap: 14px;
293
        align-items: center;
294
        background: #f7f9fd;
295
        border: 1px solid #e6ebf5;
296
        border-radius: 10px;
297
        padding: 14px 16px;
298
        margin-bottom: 14px
299
    }
300
 
301
    .pmscp-approver .pmscp-avatar {
302
        width: 52px;
303
        height: 52px;
304
        border-radius: 50%;
305
        background: #3b5bdb;
306
        color: #fff;
307
        font-weight: 700;
308
        font-size: 18px;
309
        display: inline-flex;
310
        align-items: center;
311
        justify-content: center;
312
        flex-shrink: 0
313
    }
314
 
315
    .pmscp-approver .pmscp-name {
316
        font-size: 15px;
317
        font-weight: 700;
318
        color: #1f2c4f
319
    }
320
 
321
    .pmscp-approver .pmscp-role {
322
        display: inline-block;
323
        margin-left: 8px;
324
        background: #eef2fb;
325
        color: #3b5bdb;
326
        font-size: 11px;
327
        font-weight: 700;
328
        padding: 2px 8px;
329
        border-radius: 10px;
330
        vertical-align: middle
331
    }
332
 
333
    .pmscp-approver .pmscp-mail {
334
        font-size: 12px;
335
        color: #7b8199;
336
        margin-top: 2px
337
    }
338
 
339
    .pmscp-reason-preview {
340
        background: #f2f4f8;
341
        border-radius: 8px;
342
        padding: 10px 12px;
343
        font-size: 12.5px;
344
        color: #4a5170;
345
        font-style: italic;
346
        max-height: 80px;
347
        overflow-y: auto;
348
        line-height: 1.5;
349
        white-space: pre-wrap
350
    }
351
</style>
352
 
353
<!-- Modal 1 — Create-PO confirmation (shown before any server call). -->
354
<div class="modal pmscp-modal" id="pmscpConfirmModal" tabindex="-1" role="dialog" aria-hidden="true">
355
    <div class="modal-dialog" role="document">
356
        <div class="modal-content">
357
            <div class="modal-header">
358
                <span class="pmscp-icon">📄</span>
359
                <div>
360
                    <h4>Create Purchase Order?</h4>
361
                    <span class="pmscp-sub">Please confirm the details below.</span>
362
                </div>
363
            </div>
364
            <div class="modal-body">
365
                <div>You are about to create a purchase order with the following details:</div>
366
                <div class="pmscp-summary">
367
                    <div class="pmscp-row"><span class="pmscp-lbl">Vendor</span><span class="pmscp-val"
368
                                                                                      id="pmscpSumVendor">—</span></div>
369
                    <div class="pmscp-row"><span class="pmscp-lbl">Warehouse</span><span class="pmscp-val"
370
                                                                                         id="pmscpSumWarehouse">—</span>
371
                    </div>
372
                    <div class="pmscp-row"><span class="pmscp-lbl">Items</span><span class="pmscp-val"
373
                                                                                     id="pmscpSumItems">—</span></div>
374
                    <div class="pmscp-row"><span class="pmscp-lbl">Total Qty</span><span class="pmscp-val"
375
                                                                                         id="pmscpSumQty">—</span></div>
376
                    <div class="pmscp-row"><span class="pmscp-lbl">Grand Total</span><span class="pmscp-val"
377
                                                                                           id="pmscpSumTotal">—</span>
378
                    </div>
379
                </div>
380
            </div>
381
            <div class="modal-footer">
382
                <button type="button" class="btn btn-cancel" data-dismiss="modal">Cancel</button>
383
                <button type="button" class="btn btn-primary-cta" id="pmscpConfirmCreate">Yes, Create PO</button>
384
            </div>
385
        </div>
386
    </div>
387
</div>
388
 
389
<!-- Modal 2 — Reason for aging-stock purchase (with live 50-char counter). -->
390
<div class="modal pmscp-modal" id="pmscpReasonModal" tabindex="-1" role="dialog" aria-hidden="true">
391
    <div class="modal-dialog" role="document">
392
        <div class="modal-content">
393
            <div class="modal-header">
394
                <span class="pmscp-icon" style="background:#fff3d6;color:#b78600">⚠</span>
395
                <div>
396
                    <h4>Approval Required — Reason Needed</h4>
397
                    <span class="pmscp-sub">This PO exceeds the 15-day stock cover rule.</span>
398
                </div>
399
            </div>
400
            <div class="modal-body">
401
                <div class="pmscp-warn">
402
                    <b>Why this PO needs approval:</b> Existing aging stock + this PO qty exceeds the last 15 days of
403
                    sales at the warehouse. It will be held for review by <b>Niranjan Kala</b> before being sent to the
404
                    vendor.
405
                </div>
406
 
407
                <!-- Flagged items table — populated by JS from preflight.flaggedItems.
408
                     Shows only the SKUs that tripped the rule (mixed POs may have clean
409
                     items too, which are not shown here). Helps the requester write a
410
                     specific reason rather than a generic one. -->
411
                <div id="pmscpFlaggedBox" style="margin-bottom:14px;display:none">
412
                    <div style="font-size:12px;font-weight:600;color:#4a5170;margin-bottom:6px">
413
                        Items requiring approval (<span id="pmscpFlaggedCount">0</span>)
414
                    </div>
415
                    <table style="width:100%;border-collapse:collapse;font-size:12px;border:1px solid #e6ebf5;border-radius:6px;overflow:hidden">
416
                        <thead>
417
                        <tr style="background:#f7f9fd;color:#4a5170">
418
                            <th style="text-align:left;padding:6px 10px;border-bottom:1px solid #e6ebf5">Item</th>
419
                            <th style="text-align:right;padding:6px 10px;border-bottom:1px solid #e6ebf5">Aging
420
                                Stock<br/><span style="font-weight:normal;color:#7b8199;font-size:10px">vendor + warehouse</span>
421
                            </th>
422
                            <th style="text-align:right;padding:6px 10px;border-bottom:1px solid #e6ebf5">15d
423
                                Sold<br/><span style="font-weight:normal;color:#7b8199;font-size:10px">warehouse</span>
424
                            </th>
425
                            <th style="text-align:right;padding:6px 10px;border-bottom:1px solid #e6ebf5">PO Qty</th>
426
                            <th style="text-align:right;padding:6px 10px;border-bottom:1px solid #e6ebf5">Excess</th>
427
                        </tr>
428
                        </thead>
429
                        <tbody id="pmscpFlaggedRows"></tbody>
430
                    </table>
431
                </div>
432
 
433
                <label for="pmscpReasonText"
434
                       style="display:block;font-size:12px;font-weight:600;color:#4a5170;margin-bottom:6px">
435
                    Please explain why this aging stock is required (minimum 50 characters)
436
                </label>
437
                <textarea id="pmscpReasonText"
438
                          placeholder="e.g. Vendor closing brand; must clear last-shot inventory. Or: Focused push for this SKU next 30 days per Manish. Be specific enough for Niranjan to decide."></textarea>
439
                <div class="pmscp-counter" id="pmscpReasonCounter">
440
                    <span id="pmscpReasonCount">0</span> / 50 characters minimum
441
                    <span class="pmscp-short">— need more detail</span>
442
                </div>
443
            </div>
444
            <div class="modal-footer">
445
                <button type="button" class="btn btn-cancel" data-dismiss="modal">Cancel</button>
446
                <button type="button" class="btn btn-warn-cta" id="pmscpReasonContinue" disabled>Continue &rarr;
447
                </button>
448
            </div>
449
        </div>
450
    </div>
451
</div>
452
 
453
<!-- Modal 3 — Final "sending for approval to X" confirmation. -->
454
<div class="modal pmscp-modal" id="pmscpApprovalModal" tabindex="-1" role="dialog" aria-hidden="true">
455
    <div class="modal-dialog" role="document">
456
        <div class="modal-content">
457
            <div class="modal-header">
458
                <span class="pmscp-icon" style="background:#e6f4ea;color:#177a3a">✓</span>
459
                <div>
460
                    <h4>Send for Approval</h4>
461
                    <span class="pmscp-sub">Confirm the PO will be held for approval.</span>
462
                </div>
463
            </div>
464
            <div class="modal-body">
465
                <div class="pmscp-approver">
466
                    <div class="pmscp-avatar">NK</div>
467
                    <div>
468
                        <div>
469
                            <span class="pmscp-name">Niranjan Kala</span>
470
                            <span class="pmscp-role">Category · L4</span>
471
                        </div>
472
                        <div class="pmscp-mail">niranjan.kala@smartdukaan.com</div>
473
                    </div>
474
                </div>
475
                <div style="font-size:12px;font-weight:600;color:#4a5170;margin-bottom:6px">Your reason (will be visible
476
                    to Niranjan)
477
                </div>
478
                <div class="pmscp-reason-preview" id="pmscpApprovalReasonPreview">—</div>
479
                <div style="margin-top:14px;font-size:12.5px;color:#5a6082;line-height:1.5">
480
                    By clicking <b>Confirm &amp; Send</b>, this PO will be created in a held state. Niranjan will be
481
                    notified by email and can approve or reject it from the Stock Approvals queue. You will not need to
482
                    re-create the PO — approval will release it automatically.
483
                </div>
484
            </div>
485
            <div class="modal-footer">
486
                <button type="button" class="btn btn-cancel" id="pmscpApprovalBack">&larr; Back</button>
487
                <button type="button" class="btn btn-primary-cta" id="pmscpApprovalConfirm">Confirm &amp; Send for
488
                    Approval
489
                </button>
490
            </div>
491
        </div>
492
    </div>
493
</div>