unit UMenu;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls,
  FMX.Gestures, System.Actions, FMX.ActnList, FMX.TabControl,
  FMX.ListView.Types, Data.Bind.EngExt, Fmx.Bind.DBEngExt, System.Rtti,
  System.Bindings.Outputs, Fmx.Bind.Editors, FireDAC.Stan.Intf,
  FireDAC.Stan.Option, FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS,
  FireDAC.Phys.Intf, FireDAC.DApt.Intf, Data.Bind.Components, Data.Bind.DBScope,
  Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client, FMX.ListView,
  DBXJSON, DBXJSONReflect, DBXCommon, DSHTTPClient, IndyPeerImpl, FMX.Layouts,
  FMX.Memo, Generics.Collections, Controller, UCliente, FMX.WebBrowser,
  FMX.Edit, FMX.DateTimeCtrls, UProduto, ACBrNFeDANFEFRDM, ACBrNFeDANFEClass,
  ACBrNFeDANFEFR, ACBrBase, ACBrDFe, ACBrNFe,
  ACBrDFeUtil, pcnConversao, pcnConversaoNFe, SessaoUsuario, Constantes,
  Biblioteca, Tipos, NfeDetalheVO, FMX.ListView.Appearances,
  FMX.ListView.Adapters.Base, FMX.Controls.Presentation;

type
  TFMenu = class(TForm)
    TabControl1: TTabControl;
    TabItem4: TTabItem;
    ToolBar5: TToolBar;
    lblTitle5: TLabel;
    ActionList1: TActionList;
    ChangeTabAction1: TChangeTabAction;
    ChangeTabAction2: TChangeTabAction;
    GestureManager1: TGestureManager;
    BindingsListCliente: TBindingsList;
    BotaoEmitirNFCe: TSpeedButton;
    CDSVendaDetalhe: TFDMemTable;
    ListViewItensNFCe: TListView;
    BindSourceDB3: TBindSourceDB;
    LinkListControlToField3: TLinkListControlToField;
    BotaoIncluirItem: TSpeedButton;
    procedure FormShow(Sender: TObject);
    procedure BotaoIncluirItemClick(Sender: TObject);

    procedure TelaPadrao;
    procedure ConfiguraConstantes;

    procedure InstanciaVendaAtual;
    procedure IniciaVenda;
    procedure ParametrosIniciaisVenda;
    procedure IniciaVendaDeItens;
    procedure VendeItem;
    procedure CompoeItemParaVenda;
    procedure AtualizaTotais;
    procedure IniciaEncerramentoVenda;
    procedure ConcluiEncerramentoVenda;

    procedure BotaoEmitirNFCeClick(Sender: TObject);

  private
    function GetSessaoUsuario: TSessaoUsuario;
  public
    property Sessao: TSessaoUsuario read GetSessaoUsuario;
  end;

var
  FMenu: TFMenu;
  ItemCupom: Integer;
  SubTotal, TotalGeral, Desconto, Acrescimo, ValorICMS: Extended;
  VendaDetalhe: TNfeDetalheVO;


implementation

{$R *.fmx}

uses ProdutoVO, VendedorVO, NfeNumeroVO, NfeCabecalhoVO, DavCabecalhoVO,
  UnidadeProdutoVO, UPagamento, UDanfe;

{$REGION 'Procedimentos principais e de infra'}
procedure TFMenu.FormShow(Sender: TObject);
begin
  Sessao.PopulaObjetosPrincipais;

  ConfiguraConstantes;

  TelaPadrao;
end;

function TFMenu.GetSessaoUsuario: TSessaoUsuario;
begin
  Result := TSessaoUsuario.Instance;
end;

procedure TFMenu.ConfiguraConstantes;
begin
  Constantes.TConstantes.DECIMAIS_QUANTIDADE := Sessao.Configuracao.DecimaisQuantidade;
  Constantes.TConstantes.DECIMAIS_VALOR := Sessao.Configuracao.DecimaisValor;
end;

