GnuCashew ~ Web Application compatible with GnuCash sql data files.
GCW
Loading...
Searching...
No Matches
TableModel.cpp
Go to the documentation of this file.
1#line 2 "src/Gui/BillPay/TableModel.cpp"
2
3#include <Wt/WStandardItem.h>
4
5#include "../../App.h"
6#include "../../Glb/Core.h"
7#include "../Dbo/Vars/Vars.h"
8#include "BillPay.h"
9
10namespace {
11
13{
14// name, width, alignment
15 { "accountKey" , "120px" , Wt::AlignmentFlag::Left },
16 { "last4" , "60px" , Wt::AlignmentFlag::Center },
17 { "Nickname" , "100px" , Wt::AlignmentFlag::Left },
18 { "Gp" , "50px" , Wt::AlignmentFlag::Center },
19 { "Dy" , "50px" , Wt::AlignmentFlag::Center },
20 { "Min" , "50px" , Wt::AlignmentFlag::Right },
21 { "Bgt" , "50px" , Wt::AlignmentFlag::Right },
22 { "Actual" , "75px" , Wt::AlignmentFlag::Right },
23 { "Au" , "50px" , Wt::AlignmentFlag::Center },
24 { "01" , "35px" , Wt::AlignmentFlag::Center },
25 { "02" , "35px" , Wt::AlignmentFlag::Center },
26 { "03" , "35px" , Wt::AlignmentFlag::Center },
27 { "04" , "35px" , Wt::AlignmentFlag::Center },
28 { "05" , "35px" , Wt::AlignmentFlag::Center },
29 { "06" , "35px" , Wt::AlignmentFlag::Center },
30 { "07" , "35px" , Wt::AlignmentFlag::Center },
31 { "08" , "35px" , Wt::AlignmentFlag::Center },
32 { "09" , "35px" , Wt::AlignmentFlag::Center },
33 { "10" , "35px" , Wt::AlignmentFlag::Center },
34 { "11" , "35px" , Wt::AlignmentFlag::Center },
35 { "12" , "35px" , Wt::AlignmentFlag::Center },
36};
37
38#define COLUMN_COUNT (sizeof(columns)/sizeof(GCW::Gui::BillPay::ColumnDef_t))
39
40} // endnamespace {
41
43TableModel( int _selectedMonth, int _selectedYear, const Status _status )
44: Wt::WStandardItemModel( 0, COLUMN_COUNT ),
45 m_status( _status )
46{
47
48 auto _toolTip = [&]( int _col )
49 {
50 return TR( std::string("gcw.billPay.ttp." ) + columns[ _col ].name );
51 };
52
53 /*
54 ** Load the header _only_ on the 'unpaid' view.
55 **
56 ** The unpaid view is represented first in the widget so that
57 ** bills that are unpaid appear at the top of the browser
58 ** window. The unpaid view, therefore, is the only view
59 ** that includes the header. If the other two remaining
60 ** views (Paid, Disabled) also had a header the gui would
61 ** get too cluttered, so those headers are left blank.
62 */
64 {
65 for( int col = 1; col< COLUMN_COUNT; col++ )
66 {
67 setHeaderData( col, Wt::Orientation::Horizontal, columns[ col ].name , Wt::ItemDataRole::Display );
68 setHeaderData( col, Wt::Orientation::Horizontal, _toolTip( col ) , Wt::ItemDataRole::ToolTip );
69 setHeaderData( col, Wt::Orientation::Horizontal, "pointer" , Wt::ItemDataRole::StyleClass );
70 }
71 }
72
73 /*
74 ** Load the data based on the month selected.
75 */
76 loadData( _selectedMonth, _selectedYear );
77
78} // endTableModel( const Status _status )
79
80
81auto
83filteredOut( const GCW::Gui::BillPay::Item & _bpItem )-> bool
84{
85 /*
86 ** if there is no filter, then this item should not be filtered out
87 */
88 if( m_filter.length() == 0 )
89 return false;
90
91 auto _foundIn = [this]( const std::string & _a )
92 {
93 std::string a = GCW::Core::tolower( _a );
94 std::string b = GCW::Core::tolower( m_filter );
95
96 /*
97 ** if the sub-string is not found, return false
98 */
99 if( a.find( b ) == std::string::npos )
100 return false;
101
102 /*
103 ** the sub-string is found
104 */
105 return true;
106
107 };
108
109 /*
110 ** default to 'filter out'
111 */
112 auto retVal = true;
113
114 if( _foundIn( _bpItem.accountFullName() ) ) retVal = false;
115 if( _foundIn( _bpItem.nickname() ) ) retVal = false;
116 if( _foundIn( _bpItem.url() ) ) retVal = false;
117 if( _foundIn( _bpItem.last4() ) ) retVal = false;
118 if( _foundIn( _bpItem.note() ) ) retVal = false;
119
120 return retVal;
121
122} // endfilteredOut( const GCW::Gui::BillPay::Item & _bpItem )-> bool
123
124
125auto
127loadData( int _selectedMonth, int _selectedYear )-> void
128{
129 m_selectedMonth = _selectedMonth;
130 m_selectedYear = _selectedYear;
131
132 /*!
133 ** On load, the first column-label is set to indicate the
134 ** model type as well as the month selected.
135 **
136 ** \code
137 ** Change the label on the column-0, example;
138 ** "03 Unpaid"
139 ** "06 Paid"
140 ** "12 Disabled"
141 ** \endcode
142 **
143 */
144 setHeaderData
145 (
146 0,
147 Wt::Orientation::Horizontal,
148 toString( _selectedYear ) + "-" + toString( _selectedMonth ) + " " + asString( m_status ),
150 );
151
152 /*!
153 ** On load, all existing data in the model is first dumped.
154 */
155 while( rowCount() > 0 )
156 takeRow( 0 );
157
158 /*!
159 ** Get all the var items that are for the 'managed bill pay item' (mbpi)
160 ** in to a resultList that will then be used to load the
161 ** resulting model.
162 */
163 Wt::Dbo::Transaction t( GCW::app()-> gnucashew_session() );
165
166 /*
167 ** Calculate our yes/no status for grabbing items.
168 ** For each view;
169 ** yes = Unpaid
170 ** no = Paid
171 ** maybe = Pending
172 */
173 std::string yesNo = "yes";
174 if( m_status == GCW::Gui::BillPay::Status::Pending )
175 yesNo = "maybe";
176 if( m_status == GCW::Gui::BillPay::Status::Unpaid )
177 yesNo = "no";
178
179 /*!
180 ** Run the resultList collection through an analyzer that will
181 ** extract billpay items that match the selection criteria of
182 ** month/paid/unpaid/disabled/yes/no/filter accordingly.
183 */
184 std::vector< GCW::Gui::BillPay::Item > bpItems;
185 for( auto item : items )
186 {
187 auto bpItem = GCW::Gui::BillPay::Item( item );
188
189 /*
190 ** if a filter is being used, apply it and filter-out
191 ** any items that don't meet the filter criteria
192 */
193 if( filteredOut( bpItem ) )
194 continue; // skip to the next
195
196 /*
197 ** Calculate these boolean.
198 */
199 auto isActive = bpItem.isActive () == "yes";
200 auto isVisible = bpItem.isVisible() == "yes";
201
202 /*
203 ** This is for Paid, Unpaid, Pending (not Disabled).
204 */
205 if( m_status == GCW::Gui::BillPay::Status::Paid
208 )
209 {
210 /*
211 ** The item ~must~ be active ~and~ visible.
212 */
213 if( isActive && isVisible )
214 {
215 /*
216 ** Get the .var. string that has the combo-box values for the monthly
217 ** indicators of what has been paid and what has not. Depending on the
218 ** value of that payment status, it must therefore match the yes/no clause
219 ** we calculated above. If it's a match, we grab it.
220 */
221 if( bpItem.cb( _selectedMonth ) == yesNo )
222// if( i-> getVarString( "cb" + GCW::Gui::BillPay::toString( _selectedMonth ) ) == yesNo )
223 bpItems.push_back( bpItem );
224
225 } // endif( isActive && isVisible )
226
227 } // endif( ..is active.. )
228
229 /*
230 ** This is for Disabled.
231 */
232 else
233 if( m_status == GCW::Gui::BillPay::Status::Inactive ) // capture disabled items here
234 {
235 /*
236 ** Disabled items are either notActive ~or~ notVisible.
237 */
238 if( !isActive || !isVisible )
239 bpItems.push_back( bpItem );
240
241 } // endelseif( .disabled. )
242
243 } // endfor( auto i : items )
244
245 /*!
246 ** Sort all the items by the account group.dueDay. (The
247 ** user is not allowed to sort these views so we do it) This sorts the items
248 ** with the items that are due first, above those that are due next.
249 */
250 sort( bpItems );
251
252 /*!
253 ** Each item is processed out of the sorted vector and placed
254 ** in to the item model.
255 */
256 for( auto bpItem : bpItems )
257 {
258 /*
259 ** Grab a few handles.
260 */
261 auto accountName = std::make_unique< Wt::WStandardItem >();
262 auto accountGuid = bpItem.accountGuid();
263
264 if( accountGuid != "" )
265 {
266 /*
267 ** set the bpItem.guid so we can edit this row
268 */
269 accountName-> setData( bpItem.guid(), Wt::ItemDataRole::User );
270
271 /*
272 ** fetch the account item
273 */
274 auto accountItem = GCW::Dbo::Accounts::byGuid( accountGuid );
275
276 /*
277 ** sometimes the 'account' can get lost, so check first the
278 ** account still exists.
279 */
280 if( accountItem )
281 {
282 /*
283 ** build the account column to;
284 ** display the account name
285 ** carry the account-full-name as a toolTip,
286 ** carry the guid of the originating bpItem
287 */
288 accountName-> setData( accountItem-> name() , Wt::ItemDataRole::Display );
289 accountName-> setToolTip( GCW::Dbo::Accounts::fullName( accountGuid ) );
290 }
291
292 /*
293 ** whelp, looks like we lost the account... hmmph
294 */
295 else
296 {
297 accountName-> setData( "~missing~" , Wt::ItemDataRole::Display );
298 }
299
300 } // endif( accountGuid != "" )
301
302 /*
303 ** The columns are pushed in to .columns. variable.
304 */
305 std::vector< std::unique_ptr< Wt::WStandardItem > > columns;
306 columns.push_back( std::move( accountName ) );
307 columns.push_back( std::make_unique< Wt::WStandardItem >( bpItem.last4 () ) );
308 columns.push_back( std::make_unique< Wt::WStandardItem >( bpItem.nickname () ) );
309 columns.push_back( std::make_unique< Wt::WStandardItem >( bpItem.group () ) );
310 columns.push_back( std::make_unique< Wt::WStandardItem >( bpItem.dueDay () ) );
311 columns.push_back( std::make_unique< Wt::WStandardItem >( bpItem.minimum () ) );
312 columns.push_back( std::make_unique< Wt::WStandardItem >( bpItem.budget () ) );
313 columns.push_back( std::make_unique< Wt::WStandardItem >( bpItem.actual () ) );
314 columns.push_back( std::make_unique< Wt::WStandardItem >( bpItem.autoPay () ) );
315
316 /*
317 ** Load 12-columns, one for each month.
318 */
319 for( int month=1; month<= 12; month++ )
320 {
321 auto cb = std::make_unique< Wt::WStandardItem >( bpItem.cbtr( month ) );
322
323 /*!
324 ** While building the 'month columns', apply a style class to the
325 ** column of items according to the month selected. This causes
326 ** the current selected column to be highlighted within the table
327 ** view in the browser.
328 **
329 ** \image html BillPayColumnSelector.png
330 */
331 if( _selectedMonth == month )
332 cb-> setStyleClass( "colsel" );
333
334 columns.push_back( std::move( cb ) );
335
336 } // endfor( int i=1; i<= 12; i++ )
337
338 /*
339 ** Push everything in to the model.
340 */
341 appendRow( std::move( columns ) );
342
343 } // endfor( auto bpItem : bpItems )
344
345} // endloadData( int _selectedMonth )-> void
346
347auto
350{
351 return columns[col];
352}
353
354auto
356sort( std::vector< GCW::Gui::BillPay::Item > & _bpItems )-> void
357{
358 /*!
359 ** Sort the vector of bpItems by group.dueDay
360 */
361 std::sort
362 (
363 _bpItems.begin(),
364 _bpItems.end(),
365 []( const GCW::Gui::BillPay::Item item1,
366 const GCW::Gui::BillPay::Item item2
367 )
368 {
369// auto account1 = GCW::Dbo::Accounts::byGuid( item1-> keyField() );
370// auto account2 = GCW::Dbo::Accounts::byGuid( item2-> keyField() );
371// auto name1 = account1-> name();
372// auto name2 = account2-> name();
373
374// auto name1 = item1.nickname();
375// auto name2 = item2.nickname();
376
377 /*
378 ** return .bool. of the comparison
379 */
380 return item1.sortValue()
381 < item2.sortValue()
382 ;
383 }
384 );
385
386} // endsort( std::vector< GCW::Gui::BillPay::Item > & _bpItems )-> void
387
388auto
390setFilter( const std::string & _filter )-> void
391{
392 /*
393 ** we want at least 3 characters before filtering
394 */
395// if( _filter.length() < 3 )
396// m_filter = "";
397// else
398 m_filter = _filter;
399
400 /*
401 ** Load the data based on the month selected.
402 */
403 loadData( m_selectedMonth, m_selectedYear );
404
405} // endsetFilter( const std::string & _filter )-> void
406
407
#define GCW_GUI_BILLPAY_ITEM_CFY
Definition BillPay.h:41
#define COLUMN_COUNT
auto loadData(int _selectedMonth, int _selectedYear) -> void
Reload the data based on the selected month.
TableModel(int _selectedMonth, int _selectedYear, Status _status)
ctor
auto columnDef(int _col) -> ColumnDef_t
Column Definition.
auto setFilter(const std::string &_filter) -> void
Status m_status
Model Status.
Definition TableModel.h:135
auto filteredOut(const GCW::Gui::BillPay::Item &_bpItem) -> bool
auto sort(std::vector< GCW::Gui::BillPay::Item > &_bpItems) -> void
Sorter.
static constexpr const int User
static constexpr const int ToolTip
static constexpr const int Display
static constexpr const int StyleClass
virtual bool setHeaderData(int section, Orientation orientation, const cpp17::any &value, ItemDataRole role=ItemDataRole::Edit)
#define TR(X)
Definition define.h:17
std::string tolower(const std::string &s)
Definition Core.cpp:88
auto byGuid(const std::string &_guid) -> Item::Ptr
Load Account by GUID.
auto fullName(const std::string &_guid) -> std::string
Account Fullname via GUID.
auto getByCfy(const std::string &_cfyValue) -> GCW::Dbo::Vars::Item::Vector
Definition Vars.cpp:75
auto bpItem(const std::string &_guid) -> GCW::Gui::BillPay::Item
Bill Pay Item.
Definition BillPay.cpp:33
auto bpItems() -> std::vector< GCW::Gui::BillPay::Item >
Bill Pay Items.
Definition BillPay.cpp:19
Status
Bill Status.
Definition Status.h:27
@ Pending
Pending Status.
@ Inactive
Disabled Status.
@ Unpaid
Unpaid Status.
auto asString(Status _status) -> std::string
Get Status as String.
Definition Status.cpp:7
auto toString(int _value) -> std::string
Convert Integer to String.
Definition BillPay.cpp:55
App * app()
Definition App.cpp:75