Esempio n. 1
0
    def add_stock_items(self):
        """This is normally called from ReceivingOrder when
        a the receving order is confirmed.
        """
        store = self.store
        if self.quantity > self.get_remaining_quantity():
            raise ValueError(
                u"Quantity received (%d) is greater than "
                u"quantity ordered (%d)" % (self.quantity, self.get_remaining_quantity())
            )

        branch = self.receiving_order.branch
        storable = self.sellable.product_storable
        purchase = self.purchase_item.order
        if storable is not None:
            storable.increase_stock(
                self.quantity,
                branch,
                StockTransactionHistory.TYPE_RECEIVED_PURCHASE,
                self.id,
                self.cost,
                batch=self.batch,
            )
        purchase.increase_quantity_received(self.purchase_item, self.quantity)
        ProductHistory.add_received_item(store, branch, self)
    def _create_domain(self):
        self.clean_domain([ProductHistory])

        branches = self.store.find(Branch)

        luvas = self.create_sellable(description=u'Luvas')
        luvas.code = u'1'
        botas = self.create_sellable(description=u'Botas')
        botas.code = u'2'

        ProductHistory(branch=branches[0], sellable=luvas,
                       quantity_produced=1,
                       production_date=datetime.date.today(),
                       store=self.store)
        ProductHistory(branch=branches[0], sellable=luvas,
                       quantity_lost=2,
                       production_date=datetime.date(2012, 1, 1),
                       store=self.store)
        ProductHistory(branch=branches[0], sellable=botas,
                       quantity_lost=3,
                       production_date=datetime.date(2012, 2, 2),
                       store=self.store)

        ProductHistory(branch=branches[1], sellable=luvas,
                       quantity_produced=3,
                       production_date=datetime.date(2012, 3, 3),
                       store=self.store)
        ProductHistory(branch=branches[1], sellable=botas,
                       quantity_lost=4,
                       production_date=datetime.date(2012, 4, 4),
                       store=self.store)
Esempio n. 3
0
    def add_lost(self, quantity):
        """Adds a quantity that was lost. The maximum quantity that can be
        lost is the total quantity minus the quantity already produced.

        :param quantity: the quantity that was lost.
        """
        if self.lost + quantity > self.quantity - self.produced:
            raise ValueError(
                _(u'Can not lost more items than the total production quantity.'
                  ))

        store = self.store
        store.savepoint(u'before_lose')

        for component in self.get_components():
            material = self._get_material_from_component(component)
            try:
                material.add_lost(quantity * component.quantity)
            except ValueError:
                store.rollback_to_savepoint(u'before_lose')
                raise

        self.lost += quantity
        self.order.try_finalize_production()
        ProductHistory.add_lost_item(store, self.order.branch, self)
Esempio n. 4
0
    def confirm(self):
        """Confirms the stock decrease

        """
        assert self.can_confirm()
        assert self.branch

        store = self.store
        branch = self.branch
        for item in self.get_items():
            if item.sellable.product:
                ProductHistory.add_decreased_item(store, branch, item)
            item.decrease(branch)

        old_status = self.status
        self.status = StockDecrease.STATUS_CONFIRMED

        # Save the operation_nature and branch in Invoice Table
        self.invoice.operation_nature = self.operation_nature
        self.invoice.branch = branch

        if self.group:
            self.group.confirm()

        StockOperationConfirmedEvent.emit(self, old_status)
Esempio n. 5
0
    def add_stock_items(self, user: LoginUser):
        """This is normally called from ReceivingOrder when
        a the receving order is confirmed.
        """
        store = self.store
        if self.quantity > self.get_remaining_quantity():
            raise ValueError(u"Quantity received (%d) is greater than "
                             u"quantity ordered (%d)" %
                             (self.quantity, self.get_remaining_quantity()))

        branch = self.receiving_order.branch
        storable = self.sellable.product_storable
        purchase = self.purchase_item.order
        if storable is not None:
            cost = self.cost + (self.ipi_value / self.quantity)
            storable.increase_stock(
                self.quantity,
                branch,
                StockTransactionHistory.TYPE_RECEIVED_PURCHASE,
                self.id,
                user,
                cost,
                batch=self.batch)
        purchase.increase_quantity_received(self.purchase_item, self.quantity)
        ProductHistory.add_received_item(store, branch, self)
