faktury
This commit is contained in:
commit
c7bbd6eb92
24
Dockerfile
Normal file
24
Dockerfile
Normal file
@ -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"]
|
255
ec2.py
Normal file
255
ec2.py
Normal file
@ -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()
|
73
invoice_service.py
Normal file
73
invoice_service.py
Normal file
@ -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)
|
Loading…
Reference in New Issue
Block a user