Commit 62e5907c by Javier

Documentación

parent 15b848e5
......@@ -13,7 +13,32 @@ from pydantic import BaseModel
import mbilling.functions
app = FastAPI()
description = """
Servicio API para la interacción con el Tarficador de Telefonía ☎️
## Account
Endpoints para la consulta, creación y modificación de cuentas SIP y sus atributos.
"""
tags_metadata = [
{
"name": "Account",
"description": "Consulta, creación y modificación de cuentas SIP y sus atributos.",
},
]
app = FastAPI(
title='API Magnus Billing',
description=description,
version='0.0.1 Beta',
contact={
'name': 'Javier Ramírez',
'email': 'javier@rentelwifi.com'
},
openapi_tags=tags_metadata
)
class Rate(str, Enum):
......@@ -22,10 +47,12 @@ class Rate(str, Enum):
PLANA_1000 = "Tarifa Plana 1000 Minutos"
PLANA_2000 = "Tarifa Plana 2000 Minutos"
class Tax(float, Enum):
GENERAL = 0.21
LIBRE = 0.0
class Refill(str, Enum):
AUTOMATICA = 'Recarga Automática'
LIQUIDACION = 'Liquidación Mensual de consumos Postpago'
......@@ -33,6 +60,7 @@ class Refill(str, Enum):
TRASPASO = 'Traspaso de Fondos desde A2Billing'
INICIAL = 'Recarga Inicial'
class Account(BaseModel):
"""_summary_
......@@ -59,21 +87,22 @@ class Account(BaseModel):
default=None, example='192.168.2.71', title='Centralita', description='Dirección IP de la Centralita.'
)
class AccountDetails(BaseModel):
number: str = Body(
..., regex=r'[89][1-9]\d{7}', example='856135158', title='Número', description='Identificador de entrada y salidas de Llamadas'
)
password : str = Body(
password: str = Body(
..., title='Contraseña', description='Credencial Cuenta SIP para host dinámico.'
)
host : str = Body(
host: str = Body(
..., title='Host', description='Dirección desde la que se conecta el usuario.'
)
credit : float = Body(
credit: float = Body(
..., title='Saldo Disponible', description='Adeudo o activo que tiene el cliente.'
)
......@@ -83,12 +112,12 @@ class AccountDetails(BaseModel):
class Config:
schema_extra = {
"example" : {
"number" : "856135158",
"password" : "rentel58",
"example": {
"number": "856135158",
"password": "rentel58",
"host": "192.168.2.71",
"credit": 32.45,
"rate" : Rate.PLANA_2000
"rate": Rate.PLANA_2000
}
}
......@@ -98,34 +127,34 @@ class ConnectionData(BaseModel):
"""
account : str = Body(
account: str = Body(
..., title='Cuenta', description='Usuario/Número de cuenta para Autentificación SIP.'
)
password : str = Body(
password: str = Body(
..., title='Contraseña', description='Credencial para la Autentificación.'
)
peer_details : str = Body(
peer_details: str = Body(
default=None, title='Peer Details', description='Credenciales para la salida por troncal en Centralitas.'
)
user_details : str = Body(
user_details: str = Body(
default=None, title='User Context', description='Credenciales para la entrada por troncal en Centralitas.'
)
class Config:
schema_extra = {
"example" : {
"account" : "856135158",
"password" : "rentel58",
"example": {
"account": "856135158",
"password": "rentel58",
"peer_details": "type = friend username = 951203503 host = 192.168.2.84 nat = force_rport, comedia qualify = yes insecure = invite, port",
"user_details": "type = friend host = 192.168.2.84 nat = force_rport, comedia qualify = yes insecure = invite, port"
}
}
def encode_rate(rate : Rate = Rate.ESTANDAR) -> Tuple[int,int]:
def encode_rate(rate: Rate = Rate.ESTANDAR) -> Tuple[int, int]:
# Tarifa por Defecto
plan_id = 1
offer_id = 0
......@@ -142,7 +171,8 @@ def encode_rate(rate : Rate = Rate.ESTANDAR) -> Tuple[int,int]:
return plan_id, offer_id
def decode_rate(plan_id : int, offer_id : int = 0) -> Rate:
def decode_rate(plan_id: int, offer_id: int = 0) -> Rate:
if plan_id == 1:
return Rate.ESTANDAR
elif plan_id == 2:
......@@ -150,7 +180,8 @@ def decode_rate(plan_id : int, offer_id : int = 0) -> Rate:
elif plan_id == 4:
return Rate.PLANA_1000 if offer_id == 4 else Rate.PLANA_2000
@app.post('/account', response_model=ConnectionData, name='Añadir Cuenta SIP', description='Genera una nueva cuenta en el Tarificador')
@app.post('/account', response_model=ConnectionData, name='Añadir Cuenta SIP', description='Genera una nueva cuenta en el Tarificador', tags=['Account'])
def create_account(account: Account = Depends()):
"""Genera una nueva cuenta SIP con los datos proporcionados.
......@@ -159,7 +190,6 @@ def create_account(account: Account = Depends()):
"""
plan_id, offer_id = encode_rate(account.rate)
# Generación de la Cuenta
......@@ -174,7 +204,8 @@ def create_account(account: Account = Depends()):
)
if not account.pbx_address:
response = ConnectionData(account=account.number, password=password)
response = ConnectionData(
account=account.number, password=password)
else:
response = ConnectionData(
account=account.number,
......@@ -186,8 +217,8 @@ def create_account(account: Account = Depends()):
except mbilling.functions.MagnusCommandError as e:
response = JSONResponse(
content={
'error' : 'Se ha producido un error en Magnus durante la ejecución del comando.',
'description' : str(e),
'error': 'Se ha producido un error en Magnus durante la ejecución del comando.',
'description': str(e),
},
status_code=400
)
......@@ -195,7 +226,7 @@ def create_account(account: Account = Depends()):
return response
@app.get('/account/{account_name}', response_model=AccountDetails)
@app.get('/account/{account_name}', response_model=AccountDetails, tags=['Account'])
def get_account(account_name: str = Query(..., regex=r'[89][1-9]\d{7}', name='Número', description='Cuenta SIP a recargar')):
user_data = mbilling.functions.get_user(account_name)
......@@ -212,28 +243,30 @@ def get_account(account_name: str = Query(..., regex=r'[89][1-9]\d{7}', name='N
else:
response = JSONResponse(
content={
'result' : 'ERROR',
'description' : 'No existe ningún usuario con la identificación solicitada.'
'result': 'ERROR',
'description': 'No existe ningún usuario con la identificación solicitada.'
}, status_code=404
)
return response
@app.post('/account/{account_name}/balance', name='Añade saldo a una cuenta SIP', description='Realiza una recarga en nombre del cliente.')
@app.post('/account/{account_name}/balance', name='Añade saldo a una cuenta SIP', description='Realiza una recarga en nombre del cliente.', tags=['Account'])
def add_balance(account_name: str = Query(..., regex=r'[89][1-9]\d{7}', name='Número', description='Cuenta SIP a recargar'),
quantity: float=Query(default=10.00, name='Cantidad', description='Total a ingresar incluyendo impuestos'),
tax : Tax = Query(default=Tax.GENERAL, name='Impuesto', description='Tasa impositiva a reducir del monto.'), description : Refill =
Query(default=Refill.AUTOMATICA, name='Tipo', description='Clase de Recarga') ):
quantity: float = Query(
default=10.00, name='Cantidad', description='Total a ingresar incluyendo impuestos'),
tax: Tax = Query(default=Tax.GENERAL, name='Impuesto', description='Tasa impositiva a reducir del monto.'), description: Refill =
Query(default=Refill.AUTOMATICA, name='Tipo', description='Clase de Recarga')):
if quantity >= 0 and tax >= 0:
try:
mbilling.functions.add_balance(account_name, quantity, tax if description != Refill.TRASPASO else 0.0, description)
mbilling.functions.add_balance(
account_name, quantity, tax if description != Refill.TRASPASO else 0.0, description)
response = JSONResponse(
content={
'result' : 'OK',
'description' : 'Se ha realizado una recarga de {quantity} al usuario {account}.'.format(
'result': 'OK',
'description': 'Se ha realizado una recarga de {quantity} al usuario {account}.'.format(
quantity=quantity, account=account_name
)
}, status_code=201
......@@ -241,18 +274,17 @@ def add_balance(account_name: str = Query(..., regex=r'[89][1-9]\d{7}', name='N
except mbilling.functions.MagnusCommandError as e:
response = JSONResponse(
content={
'result' : 'ERROR',
'description' : f'El usuario no ha sido localizado, {str(e)}'
'result': 'ERROR',
'description': f'El usuario no ha sido localizado, {str(e)}'
}, status_code=500
)
else:
response = JSONResponse(
content={
'result' : 'ERROR',
'description' : 'La cantidad y tasa impositiva han de ser mayores que 0.'
'result': 'ERROR',
'description': 'La cantidad y tasa impositiva han de ser mayores que 0.'
}, status_code=400
)
return response
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment