From: Vladimir Fomichev Date: Fri, 8 Aug 2025 10:24:46 +0000 (+0300) Subject: Изменения интерфейса X-Git-Url: https://gitweb.erp-flowers.ru/?a=commitdiff_plain;h=b777b85b3defdfdf49b1a441742599588e0a74ed;p=erp24_rep%2Fyii-erp24%2F.git Изменения интерфейса --- diff --git a/erp24/controllers/Products1cNomenclatureActualityController.php b/erp24/controllers/Products1cNomenclatureActualityController.php index 0b478c09..6f645f01 100644 --- a/erp24/controllers/Products1cNomenclatureActualityController.php +++ b/erp24/controllers/Products1cNomenclatureActualityController.php @@ -45,16 +45,16 @@ class Products1cNomenclatureActualityController extends Controller public function actionIndex() { $filter = new \yii\base\DynamicModel([ - 'category','subcategory','species', - 'type','color','sort','size', - 'date_from','date_to', + 'category', 'subcategory', 'species', + 'type', 'color', 'sort', 'size', + 'date_from', 'date_to', ]); $filter->addRule([ - 'category','subcategory','species', - 'type','color','sort','size', - 'date_from','date_to', + 'category', 'subcategory', 'species', + 'type', 'color', 'sort', 'size', + 'date_from', 'date_to', ], 'safe'); - $filter->addRule(['onlyActive','onlyInactive'], 'boolean'); + $filter->addRule(['onlyActive', 'onlyInactive'], 'boolean'); $filter->load(Yii::$app->request->get()); @@ -69,7 +69,7 @@ class Products1cNomenclatureActualityController extends Controller $dataProvider = new \yii\data\ActiveDataProvider([ 'query' => $emptyQuery, 'pagination' => ['pageSize' => 50], - 'sort' => ['defaultOrder'=>['name'=>SORT_ASC]], + 'sort' => ['defaultOrder' => ['name' => SORT_ASC]], ]); $attrMap = [ 'type' => ['type', 'тип'], @@ -118,54 +118,69 @@ class Products1cNomenclatureActualityController extends Controller } } - $needJoin = $filter->onlyActive || $filter->onlyInactive || $filter->date_from || $filter->date_to; - if ($needJoin) { - - - if ($filter->onlyActive) { - $query->innerJoin( - Products1cNomenclatureActuality::tableName() . ' a', - 'a.guid = n.id' - ); - $query->andWhere(['a.guid' => 'n.id']); - } elseif ($filter->onlyInactive) { - // $query->andWhere([ 'not', 'a.guid = n.id']); - } - - if ($filter->date_from || $filter->date_to) { - if (!$filter->onlyActive && !$filter->onlyInactive) { - $query->innerJoin( - Products1cNomenclatureActuality::tableName() . ' a', - 'a.guid = n.id' - ); - } + if ($filter->onlyActive) { + $query->andWhere(['exists', + Products1cNomenclatureActuality::find() + ->where('guid = n.id') + ->select(new \yii\db\Expression('1')) + ]); + } elseif ($filter->onlyInactive) { + $query->andWhere(['not exists', + Products1cNomenclatureActuality::find() + ->where('guid = n.id') + ->select(new \yii\db\Expression('1')) + ]); + } - if ($filter->date_from && $filter->date_to) { + if ($filter->date_from || $filter->date_to) { + $query->with(['actualities' => function ($q) use ($filter) { + if ($filter->date_from) { $df = (new \DateTime("{$filter->date_from}-01")) ->setTime(0, 0, 0)->format('Y-m-d H:i:s'); + $q->andWhere(['>=', 'date_to', $df]); + } + if ($filter->date_to) { $dt = (new \DateTime("{$filter->date_to}-01")) ->modify('last day of this month')->setTime(23, 59, 59) ->format('Y-m-d H:i:s'); - $query->andWhere(['<=', 'a.date_from', $dt]) - ->andWhere(['>=', 'a.date_to', $df]); - } elseif ($filter->date_from) { - $df = (new \DateTime("{$filter->date_from}-01")) - ->setTime(0, 0, 0)->format('Y-m-d H:i:s'); - $query->andWhere(['>=', 'a.date_to', $df]); - } elseif ($filter->date_to) { - $dt = (new \DateTime("{$filter->date_to}-01")) - ->modify('last day of this month')->setTime(23, 59, 59) - ->format('Y-m-d H:i:s'); - $query->andWhere(['<=', 'a.date_from', $dt]); + $q->andWhere(['<=', 'date_from', $dt]); + } + }]); + } else { + $query->with('actualities'); + } + + $products = $query->orderBy(['n.name' => SORT_ASC])->all(); + + $rows = []; + foreach ($products as $product) { + $acts = $product->actualities; + if ($acts) { + foreach ($acts as $act) { + $rows[] = [ + 'product' => $product, + 'actuality' => $act, + ]; } + } else { + $rows[] = [ + 'product' => $product, + 'actuality' => null, + ]; } } - - $dataProvider = new \yii\data\ActiveDataProvider([ - 'query' => $query, + $dataProvider = new \yii\data\ArrayDataProvider([ + 'allModels' => $rows, 'pagination' => ['pageSize' => 1000], - 'sort' => ['defaultOrder' => ['name' => SORT_ASC]], + 'sort' => [ + 'attributes' => [ + 'product.name', + 'actuality.date_from', + 'actuality.date_to' + ], + 'defaultOrder' => ['product.name' => SORT_ASC], + ], ]); } @@ -192,27 +207,27 @@ class Products1cNomenclatureActualityController extends Controller $lists = []; - foreach (['type','color','sort','size'] as $attr) { + foreach (['type', 'color', 'sort', 'size'] as $attr) { $propIds = Products1cPropType::find() ->select('id') - ->andWhere(['name'=>$attrMap[$attr]]) + ->andWhere(['name' => $attrMap[$attr]]) ->column(); $lists[$attr] = Products1cAdditionalCharacteristics::find() ->select('value')->distinct() - ->where(['property_id'=>$propIds]) + ->where(['property_id' => $propIds]) ->column(); } return $this->render('index', [ - 'filter' => $filter, - 'dataProvider' => $dataProvider, - 'categories' => array_combine($categories,$categories), - 'subcategories' => array_combine($subcategories,$subcategories), - 'species' => array_combine($species, $species), - 'types' => array_combine($lists['type'], $lists['type']), - 'colors' => array_combine($lists['color'], $lists['color']), - 'sorts' => array_combine($lists['sort'], $lists['sort']), - 'sizes' => array_combine($lists['size'], $lists['size']), + 'filter' => $filter, + 'dataProvider' => $dataProvider, + 'categories' => array_combine($categories, $categories), + 'subcategories' => array_combine($subcategories, $subcategories), + 'species' => array_combine($species, $species), + 'types' => array_combine($lists['type'], $lists['type']), + 'colors' => array_combine($lists['color'], $lists['color']), + 'sorts' => array_combine($lists['sort'], $lists['sort']), + 'sizes' => array_combine($lists['size'], $lists['size']), ]); } @@ -220,127 +235,73 @@ class Products1cNomenclatureActualityController extends Controller { $request = Yii::$app->request; - $historyDays = $request->get('historyDays'); + $historyDays = $request->get('historyDays'); $intervalMonths = $request->get('intervalMonths'); $startFrom = $request->get('startFrom', date('Y-m-d')); - if ($historyDays === null || $intervalMonths === null) { return $this->render('add-activity', [ - 'historyDays' => $historyDays ?? 14, + 'historyDays' => $historyDays ?? 14, 'intervalMonths' => $intervalMonths ?? 4, + 'startFrom' => $startFrom, ]); } - $endDate = date('Y-m-d', strtotime($startFrom)); + $endDate = date('Y-m-d', strtotime($startFrom)); $startDate = date('Y-m-d', strtotime("-{$historyDays} days", strtotime($endDate))); $productIds = (new Query()) ->select('sp.product_id') ->from(['s' => 'sales']) ->innerJoin(['sp' => 'sales_products'], 's.id = sp.check_id') - //->andWhere(['s.store_id' => $storeIds]) ->innerJoin(['p1c' => 'products_1c_nomenclature'], 'p1c.id = sp.product_id') ->andWhere(['between', 's.date', "{$startDate} 00:00:00", "{$endDate} 23:59:59"]) ->groupBy('sp.product_id') ->column(); if (empty($productIds)) { - Yii::$app->session->setFlash('info', 'Нет товаров, удовлетворяющих условиям.'); + Yii::$app->session->setFlash('info', 'Нет товаров за указанный период.'); return $this->render('add-activity', [ - 'historyDays' => $historyDays, + 'historyDays' => $historyDays, 'intervalMonths' => $intervalMonths, - 'startFrom' => $startFrom, + 'startFrom' => $startFrom, ]); } $now = new \DateTime($endDate); - $from = (clone $now)->modify("-{$intervalMonths} months") - ->modify('first day of this month')->setTime(0,0,0) - ->format('Y-m-d H:i:s'); - $to = (clone $now)->modify("+{$intervalMonths} months") - ->modify('last day of this month')->setTime(23,59,59) - ->format('Y-m-d H:i:s'); - - $userId = Yii::$app->user->id; - $createdAt = date('Y-m-d H:i:s'); - $toInsert = []; - $toDeactivate = []; - - $existingActives = Products1cNomenclatureActuality::find() - ->where(['guid' => $productIds, 'active' => 1]) - ->indexBy('guid') - ->all(); - + $fromStr = (clone $now) + ->modify("-{$intervalMonths} months") + ->modify('first day of this month')->setTime(0, 0, 0) + ->format('Y-m-d H:i:s'); + $toStr = (clone $now) + ->modify("+{$intervalMonths} months") + ->modify('last day of this month')->setTime(23, 59, 59) + ->format('Y-m-d H:i:s'); + + $rows = []; foreach ($productIds as $pid) { - $needNewRecord = true; - - if (isset($existingActives[$pid])) { - $existing = $existingActives[$pid]; - - if ($existing->date_from == $from && $existing->date_to == $to) { - $needNewRecord = false; - } else { - $toDeactivate[] = $existing->id; - } - } - - if ($needNewRecord) { - $toInsert[] = [ - 'guid' => $pid, - 'date_from' => $from, - 'date_to' => $to, - 'active' => 1, - 'created_at' => $createdAt, - 'created_by' => $userId, - ]; - } + $rows[] = [ + 'guid' => $pid, + 'from' => date('Y-m', strtotime($fromStr)), + 'to' => date('Y-m', strtotime($toStr)), + ]; } - $transaction = Yii::$app->db->beginTransaction(); - try { - if (!empty($toDeactivate)) { - Products1cNomenclatureActuality::updateAll( - [ - 'active' => 0, - 'updated_at' => $createdAt, - 'updated_by' => $userId, - ], - ['id' => $toDeactivate] - ); - } - - if (!empty($toInsert)) { - Yii::$app->db->createCommand() - ->batchInsert( - Products1cNomenclatureActuality::tableName(), - ['guid','date_from','date_to','active','created_at','created_by'], - $toInsert - ) - ->execute(); - } - - $transaction->commit(); + $this->processBatchActuality($rows); - $message = 'Таблица актуальности обновлена. '; - $message .= 'Добавлено: ' . count($toInsert) . '; '; - $message .= 'Деактивировано: ' . count($toDeactivate); - - Yii::$app->session->setFlash('success', $message); + Yii::$app->session->setFlash( + 'success', + "Обновлено актуальностей для " . count($rows) . " товаров." + ); - } catch (\Exception $e) { - $transaction->rollBack(); - Yii::$app->session->setFlash('error', 'Ошибка: ' . $e->getMessage()); - } return $this->render('add-activity', [ - 'historyDays' => $historyDays, + 'historyDays' => $historyDays, 'intervalMonths' => $intervalMonths, 'startFrom' => $startFrom, ]); } - /** * Обработка массового сохранения диапазонов актуальности. * Если из/до нет или невалидны — пропускаем. @@ -350,7 +311,7 @@ class Products1cNomenclatureActualityController extends Controller protected function processBatchActuality(array $post) { $userId = Yii::$app->user->id; - $now = date('Y-m-d H:i:s'); + $now = date('Y-m-d H:i:s'); foreach ($post as $row) { if (empty($row['from']) || empty($row['to'])) { @@ -358,55 +319,65 @@ class Products1cNomenclatureActualityController extends Controller } $fromDt = \DateTime::createFromFormat('Y-m', $row['from']); - if (!$fromDt) { - continue; - } - $newFrom = $fromDt->format('Y-m-01 00:00:00'); - $toDt = \DateTime::createFromFormat('Y-m', $row['to']); - if (!$toDt) { + if (!$fromDt || !$toDt) { continue; } - $toDt->modify('last day of this month')->setTime(23, 59, 59); - $newTo = $toDt->format('Y-m-d H:i:s'); - + $fromDt->setDate((int)$fromDt->format('Y'), (int)$fromDt->format('m'), 1) + ->setTime(0, 0, 0); + $toDt->modify('last day of this month') + ->setTime(23, 59, 59); - $warehouseNN = !empty($row['warehouse_nn']); - $warehouseMS = !empty($row['warehouse_msk']); - $supplier = $row['supplier'] ?? null; - $plantation = $row['plantation'] ?? null; + $from = $fromDt->format('Y-m-d H:i:s'); + $to = $toDt->format('Y-m-d H:i:s'); + if ($from > $to) { + Yii::warning("GUID {$row['guid']}: пропускаем — from > to"); + continue; + } - $old = Products1cNomenclatureActuality::find() - ->andWhere(['guid' => $row['guid'], 'active' => 1]) - ->one(); - - if ($old) { - if ($old->date_from === $newFrom && $old->date_to === $newTo) { - continue; + $guid = $row['guid']; + + /** @var Products1cNomenclatureActuality[] $hits */ + $hits = Products1cNomenclatureActuality::find() + ->where(['guid' => $guid]) + ->andWhere('date_to >= :from', [':from' => $from]) + ->andWhere('date_from <= :to', [':to' => $to]) + ->orderBy(['date_from' => SORT_ASC]) + ->all(); + + if (empty($hits)) { + $new = new Products1cNomenclatureActuality([ + 'guid' => $guid, + 'date_from' => $from, + 'date_to' => $to, + 'created_at' => $now, + 'created_by' => $userId, + ]); + if (!$new->save()) { + Yii::error("Ошибка создания GUID={$guid}: " . json_encode($new->getErrors(), JSON_UNESCAPED_UNICODE)); } + continue; + } - $old->active = 0; - $old->updated_by = $userId; - $old->updated_at = $now; + $allFrom = array_map(fn($r) => $r->date_from, $hits); + $allTo = array_map(fn($r) => $r->date_to, $hits); + $minFrom = min($from, min($allFrom)); + $maxTo = max($to, max($allTo)); - if (!$old->save()) { - Yii::error('Ошибка сохранения' . json_encode( - $old->getErrors(), JSON_UNESCAPED_UNICODE - )); - } - } + $master = array_shift($hits); + $master->date_from = $minFrom; + $master->date_to = $maxTo; + $master->updated_at = $now; + $master->updated_by = $userId; + if (!$master->save()) { + Yii::error("Ошибка обновления GUID={$guid}: " . json_encode($master->getErrors(), JSON_UNESCAPED_UNICODE)); + } - $new = new Products1cNomenclatureActuality([ - 'guid' => $row['guid'], - 'date_from' => $newFrom, - 'date_to' => $newTo, - 'active' => 1, - 'created_at' => $now, - 'created_by' => $userId, - ]); - $new->save(false); + foreach ($hits as $dup) { + $dup->delete(); + } } } diff --git a/erp24/records/Products1cNomenclature.php b/erp24/records/Products1cNomenclature.php index f48b0741..36c39858 100644 --- a/erp24/records/Products1cNomenclature.php +++ b/erp24/records/Products1cNomenclature.php @@ -23,6 +23,8 @@ use yii\db\ActiveQuery; */ class Products1cNomenclature extends \yii\db\ActiveRecord { + public $date_from; + public $date_to; /** * {@inheritdoc} */ @@ -31,6 +33,13 @@ class Products1cNomenclature extends \yii\db\ActiveRecord return 'products_1c_nomenclature'; } + public function attributes(): array + { + return array_merge(parent::attributes(), [ + 'date_from', + 'date_to', + ]); + } /** * {@inheritdoc} */ @@ -43,6 +52,7 @@ class Products1cNomenclature extends \yii\db\ActiveRecord [['id', 'location', 'name', 'type_num', 'category', 'subcategory', 'species', 'sort', 'measure', 'color', 'type'], 'string', 'max' => 255], [['id'], 'unique'], + [['date_from','date_to'], 'safe'], ]; } diff --git a/erp24/records/Products1cNomenclatureActuality.php b/erp24/records/Products1cNomenclatureActuality.php index 34b6318f..ba043e96 100644 --- a/erp24/records/Products1cNomenclatureActuality.php +++ b/erp24/records/Products1cNomenclatureActuality.php @@ -60,4 +60,15 @@ class Products1cNomenclatureActuality extends \yii\db\ActiveRecord ]; } + /** + * @return \yii\db\ActiveQuery + */ + public function getProduct(): \yii\db\ActiveQuery + { + return $this->hasOne( + Products1cNomenclature::class, + ['id' => 'guid'] + ); + } + } diff --git a/erp24/views/products1c-nomenclature-actuality/index.php b/erp24/views/products1c-nomenclature-actuality/index.php index 130760a1..b3ed7faa 100644 --- a/erp24/views/products1c-nomenclature-actuality/index.php +++ b/erp24/views/products1c-nomenclature-actuality/index.php @@ -36,6 +36,10 @@ function monthList() } $months = monthList(); +$monthOptions = ''; +foreach ($months as $k => $v) { + $monthOptions .= ""; +} ?>
@@ -244,45 +248,54 @@ $months = monthList(); 'floatHeader' => false, 'tableOptions' => ['class' => 'table table-bordered'], 'containerOptions' => ['style' => 'overflow:auto; max-height:500px;'], - 'rowOptions' => function($model) use ($filter) { - if ($model->hasActuality()) { - return ['class' => 'table-success']; - } - return []; + 'rowOptions' => function($row) { + return $row['actuality'] ? ['class'=>'table-success'] : []; }, 'columns' => [ [ - 'attribute' => 'name', 'label' => 'Наименование', 'format' => 'raw', - 'contentOptions' => ['style'=>'min-width:200px;'], - 'value' => function ($m) { - return Html::encode($m->name . ' (' . $m->id . ')'); + 'contentOptions' => ['style'=>'min-width:150px;'], + 'value' => function ($row, $key, $index) { + $product = $row['product']; + $name = Html::encode($product->name . ' (' . $product->id . ')'); + $btn = Html::button('+ Добавить интервал', [ + 'class' => 'btn btn-xs btn-outline-primary ms-2 add-actuality-row', + 'type' => 'button', + 'title' => 'Добавить интервал', + 'data-guid' => $product->id, + 'data-name' => $product->name, + ]); + return '
' . $name . $btn . '
'; } ], [ 'label' => 'Актуальность ассортимента', 'format' => 'raw', - 'contentOptions' => ['style'=>'white-space:nowrap; min-width:200px;'], - 'value' => function ($m, $k, $i) use ($months, $filter) { - $actuality = $m->getActualities() - ->one(); - $from = $actuality ? (new \DateTime($actuality->date_from))->format('Y-m') : null; - $to = $actuality ? (new \DateTime($actuality->date_to))->format('Y-m') : null; - return Html::hiddenInput("actuality[$i][guid]", $m->id) - . Html::tag('div', - Html::dropDownList("actuality[$i][from]", $from, $months, [ - 'class'=>'form-select from-month form-select-sm me-1', - 'prompt'=>'от', - - ]) - . Html::dropDownList("actuality[$i][to]", $to, $months, [ - 'class'=>'form-select to-month form-select-sm', - 'prompt'=>'до', - - ]), - ['class'=>'d-flex align-items-center'] - ); + 'contentOptions' => ['style'=>'white-space:nowrap; min-width:100px;'], + 'value' => function ($row, $k, $i) use ($months) { + $product = $row['product']; + $actuality = $row['actuality']; + $from = $actuality ? substr($actuality->date_from, 0, 7) : null; + $to = $actuality ? substr($actuality->date_to, 0, 7) : null; + $inputs = Html::hiddenInput("actuality[$i][guid]", $product->id); + if ($actuality) { + $inputs .= Html::hiddenInput("actuality[$i][id]", $actuality->id); + } + $inputs .= Html::tag('div', + Html::dropDownList("actuality[$i][from]", $from, $months, [ + 'class'=>'form-select from-month form-select-sm me-1', + 'prompt'=>'от', + 'style' => 'width:auto;display:inline-block' + ]) . + Html::dropDownList("actuality[$i][to]", $to, $months, [ + 'class'=>'form-select to-month form-select-sm', + 'prompt'=>'до', + 'style' => 'width:auto;display:inline-block' + ]), + ['class'=>'d-flex align-items-center'] + ); + return $inputs; } ], [ @@ -319,6 +332,11 @@ $months = monthList(); +
diff --git a/erp24/web/js/products1cNomenclatureActuality/index.js b/erp24/web/js/products1cNomenclatureActuality/index.js index 1e4a0436..88b227d5 100644 --- a/erp24/web/js/products1cNomenclatureActuality/index.js +++ b/erp24/web/js/products1cNomenclatureActuality/index.js @@ -1,34 +1,87 @@ document.addEventListener("DOMContentLoaded", () => { -$('.from-month').on('change', function(){ - var from = $(this).val(), - to = $(this).closest('td').find('.to-month'); - to.find('option').each(function(){ - $(this).toggle($(this).val() >= from); - }); - if (to.val() < from) { - to.val(from); - } -}); -$('#filter-date-from').on('change', function(){ - var from = $(this).val(); - var to = $('#filter-date-to'); - to.find('option').each(function(){ - var val = $(this).val(); - if (val === '' || val >= from) { - $(this).show(); + const monthOptions = Object.entries(window.productActualityConfig.months || {}).map( + ([k, v]) => `` + ).join(''); + + let actualIdx = $('#actuality-form table tbody tr').length || 0; + + $(document).on('click', '.add-actuality-row', function(){ + const btn = $(this); + const guid = btn.data('guid'); + const name = btn.data('name'); + const table = $('#actuality-form table'); + // Все строки для этого товара + const $rows = table.find('tbody tr').filter(function(){ + return $(this).find('input[type=hidden][name*="[guid]"]').val() == guid; + }); + const $lastRow = $rows.last(); + actualIdx++; + + const newRow = ` + + + ${name} (${guid}) + + + +
+ + +
+ + + + + + + + – + + `; + + if ($lastRow.length) { + $lastRow.after(newRow); } else { - $(this).hide(); + table.find('tbody').append(newRow); } }); - if (to.val() && to.val() < from) { - to.val(from); - } -}); -$('.clear-btn').on('click', function(){ - var target = $(this).data('target'); - $('#' + target).val(null).trigger('change'); -}); + + $(document).on('change', '.from-month', function(){ + var from = $(this).val(), + to = $(this).closest('td').find('.to-month'); + to.find('option').each(function(){ + $(this).toggle($(this).val() >= from || $(this).val() === ""); + }); + if (to.val() < from) { + to.val(from); + } + }); + + $('#filter-date-from').on('change', function(){ + var from = $(this).val(); + var to = $('#filter-date-to'); + to.find('option').each(function(){ + var val = $(this).val(); + if (val === '' || val >= from) { + $(this).show(); + } else { + $(this).hide(); + } + }); + if (to.val() && to.val() < from) { + to.val(from); + } + }); + + $('.clear-btn').on('click', function(){ + var target = $(this).data('target'); + $('#' + target).val(null).trigger('change'); + }); var $onlyActiveCheckbox = $('#onlyActiveCheckbox'); var $onlyInactiveCheckbox = $('#onlyInactiveCheckbox'); @@ -51,11 +104,53 @@ $('.clear-btn').on('click', function(){ } }); - if ($onlyActiveCheckbox.is(':checked')) { $onlyInactiveCheckbox.prop('disabled', true); } else if ($onlyInactiveCheckbox.is(':checked')) { $onlyActiveCheckbox.prop('disabled', true); } -}); \ No newline at end of file + function checkIntervalsForGuid(guid) { + // Собираем все интервалы для товара (всех строк) + let intervals = []; + $('#actuality-form table tbody tr').each(function(){ + let $row = $(this); + let rowGuid = $row.find('input[type=hidden][name*="[guid]"]').val(); + if (rowGuid == guid) { + let from = $row.find('select.from-month').val(); + let to = $row.find('select.to-month').val(); + if (from && to) intervals.push({from, to, $row}); + } + }); + intervals.sort((a,b) => a.from.localeCompare(b.from)); + + let hasOverlap = false; + for(let i=0; i= intervals[j].from) { + // Пересечение! + intervals[i].$row.addClass('table-danger'); + intervals[j].$row.addClass('table-danger'); + hasOverlap = true; + } + } + } + if (hasOverlap) { + if (!$('.interval-overlap-alert').length) { + $('
Пересекающиеся диапазоны по одному товару!
') + .insertBefore('#actuality-form'); + } + } else { + $('.interval-overlap-alert').remove(); + $('#actuality-form table tbody tr').removeClass('table-danger'); + } + return hasOverlap; + } + + $(document).on('change', '.from-month, .to-month', function(){ + let $row = $(this).closest('tr'); + let guid = $row.find('input[type=hidden][name*="[guid]"]').val(); + checkIntervalsForGuid(guid); + }); + +});