Skip to content

Commit

Permalink
Add comments
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-north committed Mar 17, 2018
1 parent 0070ead commit 97081e9
Show file tree
Hide file tree
Showing 28 changed files with 649 additions and 369 deletions.
2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
"trailingComma": "none",
"useTabs": false,
"tabWidth": 2,
"printWidth": 80,
"printWidth": 100,
"semi": true
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
"**/bower_components": true
},
"editor.formatOnSave": true,
"files.associations": {
"*.sql": "sql"
},
"[handlebars]": {
"editor.formatOnSave": false
},
Expand Down
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 4 additions & 5 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { join } from 'path';
// APPLICATION

/**
* The port the application serves HTTP responses on
*/
export const PORT = process.env.PORT || 3000;

// PATHS & FILES
export const PROJECT_ROOT = join(__dirname, '..');
export const PUBLIC_PATH = join(__dirname, 'public');

// SQLITE DATABASES
export const MASTER_DB_NAME = 'master.sqlite';
export const MASTER_DB_FILE = join(PROJECT_ROOT, MASTER_DB_NAME);
22 changes: 22 additions & 0 deletions src/data/customers.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
import { getDb } from '../db/utils';
import { sql } from '../sql-string';

/**
* Columns to SELECT for the getAllCustomers query
*/
const ALL_CUSTOMERS_COLUMNS = ['*'];

/**
* Options that may be used to customize a query for a collection of Customers
*
* @interface CustomerCollectionOptions
*/
interface CustomerCollectionOptions {
filter?: string;
}

/**
* Retrieve an array of Customers from the database
*
* @export
* @param {CustomerCollectionOptions} [options={}] Options that influence the particulars of the "all customers" query
* @returns {Promise<Customer[]>} A collection of customers
*/
export async function getAllCustomers(
options: CustomerCollectionOptions = {}
): Promise<Customer[]> {
Expand All @@ -16,6 +31,13 @@ SELECT ${ALL_CUSTOMERS_COLUMNS.join(',')}
FROM Customer`);
}

/**
* Retrieve an individual Customer (by Id) from the database
*
* @export
* @param {(string | number)} id The id of the customer to retrieve
* @returns {Promise<Customer>} The customer
*/
export async function getCustomer(id: string | number): Promise<Customer> {
const db = await getDb();
return await db.get(
Expand Down
101 changes: 63 additions & 38 deletions src/data/dashboard.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,86 @@
import { getDb } from '../db/utils';
import { sql } from '../sql-string';

/**
* Get data for the employee sales leaderboard on the dashboard page
*/
export async function getEmployeeSalesLeaderboard() {
let db = await getDb();
return await db.all(sql`SELECT (e.firstname || ' ' || e.lastname) as name, sum((od.unitprice * od.quantity))as amount FROM
Employee as e INNER JOIN CustomerOrder as o
ON o.employeeid = e.id
INNER JOIN OrderDetail as od
ON o.id = od.orderid
GROUP BY e.id
ORDER BY amount desc
LIMIT 5
`);
return await db.all(sql`
SELECT (e.firstname || ' ' || e.lastname) AS name, sum((od.unitprice * od.quantity))as amount
FROM Employee AS e
INNER JOIN CustomerOrder AS o
ON o.employeeid = e.id
INNER JOIN OrderDetail AS od
ON o.id = od.orderid
GROUP BY e.id
ORDER BY amount DESC LIMIT 5`);
}

/**
* Get data for the customer sales leaderboard on the dashboard page
*/
export async function getCustomerSalesLeaderboard() {
let db = await getDb();
return await db.all(sql`SELECT c.companyname as name, sum((od.unitprice * od.quantity))as amount FROM
Customer as c INNER JOIN CustomerOrder as o
ON o.customerid = c.id
INNER JOIN OrderDetail as od
ON o.id = od.orderid
GROUP BY c.id
ORDER BY amount desc
LIMIT 5
`);
return await db.all(sql`
SELECT c.companyname AS name,
sum((od.unitprice * od.quantity))as amount
FROM Customer AS c
INNER JOIN CustomerOrder AS o
ON o.customerid = c.id
INNER JOIN OrderDetail AS od
ON o.id = od.orderid
GROUP BY c.id
ORDER BY amount DESC LIMIT 5`);
}

/**
* Get data for the product sales leaderboard on the dashboard page
*/
export async function getProductSalesLeaderboard() {
let db = await getDb();
return await db.all(sql`SELECT p.productname as name, sum(od.unitprice * od.quantity) as amount
FROM
OrderDetail AS od
INNER JOIN CustomerOrder AS o ON od.orderid = o.id
INNER JOIN Product AS p ON od.productid = p.id
GROUP BY p.id
ORDER BY amount DESC
LIMIT 5`);
return await db.all(sql`
SELECT p.productname AS name,
sum(od.unitprice * od.quantity) AS amount
FROM OrderDetail AS od
INNER JOIN CustomerOrder AS o
ON od.orderid = o.id
INNER JOIN Product AS p
ON od.productid = p.id
GROUP BY p.id
ORDER BY amount DESC LIMIT 5`);
}

/**
* Get data for the recent sales list the dashboard page
*/
export async function getRecentOrders() {
let db = await getDb();
return await db.all(sql`
SELECT o.id, (e.firstname || ' ' || e.lastname) as employee, c.companyname as customer, o.orderdate, sum(od.unitprice * od.quantity) as subtotal FROM
CustomerOrder as o
INNER JOIN OrderDetail AS od ON od.orderid = o.id
INNER JOIN Employee AS e on o.employeeid = e.id
INNER JOIN Customer AS c on o.customerid = c.id
WHERE o.orderdate IS NOT NULL
GROUP BY o.id, e.firstname, e.lastname, c.companyname
ORDER BY o.orderdate DESC
LIMIT 5`);
SELECT o.id,
(e.firstname || ' ' || e.lastname) AS employee, c.companyname AS customer, o.orderdate, sum(od.unitprice * od.quantity) AS subtotal
FROM CustomerOrder AS o
INNER JOIN OrderDetail AS od
ON od.orderid = o.id
INNER JOIN Employee AS e
ON o.employeeid = e.id
INNER JOIN Customer AS c
ON o.customerid = c.id
WHERE o.orderdate IS NOT NULL
GROUP BY o.id, e.firstname, e.lastname, c.companyname
ORDER BY o.orderdate DESC LIMIT 5`);
}

