static GncSxInstances*
_gnc_sx_gen_instances(gpointer *data, gpointer user_data)
{
    GncSxInstances *instances = g_new0(GncSxInstances, 1);
    SchedXaction *sx = (SchedXaction*)data;
    GDate *range_end = (GDate*)user_data;
    GDate creation_end, remind_end;
    GDate cur_date;
    void *sequence_ctx;

    instances->sx = sx;

    creation_end = *range_end;
    g_date_add_days(&creation_end, xaccSchedXactionGetAdvanceCreation(sx));
    remind_end = creation_end;
    g_date_add_days(&remind_end, xaccSchedXactionGetAdvanceReminder(sx));

    /* postponed */
    {
        GList *postponed = gnc_sx_get_defer_instances(sx);
        for ( ; postponed != NULL; postponed = postponed->next)
        {
            GDate inst_date;
            int seq_num;
            GncSxInstance *inst;

            g_date_clear(&inst_date, 1);
            inst_date = xaccSchedXactionGetNextInstance(sx, postponed->data);
            seq_num = gnc_sx_get_instance_count(sx, postponed->data);
            inst = gnc_sx_instance_new(instances, SX_INSTANCE_STATE_POSTPONED, &inst_date, postponed->data, seq_num);
            instances->instance_list = g_list_append(instances->instance_list, inst);
        }
    }

    /* to-create */
    g_date_clear(&cur_date, 1);
    sequence_ctx = gnc_sx_create_temporal_state(sx);
    cur_date = xaccSchedXactionGetInstanceAfter(sx, &cur_date, sequence_ctx);
    instances->next_instance_date = cur_date;
    while (g_date_valid(&cur_date) && g_date_compare(&cur_date, &creation_end) <= 0)
    {
        GncSxInstance *inst;
        int seq_num;
        seq_num = gnc_sx_get_instance_count(sx, sequence_ctx);
        inst = gnc_sx_instance_new(instances, SX_INSTANCE_STATE_TO_CREATE, &cur_date, sequence_ctx, seq_num);
        instances->instance_list = g_list_append(instances->instance_list, inst);
        gnc_sx_incr_temporal_state(sx, sequence_ctx);
        cur_date = xaccSchedXactionGetInstanceAfter(sx, &cur_date, sequence_ctx);
    }

    /* reminders */
    while (g_date_valid(&cur_date) && g_date_compare(&cur_date, &remind_end) <= 0)
    {
        GncSxInstance *inst;
        int seq_num;
        seq_num = gnc_sx_get_instance_count(sx, sequence_ctx);
        inst = gnc_sx_instance_new(instances, SX_INSTANCE_STATE_REMINDER, &cur_date, sequence_ctx, seq_num);
        instances->instance_list = g_list_append(instances->instance_list, inst);
        gnc_sx_incr_temporal_state(sx, sequence_ctx);
        cur_date = xaccSchedXactionGetInstanceAfter(sx, &cur_date, sequence_ctx);
    }

    return instances;
}
Exemple #2
0
gint gnc_sx_get_num_occur_daterange(const SchedXaction *sx, const GDate* start_date, const GDate* end_date)
{
    gint result = 0;
    SXTmpStateData *tmpState;
    gboolean countFirstDate;

    /* SX still active? If not, return now. */
    if ((xaccSchedXactionHasOccurDef(sx)
            && xaccSchedXactionGetRemOccur(sx) <= 0)
            || (xaccSchedXactionHasEndDate(sx)
                && g_date_compare(xaccSchedXactionGetEndDate(sx), start_date) < 0))
    {
        return result;
    }

    tmpState = gnc_sx_create_temporal_state (sx);

    /* Should we count the first valid date we encounter? Only if the
     * SX has not yet occurred so far, or if its last valid date was
     * before the start date. */
    countFirstDate = !g_date_valid(&tmpState->last_date)
                     || (g_date_compare(&tmpState->last_date, start_date) < 0);

    /* No valid date? SX has never occurred so far. */
    if (!g_date_valid(&tmpState->last_date))
    {
        /* SX has never occurred so far */
        gnc_sx_incr_temporal_state (sx, tmpState);
        if (xaccSchedXactionHasOccurDef(sx) && tmpState->num_occur_rem < 0)
        {
            gnc_sx_destroy_temporal_state (tmpState);
            return result;
        }
    }

    /* Increase the tmpState until we are in our interval of
     * interest. Only calculate anything if the sx hasn't already
     * ended. */
    while (g_date_compare(&tmpState->last_date, start_date) < 0)
    {
        gnc_sx_incr_temporal_state (sx, tmpState);
        if (xaccSchedXactionHasOccurDef(sx) && tmpState->num_occur_rem < 0)
        {
            gnc_sx_destroy_temporal_state (tmpState);
            return result;
        }
    }

    /* Now we are in our interval of interest. Increment the
     * occurrence date until we are beyond the end of our
     * interval. Make sure to check for invalid dates here: It means
     * the SX has ended. */
    while (g_date_valid(&tmpState->last_date)
            && (g_date_compare(&tmpState->last_date, end_date) <= 0)
            && (!xaccSchedXactionHasEndDate(sx)
                || g_date_compare(&tmpState->last_date, xaccSchedXactionGetEndDate(sx)) <= 0)
            && (!xaccSchedXactionHasOccurDef(sx)
                /* The >=0 (i.e. the ==) is important here, otherwise
                 * we miss the last valid occurrence of a SX which is
                 * limited by num_occur */
                || tmpState->num_occur_rem >= 0))
    {
        ++result;
        gnc_sx_incr_temporal_state (sx, tmpState);
    }

    /* If the first valid date shouldn't be counted, decrease the
     * result number by one. */
    if (!countFirstDate && result > 0)
        --result;

    gnc_sx_destroy_temporal_state (tmpState);
    return result;
}