Ver Mensaje Individual
  #1  
Antiguo 02-05-2013
macugi macugi is offline
Registrado
 
Registrado: ene 2007
Posts: 7
Reputación: 0
macugi Va por buen camino
Question Migrando triggers de Firebird a PostgreSQL

Hola a todos.

Antes que nada perdón por la extensión del mensaje.

Estoy creando una nueva aplicación en la cual utilizo PostgreSQL 9.2.
Estoy intentando utilizar la misma "logica" que utilizaba en Firebird, pero por lo visto no me funciona en PostgreSQL.

Tengo una tabla Master llamada Albaranes y otra Detail llamada AlbaMov. Tengo definido unos triggers con sus correspondientes funciones, los cuales me actualizan la tabla Master al modificar algo en la tabla Detail. Todo funciona perfectamente excepto cuando quiero eliminar un registro de la tabla Master.

Al eliminar un registro de la tabla Master, se eliminan todos los registros de la Detail y me actualiza un campo "Total" a 0 en la tabla Master, pero no se elimina el registro de la tabla Master. Si elimino el registro de la tabla Master sin registros en la tabla Detail, se elimina sin problemas.

He estado haciendo pruebas y he visto que el problema está en el UPDATE a la tabla Master que se hace en una funcion a la que llamo CalculoAlbaranVenta.

Este mismo sistema funciona perfectamente en Firebird.

Esta funcion devuelve una variable de tipo %ROWTYPE la cual utilizo para actualizar una pantalla en PHP.

Aqui os dejo la definicion de las tablas con sus triggers y funciones.

Saludos y gracias por adelantado.

Manuel Cuevas.

-----------------------------------<>---------------------------------
Código SQL [-]
CREATE OR REPLACE FUNCTION public."CalculoAlbaranVenta"
(
  IN  "cSerie"      public."Serie",
  IN  "nNumeroDoc"  public."NumeroDocumento"
)
RETURNS SETOF public."Totales" AS
$$
declare nBasImp "Importes";
declare nIva "Importes";
declare nRE "Importes";
declare nTotalBase "Importes";
declare nTotalIVA "Importes";
declare nTotalRE "Importes";
declare nTotalDtoBase "Importes";
declare nTotalDtoResto "Importes";
declare nTotalDtos "Importes";
declare nTotalLinea "Importes";
declare rRow RECORD;
declare rTotales "Totales"%ROWTYPE;

begin
  nBasImp        := 0;
  nIva           := 0;
  nRE            := 0;
  nTotalBase     := 0;
  nTotalIVA      := 0;
  nTotalRE       := 0;
  nTotalDtoBase  := 0;
  nTotalDtoResto := 0;
  nTotalDtos     := 0;
  nTotalLinea    := 0;
  
  FOR rRow IN SELECT "TotalUnidades", 
                     "Precio", 
                     "PorcentajeIVA", 
                     "PorcentajeRE", 
                     "DescuentoBase", 
                     "DescuentoResto"
              FROM "AlbaMov"
              WHERE ("Serie" = "cSerie") AND ("NumeroDoc" = "nNumeroDoc") AND
                    ("Referencia" IS NOT NULL)
  LOOP
    nTotalLinea    := Round((rRow."TotalUnidades" * rRow."Precio")::numeric, 3);
    nTotalDtoBase  := Round((nTotalLinea * (rRow."DescuentoBase" / 100))::numeric, 3);
    nTotalLinea    := nTotalLinea - nTotalDtoBase; 
    nTotalDtoResto := Round((nTotalLinea * (rRow."DescuentoResto" / 100))::numeric, 3);
    nTotalLinea    := nTotalLinea - nTotalDtoResto;
    nTotalDtos     := nTotalDtos + nTotalDtoBase + nTotalDtoResto; 
    
    nBasImp := Round(nTotalLinea::numeric, 2);

    nTotalBase := nTotalBase + nBasImp;
    nTotalIVA  := nTotalIVA  + (nBasImp * rRow."PorcentajeIVA" / 100);
    nTotalRE   := nTotalRE   + (nBasImp * rRow."PorcentajeRE" / 100);
    
  END LOOP;
  
  nTotalIVA  := Round(nTotalIVA::numeric, 2);
  nTotalRE   := Round(nTotalRE::numeric, 2);
  nTotalDtos := Round(nTotalDtos::numeric, 2);

  UPDATE "Albaran"
  SET "BaseImponible" = nTotalBase,
      "TotalDescuentos" = nTotalDtos,
      "IVA" = nTotalIVA,
      "RE" = nTotalRE,
      "Total" = nTotalBase + nTotalIVA + nTotalRE
  WHERE ("Serie" = "cSerie") AND ("NumeroDoc" = "nNumeroDoc");
    
  rTotales."TotalDescuentos" := nTotalDtos;
  rTotales."BaseImponible"   := nTotalBase;
  rTotales."TotalIVA"        := nTotalIVA;
  rTotales."TotalRE"         := nTotalRE;
  rTotales."Total"           := nTotalBase + nTotalIVA + nTotalRE;
  
  RETURN NEXT rTotales;
        
