git-svn-id: https://192.168.0.254/svn/Proyectos.AlonsoYSal_FactuGES/trunk@5 9a1d36f3-7752-2d40-8ccb-50eb49674c68
543 lines
15 KiB
ObjectPascal
543 lines
15 KiB
ObjectPascal
unit uBizAsientos;
|
||
|
||
interface
|
||
|
||
uses
|
||
uDAInterfaces, uDADataTable, schAsientosClient_Intf, Classes,
|
||
DBGrids, uDBSelectionList, DB, uExceptions, Controls, uBizCuentas,
|
||
uBizIntervalos;
|
||
|
||
const
|
||
CTE_PUNTEADO = 1;
|
||
CTE_NOPUNTEADO = 0;
|
||
CTE_ASIENTO = 'A';
|
||
CTE_CIERRE = 'C';
|
||
|
||
type
|
||
TDatosAsiento = class(TObject)
|
||
public
|
||
CodigoCuenta : Integer;
|
||
FechaAsiento : TDateTime;
|
||
CodigoPago : Integer;
|
||
Descripcion : String;
|
||
Importe: Currency;
|
||
end;
|
||
|
||
IBizAsiento = interface(IAsientos)
|
||
['{4585F549-EBAF-454C-826F-A8D527AD585E}']
|
||
function getCuenta: IBizCuenta;
|
||
property Cuenta: IBizCuenta read getCuenta;
|
||
|
||
procedure setIntervalo(const Value: IBizIntervalos);
|
||
function getIntervalo: IBizIntervalos;
|
||
property Intervalo: IBizIntervalos read getIntervalo write setIntervalo;
|
||
|
||
procedure Show;
|
||
function ShowForSelect : TModalResult;
|
||
|
||
procedure cerrarCaja;
|
||
procedure eliminarCierreCaja;
|
||
procedure puntearAsiento;
|
||
end;
|
||
|
||
TBizAsientoDataTableRules = class(TAsientosDataTableRules, IBizAsiento,
|
||
IApplyUpdateFailedException, ISelectedRowList)
|
||
private
|
||
FCuenta : IBizCuenta;
|
||
FIntervalo: IBizIntervalos;
|
||
FSumaAcumulada: Currency;
|
||
|
||
FSelectedRows : TSelectedRowList;
|
||
procedure ShowToSelect;
|
||
procedure BeforeApplyUpdates(Sender: TDADataTable; const Delta: IDADelta);
|
||
procedure OnPostError(DataTable: TDADataTable; Error: EDatabaseError;
|
||
var Action: TDataAction); override;
|
||
|
||
function puntearAsientos(const ValorPunteo: Integer): TDateTime;
|
||
procedure recalcular(const DesdeFinal: Boolean);
|
||
procedure CalcularImportes;
|
||
function anadirCierre(FechaCierre: TDateTime): Boolean;
|
||
function eliminarCierre: Boolean;
|
||
|
||
function getCuenta: IBizCuenta;
|
||
function getIntervalo: IBizIntervalos;
|
||
procedure setIntervalo(const Value: IBizIntervalos);
|
||
procedure OnCuentaChanged(Sender : TObject);
|
||
procedure OnIntervaloChanged(Sender : TObject);
|
||
|
||
procedure refrescarVista;
|
||
|
||
protected
|
||
procedure OnNewRecord(Sender: TDADataTable); override;
|
||
function GetSelectedRows : TSelectedRowList; virtual;
|
||
procedure ShowApplyUpdateFailed (const Error: EDAApplyUpdateFailed); virtual;
|
||
procedure BeforeDelete(Sender: TDADataTable); override;
|
||
procedure AfterPost(Sender: TDADataTable); override;
|
||
procedure AfterDelete(Sender: TDADataTable); override;
|
||
procedure AfterOpen(Sender: TDADataTable); override;
|
||
|
||
public
|
||
property SelectedRows : TSelectedRowList read GetSelectedRows;
|
||
property Cuenta: IBizCuenta read getCuenta;
|
||
property Intervalo: IBizIntervalos read getIntervalo write setIntervalo;
|
||
|
||
constructor Create(aDataTable: TDADataTable); override;
|
||
destructor Destroy; override;
|
||
procedure Show; virtual;
|
||
// procedure ShowAll; virtual;
|
||
// procedure Preview; virtual;
|
||
function ShowForSelect : TModalResult; virtual;
|
||
|
||
procedure cerrarCaja;
|
||
procedure eliminarCierreCaja;
|
||
procedure puntearAsiento;
|
||
end;
|
||
|
||
procedure ValidarAsiento (const AAsiento : IBizAsiento);
|
||
|
||
implementation
|
||
|
||
uses
|
||
Windows, Dialogs, uDACDSDataTable, SysUtils, uDataModuleBase, uDataModuleUsuarios,
|
||
uEditorUtils, uDataModuleAsientos, Variants, Forms, uCerrarCaja,
|
||
DateUtils, uDataModuleCuentas;
|
||
|
||
|
||
procedure ValidarAsiento (const AAsiento : IBizAsiento);
|
||
begin
|
||
if (AAsiento.TIPOASIENTO = CTE_ASIENTO) then
|
||
if (AAsiento.FECHAASIENTO <= AAsiento.Cuenta.ULTIMOCIERRE) then
|
||
raise Exception.Create('El asiento no puede tener fecha anterior al <20>ltimo cierre');
|
||
end;
|
||
|
||
|
||
{ TBizAsientoDataTableRules }
|
||
|
||
{
|
||
************************** TBizAsientoDataTableRules **************************
|
||
}
|
||
|
||
procedure TBizAsientoDataTableRules.OnNewRecord(Sender: TDADataTable);
|
||
begin
|
||
inherited;
|
||
USUARIO := dmUsuarios.LoginInfo.UserID;
|
||
FECHAALTA := Date;
|
||
TIPOASIENTO := CTE_ASIENTO;
|
||
FECHAASIENTO := Date;
|
||
PUNTEADO := CTE_NOPUNTEADO;
|
||
CODIGOCUENTA := Cuenta.CODIGO;
|
||
IMPORTE := 0;
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.Show;
|
||
begin
|
||
if PUNTEADO = CTE_PUNTEADO then
|
||
begin
|
||
raise Exception.Create('No se puede modificar este asiento porque est<73> punteado');
|
||
exit;
|
||
end;
|
||
|
||
ShowEditor(IBizAsiento, Self, etItem);
|
||
end;
|
||
|
||
{procedure TBizAsientoDataTableRules.Preview;
|
||
begin
|
||
// dmContactos.Preview;
|
||
end;
|
||
}
|
||
procedure TBizAsientoDataTableRules.ShowApplyUpdateFailed(
|
||
const Error: EDAApplyUpdateFailed);
|
||
begin
|
||
if (Pos(AUF_FKVIOLATION, Error.Message) > 0) then
|
||
MessageBox(0, 'No se puede borrar este asiento porque tiene pagos asociados', 'Atenci<63>n', MB_ICONWARNING or MB_OK);
|
||
end;
|
||
|
||
function TBizAsientoDataTableRules.GetSelectedRows: TSelectedRowList;
|
||
begin
|
||
Result := FSelectedRows;
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.ShowToSelect;
|
||
begin
|
||
//
|
||
end;
|
||
|
||
constructor TBizAsientoDataTableRules.Create(aDataTable: TDADataTable);
|
||
begin
|
||
inherited;
|
||
FSumaAcumulada := 0;
|
||
FCuenta := dmCuentas.GetItems;
|
||
FCuenta.OnCuentaChanged := OnCuentaChanged;
|
||
|
||
FSelectedRows := TSelectedRowList.Create(aDataTable);
|
||
aDataTable.OnBeforeApplyUpdates := BeforeApplyUpdates;
|
||
aDataTable.AfterOpen := AfterOpen;
|
||
end;
|
||
|
||
destructor TBizAsientoDataTableRules.Destroy;
|
||
begin
|
||
FCuenta := Nil;
|
||
FSelectedRows.Free;
|
||
inherited;
|
||
end;
|
||
|
||
{procedure TBizAsientoDataTableRules.ShowAll;
|
||
begin
|
||
// ShowEditor(IBizProveedor, Self, etItems);
|
||
end;
|
||
}
|
||
function TBizAsientoDataTableRules.ShowForSelect: TModalResult;
|
||
begin
|
||
Result := ShowEditor(IBizAsiento, Self, etItems);
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.BeforeApplyUpdates(
|
||
Sender: TDADataTable; const Delta: IDADelta);
|
||
var
|
||
i: Integer;
|
||
begin
|
||
for i := 0 to Delta.Count - 1 do
|
||
case Delta.Changes[i].ChangeType of
|
||
ctInsert, ctUpdate : ValidarAsiento(Self);
|
||
// ctDelete :
|
||
end;
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.OnPostError(DataTable: TDADataTable;
|
||
Error: EDatabaseError; var Action: TDataAction);
|
||
begin
|
||
inherited;
|
||
Action := daAbort;
|
||
if (Pos(AUF_HAVEVALUE, Error.Message) > 0) then
|
||
begin
|
||
if (Pos('Nombre', Error.Message) > 0) then
|
||
MessageBox(0, 'Debe indicar una descripci<63>n', 'Atenci<63>n', MB_ICONWARNING or MB_OK)
|
||
else
|
||
raise Error;
|
||
end
|
||
else
|
||
raise Error;
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.BeforeDelete(Sender: TDADataTable);
|
||
begin
|
||
//Si es un CIERRE lo que se elimina, debemos despuntear los asientos que comprende
|
||
if TIPOASIENTO = CTE_CIERRE then
|
||
begin
|
||
puntearAsientos(CTE_NOPUNTEADO);
|
||
dmAsientos.AsignarPunteado(Cuenta.CODIGO, FECHAASIENTO, Cuenta.PENULTIMOCIERRE, CTE_NOPUNTEADO);
|
||
end;
|
||
|
||
inherited;
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.CalcularImportes;
|
||
var
|
||
varImporteAnt: double;
|
||
varImportePos: double;
|
||
ABookmark: Pointer;
|
||
begin
|
||
DataTable.DisableControls;
|
||
DataTable.DisableEventHandlers;
|
||
|
||
try
|
||
ABookmark := DataTable.GetBookMark;
|
||
DataTable.Next;
|
||
//Comprobamos si calculamos desde el principio o desde un asiento intermedio
|
||
if DataTable.EOF
|
||
then
|
||
varImportePos:= FSumaAcumulada
|
||
else
|
||
begin
|
||
varImportePos:= IMPORTEPOS;
|
||
DataTable.Prior;
|
||
end;
|
||
|
||
while not Self.DataTable.BOF do
|
||
begin
|
||
DataTable.edit;
|
||
IMPORTEANT := varImportePos;
|
||
IMPORTEPOS := IMPORTEANT + IMPORTE;
|
||
varImportePos := IMPORTEPOS;
|
||
DataTable.Post;
|
||
DataTable.Prior;
|
||
end;
|
||
finally
|
||
DataTable.GotoBookmark(Abookmark);
|
||
DataTable.FreeBookmark(ABookmark);
|
||
DataTable.EnableControls;
|
||
DataTable.EnableEventHandlers;
|
||
end;
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.AfterPost(Sender: TDADataTable);
|
||
var
|
||
i, x: Integer;
|
||
|
||
begin
|
||
//Comprobamos los cambios para solo recalcular en el caso de modificar el importe
|
||
//y a<>adir un asiento nuevo
|
||
for i:=0 to DataTable.Delta.count-1 do
|
||
if (DataTable.Delta.Changes[i].ChangeType = ctInsert) then
|
||
begin
|
||
//Este evento salta dos veces, cuando se hace el post en el cliente
|
||
//y cuando se hace el applyupdates. En el primer caso todav<61>a no se
|
||
//ha asignado el codigo, de esta forma omitiremos el recalculo y
|
||
//optimizamos el n<>mero de llamadas al mismo
|
||
if CODIGO > 0 then recalcular(False);
|
||
end
|
||
else if (DataTable.Delta.Changes[i].ChangeType = ctUpdate) then
|
||
if (DataTable.Delta.Changes[i].OldValueByName[fld_AsientosIMPORTE] <> DataTable.Delta.Changes[i].NewValueByName[fld_AsientosIMPORTE]) then
|
||
recalcular(False);
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.AfterDelete(Sender: TDADataTable);
|
||
begin
|
||
recalcular(False);
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.AfterOpen(Sender: TDADataTable);
|
||
begin
|
||
recalcular(True);
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.recalcular(const DesdeFinal: Boolean);
|
||
begin
|
||
if DesdeFinal then
|
||
DataTable.Last
|
||
else
|
||
begin
|
||
DataTable.Sort(['FECHAASIENTO', 'CODIGO'],[sdDescending, sdDescending]);
|
||
|
||
//En el caso de ser un CIERRE NUEVO el asiento introducido punteamos "localmente"
|
||
//todos los asientos anteriores al cierre y luego mandamos al servidor puntear en BD
|
||
if TIPOASIENTO = CTE_CIERRE then
|
||
begin
|
||
puntearAsientos(CTE_PUNTEADO);
|
||
dmAsientos.AsignarPunteado(Cuenta.CODIGO, FECHAASIENTO, Cuenta.PENULTIMOCIERRE, CTE_PUNTEADO);
|
||
end;
|
||
end;
|
||
|
||
CalcularImportes;
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.cerrarCaja;
|
||
begin
|
||
with TfrCerrarCaja.Create(NIL) do
|
||
try
|
||
eFechaCierre.Date := FECHAASIENTO;
|
||
ShowModal;
|
||
if ModalResult = mrOk then
|
||
begin
|
||
if anadirCierre(eFechaCierre.Date) then
|
||
begin
|
||
DataTable.ApplyUpdates;
|
||
Cuenta.DataTable.ApplyUpdates;
|
||
end
|
||
else
|
||
begin
|
||
DataTable.CancelUpdates;
|
||
Cuenta.DataTable.CancelUpdates;
|
||
end;
|
||
end;
|
||
finally
|
||
Free;
|
||
end;
|
||
end;
|
||
|
||
function TBizAsientoDataTableRules.anadirCierre(FechaCierre: TDateTime): Boolean;
|
||
begin
|
||
try
|
||
Result:= True;
|
||
//Insertamos un asiento de cierre
|
||
DataTable.Insert;
|
||
FECHAASIENTO := FechaCierre;
|
||
TIPOASIENTO := CTE_CIERRE;
|
||
PUNTEADO := CTE_PUNTEADO;
|
||
DESCRIPCION := 'CIERRE ' + DateToStr(FechaCierre);
|
||
DataTable.Post;
|
||
//Asignamos el nuevo <20>ltimo cierre de la cuenta activa
|
||
Cuenta.DataTable.Edit;
|
||
Cuenta.PENULTIMOCIERRE := Cuenta.ULTIMOCIERRE;
|
||
Cuenta.ULTIMOCIERRE := FechaCierre;
|
||
Cuenta.DataTable.Post;
|
||
except
|
||
on E: Exception do
|
||
Result:= False;
|
||
end;
|
||
end;
|
||
|
||
function TBizAsientoDataTableRules.getCuenta: IBizCuenta;
|
||
begin
|
||
if (not FCuenta.DataTable.Active) then
|
||
FCuenta.DataTable.Active := True;
|
||
|
||
Result := FCuenta;
|
||
end;
|
||
|
||
function TBizAsientoDataTableRules.puntearAsientos(const ValorPunteo: Integer): TDateTime;
|
||
//Punteamos con DisableEventHandlers con el fin de que no se produzcan deltas, ya
|
||
//que la modificaci<63>n de los registros se realizar<61> por un servicio, esto es solo
|
||
//para que los cambios se reflejen en local sin tener que refrescar.
|
||
var
|
||
ABookmark : TBookmark;
|
||
begin
|
||
Self.DataTable.DisableControls;
|
||
Self.DataTable.DisableEventHandlers;
|
||
|
||
try
|
||
//Saltamos el asiento de cierre
|
||
ABookmark := DataTable.GetBookMark;
|
||
DataTable.Next;
|
||
while (not DataTable.EOF)
|
||
and (TIPOASIENTO = CTE_ASIENTO) do
|
||
begin
|
||
DataTable.edit;
|
||
PUNTEADO := ValorPunteo;
|
||
DataTable.Post;
|
||
DataTable.Next;
|
||
end;
|
||
finally
|
||
|
||
//En el caso de salir del bucle por ser final de fichero y no por encontrar otro
|
||
//cierre restamos un d<>a para incluir todos los asientos del final de la tabla
|
||
Result := FECHAASIENTO;
|
||
if (DataTable.EOF) then
|
||
Result:= Result - 1;
|
||
|
||
DataTable.GotoBookmark(ABookmark);
|
||
DataTable.FreeBookmark(ABookmark);
|
||
DataTable.EnableControls;
|
||
DataTable.EnableEventHandlers;
|
||
end;
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.eliminarCierreCaja;
|
||
begin
|
||
if (FECHAASIENTO < Cuenta.ULTIMOCIERRE) then
|
||
raise Exception.Create('No puede eliminar un cierre anterior al <20>ltimo cierre de la cuenta');
|
||
|
||
if eliminarCierre then
|
||
begin
|
||
DataTable.ApplyUpdates;
|
||
Cuenta.DataTable.ApplyUpdates;
|
||
end
|
||
else
|
||
begin
|
||
DataTable.CancelUpdates;
|
||
Cuenta.DataTable.CancelUpdates;
|
||
end;
|
||
end;
|
||
|
||
function TBizAsientoDataTableRules.eliminarCierre: Boolean;
|
||
begin
|
||
try
|
||
Result := True;
|
||
DataTable.Delete;
|
||
|
||
//Asignamos el nuevo <20>ltimo cierre de la cuenta activa
|
||
Cuenta.Edit;
|
||
Cuenta.ULTIMOCIERRE := Cuenta.PENULTIMOCIERRE;
|
||
Cuenta.PENULTIMOCIERRE := dmAsientos.darPenultimoCierre(Cuenta.CODIGO);
|
||
Cuenta.Post;
|
||
except
|
||
on E: Exception do
|
||
Result := False;
|
||
end;
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.refrescarVista;
|
||
var
|
||
fechaini: TDateTime;
|
||
fechaFin: TDateTime;
|
||
i: integer;
|
||
|
||
begin
|
||
if DataTable.Active then
|
||
DataTable.Active := False;
|
||
|
||
if (Intervalo.DIAS = 0) and (Intervalo.MESES = 0) and (Intervalo.ANOS = 0) then
|
||
begin
|
||
fechaIni := MaxDateTime;
|
||
fechaFin := MinDateTime;
|
||
FSumaAcumulada := 0;
|
||
end
|
||
else
|
||
begin
|
||
fechaini := date;
|
||
fechaFin := date;
|
||
fechafin := IncDay(fechafin,(-1)*Intervalo.DIAS);
|
||
for i:=1 to Intervalo.MESES do
|
||
fechafin := IncDay(fechafin,(-1)*DaysInMonth(fechafin));
|
||
for i:=1 to Intervalo.ANOS do
|
||
fechafin := IncDay(fechafin,(-1)*DaysInYear(fechafin));
|
||
|
||
FSumaAcumulada := dmAsientos.darSumaAcumulada(FCuenta.CODIGO, fechafin, MinDateTime);
|
||
end;
|
||
|
||
DataTable.Where.Clear;
|
||
DataTable.Where.OpenBraket;
|
||
DataTable.Where.AddText('ASIENTOS.CODIGOCUENTA' + ' = ' + IntToStr(FCuenta.CODIGO), False);
|
||
DataTable.Where.CloseBraket;
|
||
|
||
DataTable.Where.AddOperator(opAND);
|
||
DataTable.Where.OpenBraket;
|
||
DataTable.Where.AddText('ASIENTOS.FECHAASIENTO between ''' + FormatDateTime('dd.mm.yyyy', FechaFin) + ''' and ''' + FormatDateTime('dd.mm.yyyy', FechaIni) + '''', False);
|
||
DataTable.Where.CloseBraket;
|
||
|
||
DataTable.Active := True;
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.OnIntervaloChanged(Sender: TObject);
|
||
begin
|
||
refrescarVista;
|
||
end;
|
||
|
||
function TBizAsientoDataTableRules.getIntervalo: IBizIntervalos;
|
||
begin
|
||
Result := FIntervalo;
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.setIntervalo(const Value: IBizIntervalos);
|
||
begin
|
||
FIntervalo := Value;
|
||
if Assigned(FIntervalo) then
|
||
begin
|
||
Fintervalo.OnIntervaloChanged := OnIntervaloChanged;
|
||
refrescarVista;
|
||
end;
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.OnCuentaChanged(Sender: TObject);
|
||
begin
|
||
refrescarVista;
|
||
end;
|
||
|
||
procedure TBizAsientoDataTableRules.puntearAsiento;
|
||
begin
|
||
if (FECHAASIENTO <= Cuenta.ULTIMOCIERRE) then
|
||
raise Exception.Create('No puede despuntear un asiento cerrado');
|
||
|
||
try
|
||
DataTable.Edit;
|
||
if PUNTEADO = CTE_PUNTEADO
|
||
then PUNTEADO := CTE_NOPUNTEADO
|
||
else PUNTEADO := CTE_PUNTEADO;
|
||
DataTable.Post;
|
||
DataTable.ApplyUpdates;
|
||
except
|
||
on E: Exception do
|
||
begin
|
||
DataTable.CancelUpdates;
|
||
raise Exception.Create(E.message);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
initialization
|
||
RegisterDataTableRules('BizAsiento', TBizAsientoDataTableRules);
|
||
|
||
finalization
|
||
|
||
end.
|