Exemple #1
0
def share_expense_with_group_members(sw: Splitwise, desc, cost, group_id,
                                     date):
    grp = sw.getGroup(group_id)
    current_user = sw.getCurrentUser()
    other_members = [m for m in grp.getMembers() if m.id != current_user.id]
    _debug(current_user)
    _debug(other_members)
    cost_per_user = round(cost / len(grp.members), 2)

    expense = Expense()
    expense.cost = f"{cost}"
    expense.description = f"{desc}"
    expense.group_id = f"{group_id}"
    expense.setDate(date.strftime("%Y/%m/%d"))

    users = []
    for om in other_members:
        user = ExpenseUser()
        user.setId(om.id)
        user.setPaidShare(f"0")
        user.setOwedShare(f"{cost_per_user}")
        users.append(user)
    user = ExpenseUser()
    user.setId(current_user.id)
    user.setPaidShare(f"{cost}")
    user.setOwedShare(f"{cost - len(users) * cost_per_user}")
    users.append(user)
    expense.users = users
    sw.createExpense(expense)
 def test_expense_invalidkeys_fail(self):
     sObj = Splitwise('consumerkey', 'consumersecret', {
         "oauth_token": "sdsd",
         "oauth_token_secret": "sdsdd"
     })
     expense = Expense()
     with self.assertRaises(SplitwiseUnauthorizedException):
         sObj.createExpense(expense)
Exemple #3
0
def addMoney(friendName, currency, expenseReason):
    speech = "hello"
    print "name =", friendName
    print currency
    print "inside add money"
    if not friendName or not currency:
        print "error in name or currency"
        return tell("sorry couldn't proceed with transaction")

    consumer_key = ''
    consumer_secret = ''
    sObj = Splitwise(consumer_key, consumer_secret)

    with open('accesstoken.json', 'r') as f:
        access_token = json.load(f)
        print access_token
    sObj.setAccessToken(access_token)

    amountOwed = currency['amount']
    expense = Expense()
    expense.setCost(amountOwed)
    expense.setDescription(expenseReason)

    user1 = ExpenseUser()
    user1.setId(utils.getSplitwiseId('nirmit'))
    user1.setPaidShare(str(amountOwed))
    user1.setOwedShare('0.0')

    user2 = ExpenseUser()
    user2.setId(utils.getSplitwiseId(friendName))
    user2.setPaidShare('0.00')
    user2.setOwedShare(str(amountOwed))

    users = []
    users.append(user1)
    users.append(user2)
    expense.setUsers(users)

    expense = sObj.createExpense(expense)
    print expense
class ExpenseTestCase(unittest.TestCase):
    def setUp(self):
        consumer_key = os.environ['CONSUMER_KEY']
        consumer_secret = os.environ['CONSUMER_SECRET']
        oauth_token = os.environ['OAUTH_TOKEN']
        oauth_token_secret = os.environ['OAUTH_TOKEN_SECRET']

        self.sObj = Splitwise(consumer_key, consumer_secret)
        self.sObj.setAccessToken({
            'oauth_token': oauth_token,
            'oauth_token_secret': oauth_token_secret
        })

    def test_expense_flow(self):
        receipt = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                               "receipt.jpg")
        expense = Expense()
        expense.setDescription("End2EndTest")
        expense.setCost('10')
        expense.setGroupId(19571167)
        expense.setSplitEqually()
        expense.setReceipt(receipt)
        # create expense
        expense, error = self.sObj.createExpense(expense)
        self.assertIsNone(error)
        self.assertIsNotNone(expense.getId())
        # delete expense
        success, error = self.sObj.deleteExpense(expense.getId())
        self.assertIsNone(error)
        self.assertTrue(success)

    def test_expense_invalidkeys_fail(self):
        sObj = Splitwise('consumerkey', 'consumersecret', {
            "oauth_token": "sdsd",
            "oauth_token_secret": "sdsdd"
        })
        expense = Expense()
        with self.assertRaises(SplitwiseUnauthorizedException):
            sObj.createExpense(expense)
