unit uAsientosController; interface uses Classes, SysUtils, uDADataTable, uControllerBase, uBizAsientos, uBizDiario, uIDataModuleContabilidad; type IAsientosController = interface(IControllerBase) ['{94E5F2B6-64C8-4331-B9CB-3ED730478529}'] function BuscarAsientos(IdSubCuenta: Integer = -1): IBizDiario; function Buscar(const ID: Integer): IBizAsiento; procedure VerDiario(ADiario: IBizDiario); procedure VerExtracto; procedure Ver(AAsiento: IBizAsiento); function Anadir: IBizAsiento; overload; function Anadir(IdSubcuenta:Integer): IBizAsiento; overload; function CerrarCajaBanco(IdSubcuenta:Integer): Boolean; function Eliminar(IDAsiento : Integer): Boolean; overload; function Eliminar(AAsiento : IBizAsiento): Boolean; overload; function Guardar(AAsiento : IBizAsiento): Boolean; procedure DescartarCambios(AAsiento : IBizAsiento); procedure Puntear(ADiario: IBizDiario); function SetBancoPorDefecto(IdEjercicio: Integer; IdSubcuenta:Integer): Boolean; function AnadirApuntesEntrada(AAsiento : IBizAsiento; const ADescripcion: String; const AImporte: Currency): Boolean; function AnadirApuntesSalida(AAsiento : IBizAsiento; const ADescripcion: String; const AImporte: Currency): Boolean; end; TAsientosController = class(TControllerBase, IAsientosController) protected FDataModule : IDataModuleContabilidad; procedure RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable); override; function CreateEditor(const AName : String; const IID: TGUID; out Intf): Boolean; function ValidarAsiento(AAsiento: IBizAsiento): Boolean; procedure AsignarDataModule; procedure FiltrarEjercicio(ADiario: IBizDiario); public constructor Create; override; destructor Destroy; override; function BuscarAsientos(IdSubCuenta: Integer = -1): IBizDiario; function EsModificable(AAsiento : IBizAsiento): Boolean; function EsEliminable(AAsiento : IBizAsiento): Boolean; function Eliminar(IDAsiento : Integer): Boolean; overload; function Eliminar(AAsiento : IBizAsiento): Boolean; overload; function Guardar(AAsiento : IBizAsiento): Boolean; virtual; procedure DescartarCambios(AAsiento : IBizAsiento); virtual; function Anadir: IBizAsiento; overload; function Anadir(IdSubcuenta:Integer): IBizAsiento; overload; function Buscar(const ID: Integer): IBizAsiento; procedure VerDiario(ADiario: IBizDiario); procedure VerExtracto; procedure Ver(AAsiento: IBizAsiento); procedure Puntear(ADiario: IBizDiario); function CerrarCajaBanco(IdSubcuenta:Integer): Boolean; function SetBancoPorDefecto(IdEjercicio: Integer; IdSubcuenta:Integer): Boolean; function AnadirApuntesEntrada(AAsiento : IBizAsiento; const ADescripcion: String; const AImporte: Currency): Boolean; function AnadirApuntesSalida(AAsiento : IBizAsiento; const ADescripcion: String; const AImporte: Currency): Boolean; end; implementation uses cxControls, DB, uEditorRegistryUtils, schContabilidadClient_Intf, uIEditorDiario, uIEditorExtractoMovimientos, uIEditorAsiento, uDataModuleContabilidad, uDAInterfaces, uDataTableUtils, uDialogUtils, uFactuGES_App, uBizEjercicios, uDateUtils, uROTypes, DateUtils, Controls, Windows, uApuntesController, uBizSubCuentas, uSubCuentasController; { TAsientosController } function TAsientosController.Anadir: IBizAsiento; var AAsiento : IBizAsiento; begin AAsiento := FDataModule.GetAsientoItem(ID_NULO); AAsiento.DataTable.Active := True; AAsiento.Insert; Result := AAsiento; end; function TAsientosController.Anadir(IdSubcuenta: Integer): IBizAsiento; begin Result := Anadir; //Creamos el primer apunte del asiento con la cuenta pasada por parametro with TApuntesController.Create do try Anadir(Result.Apuntes, IdSubcuenta); finally Free; end; end; function TAsientosController.AnadirApuntesEntrada(AAsiento : IBizAsiento; const ADescripcion: String; const AImporte: Currency): Boolean; var ASubCuenta : IBizSubCuenta; AController : ISubCuentasController; begin //Validamos los datos a insertar if ((Length(ADescripcion) = 0) or (AImporte = 0)) then raise Exception.Create('Debe introducir una descripción y un importe para poder realizar la entrada o salida.'); if Assigned(AAsiento) then begin if not AAsiento.Apuntes.DataTable.Editing then AAsiento.Apuntes.DataTable.Edit; //La cuenta de destino o origen ya viene rellena por defecto AAsiento.Apuntes.CONCEPTO := ADescripcion; AAsiento.Apuntes.DEBE := AImporte; AAsiento.Apuntes.DataTable.FieldByName(fld_ApuntesHABER).Clear; AAsiento.Apuntes.Post; //Si ya tiene 2 apuntes es una modificación y solo tenemos que editar //si por el contrario solo tiene uno añadimos el apunte de cuadre if (AAsiento.Apuntes.DataTable.RecordCount = 2) then begin AAsiento.Apuntes.DataTable.Next; AAsiento.Apuntes.DataTable.Edit end else AAsiento.Apuntes.Append; try AController := TSubCuentasController.Create; ASubCuenta := AController.BuscarVentas; ASubCuenta.Open; AAsiento.Apuntes.ID_SUBCUENTA := ASubCuenta.ID; AAsiento.Apuntes.REF_SUBCUENTA := ASubCuenta.REF_SUBCUENTA; AAsiento.Apuntes.SUBCUENTA := ASubCuenta.DESCRIPCION; AAsiento.Apuntes.CONCEPTO := ADescripcion; AAsiento.Apuntes.DataTable.FieldByName(fld_ApuntesDEBE).Clear; AAsiento.Apuntes.HABER := AImporte; AAsiento.Apuntes.Post; finally AController := Nil; ASubCuenta := Nil; end; end; end; function TAsientosController.AnadirApuntesSalida(AAsiento: IBizAsiento; const ADescripcion: String; const AImporte: Currency): Boolean; var ASubCuenta : IBizSubCuenta; AController : ISubCuentasController; begin //Validamos los datos a insertar if ((Length(ADescripcion) = 0) or (AImporte = 0)) then raise Exception.Create('Debe introducir una descripción y un importe para poder realizar la entrada o salida.'); if Assigned(AAsiento) then begin if not AAsiento.Apuntes.DataTable.Editing then AAsiento.Apuntes.DataTable.Edit; //La cuenta de destino o origen ya viene rellena por defecto AAsiento.Apuntes.CONCEPTO := ADescripcion; AAsiento.Apuntes.HABER := AImporte; AAsiento.Apuntes.DataTable.FieldByName(fld_ApuntesDEBE).Clear; AAsiento.Apuntes.Post; //Si ya tiene 2 apuntes es una modificación y solo tenemos que editar //si por el contrario solo tiene uno añadimos el apunte de cuadre if (AAsiento.Apuntes.DataTable.RecordCount = 2) then begin AAsiento.Apuntes.DataTable.Next; AAsiento.Apuntes.DataTable.Edit end else AAsiento.Apuntes.Append; try AController := TSubCuentasController.Create; ASubCuenta := AController.BuscarCompras; ASubCuenta.Open; AAsiento.Apuntes.ID_SUBCUENTA := ASubCuenta.ID; AAsiento.Apuntes.REF_SUBCUENTA := ASubCuenta.REF_SUBCUENTA; AAsiento.Apuntes.SUBCUENTA := ASubCuenta.DESCRIPCION; AAsiento.Apuntes.CONCEPTO := ADescripcion; AAsiento.Apuntes.DataTable.FieldByName(fld_ApuntesHABER).Clear; AAsiento.Apuntes.DEBE := AImporte; AAsiento.Apuntes.Post; finally AController := Nil; ASubCuenta := Nil; end; end; end; procedure TAsientosController.AsignarDataModule; begin FDataModule := TDataModuleContabilidad.Create(Nil); end; function TAsientosController.Buscar(const ID: Integer): IBizAsiento; begin Result := FDataModule.GetAsientoItem(ID); end; function TAsientosController.BuscarAsientos(IdSubCuenta: Integer = -1): IBizDiario; var Condicion: TDAWhereExpression; begin // En el caso de no definir cuenta lo que queremos es el diario if (IdSubcuenta < 0) then Result := FDataModule.GetAsientosDiarioItems // En el caso de querer solo los movimientos de una cuenta lo que queremos es un extracto de movimientos else Result := FDataModule.GetExtractoMovimientosItems; //Filtramos por empresa FiltrarEjercicio(Result); // Filtrar los asientos por la subcuenta elegida if (IdSubcuenta > 0) then begin if Result.DataTable.Active then Result.DataTable.Active := False; with Result.DataTable.DynamicWhere do begin // (ID_SUBCUENTA = IdSubcuenta) Condicion := NewBinaryExpression(NewField('', fld_DiarioID_SUBCUENTA), NewConstant(IdSubCuenta, datInteger), dboEqual); if IsEmpty then Expression := Condicion else Expression := NewBinaryExpression(Expression, Condicion, dboAnd); end; end; end; function TAsientosController.CerrarCajaBanco(IdSubcuenta: Integer): Boolean; var AAsiento: IBizAsiento; begin AAsiento:= Anadir(IdSubCuenta); try AAsiento.TIPO := 'X'; //CIERRE DE CAJA AAsiento.Post; //Creamos el primer apunte del asiento con la cuenta pasada por parametro with TApuntesController.Create do try AnadirCierre(AAsiento.Apuntes); finally Free; end; Guardar(AAsiento); FDataModule.PuntearSubCuenta(IdSubcuenta); Result := True; finally AAsiento := Nil; end; end; constructor TAsientosController.Create; begin inherited; AsignarDataModule; end; function TAsientosController.CreateEditor(const AName: String; const IID: TGUID; out Intf): Boolean; begin Result := Supports(EditorRegistry.CreateEditor(AName), IID, Intf); end; procedure TAsientosController.DescartarCambios(AAsiento: IBizAsiento); begin if not Assigned(AAsiento) then raise Exception.Create ('Asiento no asignado'); ShowHourglassCursor; try if (AAsiento.State in dsEditModes) then AAsiento.Cancel; AAsiento.DataTable.CancelUpdates; finally HideHourglassCursor; end; end; destructor TAsientosController.Destroy; begin FDataModule:= NIL; inherited; end; function TAsientosController.Eliminar(IDAsiento: Integer): Boolean; var AAsiento : IBizAsiento; begin AAsiento := Buscar(IDAsiento); AAsiento.DataTable.Active := True; if not Assigned(AAsiento) then raise Exception.Create(Format('No se ha encontrado el asiento con ID = %d', [IDAsiento])); Result := Eliminar(AAsiento); AAsiento := NIL; end; function TAsientosController.ValidarAsiento(AAsiento: IBizAsiento): Boolean; begin Result := False; if not Assigned(AAsiento) then raise Exception.Create ('Asiento no asignado'); if (AAsiento.DataTable.State in dsEditModes) then AAsiento.DataTable.Post; if AAsiento.FECHA_ASIENTOIsNull then raise Exception.Create('Debe indicar una fecha para este Asiento.'); // if AAsiento.ORDENIsNull then // raise Exception.Create('Debe indicar un número de orden para este Asiento.'); //Tambien validamos los detalles del asiento with TApuntesController.Create do begin ValidarApunte(AAsiento.Apuntes); Free; end; // if Length(AAsiento.CONCEPTO) = 0 then // raise Exception.Create('Debe indicar un concepto para este Asiento.'); Result := True; end; procedure TAsientosController.Ver(AAsiento: IBizAsiento); var AEditor : IEditorAsiento; begin AEditor := NIL; CreateEditor('EditorAsiento', IEditorAsiento, AEditor); if Assigned(AEditor) then try AEditor.Controller := Self; //OJO ORDEN MUY IMPORTANTE AEditor.Asiento := AAsiento; //MODO CONSULTAR if not EsModificable(AAsiento) then begin SetDataTableReadOnly(AAsiento.DataTable, True); AEditor.ReadOnly := True; end; AEditor.ShowModal; //MODO CONSULTAR (Se deja la tabla como estaba) if AEditor.ReadOnly then SetDataTableReadOnly(AAsiento.DataTable, False); finally AEditor.Release; AEditor := NIL; end; end; procedure TAsientosController.VerDiario(ADiario: IBizDiario); var AEditor : IEditorDiario; begin AEditor := NIL; CreateEditor('EditorDiario', IEditorDiario, AEditor); if Assigned(AEditor) then with AEditor do begin Controller := Self; //OJO ORDEN MUY IMPORTANTE Diario := ADiario; ShowEmbedded; end; end; procedure TAsientosController.VerExtracto; var AEditor : IEditorExtractoMovimientos; begin AEditor := NIL; CreateEditor('EditorExtractoMovimientos', IEditorExtractoMovimientos, AEditor); if Assigned(AEditor) then with AEditor do begin Controller := Self; //OJO ORDEN MUY IMPORTANTE //En este caso el objeto de negocio recae sobre la vista ShowEmbedded; end; end; function TAsientosController.Eliminar(AAsiento: IBizAsiento): Boolean; begin if not Assigned(AAsiento) then raise Exception.Create ('Asiento no asignado'); ShowHourglassCursor; try if (AAsiento.State in dsEditModes) then AAsiento.Cancel; //Siempre eliminaremos el seleccionado if EsEliminable(AAsiento) then begin AAsiento.Delete; AAsiento.DataTable.ApplyUpdates; end; HideHourglassCursor; Result := True; finally HideHourglassCursor; end; end; function TAsientosController.EsEliminable(AAsiento: IBizAsiento): Boolean; begin Result := True; end; function TAsientosController.EsModificable(AAsiento: IBizAsiento): Boolean; begin Result := True; end; procedure TAsientosController.FiltrarEjercicio(ADiario: IBizDiario); var Condicion: TDAWhereExpression; begin if ADiario.DataTable.Active then ADiario.DataTable.Active := False; if not Assigned(AppFactuGES.EjercicioActivo) then raise Exception.Create('No se ha definido ningún ejercicio activo'); // Filtrar los asientos por la empresa activa with ADiario.DataTable.DynamicWhere do begin // (ID_EJERCICIO = ID) Condicion := NewBinaryExpression(NewField('', fld_DiarioID_EJERCICIO), NewConstant(AppFactuGES.EjercicioActivo.ID, datInteger), dboEqual); if IsEmpty then Expression := Condicion else Expression := NewBinaryExpression(Expression, Condicion, dboAnd); end; end; procedure TAsientosController.RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable); begin inherited; // end; function TAsientosController.SetBancoPorDefecto(IdEjercicio, IdSubcuenta: Integer): Boolean; begin FDataModule.SetBancoPorDefecto(IdEjercicio, IdSubcuenta); end; function TAsientosController.Guardar(AAsiento: IBizAsiento): Boolean; begin Result := False; if not Assigned(AAsiento) then raise Exception.Create ('Factura no asignada'); if ValidarAsiento(AAsiento) then begin ShowHourglassCursor; // Asegurarnos de que todos los importes están bien. // RecalcularImportes(AFactura); try AAsiento.DataTable.ApplyUpdates; Result := True; finally HideHourglassCursor; end; end; end; procedure TAsientosController.Puntear(ADiario: IBizDiario); //Este procedimiento se encargará de mandar al servidor que se puntee el asiento seleccionado y //puntear en el objeto ADiario los elementos del asiento seleccionado para no tener que refrescar la tabla. var ABookmark: Pointer; IdAsiento: Integer; begin if Assigned(ADiario) then begin ShowHourglassCursor; try //Mandamos al servidor modificar todos los apuntes del asiento a punteados IdAsiento := ADiario.ID_ASIENTO; FDataModule.PuntearAsiento(IdAsiento); ABookmark := NIL; with ADiario.DataTable do begin DisableControls; DisableEventHandlers; try ABookmark := GetBookMark; First; Locate(fld_DiarioID_ASIENTO, IdAsiento, []); while (not EOF) and (ADiario.ID_ASIENTO = IdAsiento) do begin Edit; ADiario.PUNTEADO := -1 * ADiario.PUNTEADO; Post; Next; end; finally GotoBookmark(Abookmark); FreeBookmark(ABookmark); EnableControls; EnableEventHandlers; end; end; finally HideHourglassCursor; end; end; end; end.