/**
* Get data for the reorder list on the dashboard page
*/
export async function getReorderList() {
let db = await getDb();
return await db.all(
sql`SELECT productname as name, reorderlevel, unitsinstock, unitsonorder from Product WHERE (unitsinstock + unitsonorder) < reorderlevel`
);
return await db.all(sql`
SELECT productname AS name,
reorderlevel,
unitsinstock,
unitsonorder
FROM Product
WHERE (unitsinstock + unitsonorder) < reorderlevel`);
}
10 changes: 10 additions & 0 deletions src/data/employees.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import { getDb } from '../db/utils';
import { sql } from '../sql-string';

/**
* Columns to select for the `getAllEmployees` query
*/
const ALL_EMPLOYEES_COLUMNS = ['*'];

/**
* Retrieve a collection of all Employee records in the database
*/
export async function getAllEmployees(): Promise<Employee[]> {
const db = await getDb();
return await db.all(sql`
SELECT ${ALL_EMPLOYEES_COLUMNS.join(',')}
FROM Employee`);
}

/**
* Retrieve an Employee by id from the database
* @param id Employee ID
*/
export async function getEmployee(id: string | number): Promise<Employee> {
const db = await getDb();
return await db.get(
Expand Down
79 changes: 61 additions & 18 deletions src/data/orders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,38 @@ import { sql } from '../sql-string';
export const ALL_ORDERS_COLUMNS = ['*'];
export const ORDER_COLUMNS = ['*'];

/**
* Options that may be used to customize a query for a collection of CustomerOrder records
*/
interface OrderCollectionOptions {
/** Page number (zero-indexed) */
page: number;
/** Results per page */
perPage: number;
order: 'asc' | 'desc';
/** Property to sort result set by */
sort: string;
/** Direction of sort */
order: 'asc' | 'desc';
}

const DEFAULT_ORDER_COLLECTION_OPTIONS: Readonly<
OrderCollectionOptions
> = Object.freeze({
order: 'asc',
page: 1,
perPage: 20,
sort: 'id'
} as OrderCollectionOptions);
/**
* Defaults values to use when parts of OrderCollectionOptions are not provided
*/
const DEFAULT_ORDER_COLLECTION_OPTIONS: Readonly<OrderCollectionOptions> = Object.freeze({
order: 'asc',
page: 1,
perPage: 20,
sort: 'id'
} as OrderCollectionOptions);

export async function getAllOrders(
opts: Partial<OrderCollectionOptions> = {}
): Promise<Order[]> {
/**
* Retrieve a collection of "all orders" from the database.
* NOTE: This table has tens of thousands of records, so we'll probably have to apply
* some strategy for viewing only a part of the collection at any given time
* @param opts Options for customizing the query
*/
export async function getAllOrders(opts: Partial<OrderCollectionOptions> = {}): Promise<Order[]> {
// Combine the options passed into the function with the defaults
let options: OrderCollectionOptions = {
...DEFAULT_ORDER_COLLECTION_OPTIONS,
...opts
Expand All @@ -34,13 +47,23 @@ SELECT ${ALL_ORDERS_COLUMNS.join(',')}
FROM CustomerOrder`);
}

/**
* Retrieve a list of CustomerOrder records associated with a particular Customer
* @param customerId Customer id
* @param opts Options for customizing the query
*/
export async function getCustomerOrders(
customerId: string,
opts: Partial<OrderCollectionOptions> = {}
) {
// ! This is going to retrieve ALL ORDERS, not just the ones that belong to a particular customer. We'll need to fix this
return getAllOrders(opts);
}

/**
* Retrieve an individual CustomerOrder record by id
* @param id CustomerOrder id
*/
export async function getOrder(id: string | number): Promise<Order> {
const db = await getDb();
return await db.get(
Expand All @@ -52,9 +75,11 @@ WHERE id = $1`,
);
}

export async function getOrderDetails(
id: string | number
): Promise<OrderDetail[]> {
/**
* Get the OrderDetail records associated with a particular CustomerOrder record
* @param id CustomerOrder id
*/
export async function getOrderDetails(id: string | number): Promise<OrderDetail[]> {
const db = await getDb();
return await db.all(
sql`
Expand All @@ -65,25 +90,43 @@ WHERE orderid = $1`,
);
}

export async function getOrderWithDetails(
id: string | number
): Promise<[Order, OrderDetail[]]> {
/**
* Get a CustomerOrder record, and its associated OrderDetails records
* @param id CustomerOrder id
*/
export async function getOrderWithDetails(id: string | number): Promise<[Order, OrderDetail[]]> {
let order = await getOrder(id);
let items = await getOrderDetails(id);
return [order, items];
}

/**
* Create a new CustomerOrder record
* @param order data for the new CustomerOrder
* @param details data for any OrderDetail records to associate with this new CustomerOrder
* TODO: convert Partial<Order> to Pick<Order>
*/
export async function createOrder(
order: Partial<Order>,
details: Array<Partial<OrderDetail>> = []
): Promise<Partial<Order>> {
return Promise.reject('Orders#createOrder() NOT YET IMPLEMENTED');
}

/**
* Delete a CustomerOrder from the database
* @param id CustomerOrder id
*/
export async function deleteOrder(id: string | number): Promise<void> {
return Promise.reject('Orders#deleteOrder() NOT YET IMPLEMENTED');
}

/**
* Update a CustomerOrder, and its associated OrderDetail records
* @param id CustomerOrder id
* @param data new data for the CustomerOrder
* @param details data for updating any associated OrderDetail records
*/
export async function updateOrder(
id: string | number,
data: Partial<Order>,
Expand Down
Loading

0 comments on commit 97081e9

Please sign in to comment.