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
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 = 'Root Account'" )
110 .resultList()
111 ;
112
113 if( results.size() == 1 )
114 {
115 retVal = *results.begin();
116 }
117
118 return retVal;
119
120} // endrootSql()-> GCW::Dbo::Accounts::Item::Ptr
121
122} // endnamespace {
123
124auto
127{
128 return rootSql();
129// return rootGnc();
130
131} // endroot()-> GCW::Dbo::Accounts::Item::Ptr
132
133auto
135load( const std::string & _guid )-> GCW::Dbo::Accounts::Item::Ptr
136{
138
139 if( _guid != "" )
140 {
141
142 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
143
144 try
145 {
146 retVal =
147 GCW::app()-> gnucashew_session().load< GCW::Dbo::Accounts::Item >( _guid )
148 ;
149 }
150
151 /*
152 ** It is possible to provide a guid that doesn't exist. This can happen
153 ** in the bill-pay modules, since the bill-pay is somewhat loosely linked
154 ** to the actual gnucash items, if a gnucash account gets deleted and the
155 ** bill pay doesn't know about it, it can have a bad guid.
156 **
157 ** We don't care, we just return an .empty. item.
158 */
159 catch( std::exception & e )
160 {
161// std::cout << __FILE__ << ":" << __LINE__ << " " << e.what() << std::endl;
162 }
163
164 } // endif( _guid != "" )
165
166 return retVal;
167
168} // endload( const std::string & _guid )-> GCW::Dbo::Accounts::Item::Ptr
169
170auto
172byGuid( const std::string & _guid )-> GCW::Dbo::Accounts::Item::Ptr
173{
174 return load( _guid );
175
176} // endbyGuid( const std::string & _guid )-> GCW::Dbo::Accounts::Item::Ptr
177
178auto
180byChildName( const std::string & _parentGuid, const std::string & _childName )-> GCW::Dbo::Accounts::Item::Ptr
181{
183
184 /*
185 ** find an account matching the parent_guid and the child account name
186 */
187 retVal =
188 GCW::app()-> gnucashew_session().find< GCW::Dbo::Accounts::Item >()
189 .where( "parent_guid = ? AND name = ?" )
190 .bind( _parentGuid )
191 .bind( _childName )
192 .resultValue()
193 ;
194
195 return retVal;
196
197} // endbyChildName( const std::string & _parentGuid, const std::string & _childName )-> GCW::Dbo::Accounts::Item::Ptr
198
199auto
201byFullName( const std::string & _fullName )-> GCW::Dbo::Accounts::Item::Ptr
202{
204
205 /*
206 ** Here we split the account full-name, so we can dive in
207 ** to the accounts table and lope our way up to this
208 ** account.
209 **
210 */
211 auto split = GCW::Core::split( _fullName, ':' );
212
213 /*
214 ** Start at the root and lope on up. The return value
215 ** will be set accordingly as we go. We should end on
216 ** the final account, which is the one we wanted.
217 **
218 */
219 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
220 retVal = rootAccount();
221 for( int i=0; i< split.size(); i++ )
222 retVal = byChildName( retVal-> guid(), split.at(i) );
223
224 return retVal;
225
226} // endbyFullName( const std::string & _fullName )-> GCW::Dbo::Accounts::Item::Ptr
227
228auto
230byFullName( const char * _fullName )-> GCW::Dbo::Accounts::Item::Ptr
231{
232 return byFullName( std::string( _fullName ) );
233}
234
235auto
238{
239 return byFullName( _fullName.toUTF8() );
240}
241
242auto
245{
247
248 auto results =
249 GCW::app()-> gnucashew_session().find< GCW::Dbo::Accounts::Item >()
250 .resultList()
251 ;
252
253 for( auto result : results )
254 retVal.push_back( result );
255
256 sort( retVal );
257
258 return retVal;
259
260} // endallAccounts()-> GCW::Dbo::Accounts::Item::Vector
261
262auto
265{
267
268 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
269 auto results =
270 GCW::app()-> gnucashew_session().find< GCW::Dbo::Accounts::Item >()
271 .resultList()
272 ;
273
274 /*
275 ** push back all accounts that are
276 ** _not_ hidden, and
277 ** _not_ placeholder
278 **
279 */
280 for( auto & result : results )
281 if( !result-> hidden()
282 && !result-> placeHolder()
283 )
284 retVal.push_back( result );
285
286 return retVal;
287
288} // endactiveAccounts()-> GCW::Dbo::Accounts::Item::Vector
289
290auto
292byParent( const std::string & _parentGuid )-> GCW::Dbo::Accounts::Item::Vector
293{
295
296
297 return retVal;
298
299} // endvector( const std::string & _parentGuid )-> GCW::Dbo::Accounts::Item::Vector
300
301/*!
302** \brief Compute Account Full-Name from Heirarchy
303**
304** This function will calculate the "full account name" from
305** the accountGuid up to the root parent.
306**
307*/
308auto
310fullName( const std::string & _accountGuid )-> std::string
311{
312 /*!
313 ** If the provided account guid is blank, then just return
314 ** an empty string.
315 **
316 */
317 if( _accountGuid == "" )
318 return "";
319
320 std::string retVal;
321
322 /*
323 ** Fetch the account by Guid
324 **
325 */
326 auto accountItem = byGuid( _accountGuid );
327
328 if( accountItem )
329 {
330 /*!
331 ** During the building process, even though the "root account"
332 ** is a valid account, it is ignored and not included in the
333 ** results.
334 **
335 */
336 if( accountItem == rootAccount() )
337 return "";
338
339 /*
340 ** This is a recursive function that extracts the portions of
341 ** the account names and assembles them in to a contiguous
342 ** string with ':' colon separator.
343 **
344 */
345 retVal = fullName( accountItem-> parent_guid() );
346
347 /*
348 ** If we got anything then we need a separator
349 **
350 */
351 if( retVal != "" )
352 retVal += ":";
353
354 /*
355 ** And, finally the name of our account.
356 **
357 */
358 retVal += accountItem-> name();
359
360 } // endif( accountItem )
361
362 /*!
363 ** Recursively, this should generate a name such as;
364 ** "Assets:2023:Cash:FGB:OLB:2300-LSI"
365 **
366 */
367 return retVal;
368
369} // endfullName( const std::string & _accountGuid )-> std::string
370
371auto
373fullName( Item::Ptr _item )-> std::string
374{
375 return fullName( _item-> guid() );
376
377} // endfullName( Item::Ptr _item )-> std::string
378
379
380auto
382isType( const Item::Ptr _acctItem, GCW::Dbo::Accounts::Type _type )-> bool
383{
384 /*
385 ** if there is no account item, return false
386 */
387 if( !_acctItem )
388 return false;
389
390 /*
391 ** if the account item is an ~type~, return true
392 */
393 if( _acctItem-> accountType() == _type )
394 return true;
395
396 /*
397 ** poke in to the parent account, see if it's an ~type~
398 */
399 return isType( _acctItem-> parent_guid(), _type );
400
401} // endisType( const Item::Ptr _acctItem, GCW::Dbo::Accounts::Type _type )-> bool
402
403auto
405isType( const std::string & _guid, GCW::Dbo::Accounts::Type _type )-> bool
406{
407 /*
408 ** if there is no guid, return false
409 */
410 if( _guid == "" )
411 return false;
412
413 /*
414 ** make query
415 */
416 return isType( byGuid( _guid ), _type );
417
418} // endisType( const std::string & _guid, GCW::Dbo::Accounts::Type _type )-> bool
419
420
static std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
Definition Core.cpp:16
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:30
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 load(const std::string &_guid) -> Item::Ptr
Load Account by GUID.
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