Esempio n. 6
0
    def confirm(self):
        """Confirms the stock decrease

        """
        assert self.can_confirm()
        assert self.branch

        store = self.store
        branch = self.branch
        for item in self.get_items():
            if item.sellable.product:
                ProductHistory.add_decreased_item(store, branch, item)
            item.decrease(branch)

        old_status = self.status
        self.status = StockDecrease.STATUS_CONFIRMED

        # Save the operation_nature and branch in Invoice Table
        self.invoice.operation_nature = self.operation_nature
        self.invoice.branch = branch

        if self.group:
            self.group.confirm()

        StockOperationConfirmedEvent.emit(self, old_status)
Esempio n. 7
0
    def send(self):
        """Sends this item to it's destination |branch|"""
        assert self.transfer_order.can_close()

        storable = self.sellable.product_storable
        storable.decrease_stock(self.quantity, self.transfer_order.source_branch,
                                StockTransactionHistory.TYPE_TRANSFER_TO,
                                self.id)
        ProductHistory.add_transfered_item(self.store, self.transfer_order.source_branch, self)
Esempio n. 8
0
    def send_item(self, transfer_item):
        """Sends a |product| of this order to it's destination |branch|"""
        assert self.can_close()

        storable = transfer_item.sellable.product_storable
        storable.decrease_stock(transfer_item.quantity, self.source_branch,
                                StockTransactionHistory.TYPE_TRANSFER_TO,
                                transfer_item.id)
        store = self.store
        ProductHistory.add_transfered_item(store, self.source_branch,
                                           transfer_item)
Esempio n. 9
0
    def send(self):
        """Sends this item to it's destination |branch|"""
        assert self.transfer_order.can_close()

        storable = self.sellable.product_storable
        storable.decrease_stock(self.quantity,
                                self.transfer_order.source_branch,
                                StockTransactionHistory.TYPE_TRANSFER_TO,
                                self.id)
        ProductHistory.add_transfered_item(self.store,
                                           self.transfer_order.source_branch,
                                           self)
Esempio n. 10
0
 def send(self):
     """Sends this item to it's destination |branch|.
     This method should never be used directly, and to send a transfer you
     should use TransferOrder.send().
     """
     storable = self.sellable.product_storable
     storable.decrease_stock(self.quantity,
                             self.transfer_order.source_branch,
                             StockTransactionHistory.TYPE_TRANSFER_TO,
                             self.id, batch=self.batch)
     ProductHistory.add_transfered_item(self.store,
                                        self.transfer_order.source_branch,
                                        self)
Esempio n. 11
0
 def send(self):
     """Sends this item to it's destination |branch|.
     This method should never be used directly, and to send a transfer you
     should use TransferOrder.send().
     """
     storable = self.sellable.product_storable
     storable.decrease_stock(self.quantity,
                             self.transfer_order.source_branch,
                             StockTransactionHistory.TYPE_TRANSFER_TO,
                             self.id,
                             batch=self.batch)
     ProductHistory.add_transfered_item(self.store,
                                        self.transfer_order.source_branch,
                                        self)
Esempio n. 12
0
    def produce(self, quantity, produced_by=None, serials=None):
        """Sets a certain quantity as produced. The quantity will be marked as
        produced only if there are enough materials allocated, otherwise a
        ValueError exception will be raised.

        :param quantity: the quantity that will be produced.
        """
        assert self.can_produce(quantity)

        # check if its ok to produce before consuming material
        if self.product.has_quality_tests():
            # We have some quality tests to assure. Register it for later
            assert produced_by
            assert len(serials) == quantity
            # We only support yield quantity > 1 when there are no tests
            assert self.product.yield_quantity == 1

        self.store.savepoint(u'before_produce')

        for component in self.get_components():
            material = self._get_material_from_component(component)
            needed_material = quantity * component.quantity

            try:
                material.consume(needed_material)
            except ValueError:
                self.store.rollback_to_savepoint(u'before_produce')
                raise

        if self.product.has_quality_tests():
            for serial in serials:
                ProductionProducedItem(store=self.store,
                                       order=self.order,
                                       product=self.product,
                                       produced_by=produced_by,
                                       produced_date=localnow(),
                                       serial_number=serial,
                                       entered_stock=False)
        else:
            # There are no quality tests for this product. Increase stock
            # right now.
            storable = self.product.storable
            # A production process may yield more than one unit of this product
            yield_quantity = quantity * self.product.yield_quantity
            storable.increase_stock(
                yield_quantity, self.order.branch,
                StockTransactionHistory.TYPE_PRODUCTION_PRODUCED, self.id)
        self.produced += quantity
        self.order.try_finalize_production()
        ProductHistory.add_produced_item(self.store, self.order.branch, self)
