almost ready

This commit is contained in:
bob
2026-06-01 10:52:06 -05:00
parent 8b0eb0db78
commit 763305ca89
94 changed files with 8766 additions and 2674 deletions

View File

@@ -0,0 +1,146 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace BlueLaminate.EFCore.Migrations
{
/// <inheritdoc />
public partial class AddPerSiteSweepCheckpoints : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "ix_skins_listings_swept_at",
schema: "skintracker",
table: "skins");
migrationBuilder.DropIndex(
name: "ix_skin_conditions_listings_swept_at",
schema: "skintracker",
table: "skin_conditions");
migrationBuilder.DropColumn(
name: "listings_swept_at",
schema: "skintracker",
table: "skins");
migrationBuilder.DropColumn(
name: "listings_swept_at",
schema: "skintracker",
table: "skin_conditions");
migrationBuilder.CreateTable(
name: "skin_condition_sweeps",
schema: "skintracker",
columns: table => new
{
id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
skin_condition_id = table.Column<int>(type: "integer", nullable: false),
source = table.Column<string>(type: "text", nullable: false),
swept_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_skin_condition_sweeps", x => x.id);
table.ForeignKey(
name: "fk_skin_condition_sweeps_skin_conditions_skin_condition_id",
column: x => x.skin_condition_id,
principalSchema: "skintracker",
principalTable: "skin_conditions",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "skin_sweeps",
schema: "skintracker",
columns: table => new
{
id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
skin_id = table.Column<int>(type: "integer", nullable: false),
source = table.Column<string>(type: "text", nullable: false),
swept_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_skin_sweeps", x => x.id);
table.ForeignKey(
name: "fk_skin_sweeps_skins_skin_id",
column: x => x.skin_id,
principalSchema: "skintracker",
principalTable: "skins",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "ix_skin_condition_sweeps_skin_condition_id_source",
schema: "skintracker",
table: "skin_condition_sweeps",
columns: new[] { "skin_condition_id", "source" },
unique: true);
migrationBuilder.CreateIndex(
name: "ix_skin_condition_sweeps_source_swept_at",
schema: "skintracker",
table: "skin_condition_sweeps",
columns: new[] { "source", "swept_at" });
migrationBuilder.CreateIndex(
name: "ix_skin_sweeps_skin_id_source",
schema: "skintracker",
table: "skin_sweeps",
columns: new[] { "skin_id", "source" },
unique: true);
migrationBuilder.CreateIndex(
name: "ix_skin_sweeps_source_swept_at",
schema: "skintracker",
table: "skin_sweeps",
columns: new[] { "source", "swept_at" });
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "skin_condition_sweeps",
schema: "skintracker");
migrationBuilder.DropTable(
name: "skin_sweeps",
schema: "skintracker");
migrationBuilder.AddColumn<DateTimeOffset>(
name: "listings_swept_at",
schema: "skintracker",
table: "skins",
type: "timestamp with time zone",
nullable: true);
migrationBuilder.AddColumn<DateTimeOffset>(
name: "listings_swept_at",
schema: "skintracker",
table: "skin_conditions",
type: "timestamp with time zone",
nullable: true);
migrationBuilder.CreateIndex(
name: "ix_skins_listings_swept_at",
schema: "skintracker",
table: "skins",
column: "listings_swept_at");
migrationBuilder.CreateIndex(
name: "ix_skin_conditions_listings_swept_at",
schema: "skintracker",
table: "skin_conditions",
column: "listings_swept_at");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,239 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace BlueLaminate.EFCore.Migrations
{
/// <inheritdoc />
public partial class AddSkinLandListings : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "skin_land_listings",
schema: "skintracker",
columns: table => new
{
id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
listing_id = table.Column<long>(type: "bigint", nullable: false),
skin_id = table.Column<int>(type: "integer", nullable: false),
condition_id = table.Column<int>(type: "integer", nullable: true),
market_hash_name = table.Column<string>(type: "text", nullable: false),
float_value = table.Column<decimal>(type: "numeric(20,18)", nullable: true),
is_stat_trak = table.Column<bool>(type: "boolean", nullable: false),
is_souvenir = table.Column<bool>(type: "boolean", nullable: false),
name_tag = table.Column<string>(type: "text", nullable: true),
sticker_count = table.Column<int>(type: "integer", nullable: false),
price = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
currency = table.Column<string>(type: "text", nullable: false),
inspect_link = table.Column<string>(type: "text", nullable: true),
first_seen_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
last_seen_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
status = table.Column<string>(type: "text", nullable: false),
removed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("pk_skin_land_listings", x => x.id);
table.ForeignKey(
name: "fk_skin_land_listings_skin_conditions_condition_id",
column: x => x.condition_id,
principalSchema: "skintracker",
principalTable: "skin_conditions",
principalColumn: "id",
onDelete: ReferentialAction.SetNull);
table.ForeignKey(
name: "fk_skin_land_listings_skins_skin_id",
column: x => x.skin_id,
principalSchema: "skintracker",
principalTable: "skins",
principalColumn: "id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "ix_skin_land_listings_condition_id",
schema: "skintracker",
table: "skin_land_listings",
column: "condition_id");
migrationBuilder.CreateIndex(
name: "ix_skin_land_listings_listing_id",
schema: "skintracker",
table: "skin_land_listings",
column: "listing_id",
unique: true);
migrationBuilder.CreateIndex(
name: "ix_skin_land_listings_skin_id_condition_id",
schema: "skintracker",
table: "skin_land_listings",
columns: new[] { "skin_id", "condition_id" });
migrationBuilder.CreateIndex(
name: "ix_skin_land_listings_status",
schema: "skintracker",
table: "skin_land_listings",
column: "status");
// Extend the cross-market read view with a skin.land arm. skin.land exposes no
// paint seed / asset id / instance fingerprint, so those columns are NULL; the
// wear comes from the joined condition row (the offer table doesn't store it).
migrationBuilder.Sql("""
CREATE OR REPLACE VIEW skintracker.market_listings AS
SELECT
'csfloat'::text AS marketplace,
l.cs_float_listing_id AS external_id,
l.skin_id AS skin_id,
NULL::integer AS condition_id,
l.skin_instance_id AS skin_instance_id,
l.market_hash_name AS market_hash_name,
l.wear_name AS wear,
l.float_value AS float_value,
l.paint_seed AS paint_seed,
l.is_stat_trak AS is_stat_trak,
l.is_souvenir AS is_souvenir,
l.sticker_count AS sticker_count,
l.price AS price,
'USD'::text AS currency,
l.inspect_link AS inspect_link,
l.asset_id AS asset_id,
l.status AS status,
l.first_seen_at AS first_seen_at,
l.last_seen_at AS last_seen_at,
l.removed_at AS removed_at
FROM skintracker.listings l
UNION ALL
SELECT
'csmoney'::text,
c.sell_order_id::text,
c.skin_id,
c.condition_id,
c.skin_instance_id,
c.market_hash_name,
-- Normalise cs.money's wear short code to the full wear name the
-- other arms emit (csfloat wear_name / skinland condition), so the
-- view's `wear` column is consistent across marketplaces.
CASE lower(c.quality)
WHEN 'fn' THEN 'Factory New'
WHEN 'mw' THEN 'Minimal Wear'
WHEN 'ft' THEN 'Field-Tested'
WHEN 'ww' THEN 'Well-Worn'
WHEN 'bs' THEN 'Battle-Scarred'
ELSE c.quality
END,
c.float_value,
c.paint_seed,
c.is_stat_trak,
c.is_souvenir,
c.sticker_count,
c.price,
c.currency,
c.inspect_link,
c.asset_id,
c.status,
c.first_seen_at,
c.last_seen_at,
c.removed_at
FROM skintracker.cs_money_listings c
UNION ALL
SELECT
'skinland'::text,
s.listing_id::text,
s.skin_id,
s.condition_id,
NULL::integer,
s.market_hash_name,
sc.condition,
s.float_value,
NULL::integer,
s.is_stat_trak,
s.is_souvenir,
s.sticker_count,
s.price,
s.currency,
s.inspect_link,
NULL::text,
s.status,
s.first_seen_at,
s.last_seen_at,
s.removed_at
FROM skintracker.skin_land_listings s
LEFT JOIN skintracker.skin_conditions sc ON sc.id = s.condition_id;
""");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
// Restore the pre-skin.land view (csfloat + csmoney) before dropping the table
// it references, so the view never points at a missing relation.
migrationBuilder.Sql("""
CREATE OR REPLACE VIEW skintracker.market_listings AS
SELECT
'csfloat'::text AS marketplace,
l.cs_float_listing_id AS external_id,
l.skin_id AS skin_id,
NULL::integer AS condition_id,
l.skin_instance_id AS skin_instance_id,
l.market_hash_name AS market_hash_name,
l.wear_name AS wear,
l.float_value AS float_value,
l.paint_seed AS paint_seed,
l.is_stat_trak AS is_stat_trak,
l.is_souvenir AS is_souvenir,
l.sticker_count AS sticker_count,
l.price AS price,
'USD'::text AS currency,
l.inspect_link AS inspect_link,
l.asset_id AS asset_id,
l.status AS status,
l.first_seen_at AS first_seen_at,
l.last_seen_at AS last_seen_at,
l.removed_at AS removed_at
FROM skintracker.listings l
UNION ALL
SELECT
'csmoney'::text,
c.sell_order_id::text,
c.skin_id,
c.condition_id,
c.skin_instance_id,
c.market_hash_name,
-- Normalise cs.money's wear short code to the full wear name the
-- other arms emit (csfloat wear_name / skinland condition), so the
-- view's `wear` column is consistent across marketplaces.
CASE lower(c.quality)
WHEN 'fn' THEN 'Factory New'
WHEN 'mw' THEN 'Minimal Wear'
WHEN 'ft' THEN 'Field-Tested'
WHEN 'ww' THEN 'Well-Worn'
WHEN 'bs' THEN 'Battle-Scarred'
ELSE c.quality
END,
c.float_value,
c.paint_seed,
c.is_stat_trak,
c.is_souvenir,
c.sticker_count,
c.price,
c.currency,
c.inspect_link,
c.asset_id,
c.status,
c.first_seen_at,
c.last_seen_at,
c.removed_at
FROM skintracker.cs_money_listings c;
""");
migrationBuilder.DropTable(
name: "skin_land_listings",
schema: "skintracker");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace BlueLaminate.EFCore.Migrations
{
/// <inheritdoc />
public partial class MakeListingFloatNullable : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<decimal>(
name: "float_value",
schema: "skintracker",
table: "listings",
type: "numeric(20,18)",
nullable: true,
oldClrType: typeof(decimal),
oldType: "numeric(20,18)");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<decimal>(
name: "float_value",
schema: "skintracker",
table: "listings",
type: "numeric(20,18)",
nullable: false,
defaultValue: 0m,
oldClrType: typeof(decimal),
oldType: "numeric(20,18)",
oldNullable: true);
}
}
}

View File

@@ -0,0 +1,308 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace BlueLaminate.EFCore.Migrations
{
/// <inheritdoc />
public partial class ConsistencyPass_FloatBoundsCurrencyConditionPaintSeed : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "ix_inventory_items_asset_id",
schema: "skintracker",
table: "inventory_items");
migrationBuilder.RenameColumn(
name: "min_float",
schema: "skintracker",
table: "skin_conditions",
newName: "float_min");
migrationBuilder.RenameColumn(
name: "max_float",
schema: "skintracker",
table: "skin_conditions",
newName: "float_max");
// text -> integer needs an explicit USING cast; EF's AlterColumn omits it and
// Postgres won't cast automatically. Every stored seed is a stringified
// integer, so the cast is total.
migrationBuilder.Sql(
"ALTER TABLE skintracker.skin_instances " +
"ALTER COLUMN paint_seed TYPE integer USING paint_seed::integer;");
migrationBuilder.AddColumn<int>(
name: "condition_id",
schema: "skintracker",
table: "listings",
type: "integer",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "currency",
schema: "skintracker",
table: "listings",
type: "text",
nullable: false,
defaultValue: "USD");
migrationBuilder.CreateIndex(
name: "ix_trades_steam_trade_id",
schema: "skintracker",
table: "trades",
column: "steam_trade_id",
unique: true);
migrationBuilder.CreateIndex(
name: "ix_listings_condition_id",
schema: "skintracker",
table: "listings",
column: "condition_id");
migrationBuilder.CreateIndex(
name: "ix_inventory_items_asset_id",
schema: "skintracker",
table: "inventory_items",
column: "asset_id",
unique: true);
migrationBuilder.AddForeignKey(
name: "fk_listings_skin_conditions_condition_id",
schema: "skintracker",
table: "listings",
column: "condition_id",
principalSchema: "skintracker",
principalTable: "skin_conditions",
principalColumn: "id",
onDelete: ReferentialAction.SetNull);
// Now that listings carries its own condition_id and currency, the csfloat
// arm of the cross-market view uses them instead of NULL / a hardcoded 'USD'.
migrationBuilder.Sql("""
CREATE OR REPLACE VIEW skintracker.market_listings AS
SELECT
'csfloat'::text AS marketplace,
l.cs_float_listing_id AS external_id,
l.skin_id AS skin_id,
l.condition_id AS condition_id,
l.skin_instance_id AS skin_instance_id,
l.market_hash_name AS market_hash_name,
l.wear_name AS wear,
l.float_value AS float_value,
l.paint_seed AS paint_seed,
l.is_stat_trak AS is_stat_trak,
l.is_souvenir AS is_souvenir,
l.sticker_count AS sticker_count,
l.price AS price,
l.currency AS currency,
l.inspect_link AS inspect_link,
l.asset_id AS asset_id,
l.status AS status,
l.first_seen_at AS first_seen_at,
l.last_seen_at AS last_seen_at,
l.removed_at AS removed_at
FROM skintracker.listings l
UNION ALL
SELECT
'csmoney'::text,
c.sell_order_id::text,
c.skin_id,
c.condition_id,
c.skin_instance_id,
c.market_hash_name,
CASE lower(c.quality)
WHEN 'fn' THEN 'Factory New'
WHEN 'mw' THEN 'Minimal Wear'
WHEN 'ft' THEN 'Field-Tested'
WHEN 'ww' THEN 'Well-Worn'
WHEN 'bs' THEN 'Battle-Scarred'
ELSE c.quality
END,
c.float_value,
c.paint_seed,
c.is_stat_trak,
c.is_souvenir,
c.sticker_count,
c.price,
c.currency,
c.inspect_link,
c.asset_id,
c.status,
c.first_seen_at,
c.last_seen_at,
c.removed_at
FROM skintracker.cs_money_listings c
UNION ALL
SELECT
'skinland'::text,
s.listing_id::text,
s.skin_id,
s.condition_id,
NULL::integer,
s.market_hash_name,
sc.condition,
s.float_value,
NULL::integer,
s.is_stat_trak,
s.is_souvenir,
s.sticker_count,
s.price,
s.currency,
s.inspect_link,
NULL::text,
s.status,
s.first_seen_at,
s.last_seen_at,
s.removed_at
FROM skintracker.skin_land_listings s
LEFT JOIN skintracker.skin_conditions sc ON sc.id = s.condition_id;
""");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
// Restore the view to its pre-migration form (csfloat condition_id/currency
// hardcoded) FIRST, so the listings columns it now references can be dropped.
migrationBuilder.Sql("""
CREATE OR REPLACE VIEW skintracker.market_listings AS
SELECT
'csfloat'::text AS marketplace,
l.cs_float_listing_id AS external_id,
l.skin_id AS skin_id,
NULL::integer AS condition_id,
l.skin_instance_id AS skin_instance_id,
l.market_hash_name AS market_hash_name,
l.wear_name AS wear,
l.float_value AS float_value,
l.paint_seed AS paint_seed,
l.is_stat_trak AS is_stat_trak,
l.is_souvenir AS is_souvenir,
l.sticker_count AS sticker_count,
l.price AS price,
'USD'::text AS currency,
l.inspect_link AS inspect_link,
l.asset_id AS asset_id,
l.status AS status,
l.first_seen_at AS first_seen_at,
l.last_seen_at AS last_seen_at,
l.removed_at AS removed_at
FROM skintracker.listings l
UNION ALL
SELECT
'csmoney'::text,
c.sell_order_id::text,
c.skin_id,
c.condition_id,
c.skin_instance_id,
c.market_hash_name,
CASE lower(c.quality)
WHEN 'fn' THEN 'Factory New'
WHEN 'mw' THEN 'Minimal Wear'
WHEN 'ft' THEN 'Field-Tested'
WHEN 'ww' THEN 'Well-Worn'
WHEN 'bs' THEN 'Battle-Scarred'
ELSE c.quality
END,
c.float_value,
c.paint_seed,
c.is_stat_trak,
c.is_souvenir,
c.sticker_count,
c.price,
c.currency,
c.inspect_link,
c.asset_id,
c.status,
c.first_seen_at,
c.last_seen_at,
c.removed_at
FROM skintracker.cs_money_listings c
UNION ALL
SELECT
'skinland'::text,
s.listing_id::text,
s.skin_id,
s.condition_id,
NULL::integer,
s.market_hash_name,
sc.condition,
s.float_value,
NULL::integer,
s.is_stat_trak,
s.is_souvenir,
s.sticker_count,
s.price,
s.currency,
s.inspect_link,
NULL::text,
s.status,
s.first_seen_at,
s.last_seen_at,
s.removed_at
FROM skintracker.skin_land_listings s
LEFT JOIN skintracker.skin_conditions sc ON sc.id = s.condition_id;
""");
migrationBuilder.DropForeignKey(
name: "fk_listings_skin_conditions_condition_id",
schema: "skintracker",
table: "listings");
migrationBuilder.DropIndex(
name: "ix_trades_steam_trade_id",
schema: "skintracker",
table: "trades");
migrationBuilder.DropIndex(
name: "ix_listings_condition_id",
schema: "skintracker",
table: "listings");
migrationBuilder.DropIndex(
name: "ix_inventory_items_asset_id",
schema: "skintracker",
table: "inventory_items");
migrationBuilder.DropColumn(
name: "condition_id",
schema: "skintracker",
table: "listings");
migrationBuilder.DropColumn(
name: "currency",
schema: "skintracker",
table: "listings");
migrationBuilder.RenameColumn(
name: "float_min",
schema: "skintracker",
table: "skin_conditions",
newName: "min_float");
migrationBuilder.RenameColumn(
name: "float_max",
schema: "skintracker",
table: "skin_conditions",
newName: "max_float");
migrationBuilder.AlterColumn<string>(
name: "paint_seed",
schema: "skintracker",
table: "skin_instances",
type: "text",
nullable: false,
oldClrType: typeof(int),
oldType: "integer");
migrationBuilder.CreateIndex(
name: "ix_inventory_items_asset_id",
schema: "skintracker",
table: "inventory_items",
column: "asset_id");
}
}
}

