diff --git a/README.md b/README.md index 8aadaa3..7437393 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,80 @@ -# Eamco Playground +# EAMCO Playground -This is a FastAPI project for Eamco playground application. +**EAMCO Playground** is a non-production, sandboxed microservice used for development, testing, and experimentation. It provides a safe and isolated environment for prototyping new features and refining complex algorithms before they are integrated into the core production services. + +Think of this as the R&D department's workshop. It often contains experimental or alternative versions of logic found in other services like `eamco_auto_api`. + +[![Language](https://img.shields.io/badge/Language-Python-blue)](https://www.python.org/) +[![Framework](https://img.shields.io/badge/Framework-FastAPI-green)](https://fastapi.tiangolo.com/) +[![Database](https://img.shields.io/badge/Database-PostgreSQL-blue)](https://www.postgresql.org/) + +--- + +## Purpose + +The primary purpose of the Playground is to facilitate development and testing without affecting live data. Key use cases include: + +- **Algorithm Refinement**: Testing new versions of the "K-Factor" (house consumption factor) calculation, as seen in `app/script/update_auto.py`. +- **New Integrations**: Evaluating new third-party services, such as testing the `pyowm` library as an alternative for weather data. +- **API Simulation**: Mimicking the endpoints of other microservices to test interactions and data flow in a controlled environment. +- **Debugging**: Providing a space to replicate and diagnose complex issues found in the production system without the risk of data corruption. + +**This service should NOT be deployed to a production environment.** + +--- + +## Key Components + +- **Experimental Scripts**: The `app/script/` directory contains experimental logic. For example, `update_auto.py` holds a specific implementation of the K-Factor refinement algorithm. +- **Weather API Integration**: Uses the `pyowm` library to connect to the OpenWeatherMap API, likely for testing purposes. +- **Simulated API Routers**: Includes routers for `/main`, `/delivery`, `/confirm`, and `/info` that mirror the structure of other services, allowing developers to test frontend interactions or service-to-service communication. + +--- + +## Getting Started + +### Prerequisites + +- Python 3.10+ +- A PostgreSQL database (preferably a dedicated development or test instance). + +### Installation + +1. **Clone the repository and navigate into it.** + +2. **Create a virtual environment and install dependencies:** + ```bash + python -m venv venv + source venv/bin/activate + pip install -r requirements.txt + ``` + +3. **Configure your environment:** + The application's configuration is managed by environment variables set in `settings_local.py`, `settings_dev.py`, or `settings_prod.py`. Ensure your database connection URI and any API keys (like for OpenWeatherMap) are set correctly in your chosen settings file. + +### Running the Service + +This service is intended for development use. + +```bash +export MODE=DEVELOPMENT +uvicorn main:app --reload --host 0.0.0.0 --port +``` + +--- + +## Project Structure + +``` +eamco_playground/ +├── app/ +│ ├── models/ # SQLAlchemy ORM models +│ ├── routers/ # API endpoint definitions for simulating other services +│ ├── schema/ # Pydantic models +│ └── script/ # Experimental scripts and algorithms +├── config.py # Logic for loading environment-specific settings +├── database.py # SQLAlchemy engine and session setup +├── main.py # FastAPI application entry point +├── requirements.txt # Python dependencies +└── README.md # This file +``` \ No newline at end of file diff --git a/app/routers/confirm.py b/app/routers/confirm.py index 18ff681..cada9f8 100644 --- a/app/routers/confirm.py +++ b/app/routers/confirm.py @@ -1,7 +1,8 @@ -from fastapi import APIRouter, Request +from fastapi import APIRouter, Request, Depends from datetime import date -from database import session +from sqlalchemy.orm import Session +from database import get_db from pyowm import OWM from decimal import Decimal from app.models.auto import Auto_Delivery, Tickets_Auto_Delivery @@ -19,14 +20,14 @@ router = APIRouter( @router.put("/auto/update/{autoid}") -async def update_auto(autoid: int, request: Request): +async def update_auto(autoid: int, request: Request, db: Session = Depends(get_db)): request_body = await request.json() gallons_delivered = request_body['gallons_delivered'] gallons_delivered = Decimal(gallons_delivered) - get_auto_delivery = (session + get_auto_delivery = (db .query(Auto_Delivery) .filter(Auto_Delivery.id == autoid) .first()) @@ -50,9 +51,9 @@ async def update_auto(autoid: int, request: Request): get_auto_delivery.auto_status = 1 get_auto_delivery.days_since_last_fill = 0 - session.add(get_auto_delivery) + db.add(get_auto_delivery) - session.commit() + db.commit() return ({"ok": True}), 200 @@ -60,7 +61,7 @@ async def update_auto(autoid: int, request: Request): @router.post("/auto/create/{autoid}") -async def create_auto_ticket(autoid: int, request: Request): +async def create_auto_ticket(autoid: int, request: Request, db: Session = Depends(get_db)): request_body = await request.json() @@ -68,11 +69,11 @@ async def create_auto_ticket(autoid: int, request: Request): gallons_delivered = Decimal(gallons_delivered) - get_auto_delivery = (session + get_auto_delivery = (db .query(Auto_Delivery) .filter(Auto_Delivery.id == autoid) .first()) - get_todays_price = (session.query(Pricing_Oil_Oil) + get_todays_price = (db.query(Pricing_Oil_Oil) .order_by(Pricing_Oil_Oil.id.desc()) .first()) gallons_put_in_home = Decimal(gallons_delivered) @@ -95,9 +96,9 @@ async def create_auto_ticket(autoid: int, request: Request): ) - session.add(create_new_ticket) + db.add(create_new_ticket) - session.commit() + db.commit() return ({ "ok": True, diff --git a/app/routers/delivery.py b/app/routers/delivery.py index c2b9e9d..a6bd397 100644 --- a/app/routers/delivery.py +++ b/app/routers/delivery.py @@ -1,7 +1,8 @@ from fastapi import APIRouter, Request, Depends from fastapi.responses import JSONResponse from fastapi.encoders import jsonable_encoder -from database import session +from sqlalchemy.orm import Session +from database import get_db from app.models.auto import Auto_Delivery, Tickets_Auto_Delivery from app.models.delivery import Delivery @@ -17,9 +18,9 @@ router = APIRouter( @router.get("/past/{customer_id}", status_code=200) -def past(customer_id: int): +def past(customer_id: int, db: Session = Depends(get_db)): - get_customer_past_delivery = (session + get_customer_past_delivery = (db .query(Delivery) .filter(Delivery.customer_id == customer_id) .order_by(Delivery.id.desc()) @@ -30,11 +31,11 @@ def past(customer_id: int): @router.get("/all/customers", status_code=200) -def get_delivery_customers(): +def get_delivery_customers(db: Session = Depends(get_db)): automatics = ( - session.query(Auto_Delivery) + db.query(Auto_Delivery) .filter(Auto_Delivery.auto_status == 1) .order_by(Auto_Delivery.estimated_gallons_left.asc()) .all() @@ -45,9 +46,9 @@ def get_delivery_customers(): @router.get("/driver/{driver_employee_id}", status_code=200) -def get_delivery_for_specific_driver(driver_employee_id: int): +def get_delivery_for_specific_driver(driver_employee_id: int, db: Session = Depends(get_db)): automatics = ( - session.query(Delivery) + db.query(Delivery) .filter(Delivery.driver_employee_id == driver_employee_id) .filter(Delivery.automatic == 1) .filter(Delivery.delivery_status == 0) @@ -58,10 +59,10 @@ def get_delivery_for_specific_driver(driver_employee_id: int): @router.get("/{auto_id}", status_code=200) -def get_auto(auto_id): +def get_auto(auto_id, db: Session = Depends(get_db)): get_delivery = ( - session.query(Auto_Delivery) + db.query(Auto_Delivery) .filter(Auto_Delivery.id == auto_id) .first() ) @@ -71,10 +72,10 @@ def get_auto(auto_id): @router.get("/delivery/{delivery_id_order}", status_code=200) -def get_delivery(delivery_id_order): +def get_delivery(delivery_id_order, db: Session = Depends(get_db)): get_delivery = ( - session.query(Tickets_Auto_Delivery) + db.query(Tickets_Auto_Delivery) .filter(Tickets_Auto_Delivery.id == delivery_id_order) .first() ) @@ -83,10 +84,10 @@ def get_delivery(delivery_id_order): @router.get("/all/profile/{customer_id}", status_code=200) -def get_autos_customers(customer_id): +def get_autos_customers(customer_id, db: Session = Depends(get_db)): get_delivery = ( - session.query(Tickets_Auto_Delivery) + db.query(Tickets_Auto_Delivery) .filter(Tickets_Auto_Delivery.customer_id == customer_id) .order_by(Tickets_Auto_Delivery.id.asc()) .all() diff --git a/app/routers/info.py b/app/routers/info.py new file mode 100644 index 0000000..cebbda8 --- /dev/null +++ b/app/routers/info.py @@ -0,0 +1,68 @@ +from fastapi import APIRouter, Depends +from sqlalchemy.orm import Session +from datetime import datetime +from app.models.customer import Customer_Customer +from app.models.delivery import Delivery +from database import get_db +from sqlalchemy import func + +router = APIRouter( + prefix="/info", + tags=["info"], +) + +def get_customers_without_delivery_since(db: Session, date_threshold: datetime): + """ + Queries all customers who haven't received a delivery since the specified date. + + Args: + db: The database session. + date_threshold: The date threshold. Customers whose last delivery is + before this date (or have no deliveries) will be returned. + + Returns: + A tuple containing the count and a list of Customer_Customer objects. + """ + # Subquery to find the last delivery date for each customer + last_delivery_subquery = ( + db.query( + Delivery.customer_id, + func.max(Delivery.when_delivered).label("last_delivery_date") + ) + .group_by(Delivery.customer_id) + .subquery() + ) + + # Main query to join customers with their last delivery date + # and filter based on the date threshold + customers = ( + db.query(Customer_Customer) + .outerjoin( + last_delivery_subquery, + Customer_Customer.id == last_delivery_subquery.c.customer_id + ) + .filter( + (last_delivery_subquery.c.last_delivery_date < date_threshold) | + (last_delivery_subquery.c.last_delivery_date == None) + ) + .all() + ) + return len(customers), customers + +@router.get("/customers/no_delivery_since/{year}/{month}/{day}") +async def customers_no_delivery_since( + year: int, + month: int, + day: int, + db: Session = Depends(get_db) +): + """ + Get customers who have not had a delivery since the specified date. + """ + try: + threshold_date = datetime(year, month, day).date() + count, customers = get_customers_without_delivery_since(db, threshold_date) + return {"customer_count": count, "customers": customers} + except ValueError as e: + return {"error": str(e)} + diff --git a/app/routers/main.py b/app/routers/main.py index 677e4cf..0590668 100644 --- a/app/routers/main.py +++ b/app/routers/main.py @@ -1,31 +1,15 @@ ## File: app/routers/main.py (or your equivalent path) -from fastapi import APIRouter, HTTPException +from fastapi import APIRouter, HTTPException, Depends from datetime import datetime from sqlalchemy.orm import Session from sqlalchemy import func # Your existing imports -from database import session +from database import get_db from pyowm import OWM -from app.models.customer import Customer_Customer -from app.models.cards import Card_Card -# Imports needed for the migration task. -# YOU MUST ADJUST THESE IMPORTS TO MATCH YOUR PROJECT'S ACTUAL STRUCTURE. -from database import session # Assuming your SessionLocal is here for a clean session -from authorizenet import apicontractsv1 -from authorizenet.constants import constants -from authorizenet.apicontrollers import ( - createCustomerProfileController, - createCustomerPaymentProfileController - -) -from config import load_config # Assuming you have this - -# Load Authorize.net credentials -ApplicationConfig = load_config() # --- ROUTER DEFINITION --- router = APIRouter( @@ -33,323 +17,3 @@ router = APIRouter( tags=["main"], responses={404: {"description": "Not found"}}, ) - -if ApplicationConfig.CURRENT_SETTINGS == 'PRODUCTION': - constants.environment = constants.PRODUCTION - VALIDATION_MODE = "liveMode" - API_LOGIN_ID = ApplicationConfig.API_LOGIN_ID - TRANSACTION_KEY = ApplicationConfig.TRANSACTION_KEY -else: - constants.environment = constants.SANDBOX - constants.show_url_on_request = True - VALIDATION_MODE = "testMode" - API_LOGIN_ID = ApplicationConfig.API_LOGIN_ID - TRANSACTION_KEY = ApplicationConfig.TRANSACTION_KEY - - - -state_abbrevs = ['MA', 'RI', 'NH', 'ME', 'VT', 'CT', 'NY'] - -@router.post("/maintenance/migrate-cards-now") -def run_card_migration_synchronously(): - """ - Triggers a one-time, SYNCHRONOUS task to migrate all existing, insecurely - stored credit cards from the `card_card` table to secure Authorize.Net CIM profiles. - This function is self-contained and does not use `crud` or `schemas`. - - WARNING: This is a long-running process and the request may time out. - Monitor server logs for completion. This endpoint should be removed after use. - """ - - def _create_authnet_profile(customer_obj: Customer_Customer, card_obj: Card_Card): - """Helper to create a new Authorize.Net Customer Profile.""" - merchantAuth = apicontractsv1.merchantAuthenticationType(name=API_LOGIN_ID, transactionKey=TRANSACTION_KEY) - expiration_date_str = f"{card_obj.expiration_year}-{str(card_obj.expiration_month).zfill(2)}" - - # Validate expiration - month = None - year = None - if card_obj.expiration_month: - try: - month = int(card_obj.expiration_month) - except: - pass - if card_obj.expiration_year: - try: - year = int(card_obj.expiration_year) - except: - pass - if not year or not month or month < 1 or month > 12 or year < 2000 or year > 2050: - raise ValueError(f"Invalid expiration year={card_obj.expiration_year}, month={card_obj.expiration_month} for card ID {card_obj.id}") - expiration_date_str = f"{year:04d}-{month:02d}" - # // FIX 1: Sanitize card number by removing all non-digit characters - sanitized_card_number = ''.join(filter(str.isdigit, str(card_obj.card_number))) - if len(sanitized_card_number) < 13 or len(sanitized_card_number) > 19 or not sanitized_card_number.isdigit(): - raise ValueError(f"Invalid card number length {len(sanitized_card_number)} or non-numeric for card ID {card_obj.id}") - # Sanitize CVV - cardCode = str(card_obj.security_number).strip() - if len(cardCode) < 3 or len(cardCode) > 4 or not cardCode.isdigit(): - raise ValueError(f"Invalid CVV length {len(cardCode)} or non-numeric for card ID {card_obj.id}") - # Get dynamic state - the_state = state_abbrevs[customer_obj.customer_state] if 0 <= customer_obj.customer_state < len(state_abbrevs) else 'MA' - - # Debug print - print(f"DEBUG SEND CREATE: cardNumber='{sanitized_card_number}', expirationDate='{expiration_date_str}', cardCode='{cardCode}', customerID={customer_obj.id}, name='{customer_obj.customer_first_name} {customer_obj.customer_last_name}', address='{customer_obj.customer_address}', city='{customer_obj.customer_town}', state='{the_state}', zip='{customer_obj.customer_zip}', country='USA', phone='{customer_obj.customer_phone_number}', email='{customer_obj.customer_email}'") - - creditCard = apicontractsv1.creditCardType( - cardNumber=sanitized_card_number, - expirationDate=expiration_date_str, - cardCode=cardCode - ) - billTo = apicontractsv1.customerAddressType( - firstName=customer_obj.customer_first_name, - lastName=customer_obj.customer_last_name, - address=customer_obj.customer_address, - city=customer_obj.customer_town, - state=the_state, - zip=customer_obj.customer_zip, - country="USA", - phoneNumber=customer_obj.customer_phone_number - ) - paymentProfile = apicontractsv1.customerPaymentProfileType( - billTo=billTo, - payment=apicontractsv1.paymentType(creditCard=creditCard), - defaultPaymentProfile=True - ) - customerProfile = apicontractsv1.customerProfileType( - merchantCustomerId=str(customer_obj.id), - email=customer_obj.customer_email, - paymentProfiles=[paymentProfile] - ) - request = apicontractsv1.createCustomerProfileRequest( - merchantAuthentication=merchantAuth, - profile=customerProfile, - validationMode="testMode" - ) - controller = createCustomerProfileController(request) - if ApplicationConfig.CURRENT_SETTINGS == 'PRODUCTION': - controller.setenvironment(constants.PRODUCTION) - controller.execute() - elif ApplicationConfig.CURRENT_SETTINGS == 'LOCAL': - controller.setenvironment(constants.PRODUCTION) - controller.execute() - else: - controller.execute() - response = controller.getresponse() - - if response.messages.resultCode == "Ok": - profile_id = response.customerProfileId if hasattr(response, 'customerProfileId') else None - payment_ids = response.customerPaymentProfileIdList.numericString if hasattr(response, 'customerPaymentProfileIdList') and hasattr(response.customerPaymentProfileIdList, 'numericString') else [] - payment_id = payment_ids[0] if payment_ids else None - return str(profile_id), str(payment_id) if payment_id else None - else: - # Handle errors - error_msg = "Unknown Authorize.Net Error" - if response is not None and hasattr(response, 'messages') and response.messages is not None and hasattr(response.messages, 'message') and response.messages.message: - msg = response.messages.message[0] if isinstance(response.messages.message, list) else response.messages.message - if msg and hasattr(msg, 'text') and msg.text is not None: - if isinstance(msg.text, str): - error_msg = msg.text - else: - # Handle case where text might be an object with 'text' attribute - error_msg = msg.text.text if hasattr(msg.text, 'text') else str(msg.text) - print(f" AUTH.NET ERROR: {error_msg}") - return None, None - - def _add_authnet_payment_profile(profile_id: str, customer_obj: Customer_Customer, card_obj: Card_Card): - """Helper to add a new Payment Profile to an existing Customer Profile.""" - merchantAuth = apicontractsv1.merchantAuthenticationType(name=API_LOGIN_ID, transactionKey=TRANSACTION_KEY) - expiration_date_str = f"{card_obj.expiration_year}-{str(card_obj.expiration_month).zfill(2)}" - # State abbreviations list - - # // FIX 1 (Applied here as well): Sanitize card number - sanitized_card_number = ''.join(filter(str.isdigit, str(card_obj.card_number))) - - creditCard = apicontractsv1.creditCardType( - cardNumber=sanitized_card_number, - expirationDate=expiration_date_str, - cardCode=str(card_obj.security_number).strip() - ) - # Get dynamic state - the_state = state_abbrevs[customer_obj.customer_state] if 0 <= customer_obj.customer_state < len(state_abbrevs) else 'MA' - - billTo = apicontractsv1.customerAddressType( - firstName=customer_obj.customer_first_name, - lastName=customer_obj.customer_last_name, - address=customer_obj.customer_address, - city=customer_obj.customer_town, - state=the_state, - zip=customer_obj.customer_zip, - country="USA", - phoneNumber=customer_obj.customer_phone_number - ) - paymentProfile = apicontractsv1.customerPaymentProfileType( - billTo=billTo, - payment=apicontractsv1.paymentType(creditCard=creditCard), - defaultPaymentProfile=False - ) - request = apicontractsv1.createCustomerPaymentProfileRequest( - merchantAuthentication=merchantAuth, - customerProfileId=profile_id, - paymentProfile=paymentProfile, - validationMode="testMode" - ) - controller = createCustomerPaymentProfileController(request) - if ApplicationConfig.CURRENT_SETTINGS == 'PRODUCTION': - controller.setenvironment(constants.PRODUCTION) - controller.execute() - elif ApplicationConfig.CURRENT_SETTINGS == 'LOCAL': - controller.setenvironment(constants.PRODUCTION) - controller.execute() - else: - controller.execute() - - response = controller.getresponse() - if response.messages.resultCode == "Ok": - return str(response.customerPaymentProfileId) - else: - # // FIX 2 (Applied here as well): Robust error message parsing - error_msg = "Unknown Authorize.Net Error" - if response is not None and hasattr(response, 'messages') and response.messages is not None and hasattr(response.messages, 'message') and response.messages.message: - msg = response.messages.message[0] - if hasattr(msg, 'text') and msg.text is not None: - error_msg = msg.text.text - print(f" AUTH.NET ERROR: {error_msg}") - return None - - - - # --- MIGRATION SCRIPT LOGIC --- - print("="*60) - print("MIGRATION STARTED: Migrating all customer cards to Authorize.Net CIM.") - print(f"Start Time: {datetime.now()}") - print("="*60) - - customers_processed = 0 - cards_migrated = 0 - error_count = 0 - - try: - customers_to_migrate = (session - .query(Customer_Customer) - .filter(Customer_Customer.auth_net_profile_id == None) - .all()) - - total_customers = len(customers_to_migrate) - print(f"Found {total_customers} customers to migrate.") - - for index, customer in enumerate(customers_to_migrate): - customers_processed += 1 - print(f"\n--- Processing Customer {index + 1}/{total_customers} (ID: {customer.id}, Name: {customer.customer_first_name}) ---") - - insecure_cards = (session - .query(Card_Card) - .filter(Card_Card.user_id == customer.id) - .all()) - - print(f"DEBUG: Customer {customer.id} has {len(insecure_cards)} cards") - customer_profile_id_for_session = None - - # # Check for existing profile - # existing_profile, existing_payment_ids = _get_existing_profile(str(customer.id)) - # if existing_profile and existing_payment_ids: - # print(f" -> Found existing Authorize.Net profile ID {existing_profile}") - # customer.auth_net_profile_id = existing_profile - # session.add(customer) - # session.commit() - # for i, card_data in enumerate(insecure_cards): - # if i < len(existing_payment_ids): - # display_card_number = ''.join(filter(str.isdigit, str(card_data.card_number))) - # if not display_card_number: - # print(f" SKIPPING CARD: Card number is empty after sanitization for card ID {card_data.id}") - # error_count += 1 - # continue - # card_data.auth_net_payment_profile_id = existing_payment_ids[i] - # session.add(card_data) - # session.commit() - # print(f" SUCCESS: Mapped existing Payment ID {existing_payment_ids[i]} to card ending ...{display_card_number[-4:]}") - # cards_migrated += 1 - # else: - # print(f" WARNING: No existing payment profile Kawasaki for card {card_data.id}") - # error_count += 1 - # continue # skip creation loop - - for i, card_data in enumerate(insecure_cards): - try: - # Basic data validation before sending - if not card_data.card_number or not card_data.expiration_year or not card_data.expiration_month: - print(f" SKIPPING CARD: Incomplete card data for card ID {card_data.id}.") - error_count += 1 - continue - - print(f"DEBUG RAW: Card ID {card_data.id}: number='{card_data.card_number}', year='{card_data.expiration_year}', month='{card_data.expiration_month}', cvv='{card_data.security_number}', name='{customer.customer_first_name} {customer.customer_last_name}'") - - # Sanitize card number for display - display_card_number = ''.join(filter(str.isdigit, str(card_data.card_number))) - - if not display_card_number: - print(f" SKIPPING CARD: Card number is empty after sanitization for card ID {card_data.id}.") - error_count += 1 - continue - - if i == 0: - print(f" -> Creating new CIM profile with card ending in ...{display_card_number[-4:]}") - profile_id, payment_id = _create_authnet_profile(customer, card_data) - - if profile_id and payment_id: - customer.auth_net_profile_id = profile_id - session.add(customer) - - customer_profile_id_for_session = profile_id - - card_data.auth_net_payment_profile_id = payment_id - session.add(card_data) - session.commit() - - print(f" SUCCESS: Created Profile ID {profile_id} and Payment ID {payment_id}") - cards_migrated += 1 - else: - print(f" ERROR: Failed to create profile for customer {customer.id}.") - error_count += 1 - break - else: - if not display_card_number: - print(f" SKIPPING CARD: Card number is empty after sanitization for card ID {card_data.id}.") - error_count += 1 - continue - print(f" -> Adding additional card ending in ...{display_card_number[-4:]}") - payment_id = _add_authnet_payment_profile(customer_profile_id_for_session, customer, card_data) - if payment_id: - card_data.auth_net_payment_profile_id = payment_id - session.add(card_data) - session.commit() - print(f" SUCCESS: Added Payment ID {payment_id}") - cards_migrated += 1 - else: - print(f" ERROR: Failed to add additional card for customer {customer.id}.") - error_count += 1 - - except Exception as e: - print(f" CRITICAL ERROR processing a card for customer {customer.id}: {str(e)}") - error_count += 1 - session.rollback() - - except Exception as e: - print(f"A critical error occurred during the migration process: {e}") - session.rollback() - return {"ok": False, "error": f"Migration failed with a critical error: {e}"}, 500 - - finally: - print("="*60) - print("MIGRATION FINISHED!") - print(f"End Time: {datetime.now()}") - print(f"Summary: Processed {customers_processed} customers, migrated {cards_migrated} cards, encountered {error_count} errors.") - print("="*60) - - return { - "ok": True, - "message": "Migration process completed successfully.", - "customers_processed": customers_processed, - "cards_migrated": cards_migrated, - "errors": error_count, - }, 200 diff --git a/app/script/update_auto.py b/app/script/update_auto.py index e88678e..9eec846 100644 --- a/app/script/update_auto.py +++ b/app/script/update_auto.py @@ -1,5 +1,5 @@ from decimal import Decimal -from database import session +from database import Session @@ -23,4 +23,4 @@ def calc_home_factor(gallons_put_in_home, current_house_factor): customer_home_factor = Decimal(current_house_factor) if customer_home_factor <= 0: customer_home_factor = Decimal(.25) - return customer_home_factor \ No newline at end of file + return customer_home_factor diff --git a/database.py b/database.py index 1d2ab9b..fb3b3b2 100644 --- a/database.py +++ b/database.py @@ -22,7 +22,13 @@ url = URL.create( engine = create_engine(url) Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) -session = Session() Base = declarative_base() -Base.metadata.create_all(engine) \ No newline at end of file +Base.metadata.create_all(engine) + +def get_db(): + db = Session() + try: + yield db + finally: + db.close() \ No newline at end of file diff --git a/main.py b/main.py index 532059d..cdf8ac6 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,5 @@ from fastapi import FastAPI -from app.routers import main, delivery, confirm +from app.routers import main, delivery, confirm, info from fastapi.middleware.cors import CORSMiddleware @@ -9,6 +9,7 @@ app = FastAPI() app.include_router(main.router) app.include_router(delivery.router) app.include_router(confirm.router) +app.include_router(info.router) origins = [ "http://localhost:9000", diff --git a/requirements.txt b/requirements.txt index 8fe2749..afcd1bc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,3 @@ psycopg2-binary sqlalchemy pyowm setuptools -authorizenet \ No newline at end of file diff --git a/settings_dev.py b/settings_dev.py index 9920db2..35ab089 100644 --- a/settings_dev.py +++ b/settings_dev.py @@ -30,5 +30,3 @@ class ApplicationConfig: "http://localhost:9516", # Authorize service port ] - API_LOGIN_ID = '9U6w96gZmX' - TRANSACTION_KEY = '94s6Qy458mMNJr7G'