end
$$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 1;

CREATE OR REPLACE FUNCTION public."AlbaranBeforeDelete"()
RETURNS trigger AS
$$
begin
  DELETE FROM "AlbaMov"
  WHERE ("Serie" = OLD."Serie") AND ("NumeroDoc" = OLD."NumeroDoc");
  
  RETURN OLD;
end
$$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;

CREATE OR REPLACE FUNCTION public."AlbaranBeforeUpdate"()
RETURNS trigger AS
$$
begin

  NEW."Total" := Round((NEW."BaseImponible" + NEW."IVA" + NEW."RE")::numeric, 2);
  
  RETURN NEW;

end
$$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;

CREATE OR REPLACE FUNCTION public."AlbaMovAfterDelete"()
RETURNS trigger AS
$$
declare nTotalBase "Importes";
declare nTotalIVA "Importes";
declare nTotalRE "Importes";
declare nTotalDtoBase "Importes";
declare nTotalDtoResto "Importes";
declare nTotalDtos "Importes";
declare nTotalLinea "Importes";
declare cCliente "CodigoCliente";

begin
  PERFORM "CalculoAlbaranVenta"(OLD."Serie", OLD."NumeroDoc");

  nTotalLinea    := Round((OLD."TotalUnidades" * OLD."Precio")::numeric, 3);
  nTotalDtoBase  := Round((nTotalLinea * (OLD."DescuentoBase" / 100))::numeric, 3);
  nTotalLinea    := nTotalLinea - nTotalDtoBase; 
  nTotalDtoResto := Round((nTotalLinea * (OLD."DescuentoResto" / 100))::numeric, 3);
  nTotalLinea    := nTotalLinea - nTotalDtoResto;
  nTotalDtos     := nTotalDtos + nTotalDtoBase + nTotalDtoResto; 
    
  nTotalBase := Round(nTotalLinea::numeric, 2);
  nTotalIVA  := (nTotalBase * OLD."PorcentajeIVA" / 100);
  nTotalRE   := (nTotalBase * OLD."PorcentajeRE" / 100);

  nTotalIVA  := Round(nTotalIVA::numeric, 2);
  nTotalRE   := Round(nTotalRE::numeric, 2);
  nTotalDtos := Round(nTotalDtos::numeric, 2);

  PERFORM "SumaArticulo"(OLD."Referencia", OLD."TotalUnidades");

  SELECT "Cliente" INTO cCliente FROM "Albaran"
  WHERE ("Serie" = OLD."Serie") AND ("NumeroDoc" = OLD."NumeroDoc");

  PERFORM "RestaCliente"(cCliente, nTotalBase + nTotalIVA + nTotalRE);

  RETURN OLD;
end
$$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;


