* gncBillTerm: add functions to compute DueDate and DiscountDate from

a Timespec (post_date) and the Billing Term definition.

* dialog-date-close: use billing terms; if a term object is supplied,
  display the due date but do not allow the user to modify it directly.
  Use callbacks from the date-edit widget to update the due date.

* dialog-invoice: don't worry about pre-computing a due date; pass the
  billing terms into the date-close dialog.

* date: add a few convenience functions to convert from Timespec to
  day/month/year; compute the last mday from a Timespec; compute the
  last mday from a month/year.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@6997 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Derek Atkins
2002-06-22 21:55:00 +00:00
parent 23a70b22d2
commit a9df3df3f9
7 changed files with 163 additions and 22 deletions

View File

@@ -371,6 +371,84 @@ gboolean gncBillTermIsDirty (GncBillTerm *term)
return term->dirty;
}
/********************************************************/
/* functions to compute dates from Bill Terms */
#define SECS_PER_DAY 86400
/* Based on the timespec and a proximo type, compute the month and
* year this is due. The actual day is filled in below.
*/
static void
compute_monthyear (GncBillTerm *term, Timespec post_date,
int *month, int *year)
{
int iday, imonth, iyear;
int cutoff = term->cutoff;
g_return_if_fail (term->type == GNC_TERM_TYPE_PROXIMO);
gnc_timespec2dmy (post_date, &iday, &imonth, &iyear);
if (cutoff <= 0)
cutoff += gnc_timespec_last_mday (post_date);
if (iday <= cutoff) {
/* We apply this to next month */
imonth++;
} else {
/* We apply to the following month */
imonth += 2;
}
if (imonth > 12) {
iyear++;
imonth -= 12;
}
if (month) *month = imonth;
if (year) *year = iyear;
}
static Timespec
compute_time (GncBillTerm *term, Timespec post_date, int days)
{
Timespec res = post_date;
int day, month, year;
switch (term->type) {
case GNC_TERM_TYPE_DAYS:
res.tv_sec += (SECS_PER_DAY * days);
break;
case GNC_TERM_TYPE_PROXIMO:
compute_monthyear (term, post_date, &month, &year);
day = gnc_date_my_last_mday (month, year);
if (days < day)
day = days;
res = gnc_dmy2timespec (day, month, year);
break;
}
return res;
}
Timespec
gncBillTermComputeDueDate (GncBillTerm *term, Timespec post_date)
{
Timespec res = post_date;
if (!term) return res;
return compute_time (term, post_date, term->due_days);
}
Timespec
gncBillTermComputeDiscountDate (GncBillTerm *term, Timespec post_date)
{
Timespec res = post_date;
if (!term) return res;
return compute_time (term, post_date, term->disc_days);
}
/* Package-Private functions */
static void add_or_rem_object (GncBillTerm *term, gboolean add)

View File

@@ -11,6 +11,7 @@ typedef struct _gncBillTerm GncBillTerm;
#include "gnc-numeric.h"
#include "gnc-book.h"
#include "date.h"
#define GNC_BILLTERM_MODULE_NAME "gncBillTerm"
@@ -66,4 +67,11 @@ gint64 gncBillTermGetRefcount (GncBillTerm *term);
int gncBillTermCompare (GncBillTerm *a, GncBillTerm *b);
/********************************************************/
/* functions to compute dates from Bill Terms */
/* Compute the due date and discount dates from the post date */
Timespec gncBillTermComputeDueDate (GncBillTerm *term, Timespec post_date);
Timespec gncBillTermComputeDiscountDate (GncBillTerm *term, Timespec post_date);
#endif /* GNC_BILLTERM_H_ */

View File

