def _update_view(self): self.proxy.update("status_str") has_open_inventory = bool(Inventory.has_open(self.store, api.get_current_branch(self.store))) tab = self._get_tab("execution_holder") # If it's not opened, it's at least approved. # So, we can enable the execution slave tab.set_sensitive( self.model.status == WorkOrder.STATUS_WORK_IN_PROGRESS and not has_open_inventory and not self.visual_mode ) has_items = bool(self.model.order_items.count()) if self.model.can_approve(): label = _("Approve") elif self.model.can_work() and not has_items: label = _("Start") elif self.model.can_work(): label = _("Continue") elif self.model.can_pause(): label = _("Pause") else: label = "" self.toggle_status_btn.set_label(label) self.toggle_status_btn.set_sensitive(not self.visual_mode and self.model.client is not None) self.toggle_status_btn.set_visible(bool(label)) stock_id, tooltip = get_workorder_state_icon(self.model) if stock_id is not None: self.state_icon.set_from_stock(stock_id, gtk.ICON_SIZE_MENU) self.state_icon.set_visible(True) self.state_icon.set_tooltip_text(tooltip) else: self.state_icon.hide()
def _can_open(self): branch = api.get_current_branch(self.store) if Inventory.has_open(self.store, branch): return False # It doesn't make sense to open an inventory if we don't have any stock return self.store.find(ProductStockItem, branch=branch).count() > 0
def on_confirm(self): # We are using this hook as a callback for the finish button branch = self.store.fetch(self.model.branch) responsible = self.store.fetch(self.model.user) query = self._get_sellables_query() return Inventory.create_inventory(self.store, branch, api.get_current_station(self.store), responsible, query)
def new_sale(self): store = self.window.store if Inventory.has_open(store, api.get_current_branch(store)): warning(_("You cannot create a quote with an open inventory.")) return with api.new_store() as store: run_dialog(SaleQuoteWizard, None, store)
def setup_proxies(self): # Avoid changing widget states in __init__, so that plugins have a # chance to override the default settings has_open_inventory = Inventory.has_open( self.store, api.get_current_branch(self.store)) self.receive_now.set_sensitive(not bool(has_open_inventory)) self._setup_transporter_entry() self.proxy = self.add_proxy(self.model, self.proxy_widgets)
def validate_confirm(self): query = self._get_sellables_query() sellables = Inventory.get_sellables_for_inventory(self.store, self.model.branch, query) if sellables.is_empty(): info(_(u'No products have been found in the selected ' 'categories.')) return False return True
def setup_proxies(self): # Avoid changing widget states in __init__, so that plugins have a # chance to override the default settings has_open_inventory = Inventory.has_open(self.store, api.get_current_branch(self.store)) self.receive_now.set_sensitive(not bool(has_open_inventory)) self._setup_transporter_entry() self.proxy = self.add_proxy(self.model, self.proxy_widgets)
def on_confirm(self): # We are using this hook as a callback for the finish button branch = self.store.fetch(self.model.branch) responsible = self.store.fetch(self.model.user) inventory = Inventory(open_date=self.model.open_date, branch=branch, responsible=responsible, store=self.store) for sellable in self._get_sellables(): storable = sellable.product_storable if storable is None: continue if storable.is_batch: for batch in storable.get_available_batches(inventory.branch): inventory.add_sellable(sellable, batch_number=batch.batch_number) else: inventory.add_sellable(sellable)
def return_sale(self): assert not Inventory.has_open(self.store, api.get_current_branch(self.store)) sale_view = self.sales.get_selected() store = api.new_store() retval = return_sale(self.get_parent(), store.fetch(sale_view.sale), store) store.confirm(retval) store.close() if retval: self.emit("sale-returned", retval)
def _setup_widgets(self): self.edit_button.set_sensitive(False) if not self.visual_mode: self.start_production_check.hide() has_open_inventory = Inventory.has_open(self.store, get_current_branch(self.store)) self.start_production_check.set_sensitive(not bool(has_open_inventory)) self.materials.set_columns(self._get_columns()) for production_item in self.model.get_items(): self._add_materials(production_item)
def _register_inventory(self): query = Storable.id == self._product.id inventory = Inventory.create_inventory( self.store, branch=self._branch, responsible=api.get_current_user(self.store), query=query ) # At this point, the inventory should have only one item. item = inventory.get_items().one() item.counted_quantity = item.actual_quantity = self.model.quantity # item.product_cost = self.model.cost item.reason = self.model.reason item.adjust(invoice_number=None) inventory.close()
def return_sale(self): assert not Inventory.has_open(self.store, api.get_current_branch(self.store)) sale_view = self.sales.get_selected() store = api.new_store() retval = return_sale(self.get_parent(), store.fetch(sale_view.sale), store) store.confirm(retval) store.close() if retval: self.emit('sale-returned', retval)
def new_sale_with_wo(self): store = self.window.store if Inventory.has_open(store, api.get_current_branch(store)): warning(_("You cannot create a quote with an open inventory.")) return with api.new_store() as store: run_dialog(WorkOrderQuoteWizard, None, store) if store.committed: # We are unable to just refresh the ui, so 'deactivate' and # 'activate' the launcher to mimic the refresh self.window.switch_application('launcher')
def _register_inventory(self): query = Storable.id == self._product.id inventory = Inventory.create_inventory( self.store, branch=self._branch, responsible=api.get_current_user(self.store), query=query) # At this point, the inventory should have only one item. item = inventory.get_items().one() item.counted_quantity = item.actual_quantity = self.model.quantity # item.product_cost = self.model.cost item.reason = self.model.reason item.adjust(invoice_number=None) inventory.close()
def _get_available_branches_to_inventory(self): """Returns a list of branches where we can open an inventory. Note that we can open a inventory if: - There's no inventory opened yet (in the same branch) - The branch must have some stock """ available_branches = [] for branch in self._get_branches(): has_open_inventory = Inventory.has_open(self.store, branch) if not has_open_inventory: stock = self.store.find(ProductStockItem, branch=branch) if stock.count() > 0: available_branches.append(branch) return available_branches
def _update_view(self): self.proxy.update('status_str') # Cache this to avoid multiple queries has_open_inventory = bool( Inventory.has_open(self.store, api.get_current_branch(self.store))) tab = self._get_tab('execution_holder') # If it's not opened, it's at least approved. # So, we can enable the execution slave tab.set_sensitive( self.model.status == WorkOrder.STATUS_WORK_IN_PROGRESS and not has_open_inventory and not self.visual_mode) has_items = bool(self.model.order_items.count()) branch = api.get_current_branch(self.store) if self.model.can_approve(): label = _("Approve") elif self.model.can_work(branch) and not has_items: label = _("Start") elif self.model.can_work(branch): label = _("Continue") elif self.model.can_pause(): label = _("Pause") else: label = '' self.toggle_status_btn.set_label(label) self.toggle_status_btn.set_sensitive(not self.visual_mode and self.model.client is not None) self.toggle_status_btn.set_visible(bool(label)) stock_id, tooltip = get_workorder_state_icon(self.model) if stock_id is not None: self.state_icon.set_from_icon_name(stock_id, Gtk.IconSize.MENU) self.state_icon.set_visible(True) self.state_icon.set_tooltip_text(tooltip) else: self.state_icon.hide()
def on_confirm(self): # We are using this hook as a callback for the finish button branch = self.store.fetch(self.model.branch) inventory = Inventory(open_date=self.model.open_date, branch=branch, store=self.store) for sellable in self._get_sellables(): storable = sellable.product_storable if storable is None: continue # a sellable without stock can't be part of inventory # XXX if storable.get_stock_item(self.model.branch, None) is not None: recorded_quantity = storable.get_balance_for_branch( self.model.branch) # TODO: Move the creation of inventory itens to the domain. # TODO: Create one inventory item for each batch, or refactor # the way we do the inventory. InventoryItem(product=sellable.product, product_cost=sellable.cost, recorded_quantity=recorded_quantity, inventory=inventory, store=self.store)
def test_create_inventory(self): branch = self.create_branch() # A category so that we can filter the products we want in the # inventory cat = self.create_sellable_category() # First, lets create some sellables for our test # One storable with stock (it should be in the inventory) storable1 = self.create_storable(branch=branch, stock=10) storable1.product.sellable.category = cat # One storable without stock (it should NOT be in the inventory) storable2 = self.create_storable() storable2.product.sellable.category = cat # One storable with one batch, and stock (it should be in the inventory) storable3 = self.create_storable() storable3.is_batch = True storable3.product.sellable.category = cat batch1 = self.create_storable_batch(storable3, u'123') storable3.increase_stock(3, branch, batch=batch1, type=StockTransactionHistory.TYPE_INITIAL, object_id=None, unit_cost=10) # One storable with one batch and a stock item (but without stock). # it should be on the inventory storable4 = self.create_storable() storable4.is_batch = True storable4.product.sellable.category = cat batch2 = self.create_storable_batch(storable4, u'124') storable4.increase_stock(1, branch, batch=batch2, type=StockTransactionHistory.TYPE_INITIAL, object_id=None, unit_cost=10) storable4.decrease_stock(1, branch, batch=batch2, type=StockTransactionHistory.TYPE_INITIAL, object_id=None) # Then, lets open the inventory responsible = self.create_user() query = Sellable.category == cat inventory = Inventory.create_inventory(self.store, branch, responsible, query) self.assertEquals(inventory.branch, branch) self.assertEquals(inventory.responsible, responsible) # There should be only 3 items in the inventory items = inventory.get_items() self.assertEqual(items.count(), 3) self.assertEqual( set(i.product for i in items), set([storable1.product, storable3.product, storable4.product])) # Use this examples to also test get_inventory_data data = list(inventory.get_inventory_data()) self.assertEquals(len(data), 3) # each row should have 5 items row = data[0] self.assertEquals(len(row), 5) self.assertEquals(set(i[0] for i in data), set(items)) self.assertEquals(set(i[1] for i in data), set([storable1, storable3, storable4])) self.assertEquals(set(i[4] for i in data), set([None, batch1, batch2]))
def has_open_inventory(self): has_open = Inventory.has_open(self.store, api.get_current_branch(self.store)) return bool(has_open)
def post(self, store): branch_id = self.get_arg('branch_id') count = self.get_arg('count') if not branch_id: message = 'No branch_id provided' log.error(message) abort(400, message) if not count: message = 'No count provided' log.error(message) abort(400, message) if not isinstance(count, dict): message = ('count should be a JSON with barcodes or codes as keys ' 'and counted quantities as values') log.error(message) abort(400, message) branch = store.get(Branch, branch_id) if not branch: message = 'Branch {} not found'.format(branch_id) log.error(message) abort(404, message) login_user = self.get_current_user(store) station = self.get_current_station(store) sellable_count, not_found = self._convert_count_keys(store, count) query = Sellable in sellable_count.keys() inventory = Inventory.create_inventory(store, branch, station, login_user, query) stock_not_managed = self._apply_count_to_inventory( store, sellable_count, inventory) items_for_adjustment = inventory.get_items_for_adjustment() items_for_adjustment_list = [] for item_for_adjustment in items_for_adjustment: items_for_adjustment_list.append({ 'recorded_quantity': str(item_for_adjustment.recorded_quantity.normalize()), 'counted_quantity': str(item_for_adjustment.counted_quantity.normalize()), 'difference': str(item_for_adjustment.difference.normalize()), 'product': { 'sellable': { 'barcode': item_for_adjustment.product.sellable.barcode, 'code': item_for_adjustment.get_code(), 'description': item_for_adjustment.get_description() } } }) if not items_for_adjustment_list: inventory.cancel() return make_response( jsonify({ 'id': inventory.id, 'identifier': inventory.identifier, 'status': inventory.status, 'not_found': list(not_found), 'stock_not_managed': stock_not_managed, 'items': items_for_adjustment_list }), 201)
def testRegisters(self): order = self.create_receiving_order() order.receival_date = localdate(2007, 6, 1).date() order.discount_value = 10 # order.purchase.discount_value = 5 # order.purchase.surcharge_value = 8 # order.surcharge_value = 15 order.ipi_total = 10 order.freight_total = 6 order.secure_value = 6 order.expense_value = 12 supplier = self.create_supplier() company = supplier.person.has_individual_or_company_facets() company.state_registry = u'103238426117' order.supplier = supplier employee = self.create_employee() branch = get_current_branch(self.store) branch.manager = employee order.purchase.status = order.purchase.ORDER_PENDING sellable = self.create_sellable() sellable.tax_constant = SellableTaxConstant( description=u"18", tax_type=int(TaxType.CUSTOM), tax_value=18, store=self.store) self.create_receiving_order_item(order, sellable=sellable) sellable2 = self.create_sellable() sellable2.tax_constant = SellableTaxConstant( description=u"6", tax_type=int(TaxType.CUSTOM), tax_value=6, store=self.store) self.create_receiving_order_item(order, sellable=sellable2) order.purchase.confirm() order.confirm() sellable.code = u'9999' sellable2.code = u'10000' sale = self.create_sale() sale.open_date = localdate(2007, 6, 10).date() sellable3 = self.create_sellable() product = sellable3.product sellable.tax_constant = SellableTaxConstant( description=u"18", tax_type=int(TaxType.CUSTOM), tax_value=18, store=self.store) sale.add_sellable(sellable3, quantity=1) self.create_storable(product, get_current_branch(self.store), stock=100) sale.order() method = PaymentMethod.get_by_name(self.store, u'money') method.create_payment(Payment.TYPE_IN, sale.group, sale.branch, sale.get_sale_subtotal()) sale.confirm() sale.group.pay() sale.close_date = localdate(2007, 6, 10).date() sale.confirm_date = localdate(2007, 6, 10).date() sellable3.code = u'09999' inventory = Inventory(branch=branch, store=self.store) inventory.open_date = localdate(2007, 6, 15).date() # product came from sellable3 inventory_item = InventoryItem(product=product, product_cost=product.sellable.cost, inventory=inventory, recorded_quantity=99, store=self.store) inventory_item.cfop_data = self.store.get(CfopData, 1) inventory_item.reason = u'Test' inventory_item.actual_quantity = 99 inventory_item.adjust(invoice_number=999) inventory.close(close_date=localdate(2007, 6, 15).date()) generator = StoqlibSintegraGenerator(self.store, localdate(2007, 6, 1).date(), localdate(2007, 6, 30).date()) try: compare_sintegra_file(generator.sintegra, 'sintegra-receival') except AssertionError as e: self.fail(e)
def test_create_inventory(self): branch = self.create_branch() # A category so that we can filter the products we want in the # inventory cat = self.create_sellable_category() # First, lets create some sellables for our test # One storable with stock (it should be in the inventory) storable1 = self.create_storable(branch=branch, stock=10) storable1.product.sellable.category = cat # One storable without stock (it should NOT be in the inventory) storable2 = self.create_storable() storable2.product.sellable.category = cat # One storable with one batch, and stock (it should be in the inventory) storable3 = self.create_storable() storable3.is_batch = True storable3.product.sellable.category = cat batch1 = self.create_storable_batch(storable3, u'123') storable3.increase_stock(3, branch, batch=batch1, type=0, object_id=None, unit_cost=10) # One storable with one batch and a stock item (but without stock). # it should be on the inventory storable4 = self.create_storable() storable4.is_batch = True storable4.product.sellable.category = cat batch2 = self.create_storable_batch(storable4, u'124') storable4.increase_stock(1, branch, batch=batch2, type=0, object_id=None, unit_cost=10) storable4.decrease_stock(1, branch, batch=batch2, type=0, object_id=None) # Then, lets open the inventory responsible = self.create_user() query = Sellable.category == cat inventory = Inventory.create_inventory(self.store, branch, responsible, query) self.assertEquals(inventory.branch, branch) self.assertEquals(inventory.responsible, responsible) # There should be only 3 items in the inventory items = inventory.get_items() self.assertEqual(items.count(), 3) self.assertEqual(set(i.product for i in items), set([storable1.product, storable3.product, storable4.product])) # Use this examples to also test get_inventory_data data = list(inventory.get_inventory_data()) self.assertEquals(len(data), 3) # each row should have 5 items row = data[0] self.assertEquals(len(row), 5) self.assertEquals(set(i[0] for i in data), set(items)) self.assertEquals(set(i[1] for i in data), set([storable1, storable3, storable4])) self.assertEquals(set(i[4] for i in data), set([None, batch1, batch2]))
def on_confirm(self): # We are using this hook as a callback for the finish button branch = self.store.fetch(self.model.branch) responsible = self.store.fetch(self.model.user) query = self._get_sellables_query() return Inventory.create_inventory(self.store, branch, responsible, query)
def create_inventory(self, branch=None): from stoqlib.domain.inventory import Inventory branch = branch or self.create_branch(u"Main") return Inventory(branch=branch, store=self.store)
def has_open_inventory(self): return Inventory.has_open(self.store, api.get_current_branch(self.store))
def _has_open_inventory(self): store = self._parent.store has_open = Inventory.has_open(store, api.get_current_branch(store)) return bool(has_open)