GnuCash c935c2f+
Loading...
Searching...
No Matches
split-register-model-save.c
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"
37#include "split-register-p.h"
38#include "gnc-exp-parser.h"
39
40
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. */
52static QofLogModule log_module = GNC_MOD_LEDGER;
53
54
55static void
56gnc_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 */
74
75 xaccTransSetDatePostedSecsNormalized (sd->trans, cell_time);
76}
77
78static void
79gnc_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
93static void
94gnc_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 */
105 DEBUG ("DATE: %s", value ? value : "(null)");
106 gnc_date_cell_get_date ((DateCell *) cell, &time, TRUE);
107 xaccTransSetDateDue (sd->trans, time);
108}
109
110static void
111gnc_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
140static void
141gnc_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
158static void
159gnc_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
175static void
176gnc_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
192static void
193gnc_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
207static void
208gnc_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
226static void
227gnc_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. */
248static void
249gnc_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
268static void
269gnc_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
316static void
317gnc_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
336static void
337gnc_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
358gnc_numeric
359gnc_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
379static gnc_numeric
380gnc_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
393gboolean
394gnc_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
402static void
403gnc_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) ||
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,
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,
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,
508 GNC_HOW_RND_ROUND_HALF_UP);
509 xaccSplitSetAmount (sd->split, new_amount);
510 }
511}
512
513static void
514gnc_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
533static void
534gnc_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
544static void
545gnc_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
639static void
640gnc_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
647static void
648gnc_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
680static void
681gnc_template_register_save_mxfrm_cell (BasicCell * cell,
682 gpointer save_data,
683 gpointer user_data)
684{
685}
686
687static void
688save_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
717static void
718gnc_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
741static void
742gnc_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 */
758 gnc_numeric_create (0, 1),
759 gnc_numeric_create (0, 1));
760}
761
762void
763gnc_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
838void
839gnc_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
874SRSaveData *
875gnc_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
894void
895gnc_split_register_save_data_destroy (SRSaveData *sd)
896{
897 g_free (sd);
898}
Scheduled Transactions public handling routines.
convert single-entry accounts to clean double-entry
All type declarations for the whole Gnucash engine.
int xaccAccountGetCommoditySCU(const Account *acc)
Return the SCU for the account.
Definition Account.cpp:2745
#define xaccAccountGetGUID(X)
Definition Account.h:252
gboolean xaccAccountIsPriced(const Account *acc)
Returns true if the account is a stock, mutual fund or currency, otherwise false.
Definition Account.cpp:4551
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity
Definition Account.cpp:3408
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
The xaccAccountLookup() subroutine will return the account associated with the given id,...
Definition Account.cpp:2050
gnc_numeric gnc_price_cell_get_value(PriceCell *cell)
return the value of a price cell
Definition pricecell.c:208
void gnc_date_cell_commit(DateCell *cell)
Commits any pending changes to the value of the cell.
void gnc_date_cell_get_date(DateCell *cell, time64 *time, gboolean warn)
Set a time64 to the value in the DateCell.
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equal.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
gboolean gnc_commodity_is_iso(const gnc_commodity *cm)
Checks to see if the specified commodity is an ISO 4217 recognized currency.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition gnc-date.h:87
void xaccTransSetDescription(Transaction *trans, const char *desc)
Sets the transaction Description.
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Returns the valuation commodity of this transaction.
#define xaccTransAppendSplit(t, s)
Add a split to the transaction.
void xaccTransSetTxnType(Transaction *trans, char type)
Set the Transaction Type: note the type will be saved into the Transaction kvp property as a backward...
Split * xaccTransGetSplit(const Transaction *trans, int i)
Return a pointer to the indexed split in this transaction's split list.
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
This function sets the posted date of the transaction, specified by a time64 (see ctime(3)).
gboolean xaccTransUseTradingAccounts(const Transaction *trans)
Determine whether this transaction should use commodity trading accounts.
#define xaccAccountInsertSplit(acc, s)
The xaccAccountInsertSplit() method will insert the indicated split into the indicated account.
Definition Account.h:1069
void xaccTransSetDateDue(Transaction *trans, time64 time)
Dates and txn-type for A/R and A/P "invoice" postings.
void xaccTransSetNotes(Transaction *trans, const char *notes)
Sets the transaction Notes.
void qof_instance_set(QofInstance *inst, const gchar *first_prop,...)
Wrapper for g_object_set Group setting multiple parameters in a single begin/commit/rollback.
#define DEBUG(format, args...)
Print a debugging message.
Definition qoflog.h:264
#define PERR(format, args...)
Log a serious error.
Definition qoflog.h:244
gnc_numeric gnc_numeric_div(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Division.
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Multiply a times b, returning the product.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value.
void xaccSplitScrub(Split *split)
The xaccSplitScrub method ensures that if this split has the same commodity and currency,...
Definition Scrub.cpp:424
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
void xaccSplitSetReconcile(Split *split, char recn)
Set the reconcile flag.
void xaccSplitSetMemo(Split *split, const char *memo)
The memo is an arbitrary string associated with a split.
void xaccSplitSetSharePrice(Split *s, gnc_numeric price)
Definition Split.cpp:1205
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
The xaccSplitLookup() subroutine will return the split associated with the given id,...
Definition Split.cpp:1091
void xaccSplitSetValue(Split *split, gnc_numeric val)
The xaccSplitSetValue() method sets the value of this split in the transaction's commodity.
Split * xaccMallocSplit(QofBook *book)
Constructor.
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account's commodity that the split should have...
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction's commodity.
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
void xaccSplitSetSharePriceAndAmount(Split *s, gnc_numeric price, gnc_numeric amt)
The xaccSplitSetSharePriceAndAmount() method will simultaneously update the share price and the numbe...
Definition Split.cpp:1177
Split * xaccSplitGetOtherSplit(const Split *split)
The xaccSplitGetOtherSplit() is a convenience routine that returns the other of a pair of splits.
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account's commodity.
Save handlers for the SplitRegister Model and Template SplitRegister model.
private declarations for SplitRegister
STRUCTS.
The DateCell object implements a date handling cell.
Definition datecell.h:92
The type used to store guids in C.
Definition guid.h:75
The NumCell object implements a number handling cell.
Definition numcell.h:40
The PriceCell object implements a cell handler that stores a single double-precision value,...
Definition pricecell.h:55
The RecnCell object implements a cell handler that will cycle through a series of single-character va...
Definition recncell.h:48