# Path: bartercheckout/models.py
# class BarterAccount(models.Model):
#     customer_name = models.CharField(max_length=100)
#     balance = MoneyField(max_digits=6, decimal_places=2, default_currency='USD', default=0.0)
#     last_add = models.DateField(null=True)
#     last_subtract = models.DateField(null=True)
# 
#     def add(self, amount):
#         if amount < 0 or (amount * 100) % 25 != 0:
#             raise AmountInputError("Invalid amount")
# 
#         amount = Money(amount, 'USD')
# 
#         if self.balance + amount > BALANCE_LIMIT:
#             raise BalanceLimitError(f"Balance can't go above $50. Current balance ${self.balance}. You can add up to "
#                                     f"${BALANCE_LIMIT - self.balance}")
#         else:
#             self.balance += amount
#             self.last_add = date.today()
#             return self.balance
# 
#     def subtract(self, amount):
#         if amount < 0 or (amount * 100) % 25 != 0:
#             raise AmountInputError("Invalid amount")
# 
#         amount = Money(amount, 'USD')
# 
#         if self.balance - amount < Money(0, 'USD'):
#             raise BalanceLimitError(f'Balance can\'t go below {Money(0, "USD")}')
#         else:
#             self.balance -= amount
#             self.last_subtract = date.today()
#             return self.balance
# 
#     def __repr__(self):
#         return (
#             f'BarterAccount(customer_name="{self.customer_name}", '
#             f'balance={self.balance!r}, '
#             f'last_add={self.last_add!r}, '
#             f'last_subtract={self.last_subtract!r})'
#         )
# 
#     def __str__(self):
#         return f'Account: {self.customer_name}'
# 
#     @property
#     def account_balance(self):
#         return f'{self.balance}' if self.balance else ''
# 
# class BarterEvent(models.Model):
#     barter_account = models.ForeignKey('BarterAccount', on_delete=CASCADE)
# 
#     ADD = 'Add'
#     BUY_MEAL = 'Buy_meal'
#     BUY_CARD = 'Buy_card'
#     NOTE = 'Note'
# 
#     EVENT_TYPE_CHOICES = (
#         (ADD, 'Add'),
#         (BUY_MEAL, 'Buy_meal'),
#         (BUY_CARD, 'Buy_card'),
#         (NOTE, 'Note'),
#     )
# 
#     event_type = models.CharField(
#         max_length=20,
#         choices=EVENT_TYPE_CHOICES,
#         default=BUY_MEAL,
#     )
# 
#     event_time = models.DateTimeField(auto_now_add=True)
#     amount = MoneyField(max_digits=6, decimal_places=2, default_currency='USD', default=0.0)
# 
#     @property
#     def customer_name(self):
#         return self.barter_account.customer_name
# 
#     @property
#     def transaction_amount(self):
#         return f'${self.amount:,.2f}'
# 
#     # staff_id = models.ForeignKey()
# 
#     def __repr__(self):
#         return f'BarterEvent(event_time={self.event_time!r}, amount={self.amount!r}'
# 
#     def __str__(self):
#         return f'Barter event ID {self.id} for {self.customer_name}'
# 
# Path: bartercheckout/views.py
# def credit(request, account_id):
#     """
#     Add credit to a BarterAccount and create a BarterEvent
#     as a record of the transaction.
#     """
#     accounts = BarterAccount.objects.filter(id=account_id)
#     # The filter method returns None if there's no account that matches the id
#     # If accounts equals None, return an error
#     if accounts:
#         # The filter method returns a list. There should only be 1 item
#         # in this list because ID is a primary key. But we still need to
#         # grab the first item from the list.
#         account = accounts[0]
# 
#         # Get amount to add from request
#         body_unicode = request.body.decode('utf-8')
#         body_data = json.loads(body_unicode)
#         amount = body_data['amount']
# 
#         # Update the barter account
#         try:
#             newBalance = account.add(amount)
#         except BalanceLimitError:
#             return JsonResponse({'result': 'limit_error'})
#         except AmountInputError:
#             return JsonResponse({'result': 'input_error'})
#         account.save()
# 
#         # Create event
#         data = {'barter_account': account, 'event_type': 'Add', 'amount': amount}
#         event = BarterEvent(**data)
#         event.save()
# 
#         return JsonResponse({'result': 'ok'})
#     else:
#         return JsonResponse({'error': 'noSuchAccount'})


import json
from django.test import TestCase
from django.test.client import RequestFactory
from djmoney.money import Money
from .models import BarterAccount, BarterEvent
from .views import credit


# Create your tests here.
class CreditTest(TestCase):

    def setUp(self):
        # Add account to db
        summer = BarterAccount.objects.create(customer_name='Summer Salt', balance=Money(2.00, 'USD'))
        summer.save()

        self.factory = RequestFactory()

    def test_BarterAccount_exists_and_adds(self):
        # Test that user exists.
        summer = BarterAccount.objects.get(customer_name='Summer Salt')
        # Test that the add() method was called.
        summers_id = summer.id
        request = self.factory.post(f'/account/{summers_id}/credit',
                                    json.dumps({'amount': 2.50}),
                                    content_type='application/json')
        response = credit(request, summers_id)
        summer.refresh_from_db()
        self.assertEquals(summer.balance, Money(4.50, 'USD'))
        # Test that a credit event was created.
        creditevent = BarterEvent.objects.get(event_type='Add', amount=2.50)
        self.assertTrue(creditevent)
        # If exists, credit amount NOT valid, json returned describing error.
        request = self.factory.post(f'/account/{summers_id}/credit',
                                    json.dumps({'amount': 2.55}),
                                    content_type='application/json')

