WIP: Place holder while I switch devices

This commit is contained in:
Matthew Kilgore
2025-05-31 18:35:22 -04:00
parent b61edf1c99
commit b989cf0f0a
5 changed files with 566 additions and 189 deletions

View File

@@ -0,0 +1,202 @@
package postgres
import (
"context"
"database/sql"
"fmt"
"github.com/google/uuid"
"github.com/pressly/goose/v3"
"time"
)
//nolint:gochecknoinits
func init() {
goose.AddMigrationContext(Up20250531120000, Down20250531120000)
}
func Up20250531120000(ctx context.Context, tx *sql.Tx) error {
// Create entity_types table
_, err := tx.ExecContext(ctx, `
CREATE TABLE IF NOT EXISTS "entity_types" (
"id" uuid NOT NULL,
"created_at" timestamptz NOT NULL,
"updated_at" timestamptz NOT NULL,
"name" character varying NOT NULL,
"description" character varying NULL,
"icon" character varying NULL,
"color" character varying NULL,
"is_location" boolean NOT NULL DEFAULT false,
"group_entity_types" uuid NOT NULL,
PRIMARY KEY ("id"),
CONSTRAINT "entity_types_groups_entity_types" FOREIGN KEY ("group_entity_types") REFERENCES "groups" ("id") ON UPDATE NO ACTION ON DELETE CASCADE
);
`)
if err != nil {
return fmt.Errorf("failed to create entity_types table: %w", err)
}
// Create entities table
_, err = tx.ExecContext(ctx, `
CREATE TABLE IF NOT EXISTS "entities" (
"id" uuid NOT NULL,
"created_at" timestamptz NOT NULL,
"updated_at" timestamptz NOT NULL,
"name" character varying NOT NULL,
"description" character varying NULL,
"import_ref" character varying NULL,
"notes" character varying NULL,
"quantity" bigint NOT NULL DEFAULT 1,
"insured" boolean NOT NULL DEFAULT false,
"archived" boolean NOT NULL DEFAULT false,
"asset_id" bigint NOT NULL DEFAULT 0,
"serial_number" character varying NULL,
"model_number" character varying NULL,
"manufacturer" character varying NULL,
"lifetime_warranty" boolean NOT NULL DEFAULT false,
"warranty_expires" timestamptz NULL,
"warranty_details" character varying NULL,
"purchase_time" timestamptz NULL,
"purchase_from" character varying NULL,
"purchase_price" double precision NOT NULL DEFAULT 0,
"sold_time" timestamptz NULL,
"sold_to" character varying NULL,
"sold_price" double precision NOT NULL DEFAULT 0,
"sold_notes" character varying NULL,
"group_entities" uuid NOT NULL,
"entity_children" uuid NULL,
"entity_parent" uuid NULL,
"entity_type" uuid NOT NULL,
PRIMARY KEY ("id"),
CONSTRAINT "entities_groups_entities" FOREIGN KEY ("group_entities") REFERENCES "groups" ("id") ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT "entities_entities_children" FOREIGN KEY ("entity_children") REFERENCES "entities" ("id") ON UPDATE NO ACTION ON DELETE SET NULL,
CONSTRAINT "entities_entities_parent" FOREIGN KEY ("entity_parent") REFERENCES "entities" ("id") ON UPDATE NO ACTION ON DELETE SET NULL,
CONSTRAINT "entities_entity_types" FOREIGN KEY ("entity_type") REFERENCES "entity_types" ("id") ON UPDATE NO ACTION ON DELETE CASCADE
);
`)
if err != nil {
return fmt.Errorf("failed to create entities table: %w", err)
}
// Create entity_fields table
_, err = tx.ExecContext(ctx, `
CREATE TABLE IF NOT EXISTS "entity_fields" (
"id" uuid NOT NULL,
"created_at" timestamptz NOT NULL,
"updated_at" timestamptz NOT NULL,
"name" character varying NOT NULL,
"description" character varying NULL,
"type" character varying NOT NULL,
"text_value" character varying NULL,
"number_value" bigint NULL,
"boolean_value" boolean NOT NULL DEFAULT false,
"time_value" timestamptz NULL,
"entity_fields" uuid NULL,
PRIMARY KEY ("id"),
CONSTRAINT "entity_fields_entities_fields" FOREIGN KEY ("entity_fields") REFERENCES "entities" ("id") ON UPDATE NO ACTION ON DELETE CASCADE
);
`)
if err != nil {
return fmt.Errorf("failed to create entity_fields table: %w", err)
}
// Fetch all groups to create default entity types for each group
groups, err := tx.QueryContext(ctx, `SELECT id FROM "groups"`)
if err != nil {
return fmt.Errorf("failed to query groups: %w", err)
}
defer func(rows *sql.Rows) {
err := rows.Close()
if err != nil {
fmt.Printf("failed to close rows: %v\n", err)
}
}(groups)
// Process each group and create default entity types
for groups.Next() {
var groupID uuid.UUID
if err := groups.Scan(&groupID); err != nil {
return fmt.Errorf("failed to scan group ID: %w", err)
}
// Create default 'Item' entity type for this group
itemTypeID := uuid.New()
now := time.Now().UTC()
_, err = tx.ExecContext(ctx, `
INSERT INTO "entity_types" ("id", "created_at", "updated_at", "name", "description", "is_location", "group_entity_types")
VALUES ($1, $2, $3, $4, $5, $6, $7)
`, itemTypeID, now, now, "Item", "Default item type", false, groupID)
if err != nil {
return fmt.Errorf("failed to create Item entity type for group %s: %w", groupID, err)
}
// Create default 'Location' entity type for this group
locTypeID := uuid.New()
_, err = tx.ExecContext(ctx, `
INSERT INTO "entity_types" ("id", "created_at", "updated_at", "name", "description", "is_location", "group_entity_types")
VALUES ($1, $2, $3, $4, $5, $6, $7)
`, locTypeID, now, now, "Location", "Default location type", true, groupID)
if err != nil {
return fmt.Errorf("failed to create Location entity type for group %s: %w", groupID, err)
}
// Migrate existing locations to entities
_, err = tx.ExecContext(ctx, `
INSERT INTO "entities" (
"id", "created_at", "updated_at", "name", "description",
"group_entities", "entity_children", "entity_type"
)
SELECT
l."id", l."created_at", l."updated_at", l."name", l."description",
l."group_locations", l."location_children", $1
FROM "locations" l
WHERE l."group_locations" = $2
`, locTypeID, groupID)
if err != nil {
return fmt.Errorf("failed to migrate locations to entities for group %s: %w", groupID, err)
}
// Migrate existing items to entities
_, err = tx.ExecContext(ctx, `
INSERT INTO "entities" (
"id", "created_at", "updated_at", "name", "description",
"import_ref", "notes", "quantity", "insured", "archived",
"asset_id", "serial_number", "model_number", "manufacturer",
"lifetime_warranty", "warranty_expires", "warranty_details", "purchase_time",
"purchase_from", "purchase_price", "sold_time", "sold_to",
"sold_price", "sold_notes", "group_entities", "entity_children",
"entity_parent", "entity_type")
SELECT
i."id", i."created_at", i."updated_at", i."name", i."description",
i."import_ref", i."notes", i."quantity", i."insured", i."archived",
i."asset_id", i."serial_number", i."model_number", i."manufacturer",
i."lifetime_warranty", i."warranty_expires", i."warranty_details", i."purchase_time",
i."purchase_from", i."purchase_price", i."sold_time", i."sold_to",
i."sold_price", i."sold_notes", i."group_items", i."item_children",
i."item_parent", $1
FROM "items" i WHERE i."group_items" = $2
`, itemTypeID, groupID)
if err != nil {
return fmt.Errorf("failed to migrate items to entities for group %s: %w", groupID, err)
}
}
_, err = tx.ExecContext(ctx, `
INSERT INTO "entity_fields" (
"id", "created_at", "updated_at", "name", "description",
"type", "text_value", "number_value", "boolean_value", "time_value", "entity_fields"
)
SELECT
"id", "created_at", "updated_at", "name", "description",
"type", "text_value", "number_value", "boolean_value", "time_value", "item_fields"
FROM "item_fields";
`)
if err != nil {
return fmt.Errorf("failed to migrate item_fields to entity_fields: %w", err)
}
return nil
}
func Down20250531120000(ctx context.Context, tx *sql.Tx) error {
return nil
}

