예제 #1
0
    def transfer(self, amount, from_, to, agent, bank=True, subtype=None, date=None, **base_details):
        transfer_id = mk_id()
        if not subtype:
            if bank:
                subtype = "Bank Transfer"
            else:
                subtype = "Budget Transfer"

        assert (
            from_.keys() == to.keys()
        ), "You must specify both from and to values for all changed fields in your transfer"

        if bank:
            assert from_.keys() == ["bank_account"] or set(from_.keys()) == {
                "bank_account",
                "bank_id",
            }, "Bank transfers can only change bank_account, found changes to: " + str(from_.keys())
        else:
            assert "bank_account" not in from_, "bank_account cannot be changed by non-bank transfers"
            base_details["bank_account"] = "Budget Transfer"
            base_details["bank_id"] = None

        if date is None:
            date = datetime.now()

        fromDetails = dict(base_details)
        fromDetails.update(from_)
        toDetails = dict(base_details)
        toDetails.update(to)
        self.add(amount, agent, date=date, external=False, transfer_id=transfer_id, subtype=subtype, **toDetails)
        self.add(-amount, agent, date=date, external=False, transfer_id=transfer_id, subtype=subtype, **fromDetails)
예제 #2
0
 def get_entity_id(self, entity_name):
     if entity_name not in self.entity_cache:
         query = u"select counter_party, counter_party_id, agent, agent_id from {domain} where counter_party = '{name}' or agent = '{name}'"
         query = query.format(name=entity_name.replace("'", "''"), domain=domain.name)
         rs = list(domain.select(query))
         if not rs:
             self.entity_cache[entity_name] = mk_id()
         else:
             assert len(
                 rs) == 1, "Duplicate ids for entity {name}, resolve before adding new transactions for {name}:\n{details}".format(
                 name=entity_name, details=rs)
             if rs[0]['counter_party'] == entity_name:
                 self.entity_cache[entity_name] = rs[0]['counter_party_id']
             elif rs[0]['agent'] == entity_name:
                 self.entity_cache[entity_name] = rs[0]['agent_id']
             else:
                 raise AssertionError(
                     "Unexpected mismatch in entity name {name} not found in  search results:{details}".format(
                         name=entity_name, details=rs))
     return self.entity_cache[entity_name]
예제 #3
0
 def get_entity_id(self, entity_name):
     if entity_name not in self.entity_cache:
         rs = self.select_entity_by_name(entity_name)
         if not rs:
             self.entity_cache[entity_name] = mk_id()
         else:
             assert (
                 len(rs) == 1
             ), "Duplicate ids for entity {name}, resolve before adding new transactions for {name}:\n{details}".format(
                 name=entity_name, details=rs
             )
             if rs[0]["counter_party"] == entity_name:
                 self.entity_cache[entity_name] = rs[0]["counter_party_id"]
             elif rs[0]["agent"] == entity_name:
                 self.entity_cache[entity_name] = rs[0]["agent_id"]
             else:
                 raise AssertionError(
                     "Unexpected mismatch in entity name {name} not found in  search results:{details}".format(
                         name=entity_name, details=rs
                     )
                 )
     return self.entity_cache[entity_name]
예제 #4
0
 def __init__(self, **kwargs):
     super(DictItem, self).__init__(**kwargs)
     self.name = mk_id()
예제 #5
0
 def _create_item(self):
     item = self.domain.new_item(mk_id())
     return item
예제 #6
0
    def add(self, amount, agent, subtype, counter_party=None, event=None, bank_id="Cash", bank_account=None,
            external=True, date=None, effective_date=None, budget_account=None,
            test="", income=None, notes="", tax_inclusive=0, fees=(), state="New", append_event=True, **other_fields):
        if counter_party is None and external:
            if event is None:
                raise TypeError("Either event or counter_party must be specified for external transactions")
            counter_party = "Event:" + event
        if income is None:
            income = amount > 0
        if date is None:
            date = datetime.now()
        elif isinstance(date, str):
            date = dateutil.parser.parse(date)
        if effective_date is None:
            effective_date = date
        elif isinstance(effective_date, str):
            effective_date = dateutil.parser.parse(effective_date)
        if bank_account is None:
            if income:
                if bank_id == "Cash":
                    bank_account = CASH_BOX
                else:
                    bank_account = PRIMARY_CHECKING
            else:
                bank_account = EXPENSE
        if bank_account in self.agent_account_types:
            bank_account = ":".join((agent, bank_account))

        subtype = subtype.title()

        if budget_account is None:
            budget_account = [subtype]
        elif isinstance(budget_account, str):
            budget_account = [budget_account]

        if event and not append_event:
            budget_account.append(event)
        budget_account = ":".join(budget_account)

        if tax_inclusive is True:
            tax_inclusive = amount
            # for now
        other_fields['tax_inclusive'] = tax_inclusive
        if tax_inclusive > 0:
            assert external and income, "Tax may only be collected on external sales"

        item = self.domain.new_item(mk_id())

        item['amount'] = encode(Decimal(amount))
        item['agent'] = encode(agent)
        item['agent_id'] = self.get_entity_id(agent)
        item['counter_party'] = encode(counter_party)
        item['counter_party_id'] = self.get_entity_id(counter_party)
        if event:
            item['event'] = event
        item['bank_account'] = encode(bank_account)
        item['budget_account'] = encode(budget_account)
        item['external'] = encode(external)
        item['date'] = encode(date)
        item['effective_date'] = encode(effective_date)
        item['entered'] = encode(datetime.now())
        item['modified'] = encode(datetime.now())
        item['type'] = encode("Income" if income else "Expense")
        item['subtype'] = encode(subtype)
        item['bank_id'] = unicode(bank_id)
        item['notes'] = encode(notes)
        item['test'] = encode(test)
        item['state'] = encode(state)

        for key, value in other_fields.iteritems():
            item[key] = encode(value)

        item['posted'] = ""

        item.save()

        other_fields.pop("tax_inclusive") #fees are not tax inclusive
        for fee in fees:
            if len(fee) == 3:
                fee_amount, fee_cpty, bank_id = fee
            else:
                fee_amount, fee_cpty = fee
            self.add(-fee_amount, agent, subtype="Fees:" + fee_cpty, counter_party=fee_cpty, event=event,
                bank_id=bank_id, bank_account=bank_account,
                external=True, date=date, test=test, income=False,
                fee_for=item.name, **other_fields)

        return item.name