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 SKGOperationObject.
8  *
9  * @author Stephane MANKOWSKI / Guillaume DE BURE
10  */
11 #include "skgoperationobject.h"
12 
13 #include <klocalizedstring.h>
14 
15 #include "skgaccountobject.h"
16 #include "skgdocument.h"
17 #include "skgpayeeobject.h"
18 #include "skgrecurrentoperationobject.h"
19 #include "skgservices.h"
20 #include "skgsuboperationobject.h"
21 #include "skgtraces.h"
22 #include "skgunitobject.h"
23 
SKGOperationObject()24 SKGOperationObject::SKGOperationObject() : SKGOperationObject(nullptr)
25 {}
26 
SKGOperationObject(SKGDocument * iDocument,int iID)27 SKGOperationObject::SKGOperationObject(SKGDocument* iDocument, int iID) : SKGObjectBase(iDocument, QStringLiteral("v_operation"), iID)
28 {}
29 
30 SKGOperationObject::~SKGOperationObject()
31     = default;
32 
33 SKGOperationObject::SKGOperationObject(const SKGOperationObject& iObject)
34     = default;
35 
SKGOperationObject(const SKGObjectBase & iObject)36 SKGOperationObject::SKGOperationObject(const SKGObjectBase& iObject)
37 {
38     if (iObject.getRealTable() == QStringLiteral("operation")) {
39         copyFrom(iObject);
40     } else {
41         *this = SKGObjectBase(iObject.getDocument(), QStringLiteral("v_operation"), iObject.getID());
42     }
43 }
44 
operator =(const SKGObjectBase & iObject)45 SKGOperationObject& SKGOperationObject::operator= (const SKGObjectBase& iObject)
46 {
47     copyFrom(iObject);
48     return *this;
49 }
50 
operator =(const SKGOperationObject & iObject)51 SKGOperationObject& SKGOperationObject::operator= (const SKGOperationObject& iObject)
52 {
53     copyFrom(iObject);
54     return *this;
55 }
56 
duplicate(SKGOperationObject & oOperation,QDate iDate,bool iTemplateMode) const57 SKGError SKGOperationObject::duplicate(SKGOperationObject& oOperation, QDate iDate, bool iTemplateMode) const
58 {
59     SKGError err;
60     SKGTRACEINFUNCRC(20, err)
61     QDate previousDate = getDate();
62 
63     // Create the duplicated operation
64     oOperation = SKGOperationObject(getDocument(), this->getID());  // To be sure the object is on v_operation
65     IFOKDO(err, oOperation.load())
66     IFOKDO(err, oOperation.resetID())
67     IFOKDO(err, oOperation.setDate(iDate))
68     IFOKDO(err, oOperation.setStatus(SKGOperationObject::NONE))
69     IFOKDO(err, oOperation.setImported(false))
70     IFOKDO(err, oOperation.setTemplate(iTemplateMode))
71     IFOKDO(err, oOperation.setImportID(QLatin1String("")))
72     IFOKDO(err, oOperation.bookmark(false))
73     IFOKDO(err, oOperation.setNumber(QLatin1String("")))
74     IFOKDO(err, oOperation.setGroupOperation(oOperation))
75     IFOKDO(err, oOperation.setAttribute(QStringLiteral("d_createdate"), SKGServices::dateToSqlString(QDateTime::currentDateTime())))
76     IFOKDO(err, oOperation.save(false, false))
77 
78     // Duplicate subop
79     IFOK(err) {
80         SKGListSKGObjectBase subops;
81         err = getSubOperations(subops);
82         int nbsupops = subops.count();
83         for (int i = 0; !err && i < nbsupops; ++i) {
84             SKGSubOperationObject subop(subops.at(i));
85             err = subop.resetID();
86             IFOKDO(err, subop.setParentOperation(oOperation))
87             IFOKDO(err, subop.setDate(subop.getDate().addDays(previousDate.daysTo(iDate))))
88             IFOKDO(err, subop.save(false))
89         }
90     }
91 
92     // Duplicate grouped operation to support recurrent transfers
93     IFOK(err) {
94         SKGListSKGObjectBase goupops;
95         err = getGroupedOperations(goupops);
96         int nbgoupops = goupops.count();
97         for (int i = 0; !err && i < nbgoupops; ++i) {
98             SKGOperationObject groupop(goupops.at(i));
99             if (groupop != *this) {
100                 // Create the duplicated operation
101                 SKGOperationObject newgroupop = groupop;
102                 err = newgroupop.resetID();
103                 IFOKDO(err, newgroupop.setDate(iDate))
104                 IFOKDO(err, newgroupop.setStatus(SKGOperationObject::NONE))
105                 IFOKDO(err, newgroupop.setImported(false))
106                 IFOKDO(err, newgroupop.setTemplate(iTemplateMode))
107                 IFOKDO(err, newgroupop.setImportID(QLatin1String("")))
108                 IFOKDO(err, newgroupop.bookmark(false))
109                 IFOKDO(err, newgroupop.setNumber(QLatin1String("")))
110                 IFOKDO(err, newgroupop.setGroupOperation(newgroupop))
111                 IFOKDO(err, newgroupop.setGroupOperation(oOperation))
112                 IFOKDO(err, newgroupop.save(false))
113 
114                 // Duplicate subop
115                 IFOK(err) {
116                     SKGListSKGObjectBase subops;
117                     err = groupop.getSubOperations(subops);
118                     int nbsupops = subops.count();
119                     for (int j = 0; !err && j < nbsupops; ++j) {
120                         SKGSubOperationObject subop(subops.at(j));
121                         err = subop.resetID();
122                         IFOKDO(err, subop.setParentOperation(newgroupop))
123                         IFOKDO(err, subop.setDate(subop.getDate().addDays(previousDate.daysTo(iDate))))
124                         IFOKDO(err, subop.save(false))
125                     }
126                 }
127             }
128         }
129     }
130 
131     IFOKDO(err, oOperation.load())
132     return err;
133 }
134 
135 
getParentAccount(SKGAccountObject & oAccount) const136 SKGError SKGOperationObject::getParentAccount(SKGAccountObject& oAccount) const
137 {
138     SKGObjectBase objTmp;
139     SKGError err = getDocument()->getObject(QStringLiteral("v_account"), "id=" % getAttribute(QStringLiteral("rd_account_id")), objTmp);
140     oAccount = objTmp;
141     return err;
142 }
143 
setParentAccount(const SKGAccountObject & iAccount,bool iForce)144 SKGError SKGOperationObject::setParentAccount(const SKGAccountObject& iAccount, bool iForce)
145 {
146     SKGError err;
147     QString currentAccount = getAttribute(QStringLiteral("rd_account_id"));
148     QString newAccount = SKGServices::intToString(iAccount.getID());
149     if (newAccount == QStringLiteral("0")) {
150         err = SKGError(ERR_FAIL, i18nc("Error message",  "%1 failed because linked object is not yet saved in the database.", QStringLiteral("SKGOperationObject::setParentAccount")));
151     } else {
152         if (newAccount != currentAccount) {
153             if (iAccount.isClosed() && !iForce) {
154                 err = SKGError(ERR_FAIL, i18nc("Error message",  "Impossible to add an operation in a closed account"));
155             } else {
156                 err = setAttribute(QStringLiteral("rd_account_id"), newAccount);
157             }
158         }
159     }
160     return err;
161 }
162 
setMode(const QString & iMode)163 SKGError SKGOperationObject::setMode(const QString& iMode)
164 {
165     return setAttribute(QStringLiteral("t_mode"), iMode);
166 }
167 
getMode() const168 QString SKGOperationObject::getMode() const
169 {
170     return getAttribute(QStringLiteral("t_mode"));
171 }
172 
setPayee(const SKGPayeeObject & iPayee)173 SKGError SKGOperationObject::setPayee(const SKGPayeeObject& iPayee)
174 {
175     return setAttribute(QStringLiteral("r_payee_id"), SKGServices::intToString(iPayee.getID()));
176 }
177 
getPayee(SKGPayeeObject & oPayee) const178 SKGError SKGOperationObject::getPayee(SKGPayeeObject& oPayee) const
179 {
180     SKGError err = getDocument()->getObject(QStringLiteral("v_payee"), "id=" % SKGServices::intToString(SKGServices::stringToInt(getAttribute(QStringLiteral("r_payee_id")))), oPayee);
181     return err;
182 }
183 
setComment(const QString & iComment)184 SKGError SKGOperationObject::setComment(const QString& iComment)
185 {
186     return setAttribute(QStringLiteral("t_comment"), iComment);
187 }
188 
getComment() const189 QString SKGOperationObject::getComment() const
190 {
191     return getAttribute(QStringLiteral("t_comment"));
192 }
193 
setNumber(const QString & iNumber)194 SKGError SKGOperationObject::setNumber(const QString& iNumber)
195 {
196     return setAttribute(QStringLiteral("t_number"), iNumber);
197 }
198 
getNumber() const199 QString SKGOperationObject::getNumber() const
200 {
201     return getAttribute(QStringLiteral("t_number"));
202 }
203 
getStatus() const204 SKGOperationObject::OperationStatus SKGOperationObject::getStatus() const
205 {
206     QString t_status = getAttribute(QStringLiteral("t_status"));
207     if (t_status == QStringLiteral("Y")) {
208         return SKGOperationObject::CHECKED;
209     }
210     if (t_status == QStringLiteral("P")) {
211         return SKGOperationObject::POINTED;
212     }
213     return SKGOperationObject::NONE;
214 }
215 
setStatus(SKGOperationObject::OperationStatus iStatus)216 SKGError SKGOperationObject::setStatus(SKGOperationObject::OperationStatus iStatus)
217 {
218     return setAttribute(QStringLiteral("t_status"), (iStatus == SKGOperationObject::CHECKED ? QStringLiteral("Y") : (iStatus == SKGOperationObject::POINTED ? QStringLiteral("P") : QStringLiteral("N"))));
219 }
220 
setDate(QDate iDate,bool iRefreshSubOperations)221 SKGError SKGOperationObject::setDate(QDate iDate, bool iRefreshSubOperations)
222 {
223     SKGError err;
224     // Compute delta of the change of date
225     QDate previousDate = getDate();
226     if (iRefreshSubOperations) {
227         // Apply the delta on sub operations
228         SKGObjectBase::SKGListSKGObjectBase listSubOperations;
229         getSubOperations(listSubOperations);  // Error is not manage to avoid error in case of first creation
230         int nbSubOperations = listSubOperations.count();
231         for (int i = 0; !err && i < nbSubOperations; ++i) {
232             SKGSubOperationObject sop(listSubOperations.at(i));
233             QDate previousSubDate = sop.getDate();
234             if (previousSubDate.isValid()) {
235                 if (previousDate.isValid()) {
236                     int delta = previousDate.daysTo(iDate);
237                     err = sop.setDate(previousSubDate.addDays(delta));
238                     IFOKDO(err, sop.save(true, false))
239                 }
240             } else {
241                 err = sop.setDate(iDate);
242                 IFOKDO(err, sop.save(true, false))
243             }
244         }
245     }
246     IFOKDO(err, setAttribute(QStringLiteral("d_date"), SKGServices::dateToSqlString(iDate)))
247     return err;
248 }
249 
getDate() const250 QDate SKGOperationObject::getDate() const
251 {
252     return SKGServices::stringToTime(getAttribute(QStringLiteral("d_date"))).date();
253 }
254 
getUnit(SKGUnitObject & oUnit) const255 SKGError SKGOperationObject::getUnit(SKGUnitObject& oUnit) const
256 {
257     SKGError err = (getDocument() == nullptr ? SKGError(ERR_POINTER, i18nc("Error message", "Operation impossible because the document is missing")) : getDocument()->getObject(QStringLiteral("v_unit"), "id=" % getAttribute(QStringLiteral("rc_unit_id")), oUnit));
258     // SKGError err = getDocument()->getObject(QStringLiteral("v_unit"), "id=" % getAttribute(QStringLiteral("rc_unit_id")), oUnit);
259     return err;
260 }
261 
setUnit(const SKGUnitObject & iUnit)262 SKGError SKGOperationObject::setUnit(const SKGUnitObject& iUnit)
263 {
264     return setAttribute(QStringLiteral("rc_unit_id"), SKGServices::intToString(iUnit.getID()));
265 }
266 
isInGroup() const267 bool SKGOperationObject::isInGroup() const
268 {
269     return (getAttribute(QStringLiteral("i_group_id")) != QStringLiteral("0"));
270 }
271 
isTransfer(SKGOperationObject & oOperation) const272 bool SKGOperationObject::isTransfer(SKGOperationObject& oOperation) const
273 {
274     SKGTRACEINFUNC(10)
275     SKGObjectBase::SKGListSKGObjectBase ops;
276     getGroupedOperations(ops);
277     if (ops.count() == 2) {
278         oOperation = (*this == SKGOperationObject(ops.at(0)) ? ops.at(1) : ops.at(0));
279     }
280     return (getAttribute(QStringLiteral("t_TRANSFER")) == QStringLiteral("Y"));
281 }
282 
getGroupedOperations(SKGListSKGObjectBase & oGroupedOperations) const283 SKGError SKGOperationObject::getGroupedOperations(SKGListSKGObjectBase& oGroupedOperations) const
284 {
285     SKGError err;
286     QString gpId1 = getAttribute(QStringLiteral("i_group_id"));
287     if (gpId1 == QStringLiteral("0") || gpId1.isEmpty()) {
288         oGroupedOperations.clear();
289     } else {
290         err = getDocument()->getObjects(QStringLiteral("v_operation"), "i_group_id=" % gpId1, oGroupedOperations);
291     }
292     return err;
293 }
294 
getGroupOperation(SKGOperationObject & oOperation) const295 SKGError SKGOperationObject::getGroupOperation(SKGOperationObject& oOperation) const
296 {
297     SKGError err = getDocument()->getObject(QStringLiteral("v_operation"), "id=" % getAttribute(QStringLiteral("i_group_id")), oOperation);
298     return err;
299 }
300 
setGroupOperation(const SKGOperationObject & iOperation)301 SKGError SKGOperationObject::setGroupOperation(const SKGOperationObject& iOperation)
302 {
303     SKGError err;
304     SKGTRACEINFUNCRC(20, err)
305 
306     // Is it a remove group ?
307     if (iOperation == *this) {
308         // Yes
309         err = setAttribute(QStringLiteral("i_group_id"), QStringLiteral("0"));
310     } else {
311         // Get previous groups
312         QString group1 = getAttribute(QStringLiteral("i_group_id"));
313         QString group2 = iOperation.getAttribute(QStringLiteral("i_group_id"));
314 
315         // Create a new group
316         SKGStringListList result;
317         err = getDocument()->executeSelectSqliteOrder(QStringLiteral("SELECT max(i_group_id) from operation"), result);
318         IFOK(err) {
319             // Compute new group id
320             QString newIdGroup('1');
321             if (result.count() == 2) {
322                 newIdGroup = SKGServices::intToString(SKGServices::stringToInt(result.at(1).at(0)) + 1);
323             }
324 
325             // Set group id
326             SKGOperationObject op1 = SKGOperationObject(iOperation.getDocument(), iOperation.getID());
327             err = op1.setAttribute(QStringLiteral("i_group_id"), newIdGroup);
328             IFOKDO(err, op1.save(true, false))
329 
330             IFOKDO(err, setAttribute(QStringLiteral("i_group_id"), newIdGroup))
331 
332             // Update all objects of group2
333             if (!err && !group1.isEmpty() && group1 != QStringLiteral("0")) {
334                 err = getDocument()->executeSqliteOrder("UPDATE operation SET i_group_id=" % newIdGroup % " WHERE i_group_id=" % group1);
335             }
336 
337             // Update all objects of group2
338             if (!err && !group2.isEmpty() && group2 != QStringLiteral("0")) {
339                 err = getDocument()->executeSqliteOrder("UPDATE operation SET i_group_id=" % newIdGroup % " WHERE i_group_id=" % group2);
340             }
341         }
342     }
343 
344     return err;
345 }
346 
bookmark(bool iBookmark)347 SKGError SKGOperationObject::bookmark(bool iBookmark)
348 {
349     return setAttribute(QStringLiteral("t_bookmarked"), iBookmark ? QStringLiteral("Y") : QStringLiteral("N"));
350 }
351 
isBookmarked() const352 bool SKGOperationObject::isBookmarked() const
353 {
354     return (getAttribute(QStringLiteral("t_bookmarked")) == QStringLiteral("Y"));
355 }
356 
setImported(bool iImported)357 SKGError SKGOperationObject::setImported(bool iImported)
358 {
359     return setAttribute(QStringLiteral("t_imported"), iImported ? QStringLiteral("Y") : QStringLiteral("N"));
360 }
361 
isImported() const362 bool SKGOperationObject::isImported() const
363 {
364     return (getAttribute(QStringLiteral("t_imported")) != QStringLiteral("N"));
365 }
366 
setImportID(const QString & iImportID)367 SKGError SKGOperationObject::setImportID(const QString& iImportID)
368 {
369     SKGError err = setAttribute(QStringLiteral("t_import_id"), iImportID);
370     if (!err && !iImportID.isEmpty()) {
371         err = setAttribute(QStringLiteral("t_imported"), QStringLiteral("T"));
372     }
373     return err;
374 }
375 
getImportID() const376 QString SKGOperationObject::getImportID() const
377 {
378     return getAttribute(QStringLiteral("t_import_id"));
379 }
380 
setTemplate(bool iTemplate)381 SKGError SKGOperationObject::setTemplate(bool iTemplate)
382 {
383     return setAttribute(QStringLiteral("t_template"), iTemplate ? QStringLiteral("Y") : QStringLiteral("N"));
384 }
385 
isTemplate() const386 bool SKGOperationObject::isTemplate() const
387 {
388     return (getAttribute(QStringLiteral("t_template")) != QStringLiteral("N"));
389 }
390 
getNbSubOperations() const391 int SKGOperationObject::getNbSubOperations() const
392 {
393     return SKGServices::stringToInt(getAttribute(QStringLiteral("i_NBSUBOPERATIONS")));
394 }
395 
addSubOperation(SKGSubOperationObject & oSubOperation)396 SKGError SKGOperationObject::addSubOperation(SKGSubOperationObject& oSubOperation)
397 {
398     SKGError err;
399     if (getID() == 0) {
400         err = SKGError(ERR_FAIL, i18nc("Error message",  "%1 failed because linked object is not yet saved in the database.", QStringLiteral("SKGOperationObject::addSubOperation")));
401     } else {
402         oSubOperation = SKGSubOperationObject(getDocument());
403         err = oSubOperation.setParentOperation(*this);
404         IFOKDO(err, oSubOperation.setDate(getDate()))
405     }
406     return err;
407 }
408 
getSubOperations(SKGListSKGObjectBase & oSubOperations) const409 SKGError SKGOperationObject::getSubOperations(SKGListSKGObjectBase& oSubOperations) const
410 {
411     SKGError err;
412     if (getID() == 0) {
413         err = SKGError(ERR_FAIL, i18nc("Error message",  "%1 failed because linked object is not yet saved in the database.", QStringLiteral("SKGOperationObject::getSubOperations")));
414     } else {
415         err = getDocument()->getObjects(QStringLiteral("v_suboperation"),
416                                         "rd_operation_id=" % SKGServices::intToString(getID()) % " ORDER BY i_order", oSubOperations);
417     }
418     return err;
419 }
420 
getCurrentAmount() const421 double SKGOperationObject::getCurrentAmount() const
422 {
423     return SKGServices::stringToDouble(getAttribute(QStringLiteral("f_CURRENTAMOUNT")));
424 }
425 
getBalance() const426 double SKGOperationObject::getBalance() const
427 {
428     double output = 0.0;
429     SKGStringListList result;
430     SKGError err = getDocument()->executeSelectSqliteOrder("SELECT TOTAL(f_CURRENTAMOUNT) FROM v_operation WHERE t_template='N' AND "
431                    "rd_account_id=" % getAttribute(QStringLiteral("rd_account_id")) % " AND (d_date<'" % getAttribute(QStringLiteral("d_date")) % "' OR "
432                    "(d_date='" % getAttribute(QStringLiteral("d_date")) % "' AND id<=" % SKGServices::intToString(getID()) % "))", result);
433     IFOK(err) {
434         output = SKGServices::stringToDouble(result.at(1).at(0));
435     }
436 
437     return output;
438 }
439 
getAmount(QDate iDate) const440 double SKGOperationObject::getAmount(QDate iDate) const
441 {
442     // Get quantity
443     double quantity = SKGServices::stringToDouble(getAttribute(QStringLiteral("f_QUANTITY")));
444 
445     // Is the unit value already in cache ?
446     double coef = 1;
447     QString val = getDocument()->getCachedValue("unitvalue-" % getAttribute(QStringLiteral("rc_unit_id")));
448     if (!val.isEmpty()) {
449         // Yes
450         coef = SKGServices::stringToDouble(val);
451     } else {
452         // No
453         SKGUnitObject unit;
454         if (getUnit(unit).isSucceeded()) {
455             coef = unit.getAmount(iDate);
456         }
457     }
458 
459     return coef * quantity;
460 }
461 
addRecurrentOperation(SKGRecurrentOperationObject & oRecurrentOperation) const462 SKGError SKGOperationObject::addRecurrentOperation(SKGRecurrentOperationObject& oRecurrentOperation) const
463 {
464     SKGError err;
465     if (getID() == 0) {
466         err = SKGError(ERR_FAIL, i18nc("Error message",  "%1 failed because linked object is not yet saved in the database.", QStringLiteral("SKGOperationObject::addRecurrentOperation")));
467     } else {
468         oRecurrentOperation = SKGRecurrentOperationObject(getDocument());
469         err = oRecurrentOperation.setParentOperation(*this);
470         IFOK(err) oRecurrentOperation.setDate(getDate());
471     }
472     return err;
473 }
474 
getRecurrentOperations(SKGListSKGObjectBase & oRecurrentOperation) const475 SKGError SKGOperationObject::getRecurrentOperations(SKGListSKGObjectBase& oRecurrentOperation) const
476 {
477     SKGError err;
478     if (getID() == 0) {
479         err = SKGError(ERR_FAIL, i18nc("Error message",  "%1 failed because linked object is not yet saved in the database.", QStringLiteral("SKGOperationObject::getRecurrentOperation")));
480     } else {
481         err = getDocument()->getObjects(QStringLiteral("v_recurrentoperation"),
482                                         "rd_operation_id=" % SKGServices::intToString(getID()), oRecurrentOperation);
483     }
484     return err;
485 }
486 
mergeAttribute(const SKGOperationObject & iDeletedOne,SKGOperationObject::AmountAlignmentMode iMode,bool iSendMessage)487 SKGError SKGOperationObject::mergeAttribute(const SKGOperationObject& iDeletedOne, SKGOperationObject::AmountAlignmentMode iMode, bool iSendMessage)
488 {
489     // Merge operation
490     SKGError err = setDate(iDeletedOne.getDate());
491     IFOKDO(err, setImportID(iDeletedOne.getImportID()))
492     IFOKDO(err, setAttribute(QStringLiteral("t_imported"), iDeletedOne.getAttribute(QStringLiteral("t_imported"))))
493     if (!err && getComment().isEmpty()) {
494         err = setComment(iDeletedOne.getComment());
495     }
496     SKGPayeeObject payee;
497     getPayee(payee);
498     IFOKDO(err, setPayee(payee))
499     if (!err && getMode().isEmpty()) {
500         err = setMode(iDeletedOne.getMode());
501     }
502     if (!err && !isBookmarked()) {
503         err = bookmark(iDeletedOne.isBookmarked());
504     }
505     if (!err && getNumber().isEmpty()) {
506         err = setNumber(iDeletedOne.getNumber());
507     }
508     IFOKDO(err, save())
509 
510     // Merge suboperations
511     double currentAmount = getCurrentAmount();
512     double targettAmount = iDeletedOne.getCurrentAmount();
513     if (qAbs(currentAmount - targettAmount) > 0.0001) {
514         SKGObjectBase::SKGListSKGObjectBase subOps1;
515         IFOKDO(err, getSubOperations(subOps1))
516 
517         SKGObjectBase::SKGListSKGObjectBase subOps2;
518         IFOKDO(err, iDeletedOne.getSubOperations(subOps2))
519 
520         // Align amounts
521         SKGOperationObject::AmountAlignmentMode mode = iMode;
522         if (mode == DEFAULT) {
523             if (subOps2.count() == 1 && subOps1.count() == 1) {
524                 mode = PROPORTIONAL;
525             } else if (subOps2.count() >= 1 && subOps1.count() >= 1) {
526                 mode = ADDSUBOPERATION;
527             }
528         }
529 
530         if (mode == SKGOperationObject::ADDSUBOPERATION) {
531             // Add sub operation to align amount
532             SKGSubOperationObject so1;
533             IFOKDO(err, addSubOperation(so1))
534             IFOKDO(err, so1.setQuantity(targettAmount - currentAmount))
535             IFOKDO(err, so1.save())
536         } else {
537             // Keep ratio
538             for (const auto& sopbase : qAsConst(subOps1)) {
539                 SKGSubOperationObject sop(sopbase);
540                 IFOKDO(err, sop.setQuantity(targettAmount * sop.getQuantity() / currentAmount))
541                 IFOKDO(err, sop.save())
542             }
543         }
544         IFOKDO(err, load())
545         if (iSendMessage) {
546             IFOK(err) getDocument()->sendMessage(i18nc("An information message",  "Amount has been changed to be aligned with the imported operation"), SKGDocument::Positive);
547         }
548     }
549 
550     // transfers properties
551     IFOKDO(err, getDocument()->executeSqliteOrder(QStringLiteral("UPDATE parameters SET t_uuid_parent='") % getUniqueID() % QStringLiteral("' WHERE t_uuid_parent='") % iDeletedOne.getUniqueID() % QStringLiteral("'")))
552 
553     // Delete useless operation
554     IFOKDO(err, iDeletedOne.remove(false, true))
555     return err;
556 }
557 
mergeSuboperations(const SKGOperationObject & iDeletedOne)558 SKGError SKGOperationObject::mergeSuboperations(const SKGOperationObject& iDeletedOne)
559 {
560     SKGError err;
561     SKGObjectBase::SKGListSKGObjectBase subops;
562     err = iDeletedOne.getSubOperations(subops);
563     int nb = subops.count();
564     for (int i = 0; !err && i < nb; ++i) {
565         SKGSubOperationObject subop(subops.at(i));
566         err = subop.setParentOperation(*this);
567         IFOKDO(err, subop.save())
568     }
569     IFOKDO(err, iDeletedOne.remove(false))
570     return err;
571 }
572 
573 
574 
575