Commit 15b848e5 by Javier

Métodos GET/POST de Account

parent c9a51610
from enum import Enum
import imp
from lib2to3.pytree import Base
from pydoc import resolve
from tkinter.tix import Form
from turtle import title
from unicodedata import name
from urllib import response
from fastapi import Body, Depends, FastAPI
from fastapi import Body, Depends, FastAPI, Query, Response
from fastapi.responses import JSONResponse
from typing import Optional
from typing import Optional, Tuple
from pydantic import BaseModel
import mbilling.functions
......@@ -19,6 +22,16 @@ 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'
MANUAL = 'Recarga solicitada por el Cliente'
TRASPASO = 'Traspaso de Fondos desde A2Billing'
INICIAL = 'Recarga Inicial'
class Account(BaseModel):
"""_summary_
......@@ -46,6 +59,39 @@ 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(
..., title='Contraseña', description='Credencial Cuenta SIP para host dinámico.'
)
host : str = Body(
..., title='Host', description='Dirección desde la que se conecta el usuario.'
)
credit : float = Body(
..., title='Saldo Disponible', description='Adeudo o activo que tiene el cliente.'
)
rate: Rate = Body(
default=Rate.ESTANDAR, title='Tarifa', description='Plan de Precios de la Línea'
)
class Config:
schema_extra = {
"example" : {
"number" : "856135158",
"password" : "rentel58",
"host": "192.168.2.71",
"credit": 32.45,
"rate" : Rate.PLANA_2000
}
}
class ConnectionData(BaseModel):
"""Datos de Conexión
......@@ -79,29 +125,42 @@ class ConnectionData(BaseModel):
}
@app.post('/account', response_model=ConnectionData, name='Añadir Cuenta SIP', description='Genera una nueva cuenta en el Tarificador')
def create_account( account: Account = Depends()):
"""Genera una nueva cuenta SIP con los datos proporcionados.
Args:
account (Account, optional): Modelo de Cuenta. Defaults to Depends().
"""
def encode_rate(rate : Rate = Rate.ESTANDAR) -> Tuple[int,int]:
# Tarifa por Defecto
plan_id = 1
offer_id = 0
# Selección de Tarifa
if account.rate == Rate.PLANA_1000:
if rate == Rate.PLANA_1000:
plan_id = 4
offer_id = 4
elif account.rate == Rate.PLANA_2000:
elif rate == Rate.PLANA_2000:
plan_id = 4
offer_id = 5
elif account.rate == Rate.EMPRESAS:
elif rate == Rate.EMPRESAS:
plan_id = 2
return plan_id, offer_id
def decode_rate(plan_id : int, offer_id : int = 0) -> Rate:
if plan_id == 1:
return Rate.ESTANDAR
elif plan_id == 2:
return Rate.EMPRESAS
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')
def create_account(account: Account = Depends()):
"""Genera una nueva cuenta SIP con los datos proporcionados.
Args:
account (Account, optional): Modelo de Cuenta. Defaults to Depends().
"""
plan_id, offer_id = encode_rate(account.rate)
# Generación de la Cuenta
try:
......@@ -135,3 +194,65 @@ def create_account( account: Account = Depends()):
return response
@app.get('/account/{account_name}', response_model=AccountDetails)
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)
if user_data:
response = AccountDetails(
number=account_name,
password=user_data['password'],
host=user_data['host'],
credit=user_data['credit'],
rate=decode_rate(user_data['plan'], user_data['offer'])
)
else:
response = JSONResponse(
content={
'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.')
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') ):
if quantity >= 0 and tax >= 0:
try:
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(
quantity=quantity, account=account_name
)
}, status_code=201
)
except mbilling.functions.MagnusCommandError as e:
response = JSONResponse(
content={
'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.'
}, status_code=400
)
return response
MAGNUS_HOST = 'http://192.168.2.56/mbilling'
API_KEY = 'FxMqVFWMztbigCeZlFupGULLh6LRaLs8'
API_SECRET = 'rguvK0sNZMki5yWtv4RKONMJo1Hd9jiX'
DB_USER = 'magnusupdater'
DB_PASSWORD = 'magnusupdater'
\ No newline at end of file
......@@ -2,23 +2,22 @@
include 'api.php';
// ARGUMENTOS: USUARIO SALDO
// ARGUMENTOS: USUARIO SALDO DESCRIPCIÓN
if (isset($argv[1]) && isset($argv[2])) {
$result = $magnusBilling->create('refill', [
'id_user' => $magnusBilling->getId('user', 'username', $argv[1]),
'credit' => floatval($argv[2]),
'payment' => 1,
'description' => 'Recarga Saldo'
'description' => $argv[3]
]);
if ($result['success'] == 1) {
print("[201] OK id=" . $result['rows'][0]['id']);
} else {
print("[409] ERROR Ya existe una cuenta con mismo usuario.");
$error = print_r(($result));
print("[400] ".$error);
}
} else {
print("[404] ERROR No se han introducido todos los parámetros necesarios.");
}
......@@ -2,10 +2,25 @@ import subprocess
import pathlib
import re
from random import randint
import mariadb
from dotenv import dotenv_values
# Path de MBILLING
mbapi_path = pathlib.Path(pathlib.Path().resolve(), 'mbilling')
# Petición Correcta
succesful = re.compile(r'^\[20\d\]')
# Carga de Variables ENV
values = dotenv_values(pathlib.Path(mbapi_path, '.env'))
DB_CREDENTIALS = {
'host': re.match(r'.*http://([0-9\.]+).*', values['MAGNUS_HOST'], flags=re.DOTALL).group(1),
'user': values['DB_USER'],
'password': values['DB_PASSWORD'],
'port' : 3306,
'database' : 'mbilling'
}
class MagnusCommandError(Exception):
......@@ -27,7 +42,8 @@ def _create_user(phone_number: str, password: str, name: str, surname: str, plan
if not re.match(succesful, result.decode(encoding='utf-8')):
exception_cmd = ' '.join(['php', str(pathlib.Path(mbapi_path, 'create_user.php')),
phone_number, password, f'\"{name}\"', f'\"{surname}\"', str(plan_id), str(offer_id)])
raise MagnusCommandError(f'Command: {exception_cmd} Exception: {result.decode(encoding="utf-8")}')
raise MagnusCommandError(
f'Command: {exception_cmd} Exception: {result.decode(encoding="utf-8")}')
def _create_sip(phone_number: str, password: str, pbx: str = None):
......@@ -77,3 +93,56 @@ def create_user(phone_number: str, name: str, surname: str, password: str = None
_create_did(phone_number)
return password
def add_balance(phone_number: str, quantity: float, tax: float = 0.21, description: str = 'Recarga Automática'):
"""Añade saldo a una cuenta SIP
Args:
phone_number (str): Cuenta SIP
quantity (float): Cantidad Bruta a Ingresar, incluyendo impuestos.
tax (float): Impuestos. Default 0.21
description (str, optional): Tipo de Recarga. Defaults to 'Recarga Automática'.
Raises:
MagnusCommandError: Error en Procesamiento
"""
quantity = round(quantity * (1-tax), 2)
result = subprocess.check_output(
['php', pathlib.Path(mbapi_path, 'add_balance.php'),
phone_number, quantity, f'\"{description}\"']
)
if not re.match(succesful, result.decode('utf-8')):
raise MagnusCommandError(result.decode('utf-8'))
def get_user(phone_number: str) -> dict:
"""Obtiene los datos de un usuario SIP
Args:
phone_number (str): Número
Returns:
dict: Diccionario con todos los datos.
"""
with mariadb.connect(**DB_CREDENTIALS) as cnx:
with cnx.cursor() as cursor:
headers = ['username', 'password', 'host', 'credit',
'firstname', 'lastname', 'plan', 'offer']
cursor.execute(
"""SELECT u.username, s.secret password, s.host, u.credit, u.firstname, u.lastname, p.id plan, o.id offer FROM mbilling.pkg_user u
INNER JOIN mbilling.pkg_plan p ON u.id_plan=p.id
LEFT JOIN mbilling.pkg_offer o ON u.id_offer=o.id
INNER JOIN mbilling.pkg_sip s ON u.username=s.name
WHERE username=?""",
(phone_number,)
)
query = cursor.fetchone()
return dict(zip(headers, query)) if query else None
<?php
include 'api.php';
// ARGUMENTOS : USUARIO
if (isset($argv[1])) {
# Datos del Usuario
$user_id = $magnusBilling->getId('user', 'username', $argv[1]);
$magnusBilling->setFilter('id', $user_id, 'eq', 'numeric');
$user_data = $magnusBilling->read('user');
# Datos SIP
$sip_id = $magnusBilling->getId('sip', 'name', $argv[1]);
print('SIP');
print_r($sip_id);
$magnusBilling->setFilter('name', $sip_id, 'eq', 'numeric');
$sip_data = $magnusBilling->read('sip');
print('DATA');
print_r($sip_data);
} else {
print("[404] ERROR No se han introducido todos los parámetros necesarios.");
}
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