635 lines
32 KiB
Plaintext
635 lines
32 KiB
Plaintext
@model Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models.Order.OrderSearchModelExtended
|
||
|
||
@using FruitBank.Common.Interfaces
|
||
@using Nop.Services.Stores
|
||
@using Nop.Web.Areas.Admin.Components
|
||
@using Nop.Web.Areas.Admin.Models.Orders
|
||
@using Nop.Web.Framework.Infrastructure
|
||
@inject IStoreService storeService
|
||
|
||
@{
|
||
// Layout = "~/Areas/Admin/Views/Shared/_LayoutAdmin.cshtml";
|
||
ViewBag.PageTitle = "FruitBank Rendelések";
|
||
NopHtml.SetActiveMenuItemSystemName("Orders");
|
||
}
|
||
|
||
@* ── Action buttons ─────────────────────────────────────────────── *@
|
||
<form id="fb-header-form" asp-controller="Order" asp-action="List" method="post">
|
||
<div class="content-header clearfix">
|
||
<h1 class="float-left">Rendelések</h1>
|
||
<div class="float-right">
|
||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#create-order-window">
|
||
<i class="fas fa-plus"></i> @T("Admin.Common.AddNew")
|
||
</button>
|
||
<div class="btn-group">
|
||
<button type="button" class="btn btn-success"><i class="fas fa-download"></i> @T("Admin.Common.Export")</button>
|
||
<button type="button" class="btn btn-success dropdown-toggle dropdown-icon" data-toggle="dropdown"><span class="sr-only"> </span></button>
|
||
<ul class="dropdown-menu" role="menu">
|
||
<li class="dropdown-item"><button asp-action="ExportXml" type="submit" name="exportxml-all"><i class="far fa-file-code"></i> @T("Admin.Common.ExportToXml.All")</button></li>
|
||
<li class="dropdown-item"><button type="button" id="exportxml-selected"><i class="far fa-file-code"></i> @T("Admin.Common.ExportToXml.Selected")</button></li>
|
||
<li class="dropdown-divider"></li>
|
||
<li class="dropdown-item"><button asp-action="ExportExcel" type="submit" name="exportexcel-all"><i class="far fa-file-excel"></i> @T("Admin.Common.ExportToExcel.All")</button></li>
|
||
<li class="dropdown-item"><button type="button" id="exportexcel-selected"><i class="far fa-file-excel"></i> @T("Admin.Common.ExportToExcel.Selected")</button></li>
|
||
</ul>
|
||
</div>
|
||
<div class="btn-group">
|
||
<button type="button" class="btn btn-info"><i class="far fa-file-pdf"></i> @T("Admin.Orders.PdfInvoices")</button>
|
||
<button type="button" class="btn btn-info dropdown-toggle dropdown-icon" data-toggle="dropdown"><span class="sr-only"> </span></button>
|
||
<ul class="dropdown-menu" role="menu">
|
||
<li class="dropdown-item"><button asp-action="PdfInvoice" type="submit" name="pdf-invoice-all">@T("Admin.Orders.PdfInvoices.All")</button></li>
|
||
<li class="dropdown-item"><button type="button" id="pdf-invoice-selected">@T("Admin.Orders.PdfInvoices.Selected")</button></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
<section class="content">
|
||
<div class="container-fluid">
|
||
|
||
@* ── Filter Panel ─────────────────────────────────────────────── *@
|
||
<div class="card card-default card-search mb-2">
|
||
<div class="card-body py-2">
|
||
<div class="row align-items-end">
|
||
@* Date from *@
|
||
<div class="col-md-2">
|
||
<div class="form-group mb-1">
|
||
<nop-label asp-for="StartDate" />
|
||
<nop-editor asp-for="StartDate" />
|
||
</div>
|
||
</div>
|
||
@* Date to *@
|
||
<div class="col-md-2">
|
||
<div class="form-group mb-1">
|
||
<nop-label asp-for="EndDate" />
|
||
<nop-editor asp-for="EndDate" />
|
||
</div>
|
||
</div>
|
||
@* Partner autocomplete → stores customer ID in hidden *@
|
||
<div class="col-md-4">
|
||
<div class="form-group mb-1">
|
||
<label class="col-form-label">Partner</label>
|
||
<div class="input-group">
|
||
<input type="text" id="fb-company-display" autocomplete="off" class="form-control" placeholder="Cég neve..." />
|
||
<div class="input-group-append">
|
||
<button type="button" id="fb-company-clear" class="btn btn-outline-secondary" style="display:none">
|
||
<i class="fas fa-times"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<input asp-for="BillingCompany" type="hidden" id="BillingCompany" />
|
||
</div>
|
||
</div>
|
||
@* Go to order by number *@
|
||
<div class="col-md-3">
|
||
<div class="form-group mb-1">
|
||
<nop-label asp-for="GoDirectlyToCustomOrderNumber" />
|
||
<div class="input-group">
|
||
<nop-editor asp-for="GoDirectlyToCustomOrderNumber" />
|
||
<div class="input-group-append">
|
||
<button type="button" id="go-to-order-by-number" class="btn btn-info">
|
||
@T("Admin.Common.Go")
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
@* Search button *@
|
||
<div class="col-md-1">
|
||
<div class="form-group mb-1">
|
||
<label class="col-form-label"> </label>
|
||
<button type="button" id="fb-search-btn" class="btn btn-primary btn-block">
|
||
<i class="fas fa-search"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
@* ── Grid ─────────────────────────────────────────────────────── *@
|
||
<div class="card card-default">
|
||
<div class="card-body p-0">
|
||
@* Anti-forgery token for AJAX POSTs *@
|
||
@Html.AntiForgeryToken()
|
||
<table id="fb-orders-grid" class="table table-bordered table-hover m-0" style="width:100%">
|
||
<thead>
|
||
<tr>
|
||
<th><input type="checkbox" id="fb-check-all" title="Összes kijelölése"></th>
|
||
<th>Rendelés #</th>
|
||
<th>Partner</th>
|
||
<th>InnVoice</th>
|
||
<th>Súly</th>
|
||
<th>Mérhető</th>
|
||
<th>Mérés</th>
|
||
<th title="Kattintásra szerkeszthető">Átvétel <small class="text-muted">✏️</small></th>
|
||
<th>Státusz</th>
|
||
<th>Fizetés</th>
|
||
<th>Szállítás</th>
|
||
<th>Létrehozva</th>
|
||
<th>Összeg</th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
</table>
|
||
</div>
|
||
<div id="fb-totals-row" class="card-footer py-2" style="display:none">
|
||
<div id="fb-totals-content" class="small text-muted"></div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
|
||
@* ── Export selected – XML ──────────────────────────────────────── *@
|
||
<form asp-controller="Order" asp-action="ExportXmlSelected" method="post" id="export-xml-selected-form">
|
||
<input type="hidden" id="export-xml-ids" name="selectedIds" value="" />
|
||
</form>
|
||
@* ── Export selected – Excel ────────────────────────────────────── *@
|
||
<form asp-controller="Order" asp-action="ExportExcelSelected" method="post" id="export-excel-selected-form">
|
||
<input type="hidden" id="export-excel-ids" name="selectedIds" value="" />
|
||
</form>
|
||
@* ── PDF selected ───────────────────────────────────────────────── *@
|
||
<form asp-controller="Order" asp-action="PdfInvoiceSelected" method="post" id="pdf-invoice-selected-form">
|
||
<input type="hidden" id="pdf-invoice-ids" name="selectedIds" value="" />
|
||
</form>
|
||
|
||
@* ── Create Order Modal ─────────────────────────────────────────── *@
|
||
<div id="create-order-window" class="modal fade" tabindex="-1" role="dialog">
|
||
<div class="modal-dialog modal-lg">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h4 class="modal-title">@T("Admin.Orders.AddNew")</h4>
|
||
<button type="button" class="close" data-dismiss="modal"><span>×</span></button>
|
||
</div>
|
||
<form asp-controller="CustomOrder" asp-action="Create" method="post" id="create-order-form">
|
||
<div class="form-horizontal">
|
||
<div class="modal-body">
|
||
<div class="form-group row">
|
||
<div class="col-md-3"><label class="col-form-label">@T("Admin.Orders.Fields.Customer")</label></div>
|
||
<div class="col-md-9">
|
||
<input type="text" id="create-order-customer-search" autocomplete="off" class="form-control" placeholder="Ügyfél neve vagy email..." />
|
||
<span id="create-order-customer-name" class="mt-1 d-block"></span>
|
||
<input type="hidden" id="create-order-customer-id" name="customerId" />
|
||
<span class="field-validation-error" id="create-order-customer-error" style="display:none">Kérjük válasszon ügyfelet</span>
|
||
</div>
|
||
</div>
|
||
<div class="form-group row" id="create-product-search-section" style="display:none">
|
||
<div class="col-md-3"><label class="col-form-label">@T("Admin.Orders.Fields.Product")</label></div>
|
||
<div class="col-md-9">
|
||
<input type="text" id="create-order-product-search" autocomplete="off" class="form-control" placeholder="Termék neve vagy SKU..." />
|
||
</div>
|
||
</div>
|
||
<div id="create-selected-products-section" style="display:none">
|
||
<table class="table table-sm table-bordered" id="create-products-table">
|
||
<thead><tr><th>Termék</th><th style="width:100px">Menny.</th><th style="width:120px">Egységár</th><th style="width:40px"></th></tr></thead>
|
||
<tbody id="create-products-body"></tbody>
|
||
</table>
|
||
</div>
|
||
<input type="hidden" id="create-order-products-json" name="orderProductsJson" />
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-dismiss="modal">@T("Admin.Common.Cancel")</button>
|
||
<button type="submit" class="btn btn-primary">@T("Admin.Common.Create")</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<style>
|
||
/* ── Column filter row ──────────────────────────────────────── */
|
||
#fb-orders-grid thead tr.fb-filter-row th {
|
||
padding: 3px 4px;
|
||
background-color: #f4f6f9;
|
||
border-bottom: 2px solid #dee2e6;
|
||
}
|
||
#fb-orders-grid thead tr.fb-filter-row input,
|
||
#fb-orders-grid thead tr.fb-filter-row select {
|
||
width: 100%;
|
||
height: 26px;
|
||
padding: 1px 4px;
|
||
font-size: 11px;
|
||
border: 1px solid #ced4da;
|
||
border-radius: 3px;
|
||
background: #fff;
|
||
}
|
||
#fb-orders-grid thead tr.fb-filter-row input:focus,
|
||
#fb-orders-grid thead tr.fb-filter-row select:focus {
|
||
outline: none;
|
||
border-color: #80bdff;
|
||
box-shadow: 0 0 0 2px rgba(0,123,255,.15);
|
||
}
|
||
/* ── Editable date cell ────────────────────────────────────── */
|
||
#fb-orders-grid tbody td.fb-editable-date {
|
||
cursor: pointer;
|
||
}
|
||
#fb-orders-grid tbody td.fb-editable-date:hover {
|
||
background-color: #fff8e1;
|
||
}
|
||
#fb-orders-grid tbody td.fb-editable-date input[type="date"] {
|
||
width: 120px;
|
||
font-size: 12px;
|
||
padding: 1px 4px;
|
||
border: 1px solid #80bdff;
|
||
border-radius: 3px;
|
||
}
|
||
/* ── Stripe rows ───────────────────────────────────────────── */
|
||
#fb-orders-grid tbody tr:nth-child(even) {
|
||
background-color: #f9f9f9;
|
||
}
|
||
#fb-orders-grid tbody tr:hover {
|
||
background-color: #eaf2ff;
|
||
}
|
||
/* ── Processing overlay ────────────────────────────────────── */
|
||
#fb-orders-grid_processing {
|
||
background: rgba(255,255,255,0.85);
|
||
border: 1px solid #dee2e6;
|
||
border-radius: 4px;
|
||
padding: 8px 16px;
|
||
font-size: 13px;
|
||
}
|
||
/* autocomplete z-index fix in modals */
|
||
.ui-autocomplete { z-index: 1060 !important; }
|
||
</style>
|
||
|
||
<script>
|
||
$(function () {
|
||
|
||
/* ── Helpers ─────────────────────────────────────────────────── */
|
||
var _token = $('input[name="__RequestVerificationToken"]').val();
|
||
|
||
function antiForgery(obj) {
|
||
obj['__RequestVerificationToken'] = _token;
|
||
return obj;
|
||
}
|
||
|
||
var selectedIds = [];
|
||
|
||
function getSelectedIds() {
|
||
selectedIds = [];
|
||
$('#fb-orders-grid tbody .fb-row-check:checked').each(function () {
|
||
selectedIds.push($(this).val());
|
||
});
|
||
return selectedIds;
|
||
}
|
||
|
||
/* ── Column renderers ────────────────────────────────────────── */
|
||
function renderInnvoice(data) {
|
||
return data
|
||
? '<span class="badge badge-success">Igen</span>'
|
||
: '<span class="badge badge-secondary">Nem</span>';
|
||
}
|
||
|
||
function renderWeightValid(data) {
|
||
return data
|
||
? '<span class="badge badge-success">OK</span>'
|
||
: '<span class="badge badge-danger font-weight-bold">!</span>';
|
||
}
|
||
|
||
function renderMeasurable(data) {
|
||
return data
|
||
? '<span class="badge badge-info">Igen</span>'
|
||
: '<span class="badge badge-light text-secondary">Nem</span>';
|
||
}
|
||
|
||
function renderMeasuringStatus(val, row) {
|
||
var map = { 10: 'warning', 20: 'primary', 30: 'success', 40: 'danger' };
|
||
var cls = map[val] || 'secondary';
|
||
var label = row.MeasuringStatusString || String(val);
|
||
return '<span class="badge badge-' + cls + '">' + label + '</span>';
|
||
}
|
||
|
||
function renderDateOfReceipt(data) {
|
||
if (!data) return '<span class="text-muted">—</span>';
|
||
var d = new Date(data);
|
||
var dateStr = d.toLocaleDateString('hu-HU');
|
||
var timeStr = d.toLocaleTimeString('hu-HU', { hour: '2-digit', minute: '2-digit' });
|
||
return '<span>' + dateStr + ' ' + timeStr + '</span>';
|
||
}
|
||
|
||
function renderOrderStatus(statusId, row) {
|
||
var map = { 10: 'warning', 20: 'primary', 30: 'success', 40: 'danger' };
|
||
var cls = map[statusId] || 'secondary';
|
||
var label = row.OrderStatus || String(statusId);
|
||
return '<span class="badge badge-' + cls + '">' + label + '</span>';
|
||
}
|
||
|
||
/* ── DataTables ──────────────────────────────────────────────── */
|
||
var table = $('#fb-orders-grid').DataTable({
|
||
serverSide : true,
|
||
processing : true,
|
||
orderCellsTop: true,
|
||
stateSave : false,
|
||
pageLength : 50,
|
||
lengthMenu : [[20, 50, 100, 200, 500], [20, 50, 100, 200, 500]],
|
||
order : [[0, 'desc']],
|
||
language : {
|
||
processing : 'Betöltés...',
|
||
search : 'Keresés:',
|
||
lengthMenu : '_MENU_ sor/oldal',
|
||
info : '_START_ – _END_ / _TOTAL_ rendelés',
|
||
infoEmpty : '0 rendelés',
|
||
infoFiltered : '(szűrve _MAX_-ból)',
|
||
paginate : { first: '««', previous: '«', next: '»', last: '»»' },
|
||
emptyTable : 'Nincs találat',
|
||
zeroRecords : 'Nincs találat a szűrési feltételekre'
|
||
},
|
||
ajax: {
|
||
url : '@Url.Action("FruitBankOrderList", "CustomOrder")',
|
||
type: 'POST',
|
||
data: function (d) {
|
||
d.StartDate = $('#@Html.IdFor(m => m.StartDate)').val();
|
||
d.EndDate = $('#@Html.IdFor(m => m.EndDate)').val();
|
||
d.BillingCompany = $('#BillingCompany').val();
|
||
addAntiForgeryToken(d);
|
||
},
|
||
error: function (xhr) {
|
||
console.error('FruitBankOrderList AJAX error:', xhr.status, xhr.responseText);
|
||
}
|
||
},
|
||
columns: [
|
||
/* 0 */ { data: 'Id', name: 'Id', orderable: false, searchable: false, width: '32px',
|
||
className: 'text-center',
|
||
render: function (d) { return '<input type="checkbox" class="fb-row-check" value="' + d + '">'; } },
|
||
/* 1 */ { data: 'CustomOrderNumber', name: 'CustomOrderNumber', width: '95px' },
|
||
/* 2 */ { data: 'CustomerCompany', name: 'CustomerCompany' },
|
||
/* 3 */ { data: 'InnvoiceTechId', name: 'InnvoiceTechId', orderable: false, width: '75px',
|
||
className: 'text-center',
|
||
render: function (d) { return renderInnvoice(d); } },
|
||
/* 4 */ { data: 'IsAllOrderItemAvgWeightValid', name: 'IsAllOrderItemAvgWeightValid', orderable: false, width: '55px',
|
||
className: 'text-center',
|
||
render: function (d) { return renderWeightValid(d); } },
|
||
/* 5 */ { data: 'IsMeasurable', name: 'IsMeasurable', orderable: false, width: '65px',
|
||
className: 'text-center',
|
||
render: function (d) { return renderMeasurable(d); } },
|
||
/* 6 */ { data: 'MeasuringStatus', name: 'MeasuringStatus', width: '95px',
|
||
className: 'text-center',
|
||
render: function (d, t, row) { return renderMeasuringStatus(d, row); } },
|
||
/* 7 */ { data: 'DateOfReceipt', name: 'DateOfReceipt', width: '110px',
|
||
className: 'text-center fb-editable-date',
|
||
render: function (d) { return renderDateOfReceipt(d); } },
|
||
/* 8 */ { data: 'OrderStatusId', name: 'OrderStatusId', width: '105px',
|
||
className: 'text-center',
|
||
render: function (d, t, row) { return renderOrderStatus(d, row); } },
|
||
/* 9 */ { data: 'PaymentStatus', name: 'PaymentStatus', orderable: false, width: '110px',
|
||
render: function (d) { return d || '—'; } },
|
||
/* 10 */ { data: 'ShippingStatus', name: 'ShippingStatus', orderable: false, width: '110px',
|
||
render: function (d) { return d || '—'; } },
|
||
/* 11 */ { data: 'CreatedOn', name: 'CreatedOn', width: '92px',
|
||
className: 'text-center',
|
||
render: function (d) { return d ? new Date(d).toLocaleDateString('hu-HU') : '—'; } },
|
||
/* 12 */ { data: 'OrderTotal', name: 'OrderTotal', orderable: false, width: '105px',
|
||
className: 'text-right' },
|
||
/* 13 */ { data: 'Id', name: null, orderable: false, searchable: false, width: '42px',
|
||
className: 'text-center',
|
||
render: function (d) { return '<a href="/Admin/Order/Edit/' + d + '" class="btn btn-default btn-xs" title="Szerkesztés"><i class="fas fa-pencil-alt"></i></a>'; } }
|
||
],
|
||
|
||
/* ── Per-column filter row ─────────────────────────────────── */
|
||
initComplete: function () {
|
||
var api = this.api();
|
||
var $thead = $(this).find('thead');
|
||
var $filterRow = $('<tr class="fb-filter-row"></tr>').appendTo($thead);
|
||
|
||
// Filter definition per column index:
|
||
// null = no filter, 'text' = text input, {type:'select', opts:[...]} = dropdown
|
||
var defs = [
|
||
null, /* 0 checkbox */
|
||
'text', /* 1 order # */
|
||
'text', /* 2 company */
|
||
{ type: 'select', opts: [['', 'Mind'], ['has', '✓ Igen'], ['none', '✗ Nem']] }, /* 3 innvoice */
|
||
null, /* 4 weight (no per-column filter) */
|
||
{ type: 'select', opts: [['', 'Mind'], ['true', 'Igen'], ['false', 'Nem']] }, /* 5 measurable */
|
||
{ type: 'select', opts: [['', 'Mind'], ['0', 'Nincs'], ['10', '…folyamat'], ['20', 'Mérésre'], ['30', 'Mérve'], ['40', 'Lezárva']] }, /* 6 measuring */
|
||
null, /* 7 date (top-level filter handles this) */
|
||
{ type: 'select', opts: [['', 'Mind'], ['10', 'Függőben'], ['20', 'Feldolgozás'], ['30', 'Teljesítve'], ['40', 'Törölve']] }, /* 8 order status */
|
||
null, /* 9 payment */
|
||
null, /* 10 shipping */
|
||
null, /* 11 created */
|
||
null, /* 12 total */
|
||
null /* 13 button */
|
||
];
|
||
|
||
api.columns().every(function (idx) {
|
||
var col = this;
|
||
var $th = $('<th></th>').appendTo($filterRow);
|
||
var def = defs[idx];
|
||
if (!def) return;
|
||
|
||
if (def === 'text') {
|
||
var $inp = $('<input type="text" placeholder="🔍">');
|
||
$inp.appendTo($th);
|
||
var timer;
|
||
$inp.on('input', function () {
|
||
clearTimeout(timer);
|
||
var v = this.value;
|
||
timer = setTimeout(function () { col.search(v).draw(); }, 450);
|
||
});
|
||
} else if (def.type === 'select') {
|
||
var $sel = $('<select></select>');
|
||
def.opts.forEach(function (o) {
|
||
$sel.append($('<option>').val(o[0]).text(o[1]));
|
||
});
|
||
$sel.appendTo($th);
|
||
$sel.on('change', function () { col.search(this.value).draw(); });
|
||
}
|
||
});
|
||
}
|
||
});
|
||
|
||
/* ── Search / filter triggers ────────────────────────────────── */
|
||
$('#fb-search-btn').on('click', function () { table.draw(); });
|
||
|
||
/* redraw on date change */
|
||
$('#@Html.IdFor(m => m.StartDate), #@Html.IdFor(m => m.EndDate)').on('change', function () { table.draw(); });
|
||
|
||
/* ── Partner (company) autocomplete ──────────────────────────── */
|
||
$('#fb-company-display').autocomplete({
|
||
delay : 400,
|
||
minLength: 2,
|
||
source : '@Url.Action("CustomerSearchAutoComplete", "CustomOrder")',
|
||
select : function (e, ui) {
|
||
$('#BillingCompany').val(ui.item.value);
|
||
$('#fb-company-display').val(ui.item.label);
|
||
$('#fb-company-clear').show();
|
||
table.draw();
|
||
return false;
|
||
}
|
||
});
|
||
|
||
$('#fb-company-clear').on('click', function () {
|
||
$('#BillingCompany').val('');
|
||
$('#fb-company-display').val('');
|
||
$(this).hide();
|
||
table.draw();
|
||
});
|
||
|
||
/* ── Checkbox: select all on current page ────────────────────── */
|
||
$('#fb-check-all').on('change', function () {
|
||
var checked = this.checked;
|
||
$('#fb-orders-grid tbody .fb-row-check').prop('checked', checked);
|
||
});
|
||
|
||
/* ── Inline editing: DateOfReceipt ───────────────────────────── */
|
||
$(document).on('click', '#fb-orders-grid tbody td.fb-editable-date', function (e) {
|
||
var $td = $(this);
|
||
if ($td.find('input').length) return; // already in edit mode
|
||
|
||
var $row = $td.closest('tr');
|
||
var rowData = table.row($row).data();
|
||
if (!rowData) return;
|
||
|
||
// Build a datetime-local string (YYYY-MM-DDTHH:mm) for the input value
|
||
function toDatetimeLocal(iso) {
|
||
if (!iso) return '';
|
||
var d = new Date(iso);
|
||
if (isNaN(d)) return '';
|
||
var pad = function(n) { return String(n).padStart(2, '0'); };
|
||
return d.getFullYear() + '-' + pad(d.getMonth()+1) + '-' + pad(d.getDate()) +
|
||
'T' + pad(d.getHours()) + ':' + pad(d.getMinutes());
|
||
}
|
||
|
||
var currentIso = rowData.DateOfReceipt || null;
|
||
// Default to now if no date set yet
|
||
var inputVal = currentIso ? toDatetimeLocal(currentIso) : toDatetimeLocal(new Date().toISOString());
|
||
var orderId = rowData.Id;
|
||
var savedHtml = $td.html();
|
||
|
||
var $inp = $('<input type="datetime-local">').val(inputVal);
|
||
$td.html('').append($inp);
|
||
$inp.focus();
|
||
|
||
function restore() { $td.html(savedHtml); }
|
||
|
||
function persist() {
|
||
var newVal = $inp.val(); // format: YYYY-MM-DDTHH:mm
|
||
// Compare against original ISO; skip save only if identical
|
||
var newIso = newVal ? new Date(newVal).toISOString() : null;
|
||
var oldIso = currentIso ? new Date(currentIso).toISOString() : null;
|
||
if (newIso === oldIso) { restore(); return; }
|
||
|
||
$.ajax({
|
||
url : '@Url.Action("UpdateOrderField", "CustomOrder")',
|
||
type : 'POST',
|
||
data : antiForgery({ orderId: orderId, field: 'DateOfReceipt', value: newVal }),
|
||
success: function (res) {
|
||
if (res.success) {
|
||
rowData.DateOfReceipt = newVal || null;
|
||
table.row($row).data(rowData).invalidate();
|
||
/* re-render only the date cell without full redraw */
|
||
$td.html(renderDateOfReceipt(newVal));
|
||
} else {
|
||
restore();
|
||
alert('Mentési hiba: ' + (res.error || 'Ismeretlen hiba'));
|
||
}
|
||
},
|
||
error: function () { restore(); }
|
||
});
|
||
}
|
||
|
||
$inp.on('blur', function () { persist(); });
|
||
$inp.on('keydown', function (e) {
|
||
if (e.key === 'Enter') { $inp.off('blur'); persist(); }
|
||
if (e.key === 'Escape') { $inp.off('blur'); restore(); }
|
||
});
|
||
});
|
||
|
||
/* ── Go-to order by number ───────────────────────────────────── */
|
||
$('#@Html.IdFor(m => m.GoDirectlyToCustomOrderNumber)').on('keydown', function (e) {
|
||
if (e.keyCode === 13) { $('#go-to-order-by-number').trigger('click'); return false; }
|
||
});
|
||
$('#go-to-order-by-number').on('click', function () {
|
||
var num = $('#@Html.IdFor(m => m.GoDirectlyToCustomOrderNumber)').val();
|
||
if (num) {
|
||
window.location.href = '@Url.Action("GoToOrderId", "CustomOrder")?' +
|
||
'@Html.IdFor(m => m.GoDirectlyToCustomOrderNumber)=' + encodeURIComponent(num);
|
||
}
|
||
});
|
||
|
||
/* ── Export / PDF selected ───────────────────────────────────── */
|
||
function exportSelected(formId, inputId) {
|
||
var ids = getSelectedIds().join(',');
|
||
if (!ids) { alert('@T("Admin.Orders.NoOrders")'); return; }
|
||
$(inputId).val(ids);
|
||
$(formId).submit();
|
||
}
|
||
|
||
$('#exportxml-selected').on('click', function (e) { e.preventDefault(); exportSelected('#export-xml-selected-form', '#export-xml-ids'); });
|
||
$('#exportexcel-selected').on('click', function (e) { e.preventDefault(); exportSelected('#export-excel-selected-form', '#export-excel-ids'); });
|
||
$('#pdf-invoice-selected').on('click', function (e) { e.preventDefault(); exportSelected('#pdf-invoice-selected-form', '#pdf-invoice-ids'); });
|
||
|
||
/* ── Create order modal ──────────────────────────────────────── */
|
||
var createProducts = [];
|
||
|
||
$('#create-order-customer-search').autocomplete({
|
||
delay : 400,
|
||
minLength: 2,
|
||
source : '@Url.Action("CustomerSearchAutoComplete", "CustomOrder")',
|
||
select : function (e, ui) {
|
||
$('#create-order-customer-id').val(ui.item.value);
|
||
$('#create-order-customer-name').html('<strong>' + ui.item.label + '</strong>');
|
||
$('#create-order-customer-search').val('');
|
||
$('#create-product-search-section').slideDown();
|
||
return false;
|
||
}
|
||
});
|
||
|
||
$('#create-order-product-search').autocomplete({
|
||
delay : 400,
|
||
minLength: 2,
|
||
source : '@Url.Action("ProductSearchAutoComplete", "CustomOrder")',
|
||
select : function (e, ui) {
|
||
addCreateProduct(ui.item);
|
||
$('#create-order-product-search').val('');
|
||
return false;
|
||
}
|
||
});
|
||
|
||
function addCreateProduct(item) {
|
||
if (createProducts.find(function (p) { return p.id === item.value; })) return;
|
||
createProducts.push({ id: item.value, name: item.label, quantity: 1, price: item.price || 0 });
|
||
renderCreateProducts();
|
||
}
|
||
|
||
function renderCreateProducts() {
|
||
var $body = $('#create-products-body').empty();
|
||
if (!createProducts.length) { $('#create-selected-products-section').hide(); return; }
|
||
$('#create-selected-products-section').show();
|
||
createProducts.forEach(function (p, i) {
|
||
$body.append(
|
||
'<tr>' +
|
||
'<td><strong>' + p.name + '</strong></td>' +
|
||
'<td><input type="number" class="form-control form-control-sm" min="1" value="' + p.quantity + '" data-idx="' + i + '" onchange="window._fbUpdateQty(this)"></td>' +
|
||
'<td><input type="text" class="form-control form-control-sm" value="' + p.price + '" data-idx="' + i + '" onchange="window._fbUpdatePrice(this)"></td>' +
|
||
'<td class="text-center"><button type="button" class="btn btn-danger btn-xs" onclick="window._fbRemoveProduct(' + i + ')"><i class="fas fa-trash"></i></button></td>' +
|
||
'</tr>'
|
||
);
|
||
});
|
||
$('#create-order-products-json').val(JSON.stringify(createProducts));
|
||
}
|
||
|
||
window._fbUpdateQty = function (el) { createProducts[+el.dataset.idx].quantity = +el.value; renderCreateProducts(); };
|
||
window._fbUpdatePrice = function (el) { createProducts[+el.dataset.idx].price = +el.value; renderCreateProducts(); };
|
||
window._fbRemoveProduct = function (i) { createProducts.splice(i, 1); renderCreateProducts(); };
|
||
|
||
$('#create-order-form').on('submit', function (e) {
|
||
if (!$('#create-order-customer-id').val()) {
|
||
e.preventDefault();
|
||
$('#create-order-customer-error').show();
|
||
}
|
||
});
|
||
|
||
$('#create-order-window').on('hidden.bs.modal', function () {
|
||
$('#create-order-customer-search, #create-order-customer-id, #create-order-customer-name').val('').html('');
|
||
$('#create-order-customer-error').hide();
|
||
$('#create-product-search-section').hide();
|
||
createProducts = [];
|
||
renderCreateProducts();
|
||
});
|
||
});
|
||
</script>
|