GnuCashew ~ Web Application compatible with GnuCash sql data files.
GCW
Loading...
Searching...
No Matches
TransactionManager.cpp
Go to the documentation of this file.
1#line 2 "src/Eng/TransactionManager.cpp"
2
3#include "../Glb/Core.h"
4#include "../Gui/AccountRegister/Model.h"
6
9: m_prefrenceItem( GCW::Dbo::Prefrences::get() )
10{
11
12} // endManager()
13
16: m_model( _model ),
17 m_prefrenceItem( GCW::Dbo::Prefrences::get() )
18{
19
20} // endManager()
21
22auto
24newTransaction( const std::string & _accountGuid1, const std::string & _accountGuid2, const Wt::WDate & _date, GCW_NUMERIC _value, const std::string & _description )-> void
25{
26 std::cout << __FILE__ << ":" << __LINE__
27 << "\n acct1: " << _accountGuid1
28 << "\n acct2: " << _accountGuid2
29 << "\n date: '" << _date.toString() << "'"
30 << "\n value: " << _value
31 << "\n desc: " << _description
32 << std::endl;
33
34 /*!
35 ** The process begins by loading up the two accounts.
36 */
37 auto accountItem1 = GCW::Dbo::Accounts::load( _accountGuid1 );
38
39 /*
40 ** create a new transaction with two splits
41 */
42 m_transactionItem = GCW::Dbo::Transactions::add( GCW::Core::newGuid() );
43
44 /*
45 ** hook everything together
46 */
47 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
48 // transaction
49 m_transactionItem.modify()-> set_currency_guid( accountItem1-> commodity_guid() );
50 m_transactionItem.modify()-> set_enter_date( Wt::WDate::currentDate() );
51 m_transactionItem.modify()-> set_post_date( _date );
52 m_transactionItem.modify()-> set_description( _description );
53 // Split1
55 split1.modify()-> set_tx_guid ( m_transactionItem-> guid() );
56 split1.modify()-> set_account_guid ( _accountGuid1 );
57 split1.modify()-> set_reconcile_state ( GCW_RECONCILE_NO );
58 split1.modify()-> set_reconcile_date ( GCW_DEFAULT_DATE );
59 split1.modify()-> set_value ( _value );
60 split1.modify()-> set_quantity ( _value ); // qty set also?
61 // Split2
63 split2.modify()-> set_tx_guid ( m_transactionItem-> guid() );
64 split2.modify()-> set_account_guid ( _accountGuid2 );
65 split2.modify()-> set_reconcile_state ( GCW_RECONCILE_NO );
66 split2.modify()-> set_reconcile_date ( GCW_DEFAULT_DATE );
67 split2.modify()-> set_value ( -_value );
68 split2.modify()-> set_quantity ( -_value ); // qty set also?
69
70 /*!
71 ** \todo query why qty used here
72 **
73 ** this transaction posting shows that .value. as well as .quantity. are
74 ** set at the same time. If .quantity. is not set, then when re-opening
75 ** the sql file in gnucash native causes the gnucash to take a very long
76 ** time to load. This only happens once, and upon examining the database
77 ** afterwords, all the splits have the same .value. set to .quantity. So,
78 ** some sort of massive update is happening there on file-open. Therefore,
79 ** we will set .quantity. along with .value. Doing so seems to mitigate
80 ** the long/slow load time.
81 **
82 */
83
84 /*
85 ** record the splits
86 */
87 m_splits.push_back( split1 );
88 m_splits.push_back( split2 );
89
90} // endnewTransaction()-> void
91
92
93auto
95loadTransaction( const std::string & _transactionGuid )-> void
96{
97 /*
98 ** set the transaction
99 */
100 m_transactionItem = GCW::Dbo::Transactions::load( _transactionGuid );
101
102 /*
103 ** set the splits
104 */
105 m_splits = GCW::Dbo::Splits::byTransaction( m_transactionItem-> guid() );
106
107} // endloadTransaction( const std::string & _transactionGuid )-> void
108
109auto
111deleteTransaction()-> bool
112{
113
114 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
115 m_transactionItem.remove();
116 for( auto & splitItem : m_splits )
117 splitItem.remove();
118
119 return true;
120
121} // enddeleteTransaction()-> void
122
123auto
125setSplitItem( GCW::Dbo::Splits::Item::Ptr _splitItem )-> void
126{
127 if( !_splitItem )
128 return;
129
130 loadSplit( _splitItem-> guid() );
131
132} // endsetSplitItem( GCW::Dbo::Splits::Item::Ptr _splitItem )-> void
133
134auto
136loadSplit( const std::string & _splitGuid )-> void
137{
138 if( _splitGuid == "" )
139 return;
140
141 /*
142 ** in the words of spock: 'remember'
143 */
144 m_splitGuid = _splitGuid;
145
146 /*
147 ** get the split so we can grab the transaction
148 */
149 auto splitItem = GCW::Dbo::Splits::load( _splitGuid );
150
151 /*
152 ** set the transaction
153 */
154 loadTransaction( splitItem-> tx_guid() );
155
156} // endloadSplit( const std::string & _splitGuid )-> void
157
158auto
160otherGuid() const-> std::string
161{
162 for( auto & splitItem : m_splits )
163 if( splitItem-> guid() != m_splitGuid )
164 return splitItem-> guid();
165
166 return "";
167
168} // endotherGuid()-> std::string
169
170auto
172split( const std::string & _splitGuid ) const-> GCW::Dbo::Splits::Item::Ptr
173{
174 for( auto & splitItem : m_splits )
175 if( splitItem-> guid() == _splitGuid )
176 return splitItem;
177
179
180} // endsplit( const std::string & _splitGuid ) const-> GCW::Dbo::Splits::Item::Ptr
181
182auto
184thisSplit() const-> GCW::Dbo::Splits::Item::Ptr
185{
186 return split( m_splitGuid );
187
188} // endthisSplit() const-> GCW::Dbo::Splits::Item::Ptr
189
190auto
192thatSplit() const-> GCW::Dbo::Splits::Item::Ptr
193{
194 return split( otherGuid() );
195
196} // endthatSplit() const-> GCW::Dbo::Splits::Item::Ptr
197
198auto
200fromSplit() const-> GCW::Dbo::Splits::Item::Ptr
201{
202 for( auto split : m_splits )
203 {
204 if( split-> value() < 0 )
205 return split;
206 }
207
209
210} // endfromSplit() const-> GCW::Dbo::Splits::Item::Ptr
211
212auto
214toSplit() const-> GCW::Dbo::Splits::Item::Ptr
215{
216 for( auto split : m_splits )
217 if( split-> value() > 0 )
218 return split;
219
221
222} // endtoSplit() const-> GCW::Dbo::Splits::Item::Ptr
223
224auto
226getFromAccount() const-> std::string
227{
228 if( fromSplit() )
229 return GCW::Dbo::Accounts::fullName( fromSplit()-> account_guid() );
230
231 return TR8( "gcw.unassigned" );
232
233} // endgetFromAccount() const-> std::string
234
235auto
237getToAccount() const-> std::string
238{
239 if( toSplit() )
240 return GCW::Dbo::Accounts::fullName( toSplit()-> account_guid() );
241
242 return TR8( "gcw.unassigned" );
243
244} // endgetToAccount() const-> std::string
245
246
247auto
249forAccountSplit( const std::string & _accountGuid ) const-> GCW::Dbo::Splits::Item::Ptr
250{
252
253 for( auto & split : m_splits )
254 if( split-> account_guid() == _accountGuid )
255 retVal = split;
256
257 return retVal;
258
259} // endforAccount( const std::string * _accountGuid ) const-> GCW::Dbo::Splits::Item::Ptr
260
261auto
263getDate() const-> Wt::WDateTime
264{
265 return m_transactionItem-> post_date_as_date();
266
267} // endgetDate() const-> Wt::WDateTime &;
268
269auto
271getDateAsString() const-> Wt::WString
272{
273 return getDate().toString( GCW_DATE_FORMAT_DISPLAY );
274
275} // endgetDate() const-> Wt::WDateTime &;
276
277auto
279setDate( const Wt::WDateTime & _value )-> void
280{
281 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
282 m_transactionItem.modify()-> set_post_date( _value );
283
284} // endsetDate( const Wt::WDateTime & _value )-> void
285
286auto
288setDate( const Wt::WDate & _value )-> void
289{
290 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
291 m_transactionItem.modify()-> set_post_date( Wt::WDateTime( _value ) );
292
293} // endsetDate( const Wt::WDateTime & _value )-> void
294
295
296
297auto
299setAction( const std::string & _value )-> void
300{
301 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
302 m_transactionItem.modify()-> set_num( _value );
303
304} // endsetAction( const std::string & _value )-> void
305
306auto
308getDescription() const-> std::string
309{
310 return m_transactionItem-> description();
311
312} // endgetDescription() const-> std::string &
313
314auto
316setDescription( const std::string & _value )-> void
317{
318 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
319 m_transactionItem.modify()-> set_description( _value );
320
321} // endsetDescription( const std::string & _value )-> void
322
323auto
325setDescription( const Wt::WString & _value )-> void
326{
327 setDescription( _value.toUTF8() );
328
329} // ensetDescription( const Wt::WString & _value )-> void
330
331auto
333getNum() const-> std::string
334{
335 return m_transactionItem-> num();
336
337} // endgetDescription() const-> std::string &
338
339auto
341setNum( const std::string & _value )-> void
342{
343 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
344 m_transactionItem.modify()-> set_num( _value );
345
346} // endsetDescription( const std::string & _value )-> void
347
348auto
350setNum( const Wt::WString & _value )-> void
351{
352 setNum( _value.toUTF8() );
353
354} // ensetDescription( const Wt::WString & _value )-> void
355
356auto
358setTransferGuid( const std::string & _value )-> void
359{
360 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
361 thatSplit().modify()-> set_account_guid( _value );
362
363} // endsetTransferGuid( const std::string & _value )-> void
364
365auto
367setReconcile( const std::string & _value )-> void
368{
369 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
370 thisSplit().modify()-> set_reconcile_state( _value );
371
372} // endsetReconcile( const std::string & _value )-> void
373
374auto
376getValue() const-> GCW_NUMERIC
377{
378 return thisSplit()-> value();
379
380} // endgetValue() const-> GCW_NUMERIC
381
382auto
384getValueAsString() const-> std::string
385{
386 return thisSplit()-> valueAsString();
387
388} // endgetValue() const-> GCW_NUMERIC
389
390auto
392setValue( GCW_NUMERIC _value )-> void
393{
394// Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
395// thisSplit().modify()-> set_value( _value );
396// thatSplit().modify()-> set_value( _value * -1 );
397
398} // endsetDebit( GCW_NUMERIC _value )-> void
399
400auto
402setValue( const std::string & _acctGuid, GCW_NUMERIC _value )-> void
403{
404 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
405 forAccountSplit( _acctGuid ).modify()-> set_value( _value );
406
407} // endsetValue( const std::string & _acctGuid, GCW_NUMERIC _value )-> void
408
409auto
411setNotes( const std::string & _acctGuid, const std::string & _value )-> void
412{
413 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
414 forAccountSplit( _acctGuid ).modify()-> set_memo( _value );
415
416} // endsetNotes( const std::string & _value )-> void
417
418
419auto
421otherSplits() const-> GCW::Dbo::Splits::Item::Vector
422{
423 return GCW::Dbo::Splits::bySplitExcept( m_splitGuid );
424
425} // endotherSplits() const-> GCW::Dbo::Splits::Item::Vector
426
427auto
429setReadOnly( bool _value )-> void
430{
431
432} // endsetReadOnly( bool _value )-> void
433
434auto
436flags( bool _editable ) const-> Wt::WFlags< Wt::ItemFlag >
437{
439
441
442 if( _editable )
443 retVal |= Wt::ItemFlag::Editable;
444
445 return retVal;
446
447} // endflags( bool _editable ) const-> Wt::WFlags< Wt::ItemFlag >
448
449auto
451createText( const std::string & _text ) const-> std::unique_ptr< Wt::WStandardItem >
452{
453 auto retVal = std::make_unique< Wt::WStandardItem >( _text );
454
455 retVal-> setStyleClass( "blank" );
456 retVal-> setFlags( flags( false ) );
457
458 return std::move( retVal );
459
460} // endcreateBlank() const-> std::unique_ptr< Wt::WStandardItem >
461
462auto
464createBlank() const-> std::unique_ptr< Wt::WStandardItem >
465{
466 auto retVal = std::make_unique< Wt::WStandardItem >( "" );
467
468 retVal-> setStyleClass( "blank" );
469 retVal-> setFlags( flags( false ) );
470
471 return std::move( retVal );
472
473} // endcreateBlank() const-> std::unique_ptr< Wt::WStandardItem >
474
475auto
477createEmpty() const-> std::unique_ptr< Wt::WStandardItem >
478{
479 auto retVal = std::make_unique< Wt::WStandardItem >( "" );
480
481 retVal-> setStyleClass( "empty" );
482 retVal-> setFlags( flags( false ) );
483
484 return std::move( retVal );
485
486} // endcreateEmpty() const-> std::unique_ptr< Wt::WStandardItem >
487
488auto
490createDate( const TxItem & _txItem, bool _editable ) const-> std::unique_ptr< Wt::WStandardItem >
491{
492 auto retVal = std::make_unique< Wt::WStandardItem >();
493
494 retVal-> setStyleClass( "date" );
495 retVal-> setFlags( flags( _editable ) );
496
497 /*!
498 ** \note The post_date column (col-0) also carries with it the guid of the split
499 ** item itself, so that the originating split can be located from the table
500 ** view. The guid can be accessed by;
501 **
502 ** \code
503 ** Wt::WString splitRowGuid = Wt::asString( standardItem.data( Wt::ItemDataRole::User ) )
504 ** \endcode
505 **
506 ** \sa getSplitGuid
507 */
508// auto tip =
509// Wt::WString
510// (
511// "row: {1}\n"
512// "acg: {2}\n"
513// "spg: {3}\n"
514// )
515// .arg( m_model-> rowCount() )
516// .arg( thisSplit()-> account_guid() )
517// .arg( thisSplit()-> guid() )
518// ;
519
520 /*
521 ** if there is a split, set the date value
522 */
523 if( thisSplit() )
524 {
525 if( transactionItem() )
526 retVal-> setData( transactionItem()-> post_date_as_date(), Wt::ItemDataRole::Edit );
527
528 if( thisSplit() )
529 retVal-> setData( thisSplit()-> guid(), Wt::ItemDataRole::User );
530
531 }
532
533 /*
534 ** there is no split, so default to today's date
535 */
536 else
537 {
539 retVal-> setData( dateTime, Wt::ItemDataRole::Edit );
540 }
541
542// retVal-> setToolTip( tip );
543
544 return std::move( retVal );
545
546} // endcreateDate() const-> std::unique_ptr< Wt::WStandardItem > ;
547
548auto
550createNum( const TxItem & _txItem, bool _editable ) const-> std::unique_ptr< Wt::WStandardItem >
551{
552 auto retVal = std::make_unique< Wt::WStandardItem >( "" );
553 retVal-> setStyleClass( "txnum" );
554 retVal-> setFlags( flags( _editable ) );
555
556 if( thisSplit() )
557 {
558 if( _txItem )
559 {
560 retVal-> setText( _txItem-> num() );
561 }
562 }
563
564 return std::move( retVal );
565
566} // endcreateNum() const-> std::unique_ptr< Wt::WStandardItem >
567
568
569auto
571createNum( const SpItem & _spItem, bool _editable ) const-> std::unique_ptr< Wt::WStandardItem >
572{
573 auto retVal = std::make_unique< Wt::WStandardItem >( "" );
574 retVal-> setStyleClass( "spnum" );
575 retVal-> setFlags( flags( _editable ) );
576
577 if( thisSplit() )
578 {
579 if( _spItem )
580 {
581 retVal-> setText( _spItem-> action() );
582 }
583 }
584
585 return std::move( retVal );
586
587} // endcreateNum() const-> std::unique_ptr< Wt::WStandardItem >
588
589
590auto
592createDescription( const TxItem & _txItem, bool _editable ) const-> std::unique_ptr< Wt::WStandardItem >
593{
594 auto retVal = std::make_unique< Wt::WStandardItem >( "" );
595 retVal-> setStyleClass( "txdesc" );
596 retVal-> setFlags( flags( _editable ) );
597
598 if( thisSplit() )
599 {
600 if( _txItem )
601 {
602 retVal-> setText( _txItem-> description() );
603 }
604 }
605
606 return std::move( retVal );
607
608} // endcreateDescription() const-> std::unique_ptr< Wt::WStandardItem >
609
610
611auto
613createDescription( const SpItem & _spItem, bool _editable ) const-> std::unique_ptr< Wt::WStandardItem >
614{
615 auto retVal = std::make_unique< Wt::WStandardItem >( "" );
616 retVal-> setStyleClass( "spdesc" );
617 retVal-> setFlags( flags( _editable ) );
618
619 if( _spItem )
620 {
621 retVal-> setText( _spItem-> memo() );
622 }
623
624 return std::move( retVal );
625
626} // endcreateDescription() const-> std::unique_ptr< Wt::WStandardItem >
627
628#ifdef NEVER
629auto
631createAccount( const SpItem & _splitItem, bool _editable ) const-> std::unique_ptr< Wt::WStandardItem >
632{
633 auto retVal = std::make_unique< Wt::WStandardItem >( "" );
634 retVal-> setStyleClass( "acct" );
635 retVal-> setFlags( flags( _editable ) );
636
637 /*!
638 ** The 'account' text depends on the
639 ** target account defined in the split. There are three
640 ** possibilities here;
641 **
642 ** -# no splits... this shows up as an <b>'imbalance'</b> (this is an error condition)
643 ** -# 1 split... this just shows the split account on the same single line
644 ** -# >1 split... this is more than one target account, so just indicate 'split'
645 */
646 switch( otherSplits().size() )
647 {
648 /*!
649 ** \par Imbalance
650 ** This is actually a problem... We don't have another split, and
651 ** according to 'generally accepted accounting practices' we
652 ** should! So, just plop an 'imbalance' indicator in the view.
653 ** A style-class is also applied to the item to allow the rendering
654 ** in the view to highlight this problem.
655 */
656 case 0:
657 {
658 retVal-> setText( TR("gcw.AccountRegister.account.imbalanceUSD") ); // account
659 retVal-> setStyleClass( retVal-> styleClass() + " errval" );
660 retVal-> setToolTip( TR("gcw.AccountRegister.account.imbalanceUSD.toolTip") );
661 break;
662 }
663
664 /*!
665 ** \par Normal Split
666 ** This is a straight and simple 1:1 split transaction, so we can pull
667 ** the account name from the other side of the split and pop that in
668 ** to the model directly.
669 */
670 case 1:
671 {
672 auto txSplitItem = *otherSplits().begin();
673 auto splitAccountItem = GCW::Dbo::Accounts::byGuid( txSplitItem-> account_guid() );
674
675 // yes, we have one account item
676 if( splitAccountItem )
677 {
678 retVal-> setText( GCW::Dbo::Accounts::fullName( splitAccountItem-> guid() ) );
679
680 auto tip =
682 (
683 "spa:{1}\n"
684 "txi:{2}\n"
685 )
686 .arg( splitAccountItem-> guid() )
687 .arg( txSplitItem-> guid() )
688 ;
689 retVal-> setToolTip( tip );
690 }
691
692 // no, we don't have an account item
693 else
694 {
695 /*!
696 ** \par Another Imbalance
697 ** This is another problem... We have another split, but the account
698 ** we are split-to doesn't exist. This is a problem and should not
699 ** happen and represents an error in the database. This means the
700 ** account containing this guid nolonger exists. That should never
701 ** happen.
702 */
703 retVal-> setText( TR("gcw.AccountRegister.account.imbalanceUSD") );
704 retVal-> setStyleClass( retVal-> styleClass() + " errval" );
705
706 auto toolTip =
707 Wt::WString("target guid:{1}\n{2}")
708 .arg( txSplitItem-> account_guid() )
709 .arg( TR("gcw.AccountRegister.account.invalidTarget.toolTip") )
710 .toUTF8()
711 ;
712
713 retVal-> setToolTip( toolTip );
714
715 } // endelse no account item
716
717 break;
718
719 } // endcase 1:
720
721 /*!
722 ** \par Multi-Split
723 ** When we have more than one split then we cannot display
724 ** all of the split accounts on just one line, so just pop
725 ** a message that indicates that we're in a multisplit
726 ** transaction.
727 */
728 default:
729 {
730 retVal-> setText( TR("gcw.AccountRegister.account.multisplit") ); // account
731 }
732
733 } // endswitch( transMan.otherSplits().size() )
734
735
736 return std::move( retVal );
737
738} // endcreateAccount() const-> std::unique_ptr< Wt::WStandardItem >
739#endif
740
741auto
743createAccount( const SpItem & _splitItem, bool _editable ) const-> std::unique_ptr< Wt::WStandardItem >
744{
745 auto retVal = std::make_unique< Wt::WStandardItem >( "" );
746 retVal-> setStyleClass( "acct" );
747 retVal-> setFlags( flags( _editable ) );
748
749 if( _splitItem )
750 {
751 auto splitAccountItem = GCW::Dbo::Accounts::byGuid( _splitItem-> account_guid() );
752
753 // yes, we have one account item
754 if( splitAccountItem )
755 {
756 retVal-> setText( GCW::Dbo::Accounts::fullName( splitAccountItem-> guid() ) );
757
758 auto tip =
760 (
761 "spa:{1}\n"
762 "txi:{2}\n"
763 )
764 .arg( splitAccountItem-> guid() )
765 .arg( _splitItem-> guid() )
766 ;
767 retVal-> setToolTip( tip );
768 }
769
770 // no, we don't have an account item
771 else
772 {
773 /*!
774 ** \par Another Imbalance
775 ** This is another problem... We have another split, but the account
776 ** we are split-to doesn't exist. This is a problem and should not
777 ** happen and represents an error in the database. This means the
778 ** account containing this guid nolonger exists. That should never
779 ** happen.
780 */
781 retVal-> setText( TR("gcw.AccountRegister.account.imbalanceUSD") );
782 retVal-> setStyleClass( retVal-> styleClass() + " errval" );
783
784 auto toolTip =
785 Wt::WString("target guid:{1}\n{2}")
786 .arg( _splitItem-> account_guid() )
787 .arg( TR("gcw.AccountRegister.account.invalidTarget.toolTip") )
788 .toUTF8()
789 ;
790 retVal-> setToolTip( toolTip );
791
792 } // endelse no account item
793
794 } // endif( _splitItem )
795
796 return std::move( retVal );
797
798} // endcreateAccount() const-> std::unique_ptr< Wt::WStandardItem >
799
800auto
802createReconcile( const SpItem & _splitItem, bool _editable ) const-> std::unique_ptr< Wt::WStandardItem >
803{
804 auto retVal = std::make_unique< Wt::WStandardItem >( "" );
805 retVal-> setStyleClass( "rec" );
806 retVal-> setFlags( flags( _editable ) );
807
808 if( _splitItem )
809 {
810 retVal-> setText( _splitItem-> reconcile_state() );
811 }
812
813 return std::move( retVal );
814
815} // endcreateReconcile() const-> std::unique_ptr< Wt::WStandardItem >
816
817auto
819createDebit( const SpItem & _splitItem, bool _editable ) const-> std::unique_ptr< Wt::WStandardItem >
820{
821 auto retVal = std::make_unique< Wt::WStandardItem >( "" );
822 retVal-> setStyleClass( "dr" );
823 retVal-> setFlags( flags( _editable ) );
824
825 if( _splitItem )
826 {
827 /*
828 ** debits are always positive
829 */
830 if( _splitItem-> value() > 0 )
831 {
832 retVal -> setText( _splitItem-> valueAsString() );
833 }
834 }
835
836 return std::move( retVal );
837
838} // endcreateDebit() const-> std::unique_ptr< Wt::WStandardItem >
839
840auto
842createCredit( const SpItem & _splitItem, bool _editable ) const-> std::unique_ptr< Wt::WStandardItem >
843{
844 auto retVal = std::make_unique< Wt::WStandardItem >( "" );
845 retVal-> setStyleClass( "cr" );
846 retVal-> setFlags( flags( _editable ) );
847
848 if( _splitItem )
849 {
850 /*
851 ** credit are always negative
852 */
853 if( _splitItem-> value() < 0 )
854 {
855 /*
856 ** set the value and invert(true) the sign
857 */
858 retVal -> setText( _splitItem-> valueAsString( true ) );
859 }
860 }
861
862 return std::move( retVal );
863
864} // endcreateCredit() const-> std::unique_ptr< Wt::WStandardItem >
865
866auto
868createBalance() const-> std::unique_ptr< Wt::WStandardItem >
869{
870 auto retVal = std::make_unique< Wt::WStandardItem >( "" );
871 retVal-> setStyleClass( "bal" );
872 retVal-> setFlags( flags( false ) );
873
874 if( thisSplit() )
875 {
876 retVal-> setText( toString( model()-> m_balance, GCW::Cfg::decimal_format() ) );
877 }
878
879 return std::move( retVal );
880
881} // endcreateBalance() const-> std::unique_ptr< Wt::WStandardItem >
882
883auto
885highlightNegativeBalance( RowItem & _row ) const-> void
886{
887 /*
888 ** if the balance is negative, highlight the row
889 */
890 if( model()-> m_balance < 0 )
891 {
892 if( prefrenceItem().accountRegisterHighlight( GCW::Dbo::Prefrences::AccountRegisterHighlight::NEGVAL_EXTRA ) )
893 {
894 for( int col = 0; col< _row.size(); col++ )
895 _row.at( col )-> setStyleClass( _row.at( col )-> styleClass() + " negval" );
896 }
897
898 if( prefrenceItem().accountRegisterHighlight( GCW::Dbo::Prefrences::AccountRegisterHighlight::NORMAL ) )
899 {
900 _row.at( _row.size()-1 )-> setStyleClass( _row.at( _row.size()-1 )-> styleClass() + " negval" );
901 }
902
903 } // endif( model()-> m_balance < 0 )
904
905
906} // endhighlightNegativeBalance() const-> void
907
908auto
910appendBasicLedger( bool _editable ) const-> void
911{
912 RowItem row ;
913
914 bool ed = true;
915 if( thisSplit() )
916 ed = thisSplit()-> reconcile_state() == GCW_RECONCILE_NO;
917
918 row.push_back( createDate ( transactionItem() , ed ) );
919 row.push_back( createNum ( transactionItem() , ed ) );
920 row.push_back( createDescription ( transactionItem() , ed ) );
921 row.push_back( createAccount ( thatSplit() , ed ) );
922 row.push_back( createReconcile ( thisSplit() , ed ) );
923 row.push_back( createDebit ( thisSplit() , ed ) );
924 row.push_back( createCredit ( thisSplit() , ed ) );
925 row.push_back( createBalance ( ) );
926
927 highlightNegativeBalance( row );
928
929 /*
930 ** set alternating row colors (rowbl == row-basic-ledger)
931 */
932 for( int col=0; col< row.size(); col++ )
933 row.at(col)-> setStyleClass( row.at(col)-> styleClass() + " rowbl" );
934
935 model()-> appendRow( std::move( row ) );
936
937} // endappendBasicLedger() const-> void
938
939auto
941appendAutosplitLedger( bool _editable ) const-> void
942{
943} // endappendAutosplitLedger() const-> void
944
945auto
947appendTransactionJournal( bool _editable ) const-> void
948{
949 /*
950 ** set the first line
951 */
952 {
953 RowItem row ;
954
955 row.push_back( createDate ( transactionItem(), _editable ) );
956 row.push_back( createNum ( transactionItem(), _editable ) );
957 row.push_back( createDescription ( transactionItem(), _editable ) );
958 row.push_back( createEmpty ( ) ); // account is empty on this row
959 row.push_back( createEmpty ( ) ); // reconcile is empty on this row
960 row.push_back( createDebit ( thisSplit() , false ) ); // debit cannot be edited here
961 row.push_back( createCredit ( thisSplit() , false ) ); // credit cannot be edited here
962 row.push_back( createBalance ( ) );
963
964 highlightNegativeBalance( row );
965
966 /*
967 ** set static row color (rowtj == row-transaction-journal)
968 */
969 for( int col=0; col< row.size(); col++ )
970 row.at(col)-> setStyleClass( row.at(col)-> styleClass() + " rowtj" );
971
972 model()-> appendRow( std::move( row ) );
973 }
974
975 /*
976 ** set another line, one for each split
977 */
978 for( auto splitItem : splits() )
979 {
980 auto ed = splitItem-> reconcile_state() == GCW_RECONCILE_NO;
981 RowItem row ;
982 row.push_back( createEmpty ( ) );
983 row.push_back( createNum ( splitItem, ed ) );
984 row.push_back( createDescription ( splitItem, ed ) );
985 row.push_back( createAccount ( splitItem, ed ) );
986 row.push_back( createReconcile ( splitItem, ed ) );
987 row.push_back( createDebit ( splitItem, ed ) );
988 row.push_back( createCredit ( splitItem, ed ) );
989 row.push_back( createEmpty ( ) );
990
991 for( int col=0; col< row.size(); col++ )
992 row.at(col)-> setStyleClass( row.at(col)-> styleClass() + " rowtd" );
993
994 model()-> appendRow( std::move( row ) );
995 }
996
997} // endappendTransactionJournal() const-> void
998
999auto
1001appendGeneralJournal( bool _editable ) const-> void
1002{
1003} // endappendGeneralJournal() const-> void
1004
1005
1006
1007auto
1009appendRow( bool _editable )-> void
1010{
1011 /*
1012 ** calculate the running balance
1013 */
1014 if( thisSplit() )
1015 model()-> m_balance += thisSplit()-> value();
1016
1017 /*
1018 ** build a row depending on the view mode
1019 */
1020 switch( model()-> viewMode() )
1021 {
1023 {
1024 appendBasicLedger( _editable );
1025 break;
1026 }
1027
1029 {
1030 appendAutosplitLedger( _editable );
1031 break;
1032 }
1033
1035 {
1036 appendTransactionJournal( _editable );
1037 break;
1038 }
1039
1041 {
1042 appendGeneralJournal( _editable );
1043 break;
1044 }
1045
1046 } // endswitch( model()-> viewMode() )
1047
1048 if( model()-> doubleLine() )
1049 {
1050 RowItem row ;
1051 row.push_back( createEmpty() );
1052 row.push_back( createEmpty() );
1053 row.push_back( createEmpty() );
1054 row.push_back( createEmpty() );
1055 row.push_back( createEmpty() );
1056 row.push_back( createEmpty() );
1057 row.push_back( createEmpty() );
1058 row.push_back( createEmpty() );
1059
1060 for( int col=0; col< row.size(); col++ )
1061 row.at(col)-> setStyleClass( row.at(col)-> styleClass() + " rowte" );
1062
1063 model()-> appendRow( std::move( row ) );
1064 }
1065
1066} // endappendRow()-> void
1067
1068
1069auto
1071appendEmptyRow( bool _editable )-> void
1072{
1073
1074 m_splitGuid = "";
1075 m_splits.clear();
1076
1077 appendRow( _editable );
1078
1079} // endappendRow()-> void
1080
1081auto
1083insertDoubleLine( int _row )-> void
1084{
1085// if( model()-> doubleLine() )
1086 {
1087 RowItem row ;
1088 row.push_back( createEmpty() );
1089 row.push_back( createEmpty() );
1090 row.push_back( createEmpty() );
1091 row.push_back( createEmpty() );
1092 row.push_back( createEmpty() );
1093 row.push_back( createEmpty() );
1094 row.push_back( createEmpty() );
1095 row.push_back( createEmpty() );
1096
1097 for( int col=0; col< row.size(); col++ )
1098 row.at(col)-> setStyleClass( row.at(col)-> styleClass() + " rowdl" );
1099
1100 model()-> insertRow( _row, std::move( row ) );
1101 }
1102
1103} // endinsertDoubleLine( int row )-> void
1104
1105
static std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
Definition Core.cpp:16
Wt::Dbo::ptr< Item > Ptr
Definition BaseItem.h:39
auto createBalance() const -> std::unique_ptr< Wt::WStandardItem >
auto highlightNegativeBalance(RowItem &_row) const -> void
auto appendAutosplitLedger(bool _editable) const -> void
auto setTransferGuid(const std::string &_value) -> void
Set Transfer GUID.
auto deleteTransaction() -> bool
Delete Transaction.
auto insertDoubleLine(int _row) -> void
auto createAccount(const SpItem &_spItem, bool _editable) const -> std::unique_ptr< Wt::WStandardItem >
auto forAccountSplit(const std::string &_accountGuid) const -> GCW::Dbo::Splits::Item::Ptr
Load Split for Account.
auto setReconcile(const std::string &_value) -> void
auto getToAccount() const -> std::string
auto toSplit() const -> GCW::Dbo::Splits::Item::Ptr
auto getDateAsString() const -> Wt::WString
auto appendBasicLedger(bool _editable) const -> void
auto createDescription(const TxItem &_txItem, bool _editable) const -> std::unique_ptr< Wt::WStandardItem >
auto getDescription() const -> std::string
Set Description.
auto setSplitItem(GCW::Dbo::Splits::Item::Ptr _splitItem) -> void
auto thisSplit() const -> GCW::Dbo::Splits::Item::Ptr
auto getDate() const -> Wt::WDateTime
Set Date.
auto createBlank() const -> std::unique_ptr< Wt::WStandardItem >
auto setDescription(const std::string &_value) -> void
auto appendRow(bool _editable) -> void
auto createCredit(const SpItem &_spItem, bool _editable) const -> std::unique_ptr< Wt::WStandardItem >
auto getValue() const -> GCW_NUMERIC
auto getNum() const -> std::string
Set Num.
auto fromSplit() const -> GCW::Dbo::Splits::Item::Ptr
auto createReconcile(const SpItem &_spItem, bool _editable) const -> std::unique_ptr< Wt::WStandardItem >
GCW::Dbo::Splits::Item::Ptr SpItem
std::vector< std::unique_ptr< Wt::WStandardItem > > RowItem
auto otherGuid() const -> std::string
Other GUID.
auto setNum(const std::string &_value) -> void
auto setDate(const Wt::WDateTime &_value) -> void
auto loadSplit(const std::string &_splitGuid) -> void
Set Split.
auto split(const std::string &_splitGuid) const -> GCW::Dbo::Splits::Item::Ptr
auto setAction(const std::string &_value) -> void
Set Action.
auto setNotes(const std::string &_acctGuid, const std::string &_value) -> void
auto setReadOnly(bool _value) -> void
auto setValue(GCW_NUMERIC _value) -> void
auto appendGeneralJournal(bool _editable) const -> void
auto createDebit(const SpItem &_spItem, bool _editable) const -> std::unique_ptr< Wt::WStandardItem >
auto getValueAsString() const -> std::string
auto thatSplit() const -> GCW::Dbo::Splits::Item::Ptr
auto createDate(const TxItem &_txItem, bool _editable) const -> std::unique_ptr< Wt::WStandardItem >
auto otherSplits() const -> GCW::Dbo::Splits::Item::Vector
auto createEmpty() const -> std::unique_ptr< Wt::WStandardItem >
auto appendTransactionJournal(bool _editable) const -> void
auto createNum(const TxItem &_txItem, bool _editable) const -> std::unique_ptr< Wt::WStandardItem >
auto getFromAccount() const -> std::string
auto flags(bool _editable) const -> Wt::WFlags< Wt::ItemFlag >
auto createText(const std::string &_text) const -> std::unique_ptr< Wt::WStandardItem >
auto appendEmptyRow(bool _editable) -> void
auto loadTransaction(const std::string &_transactionGuid) -> void
Set Transaction.
auto newTransaction(const std::string &_accountGuid1, const std::string &_accountGuid2, const Wt::WDate &_date=Wt::WDate::currentDate(), GCW_NUMERIC _value=GCW_NUMERIC(0), const std::string &_description="") -> void
New Transaction.
Account Register Model.
Definition Model.h:30
static constexpr const int User
static constexpr const int Edit
static WDate currentDate()
std::string toUTF8() const
WString & arg(const std::wstring &value)
#define TR8(X)
Definition define.h:18
#define TR(X)
Definition define.h:17
#define GCW_RECONCILE_NO
Definition gcwglobal.h:29
#define GCW_DEFAULT_DATE
Definition gcwglobal.h:28
#define GCW_DATE_DEFAULT_TIME
Default Time.
Definition gcwglobal.h:27
#define GCW_DATE_FORMAT_DISPLAY
Definition gcwglobal.h:16
#define GCW_NUMERIC
Internal Numeric Type.
Definition gcwglobal.h:40
DECIMAL::decimal_format decimal_format()
Decimal Format Specifier.
Definition GnuCashew.cpp:21
auto newGuid() -> std::string
Generate new GUID string value.
Definition Core.cpp:235
auto load(const std::string &_guid) -> Item::Ptr
Load Account by GUID.
auto byGuid(const std::string &_guid) -> Item::Ptr
Load Account by GUID.
auto fullName(const std::string &_guid) -> std::string
Account Fullname via GUID.
@ NORMAL
normal handling - neg values are red
@ NEGVAL_EXTRA
extra handling - neg values are gold-background-full-line
auto byTransaction(const std::string &_txGuid) -> Item::Vector
Load Splits by Transaction.
Definition Splits.cpp:187
auto add(const std::string &_splitGuid) -> Item::Ptr
Add a single split.
Definition Splits.cpp:65
auto bySplitExcept(const std::string &_splitGuid) -> Item::Vector
Load Splits by Split.
Definition Splits.cpp:144
auto load(const std::string &_splitGuid) -> Item::Ptr
Load a single split.
Definition Splits.cpp:14
auto add(const std::string &_txGuid) -> Item::Ptr
Add Transaction with Guid.
auto load(const std::string &_txGuid) -> Item::Ptr
Load Transaction by Guid.
@ GENERAL_JOURNAL
multi-line ledger that shows all accounts and no balances
@ BASIC_LEDGER
basic one-line per transaction
@ AUTOSPLIT_LEDGER
one-line ledger that auto-opens to multi-line for each selected row
@ TRANSACTION_JOURNAL
multi-line ledger for every row
Definition App.h:18
App * app()
Definition App.cpp:75