Beispiel #1
0
def expenses():
    if 'access_token' not in session:
        return redirect(url_for("home2"))

    curr_dir = os.path.dirname(inspect.getfile(inspect.currentframe()))
    parent_dir = os.path.dirname(curr_dir)
    file_dir = os.path.join(parent_dir, 'txt_files')

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

    exps = sObj.getExpenses(dated_after=session['date_from'],
                            dated_before=session['date_to'],
                            limit=0)
    expenseids = []
    for i in exps:
        expenseids.append(i.getId())

    exp_concat = []
    for i in expenseids:
        exp = sObj.getExpense(i)
        for j in exp.getUsers():
            if j.getFirstName() == 'Marathe':  #3708390:

                if exp.getCreatedBy().getFirstName() == j.getFirstName(
                ) or exp.getDescription() == 'Payment':
                    owed = 0
                else:
                    owed = j.getOwedShare()
                exp_concat.append([
                    exp.getId(),
                    exp.getDate(), '',
                    j.getFirstName(),
                    exp.getCost(),
                    exp.getCategory().getName(),
                    exp.getDescription(), 'SPLITWISE', '', owed
                ])
            else:
                pass

    df = pd.DataFrame(exp_concat,
                      columns=[
                          'transation_id', 'date', 'account_id',
                          'account_owner', 'amount', 'old_category', 'name',
                          'acct_type', 'pending', 'actual_amount'
                      ])
    df['category'] = ''
    df['date'] = pd.to_datetime(df['date']).dt.date
    df = df[df['name'] != 'Settle all balances']
    df.to_csv(os.path.join(file_dir, 'trans_splitwise.txt'),
              sep='|',
              header=False,
              index=False)

    session.clear()
    return render_template('close_split.html')
Beispiel #2
0
def friends():
    if 'access_token' not in session:
        return redirect(url_for("home"))

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

    friends = sObj.getExpenses()
    for i in friends:
        print(i)
    return jsonify({'result':'success'})
Beispiel #3
0
    def get_expenses(self):
        sObj = Splitwise(Config.consumer_key, Config.consumer_secret)
        sObj.setAccessToken(session['access_token'])
        content = sObj.getExpenses()
        session['expenses'] = content

        friends = sObj.getFriends()
        self.debtors = friendsload(friends)
        #print(friendsload(friends))
        #print("\n\n\n\n\n\n" , content)
        #resp = splitwise.get('get_current_user')
        return render2('output.html', getresp="waddup")
Beispiel #4
0
    def settle(self):
        sObj = Splitwise(Config.consumer_key, Config.consumer_secret)
        sObj.setAccessToken(session['access_token'])
        content = sObj.getExpenses()
        session['expenses'] = content

        friends = sObj.getFriends()
        self.debtors = friendsload(friends)

        d = []
        d.append(Debtor("Hugh Mungus", 69.0))
        d.append(Debtor("Gareth Funk", 100000))
        d.append(Debtor("The Queen", 1000000000.01))
        return render2("settle.html", debtors=self.debtors)
Beispiel #5
0
def analyzer():
    if 'access_token' not in session:
        return redirect(url_for("home"))

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

    groups = sObj.getGroups()
    group = [x for x in groups if x.name == "88 Chemin 2018"][0]
    group.members.sort(key=wallstreet.get_index_for_dude)

    expenses = sObj.getExpenses(group_id=group.id,
                                limit=10000,
                                dated_after=datetime.datetime(2017, 5, 1))
    matrix = payment_matrix(expenses)
    wallstreet.print_matrix(matrix)
    simplified_matrix = simplify_matrix(deepcopy(matrix))
    wallstreet.print_matrix(simplified_matrix)
    return render_template("payment_matrix.html",
                           users=group.members,
                           matrix=matrix,
                           simplified_matrix=simplified_matrix)
Beispiel #6
0
def getExpenses():
    sObj = Splitwise(consumer_key, secret_key)
    sObj.setAccessToken(session['access_token'])
    total_expenses = sObj.getExpenses()
    descriptions = [name.getDescription() for name in total_expenses]
    return descriptions
Beispiel #7
0
def clear():
   sObj = Splitwise(consumer_key, secret_key)
   sObj.setAccessToken(session['access_token'])
   expenses = sObj.getExpenses()
   for expense in expenses:
       expense.setCost(0)
