<?php

	class
  TBoletoCarteiraCEF_SIGCB 
  private
    fCodigoBanco : String;
    fNumeroMoeda : String ;
    fIos : String ;
    fFixo : String ;
    fFatorVencimento : String;
    fTamanhoNossoNumeroComDV : Smallint;
    fValorStr : String;
    fNossoNumeroDVStr : String;
    fNossoNumeroSemDVStr : String;
    fCampoLivre : String;
    fBarraDvStr : String;
    fPermiteSemCPF: Integer;
    fSegmentoMensagem : Integer;
    function Modulo11NN(N : string; Peso : Integer) : string;
  public
    procedure Prepare(); override;
    function FormatarCodigoBarras() : String; override ;
    function FormatarLinhaDigitavel(CodigoBarras : String) : String ; override ;
    function FormatarNossoNumeroDV: String;override ;
    function FormatarNossoNumeroImpresso: String; override ;
  end;

implementation

uses U_StringUtil;

{ TBoletoCarteiraCEF_SIGCB }

Procedure TBoletoCarteiraCEF_SIGCB.Prepare;
begin
  fPermiteSemCPF            := 0;
  fSegmentoMensagem         := 80;  
  fCodigoBanco              := '104';
  fNumeroMoeda              := '9';
  fTamanhoNossoNumeroComDV  := 18;    // Quantidade de dígitos Nosso Número(com DV)
  fFixo     	              := '9';   // Numero fixo para a posição 05-05
  fIos	  		              := '0';   // IOS - somente para Seguradoras (Se 7% informar 7, limitado 9%) // Demais clientes usar 0 (zero)
  fFatorVencimento          := RetornaFatorVencimento(DataVencimento);
  fValorStr                 := FormatarValor(ValorBoleto);
  fNossoNumeroDVStr         := FormatarNossoNumeroDV;
  fNossoNumeroSemDvStr      := Copy(fNossoNumeroDVStr,1,length(fNossoNumeroDVStr)-1);

  ValidaTamanho(fNossoNumeroSemDvStr, 17, 'ERRO TAMANHO NOSSO NUMERO SEM DV');
  ValidaTamanho(fNossoNumeroDVStr, 18, 'ERRO TAMANHO NOSSO NUMERO COM DV');

  // especificacao do campo livre
  // 20 – 25  6   9 (6)   Código do Cedente
  // 26 – 26  1   9 (1)   Dígito Verificador do Código do Cedente
  // 27 – 29  3   9 (3)   Nosso Número – Seqüência 1
  // 30 – 30  1   9 (1)   Constante 1
  // 31 – 33  3   9 (3)   Nosso Número – Seqüência 2
  // 34 – 34  1   9 (1)   Constante 2
  // 35 – 43  9   9 (9)   Nosso Número – Seqüência 3
  // 44 – 44  1   9 (1)   Dígito Verificador do Campo Livre

  // XXXXXXD1NNNC1NNNC2NNNNNNNNND2

  if ContaDV = '' then
    ContaDV := Modulo11NN(Conta, 9);

  fcampoLivre := '';
  fcampoLivre := fcampoLivre + ZeroEsquerda(Conta, 6);            // 20 – 25  6   9 (6)   Código do Beneficiario
  fcampoLivre := fcampoLivre + ZeroEsquerda(ContaDV, 1) ;         // 26 – 26  1   9 (1)   Dígito Verificador do Código do Beneficiário
  fcampoLivre := fcampoLivre + Copy(fNossoNumeroSemDVStr, 3, 3);  // 27 – 29  3   9 (3)   Nosso Número – Seqüência 1
  fcampoLivre := fcampoLivre + Copy(fNossoNumeroSemDVStr, 1, 1);  // 30 - 30  1   9 (1)   Constante 1 (Tipo de Cobrança (1-Registrada / 2-Sem Registro))
  fcampoLivre := fcampoLivre + Copy(fNossoNumeroSemDVStr, 6, 3);  // 31 – 33  3   9 (3)   Nosso Número – Seqüência 2
  fcampoLivre := fcampoLivre + Copy(fNossoNumeroSemDVStr, 2, 1);  // 34 - 34  1   9 (1)   Constante 2 (Identificador de Emissão do Boleto (4-Beneficiário))
  fcampoLivre := fcampoLivre + Copy(fNossoNumeroSemDVStr, 9, 9);  // 35 – 43  9   9 (9)   Nosso Número – Seqüência 3
  fcampoLivre := fcampoLivre + Modulo11NN(fcampoLivre, 9);        // 44 – 44  1   9 (1)   Dígito Verificador do Campo Livre

  ValidaTamanho(fcampoLivre, 25, 'ERRO TAMANHO CAMPO LIVRE');