# Path: bartercheckout/models.py
# class BarterAccount(models.Model):
#     customer_name = models.CharField(max_length=100)
#     balance = MoneyField(max_digits=6, decimal_places=2, default_currency='USD', default=0.0)
#     last_add = models.DateField(null=True)
#     last_subtract = models.DateField(null=True)
# 
#     def add(self, amount):
#         if amount < 0 or (amount * 100) % 25 != 0:
#             raise AmountInputError("Invalid amount")
# 
#         amount = Money(amount, 'USD')
# 
#         if self.balance + amount > BALANCE_LIMIT:
#             raise BalanceLimitError(f"Balance can't go above $50. Current balance ${self.balance}. You can add up to "
#                                     f"${BALANCE_LIMIT - self.balance}")
#         else:
#             self.balance += amount
#             self.last_add = date.today()
#             return self.balance
# 
#     def subtract(self, amount):
#         if amount < 0 or (amount * 100) % 25 != 0:
#             raise AmountInputError("Invalid amount")
# 
#         amount = Money(amount, 'USD')
# 
#         if self.balance - amount < Money(0, 'USD'):
#             raise BalanceLimitError(f'Balance can\'t go below {Money(0, "USD")}')
#         else:
#             self.balance -= amount
#             self.last_subtract = date.today()
#             return self.balance
# 
#     def __repr__(self):
#         return (
#             f'BarterAccount(customer_name="{self.customer_name}", '
#             f'balance={self.balance!r}, '
#             f'last_add={self.last_add!r}, '
#             f'last_subtract={self.last_subtract!r})'
#         )
# 
#     def __str__(self):
#         return f'Account: {self.customer_name}'
# 
#     @property
#     def account_balance(self):
#         return f'{self.balance}' if self.balance else ''
# 
# class BarterEvent(models.Model):
#     barter_account = models.ForeignKey('BarterAccount', on_delete=CASCADE)
# 
#     ADD = 'Add'
#     BUY_MEAL = 'Buy_meal'
#     BUY_CARD = 'Buy_card'
#     NOTE = 'Note'
# 
#     EVENT_TYPE_CHOICES = (
#         (ADD, 'Add'),
#         (BUY_MEAL, 'Buy_meal'),
#         (BUY_CARD, 'Buy_card'),
#         (NOTE, 'Note'),
#     )
# 
#     event_type = models.CharField(
#         max_length=20,
#         choices=EVENT_TYPE_CHOICES,
#         default=BUY_MEAL,
#     )
# 
#     event_time = models.DateTimeField(auto_now_add=True)
#     amount = MoneyField(max_digits=6, decimal_places=2, default_currency='USD', default=0.0)
# 
#     @property
#     def customer_name(self):
#         return self.barter_account.customer_name
# 
#     @property
#     def transaction_amount(self):
#         return f'${self.amount:,.2f}'
# 
#     # staff_id = models.ForeignKey()
# 
#     def __repr__(self):
#         return f'BarterEvent(event_time={self.event_time!r}, amount={self.amount!r}'
# 
#     def __str__(self):
#         return f'Barter event ID {self.id} for {self.customer_name}'
# 
# Path: bartercheckout/views.py
# def credit(request, account_id):
#     """
#     Add credit to a BarterAccount and create a BarterEvent
#     as a record of the transaction.
#     """
#     accounts = BarterAccount.objects.filter(id=account_id)
#     # The filter method returns None if there's no account that matches the id
#     # If accounts equals None, return an error
#     if accounts:
#         # The filter method returns a list. There should only be 1 item
#         # in this list because ID is a primary key. But we still need to
#         # grab the first item from the list.
#         account = accounts[0]
# 
#         # Get amount to add from request
#         body_unicode = request.body.decode('utf-8')
#         body_data = json.loads(body_unicode)
#         amount = body_data['amount']
# 
#         # Update the barter account
#         try:
#             newBalance = account.add(amount)
#         except BalanceLimitError:
#             return JsonResponse({'result': 'limit_error'})
#         except AmountInputError:
#             return JsonResponse({'result': 'input_error'})
#         account.save()
# 
#         # Create event
#         data = {'barter_account': account, 'event_type': 'Add', 'amount': amount}
#         event = BarterEvent(**data)
#         event.save()
# 
#         return JsonResponse({'result': 'ok'})
#     else:
#         return JsonResponse({'error': 'noSuchAccount'})


# Path: bartercheckout/tests.py
import json
from django.test import TestCase
from django.test.client import RequestFactory
from djmoney.money import Money
from .models import BarterAccount, BarterEvent
from .views import credit



# Create your tests here.
class CreditTest(TestCase):

    def setUp(self):
        # Add account to db
        summer = BarterAccount.objects.create(customer_name='Summer Salt', balance=Money(2.00, 'USD'))
        summer.save()

        self.factory = RequestFactory()

    def test_BarterAccount_exists_and_adds(self):
        # Test that user exists.
        summer = BarterAccount.objects.get(customer_name='Summer Salt')
        # Test that the add() method was called.
        summers_id = summer.id
        request = self.factory.post(f'/account/{summers_id}/credit',
                                    json.dumps({'amount': 2.50}),
                                    content_type='application/json')
        response = credit(request, summers_id)
        summer.refresh_from_db()
        self.assertEquals(summer.balance, Money(4.50, 'USD'))
        # Test that a credit event was created.
        creditevent = BarterEvent.objects.get(event_type='Add', amount=2.50)
        self.assertTrue(creditevent)
        # If exists, credit amount NOT valid, json returned describing error.
        request = self.factory.post(f'/account/{summers_id}/credit',
                                    json.dumps({'amount': 2.55}),
                                    content_type='application/json')

        response = credit(request, summers_id)