forked from StellarSplit/StellarSplit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcompliance.processor.ts
More file actions
128 lines (115 loc) · 4.33 KB
/
Copy pathcompliance.processor.ts
File metadata and controls
128 lines (115 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { Process, Processor } from "@nestjs/bull";
import { Job } from "bull";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository, Between } from "typeorm";
import {
TaxExportRequest,
ExportStatus,
ExportFormat,
} from "./entities/tax-export-request.entity";
import { Split } from "../entities/split.entity";
import { CSVExporterService } from "./exporters/csv-exporter.service";
import { PDFExporterService } from "./exporters/pdf-exporter.service";
import { QBOExporterService } from "./exporters/qbo-exporter.service";
import { JSONExporterService } from "./exporters/json-exporter.service";
import { OFXExporterService } from "./exporters/ofx-exporter.service";
import { EmailService } from "../email/email.service";
import { Logger } from "@nestjs/common";
import * as fs from "fs";
import * as path from "path";
@Processor("compliance-export")
export class ComplianceProcessor {
private readonly logger = new Logger(ComplianceProcessor.name);
private readonly exportDir = path.join(process.cwd(), "exports");
constructor(
@InjectRepository(TaxExportRequest)
private exportRepo: Repository<TaxExportRequest>,
@InjectRepository(Split)
private splitRepo: Repository<Split>,
private csvExporter: CSVExporterService,
private pdfExporter: PDFExporterService,
private qboExporter: QBOExporterService,
private jsonExporter: JSONExporterService,
private ofxExporter: OFXExporterService,
private emailService: EmailService,
) {
if (!fs.existsSync(this.exportDir)) {
fs.mkdirSync(this.exportDir);
}
}
@Process("generate-export")
async handleExport(job: Job<{ requestId: string }>) {
const { requestId } = job.data;
const request = await this.exportRepo.findOne({ where: { id: requestId } });
if (!request) {
this.logger.error(`Export request ${requestId} not found`);
return;
}
try {
await this.exportRepo.update(requestId, {
status: ExportStatus.PROCESSING,
});
const splits = await this.splitRepo.find({
where: {
creatorWalletAddress: request.userId,
createdAt: Between(request.periodStart, request.periodEnd),
},
relations: ["category"],
});
let content: string | Buffer;
let filename = `tax-export-${requestId}`;
switch (request.exportFormat) {
case ExportFormat.CSV:
content = await this.csvExporter.generate(splits);
filename += ".csv";
break;
case ExportFormat.PDF:
content = await this.pdfExporter.generate(splits);
filename += ".pdf";
break;
case ExportFormat.QBO:
content = await this.qboExporter.generate(splits);
filename += ".qbo";
break;
case ExportFormat.JSON:
content = await this.jsonExporter.generate(splits);
filename += ".json";
break;
case ExportFormat.OFX:
content = await this.ofxExporter.generate(splits);
filename += ".ofx";
break;
default:
throw new Error(`Unsupported export format: ${request.exportFormat}`);
}
const filePath = path.join(this.exportDir, filename);
fs.writeFileSync(filePath, content);
const expiresAt = new Date();
expiresAt.setHours(expiresAt.getHours() + 48);
await this.exportRepo.update(requestId, {
status: ExportStatus.READY,
fileUrl: filePath, // Using local path for simplicity in this implementation
fileSize: fs.statSync(filePath).size,
recordCount: splits.length,
completedAt: new Date(),
expiresAt,
});
// Send email notification
// In a real app, we'd look up the user's email by wallet address
// For now, we'll assume a dummy email or use a placeholder
await this.emailService["emailQueue"].add("sendEmail", {
to: "user@example.com", // Placeholder
type: "export_ready",
context: {
requestId,
format: request.exportFormat,
downloadUrl: `http://localhost:3000/api/compliance/export/${requestId}/download`,
},
});
this.logger.log(`Export ${requestId} completed successfully`);
} catch (error) {
this.logger.error(`Export ${requestId} failed: ${error}`);
await this.exportRepo.update(requestId, { status: ExportStatus.FAILED });
}
}
}