Browse Source

fix: resolve TypeScript compilation errors for K-1 import feature

- Update pdf-parse usage from v1 to v2 API (PDFParse class with getText())
- Fix Prisma relation names: memberships -> members, isActive -> endDate: null
- Remove unused imports, variables, and service injections
- Fix noUnusedLocals/noUnusedParameters violations across 9 files
pull/6701/head
Robert Patch 2 months ago
parent
commit
f219555dab
  1. 7
      apps/api/src/app/cell-mapping/cell-mapping.controller.ts
  2. 2
      apps/api/src/app/cell-mapping/cell-mapping.service.ts
  3. 12
      apps/api/src/app/k1-import/extractors/pdf-parse-extractor.ts
  4. 7
      apps/api/src/app/k1-import/extractors/tesseract-extractor.ts
  5. 4
      apps/api/src/app/k1-import/k1-aggregation.service.ts
  6. 2
      apps/api/src/app/k1-import/k1-confidence.service.ts
  7. 26
      apps/api/src/app/k1-import/k1-import.service.ts
  8. 3
      apps/client/src/app/pages/k1-import/k1-verification/k1-verification.component.ts
  9. 1
      apps/client/src/app/services/k1-import-data.service.ts

7
apps/api/src/app/cell-mapping/cell-mapping.controller.ts

