Beispiel #1
0
  /**
   * 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;
  }
Beispiel #2
0
  /**
   * 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;
  }
Beispiel #3
0
  /**
   * 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;
  }
Beispiel #4
0
  /**
   * calculates a compensation for each participant from the balance and the all-over cash flow at
   * this point. The sharing policy is taken into account for this calculation. An example: A
   * sharing policy 1:2:3 splits the volume of all the cash flows minus the current total which is
   * the remaining amount among the first, second and third participants out of the sorted list of
   * names. The first portion is 1/6, the second 2/6 and the third is 3/6 of the volume.
   *
   * @return a sorted map containing the names as keys and the compensations as values
   */
  public ShareMap compensations(String sharingPolicy) {
    String[] sortedNames = sortedNames();
    ShareMap cashFlow = cashFlow();
    double volume = cashFlow.sum() - total();

    ShareMap differences = new ShareMap(sortedNames, volume);
    ShareMap sharedCosts = new ShareMap(sortedNames, volume, sharingPolicy);
    differences.minus(sharedCosts.rawMap.values());

    ShareMap compensations = balances().negated();
    compensations.minus(differences.negated().rawMap.values());
    return compensations;
  }