"""Machines plugin models.""" from shopdb.api import db, BaseModel class MachineType(BaseModel): """ Machine type classification. Examples: CNC, CMM, Lathe, Grinder, EDM, Part Marker, etc. """ __tablename__ = 'machinetypes' machinetypeid = db.Column(db.Integer, primary_key=True) machinetype = db.Column(db.String(100), unique=True, nullable=False) description = db.Column(db.Text) icon = db.Column(db.String(50), comment='Icon name for UI') color = db.Column(db.String(20), comment='CSS color for UI/map markers') def __repr__(self): return f"" class Machine(BaseModel): """ Machine-specific extension data. Links to core Asset table via assetid. Stores machine-specific fields like type, model, vendor, etc. """ __tablename__ = 'machines' machineid = db.Column(db.Integer, primary_key=True) # Link to core asset assetid = db.Column( db.Integer, db.ForeignKey('assets.assetid', ondelete='CASCADE'), unique=True, nullable=False, index=True ) # Machine classification machinetypeid = db.Column( db.Integer, db.ForeignKey('machinetypes.machinetypeid'), nullable=True ) # Vendor and model vendorid = db.Column( db.Integer, db.ForeignKey('vendors.vendorid'), nullable=True ) modelnumberid = db.Column( db.Integer, db.ForeignKey('models.modelnumberid'), nullable=True ) # Machine-specific fields requiresmanualconfig = db.Column( db.Boolean, default=False, comment='Multi-PC machine needs manual configuration' ) islocationonly = db.Column( db.Boolean, default=False, comment='Virtual location marker (not actual machine)' ) # Maintenance tracking lastmaintenancedate = db.Column(db.DateTime, nullable=True) nextmaintenancedate = db.Column(db.DateTime, nullable=True) maintenanceintervaldays = db.Column(db.Integer, nullable=True) # Controller info (for CNC machines) controllervendorid = db.Column( db.Integer, db.ForeignKey('vendors.vendorid'), nullable=True, comment='Controller vendor (e.g., FANUC)' ) controllermodelid = db.Column( db.Integer, db.ForeignKey('models.modelnumberid'), nullable=True, comment='Controller model (e.g., 31B)' ) # Relationships asset = db.relationship( 'Asset', backref=db.backref('machine', uselist=False, lazy='joined') ) machinetype = db.relationship('MachineType', backref='machines') vendor = db.relationship('Vendor', foreign_keys=[vendorid], backref='machine_items') model = db.relationship('Model', foreign_keys=[modelnumberid], backref='machine_items') controllervendor = db.relationship('Vendor', foreign_keys=[controllervendorid], backref='machine_controllers') controllermodel = db.relationship('Model', foreign_keys=[controllermodelid], backref='machine_controller_models') __table_args__ = ( db.Index('idx_machine_type', 'machinetypeid'), db.Index('idx_machine_vendor', 'vendorid'), ) def __repr__(self): return f"" def to_dict(self): """Convert to dictionary with related names.""" result = super().to_dict() # Add related object names if self.machinetype: result['machinetypename'] = self.machinetype.machinetype if self.vendor: result['vendorname'] = self.vendor.vendor if self.model: result['modelname'] = self.model.modelnumber if self.model.imageurl: result['imageurl'] = self.model.imageurl # The catalog model already knows its maker, so an asset that has a # model but no vendor of its own is showing a blank the database can # fill. Flagged rather than merged silently: the edit form still has # an empty vendor box, and a page implying otherwise would be lying. if not self.vendor and self.model.vendor: result['vendorname'] = self.model.vendor.vendor result['vendorfrommodel'] = True # Exposed under its OWN name. modeltypes is the catalog-wide list # covering every kind of asset, so it is not interchangeable with # this asset's own type and must never be substituted for it. if self.model.modeltype: result['modeltypename'] = self.model.modeltype.modeltype # Add controller info if self.controllervendor: result['controllervendorname'] = self.controllervendor.vendor if self.controllermodel: result['controllermodelname'] = self.controllermodel.modelnumber return result