Line data Source code
1 : /********************************************************************\
2 : * gncEmployee.c -- the Core Employee Interface *
3 : * *
4 : * This program is free software; you can redistribute it and/or *
5 : * modify it under the terms of the GNU General Public License as *
6 : * published by the Free Software Foundation; either version 2 of *
7 : * the License, or (at your option) any later version. *
8 : * *
9 : * This program is distributed in the hope that it will be useful, *
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 : * GNU General Public License for more details. *
13 : * *
14 : * You should have received a copy of the GNU General Public License*
15 : * along with this program; if not, contact: *
16 : * *
17 : * Free Software Foundation Voice: +1-617-542-5942 *
18 : * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
19 : * Boston, MA 02110-1301, USA gnu@gnu.org *
20 : * *
21 : \********************************************************************/
22 :
23 : /*
24 : * Copyright (C) 2001,2002 Derek Atkins
25 : * Copyright (C) 2003 Linas Vepstas <linas@linas.org>
26 : * Author: Derek Atkins <warlord@MIT.EDU>
27 : */
28 :
29 : #include <config.h>
30 :
31 : #include <glib.h>
32 : #include <string.h>
33 : #include <qofinstance-p.h>
34 :
35 : #include "Account.h"
36 : #include "gnc-commodity.h"
37 : #include "gncAddressP.h"
38 : #include "gncEmployee.h"
39 : #include "gncEmployeeP.h"
40 : #include "gnc-lot.h"
41 : #include "gncOwner.h"
42 :
43 : static gint empl_qof_event_handler_id = 0;
44 : static void empl_handle_qof_events (QofInstance *entity, QofEventId event_type,
45 : gpointer user_data, gpointer event_data);
46 :
47 : struct _gncEmployee
48 : {
49 : QofInstance inst;
50 : const char * id;
51 : const char * username;
52 : GncAddress * addr;
53 : gnc_commodity * currency;
54 : gboolean active;
55 : gnc_numeric * balance;
56 :
57 : const char * language;
58 : const char * acl;
59 : gnc_numeric workday;
60 : gnc_numeric rate;
61 :
62 : Account * ccard_acc;
63 : };
64 :
65 : struct _gncEmployeeClass
66 : {
67 : QofInstanceClass parent_class;
68 : };
69 :
70 : static QofLogModule log_module = GNC_MOD_BUSINESS;
71 :
72 : #define _GNC_MOD_NAME GNC_ID_EMPLOYEE
73 :
74 : static inline void mark_employee (GncEmployee *employee);
75 55 : void mark_employee (GncEmployee *employee)
76 : {
77 55 : qof_instance_set_dirty(&employee->inst);
78 55 : qof_event_gen (&employee->inst, QOF_EVENT_MODIFY, NULL);
79 55 : }
80 :
81 : /* ============================================================== */
82 :
83 : enum
84 : {
85 : PROP_0,
86 : PROP_USERNAME, /* Table */
87 : PROP_ID, /* Table */
88 : PROP_LANGUAGE, /* Table */
89 : PROP_ACL, /* Table */
90 : PROP_ACTIVE, /* Table */
91 : PROP_CURRENCY, /* Table */
92 : PROP_CCARD, /* Table */
93 : PROP_WORKDAY, /* Table (numeric) */
94 : PROP_RATE, /* Table (numeric) */
95 : PROP_ADDRESS, /* Table, 8 fields */
96 : PROP_PDF_DIRNAME, /* KVP */
97 : PROP_LAST_POSTED, /* KVP */
98 : PROP_PAYMENT_LAST_ACCT, /* KVP */
99 : };
100 :
101 : /* GObject Initialization */
102 117 : G_DEFINE_TYPE(GncEmployee, gnc_employee, QOF_TYPE_INSTANCE)
103 :
104 : static void
105 24 : gnc_employee_init(GncEmployee* emp)
106 : {
107 24 : }
108 :
109 : static void
110 12 : gnc_employee_dispose(GObject *empp)
111 : {
112 12 : G_OBJECT_CLASS(gnc_employee_parent_class)->dispose(empp);
113 12 : }
114 :
115 : static void
116 12 : gnc_employee_finalize(GObject* empp)
117 : {
118 12 : G_OBJECT_CLASS(gnc_employee_parent_class)->finalize(empp);
119 12 : }
120 :
121 : /* Note that g_value_set_object() refs the object, as does
122 : * g_object_get(). But g_object_get() only unrefs once when it disgorges
123 : * the object, leaving an unbalanced ref, which leaks. So instead of
124 : * using g_value_set_object(), use g_value_take_object() which doesn't
125 : * ref the object when used in get_property().
126 : */
127 : static void
128 13 : gnc_employee_get_property (GObject *object,
129 : guint prop_id,
130 : GValue *value,
131 : GParamSpec *pspec)
132 : {
133 : GncEmployee *emp;
134 13 : g_return_if_fail(GNC_IS_EMPLOYEE(object));
135 13 : emp = GNC_EMPLOYEE(object);
136 13 : switch (prop_id)
137 : {
138 1 : case PROP_USERNAME:
139 1 : g_value_set_string(value, emp->username);
140 1 : break;
141 1 : case PROP_ID:
142 1 : g_value_set_string(value, emp->id);
143 1 : break;
144 1 : case PROP_ACTIVE:
145 1 : g_value_set_boolean(value, emp->active);
146 1 : break;
147 1 : case PROP_LANGUAGE:
148 1 : g_value_set_string(value, emp->language);
149 1 : break;
150 1 : case PROP_CURRENCY:
151 1 : g_value_take_object(value, emp->currency);
152 1 : break;
153 1 : case PROP_ACL:
154 1 : g_value_set_string(value, emp->acl);
155 1 : break;
156 1 : case PROP_ADDRESS:
157 1 : g_value_take_object(value, emp->addr);
158 1 : break;
159 1 : case PROP_WORKDAY:
160 1 : g_value_set_boxed(value, &emp->workday);
161 1 : break;
162 1 : case PROP_RATE:
163 1 : g_value_set_boxed(value, &emp->rate);
164 1 : break;
165 1 : case PROP_CCARD:
166 1 : g_value_take_object(value, emp->ccard_acc);
167 1 : break;
168 1 : case PROP_PDF_DIRNAME:
169 1 : qof_instance_get_kvp (QOF_INSTANCE (emp), value, 1, OWNER_EXPORT_PDF_DIRNAME);
170 1 : break;
171 1 : case PROP_LAST_POSTED:
172 1 : qof_instance_get_kvp (QOF_INSTANCE (emp), value, 1, LAST_POSTED_TO_ACCT);
173 1 : break;
174 1 : case PROP_PAYMENT_LAST_ACCT:
175 1 : qof_instance_get_kvp (QOF_INSTANCE (emp), value, 2, GNC_PAYMENT, GNC_LAST_ACCOUNT);
176 1 : break;
177 0 : default:
178 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
179 0 : break;
180 : }
181 : }
182 :
183 : static void
184 12 : gnc_employee_set_property (GObject *object,
185 : guint prop_id,
186 : const GValue *value,
187 : GParamSpec *pspec)
188 : {
189 : GncEmployee *emp;
190 12 : g_return_if_fail(GNC_IS_EMPLOYEE(object));
191 12 : emp = GNC_EMPLOYEE(object);
192 12 : g_assert (qof_instance_get_editlevel(emp));
193 12 : switch (prop_id)
194 : {
195 1 : case PROP_USERNAME:
196 1 : gncEmployeeSetUsername(emp, g_value_get_string(value));
197 1 : break;
198 1 : case PROP_ID:
199 1 : gncEmployeeSetID(emp, g_value_get_string(value));
200 1 : break;
201 1 : case PROP_ACTIVE:
202 1 : gncEmployeeSetActive(emp, g_value_get_boolean(value));
203 1 : break;
204 1 : case PROP_LANGUAGE:
205 1 : gncEmployeeSetLanguage(emp, g_value_get_string(value));
206 1 : break;
207 1 : case PROP_CURRENCY:
208 1 : gncEmployeeSetCurrency(emp, g_value_get_object(value));
209 1 : break;
210 1 : case PROP_ACL:
211 1 : gncEmployeeSetAcl(emp, g_value_get_string(value));
212 1 : break;
213 1 : case PROP_ADDRESS:
214 1 : qofEmployeeSetAddr(emp, g_value_get_object(value));
215 1 : break;
216 1 : case PROP_WORKDAY:
217 1 : gncEmployeeSetWorkday(emp, *(gnc_numeric*)g_value_get_boxed(value));
218 1 : break;
219 1 : case PROP_RATE:
220 1 : gncEmployeeSetRate(emp, *(gnc_numeric*)g_value_get_boxed(value));
221 1 : break;
222 0 : case PROP_CCARD:
223 0 : gncEmployeeSetCCard(emp, g_value_get_object(value));
224 0 : break;
225 1 : case PROP_PDF_DIRNAME:
226 1 : qof_instance_set_kvp (QOF_INSTANCE (emp), value, 1, OWNER_EXPORT_PDF_DIRNAME);
227 1 : break;
228 1 : case PROP_LAST_POSTED:
229 1 : qof_instance_set_kvp (QOF_INSTANCE (emp), value, 1, LAST_POSTED_TO_ACCT);
230 1 : break;
231 1 : case PROP_PAYMENT_LAST_ACCT:
232 1 : qof_instance_set_kvp (QOF_INSTANCE (emp), value, 2, GNC_PAYMENT, GNC_LAST_ACCOUNT);
233 1 : break;
234 0 : default:
235 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
236 0 : break;
237 : }
238 : }
239 :
240 : /** Does this object refer to a specific object */
241 : static gboolean
242 0 : impl_refers_to_object(const QofInstance* inst, const QofInstance* ref)
243 : {
244 : GncEmployee* emp;
245 :
246 0 : g_return_val_if_fail(inst != NULL, FALSE);
247 0 : g_return_val_if_fail(GNC_IS_EMPLOYEE(inst), FALSE);
248 :
249 0 : emp = GNC_EMPLOYEE(inst);
250 :
251 0 : if (GNC_IS_COMMODITY(ref))
252 : {
253 0 : return (emp->currency == GNC_COMMODITY(ref));
254 : }
255 0 : else if (GNC_IS_ACCOUNT(ref))
256 : {
257 0 : return (emp->ccard_acc == GNC_ACCOUNT(ref));
258 : }
259 :
260 0 : return FALSE;
261 : }
262 :
263 : /** Returns a list of my type of object which refers to an object. For example, when called as
264 : qof_instance_get_typed_referring_object_list(taxtable, account);
265 : it will return the list of taxtables which refer to a specific account. The result should be the
266 : same regardless of which taxtable object is used. The list must be freed by the caller but the
267 : objects on the list must not.
268 : */
269 : static GList*
270 0 : impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
271 : {
272 0 : if (!GNC_IS_COMMODITY(ref) && !GNC_IS_ACCOUNT(ref))
273 : {
274 0 : return NULL;
275 : }
276 :
277 0 : return qof_instance_get_referring_object_list_from_collection(qof_instance_get_collection(inst), ref);
278 : }
279 :
280 : static void
281 7 : gnc_employee_class_init (GncEmployeeClass *klass)
282 : {
283 7 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
284 7 : QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
285 :
286 7 : gobject_class->dispose = gnc_employee_dispose;
287 7 : gobject_class->finalize = gnc_employee_finalize;
288 7 : gobject_class->set_property = gnc_employee_set_property;
289 7 : gobject_class->get_property = gnc_employee_get_property;
290 :
291 7 : qof_class->get_display_name = NULL;
292 7 : qof_class->refers_to_object = impl_refers_to_object;
293 7 : qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
294 :
295 7 : g_object_class_install_property
296 : (gobject_class,
297 : PROP_USERNAME,
298 : g_param_spec_string ("username",
299 : "Employee Name",
300 : "The employee name is an arbitrary string "
301 : "assigned by the user which provides the employee "
302 : "name.",
303 : NULL,
304 : G_PARAM_READWRITE));
305 :
306 7 : g_object_class_install_property
307 : (gobject_class,
308 : PROP_ID,
309 : g_param_spec_string ("id",
310 : "Employee ID",
311 : "The employee ID is an arbitrary string "
312 : "assigned by the user which provides the employee "
313 : "ID.",
314 : NULL,
315 : G_PARAM_READWRITE));
316 :
317 7 : g_object_class_install_property
318 : (gobject_class,
319 : PROP_ACTIVE,
320 : g_param_spec_boolean ("active",
321 : "Active",
322 : "TRUE if the employee is active. FALSE if inactive.",
323 : FALSE,
324 : G_PARAM_READWRITE));
325 :
326 7 : g_object_class_install_property
327 : (gobject_class,
328 : PROP_LANGUAGE,
329 : g_param_spec_string ("language",
330 : "Employee Language",
331 : "The language is an arbitrary string "
332 : "assigned by the user which provides the language spoken "
333 : " by the employee.",
334 : NULL,
335 : G_PARAM_READWRITE));
336 :
337 7 : g_object_class_install_property
338 : (gobject_class,
339 : PROP_CURRENCY,
340 : g_param_spec_object ("currency",
341 : "Currency",
342 : "The currency property denotes the currency used by this employee.",
343 : GNC_TYPE_COMMODITY,
344 : G_PARAM_READWRITE));
345 :
346 7 : g_object_class_install_property
347 : (gobject_class,
348 : PROP_ACL,
349 : g_param_spec_string ("acl",
350 : "Employee ACL",
351 : "The acl is an arbitrary string "
352 : "assigned by the user which provides ??? "
353 : " for the employee.",
354 : NULL,
355 : G_PARAM_READWRITE));
356 :
357 7 : g_object_class_install_property
358 : (gobject_class,
359 : PROP_ADDRESS,
360 : g_param_spec_object ("address",
361 : "Address",
362 : "The address property contains the address information for this employee.",
363 : GNC_TYPE_ADDRESS,
364 : G_PARAM_READWRITE));
365 :
366 7 : g_object_class_install_property
367 : (gobject_class,
368 : PROP_WORKDAY,
369 : g_param_spec_boxed("workday",
370 : "Workday rate",
371 : "The daily rate for this employee.",
372 : GNC_TYPE_NUMERIC,
373 : G_PARAM_READWRITE));
374 :
375 7 : g_object_class_install_property
376 : (gobject_class,
377 : PROP_RATE,
378 : g_param_spec_boxed("rate",
379 : "Hourly rate",
380 : "The hourly rate for this employee.",
381 : GNC_TYPE_NUMERIC,
382 : G_PARAM_READWRITE));
383 :
384 7 : g_object_class_install_property
385 : (gobject_class,
386 : PROP_CCARD,
387 : g_param_spec_object ("credit-card-account",
388 : "Credit card account",
389 : "The credit card account for this employee.",
390 : GNC_TYPE_ACCOUNT,
391 : G_PARAM_READWRITE));
392 :
393 7 : g_object_class_install_property
394 : (gobject_class,
395 : PROP_PDF_DIRNAME,
396 : g_param_spec_string ("export-pdf-dir",
397 : "Export PDF Directory Name",
398 : "A subdirectory for exporting PDF reports which is "
399 : "appended to the target directory when writing them "
400 : "out. It is retrieved from preferences and stored on "
401 : "each 'Owner' object which prints items after "
402 : "printing.",
403 : NULL,
404 : G_PARAM_READWRITE));
405 :
406 7 : g_object_class_install_property(
407 : gobject_class,
408 : PROP_LAST_POSTED,
409 : g_param_spec_boxed("invoice-last-posted-account",
410 : "Invoice Last Posted Account",
411 : "The last account to which an invoice belonging to "
412 : "this owner was posted.",
413 : GNC_TYPE_GUID,
414 : G_PARAM_READWRITE));
415 :
416 7 : g_object_class_install_property(
417 : gobject_class,
418 : PROP_PAYMENT_LAST_ACCT,
419 : g_param_spec_boxed("payment-last-account",
420 : "Payment Last Account",
421 : "The last account to which an payment belonging to "
422 : "this owner was posted.",
423 : GNC_TYPE_GUID,
424 : G_PARAM_READWRITE));
425 7 : }
426 :
427 : /* Create/Destroy Functions */
428 25 : GncEmployee *gncEmployeeCreate (QofBook *book)
429 : {
430 : GncEmployee *employee;
431 :
432 25 : if (!book) return NULL;
433 :
434 24 : employee = g_object_new (GNC_TYPE_EMPLOYEE, NULL);
435 24 : qof_instance_init_data (&employee->inst, _GNC_MOD_NAME, book);
436 :
437 24 : employee->id = CACHE_INSERT ("");
438 24 : employee->username = CACHE_INSERT ("");
439 24 : employee->language = CACHE_INSERT ("");
440 24 : employee->acl = CACHE_INSERT ("");
441 24 : employee->addr = gncAddressCreate (book, &employee->inst);
442 24 : employee->workday = gnc_numeric_zero();
443 24 : employee->rate = gnc_numeric_zero();
444 24 : employee->active = TRUE;
445 24 : employee->balance = NULL;
446 :
447 24 : if (empl_qof_event_handler_id == 0)
448 7 : empl_qof_event_handler_id = qof_event_register_handler (empl_handle_qof_events, NULL);
449 :
450 24 : qof_event_gen (&employee->inst, QOF_EVENT_CREATE, NULL);
451 :
452 24 : return employee;
453 : }
454 :
455 11 : void gncEmployeeDestroy (GncEmployee *employee)
456 : {
457 11 : if (!employee) return;
458 11 : qof_instance_set_destroying(employee, TRUE);
459 11 : gncEmployeeCommitEdit(employee);
460 : }
461 :
462 11 : static void gncEmployeeFree (GncEmployee *employee)
463 : {
464 11 : if (!employee) return;
465 :
466 11 : qof_event_gen (&employee->inst, QOF_EVENT_DESTROY, NULL);
467 :
468 11 : CACHE_REMOVE (employee->id);
469 11 : CACHE_REMOVE (employee->username);
470 11 : CACHE_REMOVE (employee->language);
471 11 : CACHE_REMOVE (employee->acl);
472 11 : gncAddressBeginEdit (employee->addr);
473 11 : gncAddressDestroy (employee->addr);
474 11 : g_free (employee->balance);
475 :
476 : /* qof_instance_release (&employee->inst); */
477 11 : g_object_unref (employee);
478 : }
479 :
480 : /* ============================================================== */
481 : /* Set Functions */
482 :
483 : #define SET_STR(obj, member, str) { \
484 : if (!g_strcmp0 (member, str)) return; \
485 : gncEmployeeBeginEdit (obj); \
486 : CACHE_REPLACE (member, str); \
487 : }
488 :
489 15 : void gncEmployeeSetID (GncEmployee *employee, const char *id)
490 : {
491 15 : if (!employee) return;
492 15 : if (!id) return;
493 15 : SET_STR(employee, employee->id, id);
494 15 : mark_employee (employee);
495 15 : gncEmployeeCommitEdit (employee);
496 : }
497 :
498 4 : void gncEmployeeSetUsername (GncEmployee *employee, const char *username)
499 : {
500 4 : if (!employee) return;
501 4 : if (!username) return;
502 4 : SET_STR(employee, employee->username, username);
503 4 : mark_employee (employee);
504 4 : gncEmployeeCommitEdit (employee);
505 : }
506 :
507 : /* Employees don't have a name property defined, but
508 : * in order to get a consistent interface with other owner types,
509 : * this function fakes one by setting the name property of
510 : * the employee's address.
511 : */
512 5 : void gncEmployeeSetName (GncEmployee *employee, const char *name)
513 : {
514 5 : if (!employee) return;
515 5 : if (!name) return;
516 5 : gncAddressSetName (gncEmployeeGetAddr (employee), name);
517 : }
518 :
519 3 : void gncEmployeeSetLanguage (GncEmployee *employee, const char *language)
520 : {
521 3 : if (!employee) return;
522 3 : if (!language) return;
523 3 : SET_STR(employee, employee->language, language);
524 3 : mark_employee (employee);
525 3 : gncEmployeeCommitEdit (employee);
526 : }
527 :
528 2 : void gncEmployeeSetAcl (GncEmployee *employee, const char *acl)
529 : {
530 2 : if (!employee) return;
531 2 : if (!acl) return;
532 2 : SET_STR(employee, employee->acl, acl);
533 1 : mark_employee (employee);
534 1 : gncEmployeeCommitEdit (employee);
535 : }
536 :
537 2 : void gncEmployeeSetWorkday (GncEmployee *employee, gnc_numeric workday)
538 : {
539 2 : if (!employee) return;
540 2 : if (gnc_numeric_equal (workday, employee->workday)) return;
541 1 : gncEmployeeBeginEdit (employee);
542 1 : employee->workday = workday;
543 1 : mark_employee (employee);
544 1 : gncEmployeeCommitEdit (employee);
545 : }
546 :
547 2 : void gncEmployeeSetRate (GncEmployee *employee, gnc_numeric rate)
548 : {
549 2 : if (!employee) return;
550 2 : if (gnc_numeric_equal (rate, employee->rate)) return;
551 1 : gncEmployeeBeginEdit (employee);
552 1 : employee->rate = rate;
553 1 : mark_employee (employee);
554 1 : gncEmployeeCommitEdit (employee);
555 : }
556 :
557 14 : void gncEmployeeSetCurrency (GncEmployee *employee, gnc_commodity *currency)
558 : {
559 14 : if (!employee || !currency) return;
560 14 : if (employee->currency &&
561 0 : gnc_commodity_equal (employee->currency, currency))
562 0 : return;
563 14 : gncEmployeeBeginEdit (employee);
564 14 : employee->currency = currency;
565 14 : mark_employee (employee);
566 14 : gncEmployeeCommitEdit (employee);
567 : }
568 :
569 11 : void gncEmployeeSetActive (GncEmployee *employee, gboolean active)
570 : {
571 11 : if (!employee) return;
572 11 : if (active == employee->active) return;
573 9 : gncEmployeeBeginEdit (employee);
574 9 : employee->active = active;
575 9 : mark_employee (employee);
576 9 : gncEmployeeCommitEdit (employee);
577 : }
578 :
579 0 : void gncEmployeeSetCCard (GncEmployee *employee, Account* ccard_acc)
580 : {
581 0 : if (!employee) return;
582 0 : if (ccard_acc == employee->ccard_acc) return;
583 0 : gncEmployeeBeginEdit (employee);
584 0 : employee->ccard_acc = ccard_acc;
585 0 : mark_employee (employee);
586 0 : gncEmployeeCommitEdit (employee);
587 : }
588 :
589 : void
590 1 : qofEmployeeSetAddr (GncEmployee *employee, QofInstance *addr_ent)
591 : {
592 : GncAddress *addr;
593 :
594 1 : if (!employee || !addr_ent)
595 : {
596 0 : return;
597 : }
598 1 : addr = (GncAddress*)addr_ent;
599 1 : if (addr == employee->addr)
600 : {
601 0 : return;
602 : }
603 1 : if (employee->addr != NULL)
604 : {
605 1 : gncAddressBeginEdit(employee->addr);
606 1 : gncAddressDestroy(employee->addr);
607 : }
608 1 : gncEmployeeBeginEdit(employee);
609 1 : employee->addr = addr;
610 1 : mark_employee (employee);
611 1 : gncEmployeeCommitEdit(employee);
612 : }
613 :
614 : /* ============================================================== */
615 : /* Get Functions */
616 2 : const char * gncEmployeeGetID (const GncEmployee *employee)
617 : {
618 2 : if (!employee) return NULL;
619 2 : return employee->id;
620 : }
621 :
622 3 : const char * gncEmployeeGetUsername (const GncEmployee *employee)
623 : {
624 3 : if (!employee) return NULL;
625 3 : return employee->username;
626 : }
627 :
628 : /* Employees don't have a name property defined, but
629 : * in order to get a consistent interface with other owner types,
630 : * this function fakes one by returning the name property of
631 : * the employee's address.
632 : */
633 30 : const char * gncEmployeeGetName (const GncEmployee *employee)
634 : {
635 30 : if (!employee) return NULL;
636 30 : return gncAddressGetName ( gncEmployeeGetAddr (employee));
637 : }
638 :
639 45 : GncAddress * gncEmployeeGetAddr (const GncEmployee *employee)
640 : {
641 45 : if (!employee) return NULL;
642 45 : return employee->addr;
643 : }
644 :
645 1 : const char * gncEmployeeGetLanguage (const GncEmployee *employee)
646 : {
647 1 : if (!employee) return NULL;
648 1 : return employee->language;
649 : }
650 :
651 1 : const char * gncEmployeeGetAcl (const GncEmployee *employee)
652 : {
653 1 : if (!employee) return NULL;
654 1 : return employee->acl;
655 : }
656 :
657 1 : gnc_numeric gncEmployeeGetWorkday (const GncEmployee *employee)
658 : {
659 1 : if (!employee) return gnc_numeric_zero();
660 1 : return employee->workday;
661 : }
662 :
663 1 : gnc_numeric gncEmployeeGetRate (const GncEmployee *employee)
664 : {
665 1 : if (!employee) return gnc_numeric_zero();
666 1 : return employee->rate;
667 : }
668 :
669 1 : gnc_commodity * gncEmployeeGetCurrency (const GncEmployee *employee)
670 : {
671 1 : if (!employee) return NULL;
672 1 : return employee->currency;
673 : }
674 :
675 13 : gboolean gncEmployeeGetActive (const GncEmployee *employee)
676 : {
677 13 : if (!employee) return FALSE;
678 13 : return employee->active;
679 : }
680 :
681 10 : Account * gncEmployeeGetCCard (const GncEmployee *employee)
682 : {
683 10 : if (!employee) return NULL;
684 10 : return employee->ccard_acc;
685 : }
686 :
687 14 : gboolean gncEmployeeIsDirty (const GncEmployee *employee)
688 : {
689 14 : if (!employee) return FALSE;
690 14 : return (qof_instance_get_dirty_flag(employee)
691 14 : || gncAddressIsDirty (employee->addr));
692 : }
693 :
694 80 : void gncEmployeeBeginEdit (GncEmployee *employee)
695 : {
696 80 : qof_begin_edit(&employee->inst);
697 80 : }
698 :
699 0 : static void gncEmployeeOnError (QofInstance *employee, QofBackendError errcode)
700 : {
701 0 : PERR("Employee QofBackend Failure: %d", errcode);
702 0 : gnc_engine_signal_commit_error( errcode );
703 0 : }
704 :
705 41 : static void gncEmployeeOnDone (QofInstance *inst)
706 : {
707 41 : GncEmployee *employee = (GncEmployee *) inst;
708 41 : gncAddressClearDirty (employee->addr);
709 41 : }
710 :
711 11 : static void emp_free (QofInstance *inst)
712 : {
713 11 : GncEmployee *employee = (GncEmployee *) inst;
714 11 : gncEmployeeFree (employee);
715 11 : }
716 :
717 :
718 80 : void gncEmployeeCommitEdit (GncEmployee *employee)
719 : {
720 80 : if (!qof_commit_edit (QOF_INSTANCE(employee))) return;
721 52 : qof_commit_edit_part2 (&employee->inst, gncEmployeeOnError,
722 : gncEmployeeOnDone, emp_free);
723 : }
724 :
725 : /* ============================================================== */
726 : /* Other functions */
727 :
728 0 : int gncEmployeeCompare (const GncEmployee *a, const GncEmployee *b)
729 : {
730 0 : if (!a && !b) return 0;
731 0 : if (!a && b) return 1;
732 0 : if (a && !b) return -1;
733 :
734 0 : return(strcmp(a->username, b->username));
735 : }
736 :
737 1 : gboolean gncEmployeeEqual(const GncEmployee* a, const GncEmployee* b)
738 : {
739 1 : if (a == NULL && b == NULL) return TRUE;
740 1 : if (a == NULL || b == NULL ) return FALSE;
741 :
742 1 : g_return_val_if_fail(GNC_IS_EMPLOYEE(a), FALSE);
743 1 : g_return_val_if_fail(GNC_IS_EMPLOYEE(b), FALSE);
744 :
745 1 : if (g_strcmp0(a->id, b->id) != 0)
746 : {
747 0 : PWARN("IDs differ: %s vs %s", a->id, b->id);
748 0 : return FALSE;
749 : }
750 :
751 1 : if (g_strcmp0(a->username, b->username) != 0)
752 : {
753 0 : PWARN("Usernames differ: %s vs %s", a->username, b->username);
754 0 : return FALSE;
755 : }
756 :
757 1 : if (!gncAddressEqual(a->addr, b->addr))
758 : {
759 0 : PWARN("Addresses differ");
760 0 : return FALSE;
761 : }
762 :
763 1 : if (!gnc_commodity_equal(a->currency, b->currency))
764 : {
765 0 : PWARN("Currencies differ");
766 0 : return FALSE;
767 : }
768 :
769 1 : if (a->active != b->active)
770 : {
771 0 : PWARN("Active flags differ");
772 0 : return FALSE;
773 : }
774 :
775 1 : if (g_strcmp0(a->language, b->language) != 0)
776 : {
777 0 : PWARN("Languages differ: %s vs %s", a->language, b->language);
778 0 : return FALSE;
779 : }
780 :
781 1 : if (g_strcmp0(a->acl, b->acl) != 0)
782 : {
783 0 : PWARN("ACLs differ: %s vs %s", a->acl, b->acl);
784 0 : return FALSE;
785 : }
786 :
787 1 : if (!xaccAccountEqual(a->ccard_acc, b->ccard_acc, TRUE))
788 : {
789 0 : PWARN("Accounts differ");
790 0 : return FALSE;
791 : }
792 :
793 1 : if (!gnc_numeric_equal(a->workday, b->workday))
794 : {
795 0 : PWARN("Workdays differ");
796 0 : return FALSE;
797 : }
798 :
799 1 : if (!gnc_numeric_equal(a->rate, b->rate))
800 : {
801 0 : PWARN("Rates differ");
802 0 : return FALSE;
803 : }
804 :
805 1 : return TRUE;
806 : }
807 :
808 : /* Package-Private functions */
809 :
810 1 : static const char * _gncEmployeePrintable (gpointer item)
811 : {
812 1 : GncEmployee *v = item;
813 1 : if (!item) return NULL;
814 1 : return gncAddressGetName(v->addr);
815 : }
816 :
817 : /**
818 : * Listen for qof events.
819 : *
820 : * - If the address of an employee has changed, mark the employee as dirty.
821 : * - If a lot related to an employee has changed, clear the employee's
822 : * cached balance as it likely has become invalid.
823 : *
824 : * @param entity Entity for the event
825 : * @param event_type Event type
826 : * @param user_data User data registered with the handler
827 : * @param event_data Event data passed with the event.
828 : */
829 : static void
830 141033 : empl_handle_qof_events (QofInstance *entity, QofEventId event_type,
831 : gpointer user_data, gpointer event_data)
832 : {
833 :
834 : /* Handle address change events */
835 141033 : if ((GNC_IS_ADDRESS (entity) &&
836 24 : (event_type & QOF_EVENT_MODIFY) != 0))
837 : {
838 6 : if (GNC_IS_EMPLOYEE (event_data))
839 : {
840 6 : GncEmployee* empl = GNC_EMPLOYEE (event_data);
841 6 : gncEmployeeBeginEdit (empl);
842 6 : mark_employee (empl);
843 6 : gncEmployeeCommitEdit (empl);
844 : }
845 6 : return;
846 : }
847 :
848 : /* Handle lot change events */
849 141027 : if (GNC_IS_LOT (entity))
850 : {
851 315 : GNCLot *lot = GNC_LOT (entity);
852 : GncOwner lot_owner;
853 315 : const GncOwner *end_owner = NULL;
854 315 : GncInvoice *invoice = gncInvoiceGetInvoiceFromLot (lot);
855 :
856 : /* Determine the owner associated with the lot */
857 315 : if (invoice)
858 : /* Invoice lots */
859 206 : end_owner = gncOwnerGetEndOwner (gncInvoiceGetOwner (invoice));
860 109 : else if (gncOwnerGetOwnerFromLot (lot, &lot_owner))
861 : /* Pre-payment lots */
862 36 : end_owner = gncOwnerGetEndOwner (&lot_owner);
863 :
864 315 : if (gncOwnerGetType (end_owner) == GNC_OWNER_EMPLOYEE)
865 : {
866 : /* Clear the cached balance */
867 40 : GncEmployee* empl = gncOwnerGetEmployee (end_owner);
868 40 : g_free (empl->balance);
869 40 : empl->balance = NULL;
870 : }
871 315 : return;
872 : }
873 : }
874 :
875 : static void
876 10 : destroy_employee_on_book_close(QofInstance *ent, gpointer data)
877 : {
878 10 : GncEmployee* e = GNC_EMPLOYEE(ent);
879 :
880 10 : gncEmployeeBeginEdit(e);
881 10 : gncEmployeeDestroy(e);
882 10 : }
883 :
884 : /** Handles book end - frees all employees from the book
885 : *
886 : * @param book Book being closed
887 : */
888 : static void
889 180 : gnc_employee_book_end(QofBook* book)
890 : {
891 : QofCollection *col;
892 :
893 180 : col = qof_book_get_collection(book, GNC_ID_EMPLOYEE);
894 180 : qof_collection_foreach(col, destroy_employee_on_book_close, NULL);
895 180 : }
896 :
897 : static QofObject gncEmployeeDesc =
898 : {
899 : DI(.interface_version = ) QOF_OBJECT_VERSION,
900 : DI(.e_type = ) _GNC_MOD_NAME,
901 : DI(.type_label = ) "Employee",
902 : DI(.create = ) (gpointer)gncEmployeeCreate,
903 : DI(.book_begin = ) NULL,
904 : DI(.book_end = ) gnc_employee_book_end,
905 : DI(.is_dirty = ) qof_collection_is_dirty,
906 : DI(.mark_clean = ) qof_collection_mark_clean,
907 : DI(.foreach = ) qof_collection_foreach,
908 : DI(.printable = ) _gncEmployeePrintable,
909 : DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
910 : };
911 :
912 84 : gboolean gncEmployeeRegister (void)
913 : {
914 : static QofParam params[] =
915 : {
916 : { EMPLOYEE_ID, QOF_TYPE_NATURAL, (QofAccessFunc)gncEmployeeGetID, (QofSetterFunc)gncEmployeeSetID },
917 : {
918 : EMPLOYEE_USERNAME, QOF_TYPE_STRING, (QofAccessFunc)gncEmployeeGetUsername,
919 : (QofSetterFunc)gncEmployeeSetUsername
920 : },
921 : {
922 : EMPLOYEE_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncEmployeeGetName,
923 : (QofSetterFunc)gncEmployeeSetName
924 : },
925 : {
926 : EMPLOYEE_LANGUAGE, QOF_TYPE_STRING, (QofAccessFunc)gncEmployeeGetLanguage,
927 : (QofSetterFunc)gncEmployeeSetLanguage
928 : },
929 : { EMPLOYEE_ACL, QOF_TYPE_STRING, (QofAccessFunc)gncEmployeeGetAcl, (QofSetterFunc)gncEmployeeSetAcl },
930 : {
931 : EMPLOYEE_WORKDAY, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEmployeeGetWorkday,
932 : (QofSetterFunc)gncEmployeeSetWorkday
933 : },
934 : { EMPLOYEE_RATE, QOF_TYPE_NUMERIC, (QofAccessFunc)gncEmployeeGetRate, (QofSetterFunc)gncEmployeeSetRate },
935 : { EMPLOYEE_ADDR, GNC_ID_ADDRESS, (QofAccessFunc)gncEmployeeGetAddr, (QofSetterFunc)qofEmployeeSetAddr },
936 : { EMPLOYEE_CC, GNC_ID_ACCOUNT, (QofAccessFunc)gncEmployeeGetCCard, (QofSetterFunc)gncEmployeeSetCCard },
937 : { QOF_PARAM_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)gncEmployeeGetActive, (QofSetterFunc)gncEmployeeSetActive },
938 : { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
939 : { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
940 : { NULL },
941 : };
942 :
943 84 : qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncEmployeeCompare, params);
944 :
945 84 : return qof_object_register (&gncEmployeeDesc);
946 : }
947 :
948 0 : gchar *gncEmployeeNextID (QofBook *book)
949 : {
950 0 : return qof_book_increment_and_format_counter (book, _GNC_MOD_NAME);
951 : }
952 :
953 : const gnc_numeric*
954 0 : gncEmployeeGetCachedBalance (GncEmployee *empl)
955 : {
956 0 : return empl->balance;
957 : }
958 :
959 0 : void gncEmployeeSetCachedBalance (GncEmployee *empl, const gnc_numeric *new_bal)
960 : {
961 0 : if (!new_bal)
962 : {
963 0 : if (empl->balance)
964 : {
965 0 : g_free (empl->balance);
966 0 : empl->balance = NULL;
967 : }
968 0 : return;
969 : }
970 :
971 0 : if (!empl->balance)
972 0 : empl->balance = g_new0 (gnc_numeric, 1);
973 :
974 0 : *empl->balance = *new_bal;
975 : }
|