Files
fuel_track/app/models.py
T
Mateusz Gruszczyński bd562b3da6 first commit
2026-07-13 13:19:26 +02:00

206 lines
12 KiB
Python

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"))