Merge lp:~bellini666/stoqlib/payment_list into lp:~stoq-dev/stoqlib/master
- payment_list
- Merge into master
Status: | Superseded |
---|---|
Proposed branch: | lp:~bellini666/stoqlib/payment_list |
Merge into: | lp:~stoq-dev/stoqlib/master |
Diff against target: |
2704 lines (+1065/-1154) 16 files modified
data/glade/BankDataSlave.glade (+80/-62) data/glade/BasePaymentDataEditor.glade (+118/-0) data/glade/BasePaymentMethodSlave.glade (+162/-253) data/glade/BillDataSlave.glade (+0/-124) data/glade/PaymentListSlave.glade (+48/-56) data/glade/PurchasePaymentStep.glade (+1/-66) stoqlib/database/admin.py (+1/-1) stoqlib/database/testsuite.py (+1/-1) stoqlib/domain/payment/method.py (+6/-3) stoqlib/domain/payment/operation.py (+1/-1) stoqlib/domain/payment/payment.py (+3/-1) stoqlib/gui/slaves/paymentslave.py (+431/-553) stoqlib/gui/wizards/purchasewizard.py (+4/-10) stoqlib/lib/defaults.py (+18/-23) stoqlib/lib/payment.py (+61/-0) stoqlib/lib/test/test_payment.py (+130/-0) |
To merge this branch: | bzr merge lp:~bellini666/stoqlib/payment_list |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ronaldo Maia | Needs Fixing | ||
Review via email: mp+48035@code.launchpad.net |
This proposal has been superseded by a proposal from 2011-02-01.
Commit message
Description of the change
- 3304. By Thiago Bellini
-
Refactoring of PaymentListSlave class and bugfixes.
- 3305. By Ronaldo Maia
-
Adicionando parametro para exibir (ou não) a coluna custo no wizard de venda (customização)
- 3306. By Johan Dahlin
-
Remove individual authors
Most people do no longer work on the project, so there's no use in
displaying them in the copyright header. Besides we're using a
versioning control system which can be used if anyone really want to know
who wrote the code. - 3307. By Ronaldo Maia
-
Removendo restante do ValidatableDomain
- 3308. By Ronaldo Maia
-
clean up after removing individual authors
- 3309. By Ronaldo Maia
-
update translation files
- 3310. By Ronaldo Maia
-
copy tranlations file from first attempt to use launchpad translations
- 3311. By Ronaldo Maia
-
Release 0.9.15
- 3312. By Thiago Bellini
-
Add an option to change the freight type when receiving an order. Fixes #4245
- 3313. By Gabriel Gerga
-
Removed retention functionality and added cfop field in stock_decrease_item table. r=romaia
- 3314. By Gabriel Gerga
-
Create StockDecreaseIt
emEditor, inheriting from PurchaseItemEditor. r=romaia - 3315. By George Kussumoto
-
Fix: supports_
duplicate_ receipt is a property, not a method. - 3316. By Thiago Bellini
-
Modifications to Purchase Details dialog to make it more useful. Fixes #4245
- 3317. By Gabriel Gerga
-
Added print dialog when confirmed a quote. r=romaia
- 3318. By Thiago Bellini
-
When editing a purchase, generate a better PaymentList.
When editing, the PaymentList will create the payments based on the number of
installments it had before and the first due date will be set to the first's
payment due date. - 3319. By Thiago Bellini
-
When editing a row on PaymentList, set focus on payment number.
- 3320. By Thiago Bellini
-
Code corrections.
Unmerged revisions
- 3320. By Thiago Bellini
-
Code corrections.
- 3319. By Thiago Bellini
-
When editing a row on PaymentList, set focus on payment number.
- 3318. By Thiago Bellini
-
When editing a purchase, generate a better PaymentList.
When editing, the PaymentList will create the payments based on the number of
installments it had before and the first due date will be set to the first's
payment due date.
Preview Diff
1 | === modified file 'data/glade/BankDataSlave.glade' |
2 | --- data/glade/BankDataSlave.glade 2006-06-08 19:02:06 +0000 |
3 | +++ data/glade/BankDataSlave.glade 2011-02-01 20:17:04 +0000 |
4 | @@ -4,88 +4,106 @@ |
5 | <widget class="GtkWindow" id="BankDataSlave"> |
6 | <property name="default_height">250</property> |
7 | <property name="default_width">440</property> |
8 | + <property name="mnemonics_visible">False</property> |
9 | <child> |
10 | <widget class="GtkVBox" id="vbox1"> |
11 | + <property name="border_width">3</property> |
12 | + <property name="spacing">5</property> |
13 | <property name="visible">True</property> |
14 | <child> |
15 | <widget class="GtkHSeparator" id="hseparator1"> |
16 | <property name="visible">True</property> |
17 | </widget> |
18 | - <packing> |
19 | - <property name="expand">False</property> |
20 | - <property name="padding">6</property> |
21 | - </packing> |
22 | </child> |
23 | <child> |
24 | - <widget class="GtkHBox" id="hbox1"> |
25 | - <property name="spacing">5</property> |
26 | + <widget class="GtkTable" id="table1"> |
27 | + <property name="column_spacing">6</property> |
28 | + <property name="n_columns">2</property> |
29 | + <property name="n_rows">3</property> |
30 | + <property name="row_spacing">6</property> |
31 | <property name="visible">True</property> |
32 | <child> |
33 | - <widget class="GtkAlignment" id="alignment1"> |
34 | - <property name="visible">True</property> |
35 | - <child> |
36 | - <widget class="kiwi+ui+widgets+label+Label" id="kiwilabel1"> |
37 | - <property name="data_type">unicode</property> |
38 | - <property name="label" context="yes" translatable="yes">Bank ID:</property> |
39 | - <property name="visible">True</property> |
40 | - <property name="xalign">1.0</property> |
41 | - </widget> |
42 | - </child> |
43 | - </widget> |
44 | - <packing> |
45 | - <property name="expand">False</property> |
46 | - </packing> |
47 | - </child> |
48 | - <child> |
49 | - <widget class="kiwi+ui+widgets+entry+Entry" id="bank"> |
50 | + <widget class="ProxyLabel" id="kiwilabel1"> |
51 | + <property name="data_type">unicode</property> |
52 | + <property name="label" context="yes" translatable="yes">Bank ID:</property> |
53 | + <property name="model_attribute">kiwilabel1</property> |
54 | + <property name="visible">True</property> |
55 | + <property name="xalign">1.0</property> |
56 | + </widget> |
57 | + </child> |
58 | + <child> |
59 | + <widget class="ProxyLabel" id="kiwilabel2"> |
60 | + <property name="data_type">unicode</property> |
61 | + <property name="label" context="yes" translatable="yes">Bank Branch:</property> |
62 | + <property name="model_attribute">kiwilabel2</property> |
63 | + <property name="visible">True</property> |
64 | + <property name="xalign">1.0</property> |
65 | + </widget> |
66 | + <packing> |
67 | + <property name="bottom_attach">2</property> |
68 | + <property name="top_attach">1</property> |
69 | + </packing> |
70 | + </child> |
71 | + <child> |
72 | + <widget class="ProxyLabel" id="kiwilabel3"> |
73 | + <property name="label" context="yes" translatable="yes">Bank Account:</property> |
74 | + <property name="model_attribute">kiwilabel3</property> |
75 | + <property name="visible">True</property> |
76 | + <property name="xalign">1.0</property> |
77 | + </widget> |
78 | + <packing> |
79 | + <property name="bottom_attach">3</property> |
80 | + <property name="top_attach">2</property> |
81 | + </packing> |
82 | + </child> |
83 | + <child> |
84 | + <widget class="ProxyEntry" id="bank_id"> |
85 | <property name="data_type">int</property> |
86 | <property name="is_focus">True</property> |
87 | <property name="model_attribute">bank_id</property> |
88 | <property name="visible">True</property> |
89 | <property name="width_chars">10</property> |
90 | - </widget> |
91 | - <packing> |
92 | - <property name="expand">False</property> |
93 | - <property name="position">1</property> |
94 | - </packing> |
95 | - </child> |
96 | - <child> |
97 | - <widget class="kiwi+ui+widgets+label+Label" id="kiwilabel2"> |
98 | - <property name="data_type">unicode</property> |
99 | - <property name="label" context="yes" translatable="yes">Branch Number:</property> |
100 | - <property name="visible">True</property> |
101 | - <property name="xalign">1.0</property> |
102 | - </widget> |
103 | - <packing> |
104 | - <property name="expand">False</property> |
105 | - <property name="position">2</property> |
106 | - </packing> |
107 | - </child> |
108 | - <child> |
109 | - <widget class="kiwi+ui+widgets+entry+Entry" id="branch"> |
110 | - <property name="data_type">unicode</property> |
111 | - <property name="is_focus">True</property> |
112 | - <property name="model_attribute">branch</property> |
113 | - <property name="visible">True</property> |
114 | - <property name="width_chars">10</property> |
115 | - </widget> |
116 | - <packing> |
117 | - <property name="expand">False</property> |
118 | - <property name="position">3</property> |
119 | - </packing> |
120 | - </child> |
121 | - <child> |
122 | - <widget class="GtkLabel" id="label1"> |
123 | - <property name="visible">True</property> |
124 | - </widget> |
125 | - <packing> |
126 | - <property name="expand">False</property> |
127 | - <property name="position">4</property> |
128 | + <property name="xalign">1.0</property> |
129 | + </widget> |
130 | + <packing> |
131 | + <property name="left_attach">1</property> |
132 | + <property name="right_attach">2</property> |
133 | + </packing> |
134 | + </child> |
135 | + <child> |
136 | + <widget class="ProxyEntry" id="bank_branch"> |
137 | + <property name="data_type">str</property> |
138 | + <property name="is_focus">True</property> |
139 | + <property name="model_attribute">bank_branch</property> |
140 | + <property name="visible">True</property> |
141 | + <property name="width_chars">10</property> |
142 | + <property name="xalign">1.0</property> |
143 | + </widget> |
144 | + <packing> |
145 | + <property name="bottom_attach">2</property> |
146 | + <property name="left_attach">1</property> |
147 | + <property name="right_attach">2</property> |
148 | + <property name="top_attach">1</property> |
149 | + </packing> |
150 | + </child> |
151 | + <child> |
152 | + <widget class="ProxyEntry" id="bank_account"> |
153 | + <property name="data_type">str</property> |
154 | + <property name="is_focus">True</property> |
155 | + <property name="model_attribute">bank_account</property> |
156 | + <property name="visible">True</property> |
157 | + <property name="width_chars">10</property> |
158 | + <property name="xalign">1.0</property> |
159 | + </widget> |
160 | + <packing> |
161 | + <property name="bottom_attach">3</property> |
162 | + <property name="left_attach">1</property> |
163 | + <property name="right_attach">2</property> |
164 | + <property name="top_attach">2</property> |
165 | </packing> |
166 | </child> |
167 | </widget> |
168 | <packing> |
169 | - <property name="expand">False</property> |
170 | <property name="position">1</property> |
171 | </packing> |
172 | </child> |
173 | |
174 | === added file 'data/glade/BasePaymentDataEditor.glade' |
175 | --- data/glade/BasePaymentDataEditor.glade 1970-01-01 00:00:00 +0000 |
176 | +++ data/glade/BasePaymentDataEditor.glade 2011-02-01 20:17:04 +0000 |
177 | @@ -0,0 +1,118 @@ |
178 | +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> |
179 | +<!DOCTYPE glade-interface SYSTEM "http://gazpacho.sicem.biz/gazpacho-0.1.dtd"> |
180 | +<glade-interface domain="stoqlib"> |
181 | + <widget class="GtkWindow" id="BasePaymentDataEditor"> |
182 | + <property name="border_width">5</property> |
183 | + <property name="default_height">500</property> |
184 | + <property name="default_width">500</property> |
185 | + <property name="mnemonics_visible">False</property> |
186 | + <child> |
187 | + <widget class="GtkVBox" id="vbox1"> |
188 | + <property name="border_width">5</property> |
189 | + <property name="spacing">3</property> |
190 | + <property name="visible">True</property> |
191 | + <child> |
192 | + <widget class="GtkTable" id="table1"> |
193 | + <property name="column_spacing">6</property> |
194 | + <property name="n_columns">2</property> |
195 | + <property name="n_rows">3</property> |
196 | + <property name="row_spacing">6</property> |
197 | + <property name="visible">True</property> |
198 | + <child> |
199 | + <widget class="ProxyLabel" id="kiwilabel1"> |
200 | + <property name="data_type">unicode</property> |
201 | + <property name="label" context="yes" translatable="yes">Due date:</property> |
202 | + <property name="model_attribute">kiwilabel1</property> |
203 | + <property name="visible">True</property> |
204 | + <property name="xalign">1.0</property> |
205 | + </widget> |
206 | + </child> |
207 | + <child> |
208 | + <widget class="ProxyLabel" id="kiwilabel2"> |
209 | + <property name="data_type">unicode</property> |
210 | + <property name="label" context="yes" translatable="yes">Value ($CURRENCY):</property> |
211 | + <property name="model_attribute">kiwilabel2</property> |
212 | + <property name="visible">True</property> |
213 | + <property name="xalign">1.0</property> |
214 | + </widget> |
215 | + <packing> |
216 | + <property name="bottom_attach">2</property> |
217 | + <property name="top_attach">1</property> |
218 | + </packing> |
219 | + </child> |
220 | + <child> |
221 | + <widget class="ProxyLabel" id="kiwilabel3"> |
222 | + <property name="data_type">unicode</property> |
223 | + <property name="label" context="yes" translatable="yes">Number:</property> |
224 | + <property name="model_attribute">kiwilabel3</property> |
225 | + <property name="visible">True</property> |
226 | + <property name="xalign">1.0</property> |
227 | + </widget> |
228 | + <packing> |
229 | + <property name="bottom_attach">3</property> |
230 | + <property name="top_attach">2</property> |
231 | + </packing> |
232 | + </child> |
233 | + <child> |
234 | + <widget class="ProxyDateEntry" id="due_date"> |
235 | + <property name="data_type">date</property> |
236 | + <property name="model_attribute">due_date</property> |
237 | + <property name="visible">True</property> |
238 | + </widget> |
239 | + <packing> |
240 | + <property name="left_attach">1</property> |
241 | + <property name="right_attach">2</property> |
242 | + </packing> |
243 | + </child> |
244 | + <child> |
245 | + <widget class="ProxyEntry" id="value"> |
246 | + <property name="data_type">Decimal</property> |
247 | + <property name="is_focus">True</property> |
248 | + <property name="mandatory">True</property> |
249 | + <property name="model_attribute">value</property> |
250 | + <property name="visible">True</property> |
251 | + <property name="width_chars">10</property> |
252 | + <property name="width_request">90</property> |
253 | + <property name="xalign">1.0</property> |
254 | + </widget> |
255 | + <packing> |
256 | + <property name="bottom_attach">2</property> |
257 | + <property name="left_attach">1</property> |
258 | + <property name="right_attach">2</property> |
259 | + <property name="top_attach">1</property> |
260 | + </packing> |
261 | + </child> |
262 | + <child> |
263 | + <widget class="ProxyEntry" id="payment_number"> |
264 | + <property name="data_type">str</property> |
265 | + <property name="is_focus">True</property> |
266 | + <property name="model_attribute">payment_number</property> |
267 | + <property name="visible">True</property> |
268 | + <property name="width_chars">10</property> |
269 | + <property name="width_request">90</property> |
270 | + <property name="xalign">1.0</property> |
271 | + </widget> |
272 | + <packing> |
273 | + <property name="bottom_attach">3</property> |
274 | + <property name="left_attach">1</property> |
275 | + <property name="right_attach">2</property> |
276 | + <property name="top_attach">2</property> |
277 | + </packing> |
278 | + </child> |
279 | + </widget> |
280 | + </child> |
281 | + <child> |
282 | + <widget class="GtkEventBox" id="bank_data_slave"> |
283 | + <property name="visible">True</property> |
284 | + <child> |
285 | + <placeholder/> |
286 | + </child> |
287 | + </widget> |
288 | + <packing> |
289 | + <property name="position">1</property> |
290 | + </packing> |
291 | + </child> |
292 | + </widget> |
293 | + </child> |
294 | + </widget> |
295 | +</glade-interface> |
296 | |
297 | === renamed file 'data/glade/BillCheckMethodSlave.glade' => 'data/glade/BasePaymentMethodSlave.glade' |
298 | --- data/glade/BillCheckMethodSlave.glade 2007-11-01 14:23:26 +0000 |
299 | +++ data/glade/BasePaymentMethodSlave.glade 2011-02-01 20:17:04 +0000 |
300 | @@ -1,9 +1,10 @@ |
301 | <?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> |
302 | <!DOCTYPE glade-interface SYSTEM "http://gazpacho.sicem.biz/gazpacho-0.1.dtd"> |
303 | <glade-interface domain="stoqlib"> |
304 | - <widget class="GtkWindow" id="BillCheckMethodSlave"> |
305 | - <property name="default_height">250</property> |
306 | - <property name="default_width">440</property> |
307 | + <widget class="GtkWindow" id="BasePaymentMethodSlave"> |
308 | + <property name="default_height">450</property> |
309 | + <property name="default_width">250</property> |
310 | + <property name="mnemonics_visible">False</property> |
311 | <child> |
312 | <widget class="GtkFrame" id="frame1"> |
313 | <property name="visible">True</property> |
314 | @@ -12,64 +13,26 @@ |
315 | <property name="visible">True</property> |
316 | <child> |
317 | <widget class="GtkTable" id="table1"> |
318 | - <property name="border_width">5</property> |
319 | - <property name="column_spacing">5</property> |
320 | - <property name="n_columns">5</property> |
321 | - <property name="n_rows">4</property> |
322 | - <property name="row_spacing">5</property> |
323 | + <property name="border_width">3</property> |
324 | + <property name="column_spacing">6</property> |
325 | + <property name="n_columns">3</property> |
326 | + <property name="n_rows">2</property> |
327 | + <property name="row_spacing">6</property> |
328 | <property name="visible">True</property> |
329 | <child> |
330 | - <widget class="ProxyLabel" id="kiwilabel1"> |
331 | - <property name="data_type">unicode</property> |
332 | - <property name="label" context="yes" translatable="yes">Number of installments:</property> |
333 | - <property name="model_attribute">kiwilabel1</property> |
334 | - <property name="visible">True</property> |
335 | - <property name="xalign">1.0</property> |
336 | - </widget> |
337 | - <packing> |
338 | - <property name="y_options">fill</property> |
339 | - </packing> |
340 | - </child> |
341 | - <child> |
342 | - <widget class="ProxyLabel" id="first_duedate_lbl"> |
343 | - <property name="data_type">unicode</property> |
344 | - <property name="label" context="yes" translatable="yes">First installment due:</property> |
345 | - <property name="model_attribute">first_duedate_lbl</property> |
346 | - <property name="visible">True</property> |
347 | - <property name="xalign">1.0</property> |
348 | - </widget> |
349 | - <packing> |
350 | - <property name="bottom_attach">2</property> |
351 | - <property name="top_attach">1</property> |
352 | - </packing> |
353 | - </child> |
354 | - <child> |
355 | - <widget class="ProxyLabel" id="kiwilabel5"> |
356 | - <property name="data_type">unicode</property> |
357 | - <property name="label" context="yes" translatable="yes">Based on intervals of:</property> |
358 | - <property name="model_attribute">kiwilabel5</property> |
359 | - <property name="visible">True</property> |
360 | - <property name="xalign">1.0</property> |
361 | - </widget> |
362 | - <packing> |
363 | - <property name="bottom_attach">3</property> |
364 | - <property name="top_attach">2</property> |
365 | - </packing> |
366 | - </child> |
367 | - <child> |
368 | - <widget class="GtkLabel" id="bank_label"> |
369 | - <property name="label" context="yes" translatable="yes">Default Bank:</property> |
370 | - <property name="visible">True</property> |
371 | - <property name="xalign">1.0</property> |
372 | - </widget> |
373 | - <packing> |
374 | - <property name="bottom_attach">4</property> |
375 | - <property name="top_attach">3</property> |
376 | - </packing> |
377 | - </child> |
378 | - <child> |
379 | - <widget class="GtkHBox" id="hbox2"> |
380 | - <property name="visible">True</property> |
381 | + <widget class="GtkHBox" id="hbox1"> |
382 | + <property name="spacing">6</property> |
383 | + <property name="visible">True</property> |
384 | + <child> |
385 | + <widget class="ProxyLabel" id="installments_number_lbl"> |
386 | + <property name="data_type">unicode</property> |
387 | + <property name="justify">right</property> |
388 | + <property name="label" context="yes" translatable="yes">Installments:</property> |
389 | + <property name="model_attribute">installments_number_lbl</property> |
390 | + <property name="visible">True</property> |
391 | + <property name="xalign">1.0</property> |
392 | + </widget> |
393 | + </child> |
394 | <child> |
395 | <widget class="ProxySpinButton" id="installments_number"> |
396 | <property name="adjustment">0 0 100 1 10 0</property> |
397 | @@ -78,199 +41,145 @@ |
398 | <property name="model_attribute">installments_number</property> |
399 | <property name="text" context="yes" translatable="yes">0</property> |
400 | <property name="visible">True</property> |
401 | - <property name="width_chars">6</property> |
402 | - <property name="width_request">90</property> |
403 | - </widget> |
404 | - <packing> |
405 | - <property name="expand">False</property> |
406 | - </packing> |
407 | - </child> |
408 | - <child> |
409 | - <placeholder/> |
410 | - <packing> |
411 | - <property name="position">1</property> |
412 | - </packing> |
413 | - </child> |
414 | - </widget> |
415 | - <packing> |
416 | - <property name="left_attach">1</property> |
417 | - <property name="right_attach">2</property> |
418 | - <property name="x_options">fill</property> |
419 | - <property name="y_options">fill</property> |
420 | - </packing> |
421 | - </child> |
422 | - <child> |
423 | - <widget class="ProxyDateEntry" id="first_duedate"> |
424 | - <property name="data_type">date</property> |
425 | - <property name="model_attribute">first_duedate</property> |
426 | - <property name="visible">True</property> |
427 | - </widget> |
428 | - <packing> |
429 | - <property name="bottom_attach">2</property> |
430 | - <property name="left_attach">1</property> |
431 | - <property name="right_attach">2</property> |
432 | - <property name="top_attach">1</property> |
433 | - <property name="x_options">fill</property> |
434 | - </packing> |
435 | - </child> |
436 | - <child> |
437 | - <widget class="GtkHBox" id="hbox3"> |
438 | - <property name="visible">True</property> |
439 | - <child> |
440 | - <widget class="ProxySpinButton" id="intervals"> |
441 | - <property name="adjustment">0 0 100 1 10 0</property> |
442 | - <property name="data_type">int</property> |
443 | - <property name="is_focus">True</property> |
444 | - <property name="model_attribute">intervals</property> |
445 | - <property name="text" context="yes" translatable="yes">0</property> |
446 | - <property name="visible">True</property> |
447 | - <property name="width_chars">6</property> |
448 | - <property name="width_request">90</property> |
449 | - </widget> |
450 | - <packing> |
451 | - <property name="expand">False</property> |
452 | - </packing> |
453 | - </child> |
454 | - <child> |
455 | - <placeholder/> |
456 | - <packing> |
457 | - <property name="position">1</property> |
458 | - </packing> |
459 | - </child> |
460 | - <child> |
461 | - <placeholder/> |
462 | - <packing> |
463 | - <property name="position">2</property> |
464 | - </packing> |
465 | - </child> |
466 | - </widget> |
467 | - <packing> |
468 | - <property name="bottom_attach">3</property> |
469 | - <property name="left_attach">1</property> |
470 | - <property name="right_attach">2</property> |
471 | - <property name="top_attach">2</property> |
472 | - <property name="x_options">fill</property> |
473 | - </packing> |
474 | - </child> |
475 | - <child> |
476 | - <widget class="ProxyComboEntry" id="bank_combo"> |
477 | - <property name="data_type">str</property> |
478 | - <property name="model_attribute"></property> |
479 | - <property name="visible">True</property> |
480 | - </widget> |
481 | - <packing> |
482 | - <property name="bottom_attach">4</property> |
483 | - <property name="left_attach">1</property> |
484 | - <property name="right_attach">4</property> |
485 | - <property name="top_attach">3</property> |
486 | - </packing> |
487 | - </child> |
488 | - <child> |
489 | - <placeholder/> |
490 | - <packing> |
491 | - <property name="left_attach">2</property> |
492 | - <property name="right_attach">3</property> |
493 | - <property name="x_options">fill</property> |
494 | - <property name="y_options">fill</property> |
495 | - </packing> |
496 | - </child> |
497 | - <child> |
498 | - <placeholder/> |
499 | - <packing> |
500 | - <property name="left_attach">2</property> |
501 | - <property name="right_attach">3</property> |
502 | - <property name="top_attach">1</property> |
503 | - <property name="bottom_attach">2</property> |
504 | - </packing> |
505 | - </child> |
506 | - <child> |
507 | - <widget class="GtkHBox" id="hbox1"> |
508 | - <property name="visible">True</property> |
509 | - <property name="width_request">90</property> |
510 | - <child> |
511 | - <widget class="ProxyComboBox" id="interval_type_combo"> |
512 | - <property name="data_type">int</property> |
513 | - <property name="model_attribute">interval_type</property> |
514 | - <property name="visible">True</property> |
515 | - </widget> |
516 | - </child> |
517 | - </widget> |
518 | - <packing> |
519 | - <property name="bottom_attach">3</property> |
520 | - <property name="left_attach">2</property> |
521 | - <property name="right_attach">3</property> |
522 | - <property name="top_attach">2</property> |
523 | - <property name="x_options">fill</property> |
524 | - <property name="y_options">expand | shrink</property> |
525 | - </packing> |
526 | - </child> |
527 | - <child> |
528 | - <placeholder/> |
529 | - <packing> |
530 | - <property name="left_attach">3</property> |
531 | - <property name="right_attach">4</property> |
532 | - <property name="x_options">fill</property> |
533 | - </packing> |
534 | - </child> |
535 | - <child> |
536 | - <placeholder/> |
537 | - <packing> |
538 | - <property name="left_attach">3</property> |
539 | - <property name="right_attach">4</property> |
540 | - <property name="top_attach">1</property> |
541 | - <property name="bottom_attach">2</property> |
542 | - </packing> |
543 | - </child> |
544 | - <child> |
545 | - <widget class="GtkButton" id="reset_button"> |
546 | - <property name="is_focus">True</property> |
547 | - <property name="label" context="yes" translatable="yes">_Reset List</property> |
548 | - <property name="use_underline">True</property> |
549 | - <property name="visible">True</property> |
550 | - </widget> |
551 | - <packing> |
552 | - <property name="bottom_attach">3</property> |
553 | - <property name="left_attach">3</property> |
554 | - <property name="right_attach">4</property> |
555 | - <property name="top_attach">2</property> |
556 | - <property name="x_options">fill</property> |
557 | - </packing> |
558 | - </child> |
559 | - <child> |
560 | - <placeholder/> |
561 | - <packing> |
562 | - <property name="left_attach">4</property> |
563 | - <property name="right_attach">5</property> |
564 | - </packing> |
565 | - </child> |
566 | - <child> |
567 | - <placeholder/> |
568 | - <packing> |
569 | - <property name="left_attach">4</property> |
570 | - <property name="right_attach">5</property> |
571 | - <property name="top_attach">1</property> |
572 | - <property name="bottom_attach">2</property> |
573 | - </packing> |
574 | - </child> |
575 | - <child> |
576 | - <widget class="GtkLabel" id="label1"> |
577 | - <property name="visible">True</property> |
578 | - </widget> |
579 | - <packing> |
580 | - <property name="bottom_attach">3</property> |
581 | - <property name="left_attach">4</property> |
582 | - <property name="right_attach">5</property> |
583 | - <property name="top_attach">2</property> |
584 | - <property name="y_options">fill</property> |
585 | - </packing> |
586 | - </child> |
587 | - <child> |
588 | - <placeholder/> |
589 | - <packing> |
590 | - <property name="left_attach">4</property> |
591 | - <property name="right_attach">5</property> |
592 | - <property name="top_attach">3</property> |
593 | - <property name="bottom_attach">4</property> |
594 | + <property name="width_chars">3</property> |
595 | + <property name="width_request">90</property> |
596 | + </widget> |
597 | + <packing> |
598 | + <property name="position">1</property> |
599 | + </packing> |
600 | + </child> |
601 | + </widget> |
602 | + </child> |
603 | + <child> |
604 | + <widget class="GtkHBox" id="hbox4"> |
605 | + <property name="spacing">6</property> |
606 | + <property name="visible">True</property> |
607 | + <child> |
608 | + <widget class="GtkLabel" id="bank_label"> |
609 | + <property name="justify">right</property> |
610 | + <property name="label" context="yes" translatable="yes">Default Bank:</property> |
611 | + <property name="visible">True</property> |
612 | + <property name="xalign">1.0</property> |
613 | + </widget> |
614 | + </child> |
615 | + <child> |
616 | + <widget class="ProxyComboEntry" id="bank_combo"> |
617 | + <property name="data_type">str</property> |
618 | + <property name="model_attribute">bank_combo</property> |
619 | + <property name="visible">True</property> |
620 | + </widget> |
621 | + <packing> |
622 | + <property name="position">1</property> |
623 | + </packing> |
624 | + </child> |
625 | + </widget> |
626 | + <packing> |
627 | + <property name="bottom_attach">2</property> |
628 | + <property name="right_attach">2</property> |
629 | + <property name="top_attach">1</property> |
630 | + <property name="x_padding">4</property> |
631 | + </packing> |
632 | + </child> |
633 | + <child> |
634 | + <widget class="ProxyLabel" id="kiwilabel2"> |
635 | + <property name="model_attribute">kiwilabel2</property> |
636 | + <property name="visible">True</property> |
637 | + <property name="width_chars">10</property> |
638 | + <property name="xalign">0.0</property> |
639 | + </widget> |
640 | + <packing> |
641 | + <property name="left_attach">1</property> |
642 | + <property name="right_attach">2</property> |
643 | + </packing> |
644 | + </child> |
645 | + <child> |
646 | + <widget class="GtkHBox" id="hbox5"> |
647 | + <property name="spacing">6</property> |
648 | + <property name="visible">True</property> |
649 | + <child> |
650 | + <widget class="GtkHBox" id="hbox2"> |
651 | + <property name="spacing">6</property> |
652 | + <property name="visible">True</property> |
653 | + <child> |
654 | + <widget class="ProxyLabel" id="first_duedate_lbl"> |
655 | + <property name="data_type">unicode</property> |
656 | + <property name="justify">right</property> |
657 | + <property name="label" context="yes" translatable="yes">Start at:</property> |
658 | + <property name="model_attribute">first_duedate_lbl</property> |
659 | + <property name="visible">True</property> |
660 | + <property name="xalign">1.0</property> |
661 | + </widget> |
662 | + </child> |
663 | + <child> |
664 | + <widget class="ProxyDateEntry" id="first_duedate"> |
665 | + <property name="data_type">date</property> |
666 | + <property name="model_attribute">first_duedate</property> |
667 | + <property name="visible">True</property> |
668 | + </widget> |
669 | + <packing> |
670 | + <property name="position">1</property> |
671 | + </packing> |
672 | + </child> |
673 | + </widget> |
674 | + </child> |
675 | + <child> |
676 | + <widget class="GtkHBox" id="hbox3"> |
677 | + <property name="spacing">6</property> |
678 | + <property name="visible">True</property> |
679 | + <child> |
680 | + <widget class="ProxyLabel" id="intervals_lbl"> |
681 | + <property name="data_type">unicode</property> |
682 | + <property name="justify">right</property> |
683 | + <property name="label" context="yes" translatable="yes">With intervals of:</property> |
684 | + <property name="model_attribute">intervals_lbl</property> |
685 | + <property name="visible">True</property> |
686 | + <property name="xalign">1.0</property> |
687 | + </widget> |
688 | + </child> |
689 | + <child> |
690 | + <widget class="ProxySpinButton" id="intervals"> |
691 | + <property name="adjustment">0 0 100 1 10 0</property> |
692 | + <property name="data_type">int</property> |
693 | + <property name="is_focus">True</property> |
694 | + <property name="model_attribute">intervals</property> |
695 | + <property name="text" context="yes" translatable="yes">0</property> |
696 | + <property name="visible">True</property> |
697 | + <property name="width_chars">3</property> |
698 | + <property name="width_request">90</property> |
699 | + </widget> |
700 | + <packing> |
701 | + <property name="position">1</property> |
702 | + </packing> |
703 | + </child> |
704 | + <child> |
705 | + <widget class="ProxyComboBox" id="interval_type_combo"> |
706 | + <property name="data_type">int</property> |
707 | + <property name="model_attribute">interval_type</property> |
708 | + <property name="visible">True</property> |
709 | + </widget> |
710 | + <packing> |
711 | + <property name="padding">2</property> |
712 | + <property name="position">2</property> |
713 | + </packing> |
714 | + </child> |
715 | + </widget> |
716 | + <packing> |
717 | + <property name="position">1</property> |
718 | + </packing> |
719 | + </child> |
720 | + </widget> |
721 | + <packing> |
722 | + <property name="left_attach">2</property> |
723 | + <property name="right_attach">3</property> |
724 | + </packing> |
725 | + </child> |
726 | + <child> |
727 | + <placeholder/> |
728 | + <packing> |
729 | + <property name="left_attach">2</property> |
730 | + <property name="right_attach">3</property> |
731 | + <property name="top_attach">1</property> |
732 | + <property name="bottom_attach">2</property> |
733 | </packing> |
734 | </child> |
735 | </widget> |
736 | @@ -279,7 +188,7 @@ |
737 | </packing> |
738 | </child> |
739 | <child> |
740 | - <widget class="GtkEventBox" id="bill_check_data_list"> |
741 | + <widget class="GtkEventBox" id="slave_holder"> |
742 | <property name="visible">True</property> |
743 | <child> |
744 | <placeholder/> |
745 | |
746 | === removed file 'data/glade/BillDataSlave.glade' |
747 | --- data/glade/BillDataSlave.glade 2011-01-17 13:41:17 +0000 |
748 | +++ data/glade/BillDataSlave.glade 1970-01-01 00:00:00 +0000 |
749 | @@ -1,124 +0,0 @@ |
750 | -<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> |
751 | -<!DOCTYPE glade-interface SYSTEM "http://gazpacho.sicem.biz/gazpacho-0.1.dtd"> |
752 | -<glade-interface domain="stoqlib"> |
753 | - <widget class="GtkWindow" id="BillDataSlave"> |
754 | - <property name="default_height">250</property> |
755 | - <property name="default_width">440</property> |
756 | - <child> |
757 | - <widget class="GtkVBox" id="vbox1"> |
758 | - <property name="border_width">5</property> |
759 | - <property name="visible">True</property> |
760 | - <child> |
761 | - <widget class="kiwi+ui+widgets+label+Label" id="payment_number_label"> |
762 | - <property name="data_type">unicode</property> |
763 | - <property name="visible">True</property> |
764 | - <property name="xalign">0.0</property> |
765 | - </widget> |
766 | - <packing> |
767 | - <property name="expand">False</property> |
768 | - </packing> |
769 | - </child> |
770 | - <child> |
771 | - <widget class="GtkVBox" id="vbox2"> |
772 | - <property name="visible">True</property> |
773 | - <child> |
774 | - <widget class="GtkHBox" id="hbox1"> |
775 | - <property name="border_width">3</property> |
776 | - <property name="spacing">5</property> |
777 | - <property name="visible">True</property> |
778 | - <child> |
779 | - <widget class="kiwi+ui+widgets+label+Label" id="kiwilabel1"> |
780 | - <property name="data_type">unicode</property> |
781 | - <property name="label" context="yes" translatable="yes">Duedate:</property> |
782 | - <property name="visible">True</property> |
783 | - <property name="xalign">1.0</property> |
784 | - </widget> |
785 | - <packing> |
786 | - <property name="expand">False</property> |
787 | - </packing> |
788 | - </child> |
789 | - <child> |
790 | - <widget class="ProxyDateEntry" id="due_date"> |
791 | - <property name="data_type">date</property> |
792 | - <property name="model_attribute">due_date</property> |
793 | - <property name="visible">True</property> |
794 | - </widget> |
795 | - <packing> |
796 | - <property name="position">1</property> |
797 | - </packing> |
798 | - </child> |
799 | - <child> |
800 | - <widget class="ProxyLabel" id="kiwilabel2"> |
801 | - <property name="data_type">unicode</property> |
802 | - <property name="label" context="yes" translatable="yes">Value ($CURRENCY):</property> |
803 | - <property name="visible">True</property> |
804 | - <property name="xalign">1.0</property> |
805 | - </widget> |
806 | - <packing> |
807 | - <property name="expand">False</property> |
808 | - <property name="position">2</property> |
809 | - </packing> |
810 | - </child> |
811 | - <child> |
812 | - <widget class="kiwi+ui+widgets+entry+Entry" id="value"> |
813 | - <property name="data_type">currency</property> |
814 | - <property name="is_focus">True</property> |
815 | - <property name="mandatory">True</property> |
816 | - <property name="model_attribute">value</property> |
817 | - <property name="visible">True</property> |
818 | - <property name="width_request">90</property> |
819 | - <property name="xalign">1.0</property> |
820 | - </widget> |
821 | - <packing> |
822 | - <property name="position">3</property> |
823 | - </packing> |
824 | - </child> |
825 | - <child> |
826 | - <widget class="kiwi+ui+widgets+label+Label" id="kiwilabel3"> |
827 | - <property name="data_type">unicode</property> |
828 | - <property name="label" context="yes" translatable="yes">Number:</property> |
829 | - <property name="visible">True</property> |
830 | - <property name="xalign">1.0</property> |
831 | - </widget> |
832 | - <packing> |
833 | - <property name="expand">False</property> |
834 | - <property name="position">4</property> |
835 | - </packing> |
836 | - </child> |
837 | - <child> |
838 | - <widget class="kiwi+ui+widgets+entry+Entry" id="payment_number"> |
839 | - <property name="data_type">unicode</property> |
840 | - <property name="is_focus">True</property> |
841 | - <property name="model_attribute">payment_number</property> |
842 | - <property name="visible">True</property> |
843 | - <property name="width_request">90</property> |
844 | - </widget> |
845 | - <packing> |
846 | - <property name="position">5</property> |
847 | - </packing> |
848 | - </child> |
849 | - </widget> |
850 | - <packing> |
851 | - <property name="expand">False</property> |
852 | - </packing> |
853 | - </child> |
854 | - <child> |
855 | - <widget class="GtkEventBox" id="bank_data_slave"> |
856 | - <property name="visible">True</property> |
857 | - <child> |
858 | - <placeholder/> |
859 | - </child> |
860 | - </widget> |
861 | - <packing> |
862 | - <property name="position">1</property> |
863 | - </packing> |
864 | - </child> |
865 | - </widget> |
866 | - <packing> |
867 | - <property name="position">1</property> |
868 | - </packing> |
869 | - </child> |
870 | - </widget> |
871 | - </child> |
872 | - </widget> |
873 | -</glade-interface> |
874 | |
875 | === modified file 'data/glade/PaymentListSlave.glade' |
876 | --- data/glade/PaymentListSlave.glade 2006-06-08 19:02:06 +0000 |
877 | +++ data/glade/PaymentListSlave.glade 2011-02-01 20:17:04 +0000 |
878 | @@ -4,28 +4,17 @@ |
879 | <widget class="GtkWindow" id="PaymentListSlave"> |
880 | <property name="default_height">250</property> |
881 | <property name="default_width">440</property> |
882 | + <property name="mnemonics_visible">False</property> |
883 | <child> |
884 | <widget class="GtkVBox" id="vbox1"> |
885 | <property name="border_width">5</property> |
886 | <property name="spacing">5</property> |
887 | <property name="visible">True</property> |
888 | <child> |
889 | - <widget class="GtkScrolledWindow" id="scrolled_window"> |
890 | - <property name="hscrollbar_policy">never</property> |
891 | + <widget class="ObjectList" id="payment_list"> |
892 | + <property name="border_width">5</property> |
893 | + <property name="selection_mode">single</property> |
894 | <property name="visible">True</property> |
895 | - <child> |
896 | - <widget class="GtkViewport" id="viewport4"> |
897 | - <property name="visible">True</property> |
898 | - <child> |
899 | - <widget class="GtkVBox" id="list_vbox"> |
900 | - <property name="visible">True</property> |
901 | - <child> |
902 | - <placeholder/> |
903 | - </child> |
904 | - </widget> |
905 | - </child> |
906 | - </widget> |
907 | - </child> |
908 | </widget> |
909 | </child> |
910 | <child> |
911 | @@ -34,64 +23,67 @@ |
912 | <property name="spacing">5</property> |
913 | <property name="visible">True</property> |
914 | <child> |
915 | - <widget class="GtkButton" id="add_button"> |
916 | - <property name="is_focus">True</property> |
917 | - <property name="visible">True</property> |
918 | - <child> |
919 | - <widget class="GtkImage" id="image1"> |
920 | - <property name="stock">gtk-add</property> |
921 | - <property name="visible">True</property> |
922 | - </widget> |
923 | - </child> |
924 | - </widget> |
925 | - <packing> |
926 | - <property name="expand">False</property> |
927 | - </packing> |
928 | - </child> |
929 | - <child> |
930 | - <widget class="GtkButton" id="remove_button"> |
931 | - <property name="is_focus">True</property> |
932 | - <property name="visible">True</property> |
933 | - <child> |
934 | - <widget class="GtkImage" id="image2"> |
935 | - <property name="stock">gtk-remove</property> |
936 | - <property name="visible">True</property> |
937 | - </widget> |
938 | - </child> |
939 | - </widget> |
940 | - <packing> |
941 | - <property name="expand">False</property> |
942 | - <property name="position">1</property> |
943 | - </packing> |
944 | - </child> |
945 | - <child> |
946 | - <widget class="kiwi+ui+widgets+label+Label" id="status_label"> |
947 | - <property name="data_type">unicode</property> |
948 | + <widget class="ProxyLabel" id="difference_status_label"> |
949 | + <property name="data_type">str</property> |
950 | <property name="label" context="yes" translatable="yes">Outstanding:</property> |
951 | + <property name="model_attribute">difference_status_label</property> |
952 | + <property name="visible">True</property> |
953 | <property name="xalign">1.0</property> |
954 | - <property name="visible">True</property> |
955 | </widget> |
956 | - <packing> |
957 | - <property name="position">2</property> |
958 | - </packing> |
959 | </child> |
960 | <child> |
961 | - <widget class="kiwi+ui+widgets+label+Label" id="total_label"> |
962 | - <property name="data_type">unicode</property> |
963 | - <property name="label" context="yes" translatable="yes">$20.40</property> |
964 | + <widget class="ProxyLabel" id="difference_label"> |
965 | + <property name="data_type">currency</property> |
966 | + <property name="label" context="yes" translatable="yes">$0.00</property> |
967 | + <property name="model_attribute">difference_label</property> |
968 | <property name="visible">True</property> |
969 | + <property name="xalign">1.0</property> |
970 | </widget> |
971 | <packing> |
972 | <property name="expand">False</property> |
973 | - <property name="position">3</property> |
974 | + <property name="position">1</property> |
975 | </packing> |
976 | </child> |
977 | </widget> |
978 | <packing> |
979 | <property name="expand">False</property> |
980 | + <property name="fill">False</property> |
981 | <property name="position">1</property> |
982 | </packing> |
983 | </child> |
984 | + <child> |
985 | + <widget class="GtkHBox" id="hbox2"> |
986 | + <property name="border_width">5</property> |
987 | + <property name="spacing">5</property> |
988 | + <property name="visible">True</property> |
989 | + <child> |
990 | + <widget class="ProxyLabel" id="total_status_label"> |
991 | + <property name="label" context="yes" translatable="yes">Total:</property> |
992 | + <property name="model_attribute">total_status_label</property> |
993 | + <property name="visible">True</property> |
994 | + <property name="xalign">1.0</property> |
995 | + </widget> |
996 | + </child> |
997 | + <child> |
998 | + <widget class="ProxyLabel" id="total_label"> |
999 | + <property name="data_type">currency</property> |
1000 | + <property name="label" context="yes" translatable="yes">$0.00</property> |
1001 | + <property name="model_attribute">total_label</property> |
1002 | + <property name="visible">True</property> |
1003 | + <property name="xalign">1.0</property> |
1004 | + </widget> |
1005 | + <packing> |
1006 | + <property name="expand">False</property> |
1007 | + <property name="position">1</property> |
1008 | + </packing> |
1009 | + </child> |
1010 | + </widget> |
1011 | + <packing> |
1012 | + <property name="expand">False</property> |
1013 | + <property name="fill">False</property> |
1014 | + <property name="position">2</property> |
1015 | + </packing> |
1016 | + </child> |
1017 | </widget> |
1018 | </child> |
1019 | </widget> |
1020 | |
1021 | === modified file 'data/glade/PurchasePaymentStep.glade' |
1022 | --- data/glade/PurchasePaymentStep.glade 2008-10-22 19:59:27 +0000 |
1023 | +++ data/glade/PurchasePaymentStep.glade 2011-02-01 20:17:04 +0000 |
1024 | @@ -5,6 +5,7 @@ |
1025 | <property name="border_width">5</property> |
1026 | <property name="default_height">250</property> |
1027 | <property name="default_width">440</property> |
1028 | + <property name="mnemonics_visible">False</property> |
1029 | <child> |
1030 | <widget class="GtkVBox" id="main_box"> |
1031 | <property name="border_width">5</property> |
1032 | @@ -61,72 +62,6 @@ |
1033 | <property name="position">1</property> |
1034 | </packing> |
1035 | </child> |
1036 | - <child> |
1037 | - <widget class="GtkHBox" id="hbox1"> |
1038 | - <property name="border_width">5</property> |
1039 | - <property name="spacing">5</property> |
1040 | - <property name="visible">True</property> |
1041 | - <child> |
1042 | - <widget class="ProxyLabel" id="kiwilabel3"> |
1043 | - <property name="data_type">unicode</property> |
1044 | - <property name="label" context="yes" translatable="yes">Subtotal:</property> |
1045 | - <property name="model_attribute">kiwilabel3</property> |
1046 | - <property name="visible">True</property> |
1047 | - <property name="xalign">1.0</property> |
1048 | - </widget> |
1049 | - </child> |
1050 | - <child> |
1051 | - <widget class="ProxyLabel" id="subtotal_lbl"> |
1052 | - <property name="data_type">currency</property> |
1053 | - <property name="label" context="yes" translatable="yes">0.00</property> |
1054 | - <property name="model_attribute">purchase_subtotal</property> |
1055 | - <property name="visible">True</property> |
1056 | - <property name="xalign">1.0</property> |
1057 | - </widget> |
1058 | - <packing> |
1059 | - <property name="expand">False</property> |
1060 | - <property name="position">1</property> |
1061 | - </packing> |
1062 | - </child> |
1063 | - </widget> |
1064 | - <packing> |
1065 | - <property name="expand">False</property> |
1066 | - <property name="position">2</property> |
1067 | - </packing> |
1068 | - </child> |
1069 | - <child> |
1070 | - <widget class="GtkHBox" id="hbox7"> |
1071 | - <property name="border_width">5</property> |
1072 | - <property name="spacing">5</property> |
1073 | - <property name="visible">True</property> |
1074 | - <child> |
1075 | - <widget class="ProxyLabel" id="kiwilabel5"> |
1076 | - <property name="data_type">unicode</property> |
1077 | - <property name="label" context="yes" translatable="yes">Total:</property> |
1078 | - <property name="model_attribute">kiwilabel5</property> |
1079 | - <property name="visible">True</property> |
1080 | - <property name="xalign">1.0</property> |
1081 | - </widget> |
1082 | - </child> |
1083 | - <child> |
1084 | - <widget class="ProxyLabel" id="total_lbl"> |
1085 | - <property name="data_type">currency</property> |
1086 | - <property name="label" context="yes" translatable="yes">0.00</property> |
1087 | - <property name="model_attribute">purchase_total</property> |
1088 | - <property name="visible">True</property> |
1089 | - <property name="xalign">1.0</property> |
1090 | - </widget> |
1091 | - <packing> |
1092 | - <property name="expand">False</property> |
1093 | - <property name="position">1</property> |
1094 | - </packing> |
1095 | - </child> |
1096 | - </widget> |
1097 | - <packing> |
1098 | - <property name="expand">False</property> |
1099 | - <property name="position">3</property> |
1100 | - </packing> |
1101 | - </child> |
1102 | </widget> |
1103 | </child> |
1104 | </widget> |
1105 | |
1106 | === modified file 'stoqlib/database/admin.py' |
1107 | --- stoqlib/database/admin.py 2008-12-16 19:04:09 +0000 |
1108 | +++ stoqlib/database/admin.py 2011-02-01 20:17:04 +0000 |
1109 | @@ -59,7 +59,7 @@ |
1110 | from stoqlib.importers.invoiceimporter import InvoiceImporter |
1111 | from stoqlib.lib.interfaces import IPaymentOperationManager |
1112 | from stoqlib.lib.message import error |
1113 | -from stoqlib.lib.paymentoperation import PaymentOperationManager |
1114 | +from stoqlib.lib.payment import PaymentOperationManager |
1115 | from stoqlib.lib.parameters import sysparam, ensure_system_parameters |
1116 | from stoqlib.lib.translation import stoqlib_gettext |
1117 | |
1118 | |
1119 | === modified file 'stoqlib/database/testsuite.py' |
1120 | --- stoqlib/database/testsuite.py 2009-09-25 20:13:37 +0000 |
1121 | +++ stoqlib/database/testsuite.py 2011-02-01 20:17:04 +0000 |
1122 | @@ -45,7 +45,7 @@ |
1123 | ISystemNotifier) |
1124 | from stoqlib.lib.message import DefaultSystemNotifier |
1125 | from stoqlib.lib.parameters import sysparam |
1126 | -from stoqlib.lib.paymentoperation import PaymentOperationManager |
1127 | +from stoqlib.lib.payment import PaymentOperationManager |
1128 | |
1129 | log = Logger('stoqlib.database.testsuite') |
1130 | |
1131 | |
1132 | === modified file 'stoqlib/domain/payment/method.py' |
1133 | --- stoqlib/domain/payment/method.py 2010-11-22 14:16:09 +0000 |
1134 | +++ stoqlib/domain/payment/method.py 2011-02-01 20:17:04 +0000 |
1135 | @@ -219,9 +219,10 @@ |
1136 | # They should either go into the group or to a separate payment |
1137 | # factory singleton. |
1138 | @argcheck(object, PaymentGroup, Decimal, datetime.datetime, |
1139 | - basestring, basestring, Till) |
1140 | + basestring, basestring, Till, basestring) |
1141 | def create_payment(self, iface, payment_group, value, due_date=None, |
1142 | - description=None, base_value=None, till=None): |
1143 | + description=None, base_value=None, till=None, |
1144 | + payment_number=None): |
1145 | """Creates a new payment according to a payment method interface |
1146 | @param iface: a payment method interface eg L{IOutPayment} or |
1147 | L{IInPayment} |
1148 | @@ -232,6 +233,7 @@ |
1149 | @param description: optional, description of the payment |
1150 | @param base_value: optional |
1151 | @param till: optional |
1152 | + @param payment_number: optional |
1153 | @returns: a L{PaymentAdaptToOutPayment} or L{PaymentAdaptToInPayment} |
1154 | """ |
1155 | conn = self.get_connection() |
1156 | @@ -277,7 +279,8 @@ |
1157 | method=self, |
1158 | category=None, |
1159 | till=till, |
1160 | - description=description) |
1161 | + description=description, |
1162 | + payment_number=payment_number) |
1163 | facet = payment.addFacet(iface, connection=conn) |
1164 | self.operation.payment_create(payment) |
1165 | return facet |
1166 | |
1167 | === modified file 'stoqlib/domain/payment/operation.py' |
1168 | --- stoqlib/domain/payment/operation.py 2009-02-11 13:56:34 +0000 |
1169 | +++ stoqlib/domain/payment/operation.py 2011-02-01 20:17:04 +0000 |
1170 | @@ -233,7 +233,7 @@ |
1171 | def register_payment_operations(): |
1172 | pmm = get_utility(IPaymentOperationManager, None) |
1173 | if pmm is None: |
1174 | - from stoqlib.lib.paymentoperation import PaymentOperationManager |
1175 | + from stoqlib.lib.payment import PaymentOperationManager |
1176 | pmm = PaymentOperationManager() |
1177 | provide_utility(IPaymentOperationManager, pmm) |
1178 | pmm.register('money', MoneyPaymentOperation()) |
1179 | |
1180 | === modified file 'stoqlib/domain/payment/payment.py' |
1181 | --- stoqlib/domain/payment/payment.py 2010-12-16 13:54:46 +0000 |
1182 | +++ stoqlib/domain/payment/payment.py 2011-02-01 20:17:04 +0000 |
1183 | @@ -34,7 +34,8 @@ |
1184 | |
1185 | from stoqlib.database.orm import (IntCol, DateTimeCol, UnicodeCol, ForeignKey, |
1186 | PriceCol, DecimalCol) |
1187 | -from stoqlib.database.orm import const, DESC, AND, OR, MultipleJoin |
1188 | +from stoqlib.database.orm import (const, DESC, AND, OR, MultipleJoin, |
1189 | + SingleJoin) |
1190 | from stoqlib.domain.base import Domain, ModelAdapter |
1191 | from stoqlib.domain.interfaces import IInPayment, IOutPayment |
1192 | from stoqlib.exceptions import DatabaseInconsistency, StoqlibError |
1193 | @@ -101,6 +102,7 @@ |
1194 | category = ForeignKey('PaymentCategory') |
1195 | |
1196 | comments = MultipleJoin('PaymentComment') |
1197 | + check_data = SingleJoin('CheckData', joinColumn='payment_id') |
1198 | |
1199 | def _check_status(self, status, operation_name): |
1200 | assert self.status == status, ('Invalid status for %s ' |
1201 | |
1202 | === modified file 'stoqlib/gui/slaves/paymentslave.py' |
1203 | --- stoqlib/gui/slaves/paymentslave.py 2011-01-26 19:43:02 +0000 |
1204 | +++ stoqlib/gui/slaves/paymentslave.py 2011-02-01 20:17:04 +0000 |
1205 | @@ -22,22 +22,26 @@ |
1206 | ## Author(s): Evandro Vale Miquelito <evandro@async.com.br> |
1207 | ## Johan Dahlin <jdahlin@async.com.br> |
1208 | ## George Kussumoto <george@async.com.br> |
1209 | +## Thiago Bellini <hackedbellini@async.com.br> |
1210 | ## |
1211 | ## |
1212 | """ Slaves for payment management """ |
1213 | |
1214 | import gtk |
1215 | |
1216 | -from decimal import Decimal |
1217 | + |
1218 | +from copy import deepcopy |
1219 | import datetime |
1220 | from dateutil.relativedelta import relativedelta |
1221 | +from decimal import Decimal |
1222 | |
1223 | from kiwi import ValueUnset |
1224 | +from kiwi.component import get_utility |
1225 | from kiwi.datatypes import format_price, currency, ValidationError |
1226 | -from kiwi.component import get_utility |
1227 | from kiwi.python import Settable |
1228 | from kiwi.utils import gsignal |
1229 | -from kiwi.ui.objectlist import Column |
1230 | +from kiwi.ui.delegates import GladeDelegate, GladeSlaveDelegate |
1231 | +from kiwi.ui.objectlist import ObjectList, Column, SequentialColumn |
1232 | from kiwi.ui.views import SlaveView |
1233 | |
1234 | from stoqlib.database.runtime import get_connection |
1235 | @@ -58,394 +62,403 @@ |
1236 | from stoqlib.gui.editors.baseeditor import BaseEditorSlave, BaseEditor |
1237 | from stoqlib.gui.interfaces import IDomainSlaveMapper |
1238 | from stoqlib.lib.defaults import (interval_types, INTERVALTYPE_MONTH, |
1239 | - DECIMAL_PRECISION, calculate_interval) |
1240 | + DECIMAL_PRECISION) |
1241 | from stoqlib.lib.message import info, warning |
1242 | +from stoqlib.lib.payment import (generate_payments_values, |
1243 | + generate_payments_due_dates) |
1244 | from stoqlib.lib.translation import stoqlib_gettext |
1245 | |
1246 | _ = stoqlib_gettext |
1247 | |
1248 | - |
1249 | -class _TemporaryBillData(object): |
1250 | - def __init__(self, group=None, first_duedate=None): |
1251 | - self.group = group |
1252 | - self.first_duedate = first_duedate |
1253 | - self.installments_number = 1 |
1254 | - self.intervals = 1 |
1255 | - self.interval_type = 0 |
1256 | - |
1257 | - |
1258 | -class _TemporaryMoneyData(object): |
1259 | - def __init__(self): |
1260 | - self.first_duedate = datetime.datetime.today() |
1261 | - self.installments_number = 1 |
1262 | - self.intervals = 1 |
1263 | - |
1264 | - |
1265 | -class _TemporaryStoreCreditData(object): |
1266 | - def __init__(self): |
1267 | - self.first_duedate = datetime.datetime.today() |
1268 | - self.installments_number = 1 |
1269 | - self.intervals = 1 |
1270 | - |
1271 | - |
1272 | -class _TemporaryCreditProviderGroupData(object): |
1273 | - def __init__(self, group, provider): |
1274 | - self.installments_number = 1 |
1275 | +# |
1276 | +# Temporary Objects |
1277 | +# |
1278 | + |
1279 | +DEFAULT_INSTALLMENTS_NUMBER = 1 |
1280 | +DEFAULT_INTERVALS = 1 |
1281 | +DEFAULT_INTERVAL_TYPE = INTERVALTYPE_MONTH |
1282 | + |
1283 | +class _BaseTemporaryMethodData(object): |
1284 | + def __init__(self): |
1285 | + self.first_duedate = datetime.date.today() |
1286 | + self.installments_number = DEFAULT_INSTALLMENTS_NUMBER |
1287 | + self.intervals = DEFAULT_INTERVALS |
1288 | + self.interval_type = DEFAULT_INTERVAL_TYPE |
1289 | + |
1290 | + |
1291 | +class _TemporaryCreditProviderGroupData(_BaseTemporaryMethodData): |
1292 | + def __init__(self, provider=None): |
1293 | self.provider = provider |
1294 | - self.group = group |
1295 | - |
1296 | - |
1297 | -class PaymentListSlave(BaseEditorSlave): |
1298 | - """A basic payment list slave. Each element of this list is a payment |
1299 | - method slave which hold informations about payments. Available slaves |
1300 | - are: BillDataSlave and CheckDataSlave |
1301 | - |
1302 | - Notes: |
1303 | - - get_payment_slave: is a hook method which must be defined in |
1304 | - parents. The result of this function must |
1305 | - be a BaseEditorSlave instance. |
1306 | - """ |
1307 | - |
1308 | - gladefile = 'PaymentListSlave' |
1309 | - model_type = PaymentMethod |
1310 | - |
1311 | - gsignal('remove-slave') |
1312 | - gsignal('add-slave') |
1313 | - gsignal('remove-item', SlaveView) |
1314 | - |
1315 | - def __init__(self, parent, conn, payment_method, total_amount): |
1316 | - self.parent = parent |
1317 | - self.total_amount = total_amount |
1318 | - self.max_installments = None |
1319 | - # This dict stores a reference of each toplevel widget with its own |
1320 | - # kiwi object, the slave. |
1321 | - self.payment_slaves = {} |
1322 | - BaseEditorSlave.__init__(self, conn, payment_method) |
1323 | - self.update_view() |
1324 | - |
1325 | - # |
1326 | - # Private |
1327 | - # |
1328 | - |
1329 | - def _remove_payment_slave(self, widget): |
1330 | - slave = self.payment_slaves[widget] |
1331 | - del self.payment_slaves[widget] |
1332 | - self.list_vbox.remove(widget) |
1333 | - self.update_view() |
1334 | - self.emit("remove-item", slave) |
1335 | - |
1336 | - def _remove_last_payment_slave(self): |
1337 | - vbox_children = self.list_vbox.get_children() |
1338 | - if not vbox_children: |
1339 | - return |
1340 | - widget = vbox_children[-1] |
1341 | - self._remove_payment_slave(widget) |
1342 | - |
1343 | - # |
1344 | - # Public API |
1345 | - # |
1346 | - |
1347 | - def get_total_difference(self): |
1348 | - """Get the difference for the total of check payments invoiced. If |
1349 | - the difference is zero the entire sale total value is invoiced. |
1350 | - If the difference is greater than zero, there is an outstanding |
1351 | - amount to invoice. If the value is negative, there is a overpaid |
1352 | - value. |
1353 | - """ |
1354 | - slaves = self.payment_slaves.values() |
1355 | - values = [s.get_payment_value() for s in slaves |
1356 | - if s.get_payment_value() is not None] |
1357 | - total = sum(values, currency(0)) |
1358 | - slaves_total = Decimal(str(total)) |
1359 | - slaves_total -= self.parent.get_interest_total() |
1360 | - if slaves_total == self.total_amount: |
1361 | - return currency(0) |
1362 | - return currency(self.total_amount - slaves_total) |
1363 | - |
1364 | - def update_view(self): |
1365 | - children_number = self.get_children_number() |
1366 | - can_remove = children_number > 1 |
1367 | - max = self.max_installments or 0 |
1368 | - can_add = children_number < max |
1369 | - self.remove_button.set_sensitive(can_remove) |
1370 | - self.add_button.set_sensitive(can_add) |
1371 | - self.update_total_label() |
1372 | - |
1373 | - def update_total_label(self): |
1374 | - difference = self.get_total_difference() |
1375 | - if not round(difference, DECIMAL_PRECISION): |
1376 | - label_name = difference = '' |
1377 | - elif difference < 0: |
1378 | - difference *= -1 |
1379 | - label_name = _('Overpaid:') |
1380 | - else: |
1381 | - label_name = _('Outstanding:') |
1382 | - if difference: |
1383 | - difference = format_price(difference) |
1384 | - self.total_label.set_text(difference) |
1385 | - self.status_label.set_text(label_name) |
1386 | - |
1387 | - def get_children_number(self): |
1388 | - vbox_children = self.list_vbox.get_children() |
1389 | - return len(vbox_children) |
1390 | - |
1391 | - def register_max_installments(self, inst_number): |
1392 | - self.max_installments = inst_number |
1393 | - |
1394 | - def clear_list(self): |
1395 | - for widget in self.list_vbox.get_children()[:]: |
1396 | - self._remove_payment_slave(widget) |
1397 | - |
1398 | - def update_payment_list(self, installments_number): |
1399 | - installments_number = installments_number or 0 |
1400 | - children_number = self.get_children_number() |
1401 | - difference = installments_number - children_number |
1402 | - if not difference: |
1403 | - return |
1404 | - if difference > 0: |
1405 | - for unused in range(difference): |
1406 | - self.add_slave() |
1407 | - else: |
1408 | - difference *= -1 |
1409 | - for unused in range(difference): |
1410 | - self._remove_last_payment_slave() |
1411 | - |
1412 | - def add_slave(self, slave=None): |
1413 | - if not self.max_installments: |
1414 | - raise ValueError('You call register_max_installments ' |
1415 | - 'before start adding slaves') |
1416 | - if self.get_children_number() > self.max_installments: |
1417 | - return |
1418 | - slave = slave or self.parent.get_payment_slave() |
1419 | - widget = slave.get_toplevel() |
1420 | - self.payment_slaves[widget] = slave |
1421 | - children_number = self.get_children_number() + 1 |
1422 | - slave.set_frame_label('# %d' % children_number) |
1423 | - self.list_vbox.pack_start(widget, False) |
1424 | - # Scroll to the bottom of the scrolled window |
1425 | - vadj = self.scrolled_window.get_vadjustment() |
1426 | - vadj.set_value(vadj.upper) |
1427 | - widget.show() |
1428 | - self.update_view() |
1429 | - |
1430 | - def is_all_due_dates_valid(self): |
1431 | - today = datetime.date.today() |
1432 | - for slave in self.payment_slaves.values(): |
1433 | - if slave.due_date.read() < today: |
1434 | - return False |
1435 | - return True |
1436 | - |
1437 | - # |
1438 | - # Kiwi callbacks |
1439 | - # |
1440 | - |
1441 | - def on_add_button__clicked(self, *args): |
1442 | - self.add_slave() |
1443 | - self.emit('add-slave') |
1444 | - |
1445 | - def on_remove_button__clicked(self, *args): |
1446 | - self._remove_last_payment_slave() |
1447 | - self.emit('remove-slave') |
1448 | - |
1449 | - |
1450 | -class BankDataSlave(BaseEditorSlave): |
1451 | - """ A simple slave that contains only a hbox with fields to bank name and |
1452 | - its branch. This slave is used by payment method slaves that has reference |
1453 | - to a BankAccount object. |
1454 | - """ |
1455 | - gladefile = 'BankDataSlave' |
1456 | - model_type = BankAccount |
1457 | - proxy_widgets = ('bank', 'branch') |
1458 | - |
1459 | - # |
1460 | - # BaseEditorSlave hooks |
1461 | - # |
1462 | - |
1463 | - def setup_proxies(self): |
1464 | - self.add_proxy(self.model, BankDataSlave.proxy_widgets) |
1465 | - |
1466 | - |
1467 | -class BillDataSlave(BaseEditorSlave): |
1468 | - """ A slave to set payment information of bill payment method. |
1469 | - """ |
1470 | - |
1471 | - gladefile = 'BillDataSlave' |
1472 | - model_type = Payment |
1473 | + _BaseTemporaryMethodData.__init__(self) |
1474 | + |
1475 | + |
1476 | +class _TemporaryPaymentData(object): |
1477 | + def __init__(self, description, value, due_date, |
1478 | + payment_number=None, bank_data=None): |
1479 | + self.description = description |
1480 | + self.value = value |
1481 | + self.due_date = due_date |
1482 | + self.payment_number = payment_number |
1483 | + self.bank_data = bank_data |
1484 | + |
1485 | + |
1486 | +class _TemporaryBankData(object): |
1487 | + def __init__(self, bank_id=None, bank_branch=None, bank_account=None): |
1488 | + self.bank_id = bank_id |
1489 | + self.bank_branch = bank_branch |
1490 | + self.bank_account = bank_account |
1491 | + |
1492 | + |
1493 | +# |
1494 | +# Editors |
1495 | +# |
1496 | + |
1497 | +class BasePaymentDataEditor(BaseEditor): |
1498 | + """A base editor to set payment information. |
1499 | + """ |
1500 | + |
1501 | + gladefile = 'BasePaymentDataEditor' |
1502 | + model_type = _TemporaryPaymentData |
1503 | payment_widgets = ('due_date', 'value', 'payment_number') |
1504 | - gsignal('paymentvalue-changed') |
1505 | - gsignal('duedate-validate') |
1506 | - |
1507 | - def __init__(self, conn, payment_group, due_date, value, |
1508 | - method_iface, model=None): |
1509 | - self._payment_group = payment_group |
1510 | - self._due_date = due_date |
1511 | - self._value = value |
1512 | - self._method_iface = method_iface |
1513 | - BaseEditorSlave.__init__(self, conn, model) |
1514 | - |
1515 | - def _setup_widgets(self): |
1516 | - self.payment_number_label.set_bold(True) |
1517 | - self.payment_number_label.set_size('small') |
1518 | - |
1519 | - def set_frame_label(self, label_name): |
1520 | - self.payment_number_label.set_text(label_name) |
1521 | - |
1522 | - def get_payment_value(self): |
1523 | - return self.model.value |
1524 | + slave_holder = 'bank_data_slave' |
1525 | + |
1526 | + def __init__(self, model): |
1527 | + BaseEditor.__init__(self, None, model) |
1528 | + |
1529 | + def get_title(self, model): |
1530 | + return _(u"Edit '%s'" % model.description) |
1531 | |
1532 | # |
1533 | # BaseEditorSlave hooks |
1534 | # |
1535 | |
1536 | - def create_model(self, conn): |
1537 | - bill_method = PaymentMethod.get_by_name(conn, 'bill') |
1538 | - apayment = bill_method.create_payment(self._method_iface, |
1539 | - self._payment_group, |
1540 | - self._value, |
1541 | - self._due_date) |
1542 | - return apayment.get_adapted() |
1543 | - |
1544 | def setup_proxies(self): |
1545 | - self._setup_widgets() |
1546 | - self.add_proxy(self.model, BillDataSlave.payment_widgets) |
1547 | + self.add_proxy(self.model, self.payment_widgets) |
1548 | |
1549 | # |
1550 | # Kiwi callbacks |
1551 | # |
1552 | |
1553 | - def after_value__changed(self, *args): |
1554 | - self.emit('paymentvalue-changed') |
1555 | - |
1556 | def on_due_date__validate(self, widget, value): |
1557 | - self.emit('duedate-validate') |
1558 | if value < datetime.date.today(): |
1559 | return ValidationError(_(u"Expected installment due date " |
1560 | "must be set to a future date")) |
1561 | |
1562 | - |
1563 | -class CheckDataSlave(BillDataSlave): |
1564 | - """A slave to set payment information of check payment method.""" |
1565 | - slave_holder = 'bank_data_slave' |
1566 | - model_type = CheckData |
1567 | - |
1568 | - def __init__(self, conn, payment_group, due_date, value, |
1569 | - is_sale_payment, model=None, default_bank=None): |
1570 | + def on_value__validate(self, widget, value): |
1571 | + if value < currency(0): |
1572 | + return ValidationError(_(u"The value must be " |
1573 | + "a positive number")) |
1574 | + |
1575 | + |
1576 | +class CheckDataEditor(BasePaymentDataEditor): |
1577 | + """An editor to set payment information of check payment method. |
1578 | + """ |
1579 | + |
1580 | + def __init__(self, model, default_bank=None): |
1581 | self._default_bank = default_bank |
1582 | - BillDataSlave.__init__(self, conn, payment_group, due_date, |
1583 | - value, is_sale_payment, model) |
1584 | + BasePaymentDataEditor.__init__(self, model) |
1585 | |
1586 | # |
1587 | # BaseEditorSlave hooks |
1588 | # |
1589 | |
1590 | - def get_payment_value(self): |
1591 | - return self.model.payment.value |
1592 | - |
1593 | - def create_model(self, conn): |
1594 | - check_method = PaymentMethod.get_by_name(conn, 'check') |
1595 | - payment = check_method.create_payment(self._method_iface, |
1596 | - self._payment_group, |
1597 | - self._value, self._due_date) |
1598 | - return check_method.operation.get_check_data_by_payment( |
1599 | - payment.get_adapted()) |
1600 | - |
1601 | def setup_slaves(self): |
1602 | if self._default_bank and not self.model.bank_data.bank_id: |
1603 | self.model.bank_data.bank_id = self._default_bank |
1604 | - bank_data_slave = BankDataSlave(self.conn, self.model.bank_data) |
1605 | + bank_data_slave = BankDataSlave(self.model.bank_data) |
1606 | + |
1607 | if self.get_slave(self.slave_holder): |
1608 | self.detach_slave(self.slave_holder) |
1609 | self.attach_slave(self.slave_holder, bank_data_slave) |
1610 | |
1611 | + |
1612 | +class BankDataSlave(BaseEditorSlave): |
1613 | + """A simple slave that contains only a hbox with fields to bank name and |
1614 | + its branch. This slave is used by payment method slaves that has reference |
1615 | + to a BankAccount object. |
1616 | + """ |
1617 | + |
1618 | + gladefile = 'BankDataSlave' |
1619 | + model_type = _TemporaryBankData |
1620 | + proxy_widgets = ('bank_id', 'bank_branch', 'bank_account') |
1621 | + |
1622 | + def __init__(self, model): |
1623 | + self.model = model |
1624 | + BaseEditorSlave.__init__(self, None, self.model) |
1625 | + |
1626 | + # |
1627 | + # BaseEditorSlave hooks |
1628 | + # |
1629 | + |
1630 | def setup_proxies(self): |
1631 | + self.add_proxy(self.model, self.proxy_widgets) |
1632 | + |
1633 | + |
1634 | +class PaymentListSlave(GladeSlaveDelegate): |
1635 | + """A slave to manage payments with one/multiple installment(s)""" |
1636 | + |
1637 | + gladefile = 'PaymentListSlave' |
1638 | + gsignal('payment-edited') |
1639 | + |
1640 | + def __init__(self, iface, group, method, total_value, editor_class, parent): |
1641 | + self.parent = parent |
1642 | + self.iface = iface |
1643 | + self.group = group |
1644 | + self.total_value = total_value |
1645 | + self.editor_class = editor_class |
1646 | + self.method = method |
1647 | + |
1648 | + GladeSlaveDelegate.__init__(self, gladefile=self.gladefile) |
1649 | self._setup_widgets() |
1650 | - self.add_proxy(self.model.payment, BillDataSlave.payment_widgets) |
1651 | - |
1652 | + |
1653 | + # |
1654 | + # Private Methods |
1655 | + # |
1656 | + |
1657 | + def _can_edit_payments(self): |
1658 | + return self.method.method_name != 'money' |
1659 | + |
1660 | + def _get_columns(self): |
1661 | + columns = [Column('description', title=_('Description'), |
1662 | + expand=True, data_type=str)] |
1663 | + # Add columns to show bank data when the method needs it (checks for |
1664 | + # example. |
1665 | + if self.method.method_name == 'check': |
1666 | + columns.extend([Column('bank_data.bank_id', |
1667 | + title=_('Bank ID'), |
1668 | + data_type=int, justify=gtk.JUSTIFY_RIGHT), |
1669 | + Column('bank_data.bank_branch', |
1670 | + title=_('Bank Branch'), |
1671 | + data_type=str, justify=gtk.JUSTIFY_RIGHT), |
1672 | + Column('bank_data.bank_account', |
1673 | + title=_('Bank Account'), |
1674 | + data_type=str, justify=gtk.JUSTIFY_RIGHT)]) |
1675 | + # Money methods doesn't have a payment_number related with it. |
1676 | + if self.method.method_name != 'money': |
1677 | + columns.append(Column('payment_number', title=_('Number'), |
1678 | + data_type=str, justify=gtk.JUSTIFY_RIGHT)) |
1679 | + |
1680 | + columns.extend([Column('due_date', title=_('Due Date'), |
1681 | + data_type=datetime.date), |
1682 | + Column('value', title=_('Value'), data_type=currency, |
1683 | + justify=gtk.JUSTIFY_RIGHT)]) |
1684 | + |
1685 | + return columns |
1686 | + |
1687 | + |
1688 | + def _setup_widgets(self): |
1689 | + self.payment_list.set_columns(self._get_columns()) |
1690 | + self.total_label.set_text(format_price(self.total_value, True, |
1691 | + DECIMAL_PRECISION)) |
1692 | + |
1693 | + def _update_difference_label(self): |
1694 | + difference = self.get_total_difference() |
1695 | + if not difference: |
1696 | + label_name = _('Difference') |
1697 | + elif difference > 0: |
1698 | + label_name = _('Overpaid:') |
1699 | + elif difference < 0: |
1700 | + label_name = _('Outstanding:') |
1701 | + difference *= -1 |
1702 | + difference = format_price(difference, True, DECIMAL_PRECISION) |
1703 | + self.difference_label.set_text(difference) |
1704 | + self.difference_status_label.set_text(label_name) |
1705 | + |
1706 | + def _run_edit_payment_dialog(self): |
1707 | + if not self._can_edit_payments(): |
1708 | + return |
1709 | + |
1710 | + payment = self.payment_list.get_selected() |
1711 | + old = deepcopy(payment) |
1712 | + retval = run_dialog(self.editor_class, self.parent, payment) |
1713 | + if not retval: |
1714 | + # Remove the changes if dialog was canceled. |
1715 | + pos = self.payment_list.get_selected_row_number() |
1716 | + self.payment_list.remove(payment) |
1717 | + self.payment_list.insert(pos, old) |
1718 | + self.emit('payment-edited') |
1719 | + |
1720 | + # |
1721 | + # Public API |
1722 | + # |
1723 | + |
1724 | + def update_view(self): |
1725 | + self.payment_list.refresh() |
1726 | + self._update_difference_label() |
1727 | + |
1728 | + def add_payments(self, installments_number, first_due_date, |
1729 | + interval, interval_type): |
1730 | + values = generate_payments_values(self.total_value, |
1731 | + installments_number) |
1732 | + due_dates = generate_payments_due_dates(installments_number, |
1733 | + first_due_date, interval, |
1734 | + interval_type) |
1735 | + bank_data = None |
1736 | + |
1737 | + self.clear_payments() |
1738 | + for i in range(installments_number): |
1739 | + description = self.method.describe_payment(self.group, i + 1, |
1740 | + installments_number) |
1741 | + if self.method.method_name == 'check': |
1742 | + bank_data = _TemporaryBankData() |
1743 | + payment = _TemporaryPaymentData(description, |
1744 | + currency(values[i]), |
1745 | + due_dates[i], |
1746 | + None, |
1747 | + bank_data) |
1748 | + self.payment_list.append(payment) |
1749 | + |
1750 | + self.update_view() |
1751 | + |
1752 | + def create_payments(self): |
1753 | + if not self.is_payment_list_valid(): |
1754 | + return [] |
1755 | + |
1756 | + payments = [] |
1757 | + for p in self.payment_list: |
1758 | + # FIXME: The create_payment API has an argcheck on due_date |
1759 | + # forcing it to be datetime.datetime, so we need to |
1760 | + # make this conversion. |
1761 | + due_date = datetime.datetime(p.due_date.year, |
1762 | + p.due_date.month, |
1763 | + p.due_date.day) |
1764 | + payment = self.method.create_payment(iface=self.iface, |
1765 | + payment_group=self.group, |
1766 | + value=p.value, |
1767 | + due_date=due_date, |
1768 | + description=p.description, |
1769 | + payment_number=p.payment_number) |
1770 | + if p.bank_data: |
1771 | + # Add the bank_data into the payment, if any. |
1772 | + adapted = payment.get_adapted() |
1773 | + bank_data = adapted.check_data.bank_data |
1774 | + bank_data.bank_id = p.bank_data.bank_id |
1775 | + bank_data.branch = p.bank_data.bank_branch |
1776 | + bank_data.account = p.bank_data.bank_account |
1777 | + payments.append(payment) |
1778 | + |
1779 | + return payments |
1780 | + |
1781 | + def clear_payments(self): |
1782 | + self.payment_list.clear(); |
1783 | + self.update_view() |
1784 | + |
1785 | + def get_total_difference(self): |
1786 | + total_payments = Decimal(0) |
1787 | + for payment in self.payment_list: |
1788 | + total_payments += payment.value |
1789 | + return (total_payments - self.total_value) |
1790 | + |
1791 | + def are_due_dates_valid(self): |
1792 | + previous_date = datetime.date.today() + datetime.timedelta(days=-1) |
1793 | + for payment in self.payment_list: |
1794 | + if payment.due_date <= previous_date: |
1795 | + warning(_(u"Payment dates can't repeat or be lower than " |
1796 | + "previous dates.")) |
1797 | + return False |
1798 | + previous_date = payment.due_date |
1799 | + return True |
1800 | + |
1801 | + def are_payment_values_valid(self): |
1802 | + return not self.get_total_difference() |
1803 | + |
1804 | + def is_payment_list_valid(self): |
1805 | + if not self.are_due_dates_valid(): |
1806 | + return False |
1807 | + if not self.are_payment_values_valid(): |
1808 | + return False |
1809 | + return True |
1810 | + |
1811 | + # |
1812 | + # Kiwi Callbacks |
1813 | + # |
1814 | + |
1815 | + def on_payment_list__row_activated(self, *args): |
1816 | + self._run_edit_payment_dialog() |
1817 | + self.update_view() |
1818 | + |
1819 | + |
1820 | +# |
1821 | +# Payment Method Slaves |
1822 | +# |
1823 | |
1824 | class BasePaymentMethodSlave(BaseEditorSlave): |
1825 | """A base payment method slave for Bill and Check methods.""" |
1826 | |
1827 | - gladefile = 'BillCheckMethodSlave' |
1828 | - model_type = _TemporaryBillData |
1829 | - slave_holder = 'bill_check_data_list' |
1830 | + gladefile = 'BasePaymentMethodSlave' |
1831 | + model_type = _BaseTemporaryMethodData |
1832 | + slave_holder = 'slave_holder' |
1833 | proxy_widgets = ('interval_type_combo', |
1834 | 'intervals', |
1835 | 'first_duedate', |
1836 | 'installments_number') |
1837 | - # This attribute must be defined in child. It can assume two |
1838 | - # value: CheckDataSlave, BillDataSlave |
1839 | - _data_slave_class = None |
1840 | + |
1841 | + # This attribute must be defined in child. |
1842 | + # Use BasePaymentDataEditor or one of it's children. |
1843 | + _data_editor_class = None |
1844 | |
1845 | def __init__(self, wizard, parent, conn, order_obj, payment_method, |
1846 | outstanding_value=currency(0)): |
1847 | + self.wizard = wizard |
1848 | + self.parent = parent |
1849 | # Note that 'order' may be a Sale or a PurchaseOrder object |
1850 | self.order = order_obj |
1851 | - self.wizard = wizard |
1852 | self.method = payment_method |
1853 | self.method_iface = self._get_payment_method_iface() |
1854 | - # This is very useful when calculating the total amount outstanding |
1855 | - # or overpaid of the payments |
1856 | - self.interest_total = currency(0) |
1857 | + self.total_value = outstanding_value or self._get_total_amount() |
1858 | self.payment_group = self.order.group |
1859 | self.payment_list = None |
1860 | - self._reset_btn_validation_ok = True |
1861 | - self.total_value = outstanding_value or self._get_total_amount() |
1862 | + # This is very useful when calculating the total amount outstanding |
1863 | + # or overpaid of the payments |
1864 | + self.interest_total = currency(0) |
1865 | + |
1866 | BaseEditorSlave.__init__(self, conn) |
1867 | self.register_validate_function(self._refresh_next) |
1868 | - self.parent = parent |
1869 | - self.interval_type_combo.set_sensitive(False) |
1870 | - self.intervals.set_sensitive(False) |
1871 | - self.update_view() |
1872 | + |
1873 | + # |
1874 | + # Private Methods |
1875 | + # |
1876 | |
1877 | def _refresh_next(self, validation_ok=True): |
1878 | - if validation_ok and self.payment_list: |
1879 | - total_difference = self.payment_list.get_total_difference() |
1880 | - validation_ok = (total_difference == currency(0) and |
1881 | - self.payment_list.is_all_due_dates_valid()) |
1882 | + if not self.payment_list: |
1883 | + validation_ok = False |
1884 | + if validation_ok: |
1885 | + validation_ok = self.payment_list.is_payment_list_valid() |
1886 | + |
1887 | self.wizard.refresh_next(validation_ok) |
1888 | |
1889 | - def update_view(self): |
1890 | - attrs = [self.model.installments_number, self.model.first_duedate, |
1891 | - self.model.intervals] |
1892 | - self.reset_button.set_sensitive((None not in attrs) and |
1893 | - self._reset_btn_validation_ok) |
1894 | - self._refresh_next() |
1895 | - |
1896 | - def _setup_widgets(self): |
1897 | - max = self.method.max_installments |
1898 | - self.installments_number.set_range(1, max) |
1899 | - self.installments_number.set_value(1) |
1900 | - |
1901 | - items = [(label, constant) for constant, label |
1902 | - in interval_types.items()] |
1903 | - self.interval_type_combo.prefill(items) |
1904 | - self.payment_list = PaymentListSlave(self, self.conn, |
1905 | - self.method, self.total_value) |
1906 | - self.payment_list.connect('add-slave', |
1907 | - self.update_installments_number) |
1908 | - self.payment_list.connect('remove-slave', |
1909 | - self.update_installments_number) |
1910 | - self.payment_list.connect("remove-item", |
1911 | - self._on_payment_list__remove_item) |
1912 | - self.payment_list.register_max_installments(max) |
1913 | + def _setup_payment_list(self): |
1914 | + self.payment_list = PaymentListSlave(self.method_iface, |
1915 | + self.payment_group, |
1916 | + self.method, |
1917 | + self.total_value, |
1918 | + self._data_editor_class, |
1919 | + self.wizard) |
1920 | if self.get_slave(BasePaymentMethodSlave.slave_holder): |
1921 | self.detach_slave(BasePaymentMethodSlave.slave_holder) |
1922 | self.attach_slave(BasePaymentMethodSlave.slave_holder, |
1923 | self.payment_list) |
1924 | - created_adapted_payments = self.get_created_adapted_payments() |
1925 | - if created_adapted_payments: |
1926 | - self.fill_slave_list(created_adapted_payments) |
1927 | - else: |
1928 | - # Adding the first payment |
1929 | - slave = self.get_payment_slave() |
1930 | - self.payment_list.add_slave(slave) |
1931 | - |
1932 | - def get_created_adapted_payments(self): |
1933 | - for payment in Payment.selectBy(group=self.payment_group, |
1934 | - method=self.method, |
1935 | - status=Payment.STATUS_PREVIEW, |
1936 | - connection=self.conn): |
1937 | - yield self.method_iface(payment, None) |
1938 | + self.setup_payments() |
1939 | + self.payment_list.connect('payment-edited', |
1940 | + self._on_payment_list__edit_payment) |
1941 | + |
1942 | + |
1943 | + def _setup_widgets(self): |
1944 | + max_installments = self.method.max_installments |
1945 | + self.installments_number.set_range(1, max_installments) |
1946 | + self.installments_number.set_value(1) |
1947 | + # FIXME: Workarround to make intervals never go to 0 |
1948 | + self.intervals.set_range(1, 99) |
1949 | + |
1950 | + self.intervals.set_sensitive(False) |
1951 | + items = [(label, constant) |
1952 | + for constant, label in interval_types.items()] |
1953 | + self.interval_type_combo.prefill(items) |
1954 | + self.interval_type_combo.select_item_by_data(INTERVALTYPE_MONTH) |
1955 | + self.interval_type_combo.set_sensitive(False) |
1956 | + |
1957 | + # PaymentListSlave setup |
1958 | + self._setup_payment_list() |
1959 | |
1960 | def _get_total_amount(self): |
1961 | """Returns the order total amount """ |
1962 | @@ -468,98 +481,45 @@ |
1963 | else: |
1964 | raise TypeError |
1965 | |
1966 | - # |
1967 | - # General methods |
1968 | - # |
1969 | - |
1970 | - def _setup_payments(self): |
1971 | - self.payment_list.clear_list() |
1972 | - due_dates = [] |
1973 | - interval = calculate_interval(self.model.interval_type, |
1974 | - self.model.intervals) |
1975 | - installments_number = self.model.installments_number |
1976 | - self.payment_group.installments_number = installments_number |
1977 | - due_date = self.model.first_duedate |
1978 | - for i in range(installments_number): |
1979 | - #XXX: convert to datetime.datetime |
1980 | - d = datetime.datetime(due_date.year, due_date.month, due_date.day) |
1981 | - due_dates.append(d + datetime.timedelta(i * interval)) |
1982 | - |
1983 | - payments = self.method.create_payments(self.method_iface, |
1984 | - self.payment_group, |
1985 | - self.total_value, |
1986 | - due_dates) |
1987 | - interest = Decimal(0) |
1988 | - |
1989 | - # This is very useful when calculating the total amount outstanding |
1990 | - # or overpaid of the payments |
1991 | - self.interest_total = interest |
1992 | - self.fill_slave_list(payments) |
1993 | - |
1994 | - def fill_slave_list(self, adapted_payments): |
1995 | - for adapted in adapted_payments: |
1996 | - slave = self.get_slave_by_adapted_payment(adapted) |
1997 | - self.payment_list.add_slave(slave) |
1998 | - |
1999 | - def get_slave_by_adapted_payment(self, adapted_payment): |
2000 | - raise NotImplementedError |
2001 | + def _create_payments(self): |
2002 | + """Insert the payment_list's payments in the base.""" |
2003 | + return self.payment_list.create_payments() |
2004 | + |
2005 | + # |
2006 | + # Public API |
2007 | + # |
2008 | + |
2009 | + def setup_payments(self): |
2010 | + """Setup the payments in PaymentList. |
2011 | + |
2012 | + Note: The payments are not inserted into the db until self.finish() |
2013 | + is called. The wizard is responsable for that""" |
2014 | + if not self.model.first_duedate: |
2015 | + return |
2016 | + if self.payment_list: |
2017 | + self.payment_list.add_payments(self.model.installments_number, |
2018 | + self.model.first_duedate, |
2019 | + self.model.intervals, |
2020 | + self.model.interval_type) |
2021 | + self.update_view() |
2022 | + |
2023 | + def update_view(self): |
2024 | + self._refresh_next() |
2025 | |
2026 | def get_interest_total(self): |
2027 | return self.interest_total |
2028 | |
2029 | - def get_extra_slave_args(self): |
2030 | - """ This method can be redefined in child when extra parameters needs |
2031 | - to be passed to the slave class. This method must return always a list |
2032 | - with the parameters. |
2033 | - """ |
2034 | - return [] |
2035 | - |
2036 | - # |
2037 | - # PaymentListSlave |
2038 | - # |
2039 | - |
2040 | - def get_payment_slave(self, model=None): |
2041 | - if not self._data_slave_class: |
2042 | - raise ValueError('Child classes must define a data_slave_class ' |
2043 | - 'attribute') |
2044 | - due_date = datetime.datetime.today() |
2045 | - if not self.payment_list.get_children_number(): |
2046 | - total = self.total_value |
2047 | - else: |
2048 | - total = currency(0) |
2049 | - extra_params = self.get_extra_slave_args() |
2050 | - slave = self._data_slave_class(self.conn, self.payment_group, due_date, |
2051 | - total, self.method_iface, model, |
2052 | - *extra_params) |
2053 | - slave.connect('paymentvalue-changed', |
2054 | - self._on_slave__paymentvalue_changed) |
2055 | - slave.connect('duedate-validate', |
2056 | - self._on_slave__duedate_validate) |
2057 | - return slave |
2058 | - |
2059 | - def update_installments_number(self, *args): |
2060 | - inst_number = self.payment_list.get_children_number() |
2061 | - self.model.installments_number = inst_number |
2062 | - self.proxy.update('installments_number') |
2063 | - |
2064 | # |
2065 | # PaymentMethodStep hooks |
2066 | # |
2067 | |
2068 | def finish(self): |
2069 | - # Since payments are created during this step there is no need to |
2070 | - # perform tasks here |
2071 | - |
2072 | - # Validate payment dates before moving on |
2073 | - today = datetime.date.today() |
2074 | - previous_date = today + datetime.timedelta(days=-1) |
2075 | - for slave in self.payment_list.payment_slaves.values(): |
2076 | - if (slave.due_date.read() < today or |
2077 | - slave.due_date.read() <= previous_date): |
2078 | - warning(_(u"Payment dates can't repeat or be lower than " |
2079 | - "previous dates.")) |
2080 | - return False |
2081 | - previous_date = slave.due_date.read() |
2082 | + """This method is called by the wizard when going to a next step. |
2083 | + If it returns False, the wizard can't go on.""" |
2084 | + if (not self.payment_list or |
2085 | + not self.payment_list.is_payment_list_valid()): |
2086 | + return False |
2087 | + self._create_payments() |
2088 | |
2089 | return True |
2090 | |
2091 | @@ -571,102 +531,66 @@ |
2092 | self._setup_widgets() |
2093 | self.proxy = self.add_proxy(self.model, |
2094 | BasePaymentMethodSlave.proxy_widgets) |
2095 | - self.interval_type_combo.select_item_by_data(INTERVALTYPE_MONTH) |
2096 | |
2097 | def create_model(self, conn): |
2098 | - return _TemporaryBillData(group=self.payment_group, |
2099 | - first_duedate=datetime.datetime.today()) |
2100 | + return _BaseTemporaryMethodData() |
2101 | |
2102 | # |
2103 | # Kiwi callbacks |
2104 | # |
2105 | |
2106 | - def on_installments_number__changed(self, proxyspinbutton): |
2107 | - # Call this callback *on* the value changed because we need to |
2108 | - # have the same value for the length of the payments list and |
2109 | - # validate the installments_number |
2110 | - inst_number = self.model.installments_number |
2111 | - max = self.method.max_installments |
2112 | - if inst_number > max: |
2113 | - self.installments_number.set_invalid(_("The number of installments " |
2114 | - "must be less then %d" % max)) |
2115 | - self._refresh_next(False) |
2116 | - return |
2117 | - if self.payment_list: |
2118 | - self.payment_list.update_payment_list(inst_number) |
2119 | - has_installments = inst_number > 1 |
2120 | + def _on_payment_list__edit_payment(self, *args): |
2121 | + """Callback for the 'payment-edited' signal on PaymentListSlave""" |
2122 | + self.update_view() |
2123 | + |
2124 | + def after_installments_number__changed(self, *args): |
2125 | + has_installments = self.model.installments_number > 1 |
2126 | + |
2127 | self.interval_type_combo.set_sensitive(has_installments) |
2128 | self.intervals.set_sensitive(has_installments) |
2129 | - self._refresh_next(False) |
2130 | + self.setup_payments() |
2131 | + |
2132 | + def after_intervals__changed(self, *args): |
2133 | + self.setup_payments() |
2134 | + |
2135 | + def after_interval_type_combo__changed(self, *args): |
2136 | + self.setup_payments() |
2137 | + |
2138 | + def after_first_duedate__changed(self, *args): |
2139 | + self.setup_payments() |
2140 | + |
2141 | + def on_installments_number__validate(self, widget, value): |
2142 | + if not value: |
2143 | + return ValidationError(_("The number of installments " |
2144 | + "cannot be 0")) |
2145 | + |
2146 | + max_installments = self.method.max_installments |
2147 | + if value > max_installments: |
2148 | + return ValidationError(_("The number of installments " |
2149 | + "must be less then %d" % |
2150 | + max_installments)) |
2151 | |
2152 | def on_first_duedate__validate(self, widget, value): |
2153 | if value < datetime.date.today(): |
2154 | - return ValidationError(_("Expected first installment date must be set " |
2155 | - "to a future date")) |
2156 | - self._refresh_next(False) |
2157 | - |
2158 | - def on_intervals__value_changed(self, *args): |
2159 | - self.update_view() |
2160 | - self._refresh_next(False) |
2161 | - |
2162 | - def on_interval_type_combo__changed(self, *args): |
2163 | - self.update_view() |
2164 | - self._refresh_next(False) |
2165 | - |
2166 | - def on_reset_button__clicked(self, *args): |
2167 | - self._setup_payments() |
2168 | - self.update_view() |
2169 | - |
2170 | - def on_intervals__validation_changed(self, widget, is_valid): |
2171 | - self._reset_btn_validation_ok = is_valid |
2172 | - self.update_view() |
2173 | - |
2174 | - def on_first_duedate__validation_changed(self, widget, is_valid): |
2175 | - self._reset_btn_validation_ok = is_valid |
2176 | - self.update_view() |
2177 | - |
2178 | - def on_installments_number__validation_changed(self, widget, is_valid): |
2179 | - self._reset_btn_validation_ok = is_valid |
2180 | - self.update_view() |
2181 | - |
2182 | - def _on_slave__paymentvalue_changed(self, slave): |
2183 | - self.update_view() |
2184 | - self.payment_list.update_total_label() |
2185 | - |
2186 | - def _on_slave__duedate_validate(self, slave): |
2187 | - self.update_view() |
2188 | - |
2189 | - def _on_payment_list__remove_item(self, payment_list, slave): |
2190 | - if not isinstance(slave.model, slave.model_type): |
2191 | - raise TypeError('Slave model attribute should be of type ' |
2192 | - '%s, got %s' % (slave.model_type, |
2193 | - type(slave.model))) |
2194 | - |
2195 | - if isinstance(slave.model, CheckData): |
2196 | - payment = slave.model.payment |
2197 | - else: |
2198 | - payment = slave.model |
2199 | - |
2200 | - Payment.delete(payment.id, self.conn) |
2201 | + self.payment_list.clear_payments() |
2202 | + return ValidationError(_("Expected first installment date must be " |
2203 | + "set to a future date")) |
2204 | + |
2205 | + |
2206 | +class BillMethodSlave(BasePaymentMethodSlave): |
2207 | + _data_editor_class = BasePaymentDataEditor |
2208 | + |
2209 | + def __init__(self, wizard, parent, conn, sale, payment_method, |
2210 | + outstanding_value=currency(0)): |
2211 | + BasePaymentMethodSlave.__init__(self, wizard, parent, conn, |
2212 | + sale, payment_method, |
2213 | + outstanding_value=outstanding_value) |
2214 | + self.bank_label.hide() |
2215 | + self.bank_combo.hide() |
2216 | |
2217 | |
2218 | class CheckMethodSlave(BasePaymentMethodSlave): |
2219 | - _data_slave_class = CheckDataSlave |
2220 | - |
2221 | - def get_slave_by_adapted_payment(self, adapted_payment): |
2222 | - check_data = self.method.operation.get_check_data_by_payment( |
2223 | - adapted_payment.get_adapted()) |
2224 | - return self.get_payment_slave(check_data) |
2225 | - |
2226 | - def get_extra_slave_args(self): |
2227 | - """ If there is any selected item in the banks combo, return this |
2228 | - as extra parameter to the slave (CheckDataSlave). """ |
2229 | - if (self.bank_combo.get_property("visible") |
2230 | - and len(self.bank_combo.get_model())): |
2231 | - bank_id = self.bank_combo.get_selected() |
2232 | - if bank_id: |
2233 | - return [bank_id] |
2234 | - return [] |
2235 | + _data_editor_class = CheckDataEditor |
2236 | |
2237 | def _setup_widgets(self): |
2238 | printer = get_current_cheque_printer_settings(self.conn) |
2239 | @@ -676,52 +600,14 @@ |
2240 | else: |
2241 | banks = printer.get_banks() |
2242 | items = [("%s - %s" % (code, bank.name), code) |
2243 | - for code, bank in banks.items()] |
2244 | + for code, bank in banks.items()] |
2245 | self.bank_combo.prefill(items) |
2246 | BasePaymentMethodSlave._setup_widgets(self) |
2247 | |
2248 | |
2249 | -class BillMethodSlave(BasePaymentMethodSlave): |
2250 | - _data_slave_class = BillDataSlave |
2251 | - |
2252 | - def __init__(self, wizard, parent, conn, sale, payment_method, |
2253 | - outstanding_value=currency(0)): |
2254 | - BasePaymentMethodSlave.__init__(self, wizard, parent, conn, |
2255 | - sale, payment_method, |
2256 | - outstanding_value=outstanding_value) |
2257 | - self.bank_label.hide() |
2258 | - self.bank_combo.hide() |
2259 | - |
2260 | - def get_slave_by_adapted_payment(self, adapted_payment): |
2261 | - payment = adapted_payment.get_adapted() |
2262 | - return self.get_payment_slave(payment) |
2263 | - |
2264 | - |
2265 | -class _MoneyData(BillDataSlave): |
2266 | - |
2267 | - def create_model(self, conn): |
2268 | - money_method = PaymentMethod.get_by_name(conn, 'money') |
2269 | - apayment = money_method.create_payment(self._method_iface, |
2270 | - self._payment_group, |
2271 | - self._value, |
2272 | - self._due_date) |
2273 | - return apayment.get_adapted() |
2274 | - |
2275 | - |
2276 | -class _StoreCreditData(BillDataSlave): |
2277 | - |
2278 | - def create_model(self, conn): |
2279 | - method = PaymentMethod.get_by_name(conn, 'store_credit') |
2280 | - apayment = method.create_payment(self._method_iface, |
2281 | - self._payment_group, |
2282 | - self._value, |
2283 | - self._due_date) |
2284 | - return apayment.get_adapted() |
2285 | - |
2286 | - |
2287 | class MoneyMethodSlave(BasePaymentMethodSlave): |
2288 | - model_type = _TemporaryMoneyData |
2289 | - _data_slave_class = _MoneyData |
2290 | + model_type = _BaseTemporaryMethodData |
2291 | + _data_editor_class = BasePaymentDataEditor |
2292 | |
2293 | def __init__(self, wizard, parent, conn, total_amount, |
2294 | payment_method, outstanding_value=currency(0)): |
2295 | @@ -732,17 +618,16 @@ |
2296 | self.bank_combo.hide() |
2297 | self.first_duedate_lbl.hide() |
2298 | self.first_duedate.hide() |
2299 | - |
2300 | - def get_slave_by_adapted_payment(self, adapted_payment): |
2301 | - return self.get_payment_slave(adapted_payment.get_adapted()) |
2302 | - |
2303 | - def create_model(self, conn): |
2304 | - return _TemporaryMoneyData() |
2305 | + self.intervals_lbl.hide() |
2306 | + self.intervals.hide() |
2307 | + self.interval_type_combo.hide() |
2308 | + self.installments_number_lbl.hide() |
2309 | + self.installments_number.hide() |
2310 | |
2311 | |
2312 | class StoreCreditMethodSlave(BasePaymentMethodSlave): |
2313 | - model_type = _TemporaryStoreCreditData |
2314 | - _data_slave_class = _StoreCreditData |
2315 | + model_type = _BaseTemporaryMethodData |
2316 | + _data_editor_class = BasePaymentDataEditor |
2317 | |
2318 | def __init__(self, wizard, parent, conn, total_amount, |
2319 | payment_method, outstanding_value=currency(0)): |
2320 | @@ -754,21 +639,15 @@ |
2321 | self.first_duedate_lbl.hide() |
2322 | self.first_duedate.hide() |
2323 | |
2324 | - def get_slave_by_adapted_payment(self, adapted_payment): |
2325 | - return self.get_payment_slave(adapted_payment.get_adapted()) |
2326 | - |
2327 | - def create_model(self, conn): |
2328 | - return _TemporaryStoreCreditData() |
2329 | - |
2330 | |
2331 | class CardMethodSlave(BaseEditorSlave): |
2332 | """A base payment method slave for card and finance methods. |
2333 | Available slaves are: CardMethodSlave |
2334 | """ |
2335 | + |
2336 | gladefile = 'CreditProviderMethodSlave' |
2337 | model_type = _TemporaryCreditProviderGroupData |
2338 | - proxy_widgets = ('credit_provider', |
2339 | - 'installments_number') |
2340 | + proxy_widgets = ('credit_provider', 'installments_number') |
2341 | |
2342 | def __init__(self, wizard, parent, conn, order, payment_method, |
2343 | outstanding_value=currency(0)): |
2344 | @@ -817,9 +696,7 @@ |
2345 | raise ValueError('You must have credit providers information ' |
2346 | 'stored in the database before start doing ' |
2347 | 'sales') |
2348 | - return _TemporaryCreditProviderGroupData( |
2349 | - group=self._payment_group, |
2350 | - provider=None) |
2351 | + return _TemporaryCreditProviderGroupData(provider=None) |
2352 | |
2353 | # Private |
2354 | |
2355 | @@ -920,15 +797,16 @@ |
2356 | max_installments = self.installments_number.get_range()[1] |
2357 | min_installments = self.installments_number.get_range()[0] |
2358 | if not min_installments <= installments <= max_installments: |
2359 | - return ValidationError(_(u'Number of installments must be greater' |
2360 | - ' than %d and lower than %d') |
2361 | - % (min_installments, max_installments)) |
2362 | + return ValidationError(_(u'Number of installments must be greater ' |
2363 | + 'than %d and lower than %d') |
2364 | + % (min_installments, max_installments)) |
2365 | |
2366 | |
2367 | class _MultipleMethodEditor(BaseEditor): |
2368 | """A generic editor that attaches a payment method slave in a toplevel |
2369 | window. |
2370 | """ |
2371 | + |
2372 | gladefile = 'HolderTemplate' |
2373 | model_type = PaymentGroup |
2374 | model_name = _(u'Payment') |
2375 | |
2376 | === modified file 'stoqlib/gui/wizards/purchasewizard.py' |
2377 | --- stoqlib/gui/wizards/purchasewizard.py 2011-01-07 16:03:44 +0000 |
2378 | +++ stoqlib/gui/wizards/purchasewizard.py 2011-02-01 20:17:04 +0000 |
2379 | @@ -324,8 +324,6 @@ |
2380 | gladefile = 'PurchasePaymentStep' |
2381 | model_type = PaymentGroup |
2382 | payment_widgets = ('method_combo',) |
2383 | - order_widgets = ('subtotal_lbl', |
2384 | - 'total_lbl') |
2385 | |
2386 | def __init__(self, wizard, previous, conn, model, |
2387 | outstanding_value=currency(0)): |
2388 | @@ -374,32 +372,28 @@ |
2389 | if not self.slave: |
2390 | self._set_method_slave() |
2391 | |
2392 | - def _update_totals(self, *args): |
2393 | - for field_name in ['purchase_subtotal', 'purchase_total']: |
2394 | - self.order_proxy.update(field_name) |
2395 | - |
2396 | # |
2397 | # WizardStep hooks |
2398 | # |
2399 | |
2400 | + def validate_step(self): |
2401 | + return self.slave.finish() |
2402 | + |
2403 | def next_step(self): |
2404 | return FinishPurchaseStep(self.wizard, self, self.conn, |
2405 | self.order) |
2406 | |
2407 | def post_init(self): |
2408 | + self.model.clear_unused() |
2409 | self.method_combo.grab_focus() |
2410 | self.main_box.set_focus_chain([self.payment_method_hbox, |
2411 | self.method_slave_holder]) |
2412 | self.payment_method_hbox.set_focus_chain([self.method_combo]) |
2413 | self.register_validate_function(self.wizard.refresh_next) |
2414 | self.force_validation() |
2415 | - can_finish = self.slave.payment_list.get_total_difference() == 0 |
2416 | - self.wizard.refresh_next(can_finish) |
2417 | |
2418 | def setup_proxies(self): |
2419 | self._setup_widgets() |
2420 | - self.order_proxy = self.add_proxy(self.order, |
2421 | - PurchasePaymentStep.order_widgets) |
2422 | self.proxy = self.add_proxy(self.model, |
2423 | PurchasePaymentStep.payment_widgets) |
2424 | # Set the first payment method as default |
2425 | |
2426 | === modified file 'stoqlib/lib/defaults.py' |
2427 | --- stoqlib/lib/defaults.py 2010-12-09 19:20:41 +0000 |
2428 | +++ stoqlib/lib/defaults.py 2011-02-01 20:17:04 +0000 |
2429 | @@ -61,10 +61,10 @@ |
2430 | INTERVALTYPE_MONTH: _('Months'), |
2431 | INTERVALTYPE_YEAR: _('Years')} |
2432 | |
2433 | -interval_values = {INTERVALTYPE_DAY: 1, |
2434 | - INTERVALTYPE_WEEK: 7, |
2435 | - INTERVALTYPE_MONTH: 30, |
2436 | - INTERVALTYPE_YEAR: 365} |
2437 | +interval_name = {INTERVALTYPE_DAY: 'days', |
2438 | + INTERVALTYPE_WEEK: 'weeks', |
2439 | + INTERVALTYPE_MONTH: 'months', |
2440 | + INTERVALTYPE_YEAR: 'years'} |
2441 | |
2442 | # weekday constants |
2443 | |
2444 | @@ -86,31 +86,26 @@ |
2445 | return _libc |
2446 | |
2447 | |
2448 | -def calculate_interval(interval_type, intervals): |
2449 | - """Get the interval type value for a certain INTERVALTYPE_* constant. |
2450 | - Intervals are useful modes to calculate payment duedates. |
2451 | - |
2452 | - @param interval_type: |
2453 | - @param intervals: |
2454 | - @returns: |
2455 | - |
2456 | - >>> calculate_interval(INTERVALTYPE_DAY, 5) |
2457 | - 5 |
2458 | - |
2459 | - >>> calculate_interval(INTERVALTYPE_MONTH, 3) |
2460 | - 90 |
2461 | - |
2462 | - >>> calculate_interval(INTERVALTYPE_YEAR, 10) |
2463 | - 3650 |
2464 | - |
2465 | +def calculate_delta_interval(interval_type, intervals): |
2466 | + """Get the relativedelta value for a certain INTERVALTYPE_* constant. |
2467 | + |
2468 | + Intervals are useful modes to calculate payment duedates, just sum |
2469 | + them with a L{datetime.datetime} or L{datetime.date} object. |
2470 | + |
2471 | + @param interval_type: one of the INTERVALTYPE_* above |
2472 | + @param intervals: an int representing the number of intervals |
2473 | + @returns: a L{relativedelta.relativedelta} object |
2474 | """ |
2475 | - if not interval_values.has_key(interval_type): |
2476 | + if not interval_types.has_key(interval_type): |
2477 | raise KeyError('Invalid interval_type %r argument for ' |
2478 | 'calculate_interval function.' % (interval_type,)) |
2479 | if not type(intervals) == int: |
2480 | raise TypeError('Invalid type for intervals argument. It must be ' |
2481 | 'integer, got %s' % type(intervals)) |
2482 | - return interval_values[interval_type] * intervals |
2483 | + |
2484 | + kargs = {interval_name[interval_type]: intervals} |
2485 | + |
2486 | + return relativedelta.relativedelta(**kargs) |
2487 | |
2488 | |
2489 | def get_weekday_start(): |
2490 | |
2491 | === renamed file 'stoqlib/lib/paymentoperation.py' => 'stoqlib/lib/payment.py' |
2492 | --- stoqlib/lib/paymentoperation.py 2009-02-11 13:56:34 +0000 |
2493 | +++ stoqlib/lib/payment.py 2011-02-01 20:17:04 +0000 |
2494 | @@ -20,10 +20,15 @@ |
2495 | ## Foundation, Inc., or visit: http://www.gnu.org/. |
2496 | ## |
2497 | ## Author(s): Johan Dahlin <jdahlin@async.com.br> |
2498 | +## Thiago Bellini <hackedbellini@async.com.br> |
2499 | ## |
2500 | |
2501 | +import datetime |
2502 | +from decimal import Decimal |
2503 | + |
2504 | from zope.interface import implements |
2505 | |
2506 | +from stoqlib.lib.defaults import calculate_delta_interval, quantize |
2507 | from stoqlib.lib.interfaces import IPaymentOperation, IPaymentOperationManager |
2508 | from stoqlib.lib.translation import stoqlib_gettext |
2509 | |
2510 | @@ -52,3 +57,59 @@ |
2511 | def get(self, name): |
2512 | return self._methods.get(name) |
2513 | |
2514 | + |
2515 | +def generate_payments_values(value, installments_number, |
2516 | + interest=Decimal(0)): |
2517 | + """Calculates the values of payments |
2518 | + |
2519 | + @param value: value of payment |
2520 | + @param installments_number: the number of installments |
2521 | + @param interest: a L{Decimal} with the interest |
2522 | + @returns: a list with the values |
2523 | + """ |
2524 | + assert installments_number > 0 |
2525 | + |
2526 | + if interest: |
2527 | + interest_rate = interest / 100 + 1 |
2528 | + normalized_value = quantize((value / installments_number) |
2529 | + * interest_rate) |
2530 | + interest_total = normalized_value * installments_number - value |
2531 | + else: |
2532 | + normalized_value = quantize(value / installments_number) |
2533 | + interest_total = Decimal(0) |
2534 | + |
2535 | + payments = [] |
2536 | + payments_total = Decimal(0) |
2537 | + for i in range(installments_number): |
2538 | + payments.append(normalized_value) |
2539 | + payments_total += normalized_value |
2540 | + |
2541 | + # Adjust the last payment so the total will sum up nicely. |
2542 | + difference = -(payments_total - interest_total - value) |
2543 | + if difference: |
2544 | + payments[-1] += difference |
2545 | + |
2546 | + return payments |
2547 | + |
2548 | + |
2549 | +def generate_payments_due_dates(installments_number, first_due_date, |
2550 | + interval, interval_type): |
2551 | + """Calculates the due dates of payments |
2552 | + |
2553 | + @param installments_number: the number of installments |
2554 | + @param first_due_date: a L{datetime.datetime} or L{datetime.date} |
2555 | + object containing the first due date |
2556 | + @param interval: the interval between due_dates |
2557 | + @param interval_type: an interval_type from L{stoqlib.lib.defaults} |
2558 | + @returns: a list with the due_dates |
2559 | + """ |
2560 | + assert installments_number > 0 |
2561 | + |
2562 | + due_dates = [] |
2563 | + delta = calculate_delta_interval(interval_type, interval) |
2564 | + d = first_due_date |
2565 | + for i in range(installments_number): |
2566 | + due_dates.append(d) |
2567 | + d += delta |
2568 | + |
2569 | + return due_dates |
2570 | |
2571 | === added file 'stoqlib/lib/test/test_payment.py' |
2572 | --- stoqlib/lib/test/test_payment.py 1970-01-01 00:00:00 +0000 |
2573 | +++ stoqlib/lib/test/test_payment.py 2011-02-01 20:17:04 +0000 |
2574 | @@ -0,0 +1,130 @@ |
2575 | +# -*- coding: utf-8 -*- |
2576 | +# vi:si:et:sw=4:sts=4:ts=4 |
2577 | + |
2578 | +## |
2579 | +## Copyright (C) 2008 Async Open Source <http://www.async.com.br> |
2580 | +## All rights reserved |
2581 | +## |
2582 | +## This program is free software; you can redistribute it and/or modify |
2583 | +## it under the terms of the GNU Lesser General Public License as published by |
2584 | +## the Free Software Foundation; either version 2 of the License, or |
2585 | +## (at your option) any later version. |
2586 | +## |
2587 | +## This program is distributed in the hope that it will be useful, |
2588 | +## but WITHOUT ANY WARRANTY; without even the implied warranty of |
2589 | +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2590 | +## GNU General Public License for more details. |
2591 | +## |
2592 | +## You should have received a copy of the GNU Lesser General Public License |
2593 | +## along with this program; if not, write to the Free Software |
2594 | +## Foundation, Inc., or visit: http://www.gnu.org/. |
2595 | +## |
2596 | +## Author(s): Thiago Bellini <hackedbellini@async.com.br> |
2597 | +## |
2598 | +""" Test for stoqlib/lib/payment.py module. """ |
2599 | + |
2600 | +import datetime |
2601 | +from decimal import Decimal |
2602 | + |
2603 | +from stoqlib.domain.test.domaintest import DomainTest |
2604 | +from stoqlib.lib.defaults import (INTERVALTYPE_YEAR, INTERVALTYPE_MONTH, |
2605 | + INTERVALTYPE_WEEK, INTERVALTYPE_DAY) |
2606 | +from stoqlib.lib.payment import (generate_payments_due_dates, |
2607 | + generate_payments_values) |
2608 | + |
2609 | + |
2610 | + |
2611 | +class TestPaymentFunctions(DomainTest): |
2612 | + """"A class for testing the functions on lib/payment.py |
2613 | + """ |
2614 | + |
2615 | + def testGeneratePaymentsDueDates(self): |
2616 | + # Test 1 |
2617 | + due_date = datetime.date(year=2010, month=4, day=1) |
2618 | + due_dates = generate_payments_due_dates(5, due_date, 1, |
2619 | + INTERVALTYPE_MONTH) |
2620 | + expected = [datetime.date(2010, 4, 1), |
2621 | + datetime.date(2010, 5, 1), |
2622 | + datetime.date(2010, 6, 1), |
2623 | + datetime.date(2010, 7, 1), |
2624 | + datetime.date(2010, 8, 1)] |
2625 | + self.assertEqual(due_dates, expected) |
2626 | + self.assertEqual(len(due_dates), 5) |
2627 | + self.assertEqual(due_dates[0], due_date) |
2628 | + for t in due_dates[1:]: |
2629 | + self.failUnless(t > due_date) |
2630 | + |
2631 | + # Test 2 |
2632 | + due_date = datetime.date(year=2010, month=1, day=31) |
2633 | + due_dates = generate_payments_due_dates(10, due_date, 2, |
2634 | + INTERVALTYPE_WEEK) |
2635 | + expected = [datetime.date(2010, 1, 31), |
2636 | + datetime.date(2010, 2, 14), |
2637 | + datetime.date(2010, 2, 28), |
2638 | + datetime.date(2010, 3, 14), |
2639 | + datetime.date(2010, 3, 28), |
2640 | + datetime.date(2010, 4, 11), |
2641 | + datetime.date(2010, 4, 25), |
2642 | + datetime.date(2010, 5, 9), |
2643 | + datetime.date(2010, 5, 23), |
2644 | + datetime.date(2010, 6, 6)] |
2645 | + self.assertEqual(due_dates, expected) |
2646 | + self.assertEqual(len(due_dates), 10) |
2647 | + self.assertEqual(due_dates[0], due_date) |
2648 | + for t in due_dates[1:]: |
2649 | + self.failUnless(t > due_date) |
2650 | + |
2651 | + # Test 3 |
2652 | + due_date = due_date = datetime.date(year=2011, month=3, day=14) |
2653 | + due_dates = generate_payments_due_dates(3, due_date, 10, |
2654 | + INTERVALTYPE_DAY) |
2655 | + expected = [datetime.date(2011, 3, 14), |
2656 | + datetime.date(2011, 3, 24), |
2657 | + datetime.date(2011, 4, 3)] |
2658 | + self.assertEqual(due_dates, expected) |
2659 | + self.assertEqual(len(due_dates), 3) |
2660 | + self.assertEqual(due_dates[0], due_date) |
2661 | + for t in due_dates[1:]: |
2662 | + self.failUnless(t > due_date) |
2663 | + |
2664 | + # Test 4 |
2665 | + due_date = due_date = datetime.date(year=2012, month=12, day=31) |
2666 | + due_dates = generate_payments_due_dates(4, due_date, 2, |
2667 | + INTERVALTYPE_YEAR) |
2668 | + expected = [datetime.date(2012, 12, 31), |
2669 | + datetime.date(2014, 12, 31), |
2670 | + datetime.date(2016, 12, 31), |
2671 | + datetime.date(2018, 12, 31)] |
2672 | + self.assertEqual(due_dates, expected) |
2673 | + self.assertEqual(len(due_dates), 4) |
2674 | + self.assertEqual(due_dates[0], due_date) |
2675 | + for t in due_dates[1:]: |
2676 | + self.failUnless(t > due_date) |
2677 | + |
2678 | + # Test 5 |
2679 | + due_date = due_date = datetime.date(year=2010, month=1, day=1) |
2680 | + self.assertRaises(AssertionError, generate_payments_due_dates, 0, |
2681 | + due_date, 1, INTERVALTYPE_YEAR) |
2682 | + |
2683 | + def testGeneratePaymentsValues(self): |
2684 | + # Test 1 |
2685 | + values = generate_payments_values(Decimal(101), 3) |
2686 | + expected = [Decimal('33.67'), Decimal('33.67'), Decimal('33.66')] |
2687 | + self.assertEqual(values, expected) |
2688 | + self.assertEqual(len(values), 3) |
2689 | + |
2690 | + self.assertEqual(sum(values), Decimal(101)) |
2691 | + |
2692 | + # Test 2 |
2693 | + values = generate_payments_values(Decimal('10.5'), 5, |
2694 | + Decimal('1')) |
2695 | + expected = [Decimal('2.12'), Decimal('2.12'), Decimal('2.12'), |
2696 | + Decimal('2.12'), Decimal('2.12')] |
2697 | + self.assertEqual(values, expected) |
2698 | + self.assertEqual(len(values), 5) |
2699 | + |
2700 | + self.assertEqual(sum(values), (Decimal('10.5') + Decimal('0.10'))) |
2701 | + |
2702 | + # Test 3 |
2703 | + self.assertRaises(AssertionError, generate_payments_values, |
2704 | + Decimal('2'), 0) |
Alguns ultimos comentários:
(MoneyMethodSla ve|StoreCreditM ethodSlave) .create_ model fazem a mesma coisa que o BasePaymentMeth odSlave. create_ model. Eles não precisam mais ser declarados.
def after_installme nts_number_ _changed( self, *args): installments_ number > 1
+ has_installments = self.model.
Espaço em branco a mais depois do =
=== added file 'stoqlib/ lib/test/ test_payment. py' www.async. com.br>
+## Copyright (C) 2008 Async Open Source <http://
+## All rights reserved
Copyright 2011
Não gostei muito como os testes ficaram. Achei eles meio difíceis de ler.
Algo assim fica mais legível:
first_due_date = datetime. date(year= 2010, month=4, day=1) payments_ due_dates( 5, first_due_date, 1, INTERVALTYPE_MONTH) due_dates = [datetime. date(2010, 4, 1), ..., datetime.date(2010, 8, 1)]
due_dates = generate_
expected_
self. assertEqual( due_dates, expected_due_dates)
Tem outros aspectos que vc pode testar também. Como:
self. assertEqual( len(due_ dates), 5)
E nos testes, vc só adicionou para mês e semana, faltou também para dias e anos.
A mesma coisa para o teste dos valores.
Vc pode testar também: se a quantidade está certa, a soma dos valores deves ser igual ao total original informado, no caso de informar os juros, tem que verificar se o calculo está certo também.
Corrige esses detalhes e antes de fazer esse último commit, me chama para eu ver como ficaram os testes. Que vou explicar como deve ser feito esse merge.