| | | 1 | | @using OzonDomains.Models |
| | | 2 | | @using OzonOrdersWeb.ViewModels.OrderViewModels |
| | | 3 | | @model CreateOrderViewModel |
| | | 4 | | |
| | | 5 | | @{ |
| | 0 | 6 | | ViewData["Title"] = "Создание нового заказа"; |
| | 0 | 7 | | Layout = "~/Views/Shared/_Layout.cshtml"; |
| | | 8 | | |
| | | 9 | | // Функция для определения контрастного цвета текста |
| | | 10 | | string GetContrastColor(string? hexColor) |
| | | 11 | | { |
| | 0 | 12 | | if (string.IsNullOrEmpty(hexColor)) |
| | 0 | 13 | | return "#000000"; |
| | | 14 | | |
| | 0 | 15 | | hexColor = hexColor.Trim().ToLower(); |
| | | 16 | | |
| | 0 | 17 | | if (hexColor == "transparent" || !hexColor.StartsWith("#") || (hexColor.Length != 4 && hexColor.Length != 7)) |
| | 0 | 18 | | return "#000000"; |
| | | 19 | | |
| | 0 | 20 | | hexColor = hexColor.TrimStart('#'); |
| | | 21 | | |
| | 0 | 22 | | if (hexColor.Length == 3) |
| | 0 | 23 | | hexColor = string.Format("{0}{0}{1}{1}{2}{2}", |
| | 0 | 24 | | hexColor[0], hexColor[1], hexColor[2]); |
| | | 25 | | |
| | | 26 | | try |
| | | 27 | | { |
| | 0 | 28 | | int r = Convert.ToInt32(hexColor.Substring(0, 2), 16); |
| | 0 | 29 | | int g = Convert.ToInt32(hexColor.Substring(2, 2), 16); |
| | 0 | 30 | | int b = Convert.ToInt32(hexColor.Substring(4, 2), 16); |
| | | 31 | | |
| | 0 | 32 | | double luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255; |
| | 0 | 33 | | return luminance > 0.5 ? "#000000" : "#ffffff"; |
| | | 34 | | } |
| | 0 | 35 | | catch |
| | | 36 | | { |
| | 0 | 37 | | return "#000000"; |
| | | 38 | | } |
| | 0 | 39 | | } |
| | | 40 | | } |
| | | 41 | | |
| | | 42 | | <link rel="stylesheet" href="~/css/table.css"/> |
| | | 43 | | |
| | | 44 | | <style> |
| | | 45 | | /* Стили для формы создания заказа в виде строки таблицы */ |
| | | 46 | | .create-order-table-container { |
| | | 47 | | margin-top: 1rem; |
| | | 48 | | } |
| | | 49 | | |
| | | 50 | | .create-order-form-row { |
| | | 51 | | background-color: #f8f9fa; |
| | | 52 | | } |
| | | 53 | | |
| | | 54 | | .create-order-form-row td { |
| | | 55 | | padding: 0.5rem 0.4rem; |
| | | 56 | | vertical-align: middle; |
| | | 57 | | position: relative; |
| | | 58 | | transition: all 0.3s ease; |
| | | 59 | | min-width: 100px; |
| | | 60 | | } |
| | | 61 | | |
| | | 62 | | .create-order-form-row input, |
| | | 63 | | .create-order-form-row select { |
| | | 64 | | font-size: 0.875rem; |
| | | 65 | | padding: 0.3rem 0.4rem; |
| | | 66 | | height: auto; |
| | | 67 | | transition: all 0.3s ease; |
| | | 68 | | } |
| | | 69 | | |
| | | 70 | | .create-order-form-row .form-control-sm { |
| | | 71 | | font-size: 0.85rem; |
| | | 72 | | height: 28px; |
| | | 73 | | } |
| | | 74 | | |
| | | 75 | | /* Расширение столбца при фокусе (исключая столбец с товарами) */ |
| | | 76 | | .create-order-form-row td:not(.product-column):has(input:focus), |
| | | 77 | | .create-order-form-row td:not(.product-column):has(select:focus) { |
| | | 78 | | min-width: 250px; |
| | | 79 | | z-index: 10; |
| | | 80 | | background-color: #fff; |
| | | 81 | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); |
| | | 82 | | } |
| | | 83 | | |
| | | 84 | | .create-order-form-row td:not(.product-column):has(input:focus) input, |
| | | 85 | | .create-order-form-row td:not(.product-column):has(select:focus) select { |
| | | 86 | | width: 100%; |
| | | 87 | | min-width: 220px; |
| | | 88 | | box-shadow: 0 0 10px rgba(13, 110, 253, 0.3); |
| | | 89 | | border-color: #0d6efd; |
| | | 90 | | } |
| | | 91 | | |
| | | 92 | | /* Столбец с товарами не расширяется при фокусе */ |
| | | 93 | | .create-order-form-row td.product-column { |
| | | 94 | | min-width: 350px !important; |
| | | 95 | | width: 25% !important; |
| | | 96 | | } |
| | | 97 | | |
| | | 98 | | .create-order-form-row td.product-column:has(input:focus), |
| | | 99 | | .create-order-form-row td.product-column:has(select:focus) { |
| | | 100 | | min-width: 350px !important; |
| | | 101 | | width: 25% !important; |
| | | 102 | | box-shadow: none; |
| | | 103 | | background-color: transparent; |
| | | 104 | | } |
| | | 105 | | |
| | | 106 | | .create-order-form-row td.product-column input:focus, |
| | | 107 | | .create-order-form-row td.product-column select:focus { |
| | | 108 | | width: auto !important; |
| | | 109 | | min-width: auto !important; |
| | | 110 | | box-shadow: 0 0 5px rgba(13, 110, 253, 0.2); |
| | | 111 | | } |
| | | 112 | | |
| | | 113 | | /* Подсказки для полей */ |
| | | 114 | | .create-order-form-row input[title], |
| | | 115 | | .create-order-form-row select[title] { |
| | | 116 | | cursor: help; |
| | | 117 | | } |
| | | 118 | | |
| | | 119 | | .create-order-form-row input[title]:hover, |
| | | 120 | | .create-order-form-row select[title]:hover { |
| | | 121 | | border-color: #0d6efd; |
| | | 122 | | } |
| | | 123 | | |
| | | 124 | | .create-order-actions { |
| | | 125 | | display: flex; |
| | | 126 | | gap: 0.5rem; |
| | | 127 | | align-items: center; |
| | | 128 | | justify-content: center; |
| | | 129 | | } |
| | | 130 | | |
| | | 131 | | /* Стили для заголовков как в оригинале */ |
| | | 132 | | .create-order-header { |
| | | 133 | | font-size: 0.75rem; |
| | | 134 | | font-weight: 600; |
| | | 135 | | margin-bottom: 0.25rem; |
| | | 136 | | } |
| | | 137 | | |
| | | 138 | | .create-order-header.text-dark { |
| | | 139 | | color: #212529; |
| | | 140 | | } |
| | | 141 | | |
| | | 142 | | .create-order-header.text-muted { |
| | | 143 | | color: #6c757d; |
| | | 144 | | } |
| | | 145 | | |
| | | 146 | | .create-order-header.text-info { |
| | | 147 | | color: #0dcaf0; |
| | | 148 | | } |
| | | 149 | | |
| | | 150 | | /* Стили для readonly полей */ |
| | | 151 | | .create-order-form-row input[readonly] { |
| | | 152 | | background-color: #e9ecef; |
| | | 153 | | cursor: not-allowed; |
| | | 154 | | } |
| | | 155 | | |
| | | 156 | | /* Стили для автодополнения производителя */ |
| | | 157 | | .autocomplete-dropdown { |
| | | 158 | | max-height: 200px; |
| | | 159 | | overflow-y: auto; |
| | | 160 | | position: absolute; |
| | | 161 | | z-index: 1000; |
| | | 162 | | width: 100%; |
| | | 163 | | background-color: white; |
| | | 164 | | border: 1px solid #ced4da; |
| | | 165 | | border-radius: 0.25rem; |
| | | 166 | | box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); |
| | | 167 | | } |
| | | 168 | | |
| | | 169 | | .autocomplete-dropdown .dropdown-item { |
| | | 170 | | padding: 0.375rem 0.75rem; |
| | | 171 | | cursor: pointer; |
| | | 172 | | } |
| | | 173 | | |
| | | 174 | | .autocomplete-dropdown .dropdown-item:hover, |
| | | 175 | | .autocomplete-dropdown .dropdown-item.active { |
| | | 176 | | background-color: #0d6efd; |
| | | 177 | | color: white; |
| | | 178 | | } |
| | | 179 | | |
| | | 180 | | .autocomplete-dropdown .dropdown-item small { |
| | | 181 | | font-size: 0.75rem; |
| | | 182 | | } |
| | | 183 | | |
| | | 184 | | .position-relative { |
| | | 185 | | position: relative; |
| | | 186 | | } |
| | | 187 | | |
| | | 188 | | /* Подсветка обязательных полей */ |
| | | 189 | | .create-order-form-row input[required], |
| | | 190 | | .create-order-form-row select[required] { |
| | | 191 | | border-left: 3px solid #ffc107; |
| | | 192 | | } |
| | | 193 | | |
| | | 194 | | .create-order-form-row input[required]:focus, |
| | | 195 | | .create-order-form-row select[required]:focus { |
| | | 196 | | border-left-color: #0d6efd; |
| | | 197 | | } |
| | | 198 | | |
| | | 199 | | /* Зеленая подсветка для заполненных обязательных полей */ |
| | | 200 | | .create-order-form-row input[required]:valid, |
| | | 201 | | .create-order-form-row select[required]:valid { |
| | | 202 | | border-left-color: #28a745; |
| | | 203 | | } |
| | | 204 | | |
| | | 205 | | .create-order-form-row input[required]:valid:focus, |
| | | 206 | | .create-order-form-row select[required]:valid:focus { |
| | | 207 | | border-left-color: #0d6efd; |
| | | 208 | | } |
| | | 209 | | |
| | | 210 | | /* Зеленая подсветка для заполненных обязательных полей через класс */ |
| | | 211 | | .create-order-form-row input.field-filled, |
| | | 212 | | .create-order-form-row select.field-filled { |
| | | 213 | | border-left-color: #28a745; |
| | | 214 | | } |
| | | 215 | | |
| | | 216 | | /* Стили для кнопок быстрого выбора дат */ |
| | | 217 | | .input-group-sm .btn { |
| | | 218 | | padding: 0.25rem 0.5rem; |
| | | 219 | | font-size: 0.75rem; |
| | | 220 | | } |
| | | 221 | | |
| | | 222 | | /* Улучшенные tooltips */ |
| | | 223 | | .enhanced-tooltip { |
| | | 224 | | position: relative; |
| | | 225 | | cursor: help; |
| | | 226 | | } |
| | | 227 | | |
| | | 228 | | .enhanced-tooltip:hover::after { |
| | | 229 | | content: attr(data-tooltip); |
| | | 230 | | position: absolute; |
| | | 231 | | bottom: 100%; |
| | | 232 | | left: 50%; |
| | | 233 | | transform: translateX(-50%); |
| | | 234 | | background: #333; |
| | | 235 | | color: white; |
| | | 236 | | padding: 8px 12px; |
| | | 237 | | border-radius: 4px; |
| | | 238 | | font-size: 0.875rem; |
| | | 239 | | white-space: nowrap; |
| | | 240 | | z-index: 1000; |
| | | 241 | | margin-bottom: 5px; |
| | | 242 | | box-shadow: 0 2px 8px rgba(0,0,0,0.2); |
| | | 243 | | pointer-events: none; |
| | | 244 | | } |
| | | 245 | | |
| | | 246 | | .enhanced-tooltip:hover::before { |
| | | 247 | | content: ''; |
| | | 248 | | position: absolute; |
| | | 249 | | bottom: 100%; |
| | | 250 | | left: 50%; |
| | | 251 | | transform: translateX(-50%); |
| | | 252 | | border: 5px solid transparent; |
| | | 253 | | border-top-color: #333; |
| | | 254 | | z-index: 1000; |
| | | 255 | | margin-bottom: -5px; |
| | | 256 | | } |
| | | 257 | | |
| | | 258 | | /* Цветовая индикация статусов */ |
| | | 259 | | .status-option { |
| | | 260 | | padding: 4px 8px; |
| | | 261 | | border-radius: 4px; |
| | | 262 | | display: inline-block; |
| | | 263 | | font-size: 13px; |
| | | 264 | | } |
| | | 265 | | |
| | | 266 | | /* Кастомный select для статусов */ |
| | | 267 | | .status-select-custom { |
| | | 268 | | background-color: #fff; |
| | | 269 | | border: 1px solid #ced4da; |
| | | 270 | | } |
| | | 271 | | |
| | | 272 | | .status-select-custom:hover { |
| | | 273 | | border-color: #0d6efd; |
| | | 274 | | } |
| | | 275 | | |
| | | 276 | | .status-select-custom:focus { |
| | | 277 | | border-color: #0d6efd; |
| | | 278 | | box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25); |
| | | 279 | | } |
| | | 280 | | |
| | | 281 | | /* Стили для dropdown статусов как на главной странице */ |
| | | 282 | | #appStatusDropdown { |
| | | 283 | | padding: 0.08rem 0; |
| | | 284 | | margin: 0; |
| | | 285 | | font-size: 0.875rem; |
| | | 286 | | box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); |
| | | 287 | | } |
| | | 288 | | |
| | | 289 | | #appStatusDropdown li { |
| | | 290 | | list-style: none; |
| | | 291 | | } |
| | | 292 | | |
| | | 293 | | #appStatusDropdown li a { |
| | | 294 | | display: block; |
| | | 295 | | padding: 0.08rem 0.75rem; |
| | | 296 | | text-decoration: none; |
| | | 297 | | color: inherit; |
| | | 298 | | } |
| | | 299 | | |
| | | 300 | | #appStatusDropdown li a:hover { |
| | | 301 | | background-color: rgba(0, 0, 0, 0.05) !important; |
| | | 302 | | } |
| | | 303 | | |
| | | 304 | | /* Подсветка обязательного поля статуса */ |
| | | 305 | | .status-select-custom[required] { |
| | | 306 | | border-left: 3px solid #ffc107; |
| | | 307 | | } |
| | | 308 | | |
| | | 309 | | .status-select-custom.field-filled { |
| | | 310 | | border-left-color: #28a745; |
| | | 311 | | } |
| | | 312 | | |
| | | 313 | | /* Убираем overflow для ячеек таблицы, чтобы dropdown не обрезался */ |
| | | 314 | | .create-order-form-row td { |
| | | 315 | | overflow: visible !important; |
| | | 316 | | } |
| | | 317 | | |
| | | 318 | | .create-order-table-container { |
| | | 319 | | overflow: visible !important; |
| | | 320 | | } |
| | | 321 | | |
| | | 322 | | .table-container { |
| | | 323 | | overflow: visible !important; |
| | | 324 | | } |
| | | 325 | | |
| | | 326 | | /* Модальное окно предпросмотра */ |
| | | 327 | | .preview-modal .modal-body { |
| | | 328 | | max-height: 70vh; |
| | | 329 | | overflow-y: auto; |
| | | 330 | | } |
| | | 331 | | |
| | | 332 | | .preview-field { |
| | | 333 | | margin-bottom: 0.75rem; |
| | | 334 | | padding-bottom: 0.75rem; |
| | | 335 | | border-bottom: 1px solid #e9ecef; |
| | | 336 | | } |
| | | 337 | | |
| | | 338 | | .preview-field:last-child { |
| | | 339 | | border-bottom: none; |
| | | 340 | | } |
| | | 341 | | |
| | | 342 | | .preview-label { |
| | | 343 | | font-weight: 600; |
| | | 344 | | color: #6c757d; |
| | | 345 | | font-size: 0.875rem; |
| | | 346 | | margin-bottom: 0.25rem; |
| | | 347 | | } |
| | | 348 | | |
| | | 349 | | .preview-value { |
| | | 350 | | font-size: 1rem; |
| | | 351 | | color: #212529; |
| | | 352 | | } |
| | | 353 | | </style> |
| | | 354 | | |
| | 0 | 355 | | @if (Model.ErrorMessage != null) |
| | | 356 | | { |
| | | 357 | | <div class="alert alert-dismissible alert-danger"> |
| | | 358 | | <button type="button" class="btn-close" data-bs-dismiss="alert"></button> |
| | 0 | 359 | | <p>@Html.Raw(Model.ErrorMessage)</p> |
| | | 360 | | </div> |
| | | 361 | | } |
| | | 362 | | |
| | 0 | 363 | | @if (TempData["SuccessMessage"] != null) |
| | | 364 | | { |
| | | 365 | | <div class="alert alert-dismissible alert-success"> |
| | | 366 | | <button type="button" class="btn-close" data-bs-dismiss="alert"></button> |
| | 0 | 367 | | <p>@TempData["SuccessMessage"]</p> |
| | | 368 | | </div> |
| | | 369 | | } |
| | | 370 | | |
| | | 371 | | <div class="container-fluid mt-3"> |
| | | 372 | | <div class="row mb-3"> |
| | | 373 | | <div class="col-12"> |
| | | 374 | | <h2>Создание нового заказа</h2> |
| | | 375 | | </div> |
| | | 376 | | </div> |
| | | 377 | | |
| | | 378 | | <div class="table-container create-order-table-container"> |
| | | 379 | | <table class="table" id="shipmentTable"> |
| | | 380 | | <colgroup id="tableColgroup"></colgroup> |
| | | 381 | | <thead> |
| | | 382 | | <tr> |
| | | 383 | | <th> |
| | | 384 | | <div class="create-order-header text-dark">Номер заказа</div> |
| | | 385 | | <div class="create-order-header text-muted" style="margin-top: 5px;">Доставка</div> |
| | | 386 | | </th> |
| | | 387 | | <th> |
| | | 388 | | <div class="create-order-header text-dark">Клиент</div> |
| | | 389 | | <div class="create-order-header text-muted" style="margin-top: 5px;">Город доставки</div> |
| | | 390 | | </th> |
| | | 391 | | <th> |
| | | 392 | | <div class="create-order-header text-dark">Принят</div> |
| | | 393 | | <div class="create-order-header text-muted" style="margin-top: 5px;">Дата отгр.</div> |
| | | 394 | | </th> |
| | | 395 | | <th> |
| | | 396 | | <div class="create-order-header text-dark">Срок.</div> |
| | | 397 | | <div class="create-order-header text-muted" style="margin-top: 5px;">Остал.</div> |
| | | 398 | | </th> |
| | | 399 | | <th style="min-width: 350px; width: 25%;"> |
| | | 400 | | <div class="container-fluid"> |
| | | 401 | | <div class="row mb-0 justify-content-between"> |
| | | 402 | | <div class="col-md-4"> |
| | | 403 | | <div class="create-order-header text-dark">Key</div> |
| | | 404 | | </div> |
| | | 405 | | <div class="col-md-4"> |
| | | 406 | | <div class="create-order-header text-dark">Производитель</div> |
| | | 407 | | </div> |
| | | 408 | | <div class="col-md-4"> |
| | | 409 | | <div class="create-order-header text-dark">Код товара</div> |
| | | 410 | | </div> |
| | | 411 | | </div> |
| | | 412 | | <div class="row mt-0"> |
| | | 413 | | <div class="col-12"> |
| | | 414 | | <div class="create-order-header text-muted">Наименование товара</div> |
| | | 415 | | </div> |
| | | 416 | | </div> |
| | | 417 | | </div> |
| | | 418 | | </th> |
| | | 419 | | <th> |
| | | 420 | | <div class="create-order-header text-dark">Статус клиента</div> |
| | | 421 | | <div class="create-order-header text-muted" style="margin-top: 5px;">Статус</div> |
| | | 422 | | </th> |
| | | 423 | | <th> |
| | | 424 | | <div class="create-order-header text-dark">Склад отгрузки</div> |
| | | 425 | | </th> |
| | | 426 | | <th> |
| | | 427 | | <div class="create-order-header text-dark">Категория</div> |
| | | 428 | | <div class="create-order-header text-muted" style="margin-top: 5px;">Вес V</div> |
| | | 429 | | </th> |
| | | 430 | | <th> |
| | | 431 | | <div class="create-order-header text-dark">Цена с.</div> |
| | | 432 | | <div class="create-order-header text-muted" style="margin-top: 5px;">Кол.</div> |
| | | 433 | | </th> |
| | | 434 | | <th> |
| | | 435 | | <div class="create-order-header text-dark">Цена</div> |
| | | 436 | | <div class="create-order-header text-muted" style="margin-top: 5px;">Сумма о.</div> |
| | | 437 | | </th> |
| | | 438 | | <th> |
| | | 439 | | <div style="display: flex; flex-direction: column; align-items: center; justify-content: center;"> |
| | | 440 | | <div class="create-order-header text-dark">Комис.</div> |
| | | 441 | | <div style="text-align: center; font-size: 10px;" class="text-muted"> |
| | | 442 | | <div><small>min</small></div> |
| | | 443 | | <div><small>max</small></div> |
| | | 444 | | </div> |
| | | 445 | | </div> |
| | | 446 | | </th> |
| | | 447 | | </tr> |
| | | 448 | | </thead> |
| | | 449 | | <tbody> |
| | | 450 | | <form asp-action="Create" method="post" id="createOrderForm"> |
| | | 451 | | <tr class="create-order-form-row"> |
| | | 452 | | <td> |
| | | 453 | | <div class="d-flex flex-column"> |
| | | 454 | | <input asp-for="Order.ShipmentNumber" class="form-control form-control-sm mb-1 enhanced-tool |
| | | 455 | | placeholder="Номер отправления *" required |
| | | 456 | | title="Номер отправления заказа (обязательное поле)" |
| | | 457 | | data-tooltip="Уникальный номер отправления заказа. Используется для идентификации зак |
| | | 458 | | <span asp-validation-for="Order.ShipmentNumber" class="text-danger small"></span> |
| | | 459 | | |
| | | 460 | | <select asp-for="Order.DeliveryId" asp-items="Model.DeliveriesSelectList" |
| | | 461 | | class="form-control form-control-sm mt-1 enhanced-tooltip" |
| | | 462 | | title="Тип доставки" |
| | | 463 | | data-tooltip="Выберите тип доставки из справочника. Определяет способ доставки заказ |
| | | 464 | | <option value="">Доставка</option> |
| | | 465 | | </select> |
| | | 466 | | <span asp-validation-for="Order.DeliveryId" class="text-danger small"></span> |
| | | 467 | | </div> |
| | | 468 | | </td> |
| | | 469 | | |
| | | 470 | | <td> |
| | | 471 | | <div class="d-flex flex-column"> |
| | | 472 | | <select asp-for="Order.OzonClientId" asp-items="Model.OzonClientsSelectList" |
| | | 473 | | class="form-control form-control-sm mb-1 ozon-client-select enhanced-tooltip" requir |
| | | 474 | | title="Клиент Ozon/Yandex" |
| | | 475 | | data-tooltip="Выберите клиента из справочника (Ozon, Yandex и др.). При выборе клиен |
| | | 476 | | <option value="">Клиент *</option> |
| | 0 | 477 | | @foreach (var client in Model.OzonClients) |
| | | 478 | | { |
| | 0 | 479 | | <option value="@client.Id" data-client-type="@((int)client.ClientType)"> |
| | 0 | 480 | | @client.Name |
| | | 481 | | </option> |
| | | 482 | | } |
| | | 483 | | </select> |
| | | 484 | | <span asp-validation-for="Order.OzonClientId" class="text-danger small"></span> |
| | | 485 | | |
| | | 486 | | <input asp-for="Order.DeliveryCity" class="form-control form-control-sm mt-1" |
| | | 487 | | placeholder="Город доставки" |
| | | 488 | | title="Город доставки заказа"/> |
| | | 489 | | <span asp-validation-for="Order.DeliveryCity" class="text-danger small"></span> |
| | | 490 | | </div> |
| | | 491 | | </td> |
| | | 492 | | |
| | | 493 | | <td> |
| | | 494 | | <div class="d-flex flex-column"> |
| | | 495 | | <div class="input-group input-group-sm mb-1"> |
| | | 496 | | <input asp-for="Order.ProcessingDate" type="datetime-local" |
| | | 497 | | class="form-control form-control-sm" placeholder="Дата принятия" required |
| | | 498 | | title="Дата принятия заказа в обработку (обязательное поле)" id="Order_Processing |
| | | 499 | | <button type="button" class="btn btn-outline-secondary btn-sm" |
| | | 500 | | onclick="setDateToday('Order_ProcessingDate')" |
| | | 501 | | title="Установить сегодняшнюю дату"> |
| | | 502 | | <small>Сегодня</small> |
| | | 503 | | </button> |
| | | 504 | | </div> |
| | | 505 | | <span asp-validation-for="Order.ProcessingDate" class="text-danger small"></span> |
| | | 506 | | |
| | | 507 | | <div class="input-group input-group-sm mt-1"> |
| | | 508 | | <input asp-for="Order.ShippingDate" type="datetime-local" |
| | | 509 | | class="form-control form-control-sm" placeholder="Дата отгрузки" required |
| | | 510 | | title="Дата отгрузки заказа" id="Order_ShippingDate"/> |
| | | 511 | | <button type="button" class="btn btn-outline-secondary btn-sm" |
| | | 512 | | onclick="setDateToday('Order_ShippingDate')" |
| | | 513 | | title="Установить сегодняшнюю дату"> |
| | | 514 | | <small>Сегодня</small> |
| | | 515 | | </button> |
| | | 516 | | </div> |
| | | 517 | | <span asp-validation-for="Order.ShippingDate" class="text-danger small"></span> |
| | | 518 | | </div> |
| | | 519 | | </td> |
| | | 520 | | |
| | | 521 | | <td style="width: 80px; min-width: 80px;"> |
| | | 522 | | <div class="d-flex flex-column"> |
| | | 523 | | <div id="deliveryPeriodDisplay" class="text-center mb-1" style="font-size: 1rem; min-height: |
| | | 524 | | <span class="text-muted">-</span> |
| | | 525 | | </div> |
| | | 526 | | <div id="timeLeftDisplay" class="text-center text-muted" style="font-size: 1rem; min-height: |
| | | 527 | | <span>-</span> |
| | | 528 | | </div> |
| | | 529 | | </div> |
| | | 530 | | </td> |
| | | 531 | | |
| | | 532 | | <td class="product-column" style="min-width: 350px; width: 25%;"> |
| | | 533 | | <div class="container"> |
| | | 534 | | <div class="row mb-1"> |
| | | 535 | | <div class="col-md-4"> |
| | | 536 | | <input asp-for="Order.ProductKey" class="form-control form-control-sm" |
| | | 537 | | placeholder="Key" |
| | | 538 | | title="Ключ продукта (offerId) - формируется автоматически: Артикул=Код произ |
| | | 539 | | readonly/> |
| | | 540 | | <span asp-validation-for="Order.ProductKey" class="text-danger small"></span> |
| | | 541 | | </div> |
| | | 542 | | <div class="col-md-4"> |
| | | 543 | | <div class="position-relative"> |
| | | 544 | | <input type="text" id="Order_EtProducerName" |
| | | 545 | | name="Order.EtProducerName" |
| | | 546 | | class="form-control form-control-sm et-producer-autocomplete" required |
| | | 547 | | placeholder="Производитель *" |
| | | 548 | | autocomplete="off" |
| | | 549 | | title="Производитель JCEtalon (обязательное поле, можно ввести вручную ил |
| | | 550 | | <div id="producerLoadingSpinner" class="position-absolute" style="right: 8px; to |
| | | 551 | | <div class="spinner-border spinner-border-sm text-primary" role="status" sty |
| | | 552 | | <span class="visually-hidden">Загрузка...</span> |
| | | 553 | | </div> |
| | | 554 | | </div> |
| | | 555 | | <input type="hidden" asp-for="Order.EtProducerId" id="Order_EtProducerId"/> |
| | | 556 | | </div> |
| | | 557 | | <span asp-validation-for="Order.EtProducerId" class="text-danger small"></span> |
| | | 558 | | </div> |
| | | 559 | | <div class="col-md-4"> |
| | | 560 | | <input asp-for="Order.Article" class="form-control form-control-sm" |
| | | 561 | | placeholder="Артикул *" required |
| | | 562 | | title="Артикул товара (обязательное поле)"/> |
| | | 563 | | <span asp-validation-for="Order.Article" class="text-danger small"></span> |
| | | 564 | | </div> |
| | | 565 | | </div> |
| | | 566 | | <div class="row"> |
| | | 567 | | <div class="col-12"> |
| | | 568 | | <input asp-for="Order.ProductName" class="form-control form-control-sm" |
| | | 569 | | placeholder="Наименование товара" |
| | | 570 | | title="Наименование товара"/> |
| | | 571 | | <span asp-validation-for="Order.ProductName" class="text-danger small"></span> |
| | | 572 | | </div> |
| | | 573 | | </div> |
| | | 574 | | </div> |
| | | 575 | | </td> |
| | | 576 | | |
| | | 577 | | <td> |
| | | 578 | | <div class="d-flex flex-column"> |
| | | 579 | | <select asp-for="Order.ClientStatusId" id="Order_ClientStatusId" class="form-control form-co |
| | | 580 | | title="Статус клиента"> |
| | | 581 | | <option value="">Статус клиента</option> |
| | | 582 | | </select> |
| | | 583 | | <span asp-validation-for="Order.ClientStatusId" class="text-danger small"></span> |
| | | 584 | | |
| | | 585 | | <input type="hidden" asp-for="Order.AppStatusId" id="Order_AppStatusId"/> |
| | | 586 | | <div class="position-relative"> |
| | | 587 | | <div class="form-control form-control-sm mt-1 status-select-custom" |
| | | 588 | | id="appStatusCustomSelect" |
| | | 589 | | style="cursor: pointer; display: flex; align-items: center; min-height: 28px;" |
| | | 590 | | title="Статус заказа в отчете" |
| | | 591 | | data-tooltip="Выберите статус заказа из справочника. Статусы имеют цветовую индикац |
| | | 592 | | <span id="appStatusSelectedText" style="flex: 1;">Статус</span> |
| | | 593 | | <i class="fas fa-chevron-down" style="font-size: 0.75rem; color: #6c757d;"></i> |
| | | 594 | | </div> |
| | | 595 | | <ul id="appStatusDropdown" class="dropdown-menu filter-dropdown-list" |
| | | 596 | | style="display: none; max-height: 200px; overflow-y: auto; position: fixed; z-index: |
| | | 597 | | <li> |
| | | 598 | | <a href="#" data-value="" style="font-weight: normal;"> Статус</a> |
| | | 599 | | </li> |
| | 0 | 600 | | @foreach (var status in Model.AppStatuses) |
| | | 601 | | { |
| | 0 | 602 | | var bgColor = status.StatusColor?.ColorCode ?? "#ffffff"; |
| | 0 | 603 | | var textColor = GetContrastColor(bgColor); |
| | | 604 | | <li> |
| | | 605 | | <a href="#" |
| | 0 | 606 | | data-value="@status.Id" |
| | 0 | 607 | | data-color="@bgColor" |
| | 0 | 608 | | data-status-name="@status.Name" |
| | | 609 | | style="background-color: @bgColor; color: @textColor; font-weight: normal |
| | 0 | 610 | | @status.Name |
| | | 611 | | </a> |
| | | 612 | | </li> |
| | | 613 | | } |
| | | 614 | | </ul> |
| | | 615 | | </div> |
| | | 616 | | <span asp-validation-for="Order.AppStatusId" class="text-danger small"></span> |
| | | 617 | | </div> |
| | | 618 | | </td> |
| | | 619 | | |
| | | 620 | | <td> |
| | | 621 | | <div class="d-flex flex-column"> |
| | | 622 | | <select asp-for="Order.ShipmentWarehouseId" asp-items="Model.WarehousesSelectList" |
| | | 623 | | class="form-control form-control-sm warehouse-select mb-1" required |
| | | 624 | | title="Склад отгрузки заказа (обязательное поле)"> |
| | | 625 | | <option value="">Склад отгрузки *</option> |
| | | 626 | | </select> |
| | | 627 | | <span asp-validation-for="Order.ShipmentWarehouseId" class="text-danger small"></span> |
| | | 628 | | </div> |
| | | 629 | | </td> |
| | | 630 | | |
| | | 631 | | <td> |
| | | 632 | | <div class="d-flex flex-column"> |
| | | 633 | | <input asp-for="Order.ProductInfo.CommercialCategory" class="form-control form-control-sm mb |
| | | 634 | | placeholder="Категория" |
| | | 635 | | title="Коммерческая категория товара"/> |
| | | 636 | | <span asp-validation-for="Order.ProductInfo.CommercialCategory" class="text-danger small"></ |
| | | 637 | | |
| | | 638 | | <input asp-for="Order.ProductInfo.VolumetricWeight" type="number" step="0.01" |
| | | 639 | | class="form-control form-control-sm mt-1" placeholder="Объемный вес" |
| | | 640 | | title="Объемный вес товара в килограммах"/> |
| | | 641 | | <span asp-validation-for="Order.ProductInfo.VolumetricWeight" class="text-danger small"></sp |
| | | 642 | | </div> |
| | | 643 | | </td> |
| | | 644 | | |
| | | 645 | | <td> |
| | | 646 | | <div class="d-flex flex-column"> |
| | | 647 | | <input asp-for="Order.ProductInfo.CurrentPriceWithDiscount" type="number" step="0.01" |
| | | 648 | | class="form-control form-control-sm mb-1" placeholder="Цена сайта" |
| | | 649 | | title="Цена товара на сайте с учетом скидки"/> |
| | | 650 | | <span asp-validation-for="Order.ProductInfo.CurrentPriceWithDiscount" class="text-danger sma |
| | | 651 | | |
| | | 652 | | <input asp-for="Order.Quantity" type="number" min="1" id="Order_Quantity" required |
| | | 653 | | class="form-control form-control-sm mt-1 enhanced-tooltip" placeholder="Количество *" |
| | | 654 | | title="Количество товара в заказе (обязательное поле)" |
| | | 655 | | data-tooltip="Количество единиц товара в заказе. Минимальное значение: 1. Обязательно |
| | | 656 | | <span asp-validation-for="Order.Quantity" class="text-danger small"></span> |
| | | 657 | | </div> |
| | | 658 | | </td> |
| | | 659 | | |
| | | 660 | | <td> |
| | | 661 | | <div class="d-flex flex-column"> |
| | | 662 | | <input asp-for="Order.Price" type="number" step="0.01" id="Order_Price" required |
| | | 663 | | class="form-control form-control-sm mb-1" placeholder="Цена *" |
| | | 664 | | title="Цена за единицу товара (обязательное поле)"/> |
| | | 665 | | <span asp-validation-for="Order.Price" class="text-danger small"></span> |
| | | 666 | | |
| | | 667 | | <input asp-for="Order.ShipmentAmount" type="number" step="0.01" id="Order_ShipmentAmount" |
| | | 668 | | class="form-control form-control-sm mt-1" placeholder="Сумма отправления" readonly |
| | | 669 | | title="Сумма отправления (рассчитывается автоматически: Цена × Количество)"/> |
| | | 670 | | <span asp-validation-for="Order.ShipmentAmount" class="text-danger small"></span> |
| | | 671 | | </div> |
| | | 672 | | </td> |
| | | 673 | | |
| | | 674 | | <td> |
| | | 675 | | <div class="d-flex flex-column"> |
| | | 676 | | <input asp-for="Order.MinOzonCommission" type="number" step="0.01" |
| | | 677 | | class="form-control form-control-sm mb-1" placeholder="Мин. комиссия" |
| | | 678 | | title="Минимальная комиссия ОЗОН"/> |
| | | 679 | | <span asp-validation-for="Order.MinOzonCommission" class="text-danger small"></span> |
| | | 680 | | |
| | | 681 | | <input asp-for="Order.MaxOzonCommission" type="number" step="0.01" |
| | | 682 | | class="form-control form-control-sm mt-1" placeholder="Макс. комиссия" |
| | | 683 | | title="Максимальная комиссия ОЗОН"/> |
| | | 684 | | <span asp-validation-for="Order.MaxOzonCommission" class="text-danger small"></span> |
| | | 685 | | </div> |
| | | 686 | | </td> |
| | | 687 | | |
| | | 688 | | <!-- Скрытые поля --> |
| | | 689 | | <input type="hidden" asp-for="Order.СurrencyId" id="Order_СurrencyId"/> |
| | | 690 | | <input type="hidden" asp-for="Order.PurchasePrice" id="Order_PurchasePrice"/> |
| | | 691 | | <input type="hidden" asp-for="Order.CostPrice" id="Order_CostPrice"/> |
| | | 692 | | <input type="hidden" asp-for="Order.SupplierId" id="Order_SupplierId"/> |
| | | 693 | | <input type="hidden" asp-for="Order.OrderNumberToSupplier" id="Order_OrderNumberToSupplier"/> |
| | | 694 | | </tr> |
| | | 695 | | </form> |
| | | 696 | | </tbody> |
| | | 697 | | </table> |
| | | 698 | | </div> |
| | | 699 | | |
| | | 700 | | <!-- Кнопки действий под таблицей --> |
| | | 701 | | <div class="form-group mt-3 d-flex justify-content-end"> |
| | | 702 | | <div class="input-group"> |
| | | 703 | | <span class="input-group-btn"> |
| | | 704 | | <button type="submit" form="createOrderForm" class="btn btn-primary" style="width: 170px;"> |
| | | 705 | | <i class="fas fa-check"></i> Создать |
| | | 706 | | </button> |
| | | 707 | | <a asp-action="Index" class="btn btn-secondary ms-2"> |
| | | 708 | | <i class="fas fa-times"></i> Отмена |
| | | 709 | | </a> |
| | | 710 | | </span> |
| | | 711 | | </div> |
| | | 712 | | </div> |
| | | 713 | | </div> |
| | | 714 | | |
| | | 715 | | <!-- Dropdown для производителя вне таблицы --> |
| | | 716 | | <ul id="etProducerDropdown" class="dropdown-menu autocomplete-dropdown" |
| | | 717 | | style="display: none; max-height: 200px; overflow-y: auto; position: fixed; z-index: 9999;"></ul> |
| | | 718 | | |
| | | 719 | | <!-- Модальное окно предпросмотра заказа --> |
| | | 720 | | <div class="modal fade preview-modal" id="orderPreviewModal" tabindex="-1" aria-labelledby="orderPreviewModalLabel" aria |
| | | 721 | | <div class="modal-dialog modal-lg"> |
| | | 722 | | <div class="modal-content"> |
| | | 723 | | <div class="modal-header"> |
| | | 724 | | <h5 class="modal-title" id="orderPreviewModalLabel"> |
| | | 725 | | <i class="fas fa-eye me-2"></i>Предпросмотр заказа |
| | | 726 | | </h5> |
| | | 727 | | <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
| | | 728 | | </div> |
| | | 729 | | <div class="modal-body"> |
| | | 730 | | <div class="row"> |
| | | 731 | | <div class="col-md-6"> |
| | | 732 | | <div class="preview-field"> |
| | | 733 | | <div class="preview-label">Номер заказа</div> |
| | | 734 | | <div class="preview-value" id="preview_ShipmentNumber">-</div> |
| | | 735 | | </div> |
| | | 736 | | <div class="preview-field"> |
| | | 737 | | <div class="preview-label">Доставка</div> |
| | | 738 | | <div class="preview-value" id="preview_Delivery">-</div> |
| | | 739 | | </div> |
| | | 740 | | <div class="preview-field"> |
| | | 741 | | <div class="preview-label">Клиент</div> |
| | | 742 | | <div class="preview-value" id="preview_OzonClient">-</div> |
| | | 743 | | </div> |
| | | 744 | | <div class="preview-field"> |
| | | 745 | | <div class="preview-label">Город доставки</div> |
| | | 746 | | <div class="preview-value" id="preview_DeliveryCity">-</div> |
| | | 747 | | </div> |
| | | 748 | | <div class="preview-field"> |
| | | 749 | | <div class="preview-label">Дата принятия</div> |
| | | 750 | | <div class="preview-value" id="preview_ProcessingDate">-</div> |
| | | 751 | | </div> |
| | | 752 | | <div class="preview-field"> |
| | | 753 | | <div class="preview-label">Дата отгрузки</div> |
| | | 754 | | <div class="preview-value" id="preview_ShippingDate">-</div> |
| | | 755 | | </div> |
| | | 756 | | <div class="preview-field"> |
| | | 757 | | <div class="preview-label">Срок доставки</div> |
| | | 758 | | <div class="preview-value" id="preview_DeliveryPeriod">-</div> |
| | | 759 | | </div> |
| | | 760 | | <div class="preview-field"> |
| | | 761 | | <div class="preview-label">Осталось времени</div> |
| | | 762 | | <div class="preview-value" id="preview_TimeLeft">-</div> |
| | | 763 | | </div> |
| | | 764 | | </div> |
| | | 765 | | <div class="col-md-6"> |
| | | 766 | | <div class="preview-field"> |
| | | 767 | | <div class="preview-label">Key (ProductKey)</div> |
| | | 768 | | <div class="preview-value" id="preview_ProductKey">-</div> |
| | | 769 | | </div> |
| | | 770 | | <div class="preview-field"> |
| | | 771 | | <div class="preview-label">Производитель</div> |
| | | 772 | | <div class="preview-value" id="preview_EtProducer">-</div> |
| | | 773 | | </div> |
| | | 774 | | <div class="preview-field"> |
| | | 775 | | <div class="preview-label">Код товара (Артикул)</div> |
| | | 776 | | <div class="preview-value" id="preview_Article">-</div> |
| | | 777 | | </div> |
| | | 778 | | <div class="preview-field"> |
| | | 779 | | <div class="preview-label">Наименование товара</div> |
| | | 780 | | <div class="preview-value" id="preview_ProductName">-</div> |
| | | 781 | | </div> |
| | | 782 | | <div class="preview-field"> |
| | | 783 | | <div class="preview-label">Статус клиента</div> |
| | | 784 | | <div class="preview-value" id="preview_ClientStatus">-</div> |
| | | 785 | | </div> |
| | | 786 | | <div class="preview-field"> |
| | | 787 | | <div class="preview-label">Статус заказа</div> |
| | | 788 | | <div class="preview-value" id="preview_AppStatus">-</div> |
| | | 789 | | </div> |
| | | 790 | | <div class="preview-field"> |
| | | 791 | | <div class="preview-label">Склад отгрузки</div> |
| | | 792 | | <div class="preview-value" id="preview_ShipmentWarehouse">-</div> |
| | | 793 | | </div> |
| | | 794 | | <div class="preview-field"> |
| | | 795 | | <div class="preview-label">Категория</div> |
| | | 796 | | <div class="preview-value" id="preview_CommercialCategory">-</div> |
| | | 797 | | </div> |
| | | 798 | | <div class="preview-field"> |
| | | 799 | | <div class="preview-label">Объемный вес</div> |
| | | 800 | | <div class="preview-value" id="preview_VolumetricWeight">-</div> |
| | | 801 | | </div> |
| | | 802 | | <div class="preview-field"> |
| | | 803 | | <div class="preview-label">Количество</div> |
| | | 804 | | <div class="preview-value" id="preview_Quantity">-</div> |
| | | 805 | | </div> |
| | | 806 | | <div class="preview-field"> |
| | | 807 | | <div class="preview-label">Цена</div> |
| | | 808 | | <div class="preview-value" id="preview_Price">-</div> |
| | | 809 | | </div> |
| | | 810 | | <div class="preview-field"> |
| | | 811 | | <div class="preview-label">Цена сайта</div> |
| | | 812 | | <div class="preview-value" id="preview_CurrentPriceWithDiscount">-</div> |
| | | 813 | | </div> |
| | | 814 | | <div class="preview-field"> |
| | | 815 | | <div class="preview-label">Сумма отправления</div> |
| | | 816 | | <div class="preview-value" id="preview_ShipmentAmount">-</div> |
| | | 817 | | </div> |
| | | 818 | | <div class="preview-field"> |
| | | 819 | | <div class="preview-label">Мин. комиссия</div> |
| | | 820 | | <div class="preview-value" id="preview_MinOzonCommission">-</div> |
| | | 821 | | </div> |
| | | 822 | | <div class="preview-field"> |
| | | 823 | | <div class="preview-label">Макс. комиссия</div> |
| | | 824 | | <div class="preview-value" id="preview_MaxOzonCommission">-</div> |
| | | 825 | | </div> |
| | | 826 | | </div> |
| | | 827 | | </div> |
| | | 828 | | </div> |
| | | 829 | | <div class="modal-footer"> |
| | | 830 | | <button type="button" class="btn btn-secondary" data-bs-dismiss="modal"> |
| | | 831 | | <i class="fas fa-times me-1"></i>Отмена |
| | | 832 | | </button> |
| | | 833 | | <button type="button" class="btn btn-primary" id="confirmCreateOrder"> |
| | | 834 | | <i class="fas fa-check me-1"></i>Подтвердить создание |
| | | 835 | | </button> |
| | | 836 | | </div> |
| | | 837 | | </div> |
| | | 838 | | </div> |
| | | 839 | | </div> |
| | | 840 | | |
| | 0 | 841 | | @await Html.PartialAsync("_CreateOrderScript", Model) |