/** * The transaction registers the negated sum of the shares as an expense by a group of * contributors. Additionally all the shares in the map are registered with the same entry id. * Those names in the deals map that are empty <code>String</code> trigger transfers of internal * amounts. Such an internal transfer is not allowed if the transaction causes a negative total. * * @param deals the names of the contributors and their contributions who expended an amount * matching the negated sum of the deals * @param comment a <code>String</code> to make the transaction recognizable * @param shares a <code>ShareMap</code> containing the shares of participants involved * @return the entry id of the transaction or a negative value in case the transaction failed */ public int performComplexExpense(ShareMap deals, String comment, ShareMap shares) { int entryId = -1; int transactionCode = 3; int flags = composeFlags(transactionCode, true); double amount = deals.sum(); if (Math.abs(amount + shares.sum()) < ShareUtil.delta) { if (deals.option != null) switch (deals.option) { default: setDebtLimit(1000. * deals.option); break; } if (deals.rawMap.containsKey(kitty)) entryId = performTransfer(kitty, -deals.rawMap.get(kitty), comment, kitty); else entryId = getNewEntryId(); Collection<String> dealers = ShareUtil.filter(deals.rawMap.keySet(), true, ShareUtil.isKitty); for (String name : dealers) { long rowId = addRecord( entryId, name, deals.rawMap.get(name), currency, Helper.timestampNow(), comment, flags); if (rowId < 0) { entryId = -1; break; } } } else Log.w( TAG, String.format( "the sum of the deals (%f) for '%s' doesn't match the sum of the shares (%f)", amount, comment, shares.sum())); if (entryId > -1) { if (allocate(flags, entryId, shares.rawMap)) { Log.i( TAG, String.format( "entry %d: %s expended %f %s for '%s' shared by %s", entryId, deals.toString(), Math.abs(amount), currency, comment, shares.toString())); } else { removeEntry(entryId); entryId = -1; } } if (entryId < 0) removeEntry(entryId); return entryId; }
/** * The transaction registers the negated sum of the shares with the submitter. Additionally all * the shares in the map are registered with the same entry id. This transaction does not change * the total. It registers an allocation of a certain amount. If submitter is an empty <code> * String</code> it means there is an internal reallocation which is not an expense. Such an * internal reallocation is not allowed if the transaction causes a negative total. * * @param submitter the name of the participant who expended an amount matching the negated sum of * the shares * @param comment a <code>String</code> to make the transaction recognizable * @param shares a <code>ShareMap</code> containing the shares of participants involved * @return the entry id of the transaction or -1 in case the transaction failed or -2 if the * transaction violates the 'no negative total' rule */ public int performExpense(String submitter, String comment, ShareMap shares) { double amount = -shares.sum(); boolean internal = isInternal(submitter); if (internal) { if (breaksDebtLimit(-amount)) return -2; } int transactionCode = 3; int flags = composeFlags(transactionCode, !internal); int entryId = addEntry(submitter, amount, currency, comment, flags); if (entryId < 0) return -1; if (allocate(flags, entryId, shares.rawMap)) { String action = internal ? "reallocation of" : submitter + " expended"; Log.i( TAG, String.format( "entry %d: %s %f %s for '%s' shared by %s", entryId, action, Math.abs(amount), currency, comment, shares.toString())); } else { removeEntry(entryId); entryId = -1; } return entryId; }
/** * The transaction registers multiple submissions. This transaction as a whole is not allowed if * it causes a negative total. * * @param deals a <code>ShareMap</code> containing the deals of participants involved * @param comment a <code>String</code> to make the transactions recognizable * @return the entry id of the transaction or -1 in case the transaction failed or -2 if the * transactions in the sum violate the 'no negative total' rule */ public int performMultiple(ShareMap deals, String comment) { if (breaksDebtLimit(-deals.sum())) return -2; int transactionCode = 4; int flags = composeFlags(transactionCode, false); int entryId = getNewEntryId(); if (entryId > -1) { for (Map.Entry<String, Double> share : deals.rawMap.entrySet()) if (addRecord( entryId, share.getKey(), share.getValue(), currency, Helper.timestampNow(), comment, flags) < 0) { removeEntry(entryId); return -1; } Log.i( TAG, String.format("entry %d: '%s' submissions : %s", entryId, comment, deals.toString())); } return entryId; }