]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Каталог поставщика
authorVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 14 Apr 2026 07:32:43 +0000 (10:32 +0300)
committerVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 14 Apr 2026 07:32:43 +0000 (10:32 +0300)
erp24/records/Marking.php [new file with mode: 0644]

diff --git a/erp24/records/Marking.php b/erp24/records/Marking.php
new file mode 100644 (file)
index 0000000..7b24d02
--- /dev/null
@@ -0,0 +1,195 @@
+<?php
+
+declare(strict_types=1);
+
+namespace yii_app\records;
+
+use Yii;
+use yii\behaviors\BlameableBehavior;
+use yii\behaviors\TimestampBehavior;
+use yii\db\ActiveQuery;
+use yii\db\ActiveRecord;
+use yii\db\Expression;
+
+/**
+ * Справочник маркировок.
+ * Код уникальный (3-12 символов, A-Z0-9-).
+ * UNIQUE (producer_id, plantation_id, product_name).
+ *
+ * @property int $id
+ * @property string $code             Код маркировки (SCH-RP-RN50)
+ * @property int $producer_id
+ * @property int $plantation_id
+ * @property string $product_name
+ * @property int $supplier_id
+ * @property bool $is_active
+ * @property int $created_by
+ * @property int|null $updated_by
+ * @property string $created_at
+ * @property string|null $updated_at
+ *
+ * @property-read Producer $producer
+ * @property-read Plantation $plantation
+ * @property-read Supplier $supplier
+ *
+ * @see https://itriteil.atlassian.net/browse/ERP-320
+ */
+class Marking extends ActiveRecord
+{
+    public const CODE_REGEX = '/^[A-Z0-9\-]{3,12}$/D';
+
+    public static function tableName(): string
+    {
+        return '{{%erp24.markings}}';
+    }
+
+    public function behaviors(): array
+    {
+        return [
+            [
+                'class' => TimestampBehavior::class,
+                'createdAtAttribute' => 'created_at',
+                'updatedAtAttribute' => 'updated_at',
+                'value' => new Expression('NOW()'),
+            ],
+            [
+                'class' => BlameableBehavior::class,
+                'createdByAttribute' => 'created_by',
+                'updatedByAttribute' => 'updated_by',
+                'defaultValue' => null,
+            ],
+        ];
+    }
+
+    public function rules(): array
+    {
+        return [
+            [['code', 'producer_id', 'plantation_id', 'product_name', 'supplier_id'], 'required'],
+            ['code', 'string', 'max' => 50],
+            [
+                'code',
+                'match',
+                'pattern' => self::CODE_REGEX,
+                'message' => 'Код: 3-12 символов, только A-Z, 0-9 и дефис',
+            ],
+            ['code', 'filter', 'filter' => 'strtoupper'],
+            ['code', 'unique', 'message' => 'Маркировка с таким кодом уже существует'],
+            ['product_name', 'string', 'max' => 200],
+            [['producer_id', 'plantation_id', 'supplier_id'], 'integer'],
+            [
+                'producer_id',
+                'exist',
+                'targetClass' => Producer::class,
+                'targetAttribute' => 'id',
+                'message' => 'Производитель не найден',
+            ],
+            [
+                'plantation_id',
+                'exist',
+                'targetClass' => Plantation::class,
+                'targetAttribute' => 'id',
+                'message' => 'Плантация не найдена',
+            ],
+            [
+                'supplier_id',
+                'exist',
+                'targetClass' => Supplier::class,
+                'targetAttribute' => 'id',
+                'message' => 'Поставщик не найден',
+            ],
+            [
+                ['product_name'],
+                'unique',
+                'targetAttribute' => ['producer_id', 'plantation_id', 'product_name'],
+                'message' => 'Маркировка с такой комбинацией производителя, плантации и названия уже существует',
+            ],
+            ['is_active', 'boolean'],
+            ['is_active', 'default', 'value' => true],
+        ];
+    }
+
+    public function attributeLabels(): array
+    {
+        return [
+            'id' => 'ID',
+            'code' => 'Код',
+            'producer_id' => 'Производитель',
+            'plantation_id' => 'Плантация',
+            'product_name' => 'Название',
+            'supplier_id' => 'Поставщик',
+            'is_active' => 'Статус',
+            'created_by' => 'Создал',
+            'updated_by' => 'Обновил',
+            'created_at' => 'Создано',
+            'updated_at' => 'Обновлено',
+        ];
+    }
+
+    /* --- Scopes --- */
+
+    public static function findActive(): ActiveQuery
+    {
+        return static::find()->where(['is_active' => true]);
+    }
+
+    /* --- Relations --- */
+
+    public function getProducer(): ActiveQuery
+    {
+        return $this->hasOne(Producer::class, ['id' => 'producer_id']);
+    }
+
+    public function getPlantation(): ActiveQuery
+    {
+        return $this->hasOne(Plantation::class, ['id' => 'plantation_id']);
+    }
+
+    public function getSupplier(): ActiveQuery
+    {
+        return $this->hasOne(Supplier::class, ['id' => 'supplier_id']);
+    }
+
+    /* --- Бейджи --- */
+
+    public function getStatusBadge(): string
+    {
+        if ($this->is_active) {
+            return '<span class="badge-status-active">Активна</span>';
+        }
+        return '<span class="badge-status-inactive">Неактивна</span>';
+    }
+
+    /* --- Подсчёт маппингов --- */
+
+    /**
+     * Количество привязанных маппингов (через junction mapping_markings).
+     */
+    public function getMappingsCount(): int
+    {
+        return (int)Yii::$app->db->createCommand(
+            'SELECT COUNT(*) FROM {{%erp24.mapping_markings}} WHERE marking_id = :mid',
+            [':mid' => $this->id]
+        )->queryScalar();
+    }
+
+    /* --- Деактивация --- */
+
+    /**
+     * Деактивация маркировки. Блокируется при наличии привязанных маппингов.
+     *
+     * @throws \RuntimeException если есть привязанные маппинги
+     */
+    public function deactivate(): void
+    {
+        $count = $this->getMappingsCount();
+        if ($count > 0) {
+            throw new \RuntimeException(sprintf(
+                'Нельзя деактивировать маркировку: есть %d привязанных маппингов. Сначала отвяжите их.',
+                $count
+            ));
+        }
+
+        $this->is_active = false;
+        $this->save(false);
+    }
+}