GnuCashew ~ Web Application compatible with GnuCash sql data files.
GCW
Loading...
Searching...
No Matches
Dbo/Accounts/Accounts.cpp
Go to the documentation of this file.
1#line 2 "src/Dbo/Accounts/Accounts.cpp"
2
3#include "../../Glb/Core.h"
4#include "../../App.h"
5#include "Accounts.h"
6
7const char * GCW::Dbo::Accounts::s_tableName = "accounts";
8
9/*!
10** \code
11** ; type drcr name colAccount colDr colCr parentType
12** \endcode
13**
14** These are the account-types, debit/credit types, and register column labels for said accounts.
15**
16** \sa \ref GCW::Eng::AccountRegisterModel::refreshFromDisk() "refreshFromDisk()"
17**
18** \sa \ref account_type_labels "Account Type Labels"
19*/
20const std::vector< GCW::Dbo::Accounts::AccountDef_t > GCW::Dbo::Accounts::s_accountDefs =
21{// type drcr backendName colAccount colDr colCr parentType
22 { Type::INVALID , DrCr::NONE , "INVALID" , "account" , "fundsin" , "fundsout" , },
23 { Type::NONE , DrCr::NONE , "NONE" , "account" , "fundsin" , "fundsout" , },
24 { Type::ROOT , DrCr::NONE , "ROOT" , "account" , "debit" , "credit" , },
25 { Type::BANK , DrCr::DEBIT , "BANK" , "transfer" , "deposit" , "withdrawal" , Type::ASSET },
26 { Type::CASH , DrCr::DEBIT , "CASH" , "transfer" , "receive" , "spend" , Type::ASSET },
27 { Type::CREDIT , DrCr::CREDIT , "CREDIT" , "blank" , "payment" , "charge" , Type::LIABILITY },
28 { Type::ASSET , DrCr::DEBIT , "ASSET" , "transfer" , "increase" , "decrease" , Type::ASSET },
29 { Type::LIABILITY , DrCr::CREDIT , "LIABILITY" , "account" , "decrease" , "increase" , Type::LIABILITY },
30 { Type::STOCK , DrCr::DEBIT , "STOCK" , "account" , "buy" , "sell" , Type::ASSET },
31 { Type::MUTUAL , DrCr::DEBIT , "MUTUAL" , "account" , "buy" , "sell" , Type::ASSET },
32 { Type::CURRENCY , DrCr::DEBIT , "CURRENCY" , "account" , "buy" , "sell" , Type::ASSET },
33 { Type::INCOME , DrCr::CREDIT , "INCOME" , "account" , "charge" , "income" , Type::INCOME },
34 { Type::EXPENSE , DrCr::DEBIT , "EXPENSE" , "transfer" , "expense" , "rebate" , Type::EXPENSE },
35 { Type::EQUITY , DrCr::CREDIT , "EQUITY" , "transfer" , "decrease" , "increase" , Type::EQUITY },
36 { Type::RECEIVABLE , DrCr::DEBIT , "RECEIVABLE" , "transfer" , "invoice" , "payment" , Type::ASSET },
37 { Type::PAYABLE , DrCr::CREDIT , "PAYABLE" , "account" , "payment" , "bill" , Type::LIABILITY },
38 { Type::TRADING , DrCr::DEBIT , "TRADING" , "account" , "decrease" , "increase" , Type::ASSET },
39 { Type::CHECKING , DrCr::DEBIT , "CHECKING" , "account" , "debit" , "credit" , Type::ASSET },
40 { Type::SAVINGS , DrCr::DEBIT , "SAVINGS" , "account" , "debit" , "credit" , Type::ASSET },
41 { Type::MONEYMRKT , DrCr::DEBIT , "MONEYMRKT" , "account" , "debit" , "credit" , Type::ASSET },
42 { Type::CREDITLINE , DrCr::CREDIT , "CREDITLINE" , "account" , "decrease" , "increase" , Type::LIABILITY },
43
44}; /// endGCW::Dbo::Accounts::s_accountDefs
45
46const Wt::WFormModel::Field GCW::Dbo::Accounts::Field::guid = "guid" ; // text(32) PRIMARY KEY NOT NULL
47const Wt::WFormModel::Field GCW::Dbo::Accounts::Field::name = "name" ; // text(2048) NOT NULL
48const Wt::WFormModel::Field GCW::Dbo::Accounts::Field::account_typeName = "account_type" ; // text(2048) NOT NULL
50const Wt::WFormModel::Field GCW::Dbo::Accounts::Field::commodity_scu = "commodity_scu" ; // integer NOT NULL
51const Wt::WFormModel::Field GCW::Dbo::Accounts::Field::non_std_scu = "non_std_scu" ; // integer NOT NULL
57
58namespace {
59
60/*!
61** \brief Accounts Sorter
62**
63**
64*/
65auto sort( GCW::Dbo::Accounts::Item::Vector & _accountItems )-> void
66{
67 /*!
68 ** Sort the vector of accounts by fullname so that they can be loaded
69 ** in to the model in proper sequential order.
70 **
71 */
72 std::sort
73 (
74 _accountItems.begin(),
75 _accountItems.end(),
76 []( const GCW::Dbo::Accounts::Item::Ptr item1,
78 )
79 {
80 auto fullName1 = GCW::Dbo::Accounts::fullName( item1-> guid() );
81 auto fullName2 = GCW::Dbo::Accounts::fullName( item2-> guid() );
82
83 /*
84 ** return .bool. if the .fullName1. is .less than. the .fullName2. date
85 **
86 */
87 return fullName1
88 < fullName2;
89 }
90 );
91
92} // endvoid sort( GCW::Dbo::Splits::Item::Vector & _splitItems )
93
94auto
95rootSql( const std::string & _key )-> GCW::Dbo::Accounts::Item::Ptr
96{
98
99 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
100
101 /*
102 ** Get a handle on the root account. The root account is the only
103 ** account that has no parent, and has a name == "Root Account".
104 ** There should only be one of these.
105 **
106 */
107 auto results =
108 GCW::app()-> gnucashew_session().find< GCW::Dbo::Accounts::Item >()
109 .where( "(parent_guid = '' OR parent_guid IS NULL) AND name = ?" )
110 .bind( _key )
111 .resultList()
112 ;
113
114 if( results.size() == 1 )
115 {
116 retVal = *results.begin();
117 }
118
119 return retVal;
120
121} // endrootSql()-> GCW::Dbo::Accounts::Item::Ptr
122
123} // endnamespace {
124
125auto
128{
129 return rootSql( "Root Account" );
130// return rootGnc();
131
132} // endroot()-> GCW::Dbo::Accounts::Item::Ptr
133
134auto
137{
138 return rootSql( "Template Root" );
139// return rootGnc();
140
141} // endroot()-> GCW::Dbo::Accounts::Item::Ptr
142
143auto
145load( const std::string & _guid )-> GCW::Dbo::Accounts::Item::Ptr
146{
148
149 if( _guid != "" )
150 {
151
152 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
153
154 try
155 {
156 retVal =
157 GCW::app()-> gnucashew_session().load< GCW::Dbo::Accounts::Item >( _guid )
158 ;
159 }
160
161 /*
162 ** It is possible to provide a guid that doesn't exist. This can happen
163 ** in the bill-pay modules, since the bill-pay is somewhat loosely linked
164 ** to the actual gnucash items, if a gnucash account gets deleted and the
165 ** bill pay doesn't know about it, it can have a bad guid.
166 **
167 ** We don't care, we just return an .empty. item.
168 */
169 catch( std::exception & e )
170 {
171// std::cout << __FILE__ << ":" << __LINE__ << " " << e.what() << std::endl;
172 }
173
174 } // endif( _guid != "" )
175
176 return retVal;
177
178} // endload( const std::string & _guid )-> GCW::Dbo::Accounts::Item::Ptr
179
180auto
182byGuid( const std::string & _guid )-> GCW::Dbo::Accounts::Item::Ptr
183{
184 return load( _guid );
185
186} // endbyGuid( const std::string & _guid )-> GCW::Dbo::Accounts::Item::Ptr
187
188auto
190byChildName( const std::string & _parentGuid, const std::string & _childName )-> GCW::Dbo::Accounts::Item::Ptr
191{
193
194 /*
195 ** find an account matching the parent_guid and the child account name
196 */
197 retVal =
198 GCW::app()-> gnucashew_session().find< GCW::Dbo::Accounts::Item >()
199 .where( "parent_guid = ? AND name = ?" )
200 .bind( _parentGuid )
201 .bind( _childName )
202 .resultValue()
203 ;
204
205 return retVal;
206
207} // endbyChildName( const std::string & _parentGuid, const std::string & _childName )-> GCW::Dbo::Accounts::Item::Ptr
208
209auto
211byFullName( const std::string & _fullName )-> GCW::Dbo::Accounts::Item::Ptr
212{
214
215 /*
216 ** Here we split the account full-name, so we can dive in
217 ** to the accounts table and lope our way up to this
218 ** account.
219 **
220 */
221 auto split = GCW::Core::split( _fullName, ':' );
222
223 /*
224 ** Start at the root and lope on up. The return value
225 ** will be set accordingly as we go. We should end on
226 ** the final account, which is the one we wanted.
227 **
228 */
229 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
230 retVal = rootAccount();
231 for( int i=0; i< split.size(); i++ )
232 retVal = byChildName( retVal-> guid(), split.at(i) );
233
234 return retVal;
235
236} // endbyFullName( const std::string & _fullName )-> GCW::Dbo::Accounts::Item::Ptr
237
238auto
240byFullName( const char * _fullName )-> GCW::Dbo::Accounts::Item::Ptr
241{
242 return byFullName( std::string( _fullName ) );
243}
244
245auto
248{
249 return byFullName( _fullName.toUTF8() );
250}
251
252auto
255{
257
258 auto results =
259 GCW::app()-> gnucashew_session().find< GCW::Dbo::Accounts::Item >()
260 .resultList()
261 ;
262
263 for( auto result : results )
264 retVal.push_back( result );
265
266 sort( retVal );
267
268 return retVal;
269
270} // endallAccounts()-> GCW::Dbo::Accounts::Item::Vector
271
272auto
275{
277
278 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
279 auto results =
280 GCW::app()-> gnucashew_session().find< GCW::Dbo::Accounts::Item >()
281 .resultList()
282 ;
283
284 /*
285 ** push back all accounts that are
286 ** _not_ hidden, and
287 ** _not_ placeholder
288 **
289 */
290 for( auto & result : results )
291 if( !result-> hidden()
292 && !result-> placeHolder()
293 )
294 retVal.push_back( result );
295
296 sort( retVal );
297
298 return retVal;
299
300} // endactiveAccounts()-> GCW::Dbo::Accounts::Item::Vector
301
302auto
304activeAccountsAnd( const std::string & _guid )-> GCW::Dbo::Accounts::Item::Vector
305{
307
308 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
309 auto results =
310 GCW::app()-> gnucashew_session().find< GCW::Dbo::Accounts::Item >()
311 .resultList()
312 ;
313
314 auto root = rootAccount();
315 auto tmpl = templateRootAccount();
316
317 /*
318 ** push back all accounts that are
319 ** this _guid match or
320 ** _not_ hidden, and
321 ** _not_ placeholder
322 **
323 */
324 for( auto & result : results )
325 if( result-> guid() == _guid
326 || ( result != root
327 && result != tmpl
328 && !result-> hidden()
329 && !result-> placeHolder()
330 )
331 )
332 retVal.push_back( result );
333
334 sort( retVal );
335
336 return retVal;
337
338} // endactiveAccountsAnd( const std::string & _guid )-> GCW::Dbo::Accounts::Item::Vector
339
340auto
342byParent( const std::string & _parentGuid )-> GCW::Dbo::Accounts::Item::Vector
343{
345
346#warning finish me
347
348 return retVal;
349
350} // endvector( const std::string & _parentGuid )-> GCW::Dbo::Accounts::Item::Vector
351
352/*!
353** \brief Compute Account Full-Name from Heirarchy
354**
355** This function will calculate the "full account name" from
356** the accountGuid up to the root parent.
357**
358*/
359auto
361fullName( const std::string & _accountGuid )-> std::string
362{
363 /*!
364 ** If the provided account guid is blank, then just return
365 ** an empty string.
366 **
367 */
368 if( _accountGuid == "" )
369 return "";
370
371 std::string retVal;
372
373 /*
374 ** Fetch the account by Guid
375 **
376 */
377 auto accountItem = byGuid( _accountGuid );
378
379 if( accountItem )
380 {
381 /*!
382 ** During the building process, even though the "root account"
383 ** is a valid account, it is ignored and not included in the
384 ** results.
385 **
386 */
387 if( accountItem == rootAccount() )
388 return "";
389
390 /*
391 ** This is a recursive function that extracts the portions of
392 ** the account names and assembles them in to a contiguous
393 ** string with ':' colon separator.
394 **
395 */
396 retVal = fullName( accountItem-> parent_guid() );
397
398 /*
399 ** If we got anything then we need a separator
400 **
401 */
402 if( retVal != "" )
403 retVal += ":";
404
405 /*
406 ** And, finally the name of our account.
407 **
408 */
409 retVal += accountItem-> name();
410
411 } // endif( accountItem )
412
413 /*!
414 ** Recursively, this should generate a name such as;
415 ** "Assets:2023:Cash:FGB:OLB:2300-LSI"
416 **
417 */
418 return retVal;
419
420} // endfullName( const std::string & _accountGuid )-> std::string
421
422auto
424fullName( Item::Ptr _item )-> std::string
425{
426 return fullName( _item-> guid() );
427
428} // endfullName( Item::Ptr _item )-> std::string
429
430
431auto
433isType( const Item::Ptr _acctItem, GCW::Dbo::Accounts::Type _type )-> bool
434{
435 /*
436 ** if there is no account item, return false
437 */
438 if( !_acctItem )
439 return false;
440
441 /*
442 ** if the account item is an ~type~, return true
443 */
444 if( _acctItem-> accountType() == _type )
445 return true;
446
447 /*
448 ** poke in to the parent account, see if it's an ~type~
449 */
450 return isType( _acctItem-> parent_guid(), _type );
451
452} // endisType( const Item::Ptr _acctItem, GCW::Dbo::Accounts::Type _type )-> bool
453
454auto
456isType( const std::string & _guid, GCW::Dbo::Accounts::Type _type )-> bool
457{
458 /*
459 ** if there is no guid, return false
460 */
461 if( _guid == "" )
462 return false;
463
464 /*
465 ** make query
466 */
467 return isType( byGuid( _guid ), _type );
468
469} // endisType( const std::string & _guid, GCW::Dbo::Accounts::Type _type )-> bool
470
471
static std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
Definition Core.cpp:26
std::vector< Ptr > Vector
Definition BaseItem.h:41
const char * Field
std::vector< std::string > split(const std::string &value, char delim)
Definition Core.cpp:40
auto byParent(const std::string &_parentGuid) -> Item::Vector
Child Accounts via parent.
const Wt::WFormModel::Field name
const Wt::WFormModel::Field guid
endGCW::Dbo::Accounts::s_accountDefs
const Wt::WFormModel::Field description
const Wt::WFormModel::Field commodity_scu
const Wt::WFormModel::Field account_typeName
const Wt::WFormModel::Field code
const Wt::WFormModel::Field non_std_scu
const Wt::WFormModel::Field commodity_guid
const Wt::WFormModel::Field placeHolder
const Wt::WFormModel::Field hidden
const Wt::WFormModel::Field parent_guid
auto rootAccount() -> Item::Ptr
Load Root Account.
auto activeAccountsAnd(const std::string &_guid) -> Item::Vector
Load active accounts.
auto load(const std::string &_guid) -> Item::Ptr
Load Account by GUID.
auto templateRootAccount() -> Item::Ptr
Load Root Account.
auto activeAccounts() -> Item::Vector
Load accounts as; if( !hidden() && !placeHolder() )
const std::vector< AccountDef_t > s_accountDefs
auto allAccounts() -> Item::Vector
Load all accounts.
auto isType(const Item::Ptr _acctItem, GCW::Dbo::Accounts::Type _type) -> bool
Is Account Type.
auto byFullName(const std::string &_fullName) -> Item::Ptr
Load Account by 'full name' with ':' account separator.
auto byGuid(const std::string &_guid) -> Item::Ptr
Load Account by GUID.
auto byChildName(const std::string &_parentGuid, const std::string &_childName) -> Item::Ptr
Load Account by 'child name' and 'parent id'.
auto fullName(const std::string &_guid) -> std::string
Account Fullname via GUID.
App * app()
Definition App.cpp:75