CREATE TABLE public."Albaran" (
  "NumeroDoc"        public."NumeroDocumento" NOT NULL,
  "Serie"            public."Serie" NOT NULL,
  "Fecha"            date NOT NULL,
  "Cliente"          public."CodigoCliProv" NOT NULL,
  "Nombre"           public."RazonSocial",
  "BaseImponible"    public."Importes",
  "IVA"              public."Importes",
  "RE"               public."Importes",
  "Notas"            public."Memo",
  "CodigoDir"        public."CodigoDireccion",
  "Direccion"        public."Direccion",
  "Poblacion"        public."Poblacion",
  "CodigoPostal"     public."CodigoPostal",
  "Provincia"        public."Provincia",
  "Pais"             public."Pais",
  "CIF"              public."CIF",
  "Total"            public."Importes",
  "Agente"           public."CodigoAgente",
  "SuNumeroPedido"   public."SuNumeroPedido",
  "Telefono"         public."Telefono",
  "Fax"              public."Telefono",
  "FormaPago"        public."FormaPago",
  "Transportista"    public."CodigoTransporte",
  "Repartidor"       public."CodigoRepartidor",
  "Portes"           public."Importes",
  "DebidosPagados"   public."Boolean",
  "Gastos"           public."Importes",
  "TotalDescuentos"  public."Importes",
  "TotalPesoNeto"    public."Peso",
  "TotalPesoBruto"   public."Peso",
  "Facturado"        public."Boolean",
  "Modificado"       public."Boolean"
  /* Llaves */
  CONSTRAINT "PK_Albaran"
    PRIMARY KEY ("Serie", "NumeroDoc")
) WITH (
    OIDS = FALSE
  );

CREATE INDEX "IDX_Albaran_Nombre"
  ON public."Albaran"
  ("Nombre");

CREATE TRIGGER "Albaran_BD"
  BEFORE DELETE
  ON public."Albaran"
  FOR EACH ROW
  EXECUTE PROCEDURE public."AlbaranBeforeDelete"();

CREATE TRIGGER "Albaran_BU"
  BEFORE UPDATE
  ON public."Albaran"
  FOR EACH ROW
  EXECUTE PROCEDURE public."AlbaranBeforeUpdate"();

CREATE TABLE public."AlbaMov" (
  "RecNo"              serial NOT NULL,
  "Serie"              public."Serie" NOT NULL,
  "NumeroDoc"          public."NumeroDocumento" NOT NULL,
  "Referencia"         public."CodigoArticulo" NOT NULL,
  "Descripcion"        public."Descripcion",
  "Cantidad"           public."Cantidad",
  "Precio"             public."Importes",
  "PrecioCosto"        public."Importes",
  "PorcentajeIVA"      public."Porcentaje",
  "PorcentajeRE"       public."Porcentaje",
  "Almacen"            public."CodigoAlmacen",
  "Lote"               public."Lote",
  "Unidades"           public."Cantidad",
  "TotalUnidades"      public."Cantidad",
  "CodigoPromocion"    public."CodigoArticuloOpcional",
  "Promocion"          public."Cantidad",
  "DescuentoBase"      public."Porcentaje",
  "DescuentoResto"     public."Porcentaje",
  "PesoNeto"           public."Peso",
  "PesoBruto"          public."Peso",
  "ReferenciaCliente"  public."CodigoArticuloOpcional",
  "Modificado"         public."Boolean",
  "FechaCaducidad"     date,
  "TotalLinea"         public."Importes",
  "SeriePedido"        public."Serie",
  "NumeroPedido"       public."NumeroDocumento",
  /* Llaves */
  CONSTRAINT "PK_AlbaMov"
    PRIMARY KEY ("RecNo")
) WITH (
    OIDS = FALSE
  );

CREATE INDEX "IDX_AlbaMov_SerieNumeroDoc"
  ON public."AlbaMov"
  ("Serie", "NumeroDoc", "RecNo");

CREATE TRIGGER "AlbaMov_AD"
  AFTER DELETE
  ON public."AlbaMov"
  FOR EACH ROW
  EXECUTE PROCEDURE public."AlbaMovAfterDelete"();

-----------------------------------<>---------------------------------

Última edición por Casimiro Notevi fecha: 02-05-2013 a las 12:13:20.
Responder Con Cita