Nueva publicación

Rechercher

Pregunta
· 1 mayo, 2025

Embedded Python query

Hi Guys,

How can I use this same objectscript principle in embedded python to get the value of each field in my loop? 

  s sql="SELECT ID, Name, Age FROM Sample.Person WHERE Age="_Myage    

     Set RS=##class(%ResultSet).%New()

    Set Ret=RS.Prepare(sql)

    Set Ret=RS.Execute()

    While RS.Next()

    {

         Set name=RS.GetData(2)

}

it should be similar to this example which lists the whole row but how can I get the value of each field or if I can use GetData?  

 

Thanks

2 nuevos comentarios
Comentarios (2)1
Inicie sesión o regístrese para continuar
Resumen
· 1 mayo, 2025

InterSystems 开发者社区摘要,四月 2025

您好,欢迎阅读 四月 2025 开发人员社区通讯。
统计信息
✓ 四月发布了 2 篇新帖子:
 2篇新文章
✓ 四月有 17 位新成员加入
✓ 所有时间发布了 2,375 篇帖子
✓ 所有时间有 2,183 位成员加入
最高职位
四月, 2025Month at a GlanceInterSystems Developer Community
Pregunta
· 1 mayo, 2025

White Label Web Development: A Complete Guide for Agencies

In the fast-paced digital world, agencies often face challenges in meeting client demands while managing time, costs, and expertise. This is where White Label Web Development becomes a game changer. By outsourcing development tasks under your brand, you can deliver high-quality websites without hiring an in-house team.

What is White Label Web Development?

White Label Web Development refers to the process where a specialized third-party agency or freelancer builds websites or web apps on behalf of another company. The final product is delivered under the client-facing company’s brand name. The end client never knows a third party was involved.

Example:

A digital marketing agency may sell a website development package to its client. Instead of building it in-house, they hire a white label development partner. The partner completes the work, and the agency delivers it under its own branding.

Benefits of White Label Web Development

There are several advantages to using white label services:

1. Scalability

Agencies can take on more projects without worrying about the capacity of their internal teams.

2. Cost-Efficiency

Hiring full-time developers or maintaining a tech department can be expensive. White label partnerships offer a flexible and cost-effective alternative.

3. Focus on Core Services

Agencies can focus on what they do best—like marketing, design, or strategy—while leaving the technical work to experts.

4. Faster Turnaround

With an experienced development partner, websites can be completed quickly without sacrificing quality.

Who Should Use White Label Web Development?

White label development is ideal for:

  • Digital marketing agencies that don’t have in-house developers.
  • Freelancers who want to expand their service offerings.
  • Startups looking to offer web development without investing heavily in hiring.
  • Design studios that need functional websites built from their creative mockups.

Common Services Offered in White Label Web Development

White label partners usually offer a range of services, including:

  • Custom website development (HTML, CSS, JS)
  • WordPress development
  • E-commerce development (Shopify, WooCommerce)
  • Web app development
  • Website maintenance and updates
  • Speed optimization
  • Technical SEO implementation

How to Choose the Right White Label Partner

Not all providers are the same. Here’s what to look for:

  • Portfolio and experience
  • Communication process
  • Turnaround time
  • NDA and white label agreement
  • Post-launch support
  • Pricing model (fixed, hourly, or project-based)

Challenges to Consider

While white label web development offers many benefits, there are challenges to watch out for:

  • Communication gaps – Clear guidelines and regular updates are essential.
  • Quality control – Always review work before delivery.
  • Brand consistency – Ensure the final product aligns with your brand and client expectations.

Final Thoughts

White Label Web Development is a powerful way for agencies to grow, scale, and stay competitive without stretching resources. By partnering with a trusted provider, you can expand your offerings, increase profits, and build stronger relationships with your clients—all under your brand.

Comentarios (0)1
Inicie sesión o regístrese para continuar
Resumen
· 1 mayo, 2025

InterSystems開発者コミュニティのダイジェスト、4月 2025

4月 2025開発者コミュニティ ニュースレターへようこそ。
全体統計
17 件の新しい投稿が公開 (4月 月):
 12件の新着記事
 5の新しい発表
