{ *******************************************************************************
Title: T2Ti ERP
Description: Controller relacionado à tabela [PESSOA]

The MIT License

Copyright: Copyright (C) 2014 T2Ti.COM

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

The author may be contacted at:
t2ti.com@gmail.com</p>

@author Albert Eije (t2ti.com@gmail.com)
@version 2.0
******************************************************************************* }
unit PessoaController;

interface

uses
  Classes, Dialogs, SysUtils, DBClient, DB,  Windows, Forms, Controller, Rtti, Atributos,
  VO, PessoaVO, PessoaDTO, Generics.Collections,

  SynCommons,          // framework core
  mORMot,              // RESTful server & ORM
  mORMotHttpClient     // HTTP client to a mORMot RESTful server
  ;

type
  TPessoaController = class(TController)
  private
    class var FDataSet: TClientDataSet;
  public
    class procedure Consulta(pFiltro: String; pPagina: String; pConsultaCompleta: Boolean = False);
    class function ConsultaLista(pFiltro: String): TObjectList<TPessoaVO>;
    class function ConsultaObjeto(pFiltro: String): TPessoaVO;

    class function ConsultaDTO(pId: TId): TPessoa;

    class procedure Insere(pObjeto: TPessoaVO); overload;
    class procedure Insere(pObjeto: TPessoa); overload;
    class function Altera(pObjeto: TPessoaVO): Boolean; overload;
    class function Altera(pObjeto: TPessoa): Boolean; overload;

    class function Exclui(pId: Integer): Boolean;
    class function ExcluiContato(pId: Integer): Boolean;
    class function ExcluiEndereco(pId: Integer): Boolean;
    class function ExcluiTelefone(pId: Integer): Boolean;

    class function GetDataSet: TClientDataSet; override;
    class procedure SetDataSet(pDataSet: TClientDataSet); override;
    class procedure TratarListaRetorno(pListaObjetos: TObjectList<TVO>);
  end;

implementation

uses T2TiORM,
     PessoaFisicaVO, PessoaJuridicaVO, PessoaContatoVO, PessoaEnderecoVO,
     PessoaTelefoneVO, PessoaAlteracaoVO,

     PessoaFisicaDTO, PessoaJuridicaDTO, PessoaContatoDTO, PessoaEnderecoDTO,
     PessoaTelefoneDTO;

class procedure TPessoaController.Consulta(pFiltro: String; pPagina: String; pConsultaCompleta: Boolean);
var
  Retorno: TObjectList<TPessoa>;
  RetornoPessoa: TPessoa;

  Client: TSQLRest;
  aModel: TSQLModel;
begin
  try
    //Retorno := TT2TiORM.Consultar<TPessoaVO>(pFiltro, pPagina, pConsultaCompleta);

    aModel := TSQLModel.Create([TPessoa],'root');
    Client := TSQLHttpClientWinHTTP.Create('localhost','888',aModel);

    // pega só a parte depois do LIKE
    pFiltro :=  Copy(pFiltro, pos('LIKE', pFiltro) + 5, Length(pFiltro));
    pFiltro := StringReplace(pFiltro, Chr(39), '', [rfReplaceAll]);

    Retorno := Client.RetrieveList<TPessoa>('Nome LIKE ?',[pFiltro]);

    for RetornoPessoa in Retorno do
      RetornoPessoa.PK := TID(RetornoPessoa.GetID);

    if Assigned(Retorno) then
      TratarRetorno<TPessoa>(Retorno);
  finally
  end;
end;

class function TPessoaController.ConsultaDTO(pId: TId): TPessoa;
var
  RetornoPessoa: TPessoa;
  Client: TSQLRest;
  aModel: TSQLModel;
begin
  try
    aModel := TSQLModel.Create([TPessoa, TPessoa_Telefone, TPessoa_Endereco, TPessoa_Contato, TPessoa_Fisica, TPessoa_Juridica],'root');
    Client := TSQLHttpClientWinHTTP.Create('localhost','888',aModel);

    RetornoPessoa := TPessoa.Create;
    Client.Retrieve(pId, RetornoPessoa);

    // Objetos
    RetornoPessoa.PessoaFisicaDTO := TPessoa_Fisica.Create;
    Client.Retrieve('Id_Pessoa = ' + IntToStr(pId), RetornoPessoa.PessoaFisicaDTO);

    RetornoPessoa.PessoaJuridicaDTO := TPessoa_Juridica.Create;
    Client.Retrieve('Id_Pessoa = ' + IntToStr(pId), RetornoPessoa.PessoaJuridicaDTO);

    // Listas
    RetornoPessoa.ListaPessoaContatoDTO := Client.RetrieveList<TPessoa_Contato>('Id_Pessoa = ?', [pId]);
    RetornoPessoa.ListaPessoaEnderecoDTO := Client.RetrieveList<TPessoa_Endereco>('Id_Pessoa = ?', [pId]);
    RetornoPessoa.ListaPessoaTelefoneDTO := Client.RetrieveList<TPessoa_Telefone>('Id_Pessoa = ?', [pId]);

    Result := RetornoPessoa;

    //Result := TT2TiORM.ConsultarUmObjeto<TBancoVO>(pFiltro, True);
  finally
  end;
