Merge lp:~bellini666/stoqlib/closed_product into lp:~stoq-dev/stoqlib/master
- closed_product
- Merge into master
Status: | Merged |
---|---|
Merged at revision: | 3331 |
Proposed branch: | lp:~bellini666/stoqlib/closed_product |
Merge into: | lp:~stoq-dev/stoqlib/master |
Diff against target: |
364 lines (+206/-23) 7 files modified
external/sqlobject/viewable.py (+1/-1) stoqlib/domain/sellable.py (+17/-0) stoqlib/domain/test/test_sellable.py (+52/-0) stoqlib/domain/views.py (+16/-3) stoqlib/gui/editors/sellableeditor.py (+59/-13) stoqlib/gui/search/productsearch.py (+49/-4) stoqlib/reporting/product.py (+12/-2) |
To merge this branch: | bzr merge lp:~bellini666/stoqlib/closed_product |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ronaldo Maia | Pending | ||
Review via email: mp+50754@code.launchpad.net |
Commit message
Description of the change
Opção de ter produtos inativos.
Correções para o #4304
- 3321. By Thiago Bellini
-
Quick Fix: Correcting a traceback on POS app when checkout payment method was 'check' or 'bill'
- 3322. By Thiago Bellini
-
Quick fix: Hope this will fix all problems when using a payment slave.
- 3323. By Gabriel Gerga
-
Exportar vendas a vista para NF-e. r=romaia
- 3324. By Ronaldo Maia
-
Viewable select results didn't include objects created inside a transaction,
even when selecting from that transaction.Fix a test afected by this
- 3325. By Ronaldo Maia
-
Update a few report tests pdfs
- 3326. By Thiago Bellini
-
Make the labels of the 'yesno' dialog buttons more useful.
- 3327. By Gabriel Gerga
-
Corrected values used in payments editor according freight, surcharge and discount. r=romaia
- 3328. By Thiago Bellini
-
Quick Fix: Forgot a closing ')' on sellableeditor. Sorry! :(
- 3329. By Ronaldo Maia
-
Adicionando suporte experimental para boletos bancários
- Importando Projeto Pyboleto (com algumas mudanças nosssas)
- Adicionando opção de imprimir boletos (no formato carnê) a partir dos
detalhes de uma venda - 3335. By Thiago Bellini
-
Removing the editor from Closed Products Search and code adjustments.
- 3336. By Thiago Bellini
-
Code corrections.
- 3337. By Thiago Bellini
-
Add tests for new methods and views.
- 3338. By Thiago Bellini
-
Code corrections.
- 3339. By Thiago Bellini
-
More code corrections.
Preview Diff
1 | === modified file 'external/sqlobject/viewable.py' | |||
2 | --- external/sqlobject/viewable.py 2011-02-28 15:29:21 +0000 | |||
3 | +++ external/sqlobject/viewable.py 2011-03-04 18:09:29 +0000 | |||
4 | @@ -149,7 +149,7 @@ | |||
5 | 149 | 149 | ||
6 | 150 | setup_attributes(cls, new_attrs) | 150 | setup_attributes(cls, new_attrs) |
7 | 151 | 151 | ||
9 | 152 | columns = new_attrs['columns'] | 152 | columns = new_attrs.get('columns', getattr(cls, 'columns', None)) |
10 | 153 | if not columns: | 153 | if not columns: |
11 | 154 | return | 154 | return |
12 | 155 | 155 | ||
13 | 156 | 156 | ||
14 | === modified file 'stoqlib/domain/sellable.py' | |||
15 | --- stoqlib/domain/sellable.py 2011-02-08 14:06:58 +0000 | |||
16 | +++ stoqlib/domain/sellable.py 2011-03-04 18:09:29 +0000 | |||
17 | @@ -378,6 +378,10 @@ | |||
18 | 378 | 378 | ||
19 | 379 | commission = property(_get_commission, _set_commission) | 379 | commission = property(_get_commission, _set_commission) |
20 | 380 | 380 | ||
21 | 381 | # | ||
22 | 382 | # Accessors | ||
23 | 383 | # | ||
24 | 384 | |||
25 | 381 | def can_be_sold(self): | 385 | def can_be_sold(self): |
26 | 382 | """Whether the sellable is available and can be sold. | 386 | """Whether the sellable is available and can be sold. |
27 | 383 | @returns: if the item can be sold | 387 | @returns: if the item can be sold |
28 | @@ -401,6 +405,19 @@ | |||
29 | 401 | raise ValueError('This sellable is already unavailable') | 405 | raise ValueError('This sellable is already unavailable') |
30 | 402 | self.status = self.STATUS_UNAVAILABLE | 406 | self.status = self.STATUS_UNAVAILABLE |
31 | 403 | 407 | ||
32 | 408 | def is_closed(self): | ||
33 | 409 | """Whether the sellable is closed or not. | ||
34 | 410 | |||
35 | 411 | @returns: True if closed, False otherwise. | ||
36 | 412 | """ | ||
37 | 413 | return self.status == Sellable.STATUS_CLOSED | ||
38 | 414 | |||
39 | 415 | def close(self): | ||
40 | 416 | """Mark the sellable as closed""" | ||
41 | 417 | if self.is_closed(): | ||
42 | 418 | raise ValueError('This sellable is already closed') | ||
43 | 419 | self.status = Sellable.STATUS_CLOSED | ||
44 | 420 | |||
45 | 404 | def cancel(self): | 421 | def cancel(self): |
46 | 405 | """Cancel the sellable""" | 422 | """Cancel the sellable""" |
47 | 406 | if self.can_be_sold(): | 423 | if self.can_be_sold(): |
48 | 407 | 424 | ||
49 | === modified file 'stoqlib/domain/test/test_sellable.py' | |||
50 | --- stoqlib/domain/test/test_sellable.py 2011-02-08 14:06:58 +0000 | |||
51 | +++ stoqlib/domain/test/test_sellable.py 2011-03-04 18:09:29 +0000 | |||
52 | @@ -29,6 +29,9 @@ | |||
53 | 29 | SellableCategory) | 29 | SellableCategory) |
54 | 30 | from stoqlib.domain.product import Product | 30 | from stoqlib.domain.product import Product |
55 | 31 | from stoqlib.domain.test.domaintest import DomainTest | 31 | from stoqlib.domain.test.domaintest import DomainTest |
56 | 32 | from stoqlib.domain.views import (ProductFullStockView, | ||
57 | 33 | ProductFullWithClosedStockView, | ||
58 | 34 | ProductClosedStockView) | ||
59 | 32 | 35 | ||
60 | 33 | 36 | ||
61 | 34 | class TestSellableCategory(DomainTest): | 37 | class TestSellableCategory(DomainTest): |
62 | @@ -230,3 +233,52 @@ | |||
63 | 230 | constant3 = self.create_sellable_tax_constant() | 233 | constant3 = self.create_sellable_tax_constant() |
64 | 231 | sellable.tax_constant = constant3 | 234 | sellable.tax_constant = constant3 |
65 | 232 | self.assertEquals(sellable.get_tax_constant(), constant3) | 235 | self.assertEquals(sellable.get_tax_constant(), constant3) |
66 | 236 | |||
67 | 237 | def testClose(self): | ||
68 | 238 | results_not_closed = ProductFullStockView.select(connection=self.trans) | ||
69 | 239 | results_with_closed = ProductFullWithClosedStockView.select( | ||
70 | 240 | connection=self.trans) | ||
71 | 241 | results_only_closed = ProductClosedStockView.select( | ||
72 | 242 | connection=self.trans) | ||
73 | 243 | # Count the already there results. ProductClosedStockView should | ||
74 | 244 | # not have any. | ||
75 | 245 | # obs. Using len(list(res)) instead of res.count() because of a bug | ||
76 | 246 | # on sqlobject that returns wrong count() on that views. | ||
77 | 247 | count_not_closed = len(list(results_not_closed)) | ||
78 | 248 | count_with_closed = len(list(results_with_closed)) | ||
79 | 249 | count_only_closed = len(list(results_only_closed)) | ||
80 | 250 | self.assertEqual(count_only_closed, 0) | ||
81 | 251 | |||
82 | 252 | # Here we create a sellable. It should show on | ||
83 | 253 | # ProductFullStockView and ProductFullWithClosedStock View, | ||
84 | 254 | # but not on ProductClosedStockView. | ||
85 | 255 | sellable = self.create_sellable() | ||
86 | 256 | self.assertEqual(len(list(results_not_closed)), count_not_closed + 1L) | ||
87 | 257 | self.assertEqual(len(list(results_with_closed)), count_with_closed + 1L) | ||
88 | 258 | self.assertEqual(len(list(results_only_closed)), count_only_closed) | ||
89 | 259 | ids = [result.id for result in results_not_closed] | ||
90 | 260 | self.failIf(sellable.id not in ids) | ||
91 | 261 | ids = [result.id for result in results_with_closed] | ||
92 | 262 | self.failIf(sellable.id not in ids) | ||
93 | 263 | ids = [result.id for result in results_only_closed] | ||
94 | 264 | self.failIf(sellable.id in ids) | ||
95 | 265 | |||
96 | 266 | # Here we close that sellable. It should now show on | ||
97 | 267 | # ProductClosedStockViewand ProductFullWithClosedStock View, | ||
98 | 268 | # but not on ProductFullStockView. | ||
99 | 269 | sellable.close() | ||
100 | 270 | self.assertEquals(sellable.status, Sellable.STATUS_CLOSED) | ||
101 | 271 | self.assertTrue(sellable.is_closed()) | ||
102 | 272 | self.assertEqual(len(list(results_not_closed)), count_not_closed) | ||
103 | 273 | self.assertEqual(len(list(results_with_closed)), count_with_closed + 1L) | ||
104 | 274 | self.assertEqual(len(list(results_only_closed)), count_only_closed + 1L) | ||
105 | 275 | ids = [result.id for result in results_not_closed] | ||
106 | 276 | self.failIf(sellable.id in ids) | ||
107 | 277 | ids = [result.id for result in results_with_closed] | ||
108 | 278 | self.failIf(sellable.id not in ids) | ||
109 | 279 | ids = [result.id for result in results_only_closed] | ||
110 | 280 | self.failIf(sellable.id not in ids) | ||
111 | 281 | |||
112 | 282 | # When trying to close an already closed sellable, it should | ||
113 | 283 | # raise a ValueError. | ||
114 | 284 | self.assertRaises(ValueError, sellable.close) | ||
115 | 233 | 285 | ||
116 | === modified file 'stoqlib/domain/views.py' | |||
117 | --- stoqlib/domain/views.py 2011-02-15 10:21:17 +0000 | |||
118 | +++ stoqlib/domain/views.py 2011-03-04 18:09:29 +0000 | |||
119 | @@ -79,6 +79,8 @@ | |||
120 | 79 | ) | 79 | ) |
121 | 80 | 80 | ||
122 | 81 | joins = [ | 81 | joins = [ |
123 | 82 | INNERJOINOn(None, BaseSellableInfo, | ||
124 | 83 | BaseSellableInfo.q.id == Sellable.q.base_sellable_infoID), | ||
125 | 82 | # Tax Constant | 84 | # Tax Constant |
126 | 83 | LEFTJOINOn(None, SellableTaxConstant, | 85 | LEFTJOINOn(None, SellableTaxConstant, |
127 | 84 | SellableTaxConstant.q.id == Sellable.q.tax_constantID), | 86 | SellableTaxConstant.q.id == Sellable.q.tax_constantID), |
128 | @@ -96,9 +98,7 @@ | |||
129 | 96 | ProductAdaptToStorable.q.id), | 98 | ProductAdaptToStorable.q.id), |
130 | 97 | ] | 99 | ] |
131 | 98 | 100 | ||
135 | 99 | clause = AND( | 101 | clause = Sellable.q.status != Sellable.STATUS_CLOSED |
133 | 100 | BaseSellableInfo.q.id == Sellable.q.base_sellable_infoID, | ||
134 | 101 | ) | ||
136 | 102 | 102 | ||
137 | 103 | @classmethod | 103 | @classmethod |
138 | 104 | def select_by_branch(cls, query, branch, having=None, connection=None): | 104 | def select_by_branch(cls, query, branch, having=None, connection=None): |
139 | @@ -154,6 +154,19 @@ | |||
140 | 154 | return sellable.price | 154 | return sellable.price |
141 | 155 | 155 | ||
142 | 156 | 156 | ||
143 | 157 | class ProductFullWithClosedStockView(ProductFullStockView): | ||
144 | 158 | """Stores information about products, showing the closed ones too. | ||
145 | 159 | """ | ||
146 | 160 | |||
147 | 161 | clause = None | ||
148 | 162 | |||
149 | 163 | class ProductClosedStockView(ProductFullWithClosedStockView): | ||
150 | 164 | """Stores information about products that were closed. | ||
151 | 165 | """ | ||
152 | 166 | |||
153 | 167 | clause = Sellable.q.status == Sellable.STATUS_CLOSED | ||
154 | 168 | |||
155 | 169 | |||
156 | 157 | class ProductComponentView(ProductFullStockView): | 170 | class ProductComponentView(ProductFullStockView): |
157 | 158 | columns = ProductFullStockView.columns | 171 | columns = ProductFullStockView.columns |
158 | 159 | clause = AND(ProductFullStockView.clause, | 172 | clause = AND(ProductFullStockView.clause, |
159 | 160 | 173 | ||
160 | === modified file 'stoqlib/gui/editors/sellableeditor.py' | |||
161 | --- stoqlib/gui/editors/sellableeditor.py 2011-03-02 15:16:10 +0000 | |||
162 | +++ stoqlib/gui/editors/sellableeditor.py 2011-03-04 18:09:29 +0000 | |||
163 | @@ -236,23 +236,34 @@ | |||
164 | 236 | code = u'%d' % self._sellable.id | 236 | code = u'%d' % self._sellable.id |
165 | 237 | self.code.update(code) | 237 | self.code.update(code) |
166 | 238 | self.setup_widgets() | 238 | self.setup_widgets() |
167 | 239 | if model and self._sellable.can_remove(): | ||
168 | 240 | button = self.add_button('Remove', 'gtk-delete') | ||
169 | 241 | button.connect('clicked', self._on_delete_button__activate) | ||
170 | 242 | 239 | ||
171 | 243 | self.set_description( | 240 | self.set_description( |
172 | 244 | self.model.sellable.base_sellable_info.description) | 241 | self.model.sellable.base_sellable_info.description) |
173 | 245 | 242 | ||
184 | 246 | def _on_delete_button__activate(self, button): | 243 | self._setup_delete_close_reopen_button() |
185 | 247 | msg = _(u"This will delete '%s' from the database. Are you sure?" | 244 | |
186 | 248 | % self._sellable.get_description()) | 245 | def _add_extra_button(self, label, stock=None, |
187 | 249 | if not yesno(msg, gtk.RESPONSE_NO, _(u"Delete"), _(u"Don't Delete")): | 246 | callback_func=None, connect_on='clicked'): |
188 | 250 | return | 247 | button = self.add_button(label, stock) |
189 | 251 | 248 | if callback_func: | |
190 | 252 | self._sellable.remove() | 249 | button.connect(connect_on, callback_func, label) |
191 | 253 | # We don't call self.confirm since it will call validate_confirm | 250 | |
192 | 254 | self.cancel() | 251 | def _setup_delete_close_reopen_button(self): |
193 | 255 | self.main_dialog.retval = True | 252 | if self.model and self._sellable.can_remove(): |
194 | 253 | self._add_extra_button(_('Remove'), 'gtk-delete', | ||
195 | 254 | self._on_delete_button__clicked) | ||
196 | 255 | elif self.model and self._sellable.is_unavailable(): | ||
197 | 256 | label = (self._sellable.product and | ||
198 | 257 | _('Close Product') or _('Close Service')) | ||
199 | 258 | |||
200 | 259 | self._add_extra_button(label, None, | ||
201 | 260 | self._on_close_sellable_button__clicked) | ||
202 | 261 | elif self.model and self._sellable.is_closed(): | ||
203 | 262 | label = (self._sellable.product and | ||
204 | 263 | _('Reopen Product') or _('Reopen Service')) | ||
205 | 264 | |||
206 | 265 | self._add_extra_button(label, None, | ||
207 | 266 | self._on_reopen_sellable_button__clicked) | ||
208 | 256 | 267 | ||
209 | 257 | def add_extra_tab(self, tabname, tabslave): | 268 | def add_extra_tab(self, tabname, tabslave): |
210 | 258 | self.sellable_notebook.set_show_tabs(True) | 269 | self.sellable_notebook.set_show_tabs(True) |
211 | @@ -402,6 +413,41 @@ | |||
212 | 402 | # Kiwi handlers | 413 | # Kiwi handlers |
213 | 403 | # | 414 | # |
214 | 404 | 415 | ||
215 | 416 | def _on_delete_button__clicked(self, button, parent_button_label=None): | ||
216 | 417 | msg = _(u"This will delete '%s' from the database. Are you sure?" | ||
217 | 418 | % self._sellable.get_description()) | ||
218 | 419 | if not yesno(msg, gtk.RESPONSE_NO, _(u"Delete"), _(u"Don't Delete")): | ||
219 | 420 | return | ||
220 | 421 | |||
221 | 422 | self._sellable.remove() | ||
222 | 423 | # We don't call self.confirm since it will call validate_confirm | ||
223 | 424 | self.cancel() | ||
224 | 425 | self.main_dialog.retval = True | ||
225 | 426 | |||
226 | 427 | def _on_close_sellable_button__clicked(self, button, | ||
227 | 428 | parent_button_label=None): | ||
228 | 429 | msg = _(u"Do you really want to close '%s'?\n" | ||
229 | 430 | u"Please note that when it's closed, you won't be able to " | ||
230 | 431 | u"commercialize it anymore." % self._sellable.get_description()) | ||
231 | 432 | if not yesno(msg, gtk.RESPONSE_NO, | ||
232 | 433 | parent_button_label, _(u"Don't Close")): | ||
233 | 434 | return | ||
234 | 435 | |||
235 | 436 | self._sellable.close() | ||
236 | 437 | self.confirm() | ||
237 | 438 | |||
238 | 439 | def _on_reopen_sellable_button__clicked(self, button, | ||
239 | 440 | parent_button_label=None): | ||
240 | 441 | msg = _(u"Do you really want to reopen '%s'?\n" | ||
241 | 442 | u"Note that when it's opened, you will be able to " | ||
242 | 443 | u"commercialize it again." % self._sellable.get_description()) | ||
243 | 444 | if not yesno(msg, gtk.RESPONSE_NO, | ||
244 | 445 | parent_button_label, _(u"Keep Closed")): | ||
245 | 446 | return | ||
246 | 447 | |||
247 | 448 | self._sellable.set_unavailable() | ||
248 | 449 | self.confirm() | ||
249 | 450 | |||
250 | 405 | def on_tax_constant__changed(self, combo): | 451 | def on_tax_constant__changed(self, combo): |
251 | 406 | self._update_tax_value() | 452 | self._update_tax_value() |
252 | 407 | 453 | ||
253 | 408 | 454 | ||
254 | === modified file 'stoqlib/gui/search/productsearch.py' | |||
255 | --- stoqlib/gui/search/productsearch.py 2011-02-15 10:21:17 +0000 | |||
256 | +++ stoqlib/gui/search/productsearch.py 2011-03-04 18:09:29 +0000 | |||
257 | @@ -37,7 +37,9 @@ | |||
258 | 37 | from stoqlib.domain.product import Product | 37 | from stoqlib.domain.product import Product |
259 | 38 | from stoqlib.domain.sellable import Sellable | 38 | from stoqlib.domain.sellable import Sellable |
260 | 39 | from stoqlib.domain.views import (ProductFullStockView, ProductQuantityView, | 39 | from stoqlib.domain.views import (ProductFullStockView, ProductQuantityView, |
262 | 40 | ProductFullStockItemView, SoldItemView) | 40 | ProductFullStockItemView, SoldItemView, |
263 | 41 | ProductFullWithClosedStockView, | ||
264 | 42 | ProductClosedStockView) | ||
265 | 41 | from stoqlib.gui.base.dialogs import run_dialog | 43 | from stoqlib.gui.base.dialogs import run_dialog |
266 | 42 | from stoqlib.gui.base.gtkadds import change_button_appearance | 44 | from stoqlib.gui.base.gtkadds import change_button_appearance |
267 | 43 | from stoqlib.gui.base.search import (SearchDialog, SearchEditor, | 45 | from stoqlib.gui.base.search import (SearchDialog, SearchEditor, |
268 | @@ -50,8 +52,8 @@ | |||
269 | 50 | from stoqlib.lib.translation import stoqlib_gettext | 52 | from stoqlib.lib.translation import stoqlib_gettext |
270 | 51 | from stoqlib.lib.validators import format_quantity, get_formatted_cost | 53 | from stoqlib.lib.validators import format_quantity, get_formatted_cost |
271 | 52 | from stoqlib.reporting.product import (ProductReport, ProductQuantityReport, | 54 | from stoqlib.reporting.product import (ProductReport, ProductQuantityReport, |
274 | 53 | ProductPriceReport, | 55 | ProductClosedStockReport, |
275 | 54 | ProductStockReport, | 56 | ProductPriceReport, ProductStockReport, |
276 | 55 | ProductsSoldReport) | 57 | ProductsSoldReport) |
277 | 56 | 58 | ||
278 | 57 | _ = stoqlib_gettext | 59 | _ = stoqlib_gettext |
279 | @@ -61,7 +63,7 @@ | |||
280 | 61 | title = _('Product Search') | 63 | title = _('Product Search') |
281 | 62 | table = Product | 64 | table = Product |
282 | 63 | size = (775, 450) | 65 | size = (775, 450) |
284 | 64 | search_table = ProductFullStockView | 66 | search_table = ProductFullWithClosedStockView |
285 | 65 | editor_class = ProductEditor | 67 | editor_class = ProductEditor |
286 | 66 | footer_ok_label = _('Add products') | 68 | footer_ok_label = _('Add products') |
287 | 67 | searchbar_result_strings = (_('product'), _('products')) | 69 | searchbar_result_strings = (_('product'), _('products')) |
288 | @@ -413,3 +415,46 @@ | |||
289 | 413 | if branch is not None: | 415 | if branch is not None: |
290 | 414 | branch = PersonAdaptToBranch.get(branch, connection=conn) | 416 | branch = PersonAdaptToBranch.get(branch, connection=conn) |
291 | 415 | return self.table.select_by_branch(query, branch, connection=conn) | 417 | return self.table.select_by_branch(query, branch, connection=conn) |
292 | 418 | |||
293 | 419 | |||
294 | 420 | class ProductClosedStockSearch(ProductSearch): | ||
295 | 421 | """A SearchEditor for Closed Products""" | ||
296 | 422 | |||
297 | 423 | title = _('Closed Product Stock Search') | ||
298 | 424 | table = search_table = ProductClosedStockView | ||
299 | 425 | has_new_button = False | ||
300 | 426 | |||
301 | 427 | def __init__(self, conn, hide_footer=True, hide_toolbar=True, | ||
302 | 428 | selection_mode=gtk.SELECTION_BROWSE, | ||
303 | 429 | hide_cost_column=True, use_product_statuses=None, | ||
304 | 430 | hide_price_column=True): | ||
305 | 431 | ProductSearch.__init__(self, conn, hide_footer, hide_toolbar, | ||
306 | 432 | selection_mode, hide_cost_column, | ||
307 | 433 | use_product_statuses, hide_price_column) | ||
308 | 434 | |||
309 | 435 | def create_filters(self): | ||
310 | 436 | self.set_text_field_columns(['description', 'barcode', | ||
311 | 437 | 'category_description']) | ||
312 | 438 | self.executer.set_query(self.executer_query) | ||
313 | 439 | |||
314 | 440 | # Branch | ||
315 | 441 | branch_filter = self.create_branch_filter(_('In branch:')) | ||
316 | 442 | branch_filter.select(None) | ||
317 | 443 | self.add_filter(branch_filter, columns=[]) | ||
318 | 444 | self.branch_filter = branch_filter | ||
319 | 445 | |||
320 | 446 | def _setup_print_slave(self): | ||
321 | 447 | pass | ||
322 | 448 | |||
323 | 449 | def _has_rows(self, results, obj): | ||
324 | 450 | SearchEditor._has_rows(self, results, obj) | ||
325 | 451 | |||
326 | 452 | # | ||
327 | 453 | # SearchDialog Hooks | ||
328 | 454 | # | ||
329 | 455 | |||
330 | 456 | def on_print_button_clicked(self, widget): | ||
331 | 457 | print_report(ProductClosedStockReport, self.results, | ||
332 | 458 | filters=self.search.get_search_filters(), | ||
333 | 459 | branch_name=self.branch_filter.combo.get_active_text()) | ||
334 | 460 | |||
335 | 416 | 461 | ||
336 | === modified file 'stoqlib/reporting/product.py' | |||
337 | --- stoqlib/reporting/product.py 2011-02-15 10:21:17 +0000 | |||
338 | +++ stoqlib/reporting/product.py 2011-03-04 18:09:29 +0000 | |||
339 | @@ -32,9 +32,9 @@ | |||
340 | 32 | from stoqlib.lib.validators import format_quantity, get_formatted_price | 32 | from stoqlib.lib.validators import format_quantity, get_formatted_price |
341 | 33 | from stoqlib.lib.translation import stoqlib_gettext as _ | 33 | from stoqlib.lib.translation import stoqlib_gettext as _ |
342 | 34 | from stoqlib.domain.product import ProductHistory | 34 | from stoqlib.domain.product import ProductHistory |
344 | 35 | from stoqlib.domain.views import (ProductFullStockView, | 35 | from stoqlib.domain.views import (SoldItemView, ProductFullStockView, |
345 | 36 | ProductFullStockItemView, | 36 | ProductFullStockItemView, |
347 | 37 | SoldItemView) | 37 | ProductClosedStockView) |
348 | 38 | 38 | ||
349 | 39 | 39 | ||
350 | 40 | class ProductReport(ObjectListReport): | 40 | class ProductReport(ObjectListReport): |
351 | @@ -237,3 +237,13 @@ | |||
352 | 237 | 237 | ||
353 | 238 | self.add_object_table(self._stock_products, self.get_columns(), | 238 | self.add_object_table(self._stock_products, self.get_columns(), |
354 | 239 | summary_row=self.get_summary_row()) | 239 | summary_row=self.get_summary_row()) |
355 | 240 | |||
356 | 241 | |||
357 | 242 | class ProductClosedStockReport(ProductStockReport): | ||
358 | 243 | report_name = _("Closed Product Stock Report") | ||
359 | 244 | main_object_name = _("closed products") | ||
360 | 245 | obj_type = ProductClosedStockView | ||
361 | 246 | |||
362 | 247 | def _setup_table(self): | ||
363 | 248 | self.add_object_table(self._stock_products, self.get_columns(), | ||
364 | 249 | summary_row=self.get_summary_row()) |