{ =============================================================================== Copyright (©) 2004. Rodax Software. =============================================================================== Los contenidos de este fichero son propiedad de Rodax Software titular del copyright. Este fichero sólo podrá ser copiado, distribuido y utilizado, en su totalidad o en parte, con el permiso escrito de Rodax Software, o de acuerdo con los términos y condiciones establecidas en el acuerdo/contrato bajo el que se suministra. ----------------------------------------------------------------------------- Web: www.rodax-software.com =============================================================================== Fecha primera versión: 09-05-2004 Versión actual: 1.0.1 Fecha versión actual: 24-06-2004 =============================================================================== Modificaciones: Fecha Comentarios --------------------------------------------------------------------------- 24-06-2004 Error con el tratamiento de 'LONGITUD'. =============================================================================== } unit RdxGestorContadores; {$INCLUDE COMPILE.INC} interface uses IBDatabase, Contadores; type TTipoOperacion = (toIncrementar, toDecrementar); TRdxGestorContadores = class(TObject) private FDatabase : TIBDatabase; FTransaction : TIBTransaction; FCodigoEmpresa : variant; procedure SetCodigoEmpresa(const Value: variant); function DarNuevoCodigoTabla: Variant; function DarDatosContador(Contador: TContador; var RegistroContador: TRegistroContador) : Boolean; function InsertarCabeceraContador(Contador : TContador; RegistroContador : TRegistroContador) : Boolean; function InsertarDetallesContador(Contador : TContador; RegistroContador : TRegistroContador) : Boolean; function DarDetallesContador(Contador: TContador; var ObjContador: TRegistroContador): Boolean; function ModificarContador(Contador: TContador; pvContador: Integer; pvSerie: Variant): Boolean; overload; function ModificarContador(Contador: TContador; Operacion: TTipoOperacion; Cantidad: Integer): Boolean; overload; procedure ComprobarContadores; function RecogerContador(Contador: TContador): TRegistroContador; function FormatearContador(Contador: TRegistroContador): String; function ValidarContador(Contador: TContador; Codigo: Variant): Boolean; public property BD : TIBDatabase read FDatabase write FDatabase; property Transaccion : TIBTransaction read FTransaction write FTransaction; property CodigoEmpresa : variant read FCodigoEmpresa write SetCodigoEmpresa; class function NewInstance: TObject; override; procedure FreeInstance; override; function DarNuevoCodigo(Contador: TContador): Variant; function IncrementarValor(Contador: TContador): Boolean; function DecrementarValor(Contador: TContador): Boolean; function ValidarCodigo(Contador: TContador; Codigo: Variant) : Boolean; function AsignarContador(Contador: TContador; Valor: Integer; Serie: Variant): Boolean; function FormatearCodigo(Contador: TContador; Codigo: variant): variant; function InsertarContador(Contador: TContador): Boolean; function DarValorContador(Contador: TContador): Variant; function DarSeriadoContador(Contador: TContador): Variant; end; var GestorContadores : TRdxGestorContadores = nil; implementation uses SysUtils, IBSQL, StrFunc, DateFunc, IB, Mensajes {$IFDEF RDX_D7}, Variants{$ENDIF}; Const lsMensajeUnit = 'RdxGestorContadores: Método '; lsSeparador = '/'; { TGestorContadores } function TRdxGestorContadores.DarNuevoCodigoTabla: Variant; //Recoge el siguiente codigo de tabla disponible var oSQL : TIBSQL; begin Result := '0'; oSQL := TIBSQL.Create(nil); with oSQL do begin Database := FDatabase; Transaction := FTransaction; SQL.Add('select MAX(CODIGOTABLA) + 1 from CONTADORES '); try Prepare; ExecQuery; if not EsCadenaVacia(Fields[0].AsString) then Result := Fields[0].AsString; finally Close; Transaction := NIL; Free; end; end; end; function TRdxGestorContadores.DarDatosContador(Contador: TContador; var RegistroContador: TRegistroContador) : Boolean; //Comprueba si ya existe el contador var oSQL : TIBSQL; begin Result := False; oSQL := TIBSQL.Create(nil); with oSQL do begin Database := FDatabase; Transaction := FTransaction; SQL.Add('select CODIGOTABLA, TABLA, LONGITUD, COMUN '); SQL.Add('from CONTADORES'); SQL.Add('where TABLA = :TABLA'); try ParamByName('TABLA').AsString := NombreTablasContadores[Contador]; Prepare; ExecQuery; if (RecordCount <> 0) then begin RegistroContador.CodigoTabla := FieldByName('CODIGOTABLA').AsString; RegistroContador.Tabla := FieldByName('TABLA').AsString; RegistroContador.Longitud := FieldByName('LONGITUD').AsVariant; RegistroContador.EsComun := (FieldByName('COMUN').AsInteger = 1); Result := True; end; finally Close; Transaction := NIL; Free; end; end; end; function TRdxGestorContadores.FormatearContador(Contador: TRegistroContador): String; //Formatea el codigo con la estructura SERIADOAAMMDD/XXX, siempre adaptandose al tamaño del contador var Codigo: String; LongAux: Integer; begin LongAux := Contador.Longitud; if (not esCadenaVacia(Contador.Seriado)) then begin Codigo := Contador.Seriado; LongAux := LongAux - length(Contador.Seriado); end; if (Contador.Ano) then begin Codigo := Codigo + Contador.ContAno; LongAux := LongAux - 2; end; if (Contador.Mes) then begin Codigo := Codigo + Contador.ContMes; LongAux := LongAux - 2; end; if (Contador.Dia) then begin Codigo := Codigo + Contador.ContMes; LongAux := LongAux - 2; end; if (not esCadenaVacia(Contador.Seriado)) then begin Codigo := Codigo + lsSeparador; LongAux := LongAux - 1; end; Codigo := Codigo + format('%.' + IntToStr(LongAux) + 'd', [Contador.Contador]); result := Codigo; end; procedure TRdxGestorContadores.FreeInstance; begin if GestorContadores = Self then begin GestorContadores := NIL; inherited FreeInstance; end; end; class function TRdxGestorContadores.NewInstance: TObject; begin if Assigned(GestorContadores) then Exception.Create('No se puede tener mas de una instancia') else begin Result := inherited NewInstance; with TRdxGestorContadores(Result) do begin FDatabase := NIL; FTransaction := NIL; FCodigoEmpresa := NULL; end; end; end; function TRdxGestorContadores.RecogerContador(Contador: TContador): TRegistroContador; { Función recursiva que devuelve una instancia del contador pasado por parametro. En el caso de no existir lo creara, tanto la cabecera como el detalle, es decir, que cada vez que se entre con una empresa diferente se creara una linea de detalle nueva en todos los contadores multiempresa. } var lCont : TRegistroContador; begin if not DarDatosContador(Contador, lCont) then begin InicializarContador(Contador, lCont); InsertarCabeceraContador(Contador, lCont); Result := RecogerContador(Contador); end else begin if not DarDetallesContador(Contador, lCont) then begin InicializarContador(Contador, lCont); InsertarDetallesContador(Contador, lCont); Result := RecogerContador(Contador); end else begin Result := lCont; end end; end; procedure TRdxGestorContadores.SetCodigoEmpresa(const Value: variant); begin if FCodigoEmpresa <> Value then begin FCodigoEmpresa := Value; ComprobarContadores; end; end; function TRdxGestorContadores.InsertarCabeceraContador(Contador : TContador; RegistroContador : TRegistroContador) : Boolean; // Inserta los datos del contador var oSQL : TIBSQL; begin Result := False; oSQL := TIBSQL.Create(nil); with oSQL do begin Database := FDatabase; Transaction := FTransaction; SQL.Add('insert into CONTADORES '); SQL.Add('(CODIGOTABLA, TABLA, LONGITUD, COMUN) '); SQL.Add('values (:CODIGOTABLA, :TABLA, :LONGITUD, :COMUN)'); try ParamByName('CODIGOTABLA').AsVariant := DarNuevoCodigoTabla; ParamByName('TABLA').AsVariant := NombreTablasContadores[Contador]; if (RegistroContador.EsComun) then ParamByName('COMUN').AsInteger := 1 else ParamByName('COMUN').AsInteger := 0; ParamByName('LONGITUD').AsVariant := RegistroContador.Longitud; Prepare; ExecQuery; Result := True; except on E : EIBError do begin //LOG VerMensaje(lsMensajeUnit + 'anadirContador, ' + E.Message); end; on E : Exception do begin //LOG VerMensaje(lsMensajeUnit + 'anadirContador, ' + E.Message); end; end; Close; Transaction := NIL; Free; end; end; function TRdxGestorContadores.InsertarDetallesContador( Contador : TContador; RegistroContador : TRegistroContador) : Boolean; // Insertar el detalle del nuevo contador var oSQL : TIBSQL; begin Result := False; oSQL := TIBSQL.Create(nil); with oSQL do begin Database := FDatabase; Transaction := FTransaction; SQL.Add('insert into DETALLECONTADORES (CODIGOTABLA'); if not RegistroContador.EsComun then SQL.Add(', CODIGOEMPRESA'); SQL.Add(', SERIADO, DIA, MES, ANO, CONTADOR'); if (RegistroContador.Ano) then SQL.Add(', CONTANO'); if (RegistroContador.Mes) then SQL.Add(', CONTMES'); if (RegistroContador.Dia) then SQL.Add(', CONTDIA'); SQL.Add(') values (:CODIGOTABLA'); if not RegistroContador.EsComun then SQL.Add(', :CODIGOEMPRESA'); SQL.Add(', :SERIADO, :DIA, :MES, :ANO, :CONTADOR'); if (RegistroContador.Ano) then SQL.Add(', substr(CURRENT_DATE, 3, 4)'); if (RegistroContador.Mes) then SQL.Add(', substr(CURRENT_DATE, 6, 7)'); if (RegistroContador.Dia) then SQL.Add(', substr(CURRENT_DATE, 9, 10)'); SQL.Add(')'); try if not RegistroContador.EsComun then ParamByName('CODIGOEMPRESA').AsVariant := CodigoEmpresa; ParamByName('CODIGOTABLA').AsVariant := RegistroContador.CodigoTabla; ParamByName('SERIADO').AsVariant := RegistroContador.Seriado; if (RegistroContador.Dia) then ParamByName('DIA').AsInteger := 1 else ParamByName('DIA').AsInteger := 0; if (RegistroContador.Mes) then ParamByName('MES').AsInteger := 1 else ParamByName('MES').AsInteger := 0; if (RegistroContador.Ano) then ParamByName('ANO').AsInteger := 1 else ParamByName('ANO').AsInteger := 0; ParamByName('CONTADOR').AsInteger := RegistroContador.Contador; Prepare; ExecQuery; Result := True; except on E : EIBError do begin //LOG verMensaje(lsMensajeUnit + 'anadirDetalles, ' + E.Message); end; on E : Exception do begin //LOG verMensaje(lsMensajeUnit + 'anadirDetalles, ' + E.Message); end; end; Close; Transaction := NIL; Free; end; end; function TRdxGestorContadores.DarDetallesContador(Contador: TContador; var ObjContador: TRegistroContador): Boolean; { Comprueba si existen detalles del contador pasado por parametro. Si es así, los rellena y devuelve true. } var oSQL : TIBSQL; begin Result := False; oSQL := TIBSQL.Create(nil); with oSQL do begin Database := FDatabase; Transaction := FTransaction; SQL.Add('select CODIGOEMPRESA, CODIGOTABLA, SERIADO, DIA, MES, ANO, CONTDIA, CONTMES, CONTANO, CONTADOR '); SQL.Add('from DETALLECONTADORES'); SQL.Add('where CODIGOTABLA = :CODIGOTABLA'); SQL.Add('and ((CODIGOEMPRESA = :CODIGOEMPRESA) OR (CODIGOEMPRESA IS NULL))'); SQL.Add('and (CONTANO = SUBSTR(CURRENT_DATE, 3, 4) or CONTANO IS NULL) '); SQL.Add('and (CONTMES = SUBSTR(CURRENT_DATE, 6, 7) or CONTMES IS NULL) '); SQL.Add('and (CONTDIA = SUBSTR(CURRENT_DATE, 9, 10) or CONTDIA IS NULL)'); try ParamByName('CODIGOEMPRESA').AsVariant := CodigoEmpresa; ParamByName('CODIGOTABLA').AsVariant := ObjContador.CodigoTabla; Prepare; ExecQuery; if (RecordCount <> 0) then begin ObjContador.Seriado := FieldByName('SERIADO').AsVariant; ObjContador.Dia := FieldByName('DIA').AsInteger = 1; ObjContador.Mes := FieldByName('MES').AsInteger = 1; ObjContador.Ano := FieldByName('ANO').AsInteger = 1; ObjContador.ContDia := FieldByName('CONTDIA').AsVariant; ObjContador.ContMes := FieldByName('CONTMES').AsVariant; ObjContador.ContAno := FieldByName('CONTANO').AsVariant; ObjContador.Contador := FieldByName('CONTADOR').AsInteger; Result := True; end else begin oSQL.Close; SQL.Clear; SQL.Add('select SERIADO'); SQL.Add('from DETALLECONTADORES'); SQL.Add('where CODIGOTABLA = :CODIGOTABLA'); SQL.Add('and ((CODIGOEMPRESA = :CODIGOEMPRESA) OR (CODIGOEMPRESA IS NULL))'); SQL.Add('ORDER BY CAST(DETALLECONTADORES.CONTANO as INTEGER) desc,'); SQL.Add('CAST(DETALLECONTADORES.CONTMES as INTEGER) desc,'); SQL.Add('CAST(DETALLECONTADORES.CONTDIA as INTEGER) desc'); ParamByName('CODIGOEMPRESA').AsVariant := CodigoEmpresa; ParamByName('CODIGOTABLA').AsVariant := ObjContador.CodigoTabla; Prepare; ExecQuery; if (RecordCount <> 0) then ObjContador.Seriado := FieldByName('SERIADO').AsVariant; end; finally Close; Transaction := NIL; Free; end; end; end; function TRdxGestorContadores.ModificarContador(Contador: TContador; pvContador: Integer; pvSerie: Variant): Boolean; var oSQL : TIBSQL; lCont : TRegistroContador; begin Result := False; lCont := RecogerContador(Contador); oSQL := TIBSQL.Create(nil); with oSQL do begin Database := FDatabase; Transaction := FTransaction; SQL.Add('update DETALLECONTADORES '); SQL.Add('set CONTADOR = :CONTADOR '); if (not VarIsNull(pvSerie)) then SQL.Add(', SERIADO = :SERIADO '); SQL.Add('where CODIGOTABLA = :CODIGOTABLA '); if not (lCont.EsComun) then SQL.Add('and CODIGOEMPRESA = :CODIGOEMPRESA '); SQL.Add('and (CONTANO = SUBSTR(CURRENT_DATE, 3, 4) or CONTANO IS NULL) '); SQL.Add('and (CONTMES = SUBSTR(CURRENT_DATE, 6, 7) or CONTMES IS NULL)'); try if not (lCont.EsComun) then ParamByName('CODIGOEMPRESA').AsVariant := CodigoEmpresa; ParamByName('CODIGOTABLA').AsVariant := lCont.CodigoTabla; ParamByName('CONTADOR').AsInteger := pvContador; if (not VarIsNull(pvSerie)) then ParamByName('SERIADO').AsVariant := pvSerie; Prepare; ExecQuery; if (RowsAffected = 0) then //LOG VerMensaje(lsMensajeUnit + 'asigContador, ' + 'No se ha podido asignar el contador'); Result := True; finally Close; Transaction := NIL; Free; end; end; end; function TRdxGestorContadores.ModificarContador(Contador: TContador; Operacion: TTipoOperacion; Cantidad: Integer): Boolean; var oSQL : TIBSQL; lCont : TRegistroContador; lsAux : String; begin Result := False; if not DarDatosContador(Contador, lCont) then exit; if (Operacion = toDecrementar) then lsAux := '- ' + IntToStr(Cantidad) else begin if (Operacion = toIncrementar) then lsAux := '+ ' + IntToStr(Cantidad) else exit; end; oSQL := TIBSQL.Create(nil); with oSQL do begin Database := FDatabase; Transaction := FTransaction; SQL.Add('update DETALLECONTADORES '); SQL.Add('set CONTADOR = CONTADOR ' + lsAux); SQL.Add('where CODIGOTABLA = :CODIGOTABLA'); if not (lCont.EsComun) then SQL.Add(' and CODIGOEMPRESA = :CODIGOEMPRESA'); SQL.Add('and (CONTANO = SUBSTR(CURRENT_DATE, 3, 4) or CONTANO IS NULL)'); SQL.Add('and (CONTMES = SUBSTR(CURRENT_DATE, 6, 7) or CONTMES IS NULL)'); try if not (lCont.EsComun) then ParamByName('CODIGOEMPRESA').AsVariant := CodigoEmpresa; ParamByName('CODIGOTABLA').AsVariant := lCont.CodigoTabla; Prepare; ExecQuery; if (RowsAffected = 0) then //LOG VerMensaje(lsMensajeUnit + 'incdecCodigo, ' + 'No se ha podido incrementar el contador'); Result := True; finally Close; Transaction := NIL; Free; end; end; end; function TRdxGestorContadores.ValidarContador(Contador: TContador; Codigo: Variant): Boolean; var Long : Integer; LongAux : Integer; lCont : TRegistroContador; begin Result := False; lCont := RecogerContador(Contador); if VarIsNull(lCont.Longitud) then begin Result := EsNumerico(Codigo); Exit; end; Long := lCont.Longitud; LongAux := 1; if (not EsCadenaVacia(lCont.Seriado)) then begin if (Pos(lCont.Seriado, UpperCase(Codigo)) = 0) then exit; LongAux := LongAux + length(lCont.Seriado); end; if (lCont.Ano) then begin if not EsNumerico(Copy(Codigo, LongAux, 2)) then exit; LongAux := LongAux + 2; end; if (lCont.Mes) then begin if not EsMes(Copy(Codigo, LongAux, 2)) then exit; LongAux := LongAux + 2; end; if (lCont.Dia) then begin if not EsDia(Copy(Codigo, LongAux, 2)) then exit; LongAux := LongAux + 2; end; if (not EsCadenaVacia(lCont.Seriado)) then begin if (Pos(lsSeparador, Copy(Codigo, LongAux, 1)) = 0) then exit; LongAux := LongAux + 1; end; if (not EsNumerico(Copy(Codigo, LongAux, (Long - LongAux + 1)))) then exit; Result := True; end; function TRdxGestorContadores.DarNuevoCodigo( Contador: TContador): Variant; { Función llamada por todos los dmTabla de la aplicación, devuelve el código siguiente del contador pasado por parámetro. } var lCont : TRegistroContador; begin lCont := RecogerContador(Contador); if not VarIsNull(lCont.Longitud) then Result := FormatearContador(lCont) else Result := lCont.Contador; end; function TRdxGestorContadores.FormatearCodigo(Contador: TContador; Codigo: variant): variant; // Formatea el código rellenando la parte contador XXX del código a ceros. var lCont : TRegistroContador; lInd1 : Integer; begin lCont := RecogerContador(Contador); if VarIsNull(lCont.Longitud) then Result := Contador; // Extraer los valores del contador lInd1 := Pos(lsSeparador, Codigo); lCont.Contador := StrToInt(Copy(Codigo, (lInd1+1), (Length(Codigo) - lInd1))); if (lCont.Ano) then lCont.ContAno := Copy(Codigo, 4, 2); if (lCont.Mes) then lCont.ContMes := Copy(Codigo, 6, 2); if (lCont.Dia) then lCont.ContDia := Copy(Codigo, 8, 2); Result := FormatearContador(lCont); end; function TRdxGestorContadores.DecrementarValor(Contador: TContador): Boolean; begin Result := ModificarContador(Contador, toDecrementar, 1); end; function TRdxGestorContadores.IncrementarValor(Contador: TContador): Boolean; begin Result := ModificarContador(Contador, toIncrementar, 1); end; function TRdxGestorContadores.ValidarCodigo(Contador: TContador; Codigo: Variant): Boolean; begin Result := ValidarContador(Contador, Codigo); end; function TRdxGestorContadores.AsignarContador(Contador: TContador; Valor: Integer; Serie: Variant): Boolean; begin Result := ModificarContador(Contador, Valor, Serie); end; function TRdxGestorContadores.DarSeriadoContador( Contador: TContador): Variant; var lCont : TRegistroContador; begin lCont := RecogerContador(Contador); Result := lCont.Seriado; end; function TRdxGestorContadores.DarValorContador(Contador: TContador): Variant; var lCont : TRegistroContador; begin lCont := RecogerContador(Contador); Result := lCont.Contador; end; function TRdxGestorContadores.InsertarContador(Contador: TContador): Boolean; var lCont : TRegistroContador; begin lCont := RecogerContador(Contador); Result := (lCont.Tabla <> NULL); end; procedure TRdxGestorContadores.ComprobarContadores; var i : TContador; begin for i := Low(TContador) to High(TContador) do DarNuevoCodigo(i); if FTransaction.InTransaction then FTransaction.CommitRetaining; end; procedure LiberarGestorContadores; far; Begin if Assigned(GestorContadores) then FreeAndNil(GestorContadores); end; initialization GestorContadores := TRdxGestorContadores.Create; SysUtils.AddExitProc(LiberarGestorContadores); end. end.