Skip to content

Instantly share code, notes, and snippets.

@joshbedo
Created June 1, 2017 21:59
Show Gist options
  • Save joshbedo/b61e228a2ec36a47c5b6591126d64d73 to your computer and use it in GitHub Desktop.
Save joshbedo/b61e228a2ec36a47c5b6591126d64d73 to your computer and use it in GitHub Desktop.
Checkout Model
import {Decorators as DBDecorators} from '../../core/db';
import {PermissionDenied} from '../../core/errors';
import {Cart} from '../carts/models';
import {CartSerializer} from '../carts/serializers';
import {User} from '../users/models';
import log from './logging';
const tables = {
Checkout: 'Checkouts'
};
/**
* Checkout model
*/
class Checkout {
constructor(checkoutObj) {
this.model = checkoutObj;
}
/**
* Create a new checkout
*/
@DBDecorators.table(tables.Checkout)
static async create({cartId, billingAddress=null}) {
let obj = {
currency: 'USD',
billingAddress: billingAddress || {},
createdAt: new Date()
};
// Fetch cart and its state
// Add respective ownership of order (registered user OR anonymous via token)
let cart = await Cart.get(cartId);
obj.cart = await new CartSerializer(cart).serialize();
if (cart.userId) {
obj.userId = cart.userId;
} else {
obj.accessToken = cart.accessToken;
}
// Insert checkout into database
let insert = await this.table.insert(obj).run();
// Get checkout object and return it
return await this.table.get(insert.generated_keys[0]).run();
}
/**
* Return checkout with given ID
*/
@DBDecorators.table(tables.Checkout)
static async get(id) {
return await this.table.get(id).run();
}
/**
* Return checkout with given ID if it exists and belongs to whoever requested it
* (authenticated user or anonymous user with respective token)
*/
@DBDecorators.table(tables.Checkout)
static async getIfAllowed(checkoutId, user, cartAccessToken) {
let checkout = await Checkout.get(checkoutId);
// Checkout with ID doesn't exist
if (!checkout) return null;
// Checkout belongs to another user
if (checkout.userId && (!user || user.id !== checkout.userId)) {
throw new PermissionDenied();
}
// Anonymous Checkout but invalid access token
else if (!checkout.userId && (!cartAccessToken || cartAccessToken !== checkout.cartAccessToken)) {
throw new PermissionDenied();
}
// All good, return
else {
return checkout;
}
}
/**
* Update anonymous cart's customer details
*/
@DBDecorators.table(tables.Checkout)
static async updateCustomerDetails(checkoutId, {customer}) {
// Update checkout
await this.table.get(checkoutId).update({
customer: customer,
updatedAt: new Date()
}).run();
// Fetch checkout's latest state and return.
return await Checkout.get(checkoutId);
}
/**
* Update checkouts billing address
*/
@DBDecorators.table(tables.Checkout)
static async updateAddress(checkoutId, {billingAddress}) {
// Update checkout
await this.table.get(checkoutId).update({
billingAddress: billingAddress,
updatedAt: new Date()
}).run();
// Fetch checkout's latest state and return.
return await Checkout.get(checkoutId);
}
/**
* Update checkout's payment method
*/
@DBDecorators.table(tables.Checkout)
static async updatePaymentMethod(checkoutId, {paymentMethod}) {
// Update checkout
await this.table.get(checkoutId).update({
paymentMethod: paymentMethod,
updatedAt: new Date()
}).run();
// Fetch checkout's latest state and return.
return await Checkout.get(checkoutId);
}
/**
* Archive checkout
*/
@DBDecorators.table(tables.Checkout)
static async archive(checkoutId) {
// Update checkout
await this.table.get(checkoutId).update({
archived: true,
updatedAt: new Date()
}).run();
// Fetch checkout's latest state and return.
return await Checkout.get(checkoutId);
}
/**
* Returns the customer details (name, email)
*/
async getCustomerDetails() {
if (this.model.userId) {
let user = await User.get(this.model.userId);
return {
userId: user.id,
name: user.name,
email: user.email
};
} else {
return this.model.customer;
}
}
/**
* Returns the checkout's subTotal
*/
getSubTotal() {
let amount = 0;
this.model.cart.products.forEach(function (product) {
amount += product.quantity * product.details.pricing.retail;
});
return amount;
}
/**
* Returns the total amount for given checkout (products + discounts etc)
*/
getTotal() {
// Need to factor in discounts later. Right now no point
return this.getSubTotal();
}
}
export {tables, Checkout};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment