Exemplo n.º 1
0
def recover_lost_funds(db, exchange, lost_amount, repudiation_id):
    """Recover as much money as possible from a payin which has been reverted.
    """
    original_owner = exchange.participant
    # Try (again) to swap the disputed bundles
    with db.get_cursor() as cursor:
        cursor.run("LOCK TABLE cash_bundles IN EXCLUSIVE MODE")
        disputed_bundles = [
            NS(d._asdict()) for d in cursor.all(
                """
            SELECT *
              FROM cash_bundles
             WHERE origin = %s
               AND disputed = true
        """, (exchange.id, ))
        ]
        bundles_sum = sum(b.amount for b in disputed_bundles)
        assert bundles_sum == lost_amount - exchange.fee
        for b in disputed_bundles:
            if b.owner == original_owner:
                continue
            try_to_swap_bundle(cursor, b, original_owner)
    # Move the funds back to the original wallet
    currency = exchange.amount.currency
    chargebacks_account, credit_wallet = Participant.get_chargebacks_account(
        currency)
    LiberapayOrg = Participant.from_username('LiberapayOrg')
    assert LiberapayOrg
    return_payin_bundles_to_origin(db,
                                   exchange,
                                   LiberapayOrg,
                                   create_debts=True)
    # Add a debt for the fee
    create_debt(db, original_owner, LiberapayOrg.id, exchange.fee, exchange.id)
    # Send the funds to the credit wallet
    # We have to do a SettlementTransfer instead of a normal Transfer. The amount
    # can't exceed the original payin amount, so we can't settle the fee debt.
    original_owner = Participant.from_id(original_owner)
    from_wallet = original_owner.get_current_wallet(currency).remote_id
    to_wallet = credit_wallet.remote_id
    t_id = prepare_transfer(
        db,
        original_owner.id,
        chargebacks_account.id,
        exchange.amount,
        'chargeback',
        from_wallet,
        to_wallet,
        prefer_bundles_from=exchange.id,
    )
    tr = SettlementTransfer()
    tr.AuthorId = original_owner.mangopay_user_id
    tr.CreditedUserId = chargebacks_account.mangopay_user_id
    tr.CreditedWalletId = to_wallet
    tr.DebitedFunds = exchange.amount.int()
    tr.DebitedWalletId = from_wallet
    tr.Fees = Money(0, currency)
    tr.RepudiationId = repudiation_id
    tr.Tag = str(t_id)
    return execute_transfer(db, t_id, tr)
Exemplo n.º 2
0
def return_payin_bundles_to_origin(db,
                                   exchange,
                                   last_resort_payer,
                                   create_debts=True):
    """Transfer money linked to a specific payin back to the original owner.
    """
    currency = exchange.amount.currency
    chargebacks_account = Participant.get_chargebacks_account(currency)[0]
    original_owner = exchange.participant
    origin_wallet = db.one("SELECT * FROM wallets WHERE remote_id = %s",
                           (exchange.wallet_id, ))
    transfer_kw = dict(
        tippee_wallet_id=origin_wallet.remote_id,
        tippee_mango_id=origin_wallet.remote_owner_id,
    )
    payin_bundles = [
        NS(d._asdict()) for d in db.all(
            """
        SELECT *
          FROM cash_bundles
         WHERE origin = %s
           AND disputed = true
    """, (exchange.id, ))
    ]
    grouped = group_by(payin_bundles, lambda b: (b.owner, b.withdrawal))
    for (current_owner, withdrawal), bundles in grouped.items():
        assert current_owner != chargebacks_account.id
        if current_owner == original_owner:
            continue
        amount = sum(b.amount for b in bundles)
        if current_owner is None:
            if not last_resort_payer or not create_debts:
                continue
            bundles = None
            withdrawer = db.one(
                "SELECT participant FROM exchanges WHERE id = %s",
                (withdrawal, ))
            payer = last_resort_payer.id
            create_debt(db, withdrawer, payer, amount, exchange.id)
            create_debt(db, original_owner, withdrawer, amount, exchange.id)
        else:
            bundles = [b.id for b in bundles]
            payer = current_owner
            if create_debts:
                create_debt(db, original_owner, payer, amount, exchange.id)
        transfer(db,
                 payer,
                 original_owner,
                 amount,
                 'chargeback',
                 bundles=bundles,
                 **transfer_kw)