Exemple #5
0
def transaction(Description, Group, Payer, Price, Contributors):
    # price, date, description, group ID or this particular groups name, members
    sObj = Splitwise(consumer_key, secret_key)
    sObj.setAccessToken(session['access_token'])
    user = sObj.getCurrentUser()
    groups = sObj.getGroups()
    group_dict = {group.getName(): group for group in groups}
    importedData = {'Date': datetime.datetime.now(), 'Description': Description, 'Group': Group, 'Payer': Payer, 'Debit': Price}
    expense = Expense()
    price = float(importedData['Debit'] or 0)
    expense.setCost(price)
    expense.setDate(importedData['Date'])
    expense.setDescription(importedData['Description'])
    expense.setGroupId(group_dict[importedData['Group']].getId())
    members = group_dict[importedData['Group']].getMembers()
    users = []
    contributors = Contributors
    for member in members:
        if member.getFirstName() in contributors:
            user = ExpenseUser()
            user.setId(member.getId())
            if member.getFirstName() == importedData['Payer']:
                user.setPaidShare(price)
            else:
                user.setPaidShare(0)
            users.append(user)
    paid = 0
    share = round(price/len(users), 2)
    for user in users:
        user.setOwedShare(share)
        paid = paid + share
    diff = price - paid
    if diff != 0:
        user = random.choice(users)
        user.setOwedShare(share + diff)
    expense.setUsers(users)
    expense = sObj.createExpense(expense)
Exemple #6
0
def submission():
    global df
    # TODO: add checks beforehand whether the user has clicked on all checkboxes
    # print(request.form)

    sObj = Splitwise(Config.consumer_key,Config.consumer_secret)
    sObj.setAccessToken(session['access_token'])

    saleh = ExpenseUser()
    saleh.setId(2242086)
    paypal = ExpenseUser()
    paypal.setId(18572820)
    nuraini = ExpenseUser()
    nuraini.setId(2705458)

    for key in request.form:
        if not is_number(key):
            continue
        value = request.form[key]
        if value == 'Payment':
            continue # we dont handle payments yet
        print(key, value)
        amount = df.iloc[int(float(key))]['Amount']
        users = []
        users.append(saleh)
        users.append(paypal)
        users.append(nuraini)
        saleh.setPaidShare('0.00')
        nuraini.setPaidShare('0.00')
        paypal.setPaidShare('0.00')
            
        saleh.setOwedShare('0.00')
        nuraini.setOwedShare('0.00')
        paypal.setOwedShare('0.00')

        expense = Expense()
        expense.setUsers(users)
        expense.setGroupId(6456733)
        expense.setCost(str(abs(float(amount))))
        expense.setDescription(df.iloc[int(float(key))]['Description'])

        try:
            expense.setDate(datetime.datetime.strptime(df.iloc[int(float(key))]['Trans Date'], '%m/%d/%Y').strftime('%d/%m/%Y'))
        except:
            expense.setDate(datetime.datetime.strptime(df.iloc[int(float(key))]['Trans Date'], '%m/%d/%y').strftime('%d/%m/%Y'))

        # case where a transaction is refunded
        if float(amount) > 0:
            if value == 'Saleh':
                paypal.setOwedShare(str(abs(float(amount))))
                saleh.setPaidShare(str(abs(float(amount))))
            elif value == 'Nuraini':
                paypal.setOwedShare(str(abs(float(amount))))
                nuraini.setPaidShare(str(abs(float(amount))))   
            expense = sObj.createExpense(expense)
            continue

        # case for expenses
        if value == 'Saleh':
            saleh.setOwedShare(str(abs(float(amount))))
            paypal.setPaidShare(str(abs(float(amount))))
            expense = sObj.createExpense(expense)
        elif value == 'Nuraini':
            nuraini.setOwedShare(str(abs(float(amount))))
            paypal.setPaidShare(str(abs(float(amount))))
            expense = sObj.createExpense(expense)
        elif value == 'Half-Split':
            half = round(abs(float(amount))/2,2)
            other_half = abs(float(amount))-half
            nuraini.setOwedShare(half)
            saleh.setOwedShare(other_half)
            paypal.setPaidShare(str(abs(float(amount))))
            expense = sObj.createExpense(expense)
        elif value == 'Share':
            
            continue
    
    return redirect(url_for("success"))
Exemple #7
0
class SplitwiseInterface:
    def __init__(self):
        self.consumer_key = getConsumerKey()
        self.consumer_secret = getConsumerSecret()
        self.oauth_verifier = None
        self.oauth_token = None
        self.access_token = getAccessToken()
        self.login_secret = None
        self.url = None
        self.sObj = Splitwise(self.consumer_key, self.consumer_secret)
        self.sObj.setAccessToken(self.access_token)

    def accessCheck(self) -> None:
        """
        Checks for access token. Starts login process if not
        """

        if self.access_token:
            return
        self.access_token = self.login()

    def login(self) -> None:
        """
        Logs into Splitwise. Requires manually entering the token and verifier
        """

        sObj = Splitwise(self.consumer_key, self.consumer_secret)
        self.url, self.login_secret = sObj.getAuthorizeURL()
        print(self.url)
        self.oauth_token = input('token: ')
        self.oauth_verifier = input('verifier: ')

    def authorize(self) -> None:
        """
        Authorizes app to Splitwise
        """

        if not self.login_secret:
            #TODO trigger error
            self.login()

        sObj = Splitwise(self.consumer_key, self.consumer_secret)
        self.access_token = sObj.getAccessToken(self.oauth_token,
                                                self.login_secret,
                                                self.oauth_verifier)

    def friends(self) -> List['Friend']:
        """
        Returns list of Friend objects for the current user
        """

        return self.sObj.getFriends()

    def getCurrentUser(self) -> 'CurrentUser':
        """
        Returns CurrentUser object for the current user
        """
        return self.sObj.getCurrentUser()

    def getGroup(self, group_id: int) -> 'Group':
        """
        Returns Group object for the given group_id
        """
        return self.sObj.getGroup(group_id)

    def getGroupMemberIDs(self, group: 'Group') -> Dict[str, int]:
        """
        Returns a dict of group members {name:id} from a given Group object
        """
        member_object_list = group.getMembers()
        member_dict = {}
        for member in member_object_list:
            member_dict[member.getFirstName()] = member.getId()
        return member_dict

    def addExpense(self, cost: float, description: str, group_id: int,
                   payer: str) -> None:
        """
        Adds expense to Splitwise group. If expenses don't evenly get 
        distributed, it will randomly assign pennies to even things off
        """
        expense = Expense()
        expense.setCost(str(cost))
        expense.setDescription(description)
        expense.setGroupId(group_id)

        group = self.sObj.getGroup(group_id)
        member_dict = self.getGroupMemberIDs(group)
        member_count = len(member_dict)
        per_person_cost = round(cost / member_count, 2)
        expense_members = []
        print(per_person_cost * member_count, cost)
        for member in member_dict:
            expense_user = ExpenseUser()
            expense_user.setId(member_dict[member])
            expense_user.setFirstName(member)
            expense_user.setOwedShare(str(per_person_cost))

            if member == payer:
                expense_user.setPaidShare(cost)
            else:
                expense_user.setPaidShare('0.00')

            expense_members.append(expense_user)

        if cost < per_person_cost * member_count:
            remainder = (per_person_cost * float(member_count)) - cost
            shuffle(expense_members)
            i = 0
            while remainder > 0.00:
                owed = float(expense_members[i].getOwedShare())
                owed -= 0.01
                expense_members[i].setOwedShare(str(owed))
                remainder -= 0.01
                if i == member_count - 1:
                    i = 0
                else:
                    i += 1

        elif cost > per_person_cost * member_count:
            remainder = round(cost - (per_person_cost * float(member_count)),
                              2)
            print(remainder)
            shuffle(expense_members)
            i = 0
            while remainder > 0.00:
                owed = float(expense_members[i].getOwedShare())
                owed += 0.01
                expense_members[i].setOwedShare(str(owed))
                remainder -= 0.01
                if i == member_count - 1:
                    i = 0
                else:
                    i += 1

        expense.setUsers(expense_members)
        expenses = self.sObj.createExpense(expense)
        print('Successfully added to Splitwise. Expense ID:', expenses.getId())
