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