コード例 #1
0
ファイル: gnc-invoice-sql.cpp プロジェクト: tmertens/gnucash
/* ================================================================= */
bool
GncSqlInvoiceBackend::commit (GncSqlBackend* be, QofInstance* inst)
{
    const GncGUID* guid;
    GncInvoice* invoice;
    E_DB_OPERATION op;
    gboolean is_infant;
    gboolean is_ok = TRUE;

    g_return_val_if_fail (inst != NULL, FALSE);
    g_return_val_if_fail (GNC_IS_INVOICE (inst), FALSE);
    g_return_val_if_fail (be != NULL, FALSE);

    invoice = GNC_INVOICE (inst);

    is_infant = qof_instance_get_infant (inst);
    if (qof_instance_get_destroying (inst))
    {
        op = OP_DB_DELETE;
    }
    else if (be->pristine() || is_infant)
    {
        op = OP_DB_INSERT;
    }
    else
    {
        op = OP_DB_UPDATE;
    }
    if (op != OP_DB_DELETE)
    {
        // Ensure the commodity is in the db
        is_ok = gnc_sql_save_commodity (be, gncInvoiceGetCurrency (invoice));
    }

    if (is_ok)
    {
        is_ok = gnc_sql_do_db_operation (be, op, TABLE_NAME, GNC_ID_INVOICE, inst,
                                         col_table);
    }

    if (is_ok)
    {
        // Now, commit or delete any slots
        guid = qof_instance_get_guid (inst);
        if (!qof_instance_get_destroying (inst))
        {
            is_ok = gnc_sql_slots_save (be, guid, is_infant, inst);
        }
        else
        {
            is_ok = gnc_sql_slots_delete (be, guid);
        }
    }

    return is_ok;
}
コード例 #2
0
ファイル: gnc-employee-sql.cpp プロジェクト: CAARNICL/gnucash
/* ================================================================= */
static gboolean
save_employee (GncSqlBackend* be, QofInstance* inst)
{
    GncEmployee* emp;
    const GncGUID* guid;
    E_DB_OPERATION op;
    gboolean is_infant;
    gboolean is_ok = TRUE;

    g_return_val_if_fail (inst != NULL, FALSE);
    g_return_val_if_fail (GNC_IS_EMPLOYEE (inst), FALSE);
    g_return_val_if_fail (be != NULL, FALSE);

    emp = GNC_EMPLOYEE (inst);

    is_infant = qof_instance_get_infant (inst);
    if (qof_instance_get_destroying (inst))
    {
        op = OP_DB_DELETE;
    }
    else if (be->is_pristine_db || is_infant)
    {
        op = OP_DB_INSERT;
    }
    else
    {
        op = OP_DB_UPDATE;
    }
    if (op != OP_DB_DELETE)
    {
        // Ensure the commodity is in the db
        is_ok = gnc_sql_save_commodity (be, gncEmployeeGetCurrency (emp));
    }

    if (is_ok)
    {
        is_ok = gnc_sql_do_db_operation (be, op, TABLE_NAME, GNC_ID_EMPLOYEE, emp,
                                         col_table);
    }

    if (is_ok)
    {
        // Now, commit or delete any slots
        guid = qof_instance_get_guid (inst);
        if (!qof_instance_get_destroying (inst))
        {
            is_ok = gnc_sql_slots_save (be, guid, is_infant, inst);
        }
        else
        {
            is_ok = gnc_sql_slots_delete (be, guid);
        }
    }

    return is_ok;
}
コード例 #3
0
ファイル: gnc-tax-table-sql.cpp プロジェクト: Bob-IT/gnucash
bool
GncSqlTaxTableBackend::commit (GncSqlBackend* sql_be, QofInstance* inst)
{
    GncTaxTable* tt;
    const GncGUID* guid;
    E_DB_OPERATION op;
    gboolean is_infant;
    gboolean is_ok;

    g_return_val_if_fail (inst != NULL, FALSE);
    g_return_val_if_fail (GNC_IS_TAXTABLE (inst), FALSE);
    g_return_val_if_fail (sql_be != NULL, FALSE);

    tt = GNC_TAXTABLE (inst);

    is_infant = qof_instance_get_infant (inst);
    if (qof_instance_get_destroying (inst))
    {
        op = OP_DB_DELETE;
    }
    else if (sql_be->pristine() || is_infant)
    {
        op = OP_DB_INSERT;
    }
    else
    {
        op = OP_DB_UPDATE;
    }
    is_ok = sql_be->do_db_operation(op, TT_TABLE_NAME, GNC_ID_TAXTABLE, tt,
                                    tt_col_table);

    if (is_ok)
    {
        // Now, commit or delete any slots and tax table entries
        guid = qof_instance_get_guid (inst);
        if (!qof_instance_get_destroying (inst))
        {
            is_ok = gnc_sql_slots_save (sql_be, guid, is_infant, inst);
            if (is_ok)
            {
                is_ok = save_tt_entries (sql_be, guid, gncTaxTableGetEntries (tt));
            }
        }
        else
        {
            is_ok = gnc_sql_slots_delete (sql_be, guid);
            if (is_ok)
            {
                is_ok = delete_all_tt_entries (sql_be, guid);
            }
        }
    }

    return is_ok;
}
コード例 #4
0
ファイル: gnc-vendor-sql.cpp プロジェクト: Mechtilde/gnucash
/* ================================================================= */
bool
GncSqlVendorBackend::commit (GncSqlBackend* sql_be, QofInstance* inst)
{
    GncVendor* v;
    const GncGUID* guid;
    E_DB_OPERATION op;
    gboolean is_infant;
    gboolean is_ok = TRUE;

    g_return_val_if_fail (inst != NULL, FALSE);
    g_return_val_if_fail (GNC_IS_VENDOR (inst), FALSE);
    g_return_val_if_fail (sql_be != NULL, FALSE);

    v = GNC_VENDOR (inst);

    is_infant = qof_instance_get_infant (inst);
    if (qof_instance_get_destroying (inst))
    {
        op = OP_DB_DELETE;
    }
    else if (sql_be->pristine() || is_infant)
    {
        op = OP_DB_INSERT;
    }
    else
    {
        op = OP_DB_UPDATE;
    }
    if (op != OP_DB_DELETE)
    {
        // Ensure the commodity is in the db
        is_ok = sql_be->save_commodity (gncVendorGetCurrency(v));
    }
    if (is_ok)
    {
        is_ok = sql_be->do_db_operation(op, TABLE_NAME, GNC_ID_VENDOR, v,
                                        col_table);
    }

    if (is_ok)
    {
        // Now, commit or delete any slots
        guid = qof_instance_get_guid (inst);
        if (!qof_instance_get_destroying (inst))
        {
            is_ok = gnc_sql_slots_save (sql_be, guid, is_infant, inst);
        }
        else
        {
            is_ok = gnc_sql_slots_delete (sql_be, guid);
        }
    }

    return is_ok;
}
コード例 #5
0
ファイル: Scrub2.c プロジェクト: Mechtilde/gnucash
gboolean
xaccScrubMergeSubSplits (Split *split, gboolean strict)
{
    gboolean rc = FALSE;
    Transaction *txn;
    SplitList *node;
    GNCLot *lot;

    if (strict && (FALSE == is_subsplit (split))) return FALSE;

    txn = split->parent;

    // Don't mess with splits from an invoice transaction
    // Those are the responsibility of the business code
    if (gncInvoiceGetInvoiceFromTxn (txn)) return FALSE;

    lot = xaccSplitGetLot (split);

    ENTER ("(Lot=%s)", gnc_lot_get_title(lot));
restart:
    for (node = txn->splits; node; node = node->next)
    {
        Split *s = node->data;
        if (xaccSplitGetLot (s) != lot) continue;
        if (s == split) continue;
        if (qof_instance_get_destroying(s)) continue;

        // Don't mess with splits from an invoice transaction
        // Those are the responsibility of the business code
        if (gncInvoiceGetInvoiceFromTxn (s->parent)) return FALSE;

        if (strict)
        {
            /* OK, this split is in the same lot (and thus same account)
             * as the indicated split.  Make sure it is really a subsplit
             * of the split we started with.  It's possible to have two
             * splits in the same lot and transaction that are not subsplits
             * of each other, the test-period test suite does this, for
             * example.  Only worry about adjacent sub-splits.  By
             * repeatedly merging adjacent subsplits, we'll get the non-
             * adjacent ones too. */
            if (!xaccSplitIsPeerSplit (split, s))
                continue;
        }

        merge_splits (split, s);
        rc = TRUE;
        goto restart;
    }
    if (rc && gnc_numeric_zero_p (split->amount))
    {
        time64 pdate = xaccTransGetDate (txn);
        gchar *pdatestr = gnc_ctime (&pdate);
        PWARN ("Result of merge has zero amt!");
        PWARN ("Transaction details - posted date %s - description %s", pdatestr, xaccTransGetDescription(txn));
        g_free (pdatestr);
    }
    LEAVE (" splits merged=%d", rc);
    return rc;
}
コード例 #6
0
ファイル: gncTaxTable.c プロジェクト: mlq/gnucash
static void
gncTaxTableFree (GncTaxTable *table)
{
    GList *list;
    GncTaxTable *child;

    if (!table) return;

    qof_event_gen (&table->inst, QOF_EVENT_DESTROY, NULL);
    CACHE_REMOVE (table->name);
    remObj (table);

    /* destroy the list of entries */
    for (list = table->entries; list; list = list->next)
        gncTaxTableEntryDestroy (list->data);
    g_list_free (table->entries);

    if (!qof_instance_get_destroying(table))
        PERR("free a taxtable without do_free set!");

    /* disconnect from parent */
    if (table->parent)
        gncTaxTableRemoveChild(table->parent, table);

    /* disconnect from the children */
    for (list = table->children; list; list = list->next)
    {
        child = list->data;
        gncTaxTableSetParent(child, NULL);
    }
    g_list_free(table->children);

    /* qof_instance_release (&table->inst); */
    g_object_unref (table);
}
コード例 #7
0
ファイル: gncBillTerm.c プロジェクト: c-holtermann/gnucash
static void gncBillTermFree (GncBillTerm *term)
{
    GncBillTerm *child;
    GList *list;

    if (!term) return;

    qof_event_gen (&term->inst,  QOF_EVENT_DESTROY, NULL);
    CACHE_REMOVE (term->name);
    CACHE_REMOVE (term->desc);
    remObj (term);

    if (!qof_instance_get_destroying(term))
        PERR("free a billterm without do_free set!");

    /* disconnect from parent */
    if (term->parent)
        gncBillTermRemoveChild(term->parent, term);

    /* disconnect from the children */
    for (list = term->children; list; list = list->next)
    {
        child = list->data;
        gncBillTermSetParent(child, NULL);
    }
    g_list_free(term->children);

    /* qof_instance_release(&term->inst); */
    g_object_unref (term);
}
コード例 #8
0
ファイル: gncTaxTable.c プロジェクト: mlq/gnucash
static inline void
gncTaxTableAddChild (GncTaxTable *table, GncTaxTable *child)
{
    g_return_if_fail(table);
    g_return_if_fail(child);
    g_return_if_fail(qof_instance_get_destroying(table) == FALSE);

    table->children = g_list_prepend(table->children, child);
}
コード例 #9
0
/**
 * Commits a split to the database
 *
 * @param be SQL backend
 * @param inst Split
 * @return TRUE if successful, FALSE if error
 */
