from datetime import datetime from flask_login import UserMixin from werkzeug.security import generate_password_hash, check_password_hash from .extensions import db vehicle_users = db.Table( "vehicle_users", db.Column("vehicle_id", db.Integer, db.ForeignKey("vehicle.id"), primary_key=True), db.Column("user_id", db.Integer, db.ForeignKey("user.id"), primary_key=True), ) user_favorite_stations = db.Table( "user_favorite_stations", db.Column("user_id", db.Integer, db.ForeignKey("user.id"), primary_key=True), db.Column("station_company_id", db.Integer, db.ForeignKey("fuel_station_company.id"), primary_key=True), ) company_favorite_stations = db.Table( "company_favorite_stations", db.Column("settings_id", db.Integer, db.ForeignKey("company_settings.id"), primary_key=True), db.Column("station_company_id", db.Integer, db.ForeignKey("fuel_station_company.id"), primary_key=True), ) company_allowed_stations = db.Table( "company_allowed_stations", db.Column("settings_id", db.Integer, db.ForeignKey("company_settings.id"), primary_key=True), db.Column("station_company_id", db.Integer, db.ForeignKey("fuel_station_company.id"), primary_key=True), ) class User(UserMixin, db.Model): id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(160), unique=True, nullable=False, index=True) name = db.Column(db.String(120), nullable=False) password_hash = db.Column(db.String(255), nullable=False) role = db.Column(db.String(20), nullable=False, default="user") active = db.Column(db.Boolean, default=True, nullable=False) fuel_card_id = db.Column(db.Integer, db.ForeignKey("fuel_card.id"), index=True) company_id = db.Column(db.Integer, db.ForeignKey("company_settings.id"), index=True) created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) owned_vehicles = db.relationship("Vehicle", back_populates="owner", foreign_keys="Vehicle.owner_id") shared_vehicles = db.relationship("Vehicle", secondary=vehicle_users, back_populates="drivers") fuel_card = db.relationship("FuelCard", foreign_keys=[fuel_card_id]) company = db.relationship("CompanySettings", foreign_keys=[company_id], back_populates="users") def set_password(self, password): self.password_hash = generate_password_hash(password) def check_password(self, password): return check_password_hash(self.password_hash, password) @property def is_active(self): return self.active class CompanySettings(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(160), default="Moja firma", nullable=False) entity_type = db.Column(db.String(30), default="JDG", nullable=False) vat_rate = db.Column(db.Numeric(5, 2), default=23, nullable=False) vat_deduction_percent = db.Column(db.Numeric(5, 2), default=50, nullable=False) region = db.Column(db.String(60), default="mazowieckie", nullable=False) invoice_split_day = db.Column(db.Integer, default=15, nullable=False) active = db.Column(db.Boolean, default=True, nullable=False) users = db.relationship("User", back_populates="company", foreign_keys="User.company_id") class AppSetting(db.Model): key = db.Column(db.String(80), primary_key=True) value = db.Column(db.String(255), nullable=False) class FuelCard(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(120), nullable=False, unique=True, index=True) provider = db.Column(db.String(120), nullable=False) active = db.Column(db.Boolean, default=True, nullable=False) description = db.Column(db.String(255)) company_id = db.Column(db.Integer, db.ForeignKey("company_settings.id"), index=True) created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) station_rules = db.relationship("FuelCardStationRule", back_populates="fuel_card", cascade="all, delete-orphan") company = db.relationship("CompanySettings", foreign_keys=[company_id]) class Vehicle(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(120), nullable=False) make = db.Column(db.String(80), nullable=False) model = db.Column(db.String(80), nullable=False) registration = db.Column(db.String(20), unique=True, nullable=False) fuel_type = db.Column(db.String(20), nullable=False, default="PB95") owner_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False) company_id = db.Column(db.Integer, db.ForeignKey("company_settings.id"), index=True) has_fuel_card = db.Column(db.Boolean, default=False, nullable=False) card_provider = db.Column(db.String(80)) fuel_card_id = db.Column(db.Integer, db.ForeignKey("fuel_card.id"), index=True) current_odometer = db.Column(db.Integer, default=0, nullable=False) owner = db.relationship("User", back_populates="owned_vehicles", foreign_keys=[owner_id]) drivers = db.relationship("User", secondary=vehicle_users, back_populates="shared_vehicles") fuel_card = db.relationship("FuelCard", foreign_keys=[fuel_card_id]) company = db.relationship("CompanySettings", foreign_keys=[company_id]) fuel_entries = db.relationship("FuelEntry", back_populates="vehicle", cascade="all, delete-orphan") class FuelStationCompany(db.Model): id = db.Column(db.Integer, primary_key=True) ure_key = db.Column(db.String(180), unique=True, nullable=False, index=True) brand_name = db.Column(db.String(120), nullable=False, default="", index=True) company_name = db.Column(db.String(220), nullable=False, index=True) nip = db.Column(db.String(20), index=True) regon = db.Column(db.String(20), index=True) station_names = db.Column(db.Text, default="", nullable=False) regions = db.Column(db.Text, default="", nullable=False) selected_region = db.Column(db.String(60), default="", nullable=False) station_count = db.Column(db.Integer, default=0, nullable=False) has_petrol = db.Column(db.Boolean, default=False, nullable=False) has_diesel = db.Column(db.Boolean, default=False, nullable=False) has_lpg = db.Column(db.Boolean, default=False, nullable=False) use_orlen_last_price = db.Column(db.Boolean, default=False, nullable=False) active = db.Column(db.Boolean, default=True, nullable=False) fetched_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) points = db.relationship("FuelStationPoint", back_populates="station_company", cascade="all, delete-orphan", lazy="dynamic") @property def region_list(self): return [x for x in (self.regions or "").split("|") if x] @property def station_name_list(self): return [x for x in (self.station_names or "").split("|") if x] @property def display_name(self): return self.brand_name or self.company_name class FuelStationPoint(db.Model): id = db.Column(db.Integer, primary_key=True) station_company_id = db.Column(db.Integer, db.ForeignKey("fuel_station_company.id"), nullable=False, index=True) ure_dkn = db.Column(db.String(40), nullable=False, index=True) station_name = db.Column(db.String(220), nullable=False, default="") street = db.Column(db.String(180), nullable=False, default="") street_number = db.Column(db.String(40), nullable=False, default="") postal_code = db.Column(db.String(20), nullable=False, default="") city = db.Column(db.String(120), nullable=False, default="") region = db.Column(db.String(60), nullable=False, default="") coordinates = db.Column(db.String(120), nullable=False, default="") has_petrol = db.Column(db.Boolean, default=False, nullable=False) has_diesel = db.Column(db.Boolean, default=False, nullable=False) has_lpg = db.Column(db.Boolean, default=False, nullable=False) station_company = db.relationship("FuelStationCompany", back_populates="points") __table_args__ = (db.UniqueConstraint("station_company_id", "ure_dkn", name="uq_station_company_point_dkn"),) @property def address(self): line = " ".join(x for x in (self.street, self.street_number) if x).strip() locality = " ".join(x for x in (self.postal_code, self.city) if x).strip() return ", ".join(x for x in (line, locality) if x) or "Brak adresu" class FuelCardStationRule(db.Model): id = db.Column(db.Integer, primary_key=True) fuel_card_id = db.Column(db.Integer, db.ForeignKey("fuel_card.id"), nullable=False, index=True) station_company_id = db.Column(db.Integer, db.ForeignKey("fuel_station_company.id"), nullable=False, index=True) allowed = db.Column(db.Boolean, default=True, nullable=False) use_orlen_last_price = db.Column(db.Boolean, default=False, nullable=False) discount_net_percent = db.Column(db.Numeric(6, 3), default=0, nullable=False) surcharge_net_per_liter = db.Column(db.Numeric(10, 4), default=0, nullable=False) fuel_card = db.relationship("FuelCard", back_populates="station_rules") station_company = db.relationship("FuelStationCompany") __table_args__ = (db.UniqueConstraint("fuel_card_id", "station_company_id", name="uq_card_station_rule"),) class FuelEntry(db.Model): id = db.Column(db.Integer, primary_key=True) vehicle_id = db.Column(db.Integer, db.ForeignKey("vehicle.id"), nullable=False, index=True) user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False) fueled_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow, index=True) liters = db.Column(db.Numeric(10, 3), nullable=False) price_per_liter = db.Column(db.Numeric(10, 4), nullable=False) fuel_type = db.Column(db.String(20), nullable=False) odometer = db.Column(db.Integer, nullable=False) station = db.Column(db.String(120)) station_company_id = db.Column(db.Integer, db.ForeignKey("fuel_station_company.id"), index=True) fuel_card_id = db.Column(db.Integer, db.ForeignKey("fuel_card.id"), index=True) invoice_number = db.Column(db.String(80)) used_fuel_card = db.Column(db.Boolean, default=False, nullable=False) wholesale_price = db.Column(db.Numeric(10, 4)) wholesale_source = db.Column(db.String(120)) created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) vehicle = db.relationship("Vehicle", back_populates="fuel_entries") user = db.relationship("User") station_company = db.relationship("FuelStationCompany") fuel_card = db.relationship("FuelCard") @property def gross(self): return float(self.liters) * float(self.price_per_liter) class OrlenPrice(db.Model): id = db.Column(db.Integer, primary_key=True) fuel_type = db.Column(db.String(20), nullable=False, index=True) effective_date = db.Column(db.Date, nullable=False, index=True) price_per_liter = db.Column(db.Numeric(10, 4), nullable=False) raw_value = db.Column(db.Numeric(14, 4), nullable=False) region = db.Column(db.String(60), nullable=False, default="") product_name = db.Column(db.String(80), nullable=False) source = db.Column(db.String(160), nullable=False) fetched_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) __table_args__ = (db.UniqueConstraint("fuel_type", "effective_date", "region", name="uq_orlen_price"),) class FuelCardPolicy(db.Model): id = db.Column(db.Integer, primary_key=True) vehicle_id = db.Column(db.Integer, db.ForeignKey("vehicle.id"), nullable=False, unique=True, index=True) use_orlen_last_price = db.Column(db.Boolean, default=False, nullable=False) discount_percent = db.Column(db.Numeric(6, 3), default=0, nullable=False) surcharge_per_liter = db.Column(db.Numeric(10, 4), default=0, nullable=False) description = db.Column(db.String(160)) vehicle = db.relationship("Vehicle", backref=db.backref("fuel_card_policy", uselist=False, cascade="all, delete-orphan")) User.favorite_stations = db.relationship("FuelStationCompany", secondary=user_favorite_stations, backref=db.backref("favorite_users", lazy="dynamic")) CompanySettings.allowed_stations = db.relationship("FuelStationCompany", secondary=company_allowed_stations, backref=db.backref("allowed_for_companies", lazy="dynamic")) CompanySettings.favorite_stations = db.relationship("FuelStationCompany", secondary=company_favorite_stations, backref=db.backref("favorite_for_companies", lazy="dynamic"))