pilot-qof  0.2.3
pilot-expenses.c
00001 /***************************************************************************
00002  *            qof-expenses.c
00003  *
00004  *  Thu Oct 21 07:59:13 2004
00005  *  Copyright  2004-2009  Neil Williams  <linux@codehelp.co.uk>
00006  ****************************************************************************/
00007 /*
00008     This program is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 3 of the License, or
00011     (at your option) any later version.
00012 
00013     This program is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License
00019     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00020  */
00035 #include <stdlib.h>
00036 #include <glib.h>
00037 #include <glib/gprintf.h>
00038 #include <qof.h>
00039 #include "pi-expense.h"
00040 #include "qof-main.h"
00041 #include "pilot-qof.h"
00042 #include "pilot-expenses.h"
00043 #include "pilot-expenses-p.h"
00044 
00045 #define PQOF_EXPENSES_DESC "Pilot-link QOF expenses"
00046 
00047 static QofLogModule log_module = PQ_MOD_PILOT;
00048 
00053 static GHashTable *PQCurrencyTable = NULL;
00054 
00071 void
00072 populate_currencies (void)
00073 {
00074     if (PQCurrencyTable != NULL)
00075         return;
00076     PQCurrencyTable = g_hash_table_new (g_direct_hash, g_direct_equal);
00077     {   /* Australia    0   100     AU$     AUD */
00078         PQCurrency *c = g_new0 (PQCurrency, 1);
00079         c->pq_code = 0;
00080         c->fraction = 100;
00081         c->symbol = "AU$";
00082         c->mnemonic = "AUD";
00083         c->non_utf8 = FALSE;
00084         g_hash_table_insert (PQCurrencyTable,
00085             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00086     }
00087     {   /* Austria  1   100     €     ATS */
00088         PQCurrency *c = g_new0 (PQCurrency, 1);
00089         c->pq_code = 1;
00090         c->fraction = 100;
00091         c->symbol = "€";
00092         c->mnemonic = "ATS";
00093         c->non_utf8 = TRUE;
00094         g_hash_table_insert (PQCurrencyTable,
00095             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00096     }
00097     {   /* Belgium      2   100     €     BEF */
00098         PQCurrency *c = g_new0 (PQCurrency, 1);
00099         c->pq_code = 2;
00100         c->fraction = 100;
00101         c->symbol = "€";
00102         c->mnemonic = "BEF";
00103         c->non_utf8 = TRUE;
00104         g_hash_table_insert (PQCurrencyTable,
00105             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00106     }
00107     {   /* Brazil   3   100     R$      BRL */
00108         PQCurrency *c = g_new0 (PQCurrency, 1);
00109         c->pq_code = 3;
00110         c->fraction = 100;
00111         c->symbol = "R$";
00112         c->mnemonic = "BRL";
00113         c->non_utf8 = FALSE;
00114         g_hash_table_insert (PQCurrencyTable,
00115             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00116     }
00117     {   /* Canada   4   100     $CN     CAD */
00118         PQCurrency *c = g_new0 (PQCurrency, 1);
00119         c->pq_code = 4;
00120         c->fraction = 100;
00121         c->symbol = "$CN";
00122         c->mnemonic = "CAD";
00123         c->non_utf8 = FALSE;
00124         g_hash_table_insert (PQCurrencyTable,
00125             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00126     }
00127     {   /* Denmark      5   100     DKK     DKK */
00128         PQCurrency *c = g_new0 (PQCurrency, 1);
00129         c->pq_code = 5;
00130         c->fraction = 100;
00131         c->symbol = "DKK";
00132         c->mnemonic = "DKK";
00133         c->non_utf8 = FALSE;
00134         g_hash_table_insert (PQCurrencyTable,
00135             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00136     }
00137     {   /* Finland      6   100     €     FIM */
00138         PQCurrency *c = g_new0 (PQCurrency, 1);
00139         c->pq_code = 6;
00140         c->fraction = 100;
00141         c->symbol = "€";
00142         c->mnemonic = "FIM";
00143         c->non_utf8 = TRUE;
00144         g_hash_table_insert (PQCurrencyTable,
00145             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00146     }
00147     {   /* France       7   100     €     FRF */
00148         PQCurrency *c = g_new0 (PQCurrency, 1);
00149         c->pq_code = 7;
00150         c->fraction = 100;
00151         c->symbol = "€";
00152         c->mnemonic = "FRF";
00153         c->non_utf8 = TRUE;
00154         g_hash_table_insert (PQCurrencyTable,
00155             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00156     }
00157     {   /* Germany      8   100     €     DEM */
00158         PQCurrency *c = g_new0 (PQCurrency, 1);
00159         c->pq_code = 8;
00160         c->fraction = 100;
00161         c->symbol = "€";
00162         c->mnemonic = "DEM";
00163         c->non_utf8 = TRUE;
00164         g_hash_table_insert (PQCurrencyTable,
00165             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00166     }
00167     {   /* Hong Kong    9   100     HK$     HKD */
00168         PQCurrency *c = g_new0 (PQCurrency, 1);
00169         c->pq_code = 9;
00170         c->fraction = 100;
00171         c->symbol = "HK$";
00172         c->mnemonic = "HKD";
00173         c->non_utf8 = FALSE;
00174         g_hash_table_insert (PQCurrencyTable,
00175             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00176     }
00177     {   /* Iceland  10  100     ISK     ISK */
00178         PQCurrency *c = g_new0 (PQCurrency, 1);
00179         c->pq_code = 10;
00180         c->fraction = 100;
00181         c->symbol = "ISK";
00182         c->mnemonic = "ISK";
00183         c->non_utf8 = FALSE;
00184         g_hash_table_insert (PQCurrencyTable,
00185             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00186     }
00187     {   /* Ireland      11  100     €     IEP */
00188         PQCurrency *c = g_new0 (PQCurrency, 1);
00189         c->pq_code = 11;
00190         c->fraction = 100;
00191         c->symbol = "€";
00192         c->mnemonic = "IEP";
00193         c->non_utf8 = TRUE;
00194         g_hash_table_insert (PQCurrencyTable,
00195             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00196     }
00197     {   /* Italy    12  1       EUR     ITL */
00198         /* The Italian Lira had a fraction == 1 */
00199         PQCurrency *c = g_new0 (PQCurrency, 1);
00200         c->pq_code = 12;
00201         c->fraction = 100;
00202         c->symbol = "EUR";
00203         c->mnemonic = "ITL";
00204         c->non_utf8 = FALSE;
00205         g_hash_table_insert (PQCurrencyTable,
00206             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00207     }
00208     {   /* Japan        13  1   &#165;  ¥      JPY */
00209         PQCurrency *c = g_new0 (PQCurrency, 1);
00210         c->pq_code = 13;
00211         c->fraction = 1;
00212         c->symbol = "¥";
00213         c->mnemonic = "JPY";
00214         c->non_utf8 = TRUE;
00215         g_hash_table_insert (PQCurrencyTable,
00216             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00217     }
00218     {   /* Luxembourg   14  100 &#136;  €     LUF */
00219         PQCurrency *c = g_new0 (PQCurrency, 1);
00220         c->pq_code = 14;
00221         c->fraction = 100;
00222         c->symbol = "€";
00223         c->mnemonic = "LUF";
00224         c->non_utf8 = TRUE;
00225         g_hash_table_insert (PQCurrencyTable,
00226             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00227     }
00228     {   /* Mexico       15  100     MXP     MXP */
00229         PQCurrency *c = g_new0 (PQCurrency, 1);
00230         c->pq_code = 15;
00231         c->fraction = 100;
00232         c->symbol = "MXP";
00233         c->mnemonic = "MXP";
00234         c->non_utf8 = FALSE;
00235         g_hash_table_insert (PQCurrencyTable,
00236             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00237     }
00238     {   /* Netherlands  16  100     €     ANG */
00239         PQCurrency *c = g_new0 (PQCurrency, 1);
00240         c->pq_code = 16;
00241         c->fraction = 100;
00242         c->symbol = "€";
00243         c->mnemonic = "ANG";
00244         c->non_utf8 = TRUE;
00245         g_hash_table_insert (PQCurrencyTable,
00246             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00247     }
00248     {   /* New Zealand  17  100     $NZ     NZD */
00249         PQCurrency *c = g_new0 (PQCurrency, 1);
00250         c->pq_code = 17;
00251         c->fraction = 100;
00252         c->symbol = "$NZ";
00253         c->mnemonic = "NZD";
00254         c->non_utf8 = FALSE;
00255         g_hash_table_insert (PQCurrencyTable,
00256             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00257     }
00258     {   /* Norway       18  100     NOK     NOK */
00259         PQCurrency *c = g_new0 (PQCurrency, 1);
00260         c->pq_code = 18;
00261         c->fraction = 100;
00262         c->symbol = "NOK";
00263         c->mnemonic = "NOK";
00264         c->non_utf8 = FALSE;
00265         g_hash_table_insert (PQCurrencyTable,
00266             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00267     }
00268     {   /* Spain    19  100     €     ESP */
00269         PQCurrency *c = g_new0 (PQCurrency, 1);
00270         c->pq_code = 19;
00271         c->fraction = 100;
00272         c->symbol = "€";
00273         c->mnemonic = "ESP";
00274         c->non_utf8 = TRUE;
00275         g_hash_table_insert (PQCurrencyTable,
00276             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00277     }
00278     {   /* Sweden   20  100     SEK     SEK */
00279         PQCurrency *c = g_new0 (PQCurrency, 1);
00280         c->pq_code = 20;
00281         c->fraction = 100;
00282         c->symbol = "SEK";
00283         c->mnemonic = "SEK";
00284         c->non_utf8 = FALSE;
00285         g_hash_table_insert (PQCurrencyTable,
00286             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00287     }
00288     {   /* Switzerland  21  100     CHF     CHF */
00289         PQCurrency *c = g_new0 (PQCurrency, 1);
00290         c->pq_code = 21;
00291         c->fraction = 100;
00292         c->symbol = "CHF";
00293         c->mnemonic = "CHF";
00294         c->non_utf8 = FALSE;
00295         g_hash_table_insert (PQCurrencyTable,
00296             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00297     }
00298     {   /* United Kingdom 22    100     £      GBP */
00299         PQCurrency *c = g_new0 (PQCurrency, 1);
00300         c->pq_code = 22;
00301         c->fraction = 100;
00302         c->symbol = "£";
00303         c->mnemonic = "GBP";
00304         c->non_utf8 = TRUE;
00305         g_hash_table_insert (PQCurrencyTable,
00306             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00307     }
00308     {   /* United States  23    100     $US     USD */
00309         PQCurrency *c = g_new0 (PQCurrency, 1);
00310         c->pq_code = 23;
00311         c->fraction = 100;
00312         c->symbol = "$US";
00313         c->mnemonic = "USD";
00314         c->non_utf8 = FALSE;
00315         g_hash_table_insert (PQCurrencyTable,
00316             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00317     }
00318     {   /* India        24  100     Rs      INR */
00319         PQCurrency *c = g_new0 (PQCurrency, 1);
00320         c->pq_code = 24;
00321         c->fraction = 100;
00322         c->symbol = "Rs";
00323         c->mnemonic = "INR";
00324         c->non_utf8 = FALSE;
00325         g_hash_table_insert (PQCurrencyTable,
00326             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00327     }
00328     {   /* Indonesia    25  1       Rp      IDR */
00329         PQCurrency *c = g_new0 (PQCurrency, 1);
00330         c->pq_code = 25;
00331         c->fraction = 1;
00332         c->symbol = "Rp";
00333         c->mnemonic = "IDR";
00334         c->non_utf8 = FALSE;
00335         g_hash_table_insert (PQCurrencyTable,
00336             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00337     }
00338     {   /* Korea    26  100     KRW     KRW  (South) */
00339         PQCurrency *c = g_new0 (PQCurrency, 1);
00340         c->pq_code = 26;
00341         c->fraction = 100;
00342         c->symbol = "KRW";
00343         c->mnemonic = "KRW";
00344         c->non_utf8 = FALSE;
00345         g_hash_table_insert (PQCurrencyTable,
00346             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00347     }
00348     {   /* Malaysia     27  100     RM      MYR */
00349         PQCurrency *c = g_new0 (PQCurrency, 1);
00350         c->pq_code = 27;
00351         c->fraction = 100;
00352         c->symbol = "RM";
00353         c->mnemonic = "MYR";
00354         c->non_utf8 = FALSE;
00355         g_hash_table_insert (PQCurrencyTable,
00356             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00357     }
00358     {   /* P.R.C. // People's Rep. China 28 100 RMB     CNY */
00359         PQCurrency *c = g_new0 (PQCurrency, 1);
00360         c->pq_code = 28;
00361         c->fraction = 100;
00362         c->symbol = "RMB";
00363         c->mnemonic = "CNY";
00364         c->non_utf8 = FALSE;
00365         g_hash_table_insert (PQCurrencyTable,
00366             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00367     }
00368     {   /* Phillipines  29  100     P       PHP */
00369         PQCurrency *c = g_new0 (PQCurrency, 1);
00370         c->pq_code = 29;
00371         c->fraction = 100;
00372         c->symbol = "P";
00373         c->mnemonic = "PHP";
00374         c->non_utf8 = FALSE;
00375         g_hash_table_insert (PQCurrencyTable,
00376             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00377     }
00378     {   /* Singapore    30  100     $       SGD */
00379         PQCurrency *c = g_new0 (PQCurrency, 1);
00380         c->pq_code = 30;
00381         c->fraction = 100;
00382         c->symbol = "$";
00383         c->mnemonic = "SGD";
00384         c->non_utf8 = FALSE;
00385         g_hash_table_insert (PQCurrencyTable,
00386             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00387     }
00388     {   /* Thailand     31  100     BHT     THB */
00389         PQCurrency *c = g_new0 (PQCurrency, 1);
00390         c->pq_code = 31;
00391         c->fraction = 100;
00392         c->symbol = "BHT";
00393         c->mnemonic = "THB";
00394         c->non_utf8 = FALSE;
00395         g_hash_table_insert (PQCurrencyTable,
00396             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00397     }
00398     {   /* Taiwan   32  100     NT$     TWD */
00399         PQCurrency *c = g_new0 (PQCurrency, 1);
00400         c->pq_code = 32;
00401         c->fraction = 100;
00402         c->symbol = "NT$";
00403         c->mnemonic = "TWD";
00404         c->non_utf8 = FALSE;
00405         g_hash_table_insert (PQCurrencyTable,
00406             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00407     }
00408     {   /* EU (Euro)    133 100     €     EUR */
00409         PQCurrency *c = g_new0 (PQCurrency, 1);
00410         c->pq_code = 133;
00411         c->fraction = 100;
00412         c->symbol = "€";
00413         c->mnemonic = "EUR";
00414         c->non_utf8 = TRUE;
00415         g_hash_table_insert (PQCurrencyTable,
00416             GINT_TO_POINTER (c->pq_code), (gpointer) c);
00417     }
00418 }
00419 
00420 PQCurrency *
00421 pq_currency_lookup (QofInstance * inst, gint currency_code)
00422 {
00423     PQCurrency *currency;
00424 
00425     currency = NULL;
00426     if (!PQCurrencyTable)
00427         populate_currencies ();
00428     currency =
00429         (PQCurrency *) g_hash_table_lookup (PQCurrencyTable,
00430         GINT_TO_POINTER (currency_code));
00431     if (!currency)
00432     {
00433         PERR (" unsupported currency! %d", currency_code);
00434         return NULL;
00435     }
00436     kvp_frame_set_string (qof_instance_get_slots (inst),
00437         PQ_CURRENCY_MNEMONIC, currency->mnemonic);
00438     kvp_frame_set_gint64 (qof_instance_get_slots (inst),
00439         PQ_CURRENCY_FRACTION, currency->fraction);
00440     if (currency->non_utf8)
00441     {
00442         kvp_frame_set_string (qof_instance_get_slots (inst),
00443             PQ_CURRENCY_SYMBOL,
00444             qof_util_make_utf8 ((gchar *) currency->symbol));
00445     }
00446     else
00447     {
00448         kvp_frame_set_string (qof_instance_get_slots (inst),
00449             PQ_CURRENCY_SYMBOL, currency->symbol);
00450     }
00451     return currency;
00452 }
00453 
00454 static gboolean
00455 currency_cb (gpointer key, gpointer value, gpointer data)
00456 {
00457     PQCurrency *currency;
00458     gchar * mnemonic;
00459 
00460     currency = (PQCurrency *)value;
00461     mnemonic = (gchar*) data;
00462     return (g_strcmp0 (currency->mnemonic, mnemonic)) ? FALSE: TRUE;
00463 }
00464 
00465 gint32
00466 pq_set_currency (QofInstance * inst, gchar * mnemonic)
00467 {
00468     PQCurrency *currency;
00469 
00470     currency = NULL;
00471     if (!PQCurrencyTable)
00472         populate_currencies ();
00473     currency = g_hash_table_find (PQCurrencyTable, currency_cb, mnemonic);
00474     if (!currency)
00475         return 0;
00476     pq_currency_lookup (inst, currency->pq_code);
00477     return currency->pq_code;
00478 }
00479 
00486 typedef struct
00487 {
00488     QofInstance inst;
00489     Expense_t wrap;             // 0.12
00490     enum ExpenseDistance distance_unit;
00491     gchar *category;
00492     const gchar *print_string;
00493     PQCurrency *currency;
00494     gdouble temp_amount;     
00497     gboolean reset_amount;   
00498 } QofExpense;
00499 
00500 Expense_t * pq_expense_get_pilot (QofEntity * inst)
00501 {
00502     QofExpense * e;
00503 
00504     e = (QofExpense*)inst;
00505     return &e->wrap;
00506 }
00507 
00508 static QofExpense *
00509 expense_create (QofBook * book)
00510 {
00511     Expense_t *qe;
00512     QofExpense *obj;
00513     QofCollection *coll;
00514     GList *all;
00515 
00516     obj = g_new0 (QofExpense, 1);
00517     qof_instance_init (&obj->inst, PILOT_LINK_QOF_EXPENSES, book);
00518     coll = qof_book_get_collection (book, PILOT_LINK_QOF_EXPENSES);
00519     all = qof_collection_get_data (coll);
00520     all = g_list_prepend (all, obj);
00521     qof_collection_set_data (coll, all);
00522     qe = &obj->wrap;
00523     qe->amount = g_strdup("0");
00524     /* 0 == AU$ so use an init value */
00525     qe->currency = -1;
00526     return obj;
00527 }
00528 
00529 static const gchar *
00530 qof_exp_distanceAsString (enum ExpenseDistance distance)
00531 {
00532     const gchar *string;
00533     gint i;
00534 
00535     string = "Miles";           // following install-expenses convention.
00536     for (i = 0; ExpenseDistanceNames[i] != NULL; i++)
00537     {
00538         if (i == (gint) distance)
00539             string = ExpenseDistanceNames[(gint) distance];
00540     }
00541     return string;
00542 }
00543 
00544 static const gchar *
00545 qof_exp_paymentAsString (enum ExpensePayment payment)
00546 {
00547     const gchar *string;
00548     gint i;
00549 
00550     string = "Cash";            // following install-expenses convention.
00551     for (i = 0; ExpensePaymentNames[i] != NULL; i++)
00552     {
00553         if (i == (gint) payment)
00554             string = ExpensePaymentNames[(gint) payment];
00555     }
00556     return string;
00557 }
00558 
00559 static const gchar *
00560 qof_exp_typeAsString (enum ExpenseType type)
00561 {
00562     const gchar *string;
00563     gint i;
00564 
00565     string = "Bus";             // following install-expenses convention.
00566     for (i = 0; ExpenseTypeNames[i] != NULL; i++)
00567     {
00568         if (i == (gint) type)
00569             string = ExpenseTypeNames[(gint) type];
00570     }
00571     return string;
00572 }
00573 
00574 static enum ExpensePayment
00575 qof_exp_paymentFromString (const gchar * payment_string)
00576 {
00577     guint i;
00578 
00579     for (i = 0; ExpensePaymentNames[i] != NULL; i++)
00580     {
00581         if (0 == safe_strcmp (ExpensePaymentNames[i], payment_string))
00582         {
00583             return (enum ExpensePayment) i;
00584         }
00585     }
00586     return epCash;
00587 }
00588 
00589 static enum ExpenseType
00590 qof_exp_typeFromString (const gchar * type_string)
00591 {
00592     guint i;
00593 
00594     for (i = 0; ExpenseTypeNames[i] != NULL; i++)
00595     {
00596         if (0 == safe_strcmp (ExpenseTypeNames[i], type_string))
00597             return (enum ExpenseType) i;
00598     }
00599     return etBus;
00600 }
00601 
00602 static QofTime*
00603 exp_getTime (QofExpense * e)
00604 {
00605     Expense_t *qe;
00606     QofTime *qt;
00607 
00608     g_return_val_if_fail (e != NULL, NULL);
00609     qe = &e->wrap;
00610     qt = qof_time_from_tm (&qe->date, 0);
00611     return qt;
00612 }
00613 
00614 static const gchar *
00615 exp_getType (QofExpense * e)
00616 {
00617     Expense_t *qe;
00618 
00619     g_return_val_if_fail (e != NULL, NULL);
00620     qe = &e->wrap;
00621     return qof_exp_typeAsString (qe->type);
00622 }
00623 
00624 static const gchar *
00625 exp_getPayment (QofExpense * e)
00626 {
00627     Expense_t *qe;
00628 
00629     g_return_val_if_fail (e != NULL, NULL);
00630     qe = &e->wrap;
00631     return qof_exp_paymentAsString (qe->payment);
00632 }
00633 
00634 static gint
00635 exp_getCurrency (QofExpense * e)
00636 {
00637     Expense_t *qe;
00638 
00639     g_return_val_if_fail (e != NULL, -1);
00640     qe = &e->wrap;
00641     return qe->currency;
00642 }
00643 
00644 static QofNumeric
00645 exp_getAmount (QofExpense * e)
00646 {
00647     Expense_t *qe;
00648     QofNumeric amount;
00649     gdouble pi_amount;
00650     gchar *numeric_char;
00651 
00652     amount = qof_numeric_zero ();
00653     g_return_val_if_fail (e != NULL, amount);
00654     qe = &e->wrap;
00655     if (qe->amount == 0)
00656         return amount;
00657     /* floating point as a string converts to gnc_numeric */
00658     pi_amount = strtod (qe->amount, NULL);
00659     if (e->currency)
00660         amount = qof_numeric_from_double (pi_amount, e->currency->fraction,
00661             QOF_HOW_DENOM_EXACT | QOF_HOW_RND_ROUND);
00662     else
00663     /* default: use the most common fraction in the Palm currency list. */
00664         amount = qof_numeric_from_double (pi_amount, 100,
00665             QOF_HOW_DENOM_EXACT | QOF_HOW_RND_ROUND);
00666     numeric_char = qof_numeric_to_string (amount);
00667     g_free (numeric_char);
00668     if (qof_numeric_check (amount) == QOF_ERROR_OK)
00669         return amount;
00670     return qof_numeric_zero ();
00671 }
00672 
00673 static const gchar *
00674 exp_getVendor (QofExpense * e)
00675 {
00676     Expense_t *qe;
00677 
00678     g_return_val_if_fail (e != NULL, NULL);
00679     qe = &e->wrap;
00680     return qe->vendor;
00681 }
00682 
00683 static const gchar *
00684 exp_getCity (QofExpense * e)
00685 {
00686     Expense_t *qe;
00687 
00688     g_return_val_if_fail (e != NULL, NULL);
00689     qe = &e->wrap;
00690     return qe->city;
00691 }
00692 
00693 static const gchar *
00694 exp_getAttendees (QofExpense * e)
00695 {
00696     Expense_t *qe;
00697 
00698     g_return_val_if_fail (e != NULL, NULL);
00699     qe = &e->wrap;
00700     return qe->attendees;
00701 }
00702 
00703 static const gchar *
00704 exp_getNote (QofExpense * e)
00705 {
00706     Expense_t *qe;
00707 
00708     g_return_val_if_fail (e != NULL, NULL);
00709     qe = &e->wrap;
00710     return qe->note;
00711 }
00712 
00713 static const gchar *
00714 exp_getDistance (QofExpense * e)
00715 {
00716     guint i;
00717     Expense_t *qe;
00718     enum ExpenseDistance type;
00719 
00720     qe = &e->wrap;
00721     type = edMiles;
00722     if (qe->type != etMileage)
00723         return NULL;
00724     for (i = 0; ExpenseDistanceNames[i] != NULL; i++)
00725     {
00726         if (i == e->distance_unit)
00727             type = (enum ExpenseDistance) i;
00728     }
00729     return qof_exp_distanceAsString (type);
00730 }
00731 
00732 static const gchar *
00733 exp_getCategory (QofExpense * e)
00734 {
00735     g_return_val_if_fail (e != NULL, NULL);
00736     return e->category;
00737 }
00738 
00739 static void
00740 exp_setTime (QofExpense * e, QofTime *h)
00741 {
00742     Expense_t *qe;
00743     gboolean result;
00744     QofDate *qd;
00745 
00746     g_return_if_fail (e != NULL);
00747     qe = &e->wrap;
00748     qd = qof_date_from_qtime (h);
00749     result = qof_date_to_struct_tm (qd, &qe->date, 0);
00750     if(!result)
00751         PERR (" Date too large for begin.");
00752     qof_date_free (qd);
00753 }
00754 
00755 static void
00756 exp_setType (QofExpense * e, const gchar * type_string)
00757 {
00758     Expense_t *qe;
00759 
00760     g_return_if_fail (e != NULL);
00761     qe = &e->wrap;
00762     qe->type = qof_exp_typeFromString (type_string);
00763 }
00764 
00765 static void
00766 exp_setPayment (QofExpense * e, const gchar * payment_string)
00767 {
00768     Expense_t *qe;
00769 
00770     g_return_if_fail (e != NULL);
00771     qe = &e->wrap;
00772     qe->payment = qof_exp_paymentFromString (payment_string);
00773 }
00774 
00775 static void
00776 exp_combine_currency_with_amount (QofExpense * e)
00777 {
00778     Expense_t *qe;
00779 
00780     g_return_if_fail (e != NULL);
00781     qe = &e->wrap;
00782     if (!e->currency || qe->currency < 0)
00783     {
00784         /* the gint32 currency is always set AFTER the numeric amount. :-( */
00785         e->currency = pq_currency_lookup ((QofInstance *) e, 
00786             qe->currency);
00787     }
00788     if (!e->currency)
00789     {
00790         PERR (" Unable to identify currency fraction."
00791             " Using two decimal places.");
00792         /* Amount is stored in the Palm as a string version
00793            of a floating point number. */
00794         qe->amount = g_strdup_printf ("%.2f", e->temp_amount);
00795         return;
00796     }
00797     switch (e->currency->fraction)
00798     {
00799     case 1:
00800         {
00801             qe->amount = g_strdup_printf ("%.0f", e->temp_amount);
00802             break;
00803         }
00804     case 10:
00805         {
00806             qe->amount = g_strdup_printf ("%.1f", e->temp_amount);
00807             break;
00808         }
00809     case 100:
00810         {
00811             qe->amount = g_strdup_printf ("%.2f", e->temp_amount);
00812             break;
00813         }
00814     case 1000:
00815         {
00816             qe->amount = g_strdup_printf ("%.3f", e->temp_amount);
00817             break;
00818         }
00819     default:
00820         {
00821             PERR (" Invalid currency fraction."
00822                 " Using two decimal places as default.");
00823             qe->amount = g_strdup_printf ("%.2f", e->temp_amount);
00824         }
00825     }
00826 }
00827 
00828 static void
00829 exp_setCurrency (QofExpense * e, gint code)
00830 {
00831     Expense_t *qe;
00832 
00833     g_return_if_fail (e != NULL);
00834     qe = &e->wrap;
00835     qe->currency = code;
00836     e->currency = pq_currency_lookup ((QofInstance *) e, code);
00837     if (e->reset_amount)
00838         exp_combine_currency_with_amount (e);
00839     e->reset_amount = FALSE;
00840 }
00841 
00842 static void
00843 exp_setAmount (QofExpense * e, QofNumeric h)
00844 {
00845     Expense_t *qe;
00846 
00847     g_return_if_fail (e != NULL);
00848     qe = &e->wrap;
00849     g_return_if_fail (qe != NULL);
00850     e->temp_amount = qof_numeric_to_double (h);
00851     e->reset_amount = TRUE;
00852     /* if an amount can ever be set without a currency_code,
00853        this needs to be reviewed. */
00856     if (e->currency)
00857         exp_combine_currency_with_amount (e);
00858 }
00859 
00860 static void
00861 exp_setVendor (QofExpense * e, gchar * h)
00862 {
00863     Expense_t *qe;
00864 
00865     g_return_if_fail (e != NULL);
00866     qe = &e->wrap;
00867     qe->vendor = g_strdup (qof_util_make_utf8 (h));
00868 }
00869 
00870 static void
00871 exp_setCity (QofExpense * e, gchar * h)
00872 {
00873     Expense_t *qe;
00874 
00875     g_return_if_fail (e != NULL);
00876     qe = &e->wrap;
00877     qe->city = g_strdup (qof_util_make_utf8 (h));
00878 }
00879 
00880 static void
00881 exp_setAttendees (QofExpense * e, gchar * h)
00882 {
00883     Expense_t *qe;
00884 
00885     g_return_if_fail (e != NULL);
00886     qe = &e->wrap;
00887     qe->attendees = g_strdup (qof_util_make_utf8 (h));
00888 }
00889 
00890 static void
00891 exp_setNote (QofExpense * e, gchar * h)
00892 {
00893     Expense_t *qe;
00894 
00895     g_return_if_fail (e != NULL);
00896     qe = &e->wrap;
00897     qe->note = g_strdup (qof_util_make_utf8 (h));
00898 }
00899 
00900 static void
00901 exp_setDistance (QofExpense * e, const gchar * distance_name)
00902 {
00903     gint i;
00905     for (i = 0; ExpenseDistanceNames[i] != NULL; i++)
00906     {
00907         if (0 == safe_strcmp (ExpenseDistanceNames[i], distance_name))
00908         {
00909             e->distance_unit = i;
00910         }
00911     }
00912 }
00913 
00914 static void
00915 exp_setCategory (QofExpense * e, gchar * n)
00916 {
00917     g_return_if_fail (e != NULL);
00918     e->category = g_strdup (qof_util_make_utf8 (n));
00919 }
00920 
00921 static const gchar *
00922 expensePrintable (gpointer instance)
00923 {
00924     QofExpense *obj;
00925 
00926     obj = (QofExpense *) instance;
00927     if (!obj)
00928         return NULL;
00929     if (exp_getType (obj))
00930         return g_strconcat (exp_getType (obj), " ",
00931             exp_getVendor (obj), " ", exp_getCity (obj), NULL);
00932     return NULL;
00933 }
00934 
00935 static QofObject expenses_object_def = {
00936   interface_version  :  QOF_OBJECT_VERSION,
00937   e_type             :  PILOT_LINK_QOF_EXPENSES,
00938   type_label         :  PQOF_EXPENSES_DESC,
00939   create             :  (gpointer) expense_create,
00940   book_begin         :  NULL,
00941   book_end           :  NULL,
00942   is_dirty           :  qof_collection_is_dirty,
00943   mark_clean         :  qof_collection_mark_clean,
00944   foreach            :  qof_collection_foreach,
00945   printable          :  expensePrintable,
00946   version_cmp        :  (gint (*)(gpointer, gpointer)) qof_instance_version_cmp,
00947 };
00948 
00949 gboolean
00950 PQExpensesRegister (void)
00951 {
00952     static QofParam params[] = {
00953         {EXP_DATE, QOF_TYPE_TIME, (QofAccessFunc) exp_getTime,
00954                 (QofSetterFunc) exp_setTime},
00955         {EXP_TYPE, QOF_TYPE_STRING, (QofAccessFunc) exp_getType,
00956                 (QofSetterFunc) exp_setType},
00957         {EXP_PAYMENT, QOF_TYPE_STRING, (QofAccessFunc) exp_getPayment,
00958                 (QofSetterFunc) exp_setPayment},
00959         {EXP_CURRENCY, QOF_TYPE_INT32, (QofAccessFunc) exp_getCurrency,
00960                 (QofSetterFunc) exp_setCurrency},
00961         {EXP_AMOUNT, QOF_TYPE_NUMERIC, (QofAccessFunc) exp_getAmount,
00962                 (QofSetterFunc) exp_setAmount},
00963         {EXP_VENDOR, QOF_TYPE_STRING, (QofAccessFunc) exp_getVendor,
00964                 (QofSetterFunc) exp_setVendor},
00965         {EXP_CITY, QOF_TYPE_STRING, (QofAccessFunc) exp_getCity,
00966                 (QofSetterFunc) exp_setCity},
00967         {EXP_ATTENDEES, QOF_TYPE_STRING, (QofAccessFunc) exp_getAttendees,
00968                 (QofSetterFunc) exp_setAttendees},
00969         {EXP_NOTE, QOF_TYPE_STRING, (QofAccessFunc) exp_getNote,
00970                 (QofSetterFunc) exp_setNote},
00971         {EXP_DISTANCE, QOF_TYPE_STRING, (QofAccessFunc) exp_getDistance,
00972                 (QofSetterFunc) exp_setDistance},
00973         {EXP_CATEGORY, QOF_TYPE_STRING, (QofAccessFunc) exp_getCategory,
00974                 (QofSetterFunc) exp_setCategory},
00975         {EXP_KVP, QOF_TYPE_KVP, (QofAccessFunc) qof_instance_get_slots,
00976                 NULL},
00977         {QOF_PARAM_BOOK, QOF_ID_BOOK,
00978                 (QofAccessFunc) qof_instance_get_book, NULL},
00979         {QOF_PARAM_GUID, QOF_TYPE_GUID,
00980                 (QofAccessFunc) qof_instance_get_guid, NULL},
00981         {NULL},
00982     };
00983 
00984     qof_class_register (PILOT_LINK_QOF_EXPENSES, NULL, params);
00985 
00986     return qof_object_register (&expenses_object_def);
00987 }
00988