Exemplo n.º 3
0
def recover_lost_funds(db, exchange, lost_amount, repudiation_id):
    """Recover as much money as possible from a payin which has been reverted.
    """
    original_owner = exchange.participant
    # Try (again) to swap the disputed bundles
    with db.get_cursor() as cursor:
        cursor.run("LOCK TABLE cash_bundles IN EXCLUSIVE MODE")
        disputed_bundles = [NS(d._asdict()) for d in cursor.all("""
            SELECT *
              FROM cash_bundles
             WHERE origin = %s
               AND disputed = true
        """, (exchange.id,))]
        bundles_sum = sum(b.amount for b in disputed_bundles)
        assert bundles_sum == lost_amount - exchange.fee
        for b in disputed_bundles:
            if b.owner == original_owner:
                continue
            try_to_swap_bundle(cursor, b, original_owner)
    # Move the funds back to the original wallet
    currency = exchange.amount.currency
    chargebacks_account, credit_wallet = Participant.get_chargebacks_account(currency)
    LiberapayOrg = Participant.from_username('LiberapayOrg')
    assert LiberapayOrg
    return_payin_bundles_to_origin(db, exchange, LiberapayOrg, create_debts=True)
    # Add a debt for the fee
    create_debt(db, original_owner, LiberapayOrg.id, exchange.fee, exchange.id)
    # Send the funds to the credit wallet
    # We have to do a SettlementTransfer instead of a normal Transfer. The amount
    # can't exceed the original payin amount, so we can't settle the fee debt.
    original_owner = Participant.from_id(original_owner)
    from_wallet = original_owner.get_current_wallet(currency).remote_id
    to_wallet = credit_wallet.remote_id
    t_id = prepare_transfer(
        db, original_owner.id, chargebacks_account.id, exchange.amount, 'chargeback',
        from_wallet, to_wallet, prefer_bundles_from=exchange.id,
    )
    tr = SettlementTransfer()
    tr.AuthorId = original_owner.mangopay_user_id
    tr.CreditedUserId = chargebacks_account.mangopay_user_id
    tr.CreditedWalletId = to_wallet
    tr.DebitedFunds = Money_to_cents(exchange.amount)
    tr.DebitedWalletId = from_wallet
    tr.Fees = Money(0, currency)
    tr.RepudiationId = repudiation_id
    tr.Tag = str(t_id)
    return execute_transfer(db, t_id, tr)
Exemplo n.º 4
0
def return_payin_bundles_to_origin(db, exchange, last_resort_payer, create_debts=True):
    """Transfer money linked to a specific payin back to the original owner.
    """
    currency = exchange.amount.currency
    chargebacks_account = Participant.get_chargebacks_account(currency)[0]
    original_owner = exchange.participant
    origin_wallet = db.one("SELECT * FROM wallets WHERE remote_id = %s", (exchange.wallet_id,))
    transfer_kw = dict(
        tippee_wallet_id=origin_wallet.remote_id,
        tippee_mango_id=origin_wallet.remote_owner_id,
    )
    payin_bundles = [NS(d._asdict()) for d in db.all("""
        SELECT *
          FROM cash_bundles
         WHERE origin = %s
           AND disputed = true
    """, (exchange.id,))]
    grouped = group_by(payin_bundles, lambda b: (b.owner, b.withdrawal))
    for (current_owner, withdrawal), bundles in grouped.items():
        assert current_owner != chargebacks_account.id
        if current_owner == original_owner:
            continue
        amount = sum(b.amount for b in bundles)
        if current_owner is None:
            if not last_resort_payer or not create_debts:
                continue
            bundles = None
            withdrawer = db.one("SELECT participant FROM exchanges WHERE id = %s", (withdrawal,))
            payer = last_resort_payer.id
            create_debt(db, withdrawer, payer, amount, exchange.id)
            create_debt(db, original_owner, withdrawer, amount, exchange.id)
        else:
            bundles = [b.id for b in bundles]
            payer = current_owner
            if create_debts:
                create_debt(db, original_owner, payer, amount, exchange.id)
        transfer(db, payer, original_owner, amount, 'chargeback', bundles=bundles, **transfer_kw)
