CREATE TRIGGER linkTransferTightly
    AFTER INSERT ON Transfer 
BEGIN

  SELECT RAISE(FAIL, "It is not the debtor who is set to pay")
    WHERE (SELECT debtor FROM Debit WHERE billId=NEW.billId)
       != (SELECT account FROM Credit WHERE credId=NEW.credId)
    ;

  SELECT RAISE(FAIL, "Target of a debit cannot be an incoming payment")
  FROM Credit c
    JOIN Debit d ON c.credId = d.targetCredit
  WHERE c.credId = NEW.credId
    AND c.value > 0
  GROUP BY c.credId
    HAVING count(d.billId) == 0
  ;

  INSERT INTO __INTERNAL_TRIGGER_STACK
      SELECT NEW.ROWID,
          CASE remainingDebt   WHEN 0 THEN RAISE(FAIL, "Debt settled") ELSE NEW.billId END,
          CASE remainingCredit WHEN 0 THEN RAISE(FAIL, "Credit spent") ELSE NEW.credId END,
          min(remainingDebt, remainingCredit) 
      FROM (SELECT
          (SELECT value - paid FROM Debit WHERE billId=NEW.billId) AS remainingDebt, 
          (SELECT value - spent FROM Credit WHERE credId=NEW.credId) AS remainingCredit
      )
  ;

END;

CREATE TRIGGER reflectTransfer
    AFTER INSERT ON __INTERNAL_TRIGGER_STACK
    WHEN NEW.id > 0
BEGIN

  UPDATE Debit
      SET paid = paid + NEW.m
      WHERE billId = NEW.d;

  UPDATE Credit
      SET spent = spent + NEW.m
      WHERE credId = NEW.c;

  UPDATE Transfer
      SET amount = ifnull(amount,0) + NEW.m
      WHERE ROWID = NEW.id;

  UPDATE Credit
      SET value = value + NEW.m
      WHERE credId = (
          SELECT targetCredit
          FROM Debit
          WHERE billId = NEW.d
      );

  DELETE FROM __INTERNAL_TRIGGER_STACK WHERE id=NEW.id;

END;

CREATE TRIGGER refreshTransfer
    AFTER UPDATE OF amount ON Transfer
BEGIN

    DELETE FROM Transfer
        WHERE ROWID = NEW.ROWID AND amount = 0;

    UPDATE Transfer
        SET timestamp=CURRENT_TIMESTAMP
        WHERE ROWID=NEW.ROWID;   

END;