mirror of
https://github.com/KevinMidboe/planetposen-backend.git
synced 2025-10-29 00:10:12 +00:00
* planet_id variable casing consistent with database field Renames all clientId variables to planet_id * Store stripe json response from latest payment & charge webhook Also added db seed file for stripe payments * Image support! Can now add, update & delete images from products Images moved away from product schema to it's own table. Accepts a images string and relates it to a product. Does not store the images or verify the existance. * Instead of deleting a product set field unlisted to true Endpoints with current inventory checks for unlisted = false * order_id & customer_no gets enhanced base64 function for generating id * Implemented shipping for orders using Post tracking api Added CRUD for making changes to a order's shippment. Split shipping table into shipment_courier, shipment & shipment_event. * Updated and add product & product_sku functions updated * Cart increment funciton checks stock before updating * Endpoint for getting product audit log using 91pluss trigger Read more about usage here: https://wiki.postgresql.org/wiki/Audit_trigger_91plus * On stripe charge successfull send email to user with planetposen-mail * More product seed data, linting & formatting * Log file at /var/log/planetposen_logs & rotate max 3 files 100MB each This will prob throw a error if folder does not exist, run: `(sudo) mkdir -p /var/log/planetposen_logs`. * All endpoints now prefixed with /api/v1 * Linting
140 lines
3.5 KiB
TypeScript
140 lines
3.5 KiB
TypeScript
import Cart from "./Cart";
|
|
import CartSession from "./CartSession";
|
|
import type ICart from "../interfaces/ICart";
|
|
import { IProduct } from "../interfaces/IProduct";
|
|
|
|
const cartSession = new CartSession();
|
|
|
|
class InvalidLineItemIdError extends Error {
|
|
statusCode: number;
|
|
|
|
constructor() {
|
|
const message = "Fant ikke produktet som ble lagt til";
|
|
super(message);
|
|
|
|
this.statusCode = 400;
|
|
}
|
|
}
|
|
|
|
function parseDataAsCartPayload(message: string): ICartPayload {
|
|
let json: ICartPayload = null;
|
|
|
|
try {
|
|
json = JSON.parse(message);
|
|
} catch {}
|
|
|
|
return json;
|
|
}
|
|
|
|
interface ICartPayload {
|
|
command: string;
|
|
message: string;
|
|
product_no?: number;
|
|
product_sku_no?: number;
|
|
quantity?: number;
|
|
lineitem_id?: number;
|
|
}
|
|
|
|
class WSCart {
|
|
ws: WebSocket;
|
|
planet_id: string | null;
|
|
cart: Cart;
|
|
cartSession: CartSession;
|
|
|
|
constructor(ws, planet_id) {
|
|
this.ws = ws;
|
|
this.planet_id = planet_id;
|
|
this.cart = new Cart(planet_id);
|
|
this.cartSession;
|
|
}
|
|
|
|
get isAlive() {
|
|
return this.ws.readyState === 1;
|
|
}
|
|
|
|
/* emitters */
|
|
message(message: string, success = true) {
|
|
this.ws.send(JSON.stringify({ message, success }));
|
|
}
|
|
|
|
async emitCart(cart: any[] | null = null) {
|
|
if (cart === null || cart?.length === 0) {
|
|
cart = await this.cart.get();
|
|
}
|
|
|
|
this.ws.send(JSON.stringify({ cart, success: true }));
|
|
}
|
|
|
|
/* handle known commands */
|
|
async addCartProduct(payload): Promise<boolean> {
|
|
const { product_no, product_sku_no, quantity } = payload;
|
|
if (!product_no || !quantity) {
|
|
// throw here?
|
|
this.message("Missing product_no or quantity", false);
|
|
}
|
|
|
|
await this.cart.add(product_no, product_sku_no, quantity);
|
|
return true;
|
|
}
|
|
|
|
async removeCartProduct(lineitem_id: number): Promise<boolean> {
|
|
if (isNaN(lineitem_id)) throw new InvalidLineItemIdError();
|
|
await this.cart.remove(lineitem_id);
|
|
return true;
|
|
}
|
|
|
|
async decrementProductInCart(lineitem_id: number): Promise<boolean> {
|
|
if (isNaN(lineitem_id)) throw new InvalidLineItemIdError();
|
|
await this.cart.decrement(lineitem_id);
|
|
return true;
|
|
}
|
|
|
|
async incrementProductInCart(lineitem_id: number): Promise<boolean> {
|
|
// TODO validate the quantity trying to be added here ??
|
|
|
|
if (isNaN(lineitem_id)) throw new InvalidLineItemIdError();
|
|
await this.cart.increment(lineitem_id);
|
|
return true;
|
|
}
|
|
|
|
/* main ws data/message handler */
|
|
async handleMessage(data: Buffer | string, isBinary: boolean) {
|
|
const dataMessage = isBinary ? String(data) : data.toString();
|
|
if (dataMessage === "heartbeat") return;
|
|
|
|
const payload = parseDataAsCartPayload(dataMessage);
|
|
const { command } = payload;
|
|
|
|
try {
|
|
let emitCart = false;
|
|
|
|
if (command === "cart") this.emitCart();
|
|
else if (command === "add") {
|
|
emitCart = await this.addCartProduct(payload);
|
|
} else if (command === "rm") {
|
|
emitCart = await this.removeCartProduct(payload?.lineitem_id);
|
|
} else if (command === "decrement") {
|
|
emitCart = await this.decrementProductInCart(payload?.lineitem_id);
|
|
} else if (command === "increment") {
|
|
emitCart = await this.incrementProductInCart(payload?.lineitem_id);
|
|
} else {
|
|
console.log(`client has sent us other/without command: ${dataMessage}`);
|
|
}
|
|
|
|
if (emitCart) {
|
|
this.cartSession.emitChangeToClients(this);
|
|
}
|
|
} catch (error) {
|
|
// ????
|
|
if (error.message) this.message(error?.message, false);
|
|
this.cartSession.emitChangeToClients(this);
|
|
}
|
|
}
|
|
|
|
handleError() {}
|
|
|
|
destroy() {}
|
|
}
|
|
|
|
export default WSCart;
|