192 lines
8.2 KiB
Python
192 lines
8.2 KiB
Python
from fastapi import Depends, HTTPException, status, APIRouter
|
|
from fastapi.security import OAuth2PasswordBearer
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy import select, update
|
|
import logging
|
|
from database import get_db
|
|
from models import Account_User, Customer_Customer, Customer_Description, Card
|
|
from schemas import TokenData, CustomerUpdate
|
|
from jose import JWTError, jwt
|
|
from config import load_config
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Load JWT configuration from environment
|
|
ApplicationConfig = load_config()
|
|
SECRET_KEY = ApplicationConfig.JWT_SECRET_KEY
|
|
ALGORITHM = ApplicationConfig.JWT_ALGORITHM
|
|
|
|
async def get_current_user(token: str = Depends(OAuth2PasswordBearer(tokenUrl="auth/login")), db: AsyncSession = Depends(get_db)):
|
|
credentials_exception = HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail="Could not validate credentials",
|
|
headers={"WWW-Authenticate": "Bearer"},
|
|
)
|
|
try:
|
|
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
|
username: str = payload.get("sub")
|
|
if username is None:
|
|
raise credentials_exception
|
|
token_data = TokenData(username=username)
|
|
except JWTError:
|
|
raise credentials_exception
|
|
user = await db.execute(select(Account_User).where(Account_User.username == token_data.username))
|
|
user = user.scalar_one_or_none()
|
|
if user is None:
|
|
raise credentials_exception
|
|
return user
|
|
|
|
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="auth/login")
|
|
|
|
router = APIRouter()
|
|
|
|
@router.get("/me")
|
|
async def read_users_me(current_user: Account_User = Depends(get_current_user), db: AsyncSession = Depends(get_db)):
|
|
# Get customer details for the current user using user_id
|
|
customer = None
|
|
if current_user.user_id:
|
|
customer_result = await db.execute(select(Customer_Customer).where(Customer_Customer.id == current_user.user_id))
|
|
customer = customer_result.scalar_one_or_none()
|
|
|
|
# Get house description if exists
|
|
house_description = None
|
|
if customer:
|
|
description_record = await db.execute(
|
|
select(Customer_Description).where(Customer_Description.customer_id == customer.id)
|
|
)
|
|
description_record = description_record.scalar_one_or_none()
|
|
if description_record:
|
|
house_description = description_record.description
|
|
|
|
# Map state code to name
|
|
state_mapping = {0: "MA", 1: "NH"} # Add more as needed
|
|
state_name = state_mapping.get(customer.customer_state, str(customer.customer_state)) if customer else None
|
|
|
|
return {
|
|
"id": current_user.id,
|
|
"username": current_user.username,
|
|
"email": current_user.email,
|
|
"account_number": current_user.account_number,
|
|
"customer_first_name": customer.customer_first_name if customer else None,
|
|
"customer_last_name": customer.customer_last_name if customer else None,
|
|
"customer_address": customer.customer_address if customer else None,
|
|
"customer_apt": customer.customer_apt if customer else None,
|
|
"customer_town": customer.customer_town if customer else None,
|
|
"customer_state": state_name,
|
|
"customer_zip": customer.customer_zip if customer else None,
|
|
"customer_phone_number": customer.customer_phone_number if customer else None,
|
|
"customer_home_type": customer.customer_home_type if customer else None,
|
|
"customer_email": customer.customer_email if customer else None,
|
|
"house_description": house_description,
|
|
"member_since": current_user.member_since,
|
|
"last_seen": current_user.last_seen
|
|
}
|
|
|
|
@router.put("/update-customer")
|
|
async def update_customer_info(
|
|
customer_data: CustomerUpdate,
|
|
current_user: Account_User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db)
|
|
):
|
|
if not current_user.user_id:
|
|
raise HTTPException(status_code=404, detail="Customer not found")
|
|
|
|
try:
|
|
# Update Customer_Customer table
|
|
customer_update_data = customer_data.dict(exclude_unset=True)
|
|
customer_fields = {
|
|
'customer_first_name', 'customer_last_name', 'customer_address', 'customer_apt',
|
|
'customer_town', 'customer_state', 'customer_zip', 'customer_phone_number',
|
|
'customer_home_type', 'customer_email'
|
|
}
|
|
|
|
customer_update_dict = {k: v for k, v in customer_update_data.items() if k in customer_fields}
|
|
|
|
if customer_update_dict:
|
|
await db.execute(
|
|
update(Customer_Customer)
|
|
.where(Customer_Customer.id == current_user.user_id)
|
|
.values(**customer_update_dict)
|
|
)
|
|
|
|
# Update house description if provided
|
|
if 'house_description' in customer_update_data and customer_update_data['house_description']:
|
|
# Get customer record
|
|
customer = await db.execute(
|
|
select(Customer_Customer).where(Customer_Customer.id == current_user.user_id)
|
|
)
|
|
customer = customer.scalar_one_or_none()
|
|
|
|
if customer:
|
|
# Check if description record exists
|
|
description_record = await db.execute(
|
|
select(Customer_Description).where(Customer_Description.customer_id == customer.id)
|
|
)
|
|
description_record = description_record.scalar_one_or_none()
|
|
|
|
if description_record:
|
|
# Update existing
|
|
await db.execute(
|
|
update(Customer_Description)
|
|
.where(Customer_Description.customer_id == customer.id)
|
|
.values(description=customer_update_data['house_description'])
|
|
)
|
|
else:
|
|
# Create new
|
|
new_description = Customer_Description(
|
|
customer_id=customer.id,
|
|
account_number=current_user.account_number,
|
|
company_id=customer.company_id or 1,
|
|
fill_location=0,
|
|
description=customer_update_data['house_description']
|
|
)
|
|
db.add(new_description)
|
|
|
|
await db.commit()
|
|
|
|
# Sync billing info to Authorize.net if address-related fields were updated
|
|
billing_fields = {
|
|
'customer_first_name', 'customer_last_name', 'customer_address',
|
|
'customer_town', 'customer_state', 'customer_zip', 'customer_phone_number',
|
|
'customer_email'
|
|
}
|
|
if any(k in customer_update_dict for k in billing_fields):
|
|
# Late import to avoid circular dependency
|
|
from routes.payment.routes import update_customer_profile, update_payment_profile_billing
|
|
|
|
# Refetch the updated customer
|
|
customer_result = await db.execute(
|
|
select(Customer_Customer).where(Customer_Customer.id == current_user.user_id)
|
|
)
|
|
updated_customer = customer_result.scalar_one_or_none()
|
|
|
|
if updated_customer and updated_customer.auth_net_profile_id:
|
|
# Update customer profile in Authorize.net
|
|
update_customer_profile(updated_customer.auth_net_profile_id, updated_customer)
|
|
|
|
# Update all saved payment profiles with new billing info
|
|
cards_result = await db.execute(
|
|
select(Card).where(Card.user_id == updated_customer.id)
|
|
)
|
|
cards = cards_result.scalars().all()
|
|
|
|
for card in cards:
|
|
if card.auth_net_payment_profile_id:
|
|
update_payment_profile_billing(
|
|
customer_profile_id=updated_customer.auth_net_profile_id,
|
|
payment_profile_id=card.auth_net_payment_profile_id,
|
|
customer=updated_customer,
|
|
card=card
|
|
)
|
|
|
|
logger.info(f"Synced billing info to Authorize.net for customer {updated_customer.id}")
|
|
|
|
return {"message": "Customer information updated successfully"}
|
|
|
|
except Exception as e:
|
|
await db.rollback()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Failed to update customer information: {str(e)}"
|
|
)
|