Skip to content

Commit 000e18d

Browse files
authored
Merge pull request #17 from oslabs-beta/orders
Orders yesssir
2 parents bc6f026 + 9588cc5 commit 000e18d

File tree

11 files changed

+6280
-2
lines changed

11 files changed

+6280
-2
lines changed

examples_new/microservices/orders/package-lock.json

+5,915
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples_new/microservices/orders/package.json

+36-2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,43 @@
44
"description": "",
55
"main": "index.js",
66
"scripts": {
7-
"test": "echo \"Error: no test specified\" && exit 1"
7+
"start": "ts-node-dev ./src/index.ts",
8+
"test": "jest --watchAll --no-cache"
9+
},
10+
"jest": {
11+
"preset": "ts-jest",
12+
"testEnvironment": "node",
13+
"setupFilesAfterEnv": [
14+
"./src/test/setup.ts"
15+
]
816
},
917
"keywords": [],
1018
"author": "",
11-
"license": "ISC"
19+
"license": "ISC",
20+
"dependencies": {
21+
"@chronosrx/common": "^1.0.2",
22+
"axios": "^1.6.2",
23+
"bcryptjs": "^2.4.3",
24+
"cookie-parser": "^1.4.6",
25+
"dotenv": "^16.3.1",
26+
"express": "^4.18.2",
27+
"express-async-errors": "^3.1.1",
28+
"jsonwebtoken": "^9.0.2",
29+
"mongoose": "^8.0.3",
30+
"ts-node-dev": "^2.0.0"
31+
},
32+
"devDependencies": {
33+
"@types/bcryptjs": "^2.4.6",
34+
"@types/cookie-parser": "^1.4.6",
35+
"@types/express": "^4.17.21",
36+
"@types/jest": "^29.5.11",
37+
"@types/jsonwebtoken": "^9.0.5",
38+
"@types/supertest": "^2.0.16",
39+
"jest": "^29.7.0",
40+
"mongodb-memory-server": "^9.1.1",
41+
"supertest": "^6.3.3",
42+
"ts-jest": "^29.1.1"
43+
}
1244
}
45+
46+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import request from 'supertest';
2+
import { app } from '../app';
3+
// Mongo Memory Server - Users collection always starts out empty**
4+
it('success if there is itemid and units', async () => {
5+
const itemId = '6581bbc692686e6e68d25d7d';
6+
const sellerID = '123123';
7+
await global.createItem(itemId);
8+
const response = await request(app)
9+
.get('/api/orders/getMyOrder')
10+
.send({
11+
itemId: itemId,
12+
})
13+
.expect(200);
14+
// console.log(response);
15+
expect(response.body.units).toEqual(50);
16+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import express from 'express';
2+
import 'express-async-errors';
3+
import dotenv from 'dotenv';
4+
dotenv.config();
5+
import { NotFoundError, errorHandler } from '@chronosrx/common';
6+
import cookieParser from 'cookie-parser';
7+
import orderRouter from './routes/order-router';
8+
import eventRouter from './routes/event-router';
9+
10+
const app = express();
11+
12+
app.use(express.json());
13+
app.use(cookieParser());
14+
15+
// app.get('/', (req, res) => {
16+
// console.log('💥 Test Route');
17+
// res.status(200).send({ msg: '💥 Test route' });
18+
// });
19+
20+
app.use('/api/orders', orderRouter);
21+
app.use('/events', eventRouter);
22+
23+
app.use('*', (req, res) => {
24+
throw new NotFoundError();
25+
});
26+
27+
app.use(errorHandler);
28+
29+
export { app };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { Request, Response } from 'express';
2+
import axios from 'axios';
3+
import { Order } from '../models/Order';
4+
import { BadRequestError, CurrentUserRequest, Events } from '@chronosrx/common';
5+
import { Inventory } from '../models/Inventory';
6+
7+
export const createOrder = async (req: CurrentUserRequest, res: Response) => {
8+
//deconstruct req.body
9+
const buyerId = req.currentUser;
10+
const { itemId, amount, totalPrice, sellerId } = req.body;
11+
//create Order document in the databse
12+
const newOrder = Inventory.build({});
13+
await newOrder.save();
14+
//send created order to event bus
15+
await axios.post('http://localhost:3005/', {
16+
event: {
17+
type: Events.ORDER_CREATED,
18+
payload: newOrder,
19+
},
20+
});
21+
res.status(201).send(newOrder);
22+
};
23+
24+
export const getOrder = async (req: Request, res: Response) => {
25+
// check if order already exists
26+
const { buyerId } = req.body;
27+
const exsitingOrder = await Order.findOne({ buyerId });
28+
if (!exsitingOrder) {
29+
throw new BadRequestError('Order with that id does not exists');
30+
}
31+
//check inventory itemId, amount
32+
res.status(200).send(exsitingOrder);
33+
};
34+
35+
export const getSale = async (req: Request, res: Response) => {
36+
const { sellerId } = req.body;
37+
const sales = await Order.find({ sellerId });
38+
if (!sales) {
39+
throw new BadRequestError('Sales with that sellerId does not exist');
40+
}
41+
res.status(200).send(sales);
42+
};
43+
44+
export const deleteOrder = async (req: Request, res: Response) => {
45+
const { id } = req.body;
46+
const deletedOrder = await Order.findOneAndDelete({ id });
47+
if (!deletedOrder) {
48+
throw new BadRequestError(`Could not find that order by id to delete`);
49+
}
50+
res.status(200).send(deletedOrder);
51+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { DbConnectionError } from '@chronosrx/common';
2+
import { app } from './app';
3+
import mongoose from 'mongoose';
4+
5+
const PORT = process.env.PORT || 3000;
6+
7+
const start = async () => {
8+
if (!process.env.MONGO_URI) throw new Error('MONGO_URI must be defined');
9+
if (!process.env.JWT_KEY) throw new Error('JWT_KEY must be defined');
10+
// if (!process.env.JWT_LIFETIME) throw new Error('JWT_LIFETIME must be defined');
11+
12+
try {
13+
await mongoose.connect(process.env.MONGO_URI, {});
14+
console.log('🍃 Connected to MongoDB');
15+
} catch (err) {
16+
throw new DbConnectionError();
17+
}
18+
19+
app.listen(PORT, async () => {
20+
console.log(`💥 App listening on ${PORT}`);
21+
});
22+
};
23+
24+
start();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import mongoose from 'mongoose';
2+
interface InventoryAttrs {
3+
itemName: string;
4+
sellerId: string; // some user's id)
5+
unitPrice: number;
6+
}
7+
// define item attributes
8+
interface InventoryModel extends mongoose.Model<InventoryDoc> {
9+
build(attrs: InventoryAttrs): InventoryDoc;
10+
}
11+
//create item data in the database with these types;
12+
interface InventoryDoc extends mongoose.Document {
13+
itemName: string;
14+
sellerId: string;
15+
unitPrice: number;
16+
itemId: string;
17+
units: number;
18+
}
19+
// create the Schema in mongoose with defines requirements
20+
const InventorySchema = new mongoose.Schema(
21+
{
22+
itemName: {
23+
type: String,
24+
required: true,
25+
// unique: true,
26+
},
27+
sellerId: {
28+
type: mongoose.Types.ObjectId,
29+
required: true,
30+
ref: 'User',
31+
},
32+
unitPrice: {
33+
type: Number,
34+
required: true,
35+
},
36+
itemId: {
37+
type: mongoose.Types.ObjectId,
38+
required: true,
39+
unique: true,
40+
},
41+
units: {
42+
type: Number,
43+
required: true,
44+
},
45+
},
46+
{
47+
//anytime we create JSON formatted data, transform item using following rules
48+
toJSON: {
49+
transform(doc, ret) {
50+
ret.id = ret._id;
51+
delete ret._id;
52+
delete ret.__v;
53+
},
54+
},
55+
}
56+
);
57+
InventorySchema.statics.build = (attrs: InventoryAttrs) => {
58+
//returning item document with (attrs) passed in
59+
return new Inventory(attrs);
60+
};
61+
const Inventory = mongoose.model<InventoryDoc, InventoryModel>('Inventory', InventorySchema);
62+
export { Inventory };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import mongoose from 'mongoose';
2+
//define type of objects that is being passed into build method
3+
interface OrderAttrs {
4+
itemId: string;
5+
amount: number;
6+
totalPrice: number;
7+
sellerId: string;
8+
}
9+
10+
interface OrderModel extends mongoose.Model<OrderDoc> {
11+
build(attrs: OrderAttrs): OrderDoc;
12+
}
13+
//create inventory data in the database in this shape
14+
interface OrderDoc extends mongoose.Document {
15+
itemId: string;
16+
amount: number;
17+
totalPrice: number;
18+
sellerId: string;
19+
}
20+
21+
//create the Schema in mongoose with defined requirements
22+
const OrderSchema = new mongoose.Schema(
23+
{
24+
itemId: {
25+
type: String,
26+
required: true,
27+
unique: true,
28+
},
29+
amount: {
30+
type: Number,
31+
required: true,
32+
},
33+
totalPrice: {
34+
type: Number,
35+
required: true,
36+
},
37+
sellerId: {
38+
type: String,
39+
require: true,
40+
},
41+
},
42+
{
43+
//anytime we create Json formatted data, transform the user document as following
44+
toJSON: {
45+
transform(doc, ret) {
46+
ret.id = ret._id;
47+
delete ret._id;
48+
delete ret.__v;
49+
},
50+
},
51+
}
52+
);
53+
54+
OrderSchema.statics.build = (attrs: OrderAttrs) => {
55+
return new Order({
56+
itemId: attrs.itemId,
57+
amount: attrs.amount,
58+
totalPrice: attrs.totalPrice,
59+
sellerId: attrs.sellerId,
60+
});
61+
};
62+
63+
const Order = mongoose.model<OrderDoc, OrderModel>('Order', OrderSchema);
64+
65+
export { Order };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import express from 'express';
2+
import { Events } from '@chronosrx/common';
3+
import { Order } from '../models/Order';
4+
import { Inventory } from '../models/Inventory';
5+
6+
const router = express.Router();
7+
8+
router.post('/', async (req, res) => {
9+
const { event } = req.body;
10+
console.log(event);
11+
switch (event.type) {
12+
case Events.ITEM_CREATED:
13+
const newOrder = Inventory.build(event.payload);
14+
await newOrder.save();
15+
break;
16+
default:
17+
res.send({});
18+
}
19+
20+
res.send({ message: '🎃 Event received' });
21+
});
22+
23+
export default router;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import express from 'express';
2+
import { getOrder, getSale, createOrder, deleteOrder } from '../controllers/order-controller';
3+
import { currentUser, requireAuth } from '@chronosrx/common';
4+
5+
const router = express.Router();
6+
router.use(currentUser);
7+
router.use(requireAuth);
8+
router.get('/getMyOrders', getOrder);
9+
router.get('/getMySales', getSale);
10+
router.post('/createOrder', createOrder);
11+
router.delete('/deleteOrder', deleteOrder);
12+
13+
export default router;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { MongoMemoryServer } from 'mongodb-memory-server';
2+
import mongoose from 'mongoose';
3+
import { app } from '../app';
4+
import request from 'supertest';
5+
import { Order } from '../models/Order';
6+
7+
declare global {
8+
function createOrder(itemId: string, sellerId: string): void;
9+
}
10+
11+
let mongo: any;
12+
13+
beforeAll(async () => {
14+
process.env.JWT_KEY = 'erreoivcxspasfgj';
15+
16+
mongo = await MongoMemoryServer.create();
17+
const mongoUri = mongo.getUri();
18+
19+
await mongoose.connect(mongoUri, {});
20+
});
21+
22+
beforeEach(async () => {
23+
const collections = await mongoose.connection.db.collections();
24+
25+
for (let collection of collections) {
26+
await collection.deleteMany({});
27+
}
28+
});
29+
30+
afterAll(async () => {
31+
if (mongo) {
32+
await mongo.stop();
33+
}
34+
35+
await mongoose.connection.close();
36+
});
37+
38+
global.createOrder = async (itemId, sellerId) => {
39+
const data = Order.build({
40+
itemId: itemId,
41+
amount: 50,
42+
totalPrice: 5000,
43+
sellerId: sellerId,
44+
});
45+
await data.save();
46+
};

0 commit comments

Comments
 (0)