Files
fuel_track/app/api/fuel_entries.py
T
Mateusz Gruszczyński 697ac6da30 zapamietanie akcji
2026-07-19 19:15:21 +02:00

53 lines
3.8 KiB
Python

from collections import defaultdict
from datetime import date, datetime
from decimal import Decimal
from flask import current_app, jsonify, request, url_for
from flask_login import current_user, login_required, login_user
from sqlalchemy import extract
from sqlalchemy.exc import IntegrityError
from . import api
from .common import accessible_vehicles, boolv, fail, payload, response, role_required, station_dict, user_dict, vehicle_dict
from .. import THEMES
from ..api_tokens import create_access_token
from ..extensions import db
from ..models import AppSetting, CompanySettings, FuelCard, FuelCardPolicy, FuelCardStationRule, FuelEntry, FuelStationCompany, FuelStationPoint, OrlenPrice, User, Vehicle
from ..services import POLISH_REGIONS, aggregate_ure_companies, calculate_costs, fetch_orlen_price, fetch_orlen_range, fetch_ure_stations, invoice_period
from ..station_catalog import sync_station_catalog
from ..vat import freeze_vat_action
from ..settlement import freeze as freeze_settlement
FUEL_TYPES = ("PB95", "PB98", "DIESEL", "LPG")
@api.post('/fuel-entries')
@login_required
def create_fuel_entry():
d=payload(); vehicles=accessible_vehicles()
try: vehicle=next((v for v in vehicles if v.id==int(d['vehicle_id'])),None)
except Exception: vehicle=None
if not vehicle:return fail('Brak dostępu do pojazdu',403)
try:
odo=int(d['odometer']); fueled_at=datetime.fromisoformat(d['fueled_at']); station_company=db.session.get(FuelStationCompany,int(d['station_company_id'])) if d.get('station_company_id') else None
settings=vehicle.company or current_user.company or CompanySettings.query.first()
access_mode=settings.station_access_mode or 'all_prefer_favorites'
if station_company and access_mode=='allowed_only' and station_company not in settings.allowed_stations:
return fail('Ta stacja nie jest dozwolona przez politykę firmy',403)
if station_company and access_mode=='favorites_allowed_only' and station_company not in settings.allowed_stations and station_company not in settings.favorite_stations:
return fail('Ta stacja nie jest ulubiona ani dozwolona przez politykę firmy',403)
wholesale=source=None; region=(station_company.selected_region if station_company else None) or settings.region
try:
p=fetch_orlen_price(d['fuel_type'],fueled_at.date(),region);wholesale=p['price_per_liter'];source=p['source']
except Exception: pass
card_id=int(d['fuel_card_id']) if d.get('fuel_card_id') else (vehicle.fuel_card_id or current_user.fuel_card_id)
card=db.session.get(FuelCard,card_id) if card_id else None
used_card=boolv(d,'used_fuel_card') and bool(card)
if used_card and station_company:
rule=FuelCardStationRule.query.filter_by(fuel_card_id=card.id,station_company_id=station_company.id).first()
if rule and not rule.allowed:return fail('Ta stacja jest zablokowana dla wybranej karty paliwowej',403)
e=FuelEntry(vehicle=vehicle,user_id=current_user.id,fueled_at=fueled_at,liters=Decimal(d['liters']),price_per_liter=Decimal(d['price_per_liter']),fuel_type=d['fuel_type'],odometer=odo,station=station_company.company_name if station_company else d.get('station'),station_company_id=station_company.id if station_company else None,fuel_card_id=card.id if used_card else None,invoice_number=d.get('invoice_number'),used_fuel_card=used_card,wholesale_price=wholesale,wholesale_source=source)
freeze_vat_action(e, settings.vat_rate)
freeze_settlement(e, settings, source="Automatycznie przy dodaniu przez API")
vehicle.current_odometer=odo;db.session.add(e);db.session.commit();return response({'id':e.id,'redirect':url_for('main.dashboard')},'Zapisano tankowanie',201)
except Exception as exc:db.session.rollback();return fail(str(exc),400)