end;

class function TPessoaController.ConsultaLista(pFiltro: String): TObjectList<TPessoaVO>;
begin
  try
    Result := TT2TiORM.Consultar<TPessoaVO>(pFiltro, '-1', True);
  finally
  end;
end;

class function TPessoaController.ConsultaObjeto(pFiltro: String): TPessoaVO;
begin
  try
    Result := TT2TiORM.ConsultarUmObjeto<TPessoaVO>(pFiltro, True);
  finally
  end;
end;

class procedure TPessoaController.Insere(pObjeto: TPessoa);
var
  aModel: TSQLModel;
  Client: TSQLRest;

  UltimoID: Integer;
  Contato: TPessoa_Contato;
  Endereco: TPessoa_Endereco;
  ContatosEnumerator: TEnumerator<TPessoa_Contato>;
  EnderecosEnumerator: TEnumerator<TPessoa_Endereco>;
  TipoPessoa: String;
begin
  try
    aModel := TSQLModel.Create([TPessoa, TPessoa_Telefone, TPessoa_Endereco, TPessoa_Contato, TPessoa_Fisica, TPessoa_Juridica], 'root');;
    Client := TSQLHttpClientWinHTTP.Create('localhost','888',aModel);

    TipoPessoa := pObjeto.Tipo;

    UltimoID := TID(Client.Add(pObjeto, True));

    // Tipo de Pessoa
    if TipoPessoa = 'F' then
    begin
      pObjeto.PessoaFisicaDTO.Id_Pessoa := UltimoID;
      Client.Add(pObjeto.PessoaFisicaDTO, True);
    end
    else if TipoPessoa = 'J' then
    begin
      pObjeto.PessoaJuridicaDTO.Id_Pessoa := UltimoID;
      Client.Add(pObjeto.PessoaJuridicaDTO, True);
    end;

    // Cliente
    pObjeto.ClienteDTO.Id_Pessoa := UltimoID;
    Client.Add(pObjeto.PessoaFisicaDTO, True);

    // Contatos
    ContatosEnumerator := pObjeto.ListaPessoaContatoDTO.GetEnumerator;
    try
      with ContatosEnumerator do
      begin
        while MoveNext do
        begin
          Contato := Current;
          Contato.Id_Pessoa := UltimoID;
          Client.Add(Contato, True);
        end;
      end;
    finally
      FreeAndNil(ContatosEnumerator);
    end;

    // Endereços
    EnderecosEnumerator := pObjeto.ListaPessoaEnderecoDTO.GetEnumerator;
    try
      with EnderecosEnumerator do
      begin
        while MoveNext do
        begin
          Endereco := Current;
          Endereco.Id_Pessoa := UltimoID;
          Client.Add(Endereco, True);
        end;
      end;
    finally
      FreeAndNil(EnderecosEnumerator);
    end;

  finally
  end;
end;

class function TPessoaController.Altera(pObjeto: TPessoa): Boolean;
var
  aModel: TSQLModel;
  Client: TSQLRest;

  ContatosEnumerator: TEnumerator<TPessoa_Contato>;
  EnderecosEnumerator: TEnumerator<TPessoa_Endereco>;
  TipoPessoa: String;
