Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[flake8]
max-line-length = 100
extend-ignore = E203, W503
exclude =
.git,
__pycache__,
venv,
env,
node_modules,
build,
dist,
**/migrations/*,
server/frontend
29 changes: 29 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Lint Code

on:
push:
branches: [main, master]
pull_request:
branches: [main, master]

jobs:
Lint_Python:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'

- name: Install flake8
run: |
python -m pip install --upgrade pip
pip install flake8

- name: Lint with flake8 (non-blocking)
run: |
flake8 server/djangoapp server/djangoproj --count --show-source --statistics --exit-zero

23 changes: 23 additions & 0 deletions server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM python:3.12.0-slim-bookworm

ENV PYTHONUNBUFFERED=1
ENV PYTHONWRITEBYTECODE=1
ENV APP=/app

WORKDIR $APP

# Copy dependency file and install requirements
COPY requirements.txt $APP
RUN pip install --no-cache-dir -r requirements.txt

# Copy project files
COPY . $APP

EXPOSE 8000

# Make entrypoint script executable
RUN chmod +x /app/entrypoint.sh

# Run DB migrations automatically and start Gunicorn
ENTRYPOINT ["/bin/bash","/app/entrypoint.sh"]
CMD ["gunicorn", "--bind", ":8000", "--workers", "3", "djangoproj.wsgi"]
33 changes: 29 additions & 4 deletions server/database/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,42 @@ app.get('/fetchReviews/dealer/:id', async (req, res) => {

// Express route to fetch all dealerships
app.get('/fetchDealers', async (req, res) => {
//Write your code here
try {
const dealers = await Dealerships.find({}).lean();
res.status(200).json(dealers);
} catch (err) {
console.error('fetchDealers error:', err);
res.status(500).json({ error: 'Error fetching dealers' });
}
});

// Express route to fetch Dealers by a particular state
app.get('/fetchDealers/:state', async (req, res) => {
//Write your code here
try {
const state = req.params.state;
const dealers = await Dealerships.find({
$or: [
{ state: new RegExp(`^${state}$`, 'i') }, // if your schema has `state`
{ st: new RegExp(`^${state}$`, 'i') }, // or `st` (2-letter)
],
}).lean();
res.status(200).json(dealers);
} catch (err) {
console.error('fetchDealers/:state error:', err);
res.status(500).json({ error: 'Error fetching dealers by state' });
}
});

// Express route to fetch dealer by a particular id
app.get('/fetchDealer/:id', async (req, res) => {
//Write your code here
try {
const id = Number(req.params.id);
const dealer = await Dealerships.findOne({ id }).lean();
if (!dealer) return res.status(404).json({ error: 'Dealer not found' });
res.status(200).json(dealer);
} catch (err) {
console.error('fetchDealer/:id error:', err);
res.status(500).json({ error: 'Error fetching dealer' });
}
});

//Express route to insert review
Expand Down
43 changes: 35 additions & 8 deletions server/database/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,49 @@
version: '3.9'

# services:
# # Mongodb service
# mongo_db:
# container_name: db_container
# image: mongo:latest
# ports:
# - 27017:27017
# restart: always
# volumes:
# - mongo_data:/data/db

# # Node api service
# api:
# image: nodeapp
# ports:
# - 3030:3030
# depends_on:
# - mongo_db

# volumes:
# mongo_data: {}


# docker-compose.yml
services:
# Mongodb service
mongo_db:
container_name: db_container
image: mongo:latest
image: mongo:6-jammy # good for Intel/Apple Silicon
ports:
- 27017:27017
restart: always
- "27017:27017"
restart: unless-stopped
volumes:
- mongo_data:/data/db

# Node api service
api:
image: nodeapp
build:
context: . # <— build from the current folder
dockerfile: Dockerfile
image: nodemap:latest # optional: name the built image
ports:
- 3030:3030
depends_on:
- "3030:3030"
environment:
- MONGO_URL=mongodb://mongo_db:27017/dealerships # <— use service name, not localhost
depends_on:
- mongo_db

volumes:
Expand Down
29 changes: 29 additions & 0 deletions server/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: dealership
labels:
run: dealership
spec:
replicas: 1
selector:
matchLabels:
run: dealership
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
template:
metadata:
labels:
run: dealership
spec:
containers:
- name: dealership
image: us.icr.io/sn-labs-cnabolouri/dealership:latest
imagePullPolicy: Always
ports:
- containerPort: 8000
protocol: TCP
restartPolicy: Always
4 changes: 2 additions & 2 deletions server/djangoapp/.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
backend_url =your backend url
sentiment_analyzer_url=your code engine deployment url
backend_url = https://cnabolouri-3030.theiadockernext-0-labs-prod-theiak8s-4-tor01.proxy.cognitiveclass.ai/
sentiment_analyzer_url = https://sentianalyzer.22a78yv1gizq.us-south.codeengine.appdomain.cloud
17 changes: 8 additions & 9 deletions server/djangoapp/admin.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# from django.contrib import admin
# from .models import related models
from django.contrib import admin
from .models import CarMake, CarModel


# Register your models here.
@admin.register(CarMake)
class CarMakeAdmin(admin.ModelAdmin):
list_display = ('name', 'description')

# CarModelInline class

# CarModelAdmin class

# CarMakeAdmin class with CarModelInline

# Register models here
@admin.register(CarModel)
class CarModelAdmin(admin.ModelAdmin):
list_display = ('name', 'make', 'type', 'year')
34 changes: 34 additions & 0 deletions server/djangoapp/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Generated by Django 5.2.7 on 2025-11-04 01:03

import django.core.validators
import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='CarMake',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, unique=True)),
('description', models.TextField(blank=True)),
],
),
migrations.CreateModel(
name='CarModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('type', models.CharField(choices=[('SEDAN', 'Sedan'), ('SUV', 'SUV'), ('WAGON', 'Wagon'), ('COUPE', 'Coupe'), ('HATCH', 'Hatchback'), ('TRUCK', 'Truck')], max_length=20)),
('year', models.IntegerField(validators=[django.core.validators.MinValueValidator(2015), django.core.validators.MaxValueValidator(2023)])),
('make', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='models', to='djangoapp.carmake')),
],
),
]
Empty file.
50 changes: 29 additions & 21 deletions server/djangoapp/models.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
# Uncomment the following imports before adding the Model code
from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator

# from django.db import models
# from django.utils.timezone import now
# from django.core.validators import MaxValueValidator, MinValueValidator
class CarMake(models.Model):
name = models.CharField(max_length=100, unique=True)
description = models.TextField(blank=True)
def __str__(self):
return self.name


class CarModel(models.Model):
SEDAN = "SEDAN"
SUV = "SUV"
WAGON = "WAGON"
COUPE = "COUPE"
HATCH = "HATCH"
TRUCK = "TRUCK"
TYPE_CHOICES = [
(SEDAN, "Sedan"),
(SUV, "SUV"),
(WAGON, "Wagon"),
(COUPE, "Coupe"),
(HATCH, "Hatchback"),
(TRUCK, "Truck"),
]

# Create your models here.
make = models.ForeignKey(CarMake, on_delete=models.CASCADE, related_name="models")
name = models.CharField(max_length=100)
type = models.CharField(max_length=20, choices=TYPE_CHOICES)
year = models.IntegerField(validators=[MinValueValidator(2015), MaxValueValidator(2023)])

# <HINT> Create a Car Make model `class CarMake(models.Model)`:
# - Name
# - Description
# - Any other fields you would like to include in car make model
# - __str__ method to print a car make object


# <HINT> Create a Car Model model `class CarModel(models.Model):`:
# - Many-To-One relationship to Car Make model (One Car Make has many
# Car Models, using ForeignKey field)
# - Name
# - Type (CharField with a choices argument to provide limited choices
# such as Sedan, SUV, WAGON, etc.)
# - Year (IntegerField) with min value 2015 and max value 2023
# - Any other fields you would like to include in car model
# - __str__ method to print a car make object
def __str__(self):
return f"{self.make.name} {self.name} ({self.year})"
31 changes: 30 additions & 1 deletion server/djangoapp/populate.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,31 @@
from .models import CarMake, CarModel


def initiate():
print("Populate not implemented. Add data manually")
if CarMake.objects.exists() and CarModel.objects.exists():
return

makes = [
{"name": "NISSAN", "description": "Great cars. Japanese technology"},
{"name": "Mercedes", "description": "Great cars. German technology"},
{"name": "Audi", "description": "Great cars. German technology"},
{"name": "Kia", "description": "Great cars. Korean technology"},
{"name": "Toyota", "description": "Great cars. Japanese technology"},
]

make_objs = {}
for m in makes:
make_objs[m["name"]] = CarMake.objects.create(**m)

models = [
{"name": "Pathfinder", "type": "SUV", "year": 2023, "make": make_objs["NISSAN"]},
{"name": "Qashqai", "type": "SUV", "year": 2023, "make": make_objs["NISSAN"]},
{"name": "A-Class", "type": "Sedan","year": 2023, "make": make_objs["Mercedes"]},
{"name": "CLA", "type": "Coupe","year": 2023, "make": make_objs["Mercedes"]},
{"name": "Q7", "type": "SUV", "year": 2023, "make": make_objs["Audi"]},
{"name": "Sportage", "type": "SUV", "year": 2023, "make": make_objs["Kia"]},
{"name": "Sorento", "type": "SUV", "year": 2023, "make": make_objs["Kia"]},
{"name": "Camry", "type": "Sedan","year": 2023, "make": make_objs["Toyota"]},
{"name": "Corolla", "type": "Sedan","year": 2023, "make": make_objs["Toyota"]},
]
CarModel.objects.bulk_create([CarModel(**row) for row in models])
Loading