예제 #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)
예제 #2
0
    def test_CreateSettlementTransfer(self):
        dispute = None
        for d in self._client_disputes:
            if d.status == 'CLOSED' and d.dispute_type == 'NOT_CONTESTABLE':
                dispute = d
                break

        self.assertIsNotNone(
            dispute,
            'Cannot test creating settlement transfer because there\'s no closed and not contestable disputes in the disputes list.'
        )

        repudiation = dispute.transactions.all()[0]

        self.assertIsNotNone(repudiation)

        debit_funds = Money()
        fees = Money()
        debit_funds.currency = 'EUR'
        debit_funds.amount = 1
        fees.currency = 'EUR'
        fees.amount = 0

        st = SettlementTransfer()
        st.author = repudiation.author
        st.debited_funds = debit_funds
        st.fees = fees
        st.repudiation_id = repudiation.id
        result = st.save()

        self.assertIsNotNone(result)
        self.assertEqual(result['author_id'], st.author.id)
예제 #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)
    def test_CreateSettlementTransfer(self):
        dispute = None
        for d in self._client_disputes:
            if d.status == 'CLOSED' and d.dispute_type == 'NOT_CONTESTABLE':
                dispute = d
                break

        self.assertIsNotNone(dispute, 'Cannot test creating settlement transfer because there\'s no closed and not contestable disputes in the disputes list.')

        repudiation = dispute.transactions.all()[0]

        self.assertIsNotNone(repudiation)

        debit_funds = Money()
        fees = Money()
        debit_funds.currency = 'EUR'
        debit_funds.amount = 1
        fees.currency = 'EUR'
        fees.amount = 0

        st = SettlementTransfer()
        st.author = repudiation.author
        st.debited_funds = debit_funds
        st.fees = fees
        st.repudiation_id = repudiation.id
        result = st.save()

        self.assertIsNotNone(result)
        self.assertEqual(result['author_id'], st.author.id)
예제 #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)