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)
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]
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]
def __init__(self, **kwargs): super(DictItem, self).__init__(**kwargs) self.name = mk_id()
def _create_item(self): item = self.domain.new_item(mk_id()) return item
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