Skip to content

Commit

Permalink
feat: historic order fixes and tax class error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
JannikZed committed Dec 24, 2023
1 parent d78738d commit a0a8191
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 41 deletions.
138 changes: 122 additions & 16 deletions pkg/integration-saleor-entities/src/orders/historicOrders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,26 @@ export class SaleorHistoricOrdersSync {

private readonly installedSaleorApp: InstalledSaleorApp;

private readonly tenantId: string;

constructor({
logger,
saleorClient,
db,
installedSaleorApp,
tenantId,
}: {
logger: ILogger;
saleorClient: SaleorClient;
db: PrismaClient;
installedSaleorApp: InstalledSaleorApp;
tenantId: string;
}) {
this.logger = logger;
this.saleorClient = saleorClient;
this.db = db;
this.installedSaleorApp = installedSaleorApp;
this.tenantId = tenantId;
}

/**
Expand Down Expand Up @@ -175,6 +180,7 @@ export class SaleorHistoricOrdersSync {
| null;
};
})[],
defaultSaleorTaxRateId?: string,
): OrderBulkCreateOrderLineInput[] {
return orderLineItems
.filter((o) => o.quantity > 0)
Expand All @@ -193,15 +199,19 @@ export class SaleorHistoricOrdersSync {
const saleorProductVariantId =
line?.productVariant?.saleorProductVariant?.[0]?.id;
const saleorTaxClass =
line?.productVariant?.salesTax?.saleorTaxClasses?.[0]?.id;
line?.productVariant?.salesTax?.saleorTaxClasses?.[0]?.id ||
defaultSaleorTaxRateId;
if (!saleorTaxClass)
throw new Error(
`No saleorTaxClass and no default saleor tax class given for line item with SKU ${line.productVariant.sku} `,
);
return {
createdAt: line.createdAt,
isGiftCard: false,
isShippingRequired: false,
productName: line.productVariant.product.name,
variantName: line.productVariant.variantName,
taxClassId: saleorTaxClass,
taxRate: saleorTaxClass ? undefined : 0,
variantId: saleorProductVariantId
? saleorProductVariantId
: undefined,
Expand Down Expand Up @@ -232,7 +242,10 @@ export class SaleorHistoricOrdersSync {
* @param orders
* @returns
*/
private ordersToBulkOrders(orders: any): OrderBulkCreateInput[] {
private ordersToBulkOrders(
orders: any,
defaultSaleorTaxRateId?: string,
): OrderBulkCreateInput[] {
const returningBulkOrdes: OrderBulkCreateInput[] = [];
for (const order of orders) {
try {
Expand Down Expand Up @@ -260,7 +273,10 @@ export class SaleorHistoricOrdersSync {
: undefined,
},

lines: this.orderLineItemsToLines(order.orderLineItems),
lines: this.orderLineItemsToLines(
order.orderLineItems,
defaultSaleorTaxRateId,
),
// payments: order.payments,
// packages: order.packages,
languageCode: this.schemabaseLanguageToSaleorLanguage(
Expand Down Expand Up @@ -354,6 +370,19 @@ export class SaleorHistoricOrdersSync {
},
});

/**
* When we don't have the tax class of an item, we can take this
* default saleor tax rate.
*/
const defaultSaleorTaxRateId = (
await this.db.saleorTaxClass.findFirst({
where: {
installedSaleorAppId: this.installedSaleorApp.id,
fallback: true,
},
})
)?.id;

if (orders.length === 0) {
this.logger.info("No historic orders for saleor customers found");
return;
Expand Down Expand Up @@ -390,7 +419,10 @@ export class SaleorHistoricOrdersSync {
});

try {
const orderInput = this.ordersToBulkOrders(filteredOrders);
const orderInput = this.ordersToBulkOrders(
filteredOrders,
defaultSaleorTaxRateId,
);

const chunkSize = 50;
const chunks = [];
Expand All @@ -407,26 +439,96 @@ export class SaleorHistoricOrdersSync {
orders: chunk,
errorPolicy: ErrorPolicyEnum.RejectFailedRows,
});
const bulkOrderResultErrors =
bulkOrderCreateResponse.orderBulkCreate?.results
.filter((x) => x.errors && x.errors?.length > 0)
.flatMap((x) => x.errors);
if (
bulkOrderCreateResponse.orderBulkCreate?.results.find(
(x) => x.errors && x.errors?.length > 0,
)
bulkOrderResultErrors &&
bulkOrderResultErrors?.length > 0
) {
this.logger.error(
`Error while creating historic orders in saleor: ${JSON.stringify(
bulkOrderCreateResponse.orderBulkCreate.results,
)}`,
);
for (const error of bulkOrderResultErrors) {
/**
* we already created an order with this externalReference. We store
* the corresponding Saleor Id in our DB. We need to parse the external
* reference out of the message field: "message":"Order with external_reference: 7331981 already exists."
*/
if (
error?.code === "UNIQUE" &&
error.path === "external_reference"
) {
const externalReference =
error.message?.split(" ")[3];
this.logger.info(error.message as string);
if (!externalReference) {
this.logger.error(
"Could not parse external reference from error message",
);
continue;
}
console.log("external refernce", externalReference);
const saleorOrder =
await this.saleorClient.orderByReference({
externalReference,
});
const saleorOrderId = saleorOrder.order?.id;
if (!saleorOrderId) {
this.logger.error(
`Could not find saleor order with external reference "${externalReference}"`,
);
continue;
}
await this.db.saleorOrder.upsert({
where: {
id_installedSaleorAppId: {
id: saleorOrderId,
installedSaleorAppId:
this.installedSaleorApp.id,
},
},
create: {
id: saleorOrderId,
createdAt: new Date(),
installedSaleorApp: {
connect: {
id: this.installedSaleorApp.id,
},
},
order: {
connect: {
orderNumber_tenantId: {
orderNumber: externalReference,
tenantId: this.tenantId,
},
},
},
},
update: {
order: {
connect: {
orderNumber_tenantId: {
orderNumber: externalReference,
tenantId: this.tenantId,
},
},
},
},
});
} else {
this.logger.error(JSON.stringify(error));
}
}
}
if (
bulkOrderCreateResponse.orderBulkCreate?.errors &&
bulkOrderCreateResponse.orderBulkCreate?.errors?.length > 0
) {
this.logger.error(
`Error while creating historic orders in saleor: ${JSON.stringify(
bulkOrderCreateResponse.orderBulkCreate.errors,
bulkOrderCreateResponse.orderBulkCreate?.errors,
)}`,
);
continue;
}
const results =
bulkOrderCreateResponse.orderBulkCreate?.results || [];
Expand All @@ -445,10 +547,14 @@ export class SaleorHistoricOrdersSync {
);
}
for (const result of successfulOrders) {
if (!result?.order?.id) continue;
if (!result?.order?.id || !result.order.externalReference)
continue;
await this.db.order.update({
where: {
id: result.order.id,
orderNumber_tenantId: {
orderNumber: result.order.externalReference,
tenantId: this.tenantId,
},
},
data: {
saleorOrders: {
Expand Down
1 change: 1 addition & 0 deletions pkg/integration-saleor-entities/src/orders/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ export class SaleorOrderSyncService {
logger: this.logger,
installedSaleorApp: this.installedSaleorApp,
saleorClient: this.saleorClient,
tenantId: this.tenantId,
});
await histOrders.syncHistoricOrders();
}
Expand Down
1 change: 1 addition & 0 deletions pkg/prisma/dbml/schema.dbml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Table SaleorProductType {

Table SaleorTaxClass {
id String [not null, note: 'Saleor Internal Id']
fallback Boolean [not null, default: false, note: 'When an item has no tax rate (for example for historic orders), we use this tax class']
installedSaleorApp InstalledSaleorApp [not null]
installedSaleorAppId String [not null]
tax Tax [not null]
Expand Down
3 changes: 3 additions & 0 deletions pkg/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ model SaleorTaxClass {
/// Saleor Internal Id
id String
/// When an item has no tax rate (for example for historic orders), we use this tax class
fallback Boolean @default(false)
installedSaleorApp InstalledSaleorApp @relation(fields: [installedSaleorAppId], references: [id], onDelete: Cascade)
installedSaleorAppId String
Expand Down
51 changes: 51 additions & 0 deletions pkg/saleor/src/api/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14769,6 +14769,7 @@ export type MutationTransactionInitializeArgs = {
amount?: InputMaybe<Scalars["PositiveDecimal"]>;
customerIpAddress?: InputMaybe<Scalars["String"]>;
id: Scalars["ID"];
idempotencyKey?: InputMaybe<Scalars["String"]>;
paymentGateway: PaymentGatewayToInitialize;
};

Expand Down Expand Up @@ -28101,6 +28102,12 @@ export type TransactionEvent = Node & {
externalUrl: Scalars["String"];
/** The ID of the object. */
id: Scalars["ID"];
/**
* Idempotency key assigned to the event.
*
* Added in Saleor 3.14.
*/
idempotencyKey?: Maybe<Scalars["String"]>;
/**
* Message related to the transaction's event.
*
Expand Down Expand Up @@ -28269,6 +28276,7 @@ export enum TransactionInitializeErrorCode {
GraphqlError = "GRAPHQL_ERROR",
Invalid = "INVALID",
NotFound = "NOT_FOUND",
Unique = "UNIQUE",
}

/**
Expand All @@ -28290,6 +28298,12 @@ export type TransactionInitializeSession = Event & {
customerIpAddress?: Maybe<Scalars["String"]>;
/** Payment gateway data in JSON format, received from storefront. */
data?: Maybe<Scalars["JSON"]>;
/**
* Idempotency key assigned to the transaction initialize.
*
* Added in Saleor 3.14.
*/
idempotencyKey: Scalars["String"];
/** Time of the event. */
issuedAt?: Maybe<Scalars["DateTime"]>;
/** The user or application that triggered the event. */
Expand Down Expand Up @@ -28346,6 +28360,12 @@ export type TransactionItem = Node &
chargePendingAmount: Money;
/** Total amount charged for this payment. */
chargedAmount: Money;
/**
* The related checkout.
*
* Added in Saleor 3.14.
*/
checkout?: Maybe<Checkout>;
/** Date and time at which payment transaction was created. */
createdAt: Scalars["DateTime"];
/**
Expand Down Expand Up @@ -32008,6 +32028,7 @@ export type BulkOrderCreateMutation = {
order?: {
__typename?: "Order";
id: string;
externalReference?: string | null;
errors: Array<{
__typename?: "OrderError";
code: OrderErrorCode;
Expand Down Expand Up @@ -32879,6 +32900,15 @@ export type SaleorCronOrderDetailsQuery = {
} | null;
};

export type OrderByReferenceQueryVariables = Exact<{
externalReference: Scalars["String"];
}>;

export type OrderByReferenceQuery = {
__typename?: "Query";
order?: { __typename?: "Order"; id: string } | null;
};

export type SaleorCronPackagesOverviewQueryVariables = Exact<{
createdGte?: InputMaybe<Scalars["Date"]>;
after?: InputMaybe<Scalars["String"]>;
Expand Down Expand Up @@ -33561,6 +33591,7 @@ export const BulkOrderCreateDocument = gql`
message
}
id
externalReference
}
}
}
Expand Down Expand Up @@ -34179,6 +34210,13 @@ export const SaleorCronOrderDetailsDocument = gql`
}
}
`;
export const OrderByReferenceDocument = gql`
query orderByReference($externalReference: String!) {
order(externalReference: $externalReference) {
id
}
}
`;
export const SaleorCronPackagesOverviewDocument = gql`
query saleorCronPackagesOverview(
$createdGte: Date
Expand Down Expand Up @@ -34985,6 +35023,19 @@ export function getSdk<C, E>(requester: Requester<C, E>) {
options,
) as Promise<SaleorCronOrderDetailsQuery>;
},
orderByReference(
variables: OrderByReferenceQueryVariables,
options?: C,
): Promise<OrderByReferenceQuery> {
return requester<
OrderByReferenceQuery,
OrderByReferenceQueryVariables
>(
OrderByReferenceDocument,
variables,
options,
) as Promise<OrderByReferenceQuery>;
},
saleorCronPackagesOverview(
variables: SaleorCronPackagesOverviewQueryVariables,
options?: C,
Expand Down
Loading

1 comment on commit a0a8191

@vercel
Copy link

@vercel vercel bot commented on a0a8191 Dec 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.