Updated auto code and change weather api

This commit is contained in:
2025-10-12 16:09:45 -04:00
parent c69d48dd74
commit ed2e6f96b6
8 changed files with 352 additions and 308 deletions

View File

@@ -1,15 +1,14 @@
from fastapi import APIRouter, Request
from datetime import date
from fastapi import APIRouter, Request, HTTPException
from datetime import date
from database import session
from pyowm import OWM
from decimal import Decimal
from app.models.auto import Auto_Delivery, Tickets_Auto_Delivery
# Import your models
from app.models.auto import Auto_Delivery, Tickets_Auto_Delivery
from app.models.pricing import Pricing_Oil_Oil
from app.script.update_auto import calc_home_factor
# Import the new estimator class
from app.script.fuel_estimator import FuelEstimator
router = APIRouter(
prefix="/confirm",
@@ -20,121 +19,98 @@ router = APIRouter(
@router.put("/auto/update/{autoid}")
async def update_auto(autoid: int, request: Request):
"""
Confirms a delivery, updates the ticket, and triggers the self-correcting
K-Factor (house_factor) refinement.
"""
try:
request_body = await request.json()
gallons_delivered = Decimal(request_body['gallons_delivered'])
request_body = await request.json()
gallons_delivered = request_body['gallons_delivered']
gallons_delivered = Decimal(gallons_delivered)
auto_customer = session.query(Auto_Delivery).filter(Auto_Delivery.id == autoid).first()
if not auto_customer:
raise HTTPException(status_code=404, detail="Auto Delivery profile not found")
get_auto_delivery = (session
.query(Auto_Delivery)
.filter(Auto_Delivery.id == autoid)
.first())
if auto_customer.open_ticket_id is None:
raise HTTPException(status_code=400, detail="No open ticket found for this auto-delivery. Cannot confirm delivery.")
ticket = session.query(Tickets_Auto_Delivery).filter(Tickets_Auto_Delivery.id == auto_customer.open_ticket_id).first()
if not ticket:
raise HTTPException(status_code=404, detail=f"Open ticket with ID {auto_customer.open_ticket_id} not found.")
gallons_put_in_home = Decimal(gallons_delivered)
ticket.gallons_delivered = gallons_delivered
ticket.total_amount_customer = ticket.price_per_gallon * gallons_delivered
estimator = FuelEstimator(session=session)
estimator.refine_factor_after_delivery(ticket=ticket)
customer_home_factor = get_auto_delivery.house_factor
session.add(ticket)
session.add(auto_customer)
session.commit()
new_home_factor = calc_home_factor(gallons_put_in_home = gallons_put_in_home,
current_house_factor=customer_home_factor)
gallons_left_buffer = int(get_auto_delivery.tank_size) - 30
get_auto_delivery.house_factor = new_home_factor
get_auto_delivery.tank_height = 'Full'
get_auto_delivery.last_fill = date.today()
get_auto_delivery.estimated_gallons_left = gallons_left_buffer
get_auto_delivery.estimated_gallons_left_prev_day = gallons_left_buffer
get_auto_delivery.auto_status = 1
get_auto_delivery.days_since_last_fill = 0
# Update the associated ticket if it exists
if get_auto_delivery.open_ticket_id is not None:
get_ticket = (session
.query(Tickets_Auto_Delivery)
.filter(Tickets_Auto_Delivery.id == get_auto_delivery.open_ticket_id)
.first())
if get_ticket:
get_ticket.gallons_delivered = gallons_delivered
get_ticket.total_amount_customer = get_ticket.price_per_gallon * gallons_delivered
session.add(get_ticket)
session.add(get_auto_delivery)
session.commit()
return ({"ok": True}), 200
return {"ok": True, "message": "Delivery confirmed and customer factor refined successfully."}
except Exception as e:
session.rollback()
raise HTTPException(status_code=500, detail=f"An internal error occurred: {str(e)}")
@router.post("/auto/create/{autoid}")
async def create_auto_ticket(autoid: int, request: Request):
"""
Creates a new delivery ticket and links it to the auto-delivery customer profile.
"""
request_body = await request.json()
gallons_delivered = request_body['gallons_delivered']
gallons_delivered = request_body['gallons_delivered'] # Estimated gallons for pre-auth
gallons_delivered = Decimal(gallons_delivered)
payment_type = request_body.get('payment_type')
payment_card_id = request_body.get('payment_card_id')
payment_status = request_body.get('payment_status')
get_auto_delivery = (session
.query(Auto_Delivery)
.filter(Auto_Delivery.id == autoid)
.first())
get_todays_price = (session.query(Pricing_Oil_Oil)
.order_by(Pricing_Oil_Oil.id.desc())
.first())
gallons_put_in_home = Decimal(gallons_delivered)
get_auto_delivery = session.query(Auto_Delivery).filter(Auto_Delivery.id == autoid).first()
get_todays_price = session.query(Pricing_Oil_Oil).order_by(Pricing_Oil_Oil.id.desc()).first()
todays_price = Decimal(get_todays_price.price_for_customer)
total_amount = gallons_put_in_home * todays_price
total_amount = gallons_delivered * todays_price
create_new_ticket = Tickets_Auto_Delivery(
customer_id = get_auto_delivery.customer_id,
account_number = get_auto_delivery.account_number,
customer_town = get_auto_delivery.customer_town,
customer_state = get_auto_delivery.customer_state,
customer_address = get_auto_delivery.customer_address,
customer_zip =get_auto_delivery.customer_zip,
customer_full_name = get_auto_delivery.customer_full_name,
oil_prices_id = get_todays_price.id,
gallons_delivered = gallons_delivered,
price_per_gallon = get_todays_price.price_for_customer,
total_amount_customer = total_amount,
fill_date = date.today(),
payment_type = payment_type,
payment_card_id = payment_card_id,
payment_status = payment_status,
customer_id=get_auto_delivery.customer_id,
account_number=get_auto_delivery.account_number,
customer_town=get_auto_delivery.customer_town,
customer_state=get_auto_delivery.customer_state,
customer_address=get_auto_delivery.customer_address,
customer_zip=get_auto_delivery.customer_zip,
customer_full_name=get_auto_delivery.customer_full_name,
oil_prices_id=get_todays_price.id,
gallons_delivered=gallons_delivered,
price_per_gallon=get_todays_price.price_for_customer,
total_amount_customer=total_amount,
fill_date=date.today(),
payment_type=payment_type,
payment_card_id=payment_card_id,
payment_status=payment_status,
)
session.add(create_new_ticket)
session.flush() # Generate the ID for create_new_ticket
session.flush()
# Update the auto_delivery with the open ticket id
get_auto_delivery.open_ticket_id = create_new_ticket.id
session.add(get_auto_delivery)
session.commit() # Commit all changes in one transaction
session.commit()
return ({
"ok": True,
"auto_ticket_id":create_new_ticket.id
}), 200
return ({"ok": True, "auto_ticket_id":create_new_ticket.id}), 200
@router.put("/auto/close_ticket/{ticket_id}")
async def close_ticket(ticket_id: int):
"""
Close an auto ticket by updating payment_status to 3 and setting open_ticket_id to None on the auto delivery.
Closes an auto ticket by updating payment_status and unlinking from the auto delivery profile.
"""
ticket = session.query(Tickets_Auto_Delivery).filter(Tickets_Auto_Delivery.id == ticket_id).first()
if ticket:
ticket.payment_status = 3
ticket.payment_status = 3 # Assuming 3 means closed/paid
session.add(ticket)
delivery = session.query(Auto_Delivery).filter(Auto_Delivery.open_ticket_id == ticket_id).first()
@@ -149,8 +125,7 @@ async def close_ticket(ticket_id: int):
@router.delete("/auto/delete_ticket/{ticket_id}")
async def delete_ticket(ticket_id: int):
"""
Delete an auto ticket and remove its reference from the associated auto delivery.
Used when authorization fails and the ticket needs to be cleaned up.
Deletes an auto ticket and unlinks its reference, used for cleanup (e.g., failed payment).
"""
ticket = session.query(Tickets_Auto_Delivery).filter(Tickets_Auto_Delivery.id == ticket_id).first()
if ticket:
@@ -165,13 +140,11 @@ async def delete_ticket(ticket_id: int):
return {"ok": True}, 200
@router.post("/auto/create/nopreauth/{autoid}")
async def create_auto_ticket_no_preauth(autoid: int, request: Request):
"""
Creates a new delivery ticket without pre-authorization details.
"""
request_body = await request.json()
gallons_delivered = request_body['gallons_delivered']
gallons_delivered = Decimal(gallons_delivered)
@@ -179,43 +152,31 @@ async def create_auto_ticket_no_preauth(autoid: int, request: Request):
payment_card_id = 0
payment_status = 3
get_auto_delivery = (session
.query(Auto_Delivery)
.filter(Auto_Delivery.id == autoid)
.first())
get_todays_price = (session.query(Pricing_Oil_Oil)
.order_by(Pricing_Oil_Oil.id.desc())
.first())
gallons_put_in_home = Decimal(gallons_delivered)
get_auto_delivery = session.query(Auto_Delivery).filter(Auto_Delivery.id == autoid).first()
get_todays_price = session.query(Pricing_Oil_Oil).order_by(Pricing_Oil_Oil.id.desc()).first()
todays_price = Decimal(get_todays_price.price_for_customer)
total_amount = gallons_put_in_home * todays_price
total_amount = gallons_delivered * todays_price
create_new_ticket = Tickets_Auto_Delivery(
customer_id = get_auto_delivery.customer_id,
account_number = get_auto_delivery.account_number,
customer_town = get_auto_delivery.customer_town,
customer_state = get_auto_delivery.customer_state,
customer_address = get_auto_delivery.customer_address,
customer_zip =get_auto_delivery.customer_zip,
customer_full_name = get_auto_delivery.customer_full_name,
oil_prices_id = get_todays_price.id,
gallons_delivered = gallons_delivered,
price_per_gallon = get_todays_price.price_for_customer,
total_amount_customer = total_amount,
fill_date = date.today(),
payment_type = payment_type,
payment_card_id = payment_card_id,
payment_status = payment_status,
customer_id=get_auto_delivery.customer_id,
account_number=get_auto_delivery.account_number,
customer_town=get_auto_delivery.customer_town,
customer_state=get_auto_delivery.customer_state,
customer_address=get_auto_delivery.customer_address,
customer_zip=get_auto_delivery.customer_zip,
customer_full_name=get_auto_delivery.customer_full_name,
oil_prices_id=get_todays_price.id,
gallons_delivered=gallons_delivered,
price_per_gallon=get_todays_price.price_for_customer,
total_amount_customer=total_amount,
fill_date=date.today(),
payment_type=payment_type,
payment_card_id=payment_card_id,
payment_status=payment_status,
)
session.add(create_new_ticket)
session.commit() # Commit all changes in one transaction
return ({
"ok": True,
"auto_ticket_id":create_new_ticket.id
}), 200
session.commit()
return ({"ok": True, "auto_ticket_id":create_new_ticket.id}), 200

View File

@@ -1,8 +1,7 @@
from fastapi import APIRouter, Request, Depends
from fastapi import APIRouter
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
from database import session, get_db
from sqlalchemy.orm import Session
from database import session
from app.models.auto import Auto_Delivery, Tickets_Auto_Delivery
from app.models.delivery import Delivery
@@ -113,6 +112,6 @@ def update_auto_status(auto_id: int):
if update_status:
update_status.auto_status = 3
db.commit()
session.commit()
return {"message": "Auto status updated to 3"}
return {"error": "Auto delivery not found"}

View File

@@ -1,13 +1,8 @@
from fastapi import APIRouter, Request
from datetime import datetime, date
from fastapi import APIRouter, HTTPException
from database import session
from pyowm import OWM
from app.models.auto import Auto_Delivery, Auto_Temp, Auto_Update
from app.models.delivery import Delivery
from app.script.fuel_estimator import FuelEstimator
from app.script.temp_getter import fetch_and_store_daily_temp
router = APIRouter(
prefix="/main",
@@ -15,150 +10,40 @@ router = APIRouter(
responses={404: {"description": "Not found"}},
)
def Average(lst):
return sum(lst) / len(lst)
@router.get("/temp", status_code=200)
def update_temp_manually():
"""
Manually triggers the fetch and storage of today's temperature.
This is useful for testing or for manual intervention if the cron job fails.
"""
try:
success = fetch_and_store_daily_temp()
if success:
session.commit()
return {"ok": True, "message": "Temperature updated or already exists."}
else:
# The function already rolled back, so just return an error
return HTTPException(status_code=500, detail="Failed to fetch temperature from the weather API.")
except Exception as e:
session.rollback()
raise HTTPException(status_code=500, detail=f"An unexpected server error occurred: {str(e)}")
@router.get("/update", status_code=200)
def update_auto_customers():
def update_all_customer_fuel_levels():
"""
This endpoint triggers the daily update for all customers.
It should be called once per day by a cron job or scheduler.
"""
try:
see_if_autos_updated = (session.query(Auto_Update)
.filter(Auto_Update.last_updated == date.today())
.first()
)
except:
estimator = FuelEstimator()
result = estimator.run_daily_update()
return result
except Exception as e:
session.rollback()
see_if_autos_updated = None
if see_if_autos_updated is not None:
return ({"ok": True}), 200
else:
create_new_update = Auto_Update(
last_updated = date.today()
)
today_temp = (session
.query(Auto_Temp)
.order_by(Auto_Temp.id.desc())
.first())
# get all automatic customers
auto_customers = (session
.query(Auto_Delivery)
.filter(Auto_Delivery.last_fill != None)
.order_by(Auto_Delivery.last_updated.desc())
.limit(25))
for f in auto_customers:
# figure out days since last fill
d1 = date.today()
d0 = f.last_fill
delta = d1 - d0
f.days_since_last_fill = delta.days
# figure out how much temperature effects oil
today_temptemp_avg = int(today_temp.temp_avg)
if today_temptemp_avg >= 65.01:
use_day = 1
elif 50.01 <= today_temptemp_avg <= 65:
use_day = 2
elif 35.01 <= today_temptemp_avg <= 50:
use_day = 3
elif 30.01 <= today_temptemp_avg <= 35:
use_day = 4
elif 25.01 <= today_temptemp_avg <= 30:
use_day = 5
elif 20.01 <= today_temptemp_avg <= 25:
use_day = 7
elif 15.01 <= today_temptemp_avg <= 20:
use_day = 8
elif 10.01 <= today_temptemp_avg <= 15:
use_day = 9
elif 5.01 <= today_temptemp_avg <= 10:
use_day = 10
elif 0.01 <= today_temptemp_avg <= 5:
use_day = 12
elif -20 <= today_temptemp_avg <= -1:
use_day = 15
else:
use_day = 0
# times temp factory by house factor
gallon_use_today = f.house_factor * use_day
# Log the exception e
return {"ok": False, "message": "An internal error occurred."}
# get previous day gallons left
f.estimated_gallons_left_prev_day = f.estimated_gallons_left
# get estimated gallons left
get_gallons_left = f.estimated_gallons_left_prev_day - gallon_use_today
f.estimated_gallons_left = get_gallons_left
f.last_updated = date.today()
session.add(create_new_update)
session.add(f)
session.commit()
return ({"ok": True}), 200
@router.get("/temp", status_code=200)
def update_temp():
try:
see_if_temp_exists = (session.query(Auto_Temp)
.filter(Auto_Temp.todays_date == date.today())
.first())
except:
see_if_temp_exists = None
if see_if_temp_exists is not None:
return ({"ok": True}), 200
else:
try:
temps = []
owm = OWM('21648d8c8d1a4ae495ace0b7810b4d36')
mgr = owm.weather_manager()
# Search for current weather in London (Great Britain) and get details
observation = mgr.weather_at_place('Worcester, US')
w = observation.weather
temp_dict_fahrenheit = w.temperature() # a dict in Kelvin units (default when no temperature units provided)
temp_dict_fahrenheit['temp_min']
temp_dict_fahrenheit['temp_max']
temp_dict_fahrenheit = w.temperature('fahrenheit')
low_temp = temp_dict_fahrenheit['temp_min']
high_temp = temp_dict_fahrenheit['temp_max']
temps.append(temp_dict_fahrenheit['temp_max'])
temps.append(temp_dict_fahrenheit['temp_min'])
get_avg = Average(temps)
rounded_temp = round(get_avg)
dday = (65 - ((low_temp + high_temp) /2))
add_new_temp = Auto_Temp(
temp = temp_dict_fahrenheit['temp'],
temp_max = temp_dict_fahrenheit['temp_max'],
temp_min = temp_dict_fahrenheit['temp_min'],
temp_avg = rounded_temp,
degree_day = dday,
todays_date = date.today()
)
session.add(add_new_temp)
session.commit()
return ({"ok": True}), 200
except:
return ({"ok": True}), 200