@ -1,19 +1,15 @@
import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator';
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard';
import { permissions } from '@ghostfolio/common/permissions';
import type { RequestWithUser } from '@ghostfolio/common/types';
import {
Body,
Controller,
Delete,
Get,
Inject,
Put,
Query,
UseGuards
} from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { CellMappingService } from './cell-mapping.service';
@ -21,8 +17,7 @@ import { CellMappingService } from './cell-mapping.service';
@Controller('api/v1/cell-mapping')
export class CellMappingController {
public constructor(
private readonly cellMappingService: CellMappingService,
@Inject(REQUEST) private readonly request: RequestWithUser
private readonly cellMappingService: CellMappingService
) {}
/**

2
apps/api/src/app/cell-mapping/cell-mapping.service.ts

@ -253,7 +253,7 @@ export class CellMappingService implements OnModuleInit {
where: { partnershipId }
});
const results = await this.prismaService.cellAggregationRule.createMany({
await this.prismaService.cellAggregationRule.createMany({
data: rules.map((rule, i) => ({
partnershipId,
name: rule.name,

12
apps/api/src/app/k1-import/extractors/pdf-parse-extractor.ts

@ -1,7 +1,7 @@
import type { K1ExtractionResult, K1ExtractedField, K1UnmappedItem } from '@ghostfolio/common/interfaces';
import type { K1ExtractionResult, K1ExtractedField } from '@ghostfolio/common/interfaces';
import { Injectable, Logger } from '@nestjs/common';
import * as pdfParse from 'pdf-parse';
import { PDFParse } from 'pdf-parse';
import type { K1Extractor } from './k1-extractor.interface';
@ -245,9 +245,10 @@ export class PdfParseExtractor implements K1Extractor {
): Promise<K1ExtractionResult> {
this.logger.log(`Extracting from digital PDF: ${fileName}`);
const parsed = await pdfParse(buffer);
const parser = new PDFParse({ data: buffer });
const parsed = await parser.getText();
const text = parsed.text;
const pageCount = parsed.numpages;
const pageCount = parsed.total;
// Extract metadata
const metadata = this.extractMetadata(text);
@ -394,7 +395,8 @@ export class PdfParseExtractor implements K1Extractor {
*/
public async isDigitalK1(buffer: Buffer): Promise<boolean> {
try {
const parsed = await pdfParse(buffer);
const parser = new PDFParse({ data: buffer });
const parsed = await parser.getText();
const text = parsed.text || '';
if (text.length < 100) return false;

7
apps/api/src/app/k1-import/extractors/tesseract-extractor.ts

@ -55,10 +55,11 @@ export class TesseractExtractor implements K1Extractor {
// Fallback: try pdf-parse to at least get any embedded text
try {
const pdfParse = await import('pdf-parse');
const parsed = await pdfParse.default(buffer);
const { PDFParse } = await import('pdf-parse');
const parser = new PDFParse({ data: buffer });
const parsed = await parser.getText();
text = parsed.text;
pageCount = parsed.numpages;
pageCount = parsed.total;
} catch (parseError) {
this.logger.error(
`Both Tesseract and pdf-parse failed: ${parseError}`

4
apps/api/src/app/k1-import/k1-aggregation.service.ts

@ -1,7 +1,7 @@
import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
import type { K1AggregationResult } from '@ghostfolio/common/interfaces';
import { HttpException, Injectable, Logger } from '@nestjs/common';
import { HttpException, Injectable } from '@nestjs/common';
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
import { CellMappingService } from '../cell-mapping/cell-mapping.service';
@ -13,8 +13,6 @@ import { CellMappingService } from '../cell-mapping/cell-mapping.service';
*/
@Injectable()
export class K1AggregationService {
private readonly logger = new Logger(K1AggregationService.name);
public constructor(
private readonly prismaService: PrismaService,
private readonly cellMappingService: CellMappingService

2
apps/api/src/app/k1-import/k1-confidence.service.ts

@ -16,7 +16,7 @@ export class K1ConfidenceService {
*/
public scoreFields(
fields: K1ExtractedField[],
method: 'pdf-parse' | 'azure' | 'tesseract'
_method: 'pdf-parse' | 'azure' | 'tesseract'
): K1ExtractedField[] {
const scored = fields.map((field) => ({
...field,

26
apps/api/src/app/k1-import/k1-import.service.ts

@ -7,14 +7,11 @@ import { StatusCodes, getReasonPhrase } from 'http-status-codes';
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { CellMappingService } from '../cell-mapping/cell-mapping.service';
import { UploadService } from '../upload/upload.service';
import { AzureExtractor } from './extractors/azure-extractor';
import { PdfParseExtractor } from './extractors/pdf-parse-extractor';
import { TesseractExtractor } from './extractors/tesseract-extractor';
import { K1AggregationService } from './k1-aggregation.service';
import { K1AllocationService } from './k1-allocation.service';
import { K1ConfidenceService } from './k1-confidence.service';
import { K1FieldMapperService } from './k1-field-mapper.service';
const MAX_FILE_SIZE = 25 * 1024 * 1024; // 25 MB
@ -26,11 +23,8 @@ export class K1ImportService {
public constructor(
private readonly prismaService: PrismaService,
private readonly uploadService: UploadService,
private readonly cellMappingService: CellMappingService,
private readonly fieldMapperService: K1FieldMapperService,
private readonly confidenceService: K1ConfidenceService,
private readonly allocationService: K1AllocationService,
private readonly aggregationService: K1AggregationService,
private readonly pdfParseExtractor: PdfParseExtractor,
private readonly azureExtractor: AzureExtractor,
private readonly tesseractExtractor: TesseractExtractor
@ -74,8 +68,10 @@ export class K1ImportService {
userId
},
include: {
memberships: {
where: { isActive: true }
members: {
where: {
endDate: null
}
}
}
});
@ -87,7 +83,7 @@ export class K1ImportService {
);
}
if (!partnership.memberships || partnership.memberships.length === 0) {
if (!partnership.members || partnership.members.length === 0) {
throw new HttpException(
'Partnership has no active members',
StatusCodes.BAD_REQUEST
@ -585,7 +581,7 @@ export class K1ImportService {
await this.prismaService.partnershipMembership.findMany({
where: {
partnershipId: session.partnershipId,
isActive: true
endDate: null
},
include: { entity: true }
});
@ -768,8 +764,9 @@ export class K1ImportService {
*/
private async checkPasswordProtected(buffer: Buffer): Promise<void> {
try {
const pdfParse = await import('pdf-parse');
await pdfParse.default(buffer);
const { PDFParse } = await import('pdf-parse');
const parser = new PDFParse({ data: buffer });
await parser.getText();
} catch (error) {
if (
error?.message?.includes('password') ||
@ -793,8 +790,9 @@ export class K1ImportService {
entityCount: number;
}> {
try {
const pdfParse = await import('pdf-parse');
const parsed = await pdfParse.default(buffer);
const { PDFParse } = await import('pdf-parse');
const parser = new PDFParse({ data: buffer });
const parsed = await parser.getText();
const text = parsed.text || '';
// Count "Schedule K-1" header occurrences

3
apps/client/src/app/pages/k1-import/k1-verification/k1-verification.component.ts

@ -89,8 +89,6 @@ export class K1VerificationComponent implements OnInit {
// Available box numbers for assigning unmapped items
public availableBoxNumbers: string[] = [];
private partnershipId: string;
public constructor(
private readonly activatedRoute: ActivatedRoute,
private readonly changeDetectorRef: ChangeDetectorRef,
@ -294,7 +292,6 @@ export class K1VerificationComponent implements OnInit {
}
this.taxYear = session.taxYear;
this.partnershipId = session.partnershipId;
const extraction = session.rawExtraction || session.verifiedData;
if (extraction) {

1
apps/client/src/app/services/k1-import-data.service.ts

@ -1,5 +1,4 @@
import type {
K1ExtractionResult,
K1ImportSessionSummary,
K1AggregationResult
} from '@ghostfolio/common/interfaces';

Loading…
Cancel
Save