1
|
|
|
import { CommandHandler } from '@nestjs/cqrs'; |
2
|
|
|
import { Inject } from '@nestjs/common'; |
3
|
|
|
import { ICustomerRepository } from 'src/Domain/Customer/Repository/ICustomerRepository'; |
4
|
|
|
import { GenerateBillingCommand } from './GenerateBillingCommand'; |
5
|
|
|
import { CustomerNotFoundException } from 'src/Domain/Customer/Exception/CustomerNotFoundException'; |
6
|
|
|
import { IEventRepository } from 'src/Domain/FairCalendar/Repository/IEventRepository'; |
7
|
|
|
import { Billing } from 'src/Domain/Accounting/Billing.entity'; |
8
|
|
|
import { BillingItem } from 'src/Domain/Accounting/BillingItem.entity'; |
9
|
|
|
import { IBillingRepository } from 'src/Domain/Accounting/Repository/IBillingRepository'; |
10
|
|
|
import { IBillingItemRepository } from 'src/Domain/Accounting/Repository/IBillingItemRepository'; |
11
|
|
|
import { BillingIdGenerator } from 'src/Domain/Accounting/Generators/BillingIdGenerator'; |
12
|
|
|
import { NoBillableEventsFoundException } from 'src/Domain/Accounting/Exception/NoBillableEventsFoundException'; |
13
|
|
|
|
14
|
|
|
@CommandHandler(GenerateBillingCommand) |
15
|
|
|
export class GenerateBillingCommandHandler { |
16
|
|
|
constructor( |
17
|
|
|
@Inject('ICustomerRepository') |
18
|
|
|
private readonly customerRepository: ICustomerRepository, |
19
|
|
|
@Inject('IEventRepository') |
20
|
|
|
private readonly eventRepository: IEventRepository, |
21
|
|
|
@Inject('IBillingRepository') |
22
|
|
|
private readonly billingRepository: IBillingRepository, |
23
|
|
|
@Inject('IBillingItemRepository') |
24
|
|
|
private readonly billingItemRepository: IBillingItemRepository, |
25
|
|
|
private readonly billingIdGenerator: BillingIdGenerator |
26
|
|
|
) {} |
27
|
|
|
|
28
|
|
|
public async execute(command: GenerateBillingCommand): Promise<string> { |
29
|
|
|
const { customerId, status, date, user } = command; |
30
|
|
|
|
31
|
|
|
const customer = await this.customerRepository.findOneById(customerId); |
32
|
|
|
if (!customer) { |
33
|
|
|
throw new CustomerNotFoundException(); |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
const [ billingId, events ] = await Promise.all([ |
37
|
|
|
this.billingIdGenerator.generate(), |
38
|
|
|
this.eventRepository.findBillableEventsByMonthAndCustomer(date, customer) |
39
|
|
|
]); |
40
|
|
|
|
41
|
|
|
if (!events) { |
42
|
|
|
throw new NoBillableEventsFoundException(); |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
const billing = new Billing(billingId, status, '', user, customer); |
46
|
|
|
const billingItems: BillingItem[] = []; |
47
|
|
|
|
48
|
|
|
for (const { |
49
|
|
|
time, |
50
|
|
|
billable, |
51
|
|
|
day_duration, |
52
|
|
|
project_name, |
53
|
|
|
task_name, |
54
|
|
|
first_name, |
55
|
|
|
last_name, |
56
|
|
|
amount |
57
|
|
|
} of events) { |
58
|
|
|
billingItems.push( |
59
|
|
|
new BillingItem( |
60
|
|
|
billing, |
61
|
|
|
`${project_name} - ${task_name} - ${first_name} ${last_name}`, |
62
|
|
|
Math.ceil(time / day_duration * 100) / 100, |
63
|
|
|
Number(amount), |
64
|
|
|
billable ? 0 : 100 |
65
|
|
|
) |
66
|
|
|
); |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
await this.billingRepository.save(billing); |
70
|
|
|
await this.billingItemRepository.save(billingItems); |
71
|
|
|
|
72
|
|
|
return billing.getId(); |
73
|
|
|
} |
74
|
|
|
} |
75
|
|
|
|