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

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

@ -253,7 +253,7 @@ export class CellMappingService implements OnModuleInit {
where: { partnershipId } where: { partnershipId }
}); });
const results = await this.prismaService.cellAggregationRule.createMany({ await this.prismaService.cellAggregationRule.createMany({
data: rules.map((rule, i) => ({ data: rules.map((rule, i) => ({
partnershipId, partnershipId,
name: rule.name, 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 { Injectable, Logger } from '@nestjs/common';
import * as pdfParse from 'pdf-parse'; import { PDFParse } from 'pdf-parse';
import type { K1Extractor } from './k1-extractor.interface'; import type { K1Extractor } from './k1-extractor.interface';
@ -245,9 +245,10 @@ export class PdfParseExtractor implements K1Extractor {
): Promise<K1ExtractionResult> { ): Promise<K1ExtractionResult> {
this.logger.log(`Extracting from digital PDF: ${fileName}`); 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 text = parsed.text;
const pageCount = parsed.numpages; const pageCount = parsed.total;
// Extract metadata // Extract metadata
const metadata = this.extractMetadata(text); const metadata = this.extractMetadata(text);
@ -394,7 +395,8 @@ export class PdfParseExtractor implements K1Extractor {
*/ */
public async isDigitalK1(buffer: Buffer): Promise<boolean> { public async isDigitalK1(buffer: Buffer): Promise<boolean> {
try { try {
const parsed = await pdfParse(buffer); const parser = new PDFParse({ data: buffer });
const parsed = await parser.getText();
const text = parsed.text || ''; const text = parsed.text || '';
if (text.length < 100) return false; 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 // Fallback: try pdf-parse to at least get any embedded text
try { try {
const pdfParse = await import('pdf-parse'); const { PDFParse } = await import('pdf-parse');
const parsed = await pdfParse.default(buffer); const parser = new PDFParse({ data: buffer });
const parsed = await parser.getText();
text = parsed.text; text = parsed.text;
pageCount = parsed.numpages; pageCount = parsed.total;
} catch (parseError) { } catch (parseError) {
this.logger.error( this.logger.error(
`Both Tesseract and pdf-parse failed: ${parseError}` `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 { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
import type { K1AggregationResult } from '@ghostfolio/common/interfaces'; 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 { StatusCodes, getReasonPhrase } from 'http-status-codes';
import { CellMappingService } from '../cell-mapping/cell-mapping.service'; import { CellMappingService } from '../cell-mapping/cell-mapping.service';
@ -13,8 +13,6 @@ import { CellMappingService } from '../cell-mapping/cell-mapping.service';
*/ */
@Injectable() @Injectable()
export class K1AggregationService { export class K1AggregationService {
private readonly logger = new Logger(K1AggregationService.name);
public constructor( public constructor(
private readonly prismaService: PrismaService, private readonly prismaService: PrismaService,
private readonly cellMappingService: CellMappingService private readonly cellMappingService: CellMappingService

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

@ -16,7 +16,7 @@ export class K1ConfidenceService {
*/ */
public scoreFields( public scoreFields(
fields: K1ExtractedField[], fields: K1ExtractedField[],
method: 'pdf-parse' | 'azure' | 'tesseract' _method: 'pdf-parse' | 'azure' | 'tesseract'
): K1ExtractedField[] { ): K1ExtractedField[] {
const scored = fields.map((field) => ({ const scored = fields.map((field) => ({
...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 { readFile } from 'node:fs/promises';
import { join } from 'node:path'; import { join } from 'node:path';
import { CellMappingService } from '../cell-mapping/cell-mapping.service';
import { UploadService } from '../upload/upload.service'; import { UploadService } from '../upload/upload.service';
import { AzureExtractor } from './extractors/azure-extractor'; import { AzureExtractor } from './extractors/azure-extractor';
import { PdfParseExtractor } from './extractors/pdf-parse-extractor'; import { PdfParseExtractor } from './extractors/pdf-parse-extractor';
import { TesseractExtractor } from './extractors/tesseract-extractor'; import { TesseractExtractor } from './extractors/tesseract-extractor';
import { K1AggregationService } from './k1-aggregation.service';
import { K1AllocationService } from './k1-allocation.service'; import { K1AllocationService } from './k1-allocation.service';
import { K1ConfidenceService } from './k1-confidence.service';
import { K1FieldMapperService } from './k1-field-mapper.service'; import { K1FieldMapperService } from './k1-field-mapper.service';
const MAX_FILE_SIZE = 25 * 1024 * 1024; // 25 MB const MAX_FILE_SIZE = 25 * 1024 * 1024; // 25 MB
@ -26,11 +23,8 @@ export class K1ImportService {
public constructor( public constructor(
private readonly prismaService: PrismaService, private readonly prismaService: PrismaService,
private readonly uploadService: UploadService, private readonly uploadService: UploadService,
private readonly cellMappingService: CellMappingService,
private readonly fieldMapperService: K1FieldMapperService, private readonly fieldMapperService: K1FieldMapperService,
private readonly confidenceService: K1ConfidenceService,
private readonly allocationService: K1AllocationService, private readonly allocationService: K1AllocationService,
private readonly aggregationService: K1AggregationService,
private readonly pdfParseExtractor: PdfParseExtractor, private readonly pdfParseExtractor: PdfParseExtractor,
private readonly azureExtractor: AzureExtractor, private readonly azureExtractor: AzureExtractor,
private readonly tesseractExtractor: TesseractExtractor private readonly tesseractExtractor: TesseractExtractor
@ -74,8 +68,10 @@ export class K1ImportService {
userId userId
}, },
include: { include: {
memberships: { members: {
where: { isActive: true } 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( throw new HttpException(
'Partnership has no active members', 'Partnership has no active members',
StatusCodes.BAD_REQUEST StatusCodes.BAD_REQUEST
@ -585,7 +581,7 @@ export class K1ImportService {
await this.prismaService.partnershipMembership.findMany({ await this.prismaService.partnershipMembership.findMany({
where: { where: {
partnershipId: session.partnershipId, partnershipId: session.partnershipId,
isActive: true endDate: null
}, },
include: { entity: true } include: { entity: true }
}); });
@ -768,8 +764,9 @@ export class K1ImportService {
*/ */
private async checkPasswordProtected(buffer: Buffer): Promise<void> { private async checkPasswordProtected(buffer: Buffer): Promise<void> {
try { try {
const pdfParse = await import('pdf-parse'); const { PDFParse } = await import('pdf-parse');
await pdfParse.default(buffer); const parser = new PDFParse({ data: buffer });
await parser.getText();
} catch (error) { } catch (error) {
if ( if (
error?.message?.includes('password') || error?.message?.includes('password') ||
@ -793,8 +790,9 @@ export class K1ImportService {
entityCount: number; entityCount: number;
}> { }> {
try { try {
const pdfParse = await import('pdf-parse'); const { PDFParse } = await import('pdf-parse');
const parsed = await pdfParse.default(buffer); const parser = new PDFParse({ data: buffer });
const parsed = await parser.getText();
const text = parsed.text || ''; const text = parsed.text || '';
// Count "Schedule K-1" header occurrences // 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 // Available box numbers for assigning unmapped items
public availableBoxNumbers: string[] = []; public availableBoxNumbers: string[] = [];
private partnershipId: string;
public constructor( public constructor(
private readonly activatedRoute: ActivatedRoute, private readonly activatedRoute: ActivatedRoute,
private readonly changeDetectorRef: ChangeDetectorRef, private readonly changeDetectorRef: ChangeDetectorRef,
@ -294,7 +292,6 @@ export class K1VerificationComponent implements OnInit {
} }
this.taxYear = session.taxYear; this.taxYear = session.taxYear;
this.partnershipId = session.partnershipId;
const extraction = session.rawExtraction || session.verifiedData; const extraction = session.rawExtraction || session.verifiedData;
if (extraction) { if (extraction) {

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

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

Loading…
Cancel
Save