Passed
Pull Request — master (#165)
by Mathieu
01:57
created

server/src/Application/Accounting/Command/Invoice/GenerateInvoiceCommandHandler.ts   A

Complexity

Total Complexity 7
Complexity/F 3.5

Size

Lines of Code 86
Function Count 2

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 70
dl 0
loc 86
rs 10
c 0
b 0
f 0
wmc 7
mnd 5
bc 5
fnc 2
bpm 2.5
cpm 3.5
noi 0

2 Functions

Rating   Name   Duplication   Size   Complexity  
A GenerateInvoiceCommandHandler.buildInvoiceItem 0 15 3
A GenerateInvoiceCommandHandler.execute 0 36 4
1
import { CommandHandler } from '@nestjs/cqrs';
2
import { Inject } from '@nestjs/common';
3
import { GenerateInvoiceCommand } from './GenerateInvoiceCommand';
4
import { IEventRepository } from 'src/Domain/FairCalendar/Repository/IEventRepository';
5
import { Invoice } from 'src/Domain/Accounting/Invoice.entity';
6
import { InvoiceItem } from 'src/Domain/Accounting/InvoiceItem.entity';
7
import { IInvoiceRepository } from 'src/Domain/Accounting/Repository/IInvoiceRepository';
8
import { IInvoiceItemRepository } from 'src/Domain/Accounting/Repository/IInvoiceItemRepository';
9
import { InvoiceIdGenerator } from 'src/Domain/Accounting/Generators/InvoiceIdGenerator';
10
import { NoBillableEventsFoundException } from 'src/Domain/Accounting/Exception/NoBillableEventsFoundException';
11
import { IDateUtils } from 'src/Application/IDateUtils';
12
import { IProjectRepository } from 'src/Domain/Project/Repository/IProjectRepository';
13
import { ProjectNotFoundException } from 'src/Domain/Project/Exception/ProjectNotFoundException';
14
import { Project } from 'src/Domain/Project/Project.entity';
15
16
@CommandHandler(GenerateInvoiceCommand)
17
export class GenerateInvoiceCommandHandler {
18
  constructor(
19
    @Inject('IProjectRepository')
20
    private readonly projectRepository: IProjectRepository,
21
    @Inject('IEventRepository')
22
    private readonly eventRepository: IEventRepository,
23
    @Inject('IInvoiceRepository')
24
    private readonly invoiceRepository: IInvoiceRepository,
25
    @Inject('IInvoiceItemRepository')
26
    private readonly invoiceItemRepository: IInvoiceItemRepository,
27
    @Inject('IDateUtils')
28
    private readonly dateUtils: IDateUtils,
29
    private readonly invoiceIdGenerator: InvoiceIdGenerator
30
  ) {}
31
32
  public async execute(command: GenerateInvoiceCommand): Promise<string> {
33
    const { projectId, status, generatedDate, user, expireInDays } = command;
34
35
    const project = await this.projectRepository.findOneById(projectId);
36
    if (!project) {
37
      throw new ProjectNotFoundException();
38
    }
39
40
    const [ invoiceId, events ] = await Promise.all([
41
      this.invoiceIdGenerator.generate(),
42
      this.eventRepository.findBillableEventsByMonthAndProject(generatedDate, project)
43
    ]);
44
45
    if (0 === events.length) {
46
      throw new NoBillableEventsFoundException();
47
    }
48
49
    const expiryDate = this.dateUtils.addDaysToDate(generatedDate, expireInDays);
50
    const invoiceItems: InvoiceItem[] = [];
51
    const invoice = new Invoice(
52
      invoiceId,
53
      status,
54
      expiryDate.toISOString(),
55
      user,
56
      project
57
    );
58
59
    for (const event of events) {
60
      invoiceItems.push(this.buildInvoiceItem(invoice, project, event));
61
    }
62
63
    const savedInvoice = await this.invoiceRepository.save(invoice);
64
    await this.invoiceItemRepository.save(invoiceItems);
65
66
    return savedInvoice.getId();
67
  }
68
69
  private buildInvoiceItem(invoice: Invoice, project: Project, {
70
    time_spent,
71
    billable,
72
    task_name,
73
    first_name,
74
    last_name,
75
    amount
76
  }): InvoiceItem {
77
    return new InvoiceItem(
78
      invoice,
79
      `${task_name} - ${first_name} ${last_name}`,
80
      Number(time_spent),
81
      amount ? Number(amount) : 0,
82
      billable ? 0 : 100
83
    );
84
  }
85
}
86