from flask import request, jsonify from app.search import search from app import db from app.classes.customer import Customer_Customer, Customer_Customer_schema from app.classes.delivery import Delivery_Delivery, Delivery_Delivery_schema # We now need `and_` to combine our search conditions from sqlalchemy import or_, and_ @search.route("/customer", methods=["GET"]) def search_customers(): """ Searches for customers based on a keyword. Supports special prefixes: @ for last name, ! for address, # for phone, $ for account. Otherwise searches across multiple fields for each word provided in the search query. """ keyword = request.args.get('q') if not keyword or len(keyword) < 2: return jsonify([]) # Check for special search prefixes search_type = None if keyword[0] in '!@#$': search_type = keyword[0] keyword = keyword[1:] # remove the prefix for the search term if search_type: search_pattern = f"%{keyword}%" if search_type == '@': customer_list = (db.session .query(Customer_Customer) .filter(Customer_Customer.customer_last_name.ilike(search_pattern)) .order_by(Customer_Customer.customer_last_name.asc()) .limit(20) .all()) elif search_type == '!': customer_list = (db.session .query(Customer_Customer) .filter(Customer_Customer.customer_address.ilike(search_pattern)) .order_by(Customer_Customer.customer_address.asc()) .limit(20) .all()) elif search_type == '#': customer_list = (db.session .query(Customer_Customer) .filter(Customer_Customer.customer_phone_number.ilike(search_pattern)) .order_by(Customer_Customer.customer_phone_number.asc()) .limit(20) .all()) elif search_type == '$': customer_list = (db.session .query(Customer_Customer) .filter(Customer_Customer.account_number.ilike(search_pattern)) .order_by(Customer_Customer.account_number.asc()) .limit(20) .all()) else: # fallback, though shouldn't happen return jsonify([]) customer_schema = Customer_Customer_schema(many=True) return jsonify(customer_schema.dump(customer_list)) # --- NEW SEARCH LOGIC --- # 1. Split the incoming search query into individual words. # e.g., "john main st" -> ["john", "main", "st"] search_words = keyword.split() # 2. We'll build a list of search conditions. Each condition will check # if a word exists in ANY of the relevant customer fields. conditions = [] for word in search_words: search_pattern = f"%{word}%" # For each word, create an OR clause to check against all fields conditions.append( or_( Customer_Customer.customer_first_name.ilike(search_pattern), Customer_Customer.customer_last_name.ilike(search_pattern), Customer_Customer.customer_address.ilike(search_pattern), Customer_Customer.customer_town.ilike(search_pattern), Customer_Customer.customer_phone_number.ilike(search_pattern), Customer_Customer.account_number.ilike(search_pattern) # Add any other fields you want to be searchable here ) ) # 3. Combine all our word conditions with AND. This means the customer # record must match ALL the words from the search query. # e.g., for "john main", it must contain "john" AND "main" somewhere. query = db.session.query(Customer_Customer).filter(and_(*conditions)) # Limiting results is still good practice customer_list = query.order_by(Customer_Customer.customer_last_name.asc()).limit(20).all() customer_schema = Customer_Customer_schema(many=True) return jsonify(customer_schema.dump(customer_list)) # The /delivery route is fine as is, so no changes needed there. @search.route("/delivery", methods=["GET"]) def search_delivery(): # ... (no changes to this function) keyword = request.args.get('q') if not keyword or not keyword.isdigit(): return jsonify([]) delivery_ticket = db.session.query(Delivery_Delivery).filter(Delivery_Delivery.id == keyword).first() if delivery_ticket: delivery_schema = Delivery_Delivery_schema(many=False) return jsonify(delivery_schema.dump(delivery_ticket)) else: return jsonify({})