Configuracion final de back con serve

This commit is contained in:
2026-03-17 16:22:20 -05:00
commit af07bbc36b
21 changed files with 574 additions and 0 deletions

31
.gitignore vendored Normal file
View File

@@ -0,0 +1,31 @@
# Entorno virtual
venv/
ENV/
env/
.venv/
# Archivos de configuración del entorno
.env
*.env
# Python cache
__pycache__/
*.py[cod]
*$py.class
# Logs y archivos temporales
*.log
*.sqlite3
*.db
*.DS_Store
*.egg-info/
*.egg
# IDEs y editores
.vscode/
.idea/
*.sublime-project
*.sublime-workspace
# Otros
*.pyc

View File

View File

@@ -0,0 +1,16 @@
from fastapi import APIRouter
from Back_comercial_iko.services.Comercial_service import ComercialService
from Back_comercial_iko.core.Response import ApiResponse
from Back_comercial_iko.core.HttpStatus import HttpStatus
router = APIRouter(prefix="/comercial", tags=["Comercial"])
@router.post("/create-project")
def create_project(data: dict):
try:
service = ComercialService()
result = service.create_project_commercial(data)
return ApiResponse.success(result,"Proyecto creado",HttpStatus.CREATED)
except Exception as e:
return ApiResponse.error(str(e),HttpStatus.NOT_FOUND)

View File

@@ -0,0 +1,48 @@
import jwt
from datetime import datetime, timedelta
from typing import Dict, Any
from core.Config import settings
class TokenManager:
"""
Handles token generation and validation
"""
@classmethod
def generate(cls, payload: Dict[str, Any]) -> str:
data = cls._add_expiration(payload)
return jwt.encode(
data,
settings.token_secret_key,
algorithm=settings.token_algorithm
)
@classmethod
def verify(cls, token: str) -> Dict[str, Any]:
try:
return jwt.decode(
token,
settings.token_secret_key,
algorithms=[settings.token_algorithm]
)
except jwt.ExpiredSignatureError:
raise ValueError("Token expired")
except jwt.InvalidTokenError:
raise ValueError("Invalid token")
@classmethod
def _add_expiration(cls, payload: Dict[str, Any]) -> Dict[str, Any]:
expiration = datetime.utcnow() + timedelta(
minutes=settings.token_expire_minutes
)
data = payload.copy()
data["exp"] = expiration
return data

View File

@@ -0,0 +1,15 @@
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
token_secret_key: str
token_algorithm: str
token_expire_minutes: int
class Config:
env_file = ".env"
extra = "ignore"
settings = Settings()

View File

@@ -0,0 +1,16 @@
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from fastapi import Request
from Back_comercial_iko.core.HttpStatus import HttpStatus
async def validation_exception_handler(request: Request, exc: RequestValidationError):
return JSONResponse(
status_code=HttpStatus.BAD_REQUEST,
content={
"success": False,
"message": "Formato de request inválido",
"error_code": "INVALID_JSON"
}
)

View File

@@ -0,0 +1,14 @@
class HttpStatus:
"""
Common HTTP status codes used in the API
"""
OK = 200
CREATED = 201
NO_CONTENT = 204
BAD_REQUEST = 400
UNAUTHORIZED = 401
FORBIDDEN = 403
NOT_FOUND = 404
CONFLICT = 409
UNPROCESSABLE_ENTITY = 422
INTERNAL_SERVER_ERROR = 500

View File

@@ -0,0 +1,53 @@
from fastapi.responses import JSONResponse
from typing import Any, Optional
from Back_comercial_iko.core.HttpStatus import HttpStatus
class ApiResponse:
@staticmethod
def success(
data: Optional[Any] = None,
message: str = "Success",
status_code: int = HttpStatus.OK
):
return JSONResponse(
status_code=status_code,
content={
"success": True,
"message": message,
"data": data
}
)
@staticmethod
def error(
message: str,
status_code: int = HttpStatus.BAD_REQUEST,
data: Optional[Any] = None
):
return JSONResponse(
status_code=status_code,
content={
"success": False,
"message": message,
"data": data
}
)
@staticmethod
def exception(
exception: Exception,
status_code: int = HttpStatus.INTERNAL_SERVER_ERROR
):
return JSONResponse(
status_code=status_code,
content={
"success": False,
"message": str(exception),
"data": None
}
)

View File

@@ -0,0 +1,10 @@
class SocieteNotFoundException(Exception):
def __init__(self, societe_name=None, extra_msg=None):
base_message = "Societe not found"
if societe_name:
base_message += f": '{societe_name}'"
if extra_msg:
base_message += f" - {extra_msg}"
self.message = base_message
super().__init__(self.message)