Exemple #8
0
class CreateExpenseTestCase(unittest.TestCase):
    def setUp(self):
        self.sObj = Splitwise('consumerkey', 'consumersecret')

    @patch('io.open')
    def test_createExpense_split_equally_with_receipt_success(
            self, mockOpen, mockMakeRequest):
        mockFile = MagicMock()
        mockOpen.return_value = mockFile
        mockMakeRequest.return_value = '{"expenses":[{"id":1010906976,"group_id":19433671,"friendship_id":null,"expense_bundle_id":null,"description":"Testing","repeats":false,"repeat_interval":"never","email_reminder":false,"email_reminder_in_advance":-1,"next_repeat":null,"details":null,"comments_count":0,"payment":false,"creation_method":null,"transaction_method":"offline","transaction_confirmed":false,"transaction_id":null,"cost":"10.0","currency_code":"SGD","repayments":[{"from":643871,"to":79774,"amount":"5.0"}],"date":"2020-06-24T06:57:29Z","created_at":"2020-06-24T06:57:29Z","created_by":{"id":79774,"first_name":"Naman","last_name":"Aggarwal","picture":{"medium":"https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"},"custom_picture":true},"updated_at":"2020-06-24T06:57:29Z","updated_by":null,"deleted_at":null,"deleted_by":null,"category":{"id":18,"name":"General"},"receipt":{"large":null,"original":null},"users":[{"user":{"id":79774,"first_name":"Naman","last_name":"Aggarwal","picture":{"medium":"https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"}},"user_id":79774,"paid_share":"10.0","owed_share":"5.0","net_balance":"5.0"},{"user":{"id":643871,"first_name":"Shantanu","last_name":"Alshi","picture":{"medium":"https://s3.amazonaws.com/splitwise/uploads/user/default_avatars/avatar-blue19-100px.png"}},"user_id":643871,"paid_share":"0.0","owed_share":"5.0","net_balance":"-5.0"}]}],"errors":{}}'  # noqa: E501
        expense = Expense()
        expense.setCost('10')
        expense.setDescription("Testing")
        expense.setGroupId(19433671)
        expense.setSplitEqually()
        expense.setReceipt("temp.jpg")
        expenseRes, errors = self.sObj.createExpense(expense)
        mockMakeRequest.assert_called_with(
            "https://secure.splitwise.com/api/v3.0/create_expense",
            "POST", {
                'cost': '10',
                'description': 'Testing',
                'group_id': 19433671,
                'split_equally': True,
                'receiptPath': 'temp.jpg'
            },
            files={'receipt': mockFile})
        self.assertIsNone(errors)
        self.assertEqual(expenseRes.getId(), 1010906976)
        self.assertEqual(expenseRes.getGroupId(), 19433671)
        self.assertEqual(expenseRes.getFriendshipId(), None)
        self.assertEqual(expenseRes.getExpenseBundleId(), None)
        self.assertEqual(expenseRes.getDescription(), "Testing")
        self.assertEqual(expenseRes.getRepeatInterval(), "never")
        self.assertEqual(expenseRes.getEmailReminderInAdvance(), -1)
        self.assertEqual(expenseRes.getNextRepeat(), None)
        self.assertEqual(expenseRes.getDetails(), None)
        self.assertEqual(expenseRes.getCommentsCount(), 0)
        self.assertEqual(expenseRes.getCreationMethod(), None)
        self.assertEqual(expenseRes.getTransactionMethod(), "offline")
        self.assertEqual(expenseRes.getTransactionId(), None)
        self.assertEqual(expenseRes.getCost(), "10.0")
        self.assertEqual(expenseRes.getCurrencyCode(), "SGD")
        self.assertEqual(len(expenseRes.getRepayments()), 1)
        self.assertEqual(expenseRes.getRepayments()[0].getFromUser(), 643871)
        self.assertEqual(expenseRes.getRepayments()[0].getToUser(), 79774)
        self.assertEqual(expenseRes.getRepayments()[0].getAmount(), "5.0")
        self.assertEqual(expenseRes.getDate(), "2020-06-24T06:57:29Z")
        self.assertEqual(expenseRes.getCreatedAt(), "2020-06-24T06:57:29Z")
        self.assertEqual(expenseRes.getCreatedBy().getId(), 79774)
        self.assertEqual(expenseRes.getCreatedBy().getFirstName(), "Naman")
        self.assertEqual(expenseRes.getCreatedBy().getLastName(), "Aggarwal")
        self.assertEqual(
            expenseRes.getCreatedBy().getPicture().getMedium(),
            "https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"
        )
        self.assertEqual(expenseRes.getUpdatedAt(), "2020-06-24T06:57:29Z")
        self.assertEqual(expenseRes.getUpdatedBy(), None)
        self.assertEqual(expenseRes.getDeletedAt(), None)
        self.assertEqual(expenseRes.getDeletedBy(), None)
        self.assertEqual(expenseRes.getCategory().getId(), 18)
        self.assertEqual(expenseRes.getCategory().getName(), "General")
        self.assertEqual(expenseRes.getReceipt().getLarge(), None)
        self.assertEqual(expenseRes.getReceipt().getOriginal(), None)
        self.assertEqual(len(expenseRes.getUsers()), 2)
        self.assertEqual(expenseRes.getUsers()[0].getId(), 79774)
        self.assertEqual(expenseRes.getUsers()[0].getFirstName(), "Naman")
        self.assertEqual(expenseRes.getUsers()[0].getLastName(), "Aggarwal")
        self.assertEqual(
            expenseRes.getUsers()[0].getPicture().getMedium(),
            "https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"
        )
        self.assertEqual(expenseRes.getUsers()[0].getPaidShare(), "10.0")
        self.assertEqual(expenseRes.getUsers()[0].getOwedShare(), "5.0")
        self.assertEqual(expenseRes.getUsers()[0].getNetBalance(), "5.0")
        self.assertEqual(expenseRes.getUsers()[1].getId(), 643871)
        self.assertEqual(expenseRes.getUsers()[1].getFirstName(), "Shantanu")
        self.assertEqual(expenseRes.getUsers()[1].getLastName(), "Alshi")
        self.assertEqual(
            expenseRes.getUsers()[1].getPicture().getMedium(),
            "https://s3.amazonaws.com/splitwise/uploads/user/default_avatars/avatar-blue19-100px.png"
        )
        self.assertEqual(expenseRes.getUsers()[1].getPaidShare(), "0.0")
        self.assertEqual(expenseRes.getUsers()[1].getOwedShare(), "5.0")
        self.assertEqual(expenseRes.getUsers()[1].getNetBalance(), "-5.0")
        mockOpen.assert_called_with("temp.jpg", "rb")

    def test_createExpense_split_equally_success(self, mockMakeRequest):
        mockMakeRequest.return_value = '{"expenses":[{"id":1010906976,"group_id":19433671,"friendship_id":null,"expense_bundle_id":null,"description":"Testing","repeats":false,"repeat_interval":"never","email_reminder":false,"email_reminder_in_advance":-1,"next_repeat":null,"details":null,"comments_count":0,"payment":false,"creation_method":null,"transaction_method":"offline","transaction_confirmed":false,"transaction_id":null,"cost":"10.0","currency_code":"SGD","repayments":[{"from":643871,"to":79774,"amount":"5.0"}],"date":"2020-06-24T06:57:29Z","created_at":"2020-06-24T06:57:29Z","created_by":{"id":79774,"first_name":"Naman","last_name":"Aggarwal","picture":{"medium":"https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"},"custom_picture":true},"updated_at":"2020-06-24T06:57:29Z","updated_by":null,"deleted_at":null,"deleted_by":null,"category":{"id":18,"name":"General"},"receipt":{"large":null,"original":null},"users":[{"user":{"id":79774,"first_name":"Naman","last_name":"Aggarwal","picture":{"medium":"https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"}},"user_id":79774,"paid_share":"10.0","owed_share":"5.0","net_balance":"5.0"},{"user":{"id":643871,"first_name":"Shantanu","last_name":"Alshi","picture":{"medium":"https://s3.amazonaws.com/splitwise/uploads/user/default_avatars/avatar-blue19-100px.png"}},"user_id":643871,"paid_share":"0.0","owed_share":"5.0","net_balance":"-5.0"}]}],"errors":{}}'  # noqa: E501
        expense = Expense()
        expense.setCost('10')
        expense.setDescription("Testing")
        expense.setGroupId(19433671)
        expense.setSplitEqually()
        expenseRes, errors = self.sObj.createExpense(expense)
        mockMakeRequest.assert_called_with(
            "https://secure.splitwise.com/api/v3.0/create_expense",
            "POST", {
                'cost': '10',
                'description': 'Testing',
                'group_id': 19433671,
                'split_equally': True
            },
            files=None)
        self.assertIsNone(errors)
        self.assertEqual(expenseRes.getId(), 1010906976)
        self.assertEqual(expenseRes.getGroupId(), 19433671)
        self.assertEqual(expenseRes.getFriendshipId(), None)
        self.assertEqual(expenseRes.getExpenseBundleId(), None)
        self.assertEqual(expenseRes.getDescription(), "Testing")
        self.assertEqual(expenseRes.getRepeatInterval(), "never")
        self.assertEqual(expenseRes.getEmailReminderInAdvance(), -1)
        self.assertEqual(expenseRes.getNextRepeat(), None)
        self.assertEqual(expenseRes.getDetails(), None)
        self.assertEqual(expenseRes.getCommentsCount(), 0)
        self.assertEqual(expenseRes.getCreationMethod(), None)
        self.assertEqual(expenseRes.getTransactionMethod(), "offline")
        self.assertEqual(expenseRes.getTransactionId(), None)
        self.assertEqual(expenseRes.getCost(), "10.0")
        self.assertEqual(expenseRes.getCurrencyCode(), "SGD")
        self.assertEqual(len(expenseRes.getRepayments()), 1)
        self.assertEqual(expenseRes.getRepayments()[0].getFromUser(), 643871)
        self.assertEqual(expenseRes.getRepayments()[0].getToUser(), 79774)
        self.assertEqual(expenseRes.getRepayments()[0].getAmount(), "5.0")
        self.assertEqual(expenseRes.getDate(), "2020-06-24T06:57:29Z")
        self.assertEqual(expenseRes.getCreatedAt(), "2020-06-24T06:57:29Z")
        self.assertEqual(expenseRes.getCreatedBy().getId(), 79774)
        self.assertEqual(expenseRes.getCreatedBy().getFirstName(), "Naman")
        self.assertEqual(expenseRes.getCreatedBy().getLastName(), "Aggarwal")
        self.assertEqual(
            expenseRes.getCreatedBy().getPicture().getMedium(),
            "https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"
        )
        self.assertEqual(expenseRes.getUpdatedAt(), "2020-06-24T06:57:29Z")
        self.assertEqual(expenseRes.getUpdatedBy(), None)
        self.assertEqual(expenseRes.getDeletedAt(), None)
        self.assertEqual(expenseRes.getDeletedBy(), None)
        self.assertEqual(expenseRes.getCategory().getId(), 18)
        self.assertEqual(expenseRes.getCategory().getName(), "General")
        self.assertEqual(expenseRes.getReceipt().getLarge(), None)
        self.assertEqual(expenseRes.getReceipt().getOriginal(), None)
        self.assertEqual(len(expenseRes.getUsers()), 2)
        self.assertEqual(expenseRes.getUsers()[0].getId(), 79774)
        self.assertEqual(expenseRes.getUsers()[0].getFirstName(), "Naman")
        self.assertEqual(expenseRes.getUsers()[0].getLastName(), "Aggarwal")
        self.assertEqual(
            expenseRes.getUsers()[0].getPicture().getMedium(),
            "https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"
        )
        self.assertEqual(expenseRes.getUsers()[0].getPaidShare(), "10.0")
        self.assertEqual(expenseRes.getUsers()[0].getOwedShare(), "5.0")
        self.assertEqual(expenseRes.getUsers()[0].getNetBalance(), "5.0")
        self.assertEqual(expenseRes.getUsers()[1].getId(), 643871)
        self.assertEqual(expenseRes.getUsers()[1].getFirstName(), "Shantanu")
        self.assertEqual(expenseRes.getUsers()[1].getLastName(), "Alshi")
        self.assertEqual(
            expenseRes.getUsers()[1].getPicture().getMedium(),
            "https://s3.amazonaws.com/splitwise/uploads/user/default_avatars/avatar-blue19-100px.png"
        )
        self.assertEqual(expenseRes.getUsers()[1].getPaidShare(), "0.0")
        self.assertEqual(expenseRes.getUsers()[1].getOwedShare(), "5.0")
        self.assertEqual(expenseRes.getUsers()[1].getNetBalance(), "-5.0")

    def test_createExpense_split_manually_success(self, mockMakeRequest):
        mockMakeRequest.return_value = '{"expenses":[{"id":1010934284,"group_id":null,"friendship_id":null,"expense_bundle_id":null,"description":"Testing","repeats":false,"repeat_interval":"never","email_reminder":false,"email_reminder_in_advance":-1,"next_repeat":null,"details":null,"comments_count":0,"payment":false,"creation_method":null,"transaction_method":"offline","transaction_confirmed":false,"transaction_id":null,"cost":"10.0","currency_code":"SGD","repayments":[{"from":281236,"to":79774,"amount":"8.0"}],"date":"2020-06-24T08:14:07Z","created_at":"2020-06-24T08:14:07Z","created_by":{"id":79774,"first_name":"Naman","last_name":"Aggarwal","picture":{"medium":"https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"},"custom_picture":true},"updated_at":"2020-06-24T08:14:07Z","updated_by":null,"deleted_at":null,"deleted_by":null,"category":{"id":18,"name":"General"},"receipt":{"large":null,"original":null},"users":[{"user":{"id":79774,"first_name":"Naman","last_name":"Aggarwal","picture":{"medium":"https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"}},"user_id":79774,"paid_share":"10.0","owed_share":"2.0","net_balance":"8.0"},{"user":{"id":281236,"first_name":"Siddharth","last_name":"Goel","picture":{"medium":"https://splitwise.s3.amazonaws.com/uploads/user/avatar/281236/medium_f5fccc37-0a88-4519-9398-59c8c19b92aa.jpeg"}},"user_id":281236,"paid_share":"0.0","owed_share":"8.0","net_balance":"-8.0"}]}],"errors":{}}'  # noqa: E501
        expense = Expense()
        expense.setCost('10')
        expense.setDescription("Testing")
        user1 = ExpenseUser()
        user1.setId(79774)
        user1.setPaidShare('10.00')
        user1.setOwedShare('2.0')
        user2 = ExpenseUser()
        user2.setId(281236)
        user2.setPaidShare('0.00')
        user2.setOwedShare('8.00')
        users = []
        users.append(user1)
        users.append(user2)
        expense.setUsers(users)
        expenseRes, errors = self.sObj.createExpense(expense)
        mockMakeRequest.assert_called_with(
            "https://secure.splitwise.com/api/v3.0/create_expense",
            "POST", {
                'cost': '10',
                'description': 'Testing',
                'users__0__user_id': 79774,
                'users__0__paid_share': '10.00',
                'users__0__owed_share': '2.0',
                'users__1__user_id': 281236,
                'users__1__paid_share': '0.00',
                'users__1__owed_share': '8.00'
            },
            files=None)
        self.assertIsNone(errors)
        self.assertEqual(expenseRes.getId(), 1010934284)
        self.assertEqual(expenseRes.getGroupId(), None)
        self.assertEqual(expenseRes.getFriendshipId(), None)
        self.assertEqual(expenseRes.getExpenseBundleId(), None)
        self.assertEqual(expenseRes.getDescription(), "Testing")
        self.assertEqual(expenseRes.getRepeatInterval(), "never")
        self.assertEqual(expenseRes.getEmailReminderInAdvance(), -1)
        self.assertEqual(expenseRes.getNextRepeat(), None)
        self.assertEqual(expenseRes.getDetails(), None)
        self.assertEqual(expenseRes.getCommentsCount(), 0)
        self.assertEqual(expenseRes.getCreationMethod(), None)
        self.assertEqual(expenseRes.getTransactionMethod(), "offline")
        self.assertEqual(expenseRes.getTransactionId(), None)
        self.assertEqual(expenseRes.getCost(), "10.0")
        self.assertEqual(expenseRes.getCurrencyCode(), "SGD")
        self.assertEqual(len(expenseRes.getRepayments()), 1)
        self.assertEqual(expenseRes.getRepayments()[0].getFromUser(), 281236)
        self.assertEqual(expenseRes.getRepayments()[0].getToUser(), 79774)
        self.assertEqual(expenseRes.getRepayments()[0].getAmount(), "8.0")
        self.assertEqual(expenseRes.getDate(), "2020-06-24T08:14:07Z")
        self.assertEqual(expenseRes.getCreatedAt(), "2020-06-24T08:14:07Z")
        self.assertEqual(expenseRes.getCreatedBy().getId(), 79774)
        self.assertEqual(expenseRes.getCreatedBy().getFirstName(), "Naman")
        self.assertEqual(expenseRes.getCreatedBy().getLastName(), "Aggarwal")
        self.assertEqual(
            expenseRes.getCreatedBy().getPicture().getMedium(),
            "https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"
        )
        self.assertEqual(expenseRes.getUpdatedAt(), "2020-06-24T08:14:07Z")
        self.assertEqual(expenseRes.getUpdatedBy(), None)
        self.assertEqual(expenseRes.getDeletedAt(), None)
        self.assertEqual(expenseRes.getDeletedBy(), None)
        self.assertEqual(expenseRes.getCategory().getId(), 18)
        self.assertEqual(expenseRes.getCategory().getName(), "General")
        self.assertEqual(expenseRes.getReceipt().getLarge(), None)
        self.assertEqual(expenseRes.getReceipt().getOriginal(), None)
        self.assertEqual(len(expenseRes.getUsers()), 2)
        self.assertEqual(expenseRes.getUsers()[0].getId(), 79774)
        self.assertEqual(expenseRes.getUsers()[0].getFirstName(), "Naman")
        self.assertEqual(expenseRes.getUsers()[0].getLastName(), "Aggarwal")
        self.assertEqual(
            expenseRes.getUsers()[0].getPicture().getMedium(),
            "https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"
        )
        self.assertEqual(expenseRes.getUsers()[0].getPaidShare(), "10.0")
        self.assertEqual(expenseRes.getUsers()[0].getOwedShare(), "2.0")
        self.assertEqual(expenseRes.getUsers()[0].getNetBalance(), "8.0")
        self.assertEqual(expenseRes.getUsers()[1].getId(), 281236)
        self.assertEqual(expenseRes.getUsers()[1].getFirstName(), "Siddharth")
        self.assertEqual(expenseRes.getUsers()[1].getLastName(), "Goel")
        self.assertEqual(
            expenseRes.getUsers()[1].getPicture().getMedium(),
            "https://splitwise.s3.amazonaws.com/uploads/user/avatar/281236/medium_f5fccc37-0a88-4519-9398-59c8c19b92aa.jpeg"
        )
        self.assertEqual(expenseRes.getUsers()[1].getPaidShare(), "0.0")
        self.assertEqual(expenseRes.getUsers()[1].getOwedShare(), "8.0")
        self.assertEqual(expenseRes.getUsers()[1].getNetBalance(), "-8.0")

    def test_createExpense_error(self, mockMakeRequest):
        mockMakeRequest.return_value = '{"expenses":[],"errors":{"base":["An unknown error occurred. Please try again or contact [email protected] if you experience repeated issues. Sorry for the trouble!"]}}'  # noqa: E501
        expense = Expense()
        expense.setCost('10')
        expense.setDescription("Testing")
        user1 = ExpenseUser()
        user1.setId(79774)
        user1.setPaidShare('10.00')
        user1.setOwedShare('2.0')
        user2 = ExpenseUser()
        user2.setId(281236)
        user2.setPaidShare('0.00')
        user2.setOwedShare('8.00')
        users = []
        users.append(user1)
        users.append(user2)
        expense.setUsers(users)
        expenseRes, errors = self.sObj.createExpense(expense)
        mockMakeRequest.assert_called_with(
            "https://secure.splitwise.com/api/v3.0/create_expense",
            "POST", {
                'cost': '10',
                'description': 'Testing',
                'users__0__user_id': 79774,
                'users__0__paid_share': '10.00',
                'users__0__owed_share': '2.0',
                'users__1__user_id': 281236,
                'users__1__paid_share': '0.00',
                'users__1__owed_share': '8.00'
            },
            files=None)
        self.assertEqual(
            errors.getErrors(), {
                'base': [
                    'An unknown error occurred. Please try again or contact [email protected] if you experience repeated issues. \
Sorry for the trouble!'
                ]
            })

    def test_createExpense_exception(self, mockMakeRequest):
        mockMakeRequest.side_effect = Exception(
            "Invalid response %s. Please check your consumer key and secret." %
            404)
        expense = Expense()
        expense.setCost('10')
        expense.setDescription("Testing")
        user1 = ExpenseUser()
        user1.setId(79774)
        user1.setPaidShare('10.00')
        user1.setOwedShare('2.0')
        user2 = ExpenseUser()
        user2.setId(281236)
        user2.setPaidShare('0.00')
        user2.setOwedShare('8.00')
        users = []
        users.append(user1)
        users.append(user2)
        expense.setUsers(users)
        with self.assertRaises(Exception):
            expenseRes, errors = self.sObj.createExpense(expense)
        mockMakeRequest.assert_called_with(
            "https://secure.splitwise.com/api/v3.0/create_expense",
            "POST", {
                'cost': '10',
                'description': 'Testing',
                'users__0__user_id': 79774,
                'users__0__paid_share': '10.00',
                'users__0__owed_share': '2.0',
                'users__1__user_id': 281236,
                'users__1__paid_share': '0.00',
                'users__1__owed_share': '8.00'
            },
            files=None)