tons fixes

This commit is contained in:
2025-08-25 17:59:00 -04:00
parent c526284d98
commit 652947b30a
3 changed files with 129 additions and 84 deletions

View File

@@ -18,30 +18,46 @@ class Service_Service(db.Model):
customer_town = db.Column(db.VARCHAR(140))
customer_state = db.Column(db.VARCHAR(140))
customer_zip = db.Column(db.VARCHAR(10))
# tune-up = 0
# no heat = 1
# fix = 2
# tank = 3
# other = 4
type_service_call = db.Column(db.INTEGER)
when_ordered = db.Column(db.DATETIME())
scheduled_date = db.Column(db.DATETIME())
description = db.Column(db.TEXT())
class Service_Service_schema(ma.SQLAlchemyAutoSchema):
class Meta:
model = Service_Service
scheduled_date = ma.DateTime(format='%Y-%m-%dT%H:%M:%S')
when_ordered = ma.DateTime(format='%Y-%m-%dT%H:%M:%S')
class Service_Parts(db.Model):
__tablename__ = 'service_parts'
__table_args__ = {"schema": "public"}
id = db.Column(db.Integer,
primary_key=True,
autoincrement=True,
unique=False)
customer_id = db.Column(db.INTEGER)
oil_filter = db.Column(db.VARCHAR(100))
oil_filter_2 = db.Column(db.VARCHAR(100))
oil_nozzle = db.Column(db.VARCHAR(10))
oil_nozzle_2 = db.Column(db.VARCHAR(10))
class Service_Parts_schema(ma.SQLAlchemyAutoSchema):
class Meta:
model = Service_Parts
scheduled_date = ma.DateTime(format='%Y-%m-%dT%H:%M:%S')
when_ordered = ma.DateTime(format='%Y-%m-%dT%H:%M:%S')

View File