View File

@@ -0,0 +1,188 @@
-- Create entity_types table
CREATE TABLE IF NOT EXISTS "entity_types" (
"id" uuid NOT NULL,
"created_at" timestamptz NOT NULL,
"updated_at" timestamptz NOT NULL,
"name" character varying NOT NULL,
"description" character varying NULL,
"icon" character varying NULL,
"color" character varying NULL,
"is_location" boolean NOT NULL DEFAULT false,
"group_entity_types" uuid NOT NULL,
PRIMARY KEY ("id"),
CONSTRAINT "entity_types_groups_entity_types" FOREIGN KEY ("group_entity_types") REFERENCES "groups" ("id") ON UPDATE NO ACTION ON DELETE CASCADE
);
-- Create entities table
CREATE TABLE IF NOT EXISTS "entities" (
"id" uuid NOT NULL,
"created_at" timestamptz NOT NULL,
"updated_at" timestamptz NOT NULL,
"name" character varying NOT NULL,
"description" character varying NULL,
"import_ref" character varying NULL,
"notes" character varying NULL,
"quantity" bigint NOT NULL DEFAULT 1,
"insured" boolean NOT NULL DEFAULT false,
"archived" boolean NOT NULL DEFAULT false,
"asset_id" bigint NOT NULL DEFAULT 0,
"serial_number" character varying NULL,
"model_number" character varying NULL,
"manufacturer" character varying NULL,
"lifetime_warranty" boolean NOT NULL DEFAULT false,
"warranty_expires" timestamptz NULL,
"warranty_details" character varying NULL,
"purchase_time" timestamptz NULL,
"purchase_from" character varying NULL,
"purchase_price" double precision NOT NULL DEFAULT 0,
"sold_time" timestamptz NULL,
"sold_to" character varying NULL,
"sold_price" double precision NOT NULL DEFAULT 0,
"sold_notes" character varying NULL,
"group_entities" uuid NOT NULL,
"entity_children" uuid NULL,
"entity_parent" uuid NULL,
"entity_type" uuid NOT NULL,
PRIMARY KEY ("id"),
CONSTRAINT "entities_groups_entities" FOREIGN KEY ("group_entities") REFERENCES "groups" ("id") ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT "entities_entities_children" FOREIGN KEY ("entity_children") REFERENCES "entities" ("id") ON UPDATE NO ACTION ON DELETE SET NULL,
CONSTRAINT "entities_entities_parent" FOREIGN KEY ("entity_parent") REFERENCES "entities" ("id") ON UPDATE NO ACTION ON DELETE SET NULL,
CONSTRAINT "entities_entity_types" FOREIGN KEY ("entity_type") REFERENCES "entity_types" ("id") ON UPDATE NO ACTION ON DELETE CASCADE
);
-- Create entity_fields table
CREATE TABLE IF NOT EXISTS "entity_fields" (
"id" uuid NOT NULL,
"created_at" timestamptz NOT NULL,
"updated_at" timestamptz NOT NULL,
"name" character varying NOT NULL,
"description" character varying NULL,
"type" character varying NOT NULL,
"text_value" character varying NULL,
"number_value" bigint NULL,
"boolean_value" boolean NOT NULL DEFAULT false,
"time_value" timestamptz NULL,
"entity_fields" uuid NULL,
PRIMARY KEY ("id"),
CONSTRAINT "entity_fields_entities_fields" FOREIGN KEY ("entity_fields") REFERENCES "entities" ("id") ON UPDATE NO ACTION ON DELETE CASCADE
);
-- Create default entity types
INSERT INTO "entity_types" ("id", "created_at", "updated_at", "name", "description", "is_location", "group_entity_types")
SELECT
gen_random_uuid(),
NOW(),
NOW(),
'Item',
'Default item type',
false,
id
FROM "groups";
INSERT INTO "entity_types" ("id", "created_at", "updated_at", "name", "description", "is_location", "group_entity_types")
SELECT
gen_random_uuid(),
NOW(),
NOW(),
'Location',
'Default location type',
true,
id
FROM "groups";
-- Migrate locations to entities
INSERT INTO "entities" (
"id", "created_at", "updated_at", "name", "description",
"group_entities", "entity_children", "entity_type"
)
SELECT
l."id", l."created_at", l."updated_at", l."name", l."description",
l."group_locations", l."location_children",
(SELECT et."id" FROM "entity_types" et WHERE et."name" = 'Location' AND et."group_entity_types" = l."group_locations" LIMIT 1)
FROM "locations" l;
-- Migrate items to entities
INSERT INTO "entities" (
"id", "created_at", "updated_at", "name", "description",
"import_ref", "notes", "quantity", "insured", "archived",
"asset_id", "serial_number", "model_number", "manufacturer",
"lifetime_warranty", "warranty_expires", "warranty_details",
"purchase_time", "purchase_from", "purchase_price",
"sold_time", "sold_to", "sold_price", "sold_notes",
"group_entities", "entity_children", "entity_parent", "entity_type"
)
SELECT
i."id", i."created_at", i."updated_at", i."name", i."description",
i."import_ref", i."notes", i."quantity", i."insured", i."archived",
i."asset_id", i."serial_number", i."model_number", i."manufacturer",
i."lifetime_warranty", i."warranty_expires", i."warranty_details",
i."purchase_time", i."purchase_from", i."purchase_price",
i."sold_time", i."sold_to", i."sold_price", i."sold_notes",
i."group_items", i."item_children",
i."location_items",
(SELECT et."id" FROM "entity_types" et WHERE et."name" = 'Item' AND et."group_entity_types" = i."group_items" LIMIT 1)
FROM "items" i;
-- Migrate item_fields to entity_fields
INSERT INTO "entity_fields" (
"id", "created_at", "updated_at", "name", "description",
"type", "text_value", "number_value", "boolean_value", "time_value", "entity_fields"
)
SELECT
"id", "created_at", "updated_at", "name", "description",
"type", "text_value", "number_value", "boolean_value", "time_value", "item_fields"
FROM "item_fields";
-- Update maintenance_entries to reference entities instead of items
ALTER TABLE "maintenance_entries"
ADD COLUMN "entity_id" uuid NULL;
UPDATE "maintenance_entries"
SET "entity_id" = "item_id";
ALTER TABLE "maintenance_entries"
DROP CONSTRAINT "maintenance_entries_items_maintenance_entries";
ALTER TABLE "maintenance_entries"
ADD CONSTRAINT "maintenance_entries_entities_maintenance_entries"
FOREIGN KEY ("entity_id") REFERENCES "entities" ("id")
ON UPDATE NO ACTION ON DELETE CASCADE;
ALTER TABLE "maintenance_entries"
DROP COLUMN "item_id";
-- Update attachments to reference entities instead of items
ALTER TABLE "attachments"
ADD COLUMN "entity_attachments" uuid NULL;
UPDATE "attachments"
SET "entity_attachments" = "item_attachments";
ALTER TABLE "attachments"
DROP CONSTRAINT "attachments_items_attachments";
ALTER TABLE "attachments"
ADD CONSTRAINT "attachments_entities_attachments"
FOREIGN KEY ("entity_attachments") REFERENCES "entities" ("id")
ON UPDATE NO ACTION ON DELETE CASCADE;
ALTER TABLE "attachments"
DROP COLUMN "item_attachments";
-- Update labels to reference entities
CREATE TABLE IF NOT EXISTS "label_entities" (
"label_id" uuid NOT NULL,
"entity_id" uuid NOT NULL,
PRIMARY KEY ("label_id", "entity_id"),
CONSTRAINT "label_entities_entity_id" FOREIGN KEY ("entity_id") REFERENCES "entities" ("id") ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT "label_entities_label_id" FOREIGN KEY ("label_id") REFERENCES "labels" ("id") ON UPDATE NO ACTION ON DELETE CASCADE
);
INSERT INTO "label_entities" ("label_id", "entity_id")
SELECT "label_id", "item_id" FROM "label_items";
-- Drop old tables (do this last)
DROP TABLE IF EXISTS "label_items";
DROP TABLE IF EXISTS "item_fields";
DROP TABLE IF EXISTS "items";
DROP TABLE IF EXISTS "locations";

