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 * A skrooge plugin to manage scheduled operations
8 *
9 * @author Stephane MANKOWSKI
10 */
11 #include "skgscheduledplugin.h"
12
13 #include <kaboutdata.h>
14 #include <kactioncollection.h>
15 #include <kpluginfactory.h>
16 #include <qstandardpaths.h>
17
18 #include "skgdocumentbank.h"
19 #include "skgmainpanel.h"
20 #include "skgrecurrentoperationobject.h"
21 #include "skgscheduled_settings.h"
22 #include "skgscheduledboardwidget.h"
23 #include "skgscheduledpluginwidget.h"
24 #include "skgsuboperationobject.h"
25 #include "skgtraces.h"
26 #include "skgtransactionmng.h"
27
28 /**
29 * This plugin factory.
30 */
K_PLUGIN_FACTORY(SKGScheduledPluginFactory,registerPlugin<SKGScheduledPlugin> ();)31 K_PLUGIN_FACTORY(SKGScheduledPluginFactory, registerPlugin<SKGScheduledPlugin>();)
32
33 SKGScheduledPlugin::SKGScheduledPlugin(QWidget* iWidget, QObject* iParent, const QVariantList& /*iArg*/) :
34 SKGInterfacePlugin(iParent), m_currentBankDocument(nullptr), m_counterAdvice(0)
35 {
36 Q_UNUSED(iWidget)
37 SKGTRACEINFUNC(10)
38 }
39
~SKGScheduledPlugin()40 SKGScheduledPlugin::~SKGScheduledPlugin()
41 {
42 SKGTRACEINFUNC(10)
43 m_currentBankDocument = nullptr;
44 }
45
setupActions(SKGDocument * iDocument)46 bool SKGScheduledPlugin::setupActions(SKGDocument* iDocument)
47 {
48 SKGTRACEINFUNC(10)
49
50 m_currentBankDocument = qobject_cast<SKGDocumentBank*>(iDocument);
51 if (m_currentBankDocument == nullptr) {
52 return false;
53 }
54
55 setComponentName(QStringLiteral("skrooge_scheduled"), title());
56 setXMLFile(QStringLiteral("skrooge_scheduled.rc"));
57
58 // Create yours actions here
59 auto actScheduleOperation = new QAction(SKGServices::fromTheme(icon()), i18nc("Verb, create a scheduled operation", "Schedule"), this);
60 connect(actScheduleOperation, &QAction::triggered, this, &SKGScheduledPlugin::onScheduleOperation);
61 actionCollection()->setDefaultShortcut(actScheduleOperation, Qt::CTRL + Qt::Key_I);
62 registerGlobalAction(QStringLiteral("schedule_operation"), actScheduleOperation, QStringList() << QStringLiteral("operation"), 1, -1, 410);
63
64 auto actSkipScheduledOperation = new QAction(SKGServices::fromTheme(QStringLiteral("nextuntranslated")), i18nc("Verb, skip scheduled operations", "Skip"), this);
65 connect(actSkipScheduledOperation, &QAction::triggered, this, &SKGScheduledPlugin::onSkipScheduledOperations);
66 registerGlobalAction(QStringLiteral("skip_scheduled_operations"), actSkipScheduledOperation, QStringList() << QStringLiteral("recurrentoperation"), 1, -1, 410);
67
68 return true;
69 }
70
refresh()71 void SKGScheduledPlugin::refresh()
72 {
73 SKGTRACEINFUNC(10)
74 // Automatic insert
75 if ((m_currentBankDocument != nullptr) && m_currentBankDocument->getMainDatabase() != nullptr) {
76 QString doc_id = m_currentBankDocument->getUniqueIdentifier();
77 if (m_docUniqueIdentifier != doc_id && m_currentBankDocument->getParameter(QStringLiteral("SKG_DB_BANK_VERSION")) >= QStringLiteral("0.5")) {
78 m_docUniqueIdentifier = doc_id;
79
80 SKGError err;
81 // Read Setting
82 bool check_on_open = skgscheduled_settings::check_on_open();
83
84 if (check_on_open) {
85 SKGBEGINTRANSACTION(*m_currentBankDocument, i18nc("Noun, name of the user action", "Insert recurrent operations"), err)
86 int nbi = 0;
87 err = SKGRecurrentOperationObject::process(m_currentBankDocument, nbi);
88 }
89 // Display error
90 SKGMainPanel::displayErrorMessage(err);
91 }
92 }
93 }
94
getNbDashboardWidgets()95 int SKGScheduledPlugin::getNbDashboardWidgets()
96 {
97 return 1;
98 }
99
getDashboardWidgetTitle(int iIndex)100 QString SKGScheduledPlugin::getDashboardWidgetTitle(int iIndex)
101 {
102 Q_UNUSED(iIndex)
103 return i18nc("Noun, the title of a section", "Scheduled operations");
104 }
105
getDashboardWidget(int iIndex)106 SKGBoardWidget* SKGScheduledPlugin::getDashboardWidget(int iIndex)
107 {
108 Q_UNUSED(iIndex)
109 return new SKGScheduledBoardWidget(SKGMainPanel::getMainPanel(), m_currentBankDocument);
110 }
111
getWidget()112 SKGTabPage* SKGScheduledPlugin::getWidget()
113 {
114 SKGTRACEINFUNC(10)
115 return new SKGScheduledPluginWidget(SKGMainPanel::getMainPanel(), m_currentBankDocument);
116 }
117
getPreferenceWidget()118 QWidget* SKGScheduledPlugin::getPreferenceWidget()
119 {
120 SKGTRACEINFUNC(10)
121 auto w = new QWidget();
122 ui.setupUi(w);
123
124 connect(ui.kcfg_remind_me, &QCheckBox::toggled, ui.kcfg_remind_me_days, &QSpinBox::setEnabled);
125 connect(ui.kcfg_remind_me, &QCheckBox::toggled, ui.label_3, &QSpinBox::setEnabled);
126 connect(ui.kcfg_nb_times, &QCheckBox::toggled, ui.kcfg_nb_times_val, &QSpinBox::setEnabled);
127 connect(ui.kcfg_auto_write, &QCheckBox::toggled, ui.kcfg_auto_write_days, &QSpinBox::setEnabled);
128 connect(ui.kcfg_auto_write, &QCheckBox::toggled, ui.label_4, &QSpinBox::setEnabled);
129 return w;
130 }
131
getPreferenceSkeleton()132 KConfigSkeleton* SKGScheduledPlugin::getPreferenceSkeleton()
133 {
134 return skgscheduled_settings::self();
135 }
136
title() const137 QString SKGScheduledPlugin::title() const
138 {
139 return i18nc("Noun", "Scheduled operations");
140 }
141
icon() const142 QString SKGScheduledPlugin::icon() const
143 {
144 return QStringLiteral("chronometer");
145 }
146
toolTip() const147 QString SKGScheduledPlugin::toolTip() const
148 {
149 return i18nc("Noun", "Operations scheduled management");
150 }
151
getOrder() const152 int SKGScheduledPlugin::getOrder() const
153 {
154 return 20;
155 }
156
tips() const157 QStringList SKGScheduledPlugin::tips() const
158 {
159 QStringList output;
160 output.push_back(i18nc("Description of a tips", "<p>... you can <a href=\"skg://skrooge_scheduled_plugin\">schedule</a> operations or templates.</p>"));
161 return output;
162 }
163
isInPagesChooser() const164 bool SKGScheduledPlugin::isInPagesChooser() const
165 {
166 return true;
167 }
168
savePreferences() const169 SKGError SKGScheduledPlugin::savePreferences() const
170 {
171 SKGError err;
172 if (m_currentBankDocument != nullptr) {
173 // Read Setting
174 if (skgscheduled_settings::create_template()) {
175 SKGObjectBase::SKGListSKGObjectBase recurrents;
176 err = m_currentBankDocument->getObjects(QStringLiteral("v_recurrentoperation"), QStringLiteral("(select count(1) from operation where operation.id=rd_operation_id and t_template='N')=1"), recurrents);
177 int nb = recurrents.count();
178 if (nb != 0) {
179 SKGBEGINPROGRESSTRANSACTION(*m_currentBankDocument, i18nc("Noun, name of the user action", "Conversion schedule"), err, nb)
180 for (int i = 0; !err && i < nb; ++i) {
181 // Migration of existing schedule in template mode
182 SKGRecurrentOperationObject recOp(recurrents.at(i));
183 SKGOperationObject operationObj;
184
185 IFOK(err) recOp.getParentOperation(operationObj);
186
187 SKGOperationObject operationObjOrig = operationObj;
188 IFOKDO(err, operationObjOrig.duplicate(operationObj, operationObjOrig.getDate(), true))
189
190 IFOKDO(err, recOp.setParentOperation(operationObj))
191 IFOKDO(err, recOp.save())
192 IFOKDO(err, recOp.load())
193
194 IFOKDO(err, operationObjOrig.setAttribute(QStringLiteral("r_recurrentoperation_id"), SKGServices::intToString(recOp.getID())))
195 IFOKDO(err, operationObjOrig.save())
196
197 IFOKDO(err, m_currentBankDocument->stepForward(i + 1))
198 }
199 IFOK(err) m_currentBankDocument->sendMessage(i18nc("An information message", "All scheduled operations have been converted in template"));
200 }
201 }
202 }
203 return err;
204 }
205
scheduleOperation(const SKGOperationObject & iOperation,SKGRecurrentOperationObject & oRecurrent) const206 SKGError SKGScheduledPlugin::scheduleOperation(const SKGOperationObject& iOperation, SKGRecurrentOperationObject& oRecurrent) const
207 {
208 SKGError err;
209 SKGOperationObject operationObjDuplicate = iOperation;
210 bool isTemplate = operationObjDuplicate.isTemplate();
211
212 SKGOperationObject operationObjOrig;
213 if (!isTemplate && skgscheduled_settings::create_template()) {
214 // The selected operation is not a template and settings is set to create one
215 operationObjOrig = operationObjDuplicate;
216 IFOKDO(err, operationObjOrig.duplicate(operationObjDuplicate, operationObjOrig.getDate(), true))
217 IFOK(err) m_currentBankDocument->sendMessage(i18nc("An information message", "A template has been created"), SKGDocument::Positive);
218 }
219
220 SKGRecurrentOperationObject recOp;
221 err = operationObjDuplicate.addRecurrentOperation(recOp);
222 IFOKDO(err, recOp.warnEnabled(skgscheduled_settings::remind_me()))
223 IFOKDO(err, recOp.setWarnDays(skgscheduled_settings::remind_me_days()))
224 IFOKDO(err, recOp.autoWriteEnabled(skgscheduled_settings::auto_write()))
225 IFOKDO(err, recOp.setAutoWriteDays(skgscheduled_settings::auto_write_days()))
226 IFOKDO(err, recOp.timeLimit(skgscheduled_settings::nb_times()))
227 IFOKDO(err, recOp.setTimeLimit(skgscheduled_settings::nb_times_val()))
228 IFOKDO(err, recOp.setPeriodIncrement(skgscheduled_settings::once_every()))
229 IFOKDO(err, recOp.setPeriodUnit(static_cast<SKGRecurrentOperationObject::PeriodUnit>(SKGServices::stringToInt(skgscheduled_settings::once_every_unit()))))
230 if (!err && !isTemplate) {
231 err = recOp.setDate(recOp.getNextDate());
232 }
233 IFOKDO(err, recOp.save())
234 if (!isTemplate && skgscheduled_settings::create_template()) {
235 IFOKDO(err, recOp.load())
236 IFOKDO(err, operationObjOrig.setAttribute(QStringLiteral("r_recurrentoperation_id"), SKGServices::intToString(recOp.getID())))
237 IFOKDO(err, operationObjOrig.save())
238 }
239
240 oRecurrent = recOp;
241
242 return err;
243 }
244
onScheduleOperation()245 void SKGScheduledPlugin::onScheduleOperation()
246 {
247 SKGError err;
248 SKGTRACEINFUNCRC(10, err)
249
250 // Get Selection
251 if (SKGMainPanel::getMainPanel() != nullptr) {
252 SKGObjectBase::SKGListSKGObjectBase selection = SKGMainPanel::getMainPanel()->getSelectedObjects();
253 int nb = selection.count();
254 if ((nb != 0) && (m_currentBankDocument != nullptr)) {
255 QStringList list;
256 SKGBEGINPROGRESSTRANSACTION(*m_currentBankDocument, i18nc("Noun, name of the user action", "Operation schedule"), err, nb)
257 for (int i = 0; !err && i < nb; ++i) {
258 SKGOperationObject operationObj(selection.at(i));
259 SKGRecurrentOperationObject rop;
260 err = scheduleOperation(operationObj, rop);
261
262 // Send message
263 IFOKDO(err, m_currentBankDocument->sendMessage(i18nc("An information to the user", "The operation '%1' has been scheduled", operationObj.getDisplayName()), SKGDocument::Hidden))
264
265 IFOKDO(err, m_currentBankDocument->stepForward(i + 1))
266 list.push_back(operationObj.getUniqueID());
267 }
268
269 IFOK(err) {
270 // Open the scheduled operation
271 SKGMainPanel::getMainPanel()->openPage("skg://skrooge_scheduled_plugin/?selection=" % SKGServices::encodeForUrl(SKGServices::stringsToCsv(list)));
272 }
273 }
274
275 // status bar
276 IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Operation scheduled.")))
277 else {
278 err.addError(ERR_FAIL, i18nc("Error message", "Operation schedule failed"));
279 }
280
281 // Display error
282 SKGMainPanel::displayErrorMessage(err);
283 }
284 }
285
onSkipScheduledOperations()286 void SKGScheduledPlugin::onSkipScheduledOperations()
287 {
288 SKGError err;
289 SKGTRACEINFUNCRC(10, err)
290
291 // Get Selection
292 if (SKGMainPanel::getMainPanel() != nullptr) {
293 SKGObjectBase::SKGListSKGObjectBase selection;
294 auto selectionString = sender()->property("selection").toString();
295 if (!selectionString.isEmpty()) {
296 selection.append(SKGRecurrentOperationObject(m_currentBankDocument, SKGServices::stringToInt(SKGServices::splitCSVLine(selectionString, QLatin1Char('-'), false).at(0))));
297 } else {
298 selection = SKGMainPanel::getMainPanel()->getSelectedObjects();
299 }
300 int nb = selection.count();
301 if ((nb != 0) && (m_currentBankDocument != nullptr)) {
302 QStringList list;
303 SKGBEGINPROGRESSTRANSACTION(*m_currentBankDocument, i18nc("Noun, name of the user action", "Skip scheduled operations"), err, nb)
304 for (int i = 0; !err && i < nb; ++i) {
305 SKGRecurrentOperationObject rop(m_currentBankDocument, selection.at(i).getID());
306 err = rop.setDate(rop.getNextDate());
307 if (!err && rop.hasTimeLimit()) {
308 err = rop.setTimeLimit(rop.getTimeLimit() - 1);
309 }
310 IFOKDO(err, rop.save())
311
312 IFOKDO(err, m_currentBankDocument->stepForward(i + 1))
313 list.push_back(rop.getUniqueID());
314 }
315 }
316
317 // status bar
318 IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Scheduled operations skipped.")))
319 else {
320 err.addError(ERR_FAIL, i18nc("Error message", "Skip of scheduled operation failed"));
321 }
322
323 // Display error
324 SKGMainPanel::displayErrorMessage(err);
325 }
326 }
327
328
advice(const QStringList & iIgnoredAdvice)329 SKGAdviceList SKGScheduledPlugin::advice(const QStringList& iIgnoredAdvice)
330 {
331 SKGTRACEINFUNC(10)
332 SKGAdviceList output;
333 output.reserve(20);
334
335 // Recurrent operation with the last inserted operation having a different amount
336 if (!iIgnoredAdvice.contains(QStringLiteral("skgscheduledplugin_notuptodate"))) {
337 SKGStringListList result;
338 m_currentBankDocument->executeSelectSqliteOrder("SELECT r.id, r.rd_operation_id, r.f_CURRENTAMOUNT, r2.f_CURRENTAMOUNT FROM v_recurrentoperation_display r INNER JOIN (SELECT MAX(d_date), f_CURRENTAMOUNT, r_recurrentoperation_id FROM v_operation_display GROUP BY r_recurrentoperation_id) r2 WHERE r2.r_recurrentoperation_id=r.id AND ABS(r.f_CURRENTAMOUNT-r2.f_CURRENTAMOUNT)>" % SKGServices::doubleToString(EPSILON), result);
339 int nb = result.count();
340 SKGAdvice::SKGAdviceActionList autoCorrections;
341 for (int i = 1; i < nb; ++i) { // Ignore header
342 // Get parameters
343 const QStringList& line = result.at(i);
344 int idRecu = SKGServices::stringToInt(line.at(0));
345 const QString& idOper = line.at(1);
346 const QString& amountLastOperation = line.at(3);
347
348 SKGRecurrentOperationObject recu(m_currentBankDocument, idRecu);
349 QString name = recu.getDisplayName();
350
351 SKGAdvice ad;
352 ad.setUUID("skgscheduledplugin_notuptodate|" % idOper % ';' % amountLastOperation);
353 ad.setPriority(4);
354 ad.setShortMessage(i18nc("Advice on making the best (short)", "Scheduled operation '%1' not uptodate", name));
355 ad.setLongMessage(i18nc("Advice on making the best (long)", "The scheduled operation '%1' does not have the amount of the last inserted operation (%2)", name, amountLastOperation));
356 autoCorrections.resize(0);
357 {
358 SKGAdvice::SKGAdviceAction a;
359 a.Title = i18nc("Advice on making the best (action)", "Update the next scheduled operation amount (%1)", amountLastOperation);
360 a.IconName = QStringLiteral("system-run");
361 a.IsRecommended = true;
362 autoCorrections.push_back(a);
363 }
364 ad.setAutoCorrections(autoCorrections);
365 output.push_back(ad);
366 }
367 }
368
369 // Recurrent operation with the last inserted operation having a different date
370 if (!iIgnoredAdvice.contains(QStringLiteral("skgscheduledplugin_newdate"))) {
371 SKGStringListList result;
372 m_currentBankDocument->executeSelectSqliteOrder(QStringLiteral("SELECT r.id, r.d_date, "
373 "date(r2.d_date, '+'||((CASE r.t_period_unit WHEN 'W' THEN 7 ELSE 1 END)*r.i_period_increment)||' '||(CASE r.t_period_unit WHEN 'M' THEN 'month' WHEN 'Y' THEN 'year' ELSE 'day' END)) "
374 "FROM v_recurrentoperation_display r "
375 "INNER JOIN (SELECT MAX(d_date) as d_date, r_recurrentoperation_id FROM v_operation_display GROUP BY r_recurrentoperation_id) r2 "
376 "WHERE r2.r_recurrentoperation_id=r.id AND r.d_PREVIOUS!=r2.d_date"), result);
377 int nb = result.count();
378 SKGAdvice::SKGAdviceActionList autoCorrections;
379 for (int i = 1; i < nb; ++i) { // Ignore header
380 // Get parameters
381 const QStringList& line = result.at(i);
382 int idRecu = SKGServices::stringToInt(line.at(0));
383 const QString& currentDate = line.at(1);
384 const QString& newDate = line.at(2);
385 if (SKGServices::stringToTime(newDate).date() > QDate::currentDate() && SKGServices::stringToTime(newDate).date() != SKGServices::stringToTime(currentDate).date()) {
386 SKGRecurrentOperationObject recu(m_currentBankDocument, idRecu);
387 QString name = recu.getDisplayName();
388
389 SKGAdvice ad;
390 ad.setUUID("skgscheduledplugin_newdate|" % line.at(0) % ';' % newDate);
391 ad.setPriority(4);
392 ad.setShortMessage(i18nc("Advice on making the best (short)", "Scheduled operation '%1' not uptodate", name));
393 ad.setLongMessage(i18nc("Advice on making the best (long)", "The scheduled operation '%1' does not have the date aligned with the last inserted operation (%2)", name, currentDate));
394 autoCorrections.resize(0);
395 {
396 SKGAdvice::SKGAdviceAction a;
397 a.Title = i18nc("Advice on making the best (action)", "Update the next scheduled operation date (%1)", newDate);
398 a.IconName = QStringLiteral("system-run");
399 a.IsRecommended = true;
400 autoCorrections.push_back(a);
401 }
402 ad.setAutoCorrections(autoCorrections);
403 output.push_back(ad);
404 }
405 }
406 }
407
408 // Possible recurrent operations
409 if (!iIgnoredAdvice.contains(QStringLiteral("skgscheduledplugin_possibleschedule"))) {
410 SKGStringListList result;
411
412 m_currentBankDocument->executeSelectSqliteOrder(QStringLiteral("SELECT op1.id, op1.t_displayname FROM v_operation_displayname op1 WHERE op1.id||'#'||op1.f_QUANTITY IN (SELECT op1.id||'#'||op2.f_QUANTITY FROM operation op1, v_operation_tmp1 op2 "
413 "WHERE op1.rd_account_id=op2.rd_account_id AND op1.r_payee_id=op2.r_payee_id AND op1.rc_unit_id=op2.rc_unit_id "
414 "AND op1.r_recurrentoperation_id=0 AND op1.d_date<>'0000-00-00' AND op1.d_date=date(op2.d_date, '+1 month') "
415 "AND op1.d_date>(SELECT date('now', 'localtime','-2 month')) AND op2.d_date>(SELECT date('now', 'localtime','-3 month'))) "
416 "AND op1.t_TRANSFER='N' "
417 "AND NOT EXISTS (SELECT 1 FROM recurrentoperation ro, v_operation_tmp1 rop WHERE ro.rd_operation_id=rop.id AND ro.i_period_increment=1 AND ro.t_period_unit='M' AND op1.rd_account_id=rop.rd_account_id AND op1.r_payee_id=rop.r_payee_id AND op1.f_QUANTITY=rop.f_QUANTITY AND op1.rc_unit_id=rop.rc_unit_id)"), result);
418 int nb = result.count();
419 SKGAdvice::SKGAdviceActionList autoCorrections;
420 autoCorrections.reserve(nb);
421 for (int i = 1; i < nb; ++i) { // Ignore header
422 // Get parameters
423 const QStringList& line = result.at(i);
424 const QString& id = line.at(0);
425 const QString& name = line.at(1);
426
427 SKGAdvice ad;
428 ad.setUUID("skgscheduledplugin_possibleschedule|" % id);
429 ad.setPriority(4);
430 ad.setShortMessage(i18nc("Advice on making the best (short)", "Possible schedule '%1'", name));
431 ad.setLongMessage(i18nc("Advice on making the best (long)", "The operation '%1' seems to be regularly created and could be scheduled", name));
432 autoCorrections.resize(0);
433 {
434 SKGAdvice::SKGAdviceAction a;
435 a.Title = i18nc("Advice on making the best (action)", "Monthly schedule the operation '%1'", name);
436 a.IconName = icon();
437 a.IsRecommended = false;
438 autoCorrections.push_back(a);
439 }
440 ad.setAutoCorrections(autoCorrections);
441 output.push_back(ad);
442 }
443 }
444 m_counterAdvice++;
445 return output;
446 }
447
executeAdviceCorrection(const QString & iAdviceIdentifier,int iSolution)448 SKGError SKGScheduledPlugin::executeAdviceCorrection(const QString& iAdviceIdentifier, int iSolution)
449 {
450 SKGError err;
451 if ((m_currentBankDocument != nullptr) && iAdviceIdentifier.startsWith(QLatin1String("skgscheduledplugin_notuptodate|"))) {
452 // Get parameters
453 QString parameters = iAdviceIdentifier.right(iAdviceIdentifier.length() - 31);
454 int pos = parameters.indexOf(';');
455 int idOper = SKGServices::stringToInt(parameters.left(pos));
456 double amount = SKGServices::stringToDouble(parameters.right(parameters.length() - 1 - pos));
457
458 // Update the operation
459 {
460 SKGBEGINTRANSACTION(*m_currentBankDocument, i18nc("Noun, name of the user action", "Update scheduled operation"), err)
461 SKGOperationObject op(m_currentBankDocument, idOper);
462 SKGObjectBase::SKGListSKGObjectBase subOps;
463 IFOKDO(err, op.getSubOperations(subOps))
464
465 if (subOps.count() == 1) {
466 // Change the quantity of the sub operation
467 SKGSubOperationObject so1(subOps.at(0));
468 IFOKDO(err, so1.setQuantity(amount))
469 IFOKDO(err, so1.save())
470 } else if (subOps.count() >= 1) {
471 // Add a split
472 SKGSubOperationObject so1;
473 IFOKDO(err, op.addSubOperation(so1))
474 IFOKDO(err, so1.setQuantity(amount - op.getCurrentAmount()))
475 IFOKDO(err, so1.save())
476 }
477
478 // Send message
479 IFOKDO(err, op.getDocument()->sendMessage(i18nc("An information to the user", "The amount of the scheduled operation of '%1' have been updated", op.getDisplayName()), SKGDocument::Hidden))
480 }
481
482 // status bar
483 IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Scheduled operation updated.")))
484 else {
485 err.addError(ERR_FAIL, i18nc("Error message", "Update failed"));
486 }
487
488 // Display error
489 SKGMainPanel::displayErrorMessage(err);
490
491 return err;
492 }
493 if ((m_currentBankDocument != nullptr) && iAdviceIdentifier.startsWith(QLatin1String("skgscheduledplugin_newdate|"))) {
494 // Get parameters
495 QString parameters = iAdviceIdentifier.right(iAdviceIdentifier.length() - 27);
496 int pos = parameters.indexOf(';');
497 int id = SKGServices::stringToInt(parameters.left(pos));
498 QString newDate = parameters.right(parameters.length() - 1 - pos);
499
500 // Update the operation
501 {
502 SKGBEGINTRANSACTION(*m_currentBankDocument, i18nc("Noun, name of the user action", "Update scheduled operation"), err)
503 SKGRecurrentOperationObject rop(m_currentBankDocument, id);
504 IFOKDO(err, rop.setDate(SKGServices::stringToTime(newDate).date()))
505 IFOKDO(err, rop.save())
506
507 // Send message
508 IFOKDO(err, rop.getDocument()->sendMessage(i18nc("An information to the user", "The date of the scheduled operation of '%1' have been updated", rop.getDisplayName()), SKGDocument::Hidden))
509 }
510
511 // status bar
512 IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Scheduled operation updated.")))
513 else {
514 err.addError(ERR_FAIL, i18nc("Error message", "Update failed"));
515 }
516
517 // Display error
518 SKGMainPanel::displayErrorMessage(err);
519
520 return err;
521 }
522 if ((m_currentBankDocument != nullptr) && iAdviceIdentifier.startsWith(QLatin1String("skgscheduledplugin_possibleschedule|"))) {
523 // Get parameters
524 int idOper = SKGServices::stringToInt(iAdviceIdentifier.right(iAdviceIdentifier.length() - 36));
525
526 // Update the operation
527 {
528 SKGBEGINTRANSACTION(*m_currentBankDocument, i18nc("Noun, name of the user action", "Scheduled operation"), err)
529 SKGOperationObject op(m_currentBankDocument, idOper);
530 SKGRecurrentOperationObject rop;
531 err = scheduleOperation(op, rop);
532 IFOKDO(err, rop.setPeriodUnit(SKGRecurrentOperationObject::MONTH))
533 IFOKDO(err, rop.setPeriodIncrement(1))
534 IFOKDO(err, rop.setDate(op.getDate()))
535 IFOKDO(err, rop.setDate(rop.getNextDate()))
536 IFOKDO(err, rop.save())
537
538 // Send message
539 IFOKDO(err, rop.getDocument()->sendMessage(i18nc("An information to the user", "The scheduled operation of '%1' have been added", rop.getDisplayName()), SKGDocument::Hidden))
540
541 m_counterAdvice = 0; // To force the update
542 }
543
544 // status bar
545 IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Operation scheduled.")))
546 else {
547 err.addError(ERR_FAIL, i18nc("Error message", "Schedule failed"));
548 }
549
550 // Display error
551 SKGMainPanel::displayErrorMessage(err);
552
553 return err;
554 }
555
556
557 return SKGInterfacePlugin::executeAdviceCorrection(iAdviceIdentifier, iSolution);
558 }
559
560 #include <skgscheduledplugin.moc>
561