The RecurrenceWidget gives the user a unified interface for telling the system how often certain events occur. More...
#include <recurrencewidget.h>
Public Types | |
enum | RecurrenceChangePolicy { NoPolicy = -1, IgnoreFuture, ChangeFuture } |
enum | RecurrencePeriod { Never = -1, Minutely, Hourly, Daily, Weekly, Monthly, Yearly, Custom } |
Properties | |
bool | endDateVisible |
Return whether the end date field is visible. | |
bool | endTimeVisible |
Return whether the end time field is visible. | |
bool | maxVisible |
RecurrencePeriod | minPeriod |
bool | startDateVisible |
bool | startTimeVisible |
Public Member Functions | |
RecurrenceWidget (QWidget *parent=0, const char *name=0) | |
~RecurrenceWidget () | |
virtual Q_INVOKABLE QDate | endDate () const |
Return the date the recurrence is set to end. | |
virtual Q_INVOKABLE QDateTime | endDateTime () const |
Return the date and time the recurrence is set to end. | |
virtual Q_INVOKABLE bool | endDateVisible () const |
virtual Q_INVOKABLE QTime | endTime () const |
Return the time of day the recurrence is set to end. | |
virtual Q_INVOKABLE bool | endTimeVisible () const |
virtual Q_INVOKABLE int | frequency () const |
Return the frequency (number of periods) the recurrence is set to run. | |
virtual Q_INVOKABLE RecurrenceChangePolicy | getChangePolicy () |
virtual Q_INVOKABLE bool | isRecurring () const |
virtual Q_INVOKABLE int | max () const |
virtual bool | maxVisible () const |
virtual Q_INVOKABLE RecurrencePeriod | minPeriod () const |
virtual Q_INVOKABLE bool | modified () const |
virtual Q_INVOKABLE int | parentId () const |
virtual Q_INVOKABLE QString | parentType () const |
virtual Q_INVOKABLE RecurrencePeriod | period () const |
virtual Q_INVOKABLE QString | periodCode () const |
virtual Q_INVOKABLE QDate | startDate () const |
virtual Q_INVOKABLE QDateTime | startDateTime () const |
virtual bool | startDateVisible () const |
virtual Q_INVOKABLE QTime | startTime () const |
virtual Q_INVOKABLE bool | startTimeVisible () const |
virtual Q_INVOKABLE RecurrencePeriod | stringToPeriod (QString p) const |
Convert a string representation of the period to a RecurrencePeriod. | |
Public Slots | |
virtual void | clear () |
Set the RecurrenceWidget to its default state. | |
virtual bool | save (bool intxn, RecurrenceChangePolicy cp, QString *msg=0) |
virtual void | set (bool recurring=false, int frequency=1, QString period=QString("W"), QDate startDate=QDate::currentDate(), QDate endDate=QDate(), int max=1) |
virtual void | set (bool recurring, int frequency, QString period, QDateTime startDateTime, QDateTime endDateTime, int max) |
virtual void | setEndDate (QDate p) |
virtual void | setEndDateTime (QDateTime p) |
virtual void | setEndDateVisible (bool p) |
virtual void | setEndTime (QTime p) |
virtual void | setEndTimeVisible (bool p) |
virtual void | setFrequency (int p) |
virtual void | setMax (int p) |
virtual void | setMaxVisible (bool p) |
virtual void | setMinPeriod (RecurrencePeriod minPeriod) |
virtual bool | setParent (int pid, QString ptype) |
virtual void | setPeriod (RecurrencePeriod p) |
virtual void | setPeriod (QString p) |
virtual void | setRecurring (bool p) |
virtual void | setStartDate (QDate p) |
virtual void | setStartDateTime (QDateTime p) |
virtual void | setStartDateVisible (bool p) |
virtual void | setStartTime (QTime p) |
virtual void | setStartTimeVisible (bool p) |
Protected Attributes | |
QDateTime | _eot |
int | _id |
int | _parentId |
QString | _parentType |
QDateTime | _prevEndDateTime |
int | _prevFrequency |
int | _prevMax |
int | _prevParentId |
QString | _prevParentType |
RecurrencePeriod | _prevPeriod |
bool | _prevRecurring |
QDateTime | _prevStartDateTime |
Protected Slots | |
virtual void | languageChange () |
The RecurrenceWidget gives the user a unified interface for telling the system how often certain events occur.
In general recurrences are stored in the recur table, but this is not required. Two basic values describe a recurrence:
A recurrence with the period set to W (= week) and frequency of 3 will repeat once every three weeks.
To add a new kind of recurring event or item, you need to change data in the database, stored procedures, triggers, and application code. We'll use Invoice in the examples here, with 'I' as the internal code value, even though invoices already use this mechanism (xTuple ERP 3.5.1 and later).
Add a column to the parent table to track the recurrence parent/child relationship. The column name must follow this pattern: [tablename]_recurring_[tablename]_id , e.g.
invchead_recurring_invchead_id
:
ALTER TABLE invchead ADD COLUMN invchead_recurring_invchead_id INTEGER;
COMMENT ON COLUMN invchead.invchead_recurring_invchead_id IS 'The first invchead record in the series if this is a recurring Invoice. If the invchead_recurring_invchead_id is the same as the invchead_id, this record is the first in the series.';
Add a RecurrenceWidget to the .ui for the window that will maintain data of this type (e.g. invoice.ui).
Initialize the widget in the window's constructor:
_recur->setParent(-1, 'I');
Update the widget again when the window gets an id for the object. This usually happens in either the set(), save(), or sSave() method for new objects, depending on the class, and in populate() when editing existing objects:
// cNew case in invoice::set() _recur->setParent(_invcheadid, 'I'); ... // invoice::populate() _recur->setParent(q.value("invchead_recurring_invchead_id").toInt(), "I");
Ask the user how to handle existing recurrences before saving the data and before starting a transaction. getChangePolicy will return RecurrenceWidget::NoPolicy) if the user chooses to cancel. Then when preparing to insert or update the main record, make sure to set the recurrence parentage. Finally, after the insert/update, save the recurrence and check for errors:
bool %save() { // error checking RecurrenceWidget::ChangePolicy cp = _recur->getChangePolicy(); if (cp == RecurrenceWidget::NoPolicy) return false; XSqlQuery beginq("BEGIN;"); XSqlQuery qry; ... // set up qry to insert or update if (_recur->isRecurring()) qry.bindValue(":invchead_recurring_invchead_id", _recur->parentId()); ... // execute the insert/update ... QString errmsg; if (! _recur->save(true, cp, &errmsg)) { rollbackq.exec(); systemError(this, errmsg, __FILE__, __LINE__); return false; } ... // finish processing XSqlQuery commitq("COMMIT;"); return true; }
To maintain the recurrence relationships, there must be a function that copies an existing record based on its id and gives the copy a different timestamp or date. It must have a function signature like one of these:
The copy function can take additional arguments as well, but they will be ignored by the recurrence maintenance functions. The data type of each argument must be listed in the recurtype table's recurtype_copyargs column (see below) so the appropriate casting can be done for the date or timestamp and an appropriate number of NULL arguments can be passed. The copy function must copy the [tablename]_recurring_[tablename]_id column.
There can be a function to delete records of this type as well. If there is one, it must accept a single integer id of the record to delete.
Add a row to the recurtype table to describe how the recurrence stored procedures interact with the events/items of this type ('I' == Invoice).
INSERT INTO recurtype (recurtype_type, recurtype_table, recurtype_donecheck, recurtype_schedcol, recurtype_limit, recurtype_copyfunc, recurtype_copyargs, recurtype_delfunc ) VALUES ('I', 'invchead', 'invchead_posted', 'invchead_invcdate', NULL, 'copyinvoice', '{integer,date}', 'deleteinvoice');
If there isn't a delete function, set the recurtype_delfunc to NULL. Existing records will be deleted when necessary with an SQL DELETE statement.
The DELETE trigger on the table should clean up the recurrence information:
CREATE OR REPLACE FUNCTION _invcheadBeforeTrigger() RETURNS "trigger" AS $$ DECLARE _recurid INTEGER; _newparentid INTEGER; BEGIN IF (TG_OP = 'DELETE') THEN -- after other stuff not having to do with recurrence SELECT recur_id INTO _recurid FROM recur WHERE ((recur_parent_id=OLD.invchead_id) AND (recur_parent_type='I')); IF (_recurid IS NOT NULL) THEN SELECT invchead_id INTO _newparentid FROM invchead WHERE ((invchead_recurring_invchead_id=OLD.invchead_id) AND (invchead_id!=OLD.invchead_id)) ORDER BY invchead_invcdate LIMIT 1; IF (_newparentid IS NULL) THEN DELETE FROM recur WHERE recur_id=_recurid; ELSE UPDATE recur SET recur_parent_id=_newparentid WHERE recur_id=_recurid; UPDATE invchead SET invchead_recurring_invchead_id=_newparentid WHERE invchead_recurring_invchead_id=OLD.invchead_id AND invchead_id!=OLD.invchead_id; END IF; END IF; RETURN OLD; END IF; RETURN NEW; END; $$ LANGUAGE 'plpgsql';
RecurrenceWidget::RecurrenceWidget | ( | QWidget * | parent = 0 , |
const char * | name = 0 |
||
) |
void RecurrenceWidget::clear | ( | ) | [virtual, slot] |
Set the RecurrenceWidget to its default state.
QDate RecurrenceWidget::endDate | ( | ) | const [virtual] |
Return the date the recurrence is set to end.
QDateTime RecurrenceWidget::endDateTime | ( | ) | const [virtual] |
Return the date and time the recurrence is set to end.
virtual Q_INVOKABLE bool RecurrenceWidget::endDateVisible | ( | ) | const [virtual] |
QTime RecurrenceWidget::endTime | ( | ) | const [virtual] |
Return the time of day the recurrence is set to end.
virtual Q_INVOKABLE bool RecurrenceWidget::endTimeVisible | ( | ) | const [virtual] |
int RecurrenceWidget::frequency | ( | ) | const [virtual] |
Return the frequency (number of periods) the recurrence is set to run.
bool RecurrenceWidget::isRecurring | ( | ) | const [virtual] |
void RecurrenceWidget::languageChange | ( | ) | [protected, virtual, slot] |
Reimplemented from QWidget.
int RecurrenceWidget::max | ( | ) | const [virtual] |
virtual bool RecurrenceWidget::maxVisible | ( | ) | const [virtual] |
virtual Q_INVOKABLE RecurrencePeriod RecurrenceWidget::minPeriod | ( | ) | const [virtual] |
bool RecurrenceWidget::modified | ( | ) | const [virtual] |
int RecurrenceWidget::parentId | ( | ) | const [virtual] |
QString RecurrenceWidget::parentType | ( | ) | const [virtual] |
RecurrenceWidget::RecurrencePeriod RecurrenceWidget::period | ( | ) | const [virtual] |
QString RecurrenceWidget::periodCode | ( | ) | const [virtual] |
bool RecurrenceWidget::save | ( | bool | intxn, |
RecurrenceChangePolicy | cp, | ||
QString * | msg = 0 |
||
) | [virtual, slot] |
void RecurrenceWidget::set | ( | bool | recurring = false , |
int | frequency = 1 , |
||
QString | period = QString("W") , |
||
QDate | startDate = QDate::currentDate() , |
||
QDate | endDate = QDate() , |
||
int | max = 1 |
||
) | [virtual, slot] |
void RecurrenceWidget::set | ( | bool | recurring, |
int | frequency, | ||
QString | period, | ||
QDateTime | startDateTime, | ||
QDateTime | endDateTime, | ||
int | max | ||
) | [virtual, slot] |
void RecurrenceWidget::setEndDate | ( | QDate | p | ) | [virtual, slot] |
void RecurrenceWidget::setEndDateTime | ( | QDateTime | p | ) | [virtual, slot] |
void RecurrenceWidget::setEndDateVisible | ( | bool | p | ) | [virtual, slot] |
void RecurrenceWidget::setEndTime | ( | QTime | p | ) | [virtual, slot] |
void RecurrenceWidget::setEndTimeVisible | ( | bool | p | ) | [virtual, slot] |
void RecurrenceWidget::setFrequency | ( | int | p | ) | [virtual, slot] |
void RecurrenceWidget::setMax | ( | int | p | ) | [virtual, slot] |
void RecurrenceWidget::setMaxVisible | ( | bool | p | ) | [virtual, slot] |
void RecurrenceWidget::setMinPeriod | ( | RecurrencePeriod | minPeriod | ) | [virtual, slot] |
bool RecurrenceWidget::setParent | ( | int | pid, |
QString | ptype | ||
) | [virtual, slot] |
void RecurrenceWidget::setPeriod | ( | RecurrencePeriod | p | ) | [virtual, slot] |
void RecurrenceWidget::setPeriod | ( | QString | p | ) | [virtual, slot] |
void RecurrenceWidget::setRecurring | ( | bool | p | ) | [virtual, slot] |
void RecurrenceWidget::setStartDate | ( | QDate | p | ) | [virtual, slot] |
void RecurrenceWidget::setStartDateTime | ( | QDateTime | p | ) | [virtual, slot] |
void RecurrenceWidget::setStartDateVisible | ( | bool | p | ) | [virtual, slot] |
void RecurrenceWidget::setStartTime | ( | QTime | p | ) | [virtual, slot] |
void RecurrenceWidget::setStartTimeVisible | ( | bool | p | ) | [virtual, slot] |
QDate RecurrenceWidget::startDate | ( | ) | const [virtual] |
QDateTime RecurrenceWidget::startDateTime | ( | ) | const [virtual] |
virtual bool RecurrenceWidget::startDateVisible | ( | ) | const [virtual] |
QTime RecurrenceWidget::startTime | ( | ) | const [virtual] |
virtual Q_INVOKABLE bool RecurrenceWidget::startTimeVisible | ( | ) | const [virtual] |
RecurrenceWidget::RecurrencePeriod RecurrenceWidget::stringToPeriod | ( | QString | p | ) | const [virtual] |
Convert a string representation of the period to a RecurrencePeriod.
This is used to convert between the values stored in the recur table and the enumerated values used internally by the RecurrenceWidget. It also accepts human-readable values, such as "Minutes" and "Hours".
p | The recur_period or human-readable period name to convert. This is case-sensitive. Currently accepted values are m or Minutes, H or Hours, D or Days, W or Weeks, M or Months, Y or Years, C or Custom. If current translation includes the period names, the translations are also accepted. |
QDateTime RecurrenceWidget::_eot [protected] |
int RecurrenceWidget::_id [protected] |
int RecurrenceWidget::_parentId [protected] |
QString RecurrenceWidget::_parentType [protected] |
QDateTime RecurrenceWidget::_prevEndDateTime [protected] |
int RecurrenceWidget::_prevFrequency [protected] |
int RecurrenceWidget::_prevMax [protected] |
int RecurrenceWidget::_prevParentId [protected] |
QString RecurrenceWidget::_prevParentType [protected] |
RecurrencePeriod RecurrenceWidget::_prevPeriod [protected] |
bool RecurrenceWidget::_prevRecurring [protected] |
QDateTime RecurrenceWidget::_prevStartDateTime [protected] |
bool RecurrenceWidget::endDateVisible [read, write] |
Return whether the end date field is visible.
bool RecurrenceWidget::endTimeVisible [read, write] |
Return whether the end time field is visible.
bool RecurrenceWidget::maxVisible [read, write] |
bool RecurrenceWidget::startDateVisible [read, write] |
bool RecurrenceWidget::startTimeVisible [read, write] |
Generated on Mon Jan 23 2012 12:22:36 | xTuple ERP Programmer Reference, Version 3.8.0 |
![]() |