diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 4cf9f04f15c297c7025dd3d57e3d9b1960553768..6a635c83368978d7d8d2b227b46cf0e3061d4388 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -8,12 +8,19 @@ variables:
   PIP_CACHE_DIR: $CI_PROJECT_DIR/.pip_cache
 
 cache:
+  key: dependencies-cache
   paths:
     - $PIP_CACHE_DIR
+  policy: pull-push
 
 before_script:
   - python -m venv $VENV_DIR
-  - source $VENV_DIR/Scripts/activate
+  - |
+    if [[ "$OSTYPE" == "msys" ]]; then
+      source $VENV_DIR/Scripts/activate
+    else
+      source $VENV_DIR/bin/activate
+    fi
   - pip install --upgrade pip
   - pip install -r requirements.txt --cache-dir $PIP_CACHE_DIR
 
@@ -21,6 +28,7 @@ install_dependencies:
   stage: install
   script:
     - echo "Dependencies installed successfully."
+  timeout: 20m
 
 run_tests:
   stage: test
diff --git a/app/backend/dummy_data.py b/app/backend/dummy_data.py
index e2550dfc5253d893607822247aa3681f1a514bf9..f7a55b4eebfe187e36075be20138792aa6826c24 100644
--- a/app/backend/dummy_data.py
+++ b/app/backend/dummy_data.py
@@ -34,11 +34,49 @@ def insert_dummy_data(session: Session):
         shops = [
             Shop(
                 owner_id=2,
-                name=f"Shop{i}",
-                description=f"Description for Shop {i}",
+                name="Google HQ",
+                description="Google Headquarters",
                 image_url="app/static/default/default_shop.png",
-            )
-            for i in range(1, 6)
+                address="1600 Amphitheatre Parkway, Mountain View, CA",
+                latitude=37.4220656,
+                longitude=-122.0840897,
+            ),
+            Shop(
+                owner_id=2,
+                name="Apple HQ",
+                description="Apple Headquarters",
+                image_url="app/static/default/default_shop.png",
+                address="1 Infinite Loop, Cupertino, CA",
+                latitude=37.33182,
+                longitude=-122.03118,
+            ),
+            Shop(
+                owner_id=2,
+                name="Empire State Building",
+                description="Famous skyscraper in New York",
+                image_url="app/static/default/default_shop.png",
+                address="350 Fifth Avenue, New York, NY",
+                latitude=40.748817,
+                longitude=-73.985428,
+            ),
+            Shop(
+                owner_id=2,
+                name="Sherlock's Home",
+                description="Fictional detective's residence",
+                image_url="app/static/default/default_shop.png",
+                address="221B Baker Street, London, UK",
+                latitude=51.523767,
+                longitude=-0.1585557,
+            ),
+            Shop(
+                owner_id=2,
+                name="Eiffel Tower",
+                description="Iconic landmark in Paris",
+                image_url="app/static/default/default_shop.png",
+                address="Eiffel Tower, Paris, France",
+                latitude=48.8588443,
+                longitude=2.2943506,
+            ),
         ]
         session.add_all(shops)
         session.commit()
