File indexing completed on 2024-04-28 16:30:09
0001 /*************************************************************************** 0002 * SPDX-FileCopyrightText: 2022 S. MANKOWSKI stephane@mankowski.fr 0003 * SPDX-FileCopyrightText: 2022 G. DE BURE support@mankowski.fr 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 ***************************************************************************/ 0006 /** @file 0007 * This file implements classes SKGCategoryObject. 0008 * 0009 * @author Stephane MANKOWSKI / Guillaume DE BURE 0010 */ 0011 #include "skgcategoryobject.h" 0012 0013 #include <klocalizedstring.h> 0014 0015 #include "skgdocumentbank.h" 0016 #include "skgsuboperationobject.h" 0017 #include "skgtraces.h" 0018 0019 SKGCategoryObject::SKGCategoryObject() : SKGCategoryObject(nullptr) 0020 {} 0021 0022 SKGCategoryObject::SKGCategoryObject(SKGDocument* iDocument, int iID) : SKGNamedObject(iDocument, QStringLiteral("v_category"), iID) 0023 {} 0024 0025 SKGCategoryObject::~SKGCategoryObject() 0026 = default; 0027 0028 SKGCategoryObject::SKGCategoryObject(const SKGCategoryObject& iObject) = default; 0029 0030 SKGCategoryObject::SKGCategoryObject(const SKGObjectBase& iObject) 0031 0032 { 0033 if (iObject.getRealTable() == QStringLiteral("category")) { 0034 copyFrom(iObject); 0035 } else { 0036 *this = SKGNamedObject(iObject.getDocument(), QStringLiteral("v_category"), iObject.getID()); 0037 } 0038 } 0039 0040 SKGCategoryObject& SKGCategoryObject::operator= (const SKGObjectBase& iObject) 0041 { 0042 copyFrom(iObject); 0043 return *this; 0044 } 0045 0046 SKGCategoryObject& SKGCategoryObject::operator= (const SKGCategoryObject& iObject) 0047 { 0048 copyFrom(iObject); 0049 return *this; 0050 } 0051 0052 SKGError SKGCategoryObject::setName(const QString& iName) 0053 { 0054 SKGError err; 0055 if (iName.contains(OBJECTSEPARATOR)) { 0056 err = SKGError(ERR_FAIL, i18nc("Error message", "Invalid name '%1' because of the name cannot contain '%2'", iName, QString(OBJECTSEPARATOR))); 0057 } else { 0058 err = SKGNamedObject::setName(iName); 0059 } 0060 return err; 0061 } 0062 0063 QString SKGCategoryObject::getWhereclauseId() const 0064 { 0065 // Could we use the id 0066 QString output = SKGObjectBase::getWhereclauseId(); // clazy:exclude=skipped-base-method 0067 if (output.isEmpty()) { 0068 if (!(getAttribute(QStringLiteral("t_name")).isEmpty())) { 0069 output = "t_name='" % SKGServices::stringToSqlString(getAttribute(QStringLiteral("t_name"))) % '\''; 0070 } 0071 QString rd_category_id = getAttribute(QStringLiteral("rd_category_id")); 0072 if (!output.isEmpty()) { 0073 output += QStringLiteral(" AND "); 0074 } 0075 if (rd_category_id.isEmpty()) { 0076 output += QStringLiteral("(rd_category_id=0 OR rd_category_id IS NULL OR rd_category_id='')"); 0077 } else { 0078 output += "rd_category_id=" % rd_category_id; 0079 } 0080 } 0081 return output; 0082 } 0083 0084 QString SKGCategoryObject::getFullName() const 0085 { 0086 return getAttribute(QStringLiteral("t_fullname")); 0087 } 0088 0089 SKGError SKGCategoryObject::createPathCategory(SKGDocumentBank* iDocument, 0090 const QString& iFullPath, 0091 SKGCategoryObject& oCategory, 0092 bool iSendPopupMessageOnCreation, 0093 bool iRenameIfAlreadyExist) 0094 { 0095 SKGError err; 0096 SKGTRACEINFUNCRC(10, err) 0097 0098 // Check if category is already existing 0099 if (iFullPath.isEmpty()) { 0100 oCategory = SKGCategoryObject(nullptr, 0); 0101 } else if (iDocument != nullptr) { 0102 if (!iRenameIfAlreadyExist) { 0103 iDocument->getObject(QStringLiteral("v_category"), "t_fullname='" % SKGServices::stringToSqlString(iFullPath) % '\'', oCategory); 0104 } else { 0105 oCategory.resetID(); 0106 } 0107 if (oCategory.getID() == 0) { 0108 // No, we have to create it 0109 // Search category separator 0110 int posSeparator = iFullPath.lastIndexOf(OBJECTSEPARATOR); 0111 if (posSeparator == -1) { 0112 oCategory = SKGCategoryObject(iDocument); 0113 err = oCategory.setName(iFullPath); 0114 0115 // Check if already existing 0116 if (!err && iRenameIfAlreadyExist) { 0117 int index = 1; 0118 while (!err && oCategory.exist()) { 0119 index++; 0120 err = oCategory.setName(iFullPath % " (" % SKGServices::intToString(index) % ')'); 0121 } 0122 } 0123 0124 IFOKDO(err, oCategory.save()) 0125 } else { 0126 // Get first and second parts of the branch 0127 QString first = iFullPath.mid(0, posSeparator); 0128 QString second = iFullPath.mid(posSeparator + QString(OBJECTSEPARATOR).length(), iFullPath.length() - posSeparator - QString(OBJECTSEPARATOR).length()); 0129 0130 // Get first category 0131 SKGCategoryObject FirstCategory; 0132 err = SKGCategoryObject::createPathCategory(iDocument, first, FirstCategory); 0133 0134 IFOK(err) { 0135 // Get second category 0136 err = FirstCategory.addCategory(oCategory); 0137 0138 // Add second under first 0139 IFOKDO(err, oCategory.setName(second)) 0140 0141 // Check if already existing 0142 if (!err && iRenameIfAlreadyExist) { 0143 int index = 2; 0144 while (!err && oCategory.exist()) { 0145 err = oCategory.setName(second % " (" % SKGServices::intToString(index) % ')'); 0146 ++index; 0147 } 0148 } 0149 0150 // save 0151 IFOKDO(err, oCategory.save()) 0152 } 0153 } 0154 0155 if (!err && iSendPopupMessageOnCreation) { 0156 iDocument->sendMessage(i18nc("Information message", "The category '%1' has been created", iFullPath), SKGDocument::Positive); 0157 } 0158 } 0159 } 0160 0161 return err; 0162 } 0163 0164 SKGError SKGCategoryObject::addCategory(SKGCategoryObject& oCategory) 0165 { 0166 SKGError err; 0167 SKGTRACEINFUNCRC(10, err) 0168 if (getID() == 0) { 0169 err = SKGError(ERR_FAIL, i18nc("Error message", "%1 failed because linked object is not yet saved in the database.", QStringLiteral("SKGCategoryObject::addCategory"))); 0170 } else { 0171 oCategory = SKGCategoryObject(qobject_cast<SKGDocumentBank*>(getDocument())); 0172 err = oCategory.setAttribute(QStringLiteral("rd_category_id"), SKGServices::intToString(getID())); 0173 } 0174 return err; 0175 } 0176 0177 SKGError SKGCategoryObject::setParentCategory(const SKGCategoryObject& iCategory) 0178 { 0179 SKGError err; 0180 SKGTRACEINFUNCRC(10, err) 0181 if (iCategory.getID() == 0) { 0182 err = SKGError(ERR_FAIL, i18nc("Error message", "%1 failed because linked object is not yet saved in the database.", QStringLiteral("SKGCategoryObject::setParentCategory"))); 0183 } else { 0184 // Check if it is a loop 0185 SKGCategoryObject current = iCategory; 0186 do { 0187 if (current == *this) { 0188 err = SKGError(ERR_FAIL, i18nc("Error message", "You cannot create a loop.")); 0189 } else { 0190 SKGCategoryObject parent2; 0191 current.getParentCategory(parent2); 0192 current = parent2; 0193 } 0194 } while (!err && current.getID() != 0); 0195 0196 IFOKDO(err, setAttribute(QStringLiteral("rd_category_id"), SKGServices::intToString(iCategory.getID()))) 0197 } 0198 return err; 0199 } 0200 0201 SKGError SKGCategoryObject::removeParentCategory() 0202 { 0203 return setAttribute(QStringLiteral("rd_category_id"), QStringLiteral("0")); 0204 } 0205 0206 SKGError SKGCategoryObject::getParentCategory(SKGCategoryObject& oCategory) const 0207 { 0208 SKGError err; 0209 QString parent_id = getAttribute(QStringLiteral("rd_category_id")); 0210 if (!parent_id.isEmpty() && parent_id != QStringLiteral("0")) { 0211 err = getDocument()->getObject(QStringLiteral("v_category"), "id=" % parent_id, oCategory); 0212 } 0213 return err; 0214 } 0215 0216 SKGError SKGCategoryObject::getRootCategory(SKGCategoryObject& oCategory) const 0217 { 0218 SKGError err; 0219 SKGCategoryObject parent2; 0220 err = getParentCategory(parent2); 0221 IFOK(err) { 0222 if (!parent2.exist()) { 0223 // No parent 0224 oCategory = *this; 0225 } else { 0226 // Parent exist 0227 err = parent2.getRootCategory(oCategory); 0228 } 0229 } 0230 return err; 0231 } 0232 0233 0234 SKGError SKGCategoryObject::getCategories(SKGListSKGObjectBase& oCategoryList) const 0235 { 0236 return getDocument()->getObjects(QStringLiteral("v_category"), 0237 "rd_category_id=" % SKGServices::intToString(getID()), 0238 oCategoryList); 0239 } 0240 0241 double SKGCategoryObject::getCurrentAmount() const 0242 { 0243 QString v = getAttribute(QStringLiteral("f_SUMCURRENTAMOUNT")); 0244 if (v.isEmpty()) { 0245 SKGNamedObject cat(getDocument(), QStringLiteral("v_category_display"), getID()); 0246 v = cat.getAttribute(QStringLiteral("f_SUMCURRENTAMOUNT")); 0247 } 0248 return SKGServices::stringToDouble(v); 0249 } 0250 0251 SKGError SKGCategoryObject::getSubOperations(SKGListSKGObjectBase& oSubOperations) const 0252 { 0253 SKGError err = getDocument()->getObjects(QStringLiteral("v_suboperation"), 0254 "r_category_id=" % SKGServices::intToString(getID()), 0255 oSubOperations); 0256 return err; 0257 } 0258 0259 SKGError SKGCategoryObject::bookmark(bool iBookmark) 0260 { 0261 return setAttribute(QStringLiteral("t_bookmarked"), iBookmark ? QStringLiteral("Y") : QStringLiteral("N")); 0262 } 0263 0264 bool SKGCategoryObject::isBookmarked() const 0265 { 0266 return (getAttribute(QStringLiteral("t_bookmarked")) == QStringLiteral("Y")); 0267 } 0268 0269 SKGError SKGCategoryObject::setClosed(bool iClosed) 0270 { 0271 return setAttribute(QStringLiteral("t_close"), iClosed ? QStringLiteral("Y") : QStringLiteral("N")); 0272 } 0273 0274 bool SKGCategoryObject::isClosed() const 0275 { 0276 return (getAttribute(QStringLiteral("t_close")) == QStringLiteral("Y")); 0277 } 0278 0279 SKGError SKGCategoryObject::merge(const SKGCategoryObject& iCategory) 0280 { 0281 SKGError err; 0282 0283 SKGObjectBase::SKGListSKGObjectBase ops; 0284 IFOKDO(err, iCategory.getSubOperations(ops)) 0285 int nb = ops.count(); 0286 for (int i = 0; !err && i < nb; ++i) { 0287 SKGSubOperationObject op(ops.at(i)); 0288 err = op.setCategory(*this); 0289 IFOKDO(err, op.save(true, false)) 0290 } 0291 0292 SKGObjectBase::SKGListSKGObjectBase cats; 0293 IFOKDO(err, iCategory.getCategories(cats)) 0294 nb = cats.count(); 0295 for (int i = 0; !err && i < nb; ++i) { 0296 SKGCategoryObject cat(cats.at(i)); 0297 err = cat.setParentCategory(*this); 0298 IFOKDO(err, cat.save(true, false)) 0299 } 0300 0301 IFOKDO(err, iCategory.remove(false)) 0302 return err; 0303 } 0304 0305