|
@@ -117,6 +117,7 @@ import { RefundState } from '../helpers/refund-state-machine/refund-state';
|
|
|
import { RefundStateMachine } from '../helpers/refund-state-machine/refund-state-machine';
|
|
import { RefundStateMachine } from '../helpers/refund-state-machine/refund-state-machine';
|
|
|
import { ShippingCalculator } from '../helpers/shipping-calculator/shipping-calculator';
|
|
import { ShippingCalculator } from '../helpers/shipping-calculator/shipping-calculator';
|
|
|
import { TranslatorService } from '../helpers/translator/translator.service';
|
|
import { TranslatorService } from '../helpers/translator/translator.service';
|
|
|
|
|
+import { isForeignKeyViolationError } from '../helpers/utils/db-errors';
|
|
|
import { getOrdersFromLines, totalCoveredByPayments } from '../helpers/utils/order-utils';
|
|
import { getOrdersFromLines, totalCoveredByPayments } from '../helpers/utils/order-utils';
|
|
|
import { patchEntity } from '../helpers/utils/patch-entity';
|
|
import { patchEntity } from '../helpers/utils/patch-entity';
|
|
|
|
|
|
|
@@ -1889,7 +1890,38 @@ export class OrderService {
|
|
|
const { orderToDelete, linesToInsert, linesToDelete, linesToModify } = mergeResult;
|
|
const { orderToDelete, linesToInsert, linesToDelete, linesToModify } = mergeResult;
|
|
|
let { order } = mergeResult;
|
|
let { order } = mergeResult;
|
|
|
if (orderToDelete) {
|
|
if (orderToDelete) {
|
|
|
- await this.deleteOrder(ctx, orderToDelete);
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ // Separate transaction to isolate foreign key failure, so it doesn't roll back the entire outer transaction
|
|
|
|
|
+ await this.connection.withTransaction(ctx, async innerCtx => {
|
|
|
|
|
+ await this.deleteOrder(innerCtx, orderToDelete);
|
|
|
|
|
+ });
|
|
|
|
|
+ } catch (e: any) {
|
|
|
|
|
+ if (!isForeignKeyViolationError(e)) throw e;
|
|
|
|
|
+ if (!order)
|
|
|
|
|
+ throw new Error(
|
|
|
|
|
+ `Cannot complete order merge: active order not found, while cancelling order ${orderToDelete.id}`,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // If the order has a foreign key violation (e.g. with cancelled payments),
|
|
|
|
|
+ // instead of deleting it we cancel the order and leave a note with an explanation.
|
|
|
|
|
+ // This way the previous order and all its information are preserved.
|
|
|
|
|
+ await this.cancelOrder(ctx, { orderId: orderToDelete.id });
|
|
|
|
|
+
|
|
|
|
|
+ const note = [
|
|
|
|
|
+ 'This order was cancelled during user sign-in because merging with the active order was not possible.',
|
|
|
|
|
+ `The active order is ${order.code}. This order has been preserved for reference.`,
|
|
|
|
|
+ ].join(' ');
|
|
|
|
|
+
|
|
|
|
|
+ await this.historyService.createHistoryEntryForOrder(
|
|
|
|
|
+ {
|
|
|
|
|
+ ctx,
|
|
|
|
|
+ orderId: orderToDelete.id,
|
|
|
|
|
+ type: HistoryEntryType.ORDER_NOTE,
|
|
|
|
|
+ data: { note },
|
|
|
|
|
+ },
|
|
|
|
|
+ false,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
if (order && linesToDelete) {
|
|
if (order && linesToDelete) {
|
|
|
const orderId = order.id;
|
|
const orderId = order.id;
|