Passed
Pull Request — master (#165)
by Mathieu
03:12 queued 01:18
created

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

Complexity

Total Complexity 7
Complexity/F 3.5

Size

Lines of Code 85
Function Count 2

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 7
eloc 69
mnd 5
bc 5
fnc 2
dl 0
loc 85
rs 10
bpm 2.5
cpm 3.5
noi 0
c 0
b 0
f 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
15
@CommandHandler(GenerateInvoiceCommand)
16
export class GenerateInvoiceCommandHandler {
17
  constructor(
18
    @Inject('IProjectRepository')
19
    private readonly projectRepository: IProjectRepository,
20
    @Inject('IEventRepository')
21
    private readonly eventRepository: IEventRepository,
22
    @Inject('IInvoiceRepository')
23
    private readonly invoiceRepository: IInvoiceRepository,
24
    @Inject('IInvoiceItemRepository')
25
    private readonly invoiceItemRepository: IInvoiceItemRepository,
26
    @Inject('IDateUtils')
27
    private readonly dateUtils: IDateUtils,
28
    private readonly invoiceIdGenerator: InvoiceIdGenerator
29
  ) {}
30
31
  public async execute(command: GenerateInvoiceCommand): Promise<string> {
32
    const { projectId, status, generatedDate, user, expireInDays } = command;
33
34
    const project = await this.projectRepository.findOneById(projectId);
35
    if (!project) {
36
      throw new ProjectNotFoundException();
37
    }
38
39
    const [ invoiceId, events ] = await Promise.all([
40
      this.invoiceIdGenerator.generate(),
41
      this.eventRepository.findBillableEventsByMonthAndProject(generatedDate, project)
42
    ]);
43
44
    if (0 === events.length) {
45
      throw new NoBillableEventsFoundException();
46
    }
47
48
    const expiryDate = this.dateUtils.addDaysToDate(generatedDate, expireInDays);
49
    const invoiceItems: InvoiceItem[] = [];
50
    const invoice = new Invoice(
51
      invoiceId,
52
      status,
53
      expiryDate.toISOString(),
54
      user,
55
      project
56
    );
57
58
    for (const event of events) {
59
      invoiceItems.push(this.buildInvoiceItem(invoice, event));
60
    }
61
62
    const savedInvoice = await this.invoiceRepository.save(invoice);
63
    await this.invoiceItemRepository.save(invoiceItems);
64
65
    return savedInvoice.getId();
66
  }
67
68
  private buildInvoiceItem(invoice: Invoice, {
69
    time_spent,
70
    billable,
71
    task_name,
72
    first_name,
73
    last_name,
74
    amount
75
  }): InvoiceItem {
76
    return new InvoiceItem(
77
      invoice,
78
      `${task_name} - ${first_name} ${last_name}`,
79
      Number(time_spent),
80
      amount ? Number(amount) : 0,
81
      billable ? 0 : 100
82
    );
83
  }
84
}
85