namespace BlueLaminate.EFCore.Entities; /// /// One sell-order observed on cs.money via its internal /// GET /2.0/market/sell-orders endpoint (scraped through the Python worker, /// since cs.money has no public API and sits behind Cloudflare). /// /// Kept in its own table rather than shared with the CSFloat : /// cs.money exposes a different shape (its own sell-order id, a pricing breakdown, /// quality/phase, and no def/paint index). It still links to the /// market-agnostic by fingerprint, so the same physical /// item seen on both markets rolls up to one instance for cross-market analysis. /// /// Soft-tracked across sweeps exactly like : /// / bound the observation window /// and flips to when a /// once-seen order stops appearing (sold/delisted). /// public class CsMoneyListing { public int Id { get; set; } /// cs.money's sell-order id (item.id). Natural key for dedup. public long SellOrderId { get; set; } /// /// cs.money's asset id for the listed copy. Not a stable identity, but the /// discriminator that distinguishes duped copies sharing one fingerprint. /// public string? AssetId { get; set; } // Catalogue links. Unlike the CSFloat global sweep these are NOT best-effort: // each scrape job targets one skin+wear, so the worker reports which Skin/ // Condition the results belong to and we set them directly. public int SkinId { get; set; } public Skin Skin { get; set; } = null!; public int? ConditionId { get; set; } public SkinCondition? Condition { get; set; } /// The physical item (by fingerprint), shared with CSFloat listings. public int? SkinInstanceId { get; set; } public SkinInstance? SkinInstance { get; set; } // Item identity, from the listing's asset block. public string MarketHashName { get; set; } = null!; public string? Quality { get; set; } // cs.money wear short code: fn/mw/ft/ww/bs public decimal? FloatValue { get; set; } // null for non-skin items public int? PaintSeed { get; set; } // asset.pattern public string? Phase { get; set; } // doppler phase (sapphire/ruby/…) public bool IsStatTrak { get; set; } public bool IsSouvenir { get; set; } public int StickerCount { get; set; } // Pricing. cs.money returns a breakdown; Price is the actual asking price. public decimal Price { get; set; } // pricing.default public decimal? PriceBeforeDiscount { get; set; } public decimal? ComputedPrice { get; set; } // pricing.computed (reference price) public string Currency { get; set; } = "USD"; // cs.money returns no currency field public string? InspectLink { get; set; } // Soft-tracking across sweeps. public DateTimeOffset FirstSeenAt { get; set; } public DateTimeOffset LastSeenAt { get; set; } public ListingStatus Status { get; set; } public DateTimeOffset? RemovedAt { get; set; } }