Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
36641 ranu 1
<section class="wrapper">
2
	<div class="row">
3
		<div class="col-lg-12">
36668 ranu 4
			<h3 class="page-header"><i class="icon_document_alt"></i> BEAT PLAN - BULK UPLOAD</h3>
36641 ranu 5
			<ol class="breadcrumb">
6
				<li><i class="fa fa-home"></i><a href="${rc.contextPath}/dashboard">Home</a></li>
7
				<li><i class="icon_document_alt"></i>Beat Plan Bulk Upload</li>
8
			</ol>
9
		</div>
10
	</div>
11
 
12
	<div class="row">
13
		<div class="col-lg-8">
14
			<div class="panel panel-default">
15
				<div class="panel-heading">
36668 ranu 16
					<strong>Upload Beat Plans (XLSX)</strong>
36641 ranu 17
					<a href="${rc.contextPath}/beatPlan/downloadTemplate" class="btn btn-xs btn-info pull-right">Download
18
						Template</a>
19
				</div>
20
				<div class="panel-body">
21
					<p style="margin-bottom:15px;color:#666;">
36668 ranu 22
						Upload an Excel file (.xlsx) to create beat plans and schedule them on the calendar in one
23
						go.<br>
24
						<strong>One partner per row.</strong> Beats are grouped by <strong>beat_name +
36641 ranu 25
						auth_user_id</strong>.
26
					</p>
27
 
28
					<div class="well" style="background:#f9f9f9;">
36668 ranu 29
						<strong>XLSX Format (one row = one partner):</strong>
36641 ranu 30
						<table class="table table-bordered table-condensed" style="margin-top:10px;font-size:12px;">
31
							<thead>
32
							<tr style="background:#eee;">
33
								<th>beat_name</th>
34
								<th>auth_user_id</th>
35
								<th>start_date</th>
36
								<th>day_number</th>
36668 ranu 37
								<th>sequence_order</th>
38
								<th>partner_code</th>
36641 ranu 39
							</tr>
40
							</thead>
41
							<tbody>
42
							<tr>
43
								<td>Jaipur East Route</td>
44
								<td>280</td>
45
								<td>2026-06-02</td>
46
								<td>1</td>
36668 ranu 47
								<td>1</td>
48
								<td>RJKAI1478</td>
36641 ranu 49
							</tr>
50
							<tr>
51
								<td></td>
36668 ranu 52
								<td></td>
53
								<td></td>
54
								<td>1</td>
36641 ranu 55
								<td>2</td>
36668 ranu 56
								<td>RJBUN1449</td>
36641 ranu 57
							</tr>
58
							<tr>
59
								<td></td>
36668 ranu 60
								<td></td>
61
								<td></td>
62
								<td>1</td>
36641 ranu 63
								<td>3</td>
36668 ranu 64
								<td>RJDEG1443</td>
36641 ranu 65
							</tr>
36668 ranu 66
							<tr>
67
								<td></td>
68
								<td></td>
69
								<td></td>
70
								<td>2</td>
71
								<td>1</td>
72
								<td>RJALR1362</td>
73
							</tr>
74
							<tr>
75
								<td></td>
76
								<td></td>
77
								<td></td>
78
								<td>2</td>
79
								<td>2</td>
80
								<td>RJBTR1388</td>
81
							</tr>
82
							<tr>
83
								<td></td>
84
								<td></td>
85
								<td></td>
86
								<td>3</td>
87
								<td>1</td>
88
								<td>RJRSD1518</td>
89
							</tr>
90
							<tr>
91
								<td></td>
92
								<td></td>
93
								<td></td>
94
								<td>3</td>
95
								<td>2</td>
96
								<td>RJSML356</td>
97
							</tr>
36641 ranu 98
							<tr style="border-top:2px solid #ccc;">
99
								<td>Agra Circuit</td>
100
								<td>145</td>
101
								<td>2026-06-05</td>
102
								<td>1</td>
36668 ranu 103
								<td>1</td>
104
								<td>UPAGR101</td>
36641 ranu 105
							</tr>
36668 ranu 106
							<tr>
107
								<td></td>
108
								<td></td>
109
								<td></td>
110
								<td>1</td>
111
								<td>2</td>
112
								<td>UPAGR102</td>
113
							</tr>
36641 ranu 114
							</tbody>
115
						</table>
116
						<p style="font-size:11px;color:#888;">
36668 ranu 117
							<strong>beat_name</strong>: Name for the beat - <strong>only on the first row of the
118
							beat</strong>.
119
							Leave blank for subsequent rows of the same beat. Extra spaces are normalized automatically.<br>
120
							<strong>auth_user_id</strong>: Sales user ID - <strong>only on the first row of the
121
							beat</strong>.<br>
122
							<strong>start_date</strong>: Start date (YYYY-MM-DD) - <strong>only on the first row of the
123
							beat</strong>.
124
							System auto-calculates remaining days, skipping holidays. Leave empty for unscheduled
125
							beat.<br>
