Simple Tax Calculator

Some of the Python program used behind the scenes:


        def lambda_handler(event, context):
        try:
            # Check if the 'income' query parameter is present
            if 'queryStringParameters' not in event or 'income' not in event['queryStringParameters']:
                raise ValueError("Missing 'income' query parameter")
            
            # Parse the income from the request and ensure it's a valid number
            income = event['queryStringParameters']['income']
            
            try:
                income = float(income)
            except ValueError:
                raise ValueError(f"Invalid income value: {income}")
            
            # Ensure income is non-negative
            if income < 0:
                raise ValueError(f"Income must be a positive value, but got: {income}")
    
            tax_owed = 0
            
            # Tax calculation logic
            if income <= 10000:
                tax_owed = 0
            elif income <= 40000:
                tax_owed = (income - 10000) * 0.10
            elif income <= 100000:
                tax_owed = (40000 - 10000) * 0.10 + (income - 40000) * 0.20
            else:
                tax_owed = (40000 - 10000) * 0.10 + (100000 - 40000) * 0.20 + (income - 100000) * 0.30
            
            net_income = income - tax_owed
            
            # Log the result for debugging purposes
            logger.info(f"Income: {income}, Tax Owed: {tax_owed}, Net Income: {net_income}")
    
            # Return response with CORS headers
            return {
                'statusCode': 200,
                'headers': {
                    'Access-Control-Allow-Origin': '*',
                    'Access-Control-Allow-Methods': 'GET',
                    'Access-Control-Allow-Headers': '*'
                },
                'body': json.dumps({
                    'tax_owed': tax_owed,
                    'net_income': net_income
                })
            }
    
        except Exception as e:
            # Log the error
            logger.error(f"Error: {str(e)}")
    
            # Return error response with CORS headers
            return {
                'statusCode': 400,
                'headers': {
                    'Access-Control-Allow-Origin': '*',
                    'Access-Control-Allow-Methods': 'GET',
                    'Access-Control-Allow-Headers': '*'
                },
                'body': json.dumps({'error': str(e)})
            }


    

Woah, what now?

The Python codes sits inside an AWS Lambda function. Python is a programming language designed by Guido van Rossum in 1991.

When you click the button above, a subset of a server owned by Amazon is used. That's the idea behind AWS Lambda. It is often called ``serverless compute" because I don't actually have a server and I don't have to maintain a server. The name is somewhat misleading, however, because servers are still used. The name Lambda comes from notation used in mathematics, specifically lambda calculus.

Notice how after the return keyword, we return certain headers related to access control. Headers — HTTP headers, that is — are labels that can be attached to requests, each header has a name. And each named header can take a particular value. For example, User-Agent might take the value Mozilla/5.0 or PostmanRuntime/7.32.2.

These are really important. Without them, Amazon API Gateway cannot be invoked from a web browser. Oh, how many hours of troubleshooting I've spent on this (partly because even after working out the problem is CORS, there are lots of other ways to configure CORS, using the AWS Management Console. So, remember, just make sure your Lambda code returns an object with headers in!).

The headers allow Cross-Origin Resource Sharing.

This code imagines a situation in which you get £10,000 for yourself (no tax is applied). But the next £30,000 you earn is taxed at 10%. This explains the part which states (40000 - 10000) * 0.10.

The tax calculation logic considers four possibilities. We denote the first possibility using the if keyword. (Take a look, above!) The second possibility we denote with the elif keyword. The third with the elif keyword. The fourth with the else keyword.



When code considers, and then selects, different actions for different possibilities it is called selection. (Many GCSE Computer Science specifications refer to SEQUENCE, SELECTION, and ITERATION in programming. See Mr Brown's video here, and this BBC Bitesize page for Edexcel referring to ``the three basic programming constructs".)

The sort of IF-ELIF-ELSE structure we use above is really helpful. But it is not the only way to deal with different conditions in Python. Take a look at this page to learn more.