Compare commits

...

10 Commits

Author SHA1 Message Date
Ayobami b277c8182d feat: complete day 1 2025-07-10 21:08:42 +01:00
manaknightdigital 1703819bda Merge pull request #2 from emmymayo/master
baas task
2023-12-08 02:06:12 -05:00
Mayowa Emmanuel 7bbafc90a8 baas task 2023-12-07 21:44:21 +00:00
manaknightdigital b640c08c09 Update README.md 2023-12-04 21:28:57 -05:00
manaknightdigital 04a5ae01cf Update README.md 2023-11-21 13:26:44 -05:00
Possible 5485f1af1d Update 2023-11-16 18:50:16 +01:00
ryanwong 7a6da5203e add treeql 2023-05-09 09:33:31 -04:00
manaknightdigital a4177125f8 Update README.md 2022-10-21 12:32:23 -04:00
manaknightdigital 595876509a Merge pull request #1 from To-heeb/master
update of the sequelize link in README of day1 activity to a active doc
2022-10-17 09:28:06 -04:00
Toheeb Oyekola 059da72768 update of the sequelize link in README of day1 activity to a the active doc 2022-10-12 03:05:51 +01:00
20 changed files with 553 additions and 92 deletions
+1
View File
@@ -0,0 +1 @@
# This project is a toy project for training and quality assurance purposes
+2
View File
@@ -0,0 +1,2 @@
DB_PASSWORD=ayobamidavid
PORT=8000
+1 -1
View File
@@ -4,7 +4,7 @@
- setup project
- clone to your github
- Read the documentation https://sequelize.org/docs/v6/getting-started/
- Read the documentation https://sequelize.org/docs/v7/getting-started/
- Setup the following Models in models folder. Make sure tables made by sequelize:
```
+24 -15
View File
@@ -1,29 +1,38 @@
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var createError = require("http-errors");
var express = require("express");
var path = require("path");
var cookieParser = require("cookie-parser");
var logger = require("morgan");
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var indexRouter = require("./routes/index");
var usersRouter = require("./routes/users");
const db = require("./models");
var cors = require("cors");
const shippingDockRouter = require("./routes/shippingDock");
const orderRouter = require("./routes/order");
const transactionRouter = require("./routes/transaction");
var app = express();
app.set("db", db);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "jade");
app.use(cors());
app.use(logger('dev'));
app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, "public")));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use("/", indexRouter);
app.use("/users", usersRouter);
// ROUTES
app.use("/api/v1/shipping_dock", shippingDockRouter);
app.use("/api/v1/order", orderRouter);
app.use("/api/v1/transaction", transactionRouter);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
@@ -34,11 +43,11 @@ app.use(function (req, res, next) {
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
res.locals.error = req.app.get("env") === "development" ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
res.render("error");
});
module.exports = app;
+16 -19
View File
@@ -4,16 +4,16 @@
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('day-1:server');
var http = require('http');
var app = require("../app");
var debug = require("debug")("day-1:server");
var http = require("http");
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
var port = normalizePort(process.env.PORT || "3000");
app.set("port", port);
/**
* Create HTTP server.
@@ -26,8 +26,8 @@ var server = http.createServer(app);
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
server.on("error", onError);
server.on("listening", onListening);
/**
* Normalize a port into a number, string, or false.
@@ -54,22 +54,20 @@ function normalizePort(val) {
*/
function onError(error) {
if (error.syscall !== 'listen') {
if (error.syscall !== "listen") {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
var bind = typeof port === "string" ? "Pipe " + port : "Port " + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
case "EACCES":
console.error(bind + " requires elevated privileges");
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
case "EADDRINUSE":
console.error(bind + " is already in use");
process.exit(1);
break;
default:
@@ -83,8 +81,7 @@ function onError(error) {
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
var bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port;
debug("Listening on " + bind);
console.log("Server is listening on " + bind);
}
+48 -34
View File
@@ -1,4 +1,4 @@
'use strict';
"use strict";
/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2020*/
/**
* Sequelize File
@@ -8,49 +8,63 @@
* @author Ryan Wong
*
*/
const fs = require('fs');
const path = require('path');
let Sequelize = require('sequelize');
const fs = require("fs");
const path = require("path");
let Sequelize = require("sequelize");
const basename = path.basename(__filename);
const { DataTypes } = require('sequelize');
const { DataTypes } = require("sequelize");
const config = {
DB_DATABASE: 'mysql',
DB_USERNAME: 'root',
DB_PASSWORD: 'root',
DB_ADAPTER: 'mysql',
DB_NAME: 'day_1',
DB_HOSTNAME: 'localhost',
DB_DATABASE: "mysql",
DB_USERNAME: "root",
DB_PASSWORD: process.env.DB_PASSWORD,
DB_ADAPTER: "mysql",
DB_NAME: "day_1",
DB_HOSTNAME: "localhost",
DB_PORT: 3306,
};
let db = {};
let sequelize = new Sequelize(config.DB_DATABASE, config.DB_USERNAME, config.DB_PASSWORD, {
dialect: config.DB_ADAPTER,
username: config.DB_USERNAME,
password: config.DB_PASSWORD,
database: config.DB_NAME,
host: config.DB_HOSTNAME,
port: config.DB_PORT,
logging: console.log,
timezone: '-04:00',
pool: {
maxConnections: 1,
minConnections: 0,
maxIdleTime: 100,
},
define: {
timestamps: false,
underscoredAll: true,
underscored: true,
},
});
let sequelize = new Sequelize(
config.DB_NAME,
config.DB_USERNAME,
config.DB_PASSWORD,
{
dialect: config.DB_ADAPTER,
username: config.DB_USERNAME,
password: config.DB_PASSWORD,
database: config.DB_NAME,
host: config.DB_HOSTNAME,
port: config.DB_PORT,
logging: console.log,
timezone: "-04:00",
pool: {
maxConnections: 1,
minConnections: 0,
maxIdleTime: 100,
},
define: {
timestamps: false,
underscoredAll: true,
underscored: true,
},
}
);
// sequelize.sync({ force: true });
sequelize
.sync()
.then(() => {
console.log("All tables synced successfully.");
})
.catch((err) => {
console.error("Failed to sync tables:", err);
});
fs.readdirSync(__dirname)
.filter((file) => {
return file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js';
return (
file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js"
);
})
.forEach((file) => {
var model = require(path.join(__dirname, file))(sequelize, DataTypes);
@@ -66,4 +80,4 @@ Object.keys(db).forEach((modelName) => {
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
module.exports = db;
+4 -10
View File
@@ -1,5 +1,5 @@
module.exports = (sequelize, DataTypes) => {
const location = sequelize.define(
return sequelize.define(
"location",
{
id: {
@@ -8,19 +8,13 @@ module.exports = (sequelize, DataTypes) => {
autoIncrement: true,
},
name: DataTypes.STRING,
created_at: DataTypes.DATEONLY,
updated_at: DataTypes.DATE,
},
{
timestamps: true,
freezeTableName: true,
tableName: "location",
},
{
underscoredAll: false,
underscored: false,
createdAt: "created_at",
updatedAt: "updated_at",
}
);
return location;
};
};
+37
View File
@@ -0,0 +1,37 @@
module.exports = (sequelize, DataTypes) => {
return sequelize.define(
"Order",
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
order_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
user_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
shipping_dock_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
amount: {
type: DataTypes.INTEGER,
allowNull: false,
},
notes: DataTypes.STRING,
status: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0,
},
},
{
tableName: "orders",
}
);
};
+24
View File
@@ -0,0 +1,24 @@
module.exports = (sequelize, DataTypes) => {
return sequelize.define(
"ShippingDock",
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
status: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0,
},
},
{
tableName: "shipping_dock",
}
);
};
+32
View File
@@ -0,0 +1,32 @@
module.exports = (sequelize, DataTypes) => {
return sequelize.define(
"Transaction",
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
order_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
user_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
shipping_dock_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
amount: {
type: DataTypes.INTEGER,
allowNull: false,
},
notes: DataTypes.STRING,
},
{
tableName: "transactions",
}
);
};
+2 -1
View File
@@ -3,7 +3,8 @@
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
"start": "node ./bin/www",
"dev": "node --watch --env-file=.env ./bin/www"
},
"dependencies": {
"cookie-parser": "~1.4.4",
+104
View File
@@ -0,0 +1,104 @@
const express = require("express");
const router = express.Router();
const { Order } = require("../models");
const {
handleError,
handleSuccess,
handleSequelizeError,
deepEqual,
} = require("../utils");
// GET all orders
router.get("/", async (_, res) => {
try {
const orders = await Order.findAll();
handleSuccess(res, orders);
} catch (err) {
handleSequelizeError(err, res);
}
});
// GET one order by id
router.get("/:id", async (req, res) => {
try {
const order = await Order.findByPk(req.params.id);
if (!order) return handleError("Order not found", 404, res);
handleSuccess(res, order);
} catch (err) {
handleSequelizeError(err, res);
}
});
// POST create an order
router.post("/", async (req, res) => {
try {
const { order_id, user_id, shipping_dock_id, amount, notes } = req.body;
if (
order_id === undefined ||
user_id === undefined ||
shipping_dock_id === undefined ||
amount === undefined ||
notes === undefined
) {
return handleError("All fields are required", 400, res);
}
const order = await Order.create(req.body);
handleSuccess(res, order, 201);
} catch (err) {
handleError(err.message, 500, res);
}
});
// PUT update an order
router.put("/:id", async (req, res) => {
try {
const { id } = req.params;
const order = await Order.findByPk(id);
if (!order) return handleError("Order not found", 404, res);
// Only allow updating amount, notes, and status
const allowedFields = ["amount", "notes", "status"];
const changes = {};
for (const key of allowedFields) {
if (
req.body[key] !== undefined &&
!deepEqual(req.body[key], order[key])
) {
changes[key] = req.body[key];
}
}
// Validate status if present
if (
changes.status !== undefined &&
![0, 1].includes(Number(changes.status))
) {
return handleError("Status must be 0 or 1", 400, res);
}
if (Object.keys(changes).length === 0) {
return handleError("No updated fields", 400, res); // No changes
}
await order.update(changes);
handleSuccess(res, await Order.findByPk(id));
} catch (err) {
handleSequelizeError(err, res);
}
});
// DELETE an order
router.delete("/:id", async (req, res) => {
try {
const deleted = await Order.destroy({
where: { id: req.params.id },
});
if (deleted === 0) return handleError("Order not found", 404, res);
handleSuccess(res, null, 204); // 204 No Content
} catch (err) {
handleSequelizeError(err, res);
}
});
module.exports = router;
+94
View File
@@ -0,0 +1,94 @@
const express = require("express");
const router = express.Router();
const { ShippingDock } = require("../models");
const {
handleError,
handleSuccess,
handleSequelizeError,
deepEqual,
} = require("../utils");
// GET all shipping docks
router.get("/", async (_, res) => {
try {
const docks = await ShippingDock.findAll();
handleSuccess(res, docks);
} catch (err) {
handleSequelizeError(err, res);
}
});
// GET one shipping dock by id
router.get("/:id", async (req, res) => {
try {
const dock = await ShippingDock.findByPk(req.params.id);
if (!dock) return handleError("Dock not found", 404, res);
handleSuccess(res, dock);
} catch (err) {
handleSequelizeError(err, res);
}
});
// POST create a shipping dock
router.post("/", async (req, res) => {
try {
const { name } = req.body;
if (!name || !name.trim()) {
return handleError("Name is required and cannot be empty", 400, res);
}
await ShippingDock.create(req.body);
handleSuccess(res, dock, 201);
} catch (err) {
handleError(err.message, 500, res);
}
});
// PUT update a shipping dock
router.put("/:id", async (req, res) => {
try {
const { id } = req.params;
const dock = await ShippingDock.findByPk(id);
if (!dock) return handleError("Dock not found", 404, res);
// Validate status separately
if (
req.body.status !== undefined &&
![0, 1].includes(Number(req.body.status))
) {
return handleError("Status must be 0 or 1", 400, res);
}
// Build changes object dynamically
const changes = {};
for (const key in req.body) {
if (req.body[key] !== undefined && !deepEqual(req.body[key], dock[key])) {
changes[key] = req.body[key];
}
}
if (Object.keys(changes).length === 0) {
return handleError("No updated fields", 400, res); // No changes
}
await dock.update(changes);
handleSuccess(res, await ShippingDock.findByPk(id));
} catch (err) {
handleSequelizeError(err, res);
}
});
// DELETE a shipping dock
router.delete("/:id", async (req, res) => {
try {
const deleted = await ShippingDock.destroy({
where: { id: req.params.id },
});
if (deleted === 0) return handleError("Dock not found", 404, res);
handleSuccess(res, null, 204); // 204 No Content
} catch (err) {
handleSequelizeError(err, res);
}
});
module.exports = router;
+96
View File
@@ -0,0 +1,96 @@
const express = require("express");
const router = express.Router();
const { Transaction } = require("../models");
const {
handleError,
handleSuccess,
handleSequelizeError,
deepEqual,
} = require("../utils");
// GET all transactions
router.get("/", async (_, res) => {
try {
const transactions = await Transaction.findAll();
handleSuccess(res, transactions);
} catch (err) {
handleSequelizeError(err, res);
}
});
// GET one transaction by id
router.get("/:id", async (req, res) => {
try {
const transaction = await Transaction.findByPk(req.params.id);
if (!transaction) return handleError("Transaction not found", 404, res);
handleSuccess(res, transaction);
} catch (err) {
handleSequelizeError(err, res);
}
});
// POST create a transaction
router.post("/", async (req, res) => {
try {
const { order_id, user_id, shipping_dock_id, amount, notes } = req.body;
if (
order_id === undefined ||
user_id === undefined ||
shipping_dock_id === undefined ||
amount === undefined ||
notes === undefined
) {
return handleError("All fields are required", 400, res);
}
const transaction = await Transaction.create(req.body);
handleSuccess(res, transaction, 201);
} catch (err) {
handleError(err.message, 500, res);
}
});
// PUT update a transaction
router.put("/:id", async (req, res) => {
try {
const { id } = req.params;
const transaction = await Transaction.findByPk(id);
if (!transaction) return handleError("Transaction not found", 404, res);
// Only allow updating amount and notes
const allowedFields = ["amount", "notes"];
const changes = {};
for (const key of allowedFields) {
if (
req.body[key] !== undefined &&
!deepEqual(req.body[key], transaction[key])
) {
changes[key] = req.body[key];
}
}
if (Object.keys(changes).length === 0) {
return handleError("No updated fields", 400, res); // No changes
}
await transaction.update(changes);
handleSuccess(res, await Transaction.findByPk(id));
} catch (err) {
handleSequelizeError(err, res);
}
});
// DELETE a transaction
router.delete("/:id", async (req, res) => {
try {
const deleted = await Transaction.destroy({
where: { id: req.params.id },
});
if (deleted === 0) return handleError("Transaction not found", 404, res);
handleSuccess(res, null, 204); // 204 No Content
} catch (err) {
handleSequelizeError(err, res);
}
});
module.exports = router;
+29
View File
@@ -0,0 +1,29 @@
const handleError = (message, status, res) => {
res.status(status).json({ success: false, message });
};
const handleSuccess = (res, data = null, status = 200) => {
res.status(status).json({
success: true,
...(data && { data }),
});
};
// Centralize Sequelize error handling
const handleSequelizeError = (err, res) => {
if (err.name === "SequelizeValidationError") {
return handleError(err.errors.map((e) => e.message).join(", "), 400, res);
}
handleError(err.message, 500, res);
};
function deepEqual(a, b) {
return JSON.stringify(a) === JSON.stringify(b);
}
module.exports = {
handleError,
handleSuccess,
handleSequelizeError,
deepEqual,
};
+1 -6
View File
@@ -3,9 +3,4 @@
## Instructions
- setup project
- clone to your github
- Open figma file https://www.figma.com/file/Zr1EutaLsykPcADfC3el7r/ai-marketing-site-sample?node-id=0%3A1
- Need you to finish the site by end of day both mobile and desktop responsive
- Use bootstrap 4
- CSS should be clean, not using inline style CSS but proper classes
- deploy site using github pages https://www.codecademy.com/articles/f1-u3-github-pages
- implement https://www.treeql.org/ manually
+6 -4
View File
@@ -2,7 +2,9 @@
## Instructions
- setup project
- clone to your github
- Make the frontend for this project https://www.figma.com/file/iaKhmTAN28YiYXAOZAr9rN/Scheduler-Task?node-id=0%3A1
- timezones are generated dynamically
- Setup project
- Clone to your github
- Check this https://www.figma.com/file/iaKhmTAN28YiYXAOZAr9rN/Scheduler-Task?node-id=0%3A1
- Convert it into ejs/eta.
- Timezones should be generated dynamically
- Make a book schedule API like calendly.
+30 -1
View File
@@ -1 +1,30 @@
Continue day 19 if not done
# Day 20
Read:
- https://www.notion.so/How-to-Use-Baas-00f549dda3a84dc48b352c79222f1a3a
- https://www.notion.so/Create-Manage-Projects-With-Wireframe-Tool-df67b882f0c14735a0192d69dc3ff777
- Request for Wireframe tool url from Project Manager.
1. login to Wireframe tool. Create SOW and Wireframe called <name-inventory>.
2. Navigate to Wireframe side-menu click, Edit > Setting, create a project (<name-inventory>) from here according to specifications of wireframe document provided (inventory-app.pdf).
3. Create Models. Switch to Models tab or Web/React tab (Manage Models).
4. Create Roles and set Permissions. (Web/React Tab > Manage Permissions).
5. Create React portal and marketing pages and then export React. (Web/React Tab).
6. Create Custom APIs and commit. (API tab). API code would be commited to http://23.29.118.76:3000/mkdlabs/<name-inventory_backend>.git
7. Switch to Deployment Tab. Initialize deployment and create repositories.
8. Setup BAAS locally. Clone http://23.29.118.76:3000/mkdlabs/mkd_baas.git
9. npm install and request for config from Project Manager.
10. Clone backend repo on src/backend/custom
11. Write APIs, and test locally.
Binary file not shown.
+2 -1
View File
@@ -54,7 +54,8 @@ DELETE /api/v1/user/:id (delete one)
```
1.Loop through all active users
2.Loop through all odd id emails if today is monday, wednesday, friday. Otherwise do all even id for other days.
3.Write into email queue what email to send from step 2. Set status as not sent. Set send_at as next day.
4.Loop through all the users in user table and make a table of user_id.
3.Write into email queue for each user in step 2 (so if 3 total emails, 2 ids are odd, say there 5 users so on monday you add 2 x 5 = 10 emails into email_queue.) what email to send from step 2. Set status as not sent. Set send_at as next day.
```
- create a cronjob called email_sending.js in cronjob folder