AbetoDesign_FactuGES2/Source/Modulos/Facturas de cliente/Controller/uFacturasClienteController.pas
roberto d840c1cda7 Version 4.3.3
Se arregla para que se pueda clonar facturas de cliente graden que esten emitidas como factura de proveedor en graden.
Añadir sumatorios importes en listado de contratos al agrupar pedido por miriam.
Donostia Y marbella


git-svn-id: https://192.168.0.254/svn/Proyectos.AbetoDesign_FactuGES/trunk@178 93f398dd-4eb6-7a46-baf6-13f46f578da2
2023-03-28 15:45:30 +00:00

1580 lines
55 KiB
ObjectPascal
Raw Blame History

unit uFacturasClienteController;
interface
uses
Classes, SysUtils, Variants, uDADataTable, uControllerBase, uIDataModuleFacturasCliente,
uClientesController, uDetallesFacturaClienteController, uBizAlbaranesCliente,
uBizFacturasCliente, uBizDireccionesContacto, uBizContactos;
type
IFacturasClienteController = interface(IControllerBase)
['{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;
function BuscarTodasPendientesComision(IdAgente: Integer; IdComision: Integer; IdFacturasAsociadas: String): IBizFacturaCliente;
procedure Ver(AFactura : IBizFacturaCliente);
procedure VerTodos(AFacturas: IBizFacturaCliente);
function Nuevo (WithInsert: Boolean = True) : IBizFacturaCliente;
function Anadir(AFactura : IBizFacturaCliente) : Boolean; overload;
function AnadirAbono(AFactura : IBizFacturaCliente) : Boolean;
function Anadir(AFacturas : IBizFacturaCliente; AListaAlbaranes : IBizAlbaranCliente): Boolean; overload;
function Eliminar(const ID : Integer): Boolean; overload;
function Eliminar(AFactura : IBizFacturaCliente; AllItems: Boolean = false; AListaCausas: TStringList = nil): Boolean; overload;
function Guardar(AFactura : IBizFacturaCliente): Boolean;
procedure DescartarCambios(AFactura : IBizFacturaCliente);
function Existe(const ID: Integer) : Boolean;
procedure RecuperarCliente(AFactura : IBizFacturaCliente);
procedure ActualizarFormaDePago(AFactura : IBizFacturaCliente; ID_FORMA_PAGO: Integer);
function Duplicar(AFactura: IBizFacturaCliente): IBizFacturaCliente;
function GenerarAbono(AFactura: IBizFacturaCliente): IBizFacturaCliente;
procedure Preview(AFactura : IBizFacturaCliente; AllItems: Boolean = false; VerLogotipo: Boolean = true);
procedure Print(AFactura : IBizFacturaCliente; AllItems: Boolean = false; VerLogotipo: Boolean = true);
procedure RecalcularImportes(AFactura: IBizFacturaCliente);
function ElegirFacturas(AFacturas : IBizFacturaCliente; AMensaje: String; AMultiSelect: Boolean): IBizFacturaCliente;
function ExtraerSeleccionados(ARecibosCliente: IBizFacturaCliente) : IBizFacturaCliente;
procedure CopiarDireccion (const ADireccionEnvio: IBizDireccionesContacto; AFactura: IBizFacturaCliente);
procedure SetIgnorarContabilidad (AFactura: IBizFacturaCliente; const Ignorar: Integer);
function DarListaAnosFacturas: TStringList;
procedure FiltrarAno(AFactura: IBizFacturaCliente; ADynWhereDataTable: WideString; const Ano: String);
function darTiposFacturaCliente: IBizTiposFacturaCliente;
function AsignarTipoOperacion(AFacturas: IBizFacturaCliente): Boolean;
function CambiarComercial(AFactura : IBizFacturaCliente; AComercial: IBizComercial): Boolean;
end;
TFacturasClienteController = class(TControllerBase, IFacturasClienteController)
private
FDataModule : IDataModuleFacturasCliente;
FClienteController : IClientesController;
FDetallesController : IDetallesFacturaClienteController;
function GetClienteController: IClientesController;
procedure SetClienteController(const Value: IClientesController);
function GetDetallesController: IDetallesFacturaClienteController;
procedure SetDetallesController(const Value: IDetallesFacturaClienteController);
function CreateEditor(const AName : String; const IID: TGUID; out Intf): Boolean;
function _Vacio : IBizFacturaCliente;
procedure FiltrarEmpresa(AFactura: IBizFacturaCliente);
function ValidarFactura(AFactura: IBizFacturaCliente): Boolean;
procedure GenerarRecibos(AFactura: IBizFacturaCliente);
protected
procedure RecibirAviso(ASujeto: ISujeto; ADataTable: IDAStronglyTypedDataTable); override;
public
property ClienteController: IClientesController read GetClienteController write SetClienteController;
property DetallesController: IDetallesFacturaClienteController read GetDetallesController write SetDetallesController;
constructor Create; override;
destructor Destroy; override;
function Eliminar(const ID : Integer): Boolean; overload;
function Eliminar(AFactura : IBizFacturaCliente; AllItems: Boolean = false; AListaCausas: TStringList = nil): Boolean; overload;
function Guardar(AFactura : IBizFacturaCliente): Boolean;
procedure DescartarCambios(AFactura : IBizFacturaCliente); virtual;
function Existe(const ID: Integer) : Boolean; virtual;
function Anadir(AFactura : IBizFacturaCliente): Boolean; overload;
function AnadirAbono(AFactura : IBizFacturaCliente) : Boolean;
function Anadir(AFacturas : IBizFacturaCliente; AListaAlbaranes : IBizAlbaranCliente): Boolean; overload;
function Buscar(const ID: Integer): IBizFacturaCliente;
function BuscarTodos: IBizFacturaCliente;
function BuscarTodasPendientesComision(IdAgente: Integer; IdComision: Integer; IdFacturasAsociadas: String): IBizFacturaCliente;
function Nuevo (WithInsert: Boolean = True) : IBizFacturaCliente;
procedure Ver(AFactura : IBizFacturaCliente);
procedure VerTodos(AFacturas: IBizFacturaCliente);
function Duplicar(AFactura: IBizFacturaCliente): IBizFacturaCliente;
function GenerarAbono(AFactura: IBizFacturaCliente): IBizFacturaCliente;
procedure RecuperarCliente(AFactura : IBizFacturaCliente);
procedure ActualizarFormaDePago(AFactura : IBizFacturaCliente; ID_FORMA_PAGO: Integer);
procedure Preview(AFactura : IBizFacturaCliente; AllItems: Boolean = false; VerLogotipo: Boolean = true);
procedure Print(AFactura : IBizFacturaCliente; AllItems: Boolean = false; VerLogotipo: Boolean = true);
procedure RecalcularImportes(AFactura: IBizFacturaCliente);
function EsModificable(AFactura: IBizFacturaCliente; var AComentario: Variant): Boolean;
function EsEliminable(AFactura: IBizFacturaCliente; var AComentario: Variant): Boolean;
function ElegirFacturas(AFacturas : IBizFacturaCliente; AMensaje: String; AMultiSelect: Boolean): IBizFacturaCliente;
function ExtraerSeleccionados(AFacturasCliente: IBizFacturaCliente) : IBizFacturaCliente;
procedure CopiarDireccion (const ADireccionEnvio: IBizDireccionesContacto; AFactura: IBizFacturaCliente);
procedure SetIgnorarContabilidad (AFactura: IBizFacturaCliente; const Ignorar: Integer);
function DarListaAnosFacturas: TStringList;
procedure FiltrarAno(AFactura: IBizFacturaCliente; ADynWhereDataTable: WideString; const Ano: String);
function darTiposFacturaCliente: IBizTiposFacturaCliente;
function AsignarTipoOperacion(AFacturas: IBizFacturaCliente): Boolean;
function CambiarComercial(AFactura : IBizFacturaCliente; AComercial: IBizComercial): Boolean;
end;
implementation
{$INCLUDE ..\..\..\FactuGES.inc}
uses
Windows, uDateUtils, uNumUtils, Controls, cxControls, DB, uEditorRegistryUtils, schFacturasClienteClient_Intf,
uIEditorFacturasCliente, uIEditorFacturaCliente, uFactuGES_App,
uDataModuleFacturasCliente, uBizDetallesFacturaCliente, uControllerDetallesBase,
uDataModuleUsuarios, uDAInterfaces, uDataTableUtils, uAlbaranesClienteController,
schAlbaranesClienteClient_Intf, uROTypes, uDetallesAlbaranClienteController,
uBizDetallesAlbaranCliente, uFacturasClienteReportController, DateUtils, Forms,
Dialogs, uIntegerListUtils, uIEditorElegirFacturasCliente, uStringsUtils,
uFormasPagoController, uBizFormasPago, uTiposIVAController, uBizTiposIVA,
uBizEjercicios, uRecibosClienteController, uBizRecibosCliente, uTiposOperacionVentaController;
procedure CopiarArticulosAlbaran(AOrigen: IBizDetallesAlbaranCliente;
ADestino : IBizDetallesFacturaCliente);
var
i : integer;
ADetallesController : IDetallesFacturaClienteController;
begin
if not Assigned(AOrigen) then
raise Exception.Create ('Origen no asignado (CopiarArticulosAlbaran)');
if not Assigned(ADestino) then
raise Exception.Create ('Destino no asignado (CopiarArticulosAlbaran)');
if not AOrigen.DataTable.Active then
AOrigen.DataTable.Active := True;
if not ADestino.DataTable.Active then
ADestino.DataTable.Active := True;
ADetallesController := TDetallesFacturaClienteController.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;
//En el caso de descuento de capitulo debemos a<>adirlo como una linea detalle con un descuento
if (AOrigen.TIPO_DETALLE = TIPO_DETALLE_DESCUENTO)
and (AOrigen.DESCUENTO > 0) then
begin
ADestino.CONCEPTO := AOrigen.CONCEPTO + AOrigen.DataTable.FieldByName(fld_AlbaranesCliente_DetallesDESCUENTO).AsString + ' %';
ADestino.CANTIDAD := 1;
ADestino.IMPORTE_UNIDAD := AOrigen.IMPORTE_TOTAL;
end
else
begin
ADestino.CONCEPTO := AOrigen.CONCEPTO;
ADestino.CANTIDAD := AOrigen.CANTIDAD;
ADestino.DESCUENTO := AOrigen.DESCUENTO;
ADestino.IMPORTE_UNIDAD := AOrigen.IMPORTE_UNIDAD;
end;
ADestino.IMPORTE_TOTAL := AOrigen.IMPORTE_TOTAL;
ADestino.IMPORTE_PORTE := AOrigen.IMPORTE_PORTE;
ADestino.VISIBLE := AOrigen.VISIBLE;
ADestino.VALORADO := AOrigen.VALORADO;
// ADestino.REFERENCIA_PROVEEDOR := AOrigen.REFERENCIA_PROVEEDOR;
ADestino.Post;
AOrigen.Next;
end;
finally
ADetallesController.EndUpdate(ADestino);
ADetallesController := NIL;
end;
end;
{ TFacturasClienteController }
function TFacturasClienteController.Anadir(AFactura: IBizFacturaCliente) : Boolean;
begin
if not Assigned(AFactura) then
raise Exception.Create ('Factura no asignada (Anadir)');
AFactura.Insert;
Result := True;
end;
function TFacturasClienteController.AnadirAbono(AFactura: IBizFacturaCliente): Boolean;
begin
Anadir(AFactura);
AFactura.TIPO := CTE_TIPO_ABONO;
Result := True;
end;
function TFacturasClienteController.AsignarTipoOperacion(AFacturas: IBizFacturaCliente): Boolean;
var
ATipoOperacionController : ITiposOperacionVentaController;
ATipoOperacion: Variant;
begin
Result := False;
if Assigned(AFacturas) then
begin
with TTiposOperacionVentaController.Create do
begin
try
ATipoOperacion := elegirTipoOperacionVenta;
finally
Free
end;
end;
end;
ShowHourglassCursor;
if not EsCadenaVacia(ATipoOperacion) then
begin
//Asignamos en factura
with AFacturas.DataTable do
begin
First;
while not EOF do
begin
if (AFacturas.ID_TIPO_FACTURA <> ATipoOperacion) then
begin
Edit;
AFacturas.ID_TIPO_FACTURA := ATipoOperacion;
Post;
end;
Next;
end;
ApplyUpdates;
Result := True;
end;
end;
HideHourglassCursor;
end;
procedure TFacturasClienteController.ActualizarFormaDePago(
AFactura: IBizFacturaCliente; ID_FORMA_PAGO: Integer);
var
AFormasPago : IBizFormaPago;
AFormasPagoController : IFormasPagoController;
ATiposIVA : IBizTipoIVA;
ATiposIVAController : ITiposIVAController;
bEnEdicion : Boolean;
begin
AFormasPagoController := TFormasPagoController.Create;
AFormasPago := AFormasPagoController.Buscar(ID_FORMA_PAGO);
AFormasPago.Open;
//Se cambia tambien el tipo de IVA por el de la ficha a peticion de Angelica
ATiposIVAController := TTiposIVAController.Create;
ATiposIVA := ATiposIVAController.Buscar(AFactura.Cliente.ID_TIPO_IVA);
ATiposIVA.Open;
bEnEdicion := (AFactura.DataTable.State in dsEditModes);
if not bEnEdicion then
AFactura.Edit;
AFactura.ID_FORMA_PAGO := AFormasPago.ID;
// AFactura.DataTable.FieldByName(fld_FacturasClienteFORMA_PAGO).AsString := AFormasPago.DESCRIPCION;
AFactura.ID_TIPO_IVA := ATiposIva.ID;
if not bEnEdicion then
AFactura.Post;
AFormasPago := NIL;
AFormasPagoController := NIL;
ATiposIVA := NIL;
ATiposIVAController := NIL;
end;
function TFacturasClienteController.Anadir(AFacturas: IBizFacturaCliente;
AListaAlbaranes: IBizAlbaranCliente): Boolean;
var
AFacturaActual : IBizFacturaCliente;
AAlbaranesController : IAlbaranesClienteController;
ACadena: String;
I, x: Integer;
bEnEdicion : Boolean;
begin
Result := False;
// ATENCI<43>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_FacturasClienteID_CLIENTE, AListaAlbaranes.ID_CLIENTE, []) then
begin
AFacturaActual := AFacturas;
RecuperarCliente(AFacturaActual);
AFacturaActual.Cliente.DataTable.Active := True;
//En este caso no queremos el descuento general del cliente asociado a su ficha, ya que partimos del valor que tengan las olbaranes
bEnEdicion := (AFacturaActual.DataTable.State in dsEditModes);
if not bEnEdicion then
AFacturaActual.Edit;
AFacturaActual.DESCUENTOIsNull := True;
AFacturaActual.Post;
if bEnEdicion then
AFacturaActual.Edit;
end
else begin
// No hay factura de ese cliente. Creo una nueva
Anadir(AFacturas);
AAlbaranesController.RecuperarCliente(AListaAlbaranes);
AFacturas.Cliente := AListaAlbaranes.Cliente;
//Establecemos la forma de pago establecido en la ficha del cliente
if AFacturas.Cliente.ID_FORMA_PAGO > 0 then
AFacturas.ID_FORMA_PAGO := AFacturas.Cliente.ID_FORMA_PAGO;
// if AFacturas.Cliente.ID_TIPO_IVA > 0 then
// AFacturas.ID_TIPO_IVA := AFacturas.Cliente.ID_TIPO_IVA;
//En este caso no queremos el descuento general del cliente asociado a su ficha, ya que partimos del valor que tengan las olbaranes
bEnEdicion := (AFacturas.DataTable.State in dsEditModes);
if not bEnEdicion then
AFacturas.Edit;
AFacturas.DESCUENTOIsNull := True;
AFacturas.Post;
if bEnEdicion then
AFacturas.Edit;
//Si el albaran es de tipo devoluci<63>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<61>n
AFacturaActual.Detalles.DataTable.Sort([fld_FacturasCliente_DetallesPOSICION], [uDADataTable.sdAscending]);
AFacturaActual.Detalles.DataTable.Last;
// A<>ado el t<>tulo, se cambia a petici<63>n por linea de concepto con resumen del albaran correspondiente, SE SOLICITA QUITAR POR M<>NICA 16/06/2020
Self.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_CONCEPTO);
with AFacturaActual.Detalles do
begin
ACadena := '';
ACadena := 'Albar<61>n ' + AListaAlbaranes.REFERENCIA + ' de ' + DateToStr(AListaAlbaranes.FECHA_ALBARAN);
Edit;
CONCEPTO := ACadena;
Post;
end;
// A<>ado el contenido del albar<61>n
CopiarArticulosAlbaran(AListaAlbaranes.Detalles, AFacturaActual.Detalles);
//MUCHO CUIDADO NOS TENEMOS QUE ASEGURAR DE A<>ADIR AL FINAL DEL TODO, podr<64>a calcular mal los descuentos de capitulo de la factura si los hubiera
AFacturaActual.Detalles.DataTable.Sort([fld_FacturasCliente_DetallesPOSICION], [uDADataTable.sdAscending]);
AFacturaActual.Detalles.DataTable.Last;
//Sacamos el importe del porte en el caso de tener
if (AListaAlbaranes.IMPORTE_PORTE > 0) then
begin
Self.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_CONCEPTO);
with AFacturaActual.Detalles do
begin
Edit;
CONCEPTO := 'Porte del albar<61>n';
CANTIDAD := 1;
IMPORTE_UNIDAD := AListaAlbaranes.IMPORTE_PORTE;
Post;
end;
end;
//Sacamos el descuento total del albaran en el caso de tener
if (AListaAlbaranes.IMPORTE_DESCUENTO > 0) then
begin
Self.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_CONCEPTO);
with AFacturaActual.Detalles do
begin
Edit;
CONCEPTO := 'Descuento del albar<61>n ' + AListaAlbaranes.REFERENCIA + ' - ' + AListaAlbaranes.DataTable.FieldByName(fld_AlbaranesClienteDESCUENTO).AsString + '%';
CANTIDAD := -1;
IMPORTE_UNIDAD := AListaAlbaranes.IMPORTE_DESCUENTO;
Post;
end;
end;
// A<>ado el resumen SE SOLICITA QUITAR POR M<>NICA 16/06/2020
// Self.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_SUBTOTAL);
// with AFacturaActual.Detalles do
// begin
// Edit;
// CONCEPTO := 'Total del albar<61>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<61>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 TFacturasClienteController.Anadir(AFactura: IBizFacturaCliente;
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 TFacturasClienteController.Buscar(const ID: Integer): IBizFacturaCliente;
begin
Result := (FDataModule as IDataModuleFacturasCliente).GetItem(ID);
FiltrarEmpresa(Result);
end;
function TFacturasClienteController.BuscarTodasPendientesComision(IdAgente:Integer; IdComision: Integer; IdFacturasAsociadas: String): IBizFacturaCliente;
var
Condicion: TDAWhereExpression;
Condicion1: TDAWhereExpression;
Condicion2: TDAWhereExpression;
Condicion3: TDAWhereExpression;
Condicion4: TDAWhereExpression;
Cadena : TStringList;
i: Integer;
begin
ShowHourglassCursor;
try
Result := BuscarTodos;
with Result.DataTable.DynamicWhere do
begin
//Todas las facturas que sean comisionables
Condicion := NewBinaryExpression(NewField('', fld_FacturasClienteSIN_COMISION), NewConstant(0, datInteger), dboEqual);
if IsEmpty then
Expression := Condicion
else
Expression := NewBinaryExpression(Expression, Condicion, dboAnd);
end;
with Result.DataTable.DynamicWhere do
begin
//Todas las facturas de esta liquidaci<63>n
Condicion1 := NewBinaryExpression(NewField('', fld_FacturasClienteID_COMISION_LIQUIDADA), NewConstant(IdComision, datInteger), dboEqual);
//Todas aquellas facturas que ya esten asociadas a la liquidaci<63>n actual no deben salir
if (Length(IdFacturasAsociadas) > 0) then
begin
Cadena := TStringList.Create;
Cadena.CommaText := IdFacturasAsociadas;
Condicion2 := nil;
//Vamos generando todas las where de cada uno de los ID recibidos por parametro
for i := 0 to Cadena.Count - 1 do
with Result.DataTable.DynamicWhere do
begin
Condicion4 := NewBinaryExpression(NewField('', fld_FacturasClienteID), NewConstant(StrToInt(Cadena.Strings[i]), datInteger), dboNotEqual);
if Condicion2 = nil then
Condicion2 := Condicion4
else
Condicion2 := NewBinaryExpression(Condicion2, Condicion4, dboAnd);
end;
Cadena.Free;
end;
//Todas aquellas que no esten asociadas a ninguna liquidaci<63>n, y que tampoco esten en el editor, ya que en cache estan
//asociadas a la liquidadcion pero en datos me viene como nula
Condicion3 := NewBinaryExpression(NewField('', fld_FacturasClienteID_COMISION_LIQUIDADA), NewNull(), dboEqual);
//Si no hay facturas en el editor no las tenemos en cuenta
if (Condicion2 <> nil) then
begin
Condicion1 := NewBinaryExpression(Condicion1, Condicion2, dboAnd);
Condicion3 := NewBinaryExpression(Condicion3, Condicion2, dboAnd);
end;
// Todas aquellas facturas asociadas a la comisi<73>n actual y que no est<73>n asociadas al editor (IdFacturasAsociadas)
//esto es porque se puede agregar y quitar facturas y todos los cambios estan en cache
// y por lo tanto al pedir las facturas a seleccionar debemos tener en cuenta que en el
//almac<61>n dichos cambios cache todav<61>a no se han producido
Condicion := NewBinaryExpression(Condicion1, Condicion3, dboOr);
if IsEmpty then
Expression := Condicion
else
Expression := NewBinaryExpression(Expression, Condicion, dboAnd);
end;
finally
HideHourglassCursor;
end;
end;
function TFacturasClienteController.BuscarTodos: IBizFacturaCliente;
begin
Result := FDataModule.GetItems;
FiltrarEmpresa(Result);
end;
function TFacturasClienteController.CambiarComercial(
AFactura: IBizFacturaCliente; AComercial: IBizComercial): Boolean;
var
bEnEdicion : Boolean;
begin
if not Assigned(AFactura) then
raise Exception.Create ('AContrato no asignado');
ShowHourglassCursor;
try
bEnEdicion := (AFactura.DataTable.State in dsEditModes);
if not bEnEdicion then
AFactura.Edit;
AFactura.DataTable.Edit;
AFactura.ID_AGENTE := AComercial.ID;
AFactura.NOMBRE_AGENTE := AComercial.NOMBRE;
AFactura.DELEGACION := AComercial.DELEGACION;
if not bEnEdicion then
AFactura.Post;
finally
HideHourglassCursor;
end;
end;
procedure TFacturasClienteController.CopiarDireccion(
const ADireccionEnvio: IBizDireccionesContacto; AFactura: IBizFacturaCliente);
var
bEnEdicion : Boolean;
begin
if not Assigned(AFactura) then
raise Exception.Create ('Factura no asignado (CopiarDireccionEnvio)');
if not Assigned(ADireccionEnvio) then
raise Exception.Create ('No se ha indicado la direcci<63>n (CopiarDireccionEnvio)');
if AFactura.DataTable.Active then
AFactura.DataTable.Active := True;
if ADireccionEnvio.DataTable.Active then
ADireccionEnvio.DataTable.Active := True;
bEnEdicion := (AFactura.DataTable.State in dsEditModes);
if not bEnEdicion then
AFactura.Edit;
ShowHourglassCursor;
AFactura.Edit;
try
AFactura.CALLE := ADireccionEnvio.CALLE;
AFactura.POBLACION := ADireccionEnvio.POBLACION;
AFactura.CODIGO_POSTAL := ADireccionEnvio.CODIGO_POSTAL;
AFactura.PROVINCIA := ADireccionEnvio.PROVINCIA;
AFactura.NIF_CIF := ADireccionEnvio.NIF_CIF;
AFactura.NOMBRE := ADireccionEnvio.NOMBRE;
if not bEnEdicion then
AFactura.Post;
finally
HideHourglassCursor;
end;
end;
constructor TFacturasClienteController.Create;
begin
inherited;
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.DarListaAnosFacturas: TStringList;
begin
Result := FDataModule.GetAnosItems;
end;
function TFacturasClienteController.darTiposFacturaCliente: IBizTiposFacturaCliente;
begin
Result := FDataModule.darTiposFacturaCliente;
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 := AppFactuGES.EmpresaActiva.ID;
ID_TIENDA := AppFactuGES.TiendaActiva.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);
ID_COMISION_LIQUIDADA := 0;
FAC_PROV_GRADENIsNull := True;
{$IFDEF CONTABILIDAD}
ID_EJERCICIO := AppFactuGES.EjercicioActivo.ID;
ESTADO_EJERCICIO := AppFactuGES.EjercicioActivo.ESTADO;
ASIENTO_PUNTEADO := -1;
//En el caso de que el ejercicio este cerrado dejamos duplicar factura sin asociar a contabilidad.
if ESTADO_EJERCICIO = CTE_CERRADO then
begin
IGNORAR_CONTABILIDAD := 1;
ESTADO_EJERCICIO := '';
end;
{$ENDIF}
end;
Result.Post;
finally
HideHourglassCursor;
end;
end;
function TFacturasClienteController.ValidarFactura(AFactura: IBizFacturaCliente): Boolean;
var
AFormaPago: IBizFormaPago;
begin
Result := False;
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<63>n
// cuando se generan facturas autom<6F>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');
//En el caso de asignar una retenci<63>n a la factura ser<65> obligatorio meter la fecha de retenci<63>n.
if (AFactura.IMPORTE_RETENCION > 0) then
if (EsFechaVacia(AFactura.FECHA_RETENCION)) then
raise Exception.Create('Debe indicar la fecha de vencimiento de la retenci<63>n, para poder asociarla al recibo que contendr<64> el importe de la retenci<63>n.');
if (AFactura.Detalles.DataTable.RecordCount = 0) then
raise Exception.Create('La factura debe tener al menos un concepto en su contenido');
if (AFactura.ID_FORMA_PAGO = 0) then
raise Exception.Create('Debe indicar una forma de pago 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
//OJO-----En facturas de cliente para acana no es obligatorio porque deben de poder generar facturas sin recibos asociados
{ 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;
}
{$IFDEF CONTABILIDAD}
if (AFactura.IGNORAR_CONTABILIDAD = 0) then
begin
if (AppFactuGES.EjercicioActivo.ESTADO = CTE_CERRADO) then
raise Exception.Create('Para que la factura pueda pasar a la parte contable el ejercicio activo debe esta ABIERTO');
if ((AFactura.Cliente.SubCuentas.ID < 1) or (AFactura.Cliente.SubCuentas.ID_EJERCICIO <> AppFactuGES.EjercicioActivo.ID)) then
raise Exception.Create('Para que la factura pueda pasar la parte contable es necesario que el cliente tenga asignada una subcuenta');
end;
{$ENDIF}
//En caso de ser un Abono no podra tener un importe total positivo
if (AFactura.TIPO = CTE_TIPO_ABONO) then
if (AFactura.IMPORTE_TOTAL > 0) then
raise Exception.Create('Un abono nunca no puede tener un importe positivo, asegurese que las cantidades sean negativas');
{ Esta validaci<63>n puede saltar cuando se generan facturas autom<6F>ticamente
por albaranes o pedidos y el cliente no tiene Tipo de IVA puesto, se cambia,
para signar autom<6F>ticamente por defecto a la factura la primera forma de pago,
e iva disponible (CONTADO, IVA16), en la clase de negocio }
{ if (AFactura.ID_TIPO_IVA = 0) then
raise Exception.Create('Debe indicar un tipo de IVA para esta factura');}
{ Asegurarse de valores en campos "autom<6F>ticos" tanto
en MODIFICACI<43>N como en INSERCI<43>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 TFacturasClienteController.Ver(AFactura: IBizFacturaCliente);
var
AEditor : IEditorFacturaCliente;
AComentario : Variant;
begin
AEditor := NIL;
RecuperarCliente(AFactura);
CreateEditor('EditorFacturaCliente', IEditorFacturaCliente, AEditor);
if Assigned(AEditor) then
try
AEditor.Controller := Self; //OJO ORDEN MUY IMPORTANTE
AEditor.Factura := AFactura;
//MODO CONSULTAR
if not EsModificable(AFactura, AComentario) then
begin
SetDataTableReadOnly(AFactura.DataTable, True);
AEditor.ReadOnly := True;
AEditor.Comentario := AComentario;
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 TFacturasClienteController.VerTodos(AFacturas: IBizFacturaCliente);
var
AEditor : IEditorFacturasCliente;
begin
AEditor := NIL;
CreateEditor('EditorFacturasCliente', IEditorFacturasCliente, AEditor);
if Assigned(AEditor) then
with AEditor do
begin
Controller := Self; //OJO ORDEN MUY IMPORTANTE
Facturas := AFacturas;
MultiSelect := True;
ShowEmbedded;
end;
end;
function TFacturasClienteController._Vacio: IBizFacturaCliente;
begin
Result := Buscar(ID_NULO);
end;
function TFacturasClienteController.Eliminar(const ID: Integer): Boolean;
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]));
Result := Eliminar(AFactura);
AFactura := NIL;
end;
function TFacturasClienteController.ElegirFacturas(AFacturas: IBizFacturaCliente; AMensaje: String;
AMultiSelect: Boolean): IBizFacturaCliente;
var
AEditor : IEditorElegirFacturasCliente;
begin
Result := NIL;
CreateEditor('EditorElegirFacturasCliente', IEditorElegirFacturasCliente, 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.FacturasClienteSeleccionados;
finally
AEditor.Release;
AEditor := NIL;
end;
end;
function TFacturasClienteController.Eliminar(AFactura: IBizFacturaCliente; AllItems: Boolean = false; AListaCausas: TStringList = nil): Boolean;
//Solo devolver<65> true en el caso de eliminar todos y cada uno de los elementos a eliminar
var
bEliminado: Boolean;
ACausa: Variant;
begin
bEliminado := True;
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 tanto si es una lista de facturas a eliminar como si es la propia lista del editor.
if not EsEliminable(AFactura, ACausa) then
begin
if Assigned(AListaCausas) then
AListaCausas.Add(Format('%d=%s', [AFactura.ID, ACausa]));
bEliminado := False;
end
else
AFactura.Delete;
//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 not EsEliminable(AFactura, ACausa) then
begin
if Assigned(AListaCausas) then
AListaCausas.Add(Format('%d=%s', [AFactura.ID, ACausa]));
bEliminado := False;
Next;
end
else
AFactura.Delete;
end;
end;
end;
try
AFactura.DataTable.ApplyUpdates;
Result := bEliminado;
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;
finally
HideHourglassCursor;
end;
end;
function TFacturasClienteController.EsEliminable(AFactura: IBizFacturaCliente; var AComentario: Variant): Boolean;
begin
Result := True;
if not Assigned(AFactura) then
raise Exception.Create ('Factura no asignado: EsEliminable');
if (AFactura.SITUACION <> CTE_PENDIENTE) then
begin
Result := False;
AComentario := 'La factura esta parcial o totalmente pagada, por lo que no puede ser eliminada';
end;
if not AFactura.FAC_PROV_GRADENIsNull then
begin
Result := False;
AComentario := 'La factura esta generada en Graden como factura de proveedor, elimine primero esa factura';
end;
{
else if (AFactura.ESTADO_EJERCICIO = CTE_CERRADO) then
begin
Result := False;
AComentario := 'La factura tiene un asiento asociado en la parte contable cuyo ejercicio esta cerrado, por lo que no puede ser eliminada';
end
else if (AFactura.ASIENTO_PUNTEADO > 0) then
begin
Result := False;
AComentario := 'La factura tiene un asiento asociado en la parte contable y est<73> punteado, por lo que no puede ser eliminada';
end;
}
end;
function TFacturasClienteController.EsModificable(AFactura: IBizFacturaCliente; var AComentario: Variant): Boolean;
var
AFormaPago: IBizFormaPago;
bFacturaConRecibos: Boolean;
begin
Result := True;
AComentario := Null;
if not Assigned(AFactura) then
raise Exception.Create ('Factura no asignado: EsModificable');
bFacturaConRecibos := not AFactura.FECHA_VENCIMIENTOIsNull;
if not bFacturaConRecibos then
with TFormasPagoController.Create do
begin
try
AFormaPago := Buscar(AFactura.ID_FORMA_PAGO);
AFormaPago.DataTable.Active := True;
bFacturaConRecibos := (AFormaPago.Plazos.RecordCount > 0) ;
finally
AFormaPago := NIL;
Free;
end;
end;
if (bFacturaConRecibos and (AFactura.SITUACION <> CTE_PENDIENTE)) then
begin
Result := False;
AComentario := 'La factura esta parcial o totalmente pagada, por lo que no puede ser modificada';
end;
if not AFactura.FAC_PROV_GRADENIsNull then
begin
Result := False;
AComentario := 'La factura esta generada en Graden como factura de proveedor, elimine primero esa factura';
end;
{
else if (AFactura.ESTADO_EJERCICIO = CTE_CERRADO) then
begin
Result := False;
AComentario := 'La factura tiene un asiento asociado en la parte contable cuyo ejercicio esta cerrado, por lo que no puede ser modificada';
end
else if (AFactura.ASIENTO_PUNTEADO > 0) then
begin
Result := False;
AComentario := 'La factura tiene un asiento asociado en la parte contable y est<73> punteado, por lo que no puede ser modificada';
end;
}
end;
procedure TFacturasClienteController.RecalcularImportes(
AFactura: IBizFacturaCliente);
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<63>n en la que estamos en los detalles por que
la asignaci<63>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<61>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<63>n que ten<65>amos en los detalles.
FDetallesController.LocalizarPosicion(AFactura.Detalles, ADetallePosAct);
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
RecalcularImportes(AFactura);
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;
function TFacturasClienteController.ExtraerSeleccionados(AFacturasCliente: IBizFacturaCliente): IBizFacturaCliente;
var
ASeleccionados : IBizFacturaCliente;
begin
ASeleccionados := (Self.Buscar(ID_NULO) as IBizFacturaCliente);
CopyDataTableDA5(AFacturasCliente.DataTable, ASeleccionados.DataTable, True);
Result := ASeleccionados;
end;
procedure TFacturasClienteController.FiltrarAno(AFactura: IBizFacturaCliente; 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_FacturasClienteFECHA_FACTURA), NewConstant(FechaIni, datString), dboGreaterOrEqual);
Condicion := NewBinaryExpression(NewBinaryExpression(NewField('', fld_FacturasClienteFECHA_FACTURA), NewConstant(FechaFin, datString), dboLessOrEqual), Condicion, dboAnd);
if IsEmpty then
Expression := Condicion
else
Expression := NewBinaryExpression(Condicion, Expression, dboAnd);
end;
end;
end;
procedure TFacturasClienteController.FiltrarEmpresa(AFactura: IBizFacturaCliente);
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_FacturasClienteID_EMPRESA), NewConstant(AppFactuGES.EmpresaActiva.ID, datInteger), dboEqual);
if IsEmpty then
Expression := Condicion
else
Expression := NewBinaryExpression(Expression, Condicion, dboAnd);
end;
end;
procedure TFacturasClienteController.SetClienteController(const Value: IClientesController);
begin
FClienteController := Value;
end;
procedure TFacturasClienteController.SetDetallesController(const Value: IDetallesFacturaClienteController);
begin
FDetallesController := Value;
end;
procedure TFacturasClienteController.SetIgnorarContabilidad(AFactura: IBizFacturaCliente; const Ignorar: Integer);
var
EnEdicion: Boolean;
begin
if Assigned(AFactura) then
begin
EnEdicion := AFactura.DataTable.Editing;
if not AFactura.DataTable.Editing then
AFactura.DataTable.Edit;
AFactura.IGNORAR_CONTABILIDAD := Ignorar;
AFactura.DataTable.Post;
if EnEdicion then
AFactura.DataTable.Edit;
end;
end;
function TFacturasClienteController.Guardar(AFactura: IBizFacturaCliente): Boolean;
var
IDNuevo : Integer;
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<73>n bien.
RecalcularImportes(AFactura);
try
AFactura.DataTable.ApplyUpdates;
//Se generan los recibos autom<6F>ticamente a partir de la forma de pago
GenerarRecibos(AFactura);
Result := True;
finally
HideHourglassCursor;
end;
end;
end;
function TFacturasClienteController.Nuevo (WithInsert: Boolean = True): IBizFacturaCliente;
var
AFactura : IBizFacturaCliente;
begin
AFactura := FDataModule.NewItem;
FiltrarEmpresa(AFactura);
AFactura.DataTable.Active := True;
if WithInsert then
AFactura.Insert;
Result := AFactura;
end;
procedure TFacturasClienteController.Preview(AFactura: IBizFacturaCliente; AllItems: Boolean = false; VerLogotipo: Boolean = true);
var
AReportController : IFacturasClienteReportController;
ID_Facturas: TIntegerList;
begin
AReportController := TFacturasClienteReportController.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, VerLogotipo);
finally
AReportController := NIL;
FreeANDNIL(ID_Facturas);
end;
end;
procedure TFacturasClienteController.Print(AFactura: IBizFacturaCliente; AllItems: Boolean = false; VerLogotipo: Boolean = true);
var
AReportController : IFacturasClienteReportController;
ID_Facturas: TIntegerList;
begin
AReportController := TFacturasClienteReportController.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.Print(ID_Facturas, VerLogotipo);
finally
AReportController := NIL;
FreeANDNIL(ID_Facturas);
end;
end;
function TFacturasClienteController.GenerarAbono(AFactura: IBizFacturaCliente): IBizFacturaCliente;
begin
ShowHourglassCursor;
try
Result := Duplicar(AFactura);
//A<>ade un concepto con los datos de la factura asociada al abono
FDetallesController.AnadirDetalleFacturaAsociadaAbono(Result.Detalles, AFactura.REFERENCIA, DateToStr(AFactura.FECHA_FACTURA));
//Convierte todos los articulos de la factura a negativos por se un abono
FDetallesController.CambiarSignoDetalles(Result.Detalles);
// Hay que dejar algunos campos como si fuera una factura nueva
Result.Edit;
Result.TIPO := CTE_TIPO_ABONO;
Result.Post;
finally
HideHourglassCursor;
end;
end;
procedure TFacturasClienteController.GenerarRecibos(AFactura: IBizFacturaCliente);
var
AFormasPagoController : IFormasPagoController;
AFormaPago: IBizFormaPago;
ARecibosClienteController: IRecibosClienteController;
ARecibos: IBizRecibosCliente;
AFechaVencimiento: TDateTime;
i: Integer;
ADiaVencimiento: Integer;
ADiasMas: Integer;
BSemaforo: Boolean;
AImporteAcumulado : Double;
AImporteTotal: Double;
begin
if not Assigned(AFactura) then
Exit;
AFormasPagoController := TFormasPagoController.Create;
AFormaPago := AFormasPagoController.Buscar(AFactura.ID_FORMA_PAGO);
AFormaPago.DataTable.Active := True;
ARecibosClienteController := TRecibosClienteController.Create;
//Eliminamos todos los recibos que tuviera la factura porque sabemos que todos
//estar<61>n pendientes (solo permitiremos modificar y eliminar facturas pendientes,
//parcialmente pagadas o pagadas no
ARecibos := ARecibosClienteController.BuscarRecibosFactura(AFactura.ID);
ARecibosClienteController.EliminarTodo(ARecibos);
//Si hay retenci<63>n, se generar<61> un recibo por ese importe, y el resto se generar<61>n recibos
//seg<65>n forma de pago
AImporteTotal := AFactura.IMPORTE_TOTAL - AFactura.IMPORTE_RETENCION;
//Se cambia la l<>gica a peticion de acana, en el caso de meter una fecha de vencimiento,
//los plazos de la forma de pago no tendr<64>n efecto, se generar<61> un recibo con el 100% y fecha de vencimiento
//de la factura. (Se permitir<69> para acana poder dar de alta facturas sin recibos asociados)
With AFormaPago.Plazos.DataTable do
begin
i := 1;
AImporteAcumulado := 0;
First;
repeat
//SOLO PARA ACANA (Leer comentario anterior
if (AFormaPago.Plazos.RecordCount > 0)
or (AFactura.FECHA_VENCIMIENTO <> 0) then
begin
ARecibos := ARecibosClienteController.Nuevo;
ARecibos.Edit;
ARecibos.ID_FACTURA := AFactura.ID;
ARecibos.ID_EMPRESA := AFactura.ID_EMPRESA;
ARecibos.ID_CLIENTE := AFactura.ID_CLIENTE;
ARecibos.ID_TIENDA := AFactura.ID_TIENDA;
ARecibos.REFERENCIA := AFactura.REFERENCIA + ' - ' + IntToStr(i);
ARecibos.NOMBRE := AFactura.NOMBRE; //Es la razon social de la factura
ARecibos.CALLE := AFactura.CALLE;
ARecibos.NIF_CIF := AFactura.NIF_CIF;
ARecibos.POBLACION := AFactura.POBLACION;
ARecibos.PROVINCIA := AFactura.PROVINCIA;
ARecibos.CODIGO_POSTAL := AFactura.CODIGO_POSTAL;
ARecibos.FECHA_EMISION := AFactura.FECHA_FACTURA;
if AFormaPago.Plazos.RecordCount < 1 then
begin
ARecibos.FECHA_VENCIMIENTO := AFactura.FECHA_VENCIMIENTO;
ARecibos.IMPORTE := AImporteTotal;
AImporteAcumulado := AImporteAcumulado + ARecibos.IMPORTE;
end
else
begin
AFechaVencimiento := AFactura.FECHA_FACTURA + AFormaPago.Plazos.NUM_DIAS;
ADiasMas := 0;
BSemaforo := False;
if (AFactura.Cliente.VENCIMIENTO_FACTURAS_1 <> 0)
or (AFactura.Cliente.VENCIMIENTO_FACTURAS_2 <> 0)
or (AFactura.Cliente.VENCIMIENTO_FACTURAS_3 <> 0) then
begin
ADiaVencimiento := DayOf(AFechaVencimiento);
while (ADiaVencimiento <> AFactura.Cliente.VENCIMIENTO_FACTURAS_1)
and (ADiaVencimiento <> AFactura.Cliente.VENCIMIENTO_FACTURAS_2)
and (ADiaVencimiento <> AFactura.Cliente.VENCIMIENTO_FACTURAS_3) do
begin
if ADiaVencimiento = DaysInMonth(AFechaVencimiento) then
begin
ADiaVencimiento := 1;
//Controlamos con una variable semaforo que no nos quedemos en un bucle infinito
//intentando encontrar el dia de pago establecido para el cliente (es el caso de tener
//asignado el dia de pago 30 y llegar febrero en el que no se encuentra dicho dia, o
//tener como dia de pago los d<>as 31 y en el caso de meses de 30 dias no encontrarlo.
if BSemaforo then
begin
ADiasMas := 0;
Break
end
else
BSemaforo := True;
end
else
Inc(ADiaVencimiento);
Inc(ADiasMas);
end;
end;
AFechaVencimiento := IncDay(AFechaVencimiento, ADiasMas);
ARecibos.FECHA_VENCIMIENTO := AFechaVencimiento;
ARecibos.IMPORTE := RoundCurrency(RoundCurrency(AImporteTotal) * (AFormaPago.Plazos.PORCENTAJE / 100));
AImporteAcumulado := AImporteAcumulado + ARecibos.IMPORTE;
if (i = AFormaPago.Plazos.RecordCount) then
begin
if (AImporteAcumulado < RoundCurrency(AImporteTotal)) then
ARecibos.IMPORTE := ARecibos.IMPORTE + (RoundCurrency(AImporteTotal) - AImporteAcumulado)
else if (AImporteAcumulado > RoundCurrency(AImporteTotal)) then
ARecibos.IMPORTE := ARecibos.IMPORTE - (AImporteAcumulado - RoundCurrency(AImporteTotal));
end;
end;
ARecibos.DESCRIPCION := 'RECIBO ' + ARecibos.REFERENCIA + ' - ' + ARecibos.NOMBRE; // CifraToLetras(ARecibos.IMPORTE);
ARecibosClienteController.Guardar(ARecibos);
end;
Inc(i);
Next;
until (eof);
end;
//Si hay retenci<63>n generaremos un recibo para dicha retenci<63>n
if AFactura.IMPORTE_RETENCION > 0 then
begin
ARecibos := ARecibosClienteController.Nuevo;
ARecibos.Edit;
ARecibos.ID_FACTURA := AFactura.ID;
ARecibos.ID_EMPRESA := AFactura.ID_EMPRESA;
ARecibos.ID_CLIENTE := AFactura.ID_CLIENTE;
ARecibos.ID_TIENDA := AFactura.ID_TIENDA;
ARecibos.REFERENCIA := AFactura.REFERENCIA + ' - ' + IntToStr(i);
ARecibos.NOMBRE := AFactura.NOMBRE; //Es la razon social de la factura
ARecibos.CALLE := AFactura.CALLE;
ARecibos.NIF_CIF := AFactura.NIF_CIF;
ARecibos.POBLACION := AFactura.POBLACION;
ARecibos.PROVINCIA := AFactura.PROVINCIA;
ARecibos.CODIGO_POSTAL := AFactura.CODIGO_POSTAL;
ARecibos.FECHA_EMISION := AFactura.FECHA_FACTURA;
ARecibos.FECHA_VENCIMIENTO := AFactura.FECHA_RETENCION;
ARecibos.IMPORTE := AFactura.IMPORTE_RETENCION;
ARecibos.DESCRIPCION := 'Pago de factura de retenci<63>n ' + AFactura.REFERENCIA + ' - ' + ARecibos.NOMBRE; // CifraToLetras(ARecibos.IMPORTE);
ARecibosClienteController.Guardar(ARecibos);
end;
//Liberamos
AFormasPagoController := Nil;
AFormaPago := Nil;
ARecibosClienteController := Nil;
ARecibos := Nil;
end;
function TFacturasClienteController.GetClienteController: IClientesController;
begin
Result := FClienteController;
end;
function TFacturasClienteController.GetDetallesController: IDetallesFacturaClienteController;
begin
Result := FDetallesController;
end;
end.