Esempio n. 13
0
    def produce(self, quantity, produced_by=None, serials=None):
        """Sets a certain quantity as produced. The quantity will be marked as
        produced only if there are enough materials allocated, otherwise a
        ValueError exception will be raised.

        :param quantity: the quantity that will be produced.
        """
        assert self.can_produce(quantity)

        # check if its ok to produce before consuming material
        if self.product.has_quality_tests():
            # We have some quality tests to assure. Register it for later
            assert produced_by
            assert len(serials) == quantity
            # We only support yield quantity > 1 when there are no tests
            assert self.product.yield_quantity == 1

        self.store.savepoint(u'before_produce')

        for component in self.get_components():
            material = self._get_material_from_component(component)
            needed_material = quantity * component.quantity

            try:
                material.consume(needed_material)
            except ValueError:
                self.store.rollback_to_savepoint(u'before_produce')
                raise

        if self.product.has_quality_tests():
            for serial in serials:
                ProductionProducedItem(store=self.store,
                                       order=self.order,
                                       product=self.product,
                                       produced_by=produced_by,
                                       produced_date=localnow(),
                                       serial_number=serial,
                                       entered_stock=False)
        else:
            # There are no quality tests for this product. Increase stock
            # right now.
            storable = self.product.storable
            # A production process may yield more than one unit of this product
            yield_quantity = quantity * self.product.yield_quantity
            storable.increase_stock(yield_quantity, self.order.branch,
                                    StockTransactionHistory.TYPE_PRODUCTION_PRODUCED,
                                    self.id)
        self.produced += quantity
        self.order.try_finalize_production()
        ProductHistory.add_produced_item(self.store, self.order.branch, self)
Esempio n. 14
0
    def confirm(self):
        """Confirms the sale

        """
        assert self.can_confirm()
        assert self.branch

        store = self.store
        branch = self.branch
        for item in self.get_items():
            if item.sellable.product:
                ProductHistory.add_decreased_item(store, branch, item)
            item.decrease(branch)

        self.status = StockDecrease.STATUS_CONFIRMED

        if self.group:
            self.group.confirm()
Esempio n. 15
0
    def confirm(self):
        """Confirms the sale

        """
        assert self.can_confirm()
        assert self.branch

        store = self.store
        branch = self.branch
        for item in self.get_items():
            if item.sellable.product:
                ProductHistory.add_decreased_item(store, branch, item)
            item.decrease(branch)

        self.status = StockDecrease.STATUS_CONFIRMED

        if self.group:
            self.group.confirm()
Esempio n. 16
0
    def add_lost(self, quantity):
        """Adds the quantity lost of this material. The maximum quantity that
        can be lost is given by the formula::

            - max_lost(quantity) = needed - consumed - lost - quantity

        :param quantity: the quantity that was lost.
        """
        assert quantity > 0

        if self.lost + quantity > self.needed - self.consumed:
            raise ValueError(_(u'Cannot loose this quantity.'))

        required = self.consumed + self.lost + quantity
        if required > self.allocated:
            self.allocate(required - self.allocated)

        self.lost += quantity
        store = self.store
        ProductHistory.add_lost_item(store, self.order.branch, self)
