|
|
@@ -54,6 +54,7 @@ import { OrderStateMachine } from '../helpers/order-state-machine/order-state-ma
|
|
|
import { PaymentStateMachine } from '../helpers/payment-state-machine/payment-state-machine';
|
|
|
import { RefundStateMachine } from '../helpers/refund-state-machine/refund-state-machine';
|
|
|
import { ShippingCalculator } from '../helpers/shipping-calculator/shipping-calculator';
|
|
|
+import { findOneInChannel } from '../helpers/utils/channel-aware-orm-utils';
|
|
|
import { getEntityOrThrow } from '../helpers/utils/get-entity-or-throw';
|
|
|
import {
|
|
|
orderItemsAreAllCancelled,
|
|
|
@@ -63,6 +64,7 @@ import {
|
|
|
import { patchEntity } from '../helpers/utils/patch-entity';
|
|
|
import { translateDeep } from '../helpers/utils/translate-entity';
|
|
|
|
|
|
+import { ChannelService } from './channel.service';
|
|
|
import { CountryService } from './country.service';
|
|
|
import { CustomerService } from './customer.service';
|
|
|
import { HistoryService } from './history.service';
|
|
|
@@ -90,6 +92,7 @@ export class OrderService {
|
|
|
private historyService: HistoryService,
|
|
|
private promotionService: PromotionService,
|
|
|
private eventBus: EventBus,
|
|
|
+ private channelService: ChannelService,
|
|
|
) {}
|
|
|
|
|
|
getOrderProcessStates(): OrderProcessState[] {
|
|
|
@@ -101,7 +104,10 @@ export class OrderService {
|
|
|
|
|
|
findAll(ctx: RequestContext, options?: ListQueryOptions<Order>): Promise<PaginatedList<Order>> {
|
|
|
return this.listQueryBuilder
|
|
|
- .build(Order, options, { relations: ['lines', 'customer', 'lines.productVariant'] })
|
|
|
+ .build(Order, options, {
|
|
|
+ relations: ['lines', 'customer', 'lines.productVariant', 'channels'],
|
|
|
+ channelId: ctx.channelId,
|
|
|
+ })
|
|
|
.getManyAndCount()
|
|
|
.then(([items, totalItems]) => {
|
|
|
return {
|
|
|
@@ -115,7 +121,9 @@ export class OrderService {
|
|
|
const order = await this.connection
|
|
|
.getRepository(Order)
|
|
|
.createQueryBuilder('order')
|
|
|
+ .leftJoin('order.channels', 'channel')
|
|
|
.leftJoinAndSelect('order.customer', 'customer')
|
|
|
+ .leftJoinAndSelect('customer.user', 'user') // Used in de 'Order' query, guess this didn't work before?
|
|
|
.leftJoinAndSelect('order.lines', 'lines')
|
|
|
.leftJoinAndSelect('lines.productVariant', 'productVariant')
|
|
|
.leftJoinAndSelect('productVariant.taxCategory', 'prodVariantTaxCategory')
|
|
|
@@ -126,6 +134,7 @@ export class OrderService {
|
|
|
.leftJoinAndSelect('items.fulfillment', 'fulfillment')
|
|
|
.leftJoinAndSelect('lines.taxCategory', 'lineTaxCategory')
|
|
|
.where('order.id = :orderId', { orderId })
|
|
|
+ .andWhere('channel.id = :channelId', { channelId: ctx.channelId })
|
|
|
.addOrderBy('lines.createdAt', 'ASC')
|
|
|
.addOrderBy('items.createdAt', 'ASC')
|
|
|
.getOne();
|
|
|
@@ -147,7 +156,7 @@ export class OrderService {
|
|
|
code: orderCode,
|
|
|
},
|
|
|
});
|
|
|
- return order;
|
|
|
+ return order ? this.findOne(ctx, order.id) : undefined;
|
|
|
}
|
|
|
|
|
|
async findByCustomerId(
|
|
|
@@ -163,7 +172,9 @@ export class OrderService {
|
|
|
'lines.productVariant',
|
|
|
'lines.productVariant.options',
|
|
|
'customer',
|
|
|
+ 'channels',
|
|
|
],
|
|
|
+ channelId: ctx.channelId,
|
|
|
})
|
|
|
.andWhere('order.customer.id = :customerId', { customerId })
|
|
|
.getManyAndCount()
|
|
|
@@ -208,12 +219,16 @@ export class OrderService {
|
|
|
async getActiveOrderForUser(ctx: RequestContext, userId: ID): Promise<Order | undefined> {
|
|
|
const customer = await this.customerService.findOneByUserId(userId);
|
|
|
if (customer) {
|
|
|
- const activeOrder = await this.connection.getRepository(Order).findOne({
|
|
|
- where: {
|
|
|
- customer,
|
|
|
- active: true,
|
|
|
- },
|
|
|
- });
|
|
|
+ const activeOrder = await this.connection
|
|
|
+ .createQueryBuilder(Order, 'order')
|
|
|
+ .innerJoinAndSelect('order.channels', 'channel', 'channel.id = :channelId', {
|
|
|
+ channelId: ctx.channelId,
|
|
|
+ })
|
|
|
+ .leftJoinAndSelect('order.customer', 'customer')
|
|
|
+ .where('active = :active', { active: true })
|
|
|
+ .andWhere('order.customer.id = :customerId', { customerId: customer.id })
|
|
|
+ .orderBy('order.createdAt', 'DESC')
|
|
|
+ .getOne();
|
|
|
if (activeOrder) {
|
|
|
return this.findOne(ctx, activeOrder.id);
|
|
|
}
|
|
|
@@ -239,6 +254,7 @@ export class OrderService {
|
|
|
newOrder.customer = customer;
|
|
|
}
|
|
|
}
|
|
|
+ this.channelService.assignToCurrentChannel(newOrder, ctx);
|
|
|
return this.connection.getRepository(Order).save(newOrder);
|
|
|
}
|
|
|
|
|
|
@@ -381,8 +397,8 @@ export class OrderService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- async getOrderPromotions(orderId: ID): Promise<Promotion[]> {
|
|
|
- const order = await getEntityOrThrow(this.connection, Order, orderId, {
|
|
|
+ async getOrderPromotions(ctx: RequestContext, orderId: ID): Promise<Promotion[]> {
|
|
|
+ const order = await getEntityOrThrow(this.connection, Order, orderId, ctx.channelId, {
|
|
|
relations: ['promotions'],
|
|
|
});
|
|
|
return order.promotions || [];
|
|
|
@@ -499,6 +515,7 @@ export class OrderService {
|
|
|
throw new UserInputError('error.create-fulfillment-nothing-to-fulfill');
|
|
|
}
|
|
|
const { items, orders } = await this.getOrdersAndItemsFromLines(
|
|
|
+ ctx,
|
|
|
input.lines,
|
|
|
(i) => !i.fulfillment,
|
|
|
'error.create-fulfillment-items-already-fulfilled',
|
|
|
@@ -527,9 +544,15 @@ export class OrderService {
|
|
|
fulfillmentId: fulfillment.id,
|
|
|
},
|
|
|
});
|
|
|
- const orderWithFulfillments = await this.connection.getRepository(Order).findOne(order.id, {
|
|
|
- relations: ['lines', 'lines.items', 'lines.items.fulfillment'],
|
|
|
- });
|
|
|
+ const orderWithFulfillments = await findOneInChannel(
|
|
|
+ this.connection,
|
|
|
+ Order,
|
|
|
+ order.id,
|
|
|
+ ctx.channelId,
|
|
|
+ {
|
|
|
+ relations: ['lines', 'lines.items', 'lines.items.fulfillment'],
|
|
|
+ },
|
|
|
+ );
|
|
|
if (!orderWithFulfillments) {
|
|
|
throw new InternalServerError('error.could-not-find-order');
|
|
|
}
|
|
|
@@ -605,6 +628,7 @@ export class OrderService {
|
|
|
throw new UserInputError('error.cancel-order-lines-nothing-to-cancel');
|
|
|
}
|
|
|
const { items, orders } = await this.getOrdersAndItemsFromLines(
|
|
|
+ ctx,
|
|
|
lines,
|
|
|
(i) => !i.cancelled,
|
|
|
'error.cancel-order-lines-quantity-too-high',
|
|
|
@@ -655,6 +679,7 @@ export class OrderService {
|
|
|
throw new UserInputError('error.refund-order-lines-nothing-to-refund');
|
|
|
}
|
|
|
const { items, orders } = await this.getOrdersAndItemsFromLines(
|
|
|
+ ctx,
|
|
|
input.lines,
|
|
|
(i) => !i.cancelled,
|
|
|
'error.refund-order-lines-quantity-too-high',
|
|
|
@@ -890,6 +915,7 @@ export class OrderService {
|
|
|
}
|
|
|
|
|
|
private async getOrdersAndItemsFromLines(
|
|
|
+ ctx: RequestContext,
|
|
|
orderLinesInput: OrderLineInput[],
|
|
|
itemMatcher: (i: OrderItem) => boolean,
|
|
|
noMatchesError: string,
|
|
|
@@ -900,7 +926,7 @@ export class OrderService {
|
|
|
const lines = await this.connection.getRepository(OrderLine).findByIds(
|
|
|
orderLinesInput.map((l) => l.orderLineId),
|
|
|
{
|
|
|
- relations: ['order', 'items', 'items.fulfillment'],
|
|
|
+ relations: ['order', 'items', 'items.fulfillment', 'order.channels'],
|
|
|
order: { id: 'ASC' },
|
|
|
},
|
|
|
);
|
|
|
@@ -910,6 +936,9 @@ export class OrderService {
|
|
|
continue;
|
|
|
}
|
|
|
const order = line.order;
|
|
|
+ if (!order.channels.some((channel) => channel.id === ctx.channelId)) {
|
|
|
+ throw new EntityNotFoundError('Order', order.id);
|
|
|
+ }
|
|
|
if (!orders.has(order.id)) {
|
|
|
orders.set(order.id, order);
|
|
|
}
|