static gboolean
commit_split( GncSqlBackend* be, QofInstance* inst )
{
    gint op;
    gboolean is_infant;
    gboolean is_ok;
    GncGUID *guid = (GncGUID*)qof_instance_get_guid(inst);

    g_return_val_if_fail( inst != NULL, FALSE );
    g_return_val_if_fail( be != NULL, FALSE );

    is_infant = qof_instance_get_infant( inst );
    if ( qof_instance_get_destroying( inst ) )
    {
        op = OP_DB_DELETE;
    }
    else if ( be->is_pristine_db || is_infant )
    {
        op = OP_DB_INSERT;
    }
    else
    {
        op = OP_DB_UPDATE;
    }

    if (guid_equal (guid, guid_null ()))
    {
	*guid = guid_new_return ();
	qof_instance_set_guid (inst, guid);
    }

    is_ok = gnc_sql_do_db_operation( be, op, SPLIT_TABLE, GNC_ID_SPLIT,
				     inst, split_col_table );

    if ( is_ok && !qof_instance_get_destroying (inst))
    {
        is_ok = gnc_sql_slots_save( be,
                                    guid,
                                    is_infant,
                                    qof_instance_get_slots( inst ) );
    }

    return is_ok;
}
コード例 #10
0
ファイル: gncTaxTable.c プロジェクト: mlq/gnucash
static inline void
gncTaxTableRemoveChild (GncTaxTable *table, const GncTaxTable *child)
{
    g_return_if_fail(table);
    g_return_if_fail(child);

    if (qof_instance_get_destroying(table)) return;

    table->children = g_list_remove(table->children, child);
}
コード例 #11
0
/* ================================================================= */
bool
GncSqlSchedXactionBackend::commit (GncSqlBackend* sql_be, QofInstance* inst)
{
    SchedXaction* pSx;
    const GncGUID* guid;
    E_DB_OPERATION op;
    gboolean is_infant;
    gboolean is_ok;

    g_return_val_if_fail (sql_be != NULL, FALSE);
    g_return_val_if_fail (inst != NULL, FALSE);
    g_return_val_if_fail (GNC_IS_SX (inst), FALSE);

    pSx = GNC_SX (inst);

    is_infant = qof_instance_get_infant (inst);
    if (qof_instance_get_destroying (inst))
    {
        op = OP_DB_DELETE;
    }
    else if (sql_be->pristine() || is_infant)
    {
        op = OP_DB_INSERT;
    }
    else
    {
        op = OP_DB_UPDATE;
    }
    is_ok = sql_be->do_db_operation(op, SCHEDXACTION_TABLE, GNC_SX_ID, pSx,
                                    col_table);
    guid = qof_instance_get_guid (inst);
    if (op == OP_DB_INSERT || op == OP_DB_UPDATE)
    {
        gnc_sql_recurrence_save_list (sql_be, guid, gnc_sx_get_schedule (pSx));
    }
    else
    {
        gnc_sql_recurrence_delete (sql_be, guid);
    }

    if (is_ok)
    {
        // Now, commit any slots
        if (op == OP_DB_INSERT || op == OP_DB_UPDATE)
        {
            is_ok = gnc_sql_slots_save (sql_be, guid, is_infant, inst);
        }
        else
        {
            is_ok = gnc_sql_slots_delete (sql_be, guid);
        }
    }

    return is_ok;
}
コード例 #12
0
/* ================================================================= */
static gboolean
do_commit_commodity( GncSqlBackend* be, QofInstance* inst, gboolean force_insert )
{
    const GncGUID* guid;
    gboolean is_infant;
    gint op;
    gboolean is_ok;

    is_infant = qof_instance_get_infant( inst );
    if ( qof_instance_get_destroying( inst ) )
    {
        op = OP_DB_DELETE;
    }
    else if ( be->is_pristine_db || is_infant || force_insert )
    {
        op = OP_DB_INSERT;
    }
    else
    {
        op = OP_DB_UPDATE;
    }
    is_ok = gnc_sql_do_db_operation( be, op, COMMODITIES_TABLE, GNC_ID_COMMODITY, inst, col_table );

    if ( is_ok )
    {
        // Now, commit any slots
        guid = qof_instance_get_guid( inst );
        if ( !qof_instance_get_destroying(inst) )
        {
            is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) );
        }
        else
        {
            is_ok = gnc_sql_slots_delete( be, guid );
        }
    }

    return is_ok;
}
コード例 #13
0
ファイル: Scrub2.c プロジェクト: kleopatra999/gnucash-2
gboolean
xaccScrubMergeSubSplits (Split *split)
{
    gboolean rc = FALSE;
    Transaction *txn;
    SplitList *node;
    GNCLot *lot;
    const GncGUID *guid;

    if (FALSE == is_subsplit (split)) return FALSE;

    txn = split->parent;
    lot = xaccSplitGetLot (split);

    ENTER ("(Lot=%s)", gnc_lot_get_title(lot));
restart:
    for (node = txn->splits; node; node = node->next)
    {
        Split *s = node->data;
        if (xaccSplitGetLot (s) != lot) continue;
        if (s == split) continue;
        if (qof_instance_get_destroying(s)) continue;

        /* OK, this split is in the same lot (and thus same account)
         * as the indicated split.  Make sure it is really a subsplit
         * of the split we started with.  It's possible to have two
         * splits in the same lot and transaction that are not subsplits
         * of each other, the test-period test suite does this, for
         * example.  Only worry about adjacent sub-splits.  By
         * repeatedly merging adjacent subsplits, we'll get the non-
         * adjacent ones too. */
        guid = qof_instance_get_guid(s);
        if (gnc_kvp_bag_find_by_guid (split->inst.kvp_data, "lot-split",
                                      "peer_guid", guid) == NULL)
            continue;

        merge_splits (split, s);
        rc = TRUE;
        goto restart;
    }
    if (gnc_numeric_zero_p (split->amount))
    {
        PWARN ("Result of merge has zero amt!");
    }
    LEAVE (" splits merged=%d", rc);
    return rc;
}
コード例 #14
0
ファイル: gnc-price-sql.cpp プロジェクト: CAARNICL/gnucash
static gboolean
save_price (GncSqlBackend* be, QofInstance* inst)
{
    GNCPrice* pPrice = GNC_PRICE (inst);
    E_DB_OPERATION op;
    gboolean is_infant;
    gboolean is_ok = TRUE;

    g_return_val_if_fail (be != NULL, FALSE);
    g_return_val_if_fail (inst != NULL, FALSE);
    g_return_val_if_fail (GNC_IS_PRICE (inst), FALSE);

    is_infant = qof_instance_get_infant (inst);
    if (qof_instance_get_destroying (inst))
    {
        op = OP_DB_DELETE;
    }
    else if (be->is_pristine_db || is_infant)
    {
        op = OP_DB_INSERT;
    }
    else
    {
        op = OP_DB_UPDATE;
    }

    if (op != OP_DB_DELETE)
    {
        /* Ensure commodity and currency are in the db */
        (void)gnc_sql_save_commodity (be, gnc_price_get_commodity (pPrice));
        is_ok = gnc_sql_save_commodity (be, gnc_price_get_currency (pPrice));
    }

    if (is_ok)
    {
        is_ok = gnc_sql_do_db_operation (be, op, TABLE_NAME, GNC_ID_PRICE, pPrice,
                                         col_table);
    }

    return is_ok;
}
コード例 #15
0
ファイル: gnc-budget-sql.cpp プロジェクト: Bob-IT/gnucash
/* ================================================================= */
bool
GncSqlBudgetBackend::commit (GncSqlBackend* sql_be, QofInstance* inst)
{
    GncBudget* pBudget = GNC_BUDGET (inst);
    const GncGUID* guid;
    E_DB_OPERATION op;
    gboolean is_infant;
    gboolean is_ok;

    g_return_val_if_fail (sql_be != NULL, FALSE);
    g_return_val_if_fail (inst != NULL, FALSE);
    g_return_val_if_fail (GNC_IS_BUDGET (inst), FALSE);

    is_infant = qof_instance_get_infant (inst);
    if (qof_instance_get_destroying (inst))
    {
        op = OP_DB_DELETE;
    }
    else if (sql_be->pristine() || is_infant)
    {
        op = OP_DB_INSERT;
    }
    else
    {
        op = OP_DB_UPDATE;
    }
    is_ok = sql_be->do_db_operation(op, BUDGET_TABLE, GNC_ID_BUDGET, pBudget,
                                    col_table);

    // Now, commit any slots and recurrence
    if (is_ok)
    {
        guid = qof_instance_get_guid (inst);
        if (!qof_instance_get_destroying (inst))
        {
            is_ok = save_budget_amounts (sql_be, pBudget);
            if (is_ok)
            {
                is_ok = gnc_sql_recurrence_save (sql_be, guid,
                                                 gnc_budget_get_recurrence (pBudget));
            }
            if (is_ok)
            {
                is_ok = gnc_sql_slots_save (sql_be, guid, is_infant, inst);
            }
        }
        else
        {
            is_ok = delete_budget_amounts (sql_be, pBudget);
            if (is_ok)
            {
                is_ok = gnc_sql_recurrence_delete (sql_be, guid);
            }
            if (is_ok)
            {
                (void)gnc_sql_slots_delete (sql_be, guid);
            }
        }
    }

    return is_ok;
}
コード例 #16
0
static gboolean
save_transaction( GncSqlBackend* be, Transaction* pTx, gboolean do_save_splits )
{
    const GncGUID* guid;
    gint op;
    gboolean is_infant;
    QofInstance* inst;
    gboolean is_ok = TRUE;
    gchar* err = NULL;

    g_return_val_if_fail( be != NULL, FALSE );
    g_return_val_if_fail( pTx != NULL, FALSE );

    inst = QOF_INSTANCE(pTx);
    is_infant = qof_instance_get_infant( inst );
    if ( qof_instance_get_destroying( inst ) )
    {
        op = OP_DB_DELETE;
    }
    else if ( be->is_pristine_db || is_infant )
    {
        op = OP_DB_INSERT;
    }
    else
    {
        op = OP_DB_UPDATE;
    }

    if ( op != OP_DB_DELETE )
    {
        gnc_commodity *commodity = xaccTransGetCurrency( pTx );
        // Ensure the commodity is in the db
        is_ok = gnc_sql_save_commodity( be, commodity );
        if ( ! is_ok )
        {
            err = "Commodity save failed: Probably an invalid or missing currency";
            qof_backend_set_error( &be->be, ERR_BACKEND_DATA_CORRUPT);
        }
    }

    if ( is_ok )
    {
        is_ok = gnc_sql_do_db_operation( be, op, TRANSACTION_TABLE, GNC_ID_TRANS, pTx, tx_col_table );
        if ( ! is_ok )
        {
            err = "Transaction header save failed. Check trace log for SQL errors";
        }
    }

    if ( is_ok )
    {
        // Commit slots and splits
        guid = qof_instance_get_guid( inst );
        if ( !qof_instance_get_destroying(inst) )
        {
            is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) );
            if ( ! is_ok )
            {
                err = "Slots save failed. Check trace log for SQL errors";
            }
            if ( is_ok && do_save_splits )
            {
                is_ok = save_splits( be, guid, xaccTransGetSplitList( pTx ) );
                if ( ! is_ok )
                {
                    err = "Split save failed. Check trace log for SQL errors";
                }
            }
        }
        else
        {
            is_ok = gnc_sql_slots_delete( be, guid );
            if ( ! is_ok )
            {
                err = "Slots delete failed. Check trace log for SQL errors";
            }
            if ( is_ok )
            {
                is_ok = delete_splits( be, pTx );
                if ( ! is_ok )
                {
                    err = "Split delete failed. Check trace log for SQL errors";
                }
            }
        }
    }
    if (! is_ok )
    {
        G_GNUC_UNUSED gchar *message1 = "Transaction %s dated %s in account %s not saved due to %s.%s";
        G_GNUC_UNUSED gchar *message2 = "\nDatabase may be corrupted, check your data carefully.";
        Split* split = xaccTransGetSplit( pTx, 0);
        Account *acc = xaccSplitGetAccount( split );
        /* FIXME: This needs to be implemented
        qof_error_format_secondary_text( GTK_MESSAGE_DIALOG( msg ),
        					  message1,
        					 xaccTransGetDescription( pTx ),
        					  qof_print_date( xaccTransGetDate( pTx ) ),
        					  xaccAccountGetName( acc ),
        					  err,
        					  message2 );
        */
        PERR( "Transaction %s dated %s in account %s not saved due to %s.\n",
              xaccTransGetDescription( pTx ),
              qof_print_date( xaccTransGetDate( pTx ) ),
              xaccAccountGetName( acc ),
              err );
    }
    return is_ok;
}
コード例 #17
0
ファイル: gnc-account-sql.cpp プロジェクト: Bob-IT/gnucash
/* ================================================================= */
bool
GncSqlAccountBackend::commit (GncSqlBackend* sql_be, QofInstance* inst)
{
    Account* pAcc = GNC_ACCOUNT (inst);
    const GncGUID* guid;
    gboolean is_infant;
    gboolean is_ok = FALSE;
    gnc_commodity* commodity;
    E_DB_OPERATION op;

    g_return_val_if_fail (sql_be != NULL, FALSE);
    g_return_val_if_fail (inst != NULL, FALSE);
    g_return_val_if_fail (GNC_IS_ACCOUNT (inst), FALSE);

    ENTER ("inst=%p", inst);

    is_infant = qof_instance_get_infant (inst);

    // If there is no commodity yet, this might be because a new account name
    // has been entered directly into the register and an account window will
    // be opened.  The account info is not complete yet, but the name has been
    // set, triggering this commit
    commodity = xaccAccountGetCommodity (pAcc);

    is_ok = TRUE;
    if (qof_instance_get_destroying (inst))
    {
        op = OP_DB_DELETE;
    }
    else if (sql_be->pristine() || is_infant)
    {
        op = OP_DB_INSERT;
    }
    else
    {
        op = OP_DB_UPDATE;
    }

    // If not deleting the account, ensure the commodity is in the db
    if (op != OP_DB_DELETE && commodity != NULL)
    {
        is_ok = sql_be->save_commodity(commodity);
    }

    if (is_ok)
    {
        is_ok = sql_be->do_db_operation (op, TABLE_NAME, GNC_ID_ACCOUNT, pAcc,
                                         col_table);
    }

    if (is_ok)
    {
        // Now, commit or delete any slots
        guid = qof_instance_get_guid (inst);
        if (!qof_instance_get_destroying (inst))
        {
            is_ok = gnc_sql_slots_save (sql_be, guid, is_infant, inst);
        }
        else
        {
            is_ok = gnc_sql_slots_delete (sql_be, guid);
        }
    }

    LEAVE ("is_ok=%d", is_ok);

    return is_ok;
}
コード例 #18
0
/* Commit_edit handler - find the correct backend handler for this object
 * type and call its commit handler
 */
