package models import "time" // Lot represents existing lot table type Lot struct { LotName string `gorm:"column:lot_name;primaryKey;size:255" json:"lot_name"` LotDescription string `gorm:"column:lot_description;size:10000" json:"lot_description"` LotCategory *string `gorm:"column:lot_category;size:50" json:"lot_category"` } func (Lot) TableName() string { return "lot" } // LotLog represents existing lot_log table (READ-ONLY) type LotLog struct { LotLogID uint `gorm:"column:lot_log_id;primaryKey;autoIncrement"` Lot string `gorm:"column:lot;size:255;not null"` Supplier string `gorm:"column:supplier;size:255;not null"` Date time.Time `gorm:"column:date;type:date;not null"` Price float64 `gorm:"column:price;not null"` Quality string `gorm:"column:quality;size:255"` Comments string `gorm:"column:comments;size:15000"` } func (LotLog) TableName() string { return "lot_log" } // Supplier represents the supplier table. // PriceForge manages this table for the unified import pipeline. type Supplier struct { SupplierName string `gorm:"column:supplier_name;primaryKey;size:255" json:"supplier_name"` SupplierComment string `gorm:"column:supplier_comment;size:10000" json:"supplier_comment,omitempty"` SupplierCode string `gorm:"column:supplier_code;size:100;not null;default:'';uniqueIndex:uq_supplier_code" json:"supplier_code"` SupplierType string `gorm:"column:supplier_type;type:enum('trader','self','competitor');not null;default:'trader'" json:"supplier_type"` PriceUplift float64 `gorm:"column:price_uplift;type:decimal(8,4);not null;default:1.0" json:"price_uplift"` DefaultLeadTimeWeeks *int `gorm:"column:default_lead_time_weeks" json:"default_lead_time_weeks,omitempty"` DefaultImportFormatCode *string `gorm:"column:default_import_format_code;size:100" json:"default_import_format_code,omitempty"` IsActive bool `gorm:"column:is_active;not null;default:true" json:"is_active"` } func (Supplier) TableName() string { return "supplier" } // StockLog stores warehouse stock snapshots imported from external files. type StockLog struct { StockLogID uint `gorm:"column:stock_log_id;primaryKey;autoIncrement"` Partnumber string `gorm:"column:partnumber;size:255;not null"` Supplier *string `gorm:"column:supplier;size:255"` Date time.Time `gorm:"column:date;type:date;not null"` Price float64 `gorm:"column:price;not null"` Quality *string `gorm:"column:quality;size:255"` Comments *string `gorm:"column:comments;size:15000"` Vendor *string `gorm:"column:vendor;size:255"` Qty *float64 `gorm:"column:qty"` } func (StockLog) TableName() string { return "stock_log" } // LotPartnumber is deprecated and kept only for in-memory compatibility in tests. // Runtime must use qt_partnumber_book_items.lots_json instead of the lot_partnumbers table. type LotPartnumber struct { Vendor string `gorm:"column:vendor;size:255;primaryKey" json:"vendor"` Partnumber string `gorm:"column:partnumber;size:255;primaryKey" json:"partnumber"` LotName string `gorm:"column:lot_name;size:255" json:"lot_name"` Description *string `gorm:"column:description;size:10000" json:"description,omitempty"` } func (LotPartnumber) TableName() string { return "lot_partnumbers" } // PartnumberBook is a versioned snapshot of the partnumber→LOT mapping. // Written by PriceForge; QuoteForge reads via SELECT only. type PartnumberBook struct { ID uint64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` Version string `gorm:"column:version;size:30;not null;uniqueIndex:uq_qt_partnumber_books_version" json:"version"` CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"` CreatedBy string `gorm:"column:created_by;size:100;not null;default:''" json:"created_by"` IsActive bool `gorm:"column:is_active;not null;default:false" json:"is_active"` PartnumbersJSON string `gorm:"column:partnumbers_json;type:longtext;not null" json:"partnumbers_json"` } func (PartnumberBook) TableName() string { return "qt_partnumber_books" } type PartnumberBookLot struct { LotName string `json:"lot_name"` Qty float64 `json:"qty"` } // PartnumberBookItem is the current source-of-truth row for one partnumber. // lots_json stores the resolved LOT composition with quantities. type PartnumberBookItem struct { ID uint64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` Partnumber string `gorm:"column:partnumber;size:255;not null;uniqueIndex:uq_qt_partnumber_book_items_partnumber" json:"partnumber"` LotsJSON string `gorm:"column:lots_json;type:longtext;not null" json:"lots_json"` Description *string `gorm:"column:description;size:10000" json:"description,omitempty"` } func (PartnumberBookItem) TableName() string { return "qt_partnumber_book_items" } // LotBundle is deprecated and kept only for compatibility with legacy tests. type LotBundle struct { BundleLotName string `gorm:"column:bundle_lot_name;size:255;primaryKey" json:"bundle_lot_name"` IsActive bool `gorm:"column:is_active;default:true" json:"is_active"` CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"` UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"` } func (LotBundle) TableName() string { return "qt_lot_bundles" } // LotBundleItem is deprecated and kept only for compatibility with legacy tests. type LotBundleItem struct { ID uint64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` BundleLotName string `gorm:"column:bundle_lot_name;size:255;not null;index:uq_qt_lot_bundle_items_bundle_lot,unique" json:"bundle_lot_name"` LotName string `gorm:"column:lot_name;size:255;not null;index:uq_qt_lot_bundle_items_bundle_lot,unique" json:"lot_name"` Qty float64 `gorm:"column:qty;not null" json:"qty"` CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"` UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"` } func (LotBundleItem) TableName() string { return "qt_lot_bundle_items" } type VendorPartnumberSeen struct { ID uint64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` SourceType string `gorm:"column:source_type;size:32;not null" json:"source_type"` Vendor string `gorm:"column:vendor;size:255;not null;default:'';index:idx_qt_vendor_partnumber_seen_vendor_partnumber" json:"vendor"` Partnumber string `gorm:"column:partnumber;size:255;not null;uniqueIndex:uq_qt_vendor_partnumber_seen_partnumber;index:idx_qt_vendor_partnumber_seen_vendor_partnumber" json:"partnumber"` Description *string `gorm:"column:description;size:10000" json:"description,omitempty"` LastSeenAt time.Time `gorm:"column:last_seen_at;not null" json:"last_seen_at"` IsIgnored bool `gorm:"column:is_ignored;not null;default:false;index:idx_qt_vendor_partnumber_seen_ignored" json:"is_ignored"` IsPattern bool `gorm:"column:is_pattern;not null;default:false" json:"is_pattern,omitempty"` IgnoredAt *time.Time `gorm:"column:ignored_at" json:"ignored_at,omitempty"` IgnoredBy *string `gorm:"column:ignored_by;size:100" json:"ignored_by,omitempty"` CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"` UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"` } func (VendorPartnumberSeen) TableName() string { return "qt_vendor_partnumber_seen" } // StockIgnoreRule is deprecated and kept for backward compatibility only. // New logic uses VendorPartnumberSeen.is_ignored. type StockIgnoreRule struct { ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"` Target string `gorm:"column:target;size:20;not null" json:"target"` MatchType string `gorm:"column:match_type;size:20;not null" json:"match_type"` Pattern string `gorm:"column:pattern;size:500;not null" json:"pattern"` CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"` } func (StockIgnoreRule) TableName() string { return "stock_ignore_rules" }