Branch data 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 : 48 : void mark_employee (GncEmployee *employee)
76 : : {
77 : 48 : qof_instance_set_dirty(&employee->inst);
78 : 48 : qof_event_gen (&employee->inst, QOF_EVENT_MODIFY, NULL);
79 : 48 : }
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 : 110 : G_DEFINE_TYPE(GncEmployee, gnc_employee, QOF_TYPE_INSTANCE)
103 : :
104 : : static void
105 : 21 : gnc_employee_init(GncEmployee* emp)
106 : : {
107 : 21 : }
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 : 6 : gnc_employee_class_init (GncEmployeeClass *klass)
282 : : {
283 : 6 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
284 : 6 : QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
285 : :
286 : 6 : gobject_class->dispose = gnc_employee_dispose;
287 : 6 : gobject_class->finalize = gnc_employee_finalize;
288 : 6 : gobject_class->set_property = gnc_employee_set_property;
289 : 6 : gobject_class->get_property = gnc_employee_get_property;
290 : :
291 : 6 : qof_class->get_display_name = NULL;
292 : 6 : qof_class->refers_to_object = impl_refers_to_object;
293 : 6 : qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
294 : :
295 : 6 : 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 : 6 : 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 : 6 : 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 : 6 : 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 : 6 : 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 : 6 : 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 : 6 : 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 : 6 : 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 : 6 : 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 : 6 : 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 : 6 : 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 : 6 : 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 : 6 : 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 : 6 : }
426 : :
427 : : /* Create/Destroy Functions */
428 : 22 : GncEmployee *gncEmployeeCreate (QofBook *book)
429 : : {
430 : : GncEmployee *employee;
431 : :
432 : 22 : if (!book) return NULL;
433 : :
434 : 21 : employee = g_object_new (GNC_TYPE_EMPLOYEE, NULL);
435 : 21 : qof_instance_init_data (&employee->inst, _GNC_MOD_NAME, book);
436 : :
437 : 21 : employee->id = CACHE_INSERT ("");
438 : 21 : employee->username = CACHE_INSERT ("");
439 : 21 : employee->language = CACHE_INSERT ("");
440 : 21 : employee->acl = CACHE_INSERT ("");
441 : 21 : employee->addr = gncAddressCreate (book, &employee->inst);
442 : 21 : employee->workday = gnc_numeric_zero();
443 : 21 : employee->rate = gnc_numeric_zero();
444 : 21 : employee->active = TRUE;
445 : 21 : employee->balance = NULL;
446 : :
447 : 21 : if (empl_qof_event_handler_id == 0)
448 : 6 : empl_qof_event_handler_id = qof_event_register_handler (empl_handle_qof_events, NULL);
449 : :
450 : 21 : qof_event_gen (&employee->inst, QOF_EVENT_CREATE, NULL);
451 : :
452 : 21 : 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 : 12 : void gncEmployeeSetID (GncEmployee *employee, const char *id)
490 : : {
491 : 12 : if (!employee) return;
492 : 12 : if (!id) return;
493 : 12 : SET_STR(employee, employee->id, id);
494 : 12 : mark_employee (employee);
495 : 12 : 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 : 4 : void gncEmployeeSetName (GncEmployee *employee, const char *name)
513 : : {
514 : 4 : if (!employee) return;
515 : 4 : if (!name) return;
516 : 4 : 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 : 11 : void gncEmployeeSetCurrency (GncEmployee *employee, gnc_commodity *currency)
558 : : {
559 : 11 : if (!employee || !currency) return;
560 : 11 : if (employee->currency &&
561 : 0 : gnc_commodity_equal (employee->currency, currency))
562 : 0 : return;
563 : 11 : gncEmployeeBeginEdit (employee);
564 : 11 : employee->currency = currency;
565 : 11 : mark_employee (employee);
566 : 11 : 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 : 28 : const char * gncEmployeeGetName (const GncEmployee *employee)
634 : : {
635 : 28 : if (!employee) return NULL;
636 : 28 : return gncAddressGetName ( gncEmployeeGetAddr (employee));
637 : : }
638 : :
639 : 42 : GncAddress * gncEmployeeGetAddr (const GncEmployee *employee)
640 : : {
641 : 42 : if (!employee) return NULL;
642 : 42 : 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 : 11 : gboolean gncEmployeeGetActive (const GncEmployee *employee)
676 : : {
677 : 11 : if (!employee) return FALSE;
678 : 11 : return employee->active;
679 : : }
680 : :
681 : 8 : Account * gncEmployeeGetCCard (const GncEmployee *employee)
682 : : {
683 : 8 : if (!employee) return NULL;
684 : 8 : 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 : 71 : void gncEmployeeBeginEdit (GncEmployee *employee)
695 : : {
696 : 71 : qof_begin_edit(&employee->inst);
697 : 71 : }
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 : 36 : static void gncEmployeeOnDone (QofInstance *inst)
706 : : {
707 : 36 : GncEmployee *employee = (GncEmployee *) inst;
708 : 36 : gncAddressClearDirty (employee->addr);
709 : 36 : }
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 : 71 : void gncEmployeeCommitEdit (GncEmployee *employee)
719 : : {
720 : 71 : if (!qof_commit_edit (QOF_INSTANCE(employee))) return;
721 : 47 : 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 : 84931 : empl_handle_qof_events (QofInstance *entity, QofEventId event_type,
831 : : gpointer user_data, gpointer event_data)
832 : : {
833 : :
834 : : /* Handle address change events */
835 : 84931 : if ((GNC_IS_ADDRESS (entity) &&
836 : 23 : (event_type & QOF_EVENT_MODIFY) != 0))
837 : : {
838 : 5 : if (GNC_IS_EMPLOYEE (event_data))
839 : : {
840 : 5 : GncEmployee* empl = GNC_EMPLOYEE (event_data);
841 : 5 : gncEmployeeBeginEdit (empl);
842 : 5 : mark_employee (empl);
843 : 5 : gncEmployeeCommitEdit (empl);
844 : : }
845 : 5 : return;
846 : : }
847 : :
848 : : /* Handle lot change events */
849 : 84926 : if (GNC_IS_LOT (entity))
850 : : {
851 : 225 : GNCLot *lot = GNC_LOT (entity);
852 : : GncOwner lot_owner;
853 : 225 : const GncOwner *end_owner = NULL;
854 : 225 : GncInvoice *invoice = gncInvoiceGetInvoiceFromLot (lot);
855 : :
856 : : /* Determine the owner associated with the lot */
857 : 225 : if (invoice)
858 : : /* Invoice lots */
859 : 160 : end_owner = gncOwnerGetEndOwner (gncInvoiceGetOwner (invoice));
860 : 65 : else if (gncOwnerGetOwnerFromLot (lot, &lot_owner))
861 : : /* Pre-payment lots */
862 : 24 : end_owner = gncOwnerGetEndOwner (&lot_owner);
863 : :
864 : 225 : if (gncOwnerGetType (end_owner) == GNC_OWNER_EMPLOYEE)
865 : : {
866 : : /* Clear the cached balance */
867 : 32 : GncEmployee* empl = gncOwnerGetEmployee (end_owner);
868 : 32 : g_free (empl->balance);
869 : 32 : empl->balance = NULL;
870 : : }
871 : 225 : 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 : 154 : gnc_employee_book_end(QofBook* book)
890 : : {
891 : : QofCollection *col;
892 : :
893 : 154 : col = qof_book_get_collection(book, GNC_ID_EMPLOYEE);
894 : 154 : qof_collection_foreach(col, destroy_employee_on_book_close, NULL);
895 : 154 : }
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 : 82 : gboolean gncEmployeeRegister (void)
913 : : {
914 : : static QofParam params[] =
915 : : {
916 : : { EMPLOYEE_ID, QOF_TYPE_STRING, (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 : 82 : qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncEmployeeCompare, params);
944 : :
945 : 82 : 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 : : }
|