Пример #1
0
    def handle_CreateAccount(self, command):
        ''' Handles CreateAccount command

            Keyword Arguments:
            command -- Command entity with necessary account creation data

            Returns:
            An array containing violations ocurred during execution
        '''
        assert isinstance(
            command,
            CreateAccount), '{} must be of type \'CreateAccount\''.format(
                command)

        violations = []
        account = command.accountToCreate

        existingAccounts = self.accountRepository.getByFilter(
            lambda account: True)

        if existingAccounts:
            violations += ['account-already-initialized']
            return Account.getAccountAndViolationsDict(existingAccounts[0],
                                                       violations)

        self.accountRepository.add(account)

        returnDict = Account.getAccountAndViolationsDict(account, violations)

        return returnDict
Пример #2
0
    def test_getAccountAndViolationsDict_empty(self):
        account = Account(True, 100)
        violations = []

        expectedDict = { "account": { "activeCard": True, "availableLimit": 100 }, "violations": [] }
        result = Account.getAccountAndViolationsDict(account, violations)

        self.assertDictEqual(expectedDict, result)
Пример #3
0
    def test_getAccountAndViolationsDict_Valid(self):
        account = Account(True, 99)
        violations = ['insufficient-limit']

        expectedDict = { "account": { "activeCard": True, "availableLimit": 99 }, "violations": ['insufficient-limit'] }
        result = Account.getAccountAndViolationsDict(account, violations)

        self.assertDictEqual(expectedDict, result)
    def test_JsonParseAccount_ok(self):
        jsonStr = '{ "account": { "activeCard": true, "availableLimit": 100 } }'

        expected = Account(True, 100)

        result = CreateAccount.parseAccountCreation(jsonStr)

        self.assertDictEqual(expected.toDict(), result.toDict())
    def test_CreateAccountCtor_ok(self):
        jsonStr = '{ "account": { "activeCard": true, "availableLimit": 100 } }'

        expected = Account(True, 100)

        result = CreateAccount(jsonStr)

        self.assertDictEqual(expected.toDict(), result.accountToCreate.toDict())
    def test_handleCreateAccount_ok(self):

        accountRepository = InMemoryRepository()
        transactionRepository = InMemoryRepository()

        commandHandler = TransactionCommandHandler(transactionRepository,
                                                   accountRepository)

        accountRepository.add(Account(True, 100))

        command = AuthorizeTransaction(
            '{ "transaction": { "merchant": "Burger King", "amount": 10, "time": "2019-02-13T10:00:00.000Z" } }'
        )

        expectedResult = {
            "account": {
                "activeCard": True,
                "availableLimit": 90
            },
            "violations": []
        }
        expectedAccount = {
            "account": {
                "activeCard": True,
                "availableLimit": 90
            }
        }

        result = commandHandler.handle_AuthorizeTransaction(command)

        self.assertEqual(expectedResult, result)

        resultAccount = accountRepository.getByFilter(
            lambda _: True)[0].toDict()
        self.assertDictEqual(resultAccount, expectedAccount)
    def test_handleCreateAccount_DoubledTransaction(self):

        accountRepository = InMemoryRepository()
        transactionRepository = InMemoryRepository()

        commandHandler = TransactionCommandHandler(transactionRepository,
                                                   accountRepository)

        accountRepository.add(Account(True, 75))
        transactionRepository.add(
            Transaction(
                "Burger King", 10,
                datetime.strptime("2019-02-13T11:00:00.000Z",
                                  '%Y-%m-%dT%H:%M:%S.%fZ')))
        transactionRepository.add(
            Transaction(
                "Burger King", 10,
                datetime.strptime("2019-02-13T11:01:59.000Z",
                                  '%Y-%m-%dT%H:%M:%S.%fZ')))

        command = AuthorizeTransaction(
            '{ "transaction": { "merchant": "Burger King", "amount": 10, "time": "2019-02-13T11:02:00.000Z" } }'
        )

        expectedResult = {
            "account": {
                "activeCard": True,
                "availableLimit": 75
            },
            "violations": ['doubled-transaction']
        }

        result = commandHandler.handle_AuthorizeTransaction(command)

        self.assertEqual(expectedResult, result)
    def test_handleCreateAccount_InsufficientLimit(self):

        accountRepository = InMemoryRepository()
        transactionRepository = InMemoryRepository()

        commandHandler = TransactionCommandHandler(transactionRepository,
                                                   accountRepository)

        accountRepository.add(Account(True, 100))

        command = AuthorizeTransaction(
            '{ "transaction": { "merchant": "Burger King", "amount": 101, "time": "2019-02-13T10:00:00.000Z" } }'
        )

        expectedResult = {
            "account": {
                "activeCard": True,
                "availableLimit": 100
            },
            "violations": ['insufficient-limit']
        }

        result = commandHandler.handle_AuthorizeTransaction(command)

        self.assertEqual(expectedResult, result)

        transactions = transactionRepository.getByFilter(lambda _: True)
        self.assertListEqual([], transactions)
Пример #9
0
    def parseAccountCreation(line):
        ''' Parses an AccountCreation command arguments

            Keyword arguments:
                line -- JSON operation line containing "activeCard": boolean and "availableLimit": Integer
            
            Returned Value:
                account -- Account object built with the fields from the operation
        '''
        fieldsDict = json.loads(line)['account']

        account = Account(fieldsDict['activeCard'],
                          fieldsDict['availableLimit'])

        return account
    def test_handleCreateAccount_HighFrequencySmallInterval(self):

        accountRepository = InMemoryRepository()
        transactionRepository = InMemoryRepository()

        commandHandler = TransactionCommandHandler(transactionRepository,
                                                   accountRepository)

        accountRepository.add(Account(True, 75))
        transactionRepository.add(
            Transaction(
                "Burger King", 10,
                datetime.strptime("2019-02-13T11:00:00.000Z",
                                  '%Y-%m-%dT%H:%M:%S.%fZ')))
        transactionRepository.add(
            Transaction(
                "Burger Queen", 10,
                datetime.strptime("2019-02-13T11:01:00.000Z",
                                  '%Y-%m-%dT%H:%M:%S.%fZ')))
        transactionRepository.add(
            Transaction(
                "Burger Prince", 5,
                datetime.strptime("2019-02-13T11:01:59.000Z",
                                  '%Y-%m-%dT%H:%M:%S.%fZ')))

        command = AuthorizeTransaction(
            '{ "transaction": { "merchant": "Burger Pleb", "amount": 10, "time": "2019-02-13T10:00:00.000Z" } }'
        )

        expectedResult = {
            "account": {
                "activeCard": True,
                "availableLimit": 75
            },
            "violations": ['high-frequency-small-interval']
        }

        result = commandHandler.handle_AuthorizeTransaction(command)

        self.assertEqual(expectedResult, result)
    def test_handleCreateAccount_AlreadyInitialized(self):

        repository = InMemoryRepository()
        repository.add(Account(True, 42))
        commandHandler = AccountCommandHandler(repository)
        command = CreateAccount(
            '{ "account": { "activeCard": true, "availableLimit": 100 } }')

        expectedResult = {
            "account": {
                "activeCard": True,
                "availableLimit": 42
            },
            "violations": ["account-already-initialized"]
        }

        result = commandHandler.handle_CreateAccount(command)

        self.assertDictEqual(expectedResult, result)

        emptyResults = repository.getByFilter(
            lambda account: account.availableLimit == 100)
        self.assertListEqual([], emptyResults)
Пример #12
0
    def handle_AuthorizeTransaction(self, command):
        ''' Handles AuthorizeTransaction command

            Keyword Arguments:
            command -- Command entity with necessary transaction authorization data

            Returns:
            A dictionary containing the account and a new field containing possible violations
        '''
        assert isinstance(
            command, AuthorizeTransaction
        ), '{} must be of type \'AuthorizeTransaction\''.format(command)

        transaction = command.transactionToCreate
        violations = []

        # Gets the first account
        account = self.accountRepository.getByFilter(lambda account: True)[0]

        # •	No transaction should be accepted when the card is not active: card-not-active
        if not account.activeCard:
            violations += ['card-not-active']
            return Account.getAccountAndViolationsDict(account, violations)

        # •	The transaction amount should not exceed available limit: insufficient-limit
        if account.availableLimit < transaction.amount:
            violations += ['insufficient-limit']
            return Account.getAccountAndViolationsDict(account, violations)

        # •	There should not be more than 3 transactions on a 2 minute interval: high-frequency-small-interval
        transactionTime = datetime.strptime(transaction.time,
                                            '%Y-%m-%dT%H:%M:%S.%fZ')

        minDiffInMinutes = 2
        fromDatetime = transactionTime - timedelta(minutes=minDiffInMinutes)

        recentTransactions = self.transactionRepository.getByFilter(
            lambda transactions: transactions.time >= fromDatetime)

        if len(recentTransactions) >= 3:
            violations += ['high-frequency-small-interval']
            return Account.getAccountAndViolationsDict(account, violations)

        # •	There should not be more than 2 similar transactions (same amount and merchant) in a 2 minutes interval: doubled-transaction
        doubledTransactions = list(filter(lambda transactions: \
            transactions.amount == transaction.amount \
            and transactions.merchant == transaction.merchant \
            , recentTransactions))

        if doubledTransactions and len(doubledTransactions) > 1:
            violations += ['doubled-transaction']
            return Account.getAccountAndViolationsDict(account, violations)

        # Everything should be fine down here
        transaction.time = transactionTime
        self.transactionRepository.add(transaction)

        account.availableLimit -= transaction.amount
        self.accountRepository.update(account)

        return Account.getAccountAndViolationsDict(account, violations)