View File

@@ -0,0 +1,13 @@
import re
class EmailValidator:
EMAIL_REGEX = r"^[\w\.-]+@[\w\.-]+\.\w+$"
@staticmethod
def validate(email: str) -> bool:
if not email:
return False
return re.match(EmailValidator.EMAIL_REGEX, email) is not None

View File

@@ -0,0 +1,7 @@
class FieldValidator:
@staticmethod
def required(value, field_name: str):
if value is None or value == "":
raise ValueError(f"{field_name} es obligatorio")

View File

@@ -0,0 +1,25 @@
import os
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from dotenv import load_dotenv
load_dotenv()
class Database:
def __init__(self):
self.user = os.getenv("DB_USER")
self.password = os.getenv("DB_PASSWORD")
self.server = os.getenv("DB_HOST")
self.port = os.getenv("DB_PORT")
self.database = os.getenv("DB_NAME")
self.engine = self.getconnection()
def getconnection(self):
return create_engine(
"mysql+pymysql://{0}:{1}@{2}/{3}".format(self.user, self.password, self.server, self.database)
)
def setConnection(self):
session = sessionmaker(bind=self.engine)
return session()

View File

@@ -0,0 +1,9 @@
from fastapi import FastAPI
from fastapi.exceptions import RequestValidationError
from Back_comercial_iko.core.ExceptionHandler import validation_exception_handler
from Back_comercial_iko.app.comercial.Main_comercial import router as comercial_router
app = FastAPI()
app.include_router(comercial_router)
app.add_exception_handler(RequestValidationError, validation_exception_handler)

View File

@@ -0,0 +1,24 @@
from sqlalchemy import Column, Integer, String, Date, TIMESTAMP
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime
Base = declarative_base()
class ProjetExtrafieldsModel(Base):
__tablename__ = "llx_projet_extrafields"
ROWID = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
TMS = Column(TIMESTAMP, nullable=True)
FK_OBJECT = Column(Integer, nullable=False)
IMPORT_KEY = Column(String(14), nullable=True)
DEVELOPER = Column(Integer, nullable=True)
TIPO = Column(String(255), nullable=True)
TIPO_COMERCIAL = Column(String(255), nullable=True)
FK_EMPLAZAMIENTO = Column(Integer, nullable=True)
LAST_CONTACT = Column(Date, nullable=True)
EX_MONTH = Column(Integer, nullable=True)
EX_MONTH2 = Column(String(50), nullable=True)
ESTADO = Column(String(150), nullable=True)
ESTADO_COMERCIAL = Column(String(150), nullable=True)
AGENCIA = Column(String(150), nullable=True)
ANUNCIANTE = Column(String(150), nullable=True)

View File

@@ -0,0 +1,52 @@
from sqlalchemy import Column, Integer, String, DateTime, Text, Float, Date, TIMESTAMP
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime
Base = declarative_base()
class ProjetModel(Base):
__tablename__ = "llx_projet"
ROWID = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
FK_SOC = Column(Integer, nullable=True)
DATEC = Column(DateTime, nullable=True)
TMS = Column(TIMESTAMP, nullable=True)
DATEO = Column(Date, nullable=True)
DATEE = Column(Date, nullable=True)
REF = Column(String(50), nullable=True)
ENTITY = Column(Integer, nullable=False, default=1)
TITLE = Column(String(255), nullable=False)
DESCRIPTION = Column(Text, nullable=True)
FK_USER_CREAT = Column(Integer, nullable=False)
FK_USER_MODIF = Column(Integer, nullable=True)
PUBLIC = Column(Integer, nullable=True)
FK_STATUT = Column(Integer, nullable=False, default=0)
FK_OPP_STATUS = Column(Integer, nullable=True)
OPP_PERCENT = Column(Float, nullable=True)
FK_OPP_STATUS_END = Column(Integer, nullable=True)
DATE_CLOSE = Column(DateTime, nullable=True)
FK_USER_CLOSE = Column(Integer, nullable=True)
NOTE_PRIVATE = Column(Text, nullable=True)
NOTE_PUBLIC = Column(Text, nullable=True)
EMAIL_MSGID = Column(String(175), nullable=True)
OPP_AMOUNT = Column(Float, nullable=True)
BUDGET_AMOUNT = Column(Float, nullable=True)
USAGE_OPPORTUNITY = Column(Integer, nullable=True, default=0)
USAGE_TASK = Column(Integer, nullable=True, default=1)
USAGE_BILL_TIME = Column(Integer, nullable=True, default=0)
USAGE_ORGANIZE_EVENT = Column(Integer, nullable=True, default=0)
DATE_START_EVENT = Column(DateTime, nullable=True)
DATE_END_EVENT = Column(DateTime, nullable=True)
LOCATION = Column(String(255), nullable=True)
ACCEPT_CONFERENCE_SUGGESTIONS = Column(Integer, nullable=True, default=0)
ACCEPT_BOOTH_SUGGESTIONS = Column(Integer, nullable=True, default=0)
MAX_ATTENDEES = Column(Integer, nullable=True, default=0)
PRICE_REGISTRATION = Column(Float, nullable=True)
PRICE_BOOTH = Column(Float, nullable=True)
MODEL_PDF = Column(String(255), nullable=True)
IP = Column(String(250), nullable=True)
LAST_MAIN_DOC = Column(String(255), nullable=True)
IMPORT_KEY = Column(String(14), nullable=True)
EXTRAPARAMS = Column(String(255), nullable=True)
CREATED_AT = Column(DateTime, default=datetime.utcnow)
UPDATED_AT = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

