$guid = $row['guid'];
$bouquetId = $row['bouquet_id'];
+ $id = $row['id'] ?? null;
$fromAdj = (clone $fromDate)->modify('-1 second')->format('Y-m-d H:i:s');
$toAdj = (clone $toDate)->modify('+1 second')->format('Y-m-d H:i:s');
+ if ($id) {
+ /** @var MatrixBouquetActuality|null $master */
+ $master = MatrixBouquetActuality::find()
+ ->where(['id' => $id, 'bouquet_id' => $bouquetId])
+ ->one();
+
+ if (!$master) {
+ Yii::warning("Букет {$bouquetId}: запись id={$id} не найдена, пропуск");
+ continue;
+ }
+
+ $master->date_from = $from;
+ $master->date_to = $to;
+ $master->updated_at = $now;
+ $master->updated_by = $userId;
+
+ if (!$master->save()) {
+ Yii::error("Ошибка обновления bouquet_id={$bouquetId}, id={$id}: " . json_encode($master->getErrors(), JSON_UNESCAPED_UNICODE));
+ continue;
+ }
+
+ /** @var MatrixBouquetActuality[] $neighbors */
+ $neighbors = MatrixBouquetActuality::find()
+ ->where(['bouquet_id' => $bouquetId])
+ ->andWhere(['<>', 'id', $master->id])
+ ->andWhere('date_to >= :fromAdj', [':fromAdj' => $fromAdj])
+ ->andWhere('date_from <= :toAdj', [':toAdj' => $toAdj])
+ ->orderBy(['date_from' => SORT_ASC])
+ ->all();
+
+ if (empty($neighbors)) {
+ continue;
+ }
+
+ $minFrom = $master->date_from;
+ $maxTo = $master->date_to;
+
+ foreach ($neighbors as $nei) {
+ if ($nei->date_from < $minFrom) $minFrom = $nei->date_from;
+ if ($nei->date_to > $maxTo) $maxTo = $nei->date_to;
+ }
+
+ $master->date_from = $minFrom;
+ $master->date_to = $maxTo;
+ $master->updated_at = $now;
+ $master->updated_by = $userId;
+
+ if (!$master->save()) {
+ Yii::error("Ошибка объединения bouquet_id={$bouquetId}, id={$id}: " . json_encode($master->getErrors(), JSON_UNESCAPED_UNICODE));
+ continue;
+ }
+
+ foreach ($neighbors as $nei) { $nei->delete(); }
+
+ while (true) {
+ $leftBound = (new \DateTime($master->date_from))->modify('-1 second')->format('Y-m-d H:i:s');
+ $rightBound = (new \DateTime($master->date_to))->modify('+1 second')->format('Y-m-d H:i:s');
+
+ $more = MatrixBouquetActuality::find()
+ ->where(['bouquet_id' => $bouquetId])
+ ->andWhere(['<>', 'id', $master->id])
+ ->andWhere('date_to >= :leftBound', [':leftBound' => $leftBound])
+ ->andWhere('date_from <= :rightBound', [':rightBound' => $rightBound])
+ ->orderBy(['date_from' => SORT_ASC])
+ ->all();
+
+ if (empty($more)) break;
+
+ foreach ($more as $nei) {
+ if ($nei->date_from < $master->date_from) $master->date_from = $nei->date_from;
+ if ($nei->date_to > $master->date_to) $master->date_to = $nei->date_to;
+ }
+ $master->updated_at = $now;
+ $master->updated_by = $userId;
+ if (!$master->save()) {
+ Yii::error("Ошибка повторного объединения bouquet_id={$bouquetId}, id={$id}: " . json_encode($master->getErrors(), JSON_UNESCAPED_UNICODE));
+ break;
+ }
+ foreach ($more as $nei) { $nei->delete(); }
+ }
+
+ continue;
+ }
+
/** @var MatrixBouquetActuality[] $actualities */
$actualities = MatrixBouquetActuality::find()
->where(['bouquet_id' => $bouquetId])
/** @var MatrixBouquetActuality $actuality */
$actuality->delete();
}
+
+ while (true) {
+ $leftBound = (new \DateTime($master->date_from))->modify('-1 second')->format('Y-m-d H:i:s');
+ $rightBound = (new \DateTime($master->date_to))->modify('+1 second')->format('Y-m-d H:i:s');
+
+ /** @var MatrixBouquetActuality[] $neighbors */
+ $neighbors = MatrixBouquetActuality::find()
+ ->where(['bouquet_id' => $bouquetId])
+ ->andWhere(['<>', 'id', $master->id])
+ ->andWhere('date_to >= :leftBound', [':leftBound' => $leftBound])
+ ->andWhere('date_from <= :rightBound', [':rightBound' => $rightBound])
+ ->orderBy(['date_from' => SORT_ASC])
+ ->all();
+
+ if (empty($neighbors)) {
+ break;
+ }
+
+ foreach ($neighbors as $nei) {
+ if ($nei->date_from < $master->date_from)
+ {
+ $master->date_from = $nei->date_from;
+ }
+ if ($nei->date_to > $master->date_to)
+ {
+ $master->date_to = $nei->date_to;
+ }
+ }
+ $master->updated_at = $now;
+ $master->updated_by = $userId;
+
+ if (!$master->save()) {
+ Yii::error("Ошибка повторного обновления bouquet_id={$bouquetId}: " . json_encode($master->getErrors(), JSON_UNESCAPED_UNICODE));
+ break;
+ }
+
+ foreach ($neighbors as $nei) {
+ $nei->delete();
+ }
+ }
}
}
+
+
/**
* Displays a single MatrixBouquetActuality model.
* @param int $id ID