View File

@@ -1,189 +0,0 @@
-- +goose Up
-- +goose no transaction
create table entities
(
id uuid not null
primary key,
type text not null,
created_at datetime not null,
updated_at datetime not null,
name text not null,
description text,
import_ref text,
notes text,
quantity integer default 1 not null,
insured bool default false not null,
archived bool default false not null,
asset_id integer default 0 not null,
serial_number text,
model_number text,
manufacturer text,
lifetime_warranty bool default false not null,
warranty_expires datetime,
warranty_details text,
purchase_time datetime,
purchase_from text,
purchase_price real default 0 not null,
sold_time datetime,
sold_to text,
sold_price real default 0 not null,
sold_notes text,
group_entities uuid not null
constraint entities_groups_entities
references groups
on delete cascade,
entity_children uuid
constraint entities_entities_children
references entities
on delete set null,
location_entities uuid
constraint entities_locations_entities
references entities
on delete cascade,
sync_child_entities_locations BOOLEAN default FALSE not null
);
create index entity_archived
on entities (archived);
create index entity_asset_id
on entities (asset_id);
create index entity_manufacturer
on entities (manufacturer);
create index entity_model_number
on entities (model_number);
create index entity_name
on entities (name);
create index entity_serial_number
on entities (serial_number);
PRAGMA FOREIGN_KEYS = OFF;
-- Migrate the item_fields table to the new entity_fields table
create table entity_fields
(
id uuid not null
primary key,
created_at datetime not null,
updated_at datetime not null,
name text not null,
description text,
type text not null,
text_value text,
number_value integer,
boolean_value bool default false not null,
time_value datetime not null,
entity_fields uuid
constraint entity_fields_entities_fields
references entities
on delete cascade
);
insert into entity_fields(id, created_at, updated_at, name, description, type, text_value, number_value,
boolean_value, time_value, entity_fields)
select id,
created_at,
updated_at,
name,
description,
type,
text_value,
number_value,
boolean_value,
time_value,
item_fields
from item_fields;
drop table item_fields;
-- Update maintenance_entries to use the new entities table
create table maintenance_entries_dg_tmp
(
id uuid not null
primary key,
created_at datetime not null,
updated_at datetime not null,
date datetime,
scheduled_date datetime,
name text not null,
description text,
cost real default 0 not null,
entity_id uuid not null
constraint maintenance_entries_entities_maintenance_entries
references entities
on delete cascade
);
insert into maintenance_entries_dg_tmp(id, created_at, updated_at, date, scheduled_date, name, description, cost,
entity_id)
select id,
created_at,
updated_at,
date,
scheduled_date,
name,
description,
cost,
item_id
from maintenance_entries;
drop table maintenance_entries;
alter table maintenance_entries_dg_tmp
rename to maintenance_entries;
-- Migrate the locations first
INSERT INTO entities (id, type, created_at, updated_at, name, description, group_entities, entity_children)
SELECT id,
'location',
created_at,
updated_at,
name,
description,
group_locations,
location_children
FROM locations;
-- Then migrate the items
INSERT INTO entities (id, type, created_at, updated_at, name, description, import_ref, notes, quantity, insured,
archived, asset_id, serial_number, model_number, manufacturer, lifetime_warranty,
warranty_expires, warranty_details, purchase_time, purchase_from, purchase_price, sold_time,
sold_to, sold_price, sold_notes, group_entities, entity_children, location_entities)
SELECT id,
'item',
created_at,
updated_at,
name,
description,
import_ref,
notes,
quantity,
insured,
archived,
asset_id,
serial_number,
model_number,
manufacturer,
lifetime_warranty,
warranty_expires,
warranty_details,
purchase_time,
purchase_from,
purchase_price,
sold_time,
sold_to,
sold_price,
sold_notes,
group_items,
item_children,
location_items
FROM items;
PRAGMA FOREIGN_KEYS = ON;
DROP TABLE locations;
DROP TABLE items;