6 人の新メンバーが参加 (4月 月)
1,490 件の投稿が公開 (全期間)
319 人のメンバーが参加 (全期間)
トップ記事
二要素認証について
Tomoko Furuzono順
今月のトップ作家
記事
#InterSystems IRIS
IRISから外部のWebAPIを呼び出したとき、レスポンス内の全角文字が化ける
Hiroshi Sato順
IRIS for MacにODBCアクセスする方法 その1
Hiroshi Sato順
IRIS for MACにODBCでアクセスする方法その2
Hiroshi Sato順
二要素認証について
Tomoko Furuzono順
ロードバランサやプロキシサーバ経由でアクセスしている接続元クライアントIPを取得する方法
Tomoko Furuzono順
インストールマニフェストを利用したアプリケーションのデプロイ
Tomoko Furuzono順
全角/半角混在文字列から指定された幅の文字列を取得する方法
Tomoko Furuzono順
サーバのIPアドレスやマシン名をオブジェクトスクリプトで取得する
Tomoko Furuzono順
Webゲートウェイの設定値をプログラムで変更する
Tomoko Furuzono順
Iris における Django アプリケーションの実行
Toshihiko Minamoto順
メソッドの実装に使用する言語を明示するーLanguage(メソッド・キーワード)の指定について
Tomoko Furuzono順
ADO.NET Managed Provider を使用してクラスクエリを実行し、結果セットを取得するサンプル
Megumi Kakechi順
お知らせ
4月, 2025Month at a GlanceInterSystems Developer Community
Artículo
· 30 abr, 2025 Lectura de 17 min

OpenAPI Suite - Parte 1

Olá Comunidade,

Gostaria de apresentar meu último pacote OpenAPI-Suite. Este é um conjunto de ferramentas para gerar código ObjectScript a partir de uma especificação OpenAPI versão 3.0..  IEm resumo, estes pacotes permitem:

  • Gerar classes de servidor. É bem parecido com o código gerado por ^%REST mas o valor adicionado é o suporte à versão 3.0.
  • Gerar classes de cliente HTTP.
  • Gerar classes de produção de cliente (business services, business operation, business process, Ens.Request, Ens.Response).
  • Uma interface web para gerar e baixar o código ou gerar e compilar diretamente no servidor.
  • Converter especificações das versões 1.x, 2.x para a versão 3.0.

Visão Geral

O OpenAPI Suite é dividido em vários pacotes e utiliza diferentes bibliotecas da comunidade de desenvolvedores e também serviços REST públicos. Você pode ver no esquema abaixo todos os pacotes que foram desenvolvidos, e as bibliotecas e serviços web utilizados:

Observação: Em caso de problemas ao usar serviços REST públicos, é possível iniciar uma instância Docker do serviço de conversão e validação.

O que cada pacote faz?

O OpenAPI Suite foi projetado em diferentes pacotes para facilitar a manutenção, melhoria e extensão futura. Cada pacote tem um papel. Vamos dar uma olhada!

openapi-common-lib

Isto contém todo o código comum aos outros pacotes. Por exemplo openapi-client-gen e openapi-server-gen aceitam a seguinte entrada para uma especificação OpenAPI:

  • URL
  • Caminho de arquivo
  • %Stream.Object 
  • %DynamicObject
  • Formato YAML
  • Formato JSON
  • OpenAPI versão1.x, 2.x, 3.0.x.

No entanto, apenas uma especificação 3.0.x em um %DynamicObject pode ser processada. O código para a transformação está localizado neste pacote. Ele também contém várias utilidades.

swagger-converter-cli

É uma dependência do openapi-common-lib. Este é um cliente HTTP que utiliza o serviço REST públicoconverter.swagger.iopara converter OpenAPI versão 1.x ou 2.x para a versão 3.0.

swagger-validator-cli

É também uma dependência do openapi-common-lib, mesmo que seu nome seja "validator", ele não é usado para validar a especificação. O  converter.swagger.iofornece o serviço "parse" que permite simplificar a estrutura de uma especificação OpenAPI. Por exemplo: criar uma definição para uma "nested object definition" e substituí-la por um "$ref". Isso reduz o número de casos a serem tratados no algoritmo de geração de código.

openapi-client-gen

Este pacote é dedicado à geração de código do lado do cliente para ajudar os desenvolvedores a consumir serviços REST.

Ele inclui um cliente HTTP simples ou um cliente de Produção(business services, process, operation, Production classes). Originalmente criado para suportar OpenAPI 2.x, foi completamente refatorado para suportar a versão 3.x.

