unit uPedidosClienteController; interface uses SysUtils, uDADataTable, uEditorDBItem, uControllerBase, uIDataModulePedidosCliente, uClientesController, uDetallesPedidoClienteController, uBizPedidosCliente, uBizDireccionesContacto, uBizDetallesPedidoCliente; type IPedidosClienteController = interface(IObservador) ['{21ED0332-F0E0-468D-8D53-8CA362757191}'] function GetClienteController: IClientesController; procedure SetClienteController(const Value: IClientesController); property ClienteController: IClientesController read GetClienteController write SetClienteController; function GetDetallesController: IDetallesPedidoClienteController; procedure SetDetallesController(const Value: IDetallesPedidoClienteController); property DetallesController: IDetallesPedidoClienteController read GetDetallesController write SetDetallesController; procedure RecuperarCliente(APedido : IBizPedidoCliente); function Buscar(const ID: Integer): IBizPedidoCliente; function BuscarTodos: IBizPedidoCliente; function BuscarPendientes : IBizPedidoCliente; function BuscarPendientesPedir(const ID : Integer): IBizPedidoClienteArticulosPendientesPedirAProv; procedure Ver(APedido : IBizPedidoCliente); procedure VerTodos(APedidos: IBizPedidoCliente); procedure VerDireccionEntrega(APedido : IBizPedidoCliente); function Nuevo : IBizPedidoCliente; function Anadir(APedido : IBizPedidoCliente) : Boolean; function Eliminar(const ID : Integer): Boolean; overload; function Eliminar(APedido : IBizPedidoCliente): Boolean; overload; function Guardar(APedido : IBizPedidoCliente): Boolean; procedure DescartarCambios(APedido : IBizPedidoCliente); function Existe(const ID: Integer) : Boolean; function Duplicar(APedido: IBizPedidoCliente): IBizPedidoCliente; function Localizar(APedidos: IBizPedidoCliente; const ID : Integer): Boolean; function ExtraerSeleccionados(APedido: IBizPedidoCliente) : IBizPedidoCliente; function ElegirPedidos(APedido: IBizPedidoCliente; AMensaje: String; AMultiSelect: Boolean): IBizPedidoCliente; procedure CopiarDireccionEnvio (const ADireccionEnvio: IBizDireccionesContacto; APedido: IBizPedidoCliente); procedure QuitarDireccionEnvio(APedido: IBizPedidoCliente); procedure RecalcularImportes(APedido : IBizPedidoCliente); procedure Preview(APedido : IBizPedidoCliente); procedure Print(APedido : IBizPedidoCliente); function ArticulosPendientes(const ID : Integer): IBizPedidoClienteArticulosPend; end; TPedidosClienteController = class(TObservador, IPedidosClienteController) protected FDataModule : IDataModulePedidosCliente; FClienteController : IClientesController; FDetallesController : IDetallesPedidoClienteController; function GetClienteController: IClientesController; procedure SetClienteController(const Value: IClientesController); function GetDetallesController: IDetallesPedidoClienteController; procedure SetDetallesController(const Value: IDetallesPedidoClienteController); //Estos son los tres métodos a sobre escribir si se desea heredar toda la logica de //este controller procedure AsignarDataModule; virtual; procedure RecuperarObjetos(APedido: IBizPedidoCliente); virtual; procedure AsignarEditor(out AEditor: IEditorDBItem); virtual; procedure RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable); override; procedure AsignarID(APedido: IBizPedidoCliente; const IDNuevo : Integer); function CreateEditor(const AName : String; const IID: TGUID; out Intf): Boolean; procedure FiltrarEmpresa(APedido: IBizPedidoCliente); function _Vacio : IBizPedidoCliente; function ValidarPedido(APedido: IBizPedidoCliente): Boolean; public property ClienteController: IClientesController read GetClienteController write SetClienteController; property DetallesController: IDetallesPedidoClienteController read GetDetallesController write SetDetallesController; constructor Create; virtual; destructor Destroy; override; function Localizar(APedidos: IBizPedidoCliente; const ID : Integer): Boolean; procedure RecuperarCliente(APedido : IBizPedidoCliente); function Eliminar(const ID : Integer): Boolean; overload; function Eliminar(APedido : IBizPedidoCliente): Boolean; overload; function Guardar(APedido : IBizPedidoCliente): Boolean; procedure DescartarCambios(APedido : IBizPedidoCliente); virtual; function Existe(const ID: Integer) : Boolean; virtual; function Anadir(APedido : IBizPedidoCliente) : Boolean; function Buscar(const ID: Integer): IBizPedidoCliente; function BuscarTodos: IBizPedidoCliente; function BuscarPendientes : IBizPedidoCliente; function BuscarPendientesPedir(const ID : Integer): IBizPedidoClienteArticulosPendientesPedirAProv; function Nuevo : IBizPedidoCliente; procedure Ver(APedido : IBizPedidoCliente); procedure VerTodos(APedidos: IBizPedidoCliente); procedure VerDireccionEntrega(APedido : IBizPedidoCliente); function Duplicar(APedido: IBizPedidoCliente): IBizPedidoCliente; procedure CopiarDireccionEnvio (const ADireccionEnvio: IBizDireccionesContacto; APedido: IBizPedidoCliente); procedure QuitarDireccionEnvio(APedido: IBizPedidoCliente); function ExtraerSeleccionados(APedido: IBizPedidoCliente) : IBizPedidoCliente; function ElegirPedidos(APedido: IBizPedidoCliente; AMensaje: String; AMultiSelect: Boolean): IBizPedidoCliente; procedure RecalcularImportes(APedido : IBizPedidoCliente); procedure Preview(APedido : IBizPedidoCliente); procedure Print(APedido : IBizPedidoCliente); function ArticulosPendientes(const ID : Integer): IBizPedidoClienteArticulosPend; end; implementation uses uROTypes, Controls, cxControls, DB, uEditorRegistryUtils, uEditorPreview, DateUtils, uIEditorPedidosCliente, uDataModulePedidosCliente, Variants, uBizContactos, uDataTableUtils, uDataModuleUsuarios, schPedidosClienteClient_Intf, uDAInterfaces, uDateUtils, uIEditorPedidoCliente, uIEditorElegirPedidosCliente, uIEditorDireccionEntregaPedidoCliente, schContactosClient_Intf, uPedidosClienteReportController; { TPedidosClienteController } function TPedidosClienteController.Anadir(APedido: IBizPedidoCliente): Boolean; begin if not Assigned(APedido) then raise Exception.Create ('Pedido no asignado (Anadir)'); APedido.Insert; Result := True; end; function TPedidosClienteController.ArticulosPendientes( const ID: Integer): IBizPedidoClienteArticulosPend; begin Result := FDataModule.GetArticulosPendientes(ID); end; procedure TPedidosClienteController.AsignarDataModule; begin FDataModule := TDataModulePedidosCliente.Create(Nil); end; procedure TPedidosClienteController.AsignarEditor(out AEditor: IEditorDBItem); begin CreateEditor('EditorPedidoCliente', IEditorPedidoCliente, AEditor); end; procedure TPedidosClienteController.AsignarID(APedido: IBizPedidoCliente; const IDNuevo : Integer); begin if not Assigned(APedido) then raise Exception.Create ('Pedido no asignado'); if not Assigned(APedido.Detalles) then raise Exception.Create ('Detalles de pedido no asignados'); if not Assigned(FDetallesController) then raise Exception.Create ('Controller detalles no asignado'); { Los detalles siempre hay que comprobarlos } FDetallesController.AsignarID(APedido.Detalles, IDNuevo, APedido.EsNuevo); if APedido.EsNuevo then begin APedido.Edit; APedido.ID := IDNuevo; APedido.Post; end; end; function TPedidosClienteController.Buscar(const ID: Integer): IBizPedidoCliente; begin Result := FDataModule.GetItem(ID); FiltrarEmpresa(Result); end; function TPedidosClienteController.BuscarTodos: IBizPedidoCliente; begin Result := FDataModule.GetItems; FiltrarEmpresa(Result); end; function TPedidosClienteController.BuscarPendientes: IBizPedidoCliente; begin ShowHourglassCursor; try Result := BuscarTodos; with Result.DataTable.Where do begin if NotEmpty then AddOperator(opAND); OpenBraket; AddText(fld_PedidosClienteSITUACION + ' <> ''' + SITUACION_PEDIDO_SERVIDO + ''''); CloseBraket; end; finally HideHourglassCursor; end; end; function TPedidosClienteController.BuscarPendientesPedir( const ID: Integer): IBizPedidoClienteArticulosPendientesPedirAProv; begin ShowHourglassCursor; try Result := FDataModule.GetArticulosPendientesPedirAProv(ID); finally HideHourglassCursor; end; end; procedure TPedidosClienteController.CopiarDireccionEnvio( const ADireccionEnvio: IBizDireccionesContacto; APedido: IBizPedidoCliente); var bEnEdicion : Boolean; begin if not Assigned(APedido) then raise Exception.Create ('Pedido no asignado (CopiarDireccionEnvio)'); if not Assigned(ADireccionEnvio) then raise Exception.Create ('No se ha indicado la dirección (CopiarDireccionEnvio)'); if APedido.DataTable.Active then APedido.DataTable.Active := True; if ADireccionEnvio.DataTable.Active then ADireccionEnvio.DataTable.Active := True; bEnEdicion := (APedido.DataTable.State in dsEditModes); if not bEnEdicion then APedido.Edit; ShowHourglassCursor; APedido.Edit; try APedido.CALLE := ADireccionEnvio.CALLE; APedido.POBLACION := ADireccionEnvio.POBLACION; APedido.CODIGO_POSTAL := ADireccionEnvio.CODIGO_POSTAL; APedido.PROVINCIA := ADireccionEnvio.PROVINCIA; APedido.TELEFONO := ADireccionEnvio.TELEFONO; APedido.PERSONA_CONTACTO := ADireccionEnvio.PERSONA_CONTACTO; if not bEnEdicion then APedido.Post; finally HideHourglassCursor; end; end; constructor TPedidosClienteController.Create; begin AsignarDataModule; FClienteController := TClientesController.Create; FDetallesController := TDetallesPedidoClienteController.Create; FDetallesController.addObservador(Self); end; function TPedidosClienteController.CreateEditor(const AName: String; const IID: TGUID; out Intf): Boolean; begin Result := Supports(EditorRegistry.CreateEditor(AName), IID, Intf); end; procedure TPedidosClienteController.DescartarCambios(APedido: IBizPedidoCliente); begin if not Assigned(APedido) then raise Exception.Create ('Pedido no asignada'); ShowHourglassCursor; try if (APedido.State in dsEditModes) then APedido.Cancel; APedido.DataTable.CancelUpdates; finally HideHourglassCursor; end; end; destructor TPedidosClienteController.Destroy; begin FDataModule := Nil; FClienteController := Nil; FDetallesController := Nil; inherited; end; function TPedidosClienteController.Duplicar( APedido: IBizPedidoCliente): IBizPedidoCliente; begin Result := Self._Vacio; ShowHourglassCursor; try DuplicarRegistros(APedido.DataTable, Result.DataTable, mdrActual); DuplicarRegistros(APedido.Detalles.DataTable, Result.Detalles.DataTable, mdrTodos); // Hay que dejar algunos campos como si fuera un presupuesto nuevo Result.Edit; with Result do begin ID_EMPRESA := dmUsuarios.IDEmpresaActual; USUARIO := dmUsuarios.LoginInfo.Usuario; FECHA_PEDIDO := DateOf(Now); FECHA_PREVISTA_ENVIO := 0; INCIDENCIAS_ACTIVAS := 0; INCIDENCIAS := Nil; REFERENCIA := ''; SetFieldNull(DataTable, fld_PedidosClienteREF_TIENDA_WEB); end; Result.Post; finally HideHourglassCursor; end; end; function TPedidosClienteController.ValidarPedido( APedido: IBizPedidoCliente): Boolean; begin Result := False; if not Assigned(APedido) then raise Exception.Create ('Pedido no asignado'); if (APedido.DataTable.State in dsEditModes) then APedido.DataTable.Post; //Tambien hacemos post de sus tablas hija if (APedido.Detalles.DataTable.State in dsEditModes) then APedido.Detalles.DataTable.Post; // Abrir el cliente para la validación if Assigned(APedido.Cliente) then APedido.Cliente.DataTable.Active := True; if (APedido.ID_Cliente < 0) or (not Assigned(APedido.Cliente)) or (APedido.Cliente.IsEmpty) then raise Exception.Create('Debe indicar el cliente de este pedido'); if (EsFechaVacia(APedido.FECHA_PEDIDO)) then raise Exception.Create('Debe indicar la fecha de este pedido'); if (not EsFechaVacia(APedido.FECHA_PREVISTA_ENVIO)) then begin if (APedido.FECHA_PREVISTA_ENVIO < APedido.FECHA_PEDIDO) then raise Exception.Create('La fecha prevista de envío no puede ser anterior a la fecha del pedido'); end; if (APedido.Detalles.DataTable.RecordCount = 0) then raise Exception.Create('El pedido debe tener en su contenido al menos un concepto'); { Asegurarse de valores en campos "automáticos" tanto en MODIFICACIÓN como en INSERCIÓN. } APedido.Edit; try APedido.USUARIO := dmUsuarios.LoginInfo.Usuario; if Assigned(APedido.Cliente) and (APedido.ID_CLIENTE <> APedido.Cliente.ID) then APedido.ID_CLIENTE := APedido.Cliente.ID; Result := True; finally APedido.Post; end; end; procedure TPedidosClienteController.Ver(APedido: IBizPedidoCliente); var AEditor : IEditorDBItem; begin AEditor := NIL; ShowHourglassCursor; try RecuperarObjetos(APedido); AsignarEditor(AEditor); with (AEditor as IEditorPedidoCliente) do begin Controller := Self; //OJO ORDEN MUY IMPORTANTE Pedido := APedido; end; finally HideHourglassCursor; end; if Assigned(AEditor) then try AEditor.ShowModal; AEditor.Release; finally AEditor := NIL; end; end; procedure TPedidosClienteController.VerDireccionEntrega( APedido: IBizPedidoCliente); var AEditor : IEditorDireccionEntregaPedidoCliente; begin AEditor := NIL; ShowHourglassCursor; try //RecuperarObjetos(APedido); <- No descomentar. No hace falta CreateEditor('EditorDireccionEntregaPedidoCliente', IEditorDireccionEntregaPedidoCliente, AEditor); with (AEditor as IEditorDireccionEntregaPedidoCliente) do begin Pedido := APedido; end; finally HideHourglassCursor; end; if Assigned(AEditor) then try AEditor.ShowModal; AEditor.Release; finally AEditor := NIL; end; end; procedure TPedidosClienteController.VerTodos(APedidos: IBizPedidoCliente); var AEditor : IEditorPedidosCliente; begin AEditor := NIL; ShowHourglassCursor; try CreateEditor('EditorPedidosCliente', IEditorPedidosCliente, AEditor); with AEditor do begin Controller := Self; //OJO ORDEN MUY IMPORTANTE Pedidos := APedidos; end; finally HideHourglassCursor; end; if Assigned(AEditor) then try AEditor.ShowEmbedded; finally AEditor := NIL; end; end; function TPedidosClienteController._Vacio: IBizPedidoCliente; begin Result := Buscar(ID_NULO); end; function TPedidosClienteController.Eliminar(const ID: Integer): Boolean; var APedido : IBizPedidoCliente; begin APedido := Buscar(ID); if not Assigned(APedido) then raise Exception.Create(Format('No se ha encontrado el pedido con ID = %d', [ID])); Result := Eliminar(APedido); APedido := NIL; end; function TPedidosClienteController.ElegirPedidos(APedido: IBizPedidoCliente; AMensaje: String; AMultiSelect: Boolean): IBizPedidoCliente; var AEditor : IEditorElegirPedidosCliente; begin Result := NIL; CreateEditor('EditorElegirPedidosCliente', IEditorElegirPedidosCliente, AEditor); try with AEditor do begin Controller := Self; Pedidos := APedido; MultiSelect := AMultiSelect; Mensaje := AMensaje; if IsPositiveResult(ShowModal) then Result := PedidosClienteSeleccionados; Release; end; finally AEditor := NIL; end; end; function TPedidosClienteController.Eliminar(APedido: IBizPedidoCliente): Boolean; begin Result := False; if not Assigned(APedido) then raise Exception.Create ('Pedido no asignado'); if APedido.DataTable.Active then APedido.DataTable.Active := True; if APedido.SITUACION <> SITUACION_PEDIDO_PENDIENTE then raise Exception.Create('No se puede eliminar este pedido porque está ' + APedido.SITUACION); ShowHourglassCursor; try if (APedido.State in dsEditModes) then APedido.Cancel; APedido.Delete; APedido.DataTable.ApplyUpdates; Result := True; finally HideHourglassCursor; end; end; procedure TPedidosClienteController.RecalcularImportes( APedido: IBizPedidoCliente); var bEnEdicion : Boolean; begin if not Assigned(APedido) then raise Exception.Create ('Pedido no asignado (RecalcularImportes)'); if APedido.DataTable.Active then APedido.DataTable.Active := True; bEnEdicion := (APedido.DataTable.State in dsEditModes); if not bEnEdicion then APedido.Edit; ShowHourglassCursor; APedido.Edit; try APedido.IMPORTE_NETO := FDetallesController.DarTotalImporteTotal(APedido.Detalles); if not bEnEdicion then APedido.Post; finally HideHourglassCursor; end; end; procedure TPedidosClienteController.RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable); var APedido : IBizPedidoCliente; ADetalles : IBizDetallesPedidoCliente; begin inherited; if Supports(ADataTable, IBizDetallesPedidoCliente, ADetalles) and Supports(ADetalles.DataTable.MasterSource.DataTable, IBizPedidoCliente, APedido) then begin RecalcularImportes(APedido); end; end; procedure TPedidosClienteController.RecuperarObjetos(APedido: IBizPedidoCliente); begin RecuperarCliente(APedido); end; procedure TPedidosClienteController.RecuperarCliente( APedido: IBizPedidoCliente); begin APedido._Cliente := (FClienteController.Buscar(APedido.ID_Cliente) as IBizCliente); end; function TPedidosClienteController.Existe(const ID: Integer): Boolean; var APedido : IBizPedidoCliente; begin try APedido := Buscar(ID); Result := Assigned(APedido) and (APedido.ID = ID); finally APedido := NIL; end; end; function TPedidosClienteController.ExtraerSeleccionados(APedido: IBizPedidoCliente): IBizPedidoCliente; var ASeleccionados : IBizPedidoCliente; begin ASeleccionados := (Self.Buscar(ID_NULO) as IBizPedidoCliente); CopyDataTable(APedido.DataTable, ASeleccionados.DataTable, True); Result := ASeleccionados; end; procedure TPedidosClienteController.FiltrarEmpresa( APedido: IBizPedidoCliente); begin if APedido.DataTable.Active then APedido.DataTable.Active := False; // Filtrar los presupuestos actuales por empresa with APedido.DataTable.Where do begin if NotEmpty then AddOperator(opAND); AddCondition(fld_PedidosClienteID_EMPRESA, cEqual, dmUsuarios.IDEmpresaActual); end; end; procedure TPedidosClienteController.SetClienteController(const Value: IClientesController); begin FClienteController := Value; end; procedure TPedidosClienteController.SetDetallesController(const Value: IDetallesPedidoClienteController); begin FDetallesController := Value; end; function TPedidosClienteController.Guardar(APedido: IBizPedidoCliente): Boolean; var IDNuevo: Integer; begin Result := False; if not Assigned(APedido) then raise Exception.Create ('Pedido no asignada'); if not Assigned(FDetallesController) then raise Exception.Create ('Controller detalles no asignado'); if ValidarPedido(APedido) then begin ShowHourglassCursor; // Asegurarnos de que todos los importes están bien. RecalcularImportes(APedido); try if (APedido.EsNuevo) then IDNuevo := FDataModule.GetNextID(APedido.DataTable.LogicalName) else IDNuevo := APedido.ID; AsignarID(APedido, IDNuevo); APedido.DataTable.ApplyUpdates; Result := True; finally HideHourglassCursor; end; end; end; function TPedidosClienteController.Localizar(APedidos: IBizPedidoCliente; const ID: Integer): Boolean; begin Result := True; ShowHourglassCursor; try with APedidos.DataTable do begin DisableControls; First; if not Locate(fld_PedidosClienteID, ID, []) then Result := False; EnableControls; end; finally HideHourglassCursor; end; end; function TPedidosClienteController.Nuevo: IBizPedidoCliente; var APedido : IBizPedidoCliente; begin APedido := FDataModule.NewItem; FiltrarEmpresa(APedido); APedido.DataTable.Active := True; APedido.Insert; Result := APedido; end; procedure TPedidosClienteController.QuitarDireccionEnvio( APedido: IBizPedidoCliente); var bEnEdicion : Boolean; begin if not Assigned(APedido) then raise Exception.Create ('Pedido no asignado (QuitarDireccionEnvio)'); if APedido.DataTable.Active then APedido.DataTable.Active := True; bEnEdicion := (APedido.DataTable.State in dsEditModes); if not bEnEdicion then APedido.Edit; ShowHourglassCursor; APedido.Edit; try APedido.DataTable.FieldByName(fld_PedidosClienteCALLE).Clear; APedido.DataTable.FieldByName(fld_PedidosClientePOBLACION).Clear; APedido.DataTable.FieldByName(fld_PedidosClienteCODIGO_POSTAL).Clear; APedido.DataTable.FieldByName(fld_PedidosClientePROVINCIA).Clear; APedido.DataTable.FieldByName(fld_PedidosClienteTELEFONO).Clear; APedido.DataTable.FieldByName(fld_PedidosClientePERSONA_CONTACTO).Clear; if not bEnEdicion then APedido.Post; finally HideHourglassCursor; end; end; procedure TPedidosClienteController.Preview(APedido: IBizPedidoCliente); var AReportController : IPedidosClienteReportController; begin AReportController := TPedidosClienteReportController.Create; try AReportController.Preview(APedido.ID); finally AReportController := NIL; end; end; procedure TPedidosClienteController.Print(APedido: IBizPedidoCliente); var AReportController : IPedidosClienteReportController; begin AReportController := TPedidosClienteReportController.Create; try AReportController.Print(APedido.ID); finally AReportController := NIL; end; end; function TPedidosClienteController.GetClienteController: IClientesController; begin Result := FClienteController; end; function TPedidosClienteController.GetDetallesController: IDetallesPedidoClienteController; begin Result := FDetallesController; end; end.