Created
June 1, 2017 21:59
-
-
Save joshbedo/b61e228a2ec36a47c5b6591126d64d73 to your computer and use it in GitHub Desktop.
Checkout Model
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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