openapi-server-gen

O oposto do openapi-client-gen, é dedicado à geração de código do lado do servidor. Não há interesse na versão 2.0 da especificação porque o ^%RESTexiste, mas o objetivo deste pacote é o suporte à versão 3.0.  

openapi-suite

Ele reúne todos os pacotes acima e fornece uma API REST para:

  • Gerar o código e compilar o código na instância IRIS.
  • Gerar código sem compilar para download apenas.

Uma interface web também é fornecida para consumir esta API REST e, assim, explorar as funcionalidades do OpenAPI Suite.

E as bibliotecas?

Aqui estão algumas das bibliotecas existentes no DC que foram úteis neste desenvolvimento:

objectscript-openapi-definition

Uma biblioteca útil para gerar classes de modelo a partir de uma especificação OpenAPI. Esta é uma parte muito importante deste projeto e eu também sou um contribuidor.

ssl-client

Permite criar configurações SSL. Usado principalmente para criar um nome de configuração "DefaultSSL" para requisições HTTPS.

yaml-utils

No caso de especificação em formato YAML, esta biblioteca é usada para converter para o formato JSON. Essencial neste projeto. A propósito, foi desenvolvida inicialmente para testar a especificação YAML com a versão 1 do openapi-client-gen.

io-redirect

Esta é uma das minhas bibliotecas. Ela permite redirecionar a saída de "write" para um stream, arquivo, global ou variável string. É usada pelo serviço REST para manter um rastreamento dos logs. É inspirada nesta postagem da comunidade.

Instalação IPM

Para instalar a suíte, seu melhor amigo é oIPM (zpm)Existem muitos pacotes e dependências, e usar o IPM é definitivamente conveniente.

zpm "install openapi-suite"
; opcional
; zpm "install swagger-ui"

 

Instalação Docker

Não há nada de especial, este projeto utiliza o intersystems-iris-dev-template.

git clone git@github.com:lscalese/openapi-suite.git
cd openapi-suite
docker-compose up -d

Se você tiver um erro ao iniciar o Iris, talvez seja um problema de permissão no arquivo iris-main.log.

Você pode tentar:

touch iris-main.log && chmod 777 iris-main.log

Observação: Adicionar permissão de leitura e escrita (RW) para o usuário irisowner deve ser suficiente.

Como Usar

O OpenAPI-Suite fornece uma interface web para "Gerar e baixar" ou "Gerar e instalar" código.

A interface está disponível em http://localhost:52796/openapisuite/ui/index.csp (*adapte com o seu número de porta, se necessário).

É muito simples, preencha o formulário:

  1. Nome do pacote da aplicação: este é o pacote usado para as classes geradas. Deve ser um nome de pacote inexistente.
  2. Selecione o que você deseja gerar: Cliente HTTP, Produção Cliente ou Servidor REST.
  3. Selecione o namespace onde o código será gerado. Isso faz sentido apenas se você clicar em "Install On Server"; caso contrário, este campo será ignorado.
  4. Nome da Aplicação Web é opcional e está disponível apenas se você selecionar "Servidor REST" para gerar. Deixe vazio se você não quiser criar uma Aplicação Web relacionada à classe de despacho REST gerada.
  5. O campo Especificação OpenAPI pode ser uma URL apontando para a especificação ou uma cópia/cola da própria especificação (neste caso, a especificação deve estar em formato JSON).

Se você clicar no botão "Download Only", o código será gerado e retornado em um arquivo XML, e então as classes serão excluídas do servidor. O namespace usado para armazenar temporariamente as classes geradas é o namespace onde o OpenAPI-Suite está instalado (por padrão IRISAPP se você usar uma instalação Docker).

No entanto, se você clicar no botão "Install On Server", o código será gerado e compilado, e o servidor retornará uma mensagem JSON com o status da geração/compilação do código e também os logs.

Por padrão, este recurso está desabilitado. Para habilitá-lo, basta abrir um terminal IRIS e:

Set ^openapisuite.config("web","enable-install-onserver") = 1

Explore a API REST do OpenAPI-Suite

O formulário CSP utiliza serviços REST disponíveis emhttp://localhost:52796/openapisuite.

Abra o swagger-ui http://localhost:52796/swagger-ui/index.html  e explore http://localhost:52796/openapisuite/_spec 

