1 /***************************************************************************
2 * SPDX-FileCopyrightText: 2021 S. MANKOWSKI stephane@mankowski.fr
3 * SPDX-FileCopyrightText: 2021 G. DE BURE support@mankowski.fr
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 ***************************************************************************/
6 /** @file
7 * This file implements classes SKGRecurrentOperationObject.
8 *
9 * @author Stephane MANKOWSKI / Guillaume DE BURE
10 */
11 #include "skgrecurrentoperationobject.h"
12
13 #include <klocalizedstring.h>
14
15 #include "skgdocumentbank.h"
16 #include "skgoperationobject.h"
17 #include "skgservices.h"
18 #include "skgsuboperationobject.h"
19 #include "skgtraces.h"
20
SKGRecurrentOperationObject()21 SKGRecurrentOperationObject::SKGRecurrentOperationObject(): SKGRecurrentOperationObject(nullptr)
22 {}
23
SKGRecurrentOperationObject(SKGDocument * iDocument,int iID)24 SKGRecurrentOperationObject::SKGRecurrentOperationObject(SKGDocument* iDocument, int iID): SKGObjectBase(iDocument, QStringLiteral("v_recurrentoperation"), iID)
25 {}
26
27 SKGRecurrentOperationObject::~SKGRecurrentOperationObject()
28 = default;
29
30 SKGRecurrentOperationObject::SKGRecurrentOperationObject(const SKGRecurrentOperationObject& iObject) = default;
31
SKGRecurrentOperationObject(const SKGObjectBase & iObject)32 SKGRecurrentOperationObject::SKGRecurrentOperationObject(const SKGObjectBase& iObject)
33 {
34 if (iObject.getRealTable() == QStringLiteral("recurrentoperation")) {
35 copyFrom(iObject);
36 } else {
37 *this = SKGObjectBase(iObject.getDocument(), QStringLiteral("v_recurrentoperation"), iObject.getID());
38 }
39 }
40
operator =(const SKGObjectBase & iObject)41 SKGRecurrentOperationObject& SKGRecurrentOperationObject::operator= (const SKGObjectBase& iObject)
42 {
43 copyFrom(iObject);
44 return *this;
45 }
46
operator =(const SKGRecurrentOperationObject & iObject)47 SKGRecurrentOperationObject& SKGRecurrentOperationObject::operator= (const SKGRecurrentOperationObject& iObject)
48 {
49 copyFrom(iObject);
50 return *this;
51 }
52
getParentOperation(SKGOperationObject & oOperation) const53 SKGError SKGRecurrentOperationObject::getParentOperation(SKGOperationObject& oOperation) const
54 {
55 SKGObjectBase objTmp;
56 SKGError err = getDocument()->getObject(QStringLiteral("v_operation"), "id=" % getAttribute(QStringLiteral("rd_operation_id")), objTmp);
57 oOperation = objTmp;
58 return err;
59 }
60
setParentOperation(const SKGOperationObject & iOperation)61 SKGError SKGRecurrentOperationObject::setParentOperation(const SKGOperationObject& iOperation)
62 {
63 return setAttribute(QStringLiteral("rd_operation_id"), SKGServices::intToString(iOperation.getID()));
64 }
65
setPeriodIncrement(int iIncrement)66 SKGError SKGRecurrentOperationObject::setPeriodIncrement(int iIncrement)
67 {
68 return setAttribute(QStringLiteral("i_period_increment"), SKGServices::intToString(iIncrement));
69 }
70
getPeriodIncrement() const71 int SKGRecurrentOperationObject::getPeriodIncrement() const
72 {
73 return SKGServices::stringToInt(getAttribute(QStringLiteral("i_period_increment")));
74 }
75
getPeriodUnit() const76 SKGRecurrentOperationObject::PeriodUnit SKGRecurrentOperationObject::getPeriodUnit() const
77 {
78 QString t_period_unit = getAttribute(QStringLiteral("t_period_unit"));
79 if (t_period_unit == QStringLiteral("D")) {
80 return SKGRecurrentOperationObject::DAY;
81 }
82 if (t_period_unit == QStringLiteral("W")) {
83 return SKGRecurrentOperationObject::WEEK;
84 }
85 if (t_period_unit == QStringLiteral("M")) {
86 return SKGRecurrentOperationObject::MONTH;
87 }
88 return SKGRecurrentOperationObject::YEAR;
89 }
90
setPeriodUnit(SKGRecurrentOperationObject::PeriodUnit iPeriod)91 SKGError SKGRecurrentOperationObject::setPeriodUnit(SKGRecurrentOperationObject::PeriodUnit iPeriod)
92 {
93 return setAttribute(QStringLiteral("t_period_unit"), (iPeriod == SKGRecurrentOperationObject::DAY ? QStringLiteral("D") : (iPeriod == SKGRecurrentOperationObject::WEEK ? QStringLiteral("W") : (iPeriod == SKGRecurrentOperationObject::MONTH ? QStringLiteral("M") : QStringLiteral("Y")))));
94 }
95
setAutoWriteDays(int iDays)96 SKGError SKGRecurrentOperationObject::setAutoWriteDays(int iDays)
97 {
98 return setAttribute(QStringLiteral("i_auto_write_days"), SKGServices::intToString(iDays));
99 }
100
getAutoWriteDays() const101 int SKGRecurrentOperationObject::getAutoWriteDays() const
102 {
103 return SKGServices::stringToInt(getAttribute(QStringLiteral("i_auto_write_days")));
104 }
105
setWarnDays(int iDays)106 SKGError SKGRecurrentOperationObject::setWarnDays(int iDays)
107 {
108 return setAttribute(QStringLiteral("i_warn_days"), SKGServices::intToString(iDays));
109 }
110
getWarnDays() const111 int SKGRecurrentOperationObject::getWarnDays() const
112 {
113 return SKGServices::stringToInt(getAttribute(QStringLiteral("i_warn_days")));
114 }
115
hasTimeLimit() const116 bool SKGRecurrentOperationObject::hasTimeLimit() const
117 {
118 return (getAttribute(QStringLiteral("t_times")) == QStringLiteral("Y"));
119 }
120
timeLimit(bool iTimeLimit)121 SKGError SKGRecurrentOperationObject::timeLimit(bool iTimeLimit)
122 {
123 return setAttribute(QStringLiteral("t_times"), iTimeLimit ? QStringLiteral("Y") : QStringLiteral("N"));
124 }
125
setTimeLimit(QDate iLastDate)126 SKGError SKGRecurrentOperationObject::setTimeLimit(QDate iLastDate)
127 {
128 // Get parameters
129 QDate firstDate = this->getDate();
130 if (iLastDate < firstDate) {
131 return setTimeLimit(0);
132 }
133 SKGRecurrentOperationObject::PeriodUnit period = this->getPeriodUnit();
134 int occu = qMax(this->getPeriodIncrement(), 1);
135
136 // Compute nb time
137 int nbd = firstDate.daysTo(iLastDate);
138 if (period == SKGRecurrentOperationObject::DAY) {
139 nbd = nbd / occu;
140 } else if (period == SKGRecurrentOperationObject::WEEK) {
141 nbd = nbd / (7 * occu);
142 } else if (period == SKGRecurrentOperationObject::MONTH) {
143 nbd = (iLastDate.day() >= firstDate.day() ? 0 : -1) + (iLastDate.year() - firstDate.year()) * 12 + (iLastDate.month() - firstDate.month());
144 } else if (period == SKGRecurrentOperationObject::YEAR) {
145 nbd = nbd / (365 * occu);
146 }
147
148 if (nbd < -1) {
149 nbd = -1;
150 }
151 return setTimeLimit(nbd + 1);
152 }
153
setTimeLimit(int iTimeLimit)154 SKGError SKGRecurrentOperationObject::setTimeLimit(int iTimeLimit)
155 {
156 return setAttribute(QStringLiteral("i_nb_times"), SKGServices::intToString(iTimeLimit));
157 }
158
getTimeLimit() const159 int SKGRecurrentOperationObject::getTimeLimit() const
160 {
161 return SKGServices::stringToInt(getAttribute(QStringLiteral("i_nb_times")));
162 }
163
setDate(QDate iDate)164 SKGError SKGRecurrentOperationObject::setDate(QDate iDate)
165 {
166 return setAttribute(QStringLiteral("d_date"), SKGServices::dateToSqlString(iDate));
167 }
168
getNextDate() const169 QDate SKGRecurrentOperationObject::getNextDate() const
170 {
171 QDate nextDate = getDate();
172 SKGRecurrentOperationObject::PeriodUnit punit = getPeriodUnit();
173 int p = getPeriodIncrement();
174 if (punit == SKGRecurrentOperationObject::DAY) {
175 nextDate = nextDate.addDays(p);
176 } else if (punit == SKGRecurrentOperationObject::WEEK) {
177 nextDate = nextDate.addDays(7 * p);
178 } else if (punit == SKGRecurrentOperationObject::MONTH) {
179 nextDate = nextDate.addMonths(p);
180 } else if (punit == SKGRecurrentOperationObject::YEAR) {
181 nextDate = nextDate.addYears(p);
182 }
183 return nextDate;
184 }
185
getDate() const186 QDate SKGRecurrentOperationObject::getDate() const
187 {
188 return SKGServices::stringToTime(getAttribute(QStringLiteral("d_date"))).date();
189 }
190
warnEnabled(bool iWarn)191 SKGError SKGRecurrentOperationObject::warnEnabled(bool iWarn)
192 {
193 return setAttribute(QStringLiteral("t_warn"), iWarn ? QStringLiteral("Y") : QStringLiteral("N"));
194 }
195
isWarnEnabled() const196 bool SKGRecurrentOperationObject::isWarnEnabled() const
197 {
198 return (getAttribute(QStringLiteral("t_warn")) == QStringLiteral("Y"));
199 }
200
autoWriteEnabled(bool iAutoWrite)201 SKGError SKGRecurrentOperationObject::autoWriteEnabled(bool iAutoWrite)
202 {
203 return setAttribute(QStringLiteral("t_auto_write"), iAutoWrite ? QStringLiteral("Y") : QStringLiteral("N"));
204 }
205
isAutoWriteEnabled() const206 bool SKGRecurrentOperationObject::isAutoWriteEnabled() const
207 {
208 return (getAttribute(QStringLiteral("t_auto_write")) == QStringLiteral("Y"));
209 }
210
getRecurredOperations(SKGListSKGObjectBase & oOperations) const211 SKGError SKGRecurrentOperationObject::getRecurredOperations(SKGListSKGObjectBase& oOperations) const
212 {
213 return getDocument()->getObjects(QStringLiteral("v_operation"), "r_recurrentoperation_id=" % SKGServices::intToString(getID()), oOperations);
214 }
215
process(int & oNbInserted,bool iForce,QDate iDate)216 SKGError SKGRecurrentOperationObject::process(int& oNbInserted, bool iForce, QDate iDate)
217 {
218 SKGError err;
219 SKGTRACEINFUNCRC(10, err)
220 oNbInserted = 0;
221
222 if (!hasTimeLimit() || getTimeLimit() > 0) {
223 if (isAutoWriteEnabled() || iForce) {
224 QDate nextDate = getDate();
225 if (nextDate.isValid() && iDate >= nextDate.addDays(-getAutoWriteDays())) {
226 SKGOperationObject op;
227 err = getParentOperation(op);
228 IFOK(err) {
229 // Create the duplicated operation
230 SKGOperationObject newOp;
231 err = op.duplicate(newOp, nextDate);
232
233 if (!op.isTemplate()) {
234 // Set old op as recurrent
235 IFOKDO(err, op.setAttribute(QStringLiteral("r_recurrentoperation_id"), SKGServices::intToString(getID())))
236 IFOKDO(err, op.save())
237
238 // Set new operation as reference
239 IFOKDO(err, setParentOperation(newOp))
240 } else {
241 // Set new op as recurrent
242 IFOKDO(err, newOp.setAttribute(QStringLiteral("r_recurrentoperation_id"), SKGServices::intToString(getID())))
243 IFOKDO(err, newOp.save())
244 }
245
246 IFOKDO(err, setDate(getNextDate()))
247 if (!err && hasTimeLimit()) {
248 err = setTimeLimit(getTimeLimit() - 1);
249 }
250 IFOKDO(err, save())
251 IFOKDO(err, load())
252
253 // Process again in case of multi insert needed
254 int nbi = 0;
255 IFOKDO(err, process(nbi, iForce, iDate))
256 oNbInserted = oNbInserted + 1 + nbi;
257
258 // Send message
259 IFOKDO(err, newOp.load())
260 IFOK(err) {
261 err = getDocument()->sendMessage(i18nc("An information message", "Operation '%1' has been inserted", newOp.getDisplayName()), SKGDocument::Positive);
262 }
263 }
264 }
265 }
266
267 if (isWarnEnabled() && !err) {
268 QDate nextDate = getDate();
269 if (QDate::currentDate() >= nextDate.addDays(-getWarnDays())) {
270 SKGOperationObject op;
271 err = getParentOperation(op);
272 IFOK(err) {
273 int nbdays = QDate::currentDate().daysTo(nextDate);
274 if (nbdays > 0) {
275 err = getDocument()->sendMessage(i18np("Operation '%2' will be inserted in one day", "Operation '%2' will be inserted in %1 days", nbdays, getDisplayName()));
276 }
277 }
278 }
279 }
280 }
281 return err;
282 }
283
process(SKGDocumentBank * iDocument,int & oNbInserted,bool iForce,QDate iDate)284 SKGError SKGRecurrentOperationObject::process(SKGDocumentBank* iDocument, int& oNbInserted, bool iForce, QDate iDate)
285 {
286 SKGError err;
287 oNbInserted = 0;
288
289 // Get all operation with auto_write
290 SKGListSKGObjectBase recuOps;
291 if (iDocument != nullptr) {
292 err = iDocument->getObjects(QStringLiteral("v_recurrentoperation"), QLatin1String(""), recuOps);
293 }
294
295 int nb = recuOps.count();
296 for (int i = 0; !err && i < nb; ++i) {
297 SKGRecurrentOperationObject recu(recuOps.at(i));
298 int nbi = 0;
299 err = recu.process(nbi, iForce, iDate);
300 oNbInserted += nbi;
301 }
302
303 return err;
304 }
305
306
307
308