Esempio n. 17
0
    def add_lost(self, quantity):
        """Adds the quantity lost of this material. The maximum quantity that
        can be lost is given by the formula::

            - max_lost(quantity) = needed - consumed - lost - quantity

        :param quantity: the quantity that was lost.
        """
        assert quantity > 0

        if self.lost + quantity > self.needed - self.consumed:
            raise ValueError(_(u'Cannot loose this quantity.'))

        required = self.consumed + self.lost + quantity
        if required > self.allocated:
            self.allocate(required - self.allocated)

        self.lost += quantity
        store = self.store
        ProductHistory.add_lost_item(store, self.order.branch, self)
Esempio n. 18
0
    def consume(self, quantity):
        """Consumes a certain quantity of material. The maximum quantity
        allowed to be consumed is given by the following formula:

            - max_consumed(quantity) = needed - consumed - lost - quantity

        :param quantity: the quantity to be consumed.
        """
        assert quantity > 0

        available = self.allocated - self.consumed - self.lost
        if quantity > available:
            raise ValueError(_(u'Can not consume this quantity.'))

        required = self.consumed + self.lost + quantity
        if required > self.allocated:
            self.allocate(required - self.allocated)

        self.consumed += quantity
        store = self.store
        ProductHistory.add_consumed_item(store, self.order.branch, self)
Esempio n. 19
0
    def consume(self, quantity):
        """Consumes a certain quantity of material. The maximum quantity
        allowed to be consumed is given by the following formula:

            - max_consumed(quantity) = needed - consumed - lost - quantity

        :param quantity: the quantity to be consumed.
        """
        assert quantity > 0

        available = self.allocated - self.consumed - self.lost
        if quantity > available:
            raise ValueError(_(u'Can not consume this quantity.'))

        required = self.consumed + self.lost + quantity
        if required > self.allocated:  # pragma nocover
            self.allocate(required - self.allocated)

        self.consumed += quantity
        store = self.store
        ProductHistory.add_consumed_item(store, self.order.branch, self)
Esempio n. 20
0
    def add_lost(self, quantity):
        """Adds a quantity that was lost. The maximum quantity that can be
        lost is the total quantity minus the quantity already produced.

        :param quantity: the quantity that was lost.
        """
        if self.lost + quantity > self.quantity - self.produced:
            raise ValueError(
                _(u'Can not lost more items than the total production quantity.'))

        store = self.store
        store.savepoint(u'before_lose')

        for component in self.get_components():
            material = self._get_material_from_component(component)
            try:
                material.add_lost(quantity * component.quantity)
            except ValueError:
                store.rollback_to_savepoint(u'before_lose')
                raise

        self.lost += quantity
        self.order.try_finalize_production()
        ProductHistory.add_lost_item(store, self.order.branch, self)
Esempio n. 21
0
def apply_patch(store):
    # Creation of new column in stock_decrease table.
    # And added new Cfop to cfop_data table.
    store.execute("""ALTER TABLE stock_decrease
                   ADD COLUMN cfop_id bigint REFERENCES cfop_data(id);""")

    # Default Cfop should be use in manual stock decrease.
    cfop_data = store.find(CfopData, code=u'5.949').one()
    if not cfop_data:
        cfop_data = CfopData(store=store,
                             code=u"5.949",
                             description=u"Outra saída de mercadoria ou "
                             u"prestação de serviço não "
                             u"especificado")

    # Adjusting existing manuals outputs
    for stock_decrease in store.find(StockDecrease):
        stock_decrease.cfop = cfop_data

    retentions = store.execute("""
        SELECT id, quantity, reason, retention_date, product_id, cfop_id
          FROM product_retention_history ORDER BY id;""").get_all()

    # Without retentions, there is no need to create user and employee
    # variables.
    if len(retentions):

        # Default user for migration
        user = get_admin_user(store)
        if user is None:
            users = Person.iselectBy(IUser, is_active=True,
                                     store=store).order_by(Person.id)
            user = users[0]

        # Default employee for migration
        employee = IEmployee(user.person, None)
        if employee is None:
            employees = Person.iselectBy(IEmployee,
                                         is_active=True,
                                         store=store).order_by(Person.id)
            employee = employees[0]

        default_branch = sysparam().MAIN_COMPANY
        notes = _(u"Stock decrease imported from old retention.")

    history = store.execute("""
        SELECT id, quantity_retained, sellable_id, branch_id
          FROM product_history
         WHERE quantity_retained is not null
          ORDER BY id;""").get_all()

    for i in range(len(retentions)):
        ret = retentions[i]
        hist = history[i]

        product = Product.get(ret[4], store=store)

        branch_id = hist[3]
        if ret[1] != hist[1] or product.sellable.id != hist[2]:
            branch_id = default_branch.id

        decrease = StockDecrease(store=store,
                                 confirm_date=ret[3],
                                 status=StockDecrease.STATUS_CONFIRMED,
                                 reason=ret[2],
                                 notes=notes,
                                 responsible=user,
                                 removed_by=employee,
                                 branch_id=branch_id,
                                 cfop_id=ret[5])

        decrease_item = StockDecreaseItem(store=store,
                                          quantity=ret[1],
                                          sellable=product.sellable)
        decrease.add_item(decrease_item)
        store.remove(hist[0])
        ProductHistory(branch_id=branch_id,
                       sellable=product.sellable,
                       quantity_decreased=decrease_item.quantity,
                       decreased_date=decrease.confirm_date,
                       store=store)

    store.execute("""ALTER TABLE product_history
                   DROP COLUMN quantity_retained;""")
    store.execute("DROP TABLE product_retention_history;")