@@ -25,6 +25,7 @@ typedef struct _dialog_date_close_window {
GtkWidget *post_date;
GtkWidget *acct_combo;
GtkWidget *memo_entry;
GncBillTerm *terms;
Timespec *ts, *ts2;
GList * acct_types;
GNCBook *book;
@@ -231,6 +232,18 @@ gnc_dialog_date_close_parented (GtkWidget *parent, const char *message,
return retval;
}
static void
post_date_changed_cb (GNCDateEdit *gde, gpointer d)
{
DialogDateClose *ddc = d;
Timespec post_date;
Timespec due_date;
post_date = gnc_date_edit_get_date_ts (gde);
due_date = gncBillTermComputeDueDate (ddc->terms, post_date);
gnc_date_edit_set_time_ts (GNC_DATE_EDIT (ddc->date), due_date);
}
gboolean
gnc_dialog_dates_acct_parented (GtkWidget *parent, const char *message,
const char *ddue_label_message,
@@ -238,6 +251,7 @@ gnc_dialog_dates_acct_parented (GtkWidget *parent, const char *message,
const char *acct_label_message,
gboolean ok_is_default,
GList * acct_types, GNCBook *book,
GncBillTerm *terms,
/* Returned Data... */
Timespec *ddue, Timespec *post,
char **memo, Account **acct)
@@ -259,6 +273,7 @@ gnc_dialog_dates_acct_parented (GtkWidget *parent, const char *message,
ddc->book = book;
ddc->acct_types = acct_types;
ddc->memo = memo;
ddc->terms = terms;
xml = gnc_glade_xml_new ("date-close.glade", "Date Account Dialog");
ddc->dialog = glade_xml_get_widget (xml, "Date Account Dialog");
@@ -287,10 +302,18 @@ gnc_dialog_dates_acct_parented (GtkWidget *parent, const char *message,
label = glade_xml_get_widget (xml, "acct_label");
gtk_label_set_text (GTK_LABEL (label), acct_label_message);
/* Set the date widget */
gnc_date_edit_set_time_ts (GNC_DATE_EDIT (ddc->date), *ddue);
/* Set the post date widget */
gnc_date_edit_set_time_ts (GNC_DATE_EDIT (ddc->post_date), *post);
/* Deal with the terms handling of the due date */
if (terms) {
gtk_signal_connect (GTK_OBJECT (ddc->post_date), "date_changed",
post_date_changed_cb, ddc);
gtk_widget_set_sensitive (ddc->date, FALSE);
post_date_changed_cb (ddc->post_date, ddc);
} else
gnc_date_edit_set_time_ts (GNC_DATE_EDIT (ddc->date), *ddue);
/* Setup the account widget */
fill_in_acct_info (ddc);

View File

@@ -10,6 +10,7 @@
#include "date.h"
#include "Account.h"
#include "gnc-book.h"
#include "gncBillTerm.h"
gboolean
gnc_dialog_date_close_parented (GtkWidget *parent, const char *message,
@@ -32,6 +33,7 @@ gnc_dialog_dates_acct_parented (GtkWidget *parent, const char *message,
const char *acct_label_message,
gboolean ok_is_default,
GList * acct_types, GNCBook *book,
GncBillTerm *terms,
/* Returned Data... */
Timespec *ddue, Timespec *post,
char **memo, Account **acct);

View File

@@ -307,12 +307,12 @@ gnc_invoice_window_post_invoice_cb (GtkWidget *widget, gpointer data)
/* Get the due date and posted account */
timespecFromTime_t (&postdate, time(NULL));
ddue = postdate;
ddue.tv_sec += 3600*24*30; /* XXX: due in 30 days */
memo = NULL;
if (!gnc_dialog_dates_acct_parented (iw->dialog, message, ddue_label,
post_label, acct_label, TRUE, acct_types,
iw->book, &ddue, &postdate, &memo, &acc))
post_label, acct_label, TRUE,
acct_types, iw->book, iw->terms,
&ddue, &postdate, &memo, &acc))
return;
/* Yep, we're posting. So, save the invoice...
@@ -1078,7 +1078,6 @@ gnc_invoice_update_window (InvoiceWindow *iw)
/*
gtk_widget_set_sensitive (iw->id_entry, FALSE);
gtk_widget_set_sensitive (iw->terms_menu, FALSE);
gtk_widget_set_sensitive (iw->opened_date, FALSE);
gtk_widget_set_sensitive (iw->notes_text, FALSE); *//* XXX: should notes remain writable? */
}
@@ -1163,6 +1162,10 @@ gnc_invoice_new_window (GNCBook *bookp, InvoiceDialogType type,
gtk_box_pack_start (GTK_BOX(iw->posted_date_hbox), iw->posted_date,
TRUE, TRUE, 0);
/* Make the opened and posted dates insensitive in this window */
gtk_widget_set_sensitive (iw->opened_date, FALSE);
gtk_widget_set_sensitive (iw->posted_date, FALSE);
/* Build the ledger */
switch (type) {
case EDIT_INVOICE:

View File

@@ -170,6 +170,24 @@ timespecCanonicalDayTime(Timespec t)
return retval;
}
int gnc_date_my_last_mday (int month, int year)
{
gboolean is_leap;
static int days_in_month[2][12] =
{/* non leap */ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
/* leap */ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
/* Is this a leap year? */
if (year / 2000 == 0)
is_leap = TRUE;
else if (year / 400 == 0)
is_leap = FALSE;
else
is_leap = (year / 4 == 0);
return days_in_month[is_leap][month-1];
}
/**
* date_get_last_mday
* Retrieve the last nomerical day for the month specified in the
@@ -179,22 +197,7 @@ timespecCanonicalDayTime(Timespec t)
**/
int date_get_last_mday(struct tm *tm)
{
int year;
gboolean is_leap;
static int days_in_month[2][12] =
{/* non leap */ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
/* leap */ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
/* Is this a leap year? */
year = tm->tm_year + 1900;
if (year / 2000 == 0)
is_leap = TRUE;
else if (year / 400 == 0)
is_leap = FALSE;
else
is_leap = (year / 4 == 0);
return days_in_month[is_leap][tm->tm_mon];
return gnc_date_my_last_mday (tm->tm_mon+1, tm->tm_year+1900);
}
/**
@@ -741,6 +744,26 @@ gnc_timespec_to_iso8601_buff (Timespec ts, char * buff)
return buff;
}
int
gnc_timespec_last_mday (Timespec t)
{
struct tm *result;
time_t t_secs = t.tv_sec + (t.tv_nsec / NANOS_PER_SECOND);
result = localtime(&t_secs);
return date_get_last_mday (result);
}
void
gnc_timespec2dmy (Timespec t, int *day, int *month, int *year)
{
struct tm *result;
time_t t_secs = t.tv_sec + (t.tv_nsec / NANOS_PER_SECOND);
result = localtime(&t_secs);
if (day) *day = result->tm_mday;
if (month) *month = result->tm_mon+1;
if (year) *year = result->tm_year+1900;
}
/********************************************************************\
\********************************************************************/

View File

@@ -174,6 +174,10 @@ void scanDate (const char *buff, int *day, int *month, int *year);
*/
char dateSeparator(void);
int gnc_date_my_last_mday (int month, int year);
int gnc_timespec_last_mday (Timespec ts);
void gnc_timespec2dmy (Timespec ts, int *day, int *month, int *year);
/*
* hack alert XXX FIXME -- these date routines return incorrect
* values for dates before 1970. Most of them are good only up