begin
  try
    aModel := TSQLModel.Create([TPessoa, TPessoa_Telefone, TPessoa_Endereco, TPessoa_Contato, TPessoa_Fisica, TPessoa_Juridica], 'root');;
    Client := TSQLHttpClientWinHTTP.Create('localhost','888',aModel);

    Client.Update(pObjeto);

    TipoPessoa := pObjeto.Tipo;

    // Tipo de Pessoa
    try
      if TipoPessoa = 'F' then
      begin
        Client.Update(pObjeto.PessoaFisicaDTO);
      end
      else if TipoPessoa = 'J' then
      begin
        Client.Update(pObjeto.PessoaJuridicaDTO);
      end;
    finally
    end;

    // Cliente
    Client.Update(pObjeto.ClienteDTO);

    // Contatos
    try
      ContatosEnumerator := pObjeto.ListaPessoaContatoDTO.GetEnumerator;
      with ContatosEnumerator do
      begin
        while MoveNext do
        begin
          Client.Update(Current);
        end;
      end;
    finally
      FreeAndNil(ContatosEnumerator);
    end;

    // Endereços
    try
      EnderecosEnumerator := pObjeto.ListaPessoaEnderecoDTO.GetEnumerator;
      with EnderecosEnumerator do
      begin
        while MoveNext do
        begin
          Client.Update(Current);
        end;
      end;
    finally
      FreeAndNil(EnderecosEnumerator);
    end;

  finally
  end;
end;

class procedure TPessoaController.Insere(pObjeto: TPessoaVO);
var
  UltimoID: Integer;
  Contato: TPessoaContatoVO;
  Endereco: TPessoaEnderecoVO;
  Telefone: TPessoaTelefoneVO;
  ContatosEnumerator: TEnumerator<TPessoaContatoVO>;
  EnderecosEnumerator: TEnumerator<TPessoaEnderecoVO>;
  TelefonesEnumerator: TEnumerator<TPessoaTelefoneVO>;
  TipoPessoa: String;
begin
  try
    TipoPessoa := pObjeto.Tipo;
    UltimoID := TT2TiORM.Inserir(pObjeto);

    // Tipo de Pessoa
    if TipoPessoa = 'F' then
    begin
      pObjeto.PessoaFisicaVO.IdPessoa := UltimoID;
      TT2TiORM.Inserir(pObjeto.PessoaFisicaVO);
    end
    else if TipoPessoa = 'J' then
    begin
      pObjeto.PessoaJuridicaVO.IdPessoa := UltimoID;
      TT2TiORM.Inserir(pObjeto.PessoaJuridicaVO);
    end;

    // Contatos
    ContatosEnumerator := pObjeto.ListaPessoaContatoVO.GetEnumerator;
    try
      with ContatosEnumerator do
      begin
        while MoveNext do
        begin
          Contato := Current;
          Contato.IdPessoa := UltimoID;
          TT2TiORM.Inserir(Contato);
        end;
      end;
    finally
      FreeAndNil(ContatosEnumerator);
    end;

    // Endereços
    EnderecosEnumerator := pObjeto.ListaPessoaEnderecoVO.GetEnumerator;
    try
      with EnderecosEnumerator do
      begin
        while MoveNext do
        begin
          Endereco := Current;
          Endereco.IdPessoa := UltimoID;
          TT2TiORM.Inserir(Endereco);
        end;
      end;
    finally
      FreeAndNil(EnderecosEnumerator);
    end;

    // Telefones
    TelefonesEnumerator := pObjeto.ListaPessoaTelefoneVO.GetEnumerator;
    try
      with TelefonesEnumerator do
      begin
        while MoveNext do
        begin
          Telefone := Current;
          Telefone.IdPessoa := UltimoID;
          TT2TiORM.Inserir(Telefone);
        end;
      end;
    finally
      FreeAndNil(TelefonesEnumerator);
    end;

    Consulta('ID = ' + IntToStr(UltimoID), '0');
  finally
  end;
end;

class function TPessoaController.Altera(pObjeto: TPessoaVO): Boolean;
var
  ContatosEnumerator: TEnumerator<TPessoaContatoVO>;
  EnderecosEnumerator: TEnumerator<TPessoaEnderecoVO>;
  TelefonesEnumerator: TEnumerator<TPessoaTelefoneVO>;
  PessoaAlteracao: TPessoaAlteracaoVO;
  PessoaOld: TPessoaVO;
  TipoPessoa: String;
