From c7bbd6eb92295a4e0faff85f84306b426f7c4871 Mon Sep 17 00:00:00 2001 From: dzikafoczka Date: Sat, 21 Dec 2024 21:50:28 +0100 Subject: [PATCH] faktury --- Dockerfile | 24 +++++ ec2.py | 255 +++++++++++++++++++++++++++++++++++++++++++++ invoice_service.py | 73 +++++++++++++ 3 files changed, 352 insertions(+) create mode 100644 Dockerfile create mode 100644 ec2.py create mode 100644 invoice_service.py diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..289a655 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +FROM ubuntu:20.04 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get upgrade -y \ + && apt-get install -y \ + python3 \ + python3-pip \ + python3-dev \ + libpoppler-cpp-dev \ + build-essential \ + curl \ + git \ + && apt-get clean + +RUN pip3 install --no-cache-dir Flask PyMuPDF + +WORKDIR /app + +COPY . /app + +EXPOSE 8080 + +CMD ["python3", "invoice_service.py"] diff --git a/ec2.py b/ec2.py new file mode 100644 index 0000000..ad572a1 --- /dev/null +++ b/ec2.py @@ -0,0 +1,255 @@ +import boto3 +import base64 + +REPOZYTORIUM = "https://git.wmi.amu.edu.pl/s464863/aws_faktury.git" +PREFIX = "s464863" +AMI_ID = "ami-0b5eea76982371e91" +REGION = "us-east-1" +INSTANCE_TYPE = "t2.micro" + +user_data = f""" +#!/bin/bash + +yum update -y +yum install -y amazon-linux-extras +amazon-linux-extras enable docker +yum install -y docker +yum install -y git + +service docker start +usermod -a -G docker ec2-user + +cd /home/ec2-user +git clone {REPOZYTORIUM} +cd aws_faktury + +docker build -t flask-invoice-app . + +docker run -d -p 8080:8080 flask-invoice-app +echo "Aplikacja działa na porcie 8080" +""" + +def create_vpc(ec2_client): + # Create VPC + response = ec2_client.create_vpc( + CidrBlock='10.0.0.0/16', + TagSpecifications=[ + { + 'ResourceType': 'vpc', + 'Tags': [{'Key': 'Name', 'Value': f"{PREFIX}-vpc"}] + } + ] + ) + vpc_id = response['Vpc']['VpcId'] + print(f"Created VPC with ID: {vpc_id}") + + # Enable DNS support and hostnames + ec2_client.modify_vpc_attribute(VpcId=vpc_id, EnableDnsSupport={'Value': True}) + ec2_client.modify_vpc_attribute(VpcId=vpc_id, EnableDnsHostnames={'Value': True}) + print("Enabled DNS support and hostnames.") + + return vpc_id + + +def create_subnet(ec2_client, vpc_id, cidr_block, availability_zone): + # Create subnet + response = ec2_client.create_subnet( + VpcId=vpc_id, + CidrBlock=cidr_block, + AvailabilityZone=availability_zone, + TagSpecifications=[ + { + 'ResourceType': 'subnet', + 'Tags': [{'Key': 'Name', 'Value': f"{PREFIX}-subnet"}] + } + ] + ) + subnet_id = response['Subnet']['SubnetId'] + print(f"Created Subnet with ID: {subnet_id}") + + # Public IP addresses for instances in the subnet + ec2_client.modify_subnet_attribute(SubnetId=subnet_id, MapPublicIpOnLaunch={'Value': True}) + print("Configured subnet to auto-assign public IP addresses.") + + return subnet_id + + +def create_internet_gateway(ec2_client, vpc_id): + # Create Internet Gateway + response = ec2_client.create_internet_gateway( + TagSpecifications=[ + { + 'ResourceType': 'internet-gateway', + 'Tags': [{'Key': 'Name', 'Value': f"{PREFIX}-igw"}] + } + ] + ) + igw_id = response['InternetGateway']['InternetGatewayId'] + print(f"Created Internet Gateway with ID: {igw_id}") + + # Attach Internet Gateway to VPC + ec2_client.attach_internet_gateway(InternetGatewayId=igw_id, VpcId=vpc_id) + print("Attached Internet Gateway to VPC.") + + return igw_id + + +def create_route_table(ec2_client, vpc_id, subnet_id, igw_id): + # Create Route Table + response = ec2_client.create_route_table( + VpcId=vpc_id, + TagSpecifications=[ + { + 'ResourceType': 'route-table', + 'Tags': [{'Key': 'Name', 'Value': f"{PREFIX}-rt"}] + } + ] + ) + route_table_id = response['RouteTable']['RouteTableId'] + print(f"Created Route Table with ID: {route_table_id}") + + # Create route to Internet Gateway + ec2_client.create_route( + RouteTableId=route_table_id, + DestinationCidrBlock='0.0.0.0/0', + GatewayId=igw_id + ) + print("Added route to Internet Gateway in Route Table.") + + # Associate Route Table with Subnet + ec2_client.associate_route_table(RouteTableId=route_table_id, SubnetId=subnet_id) + print("Associated Route Table with Subnet.") + + return route_table_id + + +def create_key_pair(ec2_client, key_name, save_to_file): + # Create key pair + response = ec2_client.create_key_pair(KeyName=key_name) + + # Save private key to file + private_key = response['KeyMaterial'] + with open(save_to_file, 'w') as file: + file.write(private_key) + + print(f"Key pair '{key_name}' created and saved to '{save_to_file}'.") + return response['KeyName'] + + +def create_security_group(ec2_client, vpc_id): + group_name = f"{PREFIX}-sg" + + # Create Security Group + response = ec2_client.create_security_group( + GroupName=group_name, + Description=f"Security group for {PREFIX} webservices", + VpcId=vpc_id + ) + + security_group_id = response['GroupId'] + print(f"Security group '{group_name}' created with ID: {security_group_id}") + + # Set ingress rules + ec2_client.authorize_security_group_ingress( + GroupId=security_group_id, + IpPermissions=[ + { + 'IpProtocol': 'tcp', + 'FromPort': 22, + 'ToPort': 22, + 'IpRanges': [{'CidrIp': '0.0.0.0/0', 'Description': 'SSH access'}] + }, + { + 'IpProtocol': 'tcp', + 'FromPort': 8080, + 'ToPort': 8080, + 'IpRanges': [{'CidrIp': '0.0.0.0/0', 'Description': 'HTTP access'}] + } + ] + ) + + print("Ingress rules added for SSH (22) and HTTP (80).") + return security_group_id + + +def create_launch_template(ec2_client, key_name, security_group_id): + # Create Launch Template + response = ec2_client.create_launch_template( + LaunchTemplateName=f"{PREFIX}-lt", + LaunchTemplateData={ + 'ImageId': AMI_ID, + 'InstanceType': INSTANCE_TYPE, + 'SecurityGroupIds': [security_group_id], + 'KeyName': key_name, + 'UserData': base64.b64encode(user_data.encode('utf-8')).decode('utf-8') + } + ) + + print(f"Launch Template created with ID: {response['LaunchTemplate']['LaunchTemplateId']}") + return response['LaunchTemplate']['LaunchTemplateId'] + + +def run_instance(ec2_client, launch_template_id, subnet_id): + # Run EC2 instances + response = ec2_client.run_instances( + LaunchTemplate={ + 'LaunchTemplateId': launch_template_id + }, + MaxCount=1, + MinCount=1, + SubnetId=subnet_id + ) + + instance_id = response['Instances'][0]['InstanceId'] + print(f"Instance {instance_id} is running.") + + ec2_client.get_waiter('instance_running').wait(InstanceIds=[instance_id]) + instance_info = ec2_client.describe_instances(InstanceIds=[instance_id]) + public_ip = instance_info['Reservations'][0]['Instances'][0].get('PublicIpAddress') + public_dns = instance_info['Reservations'][0]['Instances'][0].get('PublicDnsName') + + if public_ip: + return public_ip + if public_dns: + print(f"Public DNS: {public_dns}") + + return instance_id + +def main(): + # Create EC2 client + ec2_client = boto3.client('ec2', region_name=REGION) + + # Create VPC + print("Creating VPC...") + vpc_id = create_vpc(ec2_client) + + # Create subnet + print("Creating subnet...") + subnet = create_subnet(ec2_client, vpc_id, cidr_block='10.0.1.0/24', availability_zone='us-east-1a') + + # Create Internet Gateway + print("Creating Internet Gateway...") + igw_id = create_internet_gateway(ec2_client, vpc_id) + + # Create Route Table + print("Creating Route Table...") + route_table_id = create_route_table(ec2_client, vpc_id, subnet, igw_id) + + # Create Key Pair + print("Creating Key Pair...") + key_name = create_key_pair(ec2_client, f"{PREFIX}-key", f"{PREFIX}-key.pem") + + # Create Security Group + print("Creating Security Group...") + security_group_id = create_security_group(ec2_client, vpc_id) + + # Create Launch Template + print("Creating Launch Template...") + launch_template_id = create_launch_template(ec2_client, key_name, security_group_id) + + # Run EC2 instance + print("Running EC2 instance...") + ec2_id = run_instance(ec2_client, launch_template_id, subnet) + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/invoice_service.py b/invoice_service.py new file mode 100644 index 0000000..51c4aab --- /dev/null +++ b/invoice_service.py @@ -0,0 +1,73 @@ +from flask import Flask, request, jsonify +import fitz +import os +import re + +app = Flask(__name__) +UPLOAD_FOLDER = 'uploads' +os.makedirs(UPLOAD_FOLDER, exist_ok=True) + +def extract_total_alternate(text): + try: + match = re.search(r'(?i)PODSUMOWANIE\nWartość netto\nStawka VAT\nVAT\nWartość brutto\n\d+(\.\d{1,2})?\n\d+%?\n\d+(\.\d{1,2})?\n(\d+\.\d{1,2})?', text, re.DOTALL) + print(match.groups()) + if match: + return float(match.group(3).replace(',', '.')) + return None + except Exception: + return None + +def extract_total(text): + total_match = re.search(r'(?i)Wartość brutto\n([0-9.,]+) PLN', text) + total = float(total_match.group(1).replace(',', '.')) if total_match else None + + if total is None: + total = extract_total_alternate(text) + + return total + +def extract_invoice_data(text): + try: + seller_match = re.search(r'(?i)Sprzedawca:\n(.*?)\n', text) + seller_name = seller_match.group(1).strip() if seller_match else None + + nip_match = re.search(r'(?i)Sprzedawca:.*?NIP:\s*(\d+)', text, re.DOTALL) + vat_id = nip_match.group(1) if nip_match else None + + total = extract_total(text) + + return { + "vat_id": vat_id, + "seller_name": seller_name, + "total": total + } + except Exception as e: + return {"error": f"Failed to extract data: {str(e)}"} + +@app.route('/invoice', methods=['POST']) +def process_invoice(): + if 'file' not in request.files: + return jsonify({"error": "No file provided"}), 400 + + file = request.files['file'] + if file.filename == '': + return jsonify({"error": "Empty filename"}), 400 + + filepath = os.path.join(UPLOAD_FOLDER, file.filename) + file.save(filepath) + + try: + text = "" + with fitz.open(filepath) as pdf: + for page in pdf: + text += page.get_text() + invoice_data = extract_invoice_data(text) + + return jsonify(invoice_data), 200 + except Exception as e: + return jsonify({"error": str(e)}), 500 + finally: + os.remove(filepath) + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=8080) \ No newline at end of file