Add paymentStatus filter and field on order list API.
Support paid/unpaid/failed filtering from completed transactions for dashboard order tabs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
0d9e866a57
commit
7f6fa3672d
@@ -2,6 +2,7 @@ import {
|
|||||||
ArrayMinSize,
|
ArrayMinSize,
|
||||||
IsDateString,
|
IsDateString,
|
||||||
IsEnum,
|
IsEnum,
|
||||||
|
IsIn,
|
||||||
IsInt,
|
IsInt,
|
||||||
IsNumber,
|
IsNumber,
|
||||||
IsOptional,
|
IsOptional,
|
||||||
@@ -166,4 +167,9 @@ export class ListOrdersDto {
|
|||||||
@Min(0)
|
@Min(0)
|
||||||
@Type(() => Number)
|
@Type(() => Number)
|
||||||
maxTotal?: number;
|
maxTotal?: number;
|
||||||
|
|
||||||
|
/** Filter by payment outcome derived from transactions. */
|
||||||
|
@IsOptional()
|
||||||
|
@IsIn(['paid', 'unpaid', 'failed'])
|
||||||
|
paymentStatus?: 'paid' | 'unpaid' | 'failed';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ export class OrdersService {
|
|||||||
customer: this.buildCustomerSearchFilter(query.customerQuery.trim()),
|
customer: this.buildCustomerSearchFilter(query.customerQuery.trim()),
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
|
...this.paymentStatusWhere(query.paymentStatus),
|
||||||
};
|
};
|
||||||
|
|
||||||
const [items, total] = await Promise.all([
|
const [items, total] = await Promise.all([
|
||||||
@@ -762,6 +763,43 @@ export class OrdersService {
|
|||||||
return { OR: or };
|
return { OR: or };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private paymentStatusWhere(
|
||||||
|
paymentStatus: 'paid' | 'unpaid' | 'failed' | undefined,
|
||||||
|
): Prisma.OrderWhereInput {
|
||||||
|
if (paymentStatus === 'paid') {
|
||||||
|
return {
|
||||||
|
transactions: { some: { status: 'completed' } },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (paymentStatus === 'failed') {
|
||||||
|
return {
|
||||||
|
AND: [
|
||||||
|
{ transactions: { some: { status: 'failed' } } },
|
||||||
|
{ transactions: { none: { status: 'completed' } } },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (paymentStatus === 'unpaid') {
|
||||||
|
return {
|
||||||
|
transactions: { none: { status: 'completed' } },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
private derivePaymentStatus(
|
||||||
|
transactions: Array<{ status: string }>,
|
||||||
|
): 'paid' | 'unpaid' | 'failed' {
|
||||||
|
if (transactions.some((tx) => tx.status === 'completed')) return 'paid';
|
||||||
|
if (
|
||||||
|
transactions.length > 0 &&
|
||||||
|
transactions.every((tx) => tx.status === 'failed')
|
||||||
|
) {
|
||||||
|
return 'failed';
|
||||||
|
}
|
||||||
|
return 'unpaid';
|
||||||
|
}
|
||||||
|
|
||||||
private async defaultProcessStepId(businessId: bigint) {
|
private async defaultProcessStepId(businessId: bigint) {
|
||||||
const steps = await this.businessSettings.getOrderProcessSteps(businessId);
|
const steps = await this.businessSettings.getOrderProcessSteps(businessId);
|
||||||
return steps[0]?.id ?? 'processing';
|
return steps[0]?.id ?? 'processing';
|
||||||
@@ -873,6 +911,7 @@ export class OrdersService {
|
|||||||
processStepLabel: processStep?.label ?? null,
|
processStepLabel: processStep?.label ?? null,
|
||||||
processStepLabelFa: processStep?.labelFa?.trim() || null,
|
processStepLabelFa: processStep?.labelFa?.trim() || null,
|
||||||
processStepColor: processStep?.color ?? null,
|
processStepColor: processStep?.color ?? null,
|
||||||
|
paymentStatus: this.derivePaymentStatus(order.transactions ?? []),
|
||||||
source: order.source,
|
source: order.source,
|
||||||
subtotal: Number(order.subtotal),
|
subtotal: Number(order.subtotal),
|
||||||
shippingTotal: Number(order.shippingTotal),
|
shippingTotal: Number(order.shippingTotal),
|
||||||
|
|||||||
Reference in New Issue
Block a user