GnuCashew ~ Web Application compatible with GnuCash sql data files.
GCW
Loading...
Searching...
No Matches
PaymentWidget.cpp
Go to the documentation of this file.
1#line 2 "src/Gui/BillPay/PaymentWidget.cpp"
2
3#include <fstream>
4#include <filesystem>
5
6#include <Wt/WVBoxLayout.h>
7
8#include "../../Eng/TransactionManager.h"
9#include "../../Glb/Core.h"
10#include "BillPay.h"
11
13PaymentWidget( const std::string & _bpGuid )
14: Wt::WContainerWidget(),
15 m_bpGuid( _bpGuid )
16{
17 addStyleClass( "PaymentWidget" );
18
19 std::cout << __FILE__ << ":" << __LINE__ << " PaymentWidget(" + m_bpGuid + ")" << std::endl;
20
21 /*
22 ** use a layout.
23 */
24 auto lw = setLayout( std::make_unique< Wt::WVBoxLayout >() );
25
26 /*
27 ** This is a complex widget, with a header area with a
28 ** handful of fields, and some controls and whatnot.
29 */
30 auto templtMain =
31 lw->
32 addWidget( std::make_unique< Wt::WTemplate >( TR("gcw_gui.billpay.paymentwidget.form.main") ) );
33
34 /*
35 ** insert the table
36 */
38 m_table-> addStyleClass( "MakePaymentTable" );
39
40 /*
41 ** add the first row of widgets
42 */
43 m_date = table()-> elementAt( 0, 0 )-> addNew< Wt::WDateEdit >( );
44 m_num = table()-> elementAt( 0, 1 )-> addNew< Wt::WLineEdit >( );
45 m_desc = table()-> elementAt( 0, 2 )-> addNew< Wt::WLineEdit >( );
46 m_acct = table()-> elementAt( 0, 3 )-> addNew< AccountRegister::SuggestionEdit >( );
47 m_recon = table()-> elementAt( 0, 4 )-> addNew< Wt::WLineEdit >( );
48// m_debit = table()-> elementAt( 0, 5 )-> addNew< Wt::WLineEdit >( );
49 m_credit = table()-> elementAt( 0, 6 )-> addNew< Wt::WLineEdit >( );
50
51#ifdef INCLUDE_TABLE_WITH_MULTIPLE_INPUT_ROWS
52 /*
53 ** add the edit widget to the tableWidgets vector set
54 */
55 auto _addElement = [&]( size_t _row, size_t _col, const char * styleClass, Wt::WFormWidget * _element )
56 {
58
59 if( m_tableWidgets.size() <= _row )
60 m_tableWidgets.resize( _row + 1 );
61
62 if( m_tableWidgets[_row].size() <= _col )
63 m_tableWidgets[_row].resize( _col + 1 );
64
66 };
67
68 /*
69 ** add a LineEdit to the table
70 */
71 auto _addLineEdit = [&]( size_t _row, size_t _col, const char * _styleClass )
72 {
73 auto element = table()-> elementAt( _row, _col )-> addNew< Wt::WLineEdit >();
75 };
76
77 /*
78 ** add the AccountSeggestionEdit to the table
79 */
80 auto _addAcctEdit = [&]( size_t _row, size_t _col, const char * _styleClass )
81 {
82 auto element = table()-> elementAt( _row, _col )-> addNew< AccountSuggestionEdit >();
84 };
85
86 /*
87 ** build the table
88 */
89 for( int row=1; row<= 3; row++ )
90 {
91 _addLineEdit( row, 1, "num" );
92 _addLineEdit( row, 2, "desc" );
93 _addAcctEdit( row, 3, "acct" );
94 _addLineEdit( row, 4, "recon" );
95 _addLineEdit( row, 5, "debit" );
96 _addLineEdit( row, 6, "credit" );
97 }
98#endif
99
100 /*
101 ** apply styling
102 */
103 m_date -> setFormat( GCW_DATE_FORMAT_DISPLAY );
104 m_date -> addStyleClass( "date" );
105 m_num -> addStyleClass( "num" );
106 m_desc -> addStyleClass( "desc" );
107 m_acct -> addStyleClass( "acct" );
108 m_recon -> addStyleClass( "recon" );
109// m_debit -> addStyleClass( "debit" );
110 m_credit -> addStyleClass( "credit" );
111
112 m_date -> setPlaceholderText( TR("gcw.billPay.pht.date" ) );
113 m_num -> setPlaceholderText( TR("gcw.billPay.pht.num" ) );
114 m_desc -> setPlaceholderText( TR("gcw.billPay.pht.desc" ) );
115 m_acct -> setPlaceholderText( TR("gcw.billPay.pht.acct" ) );
116 m_recon -> setPlaceholderText( TR("gcw.billPay.pht.recon" ) );
117// m_debit -> setPlaceholderText( TR("gcw.billPay.pht.debit" ) );
118 m_credit -> setPlaceholderText( TR("gcw.billPay.pht.credit") );
119
120// m_trans1 -> setToolTip( TR("gcw.billPay.toolTip.trans" ) );
121// m_date1 -> setToolTip( TR("gcw.billPay.toolTip.date" ) );
122// m_memo1 -> setToolTip( TR("gcw.billPay.toolTip.memo" ) );
123// m_confirm -> setToolTip( TR("gcw.billPay.toolTip.confirm" ) );
124
126 m_confirm-> setPlaceholderText( TR("gcw.billPay.pht.confirm") );
127
128 /*
129 ** get all the data loaded
130 */
131 loadData();
132
133} // endPaymentWidget( const std::string & _bpGuid )
134
135auto
138{
139 GCW_NUMERIC retVal(0);
140
141 /*
142 ** this adds the two values together using GAAP...
143 ** the debit is 'added' and the credit is 'subtracted'
144 ** from the value
145 **
146 */
147// GCW_NUMERIC dVal( m_debit -> valueText().toUTF8() );
148 GCW_NUMERIC cVal( m_credit-> valueText().toUTF8() );
149
150 retVal = /* dVal - */ cVal;
151
152 return retVal;
153
154} // endvalue()-> GCW_NUMERIC
155
156auto
159{
160 auto splitItems = GCW::Dbo::Splits::byAccount( GCW::Gui::BillPay::bpItem( bpGuid() ).accountGuid() );
161 for( auto si = splitItems.rbegin(); si != splitItems.rend(); si++ )
162 {
163 auto splitItem = *si;
164 auto txItem = GCW::Dbo::Transactions::byGuid( splitItem-> tx_guid() );
165
166 if( txItem-> num() == "bp" )
167 return txItem;
168
169 } // endfor( ..all splits in reverse.. )
170
172
173} // endlastTx()-> GCW::Dbo::Transactions::Item::Ptr
174
175auto
178{
179 auto bpItem = GCW::Gui::BillPay::bpItem( bpGuid() );
180
181 if( auto txItem = lastTx() )
182 {
183 for( auto splitItem: GCW::Dbo::Splits::byTransaction( txItem-> guid() ) )
184 {
185 if( splitItem-> account_guid() != bpItem.accountGuid() )
186 return splitItem ;
187
188 } // endfor( ..all splits.. )
189
190 } // endif( auto txItem = lastTx() )
191
193
194} // endlastSplit()-> GCW::Dbo::Splits::Item::Ptr
195
196auto
198loadData()-> void
199{
200 /*
201 ** be safe
202 */
203 if( m_bpGuid == "" )
204 return;
205
206 auto bpItem = GCW::Gui::BillPay::bpItem( bpGuid() );
207
208 auto desc = bpItem.nickname();
209 if( bpItem.last4() != "" )
210 desc += " (" + bpItem.last4() + ")";
211
212 m_date -> setValueText( GCW::Core::currentDateTimeDisplayString() );
213 m_num -> setValueText( "bp" );
214 m_desc -> setValueText( desc );
215 m_recon -> setValueText( "n" );
216
217 if( auto splitItem = lastSplit() )
218 m_acct-> setValueText( GCW::Dbo::Accounts::fullName( splitItem-> account_guid() ) );
219
220} // endloadData()-> void
221
222auto
224saveData()-> bool
225{
226 /*
227 ** make sure the account is assigned
228 */
229 if( m_acct-> valueText() == "" )
230 {
231 Wt::WMessageBox::show( TR("gcw.billPay.lbl.billPay"), TR("gcw.billPay.save.needaccount"), Wt::StandardButton::Ok );
232 return false;
233 }
234
235 /*
236 ** make sure there is a (+) positive value
237 */
238 if( value() < 1 )
239 {
240 Wt::WMessageBox::show( TR("gcw.billPay.lbl.billPay"), TR("gcw.billPay.save.needpositive"), Wt::StandardButton::Ok );
241 return false;
242 }
243
244 /*
245 ** load up some stuff so we can work
246 */
247 auto bpItem = GCW::Gui::BillPay::bpItem( m_bpGuid );
248 auto acctItem = GCW::Dbo::Accounts::byFullName( m_acct-> valueText() );
249
250#ifdef NEVER
251 std::cout << __FILE__ << ":" << __LINE__
252 << " " << bpItem.accountFullName()
253 << " " << bpItem.accountGuid()
254 << " " << bpItem.nickname()
255 << std::endl;
256
257 std::cout << __FILE__ << ":" << __LINE__
258 << " vt:" << m_acct-> valueText()
259 << " id:" << acctItem-> guid()
260 << " ds:" << acctItem-> description()
261 << std::endl;
262#endif
263
264 /*
265 ** now build up a new transaction
266 **
267 ** BUGBUG: note, this procedure will save 'm_confirm' which is the confirmation notes
268 ** to the split item memo field. This can cause gnucash to improperly display
269 ** the value of that memo field if that value that was set there is multi-line
270 ** (ie; contains carriage return codes in the line string) If the value is
271 ** multi-line, it is able to store properly in the sql database, but the display
272 ** in gnucash does not expand to show the multiple lines, instead it shows
273 ** everything on one line with 'line-return' indicators in it. It is editable,
274 ** but I don't know the long-term impact of storing data like this that gnucash
275 ** might have to deal with.
276 */
277 {
279 transMan.newTransaction( bpItem.accountGuid(), acctItem-> guid(), m_date-> date(), value(), m_desc-> valueText().toUTF8() );
280 transMan.setValue ( acctItem-> guid() , -value() );
281 transMan.setNotes ( bpItem.accountGuid(), m_confirm-> valueText().toUTF8() ); /// \todo insure gnucash can tolerate crlf in the middle of the memo field
282 transMan.setNum ( m_num-> valueText().toUTF8() );
283 }
284
285 std::string logMessage;
287 logMessage += "\tpayment";
288 logMessage += "\t" + GCW::Dbo::Accounts::fullName( bpItem.accountGuid() );
289 logMessage += "\t" + GCW::Dbo::Accounts::fullName( acctItem-> guid() );
290 logMessage += "\t" + GCW::Core::dateStorageString( m_date-> date() );
291 logMessage += "\t" + toString( value() );
292 logMessage += "\t" + toOneLineString( m_confirm-> valueText().toUTF8() );
293
294 {
295 auto fileName =
296 Wt::WString("logs/{1}-billPay.tsv")
297 .arg( Wt::WDate::currentDate().toString("yyyy-MM-dd") )
298 .toUTF8()
299 ;
300
301 bool hasHeader = std::filesystem::exists( fileName );
302
303 std::ofstream file( fileName, std::ios_base::out | std::ios_base::app );
304
305 if( !hasHeader )
306 file << "dateTime\taction\ttoAccount\tfromAccount\tpaymentDate\tpaymentAmount\tconfirmation" << std::endl;
307
308 file << logMessage << std::endl;
309
310 std::cout << __FILE__ << ":" << __LINE__ << " " << fileName << ":\t" << logMessage << std::endl;
311
312 }
313
314 /*
315 ** good save
316 */
317 return true;
318
319} // endsaveData()-> bool
320
321auto
323paymentDate() const-> std::string
324{
325 return m_date-> valueText().toUTF8();
326
327} // endpaymentDate() const-> std::string
328
329
331PaymentWidgetDialog( const std::string & _bpGuid )
332{
333 addStyleClass( "PaymentWidgetDialog" );
334
335 rejectWhenEscapePressed( true );
336 setClosable( true );
337
338 setWindowTitle( TR( "gcw.billPay.dialog.title" ) );
339
340 m_editWidget = contents()-> addNew< PaymentWidget >( _bpGuid );
341
342 auto pbSave = titleBar()-> addNew< Wt::WPushButton >( TR( "gcw.billPay.lbl.save" ) );
343 auto pbCancel = titleBar()-> addNew< Wt::WPushButton >( TR( "gcw.billPay.lbl.cancel" ) );
344
345 pbSave -> setStyleClass( "btn-xs" );
346 pbCancel -> setStyleClass( "btn-xs" );
347
348 pbSave -> clicked().connect( this, &PaymentWidgetDialog::saveData );
349 pbCancel -> clicked().connect( this, &Wt::WDialog::reject );
350
351} // endPaymentWidgetDialog( const std::string & _bpGuid )
352
353auto
355saveData()-> void
356{
357 if( m_editWidget-> saveData() )
358 accept();
359
360} // endsaveData()-> void
361
362
363auto
365paymentDate() const-> std::string
366{
367 return m_editWidget-> paymentDate();
368
369} // endpaymentDate() const-> std::string
370
371
Wt::Dbo::ptr< Item > Ptr
Definition BaseItem.h:39
Wt::Dbo::ptr< Item > Ptr
auto setNum(const std::string &_value) -> void
auto setNotes(const std::string &_acctGuid, const std::string &_value) -> void
auto setValue(GCW_NUMERIC _value) -> void
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.
PaymentWidgetDialog(const std::string &_bpGuid)
auto paymentDate() const -> std::string
auto lastSplit() -> GCW::Dbo::Splits::Item::Ptr
Last Split.
std::vector< std::vector< Wt::WFormWidget * > > m_tableWidgets
auto table() -> Wt::WTable *
AccountRegister::SuggestionEdit * m_acct
auto value() -> GCW_NUMERIC
Value.
PaymentWidget(const std::string &_bpGuid)
auto paymentDate() const -> std::string
auto lastTx() -> GCW::Dbo::Transactions::Item::Ptr
Last Transaction.
Widget * addNew(Args &&...args)
void setLayout(std::unique_ptr< WLayout > layout)
virtual void addWidget(std::unique_ptr< WWidget > widget)
static WDate currentDate()
virtual void reject()
std::string toUTF8() const
WString & arg(const std::wstring &value)
virtual WString styleClass() const override
virtual void addStyleClass(const WString &styleClass, bool force=false) override
#define TR(X)
Definition define.h:17
#define GCW_DATE_FORMAT_DISPLAY
Definition gcwglobal.h:16
#define GCW_NUMERIC
Internal Numeric Type.
Definition gcwglobal.h:40
auto dateStorageString(const Wt::WDate *_date) -> std::string
Definition Core.cpp:280
auto currentDateTimeDisplayString() -> std::string
Definition Core.cpp:331
auto currentDateTimeStorageString() -> std::string
Definition Core.cpp:310
auto byFullName(const std::string &_fullName) -> Item::Ptr
Load Account by 'full name' with ':' account separator.
auto fullName(const std::string &_guid) -> std::string
Account Fullname via GUID.
auto byTransaction(const std::string &_txGuid) -> Item::Vector
Load Splits by Transaction.
Definition Splits.cpp:193
auto byAccount(const std::string &_accountGuid) -> Item::Vector
Load Splits by Account.
Definition Splits.cpp:76
auto byGuid(const std::string &_txGuid) -> Item::Ptr
Load Transaction by Guid.
auto bpItem(const std::string &_guid) -> GCW::Gui::BillPay::Item
Bill Pay Item.
Definition BillPay.cpp:33
auto toOneLineString(const std::string &_input) -> std::string
Convert a string with new-lines.
Definition BillPay.cpp:68
auto toString(int _value) -> std::string
Convert Integer to String.
Definition BillPay.cpp:55