View File

@@ -0,0 +1,175 @@
package sqlite3
import (
"context"
"database/sql"
"fmt"
"github.com/google/uuid"
"github.com/pressly/goose/v3"
"time"
)
//nolint:gochecknoinits
func init() {
goose.AddMigrationContext(Up20250531120000, Down20250531120000)
}
func Up20250531120000(ctx context.Context, tx *sql.Tx) error {
// Create entity_types table
_, err := tx.ExecContext(ctx, `
CREATE TABLE IF NOT EXISTS "entity_types" (
"id" text NOT NULL,
"created_at" datetime NOT NULL,
"updated_at" datetime NOT NULL,
"name" text NOT NULL,
"description" text NULL,
"icon" text NULL,
"color" text NULL,
"is_location" integer NOT NULL DEFAULT 0,
"group_entity_types" text NOT NULL,
PRIMARY KEY ("id"),
FOREIGN KEY ("group_entity_types") REFERENCES "groups" ("id") ON DELETE CASCADE
);
`)
if err != nil {
return fmt.Errorf("failed to create entity_types table: %w", err)
}
// Create entities table
_, err = tx.ExecContext(ctx, `
CREATE TABLE IF NOT EXISTS "entities" (
"id" text NOT NULL,
"created_at" datetime NOT NULL,
"updated_at" datetime NOT NULL,
"name" text NOT NULL,
"description" text NULL,
"import_ref" text NULL,
"notes" text NULL,
"quantity" integer NOT NULL DEFAULT 1,
"insured" integer NOT NULL DEFAULT 0,
"archived" integer NOT NULL DEFAULT 0,
"asset_id" integer NOT NULL DEFAULT 0,
"serial_number" text NULL,
"model_number" text NULL,
"manufacturer" text NULL,
"lifetime_warranty" integer NOT NULL DEFAULT 0,
"warranty_expires" datetime NULL,
"warranty_details" text NULL,
"purchase_time" datetime NULL,
"purchase_from" text NULL,
"purchase_price" real NOT NULL DEFAULT 0,
"sold_time" datetime NULL,
"sold_to" text NULL,
"sold_price" real NOT NULL DEFAULT 0,
"sold_notes" text NULL,
"group_entities" text NOT NULL,
"entity_children" text NULL,
"entity_parent" text NULL,
"entity_type" text NOT NULL,
PRIMARY KEY ("id"),
FOREIGN KEY ("group_entities") REFERENCES "groups" ("id") ON DELETE CASCADE,
FOREIGN KEY ("entity_children") REFERENCES "entities" ("id") ON DELETE SET NULL,
FOREIGN KEY ("entity_parent") REFERENCES "entities" ("id") ON DELETE SET NULL,
FOREIGN KEY ("entity_type") REFERENCES "entity_types" ("id") ON DELETE CASCADE
);
`)
if err != nil {
return fmt.Errorf("failed to create entities table: %w", err)
}
// Create entity_fields table
_, err = tx.ExecContext(ctx, `
CREATE TABLE IF NOT EXISTS "entity_fields" (
"id" text NOT NULL,
"created_at" datetime NOT NULL,
"updated_at" datetime NOT NULL,
"name" text NOT NULL,
"description" text NULL,
"type" text NOT NULL,
"text_value" text NULL,
"number_value" integer NULL,
"boolean_value" integer NOT NULL DEFAULT 0,
"time_value" datetime NULL,
"entity_fields" text NULL,
PRIMARY KEY ("id"),
FOREIGN KEY ("entity_fields") REFERENCES "entities" ("id") ON DELETE CASCADE
);
`)
if err != nil {
return fmt.Errorf("failed to create entity_fields table: %w", err)
}
// Fetch all groups to create default entity types for each group
rows, err := tx.QueryContext(ctx, `SELECT id FROM "groups"`)
if err != nil {
return fmt.Errorf("failed to query groups: %w", err)
}
defer rows.Close()
// Process each group and create default entity types
for rows.Next() {
var groupID string
if err := rows.Scan(&groupID); err != nil {
return fmt.Errorf("failed to scan group ID: %w", err)
}
// Create default 'Item' entity type for this group
itemTypeID := uuid.New().String()
now := time.Now().UTC()
_, err = tx.ExecContext(ctx, `
INSERT INTO "entity_types" ("id", "created_at", "updated_at", "name", "description", "is_location", "group_entity_types")
VALUES (?, ?, ?, ?, ?, ?, ?)
`, itemTypeID, now, now, "Item", "Default item type", 0, groupID)
if err != nil {
return fmt.Errorf("failed to create Item entity type for group %s: %w", groupID, err)
}
// Create default 'Location' entity type for this group
locTypeID := uuid.New().String()
_, err = tx.ExecContext(ctx, `
INSERT INTO "entity_types" ("id", "created_at", "updated_at", "name", "description", "is_location", "group_entity_types")
VALUES (?, ?, ?, ?, ?, ?, ?)
`, locTypeID, now, now, "Location", "Default location type", 1, groupID)
if err != nil {
return fmt.Errorf("failed to create Location entity type for group %s: %w", groupID, err)
}
// Migrate existing locations to entities
_, err = tx.ExecContext(ctx, `
INSERT INTO "entities" (
"id", "created_at", "updated_at", "name", "description",
"group_entities", "entity_children", "entity_type"
)
SELECT
l."id", l."created_at", l."updated_at", l."name", l."description",
l."group_locations", l."location_children", ?
FROM "locations" l
WHERE l."group_locations" = ?
`, locTypeID, groupID)
if err != nil {
return fmt.Errorf("failed to migrate locations to entities for group %s: %w", groupID, err)
}
}
return nil
}
func Down20250531120000(ctx context.Context, tx *sql.Tx) error {
// Drop tables in reverse order to avoid foreign key constraints
_, err := tx.ExecContext(ctx, `DROP TABLE IF EXISTS "entity_fields";`)
if err != nil {
return fmt.Errorf("failed to drop entity_fields table: %w", err)
}
_, err = tx.ExecContext(ctx, `DROP TABLE IF EXISTS "entities";`)
if err != nil {
return fmt.Errorf("failed to drop entities table: %w", err)
}
_, err = tx.ExecContext(ctx, `DROP TABLE IF EXISTS "entity_types";`)
if err != nil {
return fmt.Errorf("failed to drop entity_types table: %w", err)
}
return nil
}