View File

@@ -0,0 +1,99 @@
from sqlalchemy import Column, Integer, String, DateTime, Text, Float, TIMESTAMP
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime
Base = declarative_base()
class SocieteModel(Base):
__tablename__ = "llx_societe"
ROWID = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
NOM = Column(String(128), nullable=True)
NAME_ALIAS = Column(String(128), nullable=True)
ENTITY = Column(Integer, nullable=False, default=1)
REF_EXT = Column(String(255), nullable=True)
STATUT = Column(Integer, nullable=True, default=0)
PARENT = Column(Integer, nullable=True)
STATUS = Column(Integer, nullable=True, default=1)
CODE_CLIENT = Column(String(24), nullable=True)
CODE_FOURNISSEUR = Column(String(24), nullable=True)
CODE_COMPTA = Column(String(24), nullable=True)
CODE_COMPTA_FOURNISSEUR = Column(String(24), nullable=True)
ADDRESS = Column(String(255), nullable=True)
ZIP = Column(String(25), nullable=True)
TOWN = Column(String(50), nullable=True)
FK_DEPARTEMENT = Column(Integer, nullable=True, default=0)
FK_PAYS = Column(Integer, nullable=True, default=0)
FK_ACCOUNT = Column(Integer, nullable=True, default=0)
PHONE = Column(String(20), nullable=True)
FAX = Column(String(20), nullable=True)
URL = Column(String(255), nullable=True)
EMAIL = Column(String(128), nullable=True)
SOCIALNETWORKS = Column(Text, nullable=True)
FK_EFFECTIF = Column(Integer, nullable=True, default=0)
FK_TYPENT = Column(Integer, nullable=True)
FK_FORME_JURIDIQUE = Column(Integer, nullable=True, default=0)
FK_CURRENCY = Column(String(3), nullable=True)
SIREN = Column(String(128), nullable=True)
SIRET = Column(String(128), nullable=True)
APE = Column(String(128), nullable=True)
IDPROF4 = Column(String(128), nullable=True)
IDPROF5 = Column(String(128), nullable=True)
IDPROF6 = Column(String(128), nullable=True)
TVA_INTRA = Column(String(20), nullable=True)
CAPITAL = Column(Float, nullable=True)
FK_STCOMM = Column(Integer, nullable=False, default=0)
NOTE_PRIVATE = Column(Text, nullable=True)
NOTE_PUBLIC = Column(Text, nullable=True)
MODEL_PDF = Column(String(255), nullable=True)
LAST_MAIN_DOC = Column(String(255), nullable=True)
PREFIX_COMM = Column(String(5), nullable=True)
CLIENT = Column(Integer, nullable=True, default=0)
FOURNISSEUR = Column(Integer, nullable=True, default=0)
SUPPLIER_ACCOUNT = Column(String(32), nullable=True)
FK_PROSPECTLEVEL = Column(String(12), nullable=True)
FK_INCOTERMS = Column(Integer, nullable=True)
LOCATION_INCOTERMS = Column(String(255), nullable=True)
CUSTOMER_BAD = Column(Integer, nullable=True, default=0)
CUSTOMER_RATE = Column(Float, nullable=True, default=0)
SUPPLIER_RATE = Column(Float, nullable=True, default=0)
REMISE_CLIENT = Column(Float, nullable=True, default=0)
REMISE_SUPPLIER = Column(Float, nullable=True, default=0)
MODE_REGLEMENT = Column(Integer, nullable=True)
COND_REGLEMENT = Column(Integer, nullable=True)
DEPOSIT_PERCENT = Column(String(63), nullable=True)
TRANSPORT_MODE = Column(Integer, nullable=True)
MODE_REGLEMENT_SUPPLIER = Column(Integer, nullable=True)
COND_REGLEMENT_SUPPLIER = Column(Integer, nullable=True)
TRANSPORT_MODE_SUPPLIER = Column(Integer, nullable=True)
FK_SHIPPING_METHOD = Column(Integer, nullable=True)
TVA_ASSUJ = Column(Integer, nullable=True, default=1)
LOCALTAX1_ASSUJ = Column(Integer, nullable=True, default=0)
LOCALTAX1_VALUE = Column(Float, nullable=True)
LOCALTAX2_ASSUJ = Column(Integer, nullable=True, default=0)
LOCALTAX2_VALUE = Column(Float, nullable=True)
BARCODE = Column(String(180), nullable=True)
FK_BARCODE_TYPE = Column(Integer, nullable=True, default=0)
PRICE_LEVEL = Column(Integer, nullable=True)
OUTSTANDING_LIMIT = Column(Float, nullable=True)
ORDER_MIN_AMOUNT = Column(Float, nullable=True)
SUPPLIER_ORDER_MIN_AMOUNT = Column(Float, nullable=True)
DEFAULT_LANG = Column(String(6), nullable=True)
LOGO = Column(String(255), nullable=True)
LOGO_SQUARRED = Column(String(255), nullable=True)
CANVAS = Column(String(32), nullable=True)
FK_WAREHOUSE = Column(Integer, nullable=True)
WEBSERVICES_URL = Column(String(255), nullable=True)
WEBSERVICES_KEY = Column(String(128), nullable=True)
ACCOUNTANCY_CODE_SELL = Column(String(32), nullable=True)
ACCOUNTANCY_CODE_BUY = Column(String(32), nullable=True)
TMS = Column(TIMESTAMP, nullable=True)
DATEC = Column(DateTime, nullable=True)
FK_USER_CREAT = Column(Integer, nullable=True)
FK_USER_MODIF = Column(Integer, nullable=True)
FK_MULTICURRENCY = Column(Integer, nullable=True)
MULTICURRENCY_CODE = Column(String(3), nullable=True)
IMPORT_KEY = Column(String(14), nullable=True)
CREATED_AT = Column(DateTime, default=datetime.utcnow)
UPDATED_AT = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

