Merge lp:~abdsandr/financisto/abdsandr into lp:~financisto-dev/financisto/trunk

Proposed by Abdsandryk Souza
Status: Merged
Merge reported by: Denis Solonenko
Merged at revision: not available
Proposed branch: lp:~abdsandr/financisto/abdsandr
Merge into: lp:~financisto-dev/financisto/trunk
Diff against target: 2474 lines (+1698/-46)
28 files modified
.classpath (+1/-0)
AndroidManifest.xml (+2/-0)
assets/database/alter/20100721_0737_add_bill_filtering_pars_to_account.sql (+3/-0)
res/layout/credit_card_transaction.xml (+25/-0)
res/layout/monthly_view.xml (+77/-0)
res/menu/blotter_menu.xml (+5/-0)
res/menu/ccard_blotter_menu.xml (+8/-0)
res/values-pt-rBR/strings.xml (+47/-9)
res/values/ids.xml (+2/-1)
res/values/strings.xml (+37/-1)
res/xml/preferences.xml (+11/-0)
src/ru/orangesoftware/financisto/activity/AbstractTransactionActivity.java (+20/-0)
src/ru/orangesoftware/financisto/activity/AccountActivity.java (+63/-0)
src/ru/orangesoftware/financisto/activity/BlotterActivity.java (+84/-0)
src/ru/orangesoftware/financisto/activity/MainActivity.java (+250/-3)
src/ru/orangesoftware/financisto/activity/MonthlyViewActivity.java (+510/-0)
src/ru/orangesoftware/financisto/adapter/CreditCardStatementAdapter.java (+217/-0)
src/ru/orangesoftware/financisto/backup/DatabaseImport.java (+30/-4)
src/ru/orangesoftware/financisto/backup/SettingsNotConfiguredException.java (+33/-0)
src/ru/orangesoftware/financisto/db/DatabaseAdapter.java (+129/-0)
src/ru/orangesoftware/financisto/db/DatabaseHelper.java (+23/-3)
src/ru/orangesoftware/financisto/export/Export.java (+51/-6)
src/ru/orangesoftware/financisto/export/ImportExportAsyncTask.java (+10/-10)
src/ru/orangesoftware/financisto/model/Account.java (+9/-0)
src/ru/orangesoftware/financisto/model/AccountType.java (+12/-8)
src/ru/orangesoftware/financisto/model/Transaction.java (+10/-0)
src/ru/orangesoftware/financisto/utils/MyPreferences.java (+24/-0)
src/ru/orangesoftware/financisto/widget/AmountInput.java (+5/-1)
To merge this branch: bzr merge lp:~abdsandr/financisto/abdsandr
Reviewer Review Type Date Requested Status
Financisto Developers Pending
Review via email: mp+33325@code.launchpad.net

Description of the change

