unit uFacturasProformaController; interface uses Classes, SysUtils, uDADataTable, uControllerBase, uIDataModuleFacturasProforma, uClientesController, uDetallesFacturaProformaController, uBizFacturasProforma; type IFacturasProformaController = interface(IControllerBase) ['{CAD20B4E-6D0B-4A1C-9306-B195824B6CAD}'] function GetClienteController: IClientesController; procedure SetClienteController(const Value: IClientesController); property ClienteController: IClientesController read GetClienteController write SetClienteController; function GetDetallesController: IDetallesFacturaProformaController; procedure SetDetallesController(const Value: IDetallesFacturaProformaController); property DetallesController: IDetallesFacturaProformaController read GetDetallesController write SetDetallesController; function Buscar(const ID: Integer): IBizFacturaProforma; function BuscarTodos: IBizFacturaProforma; overload; function BuscarTodos(const AID_Cliente: Integer): IBizFacturaProforma; overload; procedure Ver(AFactura : IBizFacturaProforma); procedure VerTodos(AFacturas: IBizFacturaProforma; const AVerModal : Boolean = False; const AWindowCaption: String = ''; const AHeaderText: String = ''); function Nuevo (withInsert: Boolean = True) : IBizFacturaProforma; function Anadir(AFactura : IBizFacturaProforma) : Boolean; overload; function AnadirAbono(AFactura : IBizFacturaProforma) : Boolean; // function Anadir(AFacturas : IBizFacturaProforma; AListaAlbaranes : IBizAlbaranCliente): Boolean; overload; // function Anadir(AFactura : IBizFacturaProforma; const IDPedido : Integer): Boolean; overload; function Eliminar(const ID : Integer): Boolean; overload; function Eliminar(AFactura : IBizFacturaProforma; AllItems: Boolean = false): Boolean; overload; function Guardar(AFactura : IBizFacturaProforma): Boolean; procedure DescartarCambios(AFactura : IBizFacturaProforma); function Existe(const ID: Integer) : Boolean; procedure RecuperarCliente(AFactura : IBizFacturaProforma); function Duplicar(AFactura: IBizFacturaProforma): IBizFacturaProforma; procedure Preview(AFactura : IBizFacturaProforma; AllItems: Boolean = false; const VerSello: Boolean = True; const VerCopia: Boolean = True); function Print(AFactura : IBizFacturaProforma; AllItems: Boolean = false; const VerSello: Boolean = True; const VerCopia: Boolean = True): Boolean; procedure RecalcularImportes(AFactura: IBizFacturaProforma); function EsModificable(AFactura: IBizFacturaProforma): Boolean; function EsEliminable(AFactura: IBizFacturaProforma): Boolean; function ElegirFacturas(AFacturas : IBizFacturaProforma; AMensaje: String; AMultiSelect: Boolean): IBizFacturaProforma; function ExtraerSeleccionados(ARecibosCliente: IBizFacturaProforma) : IBizFacturaProforma; procedure GenerarEmailFactura(AFactura : IBizFacturaProforma); function EnviarEmailFacturas(AFacturas : IBizFacturaProforma): Boolean; function EnviarFacturaPorEMail(AFactura: IBizFacturaProforma; const AEnviarDirectamente: Boolean = True; const ADireccionEMail: String = ''; const AAsuntoEMail: String = ''; const ATextoEMail: String = ''): Boolean; function DarListaAnosFacturas: TStringList; procedure FiltrarAno(AFactura: IBizFacturaProforma; ADynWhereDataTable: WideString; const Ano: String); function CambiarSituacion(AFactura : IBizFacturaProforma; Situacion: String; AllItems: Boolean = false): Boolean; end; TFacturasProformaController = class(TControllerBase, IFacturasProformaController) private FDataModule : IDataModuleFacturasProforma; FClienteController : IClientesController; FDetallesController : IDetallesFacturaProformaController; function GetClienteController: IClientesController; procedure SetClienteController(const Value: IClientesController); function GetDetallesController: IDetallesFacturaProformaController; procedure SetDetallesController(const Value: IDetallesFacturaProformaController); function CreateEditor(const AName : String; const IID: TGUID; out Intf): Boolean; function _Vacio : IBizFacturaProforma; procedure FiltrarEmpresa(AFactura: IBizFacturaProforma); function ValidarFactura(AFactura: IBizFacturaProforma): Boolean; procedure _AnadirMarcaEnvioCorreo(AFactura: IBizFacturaProforma); protected procedure RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable); override; public property ClienteController: IClientesController read GetClienteController write SetClienteController; property DetallesController: IDetallesFacturaProformaController read GetDetallesController write SetDetallesController; constructor Create; override; destructor Destroy; override; function Eliminar(const ID : Integer): Boolean; overload; function Eliminar(AFactura : IBizFacturaProforma; AllItems: Boolean = false): Boolean; overload; function Guardar(AFactura : IBizFacturaProforma): Boolean; procedure DescartarCambios(AFactura : IBizFacturaProforma); virtual; function Existe(const ID: Integer) : Boolean; virtual; function Anadir(AFactura : IBizFacturaProforma): Boolean; overload; function AnadirAbono(AFactura : IBizFacturaProforma) : Boolean; // function Anadir(AFacturas : IBizFacturaProforma; AListaAlbaranes : IBizAlbaranCliente): Boolean; overload; // function Anadir(AFactura : IBizFacturaProforma; const IDPedido : Integer): Boolean; overload; function Buscar(const ID: Integer): IBizFacturaProforma; function BuscarTodos: IBizFacturaProforma; overload; function BuscarTodos(const AID_Cliente: Integer): IBizFacturaProforma; overload; function Nuevo (withInsert: Boolean = True) : IBizFacturaProforma; procedure Ver(AFactura : IBizFacturaProforma); procedure VerTodos(AFacturas: IBizFacturaProforma; const AVerModal : Boolean = False; const AWindowCaption: String = ''; const AHeaderText: String = ''); function Duplicar(AFactura: IBizFacturaProforma): IBizFacturaProforma; procedure RecuperarCliente(AFactura : IBizFacturaProforma); procedure Preview(AFactura : IBizFacturaProforma; AllItems: Boolean = false; const VerSello: Boolean = True; const VerCopia: Boolean = True); function Print(AFactura : IBizFacturaProforma; AllItems: Boolean = false; const VerSello: Boolean = True; const VerCopia: Boolean = True): Boolean; procedure RecalcularImportes(AFactura: IBizFacturaProforma); function EsModificable(AFactura: IBizFacturaProforma): Boolean; function EsEliminable(AFactura: IBizFacturaProforma): Boolean; function ElegirFacturas(AFacturas : IBizFacturaProforma; AMensaje: String; AMultiSelect: Boolean): IBizFacturaProforma; function ExtraerSeleccionados(AFacturasProforma: IBizFacturaProforma) : IBizFacturaProforma; procedure GenerarEmailFactura(AFactura : IBizFacturaProforma); function EnviarEmailFacturas(AFacturas : IBizFacturaProforma): Boolean; function EnviarFacturaPorEMail(AFactura: IBizFacturaProforma; const AEnviarDirectamente: Boolean = True; const ADireccionEMail: String = ''; const AAsuntoEMail: String = ''; const ATextoEMail: String = ''): Boolean; function DarListaAnosFacturas: TStringList; procedure FiltrarAno(AFactura: IBizFacturaProforma; ADynWhereDataTable: WideString; const Ano: String); function CambiarSituacion(AFactura : IBizFacturaProforma; Situacion: String; AllItems: Boolean = false): Boolean; end; implementation uses Windows, Controls, cxControls, DB, uEditorRegistryUtils, schFacturasProformaClient_Intf, uBizContactos, uIEditorFacturasProforma, uIEditorFacturaProforma, uFactuGES_App, uDataModuleFacturasProforma, uBizDetallesFacturaProforma, uControllerDetallesBase, uDataModuleUsuarios, uDAInterfaces, uDataTableUtils, uDateUtils, uNumUtils, uROTypes, // uAlbaranesClienteController, schAlbaranesClienteClient_Intf, uDetallesAlbaranClienteController, // uBizDetallesAlbaranCliente, uRecibosClienteController, uBizRecibosCliente, uFacturasProformaReportController, uDataModuleRegistroCorreos, DateUtils, Forms, uFormasPagoController, uBizFormasPago, uIEditorElegirFacturasProforma, uIntegerListUtils, uSistemaFunc, uDialogElegirEMail, uEMailUtils, Dialogs, uStringsUtils, uROXMLIntf, uIDialogListaFacturasProformaEnvioEMail; {procedure CopiarArticulosPedido(AOrigen: IBizDetallesPedidoCliente; ADestino : IBizDetallesFacturaProforma); var i : integer; ADetallesController : IDetallesFacturaProformaController; begin if not Assigned(AOrigen) then raise Exception.Create ('Origen no asignado (CopiarArticulosPedido)'); if not Assigned(ADestino) then raise Exception.Create ('Destino no asignado (CopiarArticulosPedido)'); if not AOrigen.DataTable.Active then AOrigen.DataTable.Active := True; if not ADestino.DataTable.Active then ADestino.DataTable.Active := True; ADetallesController := TDetallesFacturaProformaController.Create; try //OJO IMPORTANTE //Siempre que vayamos a trabajar con los detalles debemos hacer un beginupdate de los mismos y un endupdate para //obligarle siempre a recalcular los detalles una sola vez ADetallesController.BeginUpdate(ADestino); AOrigen.DataTable.First; for i := 0 to AOrigen.DataTable.RecordCount - 1 do begin ADetallesController.Add(ADestino, TIPO_DETALLE_CONCEPTO); ADestino.Edit; ADestino.REFERENCIA := AOrigen.REFERENCIA; if AOrigen.ID_ARTICULO > 0 then ADestino.ID_ARTICULO := AOrigen.ID_ARTICULO; ADestino.CONCEPTO := AOrigen.CONCEPTO; ADestino.CANTIDAD := AOrigen.CANTIDAD; ADestino.IMPORTE_UNIDAD := AOrigen.IMPORTE_UNIDAD; ADestino.IMPORTE_TOTAL := AOrigen.IMPORTE_TOTAL; ADestino.DESCUENTO := AOrigen.DESCUENTO; ADestino.IMPORTE_PORTE := AOrigen.IMPORTE_PORTE; ADestino.VISIBLE := AOrigen.VISIBLE; ADestino.REFERENCIA_PROVEEDOR := AOrigen.REFERENCIA_PROVEEDOR; ADestino.Post; AOrigen.Next; end; finally ADetallesController.EndUpdate(ADestino); ADetallesController := NIL; end; end;} { TFacturasProformaController } function TFacturasProformaController.Anadir(AFactura: IBizFacturaProforma) : Boolean; begin if not Assigned(AFactura) then raise Exception.Create ('Factura no asignada (Anadir)'); AFactura.Insert; Result := True; end; function TFacturasProformaController.AnadirAbono(AFactura: IBizFacturaProforma): Boolean; begin Anadir(AFactura); Result := True; end; { function TFacturasProformaController.Anadir(AFacturas: IBizFacturaProforma; AListaAlbaranes: IBizAlbaranCliente): Boolean; var AFacturaActual : IBizFacturaProforma; AAlbaranesController : IAlbaranesClienteController; I: Integer; bEnEdicion : Boolean; begin // ATENCIÓN!!! AFacturas tiene que estar vacio para no pisar facturas // ya generadas. if not Assigned(AFacturas) then raise Exception.Create ('Factura no asignada (Anadir)'); if not Assigned(AListaAlbaranes) then raise Exception.Create ('Albaranes no asignados (Anadir)'); if not AFacturas.DataTable.Active then AFacturas.DataTable.Active := True; if not AListaAlbaranes.DataTable.Active then AListaAlbaranes.DataTable.Active := True; ShowHourglassCursor; Application.ProcessMessages; AAlbaranesController := TAlbaranesClienteController.Create; try // Ordenar por fecha de albaran AListaAlbaranes.DataTable.Sort([fld_AlbaranesClienteFECHA_ALBARAN], [uDADataTable.sdAscending]); AListaAlbaranes.First; for I := 0 to AListaAlbaranes.DataTable.RecordCount - 1 do begin AListaAlbaranes._Cliente := NIL; AFacturaActual := NIL; // Busco si hay alguna factura ya hecha de ese cliente AFacturas.DataTable.First; if AFacturas.DataTable.Locate(fld_FacturasProformaID_CLIENTE, AListaAlbaranes.ID_CLIENTE, []) then begin AFacturaActual := AFacturas; RecuperarCliente(AFacturaActual); AFacturaActual.Cliente.DataTable.Active := True; end else begin // No hay factura de ese cliente. Creo una nueva Anadir(AFacturas); AAlbaranesController.RecuperarCliente(AListaAlbaranes); AListaAlbaranes.Cliente.DataTable.Active := True; AFacturas.Cliente := AListaAlbaranes.Cliente; //Si el albaran es de tipo devolución hacemos la factura de tipo abono if (AListaAlbaranes.TIPO = CTE_TIPO_ALBARAN_DEV) then begin bEnEdicion := (AFacturas.DataTable.State in dsEditModes); if not bEnEdicion then AFacturas.Edit; AFacturas.TIPO := CTE_TIPO_ABONO; AFacturas.Post; if bEnEdicion then AFacturas.Edit; end; AFacturaActual := AFacturas; end; // Ya tengo la factura. Le añado los conceptos del albarán AFacturaActual.Detalles.DataTable.Last; // Añado el título Self.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_TITULO); with AFacturaActual.Detalles do begin Edit; CONCEPTO := 'Albarán ' + AListaAlbaranes.REFERENCIA + ' del ' + DateToStr(AListaAlbaranes.FECHA_ALBARAN); Post; end; // Añado el contenido del albarán CopiarArticulosAlbaran(AListaAlbaranes.Detalles, AFacturaActual.Detalles); Self.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_CONCEPTO); with AFacturaActual.Detalles do begin Edit; CONCEPTO := 'Porte del albarán'; CANTIDAD := 1; IMPORTE_UNIDAD := AListaAlbaranes.IMPORTE_PORTE; Post; end; // Añado el resumen Self.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_SUBTOTAL); with AFacturaActual.Detalles do begin Edit; CONCEPTO := 'Total del albarán ' + AListaAlbaranes.REFERENCIA; Post; end; // Añado una línea en blanco Self.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_CONCEPTO); with AFacturaActual.Detalles do begin Edit; CONCEPTO := ''; Post; end; // Guardo la factura que acabo de generar o editar AFacturaActual.CalcularImporteTotal; Self.Guardar(AFacturaActual); // Asocio la factura con el albarán AListaAlbaranes.Edit; AListaAlbaranes.ID_FACTURA := AFacturaActual.ID; AListaAlbaranes.Post; AAlbaranesController.Guardar(AListaAlbaranes); AListaAlbaranes.Next; end; Result := True; finally AAlbaranesController := NIL; HideHourglassCursor end; end; } {function TFacturasProformaController.Anadir(AFactura: IBizFacturaProforma; const IDPedido: Integer): Boolean; var APedidosController : IPedidosClienteController; APedido : IBizPedidoCliente; begin Result := False; if not Assigned(AFactura) then raise Exception.Create ('Factura no asignada (Anadir)'); if (IDPedido < 0) or (IDPedido = 0) then raise Exception.Create (Format('ID de pedido (%d) incorrecto (Anadir)', [IDPedido])); if not AFactura.DataTable.Active then AFactura.DataTable.Active := True; ShowHourglassCursor; Application.ProcessMessages; APedido := NIL; APedidosController := TPedidosClienteController.Create; try APedido := APedidosController.Buscar(IDPedido); if not Assigned(APedido) then raise Exception.Create (Format('No se ha encontrado un pedido de cliente con ID %d (Anadir)', [IDPedido])); APedido.DataTable.Active := True; APedidosController.RecuperarCliente(APedido); Self.Anadir(AFactura); AFactura.Cliente := APedido.Cliente; CopiarArticulosPedido(APedido.Detalles, AFactura.Detalles); // Guardo la factura que acabo de generar AFactura.CalcularImporteTotal; Self.Guardar(AFactura); Result := True; finally APedido := NIL; APedidosController := NIL; HideHourglassCursor; Application.ProcessMessages; end; end;} function TFacturasProformaController.Buscar(const ID: Integer): IBizFacturaProforma; begin Result := (FDataModule as IDataModuleFacturasProforma).GetItem(ID); FiltrarEmpresa(Result); end; function TFacturasProformaController.BuscarTodos( const AID_Cliente: Integer): IBizFacturaProforma; var Condicion: TDAWhereExpression; begin ShowHourglassCursor; try Result := BuscarTodos; with Result.DataTable.DynamicWhere do begin // ID_CLIENTE Condicion := NewBinaryExpression(NewField('', fld_FacturasProformaID_CLIENTE), NewConstant(AID_Cliente, datInteger), dboEqual); if IsEmpty then Expression := Condicion else Expression := NewBinaryExpression(Expression, Condicion, dboAnd); end; finally HideHourglassCursor; end; end; function TFacturasProformaController.BuscarTodos: IBizFacturaProforma; begin Result := FDataModule.GetItems; FiltrarEmpresa(Result); end; function TFacturasProformaController.CambiarSituacion(AFactura: IBizFacturaProforma; Situacion: String; AllItems: Boolean): Boolean; // En el caso de cambiar almenos un elemento del conjunto se devuelve true begin if not Assigned(AFactura) then raise Exception.Create ('AFactura no asignado'); ShowHourglassCursor; try if not AFactura.DataTable.Active then AFactura.DataTable.Active := True; if (AFactura.State in dsEditModes) then AFactura.Cancel; //Siempre cambiaremos de situacion el seleccionado if AFactura.SITUACION <> Situacion then begin AFactura.DataTable.Edit; AFactura.SITUACION := Situacion; AFactura.DataTable.Post; end; //En el caso de querer modificar todos los items del objeto if AllItems then begin with AFactura.DataTable do begin First; while not EOF do begin if AFactura.SITUACION <> Situacion then begin AFactura.DataTable.Edit; AFactura.SITUACION := Situacion; AFactura.DataTable.Post; end; Next; end; end; end; AFactura.DataTable.ApplyUpdates; Result := True; finally HideHourglassCursor; end; end; constructor TFacturasProformaController.Create; begin inherited; FDataModule := TDataModuleFacturasProforma.Create(Nil); FClienteController := TClientesController.Create; FDetallesController := TDetallesFacturaProformaController.Create; FDetallesController.addObservador(Self); end; function TFacturasProformaController.CreateEditor(const AName: String; const IID: TGUID; out Intf): Boolean; begin Result := Supports(EditorRegistry.CreateEditor(AName), IID, Intf); end; function TFacturasProformaController.DarListaAnosFacturas: TStringList; begin Result := FDataModule.GetAnosItems; end; procedure TFacturasProformaController.DescartarCambios(AFactura: IBizFacturaProforma); 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 TFacturasProformaController.Destroy; begin FDataModule := Nil; FClienteController := Nil; FDetallesController := Nil; inherited; end; function TFacturasProformaController.Duplicar(AFactura: IBizFacturaProforma): IBizFacturaProforma; 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 := AppFactuGES.EmpresaActiva.ID; USUARIO := AppFactuGES.UsuarioActivo.UserName; REFERENCIA := ''; //Para que se asigne una nueva SITUACION := CTE_PENDIENTE; //Al ser una nueva debe de estar pendiente FECHA_FACTURA := DateOf(Now); end; Result.Post; finally HideHourglassCursor; end; end; function TFacturasProformaController.ValidarFactura(AFactura: IBizFacturaProforma): Boolean; var AFormaPago: IBizFormaPago; begin if not Assigned(AFactura) then raise Exception.Create ('Factura no asignada'); 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; if (AFactura.ID_CLIENTE < 0) or (AFactura.ID_CLIENTE = 0) then // No comprobar el objeto Cliente por que puede fallar la validación // cuando se generan facturas automáticamente. { (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'); if (AFactura.Detalles.DataTable.RecordCount = 0) then raise Exception.Create('La factura debe tener al menos un concepto en su contenido'); { Esta validación puede saltar cuando se generan facturas automáticamente por albaranes o pedidos y el cliente no tiene Tipo de IVA puesto. } { if (AFactura.ID_TIPO_IVA = 0) then raise Exception.Create('Debe indicar un tipo de IVA para esta factura');} //De esta forma obligaremos siempre a tener un recibo asociado a la factura, //porque si la forma de pago no tiene plazos es obligatorio la fecha de vencimiento with TFormasPagoController.Create do begin try AFormaPago := Buscar(AFactura.ID_FORMA_PAGO); AFormaPago.DataTable.Active := True; if (AFormaPago.Plazos.RecordCount = 0) and (EsFechaVacia(AFactura.FECHA_VENCIMIENTO)) then raise Exception.Create('Debe indicar una fecha de vencimiento para esta factura'); finally AFormaPago := NIL; Free; end; end; { Asegurarse de valores en campos "automáticos" tanto en MODIFICACIÓN como en INSERCIÓN. } AFactura.Edit; try AFactura.USUARIO := AppFactuGES.UsuarioActivo.UserName; if Assigned(AFactura.Cliente) and (AFactura.ID_CLIENTE <> AFactura.Cliente.ID) then AFactura.ID_CLIENTE := AFactura.Cliente.ID; Result := True; finally AFactura.Post; end; end; procedure TFacturasProformaController.Ver(AFactura: IBizFacturaProforma); var AEditor : IEditorFacturaProforma; begin AEditor := NIL; RecuperarCliente(AFactura); CreateEditor('EditorFacturaProforma', IEditorFacturaProforma, AEditor); if Assigned(AEditor) then try AEditor.Controller := Self; //OJO ORDEN MUY IMPORTANTE AEditor.Factura := AFactura; //MODO CONSULTAR if not EsModificable(AFactura) then begin SetDataTableReadOnly(AFactura.DataTable, True); AEditor.ReadOnly := True; end; AEditor.ShowModal; //MODO CONSULTAR (Se deja la tabla como estaba) if AEditor.ReadOnly then SetDataTableReadOnly(AFactura.DataTable, False); finally AEditor.Release; AEditor := NIL; end; end; procedure TFacturasProformaController.VerTodos(AFacturas: IBizFacturaProforma; const AVerModal : Boolean = False; const AWindowCaption: String = ''; const AHeaderText: String = ''); var AEditor : IEditorFacturasProforma; begin AEditor := NIL; CreateEditor('EditorFacturasProforma', IEditorFacturasProforma, AEditor); if Assigned(AEditor) then try if not EsCadenaVacia(AWindowCaption) then AEditor.WindowCaption := AWindowCaption; if not EsCadenaVacia(AHeaderText) then AEditor.HeaderText := AHeaderText; AEditor.Controller := Self; //OJO ORDEN MUY IMPORTANTE AEditor.Facturas := AFacturas; AEditor.MultiSelect := True; if AVerModal then AEditor.ShowModal else AEditor.ShowEmbedded; finally if AVerModal then AEditor.Release; AEditor := Nil; end; end; procedure TFacturasProformaController._AnadirMarcaEnvioCorreo(AFactura: IBizFacturaProforma); var ASoloLectura : Boolean; begin if not Assigned(AFactura) then raise Exception.Create ('Factura no asignada (_AnadirMarcaEnvioCorreo)'); if AFactura.DataTable.Active then AFactura.DataTable.Active := True; if AnadirMarcaEnvioCorreo(nme_FacturasProforma, AFactura.ID) then begin DesconectarTabla(AFactura.DataTable); try ASoloLectura := AFactura.DataTable.ReadOnly; if ASoloLectura then SetDataTableReadOnly(AFactura.DataTable, False); try AFactura.Edit; AFactura.NUM_CORREOS := AFactura.NUM_CORREOS + 1; AFactura.Post; finally if ASoloLectura then SetDataTableReadOnly(AFactura.DataTable, True); end; finally ConectarTabla(AFactura.DataTable); end; end; end; function TFacturasProformaController._Vacio: IBizFacturaProforma; begin Result := Buscar(ID_NULO); end; function TFacturasProformaController.Eliminar(const ID: Integer): Boolean; var AFactura : IBizFacturaProforma; begin AFactura := Buscar(ID); if not Assigned(AFactura) then raise Exception.Create(Format('No se ha encontrado la factura con ID = %d', [ID])); Result := Eliminar(AFactura); AFactura := NIL; end; function TFacturasProformaController.ElegirFacturas(AFacturas: IBizFacturaProforma; AMensaje: String; AMultiSelect: Boolean): IBizFacturaProforma; var AEditor : IEditorElegirFacturasProforma; begin Result := NIL; CreateEditor('EditorElegirFacturasProforma', IEditorElegirFacturasProforma, AEditor); if Assigned(AEditor) then try AEditor.Controller := Self; AEditor.Facturas := AFacturas; AEditor.MultiSelect := AMultiSelect; AEditor.Mensaje := AMensaje; if IsPositiveResult(AEditor.ShowModal) then Result := AEditor.FacturasProformaSeleccionados; finally AEditor.Release; AEditor := NIL; end; end; function TFacturasProformaController.Eliminar(AFactura: IBizFacturaProforma; AllItems: Boolean = false): Boolean; //En el caso de eliminar almenos un elemento del conjunto se devuelve true var bEliminado: Boolean; begin bEliminado := False; if not Assigned(AFactura) then raise Exception.Create ('Factura no asignada'); ShowHourglassCursor; try if not AFactura.DataTable.Active then AFactura.DataTable.Active := True; if (AFactura.State in dsEditModes) then AFactura.Cancel; //Siempre eliminaremos el seleccionado if EsEliminable(AFactura) then begin AFactura.Delete; bEliminado := True; end; //En el caso de querer eliminar todos los items del objeto AAlbaran if AllItems then begin with AFactura.DataTable do begin First; while not EOF do begin if EsEliminable(AFactura) then begin AFactura.Delete; bEliminado := True end else Next; end; end; end; if bEliminado then begin try AFactura.DataTable.ApplyUpdates; Result := True except //En el caso de una factura que tiene recibos con devoluciones hechas no se puede borrar aunque la factura este en situacion de pendiente AFactura.DataTable.CancelUpdates; Result := False; end; end else Result := False; finally HideHourglassCursor; end; end; function TFacturasProformaController.EnviarEmailFacturas(AFacturas: IBizFacturaProforma): Boolean; var ADialog : IDialogListaFacturasProformaEnvioEMail; ARespuesta : Integer; begin ADialog := NIL; if not Assigned(AFacturas) then raise Exception.Create ('Facturas no asignadas (EnviarFacturasPorEMail)'); if AFacturas.DataTable.Active then AFacturas.DataTable.Active := True; ShowHourglassCursor; try CreateEditor('DialogListaFacturasProformaEnvioEMail', IDialogListaFacturasProformaEnvioEMail, ADialog); if Assigned(ADialog) then begin try ADialog.Facturas := AFacturas; ARespuesta := ADialog.ShowModal; Result := (ARespuesta = mrOK) finally ADialog.Release; end; end; finally ADialog := NIL; HideHourglassCursor; end; end; function TFacturasProformaController.EnviarFacturaPorEMail( AFactura: IBizFacturaProforma; const AEnviarDirectamente: Boolean; const ADireccionEMail, AAsuntoEMail, ATextoEMail: String): Boolean; var AReportController : IFacturasProformaReportController; AFicheroTMP : TFileName; AEMail : String; AAsunto : String; AListaEmail : TStringList; begin if not Assigned(AFactura) then raise Exception.Create ('Factura no asignada (EnviarFacturaPorEMail)'); if AFactura.DataTable.Active then AFactura.DataTable.Active := True; RecuperarCliente(AFactura); AFactura.Cliente.DataTable.Active := True; AFicheroTMP := DarFicheroPDFTemporal(EscapeIllegalChars(AFactura.REFERENCIA)); if not EsCadenaVacia(ADireccionEMail) then AEMail := ADireccionEMail else begin AListaEmail := TStringList.Create; try if not EsCadenaVacia(AFactura.Cliente.EMAIL_ADMINISTRACION) then AListaEmail.Add(AFactura.Cliente.EMAIL_ADMINISTRACION); if not ElegirEMail(AListaEmail, AEMail) then Exit; finally FreeANDNIL(AListaEmail); end; end; if not EsCadenaVacia(AAsuntoEMail) then AAsunto := AAsuntoEMail else AAsunto := 'Factura ' + AFactura.REFERENCIA; ShowHourglassCursor; Application.ProcessMessages; AReportController := TFacturasProformaReportController.Create; try AReportController.ExportToPDF(AFactura.ID, AFicheroTMP); Result := EnviarEMailMAPI(AAsunto, ATextoEMail, AFicheroTMP, '', '', AFactura.Cliente.NOMBRE, AEMail, AEnviarDirectamente); if Result then _AnadirMarcaEnvioCorreo(AFactura); finally SysUtils.DeleteFile(AFicheroTMP); AReportController := NIL; HideHourglassCursor; Application.ProcessMessages; end; end; procedure TFacturasProformaController.GenerarEmailFactura( AFactura: IBizFacturaProforma); begin if not Assigned(AFactura) then raise Exception.Create ('Facturas no asignadas (GenerarEmailFactura)'); if AFactura.DataTable.Active then AFactura.DataTable.Active := True; ShowHourglassCursor; try RecuperarCliente(AFactura); EnviarFacturaPorEMail(AFactura, False, AFactura.Cliente.EMAIL_ADMINISTRACION); finally HideHourglassCursor; end; end; function TFacturasProformaController.EsEliminable(AFactura: IBizFacturaProforma): Boolean; begin Result := EsModificable(AFactura); end; function TFacturasProformaController.EsModificable(AFactura: IBizFacturaProforma): Boolean; begin if not Assigned(AFactura) then raise Exception.Create ('Factura no asignado: EsModificable'); Result := (AFactura.SITUACION = CTE_PENDIENTE); end; procedure TFacturasProformaController.RecalcularImportes( AFactura: IBizFacturaProforma); var bEnEdicion : Boolean; ADetallePosAct : Integer; begin if not Assigned(AFactura) then raise Exception.Create ('Factura no asignado (RecalcularImportes)'); if AFactura.DataTable.Active then AFactura.DataTable.Active := True; { Hay que guardar la posición en la que estamos en los detalles por que la asignación de valores a los campos IMPORTE_NETO e IMPORTE_PORTE (ver más adelante) colocan el puntero en la tabla detalle al principio. No he encontrado la razón por la que mueve el puntero. } ADetallePosAct := AFactura.Detalles.POSICION; bEnEdicion := (AFactura.DataTable.State in dsEditModes); if not bEnEdicion then AFactura.Edit; ShowHourglassCursor; try AFactura.IMPORTE_NETO := FDetallesController.DarTotalImporteTotal(AFactura.Detalles); AFactura.IMPORTE_PORTE := FDetallesController.DarTotalPorteTotal(AFactura.Detalles); if not bEnEdicion then AFactura.Post; finally HideHourglassCursor; // Restaurar la posición que teníamos en los detalles. FDetallesController.LocalizarPosicion(AFactura.Detalles, ADetallePosAct); end; end; procedure TFacturasProformaController.RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable); var AFactura : IBizFacturaProforma; ADetalles : IBizDetallesFacturaProforma; begin inherited; if Supports(ADataTable, IBizDetallesFacturaProforma, ADetalles) and Supports(ADetalles.DataTable.MasterSource.DataTable, IBizFacturaProforma, AFactura) then begin RecalcularImportes(AFactura); end; end; procedure TFacturasProformaController.RecuperarCliente( AFactura: IBizFacturaProforma); begin AFactura._Cliente := (FClienteController.Buscar(AFactura.ID_CLIENTE) as IBizCliente); end; function TFacturasProformaController.Existe(const ID: Integer): Boolean; var AFactura : IBizFacturaProforma; begin try AFactura := Buscar(ID); Result := Assigned(AFactura) and (AFactura.ID = ID); finally AFactura := NIL; end; end; function TFacturasProformaController.ExtraerSeleccionados(AFacturasProforma: IBizFacturaProforma): IBizFacturaProforma; var ASeleccionados : IBizFacturaProforma; begin ASeleccionados := (Self.Buscar(ID_NULO) as IBizFacturaProforma); CopyDataTableDA5(AFacturasProforma.DataTable, ASeleccionados.DataTable, True); Result := ASeleccionados; end; procedure TFacturasProformaController.FiltrarAno(AFactura: IBizFacturaProforma; ADynWhereDataTable: WideString; const Ano: String); var Condicion: TDAWhereExpression; FechaIni: String; FechaFin: String; begin AFactura.DataTable.DynamicWhere.Clear; AFactura.DataTable.DynamicWhere.Xml := ADynWhereDataTable; if (Ano <> 'Todos') then begin // Filtrar las facturas actuales por empresa FechaIni := '01/01/' + Ano; FechaFin := '31/12/' + Ano; with AFactura.DataTable.DynamicWhere do begin // (FECHA_INICIO between FECHA_FIN) Condicion := NewBinaryExpression(NewField('', fld_FacturasProformaFECHA_FACTURA), NewConstant(FechaIni, datString), dboGreaterOrEqual); Condicion := NewBinaryExpression(NewBinaryExpression(NewField('', fld_FacturasProformaFECHA_FACTURA), NewConstant(FechaFin, datString), dboLessOrEqual), Condicion, dboAnd); if IsEmpty then Expression := Condicion else Expression := NewBinaryExpression(Condicion, Expression, dboAnd); end; end; end; procedure TFacturasProformaController.FiltrarEmpresa(AFactura: IBizFacturaProforma); var Condicion: TDAWhereExpression; begin if AFactura.DataTable.Active then AFactura.DataTable.Active := False; // Filtrar las facturas actuales por empresa with AFactura.DataTable.DynamicWhere do begin // (ID_EMPRESA >= ID) Condicion := NewBinaryExpression(NewField('', fld_FacturasProformaID_EMPRESA), NewConstant(AppFactuGES.EmpresaActiva.ID, datInteger), dboEqual); if IsEmpty then Expression := Condicion else Expression := NewBinaryExpression(Expression, Condicion, dboAnd); end; end; procedure TFacturasProformaController.SetClienteController(const Value: IClientesController); begin FClienteController := Value; end; procedure TFacturasProformaController.SetDetallesController(const Value: IDetallesFacturaProformaController); begin FDetallesController := Value; end; function TFacturasProformaController.Guardar(AFactura: IBizFacturaProforma): Boolean; 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 ValidarFactura(AFactura) then begin ShowHourglassCursor; // Asegurarnos de que todos los importes están bien. RecalcularImportes(AFactura); try AFactura.DataTable.ApplyUpdates; Result := True; finally HideHourglassCursor; end; end; end; function TFacturasProformaController.Nuevo(withInsert: Boolean = True): IBizFacturaProforma; var AFactura : IBizFacturaProforma; begin AFactura := FDataModule.NewItem; FiltrarEmpresa(AFactura); AFactura.DataTable.Active := True; if WithInsert then AFactura.Insert; Result := AFactura; end; procedure TFacturasProformaController.Preview(AFactura: IBizFacturaProforma; AllItems: Boolean = false; const VerSello: Boolean = True; const VerCopia: Boolean = True); var AReportController : IFacturasProformaReportController; ID_Facturas: TIntegerList; begin AReportController := TFacturasProformaReportController.Create; ID_Facturas := TIntegerList.Create; try //Si deseamos previsualizar todos los items del objeto albaran if AllItems then begin with AFactura.DataTable do begin First; while not EOF do begin ID_Facturas.Add(AFactura.ID); Next; end; end; end //Solo previsualizamos el item seleccionado else ID_Facturas.Add(AFactura.ID); AReportController.Preview(ID_Facturas); finally AReportController := NIL; FreeANDNIL(ID_Facturas); end; end; function TFacturasProformaController.Print(AFactura: IBizFacturaProforma; AllItems: Boolean = false; const VerSello: Boolean = True; const VerCopia: Boolean = True): Boolean; var AReportController : IFacturasProformaReportController; ID_Facturas: TIntegerList; begin Result := False; AReportController := TFacturasProformaReportController.Create; ID_Facturas := TIntegerList.Create; try //Si deseamos previsualizar todos los items del objeto albaran if AllItems then begin with AFactura.DataTable do begin First; while not EOF do begin ID_Facturas.Add(AFactura.ID); Next; end; end; end //Solo previsualizamos el item seleccionado else ID_Facturas.Add(AFactura.ID); Result := AReportController.Print(ID_Facturas); finally AReportController := NIL; FreeANDNIL(ID_Facturas); end; end; function TFacturasProformaController.GetClienteController: IClientesController; begin Result := FClienteController; end; function TFacturasProformaController.GetDetallesController: IDetallesFacturaProformaController; begin Result := FDetallesController; end; end.