class m260417_000001_create_products_1c_automark_predictions extends Migration
{
+ public const TABLE_NAME = 'erp24.products_1c_automark_predictions';
+ public const PRODUCTS_1C_TABLE = 'erp24.products_1c';
+ public const INDEX_PRODUCT_ID = 'idx_automark_product_id';
+ public const INDEX_STATUS = 'idx_automark_status';
+ public const FK_PRODUCT = 'fk_automark_product';
+
public function safeUp(): void
{
- $this->createTable('products_1c_automark_predictions', [
- 'id' => $this->primaryKey(),
- 'product_id' => $this->string(36)->notNull(),
- 'category' => $this->string(255)->null(),
- 'subcategory' => $this->string(255)->null(),
- 'species' => $this->string(255)->null(),
- 'sort' => $this->string(255)->null(),
- 'type' => $this->string(255)->null(),
- 'size' => $this->integer()->null(),
- 'color' => $this->string(255)->null(),
- 'confidence' => $this->float()->notNull(),
- 'method' => $this->string(50)->notNull(),
- 'status' => $this->smallInteger()->notNull()->defaultValue(0),
- 'approved_by' => $this->integer()->null(),
- 'created_at' => $this->timestamp()->notNull()->defaultExpression('CURRENT_TIMESTAMP'),
- 'updated_at' => $this->timestamp()->null(),
- ]);
-
- $this->createIndex('idx_automark_product_id', 'products_1c_automark_predictions', 'product_id');
- $this->createIndex('idx_automark_status', 'products_1c_automark_predictions', 'status');
- $this->addForeignKey(
- 'fk_automark_product',
- 'products_1c_automark_predictions', 'product_id',
- 'products_1c', 'id',
- 'CASCADE', 'CASCADE'
- );
+ $tableSchema = $this->db->getTableSchema(self::TABLE_NAME);
+ if (!isset($tableSchema)) {
+ $this->createTable(self::TABLE_NAME, [
+ 'id' => $this->primaryKey(),
+ 'product_id' => $this->string(36)->notNull(),
+ 'category' => $this->string(255)->null(),
+ 'subcategory' => $this->string(255)->null(),
+ 'species' => $this->string(255)->null(),
+ 'sort' => $this->string(255)->null(),
+ 'type' => $this->string(255)->null(),
+ 'size' => $this->integer()->null(),
+ 'color' => $this->string(255)->null(),
+ 'confidence' => $this->float()->notNull(),
+ 'method' => $this->string(50)->notNull(),
+ 'status' => $this->smallInteger()->notNull()->defaultValue(0),
+ 'approved_by' => $this->integer()->null(),
+ 'created_at' => $this->timestamp()->notNull()->defaultExpression('CURRENT_TIMESTAMP'),
+ 'updated_at' => $this->timestamp()->null(),
+ ]);
+ }
+
+ $tableSchema = $this->db->getTableSchema(self::TABLE_NAME);
+ $productsSchema = $this->db->getTableSchema(self::PRODUCTS_1C_TABLE);
+ if (!isset($tableSchema) || !isset($productsSchema)) {
+ return;
+ }
+
+ if (!$this->hasIndex(self::INDEX_PRODUCT_ID)) {
+ $this->createIndex(self::INDEX_PRODUCT_ID, self::TABLE_NAME, 'product_id');
+ }
+
+ if (!$this->hasIndex(self::INDEX_STATUS)) {
+ $this->createIndex(self::INDEX_STATUS, self::TABLE_NAME, 'status');
+ }
+
+ if (!$this->hasForeignKey(self::FK_PRODUCT)) {
+ $this->addForeignKey(
+ self::FK_PRODUCT,
+ self::TABLE_NAME,
+ 'product_id',
+ self::PRODUCTS_1C_TABLE,
+ 'id',
+ 'CASCADE',
+ 'CASCADE'
+ );
+ }
}
public function safeDown(): void
{
- $this->dropForeignKey('fk_automark_product', 'products_1c_automark_predictions');
- $this->dropTable('products_1c_automark_predictions');
+ $tableSchema = $this->db->getTableSchema(self::TABLE_NAME);
+ if (!isset($tableSchema)) {
+ return;
+ }
+
+ if ($this->hasForeignKey(self::FK_PRODUCT)) {
+ $this->dropForeignKey(self::FK_PRODUCT, self::TABLE_NAME);
+ }
+
+ if ($this->hasIndex(self::INDEX_PRODUCT_ID)) {
+ $this->dropIndex(self::INDEX_PRODUCT_ID, self::TABLE_NAME);
+ }
+
+ if ($this->hasIndex(self::INDEX_STATUS)) {
+ $this->dropIndex(self::INDEX_STATUS, self::TABLE_NAME);
+ }
+
+ $this->dropTable(self::TABLE_NAME);
+ }
+
+ private function hasIndex(string $indexName): bool
+ {
+ return (new \yii\db\Query())
+ ->from('pg_indexes')
+ ->where([
+ 'schemaname' => $this->getSchemaName(self::TABLE_NAME),
+ 'indexname' => $indexName,
+ ])
+ ->exists($this->db);
+ }
+
+ private function hasForeignKey(string $constraintName): bool
+ {
+ return (new \yii\db\Query())
+ ->from('information_schema.table_constraints')
+ ->where([
+ 'table_schema' => $this->getSchemaName(self::TABLE_NAME),
+ 'table_name' => $this->getPureTableName(self::TABLE_NAME),
+ 'constraint_name' => $constraintName,
+ 'constraint_type' => 'FOREIGN KEY',
+ ])
+ ->exists($this->db);
+ }
+
+ private function getSchemaName(string $tableName): string
+ {
+ return explode('.', $tableName, 2)[0];
+ }
+
+ private function getPureTableName(string $tableName): string
+ {
+ return explode('.', $tableName, 2)[1] ?? $tableName;
}
}
class m260430_000001_add_llm_fields_to_automark_predictions extends Migration
{
+ public const TABLE_NAME = 'erp24.products_1c_automark_predictions';
+ public const INDEX_LLM_VERDICT = 'idx_automark_llm_verdict';
+
public function safeUp(): void
{
- $this->addColumn(
- 'products_1c_automark_predictions',
- 'llm_verdict',
- $this->string(20)->null()->defaultValue(null)->after('method')
- );
- $this->addColumn(
- 'products_1c_automark_predictions',
- 'llm_verified_at',
- $this->timestamp()->null()->defaultValue(null)->after('llm_verdict')
- );
- $this->addColumn(
- 'products_1c_automark_predictions',
- 'llm_comment',
- $this->string(500)->null()->defaultValue(null)->after('llm_verified_at')
- );
- $this->createIndex(
- 'idx_automark_llm_verdict',
- 'products_1c_automark_predictions',
- 'llm_verdict'
- );
+ $tableSchema = $this->db->getTableSchema(self::TABLE_NAME);
+ if (!isset($tableSchema)) {
+ return;
+ }
+
+ if (!$this->hasColumn('llm_verdict')) {
+ $this->addColumn(
+ self::TABLE_NAME,
+ 'llm_verdict',
+ $this->string(20)->null()->defaultValue(null)->after('method')
+ );
+ }
+
+ if (!$this->hasColumn('llm_verified_at')) {
+ $this->addColumn(
+ self::TABLE_NAME,
+ 'llm_verified_at',
+ $this->timestamp()->null()->defaultValue(null)->after('llm_verdict')
+ );
+ }
+
+ if (!$this->hasColumn('llm_comment')) {
+ $this->addColumn(
+ self::TABLE_NAME,
+ 'llm_comment',
+ $this->string(500)->null()->defaultValue(null)->after('llm_verified_at')
+ );
+ }
+
+ if (!$this->hasIndex(self::INDEX_LLM_VERDICT)) {
+ $this->createIndex(
+ self::INDEX_LLM_VERDICT,
+ self::TABLE_NAME,
+ 'llm_verdict'
+ );
+ }
}
public function safeDown(): void
{
- $this->dropIndex('idx_automark_llm_verdict', 'products_1c_automark_predictions');
- $this->dropColumn('products_1c_automark_predictions', 'llm_comment');
- $this->dropColumn('products_1c_automark_predictions', 'llm_verified_at');
- $this->dropColumn('products_1c_automark_predictions', 'llm_verdict');
+ $tableSchema = $this->db->getTableSchema(self::TABLE_NAME);
+ if (!isset($tableSchema)) {
+ return;
+ }
+
+ if ($this->hasIndex(self::INDEX_LLM_VERDICT)) {
+ $this->dropIndex(self::INDEX_LLM_VERDICT, self::TABLE_NAME);
+ }
+
+ if ($this->hasColumn('llm_comment')) {
+ $this->dropColumn(self::TABLE_NAME, 'llm_comment');
+ }
+
+ if ($this->hasColumn('llm_verified_at')) {
+ $this->dropColumn(self::TABLE_NAME, 'llm_verified_at');
+ }
+
+ if ($this->hasColumn('llm_verdict')) {
+ $this->dropColumn(self::TABLE_NAME, 'llm_verdict');
+ }
+ }
+
+ private function hasColumn(string $columnName): bool
+ {
+ $tableSchema = $this->db->getTableSchema(self::TABLE_NAME);
+ return isset($tableSchema?->columns[$columnName]);
+ }
+
+ private function hasIndex(string $indexName): bool
+ {
+ return (new \yii\db\Query())
+ ->from('pg_indexes')
+ ->where([
+ 'schemaname' => $this->getSchemaName(self::TABLE_NAME),
+ 'indexname' => $indexName,
+ ])
+ ->exists($this->db);
+ }
+
+ private function getSchemaName(string $tableName): string
+ {
+ return explode('.', $tableName, 2)[0];
}
}