Este é o primeiro passo para criar uma aplicação front-end mais avançada com o framework Angular.

Gere código programaticamente

Claro, não é obrigatório usar a interface do usuário. Nesta seção, veremos como gerar o código programaticamente e como usar os serviços gerados.

Todos os trechos de código também estão disponíveis na classe dc.openapi.suite.samples.PetStore.

 

cliente HTTP

Set features("simpleHttpClientOnly") = 1
Set sc = ##class(dc.openapi.client.Spec).generateApp("petstoreclient", "https://petstore3.swagger.io/api/v3/openapi.json", .features)

 

O primeiro argumento é o pacote onde as classes serão geradas, portanto, certifique-se de passar um nome de pacote válido. O segundo argumento pode ser uma URL apontando para a especificação, um nome de arquivo, um stream ou um %DynamicObject. "features" é um array, atualmente apenas os seguintes subscritos estão disponíveis:

simpleHttpClientOnly: se for 1, apenas um cliente HTTP simples será gerado; caso contrário, uma produção também será gerada (comportamento padrão).

compile: se for 0, o código gerado não será compilado. Isso pode ser útil se você quiser gerar código apenas para fins de exportação. Por padrão, compile = 1.

Abaixo está um exemplo de como usar o serviço "addPet" com o cliente HTTP recém-gerado:

Set messageRequest = ##class(petstoreclient.requests.addPet).%New()
Set messageRequest.%ContentType = "application/json"
Do messageRequest.PetNewObject().%JSONImport({"id":456,"name":"Mittens","photoUrls":["https://static.wikia.nocookie.net/disney/images/c/cb/Profile_-_Mittens.jpg/revision/latest?cb=20200709180903"],"status":"available"})
  
Set httpClient = ##class(petstoreclient.HttpClient).%New("https://petstore3.swagger.io/api/v3","DefaultSSL")
; MessageResponse será uma instância de petstoreclient.responses.addPet
Set sc = httpClient.addPet(messageRequest, .messageResponse)
If $$$ISERR(sc) Do $SYSTEM.Status.DisplayError(sc) Quit sc
  
Write !,"Http Status code : ", messageResponse.httpStatusCode,!
Do messageResponse.Pet.%JSONExport()

 

 
Click to show generated classes.

 

Produção de cliente HTTP

Set sc = ##class(dc.openapi.client.Spec).generateApp("petstoreproduction", "https://petstore3.swagger.io/api/v3/openapi.json")

O primeiro argumento é o nome do pacote. Se você testar a geração de código de um cliente HTTP simples e de uma produção de cliente, certifique-se de usar um nome de pacote diferente. O segundo e o terceiro seguem as mesmas regras do cliente HTTP.

Antes de testar, inicie a produção através do portal de gerenciamento usando este comando:

Do ##class(Ens.Director).StartProduction("petstoreproduction.Production")

Abaixo está um exemplo de como usar o serviço "addPet", mas desta vez com a produção gerada:

Set messageRequest = ##class(petstoreproduction.requests.addPet).%New()
Set messageRequest.%ContentType = "application/json"
Do messageRequest.PetNewObject().%JSONImport({"id":123,"name":"Kitty Galore","photoUrls":["https://www.tippett.com/wp-content/uploads/2017/01/ca2DC049.130.1264.jpg"],"status":"pending"})
; MessageResponse será uma instâncoa de petstoreclient.responses.addPet
Set sc = ##class(petstoreproduction.Utils).invokeHostSync("petstoreproduction.bp.SyncProcess", messageRequest, "petstoreproduction.bs.ProxyService", , .messageResponse)
Write !, "Take a look in visual trace (management portal)"
If $$$ISERR(sc) Do $SYSTEM.Status.DisplayError(sc)
Write !,"Http Status code : ", messageResponse.httpStatusCode,!
Do messageResponse.Pet.%JSONExport()

Agora, você pode abrir o rastreamento visual para ver os detalhes:

As classes geradas nos pacotes model, requests e responses são bem semelhantes ao código gerado para um cliente HTTP simples. As classes do pacote requests herdam de Ens.Request, e as classes do pacote responses herdam de Ens.Response. A implementação padrão da operação de negócio é muito simples, veja este trecho de código:

Class petstoreproduction.bo.Operation Extends Ens.BusinessOperation [ ProcedureBlock ]
{

Parameter ADAPTER = "EnsLib.HTTP.OutboundAdapter";
Property Adapter As EnsLib.HTTP.OutboundAdapter;
/// Implementar operationId : addPet
/// post /pet
Method addPet(requestMessage As petstoreproduction.requests.addPet, Output responseMessage As petstoreproduction.responses.addPet) As %Status
{
    Set sc = $$$OK, pHttpRequestIn = ##class(%Net.HttpRequest).%New(), responseMessage = ##class(petstoreproduction.responses.addPet).%New()
    $$$QuitOnError(requestMessage.LoadHttpRequestObject(pHttpRequestIn))
    $$$QuitOnError(..Adapter.SendFormDataArray(.pHttpResponse, "post", pHttpRequestIn, , , ..Adapter.URL_requestMessage.%URL))
    $$$QuitOnError(responseMessage.LoadFromResponse(pHttpResponse, "addPet"))
    Quit sc
}
...
}
}

 

Serviço REST HTTP do lado do servidor

Set sc = ##class(dc.openapi.server.ServerAppGenerator).Generate("petstoreserver", "https://petstore3.swagger.io/api/v3/openapi.json", "/petstore/api")

O primeiro argumento é o nome do pacote para gerar as classes. O segundo segue as mesmas regras do cliente HTTP. O terceiro argumento não é obrigatório, mas se presente, uma aplicação web será criada com o nome fornecido (tenha cuidado ao fornecer um nome de aplicação web válido).

A classe petstoreserver.disp (dispatch, despacho, %CSP.REST class) parece um código gerado por ^%REST, realizando muitas verificações para aceitar ou rejeitar a requisição e chamando a implementação do ClassMethod de serviço correspondente em petstoreserver.impl. A principal diferença é o argumento passado para o método de implementação, que é um objeto petstoreserver.requests. Exemplo:

Class petstoreserver.disp Extends %CSP.REST [ ProcedureBlock ]
{

Parameter CHARSET = "utf-8";
Parameter CONVERTINPUTSTREAM = 1;
Parameter IgnoreWrites = 1;
Parameter SpecificationClass = "petstoreserver.Spec";
/// Processar request post /pet
ClassMethod addPet() As %Status
{
    Set sc = $$$OK
    Try{
        Set acceptedMedia = $ListFromString("application/json,application/xml,application/x-www-form-urlencoded")
        If '$ListFind(acceptedMedia,$$$LOWER(%request.ContentType)) {
             Do ##class(%REST.Impl).%ReportRESTError(..#HTTP415UNSUPPORTEDMEDIATYPE,$$$ERROR($$$RESTContentType,%request.ContentType)) Quit
        }
        Do ##class(%REST.Impl).%SetContentType($Get(%request.CgiEnvs("HTTP_ACCEPT")))
        If '##class(%REST.Impl).%CheckAccepts("application/xml,application/json") Do ##class(%REST.Impl).%ReportRESTError(..#HTTP406NOTACCEPTABLE,$$$ERROR($$$RESTBadAccepts)) Quit
        If '$isobject(%request.Content) Do ##class(%REST.Impl).%ReportRESTError(..#HTTP400BADREQUEST,$$$ERROR($$$RESTRequired,"body")) Quit
        Set requestMessage = ##class(petstoreserver.requests.addPet).%New()
        Do requestMessage.LoadFromRequest(%request)
        Set scValidateRequest = requestMessage.RequestValidate()
        If $$$ISERR(scValidateRequest) Do ##class(%REST.Impl).%ReportRESTError(..#HTTP400BADREQUEST,$$$ERROR(5001,"Invalid requestMessage object.")) Quit
        Set response = ##class(petstoreserver.impl).addPet(requestMessage)
        Do ##class(petstoreserver.impl).%WriteResponse(response)
    } Catch(ex) {
        Do ##class(%REST.Impl).%ReportRESTError(..#HTTP500INTERNALSERVERERROR,ex.AsStatus(),$parameter("petstoreserver.impl","ExposeServerExceptions"))
    }
    Quit sc
}
...
}