Adding functionalities: Google Docs backup, monthly preview and credit card statements.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.classpath'
2--- .classpath 2010-07-14 02:47:40 +0000
3+++ .classpath 2010-08-22 11:18:40 +0000
4@@ -6,5 +6,6 @@
5 <classpathentry kind="lib" path="lib/rfc2445-no-joda.jar"/>
6 <classpathentry kind="src" path="src"/>
7 <classpathentry kind="src" path="gen"/>
8+ <classpathentry kind="lib" path="lib/GDocsAPI.jar"/>
9 <classpathentry kind="output" path="bin"/>
10 </classpath>
11
12=== modified file 'AndroidManifest.xml'
13--- AndroidManifest.xml 2010-07-27 13:00:40 +0000
14+++ AndroidManifest.xml 2010-08-22 11:18:40 +0000
15@@ -153,6 +153,8 @@
16
17 <activity android:name=".activity.CsvExportActivity" android:label="@string/csv_export"
18 android:theme="@android:style/Theme.Dialog" android:configChanges="orientation|keyboardHidden"/>
19+
20+ <activity android:name=".activity.MonthlyViewActivity" android:label="@string/monthly_view"/>
21
22 </application>
23
24
25=== added file 'assets/database/alter/20100721_0737_add_bill_filtering_pars_to_account.sql'
26--- assets/database/alter/20100721_0737_add_bill_filtering_pars_to_account.sql 1970-01-01 00:00:00 +0000
27+++ assets/database/alter/20100721_0737_add_bill_filtering_pars_to_account.sql 2010-08-22 11:18:40 +0000
28@@ -0,0 +1,3 @@
29+ALTER TABLE account ADD COLUMN closing_day integer not null default 0;
30+ALTER TABLE account ADD COLUMN payment_day integer not null default 0;
31+ALTER TABLE transactions ADD COLUMN is_ccard_payment integer not null default 0;
32\ No newline at end of file
33
34=== added file 'lib/GDocsAPI.jar'
35Binary files lib/GDocsAPI.jar 1970-01-01 00:00:00 +0000 and lib/GDocsAPI.jar 2010-08-22 11:18:40 +0000 differ
36=== added file 'res/drawable/btn_next.png'
37Binary files res/drawable/btn_next.png 1970-01-01 00:00:00 +0000 and res/drawable/btn_next.png 2010-08-22 11:18:40 +0000 differ
38=== added file 'res/drawable/btn_previous.png'
39Binary files res/drawable/btn_previous.png 1970-01-01 00:00:00 +0000 and res/drawable/btn_previous.png 2010-08-22 11:18:40 +0000 differ
40=== added file 'res/drawable/ic_menu_bill_off.png'
41Binary files res/drawable/ic_menu_bill_off.png 1970-01-01 00:00:00 +0000 and res/drawable/ic_menu_bill_off.png 2010-08-22 11:18:40 +0000 differ
42=== added file 'res/drawable/ic_menu_bill_on.png'
43Binary files res/drawable/ic_menu_bill_on.png 1970-01-01 00:00:00 +0000 and res/drawable/ic_menu_bill_on.png 2010-08-22 11:18:40 +0000 differ
44=== added file 'res/drawable/ic_menu_calendar.png'
45Binary files res/drawable/ic_menu_calendar.png 1970-01-01 00:00:00 +0000 and res/drawable/ic_menu_calendar.png 2010-08-22 11:18:40 +0000 differ
46=== added file 'res/drawable/ic_menu_calendar_off.png'
47Binary files res/drawable/ic_menu_calendar_off.png 1970-01-01 00:00:00 +0000 and res/drawable/ic_menu_calendar_off.png 2010-08-22 11:18:40 +0000 differ
48=== added file 'res/layout/credit_card_transaction.xml'
49--- res/layout/credit_card_transaction.xml 1970-01-01 00:00:00 +0000
50+++ res/layout/credit_card_transaction.xml 2010-08-22 11:18:40 +0000
51@@ -0,0 +1,25 @@
52+<?xml version="1.0" encoding="utf-8"?>
53+<LinearLayout
54+ xmlns:android="http://schemas.android.com/apk/res/android"
55+ android:layout_width="fill_parent"
56+ android:layout_height="wrap_content">
57+
58+ <TextView android:id="@+id/list_date"
59+ android:layout_width="wrap_content"
60+ android:layout_height="wrap_content"
61+ android:padding="3px" />
62+
63+ <TextView android:id="@+id/list_note"
64+ android:layout_width="fill_parent"
65+ android:layout_height="wrap_content"
66+ android:gravity="left"
67+ android:layout_weight="1"
68+ android:padding="3px" />
69+
70+ <TextView android:id="@+id/list_value"
71+ android:layout_width="wrap_content"
72+ android:layout_height="wrap_content"
73+ android:gravity="right"
74+ android:padding="3px" />
75+
76+</LinearLayout>
77\ No newline at end of file
78
79=== added file 'res/layout/monthly_view.xml'
80--- res/layout/monthly_view.xml 1970-01-01 00:00:00 +0000
81+++ res/layout/monthly_view.xml 2010-08-22 11:18:40 +0000
82@@ -0,0 +1,77 @@
83+<?xml version="1.0" encoding="utf-8"?>
84+<!--
85+
86+ Contributors:
87+ Abdsandryk - initial API and implementation
88+-->
89+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
90+ android:layout_height="fill_parent"
91+ android:layout_width="fill_parent"
92+ android:orientation="vertical">
93+
94+ <LinearLayout
95+ android:layout_height="wrap_content"
96+ android:layout_width="fill_parent"
97+ android:background="#000"
98+ android:paddingTop="2dp">
99+
100+ <ImageButton android:id="@+id/bt_month_previous"
101+ android:layout_width="wrap_content"
102+ android:layout_height="wrap_content"
103+ android:src="@drawable/btn_previous" />
104+
105+ <TextView android:id="@+id/monthly_view_title"
106+ android:layout_width="fill_parent"
107+ android:layout_height="fill_parent"
108+ android:layout_weight="1"
109+ android:textStyle="bold"
110+ android:gravity="center"
111+ android:textColor="#FFF" />
112+
113+ <ImageButton android:id="@+id/bt_month_next"
114+ android:layout_width="wrap_content"
115+ android:layout_height="wrap_content"
116+ android:src="@drawable/btn_next" />
117+
118+ </LinearLayout>
119+
120+ <ListView android:id="@android:id/list"
121+ android:layout_width="fill_parent"
122+ android:layout_height="wrap_content"
123+ android:layout_weight="1"
124+ android:background="#111111"
125+ android:visibility="gone" />
126+
127+ <TextView android:id="@id/android:empty"
128+ android:layout_width="fill_parent"
129+ android:layout_height="wrap_content"
130+ android:layout_weight="1"
131+ android:gravity="center"
132+ android:text="@string/no_transactions" />
133+
134+ <LinearLayout
135+ android:layout_height="wrap_content"
136+ android:layout_width="fill_parent"
137+ android:background="#000"
138+ android:paddingTop="2dp">
139+
140+ <TextView android:id="@+id/monthly_result_label"
141+ android:layout_width="wrap_content"
142+ android:layout_height="fill_parent"
143+ android:gravity="left|center"
144+ android:textColor="#000"
145+ android:background="#DEDEDE"
146+ android:text="@string/bill_on" />
147+
148+ <TextView android:id="@+id/monthly_result"
149+ android:layout_height="fill_parent"
150+ android:layout_width="fill_parent"
151+ android:layout_weight="1"
152+ android:gravity="right|center"
153+ android:textStyle="bold"
154+ android:background="#DEDEDE"
155+ android:textColor="#000"
156+ android:visibility="gone" />
157+
158+ </LinearLayout>
159+</LinearLayout>
160\ No newline at end of file
161
162=== added directory 'res/menu'
163=== added file 'res/menu/blotter_menu.xml'
164--- res/menu/blotter_menu.xml 1970-01-01 00:00:00 +0000
165+++ res/menu/blotter_menu.xml 2010-08-22 11:18:40 +0000
166@@ -0,0 +1,5 @@
167+<menu xmlns:android="http://schemas.android.com/apk/res/android">
168+ <item android:id="@+id/opt_menu_month"
169+ android:icon="@drawable/ic_menu_calendar_off"
170+ android:title="@string/monthly_view" />
171+</menu>
172
173=== added file 'res/menu/ccard_blotter_menu.xml'
174--- res/menu/ccard_blotter_menu.xml 1970-01-01 00:00:00 +0000
175+++ res/menu/ccard_blotter_menu.xml 2010-08-22 11:18:40 +0000
176@@ -0,0 +1,8 @@
177+<menu xmlns:android="http://schemas.android.com/apk/res/android">
178+ <item android:id="@+id/opt_menu_month"
179+ android:icon="@drawable/ic_menu_calendar_off"
180+ android:title="@string/monthly_view" />
181+ <item android:id="@+id/opt_menu_bill"
182+ android:icon="@drawable/ic_menu_bill_off"
183+ android:title="@string/ccard_statement" />
184+</menu>
185
186=== modified file 'res/values-pt-rBR/strings.xml'
187--- res/values-pt-rBR/strings.xml 2010-08-04 21:13:31 +0000
188+++ res/values-pt-rBR/strings.xml 2010-08-22 11:18:40 +0000
189@@ -9,6 +9,7 @@
190 Contributors:
191 Denis Solonenko - initial API and implementation
192 Charles HG Santos - Brazilian translation [http://www.provadigital.com.br]
193+ Abdsandryk Souza / Rodrigo Sousa - adding new strings
194 -->
195 <resources>
196 <string name="accounts">Contas</string>
197@@ -50,7 +51,7 @@
198 <string name="transfer">Transferência</string>
199 <string name="confirmation">Confirmação</string>
200 <string name="delete_category_dialog">Apagar esta categoria e todas as sub-categorias (se existirem)?</string>
201- <string name="currency_delete_alert">Não é possível apagar uma moeda em uso...</string>
202+ <string name="currency_delete_alert">Não é possível apagar uma moeda em uso.</string>
203 <string name="yes">Sim</string>
204 <string name="no">Não</string>
205 <string name="error">Erro</string>
206@@ -64,7 +65,7 @@
207 <string name="period_from">Período de</string>
208 <string name="period_to">Período para</string>
209 <string name="period_recur">Período recorrente</string>
210- <string name="preferences">Preferencias</string>
211+ <string name="preferences">Preferências</string>
212 <string name="amount_picker">Separador de valor</string>
213 <string name="integer_part_title">Número de dígitos</string>
214 <string name="use_hundredth_title">Usar centésimos</string>
215@@ -98,7 +99,7 @@
216 <string name="no_locations">Sem localizações</string>
217 <string name="use_gps">Usar GPS</string>
218 <string name="use_gps_summary">Usar GPS para pegar a localização nas transações</string>
219- <string name="use_my_location">Ussar Minha Localização</string>
220+ <string name="use_my_location">Usar Minha Localização</string>
221 <string name="use_my_location_summary">Usar Minha Localização para pegar a localização atual para novas transações</string>
222 <string name="select_location">Escolher localização</string>
223 <string name="no_fix">Localização desconhecida</string>
224@@ -207,7 +208,7 @@
225 <string name="card_number_hint">Os últimos 4 dígitos do cartão</string>
226 <string name="issuer">Emissor</string>
227 <string name="cash">Dinheiro</string>
228- <string name="sort_order">Ordem de lisgatem</string>
229+ <string name="sort_order">Ordem de listagem</string>
230 <string name="force_gps_location">Forçar localização GPS</string>
231 <string name="whats_new">O que tem de novo</string>
232 <string name="attribute_delete_alert">Isto apagará os atributos das categorias e transações também.</string>
233@@ -232,7 +233,7 @@
234 <string name="more_products">Mais produtos.</string>
235 <string name="pin_protection">Senha de proteção</string>
236 <string name="pin_protection_summary">Marque para proteger acesso com senha</string>
237- <string name="pin_protection_notify">Por favor, configure a senha nas Preferências</string>
238+ <string name="pin_protection_notify">Favor configurar a senha em Preferências</string>
239 <string name="change_pin">Modificar senha</string>
240 <string name="change_pin_summary">Modifica a senha.</string>
241 <string name="pin">Senha</string>
242@@ -241,11 +242,22 @@
243 <string name="restore">Restaurar</string>
244 <string name="backup_database">Backup dos dados</string>
245 <string name="backup_database_inprogress">Efetuando backup..</string>
246+ <string name="backup_database_gdocs">Backup no Google Docs</string>
247+ <string name="backup_database_gdocs_inprogress">Efetuando backup..</string>
248 <string name="csv_export">Exportar em CSV</string>
249 <string name="csv_export_inprogress">Exportando dados para formato CSV..</string>
250 <string name="restore_database">Restaurar dados</string>
251 <string name="restore_database_inprogress">Restaurando dados...</string>
252+ <string name="restore_database_gdocs">Restaurar do Google Docs</string>
253+ <string name="restore_database_inprogress_gdocs">Restaurando base...</string>
254 <string name="restore_database_success">Os dados foram restaurados com sucesso..</string>
255+ <string name="gdocs_connection_failed">Não foi possível conectar ao Google Docs.</string>
256+ <string name="gdocs_folder_not_found">A pasta de backup não foi encontrada no Google Docs.</string>
257+ <string name="gdocs_credentials_not_configured">Favor configurar login e senha do Google Docs em Preferências.</string>
258+ <string name="gdocs_folder_not_configured">Favor configurar a pasta de backup no Google Docs.</string>
259+ <string name="gdocs_login_failed">Login ou senha do Google inválido(s).</string>
260+ <string name="gdocs_backup_failed">Erro enviando arquivo de backup ao Google Docs. Tente novamente.</string>
261+ <string name="gdocs_restore_failed">Erro recuperando arquivo de backup. Tente novamente.</string>
262 <string name="success">Sucesso!</string>
263 <string name="fail">Falha..</string>
264 <string name="duplicate">Duplicatas</string>
265@@ -253,7 +265,7 @@
266 <string name="select_to_account">Selecione conta de destino..</string>
267 <string name="update_balance">Atualizar balanço</string>
268 <string name="close_account">Fechar conta</string>
269- <string name="reopen_account">Re-abrir conta</string>
270+ <string name="reopen_account">Reabrir conta</string>
271 <string name="difference">Diferença</string>
272 <string name="new_balance">Novo balanço</string>
273 <string name="duplicate_success">Transação duplicada com a mesma data e hora</string>
274@@ -343,6 +355,13 @@
275 <string name="calculating">Calculando..</string>
276 <string name="budget_mode">Condições facilitadas</string>
277 <string name="budget_mode_summary">Use menos condições restritivas (categoria OU projeto) para filtrar transações</string>
278+ <string name="gdocs_backup">Backup no Google Docs</string>
279+ <string name="user_login">Nome de usuário</string>
280+ <string name="user_login_summary">Nome de usuário no Google (usuário)</string>
281+ <string name="user_password">Senha</string>
282+ <string name="user_password_summary">Senha no Google</string>
283+ <string name="backup_folder">Pasta de backup</string>
284+ <string name="backup_folder_summary">Pasta no Google Docs para armazenar os arquivos.</string>
285 <string name="other">Outro</string>
286 <string name="send_error_reports">Enviar relatórios de erro</string>
287 <string name="send_error_reports_summary">Enviar relatõrios de erros anônimos para orangesoftware.ru (requer reiníci)</string>
288@@ -364,13 +383,13 @@
289 <string name="recurrence_period_starts_on">Iniciar em</string>
290 <string name="recurrence_weekly_days">Repetir em</string>
291 <string name="recurrence_monthly_pattern">Padrão mensal</string>
292- <string name="recurrence_monthly_every_nth_day">Todo Nésimo dia</string>
293+ <string name="recurrence_monthly_every_nth_day">Todo N-ésimo dia</string>
294 <string name="recurrence_monthly_specific_day">Especifie o dia</string>
295 <string name="recur_interval_semi_monthly_1">1º dia</string>
296 <string name="recur_interval_semi_monthly_2">2º dia</string>
297 <string name="recurrence_none">Sem recorrência</string>
298 <string name="specify_value">Especifique o valor..</string>
299- <string name="recurrence_evaluate">Previsão das dadas</string>
300+ <string name="recurrence_evaluate">Previsão das datas</string>
301 <string name="first">Primeiro</string>
302 <string name="second">Segundo</string>
303 <string name="third">Terceiro</string>
304@@ -419,7 +438,7 @@
305 <string name="notification_sound">Som</string>
306 <string name="notification_vibra">Vibração</string>
307 <string name="notification_led">Led</string>
308- <string name="transaction_status">Estatus</string>
309+ <string name="transaction_status">Estado</string>
310 <string name="transaction_status_pending">Pendente</string>
311 <string name="transaction_status_unreconciled">Não conciliada</string>
312 <string name="transaction_status_cleared">Apurada</string>
313@@ -438,4 +457,23 @@
314 <string name="report_by_sub_category">Por Sub-categoria</string>
315 <string name="report_by_sub_category_summary">Transações listadas por sub-categoria</string>
316 <string name="credits">Créditos</string>
317+
318+ <string name="payment_day">Dia do pagamento</string>
319+ <string name="closing_day">Dia do fechamento</string>
320+ <string name="closing_day_hint">Dia em que a fatura é gerada.</string>
321+ <string name="ccard_statement">Previsão de Fatura</string>
322+ <string name="monthly_view">Balanço Mensal</string>
323+ <string name="credit_card_statement">Fatura do Cartão de Crédito</string>
324+ <string name="ccard_statement_title">Fatura &lt;ccard&gt;</string>
325+ <string name="ccard_par">&lt;ccard&gt;</string>
326+ <string name="bill_on">Fatura em </string>
327+ <string name="monthly_result">Resultado do mês</string>
328+ <string name="closing_day_error">Dia de fechamento não é válido.</string>
329+ <string name="payment_day_error">Dia de pagamento não é válido.</string>
330+ <string name="statement_error">Favor registrar dias de pagamento e fechamento da fatura deste cartão nas propriedades da conta.</string>
331+ <string name="is_ccard_payment">Pagamento de Fatura</string>
332+ <string name="is_ccard_payment_summary">Nao incluir no total da fatura</string>
333+ <string name="header_payments">Pagamentos</string>
334+ <string name="header_credits">Créditos Diversos</string>
335+ <string name="header_expenses">Despesas</string>
336 </resources>
337
338=== modified file 'res/values/ids.xml'
339--- res/values/ids.xml 2010-08-19 13:42:10 +0000
340+++ res/values/ids.xml 2010-08-22 11:18:40 +0000
341@@ -60,5 +60,6 @@
342 <item type="id" name="status_clear"/>
343 <item type="id" name="attach_picture"/>
344 <item type="id" name="delete_picture"/>
345- <item type="id" name="negative_opening_amount"/>
346+ <item type="id" name="negative_opening_amount"/>
347+ <item type="id" name="is_ccard_payment"/>
348 </resources>
349
350=== modified file 'res/values/strings.xml'
351--- res/values/strings.xml 2010-08-19 13:42:10 +0000
352+++ res/values/strings.xml 2010-08-22 11:18:40 +0000
353@@ -240,11 +240,22 @@
354 <string name="restore">Restore</string>
355 <string name="backup_database">Backup Database</string>
356 <string name="backup_database_inprogress">Backing up database..</string>
357+ <string name="backup_database_gdocs">Backup on Google Docs</string>
358+ <string name="backup_database_gdocs_inprogress">Backing up database..</string>
359 <string name="csv_export">CSV Export</string>
360 <string name="csv_export_inprogress">Exporting database to CSV..</string>
361 <string name="restore_database">Restore Database</string>
362 <string name="restore_database_inprogress">Restoring database...</string>
363- <string name="restore_database_success">Database has been successfully restored..</string>
364+ <string name="restore_database_gdocs">Restore from Google Docs</string>
365+ <string name="restore_database_inprogress_gdocs">Restoring database...</string>
366+ <string name="restore_database_success">Database has been successfully restored.</string>
367+ <string name="gdocs_connection_failed">Can not connect to Google Docs.</string>
368+ <string name="gdocs_folder_not_found">The backup folder on Google Docs was not found.</string>
369+ <string name="gdocs_credentials_not_configured">Please set Google account login and password on Preferences.</string>
370+ <string name="gdocs_folder_not_configured">Please set the Google Docs backup folder on Preferences.</string>
371+ <string name="gdocs_login_failed">Google account login or password not valid.</string>
372+ <string name="gdocs_backup_failed">Error sending backup file to Google Docs. Please try again.</string>
373+ <string name="gdocs_restore_failed">Error retrieving backup file. Please try again.</string>
374 <string name="success">Success!</string>
375 <string name="fail">Fail..</string>
376 <string name="duplicate">Duplicate</string>
377@@ -343,6 +354,13 @@
378 <string name="calculating">Calculating..</string>
379 <string name="budget_mode">Ease conditions</string>
380 <string name="budget_mode_summary">Use less restrictive conditions (category OR project) to filter transactions</string>
381+ <string name="gdocs_backup">Google Docs Backup</string>
382+ <string name="user_login">Login</string>
383+ <string name="user_login_summary">Google account login (username)</string>
384+ <string name="user_password">Password</string>
385+ <string name="user_password_summary">Google account password</string>
386+ <string name="backup_folder">Backup Folder</string>
387+ <string name="backup_folder_summary">Folder on Google Docs to store backup files.</string>
388 <string name="other">Other</string>
389 <string name="send_error_reports">Send error reports</string>
390 <string name="send_error_reports_summary">Send anonymous error reports to orangesoftware.ru (requires restart)</string>
391@@ -445,4 +463,22 @@
392 <string name="negative_opening_amount">Negative opening amount</string>
393 <string name="negative_opening_amount_summary">Open account with negative opening amount</string>
394
395+ <string name="payment_day">Payment day</string>
396+ <string name="closing_day">Closing day</string>
397+ <string name="closing_day_hint">Day on which the bill closes</string>
398+ <string name="ccard_statement">Statements</string>
399+ <string name="monthly_view">Month Preview</string>
400+ <string name="credit_card_statement">Credit Card Statement</string>
401+ <string name="ccard_statement_title">&lt;ccard&gt; Statement</string>
402+ <string name="ccard_par">&lt;ccard&gt;</string>
403+ <string name="bill_on">Bill on </string>
404+ <string name="monthly_result">Balance of month</string>
405+ <string name="closing_day_error">Closing day is not valid.</string>
406+ <string name="payment_day_error">Payment day is not valid.</string>
407+ <string name="statement_error">Please set payment and closing days for this credit card on account properties.</string>
408+ <string name="is_ccard_payment">Credit Card Payment</string>
409+ <string name="is_ccard_payment_summary">Not Include into bill total</string>
410+ <string name="header_payments">Payments</string>
411+ <string name="header_credits">Various Credits</string>
412+ <string name="header_expenses">Expenses</string>
413 </resources>
414
415=== modified file 'res/xml/preferences.xml'
416--- res/xml/preferences.xml 2010-08-19 10:35:29 +0000
417+++ res/xml/preferences.xml 2010-08-22 11:18:40 +0000
418@@ -84,6 +84,17 @@
419 android:title="@string/use_my_location" android:summary="@string/use_my_location_summary"
420 android:defaultValue="true" />
421 </PreferenceCategory>
422+ <PreferenceCategory android:title="@string/gdocs_backup">
423+ <EditTextPreference android:key="user_login"
424+ android:title="@string/user_login" android:summary="@string/user_login_summary"/>
425+ <EditTextPreference
426+ android:key="user_password"
427+ android:title="@string/user_password"
428+ android:password="true"
429+ android:summary="@string/user_password_summary"/>
430+ <EditTextPreference android:key="backup_folder"
431+ android:title="@string/backup_folder" android:summary="@string/backup_folder_summary"/>
432+ </PreferenceCategory>
433 <PreferenceCategory android:title="@string/other">
434 <CheckBoxPreference android:key="include_transfers_into_reports"
435 android:title="@string/include_transfers_into_reports" android:summary="@string/include_transfers_into_reports_summary"
436
437=== modified file 'src/ru/orangesoftware/financisto/activity/AbstractTransactionActivity.java'
438--- src/ru/orangesoftware/financisto/activity/AbstractTransactionActivity.java 2010-08-19 10:35:29 +0000
439+++ src/ru/orangesoftware/financisto/activity/AbstractTransactionActivity.java 2010-08-22 11:18:40 +0000
440@@ -75,6 +75,7 @@
441 import android.view.View.OnClickListener;
442 import android.widget.ArrayAdapter;
443 import android.widget.Button;
444+import android.widget.CheckBox;
445 import android.widget.DatePicker;
446 import android.widget.EditText;
447 import android.widget.ImageButton;
448@@ -133,6 +134,8 @@
449 private ImageView pictureView;
450 private String pictureFileName;
451
452+ private CheckBox ccardPayment;
453+
454 protected long selectedAccountId = -1;
455 protected long selectedCategoryId = 0;
456 protected long selectedProjectId = 0;
457@@ -519,6 +522,12 @@
458 if (transaction.isNotTemplateLike()) {
459 pictureView = x.addPictureNodeMinus(this, layout, R.id.attach_picture, R.id.delete_picture, R.string.attach_picture, R.string.new_picture);
460 }
461+ // checkbox to register if the transaction is a credit card payment.
462+ // this will be used to exclude from totals in bill preview
463+ ccardPayment = x.addCheckboxNode(layout,
464+ R.id.is_ccard_payment, R.string.is_ccard_payment,
465+ R.string.is_ccard_payment_summary, false);
466+
467 }
468
469 protected abstract void createListNodes(LinearLayout layout);
470@@ -585,6 +594,10 @@
471 removePicture();
472 break;
473 }
474+ case R.id.is_ccard_payment: {
475+ ccardPayment.setChecked(!ccardPayment.isChecked());
476+ transaction.isCCardPayment = ccardPayment.isChecked()?1:0;
477+ }
478 }
479 }
480
481@@ -825,6 +838,13 @@
482 setNotification(transaction.notificationOptions);
483 }
484 selectPicture(transaction.attachedPicture);
485+ setIsCCardPayment(transaction.isCCardPayment);
486+ }
487+
488+ private void setIsCCardPayment(int isCCardPaymentValue) {
489+ // TODO Auto-generated method stub
490+ transaction.isCCardPayment = isCCardPaymentValue;
491+ ccardPayment.setChecked(isCCardPaymentValue==1);
492 }
493
494 private void setLocation(String provider, float accuracy, double latitude, double longitude) {
495
496=== modified file 'src/ru/orangesoftware/financisto/activity/AccountActivity.java'
497--- src/ru/orangesoftware/financisto/activity/AccountActivity.java 2010-08-19 13:42:10 +0000
498+++ src/ru/orangesoftware/financisto/activity/AccountActivity.java 2010-08-22 11:18:40 +0000
499@@ -7,6 +7,7 @@
500 *
501 * Contributors:
502 * Denis Solonenko - initial API and implementation
503+ * Abdsandryk - adding bill filtering parameters
504 ******************************************************************************/
505 package ru.orangesoftware.financisto.activity;
506
507@@ -67,6 +68,13 @@
508 private CardIssuerAdapter cardIssuerAdapter;
509 private ListAdapter currencyAdapter;
510
511+ /** for bill filtering */
512+ private EditText closingDayText;
513+ private EditText paymentDayText;
514+ private View closingDayNode;
515+ private View paymentDayNode;
516+ /***********************/
517+
518 private Account account = new Account();
519
520 @Override
521@@ -90,6 +98,17 @@
522 sortOrderText.setInputType(InputType.TYPE_CLASS_NUMBER);
523 sortOrderText.setSingleLine();
524
525+ /********** bill filtering **********/
526+ closingDayText = new EditText(this);
527+ closingDayText.setInputType(InputType.TYPE_CLASS_NUMBER);
528+ closingDayText.setHint(R.string.closing_day_hint);
529+ closingDayText.setSingleLine();
530+
531+ paymentDayText = new EditText(this);
532+ paymentDayText.setInputType(InputType.TYPE_CLASS_NUMBER);
533+ paymentDayText.setSingleLine();
534+ /************************************/
535+
536 amountInput = new AmountInput(this);
537 amountInput.setOwner(this);
538
539@@ -110,6 +129,14 @@
540
541 numberNode = x.addEditNode(layout, R.string.card_number, numberText);
542 setVisibility(numberNode, View.GONE);
543+
544+ /********** bill filtering **********/
545+ closingDayNode = x.addEditNode(layout, R.string.closing_day, closingDayText);
546+ setVisibility(closingDayNode, View.GONE);
547+
548+ paymentDayNode = x.addEditNode(layout, R.string.payment_day, paymentDayText);
549+ setVisibility(paymentDayNode, View.GONE);
550+ /************************************/
551
552 currencyCursor = em.getAllCurrencies("name");
553 startManagingCursor(currencyCursor);
554@@ -168,12 +195,36 @@
555 if (type.hasNumber) {
556 account.number = Utils.text(numberText);
557 }
558+
559+ /********** validate closing and payment days **********/
560+ if (type.isCreditCard) {
561+ String closingDay = Utils.text(closingDayText);
562+ account.closingDay = closingDay == null ? 0 : Integer.parseInt(closingDay);
563+ if (account.closingDay != 0) {
564+ if (account.closingDay>31) {
565+ Toast.makeText(AccountActivity.this, R.string.closing_day_error, Toast.LENGTH_SHORT).show();
566+ return;
567+ }
568+ }
569+
570+ String paymentDay = Utils.text(paymentDayText);
571+ account.paymentDay = paymentDay == null ? 0 : Integer.parseInt(paymentDay);
572+ if (account.paymentDay != 0) {
573+ if (account.paymentDay>31) {
574+ Toast.makeText(AccountActivity.this, R.string.payment_day_error, Toast.LENGTH_SHORT).show();
575+ return;
576+ }
577+ }
578+ }
579+ /************* validate closing and payment days *************/
580+
581 account.title = accountTitle.getText().toString();
582 account.creationDate = System.currentTimeMillis();
583 String sortOrder = Utils.text(sortOrderText);
584 account.sortOrder = sortOrder == null ? 0 : Integer.parseInt(sortOrder);
585 account.isIncludeIntoTotals = isIncludedIntoTotals.isChecked();
586 account.limitAmount = limitInput.getAmount();
587+
588 long accountId = em.saveAccount(account);
589 long amount = amountInput.getAmount();
590 if (amount != 0) {
591@@ -273,6 +324,12 @@
592 setVisibility(cardIssuerNode, type.isCard ? View.VISIBLE : View.GONE);
593 setVisibility(issuerNode, type.hasIssuer ? View.VISIBLE : View.GONE);
594 setVisibility(numberNode, type.hasNumber ? View.VISIBLE : View.GONE);
595+
596+ /******* bill filtering ********/
597+ setVisibility(closingDayNode, type.isCreditCard ? View.VISIBLE : View.GONE);
598+ setVisibility(paymentDayNode, type.isCreditCard ? View.VISIBLE : View.GONE);
599+ /*******************************/
600+
601 setVisibility(limitAmountView, type == AccountType.CREDIT_CARD ? View.VISIBLE : View.GONE);
602 account.type = type.name();
603 selectCardIssuer(account.cardIssuer != null
604@@ -311,6 +368,12 @@
605 issuerName.setText(account.issuer);
606 numberText.setText(account.number);
607 sortOrderText.setText(String.valueOf(account.sortOrder));
608+
609+ /******** bill filtering ********/
610+ closingDayText.setText(String.valueOf(account.closingDay));
611+ paymentDayText.setText(String.valueOf(account.paymentDay));
612+ /********************************/
613+
614 isIncludedIntoTotals.setChecked(account.isIncludeIntoTotals);
615 if (account.limitAmount > 0) {
616 limitInput.setAmount(account.limitAmount);
617
618=== modified file 'src/ru/orangesoftware/financisto/activity/BlotterActivity.java'
619--- src/ru/orangesoftware/financisto/activity/BlotterActivity.java 2010-08-05 11:46:29 +0000
620+++ src/ru/orangesoftware/financisto/activity/BlotterActivity.java 2010-08-22 11:18:40 +0000
621@@ -7,6 +7,7 @@
622 *
623 * Contributors:
624 * Denis Solonenko - initial API and implementation
625+ * Abdsandryk - menu option to call Credit Card Bill functionality
626 ******************************************************************************/
627 package ru.orangesoftware.financisto.activity;
628
629@@ -19,6 +20,7 @@
630 import ru.orangesoftware.financisto.blotter.WhereFilter;
631 import ru.orangesoftware.financisto.dialog.TransactionInfoDialog;
632 import ru.orangesoftware.financisto.model.Account;
633+import ru.orangesoftware.financisto.model.AccountType;
634 import ru.orangesoftware.financisto.model.Transaction;
635 import ru.orangesoftware.financisto.service.FinancistoService;
636 import ru.orangesoftware.financisto.utils.MenuItemInfo;
637@@ -31,6 +33,8 @@
638 import android.database.Cursor;
639 import android.os.Bundle;
640 import android.view.LayoutInflater;
641+import android.view.Menu;
642+import android.view.MenuInflater;
643 import android.view.MenuItem;
644 import android.view.View;
645 import android.view.View.OnClickListener;
646@@ -51,6 +55,9 @@
647 private static final int NEW_TRANSFER_REQUEST = 3;
648 private static final int EDIT_TRANSFER_REQUEST = 4;
649 private static final int NEW_TRANSACTION_FROM_TEMPLATE_REQUEST = 5;
650+ private static final int MONTHLY_VIEW_REQUEST = 6;
651+ private static final int BILL_PREVIEW_REQUEST = 7;
652+
653
654 private static final int FILTER_REQUEST = 6;
655 private static final int MENU_DUPLICATE = MENU_ADD+1;
656@@ -323,5 +330,82 @@
657 TransactionInfoDialog transactionInfoView = new TransactionInfoDialog(this, position, id, em, inflater);
658 transactionInfoView.show(id);
659 }
660+
661+ /* (non-Javadoc)
662+ * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
663+ */
664+ @Override
665+ public boolean onCreateOptionsMenu(Menu menu) {
666+
667+ long accountId = blotterFilter.getAccountId();
668+
669+ // Funcionality available for account blotter
670+ if (accountId != -1) {
671+
672+ // get account type
673+ Account account = em.getAccount(accountId);
674+ AccountType type = AccountType.valueOf(account.type);
675+
676+ if (type.isCreditCard) {
677+ // Show menu for Credit Cards - bill
678+ MenuInflater inflater = getMenuInflater();
679+ inflater.inflate(R.menu.ccard_blotter_menu, menu);
680+ } else {
681+ // Show menu for other accounts - monthly view
682+ MenuInflater inflater = getMenuInflater();
683+ inflater.inflate(R.menu.blotter_menu, menu);
684+ }
685+
686+ return true;
687+ } else {
688+ return true;
689+ }
690+ }
691+
692+ /* (non-Javadoc)
693+ * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
694+ */
695+ @Override
696+ public boolean onOptionsItemSelected(MenuItem item) {
697+
698+ long accountId = blotterFilter.getAccountId();
699+
700+ Intent intent = new Intent(this, MonthlyViewActivity.class);
701+ intent.putExtra(MonthlyViewActivity.ACCOUNT_EXTRA, accountId);
702+
703+ switch (item.getItemId()) {
704+
705+ case R.id.opt_menu_month:
706+ // call credit card bill activity sending account id
707+ intent.putExtra(MonthlyViewActivity.BILL_PREVIEW_EXTRA, false);
708+ startActivityForResult(intent, MONTHLY_VIEW_REQUEST);
709+ return true;
710+
711+ case R.id.opt_menu_bill:
712+ if (accountId != -1) {
713+ Account account = em.getAccount(accountId);
714+
715+ // call credit card bill activity sending account id
716+ if (account.paymentDay>0 && account.closingDay>0) {
717+ intent.putExtra(MonthlyViewActivity.BILL_PREVIEW_EXTRA, true);
718+ startActivityForResult(intent, BILL_PREVIEW_REQUEST);
719+ return true;
720+ } else {
721+ // display message: need payment and closing day
722+ AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this);
723+ dlgAlert.setMessage(R.string.statement_error);
724+ dlgAlert.setTitle(R.string.ccard_statement);
725+ dlgAlert.setPositiveButton(R.string.ok, null);
726+ dlgAlert.setCancelable(true);
727+ dlgAlert.create().show();
728+ return true;
729+ }
730+ } else {
731+ return true;
732+ }
733+ default:
734+ return super.onOptionsItemSelected(item);
735+ }
736+ }
737
738 }
739
740=== modified file 'src/ru/orangesoftware/financisto/activity/MainActivity.java'
741--- src/ru/orangesoftware/financisto/activity/MainActivity.java 2010-07-19 14:44:00 +0000
742+++ src/ru/orangesoftware/financisto/activity/MainActivity.java 2010-08-22 11:18:40 +0000
743@@ -11,11 +11,14 @@
744 package ru.orangesoftware.financisto.activity;
745
746 import java.util.HashMap;
747+import java.util.List;
748+import java.util.Properties;
749
750 import ru.orangesoftware.financisto.R;
751 import ru.orangesoftware.financisto.backup.Backup;
752 import ru.orangesoftware.financisto.backup.DatabaseExport;
753 import ru.orangesoftware.financisto.backup.DatabaseImport;
754+import ru.orangesoftware.financisto.backup.SettingsNotConfiguredException;
755 import ru.orangesoftware.financisto.blotter.WhereFilter;
756 import ru.orangesoftware.financisto.db.DatabaseAdapter;
757 import ru.orangesoftware.financisto.db.DatabaseHelper;
758@@ -39,6 +42,8 @@
759 import android.database.sqlite.SQLiteDatabase;
760 import android.net.Uri;
761 import android.os.Bundle;
762+import android.os.Handler;
763+import android.os.Message;
764 import android.util.Log;
765 import android.view.LayoutInflater;
766 import android.view.Menu;
767@@ -51,6 +56,16 @@
768 import android.widget.LinearLayout;
769 import android.widget.TabHost;
770 import android.widget.TextView;
771+import api.wireless.gdata.client.AbstructParserFactory;
772+import api.wireless.gdata.client.GDataParserFactory;
773+import api.wireless.gdata.client.ServiceDataClient;
774+import api.wireless.gdata.data.Feed;
775+import api.wireless.gdata.docs.client.DocsClient;
776+import api.wireless.gdata.docs.client.DocsGDataClient;
777+import api.wireless.gdata.docs.data.DocumentEntry;
778+import api.wireless.gdata.docs.data.FolderEntry;
779+import api.wireless.gdata.docs.parser.xml.XmlDocsGDataParserFactory;
780+import api.wireless.gdata.util.AuthenticationException;
781
782 import com.nullwire.trace.ExceptionHandler;
783
784@@ -69,7 +84,9 @@
785 private static final int MENU_RESTORE = Menu.FIRST+8;
786 private static final int MENU_CSV_EXPORT = Menu.FIRST+9;
787 private static final int MENU_SCHEDULED_TRANSACTIONS = Menu.FIRST+10;
788-
789+ private static final int MENU_BACKUP_GDOCS = Menu.FIRST+11;
790+ private static final int MENU_RESTORE_GDOCS = Menu.FIRST+12;
791+
792 private final HashMap<String, Boolean> started = new HashMap<String, Boolean>();
793
794 private String appVersion;
795@@ -237,6 +254,8 @@
796 menu.addSubMenu(0, MENU_CSV_EXPORT, 0, R.string.csv_export);
797 menu.addSubMenu(0, MENU_BACKUP, 0, R.string.backup_database);
798 menu.addSubMenu(0, MENU_RESTORE, 0, R.string.restore_database);
799+ menu.addSubMenu(0, MENU_BACKUP_GDOCS, 0, R.string.backup_database_gdocs);
800+ menu.addSubMenu(0, MENU_RESTORE_GDOCS, 0, R.string.restore_database_gdocs);
801 menuItem = menu.add(0, MENU_ABOUT, 0, R.string.about);
802 menuItem.setIcon(android.R.drawable.ic_menu_info_details);
803 return true;
804@@ -273,24 +292,101 @@
805 case MENU_BACKUP:
806 doBackup();
807 break;
808+ case MENU_BACKUP_GDOCS:
809+ doBackupOnline();
810+ break;
811 case MENU_RESTORE:
812 doImport();
813 break;
814+ case MENU_RESTORE_GDOCS:
815+ doImportFromGoogleDocs();
816+ break;
817 }
818 return false;
819 }
820
821+ /**
822+ * Treat assinchronous requests to popup error messages
823+ * */
824+ private Handler handler = new Handler()
825+ {
826+ @Override
827+ /**
828+ * Schedule the popup of the given error message
829+ *
830+ * @param msg The message to display
831+ * */
832+ public void handleMessage(Message msg)
833+ {
834+ showErrorPopup(MainActivity.this, msg.what);
835+ }
836+ };
837+
838+ /**
839+ * Display the error message
840+ *
841+ * @param context
842+ * @message message The message to display
843+ * */
844+ protected void showErrorPopup(Context context, int message)
845+ {
846+ new AlertDialog.Builder(context)
847+ .setMessage(message)
848+ .setTitle(R.string.error)
849+ .setPositiveButton(R.string.ok, null)
850+ .setCancelable(true)
851+ .create().show();
852+ }
853+
854+ /**
855+ * Connects to Google Docs
856+ * */
857+ protected DocsClient createDocsClient(Context context) throws AuthenticationException, SettingsNotConfiguredException
858+ {
859+ GDataParserFactory dspf = new XmlDocsGDataParserFactory(new AbstructParserFactory());
860+ DocsGDataClient dataClient = new DocsGDataClient(
861+ "cl",
862+ ServiceDataClient.DEFAULT_AUTH_PROTOCOL,
863+ ServiceDataClient.DEFAULT_AUTH_HOST);
864+ DocsClient googleDocsClient = new DocsClient(dataClient, dspf);
865+
866+ /*
867+ * Start authentication
868+ * */
869+ // check user login on preferences
870+ String login = MyPreferences.getUserLogin(context);
871+ if(login==null||login.equals(""))
872+ throw new SettingsNotConfiguredException("login");
873+ // check user password on preferences
874+ String password = MyPreferences.getUserPassword(context);
875+ if(password==null||password.equals(""))
876+ throw new SettingsNotConfiguredException("password");
877+
878+ googleDocsClient.setUserCredentials(login, password);
879+
880+ return googleDocsClient;
881+ }
882+
883 private void doBackup() {
884 ProgressDialog d = ProgressDialog.show(this, null, getString(R.string.backup_database_inprogress), true);
885 new BackupExportTask(d).execute((String[])null);
886 }
887
888+ /**
889+ * Backup to Google Docs using the Google account parameters registered on preferences.
890+ * */
891+ private void doBackupOnline() {
892+ ProgressDialog d = ProgressDialog.show(this, null, getString(R.string.backup_database_gdocs_inprogress), true);
893+ new OnlineBackupExportTask(d).execute((String[])null);
894+ }
895+
896 private void doCsvExport() {
897 Intent intent = new Intent(this, CsvExportActivity.class);
898 startActivityForResult(intent, ACTIVITY_CSV_EXPORT);
899 }
900
901 private String selectedBackupFile;
902+ private Properties backupFiles;
903
904 private void doImport() {
905 final String[] backupFiles = Backup.listBackups();
906@@ -316,6 +412,78 @@
907 .show();
908 }
909
910+ /**
911+ * Retrieves the backup file from the Google Docs account registered on preferences
912+ * */
913+ private void doImportFromGoogleDocs() {
914+ Feed<DocumentEntry> feed = null;
915+
916+ try {
917+ Context context = MainActivity.this;
918+ DocsClient docsClient = createDocsClient(context);
919+
920+ // get the list of files in the repository
921+ String folder = MyPreferences.getBackupFolder(context);
922+ // check the backup folder registered on preferences
923+ if(folder==null||folder.equals("")) {
924+ showErrorPopup(this,R.string.gdocs_folder_not_configured);
925+ return;
926+ }
927+ FolderEntry fd = docsClient.getFolderByTitle(folder);
928+ if(fd==null) // if the registered folder does not exist
929+ {
930+ showErrorPopup(this,R.string.gdocs_folder_not_found);
931+ return;
932+ }
933+ feed = docsClient.getFolderDocsListFeed(fd.getKey());
934+ } catch (AuthenticationException e) { //falha de login
935+ showErrorPopup(this,R.string.gdocs_login_failed);
936+ return;
937+ } catch (SettingsNotConfiguredException e) { //parametros de login nao configurados
938+ if(e.getMessage().equals("login"))
939+ handler.sendEmptyMessage(R.string.gdocs_credentials_not_configured);
940+ else if(e.getMessage().equals("password"))
941+ handler.sendEmptyMessage(R.string.gdocs_credentials_not_configured);
942+ return;
943+ } catch(Exception e) { //outros erros de conexao
944+ showErrorPopup(this,R.string.gdocs_connection_failed);
945+ return;
946+ }
947+
948+ /*
949+ * Convert from ListList<DocumentEntry> to String[] to use in method setSingleChoiceItems()
950+ * */
951+ List<DocumentEntry> arquivos = feed.getEntries();
952+ final String[] backupFilesNames = new String[arquivos.size()];
953+ backupFiles = new Properties();
954+ String name;
955+ for (int i=0;i<arquivos.size();i++) {
956+ name = arquivos.get(i).getTitle();
957+ backupFilesNames[i]=name;
958+ backupFiles.put(name, arquivos.get(i).getKey());
959+ }
960+
961+ new AlertDialog.Builder(this)
962+ .setTitle(R.string.restore_database)
963+ .setPositiveButton(R.string.restore, new DialogInterface.OnClickListener(){
964+ @Override
965+ public void onClick(DialogInterface dialog, int which) {
966+ if (selectedBackupFile != null) {
967+ ProgressDialog d = ProgressDialog.show(MainActivity.this, null, getString(R.string.restore_database_inprogress_gdocs), true);
968+ new OnlineBackupImportTask(d).execute(selectedBackupFile, backupFiles.get(selectedBackupFile).toString());
969+ }
970+ }
971+ })
972+ .setSingleChoiceItems(backupFilesNames, -1, new DialogInterface.OnClickListener(){
973+ @Override
974+ public void onClick(DialogInterface dialog, int which) {
975+ if (backupFilesNames != null && which >= 0 && which < backupFilesNames.length) {
976+ selectedBackupFile = backupFilesNames[which];
977+ }
978+ }
979+ })
980+ .show();
981+ }
982
983 private class CsvExportTask extends ImportExportAsyncTask {
984
985@@ -351,8 +519,45 @@
986 protected Object work(Context context, DatabaseAdapter db, String...params) throws Exception {
987 DatabaseExport export = new DatabaseExport(context, db.db());
988 return export.export();
989- }
990-
991+
992+ }
993+
994+ @Override
995+ protected String getSuccessMessage(Object result) {
996+ return String.valueOf(result);
997+ }
998+
999+ }
1000+
1001+ /**
1002+ * Task that calls backup to google docs functions
1003+ * */
1004+ private class OnlineBackupExportTask extends ImportExportAsyncTask {
1005+
1006+ public OnlineBackupExportTask(ProgressDialog dialog) {
1007+ super(MainActivity.this, dialog, null);
1008+ }
1009+
1010+ @Override
1011+ protected Object work(Context context, DatabaseAdapter db, String...params) throws AuthenticationException, Exception{
1012+ DatabaseExport export = new DatabaseExport(context, db.db());
1013+ try {
1014+ return export.exportOnline(createDocsClient(context), MyPreferences.getBackupFolder(context));
1015+ } catch (AuthenticationException e) { // connection error
1016+ handler.sendEmptyMessage(R.string.gdocs_login_failed);
1017+ throw e;
1018+ } catch (SettingsNotConfiguredException e) { // missing login or password
1019+ if(e.getMessage().equals("login"))
1020+ handler.sendEmptyMessage(R.string.gdocs_credentials_not_configured);
1021+ else if(e.getMessage().equals("password"))
1022+ handler.sendEmptyMessage(R.string.gdocs_credentials_not_configured);
1023+ throw e;
1024+ } catch (Exception e) { // Other errors
1025+ handler.sendEmptyMessage(R.string.gdocs_backup_failed);
1026+ throw e;
1027+ }
1028+ }
1029+
1030 @Override
1031 protected String getSuccessMessage(Object result) {
1032 return String.valueOf(result);
1033@@ -376,6 +581,48 @@
1034 new DatabaseImport(MainActivity.this, db.db(), params[0]).importDatabase();
1035 return true;
1036 }
1037+
1038+ @Override
1039+ protected String getSuccessMessage(Object result) {
1040+ return MainActivity.this.getString(R.string.restore_database_success);
1041+ }
1042+
1043+ }
1044+
1045+ /**
1046+ * Task that calls backup from google docs functions
1047+ * */
1048+ private class OnlineBackupImportTask extends ImportExportAsyncTask {
1049+
1050+ public OnlineBackupImportTask(ProgressDialog dialog) {
1051+ super(MainActivity.this, dialog, new ImportExportAsyncTaskListener(){
1052+ @Override
1053+ public void onCompleted() {
1054+ onTabChanged(getTabHost().getCurrentTabTag());
1055+ }
1056+ });
1057+ }
1058+
1059+ @Override
1060+ protected Object work(Context context, DatabaseAdapter db, String...params) throws Exception, AuthenticationException, SettingsNotConfiguredException {
1061+ try {
1062+ new DatabaseImport(MainActivity.this, db.db(), params[0]).
1063+ importOnlineDatabase(createDocsClient(context), params[1]);
1064+ } catch (SettingsNotConfiguredException e) { // error configuring connection parameters
1065+ if(e.getMessage().equals("login"))
1066+ handler.sendEmptyMessage(R.string.gdocs_credentials_not_configured);
1067+ else if(e.getMessage().equals("password"))
1068+ handler.sendEmptyMessage(R.string.gdocs_credentials_not_configured);
1069+ throw e;
1070+ }catch (AuthenticationException e) { // authentication error
1071+ handler.sendEmptyMessage(R.string.gdocs_login_failed);
1072+ throw e;
1073+ } catch (Exception e) { // error accessing files
1074+ handler.sendEmptyMessage(R.string.gdocs_restore_failed);
1075+ throw e;
1076+ }
1077+ return true;
1078+ }
1079
1080 @Override
1081 protected String getSuccessMessage(Object result) {
1082
1083=== added file 'src/ru/orangesoftware/financisto/activity/MonthlyViewActivity.java'
1084--- src/ru/orangesoftware/financisto/activity/MonthlyViewActivity.java 1970-01-01 00:00:00 +0000
1085+++ src/ru/orangesoftware/financisto/activity/MonthlyViewActivity.java 2010-08-22 11:18:40 +0000
1086@@ -0,0 +1,510 @@
1087+package ru.orangesoftware.financisto.activity;
1088+
1089+import java.text.SimpleDateFormat;
1090+import java.util.Calendar;
1091+import java.util.GregorianCalendar;
1092+
1093+import ru.orangesoftware.financisto.R;
1094+import ru.orangesoftware.financisto.adapter.CreditCardStatementAdapter;
1095+import ru.orangesoftware.financisto.db.DatabaseAdapter;
1096+import ru.orangesoftware.financisto.db.MyEntityManager;
1097+import ru.orangesoftware.financisto.db.DatabaseHelper.TransactionColumns;
1098+import ru.orangesoftware.financisto.model.Account;
1099+import ru.orangesoftware.financisto.model.AccountType;
1100+import ru.orangesoftware.financisto.model.Currency;
1101+import ru.orangesoftware.financisto.utils.Utils;
1102+import android.app.ListActivity;
1103+import android.content.Intent;
1104+import android.database.Cursor;
1105+import android.database.MatrixCursor;
1106+import android.database.MergeCursor;
1107+import android.graphics.Color;
1108+import android.os.Bundle;
1109+import android.view.View;
1110+import android.view.View.OnClickListener;
1111+import android.widget.ImageButton;
1112+import android.widget.TextView;
1113+
1114+/**
1115+ * Display the credit card bill, including scheduled and future transactions for a given period.
1116+ * Display only expenses, ignoring payments (positive values) in Credit Card accounts.
1117+ * @author Abdsandryk
1118+ */
1119+public class MonthlyViewActivity extends ListActivity {
1120+
1121+ private DatabaseAdapter dbAdapter;
1122+ private Cursor transactionsCursor;
1123+
1124+ private long accountId = 0;
1125+ private Account account;
1126+ private Currency currency;
1127+ private boolean isCreditCard = false;
1128+ private boolean isStatementPreview = false;
1129+
1130+ private String title;
1131+ private int closingDay = 0;
1132+ private int paymentDay = 0;
1133+ private String paymentDayStr;
1134+
1135+ private int month = 0;
1136+ private String monthStr;
1137+ private int year = 0;
1138+ private String yearStr;
1139+
1140+ private ImageButton bPrevious;
1141+ private ImageButton bNext;
1142+
1143+ private int negativeColor;
1144+ private int positiveColor;
1145+
1146+ private Utils u;
1147+
1148+ public static final String ACCOUNT_EXTRA = "account_id";
1149+ public static final String BILL_PREVIEW_EXTRA = "bill_preview";
1150+
1151+ public static final String HEADER_PAYMENTS = "bill_payments";
1152+ public static final String HEADER_CREDITS = "bill_credits";
1153+ public static final String HEADER_EXPENSES = "bill_expenses";
1154+
1155+ /** Called when the activity is first created. */
1156+ @Override
1157+ public void onCreate(Bundle savedInstanceState) {
1158+ super.onCreate(savedInstanceState);
1159+ setContentView(R.layout.monthly_view);
1160+
1161+ u = new Utils(this);
1162+ negativeColor = this.getResources().getColor(R.color.negative_amount);
1163+ positiveColor = this.getResources().getColor(R.color.positive_amount);
1164+
1165+ Intent intent = getIntent();
1166+ if (intent != null) {
1167+ accountId = intent.getLongExtra(ACCOUNT_EXTRA, 0);
1168+ isStatementPreview = intent.getBooleanExtra(BILL_PREVIEW_EXTRA, false);
1169+ }
1170+
1171+ initialize();
1172+ }
1173+
1174+ /**
1175+ * When activity lifecycle ends, release resources
1176+ */
1177+ @Override
1178+ public void onDestroy() {
1179+ // close cursor
1180+ if (transactionsCursor != null) {
1181+ transactionsCursor.close();
1182+ }
1183+ super.onDestroy();
1184+ }
1185+
1186+
1187+
1188+ /**
1189+ * Initialize data and GUI elements.
1190+ */
1191+ private void initialize() {
1192+
1193+ // get account data
1194+ dbAdapter = new DatabaseAdapter(this);
1195+ dbAdapter.open();
1196+
1197+ // set currency based on account
1198+ MyEntityManager em = new MyEntityManager(this, dbAdapter.db());
1199+ account = em.getAccount(accountId);
1200+
1201+ dbAdapter.close();
1202+
1203+ // get current month and year
1204+ Calendar cal = Calendar.getInstance();
1205+ month = cal.get(Calendar.MONTH) + 1;
1206+ year = cal.get(Calendar.YEAR);
1207+
1208+ // set part of the title, based on account name: "<CCARD> Bill"
1209+ if (account != null) {
1210+
1211+ // get account type
1212+ isCreditCard = AccountType.valueOf(account.type).isCreditCard;
1213+
1214+ currency = account.currency;
1215+
1216+ if (isCreditCard) {
1217+ if (isStatementPreview) {
1218+ // assuming that expensesOnly is true only if payment and closing days > 0 [BlotterActivity]
1219+ title = getString(R.string.ccard_statement_title);
1220+ String accountTitle = account.title;
1221+ if (account.title==null || account.title.length()==0) {
1222+ accountTitle = account.cardIssuer;
1223+ }
1224+ String toReplace = getString(R.string.ccard_par);
1225+ title = title.replaceAll(toReplace, accountTitle);
1226+ paymentDay = account.paymentDay;
1227+ closingDay = account.closingDay;
1228+ // set activity window title
1229+ this.setTitle(R.string.ccard_statement);
1230+ setCCardTitle();
1231+ setCCardInterval();
1232+ } else {
1233+ title = (account.title==null||account.title.length()==0?account.cardIssuer:account.title);
1234+ paymentDay = 1;
1235+ closingDay = 31;
1236+ setTitle();
1237+ setInterval();
1238+
1239+ // set payment date and label on total bar
1240+ TextView totalLabel = (TextView) findViewById(R.id.monthly_result_label);
1241+ totalLabel.setText(getResources().getString(R.string.monthly_result));
1242+ }
1243+ } else {
1244+ if (account.title==null||account.title.length()==0) {
1245+ if (isCreditCard) {
1246+ // title = <CARD_ISSUER>
1247+ title = account.cardIssuer;
1248+ } else {
1249+ // title = <ACCOUNT_TYPE_TITLE>
1250+ AccountType type = AccountType.valueOf(account.type);
1251+ title = getString(type.titleId);
1252+ }
1253+ } else {
1254+ // title = <TITLE>
1255+ title = account.title;
1256+ }
1257+
1258+ paymentDay = 1;
1259+ closingDay = 31;
1260+ setTitle();
1261+ setInterval();
1262+
1263+ // set payment date and label on total bar
1264+ TextView totalLabel = (TextView) findViewById(R.id.monthly_result_label);
1265+ totalLabel.setText(getResources().getString(R.string.monthly_result));
1266+ }
1267+
1268+ bPrevious = (ImageButton) findViewById(R.id.bt_month_previous);
1269+ bPrevious.setOnClickListener(new OnClickListener(){
1270+ @Override
1271+ public void onClick(View arg0) {
1272+ month--;
1273+ if (month<1) {
1274+ month=12;
1275+ year--;
1276+ }
1277+ if (isCreditCard) {
1278+ if (isStatementPreview) {
1279+ setCCardTitle();
1280+ setCCardInterval();
1281+ } else {
1282+ setTitle();
1283+ setInterval();
1284+ }
1285+ } else {
1286+ setTitle();
1287+ setInterval();
1288+ }
1289+ }
1290+ });
1291+
1292+ bNext = (ImageButton) findViewById(R.id.bt_month_next);
1293+ bNext.setOnClickListener(new OnClickListener(){
1294+ @Override
1295+ public void onClick(View arg0) {
1296+ month++;
1297+ if (month>12) {
1298+ month=1;
1299+ year++;
1300+ }
1301+ if (isCreditCard) {
1302+ if (isStatementPreview) {
1303+ setCCardTitle();
1304+ setCCardInterval();
1305+ } else {
1306+ setTitle();
1307+ setInterval();
1308+ }
1309+ } else {
1310+ setTitle();
1311+ setInterval();
1312+ }
1313+ }
1314+ });
1315+
1316+ }
1317+ }
1318+
1319+ /**
1320+ * Configure the interval based on the bill period of a credit card.
1321+ * Attention:
1322+ * Calendar.MONTH = 0 to 11
1323+ * integer month = 1 to 12
1324+ */
1325+ private void setCCardInterval() {
1326+
1327+ Calendar close = getClosingDate(month, year);
1328+ Calendar open;
1329+
1330+ if (month>1) {
1331+ // closing date from previous month
1332+ open = getClosingDate(month-1, year);
1333+ } else {
1334+ open = getClosingDate(12, year-1);
1335+ }
1336+ // add one day to the closing date of previous month
1337+ open.add(Calendar.DAY_OF_MONTH, +1);
1338+
1339+ // adjust time for closing day
1340+ close.set(Calendar.HOUR_OF_DAY, 23);
1341+ close.set(Calendar.MINUTE, 59);
1342+ close.set(Calendar.SECOND, 59);
1343+
1344+ fillData(open, close);
1345+ }
1346+
1347+ /**
1348+ * Configure the interval in a monthly perspective.
1349+ * Attention:
1350+ * Calendar.MONTH = 0 to 11
1351+ * integer month = 1 to 12
1352+ */
1353+ private void setInterval() {
1354+
1355+ Calendar close = new GregorianCalendar(year, month-1, getLastDayOfMonth(month, year));
1356+ Calendar open = new GregorianCalendar(year, month-1, 1);
1357+
1358+ // adjust time for closing day
1359+ close.set(Calendar.HOUR_OF_DAY, 23);
1360+ close.set(Calendar.MINUTE, 59);
1361+ close.set(Calendar.SECOND, 59);
1362+
1363+ fillData(open, close);
1364+ }
1365+
1366+ /**
1367+ * Returns the day on which the credit card bill closes for a given month/year.
1368+ * @param month
1369+ * @param year
1370+ * @return
1371+ */
1372+ private Calendar getClosingDate(int month, int year) {
1373+ int m = month;
1374+ if (closingDay > paymentDay) {
1375+ m--;
1376+ }
1377+ int maxDay = getLastDayOfMonth(m, year);
1378+ int day = closingDay;
1379+ if (closingDay>maxDay) {
1380+ day = maxDay;
1381+ }
1382+
1383+ return new GregorianCalendar(year, m-1, day);
1384+ }
1385+
1386+ /**
1387+ * Return the last day (maximum value of day) of the given month.
1388+ * @param month
1389+ * @param year
1390+ * @return
1391+ */
1392+ private int getLastDayOfMonth(int month, int year) {
1393+ Calendar calCurr = GregorianCalendar.getInstance();
1394+ calCurr.set(year, month-1, 1); // Months are 0 to 11
1395+ return calCurr.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);
1396+ }
1397+
1398+
1399+ /**
1400+ * Get data for a given period and display the related credit card expenses.
1401+ * @param open Start of period.
1402+ * @param close End of period.
1403+ */
1404+ private void fillData(Calendar open, Calendar close) {
1405+ dbAdapter = new DatabaseAdapter(this);
1406+ dbAdapter.open();
1407+
1408+ // closing cursor from previous request
1409+ if (transactionsCursor != null) {
1410+ transactionsCursor.close();
1411+ }
1412+
1413+ if (isStatementPreview) {
1414+ // display expenses and credits separated
1415+ Cursor expenses = dbAdapter.getAllExpenses(String.valueOf(accountId),
1416+ String.valueOf(open.getTimeInMillis()),
1417+ String.valueOf(close.getTimeInMillis()));
1418+ Cursor credits = dbAdapter.getCredits(String.valueOf(accountId),
1419+ String.valueOf(open.getTimeInMillis()),
1420+ String.valueOf(close.getTimeInMillis()));
1421+ Cursor payments = dbAdapter.getPayments(String.valueOf(accountId),
1422+ String.valueOf(open.getTimeInMillis()),
1423+ String.valueOf(close.getTimeInMillis()));
1424+ transactionsCursor = new MergeCursor(new Cursor[] { getHeader(HEADER_PAYMENTS, payments.getCount()), payments,
1425+ getHeader(HEADER_CREDITS, credits.getCount()), credits,
1426+ getHeader(HEADER_EXPENSES, expenses.getCount()), expenses});
1427+
1428+ } else {
1429+ // account filtering: credit card transactions, from open to close date
1430+ transactionsCursor = dbAdapter.getAllTransactions(String.valueOf(accountId),
1431+ String.valueOf(open.getTimeInMillis()),
1432+ String.valueOf(close.getTimeInMillis()));
1433+ }
1434+
1435+ TextView totalText = (TextView)findViewById(R.id.monthly_result);
1436+
1437+ if (transactionsCursor == null || transactionsCursor.getCount()==0) {
1438+ // display total = 0
1439+ u.setAmountText(totalText, currency, 0, false);
1440+ totalText.setTextColor(Color.BLACK);
1441+ totalText.setVisibility(View.VISIBLE);
1442+
1443+ // hide list and display empty message
1444+ this.getListView().setVisibility(View.GONE);
1445+ ((TextView)findViewById(android.R.id.empty)).setVisibility(View.VISIBLE);
1446+
1447+ } else { // display data
1448+ startManagingCursor(transactionsCursor);
1449+
1450+ // Mapping data from database
1451+ String[] from = new String[] {TransactionColumns.DATETIME, TransactionColumns.NOTE, TransactionColumns.FROM_AMOUNT};
1452+ int[] to = new int[] {R.id.list_date, R.id.list_note, R.id.list_value};
1453+
1454+ // Mapping data to view
1455+ CreditCardStatementAdapter expenses = new CreditCardStatementAdapter(this, R.layout.credit_card_transaction, transactionsCursor, from, to, currency);
1456+ expenses.setStatementPreview(isStatementPreview);
1457+ setListAdapter(expenses);
1458+
1459+ // calculate total
1460+ long total = calculateTotal(expenses.getCursor());
1461+ // display total
1462+ if (isStatementPreview) {
1463+ u.setAmountText(totalText, currency, (-1)*total, false);
1464+ totalText.setTextColor(Color.BLACK);
1465+ } else {
1466+ if (total<0) {
1467+ u.setAmountText(totalText, currency, (-1)*total, false);
1468+ totalText.setTextColor(negativeColor);
1469+ } else {
1470+ u.setAmountText(totalText, currency, total, false);
1471+ totalText.setTextColor(positiveColor);
1472+ }
1473+ }
1474+ totalText.setVisibility(View.VISIBLE);
1475+
1476+ // display list and hide empty message
1477+ this.getListView().setVisibility(View.VISIBLE);
1478+ ((TextView)findViewById(android.R.id.empty)).setVisibility(View.GONE);
1479+ }
1480+
1481+ dbAdapter.close();
1482+ System.gc();
1483+ }
1484+
1485+ /**
1486+ * Calculate the total amount based on cursor expenses and various credits.
1487+ * Credit card payments are not included.
1488+ * @param cursor
1489+ * @return The total amount.
1490+ */
1491+ private long calculateTotal(Cursor cursor) {
1492+ long total = 0;
1493+ cursor.moveToFirst();
1494+ if (isStatementPreview) {
1495+ // exclude payments
1496+ for (int i=0; i<cursor.getCount(); i++) {
1497+ if (cursor.getInt(cursor.getColumnIndex(TransactionColumns.IS_CCARD_PAYMENT))==0) {
1498+ total += cursor.getLong(cursor.getColumnIndex(TransactionColumns.FROM_AMOUNT));
1499+ }
1500+ cursor.moveToNext();
1501+ }
1502+ } else {
1503+ // consider all transactions
1504+ for (int i=0; i<cursor.getCount(); i++) {
1505+ total += cursor.getLong(cursor.getColumnIndex(TransactionColumns.FROM_AMOUNT));
1506+ cursor.moveToNext();
1507+ }
1508+ }
1509+
1510+ return total;
1511+ }
1512+
1513+
1514+ /**
1515+ * Adjust the title based on the credit card's payment day.
1516+ */
1517+ private void setCCardTitle() {
1518+
1519+ Calendar date = new GregorianCalendar(year, month-1, paymentDay);
1520+
1521+ monthStr = Integer.toString(date.get(Calendar.MONTH)+1);
1522+ yearStr = Integer.toString(date.get(Calendar.YEAR));
1523+
1524+ if (paymentDay<10) {
1525+ paymentDayStr = "0"+paymentDay;
1526+ } else {
1527+ paymentDayStr = Integer.toString(paymentDay);
1528+ }
1529+
1530+ if (monthStr.length()<2) {
1531+ monthStr = "0"+monthStr;
1532+ }
1533+
1534+ String pd = paymentDayStr + "/" + monthStr + "/" + yearStr;
1535+
1536+ // set payment date and label on title bar
1537+ TextView label = (TextView)findViewById(R.id.monthly_view_title);
1538+ label.setText(title+"\n" + pd);
1539+ // set payment date and label on total bar
1540+ TextView totalLabel = (TextView) findViewById(R.id.monthly_result_label);
1541+ totalLabel.setText(getResources().getString(R.string.bill_on)+" "+pd);
1542+ }
1543+
1544+ /**
1545+ * Adjust the title based on the credit card's payment day.
1546+ */
1547+ private void setTitle() {
1548+
1549+ Calendar date = new GregorianCalendar(year, month-1, 1);
1550+
1551+ SimpleDateFormat dateFormat = new SimpleDateFormat("MMMMM yyyy");
1552+ String pd = dateFormat.format(date.getTime());
1553+
1554+ TextView label = (TextView)findViewById(R.id.monthly_view_title);
1555+ label.setText(title+"\n" + pd);
1556+
1557+ }
1558+
1559+ // Update view
1560+ @Override
1561+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
1562+ super.onActivityResult(requestCode, resultCode, data);
1563+ setCCardInterval();
1564+ }
1565+
1566+ private Cursor getHeader(String type, int count) {
1567+ MatrixCursor header = new MatrixCursor(new String[] {
1568+ TransactionColumns.ID,
1569+ TransactionColumns.FROM_ACCOUNT_ID,
1570+ TransactionColumns.TO_ACCOUNT_ID,
1571+ TransactionColumns.CATEGORY_ID,
1572+ TransactionColumns.PROJECT_ID,
1573+ TransactionColumns.NOTE,
1574+ TransactionColumns.FROM_AMOUNT,
1575+ TransactionColumns.TO_AMOUNT,
1576+ TransactionColumns.DATETIME,
1577+ TransactionColumns.LOCATION_ID,
1578+ TransactionColumns.PROVIDER,
1579+ TransactionColumns.ACCURACY,
1580+ TransactionColumns.LATITUDE,
1581+ TransactionColumns.LONGITUDE,
1582+ TransactionColumns.IS_TEMPLATE,
1583+ TransactionColumns.TEMPLATE_NAME,
1584+ TransactionColumns.RECURRENCE,
1585+ TransactionColumns.NOTIFICATION_OPTIONS,
1586+ TransactionColumns.STATUS,
1587+ TransactionColumns.ATTACHED_PICTURE,
1588+ TransactionColumns.IS_CCARD_PAYMENT, type});
1589+ if (count>0) {
1590+ header.addRow(new Object[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,count});
1591+ }
1592+ return header;
1593+ }
1594+
1595+
1596+}
1597
1598=== added file 'src/ru/orangesoftware/financisto/adapter/CreditCardStatementAdapter.java'
1599--- src/ru/orangesoftware/financisto/adapter/CreditCardStatementAdapter.java 1970-01-01 00:00:00 +0000
1600+++ src/ru/orangesoftware/financisto/adapter/CreditCardStatementAdapter.java 2010-08-22 11:18:40 +0000
1601@@ -0,0 +1,217 @@
1602+package ru.orangesoftware.financisto.adapter;
1603+
1604+import java.util.Calendar;
1605+import java.util.GregorianCalendar;
1606+
1607+import ru.orangesoftware.financisto.R;
1608+import ru.orangesoftware.financisto.activity.MonthlyViewActivity;
1609+import ru.orangesoftware.financisto.db.DatabaseAdapter;
1610+import ru.orangesoftware.financisto.db.DatabaseHelper.TransactionColumns;
1611+import ru.orangesoftware.financisto.model.Currency;
1612+import ru.orangesoftware.financisto.utils.Utils;
1613+import android.content.Context;
1614+import android.database.Cursor;
1615+import android.graphics.Color;
1616+import android.graphics.Typeface;
1617+import android.view.LayoutInflater;
1618+import android.view.View;
1619+import android.view.ViewGroup;
1620+import android.widget.Filterable;
1621+import android.widget.SimpleCursorAdapter;
1622+import android.widget.TextView;
1623+
1624+public class CreditCardStatementAdapter extends SimpleCursorAdapter implements Filterable {
1625+
1626+ private int layout;
1627+
1628+ private Utils u;
1629+ private Currency currency;
1630+
1631+ private final int scheduledStyle = Typeface.ITALIC;
1632+ private final int scheduledColor;
1633+ private final int futureColor;
1634+ private final int negativeColor;
1635+ private final int normalStyle = Typeface.NORMAL;
1636+ private final int normalColor = Color.LTGRAY;
1637+
1638+ private boolean isStatementPreview = false;
1639+
1640+ /**
1641+ * Create an adapter to display the expenses list of a credit card bill.
1642+ * @param context The context.
1643+ * @param layout The layout id.
1644+ * @param c The cursor with all the expenses of a given credit card bill.
1645+ * @param from Array of columns.
1646+ * @param to Id of the columns in layout.
1647+ * @param cur The credit card base currency.
1648+ */
1649+ public CreditCardStatementAdapter (Context context, int layout, Cursor c, String[] from, int[] to, Currency cur) {
1650+ super(context, layout, c, from, to);
1651+ this.layout = layout;
1652+ u = new Utils(context);
1653+ this.currency = cur;
1654+ futureColor = context.getResources().getColor(R.color.future_color);
1655+ scheduledColor = context.getResources().getColor(R.color.scheduled);
1656+ negativeColor = context.getResources().getColor(R.color.negative_amount);
1657+ }
1658+
1659+ public boolean isStatementPreview() {
1660+ return isStatementPreview;
1661+ }
1662+
1663+ public void setStatementPreview(boolean isStatementPreview) {
1664+ this.isStatementPreview = isStatementPreview;
1665+ }
1666+
1667+ @Override
1668+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
1669+
1670+ Cursor c = getCursor();
1671+
1672+ final LayoutInflater inflater = LayoutInflater.from(context);
1673+ View v = inflater.inflate(layout, parent, false);
1674+
1675+ updateListItem(v, context, c);
1676+
1677+ return v;
1678+ }
1679+
1680+ @Override
1681+ public void bindView(View v, Context context, Cursor c) {
1682+ updateListItem(v, context, c);
1683+ }
1684+
1685+ /**
1686+ * Update the list of expenses, displaying the elements of the Cursor.
1687+ * @param v The view.
1688+ * @param context The context.
1689+ * @param c The cursor with all the bill transactions
1690+ */
1691+ private void updateListItem(View v, Context context, Cursor c) {
1692+ // get amount of expense
1693+ int valueCol = c.getColumnIndex(TransactionColumns.FROM_AMOUNT);
1694+ long value = c.getLong(valueCol);
1695+ // is scheduled?
1696+ boolean isScheduled = c.getInt(c.getColumnIndex(TransactionColumns.IS_TEMPLATE))==2;
1697+
1698+ // get columns values or needed parameters
1699+ long date = c.getLong(TransactionColumns.Indicies.DATETIME);
1700+ String note = c.getString(TransactionColumns.Indicies.NOTE);
1701+ int locId = c.getInt(TransactionColumns.Indicies.LOCATION_ID);
1702+ String location = null;
1703+ String desc = "";
1704+ boolean future = date>Calendar.getInstance().getTimeInMillis();
1705+
1706+ // draw headers for payments, various credits and expenses sections
1707+ if (c.getColumnIndex(MonthlyViewActivity.HEADER_PAYMENTS) != -1) {
1708+ drawGroupTitle(context.getResources().getString(R.string.header_payments), v);
1709+ return;
1710+ } else if (c.getColumnIndex(MonthlyViewActivity.HEADER_CREDITS) != -1) {
1711+ drawGroupTitle(context.getResources().getString(R.string.header_credits), v);
1712+ return;
1713+ } else if (c.getColumnIndex(MonthlyViewActivity.HEADER_EXPENSES) != -1) {
1714+ drawGroupTitle(context.getResources().getString(R.string.header_expenses), v);
1715+ return;
1716+ }
1717+
1718+ /*
1719+ * Set description:
1720+ * a) if location is set, format description considering location
1721+ * - "Location (Note)"
1722+ * b) otherwise, show description as note
1723+ * - "Note"
1724+ */
1725+ if (locId>0) {
1726+ DatabaseAdapter dba = new DatabaseAdapter(context);
1727+ dba.open();
1728+ location = dba.getLocation(locId).name;
1729+ dba.close();
1730+ if (note!=null && note.length()>0) {
1731+ desc = location+" ("+note+")";
1732+ } else {
1733+ desc = location;
1734+ }
1735+ } else {
1736+ desc = note;
1737+ }
1738+
1739+ // set expenses date, description and value to the respective columns
1740+ TextView dateText = (TextView) v.findViewById(R.id.list_date);
1741+ TextView descText = (TextView) v.findViewById(R.id.list_note);
1742+ TextView valueText = (TextView) v.findViewById(R.id.list_value);
1743+
1744+ dateText.setBackgroundColor(Color.rgb(17,17,17));
1745+ descText.setBackgroundColor(Color.rgb(17,17,17));
1746+ valueText.setBackgroundColor(Color.rgb(17,17,17));
1747+
1748+ if (dateText != null) {
1749+ dateText.setText(getDate(date)+" ");
1750+ }
1751+ if (descText != null) {
1752+ descText.setText(desc);
1753+ }
1754+ if (valueText != null) {
1755+ if (isStatementPreview) {
1756+ u.setAmountText(valueText, currency, (-1)*value, false);
1757+ } else {
1758+ u.setAmountText(valueText, currency, value, false);
1759+ }
1760+ }
1761+
1762+ // set style
1763+ if (isScheduled) {
1764+ dateText.setTypeface(Typeface.defaultFromStyle(scheduledStyle), scheduledStyle);
1765+ descText.setTypeface(Typeface.defaultFromStyle(scheduledStyle), scheduledStyle);
1766+ valueText.setTypeface(Typeface.defaultFromStyle(scheduledStyle), scheduledStyle);
1767+ dateText.setTextColor(scheduledColor);
1768+ descText.setTextColor(scheduledColor);
1769+ valueText.setTextColor(scheduledColor);
1770+ } else {
1771+ dateText.setTypeface(Typeface.defaultFromStyle(normalStyle), normalStyle);
1772+ descText.setTypeface(Typeface.defaultFromStyle(normalStyle), normalStyle);
1773+ valueText.setTypeface(Typeface.defaultFromStyle(normalStyle), normalStyle);
1774+
1775+ // set color
1776+ if (future) {
1777+ // future expenses
1778+ dateText.setTextColor(futureColor);
1779+ descText.setTextColor(futureColor);
1780+ valueText.setTextColor(futureColor);
1781+ } else {
1782+ // normal
1783+ dateText.setTextColor(normalColor);
1784+ descText.setTextColor(normalColor);
1785+ // display colored negative values in month preview, but not in bill preview
1786+ if (value<0 && !isStatementPreview) valueText.setTextColor(negativeColor); else valueText.setTextColor(normalColor);
1787+ }
1788+ }
1789+ }
1790+
1791+ private void drawGroupTitle(String title, View v) {
1792+ TextView dateText = (TextView) v.findViewById(R.id.list_date);
1793+ TextView descText = (TextView) v.findViewById(R.id.list_note);
1794+ TextView valueText = (TextView) v.findViewById(R.id.list_value);
1795+ dateText.setText("");
1796+ descText.setText(title);
1797+ valueText.setText("");
1798+ dateText.setBackgroundColor(Color.DKGRAY);
1799+ descText.setBackgroundColor(Color.DKGRAY);
1800+ valueText.setBackgroundColor(Color.DKGRAY);
1801+ descText.setTypeface(Typeface.defaultFromStyle(normalStyle), normalStyle);
1802+ descText.setTextColor(normalColor);
1803+ }
1804+
1805+ /**
1806+ * Return the string for date in the following format: dd/MM/yy.
1807+ * @param date Time in milliseconds.
1808+ * @return The string representing the given time in the format dd/MM/yy.
1809+ */
1810+ private String getDate(long date) {
1811+ Calendar cal = new GregorianCalendar();
1812+ cal.setTimeInMillis(date);
1813+ int d = cal.get(Calendar.DAY_OF_MONTH);
1814+ int m = cal.get(Calendar.MONTH)+1;
1815+ int y = cal.get(Calendar.YEAR);
1816+ return (d<10?"0"+d:d)+"/"+(m<10?"0"+m:m)+"/"+(y-2000);
1817+ }
1818+ }
1819
1820=== modified file 'src/ru/orangesoftware/financisto/backup/DatabaseImport.java'
1821--- src/ru/orangesoftware/financisto/backup/DatabaseImport.java 2010-08-05 13:50:00 +0000
1822+++ src/ru/orangesoftware/financisto/backup/DatabaseImport.java 2010-08-22 11:18:40 +0000
1823@@ -17,6 +17,7 @@
1824 import java.io.File;
1825 import java.io.FileInputStream;
1826 import java.io.IOException;
1827+import java.io.InputStream;
1828 import java.io.InputStreamReader;
1829
1830 import ru.orangesoftware.financisto.db.Database;
1831@@ -29,9 +30,10 @@
1832 import android.content.ContentValues;
1833 import android.content.Context;
1834 import android.database.Cursor;
1835-import android.database.DatabaseUtils;
1836+//import android.database.DatabaseUtils;
1837 import android.database.sqlite.SQLiteDatabase;
1838 import android.util.Log;
1839+import api.wireless.gdata.docs.client.DocsClient;
1840
1841 public class DatabaseImport {
1842
1843@@ -49,7 +51,31 @@
1844
1845 public void importDatabase() throws IOException {
1846 File file = new File(Export.EXPORT_PATH, backupFile);
1847- InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");
1848+ FileInputStream inputStream = new FileInputStream(file);
1849+ recoverDatabase(inputStream);
1850+ }
1851+
1852+ /**
1853+ * Get backup file from Google docs
1854+ *
1855+ * @param docsClient The Google Docs connection
1856+ * @param resourceId the key of the recovery document on google docs
1857+ **/
1858+ public void importOnlineDatabase(DocsClient docsClient, String resourceId) throws Exception {
1859+ InputStream inputStream=null;
1860+ inputStream = docsClient.getDocumentMediaAsTXT(resourceId);
1861+ recoverDatabase(inputStream);
1862+ inputStream.close();
1863+ }
1864+
1865+ /**
1866+ * Recover database from a inputStream
1867+ *
1868+ * @param inputStream stream with the backup data
1869+ **/
1870+ protected void recoverDatabase(InputStream inputStream) throws IOException
1871+ {
1872+ InputStreamReader isr = new InputStreamReader(inputStream, "UTF-8");
1873 BufferedReader br = new BufferedReader(isr, 65535);
1874 try {
1875 db.beginTransaction();
1876@@ -101,14 +127,14 @@
1877 }
1878 }
1879
1880- private void printCurrentSchema() {
1881+ /*private void printCurrentSchema() {
1882 Cursor c = db.rawQuery("SELECT * FROM sqlite_master where type='table'", null);
1883 try {
1884 DatabaseUtils.dumpCursor(c);
1885 } finally {
1886 c.close();
1887 }
1888- }
1889+ }*/
1890
1891 private void scheduleAll() {
1892 FinancistoService.scheduleAll(context, new MyEntityManager(context, db));
1893
1894=== added file 'src/ru/orangesoftware/financisto/backup/SettingsNotConfiguredException.java'
1895--- src/ru/orangesoftware/financisto/backup/SettingsNotConfiguredException.java 1970-01-01 00:00:00 +0000
1896+++ src/ru/orangesoftware/financisto/backup/SettingsNotConfiguredException.java 2010-08-22 11:18:40 +0000
1897@@ -0,0 +1,33 @@
1898+/* Copyright (c) 2008 Google Inc.
1899+ *
1900+ * Licensed under the Apache License, Version 2.0 (the "License");
1901+ * you may not use this file except in compliance with the License.
1902+ * You may obtain a copy of the License at
1903+ *
1904+ * http://www.apache.org/licenses/LICENSE-2.0
1905+ *
1906+ * Unless required by applicable law or agreed to in writing, software
1907+ * distributed under the License is distributed on an "AS IS" BASIS,
1908+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1909+ * See the License for the specific language governing permissions and
1910+ * limitations under the License.
1911+ */
1912+
1913+
1914+package ru.orangesoftware.financisto.backup;
1915+
1916+/**
1917+ * Exceção usada quando ocorre algum erro relacionado aos parametros de configuração do usuário
1918+ * */
1919+public class SettingsNotConfiguredException extends Exception {
1920+
1921+ public static final long serialVersionUID = 1;
1922+
1923+ public SettingsNotConfiguredException() {
1924+ super();
1925+ }
1926+
1927+ public SettingsNotConfiguredException(String msg) {
1928+ super(msg);
1929+ }
1930+}
1931
1932=== modified file 'src/ru/orangesoftware/financisto/db/DatabaseAdapter.java'
1933--- src/ru/orangesoftware/financisto/db/DatabaseAdapter.java 2010-07-27 13:00:40 +0000
1934+++ src/ru/orangesoftware/financisto/db/DatabaseAdapter.java 2010-08-22 11:18:40 +0000
1935@@ -7,6 +7,7 @@
1936 *
1937 * Contributors:
1938 * Denis Solonenko - initial API and implementation
1939+ * Abdsandryk - implement getAllExpenses method for bill filtering
1940 ******************************************************************************/
1941 package ru.orangesoftware.financisto.db;
1942
1943@@ -39,11 +40,13 @@
1944 import ru.orangesoftware.financisto.db.DatabaseHelper.CategoryAttributeColumns;
1945 import ru.orangesoftware.financisto.db.DatabaseHelper.CategoryColumns;
1946 import ru.orangesoftware.financisto.db.DatabaseHelper.CategoryViewColumns;
1947+import ru.orangesoftware.financisto.db.DatabaseHelper.LocationColumns;
1948 import ru.orangesoftware.financisto.db.DatabaseHelper.TransactionAttributeColumns;
1949 import ru.orangesoftware.financisto.db.DatabaseHelper.TransactionColumns;
1950 import ru.orangesoftware.financisto.model.Attribute;
1951 import ru.orangesoftware.financisto.model.Category;
1952 import ru.orangesoftware.financisto.model.CategoryTree;
1953+import ru.orangesoftware.financisto.model.MyLocation;
1954 import ru.orangesoftware.financisto.model.SystemAttribute;
1955 import ru.orangesoftware.financisto.model.Total;
1956 import ru.orangesoftware.financisto.model.Transaction;
1957@@ -53,6 +56,7 @@
1958 import android.content.ContentValues;
1959 import android.content.Context;
1960 import android.database.Cursor;
1961+import android.database.MergeCursor;
1962 import android.database.sqlite.SQLiteDatabase;
1963 import android.database.sqlite.SQLiteException;
1964 import android.util.Log;
1965@@ -181,6 +185,100 @@
1966 BlotterColumns.DATETIME+" DESC");
1967 }
1968
1969+ /**
1970+ * [Bill Filtering] Returns all the expenses (negative amount) for a given Account in a given period.
1971+ * @param accountId Account id.
1972+ * @param start Start date.
1973+ * @param end End date.
1974+ * @return Transactions (negative amount) of the given Account, from start date to end date.
1975+ */
1976+ public Cursor getAllExpenses(String accountId, String start, String end) {
1977+ // query
1978+ String where = TransactionColumns.FROM_ACCOUNT_ID+"=? AND "+TransactionColumns.FROM_AMOUNT+"<? AND "+
1979+ TransactionColumns.DATETIME+">? AND "+TransactionColumns.DATETIME+"<?";
1980+
1981+ try {
1982+ Cursor c = db.query(TRANSACTION_TABLE, TransactionColumns.NORMAL_PROJECTION,
1983+ where, new String[]{accountId, "0", start, end}, null, null, TransactionColumns.DATETIME);
1984+ return c;
1985+ } catch(SQLiteException e) {
1986+ return null;
1987+ }
1988+ }
1989+
1990+
1991+ /**
1992+ * [Bill Filtering] Returns the credits (positive amount) for a given Account in a given period, excluding payments.
1993+ * @param accountId Account id.
1994+ * @param start Start date.
1995+ * @param end End date.
1996+ * @return Transactions (positive amount) of the given Account, from start date to end date.
1997+ */
1998+ public Cursor getCredits(String accountId, String start, String end) {
1999+ // query
2000+ String where = TransactionColumns.FROM_ACCOUNT_ID+"=? AND "+TransactionColumns.FROM_AMOUNT+">? AND "+
2001+ TransactionColumns.DATETIME+">? AND "+TransactionColumns.DATETIME+"<? AND "+
2002+ TransactionColumns.IS_CCARD_PAYMENT+"=?";
2003+
2004+ try {
2005+ Cursor c = db.query(TRANSACTION_TABLE, TransactionColumns.NORMAL_PROJECTION,
2006+ where, new String[]{accountId, "0", start, end, "0"}, null, null, TransactionColumns.DATETIME);
2007+ return c;
2008+ } catch(SQLiteException e) {
2009+ return null;
2010+ }
2011+ }
2012+
2013+ /**
2014+ * [Bill Filtering] Returns all the payments for a given Credit Card Account in a given period.
2015+ * @param accountId Account id.
2016+ * @param start Start date.
2017+ * @param end End date.
2018+ * @return Transactions of the given Account, from start date to end date.
2019+ */
2020+ public Cursor getPayments(String accountId, String start, String end) {
2021+ // query direct payments
2022+ String where = TransactionColumns.FROM_ACCOUNT_ID+"=? AND "+TransactionColumns.FROM_AMOUNT+">? AND "+
2023+ TransactionColumns.DATETIME+">? AND "+TransactionColumns.DATETIME+"<? AND "+
2024+ TransactionColumns.IS_CCARD_PAYMENT+"=?";
2025+
2026+ String whereTransfer = TransactionColumns.TO_ACCOUNT_ID+"=? AND "+TransactionColumns.TO_AMOUNT+">? AND "+
2027+ TransactionColumns.DATETIME+">? AND "+TransactionColumns.DATETIME+"<? AND "+
2028+ TransactionColumns.IS_CCARD_PAYMENT+"=?";
2029+
2030+ try {
2031+ Cursor c1 = db.query(TRANSACTION_TABLE, TransactionColumns.NORMAL_PROJECTION,
2032+ where, new String[]{accountId, "0", start, end, "1"}, null, null, TransactionColumns.DATETIME);
2033+ Cursor c2 = db.query(TRANSACTION_TABLE, TransactionColumns.NORMAL_PROJECTION,
2034+ whereTransfer, new String[]{accountId, "0", start, end, "1"}, null, null, TransactionColumns.DATETIME);
2035+ Cursor c = new MergeCursor(new Cursor[] {c1, c2});
2036+ return c;
2037+ } catch(SQLiteException e) {
2038+ return null;
2039+ }
2040+ }
2041+
2042+ /**
2043+ * [Monthly view] Returns all the transactions for a given Account in a given period (month).
2044+ * @param accountId Account id.
2045+ * @param start Start date.
2046+ * @param end End date.
2047+ * @return Transactions (negative value) of the given Account, from start date to end date.
2048+ */
2049+ public Cursor getAllTransactions(String accountId, String start, String end) {
2050+ // query
2051+ String where = TransactionColumns.FROM_ACCOUNT_ID+"=? AND "+
2052+ TransactionColumns.DATETIME+">? AND "+TransactionColumns.DATETIME+"<?";
2053+
2054+ try {
2055+ Cursor c = db.query(TRANSACTION_TABLE, TransactionColumns.NORMAL_PROJECTION,
2056+ where, new String[]{accountId, start, end}, null, null, TransactionColumns.DATETIME);
2057+ return c;
2058+ } catch(SQLiteException e) {
2059+ return null;
2060+ }
2061+ }
2062+
2063 public Cursor getTransactions(WhereFilter filter) {
2064 String sortOrder = getBlotterSortOrder(filter);
2065 return db.query(V_BLOTTER_FOR_ACCOUNT, BlotterColumns.NORMAL_PROJECTION,
2066@@ -962,6 +1060,37 @@
2067 c.close();
2068 }
2069 }
2070+
2071+
2072+ /**
2073+ * Gets the location for a given id.
2074+ * @param id
2075+ * @return
2076+ */
2077+ public MyLocation getLocation(long id) {
2078+ Cursor c = db.query(LOCATIONS_TABLE, LocationColumns.NORMAL_PROJECTION,
2079+ LocationColumns.ID+"=?", new String[]{String.valueOf(id)}, null, null, null);
2080+ try {
2081+ if (c.moveToNext()) {
2082+ MyLocation loc = new MyLocation();
2083+ loc.id = id;
2084+ loc.accuracy = c.getLong(c.getColumnIndex(LocationColumns.ACCURACY));
2085+ loc.dateTime = c.getLong(c.getColumnIndex(LocationColumns.DATETIME));
2086+ loc.isPayee = false;
2087+ loc.latitude = c.getDouble(c.getColumnIndex(LocationColumns.LATITUDE));
2088+ loc.longitude = c.getDouble(c.getColumnIndex(LocationColumns.LONGITUDE));
2089+ loc.name = c.getString(c.getColumnIndex(LocationColumns.NAME));
2090+ loc.provider = c.getString(c.getColumnIndex(LocationColumns.PROVIDER));
2091+ loc.resolvedAddress = c.getString(c.getColumnIndex(LocationColumns.RESOLVED_ADDRESS));
2092+
2093+ return loc;
2094+ } else {
2095+ return new MyLocation();
2096+ }
2097+ } finally {
2098+ c.close();
2099+ }
2100+ }
2101
2102 }
2103
2104
2105=== modified file 'src/ru/orangesoftware/financisto/db/DatabaseHelper.java'
2106--- src/ru/orangesoftware/financisto/db/DatabaseHelper.java 2010-08-19 10:35:29 +0000
2107+++ src/ru/orangesoftware/financisto/db/DatabaseHelper.java 2010-08-22 11:18:40 +0000
2108@@ -82,7 +82,8 @@
2109 public static final String RECURRENCE = "recurrence";
2110 public static final String NOTIFICATION_OPTIONS = "notification_options";
2111 public static final String STATUS = "status";
2112- public static final String ATTACHED_PICTURE = "attached_picture";
2113+ public static final String ATTACHED_PICTURE = "attached_picture";
2114+ public static final String IS_CCARD_PAYMENT = "is_ccard_payment";
2115
2116 public static String[] NORMAL_PROJECTION = {
2117 ID,
2118@@ -104,7 +105,8 @@
2119 RECURRENCE,
2120 NOTIFICATION_OPTIONS,
2121 STATUS,
2122- ATTACHED_PICTURE};
2123+ ATTACHED_PICTURE,
2124+ IS_CCARD_PAYMENT};
2125
2126 public static class Indicies {
2127 public static final int ID = 0;
2128@@ -127,6 +129,7 @@
2129 public static final int NOTIFICATION_OPTIONS = 17;
2130 public static final int STATUS = 18;
2131 public static final int ATTACHED_PICTURE = 19;
2132+ public static final int IS_CCARD_PAYMENT = 20;
2133 }
2134
2135 private TransactionColumns() {}
2136@@ -157,7 +160,7 @@
2137 public static final String TEMPLATE_NAME = "template_name";
2138 public static final String RECURRENCE = "recurrence";
2139 public static final String NOTIFICATION_OPTIONS = "notification_options";
2140- public static final String STATUS = "status";
2141+ public static final String STATUS = "status";
2142
2143 public static final String[] NORMAL_PROJECTION = {
2144 ID,
2145@@ -233,6 +236,8 @@
2146 public static final String SORT_ORDER = "sort_order";
2147 public static final String LAST_CATEGORY_ID = "last_category_id";
2148 public static final String LAST_ACCOUNT_ID = "last_account_id";
2149+ public static final String CLOSING_DAY = "closing_day";
2150+ public static final String PAYMENT_DAY = "payment_day";
2151
2152 private AccountColumns() {}
2153
2154@@ -395,4 +400,19 @@
2155 public static String[] NORMAL_PROJECTION = {ID, NAME, CURRENCY_ID, AMOUNT, LEFT, RIGHT};
2156 }
2157
2158+ public static class LocationColumns {
2159+
2160+ public static final String ID = "_id";
2161+ public static final String NAME = "name";
2162+ public static final String DATETIME = "datetime";
2163+ public static final String PROVIDER = "provider";
2164+ public static final String ACCURACY = "accuracy";
2165+ public static final String LATITUDE = "latitude";
2166+ public static final String LONGITUDE = "longitude";
2167+ public static final String IS_PAYEE = "is_payee";
2168+ public static final String RESOLVED_ADDRESS = "resolved_address";
2169+
2170+ public static String[] NORMAL_PROJECTION = {ID, NAME, DATETIME, PROVIDER, ACCURACY, LATITUDE, LONGITUDE, IS_PAYEE, RESOLVED_ADDRESS};
2171+ }
2172+
2173 }
2174
2175=== modified file 'src/ru/orangesoftware/financisto/export/Export.java'
2176--- src/ru/orangesoftware/financisto/export/Export.java 2010-06-02 15:22:10 +0000
2177+++ src/ru/orangesoftware/financisto/export/Export.java 2010-08-22 11:18:40 +0000
2178@@ -11,32 +11,77 @@
2179 package ru.orangesoftware.financisto.export;
2180
2181 import java.io.BufferedWriter;
2182+import java.io.ByteArrayInputStream;
2183+import java.io.ByteArrayOutputStream;
2184 import java.io.File;
2185 import java.io.FileOutputStream;
2186+import java.io.InputStream;
2187+import java.io.OutputStream;
2188 import java.io.OutputStreamWriter;
2189 import java.text.SimpleDateFormat;
2190 import java.util.Date;
2191
2192+import api.wireless.gdata.docs.client.DocsClient;
2193+import api.wireless.gdata.docs.data.DocumentEntry;
2194+import api.wireless.gdata.docs.data.FolderEntry;
2195+
2196 public abstract class Export {
2197
2198 public static final String EXPORT_PATH = "/sdcard/financisto/";
2199
2200 public String export() throws Exception {
2201- SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd'_'HHmmss'_'SSS");
2202- String fileName = df.format(new Date())+getExtension();
2203+ String fileName = generateFilename();
2204 File path = new File(getPath());
2205 path.mkdirs();
2206 File file = new File(path, fileName);
2207- OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
2208+ FileOutputStream outputStream = new FileOutputStream(file);
2209+ generateBackup(outputStream);
2210+ return fileName;
2211+ }
2212+
2213+ /**
2214+ * Backup database to google docs
2215+ *
2216+ * @param docsClient Google docs connection
2217+ * @param folder Google docs folder name
2218+ * */
2219+ public String exportOnline(DocsClient docsClient, String folder) throws Exception {
2220+ // generation backup file
2221+ String fileName = generateFilename();
2222+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
2223+ generateBackup(outputStream);
2224+
2225+ // transforming streams
2226+ InputStream backup = new ByteArrayInputStream(outputStream.toByteArray());
2227+
2228+ // creating document on Google Docs
2229+ DocumentEntry entry = new DocumentEntry();
2230+ entry.setTitle(fileName);
2231+ FolderEntry fd = docsClient.getFolderByTitle(folder);
2232+ docsClient.createDocumentInFolder(entry, backup, "text/plain",fd.getKey());
2233+
2234+ return fileName;
2235+ }
2236+
2237+ private String generateFilename()
2238+ {
2239+ SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd'_'HHmmss'_'SSS");
2240+ return df.format(new Date())+getExtension();
2241+ }
2242+
2243+ private void generateBackup(OutputStream outputStream) throws Exception
2244+ {
2245+ OutputStreamWriter osw = new OutputStreamWriter(outputStream, "UTF-8");
2246 BufferedWriter bw = new BufferedWriter(osw, 65536);
2247+
2248 try {
2249 writeHeader(bw);
2250 writeBody(bw);
2251 writeFooter(bw);
2252- return fileName;
2253- } finally {
2254+ }
2255+ finally {
2256 bw.close();
2257- }
2258+ }
2259 }
2260
2261 protected abstract void writeHeader(BufferedWriter bw) throws Exception;
2262
2263=== modified file 'src/ru/orangesoftware/financisto/export/ImportExportAsyncTask.java'
2264--- src/ru/orangesoftware/financisto/export/ImportExportAsyncTask.java 2010-06-02 15:22:10 +0000
2265+++ src/ru/orangesoftware/financisto/export/ImportExportAsyncTask.java 2010-08-22 11:18:40 +0000
2266@@ -51,19 +51,19 @@
2267 @Override
2268 protected void onPostExecute(Object result) {
2269 dialog.dismiss();
2270- String message;
2271- String title;
2272- if (result instanceof Exception) {
2273- Exception e = (Exception)result;
2274- title = context.getString(R.string.fail);
2275- message = e.getClass().getSimpleName()+":"+e.getMessage();
2276- } else {
2277- title = context.getString(R.string.success);
2278- message = getSuccessMessage(result);
2279- }
2280+ String message=null;
2281+ String title=null;
2282+
2283+ if (result instanceof Exception)
2284+ return;
2285+
2286+ title = context.getString(R.string.success);
2287+ message = getSuccessMessage(result);
2288+
2289 if (listener != null) {
2290 listener.onCompleted();
2291 }
2292+
2293 new AlertDialog.Builder(context)
2294 .setTitle(title)
2295 .setMessage(message)
2296
2297=== modified file 'src/ru/orangesoftware/financisto/model/Account.java'
2298--- src/ru/orangesoftware/financisto/model/Account.java 2010-06-02 15:22:10 +0000
2299+++ src/ru/orangesoftware/financisto/model/Account.java 2010-08-22 11:18:40 +0000
2300@@ -7,6 +7,7 @@
2301 *
2302 * Contributors:
2303 * Denis Solonenko - initial API and implementation
2304+ * Abdsandryk - parameters for bill filtering
2305 ******************************************************************************/
2306 package ru.orangesoftware.financisto.model;
2307
2308@@ -65,4 +66,12 @@
2309
2310 @Column(name = "last_category_id")
2311 public long lastCategoryId;
2312+
2313+ /** parameters for credit card bills filtering */
2314+ @Column(name = "closing_day")
2315+ public int closingDay;
2316+
2317+ @Column(name = "payment_day")
2318+ public int paymentDay;
2319+ /***********************************************/
2320 }
2321
2322=== modified file 'src/ru/orangesoftware/financisto/model/AccountType.java'
2323--- src/ru/orangesoftware/financisto/model/AccountType.java 2010-06-02 15:22:10 +0000
2324+++ src/ru/orangesoftware/financisto/model/AccountType.java 2010-08-22 11:18:40 +0000
2325@@ -7,33 +7,37 @@
2326 *
2327 * Contributors:
2328 * Denis Solonenko - initial API and implementation
2329+ * Abdsandryk - parameters for bill filtering
2330 ******************************************************************************/
2331 package ru.orangesoftware.financisto.model;
2332
2333 import ru.orangesoftware.financisto.R;
2334
2335 public enum AccountType {
2336- CASH(R.string.account_type_cash, R.drawable.account_type_cash, false, false, false),
2337- BANK(R.string.account_type_bank, R.drawable.account_type_bank, true, false, false),
2338- DEBIT_CARD(R.string.account_type_debit_card, R.drawable.account_type_debit_card, true, true, true),
2339- CREDIT_CARD(R.string.account_type_credit_card, R.drawable.account_type_credit_card, true, true, true),
2340- ASSET(R.string.account_type_asset, R.drawable.account_type_other, false, false, false),
2341- LIABILITY(R.string.account_type_liability, R.drawable.account_type_other, false, false, false),
2342- OTHER(R.string.account_type_other, R.drawable.account_type_other, false, false, false);
2343+ CASH(R.string.account_type_cash, R.drawable.account_type_cash, false, false, false, false),
2344+ BANK(R.string.account_type_bank, R.drawable.account_type_bank, true, false, false, false),
2345+ DEBIT_CARD(R.string.account_type_debit_card, R.drawable.account_type_debit_card, true, true, true, false),
2346+ CREDIT_CARD(R.string.account_type_credit_card, R.drawable.account_type_credit_card, true, true, true, true),
2347+ ASSET(R.string.account_type_asset, R.drawable.account_type_other, false, false, false, false),
2348+ LIABILITY(R.string.account_type_liability, R.drawable.account_type_other, false, false, false, false),
2349+ OTHER(R.string.account_type_other, R.drawable.account_type_other, false, false, false, false);
2350
2351 public final int titleId;
2352 public final int iconId;
2353 public final boolean hasIssuer;
2354 public final boolean hasNumber;
2355 public final boolean isCard;
2356+ public final boolean isCreditCard;
2357
2358 private AccountType(int titleId, int iconId,
2359- boolean hasIssuer, boolean hasNumber, boolean isCard) {
2360+ boolean hasIssuer, boolean hasNumber, boolean isCard, boolean isCreditCard) {
2361 this.titleId = titleId;
2362 this.iconId = iconId;
2363 this.hasIssuer = hasIssuer;
2364 this.hasNumber = hasNumber;
2365 this.isCard = isCard;
2366+ this.isCreditCard = isCreditCard;
2367+
2368 }
2369
2370 }
2371
2372=== modified file 'src/ru/orangesoftware/financisto/model/Transaction.java'
2373--- src/ru/orangesoftware/financisto/model/Transaction.java 2010-06-17 15:30:33 +0000
2374+++ src/ru/orangesoftware/financisto/model/Transaction.java 2010-08-22 11:18:40 +0000
2375@@ -7,6 +7,7 @@
2376 *
2377 * Contributors:
2378 * Denis Solonenko - initial API and implementation
2379+ * Abdsandryk - identifying credit card payments
2380 ******************************************************************************/
2381 package ru.orangesoftware.financisto.model;
2382
2383@@ -89,6 +90,9 @@
2384
2385 @Column(name = "attached_picture")
2386 public String attachedPicture;
2387+
2388+ @Column(name = "is_ccard_payment")
2389+ public int isCCardPayment;
2390
2391 @Transient
2392 public EnumMap<SystemAttribute, String> systemAttributes;
2393@@ -114,6 +118,7 @@
2394 values.put(TransactionColumns.NOTIFICATION_OPTIONS, notificationOptions);
2395 values.put(TransactionColumns.STATUS, status.name());
2396 values.put(TransactionColumns.ATTACHED_PICTURE, attachedPicture);
2397+ values.put(TransactionColumns.IS_CCARD_PAYMENT, isCCardPayment);
2398 return values;
2399 }
2400
2401@@ -140,6 +145,7 @@
2402 t.notificationOptions = c.getString(TransactionColumns.Indicies.NOTIFICATION_OPTIONS);
2403 t.status = TransactionStatus.valueOf(c.getString(TransactionColumns.Indicies.STATUS));
2404 t.attachedPicture = c.getString(TransactionColumns.Indicies.ATTACHED_PICTURE);
2405+ t.isCCardPayment = c.getInt(TransactionColumns.Indicies.IS_CCARD_PAYMENT);
2406 return t;
2407 }
2408
2409@@ -163,6 +169,10 @@
2410 return isTemplate == 0;
2411 }
2412
2413+ public boolean isCreditCardPayment() {
2414+ return isCCardPayment == 1;
2415+ }
2416+
2417 public String getSystemAttribute(SystemAttribute sa) {
2418 return systemAttributes != null ? systemAttributes.get(sa) : null;
2419 }
2420
2421=== modified file 'src/ru/orangesoftware/financisto/utils/MyPreferences.java'
2422--- src/ru/orangesoftware/financisto/utils/MyPreferences.java 2010-08-19 10:35:29 +0000
2423+++ src/ru/orangesoftware/financisto/utils/MyPreferences.java 2010-08-22 11:18:40 +0000
2424@@ -125,6 +125,30 @@
2425 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
2426 return Integer.parseInt(sharedPreferences.getString("ntsl_show_location_order", "1"));
2427 }
2428+
2429+ /**
2430+ * Get google docs user login registered on preferences
2431+ * */
2432+ public static String getUserLogin(Context context) {
2433+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
2434+ return sharedPreferences.getString("user_login", null);
2435+ }
2436+
2437+ /**
2438+ * Get google docs user password registered on preferences
2439+ * */
2440+ public static String getUserPassword(Context context) {
2441+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
2442+ return sharedPreferences.getString("user_password", null);
2443+ }
2444+
2445+ /**
2446+ * Get google docs backup folder registered on preferences
2447+ * */
2448+ public static String getBackupFolder(Context context) {
2449+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
2450+ return sharedPreferences.getString("backup_folder", null);
2451+ }
2452
2453 public static boolean isShowNote(Context context) {
2454 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
2455
2456=== modified file 'src/ru/orangesoftware/financisto/widget/AmountInput.java'
2457--- src/ru/orangesoftware/financisto/widget/AmountInput.java 2010-08-19 13:42:10 +0000
2458+++ src/ru/orangesoftware/financisto/widget/AmountInput.java 2010-08-22 11:18:40 +0000
2459@@ -70,10 +70,14 @@
2460 initialize(context, null);
2461 }
2462
2463- public void allowNegativeAmount() {
2464+ public void setAllowNegativeAmount() {
2465 allowNegativeAmount = true;
2466 }
2467
2468+ public boolean allowNegativeAmount() {
2469+ return allowNegativeAmount;
2470+ }
2471+
2472 @Override
2473 public void setEnabled(boolean enabled) {
2474 super.setEnabled(enabled);