1 /***************************************************************************
2                           floskeltemplate.cpp  -
3                              -------------------
4     begin                : Don Jan 1 2004
5     copyright            : (C) 2004 by Klaas Freitag
6     email                : freitag@kde.org
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include <QString>
19 #include <QObject>
20 #include <QDebug>
21 
22 #include "kraftdb.h"
23 #include "templatesaverbase.h"
24 #include "templatesaverdb.h"
25 #include "floskeltemplate.h"
26 #include "unitmanager.h"
27 #include "calcpart.h"
28 #include "materialcalcpart.h"
29 #include "fixcalcpart.h"
30 #include "timecalcpart.h"
31 #include "stockmaterial.h"
32 
33 
FloskelTemplate()34 FloskelTemplate::FloskelTemplate()
35     : CatalogTemplate(),
36       mTemplId(-1),
37       m_chapter(0),
38       mTimeAdd(true),
39       m_listViewItem(0),
40       m_saver(0)
41 {
42     m_calcType = Calculation;
43 }
44 
FloskelTemplate(int tID,const QString & text,int einheit,int chapter,int calcKind)45 FloskelTemplate::FloskelTemplate( int tID, const QString& text,
46                                   int einheit, int chapter, int calcKind )
47  : CatalogTemplate(),
48    mTemplId(tID),
49    m_chapter(chapter),
50    mTimeAdd(true),
51    m_preis(long(0)),
52    m_listViewItem(0),
53    m_saver(0)
54 {
55   if( calcKind == 1 ) {
56     setCalculationType( ManualPrice );
57   } else if( calcKind == 2 ) {
58     setCalculationType( Calculation );
59   } else if ( calcKind == 3 ) {
60     setCalculationType( AutoCalc );
61   }
62 
63   setText( text );
64   this->setUnitId(einheit);
65   setChapterId( dbID(chapter), false );
66 }
67 
FloskelTemplate(FloskelTemplate & templ)68 FloskelTemplate::FloskelTemplate( FloskelTemplate& templ )
69     : CatalogTemplate( templ ),
70       mTemplId( templ.mTemplId ),
71       m_preis( templ.m_preis ),
72       m_listViewItem(templ.m_listViewItem ),
73       m_saver( 0 )
74 {
75   deepCopyCalcParts( templ );
76   setModifyDate( templ.modifyDate() );
77   setEnterDate( templ.enterDate() );
78   setText( templ.getText() );
79   setUnitId(templ.unit().id());
80   // m_calcParts.setAutoDelete(true);
81 }
82 
operator =(FloskelTemplate & src)83 FloskelTemplate& FloskelTemplate::operator= ( FloskelTemplate& src )
84 {
85   if ( this == &src ) return *this;
86 
87   mText = src.mText;
88   setUnitId(src.unit().id());
89   mTemplId = src.mTemplId;
90   mChapterId = src.mChapterId;
91   m_preis = src.m_preis;
92   m_listViewItem = src.m_listViewItem;
93   m_saver = 0; // src.m_saver;
94 
95   deepCopyCalcParts( src );
96 
97   return *this;
98 }
99 
~FloskelTemplate()100 FloskelTemplate::~FloskelTemplate()
101 {
102   delete m_saver;
103 }
104 
deepCopyCalcParts(FloskelTemplate & templ)105 void FloskelTemplate::deepCopyCalcParts( FloskelTemplate& templ )
106 {
107   CalcPart *cp = 0;
108 
109   m_calcParts.clear();
110 
111   QListIterator<CalcPart*> i( templ.m_calcParts );
112   while( i.hasNext()) {
113     cp = i.next();
114     CalcPart *ncp = 0;
115 
116     if( cp->getType() == KALKPART_TIME ) {
117       ncp = new TimeCalcPart( *( static_cast<TimeCalcPart*>(cp) ) );
118     } else if( cp->getType() == KALKPART_FIX ) {
119       ncp = new FixCalcPart( *( static_cast<FixCalcPart*>(cp) ) );
120     } else if( cp->getType() == KALKPART_MATERIAL ) {
121       ncp = new MaterialCalcPart( *( static_cast<MaterialCalcPart*>(cp) ) );
122     } else {
123       // qDebug () << "ERROR: Unknown Calculation-Type!" << endl;
124     }
125     m_calcParts.append( ncp );
126   }
127 }
128 
setBenefit(double g)129 void FloskelTemplate::setBenefit( double g )
130 {
131     /* Every calc part has an value for benefit. Set the benefit value for
132        each calc part, later on each can have its own value
133      */
134     for( auto *cp: m_calcParts) {
135         cp->setProzentPlus(g);
136     }
137 }
138 
getBenefit()139 double FloskelTemplate::getBenefit( )
140 {
141     bool first = true;
142     double b = 0.0;
143 
144     for( auto *cp: m_calcParts) {
145         if( first ) {
146             b = cp->getProzentPlus();
147             first = false;
148         }
149         // all benefits are the same atm, thus this ASSERT.
150         Q_ASSERT( fabs(b - cp->getProzentPlus()) < std::numeric_limits<double>::epsilon());
151     }
152     return b;
153 }
154 
setTemplID(int newID)155 void FloskelTemplate::setTemplID( int newID )
156 {
157   mTemplId = newID;
158 }
159 
unitPrice()160 Geld FloskelTemplate::unitPrice()
161 {
162   return calcPreis();
163 }
164 
165 
calcPreis()166 Geld FloskelTemplate::calcPreis()
167 {
168   Geld g;
169 
170     if( calcKind() == ManualPrice ) {
171         g = m_preis;
172     } else {
173         g = m_calcParts.calcPrice();
174        double b = getBenefit();
175        g += g.percent(b);
176     }
177     return g;
178 }
179 
getCalcPartsList()180 CalcPartList FloskelTemplate::getCalcPartsList()
181 {
182     return getCalcPartsList(ALL_KALKPARTS);
183 }
184 
185 // Returns a calcpartlist where all calcparts have lost their connection
186 // to the database from the dbID POV. That's needed for the transition
187 // from template -> document calculations.
decoupledCalcPartsList()188 CalcPartList FloskelTemplate::decoupledCalcPartsList()
189 {
190   return m_calcParts.decoupledCalcPartsList();
191 }
192 
getCalcPartsList(const QString & calcPart)193 CalcPartList FloskelTemplate::getCalcPartsList( const QString& calcPart )
194 {
195   return m_calcParts.getCalcPartsList( calcPart );
196 }
197 
addCalcPart(CalcPart * cpart)198 void FloskelTemplate::addCalcPart( CalcPart* cpart )
199 {
200     m_calcParts.append(cpart);
201 }
202 
removeCalcPart(CalcPart * cpart)203 void FloskelTemplate::removeCalcPart( CalcPart *cpart )
204 {
205   if( cpart) {
206     cpart->setToDelete(true);
207     cpart->setDirty(true);
208 
209   }
210 }
211 
clearCalcParts()212 void FloskelTemplate::clearCalcParts()
213 {
214   for(int i=0; i<m_calcParts.count(); ++i)
215   {
216     delete m_calcParts[i];
217   }
218 
219   m_calcParts.clear();
220 }
221 
costsByCalcPart(const QString & part)222 Geld FloskelTemplate::costsByCalcPart( const QString& part )
223 {
224   return m_calcParts.costPerCalcPart( part );
225 }
226 
getSaver()227 TemplateSaverBase* FloskelTemplate::getSaver()
228 {
229   if( ! m_saver )
230   {
231     m_saver = new TemplateSaverDB();
232   }
233   return m_saver;
234 }
235 
save()236 bool FloskelTemplate::save()
237 {
238     TemplateSaverBase *saver = getSaver();
239     // qDebug () << "Saver is " << saver << endl;
240     if( saver ) {
241         return saver->saveTemplate( this );
242     } else {
243         // qDebug () << "ERR: No saver available!" << endl;
244         return false;
245     }
246 }
247 
saveChapterId()248 void FloskelTemplate::saveChapterId()
249 {
250   TemplateSaverBase *saver = getSaver();
251   if( saver ) {
252     saver->saveTemplateChapter( this );
253   }
254 }
255 
256 #if 0
257 QDomElement FloskelTemplate::toXML( QDomDocument& doc)
258 {
259     QDomElement templ = doc.createElement("template");
260 
261     templ.appendChild( createDomNode(doc, "unit", getUnit().einheitSingular()));
262     templ.appendChild( createDomNode(doc, "text", getText()));
263     templ.appendChild( createDomNode(doc, "id", QString::number(getTemplID())));
264     templ.appendChild( createDomNode(doc, "benefit", QString::number(getBenefit())));
265     templ.appendChild( createDomNode(doc, "timecount", hasTimeslice() ? "yes": "no" ));
266 
267     QDomElement calcParts = doc.createElement( "calcParts" );
268     templ.appendChild(calcParts);
269     fixPartsToXML(doc, calcParts);
270     timePartsToXML(doc, calcParts);
271     materialPartsToXML(doc, calcParts);
272 
273     /* Material Calculation Parts */
274     materialPartsToXML(doc);
275     CalcPartList tpList = getCalcPartsList(KALKPART_MATERIAL);
276     MaterialCalcPart *mc = 0;
277     mc = static_cast<MaterialCalcPart*>(tpList.first());
278     for( ; mc; mc = static_cast<MaterialCalcPart*>(tpList.next()) )
279     {
280         QDomElement calcPart = doc.createElement( "MaterialCalcpart" );
281         calcParts.appendChild(calcPart);
282         calcPart.appendChild(createDomNode(doc, "name", mc->getName()));
283         calcPart.appendChild(createDomNode(doc, "dbid", mc->getDbID().toString()));
284 
285         StockMaterialList materials = mc->getCalcMaterialList();
286         StockMaterialListIterator it( materials );
287 
288         StockMaterial *mat=0;
289         while ( (mat = it.current()) != 0 )
290         {
291           ++it;
292           QDomElement matElem = doc.createElement("Material");
293           matElem.appendChild(createDomNode(doc, "MatName", mat->getName()));
294           QString h;
295           h = h.setNum(mc->getCalcAmount(mat));
296           matElem.appendChild(createDomNode(doc, "Amount", h));
297           matElem.appendChild(createDomNode(doc, "PriceSum",   mc->getPriceForMaterial(mat).toString()));
298           matElem.appendChild(createDomNode(doc, "CostSum",   mc->getCostsForMaterial(mat).toString()));
299           matElem.appendChild(createDomNode(doc, "Price",   mat->salesPrice().toString()));
300           matElem.appendChild(createDomNode(doc, "Cost",   mat->purchPrice().toString()));
301           Einheit e = mat->getUnit();
302           h = e.einheitSingular();
303           matElem.appendChild(createDomNode(doc, "Unit", h));
304           calcPart.appendChild(matElem);
305         }
306     }
307     return templ;
308 }
309 
310 void FloskelTemplate::fixPartsToXML( QDomDocument& doc, QDomElement& calcParts )
311 {
312     CalcPartList tpList = getCalcPartsList(KALKPART_FIX);
313 
314     FixCalcPart *fc = 0;
315     fc = static_cast<FixCalcPart*>(tpList.first());
316     for( ; fc; fc = static_cast<FixCalcPart*>(tpList.next()) ) {
317         QDomElement calcPart = doc.createElement("FixCalcPart");
318         calcParts.appendChild(calcPart);
319         calcPart.appendChild(createDomNode(doc, "name", fc->getName()));
320         calcPart.appendChild(createDomNode(doc, "dbid", fc->getDbID().toString()));
321 
322         QString h;
323         h.setNum(fc->getMenge());
324         calcPart.appendChild(createDomNode(doc, "amount", h));
325 
326         Geld g = fc->unitPreis();
327         calcPart.appendChild(createDomNode(doc, "price", g.toString( mLocale )));
328     }
329 }
330 
331 void FloskelTemplate::timePartsToXML( QDomDocument& doc, QDomElement& calcParts )
332 {
333     CalcPartList tpList = getCalcPartsList(KALKPART_TIME);
334 
335     TimeCalcPart *tc = 0;
336     tc = static_cast<TimeCalcPart*>(tpList.first());
337     for( ; tc; tc = static_cast<TimeCalcPart*>(tpList.next()) ) {
338         QDomElement calcPart = doc.createElement("TimeCalcPart");
339         calcParts.appendChild(calcPart);
340         calcPart.appendChild(createDomNode(doc, "name", tc->getName()));
341         calcPart.appendChild(createDomNode(doc, "dbid", tc->getDbID().toString()));
342 
343         QString h;
344         h.setNum( tc->getMinuten());
345         calcPart.appendChild(createDomNode(doc, "minutes", h));
346         StdSatz ss = tc->getStundensatz();
347         calcPart.appendChild(createDomNode(doc, "stundensatz", ss.getName()));
348         calcPart.appendChild(createDomNode(doc, "globalHourSetup",
349                              tc->globalStdSetAllowed() ? "yes" : "no"));
350     }
351 }
352 
353 void FloskelTemplate::materialPartsToXML( QDomDocument& doc, QDomElement& calcParts )
354 {
355     /* Material Calculation Parts */
356     CalcPartList tpList = getCalcPartsList(KALKPART_MATERIAL);
357     MaterialCalcPart *mc = 0;
358     mc = static_cast<MaterialCalcPart*>(tpList.first());
359     for( ; mc; mc = static_cast<MaterialCalcPart*>(tpList.next()) )
360     {
361         QDomElement calcPart = doc.createElement( "MaterialCalcpart" );
362         calcParts.appendChild(calcPart);
363         calcPart.appendChild(createDomNode(doc, "name", mc->getName()));
364         calcPart.appendChild(createDomNode(doc, "dbid", mc->getDbID().toString()));
365 
366         StockMaterialList materials = mc->getCalcMaterialList();
367         StockMaterialListIterator it( materials );
368 
369         StockMaterial *mat=0;
370         while ( (mat = it.current()) != 0 )
371         {
372             ++it;
373             QDomElement matElem = doc.createElement("Material");
374             matElem.appendChild(createDomNode(doc, "MaterialName", mat->name()));
375             QString h;
376             h = h.setNum(mc->getCalcAmount(mat));
377             matElem.appendChild(createDomNode(doc, "Amount", h));
378             matElem.appendChild(createDomNode(doc, "Price",   mc->getCostsForMaterial(mat).toString()));
379             Einheit e = mat->getUnit();
380             h = e.einheitSingular();
381             matElem.appendChild(createDomNode(doc, "Unit", h));
382             calcPart.appendChild(matElem);
383         }
384     }
385 }
386 
387 QDomElement FloskelTemplate::createDomNode( QDomDocument doc,
388                                             const QString& name, const QString& value)
389 {
390   QDomElement elem = doc.createElement(name);
391   QDomText text = doc.createTextNode(value);
392   elem.appendChild(text);
393   return elem;
394 }
395 #endif
396 
397