Exemplo n.º 5
0
def recover_lost_funds(db, exchange, lost_amount, repudiation_id):
    """Recover as much money as possible from a payin which has been reverted.
    """
    original_owner = exchange.participant
    # Try (again) to swap the disputed bundles
    with db.get_cursor() as cursor:
        cursor.run("LOCK TABLE cash_bundles IN EXCLUSIVE MODE")
        disputed_bundles = [
            NS(d._asdict()) for d in cursor.all(
                """
            SELECT *
              FROM cash_bundles
             WHERE origin = %s
               AND disputed = true
        """, (exchange.id, ))
        ]
        bundles_sum = sum(b.amount for b in disputed_bundles)
        assert bundles_sum == lost_amount - exchange.fee
        for b in disputed_bundles:
            if b.owner == original_owner:
                continue
            try_to_swap_bundle(cursor, b, original_owner)
    # Move the funds back to the original wallet
    chargebacks_account = Participant.get_chargebacks_account()
    LiberapayOrg = Participant.from_username('LiberapayOrg')
    assert LiberapayOrg
    grouped = group_by(disputed_bundles, lambda b: (b.owner, b.withdrawal))
    for (owner, withdrawal), bundles in grouped.items():
        assert owner != chargebacks_account.id
        if owner == original_owner:
            continue
        amount = sum(b.amount for b in bundles)
        if owner is None:
            bundles = None
            withdrawer = db.one(
                "SELECT participant FROM exchanges WHERE id = %s",
                (withdrawal, ))
            payer = LiberapayOrg.id
            create_debt(db, withdrawer, payer, amount, exchange.id)
            create_debt(db, original_owner, withdrawer, amount, exchange.id)
        else:
            payer = owner
            create_debt(db, original_owner, payer, amount, exchange.id)
        transfer(db,
                 payer,
                 original_owner,
                 amount,
                 'chargeback',
                 bundles=bundles)
    # Add a debt for the fee
    create_debt(db, original_owner, LiberapayOrg.id, exchange.fee, exchange.id)
    # Send the funds to the credit wallet
    # We have to do a SettlementTransfer instead of a normal Transfer. The amount
    # can't exceed the original payin amount, so we can't settle the fee debt.
    original_owner = Participant.from_id(original_owner)
    t_id = prepare_transfer(
        db,
        original_owner.id,
        chargebacks_account.id,
        exchange.amount,
        'chargeback',
        original_owner.mangopay_wallet_id,
        chargebacks_account.mangopay_wallet_id,
        prefer_bundles_from=exchange.id,
    )
    tr = SettlementTransfer()
    tr.AuthorId = original_owner.mangopay_user_id
    tr.CreditedUserId = chargebacks_account.mangopay_user_id
    tr.CreditedWalletId = chargebacks_account.mangopay_wallet_id
    tr.DebitedFunds = Money(int(exchange.amount * 100), 'EUR')
    tr.DebitedWalletId = original_owner.mangopay_wallet_id
    tr.Fees = Money(0, 'EUR')
    tr.RepudiationId = repudiation_id
    tr.Tag = str(t_id)
    tr.save()
    return record_transfer_result(db, t_id, tr)