1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @package Intraface_Procurement |
4
|
|
|
*/ |
5
|
|
|
class Procurement extends Intraface_Standard |
6
|
|
|
{ |
7
|
|
|
public $kernel; |
8
|
|
|
public $id; |
9
|
|
|
public $error; |
10
|
|
|
public $from_region_types; |
11
|
|
|
public $status_types; |
12
|
|
|
public $value; |
13
|
|
|
public $dbquery; |
14
|
|
|
|
15
|
10 |
|
function __construct($kernel, $id = 0) |
16
|
|
|
{ |
17
|
10 |
|
$this->kernel = $kernel; |
18
|
10 |
|
$this->error = new Intraface_Error; |
19
|
10 |
|
$this->id = intval($id); |
20
|
|
|
|
21
|
10 |
|
$this->dbquery = new Intraface_DBQuery($this->kernel, "procurement", "active = 1 AND intranet_id = ".$this->kernel->intranet->get("id")); |
22
|
10 |
|
$this->dbquery->useErrorObject($this->error); |
23
|
|
|
|
24
|
10 |
|
if ($this->id != 0) { |
25
|
1 |
|
$this->load(); |
26
|
1 |
|
} |
27
|
10 |
|
} |
28
|
|
|
|
29
|
6 |
|
function load() |
30
|
|
|
{ |
31
|
5 |
|
$db = new DB_Sql; |
32
|
|
|
|
33
|
5 |
|
$db->query("SELECT *, |
34
|
|
|
DATE_FORMAT(invoice_date, '%d-%m-%Y') AS dk_invoice_date, |
35
|
|
|
DATE_FORMAT(delivery_date, '%d-%m-%Y') AS dk_delivery_date, |
36
|
|
|
DATE_FORMAT(payment_date, '%d-%m-%Y') AS dk_payment_date, |
37
|
|
|
DATE_FORMAT(paid_date, '%d-%m-%Y') AS dk_paid_date, |
38
|
|
|
DATE_FORMAT(date_recieved, '%d-%m-%Y') AS dk_date_recieved, |
39
|
|
|
DATE_FORMAT(date_canceled, '%d-%m-%Y') AS dk_date_canceled, |
40
|
|
|
DATE_FORMAT(date_stated, '%d-%m-%Y') AS date_stated, |
41
|
|
|
DATE_FORMAT(date_stated, '%d-%m-%Y') AS dk_date_stated |
42
|
|
|
|
43
|
5 |
|
FROM procurement WHERE intranet_id = ".$this->kernel->intranet->get("id")." AND id = ".$this->id); |
44
|
5 |
|
if (!$db->nextRecord()) { |
45
|
|
|
return false; |
46
|
|
|
} |
47
|
|
|
|
48
|
5 |
|
$this->value["id"] = $db->f("id"); |
49
|
|
|
|
50
|
5 |
|
$this->value["invoice_date"] = $db->f("invoice_date"); |
51
|
5 |
View Code Duplication |
if ($db->f("invoice_date") != "0000-00-00") { |
52
|
5 |
|
$this->value["dk_invoice_date"] = $db->f("dk_invoice_date"); |
53
|
5 |
|
} else { |
54
|
6 |
|
$this->value["dk_invoice_date"] = ""; |
55
|
|
|
} |
56
|
|
|
|
57
|
5 |
|
$this->value["delivery_date"] = $db->f("delivery_date"); |
58
|
5 |
View Code Duplication |
if ($db->f("delivery_date") != "0000-00-00") { |
59
|
5 |
|
$this->value["dk_delivery_date"] = $db->f("dk_delivery_date"); |
60
|
5 |
|
} else { |
61
|
|
|
$this->value["dk_delivery_date"] = ""; |
62
|
|
|
} |
63
|
|
|
|
64
|
5 |
|
$this->value["payment_date"] = $db->f("payment_date"); |
65
|
|
|
|
66
|
5 |
View Code Duplication |
if ($db->f("payment_date") != "0000-00-00") { |
67
|
5 |
|
$this->value["dk_payment_date"] = $db->f("dk_payment_date"); |
68
|
5 |
|
} else { |
69
|
|
|
$this->value["dk_payment_date"] = ""; |
70
|
|
|
} |
71
|
|
|
|
72
|
5 |
|
$this->value["date_recieved"] = $db->f("date_recieved"); |
73
|
5 |
View Code Duplication |
if ($db->f("date_recieved") != "0000-00-00") { |
74
|
5 |
|
$this->value["dk_date_recieved"] = $db->f("dk_date_recieved"); |
75
|
5 |
|
} else { |
76
|
|
|
$this->value["dk_date_recieved"] = ""; |
77
|
|
|
} |
78
|
|
|
|
79
|
5 |
|
$this->value["date_canceled"] = $db->f("date_canceled"); |
80
|
5 |
View Code Duplication |
if ($db->f("date_canceled") != "0000-00-00") { |
81
|
5 |
|
$this->value["dk_date_canceled"] = $db->f("dk_date_canceled"); |
82
|
5 |
|
} else { |
83
|
|
|
$this->value["dk_date_canceled"] = ""; |
84
|
|
|
} |
85
|
|
|
|
86
|
5 |
|
$this->value["date_stated"] = $db->f('date_stated'); |
87
|
5 |
|
$this->value["dk_date_stated"] = $db->f('dk_date_stated'); |
88
|
|
|
|
89
|
5 |
|
$this->value["paid_date"] = $db->f("paid_date"); |
90
|
|
|
// this is used when stating |
91
|
5 |
|
$this->value['this_date'] = $this->value["paid_date"]; |
92
|
|
|
|
93
|
|
|
|
94
|
5 |
|
$this->value["dk_paid_date"] = $db->f("dk_paid_date"); |
95
|
5 |
|
$this->value["number"] = $db->f("number"); |
96
|
5 |
|
$this->value["contact_id"] = $db->f("contact_id"); |
97
|
|
|
|
98
|
5 |
|
$this->value["vendor"] = $db->f("vendor"); |
99
|
5 |
|
$this->value["description"] = $db->f("description"); |
100
|
5 |
|
$this->value["from_region_key"] = $db->f("from_region_key"); |
101
|
5 |
|
$region_types = $this->getRegionTypes(); |
102
|
5 |
|
$this->value["from_region"] = $region_types[$db->f("from_region_key")]; |
103
|
|
|
|
104
|
5 |
|
$this->value["price_items"] = $db->f("price_items"); |
105
|
5 |
|
$this->value["dk_price_items"] = number_format($db->f("price_items"), 2, ",", "."); |
106
|
5 |
|
$this->value["price_shipment_etc"] = $db->f("price_shipment_etc"); |
107
|
5 |
|
$this->value["dk_price_shipment_etc"] = number_format($this->value["price_shipment_etc"], 2, ",", "."); |
108
|
5 |
|
$this->value["vat"] = $db->f("vat"); |
109
|
5 |
|
$this->value["dk_vat"] = number_format($db->f("vat"), 2, ",", "."); |
110
|
5 |
|
$this->value["total_price"] = round($this->value["price_items"] + $this->value["price_shipment_etc"] + $this->value["vat"], 2); |
111
|
5 |
|
$this->value["dk_total_price"] = number_format($this->value["total_price"], 2, ",", "."); |
112
|
|
|
|
113
|
5 |
|
$this->value["status_key"] = $db->f("status_key"); |
114
|
5 |
|
$types = $this->getStatusTypes(); |
115
|
5 |
|
$this->value["status"] = $types[$db->f("status_key")]; |
116
|
|
|
//$this->value["paid_key"] = $db->f("paid"); |
|
|
|
|
117
|
|
|
|
118
|
5 |
|
$this->value["state_account_id"] = $db->f("state_account_id"); |
119
|
5 |
|
$this->value["voucher_id"] = $db->f("voucher_id"); |
120
|
5 |
|
return true; |
121
|
|
|
} |
122
|
|
|
|
123
|
1 |
|
function loadItem($id = 0) |
124
|
|
|
{ |
125
|
1 |
|
$this->item = new ProcurementItem($this, (int)$id); |
|
|
|
|
126
|
1 |
|
} |
127
|
|
|
|
128
|
6 |
|
function update($input) |
129
|
|
|
{ |
130
|
6 |
|
if (!is_array($input)) { |
131
|
|
|
throw new Exception('Procurement->update(): $input er ikke et array'); |
132
|
|
|
} |
133
|
6 |
|
$db = new DB_sql; |
134
|
|
|
|
135
|
6 |
|
$input = safeToDb($input); |
136
|
6 |
|
$validator = new Intraface_Validator($this->error); |
137
|
|
|
|
138
|
6 |
|
if (!isset($input['dk_invoice_date'])) { |
139
|
1 |
|
$input['dk_invoice_date'] = ''; |
140
|
1 |
|
} |
141
|
6 |
|
$validator->isDate($input["dk_invoice_date"], "Fakturadato er ikke en gyldig dato"); |
142
|
6 |
|
$date = new Intraface_Date($input["dk_invoice_date"]); |
143
|
6 |
|
if ($date->convert2db()) { |
144
|
5 |
|
$input["invoice_date"] = $date->get(); |
145
|
5 |
|
} else { |
146
|
1 |
|
$input["invoice_date"] = ''; |
147
|
|
|
} |
148
|
|
|
|
149
|
6 |
|
if (!isset($input['dk_delivery_date'])) { |
150
|
6 |
|
$input['dk_delivery_date'] = ''; |
151
|
6 |
|
} |
152
|
6 |
|
$validator->isDate($input["dk_delivery_date"], "Leveringsdato er ikke en gyldig dato", "allow_empty"); |
153
|
6 |
|
$date = new Intraface_Date($input["dk_delivery_date"]); |
154
|
6 |
|
if ($date->convert2db()) { |
155
|
|
|
$input["delivery_date"] = $date->get(); |
156
|
|
|
} else { |
157
|
6 |
|
$input['delivery_date'] = $input['invoice_date']; |
158
|
|
|
} |
159
|
|
|
|
160
|
6 |
|
if (!isset($input['dk_payment_date'])) { |
161
|
1 |
|
$input['dk_payment_date'] = ''; |
162
|
1 |
|
} |
163
|
6 |
|
$validator->isDate($input["dk_payment_date"], "Betalingsdato er ikke en gyldig dato", "allow_empty"); |
164
|
6 |
|
$date = new Intraface_Date($input["dk_payment_date"]); |
165
|
6 |
|
if ($date->convert2db()) { |
166
|
5 |
|
$input["payment_date"] = $date->get(); |
167
|
5 |
|
} else { |
168
|
1 |
|
$input['payment_date'] = $input['delivery_date']; |
169
|
|
|
} |
170
|
|
|
|
171
|
6 |
|
if (empty($input['number'])) { |
172
|
1 |
|
$input['number'] = 0; |
173
|
1 |
|
} |
174
|
6 |
|
$validator->isNumeric($input["number"], "Nummer er ikke et gyldigt nummer", "greater_than_zero"); |
175
|
6 |
|
$db->query("SELECT id FROM procurement WHERE id != ".$this->id." AND intranet_id = ".$this->kernel->intranet->get("id")." AND number = ".$input["number"]); |
176
|
6 |
|
if ($db->nextRecord()) { |
177
|
|
|
$this->error->set("Nummeret er allerede benyttet"); |
178
|
|
|
} |
179
|
|
|
|
180
|
6 |
|
if (!isset($input['vendor'])) { |
181
|
6 |
|
$input['vendor'] = ''; |
182
|
6 |
|
} |
183
|
6 |
|
$validator->isString($input["vendor"], "Fejl i leverandør", "", "allow_empty"); |
184
|
|
|
|
185
|
6 |
|
if (!isset($input['description'])) { |
186
|
1 |
|
$input['description'] = ''; |
187
|
1 |
|
} |
188
|
6 |
|
$validator->isString($input["description"], "Fejl i beskrivelse", "", ""); |
189
|
|
|
|
190
|
6 |
|
if (!isset($input['from_region_key'])) { |
191
|
6 |
|
$input['from_region_key'] = 0; |
192
|
6 |
|
} |
193
|
6 |
|
$region_types = $this->getRegionTypes(); |
194
|
6 |
|
if (!isset($region_types[$input["from_region_key"]])) { |
195
|
|
|
$this->error->set("Ugyldig købsregion"); |
196
|
|
|
} |
197
|
|
|
|
198
|
6 |
|
if (!isset($input['dk_price_items'])) { |
199
|
1 |
|
$input['dk_price_items'] = 0; |
200
|
1 |
|
} |
201
|
6 |
|
$validator->isDouble($input["dk_price_items"], "Varepris er ikke et gyldigt beløb", 'zero_or_greater'); |
202
|
6 |
|
$amount = new Intraface_Amount($input["dk_price_items"]); |
203
|
6 |
|
if ($amount->convert2db()) { |
204
|
6 |
|
$input["price_items"] = $amount->get(); |
205
|
6 |
|
} |
206
|
|
|
|
207
|
6 |
|
if (!isset($input['dk_price_shipment_etc'])) { |
208
|
1 |
|
$input['dk_price_shipment_etc'] = 0; |
209
|
1 |
|
} |
210
|
6 |
|
$validator->isDouble($input["dk_price_shipment_etc"], "Pris for forsendelse og andet er ikke et gyldigt beløb", 'zero_or_greater'); |
211
|
6 |
|
$amount = new Intraface_Amount($input["dk_price_shipment_etc"]); |
212
|
6 |
|
if ($amount->convert2db()) { |
213
|
6 |
|
$input["price_shipment_etc"] = $amount->get(); |
214
|
6 |
|
} |
215
|
|
|
|
216
|
6 |
|
if (!isset($input['dk_vat'])) { |
217
|
1 |
|
$input['dk_vat'] = 0; |
218
|
1 |
|
} |
219
|
6 |
|
$validator->isDouble($input["dk_vat"], "Moms er ikke et gyldigt beløb", 'zero_or_greater'); |
220
|
6 |
|
$amount = new Intraface_Amount($input["dk_vat"]); |
221
|
6 |
|
if ($amount->convert2db()) { |
222
|
6 |
|
$input["vat"] = $amount->get(); |
223
|
6 |
|
} |
224
|
|
|
|
225
|
6 |
|
if ($this->error->isError()) { |
226
|
1 |
|
return false; |
227
|
|
|
} |
228
|
|
|
|
229
|
5 |
|
$sql = "user_id = ".$this->kernel->user->get("id").", |
230
|
|
|
date_changed = NOW(), |
231
|
5 |
|
invoice_date = \"".$input["invoice_date"]."\", |
232
|
5 |
|
delivery_date = \"".$input["delivery_date"]."\", |
233
|
5 |
|
payment_date = \"".$input["payment_date"]."\", |
234
|
5 |
|
number = ".$input["number"].", |
235
|
5 |
|
vendor = \"".$input["vendor"]."\", |
236
|
5 |
|
description = \"".$input["description"]."\", |
237
|
5 |
|
from_region_key = ".$input["from_region_key"].", |
238
|
5 |
|
price_items = ".$input["price_items"].", |
239
|
5 |
|
price_shipment_etc = ".$input["price_shipment_etc"].", |
240
|
5 |
|
vat = ".$input["vat"].""; |
241
|
|
|
|
242
|
5 |
View Code Duplication |
if ($this->id != 0) { |
243
|
|
|
$db->query("UPDATE procurement SET ".$sql." WHERE id = ".$this->id." AND intranet_id = ".$this->kernel->intranet->get("id")); |
244
|
|
|
} else { |
245
|
5 |
|
$db->query("INSERT INTO procurement SET intranet_id = ".$this->kernel->intranet->get("id").", date_created = NOW(), active = 1, ".$sql); |
246
|
5 |
|
$this->id = $db->insertedId(); |
247
|
|
|
} |
248
|
5 |
|
$this->load(); |
249
|
|
|
|
250
|
5 |
|
return true; |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
function setStatus($status) |
254
|
|
|
{ |
255
|
|
|
$status_key = array_search($status, $this->getStatusTypes()); |
256
|
|
|
if ($status_key === false) { |
257
|
|
|
throw new Exception("Ugyldigt status: ".$status); |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
switch ($status) { |
261
|
|
|
case "ordered": |
262
|
|
|
$sql = ""; |
263
|
|
|
break; |
264
|
|
|
|
265
|
|
|
case "recieved": |
266
|
|
|
$sql = ", date_recieved = NOW()"; |
267
|
|
|
break; |
268
|
|
|
|
269
|
|
|
case "canceled": |
270
|
|
|
$sql = ", date_canceled = NOW()"; |
271
|
|
|
break; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
$db = new DB_sql; |
275
|
|
|
$db->query("UPDATE procurement SET status_key = ".$status_key." ".$sql." WHERE id = ".$this->id." AND intranet_id = ".$this->kernel->intranet->get("id")); |
|
|
|
|
276
|
|
|
|
277
|
|
|
$this->load(); |
278
|
|
|
|
279
|
|
|
return true; |
280
|
|
|
} |
281
|
|
|
|
282
|
3 |
|
function setPaid($dk_paid_date) |
283
|
|
|
{ |
284
|
3 |
|
if ($this->get('id') == 0) { |
285
|
|
|
return false; |
286
|
|
|
} |
287
|
|
|
|
288
|
3 |
|
if ($this->get('paid_date') != '0000-00-00') { |
289
|
|
|
$this->error->set('Betaling er allerede registreret'); |
290
|
|
|
return false; |
291
|
|
|
} |
292
|
|
|
|
293
|
3 |
|
$validator = new Intraface_Validator($this->error); |
294
|
|
|
|
295
|
3 |
|
$validator->isDate($dk_paid_date, "Betalt dato er ikke en gyldig dato"); |
296
|
3 |
|
$date = new Intraface_Date($dk_paid_date); |
297
|
3 |
|
if ($date->convert2db()) { |
298
|
3 |
|
$paid_date = $date->get(); |
299
|
3 |
|
} |
300
|
|
|
|
301
|
3 |
|
$db = new DB_sql; |
302
|
|
|
|
303
|
3 |
|
$db->query("UPDATE procurement SET paid_date = \"".$paid_date."\" WHERE intranet_id = ".$this->kernel->intranet->get('id')." AND id = ".$this->get('id')); |
|
|
|
|
304
|
3 |
|
$this->load(); |
305
|
|
|
|
306
|
3 |
|
return true; |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
function setContact($contact) |
310
|
|
|
{ |
311
|
|
|
if ($this->id == 0) { |
312
|
|
|
return 0; |
313
|
|
|
} |
314
|
|
|
|
315
|
|
|
if (!is_object($contact)) { |
316
|
|
|
throw new Exception('The parameter to set Contact need to be a contact object!'); |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
if ($contact->get('id') == 0) { |
320
|
|
|
throw new Exception('The given contact is not valid!'); |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
$db = new DB_sql; |
324
|
|
|
$db->query("UPDATE procurement SET contact_id = ".$contact->get('id').", date_changed = NOW() WHERE id = ".$this->id); |
325
|
|
|
$this->load(); |
326
|
|
|
return true; |
327
|
|
|
} |
328
|
|
|
|
329
|
|
|
function getLatest($product_id, $up_to_quantity = 0) |
330
|
|
|
{ |
331
|
|
|
$sum_quantity = 0; |
332
|
|
|
$list = array(); |
333
|
|
|
$i = 0; |
334
|
|
|
$over_quantity = 0; |
335
|
|
|
|
336
|
|
|
$db = new DB_sql; |
337
|
|
|
$db->query("SELECT DISTINCT(procurement.id) FROM procurement |
338
|
|
|
INNER JOIN procurement_item ON procurement.id = procurement_item.procurement_id |
339
|
|
|
WHERE procurement_item.active = 1 AND procurement.active = 1 |
340
|
|
|
AND procurement_item.intranet_id = ".$this->kernel->intranet->get("id")." AND procurement.intranet_id = ".$this->kernel->intranet->get("id")." |
341
|
|
|
AND procurement_item.product_id = ".$product_id." AND procurement.status_key = 1 ORDER BY procurement.invoice_date DESC, procurement_item.id ASC"); |
342
|
|
|
|
343
|
|
|
while ($db->nextRecord() && $over_quantity < 3) { // $over_quantity < 3 angiver hvor mange gange mere end det antal som er p� lageret man skal k�rer over. |
344
|
|
|
|
345
|
|
|
$procurement = new Procurement($this->kernel, $db->f('id')); |
346
|
|
|
$procurement->loadItem(); |
347
|
|
|
$items = $procurement->item->getList(); |
348
|
|
|
|
349
|
|
|
foreach ($items as $item) { |
350
|
|
|
if ($item['product_id'] == $product_id) { |
351
|
|
|
$list[$i] = $item; |
352
|
|
|
$list[$i]['dk_invoice_date'] = $procurement->get('dk_invoice_date'); |
353
|
|
|
$sum_quantity += $item['quantity']; |
354
|
|
|
$list[$i]['sum_quantity'] = $sum_quantity; |
355
|
|
|
$i++; |
356
|
|
|
} |
357
|
|
|
} |
358
|
|
|
if ($sum_quantity > $up_to_quantity && $up_to_quantity != 0) { |
359
|
|
|
$over_quantity++; |
360
|
|
|
} |
361
|
|
|
} |
362
|
|
|
|
363
|
|
|
return $list; |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
/** |
367
|
|
|
* State procurement |
368
|
|
|
* |
369
|
|
|
* @param object year year object |
370
|
|
|
* @param integer voucher_number |
371
|
|
|
* |
372
|
|
|
* @return boolean |
373
|
|
|
*/ |
374
|
2 |
|
function state($year, $voucher_number, $voucher_date, $debet_accounts, $credit_account_id, $translation) |
375
|
|
|
{ |
376
|
2 |
|
if (!is_object($year)) { |
377
|
|
|
throw new Exception('First parameter to state needs to be a Year object!'); |
378
|
|
|
} |
379
|
|
|
|
380
|
2 |
|
if (!is_object($translation)) { |
381
|
|
|
throw new Exception('Sixth parameter to state needs to be a Translation object!'); |
382
|
|
|
} |
383
|
|
|
|
384
|
2 |
|
if (!$this->readyForState($year)) { |
385
|
|
|
$this->error->set('Ikke klar til at blive bogført'); |
386
|
|
|
return false; |
387
|
|
|
} |
388
|
|
|
|
389
|
2 |
|
if (!$this->checkStateDebetAccounts($year, $debet_accounts, 'skip_amount_check')) { |
390
|
|
|
return false; |
391
|
|
|
} |
392
|
|
|
|
393
|
2 |
|
$validator = new Intraface_Validator($this->error); |
394
|
2 |
|
if ($validator->isDate($voucher_date, "Ugyldig dato")) { |
395
|
2 |
|
$voucher_date_object = new Intraface_Date($voucher_date); |
396
|
2 |
|
$voucher_date_object->convert2db(); |
397
|
2 |
|
} |
398
|
|
|
|
399
|
2 |
|
if (!$year->isDateInYear($voucher_date_object->get())) { |
|
|
|
|
400
|
|
|
$this->error->set('Datoen er ikke i det år, der er sat i regnskabsmodulet.'); |
401
|
|
|
} |
402
|
|
|
|
403
|
2 |
|
$credit_account = Account::factory($year, $credit_account_id); |
|
|
|
|
404
|
2 |
|
if (!$credit_account->validForState()) { |
405
|
|
|
$this->error->set('Ugyldig konto hvor indkøbet er betalt fra'); |
406
|
|
|
return false; |
407
|
|
|
} |
408
|
|
|
|
409
|
2 |
|
$validator->isNumeric($voucher_number, 'Ugyldigt bilagsnummer', 'greater_than_zero'); |
410
|
|
|
|
411
|
2 |
|
if ($this->error->isError()) { |
412
|
|
|
return false; |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
|
416
|
2 |
|
$text = $translation->get('procurement').'# ' . $this->get('number') . ': ' . $this->get('description'); |
417
|
2 |
|
require_once 'Intraface/modules/accounting/Voucher.php'; |
418
|
2 |
|
$voucher = Voucher::factory($year, $voucher_number); |
|
|
|
|
419
|
2 |
|
$voucher->save(array( |
420
|
2 |
|
'voucher_number' => $voucher_number, |
421
|
2 |
|
'date' => $voucher_date, |
422
|
|
|
'text' => $text |
423
|
2 |
|
)); |
424
|
|
|
|
425
|
2 |
|
$credit_total = 0; |
426
|
2 |
|
foreach ($debet_accounts as $key => $line) { |
427
|
2 |
|
$debet_account = Account::factory($year, $line['state_account_id']); |
|
|
|
|
428
|
|
|
|
429
|
2 |
|
$amount = new Intraface_Amount($line['amount']); |
430
|
2 |
|
$amount->convert2db(); |
431
|
2 |
|
$amount = $amount->get(); |
432
|
2 |
|
$credit_total += $amount; |
433
|
|
|
|
434
|
2 |
|
if (!empty($line['text'])) { |
435
|
1 |
|
$line_text = $text. ' - ' . $line['text']; |
436
|
1 |
|
} else { |
437
|
2 |
|
$line_text = $text; |
438
|
|
|
} |
439
|
|
|
|
440
|
|
|
// if the amount is stated on an account with vat we add the vat on the amount! |
441
|
2 |
|
if ($debet_account->get('vat') == 'in') { |
442
|
2 |
|
$amount += round($amount/100*$debet_account->get('vat_percent'), 2); |
443
|
2 |
|
} |
444
|
|
|
|
445
|
|
|
$input_values = array( |
446
|
2 |
|
'voucher_number' => $voucher->get('number'), |
447
|
2 |
|
'date' => $voucher_date, |
448
|
2 |
|
'amount' => number_format($amount, 2, ',', ''), |
449
|
2 |
|
'debet_account_number' => $debet_account->get('number'), |
450
|
2 |
|
'credit_account_number' => $credit_account->get('number'), |
451
|
2 |
|
'vat_off' => 0, |
452
|
|
|
'text' => $line_text |
453
|
2 |
|
); |
454
|
|
|
|
455
|
2 |
|
if (!$voucher->saveInDaybook($input_values, true)) { |
456
|
|
|
$this->error->merge($voucher->error->getMessage()); |
457
|
|
|
} |
458
|
2 |
|
} |
459
|
|
|
|
460
|
2 |
|
require_once 'Intraface/modules/accounting/VoucherFile.php'; |
461
|
2 |
|
$voucher_file = new VoucherFile($voucher); |
462
|
2 |
View Code Duplication |
if (!$voucher_file->save(array('description' => $text, 'belong_to' => 'procurement', 'belong_to_id' => $this->get('id')))) { |
463
|
|
|
$this->error->merge($voucher_file->error->getMessage()); |
464
|
|
|
$this->error->set('Filen blev ikke overflyttet'); |
465
|
|
|
} |
466
|
|
|
|
467
|
2 |
|
if ($this->error->isError()) { |
468
|
|
|
$this->error->set('Der er opstået en fejl under bogføringen af indkøbet. Det kan betyde at dele af den er bogført, men ikke det hele. Du bedes manuelt tjekke bilaget'); |
469
|
|
|
// I am not quite sure if the procurement should be set as stated, but it can give trouble to state it again, if some of it was stated... |
470
|
|
|
$this->setStated($voucher->get('id'), $voucher_date); |
471
|
|
|
return false; |
472
|
|
|
} |
473
|
|
|
|
474
|
2 |
|
$this->setStated($voucher->get('id'), $voucher_date); |
475
|
2 |
|
$this->load(); |
476
|
2 |
|
return true; |
477
|
|
|
} |
478
|
|
|
|
479
|
2 |
|
function setStated($voucher_number, $voucher_date) |
480
|
|
|
{ |
481
|
2 |
|
$db = new DB_Sql; |
482
|
|
|
|
483
|
2 |
|
$validator = new Intraface_Validator($this->error); |
484
|
2 |
|
if ($validator->isDate($voucher_date, "Ugyldig dato")) { |
485
|
2 |
|
$voucher_date = new Intraface_Date($voucher_date); |
486
|
2 |
|
$voucher_date->convert2db(); |
487
|
2 |
|
} |
488
|
|
|
|
489
|
2 |
|
$db->query("UPDATE procurement SET date_stated = '".$voucher_date->get()."', voucher_id = ".intval($voucher_number)." WHERE id = " . $this->id . " AND intranet_id = " . $this->kernel->intranet->get('id')); |
490
|
2 |
|
return 1; |
491
|
|
|
} |
492
|
|
|
|
493
|
4 |
|
function isStated() |
494
|
|
|
{ |
495
|
4 |
|
if ($this->get("date_stated") > '0000-00-00') { |
496
|
1 |
|
return true; |
497
|
|
|
} |
498
|
4 |
|
return false; |
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
/** |
502
|
|
|
* returns whether the procurement is ready for state |
503
|
|
|
* |
504
|
|
|
* @param object year accounting year |
505
|
|
|
* |
506
|
|
|
* @return boolean true or false |
507
|
|
|
*/ |
508
|
4 |
|
function readyForState($year) |
509
|
|
|
{ |
510
|
4 |
|
if (!is_object($year)) { |
511
|
|
|
throw new Exception('First parameter to readyForState needs to be a Year object!'); |
512
|
|
|
} |
513
|
|
|
|
514
|
4 |
|
if (!$year->readyForState($this->get('paid_date'))) { |
515
|
1 |
|
$this->error->set('Regnskabåret er ikke klar til bogføring.'); |
516
|
1 |
|
return false; |
517
|
|
|
} |
518
|
|
|
|
519
|
3 |
|
if ($this->get('id') == 0) { |
520
|
|
|
$this->error->set('Indkøbet er ikke gemt'); |
521
|
|
|
return false; |
522
|
|
|
} |
523
|
|
|
|
524
|
3 |
|
if ($this->get("paid_date") == "0000-00-00") { |
525
|
|
|
$this->error->set('Indkøbet skal være betalt før det kan bogføres.'); |
526
|
|
|
} |
527
|
|
|
|
528
|
3 |
|
if ($this->isStated()) { |
529
|
1 |
|
$this->error->set('Indkøbet er allerede bogført'); |
530
|
1 |
|
return false; |
531
|
|
|
} |
532
|
|
|
|
533
|
3 |
|
if ($this->error->isError()) { |
534
|
|
|
return false; |
535
|
|
|
} |
536
|
3 |
|
return true; |
537
|
|
|
} |
538
|
|
|
|
539
|
|
|
/** |
540
|
|
|
* Checks whether the debet accounts are valid |
541
|
|
|
* |
542
|
|
|
* @param object $year Accounting year object |
543
|
|
|
* @param array $debet_accounts Array with debet accounts |
544
|
|
|
* @param string $skip_amount_check Valid options: do_amount_check or skip_amount_check |
545
|
|
|
* |
546
|
|
|
* @return boolean |
547
|
|
|
*/ |
548
|
2 |
|
public function checkStateDebetAccounts($year, $debet_accounts, $skip_amount_check = 'do_amount_check') |
549
|
|
|
{ |
550
|
2 |
|
if (!is_object($year)) { |
551
|
|
|
throw new Exception('First parameter to checkStateDebetAccounts needs to be a Year object!'); |
552
|
|
|
} |
553
|
|
|
|
554
|
2 |
|
if (!is_array($debet_accounts)) { |
555
|
|
|
throw new Exception('Second parameter to checkStateDebetAccounts needs to be an array'); |
556
|
|
|
} |
557
|
|
|
|
558
|
2 |
|
if (!in_array($skip_amount_check, array('do_amount_check', 'skip_amount_check'))) { |
559
|
|
|
throw new Exception('Third parameter to checkStateDebetAccounts needs to be either do_amount_check or skip_amount_check'); |
560
|
|
|
} |
561
|
|
|
|
562
|
2 |
|
if (empty($debet_accounts)) { |
563
|
|
|
$this->error->set('you have not set any debet accounts'); |
564
|
|
|
return false; |
565
|
|
|
} |
566
|
|
|
|
567
|
2 |
|
$validator = new Intraface_Validator($this->error); |
568
|
|
|
|
569
|
2 |
|
$total = 0; |
570
|
2 |
|
$vat = 0; |
571
|
2 |
View Code Duplication |
foreach ($debet_accounts as $key => $debet_account) { |
572
|
2 |
|
if ($validator->isNumeric($debet_account['amount'], 'Ugyldig beløb i linje ' . ($key + 1) . ' "' . $debet_account['text'] . '"', 'greater_than_zero')) { |
573
|
2 |
|
$amount = new Intraface_Amount($debet_account['amount']); |
574
|
2 |
|
$amount->convert2db(); |
575
|
2 |
|
$total += $amount->get(); |
576
|
|
|
|
577
|
2 |
|
$validator->isString($debet_account['text'], 'Ugyldig tekst i linje ' . ($key + 1) . ' "' . $debet_account['text'] . '"', '', 'allow_empty'); |
578
|
|
|
|
579
|
2 |
|
if (empty($debet_account['state_account_id'])) { |
580
|
|
|
$this->error->set('Linje ' . ($key + 1) . ' "' . $debet_account['text'] . '" ved ikke hvor den skal bogføres'); |
581
|
|
|
} else { |
582
|
2 |
|
require_once 'Intraface/modules/accounting/Account.php'; |
583
|
2 |
|
$account = Account::factory($year, $debet_account['state_account_id']); |
|
|
|
|
584
|
|
|
|
585
|
|
|
// @todo check this. I changed it to make sure that we are able to state varekøb til videresalg |
586
|
|
|
// || $account->get('type') != 'operating' |
|
|
|
|
587
|
2 |
|
if ($account->get('id') == 0) { |
588
|
|
|
$this->error->set('Ugyldig konto for bogføring af linje ' . ($key + 1) . ' "' . $debet_account['text'] . '"'); |
589
|
2 |
|
} elseif ($account->get('vat') == 'in') { |
590
|
2 |
|
$vat += $amount->get() / 100 * $account->get('vat_percent'); |
591
|
2 |
|
} |
592
|
|
|
} |
593
|
2 |
|
} |
594
|
2 |
|
} |
595
|
|
|
|
596
|
2 |
|
if ($this->error->isError()) { |
597
|
|
|
return false; |
598
|
|
|
} |
599
|
|
|
|
600
|
2 |
|
if ($skip_amount_check == 'do_amount_check') { |
601
|
|
View Code Duplication |
if (round($total + $this->get('vat'), 2) != $this->get('total_price')) { |
602
|
|
|
$delta = $this->get('total_price') - ($total + $this->get('vat')); |
603
|
|
|
$this->error->set('Det samlede beløb ('.number_format($total + $this->get('vat'), 2, ',', '.').') til bogføring stemmer ikke overens med det samlede beløb på indkøbet ('.number_format($this->get('total_price'), 2, ',', '.').'). Der er en forskel på '.number_format($delta, 2, ',', '.').'. Har du fået alle varer på indkøbet med?'); |
604
|
|
|
} |
605
|
|
|
|
606
|
|
View Code Duplication |
if (round($vat, 2) != $this->get('vat')) { |
607
|
|
|
$expected = number_format($this->get('vat') * 4, 2, ',', '.'); |
608
|
|
|
$this->error->set('Momsen af de beløb du bogfører på konti med moms stemmer ikke overens med momsen på det samlede indkøb (vi forventede '.number_format($vat, 2, ',', '.').' i moms og det samlede beløb burde have været ' . $expected . '). Har du fået alle varer med? Har du husket at skrive beløbet uden moms for varerne?'); |
609
|
|
|
} |
610
|
|
|
} |
611
|
|
|
|
612
|
2 |
|
if ($this->error->isError()) { |
613
|
|
|
return false; |
614
|
|
|
} |
615
|
2 |
|
return true; |
616
|
|
|
} |
617
|
|
|
|
618
|
|
|
/** |
619
|
|
|
* Propose a solution if checkStateDebetAccounts() fails |
620
|
|
|
* |
621
|
|
|
* @param array $debet_accounts Array with debet accounts |
622
|
|
|
* |
623
|
|
|
* @return boolean |
624
|
|
|
*/ |
625
|
|
|
public function proposeSolution(array $debet_accounts) |
626
|
|
|
{ |
627
|
|
|
if (empty($debet_accounts)) { |
628
|
|
|
$this->error->set('you have not set any debet accounts'); |
629
|
|
|
return false; |
630
|
|
|
} |
631
|
|
|
|
632
|
|
|
$validator = new Intraface_Validator($this->error); |
633
|
|
|
|
634
|
|
|
$total = 0; |
635
|
|
|
$vat = 0; |
636
|
|
View Code Duplication |
foreach ($debet_accounts as $key => $debet_account) { |
637
|
|
|
if ($validator->isNumeric($debet_account['amount'], 'Ugyldig beløb i linje ' . ($key + 1) . ' "' . $debet_account['text'] . '"', 'greater_than_zero')) { |
638
|
|
|
$amount = new Intraface_Amount($debet_account['amount']); |
639
|
|
|
$amount->convert2db(); |
640
|
|
|
$total += $amount->get(); |
641
|
|
|
|
642
|
|
|
$validator->isString($debet_account['text'], 'Ugyldig tekst i linje ' . ($key + 1) . ' "' . $debet_account['text'] . '"', '', 'allow_empty'); |
643
|
|
|
|
644
|
|
|
if (empty($debet_account['state_account_id'])) { |
645
|
|
|
$this->error->set('Linje ' . ($key + 1) . ' "' . $debet_account['text'] . '" ved ikke hvor den skal bogføres'); |
646
|
|
|
} else { |
647
|
|
|
require_once 'Intraface/modules/accounting/Account.php'; |
648
|
|
|
$account = Account::factory($year, $debet_account['state_account_id']); |
|
|
|
|
649
|
|
|
|
650
|
|
|
// @todo check this. I changed it to make sure that we are able to state varekøb til videresalg |
651
|
|
|
// || $account->get('type') != 'operating' |
|
|
|
|
652
|
|
|
if ($account->get('id') == 0) { |
653
|
|
|
$this->error->set('Ugyldig konto for bogføring af linje ' . ($key + 1) . ' "' . $debet_account['text'] . '"'); |
654
|
|
|
} elseif ($account->get('vat') == 'in') { |
655
|
|
|
$vat += $amount->get() / 100 * $account->get('vat_percent'); |
656
|
|
|
} |
657
|
|
|
} |
658
|
|
|
} |
659
|
|
|
} |
660
|
|
|
|
661
|
|
|
if ($this->error->isError()) { |
662
|
|
|
return false; |
663
|
|
|
} |
664
|
|
|
|
665
|
|
View Code Duplication |
if (round($total + $this->get('vat'), 2) != $this->get('total_price')) { |
666
|
|
|
$delta = $this->get('total_price') - ($total + $this->get('vat')); |
667
|
|
|
$this->error->set('Det samlede beløb ('.number_format($total + $this->get('vat'), 2, ',', '.').') til bogføring stemmer ikke overens med det samlede beløb på indkøbet ('.number_format($this->get('total_price'), 2, ',', '.').'). Der er en forskel på '.number_format($delta, 2, ',', '.').'. Har du fået alle varer på indkøbet med?'); |
668
|
|
|
} |
669
|
|
|
|
670
|
|
View Code Duplication |
if (round($vat, 2) != $this->get('vat')) { |
671
|
|
|
$expected_vat = number_format($vat, 2, ',', '.'); |
672
|
|
|
$expected_value = number_format($this->get('vat') * 4, 2, ',', '.'); |
673
|
|
|
$this->error->set('Momsen af de beløb du bogfører på konti med moms stemmer ikke overens med momsen på det samlede indkøb (vi forventede ' . $expected_vat . ' i moms og det samlede beløb burde have været ' . $expected_value . '). Har du fået alle varer med? Har du husket at skrive beløbet uden moms for varerne?'); |
674
|
|
|
} |
675
|
|
|
|
676
|
|
|
if ($this->error->isError()) { |
677
|
|
|
return false; |
678
|
|
|
} |
679
|
|
|
return true; |
680
|
|
|
} |
681
|
|
|
|
682
|
|
|
/** |
683
|
|
|
* returns possible status types |
684
|
|
|
* |
685
|
|
|
* @todo: duplicate in Procurement class |
686
|
|
|
* |
687
|
|
|
* @return array status types |
688
|
|
|
*/ |
689
|
5 |
|
private function getStatusTypes() |
690
|
|
|
{ |
691
|
|
|
return array( |
692
|
5 |
|
0 => 'ordered', |
693
|
5 |
|
1 => 'recieved', |
694
|
|
|
2 => 'canceled' |
695
|
5 |
|
); |
696
|
|
|
} |
697
|
|
|
|
698
|
|
|
/** |
699
|
|
|
* returns the possible regions where procurement is bought |
700
|
|
|
* @todo: duplicate in Procurement class |
701
|
|
|
* |
702
|
|
|
* @return array possible regions |
703
|
|
|
*/ |
704
|
6 |
|
public function getRegionTypes() |
705
|
|
|
{ |
706
|
|
|
return array( |
707
|
6 |
|
0 => 'denmark', |
708
|
6 |
|
1 => 'eu', |
709
|
6 |
|
2 => 'eu_vat_registered', |
710
|
|
|
3 => 'outside_eu' |
711
|
6 |
|
); |
712
|
|
|
} |
713
|
|
|
|
714
|
|
|
function getItems() |
715
|
|
|
{ |
716
|
|
|
$this->loadItem(); |
717
|
|
|
$items = $this->item->getList(); |
|
|
|
|
718
|
|
|
return $items = $this->item->getList(); |
|
|
|
|
719
|
|
|
} |
720
|
|
|
} |
721
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.