@@ -1,10 +1,40 @@
from flask import jsonify
from decimal import Decimal
from app.info import info
from app import db
from app.classes.pricing import Pricing_Oil_Oil, Pricing_Oil_Oil_schema
from app.classes.admin import Admin_Company
@info.route("/price/oil/tiers", methods=["GET"])
def get_pricing_tiers():
get_price_query = (db.session
.query(Pricing_Oil_Oil)
.order_by(Pricing_Oil_Oil.date.desc())
.first())
if not get_price_query:
return jsonify({"error": "No pricing data available"}), 404
# Get the single price per gallon from the database, e.g., Decimal('2.92')
price_per_gallon = get_price_query.price_for_customer
# Define the specific gallon amounts you want to display totals for
gallon_tiers = [100, 125, 150, 175, 200, 220]
# Calculate the total price for each gallon amount by multiplication
# e.g., { 100: (2.92 * 100), 125: (2.92 * 125), ... }
pricing_totals = {
gallons: price_per_gallon * gallons
for gallons in gallon_tiers
}
# Return the dictionary of totals
# e.g., { "100": "292.00", "125": "365.00", ... }
return jsonify(pricing_totals)
@info.route("/price/oil", methods=["GET"])
def get_oil_price_today():
get_price_query = (db.session

View File

@@ -4,109 +4,108 @@ from app import db
from datetime import datetime, date
from app.classes.customer import (Customer_Customer)
from app.classes.service import (Service_Service,
Service_Service_schema
Service_Service_schema, Service_Parts, Service_Parts_schema
)
# --- NEW ENDPOINT TO GET ALL SERVICE CALLS FOR THE MASTER CALENDAR ---
@service.route("/all", methods=["GET"])
def get_all_service_calls():
"""
Fetches ALL service calls from the database and formats them for FullCalendar.
"""
# 1. Query all service records, without filtering by customer
all_services = Service_Service.query.all()
# 2. Reuse the same formatting logic (colors, titles, etc.)
color_map = {
0: {"backgroundColor": "blue", "textColor": "white"},
1: {"backgroundColor": "red", "textColor": "white"},
2: {"backgroundColor": "green", "textColor": "white"},
3: {"backgroundColor": "yellow", "textColor": "black"},
0: {"backgroundColor": "blue", "textColor": "white"}, 1: {"backgroundColor": "red", "textColor": "white"},
2: {"backgroundColor": "green", "textColor": "white"}, 3: {"backgroundColor": "yellow", "textColor": "black"},
4: {"backgroundColor": "black", "textColor": "white"}
}
service_type_map = {0: 'Tune-up', 1: 'No Heat', 2: 'Fix', 3: 'Tank Install', 4: 'Other'}
calendar_events = []
for service_record in all_services:
service_type_text = service_type_map.get(service_record.type_service_call, 'Service')
# The title now includes the customer name, which is crucial for a master calendar
event_title = f"{service_type_text}: {service_record.customer_name}"
event_colors = color_map.get(service_record.type_service_call, {"backgroundColor": "gray", "textColor": "white"})
# Use the schema to correctly format the date to a string
serialized_record = Service_Service_schema().dump(service_record)
event_data = {
"id": service_record.id,
"title": event_title,
"start": serialized_record.get('scheduled_date'), # Use the reliable formatted date
"end": None,
"id": service_record.id, "title": event_title, "start": serialized_record.get('scheduled_date'),
"end": None, "customer_id": service_record.customer_id,
"extendedProps": {
"description": service_record.description,
"type_service_call": service_record.type_service_call,
},
"backgroundColor": event_colors.get("backgroundColor"),
"textColor": event_colors.get("textColor"),
"backgroundColor": event_colors.get("backgroundColor"), "textColor": event_colors.get("textColor"),
"borderColor": event_colors.get("backgroundColor")
}
calendar_events.append(event_data)
return jsonify(calendar_events), 200
# --- YOUR OTHER EXISTING ROUTES (no changes needed below) ---
# --- THIS IS THE FIX ---
# The logic from /all has been copied here to ensure a consistent data structure.
@service.route("/upcoming", methods=["GET"])
def get_upcoming_service_calls():
# ... (no changes)
"""
Fetches a list of all future service calls from today onwards.
"""
now = datetime.now()
upcoming_services = (Service_Service.query.filter(Service_Service.scheduled_date >= now).order_by(Service_Service.scheduled_date.asc()).limit(100).all())
upcoming_services = (
Service_Service.query
.filter(Service_Service.scheduled_date >= now)
.order_by(Service_Service.scheduled_date.asc())
.limit(100)
.all()
)
service_schema = Service_Service_schema(many=True)
result = service_schema.dump(upcoming_services)
return jsonify(result), 200
@service.route("/upcoming/count", methods=["GET"])
def get_upcoming_service_calls_count():
now = datetime.now()
try:
count = (db.session.query(Service_Service).filter(Service_Service.scheduled_date >= now).count())
return jsonify({"count": count}), 200
except Exception as e:
return jsonify({"error": str(e)}), 500
@service.route("/for-customer/<int:customer_id>", methods=["GET"])
def get_service_calls_for_customer(customer_id):
service_records = (Service_Service.query.filter_by(customer_id=customer_id).order_by(Service_Service.scheduled_date.desc()).all())
service_schema = Service_Service_schema(many=True)
result = service_schema.dump(service_records)
return jsonify(result), 200
@service.route("/create", methods=["POST"])
def create_service_call():
data = request.get_json()
if not data: return jsonify({"error": "No data provided"}), 400
cus_id=data.get('customer_id')
get_customer = (db.session.query(Customer_Customer).filter(Customer_Customer.id == cus_id).first())
if not get_customer: return jsonify({"error": f"Customer with id {cus_id} not found."}), 404
# --- FIX: Use fromisoformat to parse the FULL timestamp string (e.g., "2025-08-26T14:00:00") ---
# This correctly preserves the time sent from the frontend.
scheduled_datetime_str = data.get('expected_delivery_date')
scheduled_datetime_obj = datetime.fromisoformat(scheduled_datetime_str)
new_service_call = Service_Service(
customer_id=get_customer.id, customer_name=get_customer.customer_first_name + ' ' + get_customer.customer_last_name,
customer_address=get_customer.customer_address, customer_town=get_customer.customer_town,
customer_state=get_customer.customer_state, customer_zip=get_customer.customer_zip,
type_service_call=data.get('type_service_call'), when_ordered=datetime.utcnow(),
scheduled_date=scheduled_datetime_obj, # Save the full datetime object
description=data.get('description'),
scheduled_date=scheduled_datetime_obj, description=data.get('description'),
)
db.session.add(new_service_call)
db.session.commit()
return jsonify({ "ok": True, "id": new_service_call.id }), 201
@service.route("/update/<int:id>", methods=["PUT"])
def update_service_call(id):
service_record = Service_Service.query.get_or_404(id)
data = request.get_json()
if not data: return jsonify({"error": "No data provided"}), 400
# --- FIX: Also use fromisoformat here to correctly update with time ---
scheduled_datetime_str = data.get('scheduled_date')
if scheduled_datetime_str:
service_record.scheduled_date = datetime.fromisoformat(scheduled_datetime_str)
service_record.type_service_call = data.get('type_service_call', service_record.type_service_call)
service_record.description = data.get('description', service_record.description)
try:
db.session.commit()
service_schema = Service_Service_schema(many=False)
@@ -114,46 +113,46 @@ def update_service_call(id):
except Exception as e:
db.session.rollback()
return jsonify({"error": str(e)}), 500
@service.route("/upcoming/count", methods=["GET"])
def get_upcoming_service_calls_count():
"""
Efficiently counts the number of all future service calls from today onwards.
"""
# 1. Get the current time
now = datetime.now()
# 2. Build the query and use the database's optimized count() function
@service.route("/delete/<int:id>", methods=["DELETE"])
def delete_service_call(id):
service_record = Service_Service.query.get_or_404(id)
try:
count = (
db.session.query(Service_Service)
.filter(Service_Service.scheduled_date >= now)
.count()
)
# 3. Return the count in a simple JSON object
return jsonify({"count": count}), 200
db.session.delete(service_record)
db.session.commit()
return jsonify({"ok": True, "message": "Service deleted successfully"}), 200
except Exception as e:
# Return an error if the query fails
db.session.rollback()
return jsonify({"error": str(e)}), 500
@service.route("/parts/customer/<int:customer_id>", methods=["GET"])
def get_service_parts(customer_id):
parts = Service_Parts.query.filter_by(customer_id=customer_id).first()
if parts:
parts_schema = Service_Parts_schema()
return jsonify(parts_schema.dump(parts)), 200
else:
return jsonify({
"customer_id": customer_id, "oil_filter": "", "oil_filter_2": "",
"oil_nozzle": "", "oil_nozzle_2": ""
}), 200
@service.route("/for-customer/<int:customer_id>", methods=["GET"])
def get_service_calls_for_customer(customer_id):
"""
Fetches all service calls for a specific customer, ordered by most recent first.
"""
# Query the database, filtering by customer_id and ordering by date
service_records = (
Service_Service.query
.filter_by(customer_id=customer_id)
.order_by(Service_Service.scheduled_date.desc()) # .desc() for newest first
.all()
)
# Use the schema to convert the list of objects to JSON
service_schema = Service_Service_schema(many=True)
result = service_schema.dump(service_records)
return jsonify(result), 200
@service.route("/parts/update/<int:customer_id>", methods=["POST"])
def update_service_parts(customer_id):
data = request.get_json()
if not data:
return jsonify({"error": "No data provided"}), 400
parts = Service_Parts.query.filter_by(customer_id=customer_id).first()
if not parts:
parts = Service_Parts(customer_id=customer_id)
db.session.add(parts)
parts.oil_filter = data.get('oil_filter', parts.oil_filter)
parts.oil_filter_2 = data.get('oil_filter_2', parts.oil_filter_2)
parts.oil_nozzle = data.get('oil_nozzle', parts.oil_nozzle)
parts.oil_nozzle_2 = data.get('oil_nozzle_2', parts.oil_nozzle_2)
try:
db.session.commit()
return jsonify({"ok": True, "message": "Service parts updated successfully"}), 200
except Exception as e:
db.session.rollback()
return jsonify({"error": str(e)}), 500