459 lines
19 KiB
Plaintext
459 lines
19 KiB
Plaintext
@{
|
|
Layout = "_AdminLayout";
|
|
ViewBag.PageTitle = "InnVoice Order Sync";
|
|
}
|
|
|
|
<div class="content-header clearfix">
|
|
<h1 class="float-left">
|
|
InnVoice Order Synchronization
|
|
</h1>
|
|
</div>
|
|
|
|
<section class="content">
|
|
<div class="container-fluid">
|
|
|
|
<!-- Date Range Selector Card -->
|
|
<div class="card card-default">
|
|
<div class="card-header">
|
|
<h3 class="card-title">
|
|
<i class="fas fa-calendar-alt"></i>
|
|
Select Date Range
|
|
</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-3">
|
|
<div class="form-group">
|
|
<label for="startDate">Start Date</label>
|
|
<input type="date" class="form-control" id="startDate" />
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="form-group">
|
|
<label for="endDate">End Date</label>
|
|
<input type="date" class="form-control" id="endDate" />
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label> </label>
|
|
<div>
|
|
<button type="button" class="btn btn-primary" onclick="syncOrders()">
|
|
<i class="fas fa-sync"></i> Sync Orders
|
|
</button>
|
|
<button type="button" class="btn btn-info" onclick="syncLast30Days()">
|
|
<i class="fas fa-clock"></i> Last 30 Days
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Loading Indicator -->
|
|
<div id="loadingIndicator" class="card card-info" style="display: none;">
|
|
<div class="card-body text-center">
|
|
<i class="fas fa-spinner fa-spin fa-3x"></i>
|
|
<h4 class="mt-3">Synchronizing orders...</h4>
|
|
<p>This may take a few moments depending on the date range.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Summary Card -->
|
|
<div id="summaryCard" class="card card-primary" style="display: none;">
|
|
<div class="card-header">
|
|
<h3 class="card-title">
|
|
<i class="fas fa-chart-bar"></i>
|
|
Sync Summary
|
|
</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<div class="info-box bg-info">
|
|
<span class="info-box-icon"><i class="fas fa-shopping-cart"></i></span>
|
|
<div class="info-box-content">
|
|
<span class="info-box-text">InnVoice Orders</span>
|
|
<span class="info-box-number" id="totalInnVoiceOrders">0</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="info-box bg-success">
|
|
<span class="info-box-icon"><i class="fas fa-database"></i></span>
|
|
<div class="info-box-content">
|
|
<span class="info-box-text">NopCommerce Orders</span>
|
|
<span class="info-box-number" id="totalNopOrders">0</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="info-box bg-warning">
|
|
<span class="info-box-icon"><i class="fas fa-check-double"></i></span>
|
|
<div class="info-box-content">
|
|
<span class="info-box-text">In Both Systems</span>
|
|
<span class="info-box-number" id="inBothSystems">0</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-3">
|
|
<div class="info-box bg-danger">
|
|
<span class="info-box-icon"><i class="fas fa-exclamation-triangle"></i></span>
|
|
<div class="info-box-content">
|
|
<span class="info-box-text">Only in InnVoice</span>
|
|
<span class="info-box-number" id="onlyInInnVoice">0</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="info-box bg-secondary">
|
|
<span class="info-box-icon"><i class="fas fa-question-circle"></i></span>
|
|
<div class="info-box-content">
|
|
<span class="info-box-text">Only in NopCommerce</span>
|
|
<span class="info-box-number" id="onlyInNopCommerce">0</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="info-box bg-dark">
|
|
<span class="info-box-icon"><i class="fas fa-upload"></i></span>
|
|
<div class="info-box-content">
|
|
<span class="info-box-text">Missing Uploads</span>
|
|
<span class="info-box-number" id="missingUploads">0</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="info-box bg-light text-dark">
|
|
<span class="info-box-icon bg-secondary"><i class="fas fa-trash"></i></span>
|
|
<div class="info-box-content">
|
|
<span class="info-box-text">Deleted/Cancelled</span>
|
|
<span class="info-box-number" id="deletedOrders">0</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Orders Only in InnVoice -->
|
|
<div id="innVoiceOnlyCard" class="card card-danger collapsed-card" style="display: none;">
|
|
<div class="card-header">
|
|
<h3 class="card-title">
|
|
<i class="fas fa-exclamation-triangle"></i>
|
|
Orders Only in InnVoice (<span id="innVoiceOnlyCount">0</span>)
|
|
</h3>
|
|
<div class="card-tools">
|
|
<button type="button" class="btn btn-tool" data-card-widget="collapse">
|
|
<i class="fas fa-plus"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<table class="table table-bordered table-striped" id="innVoiceOnlyTable">
|
|
<thead>
|
|
<tr>
|
|
<th>Table ID</th>
|
|
<th>Tech ID</th>
|
|
<th>Customer Name</th>
|
|
<th>External Order #</th>
|
|
<th>Total</th>
|
|
<th>Order Date</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="innVoiceOnlyBody">
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Orders Only in NopCommerce -->
|
|
<div id="nopOnlyCard" class="card card-secondary collapsed-card" style="display: none;">
|
|
<div class="card-header">
|
|
<h3 class="card-title">
|
|
<i class="fas fa-question-circle"></i>
|
|
Orders Only in NopCommerce (<span id="nopOnlyCount">0</span>)
|
|
</h3>
|
|
<div class="card-tools">
|
|
<button type="button" class="btn btn-tool" data-card-widget="collapse">
|
|
<i class="fas fa-plus"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<table class="table table-bordered table-striped" id="nopOnlyTable">
|
|
<thead>
|
|
<tr>
|
|
<th>Order ID</th>
|
|
<th>Table ID</th>
|
|
<th>Custom Order #</th>
|
|
<th>Total</th>
|
|
<th>Created On (UTC)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="nopOnlyBody">
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Missing Uploads -->
|
|
<div id="missingUploadsCard" class="card card-dark collapsed-card" style="display: none;">
|
|
<div class="card-header">
|
|
<h3 class="card-title">
|
|
<i class="fas fa-upload"></i>
|
|
Missing Uploads (<span id="missingUploadsCount">0</span>)
|
|
</h3>
|
|
<div class="card-tools">
|
|
<button type="button" class="btn btn-tool" data-card-widget="collapse">
|
|
<i class="fas fa-plus"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="text-warning"><i class="fas fa-exclamation-circle"></i> These orders should have been uploaded to InnVoice but weren't.</p>
|
|
<table class="table table-bordered table-striped" id="missingUploadsTable">
|
|
<thead>
|
|
<tr>
|
|
<th>Order ID</th>
|
|
<th>Custom Order #</th>
|
|
<th>Status</th>
|
|
<th>Items</th>
|
|
<th>Total</th>
|
|
<th>Created On (UTC)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="missingUploadsBody">
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Deleted/Cancelled Orders -->
|
|
<div id="deletedOrdersCard" class="card card-secondary collapsed-card" style="display: none;">
|
|
<div class="card-header">
|
|
<h3 class="card-title">
|
|
<i class="fas fa-trash"></i>
|
|
Deleted/Cancelled Orders (<span id="deletedOrdersCount">0</span>)
|
|
</h3>
|
|
<div class="card-tools">
|
|
<button type="button" class="btn btn-tool" data-card-widget="collapse">
|
|
<i class="fas fa-plus"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="text-muted"><i class="fas fa-info-circle"></i> These orders are deleted or cancelled and don't need to be uploaded.</p>
|
|
<table class="table table-bordered table-striped" id="deletedOrdersTable">
|
|
<thead>
|
|
<tr>
|
|
<th>Order ID</th>
|
|
<th>Custom Order #</th>
|
|
<th>Status</th>
|
|
<th>Items</th>
|
|
<th>Total</th>
|
|
<th>Created On (UTC)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="deletedOrdersBody">
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</section>
|
|
|
|
<script>
|
|
// Set default dates
|
|
$(document).ready(function() {
|
|
var today = new Date();
|
|
var thirtyDaysAgo = new Date();
|
|
thirtyDaysAgo.setDate(today.getDate() - 30);
|
|
|
|
$('#endDate').val(today.toISOString().split('T')[0]);
|
|
$('#startDate').val(thirtyDaysAgo.toISOString().split('T')[0]);
|
|
});
|
|
|
|
function syncOrders() {
|
|
var startDate = $('#startDate').val();
|
|
var endDate = $('#endDate').val();
|
|
|
|
if (!startDate || !endDate) {
|
|
alert('Please select both start and end dates');
|
|
return;
|
|
}
|
|
|
|
performSync(startDate, endDate);
|
|
}
|
|
|
|
function syncLast30Days() {
|
|
var endDate = new Date();
|
|
var startDate = new Date();
|
|
startDate.setDate(endDate.getDate() - 30);
|
|
|
|
$('#startDate').val(startDate.toISOString().split('T')[0]);
|
|
$('#endDate').val(endDate.toISOString().split('T')[0]);
|
|
|
|
performSync(
|
|
startDate.toISOString().split('T')[0],
|
|
endDate.toISOString().split('T')[0]
|
|
);
|
|
}
|
|
|
|
function performSync(startDate, endDate) {
|
|
// Show loading
|
|
$('#loadingIndicator').show();
|
|
$('#summaryCard').hide();
|
|
$('#innVoiceOnlyCard').hide();
|
|
$('#nopOnlyCard').hide();
|
|
$('#missingUploadsCard').hide();
|
|
$('#deletedOrdersCard').hide();
|
|
|
|
$.ajax({
|
|
url: '@Url.Action("SyncOrders", "InnVoiceOrderSync")',
|
|
type: 'POST',
|
|
data: {
|
|
startDate: startDate,
|
|
endDate: endDate
|
|
},
|
|
success: function(response) {
|
|
$('#loadingIndicator').hide();
|
|
|
|
if (response.success) {
|
|
displayResults(response.data);
|
|
} else {
|
|
alert('Error: ' + response.message);
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
$('#loadingIndicator').hide();
|
|
alert('Error synchronizing orders: ' + error);
|
|
}
|
|
});
|
|
}
|
|
|
|
function getOrderStatusBadge(status) {
|
|
var badges = {
|
|
'Pending': '<span class="badge badge-warning">Pending</span>',
|
|
'Processing': '<span class="badge badge-info">Processing</span>',
|
|
'Complete': '<span class="badge badge-success">Complete</span>',
|
|
'Cancelled': '<span class="badge badge-danger">Cancelled</span>'
|
|
};
|
|
return badges[status] || '<span class="badge badge-secondary">' + status + '</span>';
|
|
}
|
|
|
|
function displayResults(data) {
|
|
// Update summary
|
|
$('#totalInnVoiceOrders').text(data.summary.totalInnVoiceOrders);
|
|
$('#totalNopOrders').text(data.summary.totalNopOrders);
|
|
$('#inBothSystems').text(data.summary.inBothSystems);
|
|
$('#onlyInInnVoice').text(data.summary.onlyInInnVoice);
|
|
$('#onlyInNopCommerce').text(data.summary.onlyInNopCommerce);
|
|
$('#missingUploads').text(data.summary.totalMissingUploads || 0);
|
|
$('#deletedOrders').text(data.summary.totalDeletedOrders || 0);
|
|
$('#summaryCard').show();
|
|
|
|
// Display InnVoice only orders
|
|
if (data.innVoiceOnly && data.innVoiceOnly.length > 0) {
|
|
$('#innVoiceOnlyCount').text(data.innVoiceOnly.length);
|
|
var tbody = $('#innVoiceOnlyBody');
|
|
tbody.empty();
|
|
|
|
data.innVoiceOnly.forEach(function(order) {
|
|
tbody.append(
|
|
'<tr>' +
|
|
'<td>' + (order.tableId || '-') + '</td>' +
|
|
'<td>' + (order.techId || '-') + '</td>' +
|
|
'<td>' + (order.customerName || '-') + '</td>' +
|
|
'<td>' + (order.externalOrderNumber || '-') + '</td>' +
|
|
'<td>' + (order.totalGross || 0).toFixed(2) + ' Ft</td>' +
|
|
'<td>' + (order.orderDate || '-') + '</td>' +
|
|
'</tr>'
|
|
);
|
|
});
|
|
|
|
$('#innVoiceOnlyCard').show();
|
|
}
|
|
|
|
// Display NopCommerce only orders
|
|
if (data.nopCommerceOnly && data.nopCommerceOnly.length > 0) {
|
|
$('#nopOnlyCount').text(data.nopCommerceOnly.length);
|
|
var tbody = $('#nopOnlyBody');
|
|
tbody.empty();
|
|
|
|
data.nopCommerceOnly.forEach(function(order) {
|
|
tbody.append(
|
|
'<tr>' +
|
|
'<td><a href="/Admin/Order/Edit/' + order.orderId + '" target="_blank">' + order.orderId + '</a></td>' +
|
|
'<td>' + (order.tableId || '-') + '</td>' +
|
|
'<td>' + (order.customOrderNumber || '-') + '</td>' +
|
|
'<td>' + (order.orderTotal || 0).toFixed(2) + '</td>' +
|
|
'<td>' + new Date(order.createdOn).toLocaleString() + '</td>' +
|
|
'</tr>'
|
|
);
|
|
});
|
|
|
|
$('#nopOnlyCard').show();
|
|
}
|
|
|
|
// Display Missing Uploads
|
|
if (data.missingUploads && data.missingUploads.length > 0) {
|
|
$('#missingUploadsCount').text(data.missingUploads.length);
|
|
var tbody = $('#missingUploadsBody');
|
|
tbody.empty();
|
|
|
|
data.missingUploads.forEach(function(order) {
|
|
tbody.append(
|
|
'<tr>' +
|
|
'<td><a href="/Admin/Order/Edit/' + order.orderId + '" target="_blank">' + order.orderId + '</a></td>' +
|
|
'<td>' + (order.customOrderNumber || '-') + '</td>' +
|
|
'<td>' + getOrderStatusBadge(order.orderStatus) + '</td>' +
|
|
'<td><span class="badge badge-success">' + (order.itemCount || 0) + '</span></td>' +
|
|
'<td>' + (order.orderTotal || 0).toFixed(2) + '</td>' +
|
|
'<td>' + new Date(order.createdOn).toLocaleString() + '</td>' +
|
|
'</tr>'
|
|
);
|
|
});
|
|
|
|
$('#missingUploadsCard').show();
|
|
}
|
|
|
|
// Display Deleted/Cancelled Orders
|
|
if (data.deletedOrders && data.deletedOrders.length > 0) {
|
|
$('#deletedOrdersCount').text(data.deletedOrders.length);
|
|
var tbody = $('#deletedOrdersBody');
|
|
tbody.empty();
|
|
|
|
data.deletedOrders.forEach(function(order) {
|
|
tbody.append(
|
|
'<tr>' +
|
|
'<td><a href="/Admin/Order/Edit/' + order.orderId + '" target="_blank">' + order.orderId + '</a></td>' +
|
|
'<td>' + (order.customOrderNumber || '-') + '</td>' +
|
|
'<td>' + getOrderStatusBadge(order.orderStatus) + '</td>' +
|
|
'<td><span class="badge badge-secondary">0</span></td>' +
|
|
'<td>' + (order.orderTotal || 0).toFixed(2) + '</td>' +
|
|
'<td>' + new Date(order.createdOn).toLocaleString() + '</td>' +
|
|
'</tr>'
|
|
);
|
|
});
|
|
|
|
$('#deletedOrdersCard').show();
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.info-box-number {
|
|
font-size: 2rem;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.info-box-text {
|
|
font-size: 0.9rem;
|
|
}
|
|
</style>
|