end;

function TBoletoCarteiraCEF_SIGCB.Modulo11NN(N : string; Peso : Integer) : string;
var
  Somatorio, m, f : Integer;
begin
  m := 2;
  Somatorio := 0;
  for f := Length(N) downto 1 do
  begin
    Somatorio := Somatorio + (StrToInt(N[f]) * m);
    inc(m);
    if m = Peso + 1 then
      m := 2;
  end;

  m := (Somatorio mod 11);
  m := 11 - m ;
  if m > 9 then
    m := 0 ;

  Result := IntToStr(m);
end;

function TBoletoCarteiraCEF_SIGCB.FormatarNossoNumeroDV: String;
var
  CC, NN : String;
begin
  // FORMATO NOSSO  NUMERO CCNNNNNNNNNNNNNNN
{
  if Carteira = 'SIG11' then CC := '11'
  else if Carteira = 'SIG14' then CC := '14'
  else if Carteira = 'SIG21' then CC := '21'
  else if Carteira = 'SIG24' then CC := '24'
  else raise Exception.Create('erro');
}
  NN := '';
  NN := NN + Copy(Carteira,4,2) ;
  NN := NN + ZeroEsquerdaInt(SequenciaNossoNumero, 15);
  NN := NN + Modulo11NN(NN, 9);
  Result := NN ;
end;

function TBoletoCarteiraCEF_SIGCB.FormatarNossoNumeroImpresso: String;
var
  NN, DV : String;
begin
  NN := FormatarNossoNumeroDV ;
  DV := copy(NN, Length(NN), 1);
  NN := copy(NN, 1, Length(NN)-1);
  Result := NN +'-'+ DV ;
end;

function TBoletoCarteiraCEF_SIGCB.FormatarCodigoBarras: String;
var
  BarraSemDvTmp : String ;
begin
  BarraSemDvTmp :=  fCodigoBanco +      // 01 – 03 3   9 (3)   Identificação do banco
                    fNumeroMoeda +      // 04 – 04 1   9       Código da moeda (9 – real)
                    '' +                // 05 – 05 1   9       Dígito Verificador Geral do Código de Barras
                    fFatorVencimento +  // 06 – 09 4   9       Fator de Vencimento
                    fValorStr +         // 10 – 19 10  9 (8)   V99 Valor do Documento
                    fCampoLivre;        // 20 – 44 25  9 (25)  Campo Livre

  fBarraDvStr := DigitoCodigoBarras(BarraSemDvTmp);

  Result := '';
  Result := Copy(BarraSemDvTmp,1,4) + fBarraDvStr + Copy(BarraSemDvTmp, 5, 39);
  
  CheckCodigoBarras(Result);
end;

function TBoletoCarteiraCEF_SIGCB.FormatarLinhaDigitavel(CodigoBarras : String): String;
var
  Campo1,
  Campo2,
  Campo3,
  Campo4,
  Campo5 : String;
begin
  // Campo 1
  // Posição 01 a 04 e posição 20 a 24   09
  // Dígito verificador Módulo 10        01

  Campo1 := '';
  Campo1 := Campo1 + Copy(CodigoBarras, 1, 4);
  Campo1 := Campo1 + Copy(CodigoBarras, 20, 5);
  Campo1 := Campo1 + Modulo10(Campo1);

  // Campo 2
  // Posição 25 a 34                     10
  // Dígito verificador Módulo 10        01
  Campo2 := '';
  Campo2 := Campo2 + Copy(CodigoBarras, 25, 10);
  Campo2 := Campo2 + Modulo10(Campo2);

  // Campo 3
  // Posição 35 a 44                     10
  // Dígito verificador Módulo 10        01
  Campo3 := '';
  Campo3 := Campo3 + Copy(CodigoBarras, 35, 10);
  Campo3 := Campo3 + Modulo10(Campo3);


  // Campo 4
  // Posição 05 (DV Geral)               01
  Campo4 := Copy(CodigoBarras, 5, 1);

  // Campo 5
  // Posição 06 a 09 (Fator de Vencimento) 04
  // Posição 10 a 19 (Valor do Título)     10
  Campo5 := '';
  Campo5 := Campo5 + Copy(CodigoBarras, 6, 4);
  Campo5 := Campo5 + Copy(CodigoBarras, 10, 10);

  Result := Campo1 + Campo2 + Campo3 + Campo4 + Campo5 ;

  CheckLinhaDigitavel(Result);
end;

end.