@@ -75,8 +113,56 @@ def insert_dummy_data(session: Session):
 
     if not session.query(Order).first():
         orders = [
-            Order(user_id=1, shop_id=i, total_price=100 + (i * 50), status="pending")
-            for i in range(1, 6)
+            Order(
+                user_id=1,
+                shop_id=1,
+                total_price=150.0,
+                shipping_price=10.0,
+                status="pending",
+                delivery_address="1600 Amphitheatre Parkway, Mountain View, CA",
+                delivery_latitude=37.4220656,
+                delivery_longitude=-122.0840897,
+            ),
+            Order(
+                user_id=1,
+                shop_id=2,
+                total_price=200.0,
+                shipping_price=15.0,
+                status="shipped",
+                delivery_address="1 Infinite Loop, Cupertino, CA",
+                delivery_latitude=37.33182,
+                delivery_longitude=-122.03118,
+            ),
+            Order(
+                user_id=1,
+                shop_id=3,
+                total_price=250.0,
+                shipping_price=20.0,
+                status="delivered",
+                delivery_address="350 Fifth Avenue, New York, NY",
+                delivery_latitude=40.748817,
+                delivery_longitude=-73.985428,
+            ),
+            Order(
+                user_id=1,
+                shop_id=4,
+                total_price=300.0,
+                shipping_price=25.0,
+                status="pending",
+                delivery_address="221B Baker Street, London, UK",
+                delivery_latitude=51.523767,
+                delivery_longitude=-0.1585557,
+            ),
+            Order(
+                user_id=1,
+                shop_id=5,
+                total_price=350.0,
+                shipping_price=30.0,
+                status="canceled",
+                delivery_address="Eiffel Tower, Paris, France",
+                delivery_latitude=48.8588443,
+                delivery_longitude=2.2943506,
+            ),
         ]
         session.add_all(orders)
         session.commit()
diff --git a/app/backend/models/models.py b/app/backend/models/models.py
index 8397f9f6a4dc9c51166c40ef9d6584c58dffaadc..77b9b590cf60683d884d81632073388953082281 100644
--- a/app/backend/models/models.py
+++ b/app/backend/models/models.py
@@ -21,6 +21,10 @@ class Shop(SQLModel, table=True):
     name: str = Field(unique=True, index=True)
     description: Optional[str] = None
     image_url: Optional[str] = None  # Image URL for shop
+    # location coordinates
+    address: str
+    latitude: float
+    longitude: float
     created_at: datetime = Field(default_factory=datetime.utcnow)
 
     owner: User = Relationship(back_populates="shops")
@@ -62,7 +66,12 @@ class Order(SQLModel, table=True):
     user_id: int = Field(foreign_key="user.id")
     shop_id: int = Field(foreign_key="shop.id")
     total_price: float
+    shipping_price: float
     status: str = Field(default="pending")
+    # delivery location coordinates
+    delivery_address: str
+    delivery_latitude: float
+    delivery_longitude: float
     created_at: datetime = Field(default_factory=datetime.utcnow)
 
     user: User = Relationship(back_populates="orders")
diff --git a/app/backend/routes/order.py b/app/backend/routes/order.py
index 14b55f9a926e42f4397c760aa1ab378c7900a38b..c2eefde4e63ae7fe5b6f18772dfa033a7b5ba463 100644
--- a/app/backend/routes/order.py
+++ b/app/backend/routes/order.py
@@ -1,9 +1,11 @@
 from fastapi import APIRouter, Depends, HTTPException
 from sqlmodel import Session, select, delete
+from geopy.geocoders import Nominatim
+from geopy.distance import geodesic
 from backend.database import get_session
 from backend.routes.auth import get_current_user
-from backend.models.models import Order, OrderItem, User, Product
-from backend.schemas.order import OrderCreate, OrderRead
+from backend.models.models import Order, OrderItem, User, Product, Shop
+from backend.schemas.order import OrderCreate, OrderRead, OrderUpdate
 
 router = APIRouter()
 
@@ -14,7 +16,26 @@ def create_order(
     session: Session = Depends(get_session),
     current_user: User = Depends(get_current_user),
 ):
-    total_price = 0
+    # Fetch the shop details
+    shop = session.get(Shop, order_data.shop_id)
+    if not shop:
+        raise HTTPException(status_code=404, detail="Shop not found")
+
+    # Geocode the delivery address
+    geolocator = Nominatim(user_agent="order_locator")
+    delivery_location = geolocator.geocode(order_data.delivery_address)
+    if not delivery_location:
+        raise HTTPException(status_code=400, detail="Invalid delivery address provided")
+
+    # Calculate the distance between the shop and the delivery location
+    shop_location = (shop.latitude, shop.longitude)
+    delivery_coordinates = (delivery_location.latitude, delivery_location.longitude)
+    distance_km = geodesic(shop_location, delivery_coordinates).kilometers
+
+    # Calculate the shipping price ($1 per km)
+    shipping_price = distance_km * 1.0
+
+    total_price = shipping_price
     for item in order_data.items:
         product = session.get(Product, item.product_id)
         if not product or product.stock < item.quantity:
