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);
1349 qof_instance_set_destroying(acc, TRUE);
1353 PERR (
" instead of calling xaccFreeAccount(), please call\n" 1354 " xaccAccountBeginEdit(); xaccAccountDestroy();\n");
1357 xaccFreeAccountChildren(acc);
1363 PERR (
" instead of calling xaccFreeAccount(), please call\n" 1364 " xaccAccountBeginEdit(); xaccAccountDestroy();\n");
1366 for (lp = priv->lots; lp; lp = lp->next)
1368 GNCLot *lot =
static_cast<GNCLot*
>(lp->data);
1369 gnc_lot_destroy (lot);
1371 g_list_free (priv->lots);
1382 PERR (
" instead of calling xaccFreeAccount(), please call\n" 1383 " xaccAccountBeginEdit(); xaccAccountDestroy();\n");
1385 qof_instance_reset_editlevel(acc);
1387 slist = g_list_copy(priv->splits);
1388 for (lp = slist; lp; lp = lp->next)
1390 Split *s = (Split *) lp->data;
1403 priv->accountName = priv->accountCode = priv->description =
nullptr;
1405 if (priv->last_num != is_unset)
1406 g_free (priv->last_num);
1407 if (priv->tax_us_code != is_unset)
1408 g_free (priv->tax_us_code);
1409 if (priv->tax_us_pns != is_unset)
1410 g_free (priv->tax_us_pns);
1411 if (priv->color != is_unset)
1412 g_free (priv->color);
1413 if (priv->sort_order != is_unset)
1414 g_free (priv->sort_order);
1415 if (priv->notes != is_unset)
1416 g_free (priv->notes);
1417 if (priv->filter != is_unset)
1418 g_free (priv->filter);
1423 priv->last_num =
nullptr;
1424 priv->tax_us_code =
nullptr;
1425 priv->tax_us_pns =
nullptr;
1426 priv->color ==
nullptr;
1427 priv->sort_order ==
nullptr;
1428 priv->notes ==
nullptr;
1429 priv->filter ==
nullptr;
1431 priv->parent =
nullptr;
1432 priv->children =
nullptr;
1434 priv->balance = gnc_numeric_zero();
1435 priv->noclosing_balance = gnc_numeric_zero();
1436 priv->cleared_balance = gnc_numeric_zero();
1437 priv->reconciled_balance = gnc_numeric_zero();
1441 priv->commodity = NULL;
1443 priv->balance_dirty = FALSE;
1444 priv->sort_dirty = FALSE;
1447 g_object_unref(acc);
1457 g_return_if_fail(acc);
1461 static void on_done(QofInstance *inst)
1469 PERR(
"commit error: %d", errcode);
1470 gnc_engine_signal_commit_error( errcode );
1473 static void acc_free (QofInstance *inst)
1478 priv = GET_PRIVATE(acc);
1481 xaccFreeAccount(acc);
1485 destroy_pending_splits_for_account(QofInstance *ent, gpointer acc)
1487 Transaction *trans = (Transaction *) ent;
1491 while ((split = xaccTransFindSplitByAccount(trans, static_cast<Account*>(acc))))
1501 g_return_if_fail(acc);
1506 priv = GET_PRIVATE(acc);
1512 qof_instance_increase_editlevel(acc);
1515 xaccFreeAccountChildren(acc);
1517 PINFO (
"freeing splits for account %p (%s)",
1518 acc, priv->accountName ? priv->accountName :
"(null)");
1526 slist = g_list_copy(priv->splits);
1527 for (lp = slist; lp; lp = lp->next)
1529 Split *s =
static_cast<Split *
>(lp->data);
1536 g_list_free(priv->splits);
1537 priv->splits = NULL;
1554 for (lp = priv->lots; lp; lp = lp->next)
1556 GNCLot *lot =
static_cast<GNCLot*
>(lp->data);
1557 gnc_lot_destroy (lot);
1560 g_list_free(priv->lots);
1563 qof_instance_set_dirty(&acc->inst);
1564 qof_instance_decrease_editlevel(acc);
1568 xaccAccountBringUpToDate(acc);
1577 g_return_if_fail(GNC_IS_ACCOUNT(acc));
1579 qof_instance_set_destroying(acc, TRUE);
1587 compare_account_by_name (gconstpointer a, gconstpointer b)
1590 if (a && !b)
return 1;
1591 if (b && !a)
return -1;
1592 if (!a && !b)
return 0;
1593 priv_a = GET_PRIVATE((
Account*)a);
1594 priv_b = GET_PRIVATE((
Account*)b);
1595 if ((priv_a->accountCode && strlen (priv_a->accountCode)) ||
1596 (priv_b->accountCode && strlen (priv_b->accountCode)))
1597 return g_strcmp0 (priv_a->accountCode, priv_b->accountCode);
1598 return g_strcmp0 (priv_a->accountName, priv_b->accountName);
1602 xaccAcctChildrenEqual(
const GList *na,
1604 gboolean check_guids)
1606 if ((!na && nb) || (na && !nb))
1608 PINFO (
"only one has accounts");
1611 if (g_list_length ((GList*)na) != g_list_length ((GList*)nb))
1613 PINFO (
"Accounts have different numbers of children");
1621 GList *node = g_list_find_custom ((GList*)nb, aa,
1622 (GCompareFunc)compare_account_by_name);
1626 PINFO (
"Unable to find matching child account.");
1629 ab =
static_cast<Account*
>(node->data);
1638 PWARN (
"accounts %s and %s differ", sa, sb);
1654 if (!aa && !ab)
return TRUE;
1656 g_return_val_if_fail(GNC_IS_ACCOUNT(aa), FALSE);
1657 g_return_val_if_fail(GNC_IS_ACCOUNT(ab), FALSE);
1659 priv_aa = GET_PRIVATE(aa);
1660 priv_ab = GET_PRIVATE(ab);
1661 if (priv_aa->type != priv_ab->type)
1663 PWARN (
"types differ: %d vs %d", priv_aa->type, priv_ab->type);
1667 if (g_strcmp0(priv_aa->accountName, priv_ab->accountName) != 0)
1669 PWARN (
"names differ: %s vs %s", priv_aa->accountName, priv_ab->accountName);
1673 if (g_strcmp0(priv_aa->accountCode, priv_ab->accountCode) != 0)
1675 PWARN (
"codes differ: %s vs %s", priv_aa->accountCode, priv_ab->accountCode);
1679 if (g_strcmp0(priv_aa->description, priv_ab->description) != 0)
1681 PWARN (
"descriptions differ: %s vs %s", priv_aa->description, priv_ab->description);
1687 PWARN (
"commodities differ");
1695 PWARN (
"GUIDs differ");
1700 if (qof_instance_compare_kvp (QOF_INSTANCE (aa), QOF_INSTANCE (ab)) != 0)
1705 frame_a = qof_instance_kvp_as_string (QOF_INSTANCE (aa));
1706 frame_b = qof_instance_kvp_as_string (QOF_INSTANCE (ab));
1708 PWARN (
"kvp frames differ:\n%s\n\nvs\n\n%s", frame_a, frame_b);
1724 PWARN (
"starting balances differ: %s vs %s", str_a, str_b);
1733 priv_ab->starting_noclosing_balance))
1741 PWARN (
"starting noclosing balances differ: %s vs %s", str_a, str_b);
1749 priv_ab->starting_cleared_balance))
1757 PWARN (
"starting cleared balances differ: %s vs %s", str_a, str_b);
1766 priv_ab->starting_reconciled_balance))
1774 PWARN (
"starting reconciled balances differ: %s vs %s", str_a, str_b);
1790 PWARN (
"balances differ: %s vs %s", str_a, str_b);
1806 PWARN (
"noclosing balances differ: %s vs %s", str_a, str_b);
1821 PWARN (
"cleared balances differ: %s vs %s", str_a, str_b);
1829 if (!
gnc_numeric_equal(priv_aa->reconciled_balance, priv_ab->reconciled_balance))
1837 PWARN (
"reconciled balances differ: %s vs %s", str_a, str_b);
1848 GList *la = priv_aa->splits;
1849 GList *lb = priv_ab->splits;
1851 if ((la && !lb) || (!la && lb))
1853 PWARN (
"only one has splits");
1862 Split *sa = (Split *) la->data;
1863 Split *sb = (Split *) lb->data;
1867 PWARN (
"splits differ");
1875 if ((la != NULL) || (lb != NULL))
1877 PWARN (
"number of splits differs");
1883 if (!xaccAcctChildrenEqual(priv_aa->children, priv_ab->children, check_guids))
1885 PWARN (
"children differ");
1899 g_return_if_fail(GNC_IS_ACCOUNT(acc));
1904 priv = GET_PRIVATE(acc);
1905 priv->sort_dirty = TRUE;
1913 g_return_if_fail(GNC_IS_ACCOUNT(acc));
1918 priv = GET_PRIVATE(acc);
1919 priv->balance_dirty = TRUE;
1926 g_return_if_fail (GNC_IS_ACCOUNT (acc));
1931 priv = GET_PRIVATE (acc);
1932 priv->defer_bal_computation = defer;
1940 priv = GET_PRIVATE (acc);
1941 return priv->defer_bal_computation;
1954 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
1955 g_return_val_if_fail(GNC_IS_SPLIT(s), FALSE);
1957 priv = GET_PRIVATE(acc);
1958 node = g_list_find(priv->splits, s);
1962 if (qof_instance_get_editlevel(acc) == 0)
1964 priv->splits = g_list_insert_sorted(priv->splits, s,
1969 priv->splits = g_list_prepend(priv->splits, s);
1970 priv->sort_dirty = TRUE;
1978 priv->balance_dirty = TRUE;
1990 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
1991 g_return_val_if_fail(GNC_IS_SPLIT(s), FALSE);
1993 priv = GET_PRIVATE(acc);
1994 node = g_list_find(priv->splits, s);
1998 priv->splits = g_list_delete_link(priv->splits, node);
2004 priv->balance_dirty = TRUE;
2014 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2016 priv = GET_PRIVATE(acc);
2017 if (!priv->sort_dirty || (!force && qof_instance_get_editlevel(acc) > 0))
2019 priv->splits = g_list_sort(priv->splits, (GCompareFunc)
xaccSplitOrder);
2020 priv->sort_dirty = FALSE;
2021 priv->balance_dirty = TRUE;
2025 xaccAccountBringUpToDate(
Account *acc)
2041 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2042 g_return_if_fail(guid);
2045 PINFO(
"acct=%p", acc);
2048 qof_instance_set_dirty(&acc->inst);
2059 if (!guid || !book)
return NULL;
2072 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2074 priv = GET_PRIVATE(acc);
2083 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2095 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2097 priv = GET_PRIVATE(acc);
2099 for (node = priv->children; node; node = node->next)
2111 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
2113 return GET_PRIVATE(acc)->policy;
2121 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2123 priv = GET_PRIVATE(acc);
2131 xaccAccountRemoveLot (
Account *acc, GNCLot *lot)
2135 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2136 g_return_if_fail(GNC_IS_LOT(lot));
2138 priv = GET_PRIVATE(acc);
2139 g_return_if_fail(priv->lots);
2141 ENTER (
"(acc=%p, lot=%p)", acc, lot);
2142 priv->lots = g_list_remove(priv->lots, lot);
2145 LEAVE (
"(acc=%p, lot=%p)", acc, lot);
2156 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2157 g_return_if_fail(GNC_IS_LOT(lot));
2161 if (lot_account == acc)
2164 ENTER (
"(acc=%p, lot=%p)", acc, lot);
2169 old_acc = lot_account;
2170 opriv = GET_PRIVATE(old_acc);
2171 opriv->lots = g_list_remove(opriv->lots, lot);
2174 priv = GET_PRIVATE(acc);
2175 priv->lots = g_list_prepend(priv->lots, lot);
2176 gnc_lot_set_account(lot, acc);
2186 LEAVE (
"(acc=%p, lot=%p)", acc, lot);
2192 xaccPreSplitMove (Split *split, gpointer dummy)
2198 xaccPostSplitMove (Split *split,
Account *accto)
2202 xaccSplitSetAccount(split, accto);
2214 g_return_if_fail(GNC_IS_ACCOUNT(accfrom));
2215 g_return_if_fail(GNC_IS_ACCOUNT(accto));
2218 from_priv = GET_PRIVATE(accfrom);
2219 if (!from_priv->splits || accfrom == accto)
2224 ENTER (
"(accfrom=%p, accto=%p)", accfrom, accto);
2229 g_list_foreach(from_priv->splits, (GFunc)xaccPreSplitMove, NULL);
2246 g_list_foreach(from_priv->splits, (GFunc)xaccPostSplitMove, (gpointer)accto);
2249 g_assert(from_priv->splits == NULL);
2250 g_assert(from_priv->lots == NULL);
2254 LEAVE (
"(accfrom=%p, accto=%p)", accfrom, accto);
2290 gnc_numeric balance;
2291 gnc_numeric noclosing_balance;
2292 gnc_numeric cleared_balance;
2293 gnc_numeric reconciled_balance;
2296 if (NULL == acc)
return;
2298 priv = GET_PRIVATE(acc);
2299 if (qof_instance_get_editlevel(acc) > 0)
return;
2300 if (!priv->balance_dirty || priv->defer_bal_computation)
return;
2304 balance = priv->starting_balance;
2305 noclosing_balance = priv->starting_noclosing_balance;
2306 cleared_balance = priv->starting_cleared_balance;
2307 reconciled_balance = priv->starting_reconciled_balance;
2309 PINFO (
"acct=%s starting baln=%" G_GINT64_FORMAT
"/%" G_GINT64_FORMAT,
2310 priv->accountName, balance.num, balance.denom);
2311 for (lp = priv->splits; lp; lp = lp->next)
2313 Split *split = (Split *) lp->data;
2316 balance = gnc_numeric_add_fixed(balance, amt);
2318 if (
NREC != split->reconciled)
2320 cleared_balance = gnc_numeric_add_fixed(cleared_balance, amt);
2323 if (
YREC == split->reconciled ||
2324 FREC == split->reconciled)
2326 reconciled_balance =
2327 gnc_numeric_add_fixed(reconciled_balance, amt);
2331 noclosing_balance = gnc_numeric_add_fixed(noclosing_balance, amt);
2333 split->balance = balance;
2334 split->noclosing_balance = noclosing_balance;
2335 split->cleared_balance = cleared_balance;
2336 split->reconciled_balance = reconciled_balance;
2340 priv->balance = balance;
2341 priv->noclosing_balance = noclosing_balance;
2342 priv->cleared_balance = cleared_balance;
2343 priv->reconciled_balance = reconciled_balance;
2344 priv->balance_dirty = FALSE;
2363 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
2371 const char *da, *db;
2372 char *endptr = NULL;
2376 if ( aa && !ab )
return -1;
2377 if ( !aa && ab )
return +1;
2378 if ( !aa && !ab )
return 0;
2380 priv_aa = GET_PRIVATE(aa);
2381 priv_ab = GET_PRIVATE(ab);
2384 da = priv_aa->accountCode;
2385 db = priv_ab->accountCode;
2388 result = g_strcmp0 (da, db);
2394 if (-1 == revorder[0])
2399 revorder [typeorder[i]] = i;
2408 if (ta < tb)
return -1;
2409 if (ta > tb)
return +1;
2412 da = priv_aa->accountName;
2413 db = priv_ab->accountName;
2437 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2441 priv = GET_PRIVATE(acc);
2442 if (priv->type == tip)
2447 priv->balance_dirty = TRUE;
2458 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2459 g_return_if_fail(str);
2462 priv = GET_PRIVATE(acc);
2463 if (g_strcmp0(str, priv->accountName) == 0)
2478 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2481 priv = GET_PRIVATE(acc);
2482 if (g_strcmp0(str, priv->accountCode) == 0)
2497 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2500 priv = GET_PRIVATE(acc);
2501 if (g_strcmp0(str, priv->description) == 0)
2511 stripdup_or_null (
const char *value)
2515 auto temp = g_strstrip (g_strdup (value));
2526 set_kvp_string_path (
Account *acc, std::vector<std::string>
const & path,
2529 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2534 GValue v = G_VALUE_INIT;
2535 g_value_init (&v, G_TYPE_STRING);
2536 g_value_set_string (&v, value);
2537 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v, path);
2542 qof_instance_set_path_kvp (QOF_INSTANCE (acc), NULL, path);
2549 set_kvp_string_tag (
Account *acc,
const char *tag,
const char *value)
2551 set_kvp_string_path (acc, {tag}, value);
2555 get_kvp_string_path (
const Account *acc, std::vector<std::string>
const & path)
2557 GValue v = G_VALUE_INIT;
2558 if (acc == NULL)
return NULL;
2559 qof_instance_get_path_kvp (QOF_INSTANCE (acc), &v, path);
2560 auto retval = G_VALUE_HOLDS_STRING (&v) ? g_value_dup_string (&v) : NULL;
2566 get_kvp_string_tag (
const Account *acc,
const char *tag)
2568 return get_kvp_string_path (acc, {tag});
2574 auto priv = GET_PRIVATE (acc);
2575 if (priv->color != is_unset)
2576 g_free (priv->color);
2577 priv->color = stripdup_or_null (str);
2578 set_kvp_string_tag (acc,
"color", priv->color);
2584 auto priv = GET_PRIVATE (acc);
2585 if (priv->filter != is_unset)
2586 g_free (priv->filter);
2587 priv->filter = stripdup_or_null (str);
2588 set_kvp_string_tag (acc,
"filter", priv->filter);
2594 auto priv = GET_PRIVATE (acc);
2595 if (priv->sort_order != is_unset)
2596 g_free (priv->sort_order);
2597 priv->sort_order = stripdup_or_null (str);
2598 set_kvp_string_tag (acc,
"sort-order", priv->sort_order);
2604 auto priv = GET_PRIVATE (acc);
2605 priv->sort_reversed = sortreversed ? TriState::True : TriState::False;
2606 set_kvp_string_tag (acc,
"sort-reversed", sortreversed ?
"true" : NULL);
2610 qofAccountSetParent (
Account *acc, QofInstance *parent)
2614 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2615 g_return_if_fail(GNC_IS_ACCOUNT(parent));
2617 parent_acc = GNC_ACCOUNT(parent);
2621 mark_account (parent_acc);
2630 auto priv = GET_PRIVATE (acc);
2631 if (priv->notes != is_unset)
2632 g_free (priv->notes);
2633 priv->notes = stripdup_or_null (str);
2634 set_kvp_string_tag (acc,
"notes", priv->notes);
2644 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2645 g_return_if_fail(GNC_IS_COMMODITY(com));
2648 priv = GET_PRIVATE(acc);
2649 if (com == priv->commodity)
2654 priv->commodity = com;
2657 priv->non_standard_scu = FALSE;
2660 for (lp = priv->splits; lp; lp = lp->next)
2662 Split *s = (Split *) lp->data;
2670 priv->sort_dirty = TRUE;
2671 priv->balance_dirty = TRUE;
2688 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2690 priv = GET_PRIVATE(acc);
2692 priv->commodity_scu = scu;
2694 priv->non_standard_scu = TRUE;
2702 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 0);
2703 return GET_PRIVATE(acc)->commodity_scu;
2711 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 0);
2713 priv = GET_PRIVATE(acc);
2714 if (priv->non_standard_scu || !priv->commodity)
2715 return priv->commodity_scu;
2724 g_return_if_fail(GNC_IS_ACCOUNT(acc));
2726 priv = GET_PRIVATE(acc);
2727 if (priv->non_standard_scu == flag)
2730 priv->non_standard_scu = flag;
2738 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 0);
2739 return GET_PRIVATE(acc)->non_standard_scu;
2750 GValue v = G_VALUE_INIT;
2752 gnc_commodity *commodity;
2753 gnc_commodity_table *
table;
2755 if ((!acc) || (!currency))
return;
2756 g_value_init (&v, G_TYPE_STRING);
2757 g_value_set_string (&v, s);
2758 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v, {
"old-currency"});
2764 commodity = gnc_commodity_table_lookup_unique (
table, s);
2778 account_foreach_descendant (
const Account *acc, AccountCb thunk,
2779 void* user_data,
bool sort)
2783 g_return_if_fail (GNC_IS_ACCOUNT(acc));
2784 g_return_if_fail (thunk);
2786 auto priv{GET_PRIVATE(acc)};
2789 children = g_list_copy (priv->children);
2793 children = priv->children;
2795 for (
auto node = children; node; node = node->next)
2797 auto child =
static_cast<Account*
>(node->data);
2798 thunk (child, user_data);
2799 account_foreach_descendant (child, thunk, user_data, sort);
2803 g_list_free (children);
2814 g_assert(GNC_IS_ACCOUNT(new_parent));
2815 g_assert(GNC_IS_ACCOUNT(child));
2818 ppriv = GET_PRIVATE(new_parent);
2819 cpriv = GET_PRIVATE(child);
2820 old_parent = cpriv->parent;
2821 if (old_parent == new_parent)
2843 PWARN (
"reparenting accounts across books is not correctly supported\n");
2852 cpriv->parent = new_parent;
2853 ppriv->children = g_list_append(ppriv->children, child);
2854 qof_instance_set_dirty(&new_parent->inst);
2855 qof_instance_set_dirty(&child->inst);
2878 if (!parent)
return;
2880 ppriv = GET_PRIVATE(parent);
2881 cpriv = GET_PRIVATE(child);
2883 if (cpriv->parent != parent)
2885 PERR (
"account not a child of parent");
2891 ed.idx = g_list_index(ppriv->children, child);
2893 ppriv->children = g_list_remove(ppriv->children, child);
2899 cpriv->parent = NULL;
2907 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
2908 return GET_PRIVATE(acc)->parent;
2916 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
2918 priv = GET_PRIVATE(acc);
2919 while (priv->parent)
2922 priv = GET_PRIVATE(acc);
2931 g_return_val_if_fail(GNC_IS_ACCOUNT(account), FALSE);
2932 return (GET_PRIVATE(account)->parent == NULL);
2938 g_return_val_if_fail(GNC_IS_ACCOUNT(account), NULL);
2939 return g_list_copy(GET_PRIVATE(account)->children);
2948 g_return_val_if_fail(GNC_IS_ACCOUNT(account), NULL);
2951 priv = GET_PRIVATE(account);
2952 if (!priv->children)
2954 return g_list_sort(g_list_copy(priv->children), (GCompareFunc)
xaccAccountOrder);
2960 g_return_val_if_fail(GNC_IS_ACCOUNT(account), 0);
2961 return g_list_length(GET_PRIVATE(account)->children);
2967 g_return_val_if_fail(GNC_IS_ACCOUNT(parent), -1);
2968 g_return_val_if_fail(GNC_IS_ACCOUNT(child), -1);
2969 return g_list_index(GET_PRIVATE(parent)->children, child);
2975 g_return_val_if_fail(GNC_IS_ACCOUNT(parent), NULL);
2976 return static_cast<Account*
>(g_list_nth_data(GET_PRIVATE(parent)->children, num));
2980 count_acct (
Account *account, gpointer user_data)
2982 auto count {
static_cast<int*
>(user_data)};
2990 account_foreach_descendant (account, count_acct, &count, FALSE);
3000 g_return_val_if_fail(GNC_IS_ACCOUNT(account), 0);
3002 priv = GET_PRIVATE(account);
3005 account = priv->parent;
3006 priv = GET_PRIVATE(account);
3018 gint depth = 0, child_depth;
3020 g_return_val_if_fail(GNC_IS_ACCOUNT(account), 0);
3022 priv = GET_PRIVATE(account);
3023 if (!priv->children)
3026 for (node = priv->children; node; node = g_list_next(node))
3029 depth = MAX(depth, child_depth);
3035 collect_acct (
Account *account, gpointer user_data)
3037 auto listptr{
static_cast<GList**
>(user_data)};
3038 *listptr = g_list_prepend (*listptr, account);
3044 GList* list =
nullptr;
3045 account_foreach_descendant (account, collect_acct, &list, FALSE);
3046 return g_list_reverse (list);
3052 GList* list =
nullptr;
3053 account_foreach_descendant (account, collect_acct, &list, TRUE);
3054 return g_list_reverse (list);
3063 account_foreach_descendant_breadthfirst_until (
const Account *acc,
3067 gpointer result {
nullptr};
3069 g_return_val_if_fail (GNC_IS_ACCOUNT(acc),
nullptr);
3070 g_return_val_if_fail (thunk,
nullptr);
3072 for (
auto node = GET_PRIVATE(acc)->children; !result && node; node = node->next)
3073 result = thunk (static_cast<Account*>(node->data), user_data);
3075 for (
auto node = GET_PRIVATE(acc)->children; !result && node; node = node->next)
3076 result = account_foreach_descendant_breadthfirst_until (static_cast<Account*>(node->data), thunk, user_data);
3082 is_acct_name (
Account *account, gpointer user_data)
3084 auto name {
static_cast<gchar*
>(user_data)};
3091 return (
Account*)account_foreach_descendant_breadthfirst_until (parent, is_acct_name, (
char*)name);
3095 is_acct_code (
Account *account, gpointer user_data)
3097 auto name {
static_cast<gchar*
>(user_data)};
3104 return (
Account*)account_foreach_descendant_breadthfirst_until (parent, is_acct_code, (
char*)code);
3108 is_opening_balance_account (
Account* account, gpointer data)
3110 gnc_commodity* commodity = GNC_COMMODITY(data);
3127 gnc_account_lookup_by_full_name_helper (
const Account *parent,
3134 g_return_val_if_fail(GNC_IS_ACCOUNT(parent), NULL);
3135 g_return_val_if_fail(names, NULL);
3138 ppriv = GET_PRIVATE(parent);
3139 for (node = ppriv->children; node; node = node->next)
3143 priv = GET_PRIVATE(account);
3144 if (g_strcmp0(priv->accountName, names[0]) == 0)
3148 if (names[1] == NULL)
3152 if (!priv->children)
3156 found = gnc_account_lookup_by_full_name_helper(account, &names[1]);
3177 g_return_val_if_fail(GNC_IS_ACCOUNT(any_acc), NULL);
3178 g_return_val_if_fail(name, NULL);
3181 rpriv = GET_PRIVATE(root);
3182 while (rpriv->parent)
3184 root = rpriv->parent;
3185 rpriv = GET_PRIVATE(root);
3188 found = gnc_account_lookup_by_full_name_helper(root, names);
3197 gnc_commodity* commodity)
3200 auto rpriv{GET_PRIVATE(root)};
3201 for (
auto node = rpriv->children; node; node = node->next)
3203 auto account{
static_cast<Account*
>(node->data)};
3214 retval = g_list_prepend(retval, account);
3219 for (
auto node = rpriv->children; node; node = node->next)
3221 auto account{
static_cast<Account*
>(node->data)};
3227 retval = g_list_concat(result, retval);
3240 g_return_if_fail(GNC_IS_ACCOUNT(acc));
3241 g_return_if_fail(thunk);
3243 priv = GET_PRIVATE(acc);
3244 for (node = priv->children; node; node = node->next)
3246 thunk (static_cast<Account*>(node->data), user_data);
3255 account_foreach_descendant (acc, thunk, user_data, FALSE);
3263 gpointer result {
nullptr};
3265 g_return_val_if_fail (GNC_IS_ACCOUNT(acc),
nullptr);
3266 g_return_val_if_fail (thunk,
nullptr);
3268 auto priv{GET_PRIVATE(acc)};
3270 for (
auto node = priv->children; node; node = node->next)
3272 auto child =
static_cast<Account*
>(node->data);
3273 result = thunk (child, user_data);
3288 return GET_PRIVATE(acc)->type;
3292 qofAccountGetTypeString (
const Account *acc)
3294 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
3299 qofAccountSetType (
Account *acc,
const char *type_string)
3301 g_return_if_fail(GNC_IS_ACCOUNT(acc));
3302 g_return_if_fail(type_string);
3309 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
3310 return GET_PRIVATE(acc)->accountName;
3319 const gchar **names;
3324 if (NULL == account)
3325 return g_strdup(
"");
3328 g_return_val_if_fail(GNC_IS_ACCOUNT(account), g_strdup(
""));
3331 priv = GET_PRIVATE(account);
3333 return g_strdup(
"");
3338 for (a = account; a; a = priv->parent)
3340 priv = GET_PRIVATE(a);
3346 names = (
const gchar **)g_malloc(level *
sizeof(gchar *));
3347 names[--level] = NULL;
3348 for (a = account; level > 0; a = priv->parent)
3350 priv = GET_PRIVATE(a);
3351 names[--level] = priv->accountName;
3355 fullname = g_strjoinv(account_separator, (gchar **)names);
3364 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
3365 return GET_PRIVATE(acc)->accountCode;
3371 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
3372 return GET_PRIVATE(acc)->description;
3378 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
3379 auto priv = GET_PRIVATE (acc);
3380 if (priv->color == is_unset)
3381 priv->color = get_kvp_string_tag (acc,
"color");
3388 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 0);
3389 auto priv = GET_PRIVATE (acc);
3390 if (priv->filter == is_unset)
3391 priv->filter = get_kvp_string_tag (acc,
"filter");
3392 return priv->filter;
3398 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 0);
3399 auto priv = GET_PRIVATE (acc);
3400 if (priv->sort_order == is_unset)
3401 priv->sort_order = get_kvp_string_tag (acc,
"sort-order");
3402 return priv->sort_order;
3409 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
3410 auto priv = GET_PRIVATE (acc);
3411 if (priv->sort_reversed == TriState::Unset)
3413 auto sort_reversed = get_kvp_string_tag (acc,
"sort-reversed");
3414 priv->sort_reversed = g_strcmp0 (sort_reversed,
"true") ?
3415 TriState::False : TriState::True;
3416 g_free (sort_reversed);
3418 return (priv->sort_reversed == TriState::True);
3424 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
3425 auto priv = GET_PRIVATE (acc);
3426 if (priv->notes == is_unset)
3427 priv->notes = get_kvp_string_tag (acc,
"notes");
3434 GValue v = G_VALUE_INIT;
3435 const char *s = NULL;
3436 gnc_commodity_table *
table;
3437 gnc_commodity *retval = NULL;
3439 if (!acc)
return NULL;
3440 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v, {
"old-currency"});
3441 if (G_VALUE_HOLDS_STRING (&v))
3442 s = g_value_get_string (&v);
3446 retval = gnc_commodity_table_lookup_unique (
table, s);
3456 if (!GNC_IS_ACCOUNT(acc))
3458 return GET_PRIVATE(acc)->commodity;
3463 gnc_commodity * commodity;
3464 g_return_val_if_fail (account, NULL);
3471 const Account *parent_account = account;
3489 while (parent_account);
3501 g_return_if_fail(GNC_IS_ACCOUNT(acc));
3503 priv = GET_PRIVATE(acc);
3504 priv->starting_balance = start_baln;
3505 priv->balance_dirty = TRUE;
3510 const gnc_numeric start_baln)
3514 g_return_if_fail(GNC_IS_ACCOUNT(acc));
3516 priv = GET_PRIVATE(acc);
3517 priv->starting_cleared_balance = start_baln;
3518 priv->balance_dirty = TRUE;
3523 const gnc_numeric start_baln)
3527 g_return_if_fail(GNC_IS_ACCOUNT(acc));
3529 priv = GET_PRIVATE(acc);
3530 priv->starting_reconciled_balance = start_baln;
3531 priv->balance_dirty = TRUE;
3537 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3538 return GET_PRIVATE(acc)->balance;
3544 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3545 return GET_PRIVATE(acc)->cleared_balance;
3551 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3552 return GET_PRIVATE(acc)->reconciled_balance;
3556 xaccAccountGetProjectedMinimumBalance (
const Account *acc)
3561 gnc_numeric lowest = gnc_numeric_zero ();
3562 int seen_a_transaction = 0;
3564 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3566 priv = GET_PRIVATE(acc);
3568 for (node = g_list_last(priv->splits); node; node = node->prev)
3570 Split *split =
static_cast<Split*
>(node->data);
3572 if (!seen_a_transaction)
3575 seen_a_transaction = 1;
3594 GetBalanceAsOfDate (
Account *acc,
time64 date, gboolean ignclosing)
3602 Split *latest =
nullptr;
3604 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3609 for (GList *lp = GET_PRIVATE(acc)->splits; lp; lp = lp->next)
3613 latest = (Split *)lp->data;
3617 return gnc_numeric_zero();
3628 return GetBalanceAsOfDate (acc, date, FALSE);
3632 xaccAccountGetNoclosingBalanceAsOfDate (
Account *acc,
time64 date)
3634 return GetBalanceAsOfDate (acc, date, TRUE);
3640 gnc_numeric balance = gnc_numeric_zero();
3642 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3644 for (GList *node = GET_PRIVATE(acc)->splits; node; node = node->next)
3646 Split *split = (Split*) node->data;
3659 xaccAccountGetPresentBalance (
const Account *acc)
3661 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3678 xaccAccountConvertBalanceToCurrency(
const Account *acc,
3679 gnc_numeric balance,
3680 const gnc_commodity *balance_currency,
3681 const gnc_commodity *new_currency)
3690 book = gnc_account_get_book (acc);
3694 pdb, balance, balance_currency, new_currency);
3704 xaccAccountConvertBalanceToCurrencyAsOfDate(
const Account *acc,
3705 gnc_numeric balance,
3706 const gnc_commodity *balance_currency,
3707 const gnc_commodity *new_currency,
3717 book = gnc_account_get_book (acc);
3721 pdb, balance, balance_currency, new_currency, date);
3732 xaccAccountGetXxxBalanceInCurrency (
const Account *acc,
3733 xaccGetBalanceFn fn,
3734 const gnc_commodity *report_currency)
3737 gnc_numeric balance;
3739 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3740 g_return_val_if_fail(fn, gnc_numeric_zero());
3741 g_return_val_if_fail(GNC_IS_COMMODITY(report_currency), gnc_numeric_zero());
3743 priv = GET_PRIVATE(acc);
3745 balance = xaccAccountConvertBalanceToCurrency(acc, balance,
3752 xaccAccountGetXxxBalanceAsOfDateInCurrency(
Account *acc,
time64 date,
3753 xaccGetBalanceAsOfDateFn fn,
3754 const gnc_commodity *report_commodity)
3758 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
3759 g_return_val_if_fail(fn, gnc_numeric_zero());
3760 g_return_val_if_fail(GNC_IS_COMMODITY(report_commodity), gnc_numeric_zero());
3762 priv = GET_PRIVATE(acc);
3763 return xaccAccountConvertBalanceToCurrencyAsOfDate(
3764 acc, fn(acc, date), priv->commodity, report_commodity, date);
3772 const gnc_commodity *currency;
3773 gnc_numeric balance;
3774 xaccGetBalanceFn fn;
3775 xaccGetBalanceAsOfDateFn asOfDateFn;
3786 xaccAccountBalanceHelper (
Account *acc, gpointer data)
3789 gnc_numeric balance;
3791 if (!cb->fn || !cb->currency)
3793 balance = xaccAccountGetXxxBalanceInCurrency (acc, cb->fn, cb->currency);
3800 xaccAccountBalanceAsOfDateHelper (
Account *acc, gpointer data)
3803 gnc_numeric balance;
3805 g_return_if_fail (cb->asOfDateFn && cb->currency);
3807 balance = xaccAccountGetXxxBalanceAsOfDateInCurrency (
3808 acc, cb->date, cb->asOfDateFn, cb->currency);
3827 xaccAccountGetXxxBalanceInCurrencyRecursive (
const Account *acc,
3828 xaccGetBalanceFn fn,
3829 const gnc_commodity *report_commodity,
3830 gboolean include_children)
3832 gnc_numeric balance;
3834 if (!acc)
return gnc_numeric_zero ();
3835 if (!report_commodity)
3837 if (!report_commodity)
3838 return gnc_numeric_zero();
3840 balance = xaccAccountGetXxxBalanceInCurrency (acc, fn, report_commodity);
3844 if (include_children)
3851 cb.balance = balance;
3857 balance = cb.balance;
3864 xaccAccountGetXxxBalanceAsOfDateInCurrencyRecursive (
3866 const gnc_commodity *report_commodity, gboolean include_children)
3868 gnc_numeric balance;
3870 g_return_val_if_fail(acc, gnc_numeric_zero());
3871 if (!report_commodity)
3873 if (!report_commodity)
3874 return gnc_numeric_zero();
3876 balance = xaccAccountGetXxxBalanceAsOfDateInCurrency(
3877 acc, date, fn, report_commodity);
3881 if (include_children)
3888 cb.balance = balance;
3894 balance = cb.balance;
3901 xaccAccountGetBalanceInCurrency (
const Account *acc,
3902 const gnc_commodity *report_commodity,
3903 gboolean include_children)
3906 rc = xaccAccountGetXxxBalanceInCurrencyRecursive (
3908 PINFO(
" baln=%" G_GINT64_FORMAT
"/%" G_GINT64_FORMAT, rc.num, rc.denom);
3914 xaccAccountGetClearedBalanceInCurrency (
const Account *acc,
3915 const gnc_commodity *report_commodity,
3916 gboolean include_children)
3918 return xaccAccountGetXxxBalanceInCurrencyRecursive (
3924 xaccAccountGetReconciledBalanceInCurrency (
const Account *acc,
3925 const gnc_commodity *report_commodity,
3926 gboolean include_children)
3928 return xaccAccountGetXxxBalanceInCurrencyRecursive (
3934 xaccAccountGetPresentBalanceInCurrency (
const Account *acc,
3935 const gnc_commodity *report_commodity,
3936 gboolean include_children)
3938 return xaccAccountGetXxxBalanceAsOfDateInCurrencyRecursive (
3945 xaccAccountGetProjectedMinimumBalanceInCurrency (
3947 const gnc_commodity *report_commodity,
3948 gboolean include_children)
3950 return xaccAccountGetXxxBalanceInCurrencyRecursive (
3951 acc, xaccAccountGetProjectedMinimumBalance, report_commodity,
3958 gboolean include_children)
3960 return xaccAccountGetXxxBalanceAsOfDateInCurrencyRecursive (
3968 gboolean include_children)
3970 return xaccAccountGetXxxBalanceAsOfDateInCurrencyRecursive
3971 (acc, date, xaccAccountGetNoclosingBalanceAsOfDate,
3972 report_commodity, include_children);
3987 xaccAccountGetNoclosingBalanceChangeForPeriod (
Account *acc,
time64 t1,
3988 time64 t2, gboolean recurse)
4015 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
4017 return GET_PRIVATE(acc)->splits;
4025 PWARN (
"xaccAccountCountSplits is deprecated and will be removed \ 4026 in GnuCash 5.0. If testing for an empty account, use \ 4027 xaccAccountGetSplitList(account) == NULL instead. To test descendants \ 4028 as well, use gnc_account_and_descendants_empty.");
4029 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 0);
4042 gboolean gnc_account_and_descendants_empty (
Account *acc)
4044 g_return_val_if_fail (GNC_IS_ACCOUNT (acc), FALSE);
4045 auto priv = GET_PRIVATE (acc);
4046 if (priv->splits !=
nullptr)
return FALSE;
4047 for (
auto *n = priv->children; n; n = n->next)
4049 if (!gnc_account_and_descendants_empty (static_cast<Account*>(n->data)))
4058 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
4059 return g_list_copy(GET_PRIVATE(acc)->lots);
4064 gboolean (*match_func)(GNCLot *lot,
4065 gpointer user_data),
4066 gpointer user_data, GCompareFunc sort_func)
4070 GList *retval = NULL;
4072 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
4074 priv = GET_PRIVATE(acc);
4075 for (lot_list = priv->lots; lot_list; lot_list = lot_list->next)
4077 GNCLot *lot =
static_cast<GNCLot*
>(lot_list->data);
4083 if (match_func && !(match_func)(lot, user_data))
4087 retval = g_list_prepend (retval, lot);
4091 retval = g_list_sort (retval, sort_func);
4098 gpointer (*proc)(GNCLot *lot,
void *data),
void *data)
4102 gpointer result = NULL;
4104 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
4105 g_return_val_if_fail(proc, NULL);
4107 priv = GET_PRIVATE(acc);
4108 for (node = priv->lots; node; node = node->next)
4109 if ((result = proc((GNCLot *)node->data, data)))
4116 set_boolean_key (
Account *acc, std::vector<std::string>
const & path, gboolean option)
4118 GValue v = G_VALUE_INIT;
4119 g_return_if_fail(GNC_IS_ACCOUNT(acc));
4121 g_value_init (&v, G_TYPE_BOOLEAN);
4122 g_value_set_boolean (&v, option);
4124 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v, path);
4131 boolean_from_key (
const Account *acc, std::vector<std::string>
const & path)
4133 GValue v = G_VALUE_INIT;
4134 gboolean retval = FALSE;
4135 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4136 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v, path);
4137 if (G_VALUE_HOLDS_INT64 (&v))
4138 retval = (g_value_get_int64 (&v) != 0);
4139 if (G_VALUE_HOLDS_BOOLEAN (&v))
4140 retval = (g_value_get_boolean (&v));
4141 if (G_VALUE_HOLDS_STRING (&v))
4142 retval = !strcmp (g_value_get_string (&v),
"true");
4154 return boolean_from_key(acc, {
"tax-related"});
4160 set_boolean_key(acc, {
"tax-related"}, tax_related);
4166 auto priv = GET_PRIVATE (acc);
4167 if (priv->tax_us_code == is_unset)
4168 priv->tax_us_code = get_kvp_string_path (acc, {
"tax-US",
"code"});
4169 return priv->tax_us_code;
4175 auto priv = GET_PRIVATE (acc);
4176 if (priv->tax_us_code != is_unset)
4177 g_free (priv->tax_us_code);
4178 priv->tax_us_code = g_strdup (code);
4179 set_kvp_string_path (acc, {
"tax-US",
"code"}, priv->tax_us_code);
4185 auto priv = GET_PRIVATE (acc);
4186 if (priv->tax_us_pns == is_unset)
4187 priv->tax_us_pns = get_kvp_string_path (acc, {
"tax-US",
"payer-name-source"});
4188 return priv->tax_us_pns;
4194 auto priv = GET_PRIVATE (acc);
4195 if (priv->tax_us_pns != is_unset)
4196 g_free (priv->tax_us_pns);
4197 priv->tax_us_pns = g_strdup (source);
4198 set_kvp_string_path (acc, {
"tax-US",
"payer-name-source"}, priv->tax_us_pns);
4204 gint64 copy_number = 0;
4205 GValue v = G_VALUE_INIT;
4206 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4207 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v, {
"tax-US",
"copy-number"});
4208 if (G_VALUE_HOLDS_INT64 (&v))
4209 copy_number = g_value_get_int64 (&v);
4212 return (copy_number == 0) ? 1 : copy_number;
4218 g_return_if_fail(GNC_IS_ACCOUNT(acc));
4220 if (copy_number != 0)
4222 GValue v = G_VALUE_INIT;
4223 g_value_init (&v, G_TYPE_INT64);
4224 g_value_set_int64 (&v, copy_number);
4225 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v, {
"tax-US",
"copy-number"});
4230 qof_instance_set_path_kvp (QOF_INSTANCE (acc),
nullptr, {
"tax-US",
"copy-number"});
4243 return _(dflt_acct_debit_str);
4245 auto result = gnc_acct_debit_strs.find(acct_type);
4246 if (result != gnc_acct_debit_strs.end())
4247 return _(result->second);
4249 return _(dflt_acct_debit_str);
4255 return _(dflt_acct_credit_str);
4257 auto result = gnc_acct_credit_strs.find(acct_type);
4258 if (result != gnc_acct_credit_strs.end())
4259 return _(result->second);
4261 return _(dflt_acct_credit_str);
4270 return boolean_from_key(acc, {
"placeholder"});
4276 set_boolean_key(acc, {
"placeholder"}, val);
4282 return boolean_from_key(acc, {
"import-append-text"});
4288 set_boolean_key(acc, {
"import-append-text"}, val);
4296 auto priv = GET_PRIVATE(acc);
4297 if (priv->equity_type == TriState::Unset)
4299 auto equity_type = get_kvp_string_tag (acc,
"equity-type");
4300 priv->equity_type = g_strcmp0 (equity_type,
"opening-balance") ?
4301 TriState::False : TriState::True;
4302 g_free (equity_type);
4304 return (priv->equity_type == TriState::True);
4312 auto priv = GET_PRIVATE (acc);
4313 priv->equity_type = val ? TriState::True : TriState::False;
4314 set_kvp_string_tag(acc,
"equity-type", val ?
"opening-balance" :
nullptr);
4320 GList *descendants, *node;
4323 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), PLACEHOLDER_NONE);
4327 for (node = descendants; node; node = node->next)
4330 ret = PLACEHOLDER_CHILD;
4334 g_list_free(descendants);
4344 return boolean_from_key (acc, {KEY_RECONCILE_INFO,
"auto-interest-transfer"});
4350 set_boolean_key (acc, {KEY_RECONCILE_INFO,
"auto-interest-transfer"}, val);
4359 return boolean_from_key (acc, {
"hidden"});
4365 set_boolean_key (acc, {
"hidden"}, val);
4373 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4377 priv = GET_PRIVATE(acc);
4378 while ((acc = priv->parent) != NULL)
4380 priv = GET_PRIVATE(acc);
4395 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4396 g_return_val_if_fail(GNC_IS_ACCOUNT(ancestor), FALSE);
4399 while (parent && parent != ancestor)
4400 parent = GET_PRIVATE(parent)->parent;
4402 return (parent == ancestor);
4411 #define GNC_RETURN_ENUM_AS_STRING(x) case (ACCT_TYPE_ ## x): return #x; 4418 GNC_RETURN_ENUM_AS_STRING(NONE);
4419 GNC_RETURN_ENUM_AS_STRING(BANK);
4420 GNC_RETURN_ENUM_AS_STRING(CASH);
4421 GNC_RETURN_ENUM_AS_STRING(CREDIT);
4422 GNC_RETURN_ENUM_AS_STRING(ASSET);
4423 GNC_RETURN_ENUM_AS_STRING(LIABILITY);
4424 GNC_RETURN_ENUM_AS_STRING(STOCK);
4425 GNC_RETURN_ENUM_AS_STRING(MUTUAL);
4426 GNC_RETURN_ENUM_AS_STRING(CURRENCY);
4427 GNC_RETURN_ENUM_AS_STRING(INCOME);
4428 GNC_RETURN_ENUM_AS_STRING(EXPENSE);
4429 GNC_RETURN_ENUM_AS_STRING(EQUITY);
4430 GNC_RETURN_ENUM_AS_STRING(RECEIVABLE);
4431 GNC_RETURN_ENUM_AS_STRING(PAYABLE);
4432 GNC_RETURN_ENUM_AS_STRING(ROOT);
4433 GNC_RETURN_ENUM_AS_STRING(TRADING);
4434 GNC_RETURN_ENUM_AS_STRING(CHECKING);
4435 GNC_RETURN_ENUM_AS_STRING(SAVINGS);
4436 GNC_RETURN_ENUM_AS_STRING(MONEYMRKT);
4437 GNC_RETURN_ENUM_AS_STRING(CREDITLINE);
4439 PERR (
"asked to translate unknown account type %d.\n", type);
4445 #undef GNC_RETURN_ENUM_AS_STRING 4447 #define GNC_RETURN_ON_MATCH(x) \ 4448 if(g_strcmp0(#x, (str)) == 0) { *type = ACCT_TYPE_ ## x; return(TRUE); } 4454 GNC_RETURN_ON_MATCH(NONE);
4455 GNC_RETURN_ON_MATCH(BANK);
4456 GNC_RETURN_ON_MATCH(CASH);
4457 GNC_RETURN_ON_MATCH(CREDIT);
4458 GNC_RETURN_ON_MATCH(ASSET);
4459 GNC_RETURN_ON_MATCH(LIABILITY);
4460 GNC_RETURN_ON_MATCH(STOCK);
4461 GNC_RETURN_ON_MATCH(MUTUAL);
4462 GNC_RETURN_ON_MATCH(CURRENCY);
4463 GNC_RETURN_ON_MATCH(INCOME);
4464 GNC_RETURN_ON_MATCH(EXPENSE);
4465 GNC_RETURN_ON_MATCH(EQUITY);
4466 GNC_RETURN_ON_MATCH(RECEIVABLE);
4467 GNC_RETURN_ON_MATCH(PAYABLE);
4468 GNC_RETURN_ON_MATCH(ROOT);
4469 GNC_RETURN_ON_MATCH(TRADING);
4470 GNC_RETURN_ON_MATCH(CHECKING);
4471 GNC_RETURN_ON_MATCH(SAVINGS);
4472 GNC_RETURN_ON_MATCH(MONEYMRKT);
4473 GNC_RETURN_ON_MATCH(CREDITLINE);
4475 PERR(
"asked to translate unknown account type string %s.\n",
4476 str ? str :
"(null)");
4481 #undef GNC_RETURN_ON_MATCH 4527 return _(account_type_name [type]);
4569 PERR(
"bad account type: %d", type);
4615 PERR(
"bad account type: %d", type);
4722 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4724 priv = GET_PRIVATE(acc);
4736 GValue v = G_VALUE_INIT;
4737 gboolean retval = FALSE;
4738 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4739 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v, {KEY_RECONCILE_INFO,
"last-date"});
4740 if (G_VALUE_HOLDS_INT64 (&v))
4741 date = g_value_get_int64 (&v);
4760 GValue v = G_VALUE_INIT;
4761 g_return_if_fail(GNC_IS_ACCOUNT(acc));
4763 g_value_init (&v, G_TYPE_INT64);
4764 g_value_set_int64 (&v, last_date);
4766 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v, {KEY_RECONCILE_INFO,
"last-date"});
4777 int *months,
int *days)
4779 GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT;
4780 int64_t m = 0, d = 0;
4781 gboolean retval = FALSE;
4783 if (!acc)
return FALSE;
4784 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4785 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v1,
4786 {KEY_RECONCILE_INFO,
"last-interval",
"months"});
4787 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v2,
4788 {KEY_RECONCILE_INFO,
"last-interval",
"days"});
4789 if (G_VALUE_HOLDS_INT64 (&v1))
4790 m = g_value_get_int64 (&v1);
4791 if (G_VALUE_HOLDS_INT64 (&v2))
4792 d = g_value_get_int64 (&v2);
4801 g_value_unset (&v1);
4802 g_value_unset (&v2);
4812 GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT;
4813 g_return_if_fail(GNC_IS_ACCOUNT(acc));
4815 g_value_init (&v1, G_TYPE_INT64);
4816 g_value_set_int64 (&v1, months);
4817 g_value_init (&v2, G_TYPE_INT64);
4818 g_value_set_int64 (&v2, days);
4820 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v1,
4821 {KEY_RECONCILE_INFO,
"last-interval",
"months"});
4822 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v2,
4823 {KEY_RECONCILE_INFO,
"last-interval",
"days"});
4826 g_value_unset (&v1);
4827 g_value_unset (&v2);
4837 gboolean retval = FALSE;
4838 GValue v = G_VALUE_INIT;
4839 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4840 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v,
4841 {KEY_RECONCILE_INFO, KEY_POSTPONE,
"date"});
4842 if (G_VALUE_HOLDS_INT64 (&v))
4843 date = g_value_get_int64 (&v);
4848 *postpone_date = date;
4861 GValue v = G_VALUE_INIT;
4862 g_return_if_fail(GNC_IS_ACCOUNT(acc));
4864 g_value_init (&v, G_TYPE_INT64);
4865 g_value_set_int64 (&v, postpone_date);
4867 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v,
4868 {KEY_RECONCILE_INFO, KEY_POSTPONE,
"date"});
4879 gnc_numeric *balance)
4881 gnc_numeric bal = gnc_numeric_zero ();
4882 GValue v = G_VALUE_INIT;
4883 gboolean retval = FALSE;
4884 g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
4885 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v,
4886 {KEY_RECONCILE_INFO, KEY_POSTPONE,
"balance"});
4887 if (G_VALUE_HOLDS_BOXED (&v))
4889 bal = *(gnc_numeric*)g_value_get_boxed (&v);
4907 GValue v = G_VALUE_INIT;
4908 g_return_if_fail(GNC_IS_ACCOUNT(acc));
4910 g_value_init (&v, GNC_TYPE_NUMERIC);
4911 g_value_set_boxed (&v, &balance);
4913 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v,
4914 {KEY_RECONCILE_INFO, KEY_POSTPONE,
"balance"});
4930 qof_instance_set_path_kvp (QOF_INSTANCE(acc),
nullptr, {KEY_RECONCILE_INFO, KEY_POSTPONE});
4941 auto priv = GET_PRIVATE (acc);
4942 if (priv->last_num == is_unset)
4943 priv->last_num = get_kvp_string_tag (acc,
"last-num");
4944 return priv->last_num;
4953 auto priv = GET_PRIVATE (acc);
4954 if (priv->last_num != is_unset)
4955 g_free (priv->last_num);
4956 priv->last_num = g_strdup (num);
4957 set_kvp_string_tag (acc,
"last-num", priv->last_num);
4961 GetOrMakeOrphanAccount (
Account *root, gnc_commodity * currency)
4966 g_return_val_if_fail (root, NULL);
4971 PERR (
"No currency specified!");
4975 accname = g_strconcat (_(
"Orphaned Gains"),
"-",
4991 _(
"Realized Gains or Losses from " 4992 "Commodity or Trading Accounts " 4993 "that haven't been recorded elsewhere."));
5008 GValue v = G_VALUE_INIT;
5009 std::vector<std::string> path {KEY_LOT_MGMT,
"gains-acct",
5014 g_return_val_if_fail (acc != NULL, NULL);
5015 qof_instance_get_path_kvp (QOF_INSTANCE(acc), &v, path);
5016 if (G_VALUE_HOLDS_BOXED (&v))
5017 guid = (
GncGUID*)g_value_get_boxed (&v);
5025 GValue vr = G_VALUE_INIT;
5026 g_value_init (&vr, GNC_TYPE_GUID);
5027 g_value_set_boxed (&vr, guid);
5028 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &vr, path);
5029 qof_instance_set_dirty (QOF_INSTANCE (acc));
5030 g_value_unset (&vr);
5039 return gains_account;
5051 set_kvp_string_tag (acc,
"old-price-source", src);
5060 static char *source =
nullptr;
5061 if (!acc)
return NULL;
5066 source = get_kvp_string_tag (acc,
"old-price-source");
5078 set_kvp_string_tag (acc,
"old-quote-tz", tz);
5087 static char *quote_tz =
nullptr;
5088 if (!acc)
return NULL;
5091 quote_tz = get_kvp_string_tag (acc,
"old-quote-tz");
5101 GValue v = G_VALUE_INIT;
5109 g_value_init (&v, G_TYPE_INT64);
5110 g_value_set_int64 (&v, status);
5111 qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v,
5112 {KEY_RECONCILE_INFO, KEY_INCLUDE_CHILDREN});
5128 GValue v = G_VALUE_INIT;
5130 if (!acc)
return FALSE;
5131 qof_instance_get_path_kvp (QOF_INSTANCE (acc), &v,
5132 {KEY_RECONCILE_INFO, KEY_INCLUDE_CHILDREN});
5133 retval = G_VALUE_HOLDS_INT64 (&v) ? g_value_get_int64 (&v) : FALSE;
5147 finder_help_function(
const Account *acc,
const char *description,
5148 Split **split, Transaction **trans )
5154 if (split) *split = NULL;
5155 if (trans) *trans = NULL;
5158 if (acc == NULL)
return;
5163 priv = GET_PRIVATE(acc);
5164 for (slp = g_list_last(priv->splits); slp; slp = slp->prev)
5166 Split *lsplit =
static_cast<Split*
>(slp->data);
5171 if (split) *split = lsplit;
5172 if (trans) *trans = ltrans;
5184 finder_help_function(acc, description, &split, NULL);
5199 finder_help_function(acc, description, NULL, &trans);
5210 GList *children, *node;
5213 g_return_if_fail(GNC_IS_ACCOUNT(to_parent));
5214 g_return_if_fail(GNC_IS_ACCOUNT(from_parent));
5217 from_priv = GET_PRIVATE(from_parent);
5218 if (!from_priv->children)
5222 children = g_list_copy(from_priv->children);
5223 for (node = children; node; node = g_list_next(node))
5225 g_list_free(children);
5235 GList *node_a, *node_b, *work, *worker;
5237 g_return_if_fail(GNC_IS_ACCOUNT(parent));
5239 ppriv = GET_PRIVATE(parent);
5240 for (node_a = ppriv->children; node_a; node_a = node_a->next)
5244 priv_a = GET_PRIVATE(acc_a);
5245 for (node_b = node_a->next; node_b; node_b = g_list_next(node_b))
5249 priv_b = GET_PRIVATE(acc_b);
5250 if (0 !=
null_strcmp(priv_a->accountName, priv_b->accountName))
5252 if (0 !=
null_strcmp(priv_a->accountCode, priv_b->accountCode))
5254 if (0 !=
null_strcmp(priv_a->description, priv_b->description))
5264 if (priv_a->type != priv_b->type)
5268 if (priv_b->children)
5270 work = g_list_copy(priv_b->children);
5271 for (worker = work; worker; worker = g_list_next(worker))
5283 while (priv_b->splits)
5284 xaccSplitSetAccount (static_cast <Split*> (priv_b->splits->data), acc_a);
5288 node_b = g_list_previous(node_b);
5307 for (lp = splits; lp; lp = lp->next)
5309 Split *s = static_cast <Split*> (lp->data);
5310 Transaction *trans = s->parent;
5325 priv = GET_PRIVATE(account);
5332 if (trans == NULL)
return FALSE;
5334 if (trans->marker < stage)
5336 trans->marker = stage;
5343 static void do_one_split (Split *s, gpointer data)
5345 Transaction *trans = s->parent;
5349 static void do_one_account (
Account *account, gpointer data)
5352 g_list_foreach(priv->splits, (GFunc)do_one_split, NULL);
5362 g_list_foreach(descendants, (GFunc)do_one_account, NULL);
5363 g_list_free(descendants);
5369 TransactionCallback thunk,
5381 priv = GET_PRIVATE(acc);
5382 for (split_p = priv->splits; split_p; split_p = next)
5388 next = g_list_next(split_p);
5390 s = static_cast <Split*> (split_p->data);
5392 if (trans && (trans->marker < stage))
5394 trans->marker = stage;
5397 retval = thunk(trans, cb_data);
5398 if (retval)
return retval;
5409 TransactionCallback thunk,
5413 GList *acc_p, *split_p;
5421 priv = GET_PRIVATE(acc);
5422 for (acc_p = priv->children; acc_p; acc_p = g_list_next(acc_p))
5425 stage, thunk, cb_data);
5426 if (retval)
return retval;
5430 for (split_p = priv->splits; split_p; split_p = g_list_next(split_p))
5432 s = static_cast <Split*> (split_p->data);
5434 if (trans && (trans->marker < stage))
5436 trans->marker = stage;
5439 retval = thunk(trans, cb_data);
5440 if (retval)
return retval;
5453 int (*proc)(Transaction *t,
void *data),
5456 if (!acc || !proc)
return 0;
5467 if (!acc || !proc)
return 0;
5478 #define IMAP_FRAME "import-map" 5479 #define IMAP_FRAME_BAYES "import-map-bayes" 5487 if (!acc)
return NULL;
5495 imap->book = gnc_account_get_book (acc);
5503 const char *category,
5506 GValue v = G_VALUE_INIT;
5509 if (!imap || !key)
return NULL;
5510 std::vector<std::string> path {IMAP_FRAME};
5512 path.push_back (category);
5513 path.push_back (key);
5514 qof_instance_get_path_kvp (QOF_INSTANCE (imap->acc), &v, path);
5515 if (G_VALUE_HOLDS_BOXED (&v))
5516 guid = (
GncGUID*)g_value_get_boxed (&v);
5525 const char *category,
5529 GValue v = G_VALUE_INIT;
5530 if (!imap || !key || !acc || (strlen (key) == 0))
return;
5531 std::vector<std::string> path {IMAP_FRAME};
5533 path.emplace_back (category);
5534 path.emplace_back (key);
5535 g_value_init (&v, GNC_TYPE_GUID);
5538 qof_instance_set_path_kvp (QOF_INSTANCE (imap->acc), &v, path);
5539 qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
5547 const char *category,
5550 if (!imap || !key)
return;
5551 std::vector<std::string> path {IMAP_FRAME};
5553 path.emplace_back (category);
5554 path.emplace_back (key);
5556 if (qof_instance_has_path_slot (QOF_INSTANCE (imap->acc), path))
5558 qof_instance_slot_path_delete (QOF_INSTANCE (imap->acc), path);
5560 qof_instance_slot_path_delete_if_empty (QOF_INSTANCE (imap->acc), {IMAP_FRAME, category});
5561 qof_instance_slot_path_delete_if_empty (QOF_INSTANCE (imap->acc), {IMAP_FRAME});
5563 qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
5579 double product_difference;
5584 std::string account_guid;
5585 int64_t token_count;
5593 std::vector<AccountTokenCount> accounts;
5594 int64_t total_count;
5602 std::string account_guid;
5603 int32_t probability;
5607 build_token_info(
char const * suffix, KvpValue * value,
TokenAccountsInfo & tokenInfo)
5611 tokenInfo.total_count += value->get<int64_t>();
5613 tokenInfo.accounts.emplace_back(
AccountTokenCount{std::string{suffix}, value->get<int64_t>()});
5620 static constexpr
int probability_factor = 100000;
5622 static FinalProbabilityVec
5623 build_probabilities(ProbabilityVec
const & first_pass)
5625 FinalProbabilityVec ret;
5626 for (
auto const & first_pass_prob : first_pass)
5628 auto const & account_probability = first_pass_prob.second;
5633 int32_t probability = (account_probability.product /
5634 (account_probability.product + account_probability.product_difference)) * probability_factor;
5635 ret.push_back({first_pass_prob.first, probability});
5641 highest_probability(FinalProbabilityVec
const & probabilities)
5643 AccountInfo ret {
"", std::numeric_limits<int32_t>::min()};
5644 for (
auto const & prob : probabilities)
5645 if (prob.second > ret.probability)
5650 static ProbabilityVec
5656 for (
auto current_token = tokens; current_token; current_token = current_token->next)
5659 auto path = std::string{IMAP_FRAME_BAYES
"/"} + static_cast <
char const *> (current_token->data) +
"/";
5660 qof_instance_foreach_slot_prefix (QOF_INSTANCE (imap->acc), path, &build_token_info, tokenInfo);
5661 for (
auto const & current_account_token : tokenInfo.accounts)
5663 auto item = std::find_if(ret.begin(), ret.end(), [¤t_account_token]
5664 (std::pair<std::string, AccountProbability>
const & a) {
5665 return current_account_token.account_guid == a.first;
5667 if (item != ret.end())
5669 item->second.product = ((double)current_account_token.token_count /
5670 (
double)tokenInfo.total_count) * item->second.product;
5671 item->second.product_difference = ((
double)1 - ((double)current_account_token.token_count /
5672 (
double)tokenInfo.total_count)) * item->second.product_difference;
5678 new_probability.product = ((double)current_account_token.token_count /
5679 (
double)tokenInfo.total_count);
5680 new_probability.product_difference = 1 - (new_probability.product);
5681 ret.push_back({current_account_token.account_guid, std::move(new_probability)});
5689 look_for_old_separator_descendants (
Account *root, std::string
const & full_name,
const gchar *separator)
5691 GList *top_accounts, *ptr;
5695 PINFO(
"Incoming full_name is '%s', current separator is '%s'", full_name.c_str (), separator);
5697 for (ptr = top_accounts; ptr; ptr = g_list_next (ptr))
5701 if (g_str_has_prefix (full_name.c_str (), name))
5703 gint name_len = strlen (name);
5704 const gchar old_sep = full_name[name_len];
5705 if (!g_ascii_isalnum (old_sep))
5707 if (name_len > found_len)
5709 found_sep = full_name[name_len];
5710 found_len = name_len;
5715 g_list_free (top_accounts);
5716 std::string new_name {full_name};
5718 std::replace (new_name.begin (), new_name.end (), found_sep, *separator);
5719 PINFO (
"Return full_name is '%s'", new_name.c_str ());
5724 get_guid_from_account_name (
Account * root, std::string
const & name)
5729 auto temp_account_name = look_for_old_separator_descendants (root, name,
5734 return temp_guid.to_string ();
5738 convert_entry (KvpEntry entry,
Account* root)
5741 auto account_name = entry.first.back();
5742 if (!gnc::GUID::is_valid_guid (account_name))
5748 entry.first.pop_back();
5749 auto guid_str = get_guid_from_account_name (root, account_name);
5750 entry.first.emplace_back (guid_str);
5752 std::string new_key {std::accumulate (entry.first.begin(), entry.first.end(), std::string {})};
5753 new_key = IMAP_FRAME_BAYES + new_key;
5754 return {new_key, entry.second};
5757 static std::vector<FlatKvpEntry>
5760 auto frame = qof_instance_get_slots (QOF_INSTANCE (acc));
5761 auto slot = frame->get_slot ({IMAP_FRAME_BAYES});
5764 auto imap_frame = slot->get<KvpFrame*> ();
5765 auto flat_kvp = imap_frame->flatten_kvp ();
5767 std::vector <FlatKvpEntry> ret;
5768 for (
auto const & flat_entry : flat_kvp)
5770 auto converted_entry = convert_entry (flat_entry, root);
5772 if (converted_entry.first.size())
5773 ret.emplace_back (converted_entry);
5779 convert_imap_account_bayes_to_flat (
Account *acc)
5781 auto frame = qof_instance_get_slots (QOF_INSTANCE (acc));
5782 if (!frame->get_keys().size())
5784 auto flat_imap = get_flat_imap(acc);
5785 if (!flat_imap.size ())
5788 frame->set({IMAP_FRAME_BAYES},
nullptr);
5789 std::for_each(flat_imap.begin(), flat_imap.end(),
5790 [&frame] (FlatKvpEntry
const & entry) {
5791 frame->set({entry.first.c_str()}, entry.second);
5793 qof_instance_set_dirty (QOF_INSTANCE (acc));
5802 imap_convert_bayes_to_flat (QofBook * book)
5804 auto root = gnc_book_get_root_account (book);
5807 for (
auto ptr = accts; ptr; ptr = g_list_next (ptr))
5810 if (convert_imap_account_bayes_to_flat (acc))
5816 g_list_free (accts);
5823 imap_convert_bayes_to_flat_run =
false;
5838 check_import_map_data (QofBook *book)
5840 if (gnc_features_check_used (book, GNC_FEATURE_GUID_FLAT_BAYESIAN) ||
5841 imap_convert_bayes_to_flat_run)
5845 imap_convert_bayes_to_flat (book);
5846 imap_convert_bayes_to_flat_run =
true;
5849 static constexpr
double threshold = .90 * probability_factor;
5857 check_import_map_data (imap->book);
5858 auto first_pass = get_first_pass_probabilities(imap, tokens);
5859 if (!first_pass.size())
5861 auto final_probabilities = build_probabilities(first_pass);
5862 if (!final_probabilities.size())
5864 auto best = highest_probability(final_probabilities);
5865 if (best.account_guid ==
"")
5867 if (best.probability < threshold)
5871 guid = gnc::GUID::from_string(best.account_guid);
5875 auto account =
xaccAccountLookup (reinterpret_cast<GncGUID*>(&guid), imap->book);
5880 change_imap_entry (
GncImportMatchMap *imap, std::string
const & path, int64_t token_count)
5882 GValue value = G_VALUE_INIT;
5884 PINFO(
"Source Account is '%s', Count is '%" G_GINT64_FORMAT
"'",
5888 if (qof_instance_has_slot (QOF_INSTANCE(imap->acc), path.c_str ()))
5890 int64_t existing_token_count = 0;
5893 qof_instance_get_path_kvp (QOF_INSTANCE (imap->acc), &value, {path});
5895 if (G_VALUE_HOLDS_INT64 (&value))
5896 existing_token_count = g_value_get_int64 (&value);
5898 PINFO(
"found existing value of '%" G_GINT64_FORMAT
"'", existing_token_count);
5900 token_count = token_count + existing_token_count;
5903 if (!G_IS_VALUE (&value))
5904 g_value_init (&value, G_TYPE_INT64);
5906 g_value_set_int64 (&value, token_count);
5909 qof_instance_set_path_kvp (QOF_INSTANCE (imap->acc), &value, {path});
5911 g_value_unset (&value);
5920 GList *current_token;
5922 char *account_fullname;
5931 check_import_map_data (imap->book);
5933 g_return_if_fail (acc != NULL);
5937 PINFO(
"account name: '%s'", account_fullname);
5942 for (current_token = g_list_first(tokens); current_token;
5943 current_token = current_token->next)
5949 if (!current_token->data || (*((
char*)current_token->data) ==
'\0'))
5953 PINFO(
"adding token '%s'", (
char*)current_token->data);
5954 auto path = std::string {IMAP_FRAME_BAYES} +
'/' +
static_cast<char*
>(current_token->data) +
'/' + guid_string;
5956 change_imap_entry (imap, path, token_count);
5959 qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
5961 g_free (account_fullname);
5962 g_free (guid_string);
5969 build_non_bayes (
const char *key,
const GValue *value, gpointer user_data)
5971 if (!G_VALUE_HOLDS_BOXED (value))
5975 gchar *guid_string = NULL;
5980 guid = (
GncGUID*)g_value_get_boxed (value);
5983 PINFO(
"build_non_bayes: match string '%s', match account guid: '%s'",
5984 (
char*)key, guid_string);
5988 imapInfo_node->source_account = imapInfo->source_account;
5990 imapInfo_node->head = g_strdup (imapInfo->head);
5991 imapInfo_node->match_string = g_strdup (key);
5992 imapInfo_node->category = g_strdup (imapInfo->category);
5993 imapInfo_node->count = g_strdup (
" ");
5995 imapInfo->list = g_list_prepend (imapInfo->list, imapInfo_node);
5997 g_free (guid_string);
6001 build_bayes (
const char *suffix, KvpValue * value,
GncImapInfo & imapInfo)
6004 std::string account_guid {&suffix[guid_start]};
6008 guid = gnc::GUID::from_string (account_guid);
6012 PWARN(
"Invalid GUID string from %s%s", IMAP_FRAME_BAYES, suffix);
6014 auto map_account =
xaccAccountLookup (&guid, gnc_account_get_book (imapInfo.source_account));
6016 auto count = value->get <int64_t> ();
6017 imap_node->source_account = imapInfo.source_account;
6018 imap_node->map_account = map_account;
6019 imap_node->head = g_strdup_printf (
"%s%s", IMAP_FRAME_BAYES, suffix);
6020 imap_node->match_string = g_strndup (&suffix[1], guid_start - 2);
6021 imap_node->category = g_strdup(
" ");
6022 imap_node->count = g_strdup_printf (
"%" G_GINT64_FORMAT, count);
6023 imapInfo.list = g_list_prepend (imapInfo.list, imap_node);
6029 check_import_map_data (gnc_account_get_book (acc));
6033 qof_instance_foreach_slot_prefix (QOF_INSTANCE (acc), IMAP_FRAME_BAYES, &build_bayes, imapInfo);
6034 return g_list_reverse(imapInfo.list);
6044 std::vector<std::string> path {IMAP_FRAME};
6046 path.emplace_back (category);
6048 imapInfo.source_account = acc;
6049 imapInfo.list = list;
6051 imapInfo.head = g_strdup (IMAP_FRAME);
6052 imapInfo.category = g_strdup (category);
6054 if (qof_instance_has_path_slot (QOF_INSTANCE (acc), path))
6056 qof_instance_foreach_slot (QOF_INSTANCE(acc), IMAP_FRAME, category,
6057 build_non_bayes, &imapInfo);
6059 g_free (imapInfo.head);
6060 g_free (imapInfo.category);
6061 return g_list_reverse(imapInfo.list);
6070 return get_kvp_string_path (acc, {head, category});
6072 return get_kvp_string_path (acc, {head});
6078 char *match_string, gboolean empty)
6082 std::vector<std::string> path {head};
6084 path.emplace_back (category);
6086 path.emplace_back (match_string);
6088 if (qof_instance_has_path_slot (QOF_INSTANCE (acc), path))
6092 qof_instance_slot_path_delete_if_empty (QOF_INSTANCE(acc), path);
6094 qof_instance_slot_path_delete (QOF_INSTANCE(acc), path);
6095 PINFO(
"Account is '%s', head is '%s', category is '%s', match_string is'%s'",
6097 qof_instance_set_dirty (QOF_INSTANCE(acc));
6108 auto slots = qof_instance_get_slots_prefix (QOF_INSTANCE (acc), IMAP_FRAME_BAYES);
6109 if (!slots.size())
return;
6111 for (
auto const & entry : slots)
6113 qof_instance_slot_path_delete (QOF_INSTANCE (acc), {entry.first});
6115 qof_instance_set_dirty (QOF_INSTANCE(acc));
6124 destroy_all_child_accounts (
Account *acc, gpointer data)
6131 gnc_account_book_end(QofBook* book)
6133 Account *root_account = gnc_book_get_root_account (book);
6143 accounts = g_list_reverse (accounts);
6144 g_list_foreach (accounts, (GFunc)destroy_all_child_accounts,
nullptr);
6145 g_list_free (accounts);
6158 static QofObject account_object_def =
6161 DI(.e_type = ) GNC_ID_ACCOUNT,
6164 DI(.book_begin = ) NULL,
6165 DI(.book_end = ) gnc_account_book_end,
6173 gboolean xaccAccountRegister (
void)
6175 static QofParam params[] =
6178 ACCOUNT_NAME_, QOF_TYPE_STRING,
6183 ACCOUNT_CODE_, QOF_TYPE_STRING,
6188 ACCOUNT_DESCRIPTION_, QOF_TYPE_STRING,
6193 ACCOUNT_COLOR_, QOF_TYPE_STRING,
6198 ACCOUNT_FILTER_, QOF_TYPE_STRING,
6203 ACCOUNT_SORT_ORDER_, QOF_TYPE_STRING,
6208 ACCOUNT_SORT_REVERSED_, QOF_TYPE_BOOLEAN,
6213 ACCOUNT_NOTES_, QOF_TYPE_STRING,
6218 ACCOUNT_PRESENT_, QOF_TYPE_NUMERIC,
6222 ACCOUNT_BALANCE_, QOF_TYPE_NUMERIC,
6226 ACCOUNT_CLEARED_, QOF_TYPE_NUMERIC,
6230 ACCOUNT_RECONCILED_, QOF_TYPE_NUMERIC,
6234 ACCOUNT_TYPE_, QOF_TYPE_STRING,
6239 ACCOUNT_FUTURE_MINIMUM_, QOF_TYPE_NUMERIC,
6243 ACCOUNT_TAX_RELATED, QOF_TYPE_BOOLEAN,
6248 ACCOUNT_OPENING_BALANCE_, QOF_TYPE_BOOLEAN,
6253 ACCOUNT_SCU, QOF_TYPE_INT32,
6258 ACCOUNT_NSCU, QOF_TYPE_BOOLEAN,
6263 ACCOUNT_PARENT, GNC_ID_ACCOUNT,
6272 QOF_PARAM_GUID, QOF_TYPE_GUID,
6283 using AccountSet = std::unordered_set<Account*>;
6284 static void maybe_add_descendants (
Account* acc, gpointer arg)
6286 g_return_if_fail (acc);
6288 if (static_cast <AccountSet*> (arg)->insert (acc).second)
6289 g_list_foreach (GET_PRIVATE(acc)->children, (GFunc) maybe_add_descendants, arg);
6293 gnc_accounts_and_all_descendants (GList *accounts)
6296 g_list_foreach (accounts, (GFunc) maybe_add_descendants, &accset);
6297 return std::accumulate (accset.begin(), accset.end(), (GList*)
nullptr, g_list_prepend);
6304 utest_account_get_private (
Account *acc)
6306 return GET_PRIVATE (acc);
6310 _utest_account_fill_functions(
void)
6314 func->get_private = utest_account_get_private;
6315 func->coll_get_root_account = gnc_coll_get_root_account;
6316 func->xaccFreeAccountChildren = xaccFreeAccountChildren;
6317 func->xaccFreeAccount = xaccFreeAccount;
6318 func->qofAccountSetParent = qofAccountSetParent;
6319 func->gnc_account_lookup_by_full_name_helper =
6320 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.