procedure TFMenu.TelaPadrao;
begin
  SubTotal := 0;
  TotalGeral := 0;
  ValorICMS := 0;
  Desconto := 0;
  Acrescimo := 0;
end;
{$ENDREGION}

{$REGION 'Procedimentos para controle da venda'}
procedure TFMenu.InstanciaVendaAtual;
var
  NfeNumeroVO: TNfeNumeroVO;
begin
  try
    // instancia venda
    if not Assigned(Sessao.VendaAtual) then
    begin
      Sessao.VendaAtual := TNfeCabecalhoVO.Create;

      //Pega um número
      NfeNumeroVO := TNfeNumeroVO(TController.BuscarObjeto('NfeNumeroController.TNfeNumeroController', 'ConsultaObjeto', ['1=1'], 'GET'));

      //Gera a chave de acesso
      Sessao.VendaAtual.ChaveAcesso :=  IntToStr(Sessao.Configuracao.EmpresaVO.CodigoIbgeUf) +
                                        FormatDateTime('yy', Now) +
                                        FormatDateTime('mm', Now) +
                                        Sessao.Configuracao.EmpresaVO.Cnpj +
                                        '65' +
                                        NfeNumeroVO.Serie +
                                        StringOfChar('0', 9 - Length(IntToStr(NfeNumeroVO.Numero))) + IntToStr(NfeNumeroVO.Numero) +
                                        '1' +
                                        StringOfChar('0', 8 - Length(IntToStr(NfeNumeroVO.Numero))) + IntToStr(NfeNumeroVO.Numero);
      Sessao.VendaAtual.DigitoChaveAcesso := Modulo11(Sessao.VendaAtual.ChaveAcesso);

      Sessao.VendaAtual.UfEmitente := Sessao.Configuracao.EmpresaVO.CodigoIbgeUf;
      Sessao.VendaAtual.CodigoNumerico := StringOfChar('0', 8 - Length(IntToStr(NfeNumeroVO.Numero))) + IntToStr(NfeNumeroVO.Numero);
      Sessao.VendaAtual.NaturezaOperacao := 'VENDA';
      Sessao.VendaAtual.CodigoModelo := '65';
      Sessao.VendaAtual.Serie := NfeNumeroVO.Serie;
      Sessao.VendaAtual.Numero := StringOfChar('0', 9 - Length(IntToStr(NfeNumeroVO.Numero))) + IntToStr(NfeNumeroVO.Numero);
      Sessao.VendaAtual.DataHoraEmissao := Now;
      Sessao.VendaAtual.DataHoraEntradaSaida := Now;
      Sessao.VendaAtual.TipoOperacao := 1;
      Sessao.VendaAtual.CodigoMunicipio := Sessao.Configuracao.EmpresaVO.CodigoIbgeCidade;
      Sessao.VendaAtual.FormatoImpressaoDanfe := 4;
      Sessao.VendaAtual.TipoEmissao := 1;
      Sessao.VendaAtual.IdEmpresa := Sessao.Configuracao.EmpresaVO.Id;
      Sessao.VendaAtual.Ambiente := 2;
      Sessao.VendaAtual.FinalidadeEmissao := 1;
      Sessao.VendaAtual.ProcessoEmissao := 1;
      Sessao.VendaAtual.VersaoProcessoEmissao := '2';
      Sessao.VendaAtual.ConsumidorPresenca := 1;

    end;
  finally
    FreeAndNil(NfeNumeroVO);
  end;
end;

procedure TFMenu.BotaoIncluirItemClick(Sender: TObject);
begin
  FProduto.ShowModal;
  IniciaVendaDeItens;
end;

procedure TFMenu.BotaoEmitirNFCeClick(Sender: TObject);
begin
  IniciaEncerramentoVenda;
end;