void
GncSqlBackend::commit_edit (QofInstance* inst)
{
    sql_backend be_data;
    gboolean is_dirty;
    gboolean is_destroying;
    gboolean is_infant;

    g_return_if_fail (inst != NULL);

    if (qof_book_is_readonly(m_book))
    {
        qof_backend_set_error (&qof_be, ERR_BACKEND_READONLY);
        (void)m_conn->rollback_transaction ();
        return;
    }
    /* During initial load where objects are being created, don't commit
    anything, but do mark the object as clean. */
    if (m_loading)
    {
        qof_instance_mark_clean (inst);
        return;
    }

    // The engine has a PriceDB object but it isn't in the database
    if (strcmp (inst->e_type, "PriceDB") == 0)
    {
        qof_instance_mark_clean (inst);
        qof_book_mark_session_saved (m_book);
        return;
    }

    ENTER (" ");

    is_dirty = qof_instance_get_dirty_flag (inst);
    is_destroying = qof_instance_get_destroying (inst);
    is_infant = qof_instance_get_infant (inst);

    DEBUG ("%s dirty = %d, do_free = %d, infant = %d\n",
           (inst->e_type ? inst->e_type : "(null)"),
           is_dirty, is_destroying, is_infant);

    if (!is_dirty && !is_destroying)
    {
        LEAVE ("!dirty OR !destroying");
        return;
    }

    if (!m_conn->begin_transaction ())
    {
        PERR ("begin_transaction failed\n");
        LEAVE ("Rolled back - database transaction begin error");
        return;
    }

    bool is_ok = true;

    auto obe = m_backend_registry.get_object_backend(std::string{inst->e_type});
    if (obe != nullptr)
        is_ok = obe->commit(this, inst);
    else
    {
        PERR ("Unknown object type '%s'\n", inst->e_type);
        (void)m_conn->rollback_transaction ();

        // Don't let unknown items still mark the book as being dirty
        qof_book_mark_session_saved(m_book);
        qof_instance_mark_clean (inst);
        LEAVE ("Rolled back - unknown object type");
        return;
    }
    if (!is_ok)
    {
        // Error - roll it back
        (void)m_conn->rollback_transaction();

        // This *should* leave things marked dirty
        LEAVE ("Rolled back - database error");
        return;
    }

    (void)m_conn->commit_transaction ();

    qof_book_mark_session_saved(m_book);
    qof_instance_mark_clean (inst);

    LEAVE ("");
}
コード例 #19
0
ファイル: gncOwner.c プロジェクト: ShawnMcGough/gnucash
void gncOwnerAutoApplyPaymentsWithLots (const GncOwner *owner, GList *lots)
{
    GList *left_iter;

    /* General note: in the code below the term "payment" can
     * both mean a true payment or a document of
     * the opposite sign (invoice vs credit note) relative to
     * the lot being processed. In general this function will
     * perform a balancing action on a set of lots, so you
     * will also find frequent references to balancing instead. */

    /* Payments can only be applied when at least an owner
     * and a list of lots to use are given */
    if (!owner) return;
    if (!lots) return;

    for (left_iter = lots; left_iter; left_iter = left_iter->next)
    {
        GNCLot *left_lot = left_iter->data;
        gnc_numeric left_lot_bal;
        gboolean left_lot_has_doc;
        gboolean left_modified = FALSE;
        Account *acct;
        GList *right_iter;

        /* Only attempt to apply payments to open lots.
         * Note that due to the iterative nature of this function lots
         * in the list may become empty/closed before they are evaluated as
         * base lot, so we should check this for each lot. */
        if (!left_lot || qof_instance_get_destroying (left_lot))
            continue;
        if (gnc_lot_count_splits (left_lot) == 0)
        {
            gnc_lot_destroy (left_lot);
            continue;
        }
        if (gnc_lot_is_closed (left_lot))
            continue;

        acct = gnc_lot_get_account (left_lot);
        xaccAccountBeginEdit (acct);

        left_lot_bal = gnc_lot_get_balance (left_lot);
        left_lot_has_doc = (gncInvoiceGetInvoiceFromLot (left_lot) != NULL);

        /* Attempt to offset left_lot with any of the remaining lots. To do so
         * iterate over the remaining lots adding lot links or moving payments
         * around.
         */
        for (right_iter = left_iter->next; right_iter; right_iter = right_iter->next)
        {
            GNCLot *right_lot = right_iter->data;
            gnc_numeric right_lot_bal;
            gboolean right_lot_has_doc;

            /* Only attempt to use open lots to balance the base lot.
             * Note that due to the iterative nature of this function lots
             * in the list may become empty/closed before they are evaluated as
             * base lot, so we should check this for each lot. */
            if (!right_lot || qof_instance_get_destroying (right_lot))
                continue;
            if (gnc_lot_count_splits (right_lot) == 0)
            {
                gnc_lot_destroy (right_lot);
                continue;
            }
            if (gnc_lot_is_closed (right_lot))
                continue;

            /* Balancing transactions for invoice/payments can only happen
             * in the same account. */
            if (acct != gnc_lot_get_account (right_lot))
                continue;


            /* Only attempt to balance if the base lot and balancing lot are
             * of the opposite sign. (Otherwise we would increase the balance
             * of the lot - Duh */
            right_lot_bal = gnc_lot_get_balance (right_lot);
            if (gnc_numeric_positive_p (left_lot_bal) == gnc_numeric_positive_p (right_lot_bal))
                continue;

            /* Ok we found two lots than can (partly) offset each other.
             * Depending on the lot types, a different action is needed to accomplish this.
             * 1. Both lots are document lots (invoices/credit notes)
             *    -> Create a lot linking transaction between the lots
             * 2. Both lots are payment lots (lots without a document attached)
             *    -> Use part of the bigger lot to the close the smaller lot
             * 3. One document lot with one payment lot
             *    -> Use (part of) the payment to offset (part of) the document lot,
             *       Which one will be closed depends on which is the bigger one
             */
            right_lot_has_doc = (gncInvoiceGetInvoiceFromLot (right_lot) != NULL);
            if (left_lot_has_doc && right_lot_has_doc)
                gncOwnerCreateLotLink (left_lot, right_lot, owner);
            else if (!left_lot_has_doc && !right_lot_has_doc)
            {
                gint cmp = gnc_numeric_compare (gnc_numeric_abs (left_lot_bal),
                                                gnc_numeric_abs (right_lot_bal));
                if (cmp >= 0)
                    gncOwnerOffsetLots (left_lot, right_lot, owner);
                else
                    gncOwnerOffsetLots (right_lot, left_lot, owner);
            }
            else
            {
                GNCLot *doc_lot = left_lot_has_doc ? left_lot : right_lot;
                GNCLot *pay_lot = left_lot_has_doc ? right_lot : left_lot;
                // Ok, let's try to move a payment from pay_lot to doc_lot
                gncOwnerOffsetLots (pay_lot, doc_lot, owner);
            }

            /* If we get here, then right_lot was modified
             * If the lot has a document, send an event for send an event for it as well
             * so it gets potentially updated as paid */

            {
                GncInvoice *this_invoice = gncInvoiceGetInvoiceFromLot(right_lot);
                if (this_invoice)
                    qof_event_gen (QOF_INSTANCE(this_invoice), QOF_EVENT_MODIFY, NULL);
            }
            left_modified = TRUE;
        }

        /* If left_lot was modified and the lot has a document,
         * send an event for send an event for it as well
         * so it gets potentially updated as paid */
        if (left_modified)
        {
            GncInvoice *this_invoice = gncInvoiceGetInvoiceFromLot(left_lot);
            if (this_invoice)
                qof_event_gen (QOF_INSTANCE(this_invoice), QOF_EVENT_MODIFY, NULL);
        }
        xaccAccountCommitEdit (acct);

    }
}
コード例 #20
0
ファイル: gncBillTerm.c プロジェクト: c-holtermann/gnucash
static inline void
gncBillTermRemoveChild (GncBillTerm *table, GncBillTerm *child)
{
    if (qof_instance_get_destroying(table)) return;
    table->children = g_list_remove(table->children, child);
}