from flask import jsonify, request from app.payment import payment from app import db from app.classes.customer import Customer_Customer 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 def set_card_main(user_id, card_id): """ updates a card of a user """ get_card_count = ( db.session .query(Card_Card) .filter(Card_Card.user_id == user_id) .count() ) get_card = ( db.session .query(Card_Card) .filter(Card_Card.user_id == user_id) .filter(Card_Card.id == card_id) .first() ) if get_card_count > 0: get_old_card = ( db.session .query(Card_Card) .filter(Card_Card.main_card == True) .filter(Card_Card.user_id == user_id) .first() ) get_old_card.main_card = False get_card.main_card = True db.session.add(get_old_card) db.session.commit() else: get_card.main_card = True db.session.add(get_card) db.session.commit() @payment.route("/cards/", methods=["GET"]) def get_user_cards(user_id): """ gets all cards of a user """ get_u_cards = (db.session .query(Card_Card) .filter(Card_Card.user_id == user_id) .all()) card_schema = Card_Card_schema(many=True) return jsonify(card_schema.dump(get_u_cards)) @payment.route("/cards/onfile/", methods=["GET"]) def get_user_cards_count(user_id): """ gets all cards of a user """ get_u_cards = (db.session .query(Card_Card) .filter(Card_Card.user_id == user_id) .count()) return jsonify({ "ok": True, 'cards': get_u_cards, }), 200 @payment.route("/card/", methods=["GET"]) def get_user_specific_card(card_id): """ gets a specific card of a user """ get_user_card = (db.session .query(Card_Card) .filter(Card_Card.id == card_id) .first()) card_schema = Card_Card_schema(many=False) return jsonify(card_schema.dump(get_user_card)) @payment.route("/card/main//", methods=["PUT"]) def set_main_card(user_id, card_id): """ updates a card of a user """ get_new_main_card = (db.session .query(Card_Card) .filter(Card_Card.user_id == user_id) .filter(Card_Card.id == card_id) .first()) get_other_card = (db.session .query(Card_Card) .filter(Card_Card.main_card == True) .filter(Card_Card.user_id == user_id) .first()) if get_other_card is not None: get_other_card.main_card = False db.session.add(get_other_card) get_new_main_card.main_card = True db.session.add(get_new_main_card) db.session.commit() return jsonify({"ok": True}), 200 @payment.route("/card/remove/", methods=["DELETE"]) def remove_user_card(card_id): """ removes a card """ get_card = (db.session .query(Card_Card) .filter(Card_Card.id == card_id) .first()) db.session.delete(get_card) db.session.commit() return jsonify({"ok": True}), 200 # In your Flask payment routes file (e.g., app/routes/payment.py) # ... (your existing imports: jsonify, request, db, Customer_Customer, Card_Card) ... @payment.route("/card/create/", methods=["POST"]) def create_user_card(user_id): """ Adds a card for a user to the local database. This is its only job. """ get_customer = (db.session .query(Customer_Customer) .filter(Customer_Customer.id == user_id) .first()) if not get_customer: return jsonify({"ok": False, "error": "Customer not found"}), 404 data = request.get_json() name_on_card = data.get("name_on_card") expiration_month = data.get("expiration_month") expiration_year = data.get("expiration_year") type_of_card = data.get("type_of_card") security_number = data.get("security_number") main_card = data.get("main_card", False) zip_code = data.get("zip_code") card_number = data.get("card_number") last_four = card_number[-4:] if card_number else "" try: create_new_card = Card_Card( user_id=get_customer.id, card_number=card_number, last_four_digits=last_four, name_on_card=name_on_card, expiration_month=expiration_month, expiration_year=expiration_year, type_of_card=type_of_card, security_number=security_number, accepted_or_declined=None, # This is correct, as we don't know the status yet main_card=main_card, zip_code=zip_code ) db.session.add(create_new_card) db.session.flush() if main_card: # Assuming set_card_main is another function you have 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}") except Exception as e: db.session.rollback() print(f"DATABASE ERROR: Could not save card for user {user_id}. Error: {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/", methods=["PUT"]) def update_card_payment_profile(card_id): """ Updates the auth_net_payment_profile_id for a card """ get_card = (db.session .query(Card_Card) .filter(Card_Card.id == card_id) .first()) if not get_card: return jsonify({"ok": False, "error": "Card not found"}), 404 data = request.get_json() auth_net_payment_profile_id = data.get("auth_net_payment_profile_id") get_card.auth_net_payment_profile_id = auth_net_payment_profile_id db.session.add(get_card) db.session.commit() return jsonify({"ok": True}), 200 @payment.route("/card/edit/", methods=["PUT"]) def update_user_card(card_id): """ edits a card """ get_card = (db.session .query(Card_Card) .filter(Card_Card.id == card_id) .first()) if not get_card: return jsonify({"ok": False, "error": "Card not found"}), 404 data = request.get_json() # FIX: Use .get() for safety and get the correct key 'name_on_card' name_on_card = data.get("name_on_card") # <-- This now matches the frontend expiration_month = data.get("expiration_month") expiration_year = data.get("expiration_year") type_of_card = data.get("type_of_card") security_number = data.get("security_number") card_number = data.get("card_number") main_card = data.get("main_card", False) zip_code = data.get("zip_code") auth_net_payment_profile_id = data.get("auth_net_payment_profile_id") get_card.card_number = card_number get_card.name_on_card = name_on_card get_card.expiration_month = expiration_month get_card.expiration_year = expiration_year get_card.type_of_card = type_of_card get_card.security_number = security_number get_card.main_card = main_card get_card.zip_code = zip_code get_card.auth_net_payment_profile_id = auth_net_payment_profile_id # FIX: Correctly slice the last four digits on edit if card_number and card_number[-4:].isdigit(): get_card.last_four_digits = int(card_number[-4:]) if main_card: set_card_main(user_id=get_card.user_id, card_id=get_card.id) db.session.add(get_card) db.session.commit() return jsonify({"ok": True}), 200 @payment.route("/transactions/authorize/", methods=["GET"]) def get_authorize_transactions(page): """ Gets transactions with transaction_type = 0 (charge), for the authorize page """ try: per_page = 50 offset = (page - 1) * per_page query = ( db.session .query(Transaction, Customer_Customer) .join(Customer_Customer, Transaction.customer_id == Customer_Customer.id) .order_by(Transaction.created_at.desc()) .offset(offset) .limit(per_page) ) results = query.all() transactions_data = [] for transaction, customer in results: transactions_data.append({ "id": transaction.id, "preauthorize_amount": transaction.preauthorize_amount, "charge_amount": transaction.charge_amount, "transaction_type": transaction.transaction_type, "status": transaction.status, "customer_name": f"{customer.customer_first_name} {customer.customer_last_name}", "created_at": transaction.created_at.isoformat(), "auth_net_transaction_id": transaction.auth_net_transaction_id, "rejection_reason": transaction.rejection_reason, "delivery_id": transaction.delivery_id, "service_id": transaction.service_id, "auto_id": transaction.auto_id, }) return jsonify(transactions_data), 200 except Exception as e: return jsonify({"ok": False, "error": str(e)}), 500 @payment.route("/authorize/cleanup/", methods=["POST"]) def cleanup_authorize_profile(customer_id): """ Clean up Authorize.Net profile data in local database when API check fails. Sets customer auth_net_profile_id to null and clears all card payment profile IDs. """ try: # Get customer and set auth_net_profile_id to null customer = db.session.query(Customer_Customer).filter(Customer_Customer.id == customer_id).first() if not customer: return jsonify({"ok": False, "error": "Customer not found"}), 404 customer.auth_net_profile_id = None # Get all cards for this customer and set their auth_net_payment_profile_id to null cards = db.session.query(Card_Card).filter(Card_Card.user_id == customer_id).all() for card in cards: card.auth_net_payment_profile_id = None # Commit all changes db.session.commit() return jsonify({"ok": True, "message": f"Cleaned up Authorize.Net data for customer {customer_id}"}), 200 except Exception as e: db.session.rollback() return jsonify({"ok": False, "error": f"Failed to cleanup profile: {str(e)}"}), 500 @payment.route("/authorize/", methods=["PUT"]) def update_delivery_payment_authorize(delivery_id): """ Update a delivery's payment_type to 11 (CC - Authorize API) after successful preauthorization """ 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 get_delivery.payment_type = 11 db.session.add(get_delivery) db.session.commit() return jsonify({"ok": True}), 200 @payment.route("/transaction/delivery/", methods=["GET"]) def get_transaction_by_delivery(delivery_id): """ Get a single transaction by delivery_id for Authorize.net payments """ transaction = (db.session .query(Transaction) .filter(Transaction.delivery_id == delivery_id) .first()) if not transaction: return jsonify({"ok": False, "error": "Transaction not found"}), 404 # Convert to dict-like format for frontend return jsonify({ "ok": True, "transaction": { "id": transaction.id, "preauthorize_amount": float(transaction.preauthorize_amount or 0), "charge_amount": float(transaction.charge_amount or 0), "transaction_type": transaction.transaction_type, "status": transaction.status, "auth_net_transaction_id": transaction.auth_net_transaction_id, "delivery_id": transaction.delivery_id, "customer_id": transaction.customer_id, "service_id": transaction.service_id, "card_id": transaction.card_id, "auto_id": transaction.auto_id, "created_at": transaction.created_at.isoformat() if transaction.created_at else None } }) @payment.route("/transactions/customer//", methods=["GET"]) def get_customer_transactions(customer_id, page): """ Gets transactions for a specific customer """ try: per_page = 50 offset = (page - 1) * per_page query = ( db.session .query(Transaction) .filter(Transaction.customer_id == customer_id) .order_by(Transaction.created_at.desc()) .offset(offset) .limit(per_page) ) results = query.all() transactions_data = [] for transaction in results: transactions_data.append({ "id": transaction.id, "preauthorize_amount": transaction.preauthorize_amount, "charge_amount": transaction.charge_amount, "transaction_type": transaction.transaction_type, "status": transaction.status, "created_at": transaction.created_at.isoformat(), "auth_net_transaction_id": transaction.auth_net_transaction_id, "rejection_reason": transaction.rejection_reason, "delivery_id": transaction.delivery_id, "service_id": transaction.service_id, "auto_id": transaction.auto_id, }) return jsonify(transactions_data), 200 except Exception as e: return jsonify({"ok": False, "error": str(e)}), 500 @payment.route("/service/payment//", methods=["PUT"]) 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: return jsonify({"ok": False, "error": "Service not found"}), 404 # Set payment columns as specified service.payment_type = payment_type # 1 for Tiger service.payment_status = 2 # As specified # payment_card_id retains the selected card's ID if set in the service record try: db.session.commit() return jsonify({"ok": True}), 200 except Exception as e: db.session.rollback() return jsonify({"error": str(e)}), 500 @payment.route("/authorize/service/", methods=["PUT"]) def update_service_payment_authorize(service_id): service = db.session.query(Service_Service).filter(Service_Service.id == service_id).first() if not service: return jsonify({"error": "Service not found"}), 404 data = request.get_json() card_id = data.get('card_id') status = data.get('status', 0) service.payment_type = 11 # CC - Authorize service.payment_status = status if card_id: service.payment_card_id = card_id try: db.session.commit() return jsonify({"ok": True}), 200 except Exception as e: db.session.rollback() return jsonify({"error": str(e)}), 500 @payment.route("/capture/service/", methods=["PUT"]) def update_service_payment_capture(service_id): service = db.session.query(Service_Service).filter(Service_Service.id == service_id).first() if not service: return jsonify({"error": "Service not found"}), 404 data = request.get_json() card_id = data.get('card_id') status = data.get('status', 3) # Default to 3 for capture if service.payment_type is None or service.payment_type != 11: service.payment_type = 11 # CC - Authorize service.payment_status = status # 3 for capture if card_id: service.payment_card_id = card_id try: db.session.commit() return jsonify({"ok": True}), 200 except Exception as e: db.session.rollback() return jsonify({"error": str(e)}), 500 @payment.route("/transactions/service/", methods=["GET"]) def get_service_transactions(service_id): """ Gets all transactions for a specific service ID """ try: query = ( db.session .query(Transaction) .filter(Transaction.service_id == service_id) .order_by(Transaction.created_at.desc()) ) transactions = query.all() transactions_data = [] for transaction in transactions: transactions_data.append({ "id": transaction.id, "preauthorize_amount": float(transaction.preauthorize_amount or 0), "charge_amount": float(transaction.charge_amount or 0), "transaction_type": transaction.transaction_type, "status": transaction.status, "created_at": transaction.created_at.isoformat() if transaction.created_at else None, "auth_net_transaction_id": transaction.auth_net_transaction_id, "rejection_reason": transaction.rejection_reason, "delivery_id": transaction.delivery_id, "service_id": transaction.service_id, "card_id": transaction.card_id, }) return jsonify(transactions_data), 200 except Exception as e: print(f"Error fetching transactions for service {service_id}: {str(e)}") return jsonify({"ok": False, "error": str(e)}), 500