Ejemplo n.º 1
0
    def test_same_sign(self):
        self.assertTrue(number.same_sign(D('135.12345'), D('234.20')))
        self.assertFalse(number.same_sign(D('135.12345'), D('-234.20')))
        self.assertFalse(number.same_sign(D('-135.12345'), D('234.20')))
        self.assertTrue(number.same_sign(D('-135.12345'), D('-234.20')))

        self.assertTrue(number.same_sign(D('135.12345'), ZERO))
        self.assertTrue(number.same_sign(ZERO, D('135.12345')))
        self.assertTrue(number.same_sign(ZERO, ZERO))

        self.assertFalse(number.same_sign(D('-135.12345'), ZERO))
        self.assertFalse(number.same_sign(ZERO, D('-135.12345')))
Ejemplo n.º 2
0
    def score_model(self, model_txn, txn):
        """Score an existing transaction for its ability to provide a model
        for an incomplete transaction.

        Args:
          model_txn: The transaction to be scored.
          txn: The incomplete transaction.
        Returns:
          A float number representing the score, normalized in [0,1].
        """
        def get_description(txn):
            return ('{} {}'.format(txn.payee or '', txn.narration or '')).strip()

        # If the target transaction does not have a description, there is
        # nothing we can do
        txn_description = get_description(txn)
        n_max = len(txn_description)
        if n_max > 1:
            # Only consider model transactions whose posting to the target
            # account has the same sign as the transaction to be completed
            posting = [p for p in model_txn.postings if p.account == self.account][0]
            if number.same_sign(posting.units.number, txn.postings[0].units.number):
                model_txn_description = get_description(model_txn)
                n_match = len(path.commonprefix(
                    [model_txn_description, txn_description]))
                score = float(n_match) / float(n_max)
                return score
        return 0
Ejemplo n.º 3
0
    def score_model(self, model_txn, txn):
        """Score an existing transaction for its ability to provide a model
        for an incomplete transaction.

        Args:
          model_txn: The transaction to be scored.
          txn: The incomplete transaction.
        Returns:
          A float number representing the score, normalized in [0,1].
        """
        def get_description(txn):
            return ('{} {}'.format(txn.payee or '', txn.narration
                                   or '')).strip()

        # If the target transaction does not have a description, there is
        # nothing we can do
        txn_description = get_description(txn)
        n_max = len(txn_description)
        if n_max > 1:
            # Only consider model transactions whose posting to the target
            # account has the same sign as the transaction to be completed
            posting = [
                p for p in model_txn.postings if p.account == self.account
            ][0]
            if number.same_sign(posting.units.number,
                                txn.postings[0].units.number):
                model_txn_description = get_description(model_txn)
                n_match = len(
                    path.commonprefix([model_txn_description,
                                       txn_description]))
                score = float(n_match) / float(n_max)
                return score
        return 0
Ejemplo n.º 4
0
    def add_amount(self, units, cost=None):
        """Add to this inventory using amount and cost. This adds with strict lot
        matching, that is, no partial matches are done on the arguments to the
        keys of the inventory.

        Args:
          units: An Amount instance to add.
          cost: An instance of Cost or None, as a key to the inventory.
        Returns:
          A pair of (position, booking) where 'position' is the position that
          that was modified BEFORE it was modified, and where 'booking' is a
          Booking enum that hints at how the lot was booked to this inventory.
          Position may be None if there is no corresponding Position object,
          e.g. the position was deleted.
        """
        if ASSERTS_TYPES:
            assert isinstance(
                units, Amount), ("Internal error: {!r} (type: {})".format(
                    units,
                    type(units).__name__))
            assert cost is None or isinstance(
                cost, Cost), ("Internal error: {!r} (type: {})".format(
                    cost,
                    type(cost).__name__))

        # Find the position.
        key = (units.currency, cost)
        pos = self.get(key, None)

        if pos is not None:
            # Note: In order to augment or reduce, all the fields have to match.

            # Check if reducing.
            booking = (Booking.REDUCED
                       if not same_sign(pos.units.number, units.number) else
                       Booking.AUGMENTED)

            # Compute the new number of units.
            number = pos.units.number + units.number
            if number == ZERO:
                # If empty, delete the position.
                del self[key]
            else:
                # Otherwise update it.
                self[key] = Position(Amount(number, units.currency), cost)
        else:
            # If not found, create a new one.
            if units.number == ZERO:
                booking = Booking.IGNORED
            else:
                self[key] = Position(units, cost)
                booking = Booking.CREATED

        return pos, booking
Ejemplo n.º 5
0
    def is_reduced_by(self, ramount):
        """Return true if the amount could reduce this inventory.

        Args:
          ramount: An instance of Amount.
        Returns:
          A boolean.
        """
        if ramount.number == ZERO:
            return False
        for position in self:
            units = position.units
            if (ramount.currency == units.currency and
                not same_sign(ramount.number, units.number)):
                return True
        return False