unit uBizPresupuestosCliente; interface uses uDAInterfaces, uDADataTable, schPresupuestosClient_Intf, Classes, uBizContacto, uDBSelectionList, Controls, uBizImportesDetalleBase, uBizImportesCabeceraBase, uExceptions, uBizInformesBase, DB, uBizDocumentosAsociados; const BIZ_PRESUPUESTOCLIENTE = 'Client.PresupuestoCliente'; BIZ_DETALLESPRESUPUESTOCLIENTE = 'Client.DetallesPresupuestoCliente'; SITUACION_PENDIENTE = 'Pendiente'; SITUACION_ACEPTADO = 'Aceptado'; SITUACION_RECHAZADO = 'Rechazado'; TIPO_COCINA = 'Cocina'; TIPO_BANO = 'Baño'; TIPO_ARREGLO_C = 'Arreglo C'; TIPO_ARREGLO_B = 'Arreglo B'; TIPO_INCIDENCIA = 'Inciencia'; type IBizDetallesPresupuesto = interface(IDetallesPresupuestos) ['{7233E1B0-5B76-4AE4-AB05-4F12EF74FBDD}'] procedure CopyFrom(ADetallesPresupuesto : IBizDetallesPresupuesto); end; IBizPresupuestos = interface(IPresupuestos) ['{C699A849-3F52-486B-93AC-1EB0E6B5632F}'] function GetDetalles: IBizDetallesPresupuesto; procedure SetDetalles(Value: IBizDetallesPresupuesto); property Detalles: IBizDetallesPresupuesto read GetDetalles write SetDetalles; function GetCliente: IBizCliente; procedure SetCliente(Value: IBizCliente); property Cliente: IBizCliente read GetCliente write SetCliente; //DOCUMENTOS ASOCIADOS function GetGestorDocumentos: TGestorDocumentos; procedure SetGestorDocumentos(Value: TGestorDocumentos); property GestorDocumentos: TGestorDocumentos read GetGestorDocumentos write SetGestorDocumentos; procedure Show; procedure CopyFrom(APresupuesto : IBizPresupuestos); function ShowForSelect : TModalResult; end; TBizDetallesPresupuesto = class(TDetallesPresupuestosDataTableRules, IBizDetallesPresupuesto, IBizImportesDetalle, IBizPuntosDetalle, IBizVisibleDetalle, IBizValoradoDetalle, IParche) // PARCHE *********************** private FIsAppend : Boolean; FPosicionNueva : Integer; FPuedoLanzarEvento : Boolean; // PARCHE *********************** procedure SetCANTIDADValue(const aValue: Integer); override; procedure SetIMPORTEUNIDADValue(const aValue: Currency); override; procedure SetIMPORTETOTALValue(const aValue: Currency); override; procedure SetPUNTOSValue(const aValue: Integer); override; procedure SetIMPORTEPUNTOSValue(const aValue: Currency); override; protected procedure OnNewRecord(Sender: TDADataTable); override; procedure BeforeInsert(Sender: TDADataTable); override; procedure AfterPost(Sender: TDADataTable); override; procedure AfterInsert(Sender: TDADataTable); override; procedure AfterDelete(Sender: TDADataTable); override; procedure BeforeDelete(Sender: TDADataTable); override; // PARCHE *********************** procedure ActivarEventos; procedure DesactivarEventos; procedure Refrescar; function PuedoLanzarEvento : Boolean; public procedure CopyFrom(ADetallesPresupuesto : IBizDetallesPresupuesto); procedure RecalcularImporte; function DarSumaTotalImportes : Currency; constructor Create(aDataTable: TDADataTable); override; end; TBizPresupuestos = class(TPresupuestosDataTableRules, IBizPresupuestos, IBizImportesCabecera, ISelectedRowList, IApplyUpdateFailedException, IBizInformesAware, IBizDocumentosAsociados) private FCliente : IBizCliente; FDetalles: IBizDetallesPresupuesto; FDetallesLink: TDADataSource; FSelectedRows : TSelectedRowList; //DOCUMENTOS ASOCIADOS FGestorDocumentos: TGestorDocumentos; function GetGestorDocumentos: TGestorDocumentos; procedure SetGestorDocumentos(Value: TGestorDocumentos); procedure BeforeDelete(Sender: TDADataTable); override; procedure BeforeCancel(Sender: TDADataTable); override; protected procedure ShowApplyUpdateFailed (const Error: EDAApplyUpdateFailed); function GetDetalles: IBizDetallesPresupuesto; procedure SetDetalles(Value: IBizDetallesPresupuesto); function GetCliente: IBizCliente; procedure SetCliente(Value: IBizCliente); procedure BeforeApplyUpdates(Sender : TDADataTable; const Delta : IDADelta); procedure OnNewRecord(Sender: TDADataTable); override; function GetSelectedRows : TSelectedRowList; procedure AfterDelete(Sender: TDADataTable); override; procedure OnPostError(DataTable: TDADataTable; Error: EDatabaseError; var Action: TDataAction); override; public constructor Create(aDataTable: TDADataTable); override; destructor Destroy; override; procedure RecalcularImporte; procedure Show; function ShowForSelect : TModalResult; procedure Preview; procedure Print; procedure CopyFrom(APresupuesto : IBizPresupuestos); property Cliente: IBizCliente read GetCliente write SetCliente; property Detalles: IBizDetallesPresupuesto read GetDetalles write SetDetalles; property SelectedRows : TSelectedRowList read GetSelectedRows; //DOCUMENTOS ASOCIADOS property GestorDocumentos: TGestorDocumentos read GetGestorDocumentos write SetGestorDocumentos; end; procedure ValidarPresupuesto (const APresupuesto : IBizPresupuestos); implementation uses Windows, Dialogs, uDACDSDataTable, SysUtils, uEditorUtils, uDataModulePresupuestos, uDataModuleContactos, Variants, Math, uDataModuleBase, uDataModuleUsuarios, FactuGES_Intf, uDataTableUtils; var FMasterDeleting : Boolean; FCancelInsert : Boolean; cadena1, cadena2 : string; procedure ValidarPresupuesto (const APresupuesto : IBizPresupuestos); begin if (FloatToStr(APresupuesto.FECHAPRESUPUESTO) = '0') then raise Exception.Create('Debe indicar la fecha de este presupuesto'); if not Assigned(APresupuesto.Cliente) or (APresupuesto.Cliente.DataTable.IsEmpty) then raise Exception.Create('Debe indicar el cliente de este presupuesto'); if (FloatToStr(APresupuesto.FECHADECISION) <> '0') and (APresupuesto.SITUACION <> SITUACION_PENDIENTE) and (APresupuesto.FECHADECISION < APresupuesto.FECHAPRESUPUESTO) then raise Exception.Create('La fecha de decisición debe ser posterior a la fecha del presupuesto'); if ((APresupuesto.Tipo = TIPO_INCIDENCIA) and (APresupuesto.BASEIMPONIBLE <> 0)) then raise Exception.Create('Una incidencia debe tener importe 0 para el cliente'); if (APresupuesto.SITUACION <> SITUACION_PENDIENTE) and (FloatToStr(APresupuesto.FECHADECISION) = '0') then begin APresupuesto.Edit; APresupuesto.FECHADECISION := Date; APresupuesto.Post; end; end; procedure TBizPresupuestos.RecalcularImporte; begin RecalcularImportesCabecera(Self.DataTable, Detalles.DataTable); end; constructor TBizPresupuestos.Create(aDataTable: TDADataTable); var Ruta: Variant; begin inherited; FCliente := NIL; FDetallesLink := TDADataSource.Create(NIL); FSelectedRows := TSelectedRowList.Create(aDataTable); aDataTable.OnBeforeApplyUpdates := BeforeApplyUpdates; //DOCUMENTOS ASOCIADOS //En caso de no poder acceder a la ruta de red (Caso de dos tiendas conectadas por internet) //deshabilitamos el gestor de documentos Ruta := dmBase.darRutaDocumentos; if VarIsNull(Ruta) then FGestorDocumentos := Nil else begin FGestorDocumentos := TGestorDocumentos.Create; FGestorDocumentos.RootDocumentos := dmBase.darRutaDocumentos; aDataTable.BeforeCancel := BeforeCancel; end; end; destructor TBizPresupuestos.Destroy; begin FCliente := NIL; FDetalles := NIL; FDetallesLink.Free; FSelectedRows.Free; FreeAndNil(FGestorDocumentos); inherited; end; function TBizPresupuestos.GetDetalles: IBizDetallesPresupuesto; begin Result := FDetalles; end; function TBizPresupuestos.GetSelectedRows: TSelectedRowList; begin Result := FSelectedRows; end; procedure TBizPresupuestos.OnNewRecord(Sender: TDADataTable); begin inherited; CODIGOEMPRESA := dmBase.CodigoEmpresa; USUARIO := dmUsuarios.LoginInfo.UserID; FECHAALTA := Date; FECHAPRESUPUESTO := Date; VIGENCIAPRESUPUESTO := Date + 30; // 30 días de validez por defecto SITUACION := SITUACION_PENDIENTE; TIPO := TIPO_COCINA; CODIGO := dmPresupuestos.GetNextAutoinc; OPCION := 'OPCIÓN 1'; Self.DataTable.FieldByName('OBSERVACIONES').AsString := 'No está incluido ningún trabajo de electricidad y fontanería. Se presupuesta aparte.'; end; procedure TBizPresupuestos.Preview; begin dmPresupuestos.Preview(CODIGO); end; function TBizPresupuestos.GetCliente: IBizCliente; begin if not Assigned(FCliente) then FCliente := dmContactos.GetCliente(CODIGOCONTACTO) else if (CODIGOCONTACTO <> FCliente.Codigo) and not (FCliente.DataTable.State in dsEditModes) then dmContactos.GetContacto(FCliente, CODIGOCONTACTO); if not FCliente.DataTable.Active then FCliente.DataTable.Active := True; Result := FCliente; end; procedure TBizPresupuestos.SetCliente(Value: IBizCliente); var bEnEdicion : Boolean; begin bEnEdicion := (DataTable.State in dsEditModes); if not bEnEdicion then Edit; FCliente := Value; if Assigned(FCliente) then begin CODIGOCONTACTO := FCliente.CODIGO; Post; if bEnEdicion then Edit; end end; procedure TBizPresupuestos.SetDetalles( Value: IBizDetallesPresupuesto); begin FDetalles := Value; FDetallesLink.DataTable := Self.DataTable; FDetalles.DataTable.MasterSource := FDetallesLink; end; procedure TBizPresupuestos.Show; begin ShowEditor(IBizPresupuestos, Self, etItem); end; procedure TBizDetallesPresupuesto.ActivarEventos; begin FPuedoLanzarEvento := True; end; procedure TBizDetallesPresupuesto.AfterDelete(Sender: TDADataTable); var ACabecera : IBizImportesCabecera; begin inherited; // PARCHE ******************* if not PuedoLanzarEvento then Exit; if (not FMasterDeleting) and (not FCancelInsert) then begin ReasignarPosiciones(Self.DataTable); if Assigned(DataTable.MasterSource) and Supports(DataTable.MasterSource.DataTable, IBizImportesCabecera, ACabecera) then ACabecera.RecalcularImporte; end; FCancelInsert := False; end; procedure TBizDetallesPresupuesto.AfterInsert(Sender: TDADataTable); begin inherited; // PARCHE ******************* if not PuedoLanzarEvento then Exit; FIsAppend := DataTable.EOF; Post; // Para lanzar AfterPost y asigne posición Edit; // Para volver a dejarlo en modo de edición end; procedure TBizDetallesPresupuesto.AfterPost(Sender: TDADataTable); begin inherited; // PARCHE ******************* if not PuedoLanzarEvento then Exit; if POSICION < 0 then AsignarPosicion(Self.DataTable, FIsAppend); if NUMCONCEPTO < 0 then AsignarNumConcepto(Self.DataTable); FIsAppend := False; end; procedure TBizDetallesPresupuesto.BeforeDelete(Sender: TDADataTable); begin inherited; // PARCHE ******************* if not PuedoLanzarEvento then Exit; if (DataTable.State in dsEditModes) then DataTable.Cancel; if not FMasterDeleting then FCancelInsert := not (DataTable.MasterSource.DataTable.FieldByName('CODIGO').AsInteger = CODIGOPRESUPUESTO); end; procedure TBizDetallesPresupuesto.BeforeInsert(Sender: TDADataTable); begin inherited; // PARCHE ******************* if not PuedoLanzarEvento then Exit; if Assigned(DataTable.MasterSource) and (DataTable.MasterSource.DataTable.State in dsEditModes) then DataTable.MasterSource.DataTable.Post; if GetRecordCount = 0 then FPosicionNueva := -1 else FPosicionNueva := POSICION * (-1); end; procedure TBizDetallesPresupuesto.CopyFrom( ADetallesPresupuesto: IBizDetallesPresupuesto); begin DeleteAllTable(Self.DataTable); ADetallesPresupuesto.First; while not ADetallesPresupuesto.EOF do begin DataTable.Append; DataTable.DisableEventHandlers; try POSICION := ADetallesPresupuesto.POSICION; TIPO := ADetallesPresupuesto.TIPO; DESCRIPCION := ADetallesPresupuesto.DESCRIPCION; CANTIDAD := ADetallesPresupuesto.CANTIDAD; IMPORTEUNIDAD := ADetallesPresupuesto.IMPORTEUNIDAD; IMPORTETOTAL := ADetallesPresupuesto.IMPORTETOTAL; PUNTOS := ADetallesPresupuesto.PUNTOS; IMPORTEPUNTOS := ADetallesPresupuesto.IMPORTEPUNTOS; VISIBLE := ADetallesPresupuesto.VISIBLE; VALORADO := ADetallesPresupuesto.VALORADO; finally DataTable.EnableEventHandlers; end; DataTable.Post; ADetallesPresupuesto.Next; end; end; constructor TBizDetallesPresupuesto.Create(aDataTable: TDADataTable); begin inherited; FPosicionNueva := 1; // Los conceptos empiezan a contar en 1 // PARCHE ******************* FPuedoLanzarEvento := True; end; function TBizDetallesPresupuesto.DarSumaTotalImportes: Currency; begin Result := DarTotalDetalles(Self.DataTable, True, True); end; procedure TBizDetallesPresupuesto.DesactivarEventos; begin FPuedoLanzarEvento := False end; procedure TBizDetallesPresupuesto.OnNewRecord(Sender: TDADataTable); begin inherited; // PARCHE ******************* if not PuedoLanzarEvento then Exit; POSICION := FPosicionNueva; NUMCONCEPTO := -1; TIPO := TIPODETALLE_CONCEPTO; VISIBLE := VISIBLE_TRUE; VALORADO := VALORADO_TRUE; Self.DataTable.DisableEventHandlers; try CANTIDAD := 1; finally Self.DataTable.EnableEventHandlers; end; end; function TBizPresupuestos.ShowForSelect : TModalResult; begin Result := ShowEditor(IBizPresupuestos, Self, etSelectItems); end; procedure TBizPresupuestos.ShowApplyUpdateFailed( const Error: EDAApplyUpdateFailed); begin if (Pos(AUF_FKVIOLATION, Error.Message) > 0) then MessageBox(0, 'No se puede borrar este presupuesto porque tiene un montaje o un montaje o albarán asociado', 'Atención', MB_ICONWARNING or MB_OK); end; procedure TBizPresupuestos.BeforeDelete(Sender: TDADataTable); begin inherited; if not dmPresupuestos.PuedoEliminarPresupuesto(CODIGO) then raise Exception.Create('No se puede borrar este presupuesto porque tiene un montaje o albarán asociado'); FMasterDeleting := True; // Para que los detalles se borren de golpe y no recalcule posiciones ni totales //DOCUMENTOS ASOCIADOS if Assigned(GestorDocumentos) then begin GestorDocumentos.Directorio := CODIGO; GestorDocumentos.procesarDeleteTable; end; end; procedure TBizPresupuestos.AfterDelete(Sender: TDADataTable); begin inherited; FMasterDeleting := False; end; procedure TBizPresupuestos.Print; begin dmPresupuestos.Print(CODIGO); end; procedure TBizPresupuestos.BeforeApplyUpdates(Sender: TDADataTable; const Delta: IDADelta); var i : integer; begin for i := 0 to Delta.Count - 1 do case Delta.Changes[i].ChangeType of ctInsert, ctUpdate : ValidarPresupuesto(Self); //ctDelete : end; end; procedure TBizPresupuestos.OnPostError(DataTable: TDADataTable; Error: EDatabaseError; var Action: TDataAction); begin inherited; Action := daAbort; if (Pos(AUF_HAVEVALUE, Error.Message) > 0) then begin if (Pos('contacto', Error.Message) > 0) then MessageBox(0, 'Debe indicar el cliente de este presupuesto', 'Atención', MB_ICONWARNING or MB_OK); if (Pos('Fecha presupuesto', Error.Message) > 0) then MessageBox(0, 'Debe indicar la fecha de este presupuesto', 'Atención', MB_ICONWARNING or MB_OK); end else raise Error; end; function TBizDetallesPresupuesto.PuedoLanzarEvento: Boolean; begin Result := FPuedoLanzarEvento; end; procedure TBizDetallesPresupuesto.RecalcularImporte; begin RecalcularImporteDetalle(Self.DataTable, True, True); end; procedure TBizPresupuestos.CopyFrom(APresupuesto: IBizPresupuestos); begin DataTable.DisableEventHandlers; try if not APresupuesto.DataTable.Active then APresupuesto.DataTable.Active := True; CODIGOEMPRESA := APresupuesto.CODIGOEMPRESA; TIPO := APresupuesto.TIPO; CODIGOCONTACTO := APresupuesto.CODIGOCONTACTO; NOMBRE := APresupuesto.NOMBRE; Cliente := APresupuesto.Cliente; BASEIMPONIBLE := APresupuesto.BASEIMPONIBLE; DESCUENTO := APresupuesto.DESCUENTO; IMPORTEDESCUENTO := APresupuesto.IMPORTEDESCUENTO; IVA := APresupuesto.IVA; IMPORTEIVA := APresupuesto.IMPORTEIVA; IMPORTETOTAL := APresupuesto.IMPORTETOTAL; OBSERVACIONES := APresupuesto.OBSERVACIONES; PLAZOENTREGA := APresupuesto.PLAZOENTREGA; FORMAPAGO := APresupuesto.FORMAPAGO; finally DataTable.EnableEventHandlers; end; Post; Detalles.CopyFrom(APresupuesto.Detalles); end; procedure TBizDetallesPresupuesto.Refrescar; begin DataTable.Refresh; end; procedure TBizDetallesPresupuesto.SetCANTIDADValue(const aValue: Integer); begin if aValue = 0 then DataTable.Fields[idx_DetallesPresupuestosCANTIDAD].AsVariant := Null else inherited; end; procedure TBizDetallesPresupuesto.SetIMPORTEPUNTOSValue(const aValue: Currency); begin if aValue = 0 then DataTable.Fields[idx_DetallesPresupuestosIMPORTEPUNTOS].AsVariant := Null else inherited; end; procedure TBizDetallesPresupuesto.SetIMPORTETOTALValue(const aValue: Currency); begin if aValue = 0 then DataTable.Fields[idx_DetallesPresupuestosIMPORTETOTAL].AsVariant := Null else inherited; end; procedure TBizDetallesPresupuesto.SetIMPORTEUNIDADValue(const aValue: Currency); begin if aValue = 0 then DataTable.Fields[idx_DetallesPresupuestosIMPORTEUNIDAD].AsVariant := Null else inherited; end; procedure TBizDetallesPresupuesto.SetPUNTOSValue(const aValue: Integer); begin if aValue = 0 then DataTable.Fields[idx_DetallesPresupuestosPUNTOS].AsVariant := Null else inherited; end; procedure TBizPresupuestos.BeforeCancel(Sender: TDADataTable); begin if Assigned(GestorDocumentos) then GestorDocumentos.procesarCancelTable; end; function TBizPresupuestos.GetGestorDocumentos: TGestorDocumentos; begin if Assigned(FGestorDocumentos) then FGestorDocumentos.Directorio := CODIGO; Result := FGestorDocumentos; end; procedure TBizPresupuestos.SetGestorDocumentos(Value: TGestorDocumentos); begin FGestorDocumentos := Value; end; initialization FMasterDeleting := False; RegisterDataTableRules(BIZ_DETALLESPRESUPUESTOCLIENTE, TBizDetallesPresupuesto); RegisterDataTableRules(BIZ_PRESUPUESTOCLIENTE, TBizPresupuestos); finalization end.