409 lines
13 KiB
ObjectPascal
409 lines
13 KiB
ObjectPascal
|
|
unit uDetallesPresupuestoController;
|
|||
|
|
|
|||
|
|
interface
|
|||
|
|
|
|||
|
|
uses
|
|||
|
|
Classes, uDADataTable,
|
|||
|
|
uControllerDetallesBase, uBizDetallesPresupuesto, uIDataModulePresupuestos;
|
|||
|
|
|
|||
|
|
const
|
|||
|
|
CAMPO_DESCUENTO = 'DESCUENTO';
|
|||
|
|
|
|||
|
|
TIPO_DETALLE_DTO = 'Descuento';
|
|||
|
|
|
|||
|
|
type
|
|||
|
|
IDetallesPresupuestoController = interface(IControllerDetallesBase)
|
|||
|
|
['{30AE4357-BA51-49D1-8113-A03C97B78F32}']
|
|||
|
|
procedure AsignarID(ADetalles: IBizDetallesPresupuesto; IDNuevo: Integer; AEsNuevo:Boolean);
|
|||
|
|
procedure AddCapitulo(ADataTable: IDAStronglyTypedDataTable);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
TDetallesPresupuestoController = class(TControllerDetallesBase, IDetallesPresupuestoController)
|
|||
|
|
private
|
|||
|
|
FDataModule : IDataModulePresupuestos;
|
|||
|
|
FImporteSubtotal: Double;
|
|||
|
|
|
|||
|
|
protected
|
|||
|
|
procedure TratamientoDetalleDTO(DataTable: TDADataTable); virtual;
|
|||
|
|
procedure CalculoDetalleDTO(DataTable: TDADataTable; var ImporteAcumulado : Double; var ImporteTotal : Double); virtual;
|
|||
|
|
|
|||
|
|
procedure TratamientoDetalleSalto(DataTable: TDADataTable); override;
|
|||
|
|
procedure TratamientoDetalleTitulo(DataTable: TDADataTable); override;
|
|||
|
|
procedure TratamientoDetalleSubtotal(DataTable: TDADataTable); override;
|
|||
|
|
procedure TratamientoDetalleConcepto(DataTable: TDADataTable); override;
|
|||
|
|
|
|||
|
|
procedure validarCampos(DataTable: TDADataTable); override;
|
|||
|
|
procedure CalculoDetalleSubtotal(DataTable: TDADataTable; var ImporteAcumulado : Double;
|
|||
|
|
var ImporteTotal : Double); override;
|
|||
|
|
function CalcularTotalesHijos(Modificar: Boolean; DataTable: TDADataTable;
|
|||
|
|
var ImporteAcumulado: Double; var ImporteTotal: Double): Double; override;
|
|||
|
|
public
|
|||
|
|
procedure Move(ADataTable: IDAStronglyTypedDataTable; Posicion: TIntegerArray; Posiciones: Integer); override;
|
|||
|
|
procedure Add(ADataTable: IDAStronglyTypedDataTable; TipoConcepto: Variant); override;
|
|||
|
|
procedure Delete(ADataTable: IDAStronglyTypedDataTable; Posicion: TIntegerArray); override;
|
|||
|
|
|
|||
|
|
procedure AddCapitulo(ADataTable: IDAStronglyTypedDataTable);
|
|||
|
|
|
|||
|
|
procedure AsignarID(ADetalles: IBizDetallesPresupuesto; IDNuevo: Integer; AEsNuevo:Boolean);
|
|||
|
|
constructor Create; override;
|
|||
|
|
destructor Destroy; override;
|
|||
|
|
function DarListaTiposDetalle: TStringList; override;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
implementation
|
|||
|
|
|
|||
|
|
uses
|
|||
|
|
SysUtils, uDAInterfaces, Variants, uDataModulePresupuestos;
|
|||
|
|
|
|||
|
|
{ TDetallesPresupuestoController }
|
|||
|
|
|
|||
|
|
procedure TDetallesPresupuestoController.Add(ADataTable: IDAStronglyTypedDataTable; TipoConcepto: Variant);
|
|||
|
|
var
|
|||
|
|
AuxNumOrden : Variant;
|
|||
|
|
|
|||
|
|
begin
|
|||
|
|
//Sobreescribimos el m<>todo porque si a<>adimos teniendo el puntero en un registro
|
|||
|
|
//de tipo subtotal, comprobamos si tiene descuento para a<>adir el nuevo registro
|
|||
|
|
//despues de dicho concepto y no entre medias.
|
|||
|
|
//inherited;
|
|||
|
|
|
|||
|
|
AuxNumOrden := Null;
|
|||
|
|
BeginUpdate(ADataTable);
|
|||
|
|
try
|
|||
|
|
with ADataTable do
|
|||
|
|
begin
|
|||
|
|
if not DataTable.IsEmpty then
|
|||
|
|
begin
|
|||
|
|
AuxNumOrden := DataTable.FieldByName(CAMPO_POSICION).AsVariant;
|
|||
|
|
if (getTipo(ADataTable, AuxNumOrden) = TIPO_DETALLE_SUBTOTAL)
|
|||
|
|
and (getTipo(ADataTable, (AuxNumOrden + 1)) = TIPO_DETALLE_DTO) then
|
|||
|
|
Inc(AuxNumOrden);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
AuxNumOrden := desplazarNPosiciones(DataTable, AuxNumOrden, 1);
|
|||
|
|
|
|||
|
|
DataTable.Insert;
|
|||
|
|
DataTable.FieldByName(CAMPO_POSICION).AsInteger := AuxNumOrden;
|
|||
|
|
DataTable.FieldByName(CAMPO_TIPO).AsString := TipoConcepto;
|
|||
|
|
if (TipoConcepto = TIPO_DETALLE_TITULO)
|
|||
|
|
then DataTable.FieldByName(CAMPO_CONCEPTO).AsVariant := '{\rtf1\ansi\ansicpg1252\deff0{\fonttbl{\f0\fnil\fcharset0 Comic Sans MS;}}\viewkind4\uc1\pard\lang3082\ul\b\f0\fs20 Cap\''edtulo de ...\par}'
|
|||
|
|
else if (TipoConcepto = TIPO_DETALLE_SUBTOTAL)
|
|||
|
|
then DataTable.FieldByName(CAMPO_CONCEPTO).AsVariant := '{\rtf1\ansi\ansicpg1252\deff0{\fonttbl{\f0\fnil\fcharset0 Comic Sans MS;}{\f1\fnil Tahoma;}}\viewkind4\uc1\pard\lang3082\b\f0\fs20 Total cap\''edtulo de ...\b0\f1\fs16\par}'
|
|||
|
|
else if (TipoConcepto = TIPO_DETALLE_DTO)
|
|||
|
|
then DataTable.FieldByName(CAMPO_CONCEPTO).AsVariant := '{\rtf1\ansi\ansicpg1252\deff0{\fonttbl{\f0\fnil\fcharset0 Comic Sans MS;}{\f1\fnil Tahoma;}}\viewkind4\uc1\pard\lang3082\b\f0\fs20 Descuento especial ...\b0\f1\fs16\par}';
|
|||
|
|
DataTable.post;
|
|||
|
|
end;
|
|||
|
|
finally
|
|||
|
|
EndUpdate(ADataTable);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TDetallesPresupuestoController.AddCapitulo(ADataTable: IDAStronglyTypedDataTable);
|
|||
|
|
begin
|
|||
|
|
BeginUpdate(ADataTable);
|
|||
|
|
try
|
|||
|
|
with ADataTable do
|
|||
|
|
begin
|
|||
|
|
Add(ADataTable, TIPO_DETALLE_TITULO);
|
|||
|
|
Add(ADataTable, TIPO_DETALLE_CONCEPTO);
|
|||
|
|
Add(ADataTable, TIPO_DETALLE_CONCEPTO);
|
|||
|
|
Add(ADataTable, TIPO_DETALLE_CONCEPTO);
|
|||
|
|
Add(ADataTable, TIPO_DETALLE_SUBTOTAL);
|
|||
|
|
Add(ADataTable, TIPO_DETALLE_DTO);
|
|||
|
|
end;
|
|||
|
|
finally
|
|||
|
|
EndUpdate(ADataTable);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TDetallesPresupuestoController.AsignarID(ADetalles: IBizDetallesPresupuesto;
|
|||
|
|
IDNuevo: Integer; AEsNuevo:Boolean);
|
|||
|
|
begin
|
|||
|
|
with ADetalles do
|
|||
|
|
begin
|
|||
|
|
DataTable.DisableControls;
|
|||
|
|
try
|
|||
|
|
if not DataTable.Active then
|
|||
|
|
DataTable.Active := True;
|
|||
|
|
|
|||
|
|
{ <EFBFBD><EFBFBD><EFBFBD><EFBFBD> OJO !!!!
|
|||
|
|
Para asignar el ID en los detalles hay
|
|||
|
|
que tener en cuenta una cosa:
|
|||
|
|
Si se cambia el ID, ese detalle ya no
|
|||
|
|
pertenece a esa cabecera porque ya no se
|
|||
|
|
cumple la condici<EFBFBD>n de la relacion:
|
|||
|
|
Master.ID = Detail.ID_PRESUPUESTO.
|
|||
|
|
|
|||
|
|
Por esa raz<EFBFBD>n no sirve hacer un recorrido
|
|||
|
|
desde el principio hasta el final porque
|
|||
|
|
las detalles van desapareciendo seg<EFBFBD>n asignamos
|
|||
|
|
el valor al campo ID y nos mueve aleatoriamente
|
|||
|
|
la posici<EFBFBD>n del registro actual.
|
|||
|
|
|
|||
|
|
Es mejor hacer un bucle sencillo hasta que
|
|||
|
|
"se gasten" todos los detalles. Cuando el
|
|||
|
|
RecordCount llegue a 0 quiere decir que hemos
|
|||
|
|
tratado todos los detalles.
|
|||
|
|
|
|||
|
|
El bucle cambia en el caso de ser llamada esta funcion desde modificar
|
|||
|
|
un presupuesto ya que en ese caso s<EFBFBD> que hay que hacer un recorrido
|
|||
|
|
total de las tuplas de detalle.
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if AEsNuevo then
|
|||
|
|
begin
|
|||
|
|
while RecordCount > 0 do
|
|||
|
|
begin
|
|||
|
|
DataTable.First;
|
|||
|
|
Edit;
|
|||
|
|
ID := FDataModule.GetNextID(DataTable.LogicalName);
|
|||
|
|
ID_PRESUPUESTO := IDNuevo;
|
|||
|
|
Post
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
begin
|
|||
|
|
DataTable.First;
|
|||
|
|
while not DataTable.EOF do
|
|||
|
|
begin
|
|||
|
|
if not EsNuevo then
|
|||
|
|
begin
|
|||
|
|
Edit;
|
|||
|
|
ID := FDataModule.GetNextID(DataTable.LogicalName);
|
|||
|
|
ID_PRESUPUESTO := IDNuevo;
|
|||
|
|
Post
|
|||
|
|
end;
|
|||
|
|
DataTable.Next
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
finally
|
|||
|
|
DataTable.EnableControls;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function TDetallesPresupuestoController.CalcularTotalesHijos(Modificar: Boolean;
|
|||
|
|
DataTable: TDADataTable;
|
|||
|
|
var ImporteAcumulado, ImporteTotal: Double): Double;
|
|||
|
|
begin
|
|||
|
|
if (DataTable.FieldByName(CAMPO_TIPO).AsString = TIPO_DETALLE_DTO) then
|
|||
|
|
begin
|
|||
|
|
if Modificar then
|
|||
|
|
TratamientoDetalleDTO(DataTable);
|
|||
|
|
CalculoDetalleDTO(DataTable, ImporteAcumulado, ImporteTotal);
|
|||
|
|
end
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TDetallesPresupuestoController.CalculoDetalleDTO(DataTable: TDADataTable; var ImporteAcumulado, ImporteTotal: Double);
|
|||
|
|
var
|
|||
|
|
ImporteDto: Double;
|
|||
|
|
begin
|
|||
|
|
ImporteDto := (-1)*((FImporteSubtotal * DataTable.FieldByName(CAMPO_DESCUENTO).AsFloat) / 100);
|
|||
|
|
|
|||
|
|
with DataTable do
|
|||
|
|
begin
|
|||
|
|
if not Editing then Edit;
|
|||
|
|
FieldByName(CAMPO_IMPORTE_TOTAL).AsFloat := ImporteDto;
|
|||
|
|
Post;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
FImporteSubtotal := 0;
|
|||
|
|
ImporteTotal := ImporteTotal + ImporteDto;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TDetallesPresupuestoController.CalculoDetalleSubtotal(
|
|||
|
|
DataTable: TDADataTable; var ImporteAcumulado, ImporteTotal: Double);
|
|||
|
|
begin
|
|||
|
|
FImporteSubtotal := ImporteAcumulado;
|
|||
|
|
inherited;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
constructor TDetallesPresupuestoController.Create;
|
|||
|
|
begin
|
|||
|
|
inherited;
|
|||
|
|
FDataModule := TDataModulePresupuestos.Create(Nil);
|
|||
|
|
FImporteSubtotal := 0;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
function TDetallesPresupuestoController.DarListaTiposDetalle: TStringList;
|
|||
|
|
begin
|
|||
|
|
Result := inherited DarListaTiposDetalle;
|
|||
|
|
Result.Values[TIPO_DETALLE_DTO] := 'Descuento';
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TDetallesPresupuestoController.Delete(ADataTable: IDAStronglyTypedDataTable; Posicion: TIntegerArray);
|
|||
|
|
var
|
|||
|
|
i: integer;
|
|||
|
|
AField: TDAField;
|
|||
|
|
DeletePosicion: Integer;
|
|||
|
|
begin
|
|||
|
|
//inherited
|
|||
|
|
|
|||
|
|
AField := ADataTable.DataTable.FindField(CAMPO_POSICION);
|
|||
|
|
if not Assigned(AField) then
|
|||
|
|
raise Exception.Create('Campo ' + CAMPO_POSICION + ' no encontrado (Delete)');
|
|||
|
|
|
|||
|
|
BeginUpdate(ADataTable);
|
|||
|
|
try
|
|||
|
|
with ADataTable do
|
|||
|
|
begin
|
|||
|
|
for i := 0 to High(POSICION) do
|
|||
|
|
begin
|
|||
|
|
DataTable.First;
|
|||
|
|
DeletePosicion := POSICION[i];
|
|||
|
|
if DataTable.Locate(CAMPO_POSICION, IntToStr(DeletePosicion), []) then
|
|||
|
|
begin
|
|||
|
|
if (DataTable.FieldByName(CAMPO_TIPO).AsString = TIPO_DETALLE_SUBTOTAL) then
|
|||
|
|
begin
|
|||
|
|
DataTable.Delete;
|
|||
|
|
DataTable.First;
|
|||
|
|
if (DataTable.Locate(CAMPO_POSICION, IntToStr((DeletePosicion + 1)), []))
|
|||
|
|
and (DataTable.FieldByName(CAMPO_TIPO).AsString = TIPO_DETALLE_DTO) then
|
|||
|
|
DataTable.Delete;
|
|||
|
|
end
|
|||
|
|
else DataTable.Delete;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
renumerar(DataTable, DeletePosicion);
|
|||
|
|
end;
|
|||
|
|
finally
|
|||
|
|
EndUpdate(ADataTable);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
destructor TDetallesPresupuestoController.Destroy;
|
|||
|
|
begin
|
|||
|
|
FDataModule := Nil;
|
|||
|
|
inherited;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TDetallesPresupuestoController.Move(ADataTable: IDAStronglyTypedDataTable; Posicion: TIntegerArray;
|
|||
|
|
Posiciones: Integer);
|
|||
|
|
var
|
|||
|
|
i:Integer;
|
|||
|
|
AField: TDAField;
|
|||
|
|
PosicionesAux: Integer;
|
|||
|
|
begin
|
|||
|
|
//Sobreescribimos el m<>todo porque en el caso de mover un concepto y ser un subtitulo
|
|||
|
|
//el concepto a intercambiar posici<63>n comprobamos si tiene descuento para desplazar dos unidades
|
|||
|
|
//el concepto a mover
|
|||
|
|
//inherited;
|
|||
|
|
|
|||
|
|
AField := ADataTable.DataTable.FindField(CAMPO_POSICION);
|
|||
|
|
if not Assigned(AField) then
|
|||
|
|
raise Exception.Create('Campo ' + CAMPO_POSICION + ' no encontrado (Move presupuestos controller)');
|
|||
|
|
|
|||
|
|
BeginUpdate(ADataTable);
|
|||
|
|
try
|
|||
|
|
with ADataTable do
|
|||
|
|
begin
|
|||
|
|
//Empezamos desde abajo
|
|||
|
|
if Posiciones > 0 then
|
|||
|
|
begin
|
|||
|
|
for i:= High(POSICION) downto 0 do
|
|||
|
|
begin
|
|||
|
|
if (getTipo(ADataTable, (POSICION[i]+1)) = TIPO_DETALLE_SUBTOTAL)
|
|||
|
|
and (getTipo(ADataTable, (POSICION[i]+2)) = TIPO_DETALLE_DTO) then
|
|||
|
|
begin
|
|||
|
|
Mover(DataTable, POSICION[i], Posiciones);
|
|||
|
|
Mover(DataTable, POSICION[i]+1, Posiciones)
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
Mover(DataTable, POSICION[i], Posiciones);
|
|||
|
|
end;
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
//Empezamos desde arriba
|
|||
|
|
for i:= 0 to High(POSICION) do
|
|||
|
|
begin
|
|||
|
|
if (getTipo(ADataTable, (POSICION[i]-1)) = TIPO_DETALLE_DTO)
|
|||
|
|
and (getTipo(ADataTable, (POSICION[i]-2)) = TIPO_DETALLE_SUBTOTAL) then
|
|||
|
|
begin
|
|||
|
|
Mover(DataTable, POSICION[i], Posiciones);
|
|||
|
|
Mover(DataTable, POSICION[i]-1, Posiciones)
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
Mover(DataTable, POSICION[i], Posiciones);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
finally
|
|||
|
|
EndUpdate(ADataTable);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TDetallesPresupuestoController.TratamientoDetalleConcepto(DataTable: TDADataTable);
|
|||
|
|
begin
|
|||
|
|
inherited;
|
|||
|
|
|
|||
|
|
with DataTable do
|
|||
|
|
begin
|
|||
|
|
if not Editing then Edit;
|
|||
|
|
FieldByName(CAMPO_DESCUENTO).AsVariant := Null;
|
|||
|
|
Post;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TDetallesPresupuestoController.TratamientoDetalleDTO(DataTable: TDADataTable);
|
|||
|
|
begin
|
|||
|
|
with DataTable do
|
|||
|
|
begin
|
|||
|
|
if not Editing then Edit;
|
|||
|
|
if (FieldByName(CAMPO_CONCEPTO).AsString = CTE_DESC_SALTO) then
|
|||
|
|
FieldByName(CAMPO_CONCEPTO).AsVariant := Null;
|
|||
|
|
FieldByName(CAMPO_CANTIDAD).AsVariant := Null;
|
|||
|
|
FieldByName(CAMPO_IMPORTE_UNIDAD).AsVariant := Null;
|
|||
|
|
Post;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TDetallesPresupuestoController.TratamientoDetalleSalto(DataTable: TDADataTable);
|
|||
|
|
begin
|
|||
|
|
inherited;
|
|||
|
|
|
|||
|
|
with DataTable do
|
|||
|
|
begin
|
|||
|
|
if not Editing then Edit;
|
|||
|
|
FieldByName(CAMPO_DESCUENTO).AsVariant := Null;
|
|||
|
|
Post;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TDetallesPresupuestoController.TratamientoDetalleSubtotal(DataTable: TDADataTable);
|
|||
|
|
begin
|
|||
|
|
inherited;
|
|||
|
|
|
|||
|
|
with DataTable do
|
|||
|
|
begin
|
|||
|
|
if not Editing then Edit;
|
|||
|
|
FieldByName(CAMPO_DESCUENTO).AsVariant := Null;
|
|||
|
|
Post;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TDetallesPresupuestoController.TratamientoDetalleTitulo(DataTable: TDADataTable);
|
|||
|
|
begin
|
|||
|
|
inherited;
|
|||
|
|
|
|||
|
|
with DataTable do
|
|||
|
|
begin
|
|||
|
|
if not Editing then Edit;
|
|||
|
|
FieldByName(CAMPO_DESCUENTO).AsVariant := Null;
|
|||
|
|
Post;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure TDetallesPresupuestoController.validarCampos(DataTable: TDADataTable);
|
|||
|
|
var
|
|||
|
|
AField: TDAField;
|
|||
|
|
|
|||
|
|
begin
|
|||
|
|
inherited;
|
|||
|
|
|
|||
|
|
//Validamos la existencia de todos los campos necesarios
|
|||
|
|
AField := DataTable.FindField(CAMPO_DESCUENTO);
|
|||
|
|
if not Assigned(AField) then
|
|||
|
|
raise Exception.Create('Campo ' + CAMPO_DESCUENTO + ' no encontrado (validarCampos)');
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
end.
|