View File

@@ -215,6 +215,7 @@ namespace BlueLaminate.EFCore.Migrations
.HasName("pk_inventory_items");
b.HasIndex("AssetId")
.IsUnique()
.HasDatabaseName("ix_inventory_items_asset_id");
b.HasIndex("SkinInstanceId")
@@ -239,11 +240,20 @@ namespace BlueLaminate.EFCore.Migrations
.HasColumnType("text")
.HasColumnName("asset_id");
b.Property<int?>("ConditionId")
.HasColumnType("integer")
.HasColumnName("condition_id");
b.Property<string>("CsFloatListingId")
.IsRequired()
.HasColumnType("text")
.HasColumnName("cs_float_listing_id");
b.Property<string>("Currency")
.IsRequired()
.HasColumnType("text")
.HasColumnName("currency");
b.Property<int>("DefIndex")
.HasColumnType("integer")
.HasColumnName("def_index");
@@ -252,7 +262,7 @@ namespace BlueLaminate.EFCore.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("first_seen_at");
b.Property<decimal>("FloatValue")
b.Property<decimal?>("FloatValue")
.HasColumnType("numeric(20,18)")
.HasColumnName("float_value");
@@ -334,6 +344,9 @@ namespace BlueLaminate.EFCore.Migrations
b.HasIndex("AssetId")
.HasDatabaseName("ix_listings_asset_id");
b.HasIndex("ConditionId")
.HasDatabaseName("ix_listings_condition_id");
b.HasIndex("CsFloatListingId")
.IsUnique()
.HasDatabaseName("ix_listings_cs_float_listing_id");
@@ -553,10 +566,6 @@ namespace BlueLaminate.EFCore.Migrations
.HasColumnType("text")
.HasColumnName("image_url");
b.Property<DateTimeOffset?>("ListingsSweptAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("listings_swept_at");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text")
@@ -597,9 +606,6 @@ namespace BlueLaminate.EFCore.Migrations
b.HasKey("Id")
.HasName("pk_skins");
b.HasIndex("ListingsSweptAt")
.HasDatabaseName("ix_skins_listings_swept_at");
b.HasIndex("Slug")
.IsUnique()
.HasDatabaseName("ix_skins_slug");
@@ -632,17 +638,13 @@ namespace BlueLaminate.EFCore.Migrations
.HasColumnType("text")
.HasColumnName("condition");
b.Property<DateTimeOffset?>("ListingsSweptAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("listings_swept_at");
b.Property<decimal>("MaxFloat")
b.Property<decimal>("FloatMax")
.HasColumnType("numeric(10,9)")
.HasColumnName("max_float");
.HasColumnName("float_max");
b.Property<decimal>("MinFloat")
b.Property<decimal>("FloatMin")
.HasColumnType("numeric(10,9)")
.HasColumnName("min_float");
.HasColumnName("float_min");
b.Property<int>("SkinId")
.HasColumnType("integer")
@@ -651,15 +653,47 @@ namespace BlueLaminate.EFCore.Migrations
b.HasKey("Id")
.HasName("pk_skin_conditions");
b.HasIndex("ListingsSweptAt")
.HasDatabaseName("ix_skin_conditions_listings_swept_at");
b.HasIndex("SkinId")
.HasDatabaseName("ix_skin_conditions_skin_id");
b.ToTable("skin_conditions", "skintracker");
});
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinConditionSweep", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("SkinConditionId")
.HasColumnType("integer")
.HasColumnName("skin_condition_id");
b.Property<string>("Source")
.IsRequired()
.HasColumnType("text")
.HasColumnName("source");
b.Property<DateTimeOffset>("SweptAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("swept_at");
b.HasKey("Id")
.HasName("pk_skin_condition_sweeps");
b.HasIndex("SkinConditionId", "Source")
.IsUnique()
.HasDatabaseName("ix_skin_condition_sweeps_skin_condition_id_source");
b.HasIndex("Source", "SweptAt")
.HasDatabaseName("ix_skin_condition_sweeps_source_swept_at");
b.ToTable("skin_condition_sweeps", "skintracker");
});
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinInstance", b =>
{
b.Property<int>("Id")
@@ -689,9 +723,8 @@ namespace BlueLaminate.EFCore.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("last_seen_at");
b.Property<string>("PaintSeed")
.IsRequired()
.HasColumnType("text")
b.Property<int>("PaintSeed")
.HasColumnType("integer")
.HasColumnName("paint_seed");
b.Property<int>("SkinId")
@@ -725,6 +758,137 @@ namespace BlueLaminate.EFCore.Migrations
b.ToTable("skin_instances", "skintracker");
});
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinLandListing", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int?>("ConditionId")
.HasColumnType("integer")
.HasColumnName("condition_id");
b.Property<string>("Currency")
.IsRequired()
.HasColumnType("text")
.HasColumnName("currency");
b.Property<DateTimeOffset>("FirstSeenAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("first_seen_at");
b.Property<decimal?>("FloatValue")
.HasColumnType("numeric(20,18)")
.HasColumnName("float_value");
b.Property<string>("InspectLink")
.HasColumnType("text")
.HasColumnName("inspect_link");
b.Property<bool>("IsSouvenir")
.HasColumnType("boolean")
.HasColumnName("is_souvenir");
b.Property<bool>("IsStatTrak")
.HasColumnType("boolean")
.HasColumnName("is_stat_trak");
b.Property<DateTimeOffset>("LastSeenAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("last_seen_at");
b.Property<long>("ListingId")
.HasColumnType("bigint")
.HasColumnName("listing_id");
b.Property<string>("MarketHashName")
.IsRequired()
.HasColumnType("text")
.HasColumnName("market_hash_name");
b.Property<string>("NameTag")
.HasColumnType("text")
.HasColumnName("name_tag");
b.Property<decimal>("Price")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)")
.HasColumnName("price");
b.Property<DateTimeOffset?>("RemovedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("removed_at");
b.Property<int>("SkinId")
.HasColumnType("integer")
.HasColumnName("skin_id");
b.Property<string>("Status")
.IsRequired()
.HasColumnType("text")
.HasColumnName("status");
b.Property<int>("StickerCount")
.HasColumnType("integer")
.HasColumnName("sticker_count");
b.HasKey("Id")
.HasName("pk_skin_land_listings");
b.HasIndex("ConditionId")
.HasDatabaseName("ix_skin_land_listings_condition_id");
b.HasIndex("ListingId")
.IsUnique()
.HasDatabaseName("ix_skin_land_listings_listing_id");
b.HasIndex("Status")
.HasDatabaseName("ix_skin_land_listings_status");
b.HasIndex("SkinId", "ConditionId")
.HasDatabaseName("ix_skin_land_listings_skin_id_condition_id");
b.ToTable("skin_land_listings", "skintracker");
});
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinSweep", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("SkinId")
.HasColumnType("integer")
.HasColumnName("skin_id");
b.Property<string>("Source")
.IsRequired()
.HasColumnType("text")
.HasColumnName("source");
b.Property<DateTimeOffset>("SweptAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("swept_at");
b.HasKey("Id")
.HasName("pk_skin_sweeps");
b.HasIndex("SkinId", "Source")
.IsUnique()
.HasDatabaseName("ix_skin_sweeps_skin_id_source");
b.HasIndex("Source", "SweptAt")
.HasDatabaseName("ix_skin_sweeps_source_swept_at");
b.ToTable("skin_sweeps", "skintracker");
});
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SteamUser", b =>
{
b.Property<int>("Id")
@@ -788,6 +952,10 @@ namespace BlueLaminate.EFCore.Migrations
b.HasIndex("FromUserId")
.HasDatabaseName("ix_trades_from_user_id");
b.HasIndex("SteamTradeId")
.IsUnique()
.HasDatabaseName("ix_trades_steam_trade_id");
b.HasIndex("ToUserId")
.HasDatabaseName("ix_trades_to_user_id");
@@ -927,6 +1095,12 @@ namespace BlueLaminate.EFCore.Migrations
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Listing", b =>
{
b.HasOne("BlueLaminate.EFCore.Entities.SkinCondition", "Condition")
.WithMany()
.HasForeignKey("ConditionId")
.OnDelete(DeleteBehavior.SetNull)
.HasConstraintName("fk_listings_skin_conditions_condition_id");
b.HasOne("BlueLaminate.EFCore.Entities.Skin", "Skin")
.WithMany()
.HasForeignKey("SkinId")
@@ -939,6 +1113,8 @@ namespace BlueLaminate.EFCore.Migrations
.OnDelete(DeleteBehavior.SetNull)
.HasConstraintName("fk_listings_skin_instances_skin_instance_id");
b.Navigation("Condition");
b.Navigation("Skin");
b.Navigation("SkinInstance");
@@ -989,6 +1165,18 @@ namespace BlueLaminate.EFCore.Migrations
b.Navigation("Skin");
});
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinConditionSweep", b =>
{
b.HasOne("BlueLaminate.EFCore.Entities.SkinCondition", "SkinCondition")
.WithMany("Sweeps")
.HasForeignKey("SkinConditionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_skin_condition_sweeps_skin_conditions_skin_condition_id");
b.Navigation("SkinCondition");
});
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinInstance", b =>
{
b.HasOne("BlueLaminate.EFCore.Entities.SkinCondition", "Condition")
@@ -1009,6 +1197,38 @@ namespace BlueLaminate.EFCore.Migrations
b.Navigation("Skin");
});
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinLandListing", b =>
{
b.HasOne("BlueLaminate.EFCore.Entities.SkinCondition", "Condition")
.WithMany()
.HasForeignKey("ConditionId")
.OnDelete(DeleteBehavior.SetNull)
.HasConstraintName("fk_skin_land_listings_skin_conditions_condition_id");
b.HasOne("BlueLaminate.EFCore.Entities.Skin", "Skin")
.WithMany()
.HasForeignKey("SkinId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired()
.HasConstraintName("fk_skin_land_listings_skins_skin_id");
b.Navigation("Condition");
b.Navigation("Skin");
});
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinSweep", b =>
{
b.HasOne("BlueLaminate.EFCore.Entities.Skin", "Skin")
.WithMany("Sweeps")
.HasForeignKey("SkinId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_skin_sweeps_skins_skin_id");
b.Navigation("Skin");
});
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Trade", b =>
{
b.HasOne("BlueLaminate.EFCore.Entities.SteamUser", "FromUser")
@@ -1080,6 +1300,8 @@ namespace BlueLaminate.EFCore.Migrations
b.Navigation("Instances");
b.Navigation("PriceHistories");
b.Navigation("Sweeps");
});
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinCondition", b =>
@@ -1087,6 +1309,8 @@ namespace BlueLaminate.EFCore.Migrations
b.Navigation("Instances");
b.Navigation("PriceHistories");
b.Navigation("Sweeps");
});
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinInstance", b =>