@@ -23,13 +44,22 @@ def create_order(
             )
         total_price += item.quantity * product.price
 
+    # Create the order
     new_order = Order(
-        user_id=current_user.id, shop_id=order_data.shop_id, total_price=total_price
+        user_id=current_user.id,
+        shop_id=order_data.shop_id,
+        total_price=total_price,
+        shipping_price=shipping_price,
+        status="pending",
+        delivery_address=order_data.delivery_address,
+        delivery_latitude=delivery_location.latitude,
+        delivery_longitude=delivery_location.longitude,
     )
     session.add(new_order)
     session.commit()
     session.refresh(new_order)
 
+    # Create order items
     for item in order_data.items:
         order_item = OrderItem(
             order_id=new_order.id,
@@ -71,19 +101,50 @@ def get_order(
 @router.put("/status/{order_id}", response_model=OrderRead)
 def update_order(
     order_id: int,
-    status: str,
+    order_update: OrderUpdate,
     session: Session = Depends(get_session),
     current_user: User = Depends(get_current_user),
 ):
     order = session.get(Order, order_id)
     if not order or order.user_id != current_user.id:
         raise HTTPException(status_code=404, detail="Order not found or unauthorized")
-    if order.status != "pending" or status != "completed":
-        raise HTTPException(
-            status_code=400,
-            detail="Order can only be updated from pending to completed",
+
+    # Update the delivery address if provided
+    if order_update.delivery_address:
+        geolocator = Nominatim(user_agent="order_locator")
+        delivery_location = geolocator.geocode(order_update.delivery_address)
+        if not delivery_location:
+            raise HTTPException(status_code=400, detail="Invalid delivery address")
+        order.delivery_address = order_update.delivery_address
+        order.delivery_latitude = delivery_location.latitude
+        order.delivery_longitude = delivery_location.longitude
+
+        # Recalculate the shipping price
+        shop = session.get(Shop, order.shop_id)
+        if not shop:
+            raise HTTPException(status_code=404, detail="Shop not found")
+        shop_location = (shop.latitude, shop.longitude)
+        delivery_coordinates = (delivery_location.latitude, delivery_location.longitude)
+        distance_km = geodesic(shop_location, delivery_coordinates).kilometers
+        shipping_price = distance_km * 1.0
+
+        # Update the total price
+        product_total = sum(
+            item.quantity * session.get(Product, item.product_id).price
+            for item in order.order_items
         )
-    order.status = status
+        order.shipping_price = shipping_price
+        order.total_price = product_total + shipping_price
+
+    # Update the order status if provided
+    if order_update.status:
+        if order.status != "pending" or order_update.status != "completed":
+            raise HTTPException(
+                status_code=400,
+                detail="Order can only be updated from pending to completed",
+            )
+        order.status = order_update.status
+
     session.commit()
     session.refresh(order)
     return order
diff --git a/app/backend/routes/product.py b/app/backend/routes/product.py
index cadfba24acfe07e4b53d4151e7502f0492174415..fcad951db6c8c2d2cf4b7727a2c555599cb95b6b 100644
--- a/app/backend/routes/product.py
+++ b/app/backend/routes/product.py
@@ -1,7 +1,7 @@
 from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form
-from sqlmodel import Session
+from sqlmodel import Session, func
 from datetime import datetime
-from backend.models.models import Product, ProductImage, User, Shop
+from backend.models.models import Product, ProductImage, User, Shop, OrderItem
 from backend.schemas.product import ProductRead, ProductUpdate
 from backend.database import get_session
 from backend.routes.auth import get_current_user
@@ -76,8 +76,21 @@ def create_product(
 
 
 @router.get("/list", response_model=list[ProductRead])
-def read_all_products(session: Session = Depends(get_session)):
-    products = session.query(Product).all()
+def read_all_products(order: str = "desc", session: Session = Depends(get_session)):
+    order_by = (
+        func.count(OrderItem.id).desc()
+        if order == "desc"
+        else func.count(OrderItem.id).asc()
+    )
+
+    products = (
+        session.query(Product)
+        .outerjoin(OrderItem, Product.id == OrderItem.product_id)
+        .group_by(Product.id)
+        .order_by(order_by)
+        .all()
+    )
+
     return products
 
 
diff --git a/app/backend/routes/shop.py b/app/backend/routes/shop.py
index 643b8b2ef82f4cfa0d669dbf5ae004dcc5e125ee..a240d1be12ee0774988de102a631da60042acbc5 100644
--- a/app/backend/routes/shop.py
+++ b/app/backend/routes/shop.py
@@ -1,7 +1,8 @@
 from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form
-from sqlmodel import Session
-from backend.models.models import Shop, User
-from backend.schemas.shop import ShopCreate, ShopRead
+from sqlmodel import Session, func
+from geopy.geocoders import Nominatim
+from backend.models.models import Shop, User, Order
+from backend.schemas.shop import ShopRead
 from backend.database import get_session
 from backend.routes.auth import get_current_user
 from core.config import settings
@@ -15,36 +16,60 @@ router = APIRouter()
 def create_shop(
     name: str = Form(...),
     description: str = Form(None),
+    address: str = Form(...),
     file: UploadFile = File(None),
     session: Session = Depends(get_session),
     current_user: User = Depends(get_current_user),
 ):
-    shop = ShopCreate(name=name, description=description, owner_id=current_user.id)
-    db_shop = Shop.from_orm(shop)
-
-    session.add(db_shop)
+    # Get latitude and longitude from address
+    geolocator = Nominatim(user_agent="shop_locator")
+    location = geolocator.geocode(address)
+    if not location:
+        raise HTTPException(status_code=400, detail="Invalid address")
+
+    shop = Shop(
+        name=name,
+        description=description,
+        address=address,
+        latitude=location.latitude,
+        longitude=location.longitude,
+        owner_id=current_user.id,
+    )
+    session.add(shop)
     session.commit()
-    session.refresh(db_shop)
+    session.refresh(shop)
 
-    shop_dir = os.path.join(settings.static_dir, f"shop_{db_shop.name}")
+    shop_dir = os.path.join(settings.static_dir, f"shop_{shop.name}")
     os.makedirs(shop_dir, exist_ok=True)
 
     if file and file.filename:
         file_location = os.path.join(shop_dir, file.filename)
         with open(file_location, "wb") as buffer:
             shutil.copyfileobj(file.file, buffer)
-        db_shop.image_url = file_location
+        shop.image_url = file_location
     else:
-        db_shop.image_url = os.path.join(
-            settings.static_dir, "default/default_shop.png"
-        )
+        shop.image_url = os.path.join(settings.static_dir, "default/default_shop.png")
+
+    session.commit()
+    session.refresh(shop)
 
-    return db_shop
+    return shop
 
 
 @router.get("/list", response_model=list[ShopRead])
-def get_all_shops(session: Session = Depends(get_session)):
-    shops = session.query(Shop).all()
+def get_all_shops(order: str = "desc", session: Session = Depends(get_session)):
+    order_by = (
+        func.count(Order.id).desc() if order == "desc" else func.count(Order.id).asc()
+    )
+
+    shops = (
+        session.query(Shop)
+        .outerjoin(Order, Shop.id == Order.shop_id)
+        .group_by(Shop.id)
+        .order_by(order_by)
+        .all()
+    )
+
     return shops
 
 
@@ -61,41 +86,47 @@ def update_shop(
     shop_id: int,
     name: str = Form(None),
     description: str = Form(None),
+    address: str = Form(None),
     file: UploadFile = File(None),
     session: Session = Depends(get_session),
     current_user: User = Depends(get_current_user),
 ):
-    db_shop = session.get(Shop, shop_id)
-    if not db_shop:
+    shop = session.get(Shop, shop_id)
+    if not shop:
         raise HTTPException(status_code=404, detail="Shop not found")
 
     # Ensure the current user is the shop owner
-    if db_shop.owner_id != current_user.id:
+    if shop.owner_id != current_user.id:
         raise HTTPException(status_code=403, detail="Unauthorized to update this shop")
-
     if name:
-        db_shop.name = name
+        shop.name = name
     if description:
-        db_shop.description = description
-
-    shop_dir = os.path.join(settings.static_dir, f"shop_{db_shop.name}")
+        shop.description = description
+    if address:
+        geolocator = Nominatim(user_agent="shop_locator")
+        location = geolocator.geocode(address)
+        if not location:
+            raise HTTPException(status_code=400, detail="Invalid address")
+        shop.address = address
+        shop.latitude = location.latitude
+        shop.longitude = location.longitude
+
+    shop_dir = os.path.join(settings.static_dir, f"shop_{shop.name}")
     os.makedirs(shop_dir, exist_ok=True)
 
     if file and file.filename:
         file_location = os.path.join(shop_dir, file.filename)
         with open(file_location, "wb") as buffer:
             shutil.copyfileobj(file.file, buffer)
-        db_shop.image_url = file_location
+        shop.image_url = file_location
     else:
-        db_shop.image_url = os.path.join(
-            settings.static_dir, "default/default_shop.png"
-        )
+        shop.image_url = os.path.join(settings.static_dir, "default/default_shop.png")
 
-    session.add(db_shop)
+    session.add(shop)
     session.commit()
-    session.refresh(db_shop)
+    session.refresh(shop)
 
-    return db_shop
+    return shop
 
 
 @router.delete("/delete/{shop_id}")
diff --git a/app/backend/schemas/order.py b/app/backend/schemas/order.py
index 37fdda72ec31777d18347c516714ac9275a14abb..ca5e2ce1dbe2a38530794397f98fdd90cdc38e3a 100644
--- a/app/backend/schemas/order.py
+++ b/app/backend/schemas/order.py
@@ -11,6 +11,7 @@ class OrderItemCreate(BaseModel):
 class OrderCreate(BaseModel):
     shop_id: int
     items: List[OrderItemCreate]
+    delivery_address: str
 
 
 class OrderItemRead(BaseModel):
@@ -28,9 +29,15 @@ class OrderRead(BaseModel):
     user_id: int
     shop_id: int
     total_price: float
+    shipping_price: float
     status: str
     created_at: datetime
     order_items: List[OrderItemRead]
 
     class Config:
         from_attributes = True
+
+
+class OrderUpdate(BaseModel):
+    delivery_address: Optional[str] = None
+    status: Optional[str] = None
diff --git a/app/backend/schemas/shop.py b/app/backend/schemas/shop.py
index 71763bb8b375e6051849d32a9ad5efad889a106b..8cfb87fc29627f7ade3fd7c0b119995f728d8dec 100644
--- a/app/backend/schemas/shop.py
+++ b/app/backend/schemas/shop.py
@@ -14,6 +14,7 @@ class ShopCreate(ShopBase):
 class ShopRead(ShopBase):
     id: int
     owner_id: int
+    address: str
     image_url: Optional[str] = None
 
     class Config:
diff --git a/requirements.txt b/requirements.txt
index 098a8e9d014d631acb415fded564d5774243a0a0..2383f12bc661c32a3b8eac0fcf9146bd60a0f3fe 100644
Binary files a/requirements.txt and b/requirements.txt differ