View File

@@ -0,0 +1,88 @@
from sqlalchemy import Column, Integer, String, DateTime, Text, Float, Date, TIMESTAMP
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime
Base = declarative_base()
class UserModel(Base):
__tablename__ = "llx_user"
ROWID = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
ENTITY = Column(Integer, nullable=False, default=1)
REF_EMPLOYEE = Column(String(50), nullable=True)
REF_EXT = Column(String(50), nullable=True)
ADMIN = Column(Integer, nullable=True, default=0)
EMPLOYEE = Column(Integer, nullable=True, default=1)
FK_ESTABLISHMENT = Column(Integer, nullable=True, default=0)
DATEC = Column(DateTime, nullable=True)
TMS = Column(TIMESTAMP, nullable=True)
FK_USER_CREAT = Column(Integer, nullable=True)
FK_USER_MODIF = Column(Integer, nullable=True)
LOGIN = Column(String(50), nullable=False)
PASS_ENCODING = Column(String(24), nullable=True)
PASS = Column(String(128), nullable=True)
PASS_CRYPTED = Column(String(128), nullable=True)
PASS_TEMP = Column(String(128), nullable=True)
API_KEY = Column(String(128), nullable=True)
GENDER = Column(String(10), nullable=True)
CIVILITY = Column(String(6), nullable=True)
LASTNAME = Column(String(50), nullable=True)
FIRSTNAME = Column(String(50), nullable=True)
ADDRESS = Column(String(255), nullable=True)
ZIP = Column(String(25), nullable=True)
TOWN = Column(String(50), nullable=True)
FK_STATE = Column(Integer, nullable=True, default=0)
FK_COUNTRY = Column(Integer, nullable=True, default=0)
BIRTH = Column(Date, nullable=True)
BIRTH_PLACE = Column(String(64), nullable=True)
JOB = Column(String(128), nullable=True)
OFFICE_PHONE = Column(String(20), nullable=True)
OFFICE_FAX = Column(String(20), nullable=True)
USER_MOBILE = Column(String(20), nullable=True)
PERSONAL_MOBILE = Column(String(20), nullable=True)
EMAIL = Column(String(255), nullable=True)
PERSONAL_EMAIL = Column(String(255), nullable=True)
SIGNATURE = Column(Text, nullable=True)
SOCIALNETWORKS = Column(Text, nullable=True)
FK_SOC = Column(Integer, nullable=True)
FK_SOCPEOPLE = Column(Integer, nullable=True)
FK_MEMBER = Column(Integer, nullable=True)
FK_USER = Column(Integer, nullable=True)
FK_USER_EXPENSE_VALIDATOR = Column(Integer, nullable=True)
FK_USER_HOLIDAY_VALIDATOR = Column(Integer, nullable=True)
NOTE_PUBLIC = Column(Text, nullable=True)
NOTE_PRIVATE = Column(Text, nullable=True)
MODEL_PDF = Column(String(255), nullable=True)
DATELASTLOGIN = Column(DateTime, nullable=True)
DATEPREVIOUSLOGIN = Column(DateTime, nullable=True)
DATELASTPASSVALIDATION = Column(DateTime, nullable=True)
DATESTARTVALIDITY = Column(DateTime, nullable=True)
DATEENDVALIDITY = Column(DateTime, nullable=True)
IPLASTLOGIN = Column(String(250), nullable=True)
IPPREVIOUSLOGIN = Column(String(250), nullable=True)
EGROUPWARE_ID = Column(Integer, nullable=True)
LDAP_SID = Column(String(255), nullable=True)
OPENID = Column(String(255), nullable=True)
STATUT = Column(Integer, nullable=True, default=1)
PHOTO = Column(String(255), nullable=True)
LANG = Column(String(6), nullable=True)
COLOR = Column(String(6), nullable=True)
BARCODE = Column(String(255), nullable=True)
FK_BARCODE_TYPE = Column(Integer, nullable=True, default=0)
ACCOUNTANCY_CODE = Column(String(32), nullable=True)
NB_HOLIDAY = Column(Integer, nullable=True, default=0)
THM = Column(Float, nullable=True)
TJM = Column(Float, nullable=True)
SALARY = Column(Float, nullable=True)
SALARYEXTRA = Column(Float, nullable=True)
DATEEMPLOYMENT = Column(Date, nullable=True)
DATEEMPLOYMENTEND = Column(Date, nullable=True)
WEEKLYHOURS = Column(Float, nullable=True)
IMPORT_KEY = Column(String(14), nullable=True)
DEFAULT_RANGE = Column(Integer, nullable=True)
DEFAULT_C_EXP_TAX_CAT = Column(Integer, nullable=True)
NATIONAL_REGISTRATION_NUMBER = Column(String(50), nullable=True)
FK_WAREHOUSE = Column(Integer, nullable=True)
CREATED_AT = Column(DateTime, default=datetime.utcnow)
UPDATED_AT = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

