major claude changes
This commit is contained in:
@@ -1,20 +1,56 @@
|
||||
# coding=utf-8
|
||||
import logging
|
||||
import sys
|
||||
from flask import Flask, jsonify
|
||||
from flask_bcrypt import Bcrypt
|
||||
from flask_cors import CORS
|
||||
from flask_marshmallow import Marshmallow
|
||||
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_migrate import Migrate
|
||||
from flask_session import Session
|
||||
from flask_login import LoginManager
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from werkzeug.routing import BaseConverter
|
||||
from flask_mail import Mail
|
||||
from config import load_config
|
||||
import re
|
||||
import re
|
||||
from sqlalchemy import text
|
||||
|
||||
ApplicationConfig = load_config()
|
||||
|
||||
# Configure logging
|
||||
def setup_logging():
|
||||
"""Configure structured logging for the application."""
|
||||
log_level = logging.DEBUG if ApplicationConfig.CURRENT_SETTINGS != 'PRODUCTION' else logging.INFO
|
||||
|
||||
# Create formatter
|
||||
formatter = logging.Formatter(
|
||||
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
# Configure root logger
|
||||
root_logger = logging.getLogger()
|
||||
root_logger.setLevel(log_level)
|
||||
|
||||
# Remove existing handlers to avoid duplicates
|
||||
root_logger.handlers.clear()
|
||||
|
||||
# Console handler
|
||||
console_handler = logging.StreamHandler(sys.stdout)
|
||||
console_handler.setLevel(log_level)
|
||||
console_handler.setFormatter(formatter)
|
||||
root_logger.addHandler(console_handler)
|
||||
|
||||
# Reduce noise from third-party libraries
|
||||
logging.getLogger('werkzeug').setLevel(logging.WARNING)
|
||||
logging.getLogger('sqlalchemy.engine').setLevel(logging.WARNING)
|
||||
|
||||
return logging.getLogger('eamco_office_api')
|
||||
|
||||
logger = setup_logging()
|
||||
|
||||
app = Flask(__name__,
|
||||
static_url_path='',
|
||||
static_folder='static',
|
||||
@@ -55,6 +91,7 @@ app.config['SECRET_KEY'] = ApplicationConfig.SECRET_KEY
|
||||
|
||||
session.configure(bind=ApplicationConfig.SQLALCHEMY_DATABASE_URI)
|
||||
db = SQLAlchemy(app)
|
||||
migrate = Migrate(app, db)
|
||||
bcrypt = Bcrypt(app)
|
||||
app.config['SESSION_SQLALCHEMY'] = db
|
||||
server_session = Session(app)
|
||||
@@ -93,15 +130,8 @@ def load_user_from_request(request):
|
||||
# If no valid key is found in header or args, return None
|
||||
return None
|
||||
|
||||
# api_main = {
|
||||
# "origins": [ApplicationConfig.ORIGIN_URL],
|
||||
# "methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"],
|
||||
# "allow_headers": ['Authorization', 'application/json', 'authorization', 'Content-Type',
|
||||
# 'Access-Control-Allow-Headers', 'Origin,Accept',
|
||||
# 'X-Requested-With', 'Content-Type', 'Access-Control-Request-cMethod',
|
||||
# 'Access-Control-Request-Headers']
|
||||
# }
|
||||
cors = CORS(app,
|
||||
|
||||
cors = CORS(app,
|
||||
supports_credentials=True,
|
||||
resources={r"/*": {"origins": ApplicationConfig.CORS_ALLOWED_ORIGINS}
|
||||
})
|
||||
@@ -217,8 +247,32 @@ from .service import service as service_blueprint
|
||||
app.register_blueprint(service_blueprint, url_prefix='/service')
|
||||
|
||||
|
||||
def check_db_connection():
|
||||
"""
|
||||
Test database connectivity.
|
||||
"""
|
||||
try:
|
||||
db.session.execute(text("SELECT 1"))
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
with app.app_context():
|
||||
|
||||
db.configure_mappers()
|
||||
db.create_all()
|
||||
db.session.commit()
|
||||
|
||||
# Startup logging
|
||||
logger.info("🚀 eamco_office_api STARTING")
|
||||
mode = ApplicationConfig.CURRENT_SETTINGS.upper()
|
||||
if mode in ['DEVELOPMENT', 'DEV']:
|
||||
logger.info("🤖🤖🤖🤖🤖 Mode: Development 🤖🤖🤖🤖🤖")
|
||||
elif mode in ['PRODUCTION', 'PROD']:
|
||||
logger.info("💀💀💀💀💀💀💀💀💀💀 ⚠️ WARNING PRODUCTION 💀💀💀💀💀💀💀💀💀💀")
|
||||
logger.info(f"DB: {ApplicationConfig.SQLALCHEMY_DATABASE_URI[:30]}...")
|
||||
logger.info(f"CORS: {len(ApplicationConfig.CORS_ALLOWED_ORIGINS)} origins configured")
|
||||
|
||||
# Test database connection
|
||||
if check_db_connection():
|
||||
logger.info("DB Connection: ✅ OK")
|
||||
else:
|
||||
logger.info("DB Connection: ❌ FAILED")
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from flask import request, jsonify
|
||||
from flask_login import current_user, logout_user, login_user, login_required
|
||||
from app.admin import admin
|
||||
@@ -7,12 +8,17 @@ from app.classes.pricing import (
|
||||
Pricing_Oil_Oil,
|
||||
Pricing_Oil_Oil_schema)
|
||||
from app.classes.admin import Admin_Company, Admin_Company_schema, Call
|
||||
from app.common.decorators import admin_required
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@admin.route("/oil/create", methods=["POST"])
|
||||
@admin_required
|
||||
def create_oil_price():
|
||||
"""
|
||||
Changes the price for oil deliveries
|
||||
"""
|
||||
logger.info("POST /admin/oil/create - Creating new oil price")
|
||||
now = datetime.utcnow()
|
||||
price_from_supplier = request.json["price_from_supplier"]
|
||||
price_for_customer = request.json["price_for_customer"]
|
||||
@@ -50,10 +56,12 @@ def create_oil_price():
|
||||
|
||||
|
||||
@admin.route("/oil/get", methods=["GET"])
|
||||
@admin_required
|
||||
def get_oil_price():
|
||||
"""
|
||||
gets oil prices
|
||||
"""
|
||||
logger.info("GET /admin/oil/get - Fetching current oil prices")
|
||||
get_oil_prices = (db.session
|
||||
.query(Pricing_Oil_Oil)
|
||||
.order_by(Pricing_Oil_Oil.date.desc())
|
||||
@@ -63,7 +71,9 @@ def get_oil_price():
|
||||
|
||||
|
||||
@admin.route("/company/<int:company_id>", methods=["GET"])
|
||||
@admin_required
|
||||
def get_company(company_id):
|
||||
logger.info(f"GET /admin/company/{company_id} - Fetching company data")
|
||||
get_data_company = (db.session
|
||||
.query(Admin_Company)
|
||||
.first())
|
||||
@@ -72,11 +82,12 @@ def get_company(company_id):
|
||||
return jsonify(company_schema.dump(get_data_company))
|
||||
|
||||
@admin.route("/voip_routing", methods=["GET"])
|
||||
|
||||
@admin_required
|
||||
def get_voip_routing():
|
||||
"""
|
||||
Gets the current VOIP routing (latest Call record's current_phone)
|
||||
"""
|
||||
logger.info("GET /admin/voip_routing - Fetching current VoIP routing")
|
||||
latest_call = (db.session
|
||||
.query(Call)
|
||||
.order_by(Call.created_at.desc())
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from flask import request, jsonify
|
||||
from flask_login import current_user, logout_user, login_required
|
||||
from app.auth import auth
|
||||
@@ -5,9 +6,12 @@ from app import db, bcrypt
|
||||
from datetime import datetime
|
||||
from uuid import uuid4
|
||||
from app.classes.auth import Auth_User
|
||||
from app.classes.employee import Employee_Employee
|
||||
from app.classes.employee import Employee_Employee
|
||||
from app.schemas import LoginSchema, RegisterSchema, ChangePasswordSchema, validate_request
|
||||
import re
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@auth.route("/whoami", methods=["GET"])
|
||||
def check_session():
|
||||
"""
|
||||
@@ -25,7 +29,7 @@ def check_session():
|
||||
user = db.session.query(Auth_User).filter(Auth_User.api_key == api_key).first()
|
||||
|
||||
if not user:
|
||||
print("no user found with that api key")
|
||||
logger.warning("Authentication failed: no user found with provided API key")
|
||||
return jsonify({"ok": False, "error": "Invalid token"}), 401
|
||||
|
||||
# Now, build the complete response with both user and employee data.
|
||||
@@ -73,9 +77,11 @@ def logout():
|
||||
|
||||
|
||||
@auth.route("/login", methods=["POST"])
|
||||
@validate_request(LoginSchema)
|
||||
def login():
|
||||
username = request.json["username"]
|
||||
password = request.json["password"]
|
||||
data = request.validated_data
|
||||
username = data["username"]
|
||||
password = data["password"]
|
||||
|
||||
user = db.session.query(Auth_User).filter_by(username=username).first()
|
||||
|
||||
@@ -103,15 +109,17 @@ def login():
|
||||
}), 200
|
||||
|
||||
@auth.route("/register", methods=["POST"])
|
||||
@validate_request(RegisterSchema)
|
||||
def register_user():
|
||||
"""
|
||||
Main post function to register a user
|
||||
"""
|
||||
data = request.validated_data
|
||||
now = datetime.utcnow()
|
||||
|
||||
username = request.json["username"]
|
||||
email = request.json["email"]
|
||||
password = request.json["password"]
|
||||
username = data["username"]
|
||||
email = data["email"]
|
||||
password = data["password"]
|
||||
|
||||
part_one_code = uuid4().hex
|
||||
part_two_code = uuid4().hex
|
||||
@@ -172,6 +180,7 @@ def register_user():
|
||||
|
||||
|
||||
@auth.route('/change-password', methods=['POST'])
|
||||
@validate_request(ChangePasswordSchema)
|
||||
def change_password():
|
||||
auth_header = request.headers.get('Authorization')
|
||||
if not auth_header:
|
||||
@@ -184,8 +193,9 @@ def change_password():
|
||||
if not user:
|
||||
return jsonify({"error": "Invalid token"}), 401
|
||||
|
||||
new_password = request.json["new_password"]
|
||||
new_password_confirm = request.json["password_confirm"]
|
||||
data = request.validated_data
|
||||
new_password = data["new_password"]
|
||||
new_password_confirm = data["password_confirm"]
|
||||
|
||||
if str(new_password) != str(new_password_confirm):
|
||||
return jsonify({"error": "Error: Incorrect Passwords"}), 200
|
||||
@@ -214,7 +224,7 @@ def admin_change_password():
|
||||
if not user:
|
||||
return jsonify({"error": "Invalid token"}), 401
|
||||
|
||||
if user.admin_role != 0:
|
||||
if user.admin_role == 0:
|
||||
return jsonify({"error": "Admin access required"}), 403
|
||||
|
||||
employee_id = request.json.get("employee_id")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from flask_login import current_user
|
||||
from flask import abort
|
||||
from flask import abort, jsonify
|
||||
|
||||
from functools import wraps
|
||||
|
||||
@@ -14,3 +14,12 @@ def login_required(f):
|
||||
return f(*args, **kwargs)
|
||||
|
||||
return decorated_function
|
||||
|
||||
|
||||
def admin_required(f):
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if not current_user.is_authenticated or not current_user.admin_role:
|
||||
return jsonify({"error": "Admin access required"}), 403
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
46
app/constants.py
Normal file
46
app/constants.py
Normal file
@@ -0,0 +1,46 @@
|
||||
"""
|
||||
EAMCO Office API Constants
|
||||
|
||||
This file contains all status code constants used throughout the application
|
||||
to eliminate magic numbers and improve code maintainability.
|
||||
"""
|
||||
|
||||
class DeliveryStatus:
|
||||
"""Delivery status codes"""
|
||||
WAITING = 0
|
||||
CANCELLED = 1
|
||||
OUT_FOR_DELIVERY = 2
|
||||
TOMORROW = 3
|
||||
PARTIAL_DELIVERY = 4
|
||||
ISSUE = 5
|
||||
UNKNOWN = 6
|
||||
PENDING_PAYMENT = 9
|
||||
FINALIZED = 10
|
||||
DELIVERED = 11 # New: Replaces previous use of 1 for delivered
|
||||
|
||||
class PaymentStatus:
|
||||
"""Payment status codes"""
|
||||
UNPAID = 0
|
||||
PRE_AUTHORIZED = 1
|
||||
PROCESSING = 2
|
||||
PAID = 3
|
||||
FAILED = 4
|
||||
|
||||
class AutoStatus:
|
||||
"""Automatic delivery status codes"""
|
||||
DEFAULT = 0
|
||||
WILL_CALL = 1
|
||||
READY_FOR_FINALIZATION = 3
|
||||
|
||||
class TransactionStatus:
|
||||
"""Transaction status codes"""
|
||||
APPROVED = 0
|
||||
DECLINED = 1
|
||||
|
||||
class CustomerAutomaticStatus:
|
||||
"""Customer automatic delivery status"""
|
||||
WILL_CALL = 0
|
||||
AUTOMATIC = 1
|
||||
|
||||
# Additional constants can be added here as needed
|
||||
# For example: ServiceStatus, UserRoles, etc.
|
||||
@@ -1,8 +1,12 @@
|
||||
import logging
|
||||
from flask import request, jsonify
|
||||
from flask_login import login_required
|
||||
from geopy.geocoders import Nominatim
|
||||
from app.customer import customer
|
||||
from app import db
|
||||
from app.common.decorators import login_required as common_login_required
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
from datetime import datetime
|
||||
from app.classes.cards import Card_Card
|
||||
from app.classes.customer import \
|
||||
@@ -16,6 +20,7 @@ from app.classes.service import Service_Parts
|
||||
from app.classes.admin import Admin_Company
|
||||
from app.classes.auto import Auto_Delivery,Auto_Delivery_schema
|
||||
from app.classes.stats_customer import Stats_Customer
|
||||
from app.schemas import CreateCustomerSchema, UpdateCustomerSchema, validate_request
|
||||
import string
|
||||
import random
|
||||
|
||||
@@ -33,8 +38,9 @@ def generate_random_number_string(length):
|
||||
|
||||
|
||||
@customer.route("/all", methods=["GET"])
|
||||
|
||||
@common_login_required
|
||||
def all_customers_around():
|
||||
logger.info("GET /customer/all - Fetching all customers")
|
||||
customer_list = db.session \
|
||||
.query(Customer_Customer) \
|
||||
.all()
|
||||
@@ -43,12 +49,12 @@ def all_customers_around():
|
||||
|
||||
|
||||
@customer.route("/all/<int:page>", methods=["GET"])
|
||||
|
||||
@common_login_required
|
||||
def all_customers(page):
|
||||
"""
|
||||
pagination all customers
|
||||
"""
|
||||
|
||||
logger.info(f"GET /customer/all/{page} - Fetching customers page {page}")
|
||||
per_page_amount = 100
|
||||
if page is None:
|
||||
offset_limit = 0
|
||||
@@ -67,9 +73,11 @@ def all_customers(page):
|
||||
|
||||
|
||||
@customer.route("/<int:customer_id>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_a_customer(customer_id):
|
||||
"""
|
||||
"""
|
||||
logger.info(f"GET /customer/{customer_id} - Fetching customer")
|
||||
get_customer = (db.session
|
||||
.query(Customer_Customer)
|
||||
.filter(Customer_Customer.id == customer_id)
|
||||
@@ -79,10 +87,12 @@ def get_a_customer(customer_id):
|
||||
|
||||
|
||||
@customer.route("/description/<int:customer_id>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_a_customer_description(customer_id):
|
||||
"""
|
||||
|
||||
|
||||
"""
|
||||
logger.info(f"GET /customer/description/{customer_id} - Fetching customer description")
|
||||
get_customer_description = (db.session
|
||||
.query(Customer_Description)
|
||||
.filter(Customer_Description.customer_id == customer_id)
|
||||
@@ -112,10 +122,12 @@ def get_a_customer_description(customer_id):
|
||||
|
||||
|
||||
@customer.route("/tank/<int:customer_id>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_a_customer_tank(customer_id):
|
||||
"""
|
||||
|
||||
|
||||
"""
|
||||
logger.info(f"GET /customer/tank/{customer_id} - Fetching customer tank info")
|
||||
get_customer_tank = (db.session
|
||||
.query(Customer_Tank_Inspection)
|
||||
.filter(Customer_Tank_Inspection.customer_id == customer_id)
|
||||
@@ -142,56 +154,50 @@ def get_a_customer_tank(customer_id):
|
||||
|
||||
|
||||
@customer.route("/create", methods=["POST"])
|
||||
|
||||
@validate_request(CreateCustomerSchema)
|
||||
@common_login_required
|
||||
def create_customer():
|
||||
"""
|
||||
Create a new customer with validated input data.
|
||||
"""
|
||||
logger.info("POST /customer/create - Creating new customer")
|
||||
# Get validated data from request
|
||||
data = request.validated_data
|
||||
|
||||
now = datetime.utcnow()
|
||||
get_company = (db.session
|
||||
.query(Admin_Company)
|
||||
.filter(Admin_Company.id == 1)
|
||||
.first())
|
||||
|
||||
get_company = (db.session
|
||||
.query(Admin_Company)
|
||||
.filter(Admin_Company.id == 1)
|
||||
.first())
|
||||
|
||||
|
||||
random_string = generate_random_number_string(6)
|
||||
|
||||
|
||||
made_account_number = str(get_company.account_prefix) + '-' + str(random_string)
|
||||
see_if_exists = (db.session.query(Customer_Customer).filter(Customer_Customer.account_number == made_account_number).first())
|
||||
|
||||
if see_if_exists is not None:
|
||||
|
||||
random_string = generate_random_number_string(10)
|
||||
|
||||
made_account_number = str(get_company.account_prefix) + '-' + str(random_string)
|
||||
see_if_exists = (db.session.query(Customer_Customer).filter(Customer_Customer.account_number == made_account_number).first())
|
||||
|
||||
if see_if_exists is not None:
|
||||
|
||||
random_string = generate_random_number_string(10)
|
||||
|
||||
made_account_number = str(get_company.account_prefix) + '-' + str(random_string)
|
||||
see_if_exists = (db.session.query(Customer_Customer).filter(Customer_Customer.account_number == made_account_number).first())
|
||||
|
||||
response_customer_last_name = request.json["customer_last_name"]
|
||||
response_customer_first_name = request.json["customer_first_name"]
|
||||
response_customer_town = request.json["customer_town"]
|
||||
response_customer_state = request.json["customer_state"]
|
||||
response_customer_zip = request.json["customer_zip"]
|
||||
response_customer_email = request.json["customer_email"]
|
||||
response_customer_home_type = request.json["customer_home_type"]
|
||||
customer_phone_number = request.json["customer_phone_number"]
|
||||
customer_address = request.json["customer_address"]
|
||||
customer_apt = request.json["customer_apt"]
|
||||
customer_description_msg = request.json["customer_description"]
|
||||
|
||||
# Use validated data instead of direct request.json access
|
||||
response_customer_last_name = data["customer_last_name"]
|
||||
response_customer_first_name = data["customer_first_name"]
|
||||
response_customer_town = data["customer_town"]
|
||||
response_customer_state = data["customer_state"]
|
||||
response_customer_zip = str(data["customer_zip"])
|
||||
response_customer_email = data.get("customer_email")
|
||||
response_customer_home_type = data["customer_home_type"]
|
||||
customer_phone_number = data.get("customer_phone_number")
|
||||
customer_address = data["customer_address"]
|
||||
customer_apt = data.get("customer_apt")
|
||||
customer_description_msg = data.get("customer_description")
|
||||
|
||||
int_customer_home_type = int(response_customer_home_type)
|
||||
response_customer_zip = str(response_customer_zip)
|
||||
response_customer_state = int(response_customer_state)
|
||||
|
||||
|
||||
@@ -204,51 +210,18 @@ def create_customer():
|
||||
else:
|
||||
the_state = 'MA'
|
||||
|
||||
# if response_customer_town == 0:
|
||||
# the_town = 'Auburn'
|
||||
# elif response_customer_town == 1:
|
||||
# the_town = 'Charlton'
|
||||
# elif response_customer_town == 2:
|
||||
# the_town = 'Cherry Valley'
|
||||
# elif response_customer_town == 3:
|
||||
# the_town = 'Dudley'
|
||||
# elif response_customer_town == 4:
|
||||
# the_town = 'Grafton'
|
||||
# elif response_customer_town == 5:
|
||||
# the_town = 'Leicester'
|
||||
# elif response_customer_town == 6:
|
||||
# the_town = 'Millbury'
|
||||
# elif response_customer_town == 7:
|
||||
# the_town = 'N Oxford'
|
||||
# elif response_customer_town == 8:
|
||||
# the_town = 'Oxford'
|
||||
# elif response_customer_town == 9:
|
||||
# the_town = 'Rochdale'
|
||||
# elif response_customer_town == 10:
|
||||
# the_town = 'Shrewsbury'
|
||||
# elif response_customer_town == 11:
|
||||
# the_town = 'Southbridge'
|
||||
# elif response_customer_town == 12:
|
||||
# the_town = 'Spencer'
|
||||
# elif response_customer_town == 13:
|
||||
# the_town = 'Sturbridge'
|
||||
# elif response_customer_town == 14:
|
||||
# the_town = 'Webster'
|
||||
# elif response_customer_town == 15:
|
||||
# the_town = 'Worcester'
|
||||
# else:
|
||||
# the_town = 'NA'
|
||||
|
||||
|
||||
|
||||
geolocator = Nominatim(user_agent="auburnoil")
|
||||
address_string = customer_address + ' ' + response_customer_town+ ' ' + the_state
|
||||
try:
|
||||
location = geolocator.geocode(address_string)
|
||||
user_lat =location.latitude
|
||||
user_lat = location.latitude
|
||||
user_long = location.longitude
|
||||
cor_ad = True
|
||||
except:
|
||||
user_lat =None
|
||||
except Exception:
|
||||
user_lat = None
|
||||
user_long = None
|
||||
cor_ad = False
|
||||
|
||||
@@ -323,70 +296,95 @@ def create_customer():
|
||||
|
||||
@customer.route("/edit/<int:customer_id>", methods=["PUT"])
|
||||
@login_required
|
||||
@validate_request(UpdateCustomerSchema)
|
||||
def edit_customer(customer_id):
|
||||
"""
|
||||
"""
|
||||
logger.info(f"PUT /customer/edit/{customer_id} - Editing customer")
|
||||
get_customer = (db.session
|
||||
.query(Customer_Customer)
|
||||
.filter(Customer_Customer.id == customer_id)
|
||||
.first())
|
||||
|
||||
if not get_customer:
|
||||
return jsonify({"error": "Customer not found"}), 404
|
||||
|
||||
get_customer_description = (db.session
|
||||
.query(Customer_Description)
|
||||
.filter(Customer_Description.customer_id == customer_id)
|
||||
.first())
|
||||
response_customer_last_name = request.json["customer_last_name"]
|
||||
response_customer_first_name = request.json["customer_first_name"]
|
||||
response_customer_town = request.json["customer_town"]
|
||||
response_customer_state = request.json["customer_state"]
|
||||
response_customer_zip = request.json["customer_zip"]
|
||||
response_customer_phone_number = request.json["customer_phone_number"]
|
||||
response_customer_email = request.json["customer_email"]
|
||||
response_customer_home_type = request.json["customer_home_type"]
|
||||
response_customer_address = request.json["customer_address"]
|
||||
response_customer_apt = request.json["customer_apt"]
|
||||
response_customer_description = request.json["customer_description"]
|
||||
|
||||
response_customer_fill_location = request.json["customer_fill_location"]
|
||||
data = request.validated_data
|
||||
response_customer_last_name = data.get("customer_last_name")
|
||||
response_customer_first_name = data.get("customer_first_name")
|
||||
response_customer_town = data.get("customer_town")
|
||||
response_customer_state = data.get("customer_state")
|
||||
response_customer_zip = data.get("customer_zip")
|
||||
response_customer_phone_number = data.get("customer_phone_number")
|
||||
response_customer_email = data.get("customer_email")
|
||||
response_customer_home_type = data.get("customer_home_type")
|
||||
response_customer_address = data.get("customer_address")
|
||||
response_customer_apt = data.get("customer_apt")
|
||||
response_customer_description = data.get("customer_description")
|
||||
response_customer_fill_location = data.get("customer_fill_location")
|
||||
|
||||
|
||||
# Update description if provided
|
||||
if get_customer_description is not None:
|
||||
get_customer_description.description = response_customer_description
|
||||
get_customer_description.fill_location = response_customer_fill_location
|
||||
if response_customer_description is not None:
|
||||
get_customer_description.description = response_customer_description
|
||||
if response_customer_fill_location is not None:
|
||||
get_customer_description.fill_location = response_customer_fill_location
|
||||
db.session.add(get_customer_description)
|
||||
|
||||
if response_customer_state == 0:
|
||||
the_state = 'MA'
|
||||
elif response_customer_state == 1:
|
||||
the_state = 'RI'
|
||||
elif response_customer_state == 1:
|
||||
the_state = 'NH'
|
||||
else:
|
||||
the_state = 'MA'
|
||||
# Only update fields that were provided in the request
|
||||
if response_customer_last_name is not None:
|
||||
get_customer.customer_last_name = response_customer_last_name
|
||||
if response_customer_first_name is not None:
|
||||
get_customer.customer_first_name = response_customer_first_name
|
||||
if response_customer_town is not None:
|
||||
get_customer.customer_town = response_customer_town
|
||||
if response_customer_state is not None:
|
||||
get_customer.customer_state = response_customer_state
|
||||
if response_customer_zip is not None:
|
||||
get_customer.customer_zip = response_customer_zip
|
||||
if response_customer_phone_number is not None:
|
||||
get_customer.customer_phone_number = response_customer_phone_number
|
||||
if response_customer_email is not None:
|
||||
get_customer.customer_email = response_customer_email
|
||||
if response_customer_home_type is not None:
|
||||
get_customer.customer_home_type = response_customer_home_type
|
||||
if response_customer_apt is not None:
|
||||
get_customer.customer_apt = response_customer_apt
|
||||
|
||||
geolocator = Nominatim(user_agent="auburnoil")
|
||||
address_string = response_customer_address + ' ' + response_customer_town+ ' ' + the_state
|
||||
try:
|
||||
location = geolocator.geocode(address_string, timeout=10)
|
||||
get_customer.customer_latitude = location.latitude
|
||||
get_customer.customer_longitude = location.longitude
|
||||
cor_ad = True
|
||||
except:
|
||||
get_customer.customer_latitude = None
|
||||
get_customer.customer_longitude = None
|
||||
cor_ad = False
|
||||
|
||||
# Re-geocode if address fields changed
|
||||
if response_customer_address is not None or response_customer_town is not None or response_customer_state is not None:
|
||||
get_customer.customer_address = response_customer_address if response_customer_address is not None else get_customer.customer_address
|
||||
|
||||
get_customer.customer_address = response_customer_address
|
||||
get_customer.customer_home_type = response_customer_home_type
|
||||
get_customer.customer_phone_number = response_customer_phone_number
|
||||
get_customer.customer_last_name = response_customer_last_name
|
||||
get_customer.customer_first_name = response_customer_first_name
|
||||
get_customer.customer_town = response_customer_town
|
||||
get_customer.customer_state = response_customer_state
|
||||
get_customer.customer_zip = response_customer_zip
|
||||
get_customer.customer_email = response_customer_email
|
||||
get_customer.customer_apt = response_customer_apt
|
||||
get_customer.correct_address = cor_ad
|
||||
state_code = response_customer_state if response_customer_state is not None else get_customer.customer_state
|
||||
if state_code == 0:
|
||||
the_state = 'MA'
|
||||
elif state_code == 1:
|
||||
the_state = 'RI'
|
||||
elif state_code == 2:
|
||||
the_state = 'NH'
|
||||
else:
|
||||
the_state = 'MA'
|
||||
|
||||
town = response_customer_town if response_customer_town is not None else get_customer.customer_town
|
||||
address = get_customer.customer_address
|
||||
|
||||
geolocator = Nominatim(user_agent="auburnoil")
|
||||
address_string = address + ' ' + town + ' ' + the_state
|
||||
try:
|
||||
location = geolocator.geocode(address_string, timeout=10)
|
||||
get_customer.customer_latitude = location.latitude
|
||||
get_customer.customer_longitude = location.longitude
|
||||
get_customer.correct_address = True
|
||||
except Exception:
|
||||
get_customer.customer_latitude = None
|
||||
get_customer.customer_longitude = None
|
||||
get_customer.correct_address = False
|
||||
|
||||
|
||||
db.session.add(get_customer)
|
||||
@@ -407,6 +405,7 @@ def edit_customer(customer_id):
|
||||
def delete_customer(customer_id):
|
||||
"""
|
||||
"""
|
||||
logger.info(f"DELETE /customer/delete/{customer_id} - Deleting customer")
|
||||
get_customer = (db.session
|
||||
.query(Customer_Customer)
|
||||
.filter(Customer_Customer.id == customer_id)
|
||||
@@ -436,6 +435,7 @@ def delete_customer(customer_id):
|
||||
def customer_count():
|
||||
"""
|
||||
"""
|
||||
logger.info("GET /customer/count - Getting customer count")
|
||||
get_customer = (db.session
|
||||
.query(Customer_Customer)
|
||||
.count())
|
||||
@@ -451,6 +451,7 @@ def customer_count():
|
||||
def customer_automatic_status(customer_id):
|
||||
"""
|
||||
"""
|
||||
logger.info(f"GET /customer/automatic/status/{customer_id} - Checking auto delivery status")
|
||||
get_customer = (db.session
|
||||
.query(Customer_Customer)
|
||||
.filter(Customer_Customer.id == customer_id)
|
||||
@@ -475,7 +476,7 @@ def get_all_automatic_deliveries():
|
||||
"""
|
||||
Get all automatic deliveries for the table.
|
||||
"""
|
||||
|
||||
logger.info("GET /customer/automatic/deliveries - Fetching all auto deliveries")
|
||||
try:
|
||||
deliveries = Auto_Delivery.query.all()
|
||||
schema = Auto_Delivery_schema(many=True)
|
||||
@@ -491,6 +492,7 @@ def get_all_automatic_deliveries():
|
||||
def customer_automatic_assignment(customer_id):
|
||||
"""
|
||||
"""
|
||||
logger.info(f"GET /customer/automatic/assign/{customer_id} - Toggling auto delivery assignment")
|
||||
get_customer = (db.session
|
||||
.query(Customer_Customer)
|
||||
.filter(Customer_Customer.id == customer_id)
|
||||
@@ -578,6 +580,7 @@ def edit_customer_tank(customer_id):
|
||||
"""
|
||||
Safely edits or creates tank and description details for a customer.
|
||||
"""
|
||||
logger.info(f"PUT /customer/edit/tank/{customer_id} - Editing customer tank info")
|
||||
get_customer = db.session.query(Customer_Customer).filter(Customer_Customer.id == customer_id).one_or_none()
|
||||
if not get_customer:
|
||||
return jsonify({"ok": False, "error": "Customer not found"}), 404
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import logging
|
||||
from flask import request, jsonify
|
||||
from flask_login import current_user
|
||||
from datetime import date, datetime, timedelta
|
||||
from app.delivery import delivery
|
||||
from app import db
|
||||
from app.common.decorators import login_required as common_login_required
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
from sqlalchemy import or_
|
||||
from app.classes.customer import (Customer_Customer)
|
||||
from app.classes.delivery import (Delivery_Delivery,
|
||||
@@ -20,6 +24,7 @@ from app.classes.auto import Tickets_Auto_Delivery, Tickets_Auto_Delivery_schema
|
||||
|
||||
# This endpoint is fine, but I've added some comments for clarity.
|
||||
@delivery.route("/updatestatus", methods=["GET"])
|
||||
@common_login_required
|
||||
def move_deliveries():
|
||||
"""
|
||||
Batch updates delivery statuses based on their expected delivery date relative to today.
|
||||
@@ -28,6 +33,7 @@ def move_deliveries():
|
||||
- Future deliveries -> "Waiting" (0)
|
||||
- Past-due deliveries -> "Pending" (9)
|
||||
"""
|
||||
logger.info("GET /delivery/updatestatus - Batch updating delivery statuses")
|
||||
counter = 0
|
||||
today = date.today()
|
||||
tomorrow = today + timedelta(days=1)
|
||||
@@ -84,10 +90,12 @@ def move_deliveries():
|
||||
|
||||
|
||||
@delivery.route("/<int:delivery_id>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_a_delivery(delivery_id):
|
||||
"""
|
||||
Get a single delivery's details.
|
||||
"""
|
||||
logger.info(f"GET /delivery/{delivery_id} - Fetching delivery")
|
||||
get_delivery = db.session.query(Delivery_Delivery).filter(Delivery_Delivery.id == delivery_id).first()
|
||||
if not get_delivery:
|
||||
return jsonify({"ok": False, "error": "Delivery not found"}), 404
|
||||
@@ -101,8 +109,9 @@ def get_a_delivery(delivery_id):
|
||||
|
||||
|
||||
@delivery.route("/past1/<int:customer_id>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_customer_past_delivery1(customer_id):
|
||||
|
||||
logger.info(f"GET /delivery/past1/{customer_id} - Fetching customer past deliveries (first 5)")
|
||||
get_customer_past_delivery = (db.session
|
||||
.query(Delivery_Delivery)
|
||||
.filter(Delivery_Delivery.customer_id == customer_id)
|
||||
@@ -114,8 +123,9 @@ def get_customer_past_delivery1(customer_id):
|
||||
|
||||
|
||||
@delivery.route("/past2/<int:customer_id>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_customer_past_delivery2(customer_id):
|
||||
|
||||
logger.info(f"GET /delivery/past2/{customer_id} - Fetching customer past deliveries (next 5)")
|
||||
get_customer_past_delivery = (db.session
|
||||
.query(Delivery_Delivery)
|
||||
.filter(Delivery_Delivery.customer_id == customer_id)
|
||||
@@ -127,7 +137,9 @@ def get_customer_past_delivery2(customer_id):
|
||||
return jsonify(delivery_schema.dump(get_customer_past_delivery))
|
||||
|
||||
@delivery.route("/auto/<int:customer_id>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_customer_auto_delivery(customer_id):
|
||||
logger.info(f"GET /delivery/auto/{customer_id} - Fetching customer auto deliveries")
|
||||
get_customer_past_delivery = (db.session
|
||||
.query(Tickets_Auto_Delivery)
|
||||
.filter(Tickets_Auto_Delivery.customer_id == customer_id)
|
||||
@@ -140,6 +152,7 @@ def get_customer_auto_delivery(customer_id):
|
||||
|
||||
|
||||
@delivery.route("/order/<int:delivery_id>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_a_specific_delivery(delivery_id):
|
||||
"""
|
||||
Get a single delivery by its ID.
|
||||
@@ -155,6 +168,7 @@ def get_a_specific_delivery(delivery_id):
|
||||
|
||||
|
||||
@delivery.route("/cash/<int:delivery_id>/<int:type_of_payment>", methods=["PUT"])
|
||||
@common_login_required
|
||||
def update_a_delivery_payment(delivery_id, type_of_payment):
|
||||
"""
|
||||
This update a delivery for example if user updates to a fill
|
||||
@@ -175,6 +189,7 @@ def update_a_delivery_payment(delivery_id, type_of_payment):
|
||||
|
||||
|
||||
@delivery.route("/all/<int:page>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_deliveries_all(page):
|
||||
"""
|
||||
This will get deliveries not done
|
||||
@@ -200,6 +215,7 @@ def get_deliveries_all(page):
|
||||
|
||||
|
||||
@delivery.route("/customer/<int:customer_id>/<int:page>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_deliveries_from_customer(customer_id, page):
|
||||
"""
|
||||
This will get deliveries not done
|
||||
@@ -225,6 +241,7 @@ def get_deliveries_from_customer(customer_id, page):
|
||||
|
||||
|
||||
@delivery.route("/all/order/<int:page>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_deliveries_not_delivered(page):
|
||||
|
||||
"""
|
||||
@@ -250,6 +267,7 @@ def get_deliveries_not_delivered(page):
|
||||
|
||||
|
||||
@delivery.route("/waiting/<int:page>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_deliveries_waiting(page):
|
||||
"""
|
||||
This will get deliveries not done
|
||||
@@ -278,6 +296,7 @@ def get_deliveries_waiting(page):
|
||||
|
||||
|
||||
@delivery.route("/pending/<int:page>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_deliveries_pending(page):
|
||||
"""
|
||||
"""
|
||||
@@ -299,6 +318,7 @@ def get_deliveries_pending(page):
|
||||
return jsonify(customer_schema.dump(deliveries))
|
||||
|
||||
@delivery.route("/outfordelivery/<int:page>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_deliveries_outfordelivery(page):
|
||||
"""
|
||||
"""
|
||||
@@ -322,6 +342,7 @@ def get_deliveries_outfordelivery(page):
|
||||
|
||||
|
||||
@delivery.route("/tommorrow/<int:page>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_deliveries_tommorrow(page):
|
||||
"""
|
||||
This will get deliveries not done
|
||||
@@ -348,6 +369,7 @@ def get_deliveries_tommorrow(page):
|
||||
|
||||
|
||||
@delivery.route("/finalized/<int:page>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_deliveries_finalized(page):
|
||||
"""
|
||||
This will get deliveries not done
|
||||
@@ -372,6 +394,7 @@ def get_deliveries_finalized(page):
|
||||
|
||||
|
||||
@delivery.route("/cancelled/<int:page>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_deliveries_cancelled(page):
|
||||
"""
|
||||
This will get deliveries not done
|
||||
@@ -396,6 +419,7 @@ def get_deliveries_cancelled(page):
|
||||
|
||||
|
||||
@delivery.route("/partialdelivery/<int:page>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_deliveries_partial(page):
|
||||
"""
|
||||
This will get deliveries not done
|
||||
@@ -420,6 +444,7 @@ def get_deliveries_partial(page):
|
||||
|
||||
|
||||
@delivery.route("/issue/<int:page>", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_deliveries_issue(page):
|
||||
"""
|
||||
This will get deliveries not done
|
||||
@@ -444,6 +469,7 @@ def get_deliveries_issue(page):
|
||||
|
||||
|
||||
@delivery.route("/time/today", methods=["GET"])
|
||||
@common_login_required
|
||||
def get_deliveries_today():
|
||||
"""
|
||||
This will get today's deliveries
|
||||
@@ -460,10 +486,12 @@ def get_deliveries_today():
|
||||
|
||||
|
||||
@delivery.route("/edit/<int:delivery_id>", methods=["POST"])
|
||||
@common_login_required
|
||||
def edit_a_delivery(delivery_id):
|
||||
"""
|
||||
This will edit a delivery using a delivery id.
|
||||
"""
|
||||
logger.info(f"POST /delivery/edit/{delivery_id} - Editing delivery")
|
||||
data = request.json
|
||||
get_delivery = db.session.query(Delivery_Delivery).filter(Delivery_Delivery.id == delivery_id).first()
|
||||
|
||||
@@ -561,10 +589,12 @@ def edit_a_delivery(delivery_id):
|
||||
|
||||
|
||||
@delivery.route("/create/<int:user_id>", methods=["POST"])
|
||||
@common_login_required
|
||||
def create_a_delivery(user_id):
|
||||
"""
|
||||
This will create a delivery using a customer id
|
||||
"""
|
||||
logger.info(f"POST /delivery/create/{user_id} - Creating delivery for customer")
|
||||
get_customer = db.session\
|
||||
.query(Customer_Customer)\
|
||||
.filter(Customer_Customer.id == user_id)\
|
||||
@@ -600,7 +630,7 @@ def create_a_delivery(user_id):
|
||||
promo_id = request.json["promo_id"]
|
||||
else:
|
||||
promo_id = None
|
||||
except:
|
||||
except (KeyError, TypeError):
|
||||
promo_id = None
|
||||
if promo_id is not None:
|
||||
get_promo_data = (db.session
|
||||
@@ -651,7 +681,7 @@ def create_a_delivery(user_id):
|
||||
card_payment_id = request.json["credit_card_id"]
|
||||
else:
|
||||
card_payment_id = None
|
||||
except:
|
||||
except (KeyError, TypeError):
|
||||
card_payment_id = None
|
||||
|
||||
if card_payment_id is not None:
|
||||
@@ -777,10 +807,12 @@ def create_a_delivery(user_id):
|
||||
|
||||
|
||||
@delivery.route("/cancel/<int:delivery_id>", methods=["POST"])
|
||||
@common_login_required
|
||||
def cancel_a_delivery(delivery_id):
|
||||
"""
|
||||
This will cancel a delivery
|
||||
"""
|
||||
logger.info(f"POST /delivery/cancel/{delivery_id} - Cancelling delivery")
|
||||
get_delivery = db.session\
|
||||
.query(Delivery_Delivery)\
|
||||
.filter(Delivery_Delivery.id == delivery_id)\
|
||||
@@ -794,10 +826,12 @@ def cancel_a_delivery(delivery_id):
|
||||
|
||||
|
||||
@delivery.route("/delivered/<int:delivery_id>", methods=["POST"])
|
||||
@common_login_required
|
||||
def mark_as_delivered(delivery_id):
|
||||
"""
|
||||
This will mark the delivery as delivered
|
||||
"""
|
||||
logger.info(f"POST /delivery/delivered/{delivery_id} - Marking delivery as delivered")
|
||||
# how many gallons delivered
|
||||
gallons_put_into_tank = request.json["gallons_put_into_tank"]
|
||||
# was the tank full or not
|
||||
@@ -819,6 +853,7 @@ def mark_as_delivered(delivery_id):
|
||||
|
||||
|
||||
@delivery.route("/partial/<int:delivery_id>", methods=["POST"])
|
||||
@common_login_required
|
||||
def partial_delivery(delivery_id):
|
||||
"""
|
||||
This will mark the delivery as delivered
|
||||
@@ -842,6 +877,7 @@ def partial_delivery(delivery_id):
|
||||
|
||||
|
||||
@delivery.route("/note/technician/<int:delivery_id>", methods=["PUT"])
|
||||
@common_login_required
|
||||
def delivery_note_driver(delivery_id):
|
||||
|
||||
"""
|
||||
@@ -876,10 +912,12 @@ def delivery_note_driver(delivery_id):
|
||||
|
||||
|
||||
@delivery.route("/delete/<int:delivery_id>", methods=["DELETE"])
|
||||
@common_login_required
|
||||
def delete_call(delivery_id):
|
||||
"""
|
||||
delete a delivery call
|
||||
"""
|
||||
logger.info(f"DELETE /delivery/delete/{delivery_id} - Deleting delivery")
|
||||
get_call_to_delete = (db.session
|
||||
.query(Delivery_Delivery)
|
||||
.filter(Delivery_Delivery.id == delivery_id)
|
||||
@@ -893,6 +931,7 @@ def delete_call(delivery_id):
|
||||
|
||||
|
||||
@delivery.route("/total/<int:delivery_id>", methods=["GET"])
|
||||
@common_login_required
|
||||
def calculate_total(delivery_id):
|
||||
"""
|
||||
This will get deliveries not done
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from flask import request, jsonify
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
@@ -11,6 +12,8 @@ from app.classes.stats_employee import Stats_Employee_Oil
|
||||
from app.classes.auto import Auto_Delivery
|
||||
from app.classes.stats_customer import Stats_Customer
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@delivery_data.route("/finalize/<int:delivery_id>", methods=["PUT"])
|
||||
def office_finalize_delivery(delivery_id):
|
||||
"""
|
||||
@@ -20,6 +23,7 @@ def office_finalize_delivery(delivery_id):
|
||||
"""
|
||||
Finalizes a delivery from office
|
||||
"""
|
||||
logger.info(f"PUT /deliverydata/finalize/{delivery_id} - Finalizing delivery from office")
|
||||
now = datetime.utcnow()
|
||||
get_delivery = db.session \
|
||||
.query(Delivery_Delivery) \
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from flask import jsonify
|
||||
from datetime import date, timedelta
|
||||
from app.delivery_status import deliverystatus
|
||||
@@ -13,6 +14,8 @@ from app.classes.transactions import Transaction
|
||||
from datetime import date, timedelta, datetime
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# --- NEW EFFICIENT ENDPOINT ---
|
||||
@deliverystatus.route("/stats/sidebar-counts", methods=["GET"])
|
||||
@@ -21,6 +24,7 @@ def get_sidebar_counts():
|
||||
Efficiently gets all counts needed for the navigation sidebar in a single request.
|
||||
This combines logic from all the individual /count/* endpoints.
|
||||
"""
|
||||
logger.info("GET /deliverystatus/stats/sidebar-counts - Fetching sidebar counts")
|
||||
try:
|
||||
eastern = ZoneInfo("America/New_York")
|
||||
now_local = datetime.now(eastern).replace(tzinfo=None) # naive local time
|
||||
@@ -73,6 +77,7 @@ def get_tomorrow_totals():
|
||||
"""
|
||||
Get total gallons by town for tomorrow's deliveries, including grand total.
|
||||
"""
|
||||
logger.info("GET /deliverystatus/tomorrow-totals - Fetching tomorrow delivery totals")
|
||||
try:
|
||||
deliveries = db.session.query(
|
||||
Delivery_Delivery.customer_town,
|
||||
@@ -101,6 +106,7 @@ def get_today_totals():
|
||||
"""
|
||||
Get total gallons by town for today's deliveries, including grand total.
|
||||
"""
|
||||
logger.info("GET /deliverystatus/today-totals - Fetching today delivery totals")
|
||||
try:
|
||||
deliveries = db.session.query(
|
||||
Delivery_Delivery.customer_town,
|
||||
@@ -129,6 +135,7 @@ def get_waiting_totals():
|
||||
"""
|
||||
Get total gallons by town for waiting deliveries, including grand total.
|
||||
"""
|
||||
logger.info("GET /deliverystatus/waiting-totals - Fetching waiting delivery totals")
|
||||
try:
|
||||
deliveries = db.session.query(
|
||||
Delivery_Delivery.customer_town,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from flask import request, jsonify
|
||||
|
||||
from sqlalchemy import or_
|
||||
@@ -9,9 +10,12 @@ from app.classes.employee import Employee_Employee, Employee_Employee_schema
|
||||
from app.classes.auth import Auth_User
|
||||
from app.classes.stats_employee import Stats_Employee_Oil, Stats_Employee_Office
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@employees.route("/<int:userid>", methods=["GET"])
|
||||
@login_required
|
||||
def get_specific_employee(userid):
|
||||
logger.info(f"GET /employees/{userid} - Fetching employee by user ID")
|
||||
employee = db.session \
|
||||
.query(Employee_Employee) \
|
||||
.filter(Employee_Employee.user_id == userid) \
|
||||
@@ -31,6 +35,7 @@ def get_specific_employee(userid):
|
||||
@employees.route("/byid/<int:employee_id>", methods=["GET"])
|
||||
@login_required
|
||||
def get_employee_by_id(employee_id):
|
||||
logger.info(f"GET /employees/byid/{employee_id} - Fetching employee by ID")
|
||||
employee = db.session \
|
||||
.query(Employee_Employee) \
|
||||
.filter(Employee_Employee.id == employee_id) \
|
||||
@@ -42,6 +47,7 @@ def get_employee_by_id(employee_id):
|
||||
@employees.route("/userid/<int:userid>", methods=["GET"])
|
||||
@login_required
|
||||
def get_specific_employee_user_id(userid):
|
||||
logger.info(f"GET /employees/userid/{userid} - Fetching employee by user ID")
|
||||
employee = db.session \
|
||||
.query(Employee_Employee) \
|
||||
.filter(Employee_Employee.user_id == userid) \
|
||||
@@ -56,6 +62,7 @@ def all_employees_paginated(page):
|
||||
"""
|
||||
pagination all employees
|
||||
"""
|
||||
logger.info(f"GET /employees/all/{page} - Fetching employees page {page}")
|
||||
per_page_amount = 50
|
||||
if page is None:
|
||||
offset_limit = 0
|
||||
@@ -75,6 +82,7 @@ def all_employees_paginated(page):
|
||||
@employees.route("/all", methods=["GET"])
|
||||
@login_required
|
||||
def all_employees():
|
||||
logger.info("GET /employees/all - Fetching all employees")
|
||||
employee_list = db.session \
|
||||
.query(Employee_Employee) \
|
||||
.all()
|
||||
@@ -85,6 +93,7 @@ def all_employees():
|
||||
@employees.route("/drivers", methods=["GET"])
|
||||
@login_required
|
||||
def all_employees_drivers():
|
||||
logger.info("GET /employees/drivers - Fetching all drivers")
|
||||
employee_list = db.session \
|
||||
.query(Employee_Employee) \
|
||||
.filter(or_(Employee_Employee.employee_type == 4,
|
||||
@@ -98,6 +107,7 @@ def all_employees_drivers():
|
||||
@employees.route("/techs", methods=["GET"])
|
||||
@login_required
|
||||
def all_employees_techs():
|
||||
logger.info("GET /employees/techs - Fetching all technicians")
|
||||
employee_list = db.session \
|
||||
.query(Employee_Employee) \
|
||||
.filter(or_(Employee_Employee.employee_type == 0,
|
||||
@@ -116,6 +126,7 @@ def employee_create():
|
||||
"""
|
||||
This will create an employee
|
||||
"""
|
||||
logger.info("POST /employees/create - Creating new employee")
|
||||
e_last_name = request.json["employee_last_name"]
|
||||
e_first_name = request.json["employee_first_name"]
|
||||
e_town = request.json["employee_town"]
|
||||
@@ -180,6 +191,7 @@ def employee_edit(employee_id):
|
||||
"""
|
||||
This will update an employee
|
||||
"""
|
||||
logger.info(f"POST /employees/edit/{employee_id} - Editing employee")
|
||||
e_last_name = request.json["employee_last_name"]
|
||||
e_first_name = request.json["employee_first_name"]
|
||||
e_town = request.json["employee_town"]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from flask import jsonify
|
||||
from decimal import Decimal
|
||||
from app.info import info
|
||||
@@ -6,10 +7,15 @@ from app.classes.pricing import Pricing_Oil_Oil, Pricing_Oil_Oil_schema
|
||||
from app.classes.admin import Admin_Company
|
||||
from app.classes.delivery import Delivery_Delivery
|
||||
from app.classes.service import Service_Service
|
||||
from flask_login import login_required
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@info.route("/price/oil/tiers", methods=["GET"])
|
||||
@login_required
|
||||
def get_pricing_tiers():
|
||||
logger.info("GET /info/price/oil/tiers - Fetching oil pricing tiers")
|
||||
get_price_query = (db.session
|
||||
.query(Pricing_Oil_Oil)
|
||||
.order_by(Pricing_Oil_Oil.date.desc())
|
||||
@@ -34,7 +40,9 @@ def get_pricing_tiers():
|
||||
return jsonify(pricing_totals)
|
||||
|
||||
@info.route("/price/oil", methods=["GET"])
|
||||
@login_required
|
||||
def get_oil_price_today():
|
||||
logger.info("GET /info/price/oil - Fetching current oil prices")
|
||||
get_price_query = (db.session
|
||||
.query(Pricing_Oil_Oil)
|
||||
.order_by(Pricing_Oil_Oil.date.desc())
|
||||
@@ -50,7 +58,9 @@ def get_oil_price_today():
|
||||
|
||||
|
||||
@info.route("/price/oil/table", methods=["GET"])
|
||||
@login_required
|
||||
def get_pricing():
|
||||
logger.info("GET /info/price/oil/table - Fetching oil pricing table")
|
||||
get_price_query = (db.session
|
||||
.query(Pricing_Oil_Oil)
|
||||
.order_by(Pricing_Oil_Oil.date.desc())
|
||||
@@ -63,7 +73,9 @@ def get_pricing():
|
||||
|
||||
|
||||
@info.route("/company", methods=["GET"])
|
||||
@login_required
|
||||
def get_company():
|
||||
logger.info("GET /info/company - Fetching company information")
|
||||
get_data_company = (db.session
|
||||
.query(Admin_Company)
|
||||
.first())
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
import logging
|
||||
from flask import jsonify, Response, url_for
|
||||
from app import app
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@app.route("/favicon.ico")
|
||||
def favicon():
|
||||
logger.info("GET /favicon.ico - Serving favicon")
|
||||
return url_for('static', filename='data:,')
|
||||
|
||||
|
||||
@app.route('/robots.txt')
|
||||
@app.route('/sitemap.xml')
|
||||
def static_from_root():
|
||||
logger.info("GET /robots.txt or /sitemap.xml - Serving robots/sitemap")
|
||||
def disallow(string): return 'Disallow: {0}'.format(string)
|
||||
return Response("User-agent: *\n{0}\n".format("\n".join([
|
||||
disallow('/bin/*'),
|
||||
@@ -19,5 +24,5 @@ def static_from_root():
|
||||
@app.route('/index', methods=['GET'])
|
||||
@app.route('/', methods=['GET'])
|
||||
def index():
|
||||
logger.info("GET / or /index - API health check")
|
||||
return jsonify({"success": "Api is online"}), 200
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from flask import jsonify
|
||||
from app.money import money
|
||||
from app import db
|
||||
@@ -6,6 +7,8 @@ from datetime import date
|
||||
from app.classes.money import Money_delivery, Money_delivery_schema
|
||||
from app.classes.delivery import Delivery_Delivery, Delivery_Delivery_schema
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def get_monday_date(date_object):
|
||||
"""Gets the date of the Monday for the given date."""
|
||||
|
||||
@@ -25,6 +28,7 @@ def get_monday_date(date_object):
|
||||
|
||||
@money.route("/profit/week", methods=["GET"])
|
||||
def total_profit_week():
|
||||
logger.info("GET /money/profit/week - Calculating weekly profit")
|
||||
# Get today's date
|
||||
total_profit = 0
|
||||
total_deliveries = 0
|
||||
@@ -52,6 +56,7 @@ def total_profit_week():
|
||||
|
||||
@money.route("/profit/year", methods=["GET"])
|
||||
def total_profit_year():
|
||||
logger.info("GET /money/profit/year - Calculating yearly profit")
|
||||
# Get today's date
|
||||
total_profit = 0
|
||||
|
||||
@@ -74,10 +79,11 @@ def total_profit_year():
|
||||
def get_money_delivery(delivery_id):
|
||||
"""
|
||||
"""
|
||||
logger.info(f"GET /money/{delivery_id} - Fetching delivery profit data")
|
||||
profit = (db.session
|
||||
.query(Money_delivery)
|
||||
.filter(Money_delivery.delivery_id == delivery_id)
|
||||
.first())
|
||||
|
||||
money_schema = Money_delivery_schema(many=False)
|
||||
return jsonify(money_schema.dump(profit))
|
||||
return jsonify(money_schema.dump(profit))
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from flask import jsonify, request
|
||||
from app.payment import payment
|
||||
from app import db
|
||||
@@ -6,6 +7,9 @@ from app.classes.cards import Card_Card, Card_Card_schema
|
||||
from app.classes.transactions import Transaction
|
||||
from app.classes.delivery import Delivery_Delivery
|
||||
from app.classes.service import Service_Service, Service_Service_schema
|
||||
from flask_login import login_required
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
@@ -52,10 +56,12 @@ def set_card_main(user_id, card_id):
|
||||
|
||||
|
||||
@payment.route("/cards/<int:user_id>", methods=["GET"])
|
||||
@login_required
|
||||
def get_user_cards(user_id):
|
||||
"""
|
||||
gets all cards of a user
|
||||
"""
|
||||
logger.info(f"GET /payment/cards/{user_id} - Fetching user cards")
|
||||
get_u_cards = (db.session
|
||||
.query(Card_Card)
|
||||
.filter(Card_Card.user_id == user_id)
|
||||
@@ -66,11 +72,12 @@ def get_user_cards(user_id):
|
||||
|
||||
|
||||
@payment.route("/cards/onfile/<int:user_id>", methods=["GET"])
|
||||
@login_required
|
||||
def get_user_cards_count(user_id):
|
||||
"""
|
||||
gets all cards of a user
|
||||
"""
|
||||
|
||||
logger.info(f"GET /payment/cards/onfile/{user_id} - Getting card count")
|
||||
get_u_cards = (db.session
|
||||
.query(Card_Card)
|
||||
.filter(Card_Card.user_id == user_id)
|
||||
@@ -83,6 +90,7 @@ def get_user_cards_count(user_id):
|
||||
|
||||
|
||||
@payment.route("/card/<int:card_id>", methods=["GET"])
|
||||
@login_required
|
||||
def get_user_specific_card(card_id):
|
||||
"""
|
||||
gets a specific card of a user
|
||||
@@ -99,6 +107,7 @@ def get_user_specific_card(card_id):
|
||||
|
||||
|
||||
@payment.route("/card/main/<int:card_id>/<int:user_id>", methods=["PUT"])
|
||||
@login_required
|
||||
def set_main_card(user_id, card_id):
|
||||
"""
|
||||
updates a card of a user
|
||||
@@ -130,11 +139,12 @@ def set_main_card(user_id, card_id):
|
||||
|
||||
|
||||
@payment.route("/card/remove/<int:card_id>", methods=["DELETE"])
|
||||
@login_required
|
||||
def remove_user_card(card_id):
|
||||
"""
|
||||
removes a card
|
||||
removes a card
|
||||
"""
|
||||
|
||||
logger.info(f"DELETE /payment/card/remove/{card_id} - Removing card")
|
||||
get_card = (db.session
|
||||
.query(Card_Card)
|
||||
.filter(Card_Card.id == card_id)
|
||||
@@ -151,6 +161,7 @@ def remove_user_card(card_id):
|
||||
# ... (your existing imports: jsonify, request, db, Customer_Customer, Card_Card) ...
|
||||
|
||||
@payment.route("/card/create/<int:user_id>", methods=["POST"])
|
||||
@login_required
|
||||
def create_user_card(user_id):
|
||||
"""
|
||||
Adds a card for a user to the local database. This is its only job.
|
||||
@@ -196,17 +207,18 @@ def create_user_card(user_id):
|
||||
set_card_main(user_id=get_customer.id, card_id=create_new_card.id)
|
||||
|
||||
db.session.commit()
|
||||
print(f"SUCCESS: Card saved locally for user {user_id} with new ID {create_new_card.id}")
|
||||
logger.info(f"Card saved locally for user {user_id} with ID {create_new_card.id}")
|
||||
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
print(f"DATABASE ERROR: Could not save card for user {user_id}. Error: {e}")
|
||||
logger.error(f"Database error saving card for user {user_id}: {e}")
|
||||
return jsonify({"ok": False, "error": "Failed to save card information."}), 500
|
||||
|
||||
# Return a success response with the card_id
|
||||
return jsonify({"ok": True, "card_id": create_new_card.id}), 200
|
||||
|
||||
@payment.route("/card/update_payment_profile/<int:card_id>", methods=["PUT"])
|
||||
@login_required
|
||||
def update_card_payment_profile(card_id):
|
||||
"""
|
||||
Updates the auth_net_payment_profile_id for a card
|
||||
@@ -230,6 +242,7 @@ def update_card_payment_profile(card_id):
|
||||
|
||||
|
||||
@payment.route("/card/edit/<int:card_id>", methods=["PUT"])
|
||||
@login_required
|
||||
def update_user_card(card_id):
|
||||
"""
|
||||
edits a card
|
||||
@@ -277,6 +290,7 @@ def update_user_card(card_id):
|
||||
|
||||
|
||||
@payment.route("/transactions/authorize/<int:page>", methods=["GET"])
|
||||
@login_required
|
||||
def get_authorize_transactions(page):
|
||||
"""
|
||||
Gets transactions with transaction_type = 0 (charge), for the authorize page
|
||||
@@ -320,6 +334,7 @@ def get_authorize_transactions(page):
|
||||
|
||||
|
||||
@payment.route("/authorize/cleanup/<int:customer_id>", methods=["POST"])
|
||||
@login_required
|
||||
def cleanup_authorize_profile(customer_id):
|
||||
"""
|
||||
Clean up Authorize.Net profile data in local database when API check fails.
|
||||
@@ -349,6 +364,7 @@ def cleanup_authorize_profile(customer_id):
|
||||
|
||||
|
||||
@payment.route("/authorize/<int:delivery_id>", methods=["PUT"])
|
||||
@login_required
|
||||
def update_delivery_payment_authorize(delivery_id):
|
||||
"""
|
||||
Update a delivery's payment_type to 11 (CC - Authorize API) after successful preauthorization
|
||||
@@ -370,6 +386,7 @@ def update_delivery_payment_authorize(delivery_id):
|
||||
|
||||
|
||||
@payment.route("/transaction/delivery/<int:delivery_id>", methods=["GET"])
|
||||
@login_required
|
||||
def get_transaction_by_delivery(delivery_id):
|
||||
"""
|
||||
Get a single transaction by delivery_id for Authorize.net payments
|
||||
@@ -403,6 +420,7 @@ def get_transaction_by_delivery(delivery_id):
|
||||
|
||||
|
||||
@payment.route("/transactions/customer/<int:customer_id>/<int:page>", methods=["GET"])
|
||||
@login_required
|
||||
def get_customer_transactions(customer_id, page):
|
||||
"""
|
||||
Gets transactions for a specific customer
|
||||
@@ -445,6 +463,7 @@ def get_customer_transactions(customer_id, page):
|
||||
|
||||
|
||||
@payment.route("/service/payment/<int:service_id>/<int:payment_type>", methods=["PUT"])
|
||||
@login_required
|
||||
def process_service_payment_tiger(service_id, payment_type):
|
||||
service = db.session.query(Service_Service).filter(Service_Service.id == service_id).first()
|
||||
if not service:
|
||||
@@ -464,6 +483,7 @@ def process_service_payment_tiger(service_id, payment_type):
|
||||
|
||||
|
||||
@payment.route("/authorize/service/<int:service_id>", methods=["PUT"])
|
||||
@login_required
|
||||
def update_service_payment_authorize(service_id):
|
||||
service = db.session.query(Service_Service).filter(Service_Service.id == service_id).first()
|
||||
if not service:
|
||||
@@ -487,6 +507,7 @@ def update_service_payment_authorize(service_id):
|
||||
|
||||
|
||||
@payment.route("/capture/service/<int:service_id>", methods=["PUT"])
|
||||
@login_required
|
||||
def update_service_payment_capture(service_id):
|
||||
service = db.session.query(Service_Service).filter(Service_Service.id == service_id).first()
|
||||
if not service:
|
||||
@@ -511,6 +532,7 @@ def update_service_payment_capture(service_id):
|
||||
|
||||
|
||||
@payment.route("/transactions/service/<int:service_id>", methods=["GET"])
|
||||
@login_required
|
||||
def get_service_transactions(service_id):
|
||||
"""
|
||||
Gets all transactions for a specific service ID
|
||||
@@ -544,5 +566,5 @@ def get_service_transactions(service_id):
|
||||
return jsonify(transactions_data), 200
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error fetching transactions for service {service_id}: {str(e)}")
|
||||
logger.error(f"Error fetching transactions for service {service_id}: {e}")
|
||||
return jsonify({"ok": False, "error": str(e)}), 500
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from flask import request, jsonify
|
||||
import decimal
|
||||
from datetime import datetime
|
||||
@@ -11,6 +12,8 @@ from app.classes.delivery import (Delivery_Delivery,
|
||||
Delivery_Notes_Driver,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def convert_to_decimal(text):
|
||||
try:
|
||||
number = float(text)
|
||||
@@ -23,9 +26,10 @@ def convert_to_decimal(text):
|
||||
def get_promo(promo_id):
|
||||
"""
|
||||
"""
|
||||
get_promo_data = (db.session
|
||||
.query(Promo_Promo)
|
||||
.filter(Promo_Promo.id == promo_id)
|
||||
logger.info(f"GET /promo/{promo_id} - Fetching promo")
|
||||
get_promo_data = (db.session
|
||||
.query(Promo_Promo)
|
||||
.filter(Promo_Promo.id == promo_id)
|
||||
.first())
|
||||
query_schema = Promo_Promo_schema(many=False)
|
||||
return jsonify(query_schema.dump(get_promo_data))
|
||||
@@ -35,6 +39,7 @@ def get_promo(promo_id):
|
||||
def get_promo_price(delivery_id):
|
||||
"""
|
||||
"""
|
||||
logger.info(f"GET /promo/promoprice/{delivery_id} - Calculating promo price")
|
||||
get_delivery = (db.session
|
||||
.query(Delivery_Delivery)
|
||||
.filter(Delivery_Delivery.id == delivery_id)
|
||||
@@ -53,8 +58,9 @@ def get_promo_price(delivery_id):
|
||||
def get_all_promo():
|
||||
"""
|
||||
"""
|
||||
get_promo_data = (db.session
|
||||
.query(Promo_Promo)
|
||||
logger.info("GET /promo/all - Fetching all promos")
|
||||
get_promo_data = (db.session
|
||||
.query(Promo_Promo)
|
||||
.all())
|
||||
query_schema = Promo_Promo_schema(many=True)
|
||||
return jsonify(query_schema.dump(get_promo_data))
|
||||
@@ -64,11 +70,12 @@ def get_all_promo():
|
||||
def delete_a_promo(promo_id):
|
||||
"""
|
||||
"""
|
||||
get_promo_data = (db.session
|
||||
.query(Promo_Promo)
|
||||
.filter(Promo_Promo.id == promo_id)
|
||||
logger.info(f"DELETE /promo/delete/{promo_id} - Deleting promo")
|
||||
get_promo_data = (db.session
|
||||
.query(Promo_Promo)
|
||||
.filter(Promo_Promo.id == promo_id)
|
||||
.first())
|
||||
|
||||
|
||||
db.session.delete(get_promo_data)
|
||||
db.session.commit()
|
||||
|
||||
@@ -81,6 +88,7 @@ def delete_a_promo(promo_id):
|
||||
def create_promo():
|
||||
"""
|
||||
"""
|
||||
logger.info("POST /promo/create - Creating new promo")
|
||||
date_created = datetime.utcnow()
|
||||
name_of_promotion = request.json["name_of_promotion"]
|
||||
money_off_delivery = request.json["money_off_delivery"]
|
||||
@@ -94,13 +102,13 @@ def create_promo():
|
||||
name_of_promotion = name_of_promotion,
|
||||
money_off_delivery = amount_off,
|
||||
description = description,
|
||||
date_created = date_created,
|
||||
date_created = date_created,
|
||||
text_on_ticket=text_on_ticket
|
||||
)
|
||||
db.session.add(new_promo)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
|
||||
return jsonify({
|
||||
"ok": True,
|
||||
'promo_id':new_promo.id,
|
||||
@@ -112,9 +120,10 @@ def edit_promo(promo_id):
|
||||
"""
|
||||
|
||||
"""
|
||||
get_promo_data = (db.session
|
||||
.query(Promo_Promo)
|
||||
.filter(Promo_Promo.id == promo_id)
|
||||
logger.info(f"PUT /promo/edit/{promo_id} - Editing promo")
|
||||
get_promo_data = (db.session
|
||||
.query(Promo_Promo)
|
||||
.filter(Promo_Promo.id == promo_id)
|
||||
.first())
|
||||
text_on_ticket = request.json["text_on_ticket"]
|
||||
name_of_promotion = request.json["name_of_promotion"]
|
||||
@@ -144,13 +153,14 @@ def turn_on_promo(promo_id):
|
||||
"""
|
||||
|
||||
"""
|
||||
get_promo_data = (db.session
|
||||
.query(Promo_Promo)
|
||||
.filter(Promo_Promo.id == promo_id)
|
||||
logger.info(f"PATCH /promo/on/{promo_id} - Activating promo")
|
||||
get_promo_data = (db.session
|
||||
.query(Promo_Promo)
|
||||
.filter(Promo_Promo.id == promo_id)
|
||||
.first())
|
||||
|
||||
get_promo_data.active = True
|
||||
|
||||
|
||||
|
||||
db.session.add(get_promo_data)
|
||||
db.session.commit()
|
||||
@@ -165,13 +175,14 @@ def turn_off_promo(promo_id):
|
||||
"""
|
||||
|
||||
"""
|
||||
get_promo_data = (db.session
|
||||
.query(Promo_Promo)
|
||||
.filter(Promo_Promo.id == promo_id)
|
||||
logger.info(f"PATCH /promo/off/{promo_id} - Deactivating promo")
|
||||
get_promo_data = (db.session
|
||||
.query(Promo_Promo)
|
||||
.filter(Promo_Promo.id == promo_id)
|
||||
.first())
|
||||
|
||||
get_promo_data.active = False
|
||||
|
||||
|
||||
|
||||
db.session.add(get_promo_data)
|
||||
db.session.commit()
|
||||
@@ -179,4 +190,4 @@ def turn_off_promo(promo_id):
|
||||
return jsonify({
|
||||
"ok": True,
|
||||
'promo_id':get_promo_data.id,
|
||||
}), 200
|
||||
}), 200
|
||||
|
||||
@@ -1,34 +1,42 @@
|
||||
import logging
|
||||
from flask import jsonify
|
||||
from app.query import query
|
||||
from app import db
|
||||
from app.classes.admin import Admin_Company
|
||||
from app.classes.query import (Query_StateList,
|
||||
Query_DeliveryStatusList,
|
||||
Query_DeliveryStatusList_Schema,
|
||||
Query_StateList_Schema,
|
||||
Query_CustomerTypeList,
|
||||
Query_DeliveryStatusList,
|
||||
Query_DeliveryStatusList_Schema,
|
||||
Query_StateList_Schema,
|
||||
Query_CustomerTypeList,
|
||||
Query_CustomerTypeList_Schema,
|
||||
Query_EmployeeTypeList,
|
||||
Query_EmployeeTypeList,
|
||||
Query_EmployeeTypeList_Schema)
|
||||
from flask_login import login_required
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@query.route("/company/<int:company_id>", methods=["GET"])
|
||||
@login_required
|
||||
def get_company(company_id):
|
||||
"""
|
||||
This will get the company from env variable
|
||||
"""
|
||||
logger.info(f"GET /query/company/{company_id} - Fetching company data")
|
||||
|
||||
query_data = (db.session
|
||||
.query(Admin_Company)
|
||||
.filter(Admin_Company.id == company_id)
|
||||
query_data = (db.session
|
||||
.query(Admin_Company)
|
||||
.filter(Admin_Company.id == company_id)
|
||||
.first())
|
||||
delivery_schema = Query_DeliveryStatusList_Schema(many=False)
|
||||
return jsonify(delivery_schema.dump(query_data))
|
||||
|
||||
@query.route("/states", methods=["GET"])
|
||||
@login_required
|
||||
def get_state_list():
|
||||
"""
|
||||
This will get states
|
||||
"""
|
||||
logger.info("GET /query/states - Fetching state list")
|
||||
|
||||
query_data = db.session \
|
||||
.query(Query_StateList) \
|
||||
@@ -39,10 +47,12 @@ def get_state_list():
|
||||
|
||||
|
||||
@query.route("/customertype", methods=["GET"])
|
||||
@login_required
|
||||
def get_customer_type_list():
|
||||
"""
|
||||
This will get types of customers
|
||||
"""
|
||||
logger.info("GET /query/customertype - Fetching customer type list")
|
||||
|
||||
query_data = db.session \
|
||||
.query(Query_CustomerTypeList) \
|
||||
@@ -54,10 +64,12 @@ def get_customer_type_list():
|
||||
|
||||
|
||||
@query.route("/employeetype", methods=["GET"])
|
||||
@login_required
|
||||
def get_employee_type_list():
|
||||
"""
|
||||
This will get types of service
|
||||
"""
|
||||
logger.info("GET /query/employeetype - Fetching employee type list")
|
||||
|
||||
query_data = db.session \
|
||||
.query(Query_EmployeeTypeList) \
|
||||
@@ -67,16 +79,15 @@ def get_employee_type_list():
|
||||
|
||||
|
||||
@query.route("/deliverystatus", methods=["GET"])
|
||||
@login_required
|
||||
def get_delivery_status_list():
|
||||
"""
|
||||
This will get delivery status
|
||||
"""
|
||||
logger.info("GET /query/deliverystatus - Fetching delivery status list")
|
||||
|
||||
query_data = db.session \
|
||||
.query(Query_DeliveryStatusList) \
|
||||
.all()
|
||||
delivery_schema = Query_DeliveryStatusList_Schema(many=True)
|
||||
return jsonify(delivery_schema.dump(query_data))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from flask import jsonify
|
||||
from sqlalchemy.sql import func
|
||||
from app.reports import reports
|
||||
@@ -7,14 +8,17 @@ from app.classes.customer import Customer_Customer
|
||||
|
||||
from app.classes.delivery import Delivery_Delivery
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@reports.route("/oil/total", methods=["GET"])
|
||||
def oil_total_gallons():
|
||||
logger.info("GET /reports/oil/total - Calculating total oil delivered")
|
||||
total_oil = db.session\
|
||||
.query(func.sum(Delivery_Delivery.gallons_delivered))\
|
||||
.group_by(Delivery_Delivery.id)\
|
||||
.all()
|
||||
|
||||
|
||||
return jsonify({"ok": True, "oil": total_oil }), 200
|
||||
|
||||
@reports.route("/customers/list", methods=["GET"])
|
||||
@@ -24,6 +28,7 @@ def customer_list():
|
||||
Returns account number, first name, last name, address, town, and phone number.
|
||||
Ordered by last name from A to Z.
|
||||
"""
|
||||
logger.info("GET /reports/customers/list - Fetching customer list for reports")
|
||||
|
||||
customers = db.session.query(Customer_Customer).order_by(Customer_Customer.customer_last_name.asc()).all()
|
||||
customer_data = [
|
||||
|
||||
4
app/schemas/__init__.py
Normal file
4
app/schemas/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# Validation schemas for API requests
|
||||
from .customer import CreateCustomerSchema, UpdateCustomerSchema, UpdateDescriptionSchema
|
||||
from .auth import LoginSchema, RegisterSchema, ChangePasswordSchema
|
||||
from .utils import validate_request, validate_json
|
||||
56
app/schemas/auth.py
Normal file
56
app/schemas/auth.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from marshmallow import Schema, fields, validate, EXCLUDE
|
||||
|
||||
|
||||
class LoginSchema(Schema):
|
||||
"""Validation schema for user login"""
|
||||
class Meta:
|
||||
unknown = EXCLUDE
|
||||
|
||||
username = fields.Str(
|
||||
required=True,
|
||||
validate=validate.Length(min=3, max=100),
|
||||
error_messages={"required": "Username is required"}
|
||||
)
|
||||
password = fields.Str(
|
||||
required=True,
|
||||
validate=validate.Length(min=6, max=200),
|
||||
error_messages={"required": "Password is required"}
|
||||
)
|
||||
|
||||
|
||||
class RegisterSchema(Schema):
|
||||
"""Validation schema for user registration"""
|
||||
class Meta:
|
||||
unknown = EXCLUDE
|
||||
|
||||
username = fields.Str(
|
||||
required=True,
|
||||
validate=validate.Length(min=3, max=100),
|
||||
error_messages={"required": "Username is required"}
|
||||
)
|
||||
password = fields.Str(
|
||||
required=True,
|
||||
validate=validate.Length(min=6, max=200),
|
||||
error_messages={"required": "Password is required"}
|
||||
)
|
||||
email = fields.Email(
|
||||
required=True,
|
||||
error_messages={"required": "Email is required"}
|
||||
)
|
||||
|
||||
|
||||
class ChangePasswordSchema(Schema):
|
||||
"""Validation schema for password change"""
|
||||
class Meta:
|
||||
unknown = EXCLUDE
|
||||
|
||||
new_password = fields.Str(
|
||||
required=True,
|
||||
validate=validate.Length(min=6, max=200),
|
||||
error_messages={"required": "New password is required"}
|
||||
)
|
||||
password_confirm = fields.Str(
|
||||
required=True,
|
||||
validate=validate.Length(min=6, max=200),
|
||||
error_messages={"required": "Password confirmation is required"}
|
||||
)
|
||||
126
app/schemas/customer.py
Normal file
126
app/schemas/customer.py
Normal file
@@ -0,0 +1,126 @@
|
||||
from marshmallow import Schema, fields, validate, EXCLUDE
|
||||
|
||||
|
||||
class CreateCustomerSchema(Schema):
|
||||
"""Validation schema for creating a new customer"""
|
||||
class Meta:
|
||||
unknown = EXCLUDE
|
||||
|
||||
customer_last_name = fields.Str(
|
||||
required=True,
|
||||
validate=validate.Length(min=1, max=250),
|
||||
error_messages={"required": "Last name is required"}
|
||||
)
|
||||
customer_first_name = fields.Str(
|
||||
required=True,
|
||||
validate=validate.Length(min=1, max=250),
|
||||
error_messages={"required": "First name is required"}
|
||||
)
|
||||
customer_town = fields.Str(
|
||||
required=True,
|
||||
validate=validate.Length(min=1, max=140),
|
||||
error_messages={"required": "Town is required"}
|
||||
)
|
||||
customer_state = fields.Int(
|
||||
required=True,
|
||||
validate=validate.Range(min=0, max=50),
|
||||
error_messages={"required": "State is required"}
|
||||
)
|
||||
customer_zip = fields.Str(
|
||||
required=True,
|
||||
validate=validate.Length(min=5, max=10),
|
||||
error_messages={"required": "Zip code is required"}
|
||||
)
|
||||
customer_email = fields.Email(
|
||||
allow_none=True,
|
||||
load_default=None
|
||||
)
|
||||
customer_home_type = fields.Int(
|
||||
required=True,
|
||||
validate=validate.Range(min=0, max=10),
|
||||
error_messages={"required": "Home type is required"}
|
||||
)
|
||||
customer_phone_number = fields.Str(
|
||||
allow_none=True,
|
||||
validate=validate.Length(max=25),
|
||||
load_default=None
|
||||
)
|
||||
customer_address = fields.Str(
|
||||
required=True,
|
||||
validate=validate.Length(min=1, max=1000),
|
||||
error_messages={"required": "Address is required"}
|
||||
)
|
||||
customer_apt = fields.Str(
|
||||
allow_none=True,
|
||||
validate=validate.Length(max=140),
|
||||
load_default=None
|
||||
)
|
||||
customer_description = fields.Str(
|
||||
allow_none=True,
|
||||
validate=validate.Length(max=2000),
|
||||
load_default=None
|
||||
)
|
||||
|
||||
|
||||
class UpdateCustomerSchema(Schema):
|
||||
"""Validation schema for updating an existing customer"""
|
||||
class Meta:
|
||||
unknown = EXCLUDE
|
||||
|
||||
customer_last_name = fields.Str(
|
||||
validate=validate.Length(min=1, max=250)
|
||||
)
|
||||
customer_first_name = fields.Str(
|
||||
validate=validate.Length(min=1, max=250)
|
||||
)
|
||||
customer_town = fields.Str(
|
||||
validate=validate.Length(min=1, max=140)
|
||||
)
|
||||
customer_state = fields.Int(
|
||||
validate=validate.Range(min=0, max=50)
|
||||
)
|
||||
customer_zip = fields.Str(
|
||||
validate=validate.Length(min=5, max=10)
|
||||
)
|
||||
customer_email = fields.Email(
|
||||
allow_none=True
|
||||
)
|
||||
customer_home_type = fields.Int(
|
||||
validate=validate.Range(min=0, max=10)
|
||||
)
|
||||
customer_phone_number = fields.Str(
|
||||
allow_none=True,
|
||||
validate=validate.Length(max=25)
|
||||
)
|
||||
customer_address = fields.Str(
|
||||
validate=validate.Length(min=1, max=1000)
|
||||
)
|
||||
customer_apt = fields.Str(
|
||||
allow_none=True,
|
||||
validate=validate.Length(max=140)
|
||||
)
|
||||
customer_automatic = fields.Int(
|
||||
validate=validate.Range(min=0, max=10)
|
||||
)
|
||||
customer_description = fields.Str(
|
||||
allow_none=True,
|
||||
validate=validate.Length(max=2000)
|
||||
)
|
||||
customer_fill_location = fields.Int(
|
||||
allow_none=True,
|
||||
validate=validate.Range(min=0, max=10)
|
||||
)
|
||||
|
||||
|
||||
class UpdateDescriptionSchema(Schema):
|
||||
"""Validation schema for updating customer description"""
|
||||
class Meta:
|
||||
unknown = EXCLUDE
|
||||
|
||||
description = fields.Str(
|
||||
allow_none=True,
|
||||
validate=validate.Length(max=2000)
|
||||
)
|
||||
fill_location = fields.Int(
|
||||
allow_none=True
|
||||
)
|
||||
56
app/schemas/utils.py
Normal file
56
app/schemas/utils.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from flask import jsonify, request
|
||||
from functools import wraps
|
||||
from marshmallow import ValidationError
|
||||
|
||||
|
||||
def validate_request(schema_class):
|
||||
"""
|
||||
Decorator to validate incoming JSON request data against a marshmallow schema.
|
||||
|
||||
Usage:
|
||||
@customer.route("/create", methods=["POST"])
|
||||
@validate_request(CreateCustomerSchema)
|
||||
def create_customer():
|
||||
data = request.validated_data # Access validated data
|
||||
...
|
||||
"""
|
||||
def decorator(f):
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
# Check if request has JSON data
|
||||
if not request.is_json:
|
||||
return jsonify({"error": "Request must be JSON"}), 400
|
||||
|
||||
json_data = request.get_json()
|
||||
if json_data is None:
|
||||
return jsonify({"error": "Invalid JSON data"}), 400
|
||||
|
||||
# Validate the data
|
||||
schema = schema_class()
|
||||
try:
|
||||
validated_data = schema.load(json_data)
|
||||
# Attach validated data to request object for easy access
|
||||
request.validated_data = validated_data
|
||||
except ValidationError as err:
|
||||
return jsonify({"error": "Validation failed", "details": err.messages}), 400
|
||||
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
return decorator
|
||||
|
||||
|
||||
def validate_json(schema_class, data):
|
||||
"""
|
||||
Validate data against a schema and return (validated_data, errors).
|
||||
|
||||
Usage:
|
||||
data, errors = validate_json(CreateCustomerSchema, request.get_json())
|
||||
if errors:
|
||||
return jsonify({"error": "Validation failed", "details": errors}), 400
|
||||
"""
|
||||
schema = schema_class()
|
||||
try:
|
||||
validated_data = schema.load(data or {})
|
||||
return validated_data, None
|
||||
except ValidationError as err:
|
||||
return None, err.messages
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from flask import request, jsonify
|
||||
|
||||
from app.search import search
|
||||
@@ -5,16 +6,27 @@ from app import db
|
||||
from sqlalchemy import or_
|
||||
from app.classes.customer import Customer_Customer, Customer_Customer_schema
|
||||
from app.classes.delivery import Delivery_Delivery, Delivery_Delivery_schema
|
||||
from flask_login import login_required
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def escape_like(value: str) -> str:
|
||||
"""Escape special LIKE characters to prevent LIKE injection."""
|
||||
if value is None:
|
||||
return ""
|
||||
return value.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_")
|
||||
|
||||
|
||||
@search.route("/customer", methods=["GET"])
|
||||
@login_required
|
||||
def search_customers():
|
||||
"""
|
||||
|
||||
"""
|
||||
|
||||
keyword = request.args.get('q')
|
||||
search = "%{}%".format(keyword)
|
||||
logger.info(f"GET /search/customer - Searching customers with keyword: {keyword}")
|
||||
search = "%{}%".format(escape_like(keyword))
|
||||
search_type = (search[1])
|
||||
search = search.replace("!", "")
|
||||
search = search.replace("#", "")
|
||||
@@ -66,12 +78,14 @@ def search_customers():
|
||||
|
||||
|
||||
@search.route("/delivery", methods=["GET"])
|
||||
@login_required
|
||||
def search_delivery():
|
||||
"""
|
||||
pagination all customers
|
||||
"""
|
||||
keyword = request.args.get('q')
|
||||
search = "%{}%".format(keyword)
|
||||
logger.info(f"GET /search/delivery - Searching deliveries with keyword: {keyword}")
|
||||
search = "%{}%".format(escape_like(keyword))
|
||||
search_type = (search[1])
|
||||
|
||||
delivery_ticket = (db.session
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from flask import request, jsonify
|
||||
from app.service import service
|
||||
from app import db
|
||||
@@ -8,9 +9,14 @@ from app.classes.service import (Service_Service,
|
||||
Service_Plans, Service_Plans_schema
|
||||
)
|
||||
from app.classes.auto import Auto_Delivery
|
||||
from flask_login import login_required
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@service.route("/all", methods=["GET"])
|
||||
@login_required
|
||||
def get_all_service_calls():
|
||||
logger.info("GET /service/all - Fetching all service calls for calendar")
|
||||
try:
|
||||
all_services = Service_Service.query.all()
|
||||
color_map = {
|
||||
@@ -49,18 +55,19 @@ def get_all_service_calls():
|
||||
|
||||
return jsonify(calendar_events), 200
|
||||
except Exception as e:
|
||||
# Add error logging to see what's happening
|
||||
print(f"An error occurred in /service/all: {e}")
|
||||
logger.error(f"Error in /service/all: {e}")
|
||||
return jsonify(error=str(e)), 500
|
||||
|
||||
|
||||
# --- THIS IS THE FIX ---
|
||||
# The logic from /all has been copied here to ensure a consistent data structure.
|
||||
@service.route("/upcoming", methods=["GET"])
|
||||
@login_required
|
||||
def get_upcoming_service_calls():
|
||||
"""
|
||||
Fetches a list of all future service calls from today onwards.
|
||||
"""
|
||||
logger.info("GET /service/upcoming - Fetching upcoming service calls")
|
||||
now = datetime.now()
|
||||
upcoming_services = (
|
||||
Service_Service.query
|
||||
@@ -78,6 +85,7 @@ def get_upcoming_service_calls():
|
||||
|
||||
|
||||
@service.route("/past", methods=["GET"])
|
||||
@login_required
|
||||
def get_past_service_calls():
|
||||
"""
|
||||
Fetches a list of all past service calls before today.
|
||||
@@ -97,6 +105,7 @@ def get_past_service_calls():
|
||||
|
||||
|
||||
@service.route("/today", methods=["GET"])
|
||||
@login_required
|
||||
def get_today_service_calls():
|
||||
"""
|
||||
Fetches a list of all service calls for today.
|
||||
@@ -119,6 +128,7 @@ def get_today_service_calls():
|
||||
|
||||
|
||||
@service.route("/upcoming/count", methods=["GET"])
|
||||
@login_required
|
||||
def get_upcoming_service_calls_count():
|
||||
now = datetime.now()
|
||||
try:
|
||||
@@ -128,6 +138,7 @@ def get_upcoming_service_calls_count():
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
@service.route("/for-customer/<int:customer_id>", methods=["GET"])
|
||||
@login_required
|
||||
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)
|
||||
@@ -135,6 +146,7 @@ def get_service_calls_for_customer(customer_id):
|
||||
return jsonify(result), 200
|
||||
|
||||
@service.route("/create", methods=["POST"])
|
||||
@login_required
|
||||
def create_service_call():
|
||||
data = request.get_json()
|
||||
if not data: return jsonify({"error": "No data provided"}), 400
|
||||
@@ -155,6 +167,7 @@ def create_service_call():
|
||||
return jsonify({ "ok": True, "id": new_service_call.id }), 201
|
||||
|
||||
@service.route("/update-cost/<int:id>", methods=["PUT"])
|
||||
@login_required
|
||||
def update_service_cost(id):
|
||||
"""
|
||||
Dedicated endpoint to update only the service cost for a service call.
|
||||
@@ -196,10 +209,11 @@ def update_service_cost(id):
|
||||
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
print(f"Error updating service cost for service {id}: {str(e)}")
|
||||
logger.error(f"Error updating service cost for service {id}: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
@service.route("/update/<int:id>", methods=["PUT"])
|
||||
@login_required
|
||||
def update_service_call(id):
|
||||
service_record = Service_Service.query.get_or_404(id)
|
||||
data = request.get_json()
|
||||
@@ -222,6 +236,7 @@ def update_service_call(id):
|
||||
|
||||
# Service Plans CRUD endpoints
|
||||
@service.route("/plans/active", methods=["GET"])
|
||||
@login_required
|
||||
def get_active_service_plans():
|
||||
"""
|
||||
Get all active service plans (contract_plan > 0)
|
||||
@@ -245,6 +260,7 @@ def get_active_service_plans():
|
||||
|
||||
|
||||
@service.route("/plans/customer/<int:customer_id>", methods=["GET"])
|
||||
@login_required
|
||||
def get_customer_service_plan(customer_id):
|
||||
"""
|
||||
Get service plan for a specific customer
|
||||
@@ -261,6 +277,7 @@ def get_customer_service_plan(customer_id):
|
||||
|
||||
|
||||
@service.route("/plans/create", methods=["POST"])
|
||||
@login_required
|
||||
def create_service_plan():
|
||||
"""
|
||||
Create a new service plan for a customer
|
||||
@@ -287,6 +304,7 @@ def create_service_plan():
|
||||
|
||||
|
||||
@service.route("/plans/update/<int:customer_id>", methods=["PUT"])
|
||||
@login_required
|
||||
def update_service_plan(customer_id):
|
||||
"""
|
||||
Update existing service plan for a customer
|
||||
@@ -317,6 +335,7 @@ def update_service_plan(customer_id):
|
||||
|
||||
|
||||
@service.route("/plans/delete/<int:customer_id>", methods=["DELETE"])
|
||||
@login_required
|
||||
def delete_service_plan(customer_id):
|
||||
"""
|
||||
Delete service plan for a customer
|
||||
@@ -334,12 +353,14 @@ def delete_service_plan(customer_id):
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
@service.route("/<int:id>", methods=["GET"])
|
||||
@login_required
|
||||
def get_service_by_id(id):
|
||||
service_record = Service_Service.query.get_or_404(id)
|
||||
service_schema = Service_Service_schema()
|
||||
return jsonify({"ok": True, "service": service_schema.dump(service_record)}), 200
|
||||
|
||||
@service.route("/delete/<int:id>", methods=["DELETE"])
|
||||
@login_required
|
||||
def delete_service_call(id):
|
||||
service_record = Service_Service.query.get_or_404(id)
|
||||
try:
|
||||
@@ -351,6 +372,7 @@ def delete_service_call(id):
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
@service.route("/parts/customer/<int:customer_id>", methods=["GET"])
|
||||
@login_required
|
||||
def get_service_parts(customer_id):
|
||||
parts = Service_Parts.query.filter_by(customer_id=customer_id).first()
|
||||
if parts:
|
||||
@@ -363,6 +385,7 @@ def get_service_parts(customer_id):
|
||||
}), 200
|
||||
|
||||
@service.route("/parts/update/<int:customer_id>", methods=["POST"])
|
||||
@login_required
|
||||
def update_service_parts(customer_id):
|
||||
try:
|
||||
data = request.get_json()
|
||||
@@ -397,6 +420,7 @@ def update_service_parts(customer_id):
|
||||
|
||||
|
||||
@service.route("/payment/<int:service_id>/<int:payment_type>", methods=["PUT"])
|
||||
@login_required
|
||||
def process_service_payment(service_id, payment_type):
|
||||
service = db.session.query(Service_Service).filter(Service_Service.id == service_id).first()
|
||||
if not service:
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
import logging
|
||||
from flask import jsonify, request
|
||||
import datetime
|
||||
from app.social import social
|
||||
from app import db
|
||||
|
||||
from app.classes.customer_social import (Customer_Customer_Social_schema,
|
||||
from app.classes.customer_social import (Customer_Customer_Social_schema,
|
||||
Customer_Customer_Social)
|
||||
from flask_login import login_required
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@social.route("/posts/<int:customer_id>/<int:page>", methods=["GET"])
|
||||
@login_required
|
||||
def get_customer_posts(customer_id, page):
|
||||
logger.info(f"GET /social/posts/{customer_id}/{page} - Fetching customer posts page {page}")
|
||||
per_page_amount = 50
|
||||
if page is None:
|
||||
offset_limit = 0
|
||||
@@ -16,7 +22,7 @@ def get_customer_posts(customer_id, page):
|
||||
offset_limit = 0
|
||||
else:
|
||||
offset_limit = (per_page_amount * page) - per_page_amount
|
||||
|
||||
|
||||
customer_posts = (db.session
|
||||
.query(Customer_Customer_Social)
|
||||
.filter(Customer_Customer_Social.customer_id == customer_id)
|
||||
@@ -28,8 +34,10 @@ def get_customer_posts(customer_id, page):
|
||||
|
||||
|
||||
@social.route("/create/<int:customer_id>", methods=["POST"])
|
||||
@login_required
|
||||
def create_post(customer_id):
|
||||
|
||||
logger.info(f"POST /social/create/{customer_id} - Creating new social post")
|
||||
|
||||
comment = request.json["comment"]
|
||||
poster_employee_id = request.json["poster_employee_id"]
|
||||
|
||||
@@ -47,7 +55,9 @@ def create_post(customer_id):
|
||||
|
||||
|
||||
@social.route("/posts/<int:post_id>", methods=["PATCH"])
|
||||
@login_required
|
||||
def edit_post(post_id):
|
||||
logger.info(f"PATCH /social/posts/{post_id} - Editing social post")
|
||||
|
||||
customer_post = (db.session
|
||||
.query(Customer_Customer_Social)
|
||||
@@ -55,7 +65,7 @@ def edit_post(post_id):
|
||||
.first())
|
||||
comment = request.json["comment"]
|
||||
customer_post.comment = comment
|
||||
|
||||
|
||||
db.session.add(customer_post)
|
||||
db.session.commit()
|
||||
|
||||
@@ -64,7 +74,9 @@ def edit_post(post_id):
|
||||
|
||||
|
||||
@social.route("/delete/<int:post_id>", methods=["DELETE"])
|
||||
@login_required
|
||||
def delete_post(post_id):
|
||||
logger.info(f"DELETE /social/delete/{post_id} - Deleting social post")
|
||||
|
||||
customer_post = (db.session
|
||||
.query(Customer_Customer_Social)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from flask import jsonify
|
||||
from datetime import date
|
||||
from app.stats import stats
|
||||
@@ -7,6 +8,8 @@ from app.classes.delivery import Delivery_Delivery
|
||||
from app.classes.stats_company import Stats_Company, Stats_Company_schema
|
||||
from app.classes.stats_customer import Stats_Customer, Stats_Customer_schema
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_monday_date(date_object):
|
||||
"""Gets the date of the Monday for the given date."""
|
||||
@@ -27,6 +30,7 @@ def get_monday_date(date_object):
|
||||
|
||||
@stats.route("/calls/add", methods=["PUT"])
|
||||
def total_calls_post():
|
||||
logger.info("PUT /stats/calls/add - Incrementing call count")
|
||||
total_calls_today = (db.session
|
||||
.query(Stats_Company)
|
||||
.filter(Stats_Company.expected_delivery_date == date.today())
|
||||
@@ -38,17 +42,18 @@ def total_calls_post():
|
||||
db.session.add(total_calls_today)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
|
||||
return jsonify({"ok": True,}), 200
|
||||
|
||||
|
||||
@stats.route("/calls/count/today", methods=["GET"])
|
||||
def total_calls_today():
|
||||
logger.info("GET /stats/calls/count/today - Getting today's call count")
|
||||
total_calls_today = (db.session
|
||||
.query(Stats_Company)
|
||||
.filter(Stats_Company.expected_delivery_date == date.today())
|
||||
.count())
|
||||
|
||||
|
||||
return jsonify({"ok": True,
|
||||
'data': total_calls_today,
|
||||
}), 200
|
||||
@@ -56,17 +61,18 @@ def total_calls_today():
|
||||
|
||||
@stats.route("/gallons/total/<int:driver_id>", methods=["GET"])
|
||||
def total_gallons_delivered_driver(driver_id):
|
||||
logger.info(f"GET /stats/gallons/total/{driver_id} - Calculating total gallons for driver")
|
||||
gallons_list = []
|
||||
|
||||
|
||||
total_gallons = db.session\
|
||||
.query(Delivery_Delivery)\
|
||||
.filter(Delivery_Delivery.driver_employee_id == driver_id)\
|
||||
.all()
|
||||
|
||||
|
||||
for f in total_gallons:
|
||||
gallons_list.append(f.gallons_delivered)
|
||||
sum_of_gallons = (sum(gallons_list))
|
||||
|
||||
|
||||
return jsonify({"ok": True,
|
||||
'data': sum_of_gallons,
|
||||
}), 200
|
||||
@@ -74,6 +80,7 @@ def total_gallons_delivered_driver(driver_id):
|
||||
|
||||
@stats.route("/delivery/total/<int:driver_id>", methods=["GET"])
|
||||
def total_deliveries_driver(driver_id):
|
||||
logger.info(f"GET /stats/delivery/total/{driver_id} - Counting total deliveries for driver")
|
||||
total_stops = (db.session
|
||||
.query(Delivery_Delivery)
|
||||
.filter(Delivery_Delivery.driver_employee_id == driver_id)
|
||||
@@ -85,12 +92,13 @@ def total_deliveries_driver(driver_id):
|
||||
|
||||
@stats.route("/primes/total/<int:driver_id>", methods=["GET"])
|
||||
def total_primes_driver(driver_id):
|
||||
logger.info(f"GET /stats/primes/total/{driver_id} - Counting prime deliveries for driver")
|
||||
total_stops = (db.session
|
||||
.query(Delivery_Delivery)
|
||||
.filter(Delivery_Delivery.driver_employee_id == driver_id)
|
||||
.filter(Delivery_Delivery.prime == 1)
|
||||
.count())
|
||||
|
||||
|
||||
|
||||
return jsonify({"ok": True,
|
||||
'data': total_stops,
|
||||
@@ -98,6 +106,7 @@ def total_primes_driver(driver_id):
|
||||
|
||||
@stats.route("/delivery/count/today", methods=["GET"])
|
||||
def total_deliveries_today():
|
||||
logger.info("GET /stats/delivery/count/today - Counting today's deliveries")
|
||||
total_stops = (db.session
|
||||
.query(Delivery_Delivery)
|
||||
.filter(Delivery_Delivery.expected_delivery_date == date.today())
|
||||
@@ -109,12 +118,13 @@ def total_deliveries_today():
|
||||
|
||||
@stats.route("/delivery/count/delivered/today", methods=["GET"])
|
||||
def total_deliveries_today_finished():
|
||||
logger.info("GET /stats/delivery/count/delivered/today - Counting completed deliveries today")
|
||||
total_stops = (db.session
|
||||
.query(Delivery_Delivery)
|
||||
.filter(Delivery_Delivery.expected_delivery_date == date.today())
|
||||
.filter((Delivery_Delivery.delivery_status == 10))
|
||||
.count())
|
||||
|
||||
|
||||
return jsonify({"ok": True,
|
||||
'data': total_stops,
|
||||
}), 200
|
||||
@@ -125,6 +135,7 @@ def get_user_stats(user_id):
|
||||
"""
|
||||
gets stats of user
|
||||
"""
|
||||
logger.info(f"GET /stats/user/{user_id} - Fetching user statistics")
|
||||
get_user = db.session \
|
||||
.query(Stats_Customer) \
|
||||
.filter(Stats_Customer.customer_id == user_id) \
|
||||
@@ -157,6 +168,7 @@ def get_user_last_delivery(user_id):
|
||||
"""
|
||||
gets users last delivery. used on profile page
|
||||
"""
|
||||
logger.info(f"GET /stats/user/lastdelivery/{user_id} - Fetching user's last delivery date")
|
||||
get_delivery= db.session \
|
||||
.query(Delivery_Delivery) \
|
||||
.filter(Delivery_Delivery.customer_id == user_id) \
|
||||
@@ -174,6 +186,7 @@ def get_user_last_delivery(user_id):
|
||||
|
||||
@stats.route("/gallons/week", methods=["GET"])
|
||||
def total_gallons_delivered_this_week():
|
||||
logger.info("GET /stats/gallons/week - Calculating weekly gallons delivered")
|
||||
# Get today's date
|
||||
total_gallons = 0
|
||||
|
||||
@@ -194,6 +207,7 @@ def total_gallons_delivered_this_week():
|
||||
|
||||
@stats.route("/gallons/check/total/<int:user_id>", methods=["GET"])
|
||||
def calculate_gallons_user(user_id):
|
||||
logger.info(f"GET /stats/gallons/check/total/{user_id} - Recalculating user total gallons")
|
||||
# Get today's date
|
||||
total_gallons = 0
|
||||
|
||||
@@ -215,4 +229,3 @@ def calculate_gallons_user(user_id):
|
||||
db.session.commit()
|
||||
return jsonify({"ok": True,
|
||||
}), 200
|
||||
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import logging
|
||||
from flask import jsonify
|
||||
from app.ticket import ticket
|
||||
from app import db
|
||||
from app.classes.delivery import Delivery_Delivery
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ticket.route("/<int:ticket_id>", methods=["GET"])
|
||||
def get_ticket_printer_letter(ticket_id):
|
||||
logger.info(f"GET /ticket/{ticket_id} - Generating ticket printer letter")
|
||||
|
||||
|
||||
|
||||
return jsonify({"ok": True,
|
||||
|
||||
|
||||
}), 200
|
||||
|
||||
Reference in New Issue
Block a user