procedure TFMenu.IniciaVenda;
begin
  // instancia venda
  InstanciaVendaAtual;

  ParametrosIniciaisVenda;
  Sessao.StatusCaixa := scVendaEmAndamento;

  Sessao.VendaAtual.IdNfceMovimento := Sessao.Movimento.Id;

  TController.ExecutarMetodo('VendaController.TVendaController', 'Insere', [Sessao.VendaAtual], 'PUT', 'Objeto');
  Sessao.LiberaVendaAtual;
  Sessao.VendaAtual := TNfeCabecalhoVO(TController.ObjetoConsultado);

  lblTitle5.Text := 'NFC-e nº ' + Sessao.VendaAtual.Numero;
end;

procedure TFMenu.ParametrosIniciaisVenda;
begin
  ItemCupom := 0;
  SubTotal := 0;
  TotalGeral := 0;
  ValorICMS := 0;
end;

procedure TFMenu.IniciaVendaDeItens;
var
  Unitario, Quantidade, Total: Extended;
begin
    IniciaVenda;

    VendaDetalhe := TNfeDetalheVO.Create;
    VendaDetalhe.ProdutoVO := TProdutoVO(TController.BuscarObjeto('ProdutoController.TProdutoController', 'ConsultaPorTipo', [FMenu.CDSVendaDetalhe.FieldByName('ID_PRODUTO').AsString, 4], 'GET'));

    if Assigned(VendaDetalhe.ProdutoVO) then
    begin
      Unitario := VendaDetalhe.ProdutoVO.ValorVenda;
      Quantidade := 1;
      Total := TruncaValor(Unitario * Quantidade, Constantes.TConstantes.DECIMAIS_VALOR);

      VendeItem;

      SubTotal := SubTotal + VendaDetalhe.ValorTotal;
      TotalGeral := TotalGeral + VendaDetalhe.ValorTotal;
      ValorICMS := ValorICMS + VendaDetalhe.NfeDetalheImpostoIcmsVO.ValorIcms;
      AtualizaTotais;
    end; // if Produto.Id <> 0 then
end;

procedure TFMenu.VendeItem;
begin
  try
    CompoeItemParaVenda;

    // Imposto
    VendaDetalhe.NfeDetalheImpostoIcmsVO.OrigemMercadoria := 0; //nacional
    VendaDetalhe.NfeDetalheImpostoIcmsVO.CstIcms := '00'; //nacional
    VendaDetalhe.NfeDetalheImpostoIcmsVO.ModalidadeBcIcms := 3; //valor da operação
    VendaDetalhe.NfeDetalheImpostoIcmsVO.AliquotaIcms := VendaDetalhe.ProdutoVO.AliquotaIcmsPaf;
    VendaDetalhe.NfeDetalheImpostoIcmsVO.BaseCalculoIcms := VendaDetalhe.ValorTotal;
    VendaDetalhe.NfeDetalheImpostoIcmsVO.ValorIcms := VendaDetalhe.ValorTotal * VendaDetalhe.ProdutoVO.AliquotaIcmsPaf / 100;

    TController.ExecutarMetodo('VendaController.TVendaController', 'InsereItem', [VendaDetalhe], 'PUT', 'Objeto');
    FreeAndNil(VendaDetalhe);
    VendaDetalhe := TNfeDetalheVO(TController.ObjetoConsultado);
    Sessao.VendaAtual.ListaNfeDetalheVO.Add(VendaDetalhe);

  finally
  end;
end;