Beispiel #8
0
class SplitwiseImporter:
    def __init__(self, Secrets):
        self.ynab_budget_id = Secrets.getSecret(
            'splitwise.ynab_budget_id').strip()
        self.ynab_splitwise_account_id = Secrets.getSecret(
            'splitwise.ynab_splitwise_account_id').strip()
        self.splitwise_group_names = Secrets.getSecret(
            'splitwise.splitwise_group_names')
        self.dated_after = Secrets.getSecret(
            'splitwise.import_dated_after') or None

        consumer_key = Secrets.getSecret('splitwise.consumer_key').strip()
        consumer_secret = Secrets.getSecret(
            'splitwise.consumer_secret').strip()
        oauth_token = Secrets.getSecret('splitwise.oauth_token').strip()
        oauth_token_secret = Secrets.getSecret(
            'splitwise.oauth_token_secret').strip()

        self.logger = logging.getLogger('splitwise')

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

        self.currentUserId = self.splitwise.getCurrentUser().getId()

        self.spltiwise_group_double_map = {}
        groups = self.splitwise.getGroups()
        for g in groups:
            self.spltiwise_group_double_map[g.getId()] = g.getName()
            self.spltiwise_group_double_map[g.getName()] = g.getId()

        self.ynab_token = Secrets.getSecret("ynab_token").strip()
        self.ynabClient = YNAB(self.ynab_token)

    def generate_ynab_transaction(self, e):
        user = None
        for u in e.getUsers():
            if u.getId() == self.currentUserId:
                user = u
        if not user:
            return {}

        memo_parts = [e.getDescription()]
        if e.getGroupId():
            memo_parts.append(
                "splitwise-" +
                slugify(self.spltiwise_group_double_map[e.getGroupId()]))

        return TransactionRequest(
            self.ynab_splitwise_account_id,
            e.getDate(),
            int(float(user.getNetBalance()) * 1000),
            payee_name=(e.getDescription() if float(user.getNetBalance()) < 0
                        else "Splitwise Contribution"),
            memo=" ,".join(memo_parts),
            cleared="cleared",
            approved=False,
            import_id=e.getId())

    def run(self):
        # expenses = self.splitwise.getExpenses(group_id=self.splitwise_group_id)
        transactions = []

        if not len(self.splitwise_group_names):
            # None will get all groups
            self.splitwise_group_names = [None]

        for g in self.splitwise_group_names:
            # change group name to id
            if g:
                g = self.spltiwise_group_double_map[g]

            expenses = self.splitwise.getExpenses(dated_after=self.dated_after,
                                                  group_id=g,
                                                  limit=0)

            delta = 0
            for e in expenses:
                if e.getDeletedAt():
                    continue

                transaction = self.generate_ynab_transaction(e)
                if transaction == {}:
                    # self.logger.info("Got empty transaction for " +
                    #                  e.getDescription())
                    continue

                transactions.append(transaction)
                delta += float(transaction.amount)

        if len(transactions):
            try:
                self.ynabClient.transactions.create_transactions(
                    self.ynab_budget_id, transactions)
                self.logger.info("splitwise done")
            except Exception as e:
                self.logger.error(
                    "Exception when calling ynab->create_transactions: %s\n" %
                    e)
Beispiel #9
0
import json
from splitwise import Splitwise
import config
import utils
from excel import generate_expenses_xlsx
import yacht_expense_details

s = Splitwise(config.consumer_key,
              config.consumer_secret,
              api_key=config.API_key)
utils.create_folder(config.json_filename)
expenses = s.getExpenses(group_id=config.group_id,
                         limit=config.expenses_list_limit)
group = s.getGroup(id=config.group_id)
members_json = group.__dict__['members']
members_array = json.loads(
    json.dumps(members_json, default=lambda o: o.__dict__, ensure_ascii=False))


def expenses_to_json(expenses):
    expenses_array = []
    for expense in expenses:
        comments = s.getComments(expense.id)
        js = json.loads(
            json.dumps(expense.__dict__,
                       default=lambda o: o.__dict__,
                       ensure_ascii=False))
        js['comments'] = json.loads(
            json.dumps(comments,
                       default=lambda o: o.__dict__,
                       ensure_ascii=False))