View File

@@ -0,0 +1,20 @@
annotated-doc==0.0.4
annotated-types==0.7.0
anyio==4.12.1
click==8.3.1
colorama==0.4.6
fastapi==0.135.1
greenlet==3.3.2
h11==0.16.0
idna==3.11
pydantic==2.12.5
pydantic-settings==2.13.1
pydantic_core==2.41.5
PyJWT==2.12.1
PyMySQL==1.1.2
python-dotenv==1.2.2
SQLAlchemy==2.0.48
starlette==0.52.1
typing-inspection==0.4.2
typing_extensions==4.15.0
uvicorn==0.42.0

View File

@@ -0,0 +1,24 @@
from Back_comercial_iko.database.Database import Database
from Back_comercial_iko.models.Societe_model import SocieteModel
from Back_comercial_iko.core.validators.Field_validator import FieldValidator
from Back_comercial_iko.core.SocieteNotFoundException import SocieteNotFoundException
class ComercialService:
def __init__(self):
self.conn = Database()
self.db = self.conn.setConnection()
def create_project_commercial(self, data: dict):
FieldValidator.required(data.get("ex_societe"), "ex_societe")
FieldValidator.required(data.get("nomUser"), "nomUser")
nombre_soc = data.get("ex_societe")
result_soc = (self.db.query(SocieteModel.ROWID, SocieteModel.NOM).filter(SocieteModel.NOM == nombre_soc).first())
if not result_soc:
raise SocieteNotFoundException()
return {
"fk_soc": result_soc.ROWID,
"nombre_soc": nombre_soc
}

0
README.md Normal file
View File

10
main.py Normal file
View File

@@ -0,0 +1,10 @@
from fastapi import FastAPI
from Back_comercial_iko.main import app as backComercial
app = FastAPI()
app.mount("/Back_comercial_iko", backComercial)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)