Skip to content

Commit

Permalink
Merge pull request #79 from jrafaelrn/bot_sales
Browse files Browse the repository at this point in the history
Bot sales
  • Loading branch information
jrafaelrn authored Oct 10, 2023
2 parents be2f39e + 6addb25 commit d7c1aa1
Show file tree
Hide file tree
Showing 35 changed files with 1,118 additions and 58 deletions.
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"python.testing.unittestArgs": [
"-v",
"-s",
"./src",
"./src/functions/test/",
"-p",
"*test*.py"
"test*.py"
],
"python.testing.pytestEnabled": false,
"python.testing.unittestEnabled": true,
Expand Down
10 changes: 6 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ services:
POSTGRES_PASSWORD: password
POSTGRES_USER: user
POSTGRES_DB: db
ports:
- 5432:5432
volumes:
- ./db_data:/var/lib/postgresql/data
ports:
- 5432:5432


bot:
build:
context: ./src/bot
dockerfile: Dockerfile
restart: always
environment:
- API_KEY=${API_KEY}


site:
build:
Expand All @@ -36,6 +36,7 @@ services:
volumes:
- ./src/site:/app


pg-admin:
image: dpage/pgadmin4
depends_on:
Expand All @@ -48,6 +49,7 @@ services:
links:
- db:db


functions:
build:
context: ./src/functions
Expand Down
186 changes: 179 additions & 7 deletions src/functions/bd_update_sales/api_ifood.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,188 @@
from importer import *
from dotenv import load_dotenv
from importer import ImporterApi_Interface
from retry import retry
from bd_sales import DbSalesIfood
import os, time, requests, hashlib

def configure():
load_dotenv()

class APIIfood(ImporterApi):

ifood = ImporterApi('ifood')
api_name = 'ifood'

# STATIC VARIABLES
BASE_URL = 'https://merchant-api.ifood.com.br'


# Implements the "Importer" interface
# to provide all the necessary methods
# for downloading Ifood API data and saving it
# in the database.

class ApiIfood(ImporterApi_Interface):

def __init__(self, api):
def __init__(self):
configure()
self.CLIENT_ID = os.getenv('IFOOD_CLIENT_ID')
self.CLIENT_SECRET = os.getenv('IFOOD_CLIENT_SECRET')
self.api_name = 'ifood'
self.accessToken = None


###############################
# CONNECT #
###############################

def connect(self):
print('Getting API KEY')

print(f'Getting Access Token from {self.api_name}...')

try:
if self.accessToken != None:
return

URL = f'{BASE_URL}/authentication/v1.0/oauth/token'
data={
'clientId': self.CLIENT_ID,
'clientSecret': self.CLIENT_SECRET,
'grantType': 'client_credentials'
}

post = requests.post(URL, data=data)
self.accessToken = post.json()['accessToken']

finally:
self.configure_headers(self.accessToken)
print(f'\tAccess Token obtained!')



def configure_headers(self, access_token):
auth = f'Bearer {self.accessToken}'
self.headers = {"Authorization": auth}


###############################
# DOWNLOAD #
###############################

def download(self) -> bool:

print(f'Downloading data from {self.api_name}...')

# MERCHANTS
#self.merchants = self.download_merchants()
#self.merchants_details = self.download_merchants_details(merchants)
#self.merchants_hash_downloaded = hashlib.md5(str(self.merchants).encode('utf-8')).hexdigest()

# ORDERS
orders = self.download_orders()
self.orders_details = self.download_orders_details(orders) if orders != None else None

return True


def download_merchants(self):

print('\tDownloading merchants...')
merchants = []
URL = f'{BASE_URL}/merchant/v1.0/merchants'
post = requests.get(URL, headers=self.headers)

return post.json()


def download_merchants_details(self, merchants):

print('\tDownloading merchants details...')
URL = f'{BASE_URL}/merchant/v1.0/merchants/'
merchants_details = []

for merchant in merchants:
post = requests.get(URL + merchant['id'], headers=self.headers)
merchants_details.append(post.json())

return merchants_details


def download_orders(self):