126
							<strong>day_number</strong>: Day within the beat (1, 2, 3...) - required on every row.<br>
127
							<strong>sequence_order</strong>: Visit order within the day (1, 2, 3...). Optional - row
128
							order is used if blank.<br>
129
							<strong>partner_code</strong>: Single partner code for this row.<br><br>
130
							Multiple beats in one file - just start a new beat row (non-blank beat_name) wherever you
131
							want to switch.
36641 ranu 132
						</p>
133
					</div>
134
 
135
					<form id="beat-bulk-form" enctype="multipart/form-data" style="margin-top:15px;">
136
						<div class="form-group">
36668 ranu 137
							<label>Select XLSX File</label>
138
							<input type="file" id="beat-bulk-file" name="file" accept=".xlsx" class="form-control">
36641 ranu 139
						</div>
140
						<div class="checkbox" style="margin-bottom:10px;">
141
							<label><input type="checkbox" id="beat-bulk-include-sundays"> Include Sundays (don't skip
142
								Sundays when scheduling)</label>
143
						</div>
144
						<button type="button" class="btn btn-primary beat-bulk-submit">Upload & Process</button>
145
					</form>
146
 
147
					<div id="beat-bulk-result" style="display:none;margin-top:15px;"></div>
148
				</div>
149
			</div>
150
		</div>
151
	</div>
152
</section>
153
 
154
<script>
155
	$(document).on('click', '.beat-bulk-submit', function () {
156
		var fileInput = document.getElementById('beat-bulk-file');
157
		if (!fileInput.files || !fileInput.files[0]) {
36668 ranu 158
			alert('Please select an XLSX file');
36641 ranu 159
			return;
160
		}
161
 
162
		var formData = new FormData();
163
		formData.append('file', fileInput.files[0]);
164
		formData.append('includeSundays', $('#beat-bulk-include-sundays').is(':checked'));
165
 
166
		var $btn = $(this);
167
			$btn.prop('disabled', true).text('Processing...');
168
 
169
		$.ajax({
170
			url: context + '/beatPlan/bulkUploadProcess',
171
			type: 'POST',
172
			data: formData,
173
			processData: false,
174
			contentType: false,
175
			success: function (response) {
176
					$btn.prop('disabled', false).text('Upload & Process');
177
				var data = response.response || response;
36785 ranu 178
                var hasErrors = (data.errors || 0) > 0 || data.status === false;
179
                var html;
180
                if (!hasErrors) {
181
                    // Clean import — zero errors, every row persisted.
182
                    html = ''
183
                            + '<div class="alert alert-success" style="font-size:13px;">'
184
                            + '<i class="fa fa-check-circle" style="font-size:18px;margin-right:6px;"></i>'
185
                            + '<strong>' + (data.beatsCreated || 0) + ' beat(s) created successfully.</strong>'
186
                            + '</div>';
187
                    alert('✓ ' + (data.beatsCreated || 0) + ' beat(s) created successfully.');
188
                } else {
189
                    // All-or-nothing failure — nothing persisted, list every issue.
190
                    var errs = data.errorMessages || [];
191
                    html = ''
192
                            + '<div class="alert alert-danger" style="font-size:13px;">'
193
                            + '<div style="font-size:14px;font-weight:600;margin-bottom:6px;">'
194
                            + '<i class="fa fa-times-circle" style="margin-right:6px;"></i>'
195
                            + 'No beats were created.'
196
                            + '</div>'
197
                            + '<div style="margin-bottom:8px;color:#b91c1c;">'
198
                            + (data.message || 'Fix the issues below and re-upload the file.')
199
                            + '</div>'
200
                            + '<div style="font-weight:600;color:#7f1d1d;margin-bottom:4px;">'
201
                            + errs.length + ' issue(s) found:'
202
                            + '</div>'
203
                            + '<ol style="margin:0;padding-left:22px;line-height:1.6;color:#7f1d1d;">';
204
                    errs.forEach(function (msg) {
205
                        html += '<li>' + msg + '</li>';
206
                    });
207
                    html += '</ol></div>';
208
 
209
                    // Modal alert with the first few issues so the user can't miss it
210
                    // even if the result panel is below the fold.
211
                    var preview = errs.slice(0, 5).map(function (m, i) {
212
                        return (i + 1) + '. ' + m;
213
                    }).join('\n');
214
                    var more = errs.length > 5 ? '\n\n…and ' + (errs.length - 5) + ' more — see the panel below.' : '';
215
                    alert('✗ No beats created.\n\n' + errs.length + ' issue(s) found:\n\n' + preview + more);
36641 ranu 216
				}
217
				$('#beat-bulk-result').html(html).show();
218
			},
219
			error: function (xhr) {
220
					$btn.prop('disabled', false).text('Upload & Process');
221
				$('#beat-bulk-result').html('<div class="alert alert-danger">Error: ' + (xhr.responseText || xhr.statusText) + '</div>').show();
222
			}
223
		});
224
	});
225
</script>