Esempio n. 22
0
def apply_patch(store):
    # Creation of new column in stock_decrease table.
    # And added new Cfop to cfop_data table.
    store.execute("""ALTER TABLE stock_decrease
                   ADD COLUMN cfop_id bigint REFERENCES cfop_data(id);""")

    # Default Cfop should be use in manual stock decrease.
    cfop_data = store.find(CfopData, code=u'5.949').one()
    if not cfop_data:
        cfop_data = CfopData(store=store,
                             code=u"5.949",
                             description=u"Outra saída de mercadoria ou "
                                         u"prestação de serviço não "
                                         u"especificado")

    # Adjusting existing manuals outputs
    for stock_decrease in store.find(StockDecrease):
        stock_decrease.cfop = cfop_data

    retentions = store.execute("""
        SELECT id, quantity, reason, retention_date, product_id, cfop_id
          FROM product_retention_history ORDER BY id;""").get_all()

    # Without retentions, there is no need to create user and employee
    # variables.
    if len(retentions):

        # Default user for migration
        user = get_admin_user(store)
        if user is None:
            users = Person.iselectBy(IUser, is_active=True,
                                     store=store).order_by(Person.id)
            user = users[0]

        # Default employee for migration
        employee = IEmployee(user.person, None)
        if employee is None:
            employees = Person.iselectBy(IEmployee, is_active=True,
                                         store=store).order_by(Person.id)
            employee = employees[0]

        default_branch = sysparam(store).MAIN_COMPANY
        notes = _(u"Stock decrease imported from old retention.")

    history = store.execute("""
        SELECT id, quantity_retained, sellable_id, branch_id
          FROM product_history
         WHERE quantity_retained is not null
          ORDER BY id;""").get_all()

    for i in range(len(retentions)):
        ret = retentions[i]
        hist = history[i]

        product = Product.get(ret[4], store=store)

        branch_id = hist[3]
        if ret[1] != hist[1] or product.sellable.id != hist[2]:
            branch_id = default_branch.id

        decrease = StockDecrease(store=store,
                                 confirm_date=ret[3],
                                 status=StockDecrease.STATUS_CONFIRMED,
                                 reason=ret[2],
                                 notes=notes,
                                 responsible=user,
                                 removed_by=employee,
                                 branch_id=branch_id,
                                 cfop_id=ret[5])

        decrease_item = StockDecreaseItem(store=store,
                                          quantity=ret[1],
                                          sellable=product.sellable)
        decrease.add_item(decrease_item)

        ProductHistory.delete(hist[0], store)
        ProductHistory(branch_id=branch_id, sellable=product.sellable,
                       quantity_decreased=decrease_item.quantity,
                       decreased_date=decrease.confirm_date,
                       store=store)

    store.execute("""ALTER TABLE product_history
                   DROP COLUMN quantity_retained;""")
    store.execute("DROP TABLE product_retention_history;")