2.2.4. Stored Procedures
Some parts of the business logic will be implemented by means of stored procedures.
Adding a new invoice
The procedure for adding a new invoice is quite simple:
SET TERM ^;CREATE OR ALTER PROCEDURE SP_ADD_INVOICE (INVOICE_ID INTEGER,CUSTOMER_ID INTEGER,INVOICE_DATE TIMESTAMP = CURRENT_TIMESTAMP)ASBEGININSERT INTO INVOICE (INVOICE_ID,CUSTOMER_ID,INVOICE_DATE,TOTAL_SALE,PAID)VALUES (:INVOICE_ID,:CUSTOMER_ID,:INVOICE_DATE,0,0);END^SET TERM ;^COMMENT ON PROCEDURE SP_ADD_INVOICE IS'Adding Invoice';COMMENT ON PARAMETER SP_ADD_INVOICE.INVOICE_ID IS'Invoice number';COMMENT ON PARAMETER SP_ADD_INVOICE.CUSTOMER_ID IS'Customer Id';COMMENT ON PARAMETER SP_ADD_INVOICE.INVOICE_DATE IS'Date';GRANT INSERT ON INVOICE TO PROCEDURE SP_ADD_INVOICE;
Editing an invoice
The procedure for editing an invoice is a bit more complicated. We will include a rule to block further editing of an invoice once it is paid. We will create an exception that will be raised if an attempt is made to modify a paid invoice.
CREATE EXCEPTION E_INVOICE_ALREADY_PAYED 'Change is impossible, invoice paid.';-- The stored procedure for editing an invoice:SET TERM ^;CREATE OR ALTER PROCEDURE SP_EDIT_INVOICE (INVOICE_ID INTEGER,CUSTOMER_ID INTEGER,INVOICE_DATE TIMESTAMP)ASBEGINIF (EXISTS(SELECT *FROM INVOICEWHERE INVOICE_ID = :INVOICE_IDAND PAID = 1)) THENEXCEPTION E_INVOICE_ALREADY_PAYED;UPDATE INVOICESET CUSTOMER_ID = :CUSTOMER_ID,INVOICE_DATE = :INVOICE_DATEWHERE INVOICE_ID = :INVOICE_ID;END^SET TERM ;^COMMENT ON PROCEDURE SP_EDIT_INVOICE IS'Editing invoice';COMMENT ON PARAMETER SP_EDIT_INVOICE.INVOICE_ID IS'Invoice number';COMMENT ON PARAMETER SP_EDIT_INVOICE.CUSTOMER_ID IS'Customer Id';COMMENT ON PARAMETER SP_EDIT_INVOICE.INVOICE_DATE IS'Date';GRANT SELECT,UPDATE ON INVOICE TO PROCEDURE SP_EDIT_INVOICE;
In Firebird 3.0, the
|
Deleting an invoice
The procedure SP_DELETE_INVOICE procedure checks whether the invoice is paid and raises an exception if it is:
SET TERM ^ ;CREATE OR ALTER PROCEDURE SP_DELETE_INVOICE (INVOICE_ID INTEGER)ASBEGINIF (EXISTS(SELECT * FROM INVOICEWHERE INVOICE_ID = :INVOICE_IDAND PAID = 1)) THENEXCEPTION E_INVOICE_ALREADY_PAYED;DELETE FROM INVOICE WHERE INVOICE_ID = :INVOICE_ID;END^SET TERM ;^COMMENT ON PROCEDURE SP_DELETE_INVOICE IS'Deleting invoices';GRANT SELECT,DELETE ON INVOICE TO PROCEDURE SP_DELETE_INVOICE;
In Firebird 3.0, the
|
Paying an invoice
We will add one more procedure for paying an invoice:
SET TERM ^;CREATE OR ALTER PROCEDURE SP_PAY_FOR_INVOICE (INVOICE_ID INTEGER)ASBEGINIF (EXISTS(SELECT *FROM INVOICEWHERE INVOICE_ID = :INVOICE_IDAND PAID = 1)) THENEXCEPTION E_INVOICE_ALREADY_PAYED;UPDATE INVOICESET PAID = 1WHERE INVOICE_ID = :INVOICE_ID;END^SET TERM ;^COMMENT ON PROCEDURE SP_PAY_FOR_INVOICE IS'Payment of invoices';COMMENT ON PARAMETER SP_PAY_FOR_INVOICE.INVOICE_ID IS'Invoice number';GRANT SELECT,UPDATE ON INVOICE TO PROCEDURE SP_PAY_FOR_INVOICE;
In Firebird 3.0, the
|
Invoice Line Items
Procedures for managing invoice items will check whether the invoice is paid and block any attempt to alter the line items of paid invoices. They will also correct the invoice total according to the amount of the product sold and its price.
Adding line items
The procedure for adding a line item to an invoice:
SET TERM ^;CREATE OR ALTER PROCEDURE SP_ADD_INVOICE_LINE (INVOICE_ID INTEGER,PRODUCT_ID INTEGER,QUANTITY INTEGER)ASDECLARE sale_price D_MONEY;DECLARE paid D_BOOLEAN;BEGINSELECTpaidFROMinvoiceWHEREinvoice_id = :invoice_idINTO :paid;-- It does not allow you to edit already paid invoice.IF (paid = 1) THENEXCEPTION E_INVOICE_ALREADY_PAYED;SELECTpriceFROMproductWHEREproduct_id = :product_idINTO :sale_price;INSERT INTO invoice_line (invoice_line_id,invoice_id,product_id,quantity,sale_price)VALUES (NEXT VALUE FOR gen_invoice_line_id,:invoice_id,:product_id,:quantity,:sale_price);-- Increase the amount of the account.UPDATE invoiceSET total_sale = COALESCE(total_sale, 0) + :sale_price * :quantityWHERE invoice_id = :invoice_id;END^SET TERM ;^COMMENT ON PROCEDURE SP_ADD_INVOICE_LINE IS'Adding line invoices';COMMENT ON PARAMETER SP_ADD_INVOICE_LINE.INVOICE_ID IS'Invoice number';COMMENT ON PARAMETER SP_ADD_INVOICE_LINE.PRODUCT_ID IS'Product Id';COMMENT ON PARAMETER SP_ADD_INVOICE_LINE.QUANTITY IS'Quantity';GRANT SELECT, UPDATE ON INVOICE TO PROCEDURE SP_ADD_INVOICE_LINE;GRANT SELECT ON PRODUCT TO PROCEDURE SP_ADD_INVOICE_LINE;GRANT INSERT ON INVOICE_LINE TO PROCEDURE SP_ADD_INVOICE_LINE;-- only Firebird 3.0 and aboveGRANT USAGE ON EXCEPTION E_INVOICE_ALREADY_PAYED TO PROCEDURE SP_ADD_INVOICE_LINE;GRANT USAGE ON SEQUENCE GEN_INVOICE_LINE_ID TO PROCEDURE SP_ADD_INVOICE_LINE;
Editing line items
The procedure for editing an invoice line item:
SET TERM ^;CREATE OR ALTER PROCEDURE SP_EDIT_INVOICE_LINE (INVOICE_LINE_ID INTEGER,QUANTITY INTEGER)ASDECLARE invoice_id INT;DECLARE price D_MONEY;DECLARE paid D_BOOLEAN;BEGINSELECTproduct.price,invoice.invoice_id,invoice.paidFROMinvoice_lineJOIN invoice ON invoice.invoice_id = invoice_line.invoice_idJOIN product ON product.product_id = invoice_line.product_idWHEREinvoice_line.invoice_line_id = :invoice_line_idINTO:price,:invoice_id,:paid;-- It does not allow you to edit an already paid invoice.IF (paid = 1) THENEXCEPTION E_INVOICE_ALREADY_PAYED;-- Update price and quantity.UPDATE invoice_lineSET sale_price = :price,quantity = :quantityWHERE invoice_line_id = :invoice_line_id;-- Now update the amount of the account.MERGE INTO invoiceUSING (SELECTinvoice_id,SUM(sale_price * quantity) AS total_saleFROM invoice_lineWHERE invoice_id = :invoice_idGROUP BY invoice_id) LON invoice.invoice_id = L.invoice_idWHEN MATCHED THENUPDATE SET total_sale = L.total_sale;END^SET TERM ;^COMMENT ON PROCEDURE SP_EDIT_INVOICE_LINE IS'Editing invoice line';COMMENT ON PARAMETER SP_EDIT_INVOICE_LINE.INVOICE_LINE_ID IS'Invoice line id';COMMENT ON PARAMETER SP_EDIT_INVOICE_LINE.QUANTITY IS'Quantity';GRANT SELECT,UPDATE ON INVOICE_LINE TO PROCEDURE SP_EDIT_INVOICE_LINE;GRANT SELECT,UPDATE ON INVOICE TO PROCEDURE SP_EDIT_INVOICE_LINE;GRANT SELECT ON PRODUCT TO PROCEDURE SP_EDIT_INVOICE_LINE;-- only Firebird 3.0 and aboveGRANT USAGE ON EXCEPTION E_INVOICE_ALREADY_PAYED TO PROCEDURE SP_EDIT_INVOICE_LINE;
Deleting line items
The procedure for deleting an invoice line item from an invoice:
SET TERM ^;CREATE OR ALTER PROCEDURE SP_DELETE_INVOICE_LINE (INVOICE_LINE_ID INTEGER)ASDECLARE invoice_id INT;DECLARE price D_MONEY;DECLARE quantity INT;BEGINIF (EXISTS(SELECT *FROM invoice_lineJOIN invoice ON invoice.invoice_id = invoice_line.invoice_idWHERE invoice.paid = 1AND invoice_line.invoice_line_id = :invoice_line_id)) THENEXCEPTION E_INVOICE_ALREADY_PAYED;DELETE FROM invoice_lineWHERE invoice_line.invoice_line_id = :invoice_line_idRETURNING invoice_id, quantity, sale_priceINTO invoice_id, quantity, price;-- Reduce the amount of the account.UPDATE invoiceSET total_sale = total_sale - :quantity * :priceWHERE invoice_id = :invoice_id;END^SET TERM ;^COMMENT ON PROCEDURE SP_DELETE_INVOICE_LINE IS'Deleting invoice item';COMMENT ON PARAMETER SP_DELETE_INVOICE_LINE.INVOICE_LINE_ID IS'Code invoice item';Privileges for ProceduresGRANT SELECT,DELETE ON INVOICE_LINE TO PROCEDURE SP_DELETE_INVOICE_LINE;GRANT SELECT,UPDATE ON INVOICE TO PROCEDURE SP_DELETE_INVOICE_LINE;-- only Firebird 3.0 and aboveGRANT USAGE ON EXCEPTION E_INVOICE_ALREADY_PAYED TO PROCEDURE SP_DELETE_INVOICE_LINE;
