class FinancialReportDialog(BasicDialog): title = _("Financial Report Dialog") def __init__(self, store): self.store = store self.date_filter = DateSearchFilter(_("Year:")) self.date_filter.clear_options() self._populate_date_filter(self.date_filter) self.date_filter.select() self.date_filter.set_use_date_entries(False) BasicDialog.__init__(self, title=self.title) self.main_label.set_justify(gtk.JUSTIFY_CENTER) self.ok_button.set_label(_("Generate")) self.add(self.date_filter) self.date_filter.show() def confirm(self): start = self.date_filter.get_start_date() if start is None: warning(_("There are no transactions yet")) return f = FinancialIntervalReport(self.store, start.year) if not f.run(): return temporary = tempfile.NamedTemporaryFile( # Translators: This will be part of a filename prefix=_("stoq-yearly-report"), suffix=".xls", delete=False, ) f.write(temporary) sse = SpreadSheetExporter() sse.export_temporary(temporary) self.close() self.temporary = temporary # # Private # def _populate_date_filter(self, date_filter): transaction = self.store.find(AccountTransaction).order_by(AccountTransaction.date).first() if transaction is None: return for i in range(transaction.date.year, localtoday().year + 1): year = datetime.datetime(i, 1, 1) date_filter.add_option_fixed_interval(_("Year %d") % (i,), year, year.replace(month=12, day=31), position=0) def _date_filter_query(self, search_spec, column): executer = QueryExecuter(self.store) executer.set_filter_columns(self.date_filter, [column]) executer.set_search_spec(search_spec) return executer.search([self.date_filter.get_state()])
class TransactionPage(object): # shows either a list of: # - transactions # - payments def __init__(self, model, app, parent): self.model = model self.app = app self.parent_window = parent self._block = False self._create_search() self._add_date_filter() self._setup_search() self.refresh() def get_toplevel(self): return self.parent_window def _create_search(self): self.search = SearchSlave(self._get_columns(self.model.kind), store=self.app.store) self.search.connect('result-item-activated', self._on_search__item_activated) self.search.enable_advanced_search() self.search.set_result_view(FinancialSearchResults) self.result_view = self.search.result_view self.result_view.page = self tree_view = self.search.result_view.get_treeview() tree_view.set_rules_hint(True) tree_view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) def _add_date_filter(self): self.date_filter = DateSearchFilter(_('Date:')) self.date_filter.clear_options() self.date_filter.add_option(Any, 0) year = datetime.datetime.today().year month_names = get_month_names() for i, month in enumerate(month_names): name = month_names[i] option = type(name + 'Option', (MonthOption, ), {'name': _(name), 'month': i + 1, 'year': year}) self.date_filter.add_option(option, i + 1) self.date_filter.add_custom_options() self.date_filter.mode.select_item_by_position(0) self.search.add_filter(self.date_filter) def _append_date_query(self, field): date = self.date_filter.get_state() queries = [] if isinstance(date, DateQueryState) and date.date is not None: queries.append(Date(field) == date.date) elif isinstance(date, DateIntervalQueryState): queries.append(Date(field) >= date.start) queries.append(Date(field) <= date.end) return queries def _payment_query(self, store): executer = self.search.get_query_executer() search_spec = executer.search_spec queries = self._append_date_query(search_spec.due_date) if queries: return store.find(search_spec, And(*queries)) return store.find(search_spec) def _transaction_query(self, store): queries = [Or(self.model.id == AccountTransaction.account_id, self.model.id == AccountTransaction.source_account_id)] queries.extend(self._append_date_query(AccountTransaction.date)) return store.find(AccountTransactionView, And(*queries)) def show(self): self.search.show() def _setup_search(self): if self.model.kind == 'account': self.search.set_search_spec(AccountTransactionView) self.search.set_text_field_columns(['description']) self.search.set_query(self._transaction_query) elif self.model.kind == 'payable': self.search.set_text_field_columns(['description', 'supplier_name']) self.search.set_search_spec(OutPaymentView) self.search.set_query(self._payment_query) elif self.model.kind == 'receivable': self.search.set_text_field_columns(['description', 'drawee']) self.search.set_search_spec(InPaymentView) self.search.set_query(self._payment_query) else: raise TypeError("unknown model kind: %r" % (self.model.kind, )) def refresh(self): self.search.result_view.clear() if self.model.kind == 'account': transactions = AccountTransactionView.get_for_account(self.model, self.app.store) self.append_transactions(transactions) elif self.model.kind == 'payable': self._populate_payable_payments(OutPaymentView) elif self.model.kind == 'receivable': self._populate_payable_payments(InPaymentView) else: raise TypeError("unknown model kind: %r" % (self.model.kind, )) def _get_columns(self, kind): if kind in ['payable', 'receivable']: return self._get_payment_columns() else: return self._get_account_columns() def _get_account_columns(self): def format_withdrawal(value): if value < 0: return currency(abs(value)).format(symbol=True, precision=2) def format_deposit(value): if value > 0: return currency(value).format(symbol=True, precision=2) if self.model.account_type == Account.TYPE_INCOME: color_func = lambda x: False else: color_func = lambda x: x < 0 return [Column('date', title=_("Date"), data_type=datetime.date, sorted=True), Column('code', title=_("Code"), data_type=unicode), Column('description', title=_("Description"), data_type=unicode, expand=True), Column('account', title=_("Account"), data_type=unicode), Column('value', title=self.model.account.get_type_label(out=False), data_type=currency, format_func=format_deposit), Column('value', title=self.model.account.get_type_label(out=True), data_type=currency, format_func=format_withdrawal), ColoredColumn('total', title=_("Total"), data_type=currency, color='red', data_func=color_func)] def _get_payment_columns(self): return [SearchColumn('due_date', title=_("Due date"), data_type=datetime.date, sorted=True), IdentifierColumn('identifier', title=_("Code")), SearchColumn('description', title=_("Description"), data_type=unicode, expand=True), SearchColumn('value', title=_("Value"), data_type=currency)] def append_transactions(self, transactions): for transaction in transactions: description = transaction.get_account_description(self.model) value = transaction.get_value(self.model) self._add_transaction(transaction, description, value) self.update_totals() def _populate_payable_payments(self, view_class): for view in self.app.store.find(view_class): self.search.result_view.append(view) def _add_transaction(self, transaction, description, value): item = Settable(transaction=transaction) self._update_transaction(item, transaction, description, value) self.search.result_view.append(item) return item def _update_transaction(self, item, transaction, description, value): item.account = description item.date = transaction.date item.description = transaction.description item.value = value item.code = transaction.code def update_totals(self): total = decimal.Decimal('0') for item in self.search.result_view: total += item.value item.total = total def _edit_transaction_dialog(self, item): store = api.new_store() if isinstance(item.transaction, AccountTransactionView): account_transaction = store.fetch(item.transaction.transaction) else: account_transaction = store.fetch(item.transaction) model = getattr(self.model, 'account', self.model) transaction = run_dialog(AccountTransactionEditor, self.app, store, account_transaction, model) if transaction: store.flush() self._update_transaction(item, transaction, transaction.edited_account.description, transaction.value) self.update_totals() self.search.result_view.update(item) self.app.accounts.refresh_accounts(self.app.store) store.confirm(transaction) store.close() def on_dialog__opened(self, dialog): dialog.connect('account-added', self.on_dialog__account_added) def on_dialog__account_added(self, dialog): self.app.accounts.refresh_accounts(self.app.store) def add_transaction_dialog(self): store = api.new_store() model = getattr(self.model, 'account', self.model) model = store.fetch(model) transaction = run_dialog(AccountTransactionEditor, self.app, store, None, model) if transaction: transaction.sync() value = transaction.value other = transaction.get_other_account(model) if other == model: value = -value item = self._add_transaction(transaction, other.description, value) self.update_totals() self.search.result_view.update(item) self.app.accounts.refresh_accounts(self.app.store) store.confirm(transaction) store.close() def _on_search__item_activated(self, objectlist, item): if self.model.kind == 'account': self._edit_transaction_dialog(item)
class SintegraDialog(BasicDialog): title = _('Fiscal Printer History') def __init__(self, store): BasicDialog.__init__(self, title=self.title) self.main_label.set_justify(gtk.JUSTIFY_CENTER) self.store = store self.ok_button.set_label(_("Generate")) self.date_filter = DateSearchFilter(_('Month:')) self.date_filter.set_use_date_entries(False) self.date_filter.clear_options() self._populate_date_filter(self.date_filter) self.date_filter.select() self.add(self.date_filter) self.date_filter.show() def confirm(self): start = self.date_filter.get_start_date() end = self.date_filter.get_end_date() filename = save(_("Save Sintegra file"), self.get_toplevel(), "sintegra-%s.txt" % (start.strftime('%Y-%m'), )) if not filename: return try: generator = StoqlibSintegraGenerator(self.store, start, end) generator.write(filename) except SintegraError as e: warning(str(e)) return self.close() # # Private # def _populate_date_filter(self, date_filter): # The options we want to show to the users are the following: # 'May 2007' # 'June 2007' # ... # 'September 2008' initial_date = self.store.find(SystemTable).min( SystemTable.updated).date() # Start is the first day of the month # End is the last day of the month start = initial_date + relativedelta(day=1) end = localtoday().date() + relativedelta(day=31) intervals = [] while start < end: intervals.append((start, start + relativedelta(day=31))) start = start + relativedelta(months=1) # When we have the list of intervals, add them to the list and # make sure that they are translated month_names = get_month_names() for start, end in intervals: # Translators: Do not translate 'month' and 'year'. You can # change it's positions. In the way it is, # it will product for example 'December 2012' name = _('{month} {year}').format(month=month_names[start.month - 1], year=start.year) date_filter.add_option_fixed_interval(name, start, end, position=0) def _date_filter_query(self, search_spec, column): executer = QueryExecuter(self.store) executer.set_filter_columns(self.date_filter, [column]) executer.set_table(search_spec) return executer.search([self.date_filter.get_state()])
class SintegraDialog(BasicDialog): title = _('Fiscal Printer History') def __init__(self, store): BasicDialog.__init__(self, title=self.title) self.justify_label(gtk.JUSTIFY_CENTER) self.store = store self.ok_button.set_label(_("Generate")) self.date_filter = DateSearchFilter(_('Month:')) self.date_filter.set_use_date_entries(False) self.date_filter.clear_options() self._populate_date_filter(self.date_filter) self.date_filter.select() self.add(self.date_filter) self.date_filter.show() def confirm(self): start = self.date_filter.get_start_date() end = self.date_filter.get_end_date() filename = save(_("Save Sintegra file"), self.get_toplevel(), "sintegra-%s.txt" % (start.strftime('%Y-%m'), )) if not filename: return try: generator = StoqlibSintegraGenerator(self.store, start, end) generator.write(filename) except SintegraError as e: warning(str(e)) return self.close() # # Private # def _populate_date_filter(self, date_filter): # The options we want to show to the users are the following: # 'May 2007' # 'June 2007' # ... # 'September 2008' initial_date = self.store.find(SystemTable).min( SystemTable.updated).date() # Start is the first day of the month # End is the last day of the month start = initial_date + relativedelta(day=1) end = localtoday().date() + relativedelta(day=31) intervals = [] while start < end: intervals.append((start, start + relativedelta(day=31))) start = start + relativedelta(months=1) # When we have the list of intervals, add them to the list and # make sure that they are translated month_names = get_month_names() for start, end in intervals: # Translators: Do not translate 'month' and 'year'. You can # change it's positions. In the way it is, # it will product for example 'December 2012' name = _('{month} {year}').format( month=month_names[start.month - 1], year=start.year) date_filter.add_option_fixed_interval( name, start, end, position=0) def _date_filter_query(self, search_table, column): executer = QueryExecuter(self.store) executer.set_filter_columns(self.date_filter, [column]) executer.set_table(search_table) return executer.search([self.date_filter.get_state()])
class FinancialReportDialog(BasicDialog): title = _('Financial Report Dialog') def __init__(self, store): self.store = store self.date_filter = DateSearchFilter(_('Year:')) self.date_filter.clear_options() self._populate_date_filter(self.date_filter) self.date_filter.select() self.date_filter.set_use_date_entries(False) BasicDialog.__init__(self, title=self.title) self.justify_label(gtk.JUSTIFY_CENTER) self.ok_button.set_label(_("Generate")) self.add(self.date_filter) self.date_filter.show() def confirm(self): start = self.date_filter.get_start_date() if start is None: warning(_("There are no transactions yet")) return f = FinancialIntervalReport(self.store, start.year) if not f.run(): return temporary = tempfile.NamedTemporaryFile( # Translators: This will be part of a filename prefix=_('stoq-yearly-report'), suffix='.xls', delete=False) f.write(temporary) sse = SpreadSheetExporter() sse.export_temporary(temporary) self.close() # # Private # def _populate_date_filter(self, date_filter): transaction = self.store.find(AccountTransaction).order_by( AccountTransaction.date).first() if transaction is None: return for i in range(transaction.date.year, datetime.date.today().year + 1): year = datetime.datetime(i, 1, 1) date_filter.add_option_fixed_interval(_('Year %d') % (i, ), year, year.replace(month=12, day=31), position=0) def _date_filter_query(self, search_table, column): executer = QueryExecuter(self.store) executer.set_filter_columns(self.date_filter, [column]) executer.set_table(search_table) return executer.search([self.date_filter.get_state()])