def __init__(self, parent=None, store=None, orientation=None, reuse_store=False): """ Create a new ModelListDialog object. :param store: a store connection """ if orientation is None: orientation = gtk.ORIENTATION_VERTICAL if self.columns is None: fmt = "%s needs to set it's columns attribute" raise TypeError(fmt % (self.__class__.__name__, )) if self.model_type is None: fmt = "%s needs to set it's model_type attribute" raise TypeError(fmt % (self.__class__.__name__, )) if not store: store = api.get_default_store() assert not reuse_store self.store = store self.parent = parent self.reuse_store = reuse_store columns = self.columns or self.get_columns() ListSlave.__init__(self, columns, orientation) self._setup_permission()
def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.storables = self.slave.listcontainer.list self.storables.set_cell_data_func(self._on_storables__cell_data_func) self.attach_slave("on_slave_holder", self.slave) self._refresh_storables()
class QuoteFillingDialog(BaseEditor): gladefile = "HolderTemplate" model_type = PurchaseOrder title = _(u"Quote Filling") size = (750, 450) def __init__(self, model, store): BaseEditor.__init__(self, store, model) self._setup_widgets() def _setup_widgets(self): self.slave.listcontainer.add_items(self._get_quote_items()) def _get_columns(self): return [ Column("description", title=_(u"Description"), sorted=True, data_type=str, expand=True), Column("quantity", title=_(u"Quantity"), data_type=Decimal, editable=True), Column("cost", title=_(u"Cost"), data_type=currency, format_func=get_formatted_cost, editable=True), Column("last_cost", title=_(u"Last Cost"), data_type=currency, format_func=get_formatted_cost), Column("average_cost", title=_(u"Average Cost"), data_type=currency, format_func=get_formatted_cost), ] def _get_quote_items(self): return [_TemporaryQuoteItem(item) for item in self.model.get_items()] # # BaseEditorSlave # def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.attach_slave("place_holder", self.slave)
def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.storables = self.slave.listcontainer.list self.storables.set_cell_data_func( self._on_storables__cell_data_func) self.attach_slave("on_slave_holder", self.slave)
class QuoteFillingDialog(BaseEditor): gladefile = "HolderTemplate" model_type = PurchaseOrder title = _(u"Quote Filling") size = (750, 450) def __init__(self, model, store): BaseEditor.__init__(self, store, model) self._setup_widgets() def _setup_widgets(self): self.slave.listcontainer.add_items(self._get_quote_items()) def _get_columns(self): return [Column("description", title=_(u"Description"), sorted=True, data_type=str, expand=True), Column("quantity", title=_(u"Quantity"), data_type=Decimal, editable=True), Column("cost", title=_(u"Cost"), data_type=currency, format_func=get_formatted_cost, editable=True), Column("last_cost", title=_(u"Last Cost"), data_type=currency, format_func=get_formatted_cost), Column("average_cost", title=_(u"Average Cost"), data_type=currency, format_func=get_formatted_cost), ] def _get_quote_items(self): return [_TemporaryQuoteItem(item) for item in self.model.get_items()] # # BaseEditorSlave # def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.attach_slave("place_holder", self.slave)
def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.slave.listcontainer.list.connect("cell-edited", self._on_objectlist__cell_edited) self.attach_slave("on_slave_holder", self.slave)
class StockCostDialog(BaseEditor): gladefile = "StockCostDialog" model_type = object title = _(u"Product - Stock Cost") size = (750, 450) def __init__(self, store, branch=None): if branch is None: self._branch = api.get_current_branch(store) else: self._branch = branch BaseEditor.__init__(self, store, model=object()) self._setup_widgets() def _setup_widgets(self): self.branch_label.set_markup( _(u"Fixing stock cost for products in <b>%s</b>") % api.escape(self._branch.get_description())) items = ProductWithStockView.find_by_branch(self.store, self._branch) self._storables = [_TemporaryItem(s) for s in items] self.slave.listcontainer.add_items(self._storables) def _get_columns(self): return [ Column("code", title=_(u"Code"), data_type=str, sorted=True, width=120), Column("description", title=_(u"Description"), data_type=str, expand=True), Column("stock_cost", title=_(u"Stock Cost"), width=120, data_type=currency, format_func=get_formatted_cost, editable=True) ] def _validate_confirm(self, item, store): if (item.stock_cost is not ValueUnset and item.stock_cost > 0): storable = item.obj.product.storable # TODO: add batch information here. Should we edit the the cost of # each batch individually, or one cost for all the batches? stock_item = store.fetch( storable.get_stock_item(self._branch, None)) stock_item.stock_cost = item.stock_cost self.retval.append(item.obj.product.sellable) # # BaseEditorSlave # def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.slave.listcontainer.list.connect("cell-edited", self._on_objectlist__cell_edited) self.attach_slave("on_slave_holder", self.slave) def on_confirm(self): self.retval = [] store = api.new_store() for item in self._storables: self._validate_confirm(item, store) store.confirm(True) store.close() # # Callbacks # def _on_objectlist__cell_edited(self, objectlist, item, attr): # After filling a value, jump to the next cell or to the ok # button if we are at the last one treeview = objectlist.get_treeview() rows, column = treeview.get_cursor() next_row = rows[0] + 1 nitems = len(self._storables) if next_row < nitems: treeview.set_cursor(next_row, column) else: objectlist.unselect_all() self.main_dialog.ok_button.grab_focus()
class ProductCountingDialog(BaseEditor): gladefile = "HolderTemplate" model_type = Inventory title = _(u"Product Counting") size = (750, 450) def __init__(self, store, model): BaseEditor.__init__(self, store, model) self._setup_widgets() def _setup_widgets(self): self._inventory_items = self._get_inventory_items() self.slave.listcontainer.add_items(self._inventory_items) def _get_columns(self): #XXX: How to define an upper bound number for our spin button ? adj = gtk.Adjustment(upper=MAXINT, step_incr=1) return [Column("code", title=_(u"Code"), data_type=str, sorted=True), Column("description", title=_(u"Description"), data_type=str, expand=True), Column("actual_quantity", title=_(u"Actual quantity"), data_type=Decimal, format_func=self._format_qty, editable=True, spin_adjustment=adj)] def _format_qty(self, quantity): if quantity is ValueUnset: return None if quantity >= 0: return format_quantity(quantity) def _get_inventory_items(self): return [_TemporaryInventoryItem(i) for i in self.model.get_items() if not i.adjusted()] def _validate_inventory_item(self, item, store): inventory_item = store.fetch(item.obj) positive = item.actual_quantity >= 0 if not item.actual_quantity is ValueUnset and positive: inventory_item.actual_quantity = item.actual_quantity else: inventory_item.actual_quantity = None def _can_close_inventory_after_counting(self): if not self.model.all_items_counted(): return False return not self.model.get_items_for_adjustment() def _close_inventory(self): # We will close only if the user really wants to. # This give the option to the user update the product # counting before the adjustment be done. msg = _('You have finished the product counting and none ' 'of the products need to be adjusted.\n\n' 'Would you like to close this inventory now ?') if yesno(msg, gtk.RESPONSE_NO, _('Close inventory'), _('Continue counting')): store = api.new_store() inventory = store.fetch(self.model) inventory.close() store.confirm(inventory) store.close() # # BaseEditorSlave # def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.slave.listcontainer.list.connect( "cell-edited", self._on_objectlist__cell_edited) self.attach_slave("place_holder", self.slave) def on_confirm(self): store = api.new_store() for item in self._inventory_items: self._validate_inventory_item(item, store) # We have to call finish_transaction here, since we will check # if we can close the inventory now store.confirm(True) store.close() if self._can_close_inventory_after_counting(): self._close_inventory() # # Callbacks # def _on_objectlist__cell_edited(self, objectlist, item, attr): # After filling a value, jump to the next cell or to the ok # button if we are at the last one treeview = objectlist.get_treeview() rows, column = treeview.get_cursor() next_row = rows[0] + 1 nitems = len(self._inventory_items) if next_row < nitems: treeview.set_cursor(next_row, column) else: self.main_dialog.ok_button.grab_focus()
def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.slave.listcontainer.list.connect( "cell-edited", self._on_objectlist__cell_edited) self.attach_slave("place_holder", self.slave)
class SellablePriceDialog(BaseEditor): gladefile = "SellablePriceDialog" model_type = object title = _(u"Price Change Dialog") size = (850, 450) def __init__(self, store): self.categories = store.find(ClientCategory) self._last_cat = None BaseEditor.__init__(self, store, model=object()) self._setup_widgets() def _setup_widgets(self): self.category.prefill(api.for_combo(self.categories)) prices = self.store.find(ClientCategoryPrice) category_prices = {} for p in prices: c = category_prices.setdefault(p.sellable_id, {}) c[p.category_id] = p.price marker('SellableView') sellables = self.store.find(SellableView).order_by(Sellable.code) marker('add_items') for s in sellables: for category_id, price in category_prices.get(s.id, {}).items(): s.set_price(category_id, price) self.slave.listcontainer.list.append(s) marker('Done add_items') def _get_columns(self): marker('_get_columns') self._price_columns = {} columns = [Column("code", title=_(u"Code"), data_type=str, width=100), Column("barcode", title=_(u"Barcode"), data_type=str, width=100, visible=False), Column("category_description", title=_(u"Category"), data_type=str, width=100), Column("description", title=_(u"Description"), data_type=str, width=200), Column("cost", title=_(u"Cost"), data_type=currency, width=90), Column("price", title=_(u"Default Price"), data_type=currency, width=90) ] self._price_columns[None] = columns[-1] for cat in self.categories: columns.append(Column('price_%s' % (cat.id, ), title=cat.get_description(), data_type=currency, width=90, visible=True)) self._price_columns[cat.id] = columns[-1] self._columns = columns marker('Done _get_columns') return columns # # BaseEditorSlave # def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.attach_slave("on_slave_holder", self.slave) def on_cancel(self): # Call clear on objectlist before destruction. Workaround for a bug # when destructing the dialog taking to long self.slave.listcontainer.list.clear() def on_confirm(self): marker('Saving prices') # FIXME: Improve this part. This is just a quick workaround to # release the bugfix asap self.main_dialog.ok_button.set_sensitive(False) self.main_dialog.cancel_button.set_sensitive(False) d = ProgressDialog(_('Updating items'), pulse=False) d.set_transient_for(self.main_dialog) d.start(wait=0) d.cancel.hide() total = len(self.slave.listcontainer.list) for i, s in enumerate(self.slave.listcontainer.list): s.save_changes() d.progressbar.set_text('%s/%s' % (i + 1, total)) d.progressbar.set_fraction((i + 1) / float(total)) while gtk.events_pending(): gtk.main_iteration(False) d.stop() marker('Done saving prices') self.slave.listcontainer.list.clear() # # Callbacks # def on_apply__clicked(self, button): markup = self.markup.read() cat = self.category.read() marker('Updating prices') for i in self.slave.listcontainer.list: i.set_markup(cat, markup) self.slave.listcontainer.list.refresh(i) marker('Done updating prices')
def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.attach_slave("on_slave_holder", self.slave)
class ProductCountingDialog(BaseEditor): gladefile = "HolderTemplate" model_type = Inventory title = _(u"Product Counting") size = (750, 450) def __init__(self, store, model): BaseEditor.__init__(self, store, model) self._setup_widgets() def _setup_widgets(self): self._inventory_items = self._get_inventory_items() self.slave.listcontainer.add_items(self._inventory_items) def _get_columns(self): # XXX: How to define an upper bound number for our spin button ? adj = gtk.Adjustment(upper=MAXINT, step_incr=1) return [Column("code", title=_(u"Code"), data_type=str, sorted=True), Column("description", title=_(u"Description"), data_type=str, expand=True), Column("actual_quantity", title=_(u"Actual quantity"), data_type=Decimal, format_func=self._format_qty, editable=True, spin_adjustment=adj)] def _format_qty(self, quantity): if quantity is ValueUnset: return None if quantity >= 0: return format_quantity(quantity) def _get_inventory_items(self): return [_TemporaryInventoryItem(i) for i in self.model.get_items() if not i.adjusted()] def _validate_inventory_item(self, item, store): inventory_item = store.fetch(item.obj) positive = item.actual_quantity >= 0 if not item.actual_quantity is ValueUnset and positive: inventory_item.actual_quantity = item.actual_quantity else: inventory_item.actual_quantity = None def _can_close_inventory_after_counting(self): if not self.model.all_items_counted(): return False return not self.model.get_items_for_adjustment() def _close_inventory(self): # We will close only if the user really wants to. # This give the option to the user update the product # counting before the adjustment be done. msg = _('You have finished the product counting and none ' 'of the products need to be adjusted.\n\n' 'Would you like to close this inventory now ?') if yesno(msg, gtk.RESPONSE_NO, _('Close inventory'), _('Continue counting')): store = api.new_store() inventory = store.fetch(self.model) inventory.close() store.confirm(inventory) store.close() # # BaseEditorSlave # def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.slave.listcontainer.list.connect( "cell-edited", self._on_objectlist__cell_edited) self.attach_slave("place_holder", self.slave) def on_confirm(self): store = api.new_store() for item in self._inventory_items: self._validate_inventory_item(item, store) # We have to call finish_transaction here, since we will check # if we can close the inventory now store.confirm(True) store.close() if self._can_close_inventory_after_counting(): self._close_inventory() # # Callbacks # def _on_objectlist__cell_edited(self, objectlist, item, attr): # After filling a value, jump to the next cell or to the ok # button if we are at the last one treeview = objectlist.get_treeview() rows, column = treeview.get_cursor() next_row = rows[0] + 1 nitems = len(self._inventory_items) if next_row < nitems: treeview.set_cursor(next_row, column) else: self.main_dialog.ok_button.grab_focus()
class InitialStockDialog(BaseEditor): gladefile = "InitialStockDialog" model_type = object title = _(u"Initial Stock") size = (850, 450) help_section = 'stock-register-initial' def __init__(self, store, branch=None): if branch is None: self._branch = api.get_current_branch(store) else: self._branch = branch BaseEditor.__init__(self, store, model=object()) self._setup_widgets() def _setup_widgets(self): self.branch_label.set_markup( _(u"Registering initial stock for products in <b>%s</b>") % api.escape(self._branch.person.name)) # XXX: Find out how we are going to handle the initial stock dialog self._storables = [ _TemporaryStorableItem(s) for s in self.store.find(Storable) if s.get_stock_item(self._branch, batch=None) is None ] self.slave.listcontainer.add_items(self._storables) def _get_columns(self): adj = gtk.Adjustment(lower=0, upper=MAXINT, step_incr=1) return [ Column("code", title=_(u"Code"), data_type=str, sorted=True, width=100), Column("barcode", title=_(u"Barcode"), data_type=str, width=100), Column("category_description", title=_(u"Category"), data_type=str, width=100), Column("description", title=_(u"Description"), data_type=str, expand=True), Column('manufacturer', title=_("Manufacturer"), data_type=str, visible=False), Column('model', title=_("Model"), data_type=str, visible=False), Column("initial_stock", title=_(u"Initial Stock"), data_type=Decimal, format_func=self._format_qty, editable=True, spin_adjustment=adj, width=110), Column("unit_cost", title=_(u"Unit Cost"), width=90, data_type=currency, editable=True, spin_adjustment=adj) ] def _format_qty(self, quantity): if quantity is ValueUnset: return None if quantity >= 0: return quantity def _validate_initial_stock_quantity(self, item, store): if ValueUnset in [item.initial_stock, item.unit_cost]: return valid_stock = item.initial_stock > 0 valid_cost = item.unit_cost >= 0 if valid_stock and valid_cost: storable = store.fetch(item.obj) storable.register_initial_stock(item.initial_stock, self._branch, item.unit_cost) def _add_initial_stock(self): for item in self._storables: self._validate_initial_stock_quantity(item, self.store) # # BaseEditorSlave # def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.slave.listcontainer.list.connect("cell-edited", self._on_objectlist__cell_edited) self.attach_slave("on_slave_holder", self.slave) def on_confirm(self): self._add_initial_stock() def on_cancel(self): if self._storables: msg = _('Save data before close the dialog ?') if yesno(msg, gtk.RESPONSE_NO, _("Save data"), _("Don't save")): self._add_initial_stock() # change retval to True so the store gets commited self.retval = True # # Callbacks # def _on_objectlist__cell_edited(self, objectlist, item, attr): # After filling a value, jump to the next cell or to the ok # button if we are at the last one treeview = objectlist.get_treeview() rows, column = treeview.get_cursor() next_row = rows[0] + 1 nitems = len(self._storables) if next_row < nitems: treeview.set_cursor(next_row, column) else: objectlist.unselect_all() self.main_dialog.ok_button.grab_focus()
class InitialStockDialog(BaseEditor): gladefile = "InitialStockDialog" model_type = object title = _(u"Initial Stock") size = (850, 450) help_section = 'stock-register-initial' def __init__(self, store, branch=None): if branch is None: self._branch = api.get_current_branch(store) else: self._branch = branch BaseEditor.__init__(self, store, model=object()) self._setup_widgets() def _setup_widgets(self): self.branch_label.set_markup( _(u"Registering initial stock for products in <b>%s</b>") % api.escape(self._branch.person.name)) self.slave.listcontainer.add_items(self._get_storables()) def _get_storables(self): for s in Storable.get_storables_without_stock_item( self.store, self._branch): yield _TemporaryStorableItem(s) def _get_columns(self): adj = gtk.Adjustment(lower=0, upper=MAX_INT, step_incr=1) return [ Column("code", title=_(u"Code"), data_type=str, sorted=True, width=100), Column("barcode", title=_(u"Barcode"), data_type=str, width=100), Column("category_description", title=_(u"Category"), data_type=str, width=100), Column("description", title=_(u"Description"), data_type=str, expand=True), Column('manufacturer', title=_("Manufacturer"), data_type=str, visible=False), Column('model', title=_("Model"), data_type=str, visible=False), Column("initial_stock", title=_(u"Initial Stock"), data_type=Decimal, format_func=self._format_qty, editable=True, spin_adjustment=adj, width=110), Column("unit_cost", title=_(u"Unit Cost"), width=90, data_type=currency, editable=True, spin_adjustment=adj) ] def _format_qty(self, quantity): if quantity is ValueUnset: return None if quantity >= 0: return quantity def _validate_initial_stock_quantity(self, item, store): if ValueUnset in [item.initial_stock, item.unit_cost]: return valid_stock = item.initial_stock > 0 valid_cost = item.unit_cost >= 0 if valid_stock and valid_cost: storable = store.fetch(item.obj) if item.is_batch: for batch_item in item.batches: storable.register_initial_stock( batch_item.quantity, self._branch, item.unit_cost, batch_number=batch_item.batch) else: storable.register_initial_stock(item.initial_stock, self._branch, item.unit_cost) def _add_initial_stock(self): for item in self.storables: self._validate_initial_stock_quantity(item, self.store) # # BaseEditorSlave # def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.storables = self.slave.listcontainer.list self.storables.set_cell_data_func(self._on_storables__cell_data_func) self.attach_slave("on_slave_holder", self.slave) def on_confirm(self): self._add_initial_stock() def on_cancel(self): if len(self.storables): msg = _('Save data before close the dialog ?') if yesno(msg, gtk.RESPONSE_NO, _("Save data"), _("Don't save")): self._add_initial_stock() # change retval to True so the store gets commited self.retval = True # # Callbacks # def _on_storables__cell_data_func(self, column, renderer, obj, text): if not isinstance(renderer, gtk.CellRendererText): return text if column.attribute == 'initial_stock': renderer.set_property('editable-set', not obj.is_batch) renderer.set_property('editable', not obj.is_batch) return text def on_storables__row_activated(self, storables, item): if item.is_batch: retval = run_dialog(BatchIncreaseSelectionDialog, self, store=self.store, model=item.storable, quantity=0, original_batches=item.batches) item.batches = retval or item.batches self.storables.update(item) def on_storables__cell_edited(self, storables, item, attr): # After filling a value, jump to the next cell or to the ok # button if we are at the last one treeview = storables.get_treeview() rows, column = treeview.get_cursor() next_row = rows[0] + 1 nitems = len(self.storables) if next_row < nitems: treeview.set_cursor(next_row, column) else: storables.unselect_all() self.main_dialog.ok_button.grab_focus()
class StockCostDialog(BaseEditor): gladefile = "InitialStockDialog" model_type = object title = _(u"Product - Stock Cost") size = (750, 450) def __init__(self, store, branch=None): if branch is None: self._branch = api.get_current_branch(store) else: self._branch = branch BaseEditor.__init__(self, store, model=object()) self._setup_widgets() def _setup_widgets(self): self.branch_label.set_markup( _(u"Fixing stock cost for products in <b>%s</b>") % api.escape(self._branch.person.name)) items = ProductWithStockView.find_by_branch(self.store, self._branch) self._storables = [_TemporaryItem(s) for s in items] self.slave.listcontainer.add_items(self._storables) def _get_columns(self): return [Column("code", title=_(u"Code"), data_type=str, sorted=True, width=120), Column("description", title=_(u"Description"), data_type=str, expand=True), Column("stock_cost", title=_(u"Stock Cost"), width=120, data_type=currency, format_func=get_formatted_cost, editable=True)] def _validate_confirm(self, item, store): if (item.stock_cost is not ValueUnset and item.stock_cost > 0): storable = item.obj.product.storable stock_item = store.fetch(storable.get_stock_item(self._branch)) stock_item.stock_cost = item.stock_cost self.retval.append(item.obj.product.sellable) # # BaseEditorSlave # def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.slave.listcontainer.list.connect( "cell-edited", self._on_objectlist__cell_edited) self.attach_slave("on_slave_holder", self.slave) def on_confirm(self): self.retval = [] store = api.new_store() for item in self._storables: self._validate_confirm(item, store) store.confirm(True) store.close() # # Callbacks # def _on_objectlist__cell_edited(self, objectlist, item, attr): # After filling a value, jump to the next cell or to the ok # button if we are at the last one treeview = objectlist.get_treeview() rows, column = treeview.get_cursor() next_row = rows[0] + 1 nitems = len(self._storables) if next_row < nitems: treeview.set_cursor(next_row, column) else: objectlist.unselect_all() self.main_dialog.ok_button.grab_focus()
class InitialStockDialog(BaseEditor): gladefile = "InitialStockDialog" model_type = Settable title = _(u"Initial Stock") size = (850, 450) help_section = 'stock-register-initial' proxy_widgets = ['branch'] need_cancel_confirmation = True # # Private # def _refresh_storables(self): self.slave.listcontainer.list.add_list(self._get_storables()) def _get_storables(self): self._current_branch = self.model.branch # Cache this data, to avoid more queries when building the list of storables. self._categories = list(self.store.find(SellableCategory)) data = Storable.get_initial_stock_data(self.store, self.model.branch) for sellable, product, storable in data: yield _TemporaryStorableItem(sellable, product, storable) def _get_columns(self): adj = Gtk.Adjustment(lower=0, upper=MAX_INT, step_increment=1) return [Column("code", title=_(u"Code"), data_type=str, sorted=True, width=100), Column("barcode", title=_(u"Barcode"), data_type=str, width=100), Column("category_description", title=_(u"Category"), data_type=str, width=100), Column("description", title=_(u"Description"), data_type=str, expand=True), Column('manufacturer', title=_("Manufacturer"), data_type=str, visible=False), Column('model', title=_("Model"), data_type=str, visible=False), Column("initial_stock", title=_(u"Initial Stock"), data_type=Decimal, format_func=self._format_qty, editable=True, spin_adjustment=adj, width=110), Column("unit_cost", title=_(u"Unit Cost"), width=90, data_type=currency, editable=True, spin_adjustment=adj)] def _format_qty(self, quantity): if quantity is ValueUnset: return None if quantity >= 0: return quantity def _validate_initial_stock_quantity(self, item): if ValueUnset in [item.initial_stock, item.unit_cost]: return valid_stock = item.initial_stock > 0 valid_cost = item.unit_cost >= 0 if valid_stock and valid_cost: storable = item.storable if item.is_batch: for batch, quantity in item.batches.items(): storable.register_initial_stock(quantity, self.model.branch, item.unit_cost, batch_number=batch) else: storable.register_initial_stock(item.initial_stock, self.model.branch, item.unit_cost, api.get_current_user(self.store)) def _add_initial_stock(self): for item in self.storables: self._validate_initial_stock_quantity(item) # # BaseEditorSlave # def create_model(self, store): self._current_branch = api.get_current_branch(store) return Settable(branch=self._current_branch) def setup_proxies(self): if api.sysparam.get_bool('SYNCHRONIZED_MODE'): current = api.get_current_branch(self.store) branches = [(current.get_description(), current)] else: branches = api.for_combo(Branch.get_active_branches(self.store)) self.branch.prefill(branches) self.add_proxy(self.model, self.proxy_widgets) def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.storables = self.slave.listcontainer.list self.storables.set_cell_data_func( self._on_storables__cell_data_func) self.attach_slave("on_slave_holder", self.slave) self._refresh_storables() def on_confirm(self): self._add_initial_stock() def has_changes(self): return any(i.initial_stock > 0 for i in self.storables) # # Callbacks # def _on_storables__cell_data_func(self, column, renderer, obj, text): if not isinstance(renderer, Gtk.CellRendererText): return text if column.attribute == 'initial_stock': renderer.set_property('editable-set', not obj.is_batch) renderer.set_property('editable', not obj.is_batch) return text def on_storables__row_activated(self, storables, item): if item.is_batch: retval = run_dialog(BatchIncreaseSelectionDialog, self, store=self.store, model=item.storable, quantity=0, original_batches=item.batches) item.batches = retval or item.batches self.storables.update(item) def on_storables__cell_edited(self, storables, item, attr): # After filling a value, jump to the next cell or to the ok # button if we are at the last one treeview = storables.get_treeview() rows, column = treeview.get_cursor() next_row = rows[0] + 1 nitems = len(self.storables) if next_row < nitems: treeview.set_cursor(next_row, column) else: storables.unselect_all() self.main_dialog.ok_button.grab_focus() def after_branch__content_changed(self, widget): # There is a little bug in kiwi that causes this signal to be emmited # after just losing focus if self.model.branch == self._current_branch: return self._refresh_storables()
class InitialStockDialog(BaseEditor): gladefile = "InitialStockDialog" model_type = Settable title = _(u"Initial Stock") size = (850, 450) help_section = 'stock-register-initial' proxy_widgets = ['branch'] # # Private # def _refresh_storables(self): self.slave.listcontainer.list.add_list(self._get_storables()) def _get_storables(self): for s in Storable.get_storables_without_stock_item(self.store, self.model.branch): yield _TemporaryStorableItem(s) def _get_columns(self): adj = gtk.Adjustment(lower=0, upper=MAX_INT, step_incr=1) return [Column("code", title=_(u"Code"), data_type=str, sorted=True, width=100), Column("barcode", title=_(u"Barcode"), data_type=str, width=100), Column("category_description", title=_(u"Category"), data_type=str, width=100), Column("description", title=_(u"Description"), data_type=str, expand=True), Column('manufacturer', title=_("Manufacturer"), data_type=str, visible=False), Column('model', title=_("Model"), data_type=str, visible=False), Column("initial_stock", title=_(u"Initial Stock"), data_type=Decimal, format_func=self._format_qty, editable=True, spin_adjustment=adj, width=110), Column("unit_cost", title=_(u"Unit Cost"), width=90, data_type=currency, editable=True, spin_adjustment=adj)] def _format_qty(self, quantity): if quantity is ValueUnset: return None if quantity >= 0: return quantity def _validate_initial_stock_quantity(self, item, store): if ValueUnset in [item.initial_stock, item.unit_cost]: return valid_stock = item.initial_stock > 0 valid_cost = item.unit_cost >= 0 if valid_stock and valid_cost: storable = store.fetch(item.obj) if item.is_batch: for batch, quantity in item.batches.items(): storable.register_initial_stock(quantity, self.model.branch, item.unit_cost, batch_number=batch) else: storable.register_initial_stock(item.initial_stock, self.model.branch, item.unit_cost) def _add_initial_stock(self): for item in self.storables: self._validate_initial_stock_quantity(item, self.store) # # BaseEditorSlave # def create_model(self, store): return Settable(branch=api.get_current_branch(store)) def setup_proxies(self): self.branch.prefill( api.for_combo(Branch.get_active_branches(self.store))) self.add_proxy(self.model, self.proxy_widgets) def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.storables = self.slave.listcontainer.list self.storables.set_cell_data_func( self._on_storables__cell_data_func) self.attach_slave("on_slave_holder", self.slave) self._refresh_storables() def on_confirm(self): self._add_initial_stock() def on_cancel(self): if len(self.storables): msg = _('Save data before close the dialog ?') if yesno(msg, gtk.RESPONSE_NO, _("Save data"), _("Don't save")): self._add_initial_stock() # change retval to True so the store gets commited self.retval = True # # Callbacks # def _on_storables__cell_data_func(self, column, renderer, obj, text): if not isinstance(renderer, gtk.CellRendererText): return text if column.attribute == 'initial_stock': renderer.set_property('editable-set', not obj.is_batch) renderer.set_property('editable', not obj.is_batch) return text def on_storables__row_activated(self, storables, item): if item.is_batch: retval = run_dialog(BatchIncreaseSelectionDialog, self, store=self.store, model=item.storable, quantity=0, original_batches=item.batches) item.batches = retval or item.batches self.storables.update(item) def on_storables__cell_edited(self, storables, item, attr): # After filling a value, jump to the next cell or to the ok # button if we are at the last one treeview = storables.get_treeview() rows, column = treeview.get_cursor() next_row = rows[0] + 1 nitems = len(self.storables) if next_row < nitems: treeview.set_cursor(next_row, column) else: storables.unselect_all() self.main_dialog.ok_button.grab_focus() def after_branch__content_changed(self, widget): self._refresh_storables()
class InitialStockDialog(BaseEditor): gladefile = "InitialStockDialog" model_type = object title = _(u"Initial Stock") size = (850, 450) help_section = 'stock-register-initial' def __init__(self, store, branch=None): if branch is None: self._branch = api.get_current_branch(store) else: self._branch = branch BaseEditor.__init__(self, store, model=object()) self._setup_widgets() def _setup_widgets(self): self.branch_label.set_markup( _(u"Registering initial stock for products in <b>%s</b>") % api.escape(self._branch.person.name)) # XXX: Find out how we are going to handle the initial stock dialog self._storables = [_TemporaryStorableItem(s) for s in self.store.find(Storable) if s.get_stock_item(self._branch, batch=None) is None] self.slave.listcontainer.add_items(self._storables) def _get_columns(self): adj = gtk.Adjustment(lower=0, upper=MAXINT, step_incr=1) return [Column("code", title=_(u"Code"), data_type=str, sorted=True, width=100), Column("barcode", title=_(u"Barcode"), data_type=str, width=100), Column("category_description", title=_(u"Category"), data_type=str, width=100), Column("description", title=_(u"Description"), data_type=str, expand=True), Column('manufacturer', title=_("Manufacturer"), data_type=str, visible=False), Column('model', title=_("Model"), data_type=str, visible=False), Column("initial_stock", title=_(u"Initial Stock"), data_type=Decimal, format_func=self._format_qty, editable=True, spin_adjustment=adj, width=110), Column("unit_cost", title=_(u"Unit Cost"), width=90, data_type=currency, editable=True, spin_adjustment=adj)] def _format_qty(self, quantity): if quantity is ValueUnset: return None if quantity >= 0: return quantity def _validate_initial_stock_quantity(self, item, store): if ValueUnset in [item.initial_stock, item.unit_cost]: return valid_stock = item.initial_stock > 0 valid_cost = item.unit_cost >= 0 if valid_stock and valid_cost: storable = store.fetch(item.obj) storable.register_initial_stock(item.initial_stock, self._branch, item.unit_cost) def _add_initial_stock(self): for item in self._storables: self._validate_initial_stock_quantity(item, self.store) # # BaseEditorSlave # def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.slave.listcontainer.list.connect( "cell-edited", self._on_objectlist__cell_edited) self.attach_slave("on_slave_holder", self.slave) def on_confirm(self): self._add_initial_stock() def on_cancel(self): if self._storables: msg = _('Save data before close the dialog ?') if yesno(msg, gtk.RESPONSE_NO, _("Save data"), _("Don't save")): self._add_initial_stock() # change retval to True so the store gets commited self.retval = True # # Callbacks # def _on_objectlist__cell_edited(self, objectlist, item, attr): # After filling a value, jump to the next cell or to the ok # button if we are at the last one treeview = objectlist.get_treeview() rows, column = treeview.get_cursor() next_row = rows[0] + 1 nitems = len(self._storables) if next_row < nitems: treeview.set_cursor(next_row, column) else: objectlist.unselect_all() self.main_dialog.ok_button.grab_focus()
class SellablePriceDialog(BaseEditor): gladefile = "SellablePriceDialog" model_type = object title = _(u"Price Change Dialog") size = (850, 450) def __init__(self, store): self.categories = store.find(ClientCategory) self._last_cat = None BaseEditor.__init__(self, store, model=object()) self._setup_widgets() def _setup_widgets(self): self.category.prefill(api.for_combo(self.categories)) prices = self.store.find(ClientCategoryPrice).order_by(ClientCategoryPrice.id) category_prices = {} for p in prices: c = category_prices.setdefault(p.sellable_id, {}) c[p.category_id] = p.price marker('SellableView') sellables = self.store.find(SellableView).order_by(Sellable.code) marker('add_items') for s in sellables: for category_id, price in category_prices.get(s.id, {}).items(): s.set_price(category_id, price) self.slave.listcontainer.list.append(s) marker('Done add_items') def _get_columns(self): marker('_get_columns') self._price_columns = {} columns = [Column("code", title=_(u"Code"), data_type=str, width=100), Column("barcode", title=_(u"Barcode"), data_type=str, width=100, visible=False), Column("category_description", title=_(u"Category"), data_type=str, width=100), Column("description", title=_(u"Description"), data_type=str, width=200), Column("cost", title=_(u"Cost"), data_type=currency, width=90), Column("price", title=_(u"Default Price"), data_type=currency, width=90) ] self._price_columns[None] = columns[-1] for cat in self.categories: columns.append(Column('price_%s' % (cat.id, ), title=cat.get_description(), data_type=currency, width=90, visible=True)) self._price_columns[cat.id] = columns[-1] self._columns = columns marker('Done _get_columns') return columns # # BaseEditorSlave # def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.attach_slave("on_slave_holder", self.slave) def on_cancel(self): # Call clear on objectlist before destruction. Workaround for a bug # when destructing the dialog taking to long self.slave.listcontainer.list.clear() def on_confirm(self): marker('Saving prices') # FIXME: Improve this part. This is just a quick workaround to # release the bugfix asap self.main_dialog.ok_button.set_sensitive(False) self.main_dialog.cancel_button.set_sensitive(False) d = ProgressDialog(_('Updating items'), pulse=False) d.set_transient_for(self.main_dialog) d.start(wait=0) d.cancel.hide() total = len(self.slave.listcontainer.list) for i, s in enumerate(self.slave.listcontainer.list): s.save_changes() d.progressbar.set_text('%s/%s' % (i + 1, total)) d.progressbar.set_fraction((i + 1) / float(total)) while gtk.events_pending(): gtk.main_iteration(False) d.stop() marker('Done saving prices') self.slave.listcontainer.list.clear() # # Callbacks # def on_apply__clicked(self, button): markup = self.markup.read() cat = self.category.read() marker('Updating prices') for i in self.slave.listcontainer.list: i.set_markup(cat, markup) self.slave.listcontainer.list.refresh(i) marker('Done updating prices')
class InitialStockDialog(BaseEditor): gladefile = "InitialStockDialog" model_type = Settable title = _(u"Initial Stock") size = (850, 450) help_section = 'stock-register-initial' proxy_widgets = ['branch'] need_cancel_confirmation = True # # Private # def _refresh_storables(self): self.slave.listcontainer.list.add_list(self._get_storables()) def _get_storables(self): self._current_branch = self.model.branch # Cache this data, to avoid more queries when building the list of storables. self._categories = list(self.store.find(SellableCategory)) data = Storable.get_initial_stock_data(self.store, self.model.branch) for sellable, product, storable in data: yield _TemporaryStorableItem(sellable, product, storable) def _get_columns(self): adj = gtk.Adjustment(lower=0, upper=MAX_INT, step_incr=1) return [Column("code", title=_(u"Code"), data_type=str, sorted=True, width=100), Column("barcode", title=_(u"Barcode"), data_type=str, width=100), Column("category_description", title=_(u"Category"), data_type=str, width=100), Column("description", title=_(u"Description"), data_type=str, expand=True), Column('manufacturer', title=_("Manufacturer"), data_type=str, visible=False), Column('model', title=_("Model"), data_type=str, visible=False), Column("initial_stock", title=_(u"Initial Stock"), data_type=Decimal, format_func=self._format_qty, editable=True, spin_adjustment=adj, width=110), Column("unit_cost", title=_(u"Unit Cost"), width=90, data_type=currency, editable=True, spin_adjustment=adj)] def _format_qty(self, quantity): if quantity is ValueUnset: return None if quantity >= 0: return quantity def _validate_initial_stock_quantity(self, item): if ValueUnset in [item.initial_stock, item.unit_cost]: return valid_stock = item.initial_stock > 0 valid_cost = item.unit_cost >= 0 if valid_stock and valid_cost: storable = item.storable if item.is_batch: for batch, quantity in item.batches.items(): storable.register_initial_stock(quantity, self.model.branch, item.unit_cost, batch_number=batch) else: storable.register_initial_stock(item.initial_stock, self.model.branch, item.unit_cost) def _add_initial_stock(self): for item in self.storables: self._validate_initial_stock_quantity(item) # # BaseEditorSlave # def create_model(self, store): self._current_branch = api.get_current_branch(store) return Settable(branch=self._current_branch) def setup_proxies(self): if api.sysparam.get_bool('SYNCHRONIZED_MODE'): current = api.get_current_branch(self.store) branches = [(current.get_description(), current)] else: branches = api.for_combo(Branch.get_active_branches(self.store)) self.branch.prefill(branches) self.add_proxy(self.model, self.proxy_widgets) def setup_slaves(self): self.slave = ListSlave(self._get_columns()) self.slave.set_list_type(ListType.READONLY) self.storables = self.slave.listcontainer.list self.storables.set_cell_data_func( self._on_storables__cell_data_func) self.attach_slave("on_slave_holder", self.slave) self._refresh_storables() def on_confirm(self): self._add_initial_stock() def has_changes(self): return any(i.initial_stock > 0 for i in self.storables) # # Callbacks # def _on_storables__cell_data_func(self, column, renderer, obj, text): if not isinstance(renderer, gtk.CellRendererText): return text if column.attribute == 'initial_stock': renderer.set_property('editable-set', not obj.is_batch) renderer.set_property('editable', not obj.is_batch) return text def on_storables__row_activated(self, storables, item): if item.is_batch: retval = run_dialog(BatchIncreaseSelectionDialog, self, store=self.store, model=item.storable, quantity=0, original_batches=item.batches) item.batches = retval or item.batches self.storables.update(item) def on_storables__cell_edited(self, storables, item, attr): # After filling a value, jump to the next cell or to the ok # button if we are at the last one treeview = storables.get_treeview() rows, column = treeview.get_cursor() next_row = rows[0] + 1 nitems = len(self.storables) if next_row < nitems: treeview.set_cursor(next_row, column) else: storables.unselect_all() self.main_dialog.ok_button.grab_focus() def after_branch__content_changed(self, widget): # There is a little bug in kiwi that causes this signal to be emmited # after just losing focus if self.model.branch == self._current_branch: return self._refresh_storables()