Como você pode ver, a classe de despacho chama “LoadFromRequest” e “RequestValidate” antes de invocar o método de implementação. Esses métodos possuem uma implementação padrão, mas o gerador de código não consegue cobrir todos os casos. Atualmente, os casos mais comuns são tratados automaticamente como parâmetros em "query" (consulta), "headers" (cabeçalhos), "path" (caminho) e no corpo (body) com os tipos de conteúdo “application/json”, “application/octet-stream” ou “multipart/form-data”. O desenvolvedor precisa verificar a implementação para checar/completar se necessário (por padrão, o gerador de código define $$$ThrowStatus($$$ERROR($$$NotImplemented)) para casos não suportados).

 

 
Exemplo de classe de requisição:

Assim como no uso de ^%REST, a classe "petstoreserver.impl" contém todos os métodos relacionados aos serviços que o desenvolvedor precisa implementar.

Class petstoreserver.impl Extends %REST.Impl [ ProcedureBlock ]
{

Parameter ExposeServerExceptions = 1;
/// Implementação do serviço para post /pet
ClassMethod addPet(messageRequest As petstoreserver.requests.addPet) As %Status
{
    ; Implemente seu serviço aqui
    ; Retorne {}
    $$$ThrowStatus($$$ERROR($$$NotImplemented))
}

...
}

 

Breve descrição dos pacotes gerados:

Nome do Pacote \ Nome da Classe

Tipo

Descrição

petstoreclient.model


petstoreproduction.model

Client-side e server-side

Ele contém todos os modelos. Essas classes estendem %JSON.Adaptor para facilitar o carregamento de objetos a partir de JSON.

Se uma produção for gerada, essas classes também estenderão %Persistent.

petstoreclient.requests

 


petstoreproduction.requests

Client-side e server-side

Objeto usado para inicializar facilmente %Net.HttpRequest. Existe uma classe por operação definida na especificação.

Se a produção for gerada, essas classes estenderão Ens.Request.

Nota: A implementação desta classe é diferente se for gerada para propósitos do lado do servidor ou do lado do cliente. No caso do lado do cliente, todas as classes contêm um método "LoadHttpRequestObject" permitindo carregar um "%Net.HttpRequest" a partir das propriedades desta classe.

Se as classes forem geradas para propósitos do lado do servidor, cada classe contém um método "LoadFromRequest" para carregar a instância a partir do objeto "%request".

petstoreclient.responses


petstoreproduction.responses

Client-side e server-side

É o oposto de petstoreclient.requests. Ele permite manipular a resposta de um %Net.HttpRequest.

Se a produção for gerada, essas classes estenderão Ens.Response.

petstoreclient.HttpClient

Client-side

Contém todos os métodos para executar requisições HTTP; existe um método por operação definida na especificação OpenAPI.

petstoreproduction. bo.Operation

Client-side

A classe de Operação possui um método por operação definida na especificação OpenAPI.

petstoreproduction.bp

Client-side

Dois processos de negócio padrão são definidos: síncrono e assíncrono.

petstoreproduction.bs

Client-side

Contém todos os serviços de negócio vazios para implementar.

petstoreproduction.Production

Client-side

Configuração de produção.

petstoreserver.disp

Server-side

Classe de despacho %CSP.REST.

petstoreserver.Spec

Server-side

Esta classe contém a especificação OpenAPI em um bloco XData.

petstoreserver.impl

Server-side

Ele contém todos os métodos vazios relacionados às operações definidas na especificação OpenAPI. Esta é a classe (que estende %REST.Impl) onde os desenvolvedores precisam implementar os serviços.

Status de desenvolvimento

O OpenAPI-Suite ainda é um produto muito novo e precisa ser mais testado e então aprimorado. O suporte ao OpenAPI 3 é parcial, mais possibilidades poderiam ser suportadas.

Os testes foram realizados com a especificação públicahttps://petstore3.swagger.io/api/v3/openapi.json e outras duas relativamente simples. Obviamente, isso não é suficiente para cobrir todos os casos. Se você tiver alguma especificação para compartilhar, ficaria feliz em usá-las para meus testes.

Acredito que a base do projeto é boa e ele pode evoluir facilmente, por exemplo, ser estendido para suportar AsyncAPI.

Não hesite em deixar feedback.

Espero que você goste desta aplicação e que ela mereça seu apoio para o concurso de ferramentas para desenvolvedores.

Obrigado por ler.

Comentarios (0)1
Inicie sesión o regístrese para continuar