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 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_id=vehicle.id,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) 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)