procedure TFMenu.CompoeItemParaVenda;
begin
  inc(ItemCupom);
  VendaDetalhe.NumeroItem := ItemCupom;
  VendaDetalhe.IdProduto := VendaDetalhe.ProdutoVO.Id;
  VendaDetalhe.CFOP := Sessao.Configuracao.CFOP;
  VendaDetalhe.IdNfeCabecalho := Sessao.VendaAtual.Id;
  VendaDetalhe.CodigoProduto := VendaDetalhe.ProdutoVO.GTIN;
  VendaDetalhe.GTIN := VendaDetalhe.ProdutoVO.GTIN;
  VendaDetalhe.NomeProduto := VendaDetalhe.ProdutoVO.Nome;
  VendaDetalhe.Ncm := VendaDetalhe.ProdutoVO.Ncm;
  //VendaDetalhe.ExTipi := StrToInt(VendaDetalhe.ProdutoVO.ExTipi);
  VendaDetalhe.UnidadeComercial := VendaDetalhe.ProdutoVO.UnidadeProdutoVO.Sigla;
  VendaDetalhe.UnidadeTributavel := VendaDetalhe.ProdutoVO.UnidadeProdutoVO.Sigla;

  if Sessao.StatusCaixa = scVendaEmAndamento then
  begin
    VendaDetalhe.QuantidadeComercial := 1;
    VendaDetalhe.QuantidadeTributavel := 1;
    VendaDetalhe.ValorUnitarioComercial := ArredondaTruncaValor('A', VendaDetalhe.ProdutoVO.ValorVenda, 2);;
    VendaDetalhe.ValorUnitarioTributavel := ArredondaTruncaValor('A', VendaDetalhe.ProdutoVO.ValorVenda, 2);;
    VendaDetalhe.ValorBrutoProduto := ArredondaTruncaValor('A', VendaDetalhe.QuantidadeComercial * VendaDetalhe.ProdutoVO.ValorVenda, 2);
    VendaDetalhe.ValorSubtotal := VendaDetalhe.ValorBrutoProduto;
    // Exercício: implemente o desconto sobre o valor do item de acordo com a sua necessidade
    VendaDetalhe.ValorDesconto := 0;
    VendaDetalhe.ValorTotal := VendaDetalhe.ValorSubtotal - VendaDetalhe.ValorDesconto;
  end;
end;

procedure TFMenu.AtualizaTotais;
var
  DescontoAcrescimo: Extended;
begin
  Sessao.VendaAtual.ValorTotalProdutos := SubTotal;
  Sessao.VendaAtual.ValorDesconto := Desconto;
  Sessao.VendaAtual.ValorDespesasAcessorias := Acrescimo;

  Sessao.VendaAtual.ValorTotal := TotalGeral - Desconto + Acrescimo;
  Sessao.VendaAtual.BaseCalculoIcms := Sessao.VendaAtual.ValorTotal;
  Sessao.VendaAtual.ValorIcms := ValorICMS;
  DescontoAcrescimo := Acrescimo - Desconto;

  if DescontoAcrescimo < 0 then
  begin
    Sessao.VendaAtual.ValorDesconto := -DescontoAcrescimo;
    Sessao.VendaAtual.ValorDespesasAcessorias := 0;
  end
  else if DescontoAcrescimo > 0 then
  begin
    Sessao.VendaAtual.ValorDesconto := 0;
    Sessao.VendaAtual.ValorDespesasAcessorias := DescontoAcrescimo;
  end
  else
  begin
    Acrescimo := 0;
    Desconto := 0;
  end;
end;

procedure TFMenu.IniciaEncerramentoVenda;
begin
  FPagamento.ShowModal;
end;

procedure TFMenu.ConcluiEncerramentoVenda;
begin
  try
    Sessao.VendaAtual.StatusNota := 4;
    FDanfe.ShowModal;
    TController.ExecutarMetodo('VendaController.TVendaController', 'Altera', [Sessao.VendaAtual], 'POST', 'Boolean');
  finally
    TelaPadrao;
  end;
end;
{$ENDREGION}

end.


/// EXERCICIO
///  Converta esse projeto para três camadas e utilize o servidor de aplicações
///  Faça testes num dispositivo real ou emulador
///
/// EXERCICIO
///  Remova os possíveis códigos VCL da aplicação
///
/// EXERCICIO
///  Implemente o cancelamento do item
///
/// EXERCICIO
///  Implemente o cancelamento da nota
///
/// EXERCICIO
///  Implemente a identificação do cliente
///
/// EXERCICIO
///  Implemente a identificação do vendedor
///
/// EXERCICIO
///  Implemente o desconto/acréscimo
