This repository has been archived on 2024-12-02. You can view files and clone it, but cannot push or open issues or pull requests.
AlonsoYSal_FactuGES/Modulos/Asientos/Reglas/uBizAsientos.pas
2007-06-21 16:02:50 +00:00

543 lines
15 KiB
ObjectPascal
Raw Blame History

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.