unit uFacturasClienteController; interface uses Classes, SysUtils, uDADataTable, uControllerBase, uIDataModuleFacturasCliente, uClientesController, uDetallesFacturaClienteController, uBizFacturasCliente; type IFacturasClienteController = interface(IObservador) ['{CAD20B4E-6D0B-4A1C-9306-B195824B6CAD}'] function GetClienteController: IClientesController; procedure SetClienteController(const Value: IClientesController); property ClienteController: IClientesController read GetClienteController write SetClienteController; function GetDetallesController: IDetallesFacturaClienteController; procedure SetDetallesController(const Value: IDetallesFacturaClienteController); property DetallesController: IDetallesFacturaClienteController read GetDetallesController write SetDetallesController; function Buscar(const ID: Integer): IBizFacturaCliente; function BuscarTodos: IBizFacturaCliente; procedure Ver(AFactura : IBizFacturaCliente); procedure VerTodos(AFacturas: IBizFacturaCliente); function Nuevo : IBizFacturaCliente; procedure Anadir(AFactura : IBizFacturaCliente); procedure Eliminar(const ID : Integer); overload; procedure Eliminar(AFactura : IBizFacturaCliente); overload; procedure Guardar(AFactura : IBizFacturaCliente); procedure DescartarCambios(AFactura : IBizFacturaCliente); function Existe(const ID: Integer) : Boolean; procedure RecuperarCliente(AFactura : IBizFacturaCliente); function Duplicar(AFactura: IBizFacturaCliente): IBizFacturaCliente; function CambiarSituacion(AFactura: IBizFacturaCliente; ASituacion : String; AFechaPagado: TDateTime = 0; DoPost : Boolean = True): Boolean; overload; function CambiarSituacion(AFactura: IBizFacturaCliente): Boolean; overload; procedure Preview(AFactura : IBizFacturaCliente); procedure Print(AFactura : IBizFacturaCliente); // function DarListaSituaciones: TStringList; end; TFacturasClienteController = class(TObservador, IFacturasClienteController) private FDataModule : IDataModuleFacturasCliente; FClienteController : IClientesController; FDetallesController : IDetallesFacturaClienteController; function GetClienteController: IClientesController; procedure SetClienteController(const Value: IClientesController); function GetDetallesController: IDetallesFacturaClienteController; procedure SetDetallesController(const Value: IDetallesFacturaClienteController); procedure RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable); override; procedure AsignarID(AFactura: IBizFacturaCliente; const NuevoID:Integer); function CreateEditor(const AName : String; const IID: TGUID; out Intf): Boolean; function _Vacio : IBizFacturaCliente; procedure FiltrarEmpresa(AFactura: IBizFacturaCliente); function ValidarFactura(AFactura: IBizFacturaCliente): Boolean; function ValidarSituacion(ASituacion: String; AFechaFactura: TDateTime; var AFechaPagado: TDateTime): Boolean; public property ClienteController: IClientesController read GetClienteController write SetClienteController; property DetallesController: IDetallesFacturaClienteController read GetDetallesController write SetDetallesController; constructor Create; destructor Destroy; override; procedure Eliminar(const ID : Integer); overload; procedure Eliminar(AFactura : IBizFacturaCliente); overload; procedure Guardar(AFactura : IBizFacturaCliente); procedure DescartarCambios(AFactura : IBizFacturaCliente); virtual; function Existe(const ID: Integer) : Boolean; virtual; procedure Anadir(AFactura : IBizFacturaCliente); function Buscar(const ID: Integer): IBizFacturaCliente; function BuscarTodos: IBizFacturaCliente; function Nuevo : IBizFacturaCliente; procedure Ver(AFactura : IBizFacturaCliente); procedure VerTodos(AFacturas: IBizFacturaCliente); function Duplicar(AFactura: IBizFacturaCliente): IBizFacturaCliente; function CambiarSituacion(AFactura: IBizFacturaCliente; ASituacion : String; AFechaPagado: TDateTime = 0; DoPost : Boolean = True): Boolean; overload; function CambiarSituacion(AFactura: IBizFacturaCliente): Boolean; overload; procedure RecuperarCliente(AFactura : IBizFacturaCliente); procedure Preview(AFactura : IBizFacturaCliente); procedure Print(AFactura : IBizFacturaCliente); function DarListaSituaciones: TStringList; end; implementation uses cxControls, DB, uEditorRegistryUtils, schFacturasClienteClient_Intf, uBizContactos, uIEditorFacturasCliente, uIEditorFacturaCliente, uDataModuleFacturasCliente, uBizDetallesFacturaCliente, uDataModuleUsuarios, uDAInterfaces, uDataTableUtils, uDateUtils, uIEditorSituacionFacturaCliente, uROTypes, uFacturasClienteReportController, DateUtils; { TFacturasClienteController } procedure TFacturasClienteController.Anadir(AFactura: IBizFacturaCliente); begin AFactura.Insert; AFactura.Cliente := (FClienteController.Nuevo as IBizCliente); end; procedure TFacturasClienteController.AsignarID(AFactura: IBizFacturaCliente; const NuevoID:Integer); begin if not Assigned(AFactura) then raise Exception.Create ('Factura no asignada'); if not Assigned(FDetallesController) then raise Exception.Create ('Controller detalles no asignado'); { ¡¡¡ OJO !!! Primero cambiamos el ID de las tablas detalles porque si cambiamos antes el ID de la cabecera deja de funcionar la relacion M/D y no encontraríamos las filas detalle. --> MASTER.ID = DETAIL.ID_FACTURA <-- } FDetallesController.AsignarID(AFactura.Detalles, NuevoID, AFactura.EsNuevo); if AFactura.EsNuevo then begin AFactura.Edit; AFactura.ID := NuevoID; AFactura.Post; end; end; function TFacturasClienteController.Buscar(const ID: Integer): IBizFacturaCliente; begin Result := (FDataModule as IDataModuleFacturasCliente).GetItem(ID); FiltrarEmpresa(Result); end; function TFacturasClienteController.BuscarTodos: IBizFacturaCliente; begin Result := FDataModule.GetItems; FiltrarEmpresa(Result); end; function TFacturasClienteController.CambiarSituacion( AFactura: IBizFacturaCliente): Boolean; var AEditor : IEditorSituacionFacturaCliente; begin AEditor := NIL; ShowHourglassCursor; try RecuperarCliente(AFactura); CreateEditor('EditorSituacionFacturaCliente', IEditorSituacionFacturaCliente, AEditor); with AEditor do begin Controller := Self; //OJO ORDEN MUY IMPORTANTE FacturaCliente := AFactura; end; finally HideHourglassCursor; end; if Assigned(AEditor) then AEditor.ShowModal; end; function TFacturasClienteController.CambiarSituacion( AFactura: IBizFacturaCliente; ASituacion : String; AFechaPagado: TDateTime; DoPost : Boolean): Boolean; begin Result := False; // Validar la situación de la factura if ValidarSituacion(ASituacion, AFactura.FECHA_FACTURA, AFechaPagado) then begin ShowHourglassCursor; AFactura.DataTable.DisableControls; try AFactura.Edit; AFactura.SITUACION := ASituacion; if AFechaPagado <> AFactura.FECHA_PAGADO then AFactura.FECHA_PAGADO := AFechaPagado; AFactura.Post; if DoPost then Guardar(AFactura); Result := True; finally AFactura.DataTable.EnableControls; HideHourglassCursor; end; end; end; constructor TFacturasClienteController.Create; begin FDataModule := TDataModuleFacturasCliente.Create(Nil); FClienteController := TClientesController.Create; FDetallesController := TDetallesFacturaClienteController.Create; FDetallesController.addObservador(Self); end; function TFacturasClienteController.CreateEditor(const AName: String; const IID: TGUID; out Intf): Boolean; begin Result := Supports(EditorRegistry.CreateEditor(AName), IID, Intf); end; function TFacturasClienteController.DarListaSituaciones: TStringList; begin Result := TStringList.Create; with Result do begin Add(SITUACION_PENDIENTE); Add(SITUACION_PAGADO); end; end; procedure TFacturasClienteController.DescartarCambios(AFactura: IBizFacturaCliente); begin if not Assigned(AFactura) then raise Exception.Create ('Factura no asignada'); ShowHourglassCursor; try if (AFactura.State in dsEditModes) then AFactura.Cancel; AFactura.DataTable.CancelUpdates; finally HideHourglassCursor; end; end; destructor TFacturasClienteController.Destroy; begin FDataModule := Nil; FClienteController := Nil; FDetallesController := Nil; inherited; end; function TFacturasClienteController.Duplicar( AFactura: IBizFacturaCliente): IBizFacturaCliente; begin Result := Self._Vacio; ShowHourglassCursor; try DuplicarRegistros(AFactura.DataTable, Result.DataTable, mdrActual); DuplicarRegistros(AFactura.Detalles.DataTable, Result.Detalles.DataTable, mdrTodos); // Hay que dejar algunos campos como si fuera una factura nueva Result.Edit; with Result do begin ID_EMPRESA := dmUsuarios.IDEmpresaActual; USUARIO := dmUsuarios.LoginInfo.Usuario; REFERENCIA := ''; //Para que se asigne una nueva FECHA_FACTURA := DateOf(Now); SITUACION := SITUACION_PENDIENTE; end; Result.Post; finally HideHourglassCursor; end; end; function TFacturasClienteController.ValidarFactura(AFactura: IBizFacturaCliente): Boolean; var AFechaPagado : TDateTime; begin Result := False; if not Assigned(AFactura) then raise Exception.Create ('Factura no asignada'); if not Assigned(FDetallesController) then raise Exception.Create ('Controller detalles no asignado'); if (AFactura.DataTable.State in dsEditModes) then AFactura.DataTable.Post; //Tambien hacemos post de sus tablas hija if (AFactura.Detalles.DataTable.State in dsEditModes) then AFactura.Detalles.DataTable.Post; //VALIDACION if (AFactura.ID_CLIENTE < 0) or (not Assigned(AFactura.Cliente)) or (AFactura.Cliente.IsEmpty) then raise Exception.Create('Debe indicar el cliente de esta factura'); if (EsFechaVacia(AFactura.FECHA_FACTURA)) then raise Exception.Create('Debe indicar la fecha de esta factura'); // Validar la situación del presupuesto AFechaPagado := AFactura.FECHA_PAGADO; if not ValidarSituacion(AFactura.SITUACION, AFactura.FECHA_FACTURA, AFechaPagado) then Exit; // Asegurarse de valores en campos "automáticos" AFactura.Edit; try if AFechaPagado <> AFactura.FECHA_PAGADO then AFactura.FECHA_PAGADO := AFechaPagado; AFactura.USUARIO := dmUsuarios.LoginInfo.Usuario; if Assigned(AFactura.Cliente) then AFactura.ID_CLIENTE := AFactura.Cliente.ID; Result := True; finally AFactura.Post; end; end; function TFacturasClienteController.ValidarSituacion(ASituacion: String; AFechaFactura: TDateTime; var AFechaPagado: TDateTime): Boolean; begin Result := False; if ASituacion = SITUACION_PENDIENTE then AFechaPagado := 0 else begin if (EsFechaVacia(AFechaPagado)) then raise Exception.Create('Hay que indicar una fecha de pago') else if (AFechaPagado < AFechaFactura) then raise Exception.Create('La fecha de pago debe ser posterior a la fecha de la factura'); end; Result := True; end; procedure TFacturasClienteController.Ver(AFactura: IBizFacturaCliente); var AEditor : IEditorFacturaCliente; begin AEditor := NIL; ShowHourglassCursor; try RecuperarCliente(AFactura); CreateEditor('EditorFacturaCliente', IEditorFacturaCliente, AEditor); with AEditor do begin Controller := Self; //OJO ORDEN MUY IMPORTANTE Factura := AFactura; end; finally HideHourglassCursor; end; if Assigned(AEditor) then AEditor.ShowModal; end; procedure TFacturasClienteController.VerTodos(AFacturas: IBizFacturaCliente); var AEditor : IEditorFacturasCliente; begin AEditor := NIL; ShowHourglassCursor; try CreateEditor('EditorFacturasCliente', IEditorFacturasCliente, AEditor); with AEditor do begin Controller := Self; //OJO ORDEN MUY IMPORTANTE Facturas := AFacturas; end; finally HideHourglassCursor; end; if Assigned(AEditor) then AEditor.ShowEmbedded; end; function TFacturasClienteController._Vacio: IBizFacturaCliente; begin Result := Buscar(ID_NULO); end; procedure TFacturasClienteController.Eliminar(const ID: Integer); var AFactura : IBizFacturaCliente; begin AFactura := Buscar(ID); if not Assigned(AFactura) then raise Exception.Create(Format('No se ha encontrado la factura con ID = %d', [ID])); Eliminar(AFactura); AFactura := NIL; end; procedure TFacturasClienteController.Eliminar(AFactura: IBizFacturaCliente); begin if not Assigned(AFactura) then raise Exception.Create ('Factura no asignada'); ShowHourglassCursor; try if (AFactura.State in dsEditModes) then AFactura.Cancel; AFactura.Delete; AFactura.DataTable.ApplyUpdates; finally HideHourglassCursor; end; end; procedure TFacturasClienteController.RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable); var AFactura : IBizFacturaCliente; ADetalles : IBizDetallesFacturaCliente; begin inherited; if Supports(ADataTable, IBizDetallesFacturaCliente, ADetalles) and Supports(ADetalles.DataTable.MasterSource.DataTable, IBizFacturaCliente, AFactura) then begin AFactura.Edit; try AFactura.BASE_IMPONIBLE := FDetallesController.DarTotalImporteTotal(ADetalles); finally AFactura.Post; end; end; end; procedure TFacturasClienteController.RecuperarCliente( AFactura: IBizFacturaCliente); begin AFactura.Cliente := (FClienteController.Buscar(AFactura.ID_CLIENTE) as IBizCliente); end; function TFacturasClienteController.Existe(const ID: Integer): Boolean; var AFactura : IBizFacturaCliente; begin try AFactura := Buscar(ID); Result := Assigned(AFactura) and (AFactura.ID = ID); finally AFactura := NIL; end; end; procedure TFacturasClienteController.FiltrarEmpresa(AFactura: IBizFacturaCliente); begin if AFactura.DataTable.Active then AFactura.DataTable.Active := False; // Filtrar las facturas actuales por empresa with AFactura.DataTable.Where do begin if NotEmpty then AddOperator(opAND); AddCondition(fld_FacturasClienteID_EMPRESA, cEqual, dmUsuarios.IDEmpresaActual); end; end; procedure TFacturasClienteController.SetClienteController(const Value: IClientesController); begin FClienteController := Value; end; procedure TFacturasClienteController.SetDetallesController(const Value: IDetallesFacturaClienteController); begin FDetallesController := Value; end; procedure TFacturasClienteController.Guardar(AFactura: IBizFacturaCliente); var NuevoID: Integer; begin if ValidarFactura(AFactura) then begin ShowHourglassCursor; try if AFactura.EsNuevo then NuevoID := FDataModule.GetNextID(AFactura.DataTable.LogicalName) else NuevoID := AFactura.ID; AsignarID(AFactura, NuevoID); AFactura.DataTable.ApplyUpdates; finally HideHourglassCursor; end; end; end; function TFacturasClienteController.Nuevo: IBizFacturaCliente; var AFactura : IBizFacturaCliente; begin AFactura := FDataModule.NewItem; FiltrarEmpresa(AFactura); AFactura.DataTable.Active := True; AFactura.Insert; AFactura.Cliente := (FClienteController.Nuevo as IBizCliente); Result := AFactura; end; procedure TFacturasClienteController.Preview(AFactura: IBizFacturaCliente); var AReportController : IFacturasClienteReportController; begin AReportController := TFacturasClienteReportController.Create; try AReportController.Preview(AFactura.ID); finally AReportController := NIL; end; end; procedure TFacturasClienteController.Print(AFactura: IBizFacturaCliente); var AReportController : IFacturasClienteReportController; begin AReportController := TFacturasClienteReportController.Create; try AReportController.Print(AFactura.ID); finally AReportController := NIL; end; end; function TFacturasClienteController.GetClienteController: IClientesController; begin Result := FClienteController; end; function TFacturasClienteController.GetDetallesController: IDetallesFacturaClienteController; begin Result := FDetallesController; end; end.