begin
  try
    PessoaOld := ConsultaObjeto('ID='+pObjeto.Id.ToString);
    Result := TT2TiORM.Alterar(pObjeto);

    TipoPessoa := pObjeto.Tipo;

    // Tipo de Pessoa
    try
      if TipoPessoa = 'F' then
      begin
        if pObjeto.PessoaFisicaVO.Id > 0 then
          Result := TT2TiORM.Alterar(pObjeto.PessoaFisicaVO)
        else
          Result := TT2TiORM.Inserir(pObjeto.PessoaFisicaVO) > 0;
      end
      else if TipoPessoa = 'J' then
      begin
        if pObjeto.PessoaJuridicaVO.Id > 0 then
          Result := TT2TiORM.Alterar(pObjeto.PessoaJuridicaVO)
        else
          Result := TT2TiORM.Inserir(pObjeto.PessoaJuridicaVO) > 0;
      end;
    finally
    end;

    // Contatos
    try
      ContatosEnumerator := pObjeto.ListaPessoaContatoVO.GetEnumerator;
      with ContatosEnumerator do
      begin
        while MoveNext do
        begin
          if Current.Id > 0 then
            Result := TT2TiORM.Alterar(Current)
          else
          begin
            Current.IdPessoa := pObjeto.Id;
            Result := TT2TiORM.Inserir(Current) > 0;
          end;
        end;
      end;
    finally
      FreeAndNil(ContatosEnumerator);
    end;

    // Endereços
    try
      EnderecosEnumerator := pObjeto.ListaPessoaEnderecoVO.GetEnumerator;
      with EnderecosEnumerator do
      begin
        while MoveNext do
        begin
          if Current.Id > 0 then
            Result := TT2TiORM.Alterar(Current)
          else
          begin
            Current.IdPessoa := pObjeto.Id;
            Result := TT2TiORM.Inserir(Current) > 0;
          end;
        end;
      end;
    finally
      FreeAndNil(EnderecosEnumerator);
    end;

    // Telefones
    try
      TelefonesEnumerator := pObjeto.ListaPessoaTelefoneVO.GetEnumerator;
      with TelefonesEnumerator do
      begin
        while MoveNext do
        begin
          if Current.Id > 0 then
            Result := TT2TiORM.Alterar(Current)
          else
          begin
            Current.IdPessoa := pObjeto.Id;
            Result := TT2TiORM.Inserir(Current) > 0;
          end;
        end;
      end;
    finally
      FreeAndNil(TelefonesEnumerator);
    end;

    // Alteração - Para Registro 0175 do Sped Fiscal.
    PessoaAlteracao := TPessoaAlteracaoVO.Create;
    PessoaAlteracao.IdPessoa := pObjeto.Id;
    PessoaAlteracao.DataAlteracao := Date;
    PessoaAlteracao.ObjetoAntigo := PessoaOld.ToJsonString;
    PessoaAlteracao.ObjetoNovo := pObjeto.ToJsonString;
    TT2TiORM.Inserir(PessoaAlteracao)

  finally
    FreeAndNil(PessoaAlteracao);
    FreeAndNil(PessoaOld);
  end;
end;


class function TPessoaController.Exclui(pId: Integer): Boolean;
begin
  try
    raise Exception.Create('Não é permitido excluir uma Pessoa.');
  finally
  end;
end;

class function TPessoaController.ExcluiContato(pId: Integer): Boolean;
var
  ObjetoLocal: TPessoaContatoVO;
begin
  try
    ObjetoLocal := TPessoaContatoVO.Create;
    ObjetoLocal.Id := pId;
    Result := TT2TiORM.Excluir(ObjetoLocal);
    TratarRetorno(Result);
  finally
    FreeAndNil(ObjetoLocal)
  end;
end;

class function TPessoaController.ExcluiEndereco(pId: Integer): Boolean;
var
  ObjetoLocal: TPessoaEnderecoVO;
begin
  try
    ObjetoLocal := TPessoaEnderecoVO.Create;
    ObjetoLocal.Id := pId;
    Result := TT2TiORM.Excluir(ObjetoLocal);
    TratarRetorno(Result);
  finally
    FreeAndNil(ObjetoLocal)
  end;
end;

class function TPessoaController.ExcluiTelefone(pId: Integer): Boolean;
var
  ObjetoLocal: TPessoaTelefoneVO;
begin
  try
    ObjetoLocal := TPessoaTelefoneVO.Create;
    ObjetoLocal.Id := pId;
    Result := TT2TiORM.Excluir(ObjetoLocal);
    TratarRetorno(Result);
  finally
    FreeAndNil(ObjetoLocal)
  end;
end;

class function TPessoaController.GetDataSet: TClientDataSet;
begin
  Result := FDataSet;
end;

class procedure TPessoaController.SetDataSet(pDataSet: TClientDataSet);
begin
  FDataSet := pDataSet;
end;

class procedure TPessoaController.TratarListaRetorno(pListaObjetos: TObjectList<TVO>);
begin
  try
    TratarRetorno<TPessoaVO>(TObjectList<TPessoaVO>(pListaObjetos));
  finally
    FreeAndNil(pListaObjetos);
  end;
end;

initialization
  Classes.RegisterClass(TPessoaController);

finalization
  Classes.UnRegisterClass(TPessoaController);

end.
