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 retVal =
185 GCW::app()-> gnucashew_session().find< GCW::Dbo::Accounts::Item >()
186 .where( "parent_guid = ? AND name = ?" )
187 .bind( _parentGuid )
188 .bind( _childName )
189 .resultValue()
190 ;
191
192 return retVal;
193
194} // endbyChildName( const std::string & _parentGuid, const std::string & _childName )-> GCW::Dbo::Accounts::Item::Ptr
195
196auto
198byFullName( const std::string & _fullName )-> GCW::Dbo::Accounts::Item::Ptr
199{
201
202 /*
203 ** Here we split the account full-name, so we can dive in
204 ** to the accounts table and lope our way up to this
205 ** account.
206 **
207 */
208 auto split = GCW::Core::split( _fullName, ':' );
209
210 /*
211 ** Start at the root and lope on up. The return value
212 ** will be filled-in as we go. We should end on the final
213 ** account, which is the one we wanted.
214 **
215 */
216 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
217 retVal = rootAccount();
218 for( int i=0; i< split.size(); i++ )
219 retVal = byChildName( retVal-> guid(), split.at(i) );
220
221 return retVal;
222
223} // endbyFullName( const std::string & _fullName )-> GCW::Dbo::Accounts::Item::Ptr
224
225auto
228{
229 return byFullName( _fullName.toUTF8() );
230}
231
232auto
235{
237
238 auto results =
239 GCW::app()-> gnucashew_session().find< GCW::Dbo::Accounts::Item >()
240 .resultList()
241 ;
242
243 for( auto result : results )
244 retVal.push_back( result );
245
246 sort( retVal );
247
248 return retVal;
249
250} // endallAccounts()-> GCW::Dbo::Accounts::Item::Vector
251
252auto
255{
257
258 auto results =
259 GCW::app()-> gnucashew_session().find< GCW::Dbo::Accounts::Item >()
260 .resultList()
261 ;
262
263 /*
264 ** push back all accounts that are
265 ** _not_ hidden, and
266 ** _not_ placeholder
267 **
268 */
269 for( auto & result : results )
270 if( !result-> hidden()
271 && !result-> placeHolder()
272 )
273 retVal.push_back( result );
274
275 return retVal;
276
277} // endactiveAccounts()-> GCW::Dbo::Accounts::Item::Vector
278
279auto
281vector( const std::string & _parentGuid )-> GCW::Dbo::Accounts::Item::Vector
282{
284
285
286 return retVal;
287
288} // endvector( const std::string & _parentGuid )-> GCW::Dbo::Accounts::Item::Vector
289
290/*!
291** \brief Compute Account Full-Name from Heirarchy
292**
293** This function will calculate the "full account name" from
294** the accountGuid up to the root parent.
295**
296*/
297auto
299fullName( const std::string & _accountGuid )-> std::string
300{
301 /*!
302 ** If the provided account guid is blank, then just return
303 ** an empty string.
304 **
305 */
306 if( _accountGuid == "" )
307 return "";
308
309 std::string retVal;
310
311 /*
312 ** Fetch the account by Guid
313 **
314 */
315 auto accountItem = byGuid( _accountGuid );
316
317 if( accountItem )
318 {
319 /*!
320 ** During the building process, even though the "root account"
321 ** is a valid account, it is ignored and not included in the
322 ** results.
323 **
324 */
325 if( accountItem == rootAccount() )
326 return "";
327
328 /*
329 ** This is a recursive function that extracts the portions of
330 ** the account names and assembles them in to a contiguous
331 ** string with ':' color separator.
332 **
333 */
334 retVal = fullName( accountItem-> parent_guid() );
335
336 /*
337 ** If we got anything then we need a separator
338 **
339 */
340 if( retVal != "" )
341 retVal += ":";
342
343 /*
344 ** And, finally the name of our account.
345 **
346 */
347 retVal += accountItem-> name();
348
349 } // endif( accountItem )
350
351 /*!
352 ** Recursively, this should generate a name such as;
353 ** "Assets:2023:Cash:FGB:OLB:2300-LSI"
354 **
355 */
356 return retVal;
357
358} // endfullName( const std::string & _accountGuid )-> std::string
359
360auto
362fullName( Item::Ptr _item )-> std::string
363{
364 return fullName( _item-> guid() );
365
366} // endfullName( Item::Ptr _item )-> std::string
367
368
369auto
371isType( const Item::Ptr _acctItem, GCW::Dbo::Accounts::Type _type )-> bool
372{
373 /*
374 ** if there is no account item, return false
375 */
376 if( !_acctItem )
377 return false;
378
379 /*
380 ** if the account item is an ~type~, return true
381 */
382 if( _acctItem-> accountType() == _type )
383 return true;
384
385 /*
386 ** poke in to the parent account, see if it's an ~type~
387 */
388 return isType( _acctItem-> parent_guid(), _type );
389
390} // endisType( const Item::Ptr _acctItem, GCW::Dbo::Accounts::Type _type )-> bool
391
392auto
394isType( const std::string & _guid, GCW::Dbo::Accounts::Type _type )-> bool
395{
396 /*
397 ** if there is no guid, return false
398 */
399 if( _guid == "" )
400 return false;
401
402 /*
403 ** make query
404 */
405 return isType( byGuid( _guid ), _type );
406
407} // endisType( const std::string & _guid, GCW::Dbo::Accounts::Type _type )-> bool
408
409
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 vector(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