Passed
Push — master ( be6fbd...8a140a )
by Andreas
24:16
created

org_openpsa_invoices_calculator::set_invoice()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package org.openpsa.invoices
4
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
6
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
7
 */
8
9
/**
10
 * Helper class for deliverable invoicing
11
 *
12
 * @package org.openpsa.invoices
13
 */
14
class org_openpsa_invoices_calculator
15
{
16
    /**
17
     * @var org_openpsa_sales_salesproject_deliverable_dba
18
     */
19
    private $_deliverable;
20
21
    /**
22
     * @var org_openpsa_invoices_invoice_dba
23
     */
24
    private $_invoice;
25
26 8
    public function process_deliverable(org_openpsa_sales_salesproject_deliverable_dba $deliverable, $cycle_number = null)
27
    {
28 8
        $this->_deliverable = $deliverable;
29
        // Recalculate price to catch possible unit changes
30 8
        $client_class = midcom_baseclasses_components_configuration::get('org.openpsa.sales', 'config')->get('calculator');
31 8
        $client = new $client_class();
32 8
        $client->run($this->_deliverable);
33
34 8
        $this_cycle_amount = $client->get_price();
35
36 8
        if ($this_cycle_amount == 0) {
37 3
            debug_add('Invoice sum 0, skipping invoice creation');
38 3
            return 0;
39
        }
40
41 5
        $this->_invoice = $this->_probe_invoice($cycle_number);
42
43 5
        if (!$this->_invoice->update()) {
44
            throw new midcom_error("The invoice could not be saved. Last Midgard error was: " . midcom_connection::get_error_string());
45
        }
46
47
        // TODO: Create invoicing task if assignee is defined
48
49 5
        $items = $client->get_invoice_items($this->_invoice);
50
51 5
        foreach ($items as $item) {
52 5
            $item->deliverable = $this->_deliverable->id;
53 5
            $item->skip_invoice_update = true;
54 5
            $stat = ($item->id) ? $item->update() : $item->create();
55 5
            if (!$stat) {
56
                throw new midcom_error('Failed to save item to disk, ' . midcom_connection::get_error_string());
57
            }
58
        }
59 5
        org_openpsa_invoices_invoice_item_dba::update_invoice($this->_invoice);
60 5
        org_openpsa_invoices_invoice_item_dba::update_deliverable($this->_deliverable);
61
62 5
        return $this_cycle_amount;
63
    }
64
65 4
    public function get_invoice() : org_openpsa_invoices_invoice_dba
66
    {
67 4
        return $this->_invoice;
68
    }
69
70
    /**
71
     * Try to locate unsent invoices for deliverables in the same salesproject
72
     *
73
     * Example use case: A support contract with multiple hourly rates (defined
74
     * as deliverables) for different types of work. Instead of sending the customer
75
     * one invoice per hourly rate per month, one composite invoice for all fees is generated
76
     */
77 5
    private function _probe_invoice($cycle_number) : org_openpsa_invoices_invoice_dba
78
    {
79 5
        $item_mc = org_openpsa_invoices_invoice_item_dba::new_collector('deliverable.salesproject', $this->_deliverable->salesproject);
80 5
        $item_mc->add_constraint('invoice.sent', '=', 0);
81 5
        $suspects = $item_mc->get_values('invoice');
82
83
        // validate suspects.. we want no cancelation invoices
84 5
        if (!empty($suspects)) {
85 1
            $invoice_mc = org_openpsa_invoices_invoice_dba::new_collector();
86 1
            $invoice_mc->add_constraint('cancelationInvoice', 'IN', array_values($suspects));
87 1
            $cancelation_ids = $invoice_mc->get_values('cancelationInvoice');
88
89 1
            $suspects = array_diff($suspects, $cancelation_ids);
90
            // check which suspects are left
91 1
            if (!empty($suspects)) {
92 1
                return new org_openpsa_invoices_invoice_dba(array_pop($suspects));
93
            }
94
        }
95
96
        // Nothing found, create a new invoice
97 5
        return $this->_create_invoice($cycle_number);
98
    }
99
100 5
    private function _create_invoice($cycle_number) : org_openpsa_invoices_invoice_dba
101
    {
102 5
        $salesproject = new org_openpsa_sales_salesproject_dba($this->_deliverable->salesproject);
103 5
        $invoice = new org_openpsa_invoices_invoice_dba();
104 5
        $invoice->customer = $salesproject->customer;
105 5
        $invoice->customerContact = $salesproject->customerContact;
106 5
        $invoice->number = $invoice->generate_invoice_number();
107 5
        $invoice->owner = $salesproject->owner;
108 5
        $invoice->vat = $invoice->get_default('vat');
109 5
        $invoice->description = $invoice->get_default('remarks');
110
111 5
        if (!$invoice->create()) {
112
            throw new midcom_error('Failed to create invoice, ' . midcom_connection::get_error_string());
113
        }
114
        // Register the cycle number for reporting purposes
115 5
        if ($cycle_number !== null) {
116 4
            $invoice->set_parameter('org.openpsa.sales', 'cycle_number', $cycle_number);
117
        }
118 5
        return $invoice;
119
    }
120
}
121