init
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { Repository } from 'typeorm';
|
||||
import type { CookieCartSummary } from '../../storefrontCart/types/CookieCartSummary';
|
||||
import { deriveCheckoutSessionState } from '../../../utils/checkout/deriveCheckoutSessionState';
|
||||
import { InvoiceReason } from '../../payment/types/InvoiceReason';
|
||||
import { InvoiceService } from '../../payment/services/InvoiceService';
|
||||
import { PaymentMethod } from '../../payment/types/PaymentMethod';
|
||||
import { CheckoutSessionDiscount } from '../entities/CheckoutSessionDiscount';
|
||||
import { CheckoutSessionLine } from '../entities/CheckoutSessionLine';
|
||||
import { CheckoutSession } from '../entities/CheckoutSession';
|
||||
|
||||
@Injectable()
|
||||
export class CheckoutSessionService {
|
||||
constructor(
|
||||
@InjectRepository(CheckoutSession)
|
||||
private readonly sessionRepo: Repository<CheckoutSession>,
|
||||
@InjectRepository(CheckoutSessionLine)
|
||||
private readonly lineRepo: Repository<CheckoutSessionLine>,
|
||||
@InjectRepository(CheckoutSessionDiscount)
|
||||
private readonly discountRepo: Repository<CheckoutSessionDiscount>,
|
||||
private readonly invoiceService: InvoiceService
|
||||
) {}
|
||||
|
||||
async findById(id: string): Promise<CheckoutSession | null> {
|
||||
return this.sessionRepo.findOne({
|
||||
where: { id },
|
||||
relations: ['lines', 'discounts', 'invoice', 'invoice.moneroDetails', 'invoice.payments']
|
||||
});
|
||||
}
|
||||
|
||||
async createFromCartSummary(summary: CookieCartSummary): Promise<CheckoutSession> {
|
||||
if (summary.cartExtended.length === 0) {
|
||||
throw new BadRequestException('Your cart is empty');
|
||||
}
|
||||
|
||||
if (summary.hasIssues) {
|
||||
throw new BadRequestException('Resolve cart issues before paying');
|
||||
}
|
||||
|
||||
const sessionId = randomUUID();
|
||||
|
||||
const invoice = await this.invoiceService.issueInvoice({
|
||||
paymentMethod: PaymentMethod.Xmr,
|
||||
reason: InvoiceReason.Checkout,
|
||||
contextId: sessionId,
|
||||
amountFiat: summary.cartTotalPrice
|
||||
});
|
||||
|
||||
const lines = summary.cartExtended.map(line =>
|
||||
this.lineRepo.create({
|
||||
variantId: line.id,
|
||||
productId: line.productId,
|
||||
productTitle: line.productTitle,
|
||||
variantTitle: line.title,
|
||||
thumbnailUrl: line.thumbnailUrl,
|
||||
qty: line.qty,
|
||||
unitPriceFiat: line.price,
|
||||
lineSubtotalFiat: line.lineSubtotal,
|
||||
deliveryMode: line.deliveryMode
|
||||
})
|
||||
);
|
||||
|
||||
const discounts = summary.discounts
|
||||
.filter(d => d.amount !== null && d.amount > 0 && !d.issueMessage)
|
||||
.map(d =>
|
||||
this.discountRepo.create({
|
||||
code: d.code,
|
||||
amountFiat: d.amount!
|
||||
})
|
||||
);
|
||||
|
||||
const session = this.sessionRepo.create({
|
||||
id: sessionId,
|
||||
invoice,
|
||||
lines,
|
||||
discounts
|
||||
});
|
||||
|
||||
return this.sessionRepo.save(session);
|
||||
}
|
||||
|
||||
async cancelSession(sessionId: string): Promise<void> {
|
||||
const session = await this.sessionRepo.findOne({
|
||||
where: { id: sessionId },
|
||||
relations: ['invoice', 'invoice.moneroDetails', 'invoice.payments']
|
||||
});
|
||||
|
||||
if (!session) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { isOpenForPayment } = deriveCheckoutSessionState(session);
|
||||
|
||||
if (!isOpenForPayment) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.sessionRepo.update(session.id, { cancelledAt: new Date() });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user