1 /********************************************************************\
2  * split-register-model-save.c -- split register model object       *
3  * Copyright (C) 2017 Aaron Laws                                    *
4  *                                                                  *
5  * This program is free software; you can redistribute it and/or    *
6  * modify it under the terms of the GNU General Public License as   *
7  * published by the Free Software Foundation; either version 2 of   *
8  * the License, or (at your option) any later version.              *
9  *                                                                  *
10  * This program is distributed in the hope that it will be useful,  *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
13  * GNU General Public License for more details.                     *
14  *                                                                  *
15  * You should have received a copy of the GNU General Public License*
16  * along with this program; if not, contact:                        *
17  *                                                                  *
18  * Free Software Foundation           Voice:  +1-617-542-5942       *
19  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
20  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
21  *                                                                  *
22 \********************************************************************/
23 
24 #include <config.h>
25 
26 #include <glib.h>
27 
28 #include "Scrub.h"
29 #include "SchedXaction.h"
30 #include "datecell.h"
31 #include "gnc-engine.h"
32 #include "engine-helpers.h"
33 #include "numcell.h"
34 #include "pricecell.h"
35 #include "recncell.h"
36 #include "split-register-model-save.h"
37 #include "split-register-p.h"
38 #include "gnc-exp-parser.h"
39 
40 
41 struct sr_save_data
42 {
43     Transaction *trans;
44     Split *split;
45 
46     gboolean handled_dc; /* We have already handled the debit/credit cells. */
47     gboolean do_scrub;   /* Scrub other split at the end. */
48     gboolean reg_expanded; /* Register is in expanded (split) mode */
49 };
50 
51 /* This static indicates the debugging module that this .o belongs to. */
52 static QofLogModule log_module = GNC_MOD_LEDGER;
53 
54 
55 static void
gnc_split_register_save_date_cell(BasicCell * cell,gpointer save_data,gpointer user_data)56 gnc_split_register_save_date_cell (BasicCell * cell,
57                                    gpointer save_data,
58                                    gpointer user_data)
59 {
60     SRSaveData *sd = save_data;
61     const char *value;
62     time64 cell_time;
63 
64     g_return_if_fail (gnc_basic_cell_has_name (cell, DATE_CELL));
65 
66     value = gnc_basic_cell_get_value (cell);
67 
68     DEBUG ("DATE: %s", value ? value : "(null)");
69 
70     gnc_date_cell_get_date ((DateCell *) cell, &cell_time, TRUE);
71 
72     /* commit any pending changes */
73     gnc_date_cell_commit ((DateCell *) cell);
74 
75     xaccTransSetDatePostedSecsNormalized (sd->trans, cell_time);
76 }
77 
78 static void
gnc_split_register_save_type_cell(BasicCell * cell,gpointer save_data,gpointer user_data)79 gnc_split_register_save_type_cell (BasicCell * cell,
80                                    gpointer save_data,
81                                    gpointer user_data)
82 {
83     SRSaveData *sd = save_data;
84     char value;
85 
86     g_return_if_fail (gnc_basic_cell_has_name (cell, TYPE_CELL));
87 
88     value = gnc_recn_cell_get_flag ((RecnCell *)cell);
89 
90     xaccTransSetTxnType (sd->trans, value);
91 }
92 
93 static void
gnc_split_register_save_due_date_cell(BasicCell * cell,gpointer save_data,gpointer user_data)94 gnc_split_register_save_due_date_cell (BasicCell * cell,
95                                        gpointer save_data,
96                                        gpointer user_data)
97 {
98     SRSaveData *sd = save_data;
99     const char *value;
100     time64 time;
101     g_return_if_fail (gnc_basic_cell_has_name (cell, DDUE_CELL));
102     value = gnc_basic_cell_get_value (cell);
103     /* commit any pending changes */
104     gnc_date_cell_commit ((DateCell *) cell);
105     DEBUG ("DATE: %s", value ? value : "(null)");
106     gnc_date_cell_get_date ((DateCell *) cell, &time, TRUE);
107     xaccTransSetDateDue (sd->trans, time);
108 }
109 
110 static void
gnc_split_register_save_num_cell(BasicCell * cell,gpointer save_data,gpointer user_data)111 gnc_split_register_save_num_cell (BasicCell * cell,
112                                   gpointer save_data,
113                                   gpointer user_data)
114 {
115     SRSaveData *sd = save_data;
116     SplitRegister *reg = user_data;
117     const char *value;
118 
119     g_return_if_fail (gnc_basic_cell_has_name (cell, NUM_CELL));
120 
121     value = gnc_basic_cell_get_value (cell);
122 
123     DEBUG ("NUM: %s\n", value ? value : "(null)");
124 
125     /* set per book option */
126     gnc_set_num_action (sd->trans, sd->split, value, NULL);
127 
128     if (gnc_num_cell_set_last_num ((NumCell *) cell, value))
129     {
130         SRInfo *info = gnc_split_register_get_info (reg);
131         Split *blank_split = xaccSplitLookup (&info->blank_split_guid,
132                                                   gnc_get_current_book ());
133         Transaction *blank_trans = xaccSplitGetParent (blank_split);
134 
135         if (sd->trans == blank_trans)
136            gnc_split_register_set_last_num (reg, gnc_basic_cell_get_value (cell));
137     }
138 }
139 
140 static void
gnc_split_register_save_tnum_cell(BasicCell * cell,gpointer save_data,gpointer user_data)141 gnc_split_register_save_tnum_cell (BasicCell * cell,
142                                   gpointer save_data,
143                                   gpointer user_data)
144 {
145     SRSaveData *sd = save_data;
146     const char *value;
147 
148     g_return_if_fail (gnc_basic_cell_has_name (cell, TNUM_CELL));
149 
150     value = gnc_basic_cell_get_value (cell);
151 
152     DEBUG ("TNUM: %s\n", value ? value : "(null)");
153 
154     /* set tran-num using utility function */
155     gnc_set_num_action (sd->trans, NULL, value, NULL);
156 }
157 
158 static void
gnc_split_register_save_desc_cell(BasicCell * cell,gpointer save_data,gpointer user_data)159 gnc_split_register_save_desc_cell (BasicCell * cell,
160                                    gpointer save_data,
161                                    gpointer user_data)
162 {
163     SRSaveData *sd = save_data;
164     const char *value;
165 
166     g_return_if_fail (gnc_basic_cell_has_name (cell, DESC_CELL));
167 
168     value = gnc_basic_cell_get_value (cell);
169 
170     DEBUG ("DESC: %s", value ? value : "(null)");
171 
172     xaccTransSetDescription (sd->trans, value);
173 }
174 
175 static void
gnc_split_register_save_notes_cell(BasicCell * cell,gpointer save_data,gpointer user_data)176 gnc_split_register_save_notes_cell (BasicCell * cell,
177                                     gpointer save_data,
178                                     gpointer user_data)
179 {
180     SRSaveData *sd = save_data;
181     const char *value;
182 
183     g_return_if_fail (gnc_basic_cell_has_name (cell, NOTES_CELL));
184 
185     value = gnc_basic_cell_get_value (cell);
186 
187     DEBUG ("NOTES: %s", value ? value : "(null)");
188 
189     xaccTransSetNotes (sd->trans, value);
190 }
191 
192 static void
gnc_split_register_save_recn_cell(BasicCell * bcell,gpointer save_data,gpointer user_data)193 gnc_split_register_save_recn_cell (BasicCell * bcell,
194                                    gpointer save_data,
195                                    gpointer user_data)
196 {
197     SRSaveData *sd = save_data;
198     RecnCell *cell = (RecnCell *) bcell;
199 
200     g_return_if_fail (gnc_basic_cell_has_name (bcell, RECN_CELL));
201 
202     DEBUG ("RECN: %c", gnc_recn_cell_get_flag (cell));
203 
204     xaccSplitSetReconcile (sd->split, gnc_recn_cell_get_flag (cell));
205 }
206 
207 static void
gnc_split_register_save_actn_cell(BasicCell * cell,gpointer save_data,gpointer user_data)208 gnc_split_register_save_actn_cell (BasicCell * cell,
209                                    gpointer save_data,
210                                    gpointer user_data)
211 {
212     SRSaveData *sd = save_data;
213     const char *value;
214 
215     g_return_if_fail (gnc_basic_cell_has_name (cell, ACTN_CELL));
216 
217     value = gnc_basic_cell_get_value (cell);
218 
219     DEBUG ("ACTN: %s", value ? value : "(null)");
220 
221     /* Set split-action with gnc_set_num_action which is the same as
222      * xaccSplitSetAction with these arguments */
223     gnc_set_num_action (NULL, sd->split, NULL, value);
224 }
225 
226 static void
gnc_split_register_save_memo_cell(BasicCell * cell,gpointer save_data,gpointer user_data)227 gnc_split_register_save_memo_cell (BasicCell * cell,
228                                    gpointer save_data,
229                                    gpointer user_data)
230 {
231     SRSaveData *sd = save_data;
232     const char *value;
233 
234     g_return_if_fail (gnc_basic_cell_has_name (cell, MEMO_CELL));
235 
236     value = gnc_basic_cell_get_value (cell);
237 
238     DEBUG ("MEMO: %s", value ? value : "(null)");
239 
240     xaccSplitSetMemo (sd->split, value);
241 }
242 
243 /* OK, the handling of transfers gets complicated because it depends
244  * on what was displayed to the user. For a multi-line display, we
245  * just reparent the indicated split. For a two-line display, we want
246  * to reparent the "other" split, but only if there is one. XFRM is
247  * the straight split, MXFRM is the mirrored split. */
248 static void
gnc_split_register_save_xfrm_cell(BasicCell * cell,gpointer save_data,gpointer user_data)249 gnc_split_register_save_xfrm_cell (BasicCell * cell,
250                                    gpointer save_data,
251                                    gpointer user_data)
252 {
253     SRSaveData *sd = save_data;
254     SplitRegister *reg = user_data;
255     Account *old_acc;
256     Account *new_acc;
257 
258     g_return_if_fail (gnc_basic_cell_has_name (cell, XFRM_CELL));
259 
260     old_acc = xaccSplitGetAccount (sd->split);
261 
262     new_acc = gnc_split_register_get_account (reg, XFRM_CELL);
263 
264     if ((new_acc != NULL) && (old_acc != new_acc))
265         xaccAccountInsertSplit (new_acc, sd->split);
266 }
267 
268 static void
gnc_split_register_save_mxfrm_cell(BasicCell * cell,gpointer save_data,gpointer user_data)269 gnc_split_register_save_mxfrm_cell (BasicCell * cell,
270                                     gpointer save_data,
271                                     gpointer user_data)
272 {
273     SRSaveData *sd = save_data;
274     SplitRegister *reg = user_data;
275     Split * other_split;
276 
277     g_return_if_fail (gnc_basic_cell_has_name (cell, MXFRM_CELL));
278 
279     other_split = xaccSplitGetOtherSplit (sd->split);
280 
281     /* other_split may be null for two very different reasons:
282      * (1) the parent transaction has three or more splits in it,
283      *     and so the "other" split is ambiguous, and thus null.
284      * (2) the parent transaction has only this one split as a child.
285      *     and "other" is null because there is no other.
286      *
287      * In the case (2), we want to create the other split, so that
288      * the user's request to transfer actually works out. */
289 
290     if (!other_split)
291     {
292         other_split = xaccTransGetSplit (sd->trans, 1);
293 
294         if (!other_split)
295         {
296             other_split = xaccMallocSplit (gnc_get_current_book ());
297             xaccTransAppendSplit (sd->trans, other_split);
298         }
299     }
300 
301     if (other_split)
302     {
303         Account *old_acc;
304         Account *new_acc;
305 
306         /* Do some reparenting. Insertion into new account
307          * will automatically delete from the old account. */
308         old_acc = xaccSplitGetAccount (other_split);
309         new_acc = gnc_split_register_get_account (reg, MXFRM_CELL);
310 
311         if ((new_acc != NULL) && (old_acc != new_acc))
312             xaccAccountInsertSplit (new_acc, other_split);
313     }
314 }
315 
316 static void
gnc_split_register_save_shares_cell(BasicCell * bcell,gpointer save_data,gpointer user_data)317 gnc_split_register_save_shares_cell (BasicCell * bcell,
318                                      gpointer save_data,
319                                      gpointer user_data)
320 {
321     SRSaveData *sd = save_data;
322     PriceCell *cell = (PriceCell *) bcell;
323     gnc_numeric amount;
324 
325     g_return_if_fail (gnc_basic_cell_has_name (bcell, SHRS_CELL));
326 
327     amount = gnc_price_cell_get_value (cell);
328 
329     DEBUG ("SHRS");
330 
331     xaccSplitSetAmount (sd->split, amount);
332 
333     sd->do_scrub = TRUE;
334 }
335 
336 static void
gnc_split_register_save_price_cell(BasicCell * bcell,gpointer save_data,gpointer user_data)337 gnc_split_register_save_price_cell (BasicCell * bcell,
338                                     gpointer save_data,
339                                     gpointer user_data)
340 {
341     SRSaveData *sd = save_data;
342     PriceCell *cell = (PriceCell *) bcell;
343     gnc_numeric price;
344 
345     g_return_if_fail (gnc_basic_cell_has_name (bcell, PRIC_CELL));
346 
347     price = gnc_price_cell_get_value (cell);
348 
349     DEBUG ("PRIC");
350 
351     /* If we handled the Debcred cell then don't set the share price! */
352     if (!sd->handled_dc)
353         xaccSplitSetSharePrice (sd->split, price);
354 
355     sd->do_scrub = TRUE;
356 }
357 
358 gnc_numeric
gnc_split_register_debcred_cell_value(SplitRegister * reg)359 gnc_split_register_debcred_cell_value (SplitRegister *reg)
360 {
361     PriceCell *cell;
362     gnc_numeric new_amount;
363     gnc_numeric credit;
364     gnc_numeric debit;
365 
366     cell = (PriceCell *) gnc_table_layout_get_cell (reg->table->layout,
367             CRED_CELL);
368     credit = gnc_price_cell_get_value (cell);
369 
370     cell = (PriceCell *) gnc_table_layout_get_cell (reg->table->layout,
371             DEBT_CELL);
372     debit  = gnc_price_cell_get_value (cell);
373 
374     new_amount = gnc_numeric_sub_fixed (debit, credit);
375 
376     return new_amount;
377 }
378 
379 static gnc_numeric
gnc_split_register_get_rate_cell(SplitRegister * reg,const char * cell_name)380 gnc_split_register_get_rate_cell (SplitRegister *reg, const char *cell_name)
381 {
382     PriceCell *rate_cell;
383 
384     rate_cell = (PriceCell*) gnc_table_layout_get_cell (reg->table->layout,
385                 cell_name);
386     if (rate_cell)
387         return gnc_price_cell_get_value (rate_cell);
388 
389     /* Uhh, just return '1' */
390     return gnc_numeric_create (100, 100);
391 }
392 
393 gboolean
gnc_split_register_split_needs_amount(SplitRegister * reg,Split * split)394 gnc_split_register_split_needs_amount (SplitRegister *reg, Split *split)
395 {
396     Transaction *txn = xaccSplitGetParent (split);
397     Account *acc = xaccSplitGetAccount (split);
398 
399     return gnc_split_register_needs_conv_rate (reg, txn, acc);
400 }
401 
402 static void
gnc_split_register_save_amount_values(SRSaveData * sd,SplitRegister * reg)403 gnc_split_register_save_amount_values (SRSaveData *sd, SplitRegister *reg)
404 {
405     Account *acc;
406     gnc_numeric new_amount, convrate, amtconv, value;
407     gnc_commodity *curr, *reg_com, *xfer_com;
408     Account *xfer_acc;
409 
410     new_amount = gnc_split_register_debcred_cell_value (reg);
411     acc = gnc_split_register_get_default_account (reg);
412 
413     xfer_acc = xaccSplitGetAccount (sd->split);
414     xfer_com = xaccAccountGetCommodity (xfer_acc);
415     reg_com = xaccAccountGetCommodity (acc);
416     curr = xaccTransGetCurrency (sd->trans);
417 
418     /* First, compute the conversion rate to convert the value to the
419       * amount.
420       */
421     amtconv = convrate = gnc_split_register_get_rate_cell (reg, RATE_CELL);
422     if (acc && gnc_split_register_needs_conv_rate (reg, sd->trans, acc))
423     {
424 
425         /* If we are in an expanded register and the xfer_acc->comm !=
426         * reg_acc->comm then we need to compute the convrate here.
427         * Otherwise, we _can_ use the rate_cell!
428         */
429         if (sd->reg_expanded && ! gnc_commodity_equal (reg_com, xfer_com))
430             amtconv = xaccTransGetAccountConvRate(sd->trans, acc);
431     }
432 
433     if (xaccTransUseTradingAccounts (sd->trans))
434     {
435         /* Using currency accounts, the amount is probably really the
436            amount and not the value. */
437         gboolean is_amount;
438         if (reg->type == STOCK_REGISTER ||
439                 reg->type == CURRENCY_REGISTER ||
440                 reg->type == PORTFOLIO_LEDGER)
441         {
442             if (xaccAccountIsPriced(xfer_acc) ||
443                     !gnc_commodity_is_iso(xaccAccountGetCommodity(xfer_acc)))
444                 is_amount = FALSE;
445             else
446                 is_amount = TRUE;
447         }
448         else
449         {
450             is_amount = TRUE;
451         }
452 
453         if (is_amount)
454         {
455             xaccSplitSetAmount(sd->split, new_amount);
456             if (gnc_split_register_split_needs_amount (reg, sd->split))
457             {
458                 value = gnc_numeric_div(new_amount, amtconv,
459                                         gnc_commodity_get_fraction(curr),
460                                         GNC_HOW_RND_ROUND_HALF_UP);
461                 xaccSplitSetValue(sd->split, value);
462             }
463             else
464                 xaccSplitSetValue(sd->split, new_amount);
465         }
466         else
467         {
468             xaccSplitSetValue(sd->split, new_amount);
469         }
470 
471         return;
472     }
473 
474     /* How to interpret new_amount depends on our view of this
475      * transaction.  If we're sitting in an account with the same
476      * commodity as the transaction, then we can set the Value and then
477      * compute the amount.  Otherwise we are setting the "converted
478      * value".  This means we need to convert new_amount to the actual
479      * 'value' by dividing by the convrate in order to set the value.
480      */
481 
482     /* Now compute/set the split value.  Amount is in the register
483      * currency but we need to convert to the txn currency.
484      */
485     if (acc && gnc_split_register_needs_conv_rate (reg, sd->trans, acc))
486     {
487 
488         /* convert the amount to the Value ... */
489         value = gnc_numeric_div (new_amount, amtconv,
490                                  gnc_commodity_get_fraction (curr),
491                                  GNC_HOW_RND_ROUND_HALF_UP);
492         xaccSplitSetValue (sd->split, value);
493     }
494     else
495         xaccSplitSetValue (sd->split, new_amount);
496 
497     /* Now re-compute the Amount from the Value.  We may need to convert
498      * from the Value back to the amount here using the convrate from
499      * earlier.
500      */
501     value = xaccSplitGetValue (sd->split);
502 
503     if (gnc_split_register_split_needs_amount (reg, sd->split))
504     {
505         acc = xaccSplitGetAccount (sd->split);
506         new_amount = gnc_numeric_mul (value, convrate,
507                                       xaccAccountGetCommoditySCU (acc),
508                                       GNC_HOW_RND_ROUND_HALF_UP);
509         xaccSplitSetAmount (sd->split, new_amount);
510     }
511 }
512 
513 static void
gnc_split_register_save_debcred_cell(BasicCell * bcell,gpointer save_data,gpointer user_data)514 gnc_split_register_save_debcred_cell (BasicCell * bcell,
515                                       gpointer save_data,
516                                       gpointer user_data)
517 {
518     SRSaveData *sd = save_data;
519     SplitRegister *reg = user_data;
520 
521     g_return_if_fail (gnc_basic_cell_has_name (bcell, DEBT_CELL) ||
522                       gnc_basic_cell_has_name (bcell, CRED_CELL));
523 
524     if (sd->handled_dc)
525         return;
526 
527     gnc_split_register_save_amount_values (sd, reg);
528 
529     sd->handled_dc = TRUE;
530     sd->do_scrub = TRUE;
531 }
532 
533 static void
gnc_split_register_save_rate_cell(BasicCell * bcell,gpointer save_data,gpointer user_data)534 gnc_split_register_save_rate_cell (BasicCell * bcell,
535                                    gpointer save_data,
536                                    gpointer user_data)
537 {
538     SRSaveData *sd = save_data;
539 
540     /* if the exchrate cell changed, then make sure to force a scrub */
541     sd->do_scrub = TRUE;
542 }
543 
544 static void
gnc_split_register_save_cells(gpointer save_data,gpointer user_data)545 gnc_split_register_save_cells (gpointer save_data,
546                                gpointer user_data)
547 {
548     SRSaveData *sd = save_data;
549     SplitRegister *reg = user_data;
550     Split *other_split;
551     gnc_commodity *txn_cur;
552     gnc_numeric rate;
553 
554     g_return_if_fail (sd != NULL);
555 
556     if (!sd->do_scrub)
557         return;
558 
559     other_split = xaccSplitGetOtherSplit (sd->split);
560     txn_cur = xaccTransGetCurrency (sd->trans);
561 
562     xaccSplitScrub (sd->split);
563 
564     rate = gnc_split_register_get_rate_cell (reg, RATE_CELL);
565 
566     if (other_split && !sd->reg_expanded)
567     {
568         gnc_numeric amount, value = xaccSplitGetValue (sd->split);
569         Account *acc;
570         gboolean split_needs_amount;
571 
572         split_needs_amount = gnc_split_register_split_needs_amount(reg, sd->split);
573 
574         /* We are changing the rate on the current split, but it was not
575          * handled in the debcred handler, so we need to do it here.
576          */
577         if (!sd->handled_dc && split_needs_amount && !gnc_numeric_zero_p (rate))
578         {
579             gnc_numeric amount = xaccSplitGetAmount (sd->split);
580             value = gnc_numeric_div(
581                         amount, rate, gnc_commodity_get_fraction(txn_cur), GNC_HOW_RND_ROUND_HALF_UP);
582             xaccSplitSetValue (sd->split, value);
583 
584             /* XXX: do we need to set the amount on the other split? */
585         }
586 
587         /* Now reverse the value for the other split */
588         value = gnc_numeric_neg (value);
589 
590         if (gnc_split_register_split_needs_amount (reg, other_split))
591         {
592             acc = xaccSplitGetAccount (other_split);
593 
594             /* If we don't have an exchange rate then figure it out.  Or, if
595              * BOTH splits require an amount, then most likely we're in the
596              * strange case of having a transaction currency different than
597              * _both_ accounts -- so grab the other exchange rate.
598              */
599             if (gnc_numeric_zero_p (rate) || split_needs_amount)
600                 rate = xaccTransGetAccountConvRate(xaccSplitGetParent (other_split),
601                                                    acc);
602 
603             amount = gnc_numeric_mul (value, rate, xaccAccountGetCommoditySCU (acc),
604                                       GNC_HOW_RND_ROUND_HALF_UP);
605             xaccSplitSetAmount (other_split, amount);
606 
607         }
608 
609         xaccSplitSetValue (other_split, value);
610 
611         xaccSplitScrub (other_split);
612     }
613     else if (gnc_split_register_split_needs_amount (reg, sd->split) &&
614              ! gnc_numeric_zero_p (rate))
615     {
616         /* this is either a multi-split or expanded transaction, so only
617          * deal with this split...  In particular we need to reset the
618          * Value if the conv-rate changed.
619          *
620          * If we handled the debcred then no need to do anything there --
621          * the debcred handler did all the computation.  If NOT, then the
622          * convrate changed -- reset the value from the amount.
623          */
624         if (!sd->handled_dc)
625         {
626             gnc_split_register_save_amount_values (sd, reg);
627 #if 0
628             gnc_numeric value, amount;
629 
630             amount = xaccSplitGetAmount (sd->split);
631             value = gnc_numeric_div (amount, rate, gnc_commodity_get_fraction (txn_cur),
632                                      GNC_HOW_RND_ROUND_HALF_UP);
633             xaccSplitSetValue (sd->split, value);
634 #endif
635         }
636     }
637 }
638 
639 static void
gnc_template_register_save_unexpected_cell(BasicCell * cell,gpointer save_data,gpointer user_data)640 gnc_template_register_save_unexpected_cell (BasicCell * cell,
641         gpointer save_data,
642         gpointer user_data)
643 {
644     PERR ("unexpected changed fields in a template register");
645 }
646 
647 static void
gnc_template_register_save_xfrm_cell(BasicCell * cell,gpointer save_data,gpointer user_data)648 gnc_template_register_save_xfrm_cell (BasicCell * cell,
649                                       gpointer save_data,
650                                       gpointer user_data)
651 {
652     SRSaveData *sd = save_data;
653     SplitRegister *reg = user_data;
654     SRInfo *info = gnc_split_register_get_info (reg);
655     Account *template_acc;
656     const GncGUID *acctGUID;
657     Account *acct;
658 
659     g_return_if_fail (gnc_basic_cell_has_name (cell, XFRM_CELL));
660 
661     /* save the account GncGUID into the kvp_data. */
662     acct = gnc_split_register_get_account (reg, XFRM_CELL);
663     if (!acct)
664     {
665         PERR ("unknown account");
666         return;
667     }
668 
669     acctGUID = xaccAccountGetGUID (acct);
670     qof_instance_set (QOF_INSTANCE (sd->split),
671 		      "sx-account", acctGUID,
672 		      NULL);
673     template_acc = xaccAccountLookup (&info->template_account,
674                                       gnc_get_current_book ());
675 
676     /* set the actual account to the fake account for these templates */
677     xaccAccountInsertSplit (template_acc, sd->split);
678 }
679 
680 static void
gnc_template_register_save_mxfrm_cell(BasicCell * cell,gpointer save_data,gpointer user_data)681 gnc_template_register_save_mxfrm_cell (BasicCell * cell,
682                                        gpointer save_data,
683                                        gpointer user_data)
684 {
685 }
686 
687 static void
save_cell(SplitRegister * reg,Split * split,const char * cell_name)688 save_cell (SplitRegister *reg, Split* split, const char *cell_name)
689 {
690     const gboolean is_credit = g_strcmp0 (cell_name, FCRED_CELL) == 0;
691     const char *formula = is_credit ?
692         "sx-credit-formula" : "sx-debit-formula";
693     const char *numeric = is_credit ?
694         "sx-credit-numeric" : "sx-debit-numeric";
695     const char *value = gnc_table_layout_get_cell_value (reg->table->layout,
696                                                          cell_name);
697     gnc_numeric new_amount = gnc_numeric_zero ();
698     GHashTable *parser_vars = g_hash_table_new (g_str_hash, g_str_equal);
699     char *error_loc;
700 
701     /* If the value can be parsed into a numeric result (without any
702      * further variable definitions), store that numeric value
703      * additionally in the kvp. Otherwise store a zero numeric
704      * there.*/
705     const gboolean parse_result =
706         gnc_exp_parser_parse_separate_vars (value, &new_amount,
707                                             &error_loc, parser_vars);
708     if (!parse_result || g_hash_table_size (parser_vars) != 0)
709         new_amount = gnc_numeric_zero ();
710     g_hash_table_unref (parser_vars);
711     qof_instance_set (QOF_INSTANCE (split),
712 		  numeric, &new_amount,
713 		  formula, value,
714 		  NULL);
715 }
716 
717 static void
gnc_template_register_save_debcred_cell(BasicCell * cell,gpointer save_data,gpointer user_data)718 gnc_template_register_save_debcred_cell (BasicCell * cell,
719         gpointer save_data,
720         gpointer user_data)
721 {
722     SRSaveData *sd = save_data;
723     SplitRegister *reg = user_data;
724 
725     g_return_if_fail (gnc_basic_cell_has_name (cell, FDEBT_CELL) ||
726                       gnc_basic_cell_has_name (cell, FCRED_CELL));
727 
728     if (sd->handled_dc)
729         return;
730 
731     save_cell (reg, sd->split, FCRED_CELL);
732     save_cell (reg, sd->split, FDEBT_CELL);
733 
734     /* set the amount to an innocuous value */
735     /* Note that this marks the split dirty */
736     xaccSplitSetValue (sd->split, gnc_numeric_create (0, 1));
737 
738     sd->handled_dc = TRUE;
739 }
740 
741 static void
gnc_template_register_save_shares_cell(BasicCell * cell,gpointer save_data,gpointer user_data)742 gnc_template_register_save_shares_cell (BasicCell * cell,
743                                         gpointer save_data,
744                                         gpointer user_data)
745 {
746     SRSaveData *sd = save_data;
747     char *sharesStr = "(x + y)/42";
748 
749     g_return_if_fail (gnc_basic_cell_has_name (cell, SHRS_CELL));
750     /* FIXME: shares cells are numeric by definition. */
751     qof_instance_set (QOF_INSTANCE (sd->split),
752 		      "sx-shares", sharesStr,
753 		      NULL);
754 
755     /* set the shares to an innocuous value */
756     /* Note that this marks the split dirty */
757     xaccSplitSetSharePriceAndAmount (sd->split,
758                                      gnc_numeric_create (0, 1),
759                                      gnc_numeric_create (0, 1));
760 }
761 
762 void
gnc_split_register_model_add_save_handlers(TableModel * model)763 gnc_split_register_model_add_save_handlers (TableModel *model)
764 {
765     g_return_if_fail (model != NULL);
766 
767     gnc_table_model_set_save_handler (model,
768                                       gnc_split_register_save_date_cell,
769                                       DATE_CELL);
770 
771     gnc_table_model_set_save_handler (model,
772                                       gnc_split_register_save_due_date_cell,
773                                       DDUE_CELL);
774 
775     gnc_table_model_set_save_handler (model,
776                                       gnc_split_register_save_type_cell,
777                                       TYPE_CELL);
778 
779     gnc_table_model_set_save_handler (model,
780                                       gnc_split_register_save_num_cell,
781                                       NUM_CELL);
782 
783     gnc_table_model_set_save_handler (model,
784                                       gnc_split_register_save_tnum_cell,
785                                       TNUM_CELL);
786 
787     gnc_table_model_set_save_handler (model,
788                                       gnc_split_register_save_desc_cell,
789                                       DESC_CELL);
790 
791     gnc_table_model_set_save_handler (model,
792                                       gnc_split_register_save_notes_cell,
793                                       NOTES_CELL);
794 
795     gnc_table_model_set_save_handler (model,
796                                       gnc_split_register_save_recn_cell,
797                                       RECN_CELL);
798 
799     gnc_table_model_set_save_handler (model,
800                                       gnc_split_register_save_actn_cell,
801                                       ACTN_CELL);
802 
803     gnc_table_model_set_save_handler (model,
804                                       gnc_split_register_save_memo_cell,
805                                       MEMO_CELL);
806 
807     gnc_table_model_set_save_handler (model,
808                                       gnc_split_register_save_xfrm_cell,
809                                       XFRM_CELL);
810 
811     gnc_table_model_set_save_handler (model,
812                                       gnc_split_register_save_mxfrm_cell,
813                                       MXFRM_CELL);
814 
815     gnc_table_model_set_save_handler (model,
816                                       gnc_split_register_save_shares_cell,
817                                       SHRS_CELL);
818 
819     gnc_table_model_set_save_handler (model,
820                                       gnc_split_register_save_price_cell,
821                                       PRIC_CELL);
822 
823     gnc_table_model_set_save_handler (model,
824                                       gnc_split_register_save_debcred_cell,
825                                       DEBT_CELL);
826 
827     gnc_table_model_set_save_handler (model,
828                                       gnc_split_register_save_debcred_cell,
829                                       CRED_CELL);
830 
831     gnc_table_model_set_save_handler (model,
832                                       gnc_split_register_save_rate_cell,
833                                       RATE_CELL);
834 
835     gnc_table_model_set_post_save_handler (model, gnc_split_register_save_cells);
836 }
837 
838 void
gnc_template_register_model_add_save_handlers(TableModel * model)839 gnc_template_register_model_add_save_handlers (TableModel *model)
840 {
841     g_return_if_fail (model != NULL);
842 
843     gnc_split_register_model_add_save_handlers (model);
844 
845     gnc_table_model_set_save_handler (model,
846                                       gnc_template_register_save_unexpected_cell,
847                                       DATE_CELL);
848 
849     gnc_table_model_set_save_handler (model,
850                                       gnc_template_register_save_unexpected_cell,
851                                       DDUE_CELL);
852 
853     gnc_table_model_set_save_handler (model,
854                                       gnc_template_register_save_xfrm_cell,
855                                       XFRM_CELL);
856 
857     gnc_table_model_set_save_handler (model,
858                                       gnc_template_register_save_mxfrm_cell,
859                                       MXFRM_CELL);
860 
861     gnc_table_model_set_save_handler (model,
862                                       gnc_template_register_save_debcred_cell,
863                                       FDEBT_CELL);
864 
865     gnc_table_model_set_save_handler (model,
866                                       gnc_template_register_save_debcred_cell,
867                                       FCRED_CELL);
868 
869     gnc_table_model_set_save_handler (model,
870                                       gnc_template_register_save_shares_cell,
871                                       SHRS_CELL);
872 }
873 
874 SRSaveData *
gnc_split_register_save_data_new(Transaction * trans,Split * split,gboolean expanded)875 gnc_split_register_save_data_new (Transaction *trans, Split *split,
876                                   gboolean expanded)
877 {
878     SRSaveData *sd;
879 
880     g_return_val_if_fail (trans != NULL, NULL);
881     g_return_val_if_fail (split != NULL, NULL);
882 
883     sd = g_new0 (SRSaveData, 1);
884 
885     sd->trans = trans;
886     sd->split = split;
887     sd->handled_dc = FALSE;
888     sd->do_scrub = FALSE;
889     sd->reg_expanded = expanded;
890 
891     return sd;
892 }
893 
894 void
gnc_split_register_save_data_destroy(SRSaveData * sd)895 gnc_split_register_save_data_destroy (SRSaveData *sd)
896 {
897     g_free (sd);
898 }
899