Project Introduction
The Car Sales Inventory System is a web application designed to streamline the buying and selling of cars. Built using Node.js, this platform allows users to manage car listings, track sales, and handle customer interactions efficiently. The system supports multiple user roles, including admin, sales staff, and customers, ensuring a comprehensive and user-friendly experience. The underlying MySQL database schema is structured to manage users, cars, sales transactions, customer feedback, test drives, promotions, and payment transactions, providing a robust foundation for a seamless car sales process.
Project Objectives
- To develop a user-friendly interface for customers to browse and purchase cars.
- To implement a secure user authentication system with role-based access control.
- To allow sales staff to manage car inventory, including adding, updating, and removing car listings.
- To facilitate the management of sales transactions, including payment processing and tracking.
- To provide a feedback mechanism for customers to rate their experience and provide comments on cars.
- To enable customers to schedule test drives and provide feedback on their experience.
- To implement promotional offers and discounts to attract customers.
- To ensure the application is scalable and maintainable for future enhancements.
Project Modules
- User Management Module:
This module handles user registration, authentication, and role management, allowing users to manage their accounts based on their designated roles.
- Car Management Module:
This module allows sales staff to add, update, and manage car listings, including details such as make, model, year, price, and condition.
- Car Image Management Module:
This module enables the uploading and management of images associated with each car listing.
- Sales Management Module:
This module tracks sales transactions, including customer details, sale price, and payment status.
- Customer Feedback Module:
This module allows customers to provide feedback on their purchased cars, including ratings and comments.
- Test Drive Management Module:
This module enables customers to schedule test drives and provides a mechanism for collecting feedback on the test drive experience.
- Promotions Module:
This module manages promotional offers and discounts for specific cars, including start and end dates for promotions.
- Payment Management Module:
This module handles payment transactions for sales, including various payment methods and tracking payment statuses.
Set Up the Project
Initialize a new Node.js project and install the required packages.
Step 1: Set Up the Project
mkdir vehicle-dealership-app
cd vehicle-dealership-app
npm init -y
npm install express sequelize mysql2 body-parser ejs
Step 2: Configure Sequelize
Create a file named config.js for database configuration.
config.js
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize('database_name', 'username', 'password', {
host: 'localhost',
dialect: 'mysql',
});
module.exports = sequelize;
Step 3: Create Models
Create a folder named models and create model files for each table.
models/User.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class User extends Model {}
User .init({
UserId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
Username: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
},
PasswordHash: {
type: DataTypes.STRING(255),
allowNull: false,
},
Email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
},
Phone: {
type: DataTypes.STRING(15),
},
RoleId: {
type: DataTypes.INTEGER,
},
}, {
sequelize,
modelName: 'User ',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt',
});
module.exports = User;
models/Role.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Role extends Model {}
Role.init({
RoleId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
RoleName: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
},
}, {
sequelize,
modelName: 'Role',
timestamps: false,
});
module.exports = Role;
models/Vehicle.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Vehicle extends Model {}
Vehicle.init({
VehicleId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
Make: {
type: DataTypes.STRING(50),
allowNull: false,
},
Model: {
type: DataTypes.STRING(50),
allowNull: false,
},
Year: {
type: DataTypes.INTEGER,
allowNull: false,
},
VIN: {
type: DataTypes.STRING(17),
allowNull: false,
unique: true,
},
Color: {
type: DataTypes.STRING(30),
},
Price: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false,
},
}, {
sequelize,
modelName: 'Vehicle',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt',
});
module.exports = Vehicle;
models/Inventory.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Inventory extends Model {}
Inventory.init({
InventoryId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
VehicleId: {
type: DataTypes.INTEGER,
references: {
model: 'Vehicles',
key: 'VehicleId',
},
},
Quantity: {
type: DataTypes.INTEGER,
allowNull: false,
},
}, {
sequelize,
modelName: 'Inventory',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt',
});
module.exports = Inventory;
models/Customer.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Customer extends Model {}
Customer.init({
CustomerId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
FirstName: {
type: DataTypes.STRING(50),
allowNull: false,
},
LastName: {
type: DataTypes.STRING(50),
allowNull: false,
},
Email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
},
Phone: {
type: DataTypes.STRING(15),
},
}, {
sequelize,
modelName: 'Customer',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt',
});
module.exports = Customer;
models/Sale.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Sale extends Model {}
Sale.init({
SaleId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
VehicleId: {
type: DataTypes.INTEGER,
references: {
model: 'Vehicles',
key: 'VehicleId',
},
},
CustomerId: {
type: DataTypes.INTEGER,
references: {
model: 'Customers',
key: 'CustomerId',
},
},
SaleDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
SalePrice: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false,
},
PaymentId: {
type: DataTypes.INTEGER,
references: {
model: 'Payments',
key: 'PaymentId',
},
},
}, {
sequelize,
modelName: 'Sale',
timestamps: false,
});
module.exports = Sale;
models/Payment.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Payment extends Model {}
Payment.init({
PaymentId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
SaleId: {
type: DataTypes.INTEGER,
references: {
model: 'Sales',
key: 'SaleId',
},
},
PaymentDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
Amount: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false,
},
PaymentMethod: {
type: DataTypes.STRING(50),
},
Status: {
type: DataTypes.STRING(20),
defaultValue: 'Pending',
},
}, {
sequelize,
modelName: 'Payment',
timestamps: false,
});
module.exports = Payment;
models/Invoice.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Invoice extends Model {}
Invoice.init({
InvoiceId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
SaleId: {
type: DataTypes.INTEGER,
references: {
model: 'Sales',
key: 'SaleId',
},
},
InvoiceDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
TotalAmount: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false,
},
}, {
sequelize,
modelName: 'Invoice',
timestamps: false,
});
module.exports = Invoice;
models/Report.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Report extends Model {}
Report.init({
ReportId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
ReportDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
TotalSales: {
type: DataTypes.INTEGER,
},
TotalRevenue: {
type: DataTypes.DECIMAL(10, 2),
},
}, {
sequelize,
modelName: 'Report',
timestamps: true,
createdAt: 'CreatedAt',
});
module.exports = Report;
models/Campaign.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Campaign extends Model {}
Campaign.init({
CampaignId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
CampaignName: {
type: DataTypes.STRING(100),
allowNull: false,
},
StartDate: {
type: DataTypes.DATE,
},
EndDate: {
type: DataTypes.DATE,
},
DiscountPercentage: {
type: DataTypes.DECIMAL(5, 2),
},
}, {
sequelize modelName: 'Campaign',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt',
});
module.exports = Campaign;
models/TestDrive.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class TestDrive extends Model {}
TestDrive.init({
TestDriveId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
CustomerId: {
type: DataTypes.INTEGER,
references: {
model: 'Customers',
key: 'CustomerId',
},
},
VehicleId: {
type: DataTypes.INTEGER,
references: {
model: 'Vehicles',
key: 'VehicleId',
},
},
TestDriveDate: {
type: DataTypes.DATE,
},
Status: {
type: DataTypes.STRING(20),
defaultValue: 'Scheduled',
},
}, {
sequelize,
modelName: 'TestDrive',
timestamps: true,
});
module.exports = TestDrive;
models/ServiceRecord.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class ServiceRecord extends Model {}
ServiceRecord.init({
ServiceRecordId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
VehicleId: {
type: DataTypes.INTEGER,
references: {
model: 'Vehicles',
key: 'VehicleId',
},
},
ServiceDate: {
type: DataTypes.DATE,
},
Description: {
type: DataTypes.TEXT,
},
Cost: {
type: DataTypes.DECIMAL(10, 2),
},
}, {
sequelize,
modelName: 'ServiceRecord',
timestamps: true,
});
module.exports = ServiceRecord;
Step 4: Create Repositories
Create a folder named repositories and implement repository functions.
repositories/userRepository.js
const User = require('../models/User');
exports.createUser = async (userData) => {
return await User.create(userData);
};
exports.getAllUsers = async () => {
return await User.findAll();
};
exports.getUser ById = async (id) => {
return await User.findByPk(id);
};
exports.updateUser = async (id, userData) => {
const user = await User.findByPk(id);
if (user) {
return await user.update(userData);
}
return null;
};
exports.deleteUser = async (id) => {
const user = await User.findByPk(id);
if (user) {
return await user.destroy();
}
return null;
};
Step 5: Create Controllers
Create a folder named controllers and implement controller functions.
controllers/userController.js
const userRepository = require('../repositories/userRepository');
exports.createUser = async (req, res) => {
try {
const user = await userRepository.createUser (req.body);
res.status(201).json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getAllUsers = async (req, res) => {
try {
const users = await userRepository.getAllUsers();
res.status(200).json(users);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getUser ById = async (req, res) => {
try {
const user = await userRepository.getUser ById(req.params.id);
if (user) {
res.status(200).json(user);
} else {
res.status(404).json({ message: 'User not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.updateUser = async (req, res) => {
try {
const user = await userRepository.updateUser (req.params.id, req.body);
if (user) {
res.status(200).json(user);
} else {
res.status(404).json({ message: 'User not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.deleteUser = async (req, res) => {
try {
const result = await userRepository.deleteUser (req.params.id);
if (result) {
res.status(204).send();
} else {
res.status(404).json({ message: 'User not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
Step 6: Set Up Routes
Create a folder named routes and define routes for the user operations.
routes/userRoutes.js
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
router.post('/users', userController.createUser );
router.get('/users', userController.getAllUsers);
router.get('/users/:id', userController.getUser ById);
router.put('/users/:id', userController.updateUser );
router.delete('/users/:id', userController.deleteUser );
module.exports = router;
Step 7: Create Views
Create a folder named views and create EJS files for user management with Bootstrap 5.
views/users.ejs
<% layout('layouts/layout') -%>
<h1>User Management</h1>
<table class="table">
<thead>
<tr>
<th>User ID</th>
<th>Username</th>
<th>Email</th>
<th>Actions</th>
</tr></thead>
<tbody>
<% users.forEach(user => { %>
<tr>
<td><%= user.UserId %></td>
<td><%= user.Username %></td>
<td><%= user.Email %></td>
<td>
<a href="/users/<%= user.UserId %>" class="btn btn-info">View</a>
<a href="/users/edit/<%= user.UserId %>" class="btn btn-warning">Edit</a>
<form action="/users/<%= user.UserId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/users/new" class="btn btn-primary">Add User</a>
views/userForm.ejs
<% layout('layouts/layout') -%>
<h1><%= user ? 'Edit User' : 'Add User' %></h1>
<form action="<%= user ? '/users/' + user.UserId : '/users' %>" method="POST">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="Username" value="<%= user ? user.Username : '' %>" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="Email" value="<%= user ? user.Email : '' %>" required>
</div>
<div class="mb-3">
<label for="phone" class="form-label">Phone</label>
<input type="text" class="form-control" id="phone" name="Phone" value="<%= user ? user.Phone : '' %>">
</div>
<button type="submit" class="btn btn-success"><%= user ? 'Update' : 'Create' %></button>
</form>
Step 8: Run the Application
In your main application file (e.g., app.js), set up the Express server and include the routes.
app.js
const express = require('express');
const bodyParser = require('body-parser');
const methodOverride = require('method-override');
const sequelize = require('./config');
const userRoutes = require('./routes/userRoutes');
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(methodOverride('_method'));
app.use(express.static('public'));
app.use('/', userRoutes);
const PORT = process.env.PORT || 3000;
sequelize.sync().then(() => {
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
}).catch(err => {
console.error('Unable to connect to the database:', err);
});
Step 1: Create Models
models/Inventory.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Inventory extends Model {}
Inventory.init({
InventoryId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
VehicleId: {
type: DataTypes.INTEGER,
references: {
model: 'Vehicles',
key: 'VehicleId',
},
},
Quantity: {
type: DataTypes.INTEGER,
allowNull: false,
},
}, {
sequelize,
modelName: 'Inventory',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt',
});
module.exports = Inventory;
models/Customer.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Customer extends Model {}
Customer.init({
CustomerId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
FirstName: {
type: DataTypes.STRING(50),
allowNull: false,
},
LastName: {
type: DataTypes.STRING(50),
allowNull: false,
},
Email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
},
Phone: {
type: DataTypes.STRING(15),
},
}, {
sequelize,
modelName: 'Customer',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt',
});
module.exports = Customer;
models/Sale.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Sale extends Model {}
Sale.init({
SaleId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
VehicleId: {
type: DataTypes.INTEGER,
references: {
model: 'Vehicles',
key: 'VehicleId',
},
},
CustomerId: {
type: DataTypes.INTEGER,
references: {
model: 'Customers',
key: 'CustomerId',
},
},
SaleDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
SalePrice: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false,
},
PaymentId: {
type: DataTypes.INTEGER,
references: {
model: 'Payments',
key: 'PaymentId',
},
},
}, {
sequelize,
modelName: 'Sale',
timestamps: false,
});
module.exports = Sale;
models/Payment.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Payment extends Model {}
Payment.init({
PaymentId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
SaleId: {
type: DataTypes.INTEGER,
references: {
model: 'Sales',
key: 'SaleId',
},
},
PaymentDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
Amount: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false,
},
PaymentMethod: {
type: DataTypes.STRING(50),
},
Status: {
type: DataTypes.STRING(20),
defaultValue: 'Pending',
},
}, {
sequelize,
modelName: 'Payment',
timestamps: false,
});
module.exports = Payment;
models/Invoice.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Invoice extends Model {}
Invoice.init({
InvoiceId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
SaleId: {
type: DataTypes.INTEGER,
references: {
model: 'Sales',
key: 'SaleId',
},
},
InvoiceDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
TotalAmount: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false,
},
}, {
sequelize,
modelName: 'Invoice',
timestamps: false,
});
module.exports = Invoice;
models/Report.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Report extends Model {}
Report.init({
ReportId: {
type: DataTypes.INTEGER,
primaryKey: true autoIncrement: true,
},
ReportDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
TotalSales: {
type: DataTypes.INTEGER,
},
TotalRevenue: {
type: DataTypes.DECIMAL(10, 2),
},
}, {
sequelize,
modelName: 'Report',
timestamps: true,
createdAt: 'CreatedAt',
});
module.exports = Report;
models/Campaign.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Campaign extends Model {}
Campaign.init({
CampaignId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
CampaignName: {
type: DataTypes.STRING(100),
allowNull: false,
},
StartDate: {
type: DataTypes.DATE,
},
EndDate: {
type: DataTypes.DATE,
},
DiscountPercentage: {
type: DataTypes.DECIMAL(5, 2),
},
}, {
sequelize,
modelName: 'Campaign',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt',
});
module.exports = Campaign;
models/TestDrive.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class TestDrive extends Model {}
TestDrive.init({
TestDriveId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
CustomerId: {
type: DataTypes.INTEGER,
references: {
model: 'Customers',
key: 'CustomerId',
},
},
VehicleId: {
type: DataTypes.INTEGER,
references: {
model: 'Vehicles',
key: 'VehicleId',
},
},
TestDriveDate: {
type: DataTypes.DATE,
},
Status: {
type: DataTypes.STRING(20),
defaultValue: 'Scheduled',
},
}, {
sequelize,
modelName: 'TestDrive',
timestamps: true,
});
module.exports = TestDrive;
models/ServiceRecord.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class ServiceRecord extends Model {}
ServiceRecord.init({
ServiceRecordId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
VehicleId: {
type: DataTypes.INTEGER,
references: {
model: 'Vehicles',
key: 'VehicleId',
},
},
ServiceDate: {
type: DataTypes.DATE,
},
Description: {
type: DataTypes.TEXT,
},
Cost: {
type: DataTypes.DECIMAL(10, 2),
},
}, {
sequelize,
modelName: 'ServiceRecord',
timestamps: true,
});
module.exports = ServiceRecord;
Step 2: Create Repositories
repositories/inventoryRepository.js
const Inventory = require('../models/Inventory');
exports.createInventory = async (inventoryData) => {
return await Inventory.create(inventoryData);
};
exports.getAllInventory = async () => {
return await Inventory.findAll();
};
exports.getInventoryById = async (id) => {
return await Inventory.findByPk(id);
};
exports.updateInventory = async (id, inventoryData) => {
const inventory = await Inventory.findByPk(id);
if (inventory) {
return await inventory.update(inventoryData);
}
return null;
};
exports.deleteInventory = async (id) => {
const inventory = await Inventory.findByPk(id);
if (inventory) {
return await inventory.destroy();
}
return null;
};
repositories/customerRepository.js
const Customer = require('../models/Customer');
exports.createCustomer = async (customerData) => {
return await Customer.create(customerData);
};
exports.getAllCustomers = async () => {
return await Customer.findAll();
};
exports.getCustomerById = async (id) => {
return await Customer.findByPk(id);
};
exports.updateCustomer = async (id, customerData) => {
const customer = await Customer.findByPk(id);
if (customer) {
return await customer.update(customerData);
}
return null;
};
exports.deleteCustomer = async (id) => {
const customer = await Customer.findByPk(id);
if (customer) {
return await customer.destroy();
}
return null;
};
repositories/saleRepository.js
const Sale = require('../models/Sale');
exports.createSale = async (saleData) => {
return await Sale.create(saleData);
};
exports.get AllSales = async () => {
return await Sale.findAll();
};
exports.getSaleById = async (id) => {
return await Sale.findByPk(id);
};
exports.updateSale = async (id, saleData) => {
const sale = await Sale.findByPk(id);
if (sale) {
return await sale.update(saleData);
}
return null;
};
exports.deleteSale = async (id) => {
const sale = await Sale.findByPk(id);
if (sale) {
return await sale.destroy();
}
return null;
};
repositories/paymentRepository.js
const Payment = require('../models/Payment');
exports.createPayment = async (paymentData) => {
return await Payment.create(paymentData);
};
exports.getAllPayments = async () => {
return await Payment.findAll();
};
exports.getPaymentById = async (id) => {
return await Payment.findByPk(id);
};
exports.updatePayment = async (id, paymentData) => {
const payment = await Payment.findByPk(id);
if (payment) {
return await payment.update(paymentData);
}
return null;
};
exports.deletePayment = async (id) => {
const payment = await Payment.findByPk(id);
if (payment) {
return await payment.destroy();
}
return null;
};
repositories/invoiceRepository.js
const Invoice = require('../models/Invoice');
exports.createInvoice = async (invoiceData) => {
return await Invoice.create(invoiceData);
};
exports.getAllInvoices = async () => {
return await Invoice.findAll();
};
exports.getInvoiceById = async (id) => {
return await Invoice.findByPk(id);
};
exports.updateInvoice = async (id, invoiceData) => {
const invoice = await Invoice.findByPk(id);
if (invoice) {
return await invoice.update(invoiceData);
}
return null;
};
exports.deleteInvoice = async (id) => {
const invoice = await Invoice.findByPk(id);
if (invoice) {
return await invoice.destroy();
}
return null;
};
repositories/reportRepository.js
const Report = require('../models/Report');
exports.createReport = async (reportData) => {
return await Report.create(reportData);
};
exports.getAllReports = async () => {
return await Report.findAll();
};
exports.getReportById = async (id) => {
return await Report.findByPk(id);
};
exports.updateReport = async (id, reportData) => {
const report = await Report.findByPk(id);
if (report) {
return await report.update(reportData);
}
return null;
};
exports.deleteReport = async (id) => {
const report = await Report.findByPk(id);
if (report) {
return await report.destroy();
}
return null;
};
repositories/campaignRepository.js
const Campaign = require('../models/Campaign');
exports.createCampaign = async (campaignData) => {
return await Campaign.create(campaignData);
};
exports.getAllCampaigns = async () => {
return await Campaign.findAll();
};
exports.getCampaignById = async (id) => {
return await Campaign.findByPk(id);
};
exports.updateCampaign = async (id, campaignData) => {
const campaign = await Campaign.findByPk(id);
if (campaign) {
return await campaign.update(campaignData);
}
return null;
};
exports.deleteCampaign = async (id) => {
const campaign = await Campaign.findByPk(id);
if (campaign) {
return await campaign.destroy();
}
return null;
};
repositories/testDriveRepository.js
const TestDrive = require('../models/TestDrive');
exports.createTestDrive = async (testDriveData) => {
return await TestDrive.create(testDriveData);
};
exports.getAllTestDrives = async () => {
return await TestDrive.findAll();
};
exports.getTestDriveById = async (id) => {
return await TestDrive.findByPk(id);
};
exports.updateTestDrive = async (id, testDriveData) => {
const testDrive = await TestDrive.findByPk(id);
if (testDrive) {
return await testDrive.update(testDriveData);
}
return null;
};
exports.deleteTestDrive = async (id) => {
const testDrive = await TestDrive.findByPk(id);
if (testDrive) {
return await testDrive.destroy();
}
return null;
};
repositories/serviceRecordRepository.js
const ServiceRecord = require('../models/ServiceRecord');
exports.createServiceRecord = async (serviceRecordData) => {
return await ServiceRecord.create(serviceRecordData);
};
exports.getAllServiceRecords = async () => {
return await ServiceRecord.findAll();
};
exports.getServiceRecordById = async (id) => {
return await ServiceRecord.findByPk(id);
};
exports.updateServiceRecord = async (id, serviceRecordData) => {
const serviceRecord = await ServiceRecord.findByPk(id);
if (serviceRecord) {
return await serviceRecord.update(serviceRecordData);
}
return null;
};
exports.deleteServiceRecord = async (id) => {
const serviceRecord = await ServiceRecord.findByPk(id);
if (serviceRecord) {
return await serviceRecord.destroy();
}
return null;
};
Step 3: Create Controllers
controllers/inventoryController.js
const inventoryRepository = require('../repositories/inventoryRepository');
exports.createInventory = async (req, res) => {
try {
const inventory = await inventoryRepository.createInventory(req.body);
res.status(201).json(inventory);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getAllInventory = async (req, res) => {
try {
const inventory = await inventoryRepository.getAllInventory();
res.status(200).json(inventory);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getInventoryById = async (req, res) => {
try {
const inventory = await inventoryRepository.getInventoryById(req.params.id);
if (inventory) {
res.status(200).json(inventory);
} else {
res.status(404).json({ message: 'Inventory not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.updateInventory = async (req, res) => {
try {
const inventory = await inventoryRepository.updateInventory(req.params.id, req.body);
if (inventory) {
res.status(200).json(inventory);
} else {
res.status(404).json({ message: 'Inventory not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.deleteInventory = async (req, res) => {
try {
const result = await inventoryRepository.deleteInventory(req.params.id);
if (result) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Inventory not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
controllers/customerController.js
const customerRepository = require('../repositories/customerRepository');
exports.createCustomer = async (req, res) => {
try {
const customer = await customerRepository.createCustomer(req.body);
res.status(201).json(customer);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getAllCustomers = async (req, res) => {
try {
const customers = await customerRepository.getAllCustomers();
res.status(200).json(customers);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getCustomerById = async (req, res) => {
try {
const customer = await customerRepository.getCustomerById(req.params.id);
if (customer) {
res.status(200).json(customer);
} else {
res.status(404).json({ message: 'Customer not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.updateCustomer = async (req, res) => {
try {
const customer = await customerRepository.updateCustomer(req.params.id, req.body);
if (customer) {
res.status(200).json(customer);
} else {
res.status(404).json({ message: 'Customer not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.deleteCustomer = async (req, res) => {
try {
const result = await customerRepository.deleteCustomer(req.params.id);
if (result) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Customer not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
controllers/saleController.js
const saleRepository = require('../repositories/saleRepository');
exports.createSale = async (req, res) => {
try {
const sale = await saleRepository.createSale(req.body);
res.status (201).json(sale);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getAllSales = async (req, res) => {
try {
const sales = await saleRepository.getAllSales();
res.status(200).json(sales);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getSaleById = async (req, res) => {
try {
const sale = await saleRepository.getSaleById(req.params.id);
if (sale) {
res.status(200).json(sale);
} else {
res.status(404).json({ message: 'Sale not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.updateSale = async (req, res) => {
try {
const sale = await saleRepository.updateSale(req.params.id, req.body);
if (sale) {
res.status(200).json(sale);
} else {
res.status(404).json({ message: 'Sale not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.deleteSale = async (req, res) => {
try {
const result = await saleRepository.deleteSale(req.params.id);
if (result) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Sale not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
controllers/paymentController.js
const paymentRepository = require('../repositories/paymentRepository');
exports.createPayment = async (req, res) => {
try {
const payment = await paymentRepository.createPayment(req.body);
res.status(201).json(payment);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getAllPayments = async (req, res) => {
try {
const payments = await paymentRepository.getAllPayments();
res.status(200).json(payments);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getPaymentById = async (req, res) => {
try {
const payment = await paymentRepository.getPaymentById(req.params.id);
if (payment) {
res.status(200).json(payment);
} else {
res.status(404).json({ message: 'Payment not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.updatePayment = async (req, res) => {
try {
const payment = await paymentRepository.updatePayment(req.params.id, req.body);
if (payment) {
res.status(200).json(payment);
} else {
res.status(404).json({ message: 'Payment not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.deletePayment = async (req, res) => {
try {
const result = await paymentRepository.deletePayment(req.params.id);
if (result) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Payment not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
controllers/invoiceController.js
const invoiceRepository = require('../repositories/invoiceRepository');
exports.createInvoice = async (req, res) => {
try {
const invoice = await invoiceRepository.createInvoice(req.body);
res.status(201).json(invoice);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getAllInvoices = async (req, res) => {
try {
const invoices = await invoiceRepository.getAllInvoices();
res.status(200).json(invoices);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getInvoiceById = async (req, res) => {
try {
const invoice = await invoiceRepository.getInvoiceById(req.params.id);
if (invoice) {
res.status(200).json(invoice);
} else {
res.status(404).json({ message: 'Invoice not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.updateInvoice = async (req, res) => {
try {
const invoice = await invoiceRepository.updateInvoice(req.params.id, req.body);
if (invoice) {
res.status(200).json(invoice);
} else {
res.status(404).json({ message: 'Invoice not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.deleteInvoice = async (req, res) => {
try {
const result = await invoiceRepository.deleteInvoice(req.params.id);
if (result) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Invoice not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
controllers/reportController.js
const reportRepository = require('../repositories/reportRepository');
exports.createReport = async (req, res) => {
try {
const report = await reportRepository.createReport(req.body);
res.status(201).json(report);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getAllReports = async (req, res) => {
try {
const reports = await reportRepository.getAllReports();
res.status(200).json(reports);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getReportById = async (req, res) => {
try {
const report = await reportRepository.getReportById(req.params.id);
if (report) {
res.status(200).json(report);
} else {
res.status(404).json({ message: 'Report not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.updateReport = async (req, res) => {
try {
const report = await reportRepository.updateReport(req.params.id, req.body);
if (report) {
res.status(200).json(report);
} else {
res.status(404).json({ message: 'Report not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.deleteReport = async (req, res) => {
try {
const result = await reportRepository.deleteReport(req.params.id);
if (result) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Report not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
controllers/campaignController.js
const campaignRepository = require('../repositories/campaignRepository');
exports.createCampaign = async (req, res) => {
try {
const campaign = await campaignRepository.createCampaign(req.body);
res.status(201).json(campaign);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getAllCampaigns = async (req, res) => {
try {
const campaigns = await campaignRepository.getAllCampaigns();
res.status(200).json(campaigns);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getCampaignById = async (req, res) => {
try {
const campaign = await campaignRepository.getCampaignById(req.params.id);
if (campaign) {
res.status(200).json(campaign);
} else {
res.status(404).json({ message: 'Campaign not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.updateCampaign = async (req, res) => {
try {
const campaign = await campaignRepository.updateCampaign(req.params.id, req.body);
if (campaign) {
res.status(200).json(campaign);
} else {
res.status(404).json({ message: 'Campaign not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.deleteCampaign = async (req, res) => {
try {
const result = await campaignRepository.deleteCampaign(req.params.id);
if (result) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Campaign not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
controllers/testDriveController.js
const testDriveRepository = require('../repositories/testDriveRepository');
exports.createTestDrive = async (req, res) => {
try {
const testDrive = await testDriveRepository.createTestDrive(req.body);
res.status(201).json(testDrive);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getAllTestDrives = async (req, res) => {
try {
const testDrives = await testDriveRepository.getAllTestDrives();
res.status(200).json(testDrives);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getTestDriveById = async (req, res) => {
try {
const testDrive = await testDriveRepository.getTestDriveById(req.params.id);
if (testDrive) {
res.status(200).json(testDrive);
} else {
res.status(404).json({ message: 'Test Drive not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.updateTestDrive = async (req, res) => {
try {
const testDrive = await testDriveRepository.updateTestDrive(req.params.id, req.body);
if (testDrive) {
res.status(200).json(testDrive);
} else {
res.status(404).json({ message: 'Test Drive not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.deleteTestDrive = async (req, res) => {
try {
const result = await testDriveRepository.deleteTestDrive(req.params.id);
if (result) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Test Drive not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
controllers/serviceRecordController.js
const serviceRecordRepository = require('../repositories/serviceRecordRepository');
exports.createServiceRecord = async (req, res) => {
try {
const serviceRecord = await serviceRecordRepository.createServiceRecord(req.body);
res.status(201).json(serviceRecord);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getAllServiceRecords = async (req, res) => {
try {
const serviceRecords = await serviceRecordRepository.getAllServiceRecords();
res.status(200).json(serviceRecords);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.getServiceRecordById = async (req, res) => {
try {
const serviceRecord = await serviceRecordRepository.getServiceRecordById(req.params.id);
if (serviceRecord) {
res.status(200).json(serviceRecord);
} else {
res.status(404).json({ message: 'Service Record not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.updateServiceRecord = async (req, res) => {
try {
const serviceRecord = await serviceRecordRepository.updateServiceRecord(req.params.id, req.body);
if (serviceRecord) {
res.status(200).json(serviceRecord);
} else {
res.status(404).json({ message: 'Service Record not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.deleteServiceRecord = async (req, res) => {
try {
const result = await serviceRecordRepository.deleteServiceRecord(req.params.id);
if (result) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Service Record not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
};
Step 4: Create Remaining Routes
routes/inventoryRoutes.js
const express = require('express');
const router = express.Router();
const inventoryController = require('../controllers/inventoryController');
router.post('/inventory', inventoryController.createInventory);
router.get('/inventory', inventoryController.getAllInventory);
router.get('/inventory/:id', inventoryController.getInventoryById);
router.put('/inventory/:id', inventoryController.updateInventory);
router.delete('/inventory/:id', inventoryController.deleteInventory);
module.exports = router;
Step 4: Create Routes
routes/customerRoutes.js
const express = require('express');
const router = express.Router();
const customerController = require('../controllers/customerController');
router.post('/customers', customerController.createCustomer);
router.get('/customers', customerController.getAllCustomers);
router.get('/customers/:id', customerController getCustomerById);
router.put('/customers/:id', customerController.updateCustomer);
router.delete('/customers/:id', customerController.deleteCustomer);
module.exports = router;
routes/saleRoutes.js
const express = require('express');
const router = express.Router();
const saleController = require('../controllers/saleController');
router.post('/sales', saleController.createSale);
router.get('/sales', saleController.getAllSales);
router.get('/sales/:id', saleController.getSaleById);
router.put('/sales/:id', saleController.updateSale);
router.delete('/sales/:id', saleController.deleteSale);
module.exports = router;
routes/paymentRoutes.js
const express = require('express');
const router = express.Router();
const paymentController = require('../controllers/paymentController');
router.post('/payments', paymentController.createPayment);
router.get('/payments', paymentController.getAllPayments);
router.get('/payments/:id', paymentController.getPaymentById);
router.put('/payments/:id', paymentController.updatePayment);
router.delete('/payments/:id', paymentController.deletePayment);
module.exports = router;
routes/invoiceRoutes.js
const express = require('express');
const router = express.Router();
const invoiceController = require('../controllers/invoiceController');
router.post('/invoices', invoiceController.createInvoice);
router.get('/invoices', invoiceController.getAllInvoices);
router.get('/invoices/:id', invoiceController.getInvoiceById);
router.put('/invoices/:id', invoiceController.updateInvoice);
router.delete('/invoices/:id', invoiceController.deleteInvoice);
module.exports = router;
routes/reportRoutes.js
const express = require('express');
const router = express.Router();
const reportController = require('../controllers/reportController');
router.post('/reports', reportController.createReport);
router.get('/reports', reportController.getAllReports);
router.get('/reports/:id', reportController.getReportById);
router.put('/reports/:id', reportController.updateReport);
router.delete('/reports/:id', reportController.deleteReport);
module.exports = router;
routes/campaignRoutes.js
const express = require('express');
const router = express.Router();
const campaignController = require('../controllers/campaignController');
router.post('/campaigns', campaignController.createCampaign);
router.get('/campaigns', campaignController.getAllCampaigns);
router.get('/campaigns/:id', campaignController.getCampaignById);
router.put('/campaigns/:id', campaignController.updateCampaign);
router.delete('/campaigns/:id', campaignController.deleteCampaign);
module.exports = router;
routes/testDriveRoutes.js
const express = require('express');
const router = express.Router();
const testDriveController = require('../controllers/testDriveController');
router.post('/test-drives', testDriveController.createTestDrive);
router.get('/test-drives', testDriveController.getAllTestDrives);
router.get('/test-drives/:id', testDriveController.getTestDriveById);
router.put('/test-drives/:id', testDriveController.updateTestDrive);
router.delete('/test-drives/:id', testDriveController.deleteTestDrive);
module.exports = router;
routes/serviceRecordRoutes.js
const express = require('express');
const router = express.Router();
const serviceRecordController = require('../controllers/serviceRecordController');
router.post('/service-records', serviceRecordController.createServiceRecord);
router.get('/service-records', serviceRecordController.getAllServiceRecords);
router.get('/service-records/:id', serviceRecordController.getServiceRecordById);
router.put('/service-records/:id', serviceRecordController.updateServiceRecord);
router.delete('/service-records/:id', serviceRecordController.deleteServiceRecord);
module.exports = router;
Step 5: Update Main Application File
In your main application file (e.g., app.js), set up the Express server and include all the routes.
app.js
const express = require('express');
const bodyParser = require('body-parser');
const methodOverride = require('method-override');
const sequelize = require('./config');
const userRoutes = require('./routes/userRoutes');
const inventoryRoutes = require('./routes/inventoryRoutes');
const customerRoutes = require('./routes/customerRoutes');
const saleRoutes = require('./routes/saleRoutes');
const paymentRoutes = require('./routes/paymentRoutes');
const invoiceRoutes = require('./routes/invoiceRoutes');
const reportRoutes = require('./routes/reportRoutes');
const campaignRoutes = require('./routes/campaignRoutes');
const testDriveRoutes = require('./routes/testDriveRoutes');
const serviceRecordRoutes = require('./routes/serviceRecordRoutes');
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(methodOverride('_method'));
app.use(express.static('public'));
app.use('/', userRoutes);
app.use('/', inventoryRoutes);
app.use('/', customer Routes);
app.use('/', saleRoutes);
app.use('/', paymentRoutes);
app.use('/', invoiceRoutes);
app.use('/', reportRoutes);
app.use('/', campaignRoutes);
app.use('/', testDriveRoutes);
app.use('/', serviceRecordRoutes);
const PORT = process.env.PORT || 3000;
sequelize.sync().then(() => {
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
}).catch(err => {
console.error('Unable to connect to the database:', err);
});
Step 6: Create Views for Remaining Entities
views/inventory.ejs
<% layout('layouts/layout') -%>
<h1>Inventory Management</h1>
<table class="table">
<thead>
<tr>
<th>Inventory ID</th>
<th>Vehicle ID</th>
<th>Quantity</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% inventory.forEach(item => { %>
<tr>
<td><%= item.InventoryId %></td>
<td><%= item.VehicleId %></td>
<td><%= item.Quantity %></td>
<td>
<a href="/inventory/<%= item.InventoryId %>" class="btn btn-info">View</a>
<a href="/inventory/edit/<%= item.InventoryId %>" class="btn btn-warning">Edit</a>
<form action="/inventory/<%= item.InventoryId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/inventory/new" class="btn btn-primary">Add Inventory</a>
views/customer.ejs
<% layout('layouts/layout') -%>
<h1>Customer Management</h1>
<table class="table">
<thead>
<tr>
<th>Customer ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% customers.forEach(customer => { %>
<tr>
<td><%= customer.CustomerId %></td>
<td><%= customer.FirstName %></td>
<td><%= customer.LastName %></td>
<td><%= customer.Email %></td>
<td>
<a href="/customers/<%= customer.CustomerId %>" class="btn btn-info">View</a>
<a href="/customers/edit/<%= customer.CustomerId %>" class="btn btn-warning">Edit</a>
<form action="/customers/<%= customer.CustomerId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/customers/new" class="btn btn-primary">Add Customer</a>
views/sale.ejs
<% layout('layouts/layout') -%>
<h1>Sale Management</h1>
<table class="table">
<thead>
<tr>
<th>Sale ID</th>
<th>Vehicle ID</th>
<th>Customer ID</th>
<th>Sale Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% sales.forEach(sale => { %>
<tr>
<td><%= sale.SaleId %></td>
<td><%= sale.VehicleId %></td>
<td><%= sale.CustomerId %></td>
<td><%= sale.SalePrice %></td>
<td>
<a href="/sales/<%= sale.SaleId %>" class="btn btn-info">View</a>
<a href="/sales/edit/<%= sale.SaleId %>" class="btn btn-warning">Edit</a>
<form action="/sales/<%= sale.SaleId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/sales/new" class="btn btn-primary">Add Sale</a>
views/payment.ejs
<% layout('layouts/layout') -%>
<h1>Payment Management</h1>
<table class="table">
<thead>
<tr>
<th>Payment ID</th>
<th>Sale ID</th>
<th>Amount</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% payments.forEach(payment => { %>
<tr>
<td><%= payment.PaymentId %></td>
<td><%= payment.SaleId %></td>
<td><%= payment.Amount %></td>
<td><%= payment.Status %></td>
<td>
<a href="/payments/<%= payment.PaymentId %>" class="btn btn-info">View</a>
<a href="/payments/edit/<%= payment.PaymentId %>" class="btn btn-warning">Edit</a>
<form action="/payments/<%= payment.PaymentId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/payments/new" class="btn btn-primary">Add Payment</a>
views/invoice.ejs
<% layout('layouts/layout') -%>
<h1>Invoice Management</h1>
<table class="table">
<thead>
<tr>
<th>Invoice ID</th>
<th>Sale ID</th>
<th>Total Amount</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% invoices.forEach(invoice => { %>
<tr>
<td><%= invoice.InvoiceId %></td>
<td><%= invoice.SaleId %></td>
<td><%= invoice.TotalAmount %></td>
<td>
<a href="/invoices/<%= invoice.InvoiceId %>" class="btn btn-info">View</a>
<a href="/invoices/edit/<%= invoice.InvoiceId %>" class="btn btn-warning">Edit</a>
<form action="/invoices/<%= invoice.InvoiceId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/invoices/new" class="btn btn-primary">Add Invoice</a>
views/report.ejs
<% layout('layouts/layout') -%>
<h1>Report Management</h1>
<table class="table">
<thead>
<tr>
<th>Report ID</th>
<th>Report Date</th>
<th>Total Sales</th>
<th>Total Revenue</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% reports.forEach(report => { %>
<tr>
<td><%= report.ReportId %></td>
<td><%= report.ReportDate %></td>
<td><%= report.TotalSales %></td>
<td><%= report.TotalRevenue %></td>
<td>
<a href="/reports/<%= report.ReportId %>" class="btn btn-info">View</a>
<a href="/reports/edit/<%= report.ReportId %>" class="btn btn-warning">Edit</a>
<form action="/reports/<%= report.ReportId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/reports/new" class="btn btn-primary">Add Report</a>
views/campaign.ejs
<% layout('layouts/layout') -%>
<h1>Campaign Management</h1>
<table class="table">
<thead>
<tr>
<th>Campaign ID</th>
<th>Campaign Name</th>
<th>Start Date</th>
<th>End Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% campaigns.forEach(campaign => { %>
<tr>
<td><%= campaign.CampaignId %></td>
<td><%= campaign.CampaignName %></td>
<td><%= campaign.StartDate %></td>
<td><%= campaign.EndDate %></td>
<td>
<a href="/campaigns/<%= campaign.CampaignId %>" class="btn btn-info">View</a>
<a href="/campaigns/edit/<%= campaign.CampaignId %>" class="btn btn-warning">Edit</a>
<form action="/campaigns/<%= campaign.CampaignId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/campaigns/new" class="btn btn-primary">Add Campaign</a>
views/testDrive.ejs
<% layout('layouts/layout') -%>
<h1>Test Drive Management</h1>
<table class="table">
<thead>
<tr>
<th>Test Drive ID</th>
<th>Customer ID</th>
<th>Vehicle ID</th>
<th>Test Drive Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% testDrives.forEach(testDrive => { %>
<tr>
<td><%= testDrive.TestDriveId %></td>
<td><%= testDrive.CustomerId %></td>
<td><%= testDrive.VehicleId %></td>
<td><%= testDrive.TestDriveDate %></td>
<td><%= testDrive.Status %></td>
<td>
<a href="/test-drives/<%= testDrive.TestDriveId %>" class="btn btn-info">View</a>
<a href="/test-drives/edit/<%= testDrive.TestDriveId %>" class="btn btn-warning">Edit</a>
<form action="/test-drives/<%= testDrive.TestDriveId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/test-drives/new" class="btn btn-primary">Add Test Drive</a>
views/serviceRecord.ejs
<% layout('layouts/layout') -%>
<h1>Service Record Management</h1>
<table class="table">
<thead>
<tr>
<th>Service Record ID</th>
<th>Vehicle ID</th>
<th>Service Date</th>
<th>Cost</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% serviceRecords.forEach(serviceRecord => { %>
<tr>
<td><%= serviceRecord.ServiceRecordId %></td>
<td><%= serviceRecord.VehicleId %></td>
<td><%= serviceRecord.ServiceDate %></td>
<td><%= serviceRecord.Cost %></td>
<td>
<a href="/service-records/<%= serviceRecord.ServiceRecordId %>" class="btn btn-info">View</a>
<a href="/service-records/edit/<%= serviceRecord.ServiceRecordId %>" class="btn btn-warning">Edit</a>
<form action="/service-records/<%= serviceRecord.ServiceRecordId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/service-records/new" class="btn btn-primary">Add Service Record</a>
Final Steps
Run the Application: Start your Node.js application using node app.js and navigate to http://localhost:3000 to access the application.
Test Operations: Ensure that all operations work correctly for each entity by testing the respective routes and views.
This completes the implementation of the vehicle dealership application with complete CRUD operations for all entities using Node.js, Sequelize, Express, EJS, and Bootstrap 5.
To create a complete set of EJS view files that are Bootstrap 5 compatible and use a layout structure for all the controllers in your vehicle dealership application, we will follow these steps:
Create a Layout File: This will serve as the base template for all views.
Create Individual View Files: For each model (Users, Roles, Vehicles, Inventory, Customers, Sales, Payments, Invoices, Reports, Campaigns, Test Drives, and Service Records), we will create the necessary views for listing, creating, editing, and viewing details.
Step 1: Create a Layout File
Create a folder named views/layouts and create a file named layout.ejs.
views/layouts/layout.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-beta1/css/bootstrap.min.css">
<title><%= title %></title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">Vehicle Dealership</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/users">Users</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/roles">Roles</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/vehicles">Vehicles</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/inventory">Inventory</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/customers">Customers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/sales">Sales</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/payments">Payments</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/invoices">Invoices</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/reports">Reports</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/campaigns">Campaigns</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/test-drives">Test Drives</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/service-records">Service Records</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-4">
<%- body %>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-beta1/js/bootstrap.min.js"></script>
</body>
</html>
Step 2: Create Individual View Files
Now, we will create the necessary views for each model. Each model will have views for listing, creating, and editing.
Users Views
views/users/index.ejs
<% layout('layouts/layout') -%>
<h1>User Management</h1>
<a href="/users/new" class="btn btn-primary mb-3">Add User</a>
<table class="table">
<thead>
<tr>
<th>User ID</th>
<th>Username</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% users.forEach(user => { %>
<tr>
<td><%= user.UserId %></td>
<td><%= user.Username %></td>
<td><%= user.Email %></td>
<td>
<a href="/users/<%= user.UserId %>" class="btn btn-info">View</a>
<a href="/users/edit/<%= user.UserId %>" class="btn btn-warning">Edit</a>
<form action="/users/<%= user.UserId %>" method=" POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
views/users/new.ejs
<% layout('layouts/layout') -%>
<h1>Add User</h1>
<form action="/users" method="POST">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<button type="submit" class="btn btn-primary">Create User</button>
</form>
views/users/edit.ejs
<% layout('layouts/layout') -%>
<h1>Edit User</h1>
<form action="/users/<%= user.UserId %>?_method=PUT" method="POST">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username" value="<%= user.Username %>" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" value="<%= user.Email %>" required>
</div>
<button type="submit" class="btn btn-primary">Update User</button>
</form>
Roles Views
views/roles/index.ejs
<% layout('layouts/layout') -%>
<h1>Role Management</h1>
<a href="/roles/new" class="btn btn-primary mb-3">Add Role</a>
<table class="table">
<thead>
<tr>
<th>Role ID</th>
<th>Role Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% roles.forEach(role => { %>
<tr>
<td><%= role.RoleId %></td>
<td><%= role.RoleName %></td>
<td>
<a href="/roles/<%= role.RoleId %>" class="btn btn-info">View</a>
<a href="/roles/edit/<%= role.RoleId %>" class="btn btn-warning">Edit</a>
<form action="/roles/<%= role.RoleId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
views/roles/new.ejs
<% layout('layouts/layout') -%>
<h1>Add Role</h1>
<form action="/roles" method="POST">
<div class="mb-3">
<label for="roleName" class="form-label">Role Name</label>
<input type="text" class="form-control" id="roleName" name="roleName" required>
</div>
<button type="submit" class="btn btn-primary">Create Role</button>
</form>
views/roles/edit.ejs
<% layout('layouts/layout') -%>
<h1>Edit Role</h1>
<form action="/roles/<%= role.RoleId %>?_method=PUT" method="POST">
<div class="mb-3">
<label for="roleName" class="form-label">Role Name</label>
<input type="text" class="form-control" id="roleName" name="roleName" value="<%= role.RoleName %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Role</button>
</form>
Vehicles Views
views/vehicles/index.ejs
<% layout('layouts/layout') -%>
<h1>Vehicle Management</h1>
<a href="/vehicles/new" class="btn btn-primary mb-3">Add Vehicle</a>
<table class="table">
<thead>
<tr>
<th>Vehicle ID</th>
<th>Make</th>
<th>Model</th>
<th>Year</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% vehicles.forEach(vehicle => { %>
<tr>
<td><%= vehicle.VehicleId %></td>
<td><%= vehicle.Make %></td>
<td><%= vehicle.Model %></td>
<td><%= vehicle.Year %></td>
<td><%= vehicle.Price %></td>
<td>
<a href="/vehicles/<%= vehicle.VehicleId %>" class="btn btn-info">View</a>
<a href="/vehicles/edit/<%= vehicle.VehicleId %>" class="btn btn-warning">Edit</a>
<form action="/vehicles/<%= vehicle.VehicleId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
views/vehicles/new.ejs
<% layout('layouts/layout') -%>
<h1>Add Vehicle</h1>
<form action="/vehicles" method="POST">
<div class="mb-3">
<label for="make" class="form-label">Make</label>
<input type="text" class="form-control" id="make" name="make" required>
</div>
<div class="mb-3">
<label for="model" class="form-label">Model</label>
<input type="text" class="form-control" id="model" name="model" required>
</div>
<div class="mb-3">
<label for="year" class="form-label">Year</label>
<input type="number" class="form-control" id="year" name="year" required>
</div>
<div class="mb-3">
<label for="price" class="form-label">Price</label>
<input type="number" class="form-control" id="price" name="price" required>
</div>
<button type="submit" class="btn btn-primary">Create Vehicle</button>
</form>
views/vehicles/edit.ejs
<% layout('layouts/layout') -%>
<h1>Edit Vehicle</h1>
<form action="/vehicles/<%= vehicle.VehicleId %>?_method=PUT" method="POST">
<div class="mb-3">
<label for="make" class="form-label">Make</label>
<input type="text" class="form-control" id="make" name="make" value="<%= vehicle.Make %>" required>
</div>
<div class="mb-3">
<label for="model" class="form-label">Model</label>
<input type="text" class="form-control" id="model" name="model" value="<%= vehicle.Model %>" required>
</div>
<div class="mb-3">
<label for="year" class="form-label">Year</label>
<input type="number" class="form-control" id="year" name="year" value="<%= vehicle.Year %>" required>
</div>
<div class="mb-3">
<label for="price" class="form-label">Price</label>
<input type="number" class="form-control" id="price" name="price" value="<%= vehicle.Price %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Vehicle</button>
</form>
Inventory Views
views/inventory/index.ejs
<% layout('layouts/layout') -%>
<h1>Inventory Management</h1>
<a href="/inventory/new" class="btn btn-primary mb-3">Add Inventory</a>
<table class="table">
<thead>
<tr>
<th>Inventory ID</th>
<th>Vehicle ID</th>
<th>Quantity</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% inventory.forEach(item => { %>
<tr>
<td><%= item.InventoryId %></td>
<td><%= item.VehicleId %></td>
<td><%= item.Quantity %></td>
<td>
<a href="/inventory/<%= item.InventoryId %>" class="btn btn-info">View</a>
<a href="/inventory/edit/<%= item.InventoryId %>" class="btn btn -warning">Edit</a>
<form action="/inventory/<%= item.InventoryId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
views/inventory/new.ejs
<% layout('layouts/layout') -%>
<h1>Add Inventory</h1>
<form action="/inventory" method="POST">
<div class="mb-3">
<label for="vehicleId" class="form-label">Vehicle ID</label>
<input type="number" class="form-control" id="vehicleId" name="vehicleId" required>
</div>
<div class="mb-3">
<label for="quantity" class="form-label">Quantity</label>
<input type="number" class="form-control" id="quantity" name="quantity" required>
</div>
<button type="submit" class="btn btn-primary">Create Inventory</button>
</form>
views/inventory/edit.ejs
<% layout('layouts/layout') -%>
<h1>Edit Inventory</h1>
<form action="/inventory/<%= inventory.InventoryId %>?_method=PUT" method="POST">
<div class="mb-3">
<label for="vehicleId" class="form-label">Vehicle ID</label>
<input type="number" class="form-control" id="vehicleId" name="vehicleId" value="<%= inventory.VehicleId %>" required>
</div>
<div class="mb-3">
<label for="quantity" class="form-label">Quantity</label>
<input type="number" class="form-control" id="quantity" name="quantity" value="<%= inventory.Quantity %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Inventory</button>
</form>
Customers Views
views/customers/index.ejs
<% layout('layouts/layout') -%>
<h1>Customer Management</h1>
<a href="/customers/new" class="btn btn-primary mb-3">Add Customer</a>
<table class="table">
<thead>
<tr>
<th>Customer ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% customers.forEach(customer => { %>
<tr>
<td><%= customer.CustomerId %></td>
<td><%= customer.FirstName %></td>
<td><%= customer.LastName %></td>
<td><%= customer.Email %></td>
<td>
<a href="/customers/<%= customer.CustomerId %>" class="btn btn-info">View</a>
<a href="/customers/edit/<%= customer.CustomerId %>" class="btn btn-warning">Edit</a>
<form action="/customers/<%= customer.CustomerId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
views/customers/new.ejs
<% layout('layouts/layout') -%>
<h1>Add Customer</h1>
<form action="/customers" method="POST">
<div class="mb-3">
<label for="firstName" class="form-label">First Name</label>
<input type="text" class="form-control" id="firstName" name="firstName" required>
</div>
<div class="mb-3">
<label for="lastName" class="form-label">Last Name</label>
<input type="text" class="form-control" id="lastName" name="lastName" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="mb-3">
<label for="phone" class="form-label">Phone</label>
<input type="text" class="form-control" id="phone" name="phone">
</div>
<button type="submit" class="btn btn-primary">Create Customer</button>
</form>
views/customers/edit.ejs
<% layout('layouts/layout') -%>
<h1>Edit Customer</h1>
<form action="/customers/<%= customer.CustomerId %>?_method=PUT" method="POST">
<div class="mb-3">
<label for="firstName" class="form-label">First Name</label>
<input type="text" class="form-control" id="firstName" name="firstName" value="<%= customer.FirstName %>" required>
</div>
<div class="mb-3">
<label for="lastName" class="form-label">Last Name</label>
<input type="text" class="form-control" id="lastName" name="lastName" value="<%= customer.LastName %>" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" value="<%= customer.Email %>" required>
</div>
<div class="mb-3">
<label for="phone" class="form-label">Phone</label>
<input type="text" class="form-control" id="phone" name="phone" value="<%= customer.Phone %>">
</div>
<button type="submit" class="btn btn-primary">Update Customer</button>
</form>
Sales Views
views/sales/index.ejs
<% layout('layouts/layout') -%>
<h1>Sale Management</h1>
<a href="/sales/new" class="btn btn-primary mb-3">Add Sale</a>
<table class="table">
<thead>
<tr>
<th>Sale ID</th>
<th>Vehicle ID</th>
<th>Customer ID</th>
<th>Sale Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% sales.forEach(sale => { %>
<tr>
<td><%= sale.SaleId %></td>
<td><%= sale.VehicleId %></td>
<td><%= sale.CustomerId %></td>
<td><%= sale.SalePrice %></td>
<td>
<a href="/sales/<%= sale.SaleId %>" class="btn btn-info">View</a>
<a href="/sales/edit/<%= sale.SaleId %>" class="btn btn-warning">Edit</a>
<form action="/sales/<%= sale.SaleId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
views/sales/new.ejs
<% layout('layouts/layout') -%>
<h1>Add Sale</h1>
<form action="/sales" method="POST">
<div class="mb-3">
<label for="vehicleId" class="form-label">Vehicle ID</label>
<input type="number" class="form-control" id="vehicleId" name="vehicleId" required>
</div>
<div class="mb-3">
<label for="customerId" class="form-label">Customer ID</label>
<input type="number" class="form-control" id="customerId" name="customerId" required>
</div>
<div class="mb-3">
<label for="salePrice" class="form-label">Sale Price</label>
<input type="number" class="form-control" id="salePrice" name="salePrice" required>
</div>
<button type="submit" class="btn btn-primary">Create Sale</button>
</form>
views/sales/edit.ejs
<% layout('layouts/layout') -%>
<h1>Edit Sale</h1>
<form action="/sales/<%= sale.SaleId %>?_method=PUT" method="POST">
<div class="mb-3">
<label for="vehicleId" class="form-label">Vehicle ID</label>
<input type="number" class="form-control" id="vehicleId" name="vehicleId" value="<%= sale.VehicleId %>" required>
</div>
<div class="mb-3">
<label for="customerId" class="form-label">Customer ID</label>
<input type="number" class="form-control" id="customer Id" name="customerId" value="<%= sale.CustomerId %>" required>
</div>
<div class="mb-3">
<label for="salePrice" class="form-label">Sale Price</label>
<input type="number" class="form-control" id="salePrice" name="salePrice" value="<%= sale.SalePrice %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Sale</button>
</form>
Payments Views
views/payments/index.ejs
<% layout('layouts/layout') -%>
<h1>Payment Management</h1>
<a href="/payments/new" class="btn btn-primary mb-3">Add Payment</a>
<table class="table">
<thead>
<tr>
<th>Payment ID</th>
<th>Sale ID</th>
<th>Amount</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% payments.forEach(payment => { %>
<tr>
<td><%= payment.PaymentId %></td>
<td><%= payment.SaleId %></td>
<td><%= payment.Amount %></td>
<td><%= payment.Status %></td>
<td>
<a href="/payments/<%= payment.PaymentId %>" class="btn btn-info">View</a>
<a href="/payments/edit/<%= payment.PaymentId %>" class="btn btn-warning">Edit</a>
<form action="/payments/<%= payment.PaymentId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
views/payments/new.ejs
<% layout('layouts/layout') -%>
<h1>Add Payment</h1>
<form action="/payments" method="POST">
<div class="mb-3">
<label for="saleId" class="form-label">Sale ID</label>
<input type="number" class="form-control" id="saleId" name="saleId" required>
</div>
<div class="mb-3">
<label for="amount" class="form-label">Amount</label>
<input type="number" class="form-control" id="amount" name="amount" required>
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<input type="text" class="form-control" id="status" name="status">
</div>
<button type="submit" class="btn btn-primary">Create Payment</button>
</form>
views/payments/edit.ejs
<% layout('layouts/layout') -%>
<h1>Edit Payment</h1>
<form action="/payments/<%= payment.PaymentId %>?_method=PUT" method="POST">
<div class="mb-3">
<label for="saleId" class="form-label">Sale ID</label>
<input type="number" class="form-control" id="saleId" name="saleId" value="<%= payment.SaleId %>" required>
</div>
<div class="mb-3">
<label for="amount" class="form-label">Amount</label>
<input type="number" class="form-control" id="amount" name="amount" value="<%= payment.Amount %>" required>
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<input type="text" class="form-control" id="status" name="status" value="<%= payment.Status %>">
</div>
<button type="submit" class="btn btn-primary">Update Payment</button>
</form>
Invoices Views
views/invoices/index.ejs
<% layout('layouts/layout') -%>
<h1>Invoice Management</h1>
<a href="/invoices/new" class="btn btn-primary mb-3">Add Invoice</a>
<table class="table">
<thead>
<tr>
<th>Invoice ID</th>
<th>Sale ID</th>
<th>Total Amount</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% invoices.forEach(invoice => { %>
<tr>
<td><%= invoice.InvoiceId %></td>
<td><%= invoice.SaleId %></td>
<td><%= invoice.TotalAmount %></td>
<td>
<a href="/invoices/<%= invoice.InvoiceId %>" class="btn btn-info">View</a>
<a href="/invoices/edit/<%= invoice.InvoiceId %>" class="btn btn-warning">Edit</a>
<form action="/invoices/<%= invoice.InvoiceId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
views/invoices/new.ejs
<% layout('layouts/layout') -%>
<h1>Add Invoice</h1>
<form action="/invoices" method="POST">
<div class="mb-3">
<label for="saleId" class="form-label">Sale ID</label>
<input type="number" class="form-control" id="saleId" name="saleId" required>
</div>
<div class="mb-3">
<label for="totalAmount" class="form-label">Total Amount</label>
<input type="number" class="form-control" id="totalAmount" name="totalAmount" required>
</div>
<button type="submit" class="btn btn-primary">Create Invoice</button>
</form>
views/invoices/edit.ejs
<% layout('layouts/layout') -%>
<h1>Edit Invoice</h1>
<form action="/invoices/<%= invoice.InvoiceId %>?_method=PUT" method="POST">
<div class="mb-3">
<label for="saleId" class="form-label">Sale ID</label>
<input type="number" class="form-control" id="saleId" name="saleId" value="<%= invoice.SaleId %>" required>
</div>
<div class="mb-3">
<label for="totalAmount" class="form-label">Total Amount</label>
<input type="number" class="form-control" id="totalAmount" name="totalAmount" value="<%= invoice.TotalAmount %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Invoice</button>
</form>
Reports Views
views/reports/index.ejs
<% layout('layouts/layout') -%>
<h1>Report Management</h1>
<a href="/reports/new" class="btn btn-primary mb-3">Add Report</a>
<table class="table">
<thead>
<tr>
<th>Report ID</th>
<th>Report Date</th>
<th>Total Sales</th>
<th>Total Revenue</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% reports.forEach(report => { %>
<tr>
<td><%= report.ReportId %></td>
<td><%= report.ReportDate %></td>
<td><%= report.TotalSales %></td>
<td><%= report.TotalRevenue %></td>
<td>
<a href="/reports/<%= report.ReportId %>" class="btn btn-info">View</a>
<a href="/reports/edit/<%= report.ReportId %>" class="btn btn-warning">Edit</a>
<form action="/reports/<%= report.ReportId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
views/reports/new.ejs
<% layout('layouts/layout') -%>
<h1>Add Report</h1>
<form action="/reports" method="POST">
<div class="mb-3">
<label for="totalSales" class="form-label">Total Sales</label>
<input type="number" class="form-control" id="totalSales" name="totalSales" required>
</div>
<div class="mb-3">
<label for="totalRevenue" class="form-label">Total Revenue</label>
<input type="number" class="form-control" id="totalRevenue" name="totalRevenue" required>
</div>
<button type="submit" class="btn btn-primary">Create Report</button>
</form>
views/reports/edit.ejs
<% layout('layouts/layout') -%>
<h1>Edit Report</h1>
<form action="/reports/<%= report.ReportId %>?_method=PUT" method="POST">
<div class="mb-3">
<label for="totalSales" class="form-label">Total Sales</label>
<input type="number" class="form-control" id="totalSales" name="totalSales" value="<%= report.TotalSales %>" required>
</div>
<div class="mb-3">
<label for="totalRevenue" class="form-label">Total Revenue</label>
<input type="number" class="form-control" id="totalRevenue" name="totalRevenue" value="<%= report.TotalRevenue %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Report</button>
</form>
Campaigns Views
views/campaigns/index.ejs
<% layout('layouts/layout') -%>
<h1>Campaign Management</h1>
<a href="/campaigns/new" class="btn btn-primary mb-3">Add Campaign</a>
<table class="table">
<thead>
<tr>
<th>Campaign ID</th>
<th>Campaign Name</th>
<th>Start Date</th>
<th>End Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% campaigns.forEach(campaign => { %>
<tr>
<td><%= campaign.CampaignId %></td>
<td><%= campaign.CampaignName %></td>
<td><%= campaign.StartDate %></td>
<td><%= campaign.EndDate %></td>
<td>
<a href="/campaigns/<%= campaign.CampaignId %>" class="btn btn-info">View</a>
<a href="/campaigns/edit/<%= campaign.CampaignId %>" class="btn btn-warning">Edit</a>
<form action="/campaigns/<%= campaign.CampaignId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
views/campaigns/new.ejs
<% layout('layouts/layout') -%>
<h1>Add Campaign</h1>
<form action="/campaigns" method="POST">
<div class="mb-3">
<label for="campaignName" class="form-label">Campaign Name</label>
<input type="text" class="form-control" id="campaignName" name="campaignName" required>
</div>
<div class="mb-3">
<label for="startDate" class="form-label">Start Date</label>
<input type="date" class="form-control" id="startDate" name="startDate" required>
</div>
<div class="mb-3">
<label for="endDate" class="form-label">End Date</label>
<input type="date" class="form-control" id="endDate" name="endDate" required>
</div>
<div class="mb-3">
<label for="discountPercentage" class="form-label">Discount Percentage</label>
<input type="number" class="form-control" id="discountPercentage" name="discountPercentage" required>
</div>
<button type="submit" class="btn btn-primary">Create Campaign</button>
</form>
views/campaigns/edit.ejs
<% layout('layouts/layout') -%>
<h1>Edit Campaign</h1>
<form action="/campaigns/<%= campaign.CampaignId %>?_method=PUT" method="POST">
<div class="mb-3">
<label for="campaignName" class="form-label">Campaign Name</label>
<input type="text" class="form-control" id="campaignName" name="campaignName" value="<%= campaign.CampaignName %>" required>
</div>
<div class="mb-3">
<label for="startDate" class="form-label">Start Date</label>
<input type="date" class="form-control" id="startDate" name="startDate" value="<%= campaign.StartDate %>" required>
</div>
<div class="mb-3">
<label for="endDate" class="form-label">End Date</label>
<input type="date" class="form-control" id="endDate" name="endDate" value="<%= campaign.EndDate %>" required>
</div>
<div class="mb-3">
<label for="discountPercentage" class="form-label">Discount Percentage</label>
<input type="number" class="form-control" id="discountPercentage" name="discountPercentage" value="<%= campaign.DiscountPercentage %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Campaign</button>
</form>
Test Drives Views
views/test-drives/index.ejs
<% layout('layouts/layout') -%>
<h1>Test Drive Management</h1>
<a href="/test-drives/new" class="btn btn-primary mb-3">Add Test Drive</a>
<table class="table">
<thead>
<tr>
<th>Test Drive ID</th>
<th>Customer ID</th>
<th>Vehicle ID</th>
<th>Test Drive Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% testDrives.forEach(testDrive => { %>
<tr>
<td><%= testDrive.TestDriveId %></td>
<td><%= testDrive.CustomerId %></td>
<td><%= testDrive.VehicleId %></td>
<td><%= testDrive.TestDriveDate %></td>
<td><%= testDrive.Status %></td>
<td>
<a href="/test-drives/<%= testDrive.TestDriveId %>" class="btn btn-info">View</a>
<a href="/test-drives/edit/<%= testDrive.TestDriveId %>" class="btn btn-warning">Edit</a>
<form action="/test-drives/<%= testDrive.TestDriveId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
views/test-drives/new.ejs
<% layout('layouts/layout') -%>
<h1>Add Test Drive</h1>
<form action="/test-drives" method="POST">
<div class="mb-3">
<label for="customerId" class="form-label">Customer ID</label>
<input type="number" class="form-control" id="customerId" name="customerId" required>
</div>
<div class="mb-3">
<label for="vehicleId" class="form-label">Vehicle ID</label>
<input type="number" class="form-control" id="vehicleId" name="vehicleId" required>
</div>
<div class="mb-3">
<label for="testDriveDate" class="form-label">Test Drive Date</label>
<input type="date" class="form-control" id="testDriveDate" name="testDriveDate" required>
</div>
<button type="submit" class="btn btn-primary">Create Test Drive</button>
</form>
views/test-drives/edit.ejs
<% layout('layouts/layout') -%>
<h1>Edit Test Drive</h1>
<form action="/test-drives/<%= testDrive.TestDriveId %>?_method=PUT" method="POST">
<div class="mb-3">
<label for="customerId" class="form-label">Customer ID</label>
<input type="number" class="form-control" id="customerId" name="customerId" value="<%= testDrive.CustomerId %>" required>
</div>
<div class="mb-3">
<label for="vehicleId" class="form-label">Vehicle ID</label>
<input type="number" class="form-control" id="vehicleId" name="vehicleId" value="<%= testDrive.VehicleId %>" required>
</div>
<div class="mb-3">
<label for="testDriveDate" class="form-label">Test Drive Date</label>
<input type="date" class="form-control" id="testDriveDate" name="testDriveDate" value="<%= testDrive.TestDriveDate %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Test Drive</button>
</form>
Service Records Views
views/service-records/index.ejs
<% layout('layouts/layout') -%>
<h1>Service Record Management</h1>
<a href="/service-records/new" class="btn btn-primary mb-3">Add Service Record</a>
<table class="table">
<thead>
<tr>
<th>Service Record ID</th>
<th>Vehicle ID</th>
<th>Service Date</th>
<th>Cost</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% serviceRecords.forEach(serviceRecord => { %>
<tr>
<td><%= serviceRecord.ServiceRecordId %></td>
<td><%= serviceRecord.VehicleId %></td>
<td><%= serviceRecord.ServiceDate %></td>
<td><%= serviceRecord.Cost %></td>
<td>
<a href="/service-records/<%= serviceRecord.ServiceRecordId %>" class="btn btn-info">View</a>
<a href="/service-records/edit/<%= serviceRecord.ServiceRecordId %>" class="btn btn-warning">Edit</a>
<form action="/service-records/<%= serviceRecord.ServiceRecordId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
views/service-records/new.ejs
<% layout('layouts/layout') -%>
<h1>Add Service Record</h1>
<form action="/service-records" method="POST">
<div class="mb-3">
<label for="vehicleId" class="form-label">Vehicle ID</label>
<input type="number" class="form-control" id="vehicleId" name="vehicleId" required>
</div>
<div class="mb-3">
<label for="serviceDate" class="form-label">Service Date</label>
<input type="date" class="form-control" id="serviceDate" name="serviceDate" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="description" required></textarea>
</div>
<div class="mb-3">
<label for="cost" class="form-label">Cost</label>
<input type="number" class="form-control" id="cost" name="cost" required>
</div>
<button type="submit" class="btn btn-primary">Create Service Record</button>
</form>
views/service-records/edit.ejs
<% layout('layouts/layout') -%>
<h1>Edit Service Record</h1>
<form action="/service-records/<%= serviceRecord.ServiceRecordId %>?_method=PUT" method="POST">
<div class="mb-3">
<label for="vehicleId" class="form-label">Vehicle ID</label>
<input type="number" class="form-control" id="vehicleId" name="vehicleId" value="<%= serviceRecord.VehicleId %>" required>
</div>
<div class="mb-3">
<label for="serviceDate" class="form-label">Service Date</label>
<input type="date" class="form-control" id="serviceDate" name="serviceDate" value="<%= serviceRecord.ServiceDate %>" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="description" required><%= serviceRecord.Description %></textarea>
</div>
<div class="mb-3">
<label for="cost" class="form-label">Cost</label>
<input type="number" class="form-control" id="cost" name="cost" value="<%= serviceRecord.Cost %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Service Record</button>
</form>
Final Notes
Ensure Bootstrap 5 is Loaded: The layout file includes Bootstrap 5 CSS and JS links. Make sure you have internet access or download Bootstrap files locally if needed.
Test All Views: After creating all the views, run your application and navigate through each section to ensure that all operations work as expected.
Adjust Styles as Needed: You can customize the styles further based on your design preferences.
This completes the creation of all EJS view files that are Bootstrap 5 compatible and use a layout structure for your vehicle dealership application.
To create a dashboard page for your vehicle dealership application that displays consolidated data, we will follow these steps:
Create the Dashboard View: This will display the consolidated data.
Create the Dashboard Controller: This will handle the logic for fetching the data.
Set Up the Route: This will define the route for accessing the dashboard.
Fetch and Display Data: The dashboard will show total counts for Users, Vehicles, Customers, Sales, Payments, and any other relevant metrics.
Step 1: Create the Dashboard View
Create a new EJS file for the dashboard in the views directory.
views/dashboard.ejs
<% layout('layouts/layout') -%>
<h1>Dashboard</h1>
<div class="row">
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Total Users</h5>
<p class="card-text"><%= totalUsers %></p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Total Vehicles</h5>
<p class="card-text"><%= totalVehicles %></p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Total Customers</h5>
<p class="card-text"><%= totalCustomers %></p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Total Sales</h5>
<p class="card-text"><%= totalSales %></p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Total Payments</h5>
<p class="card-text"><%= totalPayments %></p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Total Revenue</h5>
<p class="card-text"><%= totalRevenue %></p>
</div>
</div>
</div>
</div>
Step 2: Create the Dashboard Controller
In your controllers directory, create a new file for the dashboard logic.
controllers/dashboardController.js
const User = require('../models/User');
const Vehicle = require('../models/Vehicle');
const Customer = require('../models/Customer');
const Sale = require('../models/Sale');
const Payment = require('../models/Payment');
exports.getDashboard = async (req, res) => {
try {
const totalUsers = await User.count();
const totalVehicles = await Vehicle.count();
const totalCustomers = await Customer.count();
const totalSales = await Sale.count();
const totalPayments = await Payment.count();
const totalRevenue = await Payment.sum('Amount'); // Assuming you want the total revenue from payments
res.render('dashboard', {
title: 'Dashboard',
totalUsers,
totalVehicles,
totalCustomers,
totalSales,
totalPayments,
totalRevenue
});
} catch (error) {
console.error(error);
res.status(500).send('Server Error');
}
};
Step 3: Set Up the Route
In your routes file, add a route for the dashboard.
routes/dashboardRoutes.js
const express = require('express');
const router = express.Router();
const dashboardController = require('../controllers/dashboardController');
router.get('/dashboard', dashboardController.getDashboard);
module.exports = router;
Step 4: Update Main Application File
In your main application file (e.g., app.js), include the dashboard routes.
app.js
const express = require('express');
const bodyParser = require('body-parser');
const methodOverride = require('method-override');
const sequelize = require('./config');
const userRoutes = require('./routes/userRoutes');
const inventoryRoutes = require('./routes/inventoryRoutes');
const customerRoutes = require('./routes/customerRoutes');
const saleRoutes = require('./routes/saleRoutes');
const paymentRoutes = require('./routes/paymentRoutes');
const invoiceRoutes = require('./routes/invoiceRoutes');
const reportRoutes = require('./routes/reportRoutes');
const campaignRoutes = require('./routes/campaignRoutes');
const testDriveRoutes = require('./routes/testDriveRoutes');
const serviceRecordRoutes = require('./routes/serviceRecordRoutes');
const dashboardRoutes = require('./routes/dashboardRoutes'); // Include dashboard routes
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({ extended : true }));
app.use(methodOverride('_method'));
app.use(express.static('public'));
app.use('/users', userRoutes);
app.use('/inventory', inventoryRoutes);
app.use('/customers', customerRoutes);
app.use('/sales', saleRoutes);
app.use('/payments', paymentRoutes);
app.use('/invoices', invoiceRoutes);
app.use('/reports', reportRoutes);
app.use('/campaigns', campaignRoutes);
app.use('/test-drives', testDriveRoutes);
app.use('/service-records', serviceRecordRoutes);
app.use('/', dashboardRoutes); // Use dashboard routes
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Final Notes
Ensure Models are Defined: Make sure that the models for User, Vehicle, Customer, Sale, and Payment are correctly defined and connected to your database.
Test the Dashboard: After implementing the dashboard, navigate to /dashboard in your application to see the consolidated data displayed.
Customize as Needed: You can further customize the dashboard layout and the data displayed based on your project requirements.