print('\tDownloading orders...')
orders = []
URL = f'{BASE_URL}/order/v1.0/events:polling'
post = requests.get(URL, headers=self.headers)

if post.status_code != 200:
print(f'\t\tStatus code: {post.status_code}')
return None

return post.json()


def download_orders_details(self, orders):

print('\tDownloading orders details...')
orders_details = []
URL = f'{BASE_URL}/order/v1.0/orders/'

for order in orders:
URL = f"{URL}{order['orderId']}"
post = requests.get(URL, headers=self.headers)

if post.status_code == 200:
orders_details.append(post.json())

return orders_details


###############################
# SAVE #
###############################

def save_db(self):

print(f'Saving data from {self.api_name}...')

db = DbSalesIfood()

#if self.merchants_hash_downloaded != self.merchants_hash_saved:
#db.insert_merchants(self.merchants)
#self.merchants_hash_saved = self.merchants_hash_downloaded

if self.orders_details != None:
db.insert_orders(self.orders_details)


def send_acks():
pass


def send_ack(id):
pass


###############################
# WATCHER #
###############################

@retry(delay=10, tries=1000)
def start(self):

try:

self.connect()
self.merchants_hash_saved = None

while True:
if self.download():
self.save_db()

time.sleep(5)

except Exception as e:
print(f'Error: {e}')
raise e



def start():
ifood = ApiIfood()
ifood.start()
58 changes: 58 additions & 0 deletions src/functions/bd_update_sales/api_rappi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from dotenv import load_dotenv
from .importer import ImporterApi_Interface
from retry import retry
import os, time

def configure():
load_dotenv()


# STATIC VARIABLES
BASE_URL = 'https://merchant-api.ifood.com.br'
CLIENT_ID = os.getenv('IFOOD_CLIENT_ID')
CLIENT_SECRET = os.getenv('IFOOD_CLIENT_SECRET')


# Implements the "Importer" interface
# to provide all the necessary methods
# for downloading Rappi API data and saving it
# in the database.

class ApiRappi(ImporterApi_Interface):

def __init__(self):
configure()
self.api_name = 'rappi'


def connect(self):
print(f'Getting API KEY from {self.api_name}...')


def download(self) -> bool:
print(f'Downloading data from {self.api_name}...')


def save_db(self) -> bool:
print(f'Saving data from {self.api_name}...')


@retry(delay=120, tries=1000)
def start(self):

try:

while True:
self.connect()
self.download()
self.save_db()
time.sleep(7)

except Exception as e:
print(f'Error: {e}')



def start():
rappi = ApiRappi()
rappi.start()
79 changes: 56 additions & 23 deletions src/functions/bd_update_sales/apis.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,63 @@
class connectAPI:

def __init__(self, api_name):
print(f'Starting API to {api_name}')
self.api_name = api_name
from multiprocessing import Pool, Process
import importlib, multiprocessing


def get_apis_list(apis_name):

modules_name = lambda x : f'api_{x}'
modules_api_list = list(map(modules_name, apis_name))
return modules_api_list



def transform_module_into_processes(modules):

procs = []

for module in modules:

print(f'Importing module: {module}')
mod = importlib.import_module(module)

# Creating process
proc = multiprocessing.Process(target=mod.start)
procs.append(proc)

def send_email(self):
print(f'Sending email to {self.api_name}')
pass
return procs



def run_processes(procs):

# Starting all processes
for proc in procs:
proc.start()

def connect(self):
print(f'Connecting to {self.api_name}')
pass

for proc in procs:
proc.join()




def send_email():
pass



def run():

# Gets the list of all modules(files) starting with "api_ + base list"
API_BASE_LIST = ['ifood']
modules = get_apis_list(API_BASE_LIST)

# Turns all modules into processes, with the "start" method to run
procs = transform_module_into_processes(modules)

run_processes(procs)

def run(self):

try:
print(f'Running {self.api_name}')
self.send_email()
self.connect()
print(f'Finished sucessfully {self.api_name}!')
return True
except:
print(f'Error running {self.api_name}')
return False




if __name__ == '__main__':
run()
Loading

0 comments on commit d7c1aa1

Please sign in to comment.