Commit 640e0a1c by Javier

Versión Inicial

parent 802e1d6c
venv/ venv/
__pycache__ __pycache__
vendor/ vendor/
\ No newline at end of file *.log
*.tar
test*
\ No newline at end of file
...@@ -5,6 +5,15 @@ ...@@ -5,6 +5,15 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "API",
"type": "python",
"request": "launch",
"module": "uvicorn",
"args": ["main:app", "--host", "0.0.0.0" ,"--port", "8080"],
"console": "integratedTerminal",
"justMyCode": true
},
{
"name": "CLI: Sincronizar", "name": "CLI: Sincronizar",
"type": "python", "type": "python",
"request": "launch", "request": "launch",
...@@ -13,7 +22,25 @@ ...@@ -13,7 +22,25 @@
"console": "integratedTerminal", "console": "integratedTerminal",
"justMyCode": true "justMyCode": true
}, },
{ {
"name": "CLI: Restore",
"type": "python",
"request": "launch",
"program": "cli.py",
"args": ["restore"],
"console": "integratedTerminal",
"justMyCode": true
},
{
"name": "CLI: Test",
"type": "python",
"request": "launch",
"program": "cli.py",
"args": ["test"],
"console": "integratedTerminal",
"justMyCode": true
},
{
"type": "python", "type": "python",
"request": "launch", "request": "launch",
"module": "uvicorn", "module": "uvicorn",
......
...@@ -35,7 +35,17 @@ def get_dids_account(username: str) -> Tuple: ...@@ -35,7 +35,17 @@ def get_dids_account(username: str) -> Tuple:
return tuple(data) return tuple(data)
def get_redirected_dids():
with mariadb.connect(**DB_CREDENTIALS) as cnx:
with cnx.cursor() as cursor:
cursor.execute(
'SELECT did FROM cc_did_destination dest \
INNER JOIN cc_did did ON did.id=dest.id_cc_did \
WHERE dest.destination LIKE \'SIP/%@192.168.2.84\'')
dids = [did[0] for did in cursor.fetchall()]
return dids
def account_data(callerid: str = None, account : str = None) -> dict: def account_data(callerid: str = None, account : str = None) -> dict:
"""Consulta los datos de una Cuenta A2Billing """Consulta los datos de una Cuenta A2Billing
...@@ -69,4 +79,4 @@ def account_data(callerid: str = None, account : str = None) -> dict: ...@@ -69,4 +79,4 @@ def account_data(callerid: str = None, account : str = None) -> dict:
return dict(zip(headers, data + get_dids_account(data[0]))) if data else None return dict(zip(headers, data + get_dids_account(data[0]))) if data else None
if __name__ == '__main__': if __name__ == '__main__':
print(account_data('956368558')) print(account_data('956364709'))
...@@ -3,7 +3,8 @@ from typing import Tuple ...@@ -3,7 +3,8 @@ from typing import Tuple
import typer import typer
from mbilling.functions import MagnusCommandError, SipAccount, active_users, fully_ported_users from mbilling.functions import MagnusCommandError, SipAccount, active_users, fully_ported_users
from mbilling.functions import get_sip_accounts, get_cdrs, add_balance, get_user, get_plan_consumption from mbilling.functions import get_sip_accounts, get_cdrs, add_balance, get_user, get_plan_consumption
from mbilling.functions import get_accounts from mbilling.functions import get_accounts, get_flat_plan_ids, update_payment_method
import mbilling.functions as mb
import time import time
import pyodbc import pyodbc
import os import os
...@@ -40,64 +41,91 @@ def update_sip_accounts() -> 'Tuple[int,int]': ...@@ -40,64 +41,91 @@ def update_sip_accounts() -> 'Tuple[int,int]':
Tuple[int,int]: Tupla que contiene el número de cuentas SIP y DIDs Tuple[int,int]: Tupla que contiene el número de cuentas SIP y DIDs
""" """
# Inicialización de Variables Locales
sip_accounts_updated = 0 sip_accounts_updated = 0
did_accounts_updated = 0 did_accounts_updated = 0
flat_plan_ids = get_flat_plan_ids()
with pyodbc.connect(SQL_SERVER_CNX_STRING) as cnx: with pyodbc.connect(SQL_SERVER_CNX_STRING) as cnx:
with cnx.cursor() as cursor: with cnx.cursor() as cursor:
with typer.progressbar(get_accounts(only_fullyported=True), label="Sincronizando Cuentas") as accounts: with typer.progressbar(get_accounts(only_fullyported=True), label="Sincronizando Cuentas") as accounts:
for account in accounts: for account in accounts:
# Tarifa Plana if account.callerid == account.account:
flat_rate = account.plan == 4
# Saldo, 999 si es Tarifa Plana # Tarifa Plana
credit = 999.99 if flat_rate else account.credit flat_rate = account.plan in flat_plan_ids
cursor.execute( # Saldo, 999 si es Tarifa Plana
"UPDATE [bdd_wifi].[dbo].[TB_ServicioFijo]\ credit = 999.99 if account.postpaid else account.credit
SET SaldoActual=?, Activo=?, TarifaPlana=?, Pospago=?, IdTarifa=?,\
UsuarioEXT=?, ClaveEXT=?, NuevaPlataforma=1 WHERE DDI=? AND FechaBaja is NULL",
(credit, account.active, flat_rate, account.postpaid, cursor.execute(
account.plan, account.account, account.secret, account.account) "UPDATE [bdd_wifi].[dbo].[TB_ServicioFijo]\
) SET SaldoActual=?, Activo=?, TarifaPlana=?, Pospago=?, IdTarifa=?,\
UsuarioEXT=?, ClaveEXT=?, NuevaPlataforma=1 WHERE DDI=? AND FechaBaja is NULL",
(credit, account.active, flat_rate, account.postpaid or flat_rate,
account.plan, account.account, account.secret, account.account)
)
sip_accounts_updated += 1 sip_accounts_updated += 1
for did in account.dids: for did in mb.get_dids(account.account):
if did != account.account:
cursor.execute( cursor.execute(
'UPDATE [bdd_wifi].[dbo].[TB_ServicioFijo] SET CuentaA2Billing=NULL,\ 'UPDATE [bdd_wifi].[dbo].[TB_ServicioFijo] SET CuentaA2Billing=NULL,\
UsuarioEXT=NULL, ClaveEXT=NULL, Activo=?, TarifaPlana=0, Pospago=0,\ UsuarioEXT=NULL, ClaveEXT=NULL, Activo=?, TarifaPlana=0, Pospago=0,\
IdTarifa=0, SaldoActual=0.0 WHERE DDI=?', IdTarifa=0, SaldoActual=0.0, NuevaPlataforma=1 WHERE DDI=?',
(account.active, did) (account.active, did)
) )
did_accounts_updated += 1 did_accounts_updated += 1
cnx.commit() cnx.commit()
cursor.execute( cursor.execute(
'UPDATE [bdd_wifi].[dbo].[TB_ServicioFijo] SET \ 'UPDATE [bdd_wifi].[dbo].[TB_ServicioFijo] SET \
TarifaPlana=0, Pospago=0, IdTarifa=0, SaldoActual=0.0\ TarifaPlana=0, Pospago=0, IdTarifa=0, SaldoActual=0.0\
WHERE FechaBaja is not NULL', (account.active, did) WHERE FechaBaja is not NULL'
) )
cnx.commit()
return sip_accounts_updated, did_accounts_updated return sip_accounts_updated, did_accounts_updated
def synchronize_payment_method():
# Pasa a Pospago a todas las cuentas de un usuario que tenga,
# al menos una mediante pago posterior.
with pyodbc.connect(SQL_SERVER_CNX_STRING) as cnx:
with cnx.cursor() as cursor:
cursor.execute(
'UPDATE[bdd_wifi].[dbo].[TB_ServicioFijo] SET \
ImpMinimoAuto=0, ImpRecarga=0, ImpRecarga1=0, Autorecarga=0, Pospago=1 \
WHERE IDCliente IN( \
SELECT[IDCliente] \
FROM[bdd_wifi].[dbo].[TB_ServicioFijo] \
WHERE Pospago=1 AND FechaBaja is NULL AND UsuarioWifi <> \'\'\
GROUP BY IDCliente)'
)
cursor.execute(
'SELECT DDI FROM [bdd_wifi].[dbo].[TB_ServicioFijo]\
WHERE Pospago=1 AND FechaBaja is NULL'
)
for did in cursor.fetchall():
update_payment_method(did[0], postpayment=True)
def activate_new_plataform(): def activate_new_plataform():
"""Activa el Check NuevaPlataforma en las Cuentas SIP cuyas llamadas\ """Activa el Check NuevaPlataforma en las Cuentas SIP cuyas llamadas\
salgan por MagnusBilling""" salgan por MagnusBilling"""
with pyodbc.connect(SQL_SERVER_CNX_STRING) as cnx: with pyodbc.connect(SQL_SERVER_CNX_STRING) as cnx:
with cnx.cursor() as cursor: with cnx.cursor() as cursor:
for user in get_accounts(only_fullyported=True): for user in get_accounts(only_fullyported=True, only_active=True):
cursor.execute( cursor.execute(
'UPDATE [bdd_wifi].[dbo].[TB_ServicioFijo] SET NuevaPlataforma=1 WHERE DDI=?\ 'UPDATE [bdd_wifi].[dbo].[TB_ServicioFijo] SET NuevaPlataforma=1 WHERE DDI=?\
AND FechaBaja is NULL', AND FechaBaja is NULL', (user.account,)
(user.account,)
) )
cursor.execute( cursor.execute(
...@@ -137,14 +165,7 @@ def perform_migration(): ...@@ -137,14 +165,7 @@ def perform_migration():
a2billing_user['account'] if a2billing_user else None) a2billing_user['account'] if a2billing_user else None)
) )
for user_did in user.dids:
if user_did != user.account:
cursor.execute(
'UPDATE [bdd_wifi].[dbo].[TB_ServicioFijo] SET CuentaA2Billing=NULL,\
UsuarioEXT=NULL, ClaveEXT=NULL, Activo=?, TarifaPlana=0, Pospago=0,\
IdTarifa=0, SaldoActual=0.0 WHERE DDI=? AND FechaBaja is NULL',
(user.active, user_did)
)
cnx.commit() cnx.commit()
...@@ -211,7 +232,7 @@ def update_balance() -> Tuple[int, Decimal]: ...@@ -211,7 +232,7 @@ def update_balance() -> Tuple[int, Decimal]:
if sip_account['username'] != sip_account['sip']: if sip_account['username'] != sip_account['sip']:
credit = 0.0 credit = 0.0
elif sip_account['credit'] <= 0.0 and sip_account['postpaid'] == True: elif sip_account['postpaid'] == True:
credit = 999.00 credit = 999.00
else: else:
credit = round(sip_account['credit'], 2) credit = round(sip_account['credit'], 2)
...@@ -236,10 +257,26 @@ def update_balance() -> Tuple[int, Decimal]: ...@@ -236,10 +257,26 @@ def update_balance() -> Tuple[int, Decimal]:
def update_a2billing_balance(): def update_a2billing_balance():
with pyodbc.connect(SQL_SERVER_CNX_STRING) as cnx: with pyodbc.connect(SQL_SERVER_CNX_STRING) as cnx:
with cnx.cursor() as cursor: with cnx.cursor() as cursor:
# Si la Cuenta no tiene Campo A2Billing, se añade.
cursor.execute(
'SELECT ID, DDI FROM TB_ServicioFijo \
WHERE CuentaA2Billing is NULL AND FechaBaja is NULL AND DDI <> \'\'')
for ddi in cursor.fetchall():
a2billing_account = a2billing.account_data(ddi[1])
if a2billing_account:
cursor.execute(
'UPDATE TB_ServicioFijo SET CuentaA2Billing=? WHERE ID=?',
(ddi[1], ddi[0])
)
cnx.commit()
# Selección de Cuentas A2Billing
cursor.execute( cursor.execute(
'SELECT DDI, UsuarioEXT FROM [bdd_wifi].[dbo].[TB_ServicioFijo]\ 'SELECT DDI, UsuarioEXT FROM [bdd_wifi].[dbo].[TB_ServicioFijo]\
WHERE NuevaPlataforma=0 AND FechaBaja is NULL AND UsuarioEXT is not NULL') WHERE NuevaPlataforma=0 AND FechaBaja is NULL AND UsuarioEXT is not NULL')
# Actualización
for cli in cursor.fetchall(): for cli in cursor.fetchall():
account_data = a2billing.account_data( account_data = a2billing.account_data(
callerid=cli[0], account=cli[1]) callerid=cli[0], account=cli[1])
...@@ -470,17 +507,19 @@ def synchronize(): ...@@ -470,17 +507,19 @@ def synchronize():
# Sincronización de Cuentas # Sincronización de Cuentas
activate_new_plataform() activate_new_plataform()
sip_accounts, did_accounts = update_sip_accounts()
perform_migration() perform_migration()
#update_a2billing_balance() synchronize_payment_method()
msg += f'\t- Se han actualizado {typer.style(sip_accounts, fg=typer.colors.GREEN, bold=True)} CLIs y ' update_a2billing_balance()
msg += f'{typer.style(did_accounts, fg=typer.colors.BRIGHT_YELLOW, bold=True)} DIDs.'
# Recargas # Recargas
total_refills, amount = process_refills() total_refills, amount = process_refills()
msg += f"\n\t- Se han procesado {typer.style(total_refills, fg=typer.colors.GREEN, bold=True)} " msg += f"\n\t- Se han procesado {typer.style(total_refills, fg=typer.colors.GREEN, bold=True)} "
msg += f"recargas con un importe total de {typer.style(f'{amount}€', fg=typer.colors.GREEN, bold=True)}" msg += f"recargas con un importe total de {typer.style(f'{amount}€', fg=typer.colors.GREEN, bold=True)}"
sip_accounts, did_accounts = update_sip_accounts()
msg += f'\n\t- Se han actualizado {typer.style(sip_accounts, fg=typer.colors.GREEN, bold=True)} CLIs y '
msg += f'{typer.style(did_accounts, fg=typer.colors.BRIGHT_YELLOW, bold=True)} DIDs.'
# Actualización de CDRs # Actualización de CDRs
new_cdrs = add_cdrs() new_cdrs = add_cdrs()
msg += f"\n\t- Se han agregado {len(new_cdrs)} llamadas al CDR." msg += f"\n\t- Se han agregado {len(new_cdrs)} llamadas al CDR."
...@@ -490,7 +529,8 @@ def synchronize(): ...@@ -490,7 +529,8 @@ def synchronize():
@app.command() @app.command()
def test(): def test():
update_a2billing_balance() print(a2billing.account_data('956810498'))
# update_a2billing_balance()
if __name__ == "__main__": if __name__ == "__main__":
......
from enum import Enum from enum import Enum
import imp
from lib2to3.pytree import Base
from pydoc import resolve
from re import RegexFlag
from tkinter.tix import Form
from turtle import title
from unicodedata import name
from urllib import response
from fastapi import Body, Depends, FastAPI, HTTPException, Query, Response from fastapi import Body, Depends, FastAPI, HTTPException, Query, Response
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from typing import Optional, Tuple from typing import Optional, Tuple
...@@ -126,6 +118,118 @@ class ConnectionData(BaseModel): ...@@ -126,6 +118,118 @@ class ConnectionData(BaseModel):
} }
class PeerDetails(BaseModel):
username: str = Body(
..., title='username', description='Nombre de Usuario'
)
secret: str = Body(
..., title='Secret', description='Contraseña'
)
fromuser: str = Body(
..., title='fromuser', description='Usuario SIP'
)
careinvite: bool = Body(
default=False, title='CareInvite', description='Comportamiento Invite, por defecto False.'
)
natforce: str = Body(
default='force_rport,comedia', title='NAT', description='Network Address Translation'
)
qualify: str = Body(
default='yes', title='Qualify', description='SIP Ping a Central'
)
type: str = Body(
default='friend', title='Type', description='Tipo de Conexión'
)
dtmfmode: str = Body(
default='RFC2833', title='DTMF', description='Tipo de Señalización'
)
insecure: str = Body(
default='port', title='Insecure', description='Permite autentificación relajada si coincide IP'
)
host: str = Body(
default='192.168.2.84', title='Host', description='Dirección del Tarificador'
)
disallow: str = Body(
default='all', title='Disallow', description='Codecs no Permitidos'
)
allow: str = Body(
default='gsm,opus,alaw,g729', title='Allow', description='Códecs Permitidos'
)
class UserDetails(BaseModel):
username: str = Body(
..., title='username', description='Nombre de Usuario'
)
secret: str = Body(
..., title='Secret', description='Contraseña'
)
fromuser: str = Body(
..., title='fromuser', description='Usuario SIP'
)
careinvite: bool = Body(
default=False, title='CareInvite', description='Comportamiento Invite, por defecto False.'
)
type: str = Body(
default='friend', title='Type', description='Tipo de Conexión'
)
dtmfmode: str = Body(
default='RFC2833', title='DTMF', description='Tipo de Señalización'
)
insecure: str = Body(
default='port', title='Insecure', description='Permite autentificación relajada si coincide IP'
)
host: str = Body(
default='192.168.2.84', title='Host', description='Dirección del Tarificador'
)
disallow: str = Body(
default='all', title='Disallow', description='Codecs no Permitidos'
)
allow: str = Body(
default='gsm,opus,alaw,g729', title='Allow', description='Códecs Permitidos'
)
class VoipCredentials(BaseModel):
trunk_name: str = Body(
..., title='Trunk', description='Nombre de la Troncal'
)
peer_details: PeerDetails = Body(
..., title='Peer Details', description='Credenciales llamadas Salientes'
)
user_context: str = Body(
default='from-trunk', title='Contexto', description='Contexto de Llamada'
)
user_details: UserDetails = Body(
..., title='User Details', description='Credenciales llamadas Entrantes'
)
class AccountDetails(BaseModel): class AccountDetails(BaseModel):
"""Detalles de una cuenta SIP """Detalles de una cuenta SIP
...@@ -144,7 +248,7 @@ class AccountDetails(BaseModel): ...@@ -144,7 +248,7 @@ class AccountDetails(BaseModel):
default=Rate.ESTANDAR, title='Tarifa', description='Plan de Precios de la Línea' default=Rate.ESTANDAR, title='Tarifa', description='Plan de Precios de la Línea'
) )
credentials: ConnectionData = Body( credentials: VoipCredentials = Body(
..., title='Datos de Conexión', ..., title='Datos de Conexión',
) )
...@@ -159,6 +263,13 @@ class AccountDetails(BaseModel): ...@@ -159,6 +263,13 @@ class AccountDetails(BaseModel):
} }
} }
def account_details(account_name : str) -> AccountDetails:
user_data = mbilling.functions.get_user(account_name)
if user_data:
return None
else:
return None
def encode_rate(rate: Rate = Rate.ESTANDAR) -> Tuple[int, int]: def encode_rate(rate: Rate = Rate.ESTANDAR) -> Tuple[int, int]:
"""Genera los ID de plan y oferta. """Genera los ID de plan y oferta.
...@@ -254,7 +365,8 @@ def create_account(account: Account = Depends()): ...@@ -254,7 +365,8 @@ def create_account(account: Account = Depends()):
) )
else: else:
response = JSONResponse(content={'error' : 'El número ya está registrado en MagnusBilling'}, status_code=409) response = JSONResponse(
content={'error': 'El número ya está registrado en MagnusBilling'}, status_code=409)
return response return response
...@@ -293,9 +405,11 @@ def get_account(account_name: str = Query(..., regex=r'[89][1-9]\d{7}', name='N ...@@ -293,9 +405,11 @@ def get_account(account_name: str = Query(..., regex=r'[89][1-9]\d{7}', name='N
@app.post('/account/{account_name}/balance', name='Añade saldo a una cuenta SIP', description='Realiza una recarga en nombre del cliente.', tags=['Account']) @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'), 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'), quantity: float = Query(
tax: Tax = Query(default=Tax.GENERAL, name='Impuesto', description='Tasa impositiva a reducir del monto.'), default=10.00, name='Cantidad', description='Total a ingresar incluyendo impuestos'),
description: Refill =Query(default=Refill.AUTOMATICA, name='Tipo', description='Clase de Recarga')): 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: if quantity >= 0:
try: try:
...@@ -321,6 +435,11 @@ def add_balance(account_name: str = Query(..., regex=r'[89][1-9]\d{7}', name='N ...@@ -321,6 +435,11 @@ def add_balance(account_name: str = Query(..., regex=r'[89][1-9]\d{7}', name='N
}, status_code=201 }, status_code=201
) )
except mbilling.functions.MagnusCommandError as e: except mbilling.functions.MagnusCommandError as e:
raise HTTPException(status_code=404, detail="La cuenta SIP no ha sido localizada.") raise HTTPException(
status_code=404, detail="La cuenta SIP no ha sido localizada.")
else: else:
raise HTTPException(status_code=400, detail="La cantidad debe ser mayor que 0.0€") raise HTTPException(
status_code=400, detail="La cantidad debe ser mayor que 0.0€")
if __name__ == '__main__':
user = account_details('856135158')
\ No newline at end of file
...@@ -29,7 +29,9 @@ class SipAccount: ...@@ -29,7 +29,9 @@ class SipAccount:
def __init__(self, callerid: str, account: str, secret: str, def __init__(self, callerid: str, account: str, secret: str,
firstname: str, lastname: str, credit: float, firstname: str, lastname: str, credit: float,
plan: int, offer: int, active: bool, postpaid: bool, plan: int, offer: int, active: bool, postpaid: bool,
host: str = None, dids: list = None) -> None: dtmf: str, insecure: str, nat: str, qualify : str,
type: str, disallow: str, allow : str, host: str = None,
dids: list = None) -> None:
self.callerid = callerid self.callerid = callerid
self.account = account self.account = account
...@@ -41,7 +43,13 @@ class SipAccount: ...@@ -41,7 +43,13 @@ class SipAccount:
self.active = active self.active = active
self.postpaid = postpaid self.postpaid = postpaid
self.dids = dids self.dids = dids
self.dtmf = dtmf
self.insecure = insecure
self.nat = nat
self.qualify = qualify
self.type = type
self.disallow = disallow
self.allow = allow
class MagnusCommandError(Exception): class MagnusCommandError(Exception):
...@@ -212,38 +220,37 @@ def get_user(phone_number: str) -> SipAccount: ...@@ -212,38 +220,37 @@ def get_user(phone_number: str) -> SipAccount:
""" """
if phone_number: if phone_number:
account = None
with mariadb.connect(**DB_CREDENTIALS) as cnx: with mariadb.connect(**DB_CREDENTIALS) as cnx:
with cnx.cursor() as cursor: with cnx.cursor() as cursor:
headers = ['callerid', 'account', 'secret', 'host', 'credit', headers = ['callerid', 'account', 'secret', 'host', 'credit',
'firstname', 'lastname', 'plan', 'offer', 'firstname', 'lastname', 'plan', 'offer', 'active',
'active', 'postpaid'] 'postpaid', 'dtmf', 'insecure', 'nat', 'qualify',
'type', 'disallow', 'allow']
cursor.execute(
'SELECT s.name, u.username, s.secret password, s.host, u.credit, u.firstname,\ query = 'SELECT s.name, u.username, s.secret password, s.host, u.credit, u.firstname, \
u.lastname, p.id plan, IFNULL(o.id, 0) offer, u.active active, u.typepaid\ u.lastname, p.id plan, IFNULL(o.id, 0) offer, u.active active, u.typepaid, \
FROM mbilling.pkg_user u\ s.dtmfmode, s.insecure, s.nat, s.qualify, s.type, s.disallow, s.allow \
INNER JOIN mbilling.pkg_plan p ON u.id_plan=p.id\ FROM mbilling.pkg_user u \
LEFT JOIN mbilling.pkg_offer o ON u.id_offer=o.id\ INNER JOIN mbilling.pkg_plan p ON u.id_plan=p.id \
INNER JOIN mbilling.pkg_sip s ON u.id=s.id_user\ LEFT JOIN mbilling.pkg_offer o ON u.id_offer=o.id \
WHERE s.name=? OR u.username=?', INNER JOIN mbilling.pkg_sip s ON u.id=s.id_user \
(phone_number,phone_number) WHERE s.name={phone_number}'.format(phone_number=phone_number)
) cursor.execute(query)
query = cursor.fetchone() sip_accounts = cursor.fetchall()
account = dict(zip(headers, query)) if query else None
if sip_accounts:
if account: account = dict(
cursor.execute( zip(
'SELECT s.name from pkg_user u INNER JOIN pkg_sip s ON u.id=s.id_user\ headers, [
WHERE u.username=?', x for x in sip_accounts if x[0] == x[1]][0]
(account['account'],) )
) )
account['dids'] = [ddi[0] for ddi in cursor.fetchall()] if not account:
else: print(account)
account['dids'] = None
else:
account = None
return SipAccount(**account) if account else None return SipAccount(**account) if account else None
...@@ -272,6 +279,19 @@ def fully_ported_users() -> 'list[tuple]': ...@@ -272,6 +279,19 @@ def fully_ported_users() -> 'list[tuple]':
return data return data
def get_dids(account : str) -> list:
with mariadb.connect(**DB_CREDENTIALS) as cnx:
with cnx.cursor() as cursor:
cursor.execute(
'SELECT s.name FROM pkg_user u \
LEFT JOIN pkg_sip s ON u.id=s.id_user \
WHERE u.username=? AND s.name <> u.username',
(account,)
)
dids = [x[0] for x in cursor.fetchall()]
return dids
def get_plan_consumption(*account: str) -> dict: def get_plan_consumption(*account: str) -> dict:
...@@ -428,3 +448,41 @@ def get_accounts(only_active: bool = False, only_postpaid: bool = False, ...@@ -428,3 +448,41 @@ def get_accounts(only_active: bool = False, only_postpaid: bool = False,
for account in cursor.fetchall(): for account in cursor.fetchall():
yield get_user(account[0]) yield get_user(account[0])
def get_flat_plan_ids() -> list:
"""Obtiene un listado de las IDs de las Tarifas Planas
Returns:
list: Listado de IDs de Tarifas Planas
"""
with mariadb.connect(**DB_CREDENTIALS) as cnx:
with cnx.cursor() as cursor:
cursor.execute(
'SELECT id FROM mbilling.pkg_plan WHERE name LIKE \'%Plana%\'')
flat_plan_ids = [plan_id[0] for plan_id in cursor.fetchall()]
return flat_plan_ids
def update_payment_method(phone_number: str, postpayment: bool, limit: float = 30.00):
"""Modifica el método de pago del cliente.
Args:
phone_number (str): Número de Teléfono asociado a la Cuenta
postpayment (bool, optional): Postpago. Defaults to True.
limit (float, optional): Límite. Defaults to 30.00.
override_limit (bool, optional): Sobrescribe el límite de crédito si ya existe uno. Defaults to False.
"""
with mariadb.connect(**DB_CREDENTIALS) as cnx:
with cnx.cursor() as cursor:
cursor.execute(
'UPDATE mbilling.pkg_user u \
LEFT JOIN mbilling.pkg_user u2 ON u.firstname=u2.firstname AND u.lastname=u2.lastname \
LEFT JOIN mbilling.pkg_did did ON u.id=did.id_user \
SET u2.typepaid=?, u2.creditlimit=? \
WHERE did.did=?',
(postpayment, limit if postpayment else 0.0, phone_number)
)
cnx.commit()
API_HOST='https://apifijo.ptvtelecom.com'
USER = 'B72130198'
PASSWORD = 'dFrU6iKw'
TOKEN = 'RwBYAKwBP2eBnP2'
\ No newline at end of file
No preview for this file type
from email import message import pyodbc
from a2billing.a2billing import account_data
import os
sql_server_hostname = "192.168.2.200"
sql_server_database = "bdd_wifi"
sql_server_username = "api-mbilling"
sql_server_password = "mbillingmbilling"
sql_server_driver = 'ODBC Driver 17 for SQL Server' if os.name == 'nt' else 'FreeTDS'
# Cadena de Conexión
SQL_SERVER_CNX_STRING = "DRIVER={driver};SERVER={server};\
DATABASE={database};UID={username};PWD={password};TDS_Version=7.0;".format(
driver=sql_server_driver, server=sql_server_hostname,
database=sql_server_database, username=sql_server_username,
password=sql_server_password)
with pyodbc.connect(SQL_SERVER_CNX_STRING) as cnx:
with cnx.cursor() as cursor:
cursor.execute(
'SELECT [ID], [DDI] \
FROM [bdd_wifi].[dbo].[TB_ServicioFijo] \
WHERE FechaBaja is NULL AND NuevaPlataforma=1 \
ORDER BY UsuarioWifi, UsuarioEXT DESC'
)
for ddi in cursor.fetchall():
data = account_data(ddi[1])
cursor.execute(
'UPDATE [bdd_wifi].[dbo].[TB_ServicioFijo] SET CuentaA2Billing=? WHERE ID=?',
(data['account'] if data else None, ddi[0])
)
cnx.commit()
def fibonacci(n : int):
if n < 0:
raise ValueError()
a,b = 0,1
for i in range(n+1):
a, b = b, a + b
yield a
class Private:
def __init__(self, msg):
self._message = msg
class SecurePrivate(Private):
def __init__(self, password, msg):
self.password = password
super().__init__(msg)
def get_message(self, password):
if self.password == password:
return self._message
private = SecurePrivate('Hola', 'Mundo')
print(private.get_message('Hola'))
\ No newline at end of file
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