Commit 75c1e913 authored by alish's avatar alish
Browse files

feat: complete addMore function for WarehousesOrdersService

parent 1522f24a
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ import Order from '@modules/server.common/entities/Order';
import IWarehouseOrdersRouter, {
	IWarehouseOrdersRouterGetOptions,
	IOrderCreateInput,
	IOrderCreateInputProduct,
} from '@modules/server.common/routers/IWarehouseOrdersRouter';
import DeliveryType from '@modules/server.common/enums/DeliveryType';

@@ -42,6 +43,22 @@ export class WarehouseOrdersRouter implements IWarehouseOrdersRouter {
		return this._orderFactory(order);
	}

	async addMore(
		warehouseId: string,
		userId: string,
		orderId: string,
		products: IOrderCreateInputProduct[]
	): Promise<Order> {
		const order = await this.router.run<IOrder>(
			'addMore',
			userId,
			warehouseId,
			orderId,
			products
		);
		return this._orderFactory(order);
	}

	async createByProductType(
		userId: string,
		warehouseId: string,
+7 −0
Original line number Diff line number Diff line
@@ -37,6 +37,13 @@ interface IWarehouseOrdersRouter {

	cancel(orderId: string): Promise<Order>;

	addMore(
		warehouseId: string,
		userId: string,
		orderId: string,
		products: IOrderCreateInputProduct[]
	): Promise<Order>;

	createByProductType(
		userId: string,
		warehouseId: string,
+130 −113
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import IPagingOptions from '@modules/server.common/interfaces/IPagingOptions';
import OrderWarehouseStatus from '@modules/server.common/enums/OrderWarehouseStatus';
import OrderCarrierStatus from '@modules/server.common/enums/OrderCarrierStatus';
import DeliveryType from '@modules/server.common/enums/DeliveryType';
import User from '@ever-platform/common/src/entities/User';

/**
 * Warehouses Orders Service
@@ -206,22 +207,11 @@ export class WarehousesOrdersService
			autoConfirm: !!options.autoConfirm,
		};

		const user = await this.usersService
			.get(userId)
			.pipe(first())
			.toPromise();

		const warehouse = (await this.warehousesService
			.get(warehouseId, true)
			.pipe(first())
			.toPromise()) as WithFullProducts;
		const user = await this._getUser(userId);
		const warehouse = await this._getWarehouse(warehouseId);

		const warehouseProducts = _.keyBy(warehouse.products, 'productId');

		if (user == null) {
			throw new Error(`There is no user with the id ${userId}`);
		}

		this.log.info(
			{
				user,
@@ -233,30 +223,9 @@ export class WarehousesOrdersService

		// If no image was given from client side for an order product,
		// we should copy it from product in DB
		const orderProducts = await _.map(
		const orderProducts = await this._getOrderProducts(
			products,
			(args): IOrderProductCreateObject => {
				const wProduct = warehouseProducts[args.productId];

				if (!wProduct) {
					throw new Error(
						`WarehouseOrdersService got call to create(userId, orderProducts) - But there is no product with the id ${args.productId}!`
					);
				}

				return {
					count: args.count,
					price: wProduct.price,
					initialPrice: wProduct.initialPrice,
					deliveryTimeMin: wProduct.deliveryTimeMin,
					deliveryTimeMax: wProduct.deliveryTimeMax,
					product: wProduct.product as Product,
					isManufacturing: wProduct.isManufacturing,
					isCarrierRequired: wProduct.isCarrierRequired,
					isDeliveryRequired: wProduct.isDeliveryRequired,
					isTakeaway: wProduct.isTakeaway,
				};
			}
			warehouseProducts
		);

		// TODO next should be in the single transaction!
@@ -273,47 +242,11 @@ export class WarehousesOrdersService
		});

		// we do all remove operations and notify about warehouse orders change after we remove products from warehouse
		await (<any>Bluebird).map(
			order.products,
			async (orderProduct: OrderProduct) => {
				const productId = orderProduct.product.id;

				this.log.info(
					{
						warehouseId,
						productId,
						count: orderProduct.count,
					},
					'Order create remove products call'
				);

				await this.warehousesProductsService.decreaseCount(
					warehouseId,
					productId, // what product availability should be decreased
					orderProduct.count // how many to remove
				);

				await this.warehousesProductsService.increaseSoldCount(
					warehouseId,
					productId,
					orderProduct.count
				);

				this.log.info(
					{
						warehouseId,
						productId,
						count: orderProduct.count,
					},
					'Order create remove products call succeed'
				);
			}
		);
		await this._updateProductCount(order, warehouseId);

		return order;
	}

	// TODO test and fix if needed
	/**
	 * Add product to existed order
	 *
@@ -325,56 +258,44 @@ export class WarehousesOrdersService
	 * @memberof WarehousesOrdersService
	 */
	@asyncListener()
	async addMore(warehouseId, userId, orderId, product): Promise<Order> {
		// TODO check is existed order has same warehouseId and userId

		let existedOrder = await this.ordersService
	async addMore(warehouseId, userId, orderId, products): Promise<Order> {
		const existedOrder = await this.ordersService
			.get(orderId)
			.pipe(first())
			.toPromise();

		const newProducts = [...existedOrder.products, product];
		const order = await this.ordersService.update(orderId, {
			products: newProducts,
		});
		if (existedOrder.warehouseId !== warehouseId) {
			throw new Error(
				`The order is not used by warehouse with Id ${warehouseId}`
			);
		}

		// TODO export  duplicate code
		await (<any>Bluebird).map(
			order.products,
			async (orderProduct: OrderProduct) => {
				const productId = orderProduct.product.id;
		if (existedOrder.user.id !== userId) {
			throw new Error(`The order is not used by user with Id ${userId}`);
		}

		const user = await this._getUser(userId);
		const warehouse = await this._getWarehouse(warehouseId);

		const warehouseProducts = _.keyBy(warehouse.products, 'productId');

		this.log.info(
					{
						warehouseId,
						productId,
						count: orderProduct.count,
					},
					'Order create remove products call'
			{ user, warehouseId, orderId, products },
			'Add more products call'
		);

				await this.warehousesProductsService.decreaseCount(
					warehouseId,
					productId, // what product availability should be decreased
					orderProduct.count // how many to remove
		const orderProducts = await this._getOrderProducts(
			products,
			warehouseProducts
		);

				await this.warehousesProductsService.increaseSoldCount(
					warehouseId,
					productId,
					orderProduct.count
				);
		const newProducts = [...existedOrder.products, ...orderProducts];

				this.log.info(
					{
						warehouseId,
						productId,
						count: orderProduct.count,
					},
					'Order create remove products call succeed'
				);
			}
		);
		const order = await this.ordersService.update(orderId, {
			products: newProducts,
		});

		await this._updateProductCount(order, warehouseId);

		return order;
	}
@@ -591,6 +512,102 @@ export class WarehousesOrdersService

		return orders;
	}

	private async _getUser(userId: string): Promise<User> {
		const user = await this.usersService
			.get(userId)
			.pipe(first())
			.toPromise();

		if (user == null) {
			throw new Error(`There is no user with the id ${userId}`);
		}

		return user;
	}

	private async _getWarehouse(
		warehouseId: string
	): Promise<WithFullProducts> {
		const warehouse = (await this.warehousesService
			.get(warehouseId, true)
			.pipe(first())
			.toPromise()) as WithFullProducts;

		if (warehouse == null) {
			throw new Error(`There is no warehouse with the id ${warehouseId}`);
		}

		return warehouse;
	}

	private async _getOrderProducts(
		products,
		warehouseProducts
	): Promise<IOrderProductCreateObject[]> {
		return _.map(
			products,
			(args): IOrderProductCreateObject => {
				const wProduct = warehouseProducts[args.productId];
				if (!wProduct) {
					throw new Error(
						`WarehouseOrdersService got call to create(userId, orderProducts) - But there is no product with the id ${args.productId}!`
					);
				}
				return {
					count: args.count,
					price: wProduct.price,
					initialPrice: wProduct.initialPrice,
					deliveryTimeMin: wProduct.deliveryTimeMin,
					deliveryTimeMax: wProduct.deliveryTimeMax,
					product: wProduct.product as Product,
					isManufacturing: wProduct.isManufacturing,
					isCarrierRequired: wProduct.isCarrierRequired,
					isDeliveryRequired: wProduct.isDeliveryRequired,
					isTakeaway: wProduct.isTakeaway,
				};
			}
		);
	}

	private async _updateProductCount(order, warehouseId) {
		await (<any>Bluebird).map(
			order.products,
			async (orderProduct: OrderProduct) => {
				const productId = orderProduct.product.id;

				this.log.info(
					{
						warehouseId,
						productId,
						count: orderProduct.count,
					},
					'Order create remove products call'
				);

				await this.warehousesProductsService.decreaseCount(
					warehouseId,
					productId, // what product availability should be decreased
					orderProduct.count // how many to remove
				);

				await this.warehousesProductsService.increaseSoldCount(
					warehouseId,
					productId,
					orderProduct.count
				);

				this.log.info(
					{
						warehouseId,
						productId,
						count: orderProduct.count,
					},
					'Order create remove products call succeed'
				);
			}
		);
	}
}

export function getStoreOrdersFingObj(storeId: string, status: string) {