Beispiel #10
0
a_cost = None
a_date_start = None
a_date_end = None
a_category_id = None

# Parameters to substitute to found expenses
b_group_id = None
b_friendship_id = None
b_expense_bundle_id = None
b_description = None
b_details = None
b_payment = None
b_cost = None
b_category_id = None

ex = sObj.getExpenses(limit=0)
for e in ex:
    new_data = {}
    
    if a_date_start is not None:
        if e.date < a_date_start
            continue
    if a_date_end is not None:
        if e.date > a_date_end:
            continue
    
    if e.group_id == a_group_id:
        new_data['group_id'] = b_group_id
    else:
        continue
    if e.friendship_id == a_friendship_id:
Beispiel #11
0
class GetExpensesTestCase(unittest.TestCase):

    def setUp(self):
        self.sObj = Splitwise('consumerkey', 'consumersecret')

    def test_getExpenses_limit_and_offset_success(self, mockMakeRequest):
        mockMakeRequest.return_value = '{"expenses":[{"id":1010395720,"group_id":10843533,"friendship_id":null,"expense_bundle_id":null,"description":"Potato","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":"equal","transaction_method":"offline","transaction_confirmed":false,"transaction_id":null,"cost":"0.9","currency_code":"SGD","repayments":[{"from":281236,"to":79774,"amount":"0.3"},{"from":643871,"to":79774,"amount":"0.3"}],"date":"2020-06-23T09:32:56Z","created_at":"2020-06-23T09:33:05Z","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-23T09:33:05Z","updated_by":null,"deleted_at":null,"deleted_by":null,"category":{"id":12,"name":"Groceries"},"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":"0.9","owed_share":"0.3","net_balance":"0.6"},{"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":"0.3","net_balance":"-0.3"},{"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":"0.3","net_balance":"-0.3"}]},{"id":1009711631,"group_id":10843533,"friendship_id":null,"expense_bundle_id":null,"description":"Mexican Dinner","repeats":false,"repeat_interval":"never","email_reminder":true,"email_reminder_in_advance":null,"next_repeat":null,"details":"","comments_count":0,"payment":false,"creation_method":"split","transaction_method":"offline","transaction_confirmed":false,"transaction_id":null,"cost":"32.7","currency_code":"SGD","repayments":[{"from":281236,"to":79774,"amount":"10.9"},{"from":643871,"to":79774,"amount":"10.9"}],"date":"2020-06-22T07:17:32Z","created_at":"2020-06-22T07:17:54Z","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-22T07:17:54Z","updated_by":null,"deleted_at":null,"deleted_by":null,"category":{"id":13,"name":"Dining out"},"receipt":{"large":null,"original":null},"users":[{"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":"10.9","net_balance":"-10.9"},{"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":"10.9","net_balance":"-10.9"},{"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":"32.7","owed_share":"10.9","net_balance":"21.8"}]}]}'  # noqa: E501
        expenses = self.sObj.getExpenses(2, 3)
        args, kwargs = mockMakeRequest.call_args
        parsed = urlparse.urlparse(args[0])
        qs = parse_qs(parsed.query)
        self.assertEqual(qs['offset'], ['2'])
        self.assertEqual(qs['limit'], ['3'])
        self.assertEqual(len(expenses), 2)
        self.assertEqual(expenses[0].getId(), 1010395720)
        self.assertEqual(expenses[0].getGroupId(), 10843533)
        self.assertEqual(expenses[0].getFriendshipId(), None)
        self.assertEqual(expenses[0].getExpenseBundleId(), None)
        self.assertEqual(expenses[0].getDescription(), "Potato")
        self.assertEqual(expenses[0].getRepeatInterval(), "never")
        self.assertEqual(expenses[0].getEmailReminderInAdvance(), -1)
        self.assertEqual(expenses[0].getNextRepeat(), None)
        self.assertEqual(expenses[0].getDetails(), None)
        self.assertEqual(expenses[0].getCommentsCount(), 0)
        self.assertEqual(expenses[0].getCreationMethod(), "equal")
        self.assertEqual(expenses[0].getTransactionMethod(), "offline")
        # self.assertEqual(expenses[0].getTransactionId(), None)
        self.assertEqual(expenses[0].getCost(), "0.9")
        self.assertEqual(expenses[0].getCurrencyCode(), "SGD")
        self.assertEqual(len(expenses[0].getRepayments()), 2)
        self.assertEqual(expenses[0].getRepayments()[0].getFromUser(), 281236)
        self.assertEqual(expenses[0].getRepayments()[0].getToUser(), 79774)
        self.assertEqual(expenses[0].getRepayments()[0].getAmount(), "0.3")
        self.assertEqual(expenses[0].getRepayments()[1].getFromUser(), 643871)
        self.assertEqual(expenses[0].getRepayments()[1].getToUser(), 79774)
        self.assertEqual(expenses[0].getRepayments()[1].getAmount(), "0.3")
        self.assertEqual(expenses[0].getDate(), "2020-06-23T09:32:56Z")
        self.assertEqual(expenses[0].getCreatedAt(), "2020-06-23T09:33:05Z")
        self.assertEqual(expenses[0].getCreatedBy().getId(), 79774)
        self.assertEqual(expenses[0].getCreatedBy().getFirstName(), "Naman")
        self.assertEqual(expenses[0].getCreatedBy().getLastName(), "Aggarwal")
        self.assertEqual(expenses[0].getCreatedBy().getPicture().getMedium(),
                         "https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg")
        self.assertEqual(expenses[0].getUpdatedAt(), "2020-06-23T09:33:05Z")
        self.assertEqual(expenses[0].getUpdatedBy(), None)
        self.assertEqual(expenses[0].getDeletedAt(), None)
        self.assertEqual(expenses[0].getDeletedBy(), None)
        self.assertEqual(expenses[0].getCategory().getId(), 12)
        self.assertEqual(expenses[0].getCategory().getName(), "Groceries")
        self.assertEqual(expenses[0].getReceipt().getLarge(), None)
        self.assertEqual(expenses[0].getReceipt().getOriginal(), None)
        self.assertEqual(len(expenses[0].getUsers()), 3)
        self.assertEqual(expenses[0].getUsers()[0].getId(), 79774)
        self.assertEqual(expenses[0].getUsers()[0].getFirstName(), "Naman")
        self.assertEqual(expenses[0].getUsers()[0].getLastName(), "Aggarwal")
        self.assertEqual(expenses[0].getUsers()[0].getPicture().getMedium(),
                         "https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg")
        self.assertEqual(expenses[0].getUsers()[0].getPaidShare(), "0.9")
        self.assertEqual(expenses[0].getUsers()[0].getOwedShare(), "0.3")
        self.assertEqual(expenses[0].getUsers()[0].getNetBalance(), "0.6")
        self.assertEqual(expenses[0].getUsers()[1].getId(), 281236)
        self.assertEqual(expenses[0].getUsers()[1].getFirstName(), "Siddharth")
        self.assertEqual(expenses[0].getUsers()[1].getLastName(), "Goel")
        self.assertEqual(expenses[0].getUsers()[1].getPicture().getMedium(
        ), "https://splitwise.s3.amazonaws.com/uploads/user/avatar/281236/medium_f5fccc37-0a88-4519-9398-59c8c19b92aa.jpeg")
        self.assertEqual(expenses[0].getUsers()[1].getPaidShare(), "0.0")
        self.assertEqual(expenses[0].getUsers()[1].getOwedShare(), "0.3")
        self.assertEqual(expenses[0].getUsers()[1].getNetBalance(), "-0.3")
        self.assertEqual(expenses[0].getUsers()[2].getId(), 643871)
        self.assertEqual(expenses[0].getUsers()[2].getFirstName(), "Shantanu")
        self.assertEqual(expenses[0].getUsers()[2].getLastName(), "Alshi")
        self.assertEqual(expenses[0].getUsers()[2].getPicture().getMedium(),
                         "https://s3.amazonaws.com/splitwise/uploads/user/default_avatars/avatar-blue19-100px.png")
        self.assertEqual(expenses[0].getUsers()[2].getPaidShare(), "0.0")
        self.assertEqual(expenses[0].getUsers()[2].getOwedShare(), "0.3")
        self.assertEqual(expenses[0].getUsers()[2].getNetBalance(), "-0.3")
        self.assertEqual(expenses[1].getId(), 1009711631)
        self.assertEqual(expenses[1].getGroupId(), 10843533)
        self.assertEqual(expenses[1].getFriendshipId(), None)
        self.assertEqual(expenses[1].getExpenseBundleId(), None)
        self.assertEqual(expenses[1].getDescription(), "Mexican Dinner")
        self.assertEqual(expenses[1].getRepeatInterval(), "never")
        self.assertEqual(expenses[1].getEmailReminderInAdvance(), None)
        self.assertEqual(expenses[1].getNextRepeat(), None)
        self.assertEqual(expenses[1].getDetails(), "")
        self.assertEqual(expenses[1].getCommentsCount(), 0)
        self.assertEqual(expenses[1].getCreationMethod(), "split")
        self.assertEqual(expenses[1].getTransactionMethod(), "offline")
        # self.assertEqual(expenses[1].getTransactionId(), None)
        self.assertEqual(expenses[1].getCost(), "32.7")
        self.assertEqual(expenses[1].getCurrencyCode(), "SGD")
        self.assertEqual(len(expenses[1].getRepayments()), 2)
        self.assertEqual(expenses[1].getRepayments()[0].getFromUser(), 281236)
        self.assertEqual(expenses[1].getRepayments()[0].getToUser(), 79774)
        self.assertEqual(expenses[1].getRepayments()[0].getAmount(), "10.9")
        self.assertEqual(expenses[1].getRepayments()[1].getFromUser(), 643871)
        self.assertEqual(expenses[1].getRepayments()[1].getToUser(), 79774)
        self.assertEqual(expenses[1].getRepayments()[1].getAmount(), "10.9")
        self.assertEqual(expenses[1].getDate(), "2020-06-22T07:17:32Z")
        self.assertEqual(expenses[1].getCreatedAt(), "2020-06-22T07:17:54Z")
        self.assertEqual(expenses[1].getCreatedBy().getId(), 79774)
        self.assertEqual(expenses[1].getCreatedBy().getFirstName(), "Naman")
        self.assertEqual(expenses[1].getCreatedBy().getLastName(), "Aggarwal")
        self.assertEqual(expenses[1].getCreatedBy().getPicture().getMedium(),
                         "https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg")
        self.assertEqual(expenses[1].getUpdatedAt(), "2020-06-22T07:17:54Z")
        self.assertEqual(expenses[1].getUpdatedBy(), None)
        self.assertEqual(expenses[1].getDeletedAt(), None)
        self.assertEqual(expenses[1].getDeletedBy(), None)
        self.assertEqual(expenses[1].getCategory().getId(), 13)
        self.assertEqual(expenses[1].getCategory().getName(), "Dining out")
        self.assertEqual(expenses[1].getReceipt().getLarge(), None)
        self.assertEqual(expenses[1].getReceipt().getOriginal(), None)
        self.assertEqual(len(expenses[1].getUsers()), 3)
        self.assertEqual(expenses[1].getUsers()[0].getId(), 281236)
        self.assertEqual(expenses[1].getUsers()[0].getFirstName(), "Siddharth")
        self.assertEqual(expenses[1].getUsers()[0].getLastName(), "Goel")
        self.assertEqual(expenses[1].getUsers()[0].getPicture().getMedium(
        ), "https://splitwise.s3.amazonaws.com/uploads/user/avatar/281236/medium_f5fccc37-0a88-4519-9398-59c8c19b92aa.jpeg")
        self.assertEqual(expenses[1].getUsers()[0].getPaidShare(), "0.0")
        self.assertEqual(expenses[1].getUsers()[0].getOwedShare(), "10.9")
        self.assertEqual(expenses[1].getUsers()[0].getNetBalance(), "-10.9")
        self.assertEqual(expenses[1].getUsers()[1].getId(), 643871)
        self.assertEqual(expenses[1].getUsers()[1].getFirstName(), "Shantanu")
        self.assertEqual(expenses[1].getUsers()[1].getLastName(), "Alshi")
        self.assertEqual(expenses[1].getUsers()[1].getPicture().getMedium(),
                         "https://s3.amazonaws.com/splitwise/uploads/user/default_avatars/avatar-blue19-100px.png")
        self.assertEqual(expenses[1].getUsers()[1].getPaidShare(), "0.0")
        self.assertEqual(expenses[1].getUsers()[1].getOwedShare(), "10.9")
        self.assertEqual(expenses[1].getUsers()[1].getNetBalance(), "-10.9")
        self.assertEqual(expenses[1].getUsers()[2].getId(), 79774)
        self.assertEqual(expenses[1].getUsers()[2].getFirstName(), "Naman")
        self.assertEqual(expenses[1].getUsers()[2].getLastName(), "Aggarwal")
        self.assertEqual(expenses[1].getUsers()[2].getPicture().getMedium(),
                         "https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg")
        self.assertEqual(expenses[1].getUsers()[2].getPaidShare(), "32.7")
        self.assertEqual(expenses[1].getUsers()[2].getOwedShare(), "10.9")
        self.assertEqual(expenses[1].getUsers()[2].getNetBalance(), "21.8")

    def test_getExpenses_all_options_success(self, mockMakeRequest):
        mockMakeRequest.return_value = '{"expenses":[{"id":1010395720,"group_id":10843533,"friendship_id":null,"expense_bundle_id":null,"description":"Potato","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":"equal","transaction_method":"offline","transaction_confirmed":false,"transaction_id":null,"cost":"0.9","currency_code":"SGD","repayments":[{"from":281236,"to":79774,"amount":"0.3"},{"from":643871,"to":79774,"amount":"0.3"}],"date":"2020-06-23T09:32:56Z","created_at":"2020-06-23T09:33:05Z","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-23T09:33:05Z","updated_by":null,"deleted_at":null,"deleted_by":null,"category":{"id":12,"name":"Groceries"},"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":"0.9","owed_share":"0.3","net_balance":"0.6"},{"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":"0.3","net_balance":"-0.3"},{"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":"0.3","net_balance":"-0.3"}]},{"id":1009711631,"group_id":10843533,"friendship_id":null,"expense_bundle_id":null,"description":"Mexican Dinner","repeats":false,"repeat_interval":"never","email_reminder":true,"email_reminder_in_advance":null,"next_repeat":null,"details":"","comments_count":0,"payment":false,"creation_method":"split","transaction_method":"offline","transaction_confirmed":false,"transaction_id":null,"cost":"32.7","currency_code":"SGD","repayments":[{"from":281236,"to":79774,"amount":"10.9"},{"from":643871,"to":79774,"amount":"10.9"}],"date":"2020-06-22T07:17:32Z","created_at":"2020-06-22T07:17:54Z","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-22T07:17:54Z","updated_by":null,"deleted_at":null,"deleted_by":null,"category":{"id":13,"name":"Dining out"},"receipt":{"large":null,"original":null},"users":[{"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":"10.9","net_balance":"-10.9"},{"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":"10.9","net_balance":"-10.9"},{"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":"32.7","owed_share":"10.9","net_balance":"21.8"}]}]}'  # noqa: E501
        self.sObj.getExpenses(2, 3, "123", "1234", "2020-12-12", "2020-12-19", "2020-12-13", "2020-12-18")
        args, kwargs = mockMakeRequest.call_args
        parsed = urlparse.urlparse(args[0])
        qs = parse_qs(parsed.query)
        self.assertEqual(qs['offset'], ['2'])
        self.assertEqual(qs['limit'], ['3'])
        self.assertEqual(qs['group_id'], ['123'])
        self.assertEqual(qs['friendship_id'], ['1234'])
        self.assertEqual(qs['dated_after'], ['2020-12-12'])
        self.assertEqual(qs['dated_before'], ['2020-12-19'])
        self.assertEqual(qs['updated_after'], ['2020-12-13'])
        self.assertEqual(qs['updated_before'], ['2020-12-18'])

    def test_getExpenses_exception(self, mockMakeRequest):
        mockMakeRequest.side_effect = Exception(
            "Invalid response %s. Please check your consumer key and secret." % 404)
        with self.assertRaises(Exception):
            self.sObj.getExpenses(2, 3)
        args, kwargs = mockMakeRequest.call_args
        parsed = urlparse.urlparse(args[0])
        qs = parse_qs(parsed.query)
        self.assertEqual(qs['offset'], ['2'])
        self.assertEqual(qs['limit'], ['3'])