33 #include <glib/gi18n.h> 41 #include "TransactionP.h" 46 #include "qofinstance-p.h" 52 #include <unordered_set> 54 static QofLogModule log_module = GNC_MOD_ACCOUNT;
57 static gchar account_separator[8] =
".";
58 static gunichar account_uc_separator =
':';
60 static bool imap_convert_bayes_to_flat_run =
false;
63 static const std::string KEY_ASSOC_INCOME_ACCOUNT(
"ofx/associated-income-account");
64 static const std::string KEY_RECONCILE_INFO(
"reconcile-info");
65 static const std::string KEY_INCLUDE_CHILDREN(
"include-children");
66 static const std::string KEY_POSTPONE(
"postpone");
67 static const std::string KEY_LOT_MGMT(
"lot-mgmt");
68 static const std::string KEY_ONLINE_ID(
"online_id");
69 static const std::string KEY_IMP_APPEND_TEXT(
"import-append-text");
70 static const std::string AB_KEY(
"hbci");
71 static const std::string AB_ACCOUNT_ID(
"account-id");
72 static const std::string AB_ACCOUNT_UID(
"account-uid");
73 static const std::string AB_BANK_CODE(
"bank-code");
74 static const std::string AB_TRANS_RETRIEVAL(
"trans-retrieval");
76 static gnc_numeric GetBalanceAsOfDate (
Account *acc,
time64 date, gboolean ignclosing);
78 using FinalProbabilityVec=std::vector<std::pair<std::string, int32_t>>;
79 using ProbabilityVec=std::vector<std::pair<std::string, struct AccountProbability>>;
80 using FlatKvpEntry=std::pair<std::string, KvpValue*>;
103 PROP_END_NOCLOSING_BALANCE,
104 PROP_END_CLEARED_BALANCE,
105 PROP_END_RECONCILED_BALANCE,
110 PROP_TAX_COPY_NUMBER,
121 PROP_IMP_APPEND_TEXT,
122 PROP_IS_OPENING_BALANCE,
123 PROP_OFX_INCOME_ACCOUNT,
127 PROP_AB_TRANS_RETRIEVAL,
135 PROP_START_NOCLOSING_BALANCE,
136 PROP_START_CLEARED_BALANCE,
137 PROP_START_RECONCILED_BALANCE,
140 #define GET_PRIVATE(o) \ 141 ((AccountPrivate*)gnc_account_get_instance_private((Account*)o)) 144 static const std::map<GNCAccountType, const char*> gnc_acct_debit_strs = {
161 static const char* dflt_acct_debit_str = N_(
"Debit");
164 static const std::map<GNCAccountType, const char*> gnc_acct_credit_strs = {
181 static const char* dflt_acct_credit_str = N_(
"Credit");
190 static void xaccAccountBringUpToDate (
Account *acc);
203 return account_separator;
207 gnc_get_account_separator (
void)
209 return account_uc_separator;
213 gnc_set_account_separator (
const gchar *separator)
218 uc = g_utf8_get_char_validated(separator, -1);
219 if ((uc == (gunichar) - 2) || (uc == (gunichar) - 1) || g_unichar_isalnum(uc))
221 account_uc_separator =
':';
222 strcpy(account_separator,
":");
226 account_uc_separator = uc;
227 count = g_unichar_to_utf8(uc, account_separator);
228 account_separator[count] =
'\0';
233 gchar *message = NULL;
235 if ( !invalid_account_names )
244 message = g_strdup_printf(
245 _(
"The separator character \"%s\" is used in one or more account names.\n\n" 246 "This will result in unexpected behaviour. " 247 "Either change the account names or choose another separator character.\n\n" 248 "Below you will find the list of invalid account names:\n" 249 "%s"), separator, account_list );
250 g_free ( account_list );
257 const gchar *separator;
261 check_acct_name (
Account *acct, gpointer user_data)
265 if (g_strstr_len (name, -1, cb->separator))
266 cb->list = g_list_prepend (cb->list, g_strdup (name));
271 g_return_val_if_fail (separator != NULL,
nullptr);
272 if (!book)
return nullptr;
275 (AccountCb)check_acct_name, &cb);
282 static inline void mark_account (
Account *acc);
286 qof_instance_set_dirty(&acc->inst);
292 static constexpr
const char* is_unset {
"unset"};
295 G_DEFINE_TYPE_WITH_PRIVATE(
Account, gnc_account, QOF_TYPE_INSTANCE)
302 priv = GET_PRIVATE(acc);
304 priv->children = NULL;
317 priv->commodity = NULL;
318 priv->commodity_scu = 0;
319 priv->non_standard_scu = FALSE;
321 priv->balance = gnc_numeric_zero();
322 priv->noclosing_balance = gnc_numeric_zero();
323 priv->cleared_balance = gnc_numeric_zero();
324 priv->reconciled_balance = gnc_numeric_zero();
325 priv->starting_balance = gnc_numeric_zero();
326 priv->starting_noclosing_balance = gnc_numeric_zero();
327 priv->starting_cleared_balance = gnc_numeric_zero();
328 priv->starting_reconciled_balance = gnc_numeric_zero();
329 priv->balance_dirty = FALSE;
331 priv->last_num = (
char*) is_unset;
332 priv->tax_us_code = (
char*) is_unset;
333 priv->tax_us_pns = (
char*) is_unset;
334 priv->color = (
char*) is_unset;
335 priv->sort_order = (
char*) is_unset;
336 priv->notes = (
char*) is_unset;
337 priv->filter = (
char*) is_unset;
338 priv->equity_type = TriState::Unset;
339 priv->sort_reversed = TriState::Unset;
342 priv->sort_dirty = FALSE;
346 gnc_account_dispose (GObject *acctp)
348 G_OBJECT_CLASS(gnc_account_parent_class)->dispose(acctp);
352 gnc_account_finalize(GObject* acctp)
354 G_OBJECT_CLASS(gnc_account_parent_class)->finalize(acctp);
364 gnc_account_get_property (GObject *
object,
373 g_return_if_fail(GNC_IS_ACCOUNT(
object));
375 account = GNC_ACCOUNT(
object);
376 priv = GET_PRIVATE(account);
380 g_value_set_string(value, priv->accountName);
386 g_value_set_string(value, priv->accountCode);
388 case PROP_DESCRIPTION:
389 g_value_set_string(value, priv->description);
399 g_value_set_int(value, priv->type);
402 g_value_take_object(value, priv->commodity);
404 case PROP_COMMODITY_SCU:
405 g_value_set_int(value, priv->commodity_scu);
407 case PROP_NON_STD_SCU:
408 g_value_set_boolean(value, priv->non_standard_scu);
410 case PROP_SORT_DIRTY:
411 g_value_set_boolean(value, priv->sort_dirty);
413 case PROP_BALANCE_DIRTY:
414 g_value_set_boolean(value, priv->balance_dirty);
416 case PROP_START_BALANCE:
417 g_value_set_boxed(value, &priv->starting_balance);
419 case PROP_START_NOCLOSING_BALANCE:
420 g_value_set_boxed(value, &priv->starting_noclosing_balance);
422 case PROP_START_CLEARED_BALANCE:
423 g_value_set_boxed(value, &priv->starting_cleared_balance);
425 case PROP_START_RECONCILED_BALANCE:
426 g_value_set_boxed(value, &priv->starting_reconciled_balance);
428 case PROP_END_BALANCE:
429 g_value_set_boxed(value, &priv->balance);
431 case PROP_END_NOCLOSING_BALANCE:
432 g_value_set_boxed(value, &priv->noclosing_balance);
434 case PROP_END_CLEARED_BALANCE:
435 g_value_set_boxed(value, &priv->cleared_balance);
437 case PROP_END_RECONCILED_BALANCE:
438 g_value_set_boxed(value, &priv->reconciled_balance);
442 g_value_set_pointer(value, priv->policy);
445 g_value_set_int(value, priv->mark);
447 case PROP_TAX_RELATED:
453 case PROP_TAX_SOURCE:
454 g_value_set_string(value,
457 case PROP_TAX_COPY_NUMBER:
458 g_value_set_int64(value,
464 case PROP_AUTO_INTEREST:
467 case PROP_IS_OPENING_BALANCE:
470 case PROP_PLACEHOLDER:
476 case PROP_SORT_ORDER:
479 case PROP_SORT_REVERSED:
482 case PROP_LOT_NEXT_ID:
484 g_value_set_int64 (value, 0);
485 qof_instance_get_path_kvp (QOF_INSTANCE (account), value, {KEY_LOT_MGMT,
"next-id"});
487 case PROP_ONLINE_ACCOUNT:
488 qof_instance_get_path_kvp (QOF_INSTANCE (account), value, {KEY_ONLINE_ID});
490 case PROP_IMP_APPEND_TEXT:
493 case PROP_OFX_INCOME_ACCOUNT:
494 qof_instance_get_path_kvp (QOF_INSTANCE (account), value, {KEY_ASSOC_INCOME_ACCOUNT});
496 case PROP_AB_ACCOUNT_ID:
497 qof_instance_get_path_kvp (QOF_INSTANCE (account), value, {AB_KEY, AB_ACCOUNT_ID});
499 case PROP_AB_ACCOUNT_UID:
500 qof_instance_get_path_kvp (QOF_INSTANCE (account), value, {AB_KEY, AB_ACCOUNT_UID});
502 case PROP_AB_BANK_CODE:
503 qof_instance_get_path_kvp (QOF_INSTANCE (account), value, {AB_KEY, AB_BANK_CODE});
505 case PROP_AB_TRANS_RETRIEVAL:
506 qof_instance_get_path_kvp (QOF_INSTANCE (account), value, {AB_KEY, AB_TRANS_RETRIEVAL});
509 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, prop_id, pspec);
515 gnc_account_set_property (GObject *
object,
522 g_return_if_fail(GNC_IS_ACCOUNT(
object));
523 account = GNC_ACCOUNT(
object);
524 if (prop_id < PROP_RUNTIME_0)
525 g_assert (qof_instance_get_editlevel(account));
535 case PROP_DESCRIPTION:
551 case PROP_COMMODITY_SCU:
554 case PROP_NON_STD_SCU:
557 case PROP_SORT_DIRTY:
560 case PROP_BALANCE_DIRTY:
563 case PROP_START_BALANCE:
564 number =
static_cast<gnc_numeric*
>(g_value_get_boxed(value));
567 case PROP_START_CLEARED_BALANCE:
568 number =
static_cast<gnc_numeric*
>(g_value_get_boxed(value));
571 case PROP_START_RECONCILED_BALANCE:
572 number =
static_cast<gnc_numeric*
>(g_value_get_boxed(value));
581 case PROP_TAX_RELATED:
587 case PROP_TAX_SOURCE:
589 g_value_get_string(value));
591 case PROP_TAX_COPY_NUMBER:
593 g_value_get_int64(value));
598 case PROP_AUTO_INTEREST:
601 case PROP_IS_OPENING_BALANCE:
604 case PROP_PLACEHOLDER:
610 case PROP_SORT_ORDER:
613 case PROP_SORT_REVERSED:
616 case PROP_LOT_NEXT_ID:
617 qof_instance_set_path_kvp (QOF_INSTANCE (account), value, {KEY_LOT_MGMT,
"next-id"});
619 case PROP_ONLINE_ACCOUNT:
620 qof_instance_set_path_kvp (QOF_INSTANCE (account), value, {KEY_ONLINE_ID});
622 case PROP_IMP_APPEND_TEXT:
625 case PROP_OFX_INCOME_ACCOUNT:
626 qof_instance_set_path_kvp (QOF_INSTANCE (account), value, {KEY_ASSOC_INCOME_ACCOUNT});
628 case PROP_AB_ACCOUNT_ID:
629 qof_instance_set_path_kvp (QOF_INSTANCE (account), value, {AB_KEY, AB_ACCOUNT_ID});
631 case PROP_AB_ACCOUNT_UID:
632 qof_instance_set_path_kvp (QOF_INSTANCE (account), value, {AB_KEY, AB_ACCOUNT_UID});
634 case PROP_AB_BANK_CODE:
635 qof_instance_set_path_kvp (QOF_INSTANCE (account), value, {AB_KEY, AB_BANK_CODE});
637 case PROP_AB_TRANS_RETRIEVAL:
638 qof_instance_set_path_kvp (QOF_INSTANCE (account), value, {AB_KEY, AB_TRANS_RETRIEVAL});
641 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, prop_id, pspec);
649 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
651 gobject_class->dispose = gnc_account_dispose;
652 gobject_class->finalize = gnc_account_finalize;
653 gobject_class->set_property = gnc_account_set_property;
654 gobject_class->get_property = gnc_account_get_property;
656 g_object_class_install_property
659 g_param_spec_string (
"name",
661 "The accountName is an arbitrary string " 662 "assigned by the user. It is intended to " 663 "a short, 5 to 30 character long string " 664 "that is displayed by the GUI as the " 665 "account mnemonic. Account names may be " 666 "repeated. but no two accounts that share " 667 "a parent may have the same name.",
669 static_cast<GParamFlags>(G_PARAM_READWRITE)));
671 g_object_class_install_property
674 g_param_spec_string (
"fullname",
676 "The name of the account concatenated with " 677 "all its parent account names to indicate " 680 static_cast<GParamFlags>(G_PARAM_READABLE)));
682 g_object_class_install_property
685 g_param_spec_string (
"code",
687 "The account code is an arbitrary string " 688 "assigned by the user. It is intended to " 689 "be reporting code that is a synonym for " 692 static_cast<GParamFlags>(G_PARAM_READWRITE)));
694 g_object_class_install_property
697 g_param_spec_string (
"description",
698 "Account Description",
699 "The account description is an arbitrary " 700 "string assigned by the user. It is intended " 701 "to be a longer, 1-5 sentence description of " 702 "what this account is all about.",
704 static_cast<GParamFlags>(G_PARAM_READWRITE)));
706 g_object_class_install_property
709 g_param_spec_string (
"color",
711 "The account color is a color string assigned " 712 "by the user. It is intended to highlight the " 713 "account based on the users wishes.",
715 static_cast<GParamFlags>(G_PARAM_READWRITE)));
717 g_object_class_install_property
720 g_param_spec_string (
"notes",
722 "The account notes is an arbitrary provided " 723 "for the user to attach any other text that " 724 "they would like to associate with the account.",
726 static_cast<GParamFlags>(G_PARAM_READWRITE)));
728 g_object_class_install_property
731 g_param_spec_int (
"type",
733 "The account type, picked from the enumerated list " 734 "that includes ACCT_TYPE_BANK, ACCT_TYPE_STOCK, " 735 "ACCT_TYPE_CREDIT, ACCT_TYPE_INCOME, etc.",
739 static_cast<GParamFlags>(G_PARAM_READWRITE)));
741 g_object_class_install_property
744 g_param_spec_object (
"commodity",
746 "The commodity field denotes the kind of " 747 "'stuff' stored in this account, whether " 748 "it is USD, gold, stock, etc.",
750 static_cast<GParamFlags>(G_PARAM_READWRITE)));
752 g_object_class_install_property
755 g_param_spec_int (
"commodity-scu",
757 "The smallest fraction of the commodity that is " 758 "tracked. This number is used as the denominator " 759 "value in 1/x, so a value of 100 says that the " 760 "commodity can be divided into hundredths. E.G." 761 "1 USD can be divided into 100 cents.",
765 static_cast<GParamFlags>(G_PARAM_READWRITE)));
767 g_object_class_install_property
770 g_param_spec_boolean (
"non-std-scu",
772 "TRUE if the account SCU doesn't match " 773 "the commodity SCU. This indicates a case " 774 "where the two were accidentally set to " 775 "mismatched values in older versions of " 778 static_cast<GParamFlags>(G_PARAM_READWRITE)));
780 g_object_class_install_property
783 g_param_spec_boolean(
"sort-dirty",
785 "TRUE if the splits in the account needs to be " 786 "resorted. This flag is set by the accounts " 787 "code for certain internal modifications, or " 788 "when external code calls the engine to say a " 789 "split has been modified in a way that may " 790 "affect the sort order of the account. Note: " 791 "This value can only be set to TRUE.",
793 static_cast<GParamFlags>(G_PARAM_READWRITE)));
795 g_object_class_install_property
798 g_param_spec_boolean(
"balance-dirty",
800 "TRUE if the running balances in the account " 801 "needs to be recalculated. This flag is set " 802 "by the accounts code for certain internal " 803 "modifications, or when external code calls " 804 "the engine to say a split has been modified. " 805 "Note: This value can only be set to TRUE.",
807 static_cast<GParamFlags>(G_PARAM_READWRITE)));
809 g_object_class_install_property
812 g_param_spec_boxed(
"start-balance",
814 "The starting balance for the account. This " 815 "parameter is intended for use with backends that " 816 "do not return the complete list of splits for an " 817 "account, but rather return a partial list. In " 818 "such a case, the backend will typically return " 819 "all of the splits after some certain date, and " 820 "the 'starting balance' will represent the " 821 "summation of the splits up to that date.",
823 static_cast<GParamFlags>(G_PARAM_READWRITE)));
825 g_object_class_install_property
827 PROP_START_NOCLOSING_BALANCE,
828 g_param_spec_boxed(
"start-noclosing-balance",
829 "Starting No-closing Balance",
830 "The starting balance for the account, ignoring closing." 831 "This parameter is intended for use with backends " 832 "that do not return the complete list of splits " 833 "for an account, but rather return a partial " 834 "list. In such a case, the backend will " 835 "typically return all of the splits after " 836 "some certain date, and the 'starting noclosing " 837 "balance' will represent the summation of the " 838 "splits up to that date, ignoring closing splits.",
840 static_cast<GParamFlags>(G_PARAM_READWRITE)));
842 g_object_class_install_property
844 PROP_START_CLEARED_BALANCE,
845 g_param_spec_boxed(
"start-cleared-balance",
846 "Starting Cleared Balance",
847 "The starting cleared balance for the account. " 848 "This parameter is intended for use with backends " 849 "that do not return the complete list of splits " 850 "for an account, but rather return a partial " 851 "list. In such a case, the backend will " 852 "typically return all of the splits after " 853 "some certain date, and the 'starting cleared " 854 "balance' will represent the summation of the " 855 "splits up to that date.",
857 static_cast<GParamFlags>(G_PARAM_READWRITE)));
859 g_object_class_install_property
861 PROP_START_RECONCILED_BALANCE,
862 g_param_spec_boxed(
"start-reconciled-balance",
863 "Starting Reconciled Balance",
864 "The starting reconciled balance for the " 865 "account. This parameter is intended for use " 866 "with backends that do not return the complete " 867 "list of splits for an account, but rather return " 868 "a partial list. In such a case, the backend " 869 "will typically return all of the splits after " 870 "some certain date, and the 'starting reconciled " 871 "balance' will represent the summation of the " 872 "splits up to that date.",
874 static_cast<GParamFlags>(G_PARAM_READWRITE)));
876 g_object_class_install_property
879 g_param_spec_boxed(
"end-balance",
880 "Ending Account Balance",
881 "This is the current ending balance for the " 882 "account. It is computed from the sum of the " 883 "starting balance and all splits in the account.",
887 g_object_class_install_property
889 PROP_END_NOCLOSING_BALANCE,
890 g_param_spec_boxed(
"end-noclosing-balance",
891 "Ending Account Noclosing Balance",
892 "This is the current ending no-closing balance for " 893 "the account. It is computed from the sum of the " 894 "starting balance and all cleared splits in the " 899 g_object_class_install_property
901 PROP_END_CLEARED_BALANCE,
902 g_param_spec_boxed(
"end-cleared-balance",
903 "Ending Account Cleared Balance",
904 "This is the current ending cleared balance for " 905 "the account. It is computed from the sum of the " 906 "starting balance and all cleared splits in the " 911 g_object_class_install_property
913 PROP_END_RECONCILED_BALANCE,
914 g_param_spec_boxed(
"end-reconciled-balance",
915 "Ending Account Reconciled Balance",
916 "This is the current ending reconciled balance " 917 "for the account. It is computed from the sum of " 918 "the starting balance and all reconciled splits " 921 static_cast<GParamFlags>(G_PARAM_READABLE)));
923 g_object_class_install_property
926 g_param_spec_pointer (
"policy",
928 "The account lots policy.",
929 static_cast<GParamFlags>(G_PARAM_READWRITE)));
931 g_object_class_install_property
934 g_param_spec_int (
"acct-mark",
940 static_cast<GParamFlags>(G_PARAM_READWRITE)));
942 g_object_class_install_property
945 g_param_spec_boolean (
"tax-related",
947 "Whether the account maps to an entry on an " 948 "income tax document.",
950 static_cast<GParamFlags>(G_PARAM_READWRITE)));
952 g_object_class_install_property
954 PROP_IS_OPENING_BALANCE,
955 g_param_spec_boolean (
"opening-balance",
957 "Whether the account holds opening balances",
959 static_cast<GParamFlags>(G_PARAM_READWRITE)));
961 g_object_class_install_property
964 g_param_spec_string (
"tax-code",
966 "This is the code for mapping an account to a " 967 "specific entry on a taxable document. In the " 968 "United States it is used to transfer totals " 969 "into tax preparation software.",
971 static_cast<GParamFlags>(G_PARAM_READWRITE)));
973 g_object_class_install_property
976 g_param_spec_string (
"tax-source",
978 "This specifies where exported name comes from.",
980 static_cast<GParamFlags>(G_PARAM_READWRITE)));
982 g_object_class_install_property
984 PROP_TAX_COPY_NUMBER,
985 g_param_spec_int64 (
"tax-copy-number",
987 "This specifies the copy number of the tax " 992 static_cast<GParamFlags>(G_PARAM_READWRITE)));
994 g_object_class_install_property
997 g_param_spec_boolean (
"hidden",
999 "Whether the account should be hidden in the " 1002 static_cast<GParamFlags>(G_PARAM_READWRITE)));
1004 g_object_class_install_property
1007 g_param_spec_boolean (
"auto-interest-transfer",
1009 "Whether an interest transfer should be automatically " 1010 "added before reconcile.",
1012 static_cast<GParamFlags>(G_PARAM_READWRITE)));
1014 g_object_class_install_property
1017 g_param_spec_boolean (
"placeholder",
1019 "Whether the account is a placeholder account which does not " 1020 "allow transactions to be created, edited or deleted.",
1022 static_cast<GParamFlags>(G_PARAM_READWRITE)));
1024 g_object_class_install_property
1027 g_param_spec_string (
"filter",
1029 "The account filter is a value saved to allow " 1030 "filters to be recalled.",
1032 static_cast<GParamFlags>(G_PARAM_READWRITE)));
1034 g_object_class_install_property
1037 g_param_spec_string (
"sort-order",
1038 "Account Sort Order",
1039 "The account sort order is a value saved to allow " 1040 "the sort order to be recalled.",
1042 static_cast<GParamFlags>(G_PARAM_READWRITE)));
1044 g_object_class_install_property
1047 g_param_spec_boolean (
"sort-reversed",
1048 "Account Sort Reversed",
1049 "Parameter to store whether the sort order is reversed or not.",
1051 static_cast<GParamFlags>(G_PARAM_READWRITE)));
1053 g_object_class_install_property
1056 g_param_spec_int64 (
"lot-next-id",
1058 "Tracks the next id to use in gnc_lot_make_default.",
1062 static_cast<GParamFlags>(G_PARAM_READWRITE)));
1064 g_object_class_install_property
1066 PROP_ONLINE_ACCOUNT,
1067 g_param_spec_string (
"online-id",
1068 "Online Account ID",
1069 "The online account which corresponds to this " 1070 "account for OFX import",
1072 static_cast<GParamFlags>(G_PARAM_READWRITE)));
1074 g_object_class_install_property
1076 PROP_IMP_APPEND_TEXT,
1077 g_param_spec_boolean (
"import-append-text",
1078 "Import Append Text",
1079 "Saved state of Append checkbox for setting initial " 1080 "value next time this account is imported.",
1082 static_cast<GParamFlags>(G_PARAM_READWRITE)));
1084 g_object_class_install_property(
1086 PROP_OFX_INCOME_ACCOUNT,
1087 g_param_spec_boxed(
"ofx-income-account",
1088 "Associated income account",
1089 "Used by the OFX importer.",
1091 static_cast<GParamFlags>(G_PARAM_READWRITE)));
1093 g_object_class_install_property
1096 g_param_spec_string (
"ab-account-id",
1097 "AQBanking Account ID",
1098 "The AqBanking account which corresponds to this " 1099 "account for AQBanking import",
1101 static_cast<GParamFlags>(G_PARAM_READWRITE)));
1102 g_object_class_install_property
1105 g_param_spec_string (
"ab-bank-code",
1106 "AQBanking Bank Code",
1107 "The online account which corresponds to this " 1108 "account for AQBanking import",
1110 static_cast<GParamFlags>(G_PARAM_READWRITE)));
1112 g_object_class_install_property
1114 PROP_AB_ACCOUNT_UID,
1115 g_param_spec_int64 (
"ab-account-uid",
1116 "AQBanking Account UID",
1117 "Tracks the next id to use in gnc_lot_make_default.",
1121 static_cast<GParamFlags>(G_PARAM_READWRITE)));
1123 g_object_class_install_property
1125 PROP_AB_TRANS_RETRIEVAL,
1126 g_param_spec_boxed(
"ab-trans-retrieval",
1127 "AQBanking Last Transaction Retrieval",
1128 "The time of the last transaction retrieval for this " 1131 static_cast<GParamFlags>(G_PARAM_READWRITE)));
1136 xaccInitAccount (
Account * acc, QofBook *book)
1138 ENTER (
"book=%p\n", book);
1141 LEAVE (
"account=%p\n", acc);
1148 gnc_account_get_book(
const Account *account)
1150 if (!account)
return NULL;
1158 gnc_coll_get_root_account (QofCollection *col)
1160 if (!col)
return NULL;
1165 gnc_coll_set_root_account (QofCollection *col,
Account *root)
1171 old_root = gnc_coll_get_root_account (col);
1172 if (old_root == root)
return;
1177 rpriv = GET_PRIVATE(root);
1185 qof_collection_set_data (col, root);
1195 gnc_book_get_root_account (QofBook *book)
1200 if (!book)
return NULL;
1202 root = gnc_coll_get_root_account (col);
1209 gnc_book_set_root_account (QofBook *book,
Account *root)
1214 if (root && gnc_account_get_book(root) != book)
1216 PERR (
"cannot mix and match books freely!");
1221 gnc_coll_set_root_account (col, root);
1232 g_return_val_if_fail (book, NULL);
1234 acc =
static_cast<Account*
>(g_object_new (GNC_TYPE_ACCOUNT, NULL));
1235 xaccInitAccount (acc, book);
1248 rpriv = GET_PRIVATE(root);
1252 mark_account (root);
1254 gnc_book_set_root_account(book, root);
1264 g_return_val_if_fail(GNC_IS_ACCOUNT(from), NULL);
1265 g_return_val_if_fail(QOF_IS_BOOK(book), NULL);
1268 ret =
static_cast<Account*
>(g_object_new (GNC_TYPE_ACCOUNT, NULL));
1269 g_return_val_if_fail (ret, NULL);
1271 from_priv = GET_PRIVATE(from);
1272 priv = GET_PRIVATE(ret);
1273 xaccInitAccount (ret, book);
1278 priv->type = from_priv->type;
1284 qof_instance_copy_kvp (QOF_INSTANCE (ret), QOF_INSTANCE (from));
1291 priv->commodity_scu = from_priv->commodity_scu;
1292 priv->non_standard_scu = from_priv->non_standard_scu;
1294 qof_instance_set_dirty(&ret->inst);
1303 xaccFreeOneChildAccount (
Account *acc, gpointer dummy)
1307 if (qof_instance_get_editlevel(acc) == 0)
1313 xaccFreeAccountChildren (
Account *acc)
1319 priv = GET_PRIVATE(acc);
1320 children = g_list_copy(priv->children);
1321 g_list_foreach(children, (GFunc)xaccFreeOneChildAccount, NULL);
1322 g_list_free(children);
1326 g_list_free(priv->children);
1327 priv->children = NULL;
1335 xaccFreeAccount (
Account *acc)
1340 g_return_if_fail(GNC_IS_ACCOUNT(acc));
1342 priv = GET_PRIVATE(acc);
1347 PERR (
" instead of calling xaccFreeAccount(), please call\n" 1348 " xaccAccountBeginEdit(); xaccAccountDestroy();\n");
1351 xaccFreeAccountChildren(acc);
1357 PERR (
" instead of calling xaccFreeAccount(), please call\n" 1358 " xaccAccountBeginEdit(); xaccAccountDestroy();\n");
1360 for (lp = priv->lots; lp; lp = lp->next)
1362 GNCLot *lot =
static_cast<GNCLot*
>(lp->data);
1363 gnc_lot_destroy (lot);
1365 g_list_free (priv->lots);
1376 PERR (
" instead of calling xaccFreeAccount(), please call\n" 1377 " xaccAccountBeginEdit(); xaccAccountDestroy();\n");
1379 qof_instance_reset_editlevel(acc);
1381 slist = g_list_copy(priv->splits);
1382 for (lp = slist; lp; lp = lp->next)
1384 Split *s = (Split *) lp->data;
1397 priv->accountName = priv->accountCode = priv->description =
nullptr;
1399 if (priv->last_num != is_unset)
1400 g_free (priv->last_num);
1401 if (priv->tax_us_code != is_unset)
1402 g_free (priv->tax_us_code);
1403 if (priv->tax_us_pns != is_unset)
1404 g_free (priv->tax_us_pns);
1405 if (priv->color != is_unset)
1406 g_free (priv->color);
1407 if (priv->sort_order != is_unset)
1408 g_free (priv->sort_order);
1409 if (priv->notes != is_unset)
1410 g_free (priv->notes);
1411 if (priv->filter != is_unset)
1412 g_free (priv->filter);
1417 priv->last_num =
nullptr;
1418 priv->tax_us_code =
nullptr;
1419 priv->tax_us_pns =
nullptr;
1420 priv->color ==
nullptr;
1421 priv->sort_order ==
nullptr;
1422 priv->notes ==
nullptr;
1423 priv->filter ==
nullptr;
1425 priv->parent =
nullptr;
1426 priv->children =
nullptr;
1428 priv->balance = gnc_numeric_zero();
1429 priv->noclosing_balance = gnc_numeric_zero();
1430 priv->cleared_balance = gnc_numeric_zero();
1431 priv->reconciled_balance = gnc_numeric_zero();
1435 priv->commodity = NULL;
1437 priv->balance_dirty = FALSE;
1438 priv->sort_dirty = FALSE;
1441 g_object_unref(acc);
1451 g_return_if_fail(acc);
1455 static void on_done(QofInstance *inst)
1463 PERR(
"commit error: %d", errcode);
1464 gnc_engine_signal_commit_error( errcode );
1467 static void acc_free (QofInstance *inst)
1472 priv = GET_PRIVATE(acc);
1475 xaccFreeAccount(acc);
1479 destroy_pending_splits_for_account(QofInstance *ent, gpointer acc)
1481 Transaction *trans = (Transaction *) ent;
1485 while ((split = xaccTransFindSplitByAccount(trans, static_cast<Account*>(acc))))
1495 g_return_if_fail(acc);
1500 priv = GET_PRIVATE(acc);
1506 qof_instance_increase_editlevel(acc);
1509 xaccFreeAccountChildren(acc);
1511 PINFO (
"freeing splits for account %p (%s)",
1512 acc, priv->accountName ? priv->accountName :
"(null)");
1520 slist = g_list_copy(priv->splits);
1521 for (lp = slist; lp; lp = lp->next)
1523 Split *s =
static_cast<Split *
>(lp->data);
1530 g_list_free(priv->splits);
1531 priv->splits = NULL;
1548 for (lp = priv->lots; lp; lp = lp->next)
1550 GNCLot *lot =
static_cast<GNCLot*
>(lp->data);
1551 gnc_lot_destroy (lot);
1554 g_list_free(priv->lots);
1557 qof_instance_set_dirty(&acc->inst);
1558 qof_instance_decrease_editlevel(acc);
1562 xaccAccountBringUpToDate(acc);
1571 g_return_if_fail(GNC_IS_ACCOUNT(acc));
1573 qof_instance_set_destroying(acc, TRUE);
1581 compare_account_by_name (gconstpointer a, gconstpointer b)
1584 if (a && !b)
return 1;
1585 if (b && !a)
return -1;
1586 if (!a && !b)
return 0;
1587 priv_a = GET_PRIVATE((
Account*)a);
1588 priv_b = GET_PRIVATE((
Account*)b);
1589 if ((priv_a->accountCode && strlen (priv_a->accountCode)) ||
1590 (priv_b->accountCode && strlen (priv_b->accountCode)))
1591 return g_strcmp0 (priv_a->accountCode, priv_b->accountCode);
1592 return g_strcmp0 (priv_a->accountName, priv_b->accountName);
1596 xaccAcctChildrenEqual(
const GList *na,
1598 gboolean check_guids)
1600 if ((!na && nb) || (na && !nb))
1602 PINFO (
"only one has accounts");
1605 if (g_list_length ((GList*)na) != g_list_length ((GList*)nb))
1607 PINFO (
"Accounts have different numbers of children");
1615 GList *node = g_list_find_custom ((GList*)nb, aa,
1616 (GCompareFunc)compare_account_by_name);
1620 PINFO (
"Unable to find matching child account.");
1623 ab =
static_cast<Account*
>(node->data);
1632 PWARN (
"accounts %s and %s differ", sa, sb);
1648 if (!aa && !ab)
return TRUE;
1650 g_return_val_if_fail(GNC_IS_ACCOUNT(aa), FALSE);
1651 g_return_val_if_fail(GNC_IS_ACCOUNT(ab), FALSE);
1653 priv_aa = GET_PRIVATE(aa);
1654 priv_ab = GET_PRIVATE(ab);
1655 if (priv_aa->type != priv_ab->type)
1657 PWARN (
"types differ: %d vs %d", priv_aa->type, priv_ab->type);
1661 if (g_strcmp0(priv_aa->accountName, priv_ab->accountName) != 0)
1663 PWARN (
"names differ: %s vs %s", priv_aa->accountName, priv_ab->accountName);
1667 if (g_strcmp0(priv_aa->accountCode, priv_ab->accountCode) != 0)
1669 PWARN (
"codes differ: %s vs %s", priv_aa->accountCode, priv_ab->accountCode);
1673 if (g_strcmp0(priv_aa->description, priv_ab->description) != 0)
1675 PWARN (
"descriptions differ: %s vs %s", priv_aa->description, priv_ab->description);
1681 PWARN (
"commodities differ");
1689 PWARN (
"GUIDs differ");
1694 if (qof_instance_compare_kvp (QOF_INSTANCE (aa), QOF_INSTANCE (ab)) != 0)
1699 frame_a = qof_instance_kvp_as_string (QOF_INSTANCE (aa));
1700 frame_b = qof_instance_kvp_as_string (QOF_INSTANCE (ab));
1702 PWARN (
"kvp frames differ:\n%s\n\nvs\n\n%s", frame_a, frame_b);
1718 PWARN (
"starting balances differ: %s vs %s", str_a, str_b);
1727 priv_ab->starting_noclosing_balance))
1735 PWARN (
"starting noclosing balances differ: %s vs %s", str_a, str_b);
1743 priv_ab->starting_cleared_balance))
1751 PWARN (
"starting cleared balances differ: %s vs %s", str_a, str_b);
1760 priv_ab->starting_reconciled_balance))
1768 PWARN (
"starting reconciled balances differ: %s vs %s", str_a, str_b);
1784 PWARN (
"balances differ: %s vs %s", str_a, str_b);
1800 PWARN (
"noclosing balances differ: %s vs %s", str_a, str_b);
1815 PWARN (
"cleared balances differ: %s vs %s", str_a, str_b);
1823 if (!
gnc_numeric_equal(priv_aa->reconciled_balance, priv_ab->reconciled_balance))
1831 PWARN (
"reconciled balances differ: %s vs %s", str_a, str_b);
1842 GList *la = priv_aa->splits;
1843 GList *lb = priv_ab->splits;
1845 if ((la && !lb) || (!la && lb))
1847 PWARN (
"only one has splits");
1856 Split *sa = (Split *) la->data;
1857 Split *sb = (Split *) lb->data;
1861 PWARN (
"splits differ");
1869 if ((la != NULL) || (lb != NULL))
1871 PWARN (
"number of splits differs");
1877 if (!xaccAcctChildrenEqual(priv_aa->children, priv_ab->children, check_guids))
1879 PWARN (
"children differ");
1893 g_return_if_fail(GNC_IS_ACCOUNT(acc));
1898 priv = GET_PRIVATE(acc);
1899 priv->sort_dirty = TRUE;
1907 g_return_if_fail(GNC_IS_ACCOUNT(acc));
1912 priv = GET_PRIVATE(acc);
1913 priv->balance_dirty = TRUE;
1920 g_return_if_fail (GNC_IS_ACCOUNT (acc));
1925 priv = GET_PRIVATE (acc);
1926 priv->defer_bal_computation = defer;
1934 priv = GET_PRIVATE (acc);
1935 return priv->defer_bal_computation;
1948 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
1949 g_return_val_if_fail(GNC_IS_SPLIT(s), FALSE);
1951 priv = GET_PRIVATE(acc);
1952 node = g_list_find(priv->splits, s);
1956 if (qof_instance_get_editlevel(acc) == 0)
1958 priv->splits = g_list_insert_sorted(priv->splits, s,
1963 priv->splits = g_list_prepend(priv->splits, s);
1964 priv->sort_dirty = TRUE;
1972 priv->balance_dirty = TRUE;
1984 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
1985 g_return_val_if_fail(GNC_IS_SPLIT(s), FALSE);
1987 priv = GET_PRIVATE(acc);
1988 node = g_list_find(priv->splits, s);
1992 priv->splits = g_list_delete_link(priv->splits, node);
1998 priv->balance_dirty = TRUE;
2008 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2010 priv = GET_PRIVATE(acc);
2011 if (!priv->sort_dirty || (!force && qof_instance_get_editlevel(acc) > 0))
2013 priv->splits = g_list_sort(priv->splits, (GCompareFunc)
xaccSplitOrder);
2014 priv->sort_dirty = FALSE;
2015 priv->balance_dirty = TRUE;
2019 xaccAccountBringUpToDate(
Account *acc)
2035 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2036 g_return_if_fail(guid);
2039 PINFO(
"acct=%p", acc);
2042 qof_instance_set_dirty(&acc->inst);
2053 if (!guid || !book)
return NULL;
2066 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2068 priv = GET_PRIVATE(acc);
2077 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2089 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2091 priv = GET_PRIVATE(acc);
2093 for (node = priv->children; node; node = node->next)
2105 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
2107 return GET_PRIVATE(acc)->policy;
2115 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2117 priv = GET_PRIVATE(acc);
2125 xaccAccountRemoveLot (
Account *acc, GNCLot *lot)
2129 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2130 g_return_if_fail(GNC_IS_LOT(lot));
2132 priv = GET_PRIVATE(acc);
2133 g_return_if_fail(priv->lots);
2135 ENTER (
"(acc=%p, lot=%p)", acc, lot);
2136 priv->lots = g_list_remove(priv->lots, lot);
2139 LEAVE (
"(acc=%p, lot=%p)", acc, lot);
2150 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2151 g_return_if_fail(GNC_IS_LOT(lot));
2155 if (lot_account == acc)
2158 ENTER (
"(acc=%p, lot=%p)", acc, lot);
2163 old_acc = lot_account;
2164 opriv = GET_PRIVATE(old_acc);
2165 opriv->lots = g_list_remove(opriv->lots, lot);
2168 priv = GET_PRIVATE(acc);
2169 priv->lots = g_list_prepend(priv->lots, lot);
2170 gnc_lot_set_account(lot, acc);
2180 LEAVE (
"(acc=%p, lot=%p)", acc, lot);
2186 xaccPreSplitMove (Split *split, gpointer dummy)
2192 xaccPostSplitMove (Split *split,
Account *accto)
2196 xaccSplitSetAccount(split, accto);
2208 g_return_if_fail(GNC_IS_ACCOUNT(accfrom));
2209 g_return_if_fail(GNC_IS_ACCOUNT(accto));
2212 from_priv = GET_PRIVATE(accfrom);
2213 if (!from_priv->splits || accfrom == accto)
2218 ENTER (
"(accfrom=%p, accto=%p)", accfrom, accto);
2223 g_list_foreach(from_priv->splits, (GFunc)xaccPreSplitMove, NULL);
2240 g_list_foreach(from_priv->splits, (GFunc)xaccPostSplitMove, (gpointer)accto);
2243 g_assert(from_priv->splits == NULL);
2244 g_assert(from_priv->lots == NULL);
2248 LEAVE (
"(accfrom=%p, accto=%p)", accfrom, accto);
2284 gnc_numeric balance;
2285 gnc_numeric noclosing_balance;
2286 gnc_numeric cleared_balance;
2287 gnc_numeric reconciled_balance;
2290 if (NULL == acc)
return;
2292 priv = GET_PRIVATE(acc);
2293 if (qof_instance_get_editlevel(acc) > 0)
return;
2294 if (!priv->balance_dirty || priv->defer_bal_computation)
return;
2298 balance = priv->starting_balance;
2299 noclosing_balance = priv->starting_noclosing_balance;
2300 cleared_balance = priv->starting_cleared_balance;
2301 reconciled_balance = priv->starting_reconciled_balance;
2303 PINFO (
"acct=%s starting baln=%" G_GINT64_FORMAT
"/%" G_GINT64_FORMAT,
2304 priv->accountName, balance.num, balance.denom);
2305 for (lp = priv->splits; lp; lp = lp->next)
2307 Split *split = (Split *) lp->data;
2310 balance = gnc_numeric_add_fixed(balance, amt);
2312 if (
NREC != split->reconciled)
2314 cleared_balance = gnc_numeric_add_fixed(cleared_balance, amt);
2317 if (
YREC == split->reconciled ||
2318 FREC == split->reconciled)
2320 reconciled_balance =
2321 gnc_numeric_add_fixed(reconciled_balance, amt);
2325 noclosing_balance = gnc_numeric_add_fixed(noclosing_balance, amt);
2327 split->balance = balance;
2328 split->noclosing_balance = noclosing_balance;
2329 split->cleared_balance = cleared_balance;
2330 split->reconciled_balance = reconciled_balance;
2334 priv->balance = balance;
2335 priv->noclosing_balance = noclosing_balance;
2336 priv->cleared_balance = cleared_balance;
2337 priv->reconciled_balance = reconciled_balance;
2338 priv->balance_dirty = FALSE;
2357 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
2365 const char *da, *db;
2366 char *endptr = NULL;
2370 if ( aa && !ab )
return -1;
2371 if ( !aa && ab )
return +1;
2372 if ( !aa && !ab )
return 0;
2374 priv_aa = GET_PRIVATE(aa);
2375 priv_ab = GET_PRIVATE(ab);
2378 da = priv_aa->accountCode;
2379 db = priv_ab->accountCode;
2382 result = g_strcmp0 (da, db);
2388 if (-1 == revorder[0])
2393 revorder [typeorder[i]] = i;
2402 if (ta < tb)
return -1;
2403 if (ta > tb)
return +1;
2406 da = priv_aa->accountName;
2407 db = priv_ab->accountName;
2431 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2435 priv = GET_PRIVATE(acc);
2436 if (priv->type == tip)
2441 priv->balance_dirty = TRUE;
2452 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2453 g_return_if_fail(str);
2456 priv = GET_PRIVATE(acc);
2457 if (g_strcmp0(str, priv->accountName) == 0)
2472 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2475 priv = GET_PRIVATE(acc);
2476 if (g_strcmp0(str, priv->accountCode) == 0)
2491 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2494 priv = GET_PRIVATE(acc);
2495 if (g_strcmp0(str, priv->description) == 0)
2505 stripdup_or_null (
const char *value)
2509 auto temp = g_strstrip (g_strdup (value));
2520 set_kvp_string_path (
Account *acc, std::vector<std::string>
const & path,
2523 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2528 GValue v = G_VALUE_INIT;
2529 g_value_init (&v, G_TYPE_STRING);
2530 g_value_set_string (&v, value);
2531 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v, path);
2536 qof_instance_set_path_kvp (QOF_INSTANCE (acc), NULL, path);
2543 set_kvp_string_tag (
Account *acc,
const char *tag,
const char *value)
2545 set_kvp_string_path (acc, {tag}, value);
2549 get_kvp_string_path (
const Account *acc, std::vector<std::string>
const & path)
2551 GValue v = G_VALUE_INIT;
2552 if (acc == NULL)
return NULL;
2553 qof_instance_get_path_kvp (QOF_INSTANCE (acc), &v, path);
2554 auto retval = G_VALUE_HOLDS_STRING (&v) ? g_value_dup_string (&v) : NULL;
2560 get_kvp_string_tag (
const Account *acc,
const char *tag)
2562 return get_kvp_string_path (acc, {tag});
2568 auto priv = GET_PRIVATE (acc);
2569 if (priv->color != is_unset)
2570 g_free (priv->color);
2571 priv->color = stripdup_or_null (str);
2572 set_kvp_string_tag (acc,
"color", priv->color);
2578 auto priv = GET_PRIVATE (acc);
2579 if (priv->filter != is_unset)
2580 g_free (priv->filter);
2581 priv->filter = stripdup_or_null (str);
2582 set_kvp_string_tag (acc,
"filter", priv->filter);
2588 auto priv = GET_PRIVATE (acc);
2589 if (priv->sort_order != is_unset)
2590 g_free (priv->sort_order);
2591 priv->sort_order = stripdup_or_null (str);
2592 set_kvp_string_tag (acc,
"sort-order", priv->sort_order);
2598 auto priv = GET_PRIVATE (acc);
2599 priv->sort_reversed = sortreversed ? TriState::True : TriState::False;
2600 set_kvp_string_tag (acc,
"sort-reversed", sortreversed ?
"true" : NULL);
2604 qofAccountSetParent (
Account *acc, QofInstance *parent)
2608 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2609 g_return_if_fail(GNC_IS_ACCOUNT(parent));
2611 parent_acc = GNC_ACCOUNT(parent);
2615 mark_account (parent_acc);
2624 auto priv = GET_PRIVATE (acc);
2625 if (priv->notes != is_unset)
2626 g_free (priv->notes);
2627 priv->notes = stripdup_or_null (str);
2628 set_kvp_string_tag (acc,
"notes", priv->notes);
2638 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2639 g_return_if_fail(GNC_IS_COMMODITY(com));
2642 priv = GET_PRIVATE(acc);
2643 if (com == priv->commodity)
2648 priv->commodity = com;
2651 priv->non_standard_scu = FALSE;
2654 for (lp = priv->splits; lp; lp = lp->next)
2656 Split *s = (Split *) lp->data;
2664 priv->sort_dirty = TRUE;
2665 priv->balance_dirty = TRUE;
2682 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2684 priv = GET_PRIVATE(acc);
2686 priv->commodity_scu = scu;
2688 priv->non_standard_scu = TRUE;
2696 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 0);
2697 return GET_PRIVATE(acc)->commodity_scu;
2705 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 0);
2707 priv = GET_PRIVATE(acc);
2708 if (priv->non_standard_scu || !priv->commodity)
2709 return priv->commodity_scu;
2718 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2720 priv = GET_PRIVATE(acc);
2721 if (priv->non_standard_scu == flag)
2724 priv->non_standard_scu = flag;
2732 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 0);
2733 return GET_PRIVATE(acc)->non_standard_scu;
2744 GValue v = G_VALUE_INIT;
2746 gnc_commodity *commodity;
2747 gnc_commodity_table *
table;
2749 if ((!acc) || (!currency))
return;
2750 g_value_init (&v, G_TYPE_STRING);
2751 g_value_set_string (&v, s);
2752 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v, {
"old-currency"});
2758 commodity = gnc_commodity_table_lookup_unique (
table, s);
2772 account_foreach_descendant (
const Account *acc, AccountCb thunk,
2773 void* user_data,
bool sort)
2777 g_return_if_fail (GNC_IS_ACCOUNT(acc));
2778 g_return_if_fail (thunk);
2780 auto priv{GET_PRIVATE(acc)};
2783 children = g_list_copy (priv->children);
2787 children = priv->children;
2789 for (
auto node = children; node; node = node->next)
2791 auto child =
static_cast<Account*
>(node->data);
2792 thunk (child, user_data);
2793 account_foreach_descendant (child, thunk, user_data, sort);
2797 g_list_free (children);
2808 g_assert(GNC_IS_ACCOUNT(new_parent));
2809 g_assert(GNC_IS_ACCOUNT(child));
2812 ppriv = GET_PRIVATE(new_parent);
2813 cpriv = GET_PRIVATE(child);
2814 old_parent = cpriv->parent;
2815 if (old_parent == new_parent)
2837 PWARN (
"reparenting accounts across books is not correctly supported\n");
2846 cpriv->parent = new_parent;
2847 ppriv->children = g_list_append(ppriv->children, child);
2848 qof_instance_set_dirty(&new_parent->inst);
2849 qof_instance_set_dirty(&child->inst);
2872 if (!parent)
return;
2874 ppriv = GET_PRIVATE(parent);
2875 cpriv = GET_PRIVATE(child);
2877 if (cpriv->parent != parent)
2879 PERR (
"account not a child of parent");
2885 ed.idx = g_list_index(ppriv->children, child);
2887 ppriv->children = g_list_remove(ppriv->children, child);
2893 cpriv->parent = NULL;
2901 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
2902 return GET_PRIVATE(acc)->parent;
2910 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
2912 priv = GET_PRIVATE(acc);
2913 while (priv->parent)
2916 priv = GET_PRIVATE(acc);
2925 g_return_val_if_fail(GNC_IS_ACCOUNT(account), FALSE);
2926 return (GET_PRIVATE(account)->parent == NULL);
2932 g_return_val_if_fail(GNC_IS_ACCOUNT(account), NULL);
2933 return g_list_copy(GET_PRIVATE(account)->children);
2942 g_return_val_if_fail(GNC_IS_ACCOUNT(account), NULL);
2945 priv = GET_PRIVATE(account);
2946 if (!priv->children)
2948 return g_list_sort(g_list_copy(priv->children), (GCompareFunc)
xaccAccountOrder);
2954 g_return_val_if_fail(GNC_IS_ACCOUNT(account), 0);
2955 return g_list_length(GET_PRIVATE(account)->children);
2961 g_return_val_if_fail(GNC_IS_ACCOUNT(parent), -1);
2962 g_return_val_if_fail(GNC_IS_ACCOUNT(child), -1);
2963 return g_list_index(GET_PRIVATE(parent)->children, child);
2969 g_return_val_if_fail(GNC_IS_ACCOUNT(parent), NULL);
2970 return static_cast<Account*
>(g_list_nth_data(GET_PRIVATE(parent)->children, num));
2974 count_acct (
Account *account, gpointer user_data)
2976 auto count {
static_cast<int*
>(user_data)};
2984 account_foreach_descendant (account, count_acct, &count, FALSE);
2994 g_return_val_if_fail(GNC_IS_ACCOUNT(account), 0);
2996 priv = GET_PRIVATE(account);
2999 account = priv->parent;
3000 priv = GET_PRIVATE(account);
3012 gint depth = 0, child_depth;
3014 g_return_val_if_fail(GNC_IS_ACCOUNT(account), 0);
3016 priv = GET_PRIVATE(account);
3017 if (!priv->children)
3020 for (node = priv->children; node; node = g_list_next(node))
3023 depth = MAX(depth, child_depth);
3029 collect_acct (
Account *account, gpointer user_data)
3031 auto listptr{
static_cast<GList**
>(user_data)};
3032 *listptr = g_list_prepend (*listptr, account);
3038 GList* list =
nullptr;
3039 account_foreach_descendant (account, collect_acct, &list, FALSE);
3040 return g_list_reverse (list);
3046 GList* list =
nullptr;
3047 account_foreach_descendant (account, collect_acct, &list, TRUE);
3048 return g_list_reverse (list);
3057 account_foreach_descendant_breadthfirst_until (
const Account *acc,
3061 gpointer result {
nullptr};
3063 g_return_val_if_fail (GNC_IS_ACCOUNT(acc),
nullptr);
3064 g_return_val_if_fail (thunk,
nullptr);
3066 for (
auto node = GET_PRIVATE(acc)->children; !result && node; node = node->next)
3067 result = thunk (static_cast<Account*>(node->data), user_data);
3069 for (
auto node = GET_PRIVATE(acc)->children; !result && node; node = node->next)
3070 result = account_foreach_descendant_breadthfirst_until (static_cast<Account*>(node->data), thunk, user_data);
3076 is_acct_name (
Account *account, gpointer user_data)
3078 auto name {
static_cast<gchar*
>(user_data)};
3085 return (
Account*)account_foreach_descendant_breadthfirst_until (parent, is_acct_name, (
char*)name);
3089 is_acct_code (
Account *account, gpointer user_data)
3091 auto name {
static_cast<gchar*
>(user_data)};
3098 return (
Account*)account_foreach_descendant_breadthfirst_until (parent, is_acct_code, (
char*)code);
3102 is_opening_balance_account (
Account* account, gpointer data)
3104 gnc_commodity* commodity = GNC_COMMODITY(data);
3121 gnc_account_lookup_by_full_name_helper (
const Account *parent,
3128 g_return_val_if_fail(GNC_IS_ACCOUNT(parent), NULL);
3129 g_return_val_if_fail(names, NULL);
3132 ppriv = GET_PRIVATE(parent);
3133 for (node = ppriv->children; node; node = node->next)
3137 priv = GET_PRIVATE(account);
3138 if (g_strcmp0(priv->accountName, names[0]) == 0)
3142 if (names[1] == NULL)
3146 if (!priv->children)
3150 found = gnc_account_lookup_by_full_name_helper(account, &names[1]);
3171 g_return_val_if_fail(GNC_IS_ACCOUNT(any_acc), NULL);
3172 g_return_val_if_fail(name, NULL);
3175 rpriv = GET_PRIVATE(root);
3176 while (rpriv->parent)
3178 root = rpriv->parent;
3179 rpriv = GET_PRIVATE(root);
3182 found = gnc_account_lookup_by_full_name_helper(root, names);
3191 gnc_commodity* commodity)
3194 auto rpriv{GET_PRIVATE(root)};
3195 for (
auto node = rpriv->children; node; node = node->next)
3197 auto account{
static_cast<Account*
>(node->data)};
3208 retval = g_list_prepend(retval, account);
3213 for (
auto node = rpriv->children; node; node = node->next)
3215 auto account{
static_cast<Account*
>(node->data)};
3221 retval = g_list_concat(result, retval);
3234 g_return_if_fail(GNC_IS_ACCOUNT(acc));
3235 g_return_if_fail(thunk);
3237 priv = GET_PRIVATE(acc);
3238 for (node = priv->children; node; node = node->next)
3240 thunk (static_cast<Account*>(node->data), user_data);
3249 account_foreach_descendant (acc, thunk, user_data, FALSE);
3257 gpointer result {
nullptr};
3259 g_return_val_if_fail (GNC_IS_ACCOUNT(acc),
nullptr);
3260 g_return_val_if_fail (thunk,
nullptr);
3262 auto priv{GET_PRIVATE(acc)};
3264 for (
auto node = priv->children; node; node = node->next)
3266 auto child =
static_cast<Account*
>(node->data);
3267 result = thunk (child, user_data);
3282 return GET_PRIVATE(acc)->type;
3286 qofAccountGetTypeString (
const Account *acc)
3288 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
3293 qofAccountSetType (
Account *acc,
const char *type_string)
3295 g_return_if_fail(GNC_IS_ACCOUNT(acc));
3296 g_return_if_fail(type_string);
3303 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
3304 return GET_PRIVATE(acc)->accountName;
3313 const gchar **names;
3318 if (NULL == account)
3319 return g_strdup(
"");
3322 g_return_val_if_fail(GNC_IS_ACCOUNT(account), g_strdup(
""));
3325 priv = GET_PRIVATE(account);
3327 return g_strdup(
"");
3332 for (a = account; a; a = priv->parent)
3334 priv = GET_PRIVATE(a);
3340 names = (
const gchar **)g_malloc(level *
sizeof(gchar *));
3341 names[--level] = NULL;
3342 for (a = account; level > 0; a = priv->parent)
3344 priv = GET_PRIVATE(a);
3345 names[--level] = priv->accountName;
3349 fullname = g_strjoinv(account_separator, (gchar **)names);
3358 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
3359 return GET_PRIVATE(acc)->accountCode;
3365 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
3366 return GET_PRIVATE(acc)->description;
3372 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
3373 auto priv = GET_PRIVATE (acc);
3374 if (priv->color == is_unset)
3375 priv->color = get_kvp_string_tag (acc,
"color");
3382 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 0);
3383 auto priv = GET_PRIVATE (acc);
3384 if (priv->filter == is_unset)
3385 priv->filter = get_kvp_string_tag (acc,
"filter");
3386 return priv->filter;
3392 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 0);
3393 auto priv = GET_PRIVATE (acc);
3394 if (priv->sort_order == is_unset)
3395 priv->sort_order = get_kvp_string_tag (acc,
"sort-order");
3396 return priv->sort_order;
3403 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
3404 auto priv = GET_PRIVATE (acc);
3405 if (priv->sort_reversed == TriState::Unset)
3407 auto sort_reversed = get_kvp_string_tag (acc,
"sort-reversed");
3408 priv->sort_reversed = g_strcmp0 (sort_reversed,
"true") ?
3409 TriState::False : TriState::True;
3410 g_free (sort_reversed);
3412 return (priv->sort_reversed == TriState::True);
3418 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
3419 auto priv = GET_PRIVATE (acc);
3420 if (priv->notes == is_unset)
3421 priv->notes = get_kvp_string_tag (acc,
"notes");
3428 GValue v = G_VALUE_INIT;
3429 const char *s = NULL;
3430 gnc_commodity_table *
table;
3431 gnc_commodity *retval = NULL;
3433 if (!acc)
return NULL;
3434 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v, {
"old-currency"});
3435 if (G_VALUE_HOLDS_STRING (&v))
3436 s = g_value_get_string (&v);
3440 retval = gnc_commodity_table_lookup_unique (
table, s);
3450 if (!GNC_IS_ACCOUNT(acc))
3452 return GET_PRIVATE(acc)->commodity;
3457 gnc_commodity * commodity;
3458 g_return_val_if_fail (account, NULL);
3465 const Account *parent_account = account;
3483 while (parent_account);
3495 g_return_if_fail(GNC_IS_ACCOUNT(acc));
3497 priv = GET_PRIVATE(acc);
3498 priv->starting_balance = start_baln;
3499 priv->balance_dirty = TRUE;
3504 const gnc_numeric start_baln)
3508 g_return_if_fail(GNC_IS_ACCOUNT(acc));
3510 priv = GET_PRIVATE(acc);
3511 priv->starting_cleared_balance = start_baln;
3512 priv->balance_dirty = TRUE;
3517 const gnc_numeric start_baln)
3521 g_return_if_fail(GNC_IS_ACCOUNT(acc));
3523 priv = GET_PRIVATE(acc);
3524 priv->starting_reconciled_balance = start_baln;
3525 priv->balance_dirty = TRUE;
3531 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3532 return GET_PRIVATE(acc)->balance;
3538 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3539 return GET_PRIVATE(acc)->cleared_balance;
3545 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3546 return GET_PRIVATE(acc)->reconciled_balance;
3550 xaccAccountGetProjectedMinimumBalance (
const Account *acc)
3555 gnc_numeric lowest = gnc_numeric_zero ();
3556 int seen_a_transaction = 0;
3558 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3560 priv = GET_PRIVATE(acc);
3562 for (node = g_list_last(priv->splits); node; node = node->prev)
3564 Split *split =
static_cast<Split*
>(node->data);
3566 if (!seen_a_transaction)
3569 seen_a_transaction = 1;
3588 GetBalanceAsOfDate (
Account *acc,
time64 date, gboolean ignclosing)
3596 Split *latest =
nullptr;
3598 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3603 for (GList *lp = GET_PRIVATE(acc)->splits; lp; lp = lp->next)
3607 latest = (Split *)lp->data;
3611 return gnc_numeric_zero();
3622 return GetBalanceAsOfDate (acc, date, FALSE);
3626 xaccAccountGetNoclosingBalanceAsOfDate (
Account *acc,
time64 date)
3628 return GetBalanceAsOfDate (acc, date, TRUE);
3634 gnc_numeric balance = gnc_numeric_zero();
3636 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3638 for (GList *node = GET_PRIVATE(acc)->splits; node; node = node->next)
3640 Split *split = (Split*) node->data;
3653 xaccAccountGetPresentBalance (
const Account *acc)
3655 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3672 xaccAccountConvertBalanceToCurrency(
const Account *acc,
3673 gnc_numeric balance,
3674 const gnc_commodity *balance_currency,
3675 const gnc_commodity *new_currency)
3684 book = gnc_account_get_book (acc);
3688 pdb, balance, balance_currency, new_currency);
3698 xaccAccountConvertBalanceToCurrencyAsOfDate(
const Account *acc,
3699 gnc_numeric balance,
3700 const gnc_commodity *balance_currency,
3701 const gnc_commodity *new_currency,
3711 book = gnc_account_get_book (acc);
3715 pdb, balance, balance_currency, new_currency, date);
3726 xaccAccountGetXxxBalanceInCurrency (
const Account *acc,
3727 xaccGetBalanceFn fn,
3728 const gnc_commodity *report_currency)
3731 gnc_numeric balance;
3733 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3734 g_return_val_if_fail(fn, gnc_numeric_zero());
3735 g_return_val_if_fail(GNC_IS_COMMODITY(report_currency), gnc_numeric_zero());
3737 priv = GET_PRIVATE(acc);
3739 balance = xaccAccountConvertBalanceToCurrency(acc, balance,
3746 xaccAccountGetXxxBalanceAsOfDateInCurrency(
Account *acc,
time64 date,
3747 xaccGetBalanceAsOfDateFn fn,
3748 const gnc_commodity *report_commodity)
3752 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3753 g_return_val_if_fail(fn, gnc_numeric_zero());
3754 g_return_val_if_fail(GNC_IS_COMMODITY(report_commodity), gnc_numeric_zero());
3756 priv = GET_PRIVATE(acc);
3757 return xaccAccountConvertBalanceToCurrencyAsOfDate(
3758 acc, fn(acc, date), priv->commodity, report_commodity, date);
3766 const gnc_commodity *currency;
3767 gnc_numeric balance;
3768 xaccGetBalanceFn fn;
3769 xaccGetBalanceAsOfDateFn asOfDateFn;
3780 xaccAccountBalanceHelper (
Account *acc, gpointer data)
3783 gnc_numeric balance;
3785 if (!cb->fn || !cb->currency)
3787 balance = xaccAccountGetXxxBalanceInCurrency (acc, cb->fn, cb->currency);
3794 xaccAccountBalanceAsOfDateHelper (
Account *acc, gpointer data)
3797 gnc_numeric balance;
3799 g_return_if_fail (cb->asOfDateFn && cb->currency);
3801 balance = xaccAccountGetXxxBalanceAsOfDateInCurrency (
3802 acc, cb->date, cb->asOfDateFn, cb->currency);
3821 xaccAccountGetXxxBalanceInCurrencyRecursive (
const Account *acc,
3822 xaccGetBalanceFn fn,
3823 const gnc_commodity *report_commodity,
3824 gboolean include_children)
3826 gnc_numeric balance;
3828 if (!acc)
return gnc_numeric_zero ();
3829 if (!report_commodity)
3831 if (!report_commodity)
3832 return gnc_numeric_zero();
3834 balance = xaccAccountGetXxxBalanceInCurrency (acc, fn, report_commodity);
3838 if (include_children)
3845 cb.balance = balance;
3851 balance = cb.balance;
3858 xaccAccountGetXxxBalanceAsOfDateInCurrencyRecursive (
3860 const gnc_commodity *report_commodity, gboolean include_children)
3862 gnc_numeric balance;
3864 g_return_val_if_fail(acc, gnc_numeric_zero());
3865 if (!report_commodity)
3867 if (!report_commodity)
3868 return gnc_numeric_zero();
3870 balance = xaccAccountGetXxxBalanceAsOfDateInCurrency(
3871 acc, date, fn, report_commodity);
3875 if (include_children)
3882 cb.balance = balance;
3888 balance = cb.balance;
3895 xaccAccountGetBalanceInCurrency (
const Account *acc,
3896 const gnc_commodity *report_commodity,
3897 gboolean include_children)
3900 rc = xaccAccountGetXxxBalanceInCurrencyRecursive (
3902 PINFO(
" baln=%" G_GINT64_FORMAT
"/%" G_GINT64_FORMAT, rc.num, rc.denom);
3908 xaccAccountGetClearedBalanceInCurrency (
const Account *acc,
3909 const gnc_commodity *report_commodity,
3910 gboolean include_children)
3912 return xaccAccountGetXxxBalanceInCurrencyRecursive (
3918 xaccAccountGetReconciledBalanceInCurrency (
const Account *acc,
3919 const gnc_commodity *report_commodity,
3920 gboolean include_children)
3922 return xaccAccountGetXxxBalanceInCurrencyRecursive (
3928 xaccAccountGetPresentBalanceInCurrency (
const Account *acc,
3929 const gnc_commodity *report_commodity,
3930 gboolean include_children)
3932 return xaccAccountGetXxxBalanceAsOfDateInCurrencyRecursive (
3939 xaccAccountGetProjectedMinimumBalanceInCurrency (
3941 const gnc_commodity *report_commodity,
3942 gboolean include_children)
3944 return xaccAccountGetXxxBalanceInCurrencyRecursive (
3945 acc, xaccAccountGetProjectedMinimumBalance, report_commodity,
3952 gboolean include_children)
3954 return xaccAccountGetXxxBalanceAsOfDateInCurrencyRecursive (
3962 gboolean include_children)
3964 return xaccAccountGetXxxBalanceAsOfDateInCurrencyRecursive
3965 (acc, date, xaccAccountGetNoclosingBalanceAsOfDate,
3966 report_commodity, include_children);
3981 xaccAccountGetNoclosingBalanceChangeForPeriod (
Account *acc,
time64 t1,
3982 time64 t2, gboolean recurse)
4009 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
4011 return GET_PRIVATE(acc)->splits;
4019 PWARN (
"xaccAccountCountSplits is deprecated and will be removed \ 4020 in GnuCash 5.0. If testing for an empty account, use \ 4021 xaccAccountGetSplitList(account) == NULL instead. To test descendants \ 4022 as well, use gnc_account_and_descendants_empty.");
4023 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 0);
4036 gboolean gnc_account_and_descendants_empty (
Account *acc)
4038 g_return_val_if_fail (GNC_IS_ACCOUNT (acc), FALSE);
4039 auto priv = GET_PRIVATE (acc);
4040 if (priv->splits !=
nullptr)
return FALSE;
4041 for (
auto *n = priv->children; n; n = n->next)
4043 if (!gnc_account_and_descendants_empty (static_cast<Account*>(n->data)))
4052 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
4053 return g_list_copy(GET_PRIVATE(acc)->lots);
4058 gboolean (*match_func)(GNCLot *lot,
4059 gpointer user_data),
4060 gpointer user_data, GCompareFunc sort_func)
4064 GList *retval = NULL;
4066 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
4068 priv = GET_PRIVATE(acc);
4069 for (lot_list = priv->lots; lot_list; lot_list = lot_list->next)
4071 GNCLot *lot =
static_cast<GNCLot*
>(lot_list->data);
4077 if (match_func && !(match_func)(lot, user_data))
4081 retval = g_list_prepend (retval, lot);
4085 retval = g_list_sort (retval, sort_func);
4092 gpointer (*proc)(GNCLot *lot,
void *data),
void *data)
4096 gpointer result = NULL;
4098 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
4099 g_return_val_if_fail(proc, NULL);
4101 priv = GET_PRIVATE(acc);
4102 for (node = priv->lots; node; node = node->next)
4103 if ((result = proc((GNCLot *)node->data, data)))
4110 set_boolean_key (
Account *acc, std::vector<std::string>
const & path, gboolean option)
4112 GValue v = G_VALUE_INIT;
4113 g_return_if_fail(GNC_IS_ACCOUNT(acc));
4115 g_value_init (&v, G_TYPE_BOOLEAN);
4116 g_value_set_boolean (&v, option);
4118 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v, path);
4125 boolean_from_key (
const Account *acc, std::vector<std::string>
const & path)
4127 GValue v = G_VALUE_INIT;
4128 gboolean retval = FALSE;
4129 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4130 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v, path);
4131 if (G_VALUE_HOLDS_INT64 (&v))
4132 retval = (g_value_get_int64 (&v) != 0);
4133 if (G_VALUE_HOLDS_BOOLEAN (&v))
4134 retval = (g_value_get_boolean (&v));
4135 if (G_VALUE_HOLDS_STRING (&v))
4136 retval = !strcmp (g_value_get_string (&v),
"true");
4148 return boolean_from_key(acc, {
"tax-related"});
4154 set_boolean_key(acc, {
"tax-related"}, tax_related);
4160 auto priv = GET_PRIVATE (acc);
4161 if (priv->tax_us_code == is_unset)
4162 priv->tax_us_code = get_kvp_string_path (acc, {
"tax-US",
"code"});
4163 return priv->tax_us_code;
4169 auto priv = GET_PRIVATE (acc);
4170 if (priv->tax_us_code != is_unset)
4171 g_free (priv->tax_us_code);
4172 priv->tax_us_code = g_strdup (code);
4173 set_kvp_string_path (acc, {
"tax-US",
"code"}, priv->tax_us_code);
4179 auto priv = GET_PRIVATE (acc);
4180 if (priv->tax_us_pns == is_unset)
4181 priv->tax_us_pns = get_kvp_string_path (acc, {
"tax-US",
"payer-name-source"});
4182 return priv->tax_us_pns;
4188 auto priv = GET_PRIVATE (acc);
4189 if (priv->tax_us_pns != is_unset)
4190 g_free (priv->tax_us_pns);
4191 priv->tax_us_pns = g_strdup (source);
4192 set_kvp_string_path (acc, {
"tax-US",
"payer-name-source"}, priv->tax_us_pns);
4198 gint64 copy_number = 0;
4199 GValue v = G_VALUE_INIT;
4200 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4201 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v, {
"tax-US",
"copy-number"});
4202 if (G_VALUE_HOLDS_INT64 (&v))
4203 copy_number = g_value_get_int64 (&v);
4206 return (copy_number == 0) ? 1 : copy_number;
4212 g_return_if_fail(GNC_IS_ACCOUNT(acc));
4214 if (copy_number != 0)
4216 GValue v = G_VALUE_INIT;
4217 g_value_init (&v, G_TYPE_INT64);
4218 g_value_set_int64 (&v, copy_number);
4219 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v, {
"tax-US",
"copy-number"});
4224 qof_instance_set_path_kvp (QOF_INSTANCE (acc),
nullptr, {
"tax-US",
"copy-number"});
4237 return _(dflt_acct_debit_str);
4239 auto result = gnc_acct_debit_strs.find(acct_type);
4240 if (result != gnc_acct_debit_strs.end())
4241 return _(result->second);
4243 return _(dflt_acct_debit_str);
4249 return _(dflt_acct_credit_str);
4251 auto result = gnc_acct_credit_strs.find(acct_type);
4252 if (result != gnc_acct_credit_strs.end())
4253 return _(result->second);
4255 return _(dflt_acct_credit_str);
4264 return boolean_from_key(acc, {
"placeholder"});
4270 set_boolean_key(acc, {
"placeholder"}, val);
4276 return boolean_from_key(acc, {
"import-append-text"});
4282 set_boolean_key(acc, {
"import-append-text"}, val);
4290 auto priv = GET_PRIVATE(acc);
4291 if (priv->equity_type == TriState::Unset)
4293 auto equity_type = get_kvp_string_tag (acc,
"equity-type");
4294 priv->equity_type = g_strcmp0 (equity_type,
"opening-balance") ?
4295 TriState::False : TriState::True;
4296 g_free (equity_type);
4298 return (priv->equity_type == TriState::True);
4306 auto priv = GET_PRIVATE (acc);
4307 priv->equity_type = val ? TriState::True : TriState::False;
4308 set_kvp_string_tag(acc,
"equity-type", val ?
"opening-balance" :
nullptr);
4314 GList *descendants, *node;
4317 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), PLACEHOLDER_NONE);
4321 for (node = descendants; node; node = node->next)
4324 ret = PLACEHOLDER_CHILD;
4328 g_list_free(descendants);
4338 return boolean_from_key (acc, {KEY_RECONCILE_INFO,
"auto-interest-transfer"});
4344 set_boolean_key (acc, {KEY_RECONCILE_INFO,
"auto-interest-transfer"}, val);
4353 return boolean_from_key (acc, {
"hidden"});
4359 set_boolean_key (acc, {
"hidden"}, val);
4367 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4371 priv = GET_PRIVATE(acc);
4372 while ((acc = priv->parent) != NULL)
4374 priv = GET_PRIVATE(acc);
4389 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4390 g_return_val_if_fail(GNC_IS_ACCOUNT(ancestor), FALSE);
4393 while (parent && parent != ancestor)
4394 parent = GET_PRIVATE(parent)->parent;
4396 return (parent == ancestor);
4405 #define GNC_RETURN_ENUM_AS_STRING(x) case (ACCT_TYPE_ ## x): return #x; 4412 GNC_RETURN_ENUM_AS_STRING(NONE);
4413 GNC_RETURN_ENUM_AS_STRING(BANK);
4414 GNC_RETURN_ENUM_AS_STRING(CASH);
4415 GNC_RETURN_ENUM_AS_STRING(CREDIT);
4416 GNC_RETURN_ENUM_AS_STRING(ASSET);
4417 GNC_RETURN_ENUM_AS_STRING(LIABILITY);
4418 GNC_RETURN_ENUM_AS_STRING(STOCK);
4419 GNC_RETURN_ENUM_AS_STRING(MUTUAL);
4420 GNC_RETURN_ENUM_AS_STRING(CURRENCY);
4421 GNC_RETURN_ENUM_AS_STRING(INCOME);
4422 GNC_RETURN_ENUM_AS_STRING(EXPENSE);
4423 GNC_RETURN_ENUM_AS_STRING(EQUITY);
4424 GNC_RETURN_ENUM_AS_STRING(RECEIVABLE);
4425 GNC_RETURN_ENUM_AS_STRING(PAYABLE);
4426 GNC_RETURN_ENUM_AS_STRING(ROOT);
4427 GNC_RETURN_ENUM_AS_STRING(TRADING);
4428 GNC_RETURN_ENUM_AS_STRING(CHECKING);
4429 GNC_RETURN_ENUM_AS_STRING(SAVINGS);
4430 GNC_RETURN_ENUM_AS_STRING(MONEYMRKT);
4431 GNC_RETURN_ENUM_AS_STRING(CREDITLINE);
4433 PERR (
"asked to translate unknown account type %d.\n", type);
4439 #undef GNC_RETURN_ENUM_AS_STRING 4441 #define GNC_RETURN_ON_MATCH(x) \ 4442 if(g_strcmp0(#x, (str)) == 0) { *type = ACCT_TYPE_ ## x; return(TRUE); } 4448 GNC_RETURN_ON_MATCH(NONE);
4449 GNC_RETURN_ON_MATCH(BANK);
4450 GNC_RETURN_ON_MATCH(CASH);
4451 GNC_RETURN_ON_MATCH(CREDIT);
4452 GNC_RETURN_ON_MATCH(ASSET);
4453 GNC_RETURN_ON_MATCH(LIABILITY);
4454 GNC_RETURN_ON_MATCH(STOCK);
4455 GNC_RETURN_ON_MATCH(MUTUAL);
4456 GNC_RETURN_ON_MATCH(CURRENCY);
4457 GNC_RETURN_ON_MATCH(INCOME);
4458 GNC_RETURN_ON_MATCH(EXPENSE);
4459 GNC_RETURN_ON_MATCH(EQUITY);
4460 GNC_RETURN_ON_MATCH(RECEIVABLE);
4461 GNC_RETURN_ON_MATCH(PAYABLE);
4462 GNC_RETURN_ON_MATCH(ROOT);
4463 GNC_RETURN_ON_MATCH(TRADING);
4464 GNC_RETURN_ON_MATCH(CHECKING);
4465 GNC_RETURN_ON_MATCH(SAVINGS);
4466 GNC_RETURN_ON_MATCH(MONEYMRKT);
4467 GNC_RETURN_ON_MATCH(CREDITLINE);
4469 PERR(
"asked to translate unknown account type string %s.\n",
4470 str ? str :
"(null)");
4475 #undef GNC_RETURN_ON_MATCH 4521 return _(account_type_name [type]);
4563 PERR(
"bad account type: %d", type);
4609 PERR(
"bad account type: %d", type);
4716 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4718 priv = GET_PRIVATE(acc);
4730 GValue v = G_VALUE_INIT;
4731 gboolean retval = FALSE;
4732 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4733 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v, {KEY_RECONCILE_INFO,
"last-date"});
4734 if (G_VALUE_HOLDS_INT64 (&v))
4735 date = g_value_get_int64 (&v);
4754 GValue v = G_VALUE_INIT;
4755 g_return_if_fail(GNC_IS_ACCOUNT(acc));
4757 g_value_init (&v, G_TYPE_INT64);
4758 g_value_set_int64 (&v, last_date);
4760 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v, {KEY_RECONCILE_INFO,
"last-date"});
4771 int *months,
int *days)
4773 GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT;
4774 int64_t m = 0, d = 0;
4775 gboolean retval = FALSE;
4777 if (!acc)
return FALSE;
4778 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4779 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v1,
4780 {KEY_RECONCILE_INFO,
"last-interval",
"months"});
4781 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v2,
4782 {KEY_RECONCILE_INFO,
"last-interval",
"days"});
4783 if (G_VALUE_HOLDS_INT64 (&v1))
4784 m = g_value_get_int64 (&v1);
4785 if (G_VALUE_HOLDS_INT64 (&v2))
4786 d = g_value_get_int64 (&v2);
4795 g_value_unset (&v1);
4796 g_value_unset (&v2);
4806 GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT;
4807 g_return_if_fail(GNC_IS_ACCOUNT(acc));
4809 g_value_init (&v1, G_TYPE_INT64);
4810 g_value_set_int64 (&v1, months);
4811 g_value_init (&v2, G_TYPE_INT64);
4812 g_value_set_int64 (&v2, days);
4814 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v1,
4815 {KEY_RECONCILE_INFO,
"last-interval",
"months"});
4816 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v2,
4817 {KEY_RECONCILE_INFO,
"last-interval",
"days"});
4820 g_value_unset (&v1);
4821 g_value_unset (&v2);
4831 gboolean retval = FALSE;
4832 GValue v = G_VALUE_INIT;
4833 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4834 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v,
4835 {KEY_RECONCILE_INFO, KEY_POSTPONE,
"date"});
4836 if (G_VALUE_HOLDS_INT64 (&v))
4837 date = g_value_get_int64 (&v);
4842 *postpone_date = date;
4855 GValue v = G_VALUE_INIT;
4856 g_return_if_fail(GNC_IS_ACCOUNT(acc));
4858 g_value_init (&v, G_TYPE_INT64);
4859 g_value_set_int64 (&v, postpone_date);
4861 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v,
4862 {KEY_RECONCILE_INFO, KEY_POSTPONE,
"date"});
4873 gnc_numeric *balance)
4875 gnc_numeric bal = gnc_numeric_zero ();
4876 GValue v = G_VALUE_INIT;
4877 gboolean retval = FALSE;
4878 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4879 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v,
4880 {KEY_RECONCILE_INFO, KEY_POSTPONE,
"balance"});
4881 if (G_VALUE_HOLDS_BOXED (&v))
4883 bal = *(gnc_numeric*)g_value_get_boxed (&v);
4901 GValue v = G_VALUE_INIT;
4902 g_return_if_fail(GNC_IS_ACCOUNT(acc));
4904 g_value_init (&v, GNC_TYPE_NUMERIC);
4905 g_value_set_boxed (&v, &balance);
4907 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v,
4908 {KEY_RECONCILE_INFO, KEY_POSTPONE,
"balance"});
4924 qof_instance_set_path_kvp (QOF_INSTANCE(acc),
nullptr, {KEY_RECONCILE_INFO, KEY_POSTPONE});
4935 auto priv = GET_PRIVATE (acc);
4936 if (priv->last_num == is_unset)
4937 priv->last_num = get_kvp_string_tag (acc,
"last-num");
4938 return priv->last_num;
4947 auto priv = GET_PRIVATE (acc);
4948 if (priv->last_num != is_unset)
4949 g_free (priv->last_num);
4950 priv->last_num = g_strdup (num);
4951 set_kvp_string_tag (acc,
"last-num", priv->last_num);
4955 GetOrMakeOrphanAccount (
Account *root, gnc_commodity * currency)
4960 g_return_val_if_fail (root, NULL);
4965 PERR (
"No currency specified!");
4969 accname = g_strconcat (_(
"Orphaned Gains"),
"-",
4985 _(
"Realized Gains or Losses from " 4986 "Commodity or Trading Accounts " 4987 "that haven't been recorded elsewhere."));
5002 GValue v = G_VALUE_INIT;
5003 std::vector<std::string> path {KEY_LOT_MGMT,
"gains-acct",
5008 g_return_val_if_fail (acc != NULL, NULL);
5009 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v, path);
5010 if (G_VALUE_HOLDS_BOXED (&v))
5011 guid = (
GncGUID*)g_value_get_boxed (&v);
5019 GValue vr = G_VALUE_INIT;
5020 g_value_init (&vr, GNC_TYPE_GUID);
5021 g_value_set_boxed (&vr, guid);
5022 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &vr, path);
5023 qof_instance_set_dirty (QOF_INSTANCE (acc));
5024 g_value_unset (&vr);
5033 return gains_account;
5045 set_kvp_string_tag (acc,
"old-price-source", src);
5054 static char *source =
nullptr;
5055 if (!acc)
return NULL;
5060 source = get_kvp_string_tag (acc,
"old-price-source");
5072 set_kvp_string_tag (acc,
"old-quote-tz", tz);
5081 static char *quote_tz =
nullptr;
5082 if (!acc)
return NULL;
5085 quote_tz = get_kvp_string_tag (acc,
"old-quote-tz");
5095 GValue v = G_VALUE_INIT;
5103 g_value_init (&v, G_TYPE_INT64);
5104 g_value_set_int64 (&v, status);
5105 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v,
5106 {KEY_RECONCILE_INFO, KEY_INCLUDE_CHILDREN});
5122 GValue v = G_VALUE_INIT;
5124 if (!acc)
return FALSE;
5125 qof_instance_get_path_kvp (QOF_INSTANCE (acc), &v,
5126 {KEY_RECONCILE_INFO, KEY_INCLUDE_CHILDREN});
5127 retval = G_VALUE_HOLDS_INT64 (&v) ? g_value_get_int64 (&v) : FALSE;
5141 finder_help_function(
const Account *acc,
const char *description,
5142 Split **split, Transaction **trans )
5148 if (split) *split = NULL;
5149 if (trans) *trans = NULL;
5152 if (acc == NULL)
return;
5157 priv = GET_PRIVATE(acc);
5158 for (slp = g_list_last(priv->splits); slp; slp = slp->prev)
5160 Split *lsplit =
static_cast<Split*
>(slp->data);
5165 if (split) *split = lsplit;
5166 if (trans) *trans = ltrans;
5178 finder_help_function(acc, description, &split, NULL);
5193 finder_help_function(acc, description, NULL, &trans);
5204 GList *children, *node;
5207 g_return_if_fail(GNC_IS_ACCOUNT(to_parent));
5208 g_return_if_fail(GNC_IS_ACCOUNT(from_parent));
5211 from_priv = GET_PRIVATE(from_parent);
5212 if (!from_priv->children)
5216 children = g_list_copy(from_priv->children);
5217 for (node = children; node; node = g_list_next(node))
5219 g_list_free(children);
5229 GList *node_a, *node_b, *work, *worker;
5231 g_return_if_fail(GNC_IS_ACCOUNT(parent));
5233 ppriv = GET_PRIVATE(parent);
5234 for (node_a = ppriv->children; node_a; node_a = node_a->next)
5238 priv_a = GET_PRIVATE(acc_a);
5239 for (node_b = node_a->next; node_b; node_b = g_list_next(node_b))
5243 priv_b = GET_PRIVATE(acc_b);
5244 if (0 !=
null_strcmp(priv_a->accountName, priv_b->accountName))
5246 if (0 !=
null_strcmp(priv_a->accountCode, priv_b->accountCode))
5248 if (0 !=
null_strcmp(priv_a->description, priv_b->description))
5258 if (priv_a->type != priv_b->type)
5262 if (priv_b->children)
5264 work = g_list_copy(priv_b->children);
5265 for (worker = work; worker; worker = g_list_next(worker))
5277 while (priv_b->splits)
5278 xaccSplitSetAccount (static_cast <Split*> (priv_b->splits->data), acc_a);
5282 node_b = g_list_previous(node_b);
5301 for (lp = splits; lp; lp = lp->next)
5303 Split *s = static_cast <Split*> (lp->data);
5304 Transaction *trans = s->parent;
5319 priv = GET_PRIVATE(account);
5326 if (trans == NULL)
return FALSE;
5328 if (trans->marker < stage)
5330 trans->marker = stage;
5337 static void do_one_split (Split *s, gpointer data)
5339 Transaction *trans = s->parent;
5343 static void do_one_account (
Account *account, gpointer data)
5346 g_list_foreach(priv->splits, (GFunc)do_one_split, NULL);
5356 g_list_foreach(descendants, (GFunc)do_one_account, NULL);
5357 g_list_free(descendants);
5363 TransactionCallback thunk,
5375 priv = GET_PRIVATE(acc);
5376 for (split_p = priv->splits; split_p; split_p = next)
5382 next = g_list_next(split_p);
5384 s = static_cast <Split*> (split_p->data);
5386 if (trans && (trans->marker < stage))
5388 trans->marker = stage;
5391 retval = thunk(trans, cb_data);
5392 if (retval)
return retval;
5403 TransactionCallback thunk,
5407 GList *acc_p, *split_p;
5415 priv = GET_PRIVATE(acc);
5416 for (acc_p = priv->children; acc_p; acc_p = g_list_next(acc_p))
5419 stage, thunk, cb_data);
5420 if (retval)
return retval;
5424 for (split_p = priv->splits; split_p; split_p = g_list_next(split_p))
5426 s = static_cast <Split*> (split_p->data);
5428 if (trans && (trans->marker < stage))
5430 trans->marker = stage;
5433 retval = thunk(trans, cb_data);
5434 if (retval)
return retval;
5447 int (*proc)(Transaction *t,
void *data),
5450 if (!acc || !proc)
return 0;
5461 if (!acc || !proc)
return 0;
5472 #define IMAP_FRAME "import-map" 5473 #define IMAP_FRAME_BAYES "import-map-bayes" 5481 if (!acc)
return NULL;
5489 imap->book = gnc_account_get_book (acc);
5497 const char *category,
5500 GValue v = G_VALUE_INIT;
5503 if (!imap || !key)
return NULL;
5504 std::vector<std::string> path {IMAP_FRAME};
5506 path.push_back (category);
5507 path.push_back (key);
5508 qof_instance_get_path_kvp (QOF_INSTANCE (imap->acc), &v, path);
5509 if (G_VALUE_HOLDS_BOXED (&v))
5510 guid = (
GncGUID*)g_value_get_boxed (&v);
5519 const char *category,
5523 GValue v = G_VALUE_INIT;
5524 if (!imap || !key || !acc || (strlen (key) == 0))
return;
5525 std::vector<std::string> path {IMAP_FRAME};
5527 path.emplace_back (category);
5528 path.emplace_back (key);
5529 g_value_init (&v, GNC_TYPE_GUID);
5532 qof_instance_set_path_kvp (QOF_INSTANCE (imap->acc), &v, path);
5533 qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
5541 const char *category,
5544 if (!imap || !key)
return;
5545 std::vector<std::string> path {IMAP_FRAME};
5547 path.emplace_back (category);
5548 path.emplace_back (key);
5550 if (qof_instance_has_path_slot (QOF_INSTANCE (imap->acc), path))
5552 qof_instance_slot_path_delete (QOF_INSTANCE (imap->acc), path);
5554 qof_instance_slot_path_delete_if_empty (QOF_INSTANCE (imap->acc), {IMAP_FRAME, category});
5555 qof_instance_slot_path_delete_if_empty (QOF_INSTANCE (imap->acc), {IMAP_FRAME});
5557 qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
5573 double product_difference;
5578 std::string account_guid;
5579 int64_t token_count;
5587 std::vector<AccountTokenCount> accounts;
5588 int64_t total_count;
5596 std::string account_guid;
5597 int32_t probability;
5601 build_token_info(
char const * suffix, KvpValue * value,
TokenAccountsInfo & tokenInfo)
5605 tokenInfo.total_count += value->get<int64_t>();
5607 tokenInfo.accounts.emplace_back(
AccountTokenCount{std::string{suffix}, value->get<int64_t>()});
5614 static constexpr
int probability_factor = 100000;
5616 static FinalProbabilityVec
5617 build_probabilities(ProbabilityVec
const & first_pass)
5619 FinalProbabilityVec ret;
5620 for (
auto const & first_pass_prob : first_pass)
5622 auto const & account_probability = first_pass_prob.second;
5627 int32_t probability = (account_probability.product /
5628 (account_probability.product + account_probability.product_difference)) * probability_factor;
5629 ret.push_back({first_pass_prob.first, probability});
5635 highest_probability(FinalProbabilityVec
const & probabilities)
5637 AccountInfo ret {
"", std::numeric_limits<int32_t>::min()};
5638 for (
auto const & prob : probabilities)
5639 if (prob.second > ret.probability)
5644 static ProbabilityVec
5650 for (
auto current_token = tokens; current_token; current_token = current_token->next)
5653 auto path = std::string{IMAP_FRAME_BAYES
"/"} + static_cast <
char const *> (current_token->data) +
"/";
5654 qof_instance_foreach_slot_prefix (QOF_INSTANCE (imap->acc), path, &build_token_info, tokenInfo);
5655 for (
auto const & current_account_token : tokenInfo.accounts)
5657 auto item = std::find_if(ret.begin(), ret.end(), [¤t_account_token]
5658 (std::pair<std::string, AccountProbability>
const & a) {
5659 return current_account_token.account_guid == a.first;
5661 if (item != ret.end())
5663 item->second.product = ((double)current_account_token.token_count /
5664 (
double)tokenInfo.total_count) * item->second.product;
5665 item->second.product_difference = ((
double)1 - ((double)current_account_token.token_count /
5666 (
double)tokenInfo.total_count)) * item->second.product_difference;
5672 new_probability.product = ((double)current_account_token.token_count /
5673 (
double)tokenInfo.total_count);
5674 new_probability.product_difference = 1 - (new_probability.product);
5675 ret.push_back({current_account_token.account_guid, std::move(new_probability)});
5683 look_for_old_separator_descendants (
Account *root, std::string
const & full_name,
const gchar *separator)
5685 GList *top_accounts, *ptr;
5689 PINFO(
"Incoming full_name is '%s', current separator is '%s'", full_name.c_str (), separator);
5691 for (ptr = top_accounts; ptr; ptr = g_list_next (ptr))
5695 if (g_str_has_prefix (full_name.c_str (), name))
5697 gint name_len = strlen (name);
5698 const gchar old_sep = full_name[name_len];
5699 if (!g_ascii_isalnum (old_sep))
5701 if (name_len > found_len)
5703 found_sep = full_name[name_len];
5704 found_len = name_len;
5709 g_list_free (top_accounts);
5710 std::string new_name {full_name};
5712 std::replace (new_name.begin (), new_name.end (), found_sep, *separator);
5713 PINFO (
"Return full_name is '%s'", new_name.c_str ());
5718 get_guid_from_account_name (
Account * root, std::string
const & name)
5723 auto temp_account_name = look_for_old_separator_descendants (root, name,
5728 return temp_guid.to_string ();
5732 convert_entry (KvpEntry entry,
Account* root)
5735 auto account_name = entry.first.back();
5736 if (!gnc::GUID::is_valid_guid (account_name))
5742 entry.first.pop_back();
5743 auto guid_str = get_guid_from_account_name (root, account_name);
5744 entry.first.emplace_back (guid_str);
5746 std::string new_key {std::accumulate (entry.first.begin(), entry.first.end(), std::string {})};
5747 new_key = IMAP_FRAME_BAYES + new_key;
5748 return {new_key, entry.second};
5751 static std::vector<FlatKvpEntry>
5754 auto frame = qof_instance_get_slots (QOF_INSTANCE (acc));
5755 auto slot = frame->get_slot ({IMAP_FRAME_BAYES});
5758 auto imap_frame = slot->get<KvpFrame*> ();
5759 auto flat_kvp = imap_frame->flatten_kvp ();
5761 std::vector <FlatKvpEntry> ret;
5762 for (
auto const & flat_entry : flat_kvp)
5764 auto converted_entry = convert_entry (flat_entry, root);
5766 if (converted_entry.first.size())
5767 ret.emplace_back (converted_entry);
5773 convert_imap_account_bayes_to_flat (
Account *acc)
5775 auto frame = qof_instance_get_slots (QOF_INSTANCE (acc));
5776 if (!frame->get_keys().size())
5778 auto flat_imap = get_flat_imap(acc);
5779 if (!flat_imap.size ())
5782 frame->set({IMAP_FRAME_BAYES},
nullptr);
5783 std::for_each(flat_imap.begin(), flat_imap.end(),
5784 [&frame] (FlatKvpEntry
const & entry) {
5785 frame->set({entry.first.c_str()}, entry.second);
5787 qof_instance_set_dirty (QOF_INSTANCE (acc));
5796 imap_convert_bayes_to_flat (QofBook * book)
5798 auto root = gnc_book_get_root_account (book);
5801 for (
auto ptr = accts; ptr; ptr = g_list_next (ptr))
5804 if (convert_imap_account_bayes_to_flat (acc))
5810 g_list_free (accts);
5817 imap_convert_bayes_to_flat_run =
false;
5832 check_import_map_data (QofBook *book)
5834 if (gnc_features_check_used (book, GNC_FEATURE_GUID_FLAT_BAYESIAN) ||
5835 imap_convert_bayes_to_flat_run)
5839 imap_convert_bayes_to_flat (book);
5840 imap_convert_bayes_to_flat_run =
true;
5843 static constexpr
double threshold = .90 * probability_factor;
5851 check_import_map_data (imap->book);
5852 auto first_pass = get_first_pass_probabilities(imap, tokens);
5853 if (!first_pass.size())
5855 auto final_probabilities = build_probabilities(first_pass);
5856 if (!final_probabilities.size())
5858 auto best = highest_probability(final_probabilities);
5859 if (best.account_guid ==
"")
5861 if (best.probability < threshold)
5865 guid = gnc::GUID::from_string(best.account_guid);
5869 auto account =
xaccAccountLookup (reinterpret_cast<GncGUID*>(&guid), imap->book);
5874 change_imap_entry (
GncImportMatchMap *imap, std::string
const & path, int64_t token_count)
5876 GValue value = G_VALUE_INIT;
5878 PINFO(
"Source Account is '%s', Count is '%" G_GINT64_FORMAT
"'",
5882 if (qof_instance_has_slot (QOF_INSTANCE(imap->acc), path.c_str ()))
5884 int64_t existing_token_count = 0;
5887 qof_instance_get_path_kvp (QOF_INSTANCE (imap->acc), &value, {path});
5889 if (G_VALUE_HOLDS_INT64 (&value))
5890 existing_token_count = g_value_get_int64 (&value);
5892 PINFO(
"found existing value of '%" G_GINT64_FORMAT
"'", existing_token_count);
5894 token_count = token_count + existing_token_count;
5897 if (!G_IS_VALUE (&value))
5898 g_value_init (&value, G_TYPE_INT64);
5900 g_value_set_int64 (&value, token_count);
5903 qof_instance_set_path_kvp (QOF_INSTANCE (imap->acc), &value, {path});
5905 g_value_unset (&value);
5914 GList *current_token;
5916 char *account_fullname;
5925 check_import_map_data (imap->book);
5927 g_return_if_fail (acc != NULL);
5931 PINFO(
"account name: '%s'", account_fullname);
5936 for (current_token = g_list_first(tokens); current_token;
5937 current_token = current_token->next)
5943 if (!current_token->data || (*((
char*)current_token->data) ==
'\0'))
5947 PINFO(
"adding token '%s'", (
char*)current_token->data);
5948 auto path = std::string {IMAP_FRAME_BAYES} +
'/' +
static_cast<char*
>(current_token->data) +
'/' + guid_string;
5950 change_imap_entry (imap, path, token_count);
5953 qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
5955 g_free (account_fullname);
5956 g_free (guid_string);
5963 build_non_bayes (
const char *key,
const GValue *value, gpointer user_data)
5965 if (!G_VALUE_HOLDS_BOXED (value))
5969 gchar *guid_string = NULL;
5974 guid = (
GncGUID*)g_value_get_boxed (value);
5977 PINFO(
"build_non_bayes: match string '%s', match account guid: '%s'",
5978 (
char*)key, guid_string);
5982 imapInfo_node->source_account = imapInfo->source_account;
5984 imapInfo_node->head = g_strdup (imapInfo->head);
5985 imapInfo_node->match_string = g_strdup (key);
5986 imapInfo_node->category = g_strdup (imapInfo->category);
5987 imapInfo_node->count = g_strdup (
" ");
5989 imapInfo->list = g_list_prepend (imapInfo->list, imapInfo_node);
5991 g_free (guid_string);
5995 build_bayes (
const char *suffix, KvpValue * value,
GncImapInfo & imapInfo)
5998 std::string account_guid {&suffix[guid_start]};
6002 guid = gnc::GUID::from_string (account_guid);
6006 PWARN(
"Invalid GUID string from %s%s", IMAP_FRAME_BAYES, suffix);
6008 auto map_account =
xaccAccountLookup (&guid, gnc_account_get_book (imapInfo.source_account));
6010 auto count = value->get <int64_t> ();
6011 imap_node->source_account = imapInfo.source_account;
6012 imap_node->map_account = map_account;
6013 imap_node->head = g_strdup_printf (
"%s%s", IMAP_FRAME_BAYES, suffix);
6014 imap_node->match_string = g_strndup (&suffix[1], guid_start - 2);
6015 imap_node->category = g_strdup(
" ");
6016 imap_node->count = g_strdup_printf (
"%" G_GINT64_FORMAT, count);
6017 imapInfo.list = g_list_prepend (imapInfo.list, imap_node);
6023 check_import_map_data (gnc_account_get_book (acc));
6027 qof_instance_foreach_slot_prefix (QOF_INSTANCE (acc), IMAP_FRAME_BAYES, &build_bayes, imapInfo);
6028 return g_list_reverse(imapInfo.list);
6038 std::vector<std::string> path {IMAP_FRAME};
6040 path.emplace_back (category);
6042 imapInfo.source_account = acc;
6043 imapInfo.list = list;
6045 imapInfo.head = g_strdup (IMAP_FRAME);
6046 imapInfo.category = g_strdup (category);
6048 if (qof_instance_has_path_slot (QOF_INSTANCE (acc), path))
6050 qof_instance_foreach_slot (QOF_INSTANCE(acc), IMAP_FRAME, category,
6051 build_non_bayes, &imapInfo);
6053 g_free (imapInfo.head);
6054 g_free (imapInfo.category);
6055 return g_list_reverse(imapInfo.list);
6064 return get_kvp_string_path (acc, {head, category});
6066 return get_kvp_string_path (acc, {head});
6072 char *match_string, gboolean empty)
6076 std::vector<std::string> path {head};
6078 path.emplace_back (category);
6080 path.emplace_back (match_string);
6082 if (qof_instance_has_path_slot (QOF_INSTANCE (acc), path))
6086 qof_instance_slot_path_delete_if_empty (QOF_INSTANCE(acc), path);
6088 qof_instance_slot_path_delete (QOF_INSTANCE(acc), path);
6089 PINFO(
"Account is '%s', head is '%s', category is '%s', match_string is'%s'",
6091 qof_instance_set_dirty (QOF_INSTANCE(acc));
6102 auto slots = qof_instance_get_slots_prefix (QOF_INSTANCE (acc), IMAP_FRAME_BAYES);
6103 if (!slots.size())
return;
6105 for (
auto const & entry : slots)
6107 qof_instance_slot_path_delete (QOF_INSTANCE (acc), {entry.first});
6109 qof_instance_set_dirty (QOF_INSTANCE(acc));
6118 destroy_all_child_accounts (
Account *acc, gpointer data)
6125 gnc_account_book_end(QofBook* book)
6127 Account *root_account = gnc_book_get_root_account (book);
6137 accounts = g_list_reverse (accounts);
6138 g_list_foreach (accounts, (GFunc)destroy_all_child_accounts,
nullptr);
6139 g_list_free (accounts);
6152 static QofObject account_object_def =
6155 DI(.e_type = ) GNC_ID_ACCOUNT,
6158 DI(.book_begin = ) NULL,
6159 DI(.book_end = ) gnc_account_book_end,
6167 gboolean xaccAccountRegister (
void)
6169 static QofParam params[] =
6172 ACCOUNT_NAME_, QOF_TYPE_STRING,
6177 ACCOUNT_CODE_, QOF_TYPE_STRING,
6182 ACCOUNT_DESCRIPTION_, QOF_TYPE_STRING,
6187 ACCOUNT_COLOR_, QOF_TYPE_STRING,
6192 ACCOUNT_FILTER_, QOF_TYPE_STRING,
6197 ACCOUNT_SORT_ORDER_, QOF_TYPE_STRING,
6202 ACCOUNT_SORT_REVERSED_, QOF_TYPE_BOOLEAN,
6207 ACCOUNT_NOTES_, QOF_TYPE_STRING,
6212 ACCOUNT_PRESENT_, QOF_TYPE_NUMERIC,
6216 ACCOUNT_BALANCE_, QOF_TYPE_NUMERIC,
6220 ACCOUNT_CLEARED_, QOF_TYPE_NUMERIC,
6224 ACCOUNT_RECONCILED_, QOF_TYPE_NUMERIC,
6228 ACCOUNT_TYPE_, QOF_TYPE_STRING,
6233 ACCOUNT_FUTURE_MINIMUM_, QOF_TYPE_NUMERIC,
6237 ACCOUNT_TAX_RELATED, QOF_TYPE_BOOLEAN,
6242 ACCOUNT_OPENING_BALANCE_, QOF_TYPE_BOOLEAN,
6247 ACCOUNT_SCU, QOF_TYPE_INT32,
6252 ACCOUNT_NSCU, QOF_TYPE_BOOLEAN,
6257 ACCOUNT_PARENT, GNC_ID_ACCOUNT,
6266 QOF_PARAM_GUID, QOF_TYPE_GUID,
6277 using AccountSet = std::unordered_set<Account*>;
6278 static void maybe_add_descendants (
Account* acc, gpointer arg)
6280 g_return_if_fail (acc);
6282 if (static_cast <AccountSet*> (arg)->insert (acc).second)
6283 g_list_foreach (GET_PRIVATE(acc)->children, (GFunc) maybe_add_descendants, arg);
6287 gnc_accounts_and_all_descendants (GList *accounts)
6290 g_list_foreach (accounts, (GFunc) maybe_add_descendants, &accset);
6291 return std::accumulate (accset.begin(), accset.end(), (GList*)
nullptr, g_list_prepend);
6298 utest_account_get_private (
Account *acc)
6300 return GET_PRIVATE (acc);
6304 _utest_account_fill_functions(
void)
6308 func->get_private = utest_account_get_private;
6309 func->coll_get_root_account = gnc_coll_get_root_account;
6310 func->xaccFreeAccountChildren = xaccFreeAccountChildren;
6311 func->xaccFreeAccount = xaccFreeAccount;
6312 func->qofAccountSetParent = qofAccountSetParent;
6313 func->gnc_account_lookup_by_full_name_helper =
6314 gnc_account_lookup_by_full_name_helper;
void xaccAccountSetType(Account *acc, GNCAccountType tip)
Set the account's type.
int qof_instance_version_cmp(const QofInstance *left, const QofInstance *right)
Compare two instances, based on their last update times.
gnc_commodity * gnc_commodity_table_insert(gnc_commodity_table *table, gnc_commodity *comm)
Add a new commodity to the commodity table.
Account * gnc_account_get_parent(const Account *acc)
This routine returns a pointer to the parent of the specified account.
void xaccAccountSetFilter(Account *acc, const char *str)
Set the account's Filter.
void xaccAccountSetSortOrder(Account *acc, const char *str)
Set the account's Sort Order.
gint xaccAccountForEachTransaction(const Account *acc, TransactionCallback proc, void *data)
The xaccAccountForEachTransaction() routine will traverse all of the transactions in account and call...
int xaccAccountTreeForEachTransaction(Account *acc, TransactionCallback proc, void *data)
Traverse all of the transactions in the given account group.
gint xaccSplitOrder(const Split *sa, const Split *sb)
The xaccSplitOrder(sa,sb) method is useful for sorting.
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
Returns the commodity table associated with a book.
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b represent the same number.
int gnc_account_tree_staged_transaction_traversal(const Account *acc, unsigned int stage, TransactionCallback thunk, void *cb_data)
gnc_account_tree_staged_transaction_traversal() calls thunk on each transaction in the group whose cu...
gboolean xaccAccountGetAutoInterest(const Account *acc)
Get the "auto interest" flag for an account.
holds an account guid and its corresponding integer probability the integer probability is some facto...
const char * xaccAccountGetLastNum(const Account *acc)
Get the last num field of an Account.
GNCAccountType xaccAccountTypeGetFundamental(GNCAccountType t)
Convenience function to return the fundamental type asset/liability/income/expense/equity given an ac...
gchar * gnc_account_get_map_entry(Account *acc, const char *head, const char *category)
Returns the text string pointed to by head and category for the Account, free the returned text...
gboolean gnc_commodity_is_currency(const gnc_commodity *cm)
Checks to see if the specified commodity is an ISO 4217 recognized currency or a legacy currency...
GList LotList
GList of GNCLots.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
gboolean xaccAccountGetSortReversed(const Account *acc)
Get the account's Sort Order direction.
guint32 xaccAccountTypesCompatibleWith(GNCAccountType type)
Return the bitmask of account types compatible with a given type.
void gnc_account_append_child(Account *new_parent, Account *child)
This function will remove from the child account any pre-existing parent relationship, and will then add the account as a child of the new parent.
const GncGUID * qof_instance_get_guid(gconstpointer inst)
Return the GncGUID of this instance.
gpointer xaccAccountForEachLot(const Account *acc, gpointer(*proc)(GNCLot *lot, gpointer user_data), gpointer user_data)
The xaccAccountForEachLot() method will apply the function 'proc' to each lot in the account...
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
GList * gnc_account_get_descendants_sorted(const Account *account)
This function returns a GList containing all the descendants of the specified account, sorted at each level.
gint gnc_account_n_descendants(const Account *account)
Return the number of descendants of the specified account.
void qof_instance_set_guid(gpointer ptr, const GncGUID *guid)
Set the GncGUID of this instance.
gint64 xaccAccountGetTaxUSCopyNumber(const Account *acc)
DOCUMENT ME!
gboolean gnc_account_is_root(const Account *account)
This routine indicates whether the specified account is the root node of an account tree...
SplitList * xaccAccountGetSplitList(const Account *acc)
The xaccAccountGetSplitList() routine returns a pointer to a GList of the splits in the account...
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
gboolean xaccAccountGetNonStdSCU(const Account *acc)
Return boolean, indicating whether this account uses a non-standard SCU.
int xaccAccountGetCommoditySCUi(const Account *acc)
Return the 'internal' SCU setting.
#define GNC_COMMODITY_MAX_FRACTION
Max fraction is 10^9 because 10^10 would require changing it to an int64_t.
const char * qof_string_cache_replace(char const *dst, char const *src)
Same as CACHE_REPLACE below, but safe to call from C++.
gchar * gnc_g_list_stringjoin(GList *list_of_strings, const gchar *sep)
Return a string joining a GList whose elements are gchar* strings.
gnc_commodity * DxaccAccountGetCurrency(const Account *acc)
void gnc_account_foreach_descendant(const Account *acc, AccountCb thunk, gpointer user_data)
This method will traverse all children of this accounts and their descendants, calling 'func' on each...
void xaccAccountSetNotes(Account *acc, const char *str)
Set the account's notes.
QofBook * qof_instance_get_book(gconstpointer inst)
Return the book pointer.
gboolean xaccAccountIsPriced(const Account *acc)
Returns true if the account is a stock, mutual fund or currency, otherwise false. ...
gboolean qof_collection_is_dirty(const QofCollection *col)
Return value of 'dirty' flag on collection.
void gnc_account_delete_map_entry(Account *acc, char *head, char *category, char *match_string, gboolean empty)
Delete the entry for Account pointed to by head,category and match_string, if empty is TRUE then use ...
gboolean xaccTransIsOpen(const Transaction *trans)
The xaccTransIsOpen() method returns TRUE if the transaction is open for editing. ...
a simple price database for gnucash
QofInstance * qof_collection_lookup_entity(const QofCollection *col, const GncGUID *guid)
Find the entity going only from its guid.
Expense accounts are used to denote expenses.
int safe_utf8_collate(const char *da, const char *db)
Collate two UTF-8 strings.
#define PINFO(format, args...)
Print an informational note.
const char * xaccAccountGetFilter(const Account *acc)
Get the account's filter.
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
gboolean xaccSplitDestroy(Split *split)
Destructor.
void xaccAccountSetMark(Account *acc, short m)
Set a mark on the account.
QofBackendError
The errors that can be reported to the GUI & other front-end users.
int xaccAccountGetCommoditySCU(const Account *acc)
Return the SCU for the account.
const char * xaccAccountGetCode(const Account *acc)
Get the account's accounting code.
gboolean xaccAccountGetAppendText(const Account *acc)
Get the "import-append-text" flag for an account.
void xaccAccountSetReconcileLastDate(Account *acc, time64 last_date)
DOCUMENT ME!
total_count and the token_count for a given account let us calculate the probability of a given accou...
Account * gnc_account_create_root(QofBook *book)
Create a new root level account.
void gnc_commodity_decrement_usage_count(gnc_commodity *cm)
Decrement a commodity's internal counter that tracks how many accounts are using that commodity...
void xaccAccountSetTaxRelated(Account *acc, gboolean tax_related)
DOCUMENT ME!
gboolean qof_instance_get_destroying(gconstpointer ptr)
Retrieve the flag that indicates whether or not this object is about to be destroyed.
Mutual Fund accounts will typically be shown in registers which show three columns: price...
void gnc_features_set_used(QofBook *book, const gchar *feature)
Indicate that the current book uses the given feature.
void qof_class_register(QofIdTypeConst obj_name, QofSortFunc default_sort_function, const QofParam *params)
This function registers a new object class with the Qof subsystem.
char xaccSplitGetReconcile(const Split *split)
Returns the value of the reconcile flag.
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equal.
void xaccAccountSortSplits(Account *acc, gboolean force)
The xaccAccountSortSplits() routine will resort the account's splits if the sort is dirty...
void xaccAccountSetCode(Account *acc, const char *str)
Set the account's accounting code.
gpointer gnc_account_foreach_descendant_until(const Account *acc, AccountCb2 thunk, gpointer user_data)
This method will traverse all children of this accounts and their descendants, calling 'func' on each...
void gnc_account_set_policy(Account *acc, GNCPolicy *policy)
Set the account's lot order policy.
void xaccAccountSetReconcileLastInterval(Account *acc, int months, int days)
DOCUMENT ME!
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Return a+b.
gboolean gnc_account_remove_split(Account *acc, Split *s)
Remove the given split from an account.
gnc_numeric xaccAccountGetBalanceAsOfDateInCurrency(Account *acc, time64 date, gnc_commodity *report_commodity, gboolean include_children)
This function gets the balance at the end of the given date in the desired commodity.
guint32 xaccAccountTypesValid(void)
Returns the bitmask of the account type enums that are valid.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
const char * xaccAccountTypeEnumAsString(GNCAccountType type)
Conversion routines for the account types to/from strings that are used in persistent storage...
stop here; the following types just aren't ready for prime time
GList * gnc_account_list_name_violations(QofBook *book, const gchar *separator)
Runs through all the accounts and returns a list of account names that contain the provided separator...
void xaccAccountInsertLot(Account *acc, GNCLot *lot)
The xaccAccountInsertLot() method will register the indicated lot with this account.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
API for Transactions and Splits (journal entries)
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
int(* QofSortFunc)(gconstpointer, gconstpointer)
This function is the default sort function for a particular object type.
int gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
Returns 1 if a>b, -1 if b>a, 0 if a == b.
#define QOF_OBJECT_VERSION
Defines the version of the core object object registration interface.
gchar * gnc_numeric_to_string(gnc_numeric n)
Convert to string.
void xaccAccountMoveAllSplits(Account *accfrom, Account *accto)
The xaccAccountMoveAllSplits() routine reassigns each of the splits in accfrom to accto...
gboolean qof_commit_edit(QofInstance *inst)
commit_edit helpers
#define PERR(format, args...)
Log a serious error.
void gnc_account_set_sort_dirty(Account *acc)
Tell the account believes that the splits may be incorrectly sorted and need to be resorted...
#define ENTER(format, args...)
Print a function entry debugging message.
gnc_numeric gnc_pricedb_convert_balance_nearest_before_price_t64(GNCPriceDB *pdb, gnc_numeric balance, const gnc_commodity *balance_currency, const gnc_commodity *new_currency, time64 t)
Convert a balance from one currency to another using the price nearest to before the given time...
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
The cash account type is used to denote a shoe-box or pillowcase stuffed with * cash.
const char * gnc_account_get_debit_string(GNCAccountType acct_type)
Get the debit string associated with this account type.
gnc_numeric xaccSplitGetBalance(const Split *s)
Returns the running balance up to and including the indicated split.
#define QOF_PARAM_BOOK
"Known" Object Parameters – all objects must support these
void xaccAccountSetLastNum(Account *acc, const char *num)
Set the last num field of an Account.
const char * qof_string_cache_insert(const char *key)
You can use this function with g_hash_table_insert(), for the key (or value), as long as you use the ...
gnc_numeric xaccAccountGetClearedBalance(const Account *acc)
Get the current balance of the account, only including cleared transactions.
void qof_collection_foreach(const QofCollection *col, QofInstanceForeachCB cb_func, gpointer user_data)
Call the callback for each entity in the collection.
void(* QofSetterFunc)(gpointer, gpointer)
The QofSetterFunc defines an function pointer for parameter setters.
GNCPriceDB * gnc_pricedb_get_db(QofBook *book)
Return the pricedb associated with the book.
Account * gnc_account_imap_find_account_bayes(GncImportMatchMap *imap, GList *tokens)
Look up an Account in the map.
gnc_numeric gnc_pricedb_convert_balance_latest_price(GNCPriceDB *pdb, gnc_numeric balance, const gnc_commodity *balance_currency, const gnc_commodity *new_currency)
Convert a balance from one currency to another using the most recent price between the two...
gboolean xaccAccountGetReconcilePostponeDate(const Account *acc, time64 *postpone_date)
DOCUMENT ME!
intermediate values used to calculate the bayes probability of a given account where p(AB) = (a*b)/[a...
Account used to record multiple commodity transactions.
void xaccAccountDestroy(Account *acc)
The xaccAccountDestroy() routine can be used to get rid of an account.
gboolean xaccAccountIsHidden(const Account *acc)
Should this account be "hidden".
gboolean xaccSplitEqual(const Split *sa, const Split *sb, gboolean check_guids, gboolean check_balances, gboolean check_txn_splits)
Equality.
Account * gnc_account_lookup_by_name(const Account *parent, const char *name)
The gnc_account_lookup_by_name() subroutine fetches the account by name from the descendants of the s...
#define PWARN(format, args...)
Log a warning.
void gnc_account_remove_child(Account *parent, Account *child)
This function will remove the specified child account from the specified parent account.
int xaccAccountOrder(const Account *aa, const Account *ab)
The xaccAccountOrder() subroutine defines a sorting order on accounts.
Stock accounts will typically be shown in registers which show three columns: price, number of shares, and value.
const char * xaccAccountGetColor(const Account *acc)
Get the account's color.
Split * xaccAccountFindSplitByDesc(const Account *acc, const char *description)
Returns a pointer to the split, not a copy.
void qof_instance_init_data(QofInstance *inst, QofIdType type, QofBook *book)
Initialise the settings associated with an instance.
gboolean qof_begin_edit(QofInstance *inst)
begin_edit
#define xaccAccountGetGUID(X)
gboolean xaccAccountIsAssetLiabType(GNCAccountType t)
Convenience function to check if the account is a valid Asset or Liability type, but not a business a...
void xaccClearMarkDown(Account *acc, short val)
The xaccClearMarkDown will clear the mark only in this and in sub-accounts.
GList SplitList
GList of Split.
GNCAccountType xaccAccountStringToEnum(const char *str)
Conversion routines for the account types to/from strings that are used in persistent storage...
bank account type – don't use this for now, see NUM_ACCOUNT_TYPES
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account's commodity that the split should have...
gchar * gnc_account_get_full_name(const Account *account)
The gnc_account_get_full_name routine returns the fully qualified name of the account using the given...
gnc_numeric xaccAccountGetReconciledBalanceAsOfDate(Account *acc, time64 date)
Get the reconciled balance of the account at the end of the day of the date specified.
void gnc_account_imap_add_account_bayes(GncImportMatchMap *imap, GList *tokens, Account *acc)
Updates the imap for a given account using a list of tokens.
void xaccAccountSetPlaceholder(Account *acc, gboolean val)
Set the "placeholder" flag for an account.
gboolean xaccAccountTypesCompatible(GNCAccountType parent_type, GNCAccountType child_type)
Return TRUE if accounts of type parent_type can have accounts of type child_type as children...
gnc_numeric xaccAccountGetNoclosingBalanceAsOfDateInCurrency(Account *acc, time64 date, gnc_commodity *report_commodity, gboolean include_children)
This function gets the balance at the end of the given date, ignoring closing entries, in the desired commodity.
gchar * gnc_account_name_violations_errmsg(const gchar *separator, GList *invalid_account_names)
Composes a translatable error message showing which account names clash with the current account sepa...
gboolean xaccTransactionTraverse(Transaction *trans, int stage)
xaccTransactionTraverse() checks the stage of the given transaction.
void xaccAccountSetColor(Account *acc, const char *str)
Set the account's Color.
Transaction * xaccAccountFindTransByDesc(const Account *acc, const char *description)
Returns a pointer to the transaction, not a copy.
void gnc_account_set_balance_dirty(Account *acc)
Tell the account that the running balances may be incorrect and need to be recomputed.
Income accounts are used to denote income.
void gnc_account_foreach_child(const Account *acc, AccountCb thunk, gpointer user_data)
This method will traverse the immediate children of this accounts, calling 'func' on each account...
#define YREC
The Split has been reconciled.
Account * gnc_account_lookup_by_code(const Account *parent, const char *code)
The gnc_account_lookup_by_code() subroutine works like gnc_account_lookup_by_name, but uses the account code.
void gnc_account_tree_begin_staged_transaction_traversals(Account *account)
gnc_account_tree_begin_staged_transaction_traversals() resets the traversal marker inside every trans...
void dxaccAccountSetPriceSrc(Account *acc, const char *src)
Set a string that identifies the Finance::Quote backend that should be used to retrieve online prices...
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
void xaccAccountBeginStagedTransactionTraversals(const Account *account)
xaccAccountBeginStagedTransactionTraversals() resets the traversal marker for each transaction which ...
void gnc_commodity_increment_usage_count(gnc_commodity *cm)
Increment a commodity's internal counter that tracks how many accounts are using that commodity...
#define FREC
frozen into accounting period
GNCPlaceholderType xaccAccountGetDescendantPlaceholder(const Account *acc)
Returns PLACEHOLDER_NONE if account is NULL or neither account nor any descendant of account is a pla...
const char * xaccAccountGetDescription(const Account *acc)
Get the account's description.
void gnc_account_set_start_reconciled_balance(Account *acc, const gnc_numeric start_baln)
This function will set the starting reconciled commodity balance for this account.
void gnc_account_delete_all_bayes_maps(Account *acc)
Delete all bayes entries for Account.
const char * dxaccAccountGetQuoteTZ(const Account *acc)
Get the timezone to be used when interpreting the results from a given Finance::Quote backend...
line of credit – don't use this for now, see NUM_ACCOUNT_TYPES
void xaccAccountClearReconcilePostpone(Account *acc)
DOCUMENT ME!
const char * xaccAccountGetTaxUSPayerNameSource(const Account *acc)
DOCUMENT ME!
void xaccSplitsBeginStagedTransactionTraversals(GList *splits)
xaccSplitsBeginStagedTransactionTraversals() resets the traversal marker for each transaction which i...
gnc_numeric xaccSplitGetNoclosingBalance(const Split *s)
The noclosing-balance is the currency-denominated balance of all transactions except 'closing' transa...
gint null_strcmp(const gchar *da, const gchar *db)
The null_strcmp compares strings a and b the same way that strcmp() does, except that either may be n...
void gnc_account_reset_convert_bayes_to_flat(void)
Reset the flag that indicates the function imap_convert_bayes_to_flat has been run.
GList * gnc_account_get_children_sorted(const Account *account)
This routine returns a GList of all children accounts of the specified account, ordered by xaccAccoun...
The bank account type denotes a savings or checking account held at a bank.
LotList * xaccAccountGetLotList(const Account *acc)
The xaccAccountGetLotList() routine returns a list of all lots in this account.
void xaccAccountRecomputeBalance(Account *acc)
The following recompute the partial balances (stored with the transaction) and the total balance...
GList * gnc_account_imap_get_info_bayes(Account *acc)
Returns a GList of structure imap_info of all Bayesian mappings for required Account.
GList * gnc_account_imap_get_info(Account *acc, const char *category)
Returns a GList of structure imap_info of all Non Bayesian mappings for required Account.
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
Account * gnc_account_lookup_by_full_name(const Account *any_acc, const gchar *name)
The gnc_account_lookup_full_name() subroutine works like gnc_account_lookup_by_name, but uses fully-qualified names using the given separator.
gboolean gnc_account_get_defer_bal_computation(Account *acc)
Get the account's flag for deferred balance computation.
void xaccAccountSetReconcilePostponeDate(Account *acc, time64 postpone_date)
DOCUMENT ME!
gboolean qof_commit_edit_part2(QofInstance *inst, void(*on_error)(QofInstance *, QofBackendError), void(*on_done)(QofInstance *), void(*on_free)(QofInstance *))
part2 – deal with the backend
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
The QofAccessFunc defines an arbitrary function pointer for access functions.
const char * xaccAccountGetTaxUSCode(const Account *acc)
DOCUMENT ME!
gboolean xaccAccountIsAPARType(GNCAccountType t)
Convenience function to check if the account is a valid business account type (meaning an Accounts Pa...
void qof_collection_insert_entity(QofCollection *, QofInstance *)
Take entity, remove it from whatever collection its currently in, and place it in a new collection...
bank account type – don't use this for now, see NUM_ACCOUNT_TYPES
void qof_collection_mark_clean(QofCollection *)
reset value of dirty flag
gboolean xaccAccountStringToType(const char *str, GNCAccountType *type)
Conversion routines for the account types to/from strings that are used in persistent storage...
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
Additional event handling code.
void xaccAccountSetIsOpeningBalance(Account *acc, gboolean val)
Set the "opening-balance" flag for an account.
void xaccAccountSetReconcilePostponeBalance(Account *acc, gnc_numeric balance)
DOCUMENT ME!
gboolean xaccAccountEqual(const Account *aa, const Account *ab, gboolean check_guids)
Compare two accounts for equality - this is a deep compare.
gboolean xaccAccountGetTaxRelated(const Account *acc)
DOCUMENT ME!
void gnc_account_set_start_cleared_balance(Account *acc, const gnc_numeric start_baln)
This function will set the starting cleared commodity balance for this account.
Account * xaccCloneAccount(const Account *from, QofBook *book)
The xaccCloneAccount() routine makes a simple copy of the indicated account, placing it in the indica...
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
gnc_numeric xaccAccountGetReconciledBalance(const Account *acc)
Get the current balance of the account, only including reconciled transactions.
asset (and liability) accounts indicate generic, generalized accounts that are none of the above...
gint gnc_account_n_children(const Account *account)
Return the number of children of the specified account.
void gnc_account_join_children(Account *to_parent, Account *from_parent)
The gnc_account_join_children() subroutine will move (reparent) all child accounts from the from_pare...
gnc_numeric xaccAccountGetBalanceAsOfDate(Account *acc, time64 date)
Get the balance of the account at the end of the day before the date specified.
gnc_numeric xaccAccountGetBalance(const Account *acc)
Get the current balance of the account, which may include future splits.
gboolean xaccAccountGetReconcileLastDate(const Account *acc, time64 *last_date)
DOCUMENT ME!
void dxaccAccountSetQuoteTZ(Account *acc, const char *tz)
Set the timezone to be used when interpreting the results from a given Finance::Quote backend...
The currency account type indicates that the account is a currency trading account.
void xaccAccountSetCommoditySCU(Account *acc, int scu)
Set the SCU for the account.
gboolean qof_instance_books_equal(gconstpointer ptr1, gconstpointer ptr2)
See if two QofInstances share the same book.
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed...
gnc_commodity * gnc_account_get_currency_or_parent(const Account *account)
Returns a gnc_commodity that is a currency, suitable for being a Transaction's currency.
gboolean xaccAccountGetHidden(const Account *acc)
Get the "hidden" flag for an account.
All arguments are required to have the same denominator, that denominator is to be used in the output...
void xaccAccountSetAppendText(Account *acc, gboolean val)
Set the "import-append-text" flag for an account.
GncImportMatchMap * gnc_account_imap_create_imap(Account *acc)
Obtain an ImportMatchMap object from an Account or a Book.
Generic api to store and retrieve preferences.
gint64 xaccAccountCountSplits(const Account *acc, gboolean include_children)
The xaccAccountCountSplits() routine returns the number of all the splits in the account.
gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Return a-b.
gboolean gnc_account_insert_split(Account *acc, Split *s)
Insert the given split from an account.
Definition: