Building a Serverless Profit/Loss Calculator with AWS Lambda, AWS API Gateway and React

Building a Serverless Profit/Loss Calculator with AWS Lambda, AWS API Gateway and React


Project Architecture

Our application follows a serverless architecture:

  • Frontend: React application hosted on Netlify

  • Backend: AWS Lambda function written in Python

  • API: AWS API Gateway to expose our Lambda function

  • Version Control: GitLab repository

  • Hosting: Netlify (frontend), AWS (backend)

This architecture allows for scalability, cost-effectiveness, and ease of maintenance.

Setting Up the Backend

Let's start by creating our AWS Lambda function:

AWS Lambda Setup (Console)

  1. Open the AWS Lambda console

  2. Click "Create function"

  3. Choose "Author from scratch"

  4. Enter a function name (e.g., "profit-loss-calculator")

  5. Select Python 3.8 (or later) as the runtime

  6. Click "Create function"

  1. In the function code section, paste the following Python code:
import json

def calculate_profit_loss(revenue, costs):
    profit_loss = revenue - costs
    return profit_loss

def lambda_handler(event, context):
    try:
        # Parse input from the event
        body = json.loads(event['body'])
        revenue = float(body['revenue'])
        costs = float(body['costs'])

        # Calculate profit/loss
        profit_loss = calculate_profit_loss(revenue, costs)

        # Prepare the response
        response = {
            'profit_loss': profit_loss,
            'message': 'Profit' if profit_loss > 0 else 'Loss' if profit_loss < 0 else 'Break-even'
        }

        return {
            'statusCode': 200,
            'body': json.dumps(response),
            'headers': {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin': '*'  # Enable CORS for all origins
            }
        }
    except Exception as e:
        return {
            'statusCode': 400,
            'body': json.dumps({'error': str(e)}),
            'headers': {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin': '*'
            }
        }
  1. Click "Deploy" to save changes

API Gateway Setup (Console)

  1. Open the API Gateway console

  2. Click "Create API"

  3. Choose "REST API" and click "Build"

  4. Enter an API name (e.g., "Profit-Loss-API")

  5. Click "Create API"

[Placeholder for screenshot: API Gateway creation page]

  1. Click "Create Resource"

  2. Enter a resource name (e.g., "calculate")

  3. Click "Create Resource"

  4. With the new resource selected, click "Create Method"

  5. Select "POST" from the dropdown and click the checkmark

  6. Set Integration type to "Lambda Function"

  7. Select your Lambda function and click "Save"

Developing the Frontend

Now, let's create our React frontend:

npx create-react-app profit-loss-calculator
cd profit-loss-calculator

Replace the contents of src/App.js and also create FinancialModel.js Component:

App.js

import React from 'react';
import FinancialModel from './FinancialModel';

function App() {
  return (
    <div className="App">
      <FinancialModel />
    </div>
  );
}

export default App;

FinancialModel.js Component

import React, { useState } from 'react';

const FinancialModel = () => {
  const [revenue, setRevenue] = useState('');
  const [costs, setCosts] = useState('');
  const [result, setResult] = useState(null);
  const [error, setError] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();
    setError('');
    setResult(null);

    try {
      const response = await fetch('YOUR_API_GATEWAT_URL"), {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ revenue: parseFloat(revenue), costs: parseFloat(costs) }),
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const data = await response.json();
      setResult(data);
    } catch (error) {
      console.error('Fetch error:', error);
      if (error.message.includes('CORS')) {
        setError('CORS error: The server is not allowing this request. Please check CORS configuration.');
      } else {
        setError(`An error occurred: ${error.message}. Please try again.`);
      }
    }
  };

  return (
    <div style={{ maxWidth: '400px', margin: '0 auto', padding: '20px' }}>
      <h2 style={{ textAlign: 'center' }}>Financial Model Calculator</h2>
      <form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
        <div>
          <label htmlFor="revenue">Revenue</label>
          <input
            id="revenue"
            type="number"
            value={revenue}
            onChange={(e) => setRevenue(e.target.value)}
            required
            placeholder="Enter revenue"
            style={{ width: '100%', padding: '5px' }}
          />
        </div>
        <div>
          <label htmlFor="costs">Costs</label>
          <input
            id="costs"
            type="number"
            value={costs}
            onChange={(e) => setCosts(e.target.value)}
            required
            placeholder="Enter costs"
            style={{ width: '100%', padding: '5px' }}
          />
        </div>
        <button type="submit" style={{ padding: '10px', backgroundColor: '#007bff', color: 'white', border: 'none', cursor: 'pointer' }}>
          Calculate
        </button>
      </form>

      {error && (
        <div style={{ marginTop: '10px', padding: '10px', backgroundColor: '#ffcccc', color: '#ff0000' }}>
          {error}
        </div>
      )}

      {result && (
        <div style={{ marginTop: '10px' }}>
          <h3>Result:</h3>
          <p>Profit/Loss: ${result.profit_loss.toFixed(2)}</p>
          <p>Status: {result.message}</p>
        </div>
      )}
    </div>
  );
};

export default FinancialModel;

React app in development mode

Version Control with GitLab

To set up version control:

  1. Create a new project in GitLab

  2. Follow the instructions to push an existing folder:

cd existing_folder
git init
git remote add origin git@gitlab.com:your-username/profit-loss-calculator.git
git add .
git commit -m "Initial commit"
git push -u origin master

Deploying the Application

Backend Deployment

The backend is automatically deployed when you create and update your Lambda function and API Gateway.

Frontend Deployment with Netlify

  1. Log in to Netlify

  2. Click "New site from Git"

  3. Choose GitLab and select your repository

  4. Configure build settings:

    • Netlify deploy settings
  5. Click "Deploy site"

After deployment, Netlify will provide a URL for your site.

Testing and Troubleshooting

Common issues and solutions:

  • CORS errors: Ensure API Gateway and Lambda both have CORS enabled

  • API Gateway integration errors: Check Lambda function permissions

  • React build errors: Verify all dependencies are correctly installed

💡
Add “*” to “Access-Control-Allow-Origin” during the testing stage.

Conclusion

We've successfully built a serverless profit/loss calculator using React, AWS Lambda, and API Gateway. This architecture provides a scalable and cost-effective solution.

Future improvements could include:

  • Adding more complex financial calculations

  • Implementing user authentication

  • Storing calculation history in a database