CREATE OR REPLACE PACKAGE mip_quotation_document IS -- Author : HARDYA -- Created : 15/11/2007 11:27:58 -- Purpose : Handle life-cycle of quotations -- Public type declarations --type is ; TYPE caveat_text IS VARRAY(20) OF VARCHAR2(4000); TYPE img_props IS RECORD( width NUMBER ,height NUMBER); TYPE cost_line IS RECORD( cost_description VARCHAR2(160) ,cost_price NUMBER); TYPE address IS VARRAY(7) OF VARCHAR2(160); TYPE works IS VARRAY(20) OF VARCHAR2(160); TYPE costs IS VARRAY(20) OF cost_line; TYPE caveats IS VARRAY(20) OF VARCHAR2(2000); TYPE dimensions IS VARRAY(10) OF NUMBER; TYPE quote_data IS RECORD( enquiry_ref NUMBER ,quote_ref NUMBER ,transaction_ref VARCHAR2(80) ,mprn NUMBER(30) ,supplier_address address := address(NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL) ,current_date DATE ,agent_first_name VARCHAR2(80) ,site_address address := address(NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL) ,mam VARCHAR2(80) ,quote_works works := works(NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL) ,caveat_desc_works caveat_text := caveat_text(NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL) ,lead_time NUMBER ,total_cost NUMBER ,caveat_cont_sum caveat_text := caveat_text(NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL) ,quote_costs costs := costs(NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL) ,house_length NUMBER ,house_depth NUMBER ,house_height NUMBER ,house_ventilation NUMBER ,base_length NUMBER ,base_depth NUMBER ,base_height NUMBER ,outlet_termninal_size NUMBER ,caveat_term_cond caveat_text := caveat_text(NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL) ,liquid_damage_day NUMBER ,liquid_damage_cap NUMBER ,base_dimensions dimensions := dimensions(NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL) ,base_diagram VARCHAR2(80) ,house_dimensions dimensions := dimensions(NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL) ,house_diagram VARCHAR2(80) ,module_dimensions dimensions := dimensions(NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL) ,module_reference VARCHAR2(80) ,module_diagram VARCHAR2(80) ,requested_qmax NUMBER ,module_qmax NUMBER ,module_qmin NUMBER ,module_inlet_height NUMBER ,module_outlet_height NUMBER ,module_inlet_size NUMBER ,module_outlet_size NUMBER ,module_inlet_type VARCHAR2(80) ,module_outlet_type VARCHAR2(80) ,module_inlet_orientation VARCHAR2(80) ,module_outlet_orientation VARCHAR2(80) ,meter_reference VARCHAR(80) ,existing_meter_reference VARCHAR(80) ,caveat_cont_sum_qa caveat_text := caveat_text(NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL) ,mety_code VARCHAR(80) ,svcpt_code VARCHAR(10) ,show_lifting_gear BOOLEAN); FUNCTION generate_quote_pdf(p_quote_id IN NUMBER) RETURN VARCHAR2; END mip_quotation_document; / CREATE OR REPLACE PACKAGE BODY mip_quotation_document IS TYPE t_rec_font_details IS RECORD( fontname VARCHAR2(80) ,fontsize NUMBER ,fontstyle VARCHAR2(80)); PROCEDURE pl(p_in IN VARCHAR2 ,p_line IN NUMBER DEFAULT NULL) IS BEGIN $IF mip_debug_constants.debugging $THEN mip_debug.pl(p_unit => $$PLSQL_UNIT ,p_line => p_line ,p_in => p_in); $END NULL; END pl; FUNCTION get_current_font_details RETURN t_rec_font_details IS l_rec_font_details t_rec_font_details; BEGIN l_rec_font_details.fontname := plpdf.getprintfontname; l_rec_font_details.fontsize := plpdf.getprintfontsize; l_rec_font_details.fontstyle := plpdf.getprintfontstyle; END get_current_font_details; PROCEDURE print_costs(p_description IN VARCHAR2 ,p_description_width IN NUMBER DEFAULT 70 ,p_cost IN NUMBER DEFAULT NULL ,p_border IN VARCHAR2 DEFAULT '0' ,p_suffix IN VARCHAR2 DEFAULT NULL) IS l_row_data plpdf_type.t_row_datas; l_row_width plpdf_type.t_row_widths; l_row_align plpdf_type.t_row_aligns; l_row_border plpdf_type.t_row_borders; l_row_maxline plpdf_type.t_row_maxlines; l_row_style plpdf_type.t_row_styles; BEGIN l_row_data(1) := p_description; IF p_cost IS NOT NULL THEN l_row_data(2) := TO_CHAR(p_cost ,'FML999G990D00'); ELSE l_row_data(2) := NULL; END IF; l_row_data(3) := p_suffix; l_row_width(1) := p_description_width; l_row_width(2) := 25; l_row_width(3) := 0; l_row_align(1) := 'L'; l_row_align(2) := 'R'; l_row_align(3) := 'L'; l_row_border(1) := p_border; l_row_border(2) := p_border; l_row_border(3) := p_border; plpdf.row_print2(p_data => l_row_data -- plpdf_type.t_row_datas: Data shown in the cells ,p_width => l_row_width -- plpdf_type.t_row_widths: Width of the cells ,p_align => l_row_align -- plpdf_type.t_row_aligns: Alignment of the cells ,p_border => l_row_border ,p_style => l_row_style ,p_maxline => l_row_maxline ,p_h => 4 --number default 5: Height of the cells ,p_fill => 0 --number default 0: Fill --o 0: no fill --o 1: fill with current fill color ,p_min_height => 0 --number default 0: Minimal height of row, 0 means not USE this parameter -- ,p_clipping => 0 --number default 1: Clipping text --o 0: no clipping --o 1: clipping ); END print_costs; PROCEDURE print_works(p_description IN VARCHAR2 ,p_description_width IN NUMBER DEFAULT 80 ,p_work IN VARCHAR2 DEFAULT NULL ,p_border IN VARCHAR2 DEFAULT '0') IS l_row_data plpdf_type.t_row_datas; l_row_width plpdf_type.t_row_widths; l_row_align plpdf_type.t_row_aligns; l_row_border plpdf_type.t_row_borders; l_row_maxline plpdf_type.t_row_maxlines; l_row_style plpdf_type.t_row_styles; l_rec_font_details t_rec_font_details; BEGIN l_rec_font_details := get_current_font_details; plpdf.setprintfont(p_family => l_rec_font_details.fontname ,p_style => 'B' ,p_size => l_rec_font_details.fontsize); l_row_data(1) := p_description; IF p_work IS NOT NULL THEN l_row_data(2) := p_work; END IF; l_row_width(1) := p_description_width; l_row_width(2) := 0; l_row_align(1) := 'L'; l_row_align(2) := 'L'; l_row_border(1) := p_border; l_row_border(2) := p_border; l_row_border(3) := p_border; plpdf.row_print2(p_data => l_row_data -- plpdf_type.t_row_datas: Data shown in the cells ,p_width => l_row_width -- plpdf_type.t_row_widths: Width of the cells ,p_align => l_row_align -- plpdf_type.t_row_aligns: Alignment of the cells ,p_border => l_row_border ,p_style => l_row_style ,p_maxline => l_row_maxline ,p_h => 4 --number default 5: Height of the cells ,p_fill => 0 --number default 0: Fill --o 0: no fill --o 1: fill with current fill color ,p_min_height => 0 --number default 0: Minimal height of row, 0 means not USE this parameter -- ,p_clipping => 0 --number default 1: Clipping text --o 0: no clipping --o 1: clipping ); plpdf.setprintfont(p_family => l_rec_font_details.fontname ,p_style => l_rec_font_details.fontstyle ,p_size => l_rec_font_details.fontsize); END print_works; /* function get_meter_type_code_desc --recives a meter code and returns the corresponding meter type description %param p_meter_type_code - the meter type code you want the description for */ FUNCTION get_meter_type_code_desc(p_meter_type_code VARCHAR2) RETURN VARCHAR2 IS --Meter Description CURSOR c_get_meter_type_desc(cp_metertypecode VARCHAR2) IS SELECT description FROM meter_types WHERE code = cp_metertypecode; l_meter_type_desc meter_types.description%TYPE; --The description of the meter BEGIN IF NOT c_get_meter_type_desc%ISOPEN THEN OPEN c_get_meter_type_desc(p_meter_type_code); END IF; FETCH c_get_meter_type_desc INTO l_meter_type_desc; CLOSE c_get_meter_type_desc; RETURN l_meter_type_desc; END get_meter_type_code_desc; /* PROCEDURE print_caveats --Prints the supplied caveats to the current PLPDF page %param p_caveats - an array of caveat paragraphs to print %param p_vertical_offset - how far down the page we start printing %param p_line_spacing - the line spacing to use, defaults to 4 %param p_line_breaks - the number or line breaks between caveat texts */ PROCEDURE print_caveats(p_caveats IN caveat_text ,p_vertical_offset IN NUMBER ,p_line_spacing IN NUMBER := 4 ,p_line_breaks IN NUMBER := 2) IS l_caveats_counter NUMBER; l_cell_margin NUMBER; BEGIN cout_assert.isnotnull(p_vertical_offset ,p_message => 'veritcal offest null!'); --set up the screen so we can have our size 4 spacing l_cell_margin := plpdf.getcellmargin; plpdf.setleftmargin(33.7); plpdf.setcellmargin(-2); plpdf.setcurrenty(p_vertical_offset); l_caveats_counter := 1; WHILE p_caveats(l_caveats_counter) IS NOT NULL LOOP plpdf.printflowingtext(p_line_spacing ,p_caveats(l_caveats_counter)); FOR l_index IN 1 .. p_line_breaks LOOP plpdf.linebreak; END LOOP; l_caveats_counter := l_caveats_counter + 1; END LOOP; --revert back to the original screen settings plpdf.setcellmargin(l_cell_margin); plpdf.setleftmargin(31.7); END print_caveats; /* FUNCTION glue_one_line_caveat --Concats the supplied caveats into one line of text %param p_caveats - an array of caveat paragraphs to join together */ FUNCTION glue_one_line_caveat(p_caveats IN caveat_text) RETURN VARCHAR2 IS l_caveats_counter NUMBER; l_caveat_total_text VARCHAR2(5000); BEGIN l_caveats_counter := 1; WHILE p_caveats(l_caveats_counter) IS NOT NULL LOOP l_caveat_total_text := l_caveat_total_text || ' ' || p_caveats(l_caveats_counter); l_caveats_counter := l_caveats_counter + 1; END LOOP; RETURN ltrim(l_caveat_total_text); END glue_one_line_caveat; /* PROCEDURE print_one_line_caveats --Prints the supplied caveats to the current PLPDF page on one line %param p_caveats - an array of caveat paragraphs to print %param p_vertical_offset - how far down the page we start printing %param p_horizontal_offset - how far across the page we start printing %param p_line_spacing - the line spacing to use, defaults to 4 */ PROCEDURE print_one_line_caveats(p_caveats IN caveat_text ,p_vertical_offset IN NUMBER ,p_horizontal_offset IN NUMBER ,p_line_spacing IN NUMBER := 4) IS l_cell_margin NUMBER; l_caveat_total_text VARCHAR2(5000); BEGIN cout_assert.isnotnull(p_vertical_offset ,'vertical offset null!!'); cout_assert.isnotnull(p_horizontal_offset ,'horz offset null!!'); --set up the screen so we can have our size 4 spacing l_cell_margin := plpdf.getcellmargin; plpdf.setleftmargin(33.7); plpdf.setcellmargin(-2); plpdf.setcurrenty(p_vertical_offset); plpdf.setcurrentx(p_horizontal_offset); l_caveat_total_text := glue_one_line_caveat(p_caveats); plpdf.printflowingtext(p_line_spacing ,l_caveat_total_text); plpdf.linebreak; --revert back to the original screen settings plpdf.setcellmargin(l_cell_margin); plpdf.setleftmargin(31.7); END print_one_line_caveats; /* FUNCTION scale_image_dimensions --The scale_image_dimensions provides the width and height of an image to --correctly scale into a specified size. %param p_req_width - The maximum width required for the image %param p_req_height - The maximum height required for the image %param p_image_blob - The image we may need to scale down %return img_props - the new width and height of the image */ FUNCTION scale_image_dimensions(p_req_width IN NUMBER ,p_req_height IN NUMBER ,p_image_blob IN BLOB) RETURN img_props IS l_new_width NUMBER; l_ratio NUMBER; l_new_height NUMBER; l_cur_width NUMBER; l_image_props plpdf_type.t_imageprops; l_new_dimensions img_props; BEGIN --Get the properties for the image from plpdf l_image_props := plpdf_img.getimageprops(p_image_blob); --if the image is too high cut it down to the limit and record the ratio --and cutting the width by the recored ratio IF l_image_props.height > p_req_height THEN l_new_height := p_req_height; l_ratio := l_image_props.height / p_req_height; l_cur_width := l_image_props.width / l_ratio; ELSE l_new_height := l_image_props.height; l_cur_width := l_image_props.width; END IF; --if it's too wide then cut it down to the limit and record the ratio --and cutting the height by the recored ratio IF l_cur_width > p_req_width THEN l_new_width := p_req_width; l_ratio := l_cur_width / p_req_width; l_new_height := l_new_height / l_ratio; ELSE l_new_width := l_cur_width; END IF; l_new_dimensions.width := l_new_width; l_new_dimensions.height := l_new_height; RETURN l_new_dimensions; END scale_image_dimensions; /* FUNCTION get_drawing --The get_drawing function returns a blob of the drawing code %param p_drwg_code - the code of the drawing you want the blob of. %return blob the drawing image */ FUNCTION get_drawing(p_drwg_code VARCHAR2) RETURN BLOB IS l_blob BLOB; CURSOR c_get_drawing(cp_drwg VARCHAR2) IS SELECT blob_content FROM wwv_flow_files WHERE NAME = (SELECT uri FROM documents WHERE (SELECT docu_id FROM document_roles WHERE cp_drwg = drwg_code) = id); BEGIN IF NOT c_get_drawing%ISOPEN THEN OPEN c_get_drawing(p_drwg_code); END IF; FETCH c_get_drawing INTO l_blob; CLOSE c_get_drawing; RETURN l_blob; END get_drawing; /* FUNCTION get_mam --The get_mam function returns a meter asset manager description for the supplied region code. %param p_region_code - the code of the region you want to get the mam description of. %return varchar(80)description of the supplied regions code mam */ FUNCTION get_mam(p_region_code VARCHAR2) RETURN VARCHAR2 IS l_mam_desc VARCHAR2(80); CURSOR c_get_mam(cp_region_code VARCHAR2) IS SELECT quotation_text FROM regions WHERE code = cp_region_code; BEGIN IF NOT c_get_mam%ISOPEN THEN OPEN c_get_mam(p_region_code); END IF; FETCH c_get_mam INTO l_mam_desc; CLOSE c_get_mam; RETURN l_mam_desc; END get_mam; /* FUNCTION get_enquiry_row --The get_enquiry_row function returns an enquiry record for the supplied enquiry id. %param p_enquiry_id - the id of the enquiry you want to get a record of. %return enquiry row of the supplied enquiry id */ FUNCTION get_enquiry_row(p_enquiry_id NUMBER) RETURN enquiries%ROWTYPE IS --Enquiry data l_enqu_row enquiries%ROWTYPE; CURSOR c_get_enquiry(cp_enqu_id NUMBER) IS SELECT * FROM enquiries WHERE id = cp_enqu_id; BEGIN --get the enquiry data IF NOT c_get_enquiry%ISOPEN THEN OPEN c_get_enquiry(p_enquiry_id); END IF; FETCH c_get_enquiry INTO l_enqu_row; CLOSE c_get_enquiry; RETURN l_enqu_row; END get_enquiry_row; /* FUNCTION get_quote_row --The get_quote_row function returns a quote record for the supplied quote id. %param p_quote_id - the id of the quote you want to get a record of. %return quote row of the supplied quote id */ FUNCTION get_quote_row(p_quote_id NUMBER) RETURN quotes%ROWTYPE IS --Quote data l_quote_row quotes%ROWTYPE; CURSOR c_get_quote(cp_quote_id NUMBER) IS SELECT * FROM quotes WHERE id = cp_quote_id; BEGIN --get the quote data IF NOT c_get_quote%ISOPEN THEN OPEN c_get_quote(p_quote_id); END IF; FETCH c_get_quote INTO l_quote_row; CLOSE c_get_quote; RETURN l_quote_row; END get_quote_row; /* FUNCTION get_meter_row --The get_meter_row function returns a meter record for the supplied meter code. %param p_code - the code of the meter you want to get a record of. %return meters row of the supplied meter code */ FUNCTION get_meter_row(p_code VARCHAR2) RETURN meters%ROWTYPE IS l_meter_row meters%ROWTYPE; CURSOR c_get_meter(cp_meter_code VARCHAR2) IS SELECT * FROM meters WHERE code = cp_meter_code; BEGIN IF NOT c_get_meter%ISOPEN THEN OPEN c_get_meter(p_code); END IF; FETCH c_get_meter INTO l_meter_row; CLOSE c_get_meter; RETURN l_meter_row; END get_meter_row; /* FUNCTION get_module_row --The get_module_row function returns a module record for the supplied module code. %param p_code - the code of the module you want to get a record of. %return modules row of the supplied module code */ FUNCTION get_module_row(p_code VARCHAR2) RETURN modules%ROWTYPE IS l_module_row modules%ROWTYPE; CURSOR c_get_module(cp_module_code VARCHAR2) IS SELECT * FROM modules WHERE code = cp_module_code; BEGIN IF NOT c_get_module%ISOPEN THEN OPEN c_get_module(p_code); END IF; FETCH c_get_module INTO l_module_row; CLOSE c_get_module; RETURN l_module_row; END get_module_row; /* FUNCTION get_housing_row --The get_housing_row function returns a housing record for the supplied housing code. %param p_code - the code of the housing you want to get a record of. %return housings row of the supplied housing code */ FUNCTION get_housing_row(p_code VARCHAR2) RETURN housings%ROWTYPE IS l_housing_row housings%ROWTYPE; CURSOR c_get_housing(cp_housing_code VARCHAR2) IS SELECT * FROM housings WHERE code = cp_housing_code; BEGIN IF NOT c_get_housing%ISOPEN THEN OPEN c_get_housing(p_code); END IF; FETCH c_get_housing INTO l_housing_row; CLOSE c_get_housing; RETURN l_housing_row; END get_housing_row; /* FUNCTION get_base_row --The get_base_row function returns a base record for the supplied base code. %param p_code - the code of the base you want to get a record of. %return bases row of the supplied base code */ FUNCTION get_base_row(p_code VARCHAR2) RETURN bases%ROWTYPE IS l_base_row bases%ROWTYPE; CURSOR c_get_base(cp_base_code VARCHAR2) IS SELECT * FROM bases WHERE code = cp_base_code; BEGIN IF NOT c_get_base%ISOPEN THEN OPEN c_get_base(p_code); END IF; FETCH c_get_base INTO l_base_row; CLOSE c_get_base; RETURN l_base_row; END get_base_row; /* FUNCTION get_additional_item --The get_additional_item function returns an additional_item record for the supplied additional --item code. %param p_code - the code of the additional item you want to get a record of. %return additional_items row of the supplied item code */ FUNCTION get_additional_item(p_code VARCHAR2) RETURN additional_items%ROWTYPE IS --Additional Items l_add_item_row additional_items%ROWTYPE; CURSOR c_get_add_item(cp_additid VARCHAR2) IS SELECT * FROM additional_items WHERE code = cp_additid; BEGIN --get additional item IF NOT c_get_add_item%ISOPEN THEN OPEN c_get_add_item(p_code); END IF; FETCH c_get_add_item INTO l_add_item_row; CLOSE c_get_add_item; RETURN l_add_item_row; END get_additional_item; /* FUNCTION get_max_lead_time --The get_max lead_time function returns the contracted lead time for the provided quotation. --It takes the largest lead time of all the quotation items (modules, addons, housings bases) --hence the max bit %param p_quoteid - the id of the quote you want to get the lead time. %return number the maximum contacted lead time for the supplied quotation */ FUNCTION get_max_lead_time(p_quoteid NUMBER) RETURN NUMBER IS l_quote_item_maxlt NUMBER; CURSOR c_get_max_lead_time(cp_id NUMBER) IS SELECT MAX(lead_time) FROM quote_items WHERE qute_id = cp_id; BEGIN IF NOT c_get_max_lead_time%ISOPEN THEN OPEN c_get_max_lead_time(p_quoteid); END IF; FETCH c_get_max_lead_time INTO l_quote_item_maxlt; CLOSE c_get_max_lead_time; RETURN l_quote_item_maxlt; END get_max_lead_time; /* FUNCTION get_total_cost --The get_total_cost function returns the total cost for a quotation (excluding lifting gear) %param p_quoteid - the id of the quote you want to get the total cost for. %return number the total cost */ FUNCTION get_total_cost(p_quoteid NUMBER) RETURN NUMBER IS l_quote_total_cost NUMBER; BEGIN SELECT SUM(nvl(selling_price ,0) + nvl(delivery_price ,0)) INTO l_quote_total_cost FROM quote_items WHERE qute_id = p_quoteid AND NOT (quit_type = 'AQI' AND adit_code IN ('LIFTING GEAR')); RETURN l_quote_total_cost; END get_total_cost; /* PROCEDURE set_quote_items --This procedure sets the data for each of the items associated with the quotation. %param p_quote_data in out - The current data for this enquiry(what write our data values to) %param p_quoteid - used to list all the quote items. %param p_enqu_row - the current enquiry row to get data only available in the enquiry. */ PROCEDURE set_quote_items_data(p_quote_data IN OUT quote_data ,p_quoteid NUMBER ,p_enqu_row enquiries%ROWTYPE) IS --Enquiry type l_enqu_type_row enquiry_types%ROWTYPE; CURSOR c_get_enquiry_type(cp_enty_code VARCHAR2) IS SELECT * FROM enquiry_types WHERE code = cp_enty_code; --Quote Items CURSOR c_get_quote_item(cp_quoteid NUMBER) IS SELECT * FROM quote_items WHERE qute_id = cp_quoteid; --Module data l_module_row modules%ROWTYPE; --Additional Items l_add_item_row additional_items%ROWTYPE; l_works works := works(NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL); --list of works for the quote l_works_counter NUMBER; l_works_tidy works := works(NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL); --list of works for the quote l_works_tidy_counter NUMBER; l_costs_counter NUMBER; l_costs_tidy costs := costs(NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL); l_quote_cost_tidy_counter NUMBER; l_addons VARCHAR(300); --list of addons for the quote l_housing_row housings%ROWTYPE; l_base_row bases%ROWTYPE; l_meter_row meters%ROWTYPE; -- used to get the qmax and qmin of the meter l_total_cost NUMBER; --used to figure out the liquidated damages costs l_counter NUMBER; l_service_pressure VARCHAR2(80); --these three used to determine whether to set l_meter_type VARCHAR2(80); --the lifting gear item or not l_enqu_type VARCHAR2(80); BEGIN --get the pressure l_service_pressure := p_enqu_row.required_svcp_code; --cycle through the quote items picking up each item to store in the --p_quote_data record l_counter := 0; p_quote_data.show_lifting_gear := FALSE; --ensure by default we don't show the lifting gear caveat FOR quote_item_rec IN c_get_quote_item(p_quoteid) LOOP --get the meter type and job type (we test each line) IF NOT quote_item_rec.mety_code IS NULL THEN l_meter_type := quote_item_rec.mety_code; END IF; IF NOT quote_item_rec.enty_code IS NULL THEN l_enqu_type := quote_item_rec.enty_code; END IF; l_counter := l_counter + 1; CASE quote_item_rec.quit_type WHEN 'BQI' THEN --base item l_addons := l_addons || ', Base'; --Set the costs p_quote_data.quote_costs(l_counter).cost_description := 'Base Materials cost'; p_quote_data.quote_costs(l_counter).cost_price := quote_item_rec.selling_price; IF NOT (quote_item_rec.delivery_price IS NULL) THEN l_counter := l_counter + 1; p_quote_data.quote_costs(l_counter).cost_description := 'Base Delivery cost'; p_quote_data.quote_costs(l_counter).cost_price := quote_item_rec.delivery_price; END IF; --get base technical details p_quote_data.base_dimensions(1) := l_base_row.depth; p_quote_data.base_dimensions(2) := l_base_row.dim_a; p_quote_data.base_dimensions(3) := l_base_row.dim_b; p_quote_data.base_dimensions(4) := l_base_row.dim_c; p_quote_data.base_dimensions(5) := l_base_row.dim_d; p_quote_data.base_dimensions(6) := l_base_row.dim_e; p_quote_data.base_dimensions(7) := l_base_row.dim_f; p_quote_data.base_dimensions(8) := l_base_row.dim_g; p_quote_data.base_dimensions(9) := l_base_row.dim_h; p_quote_data.base_dimensions(10) := l_base_row.dim_i; p_quote_data.base_diagram := l_base_row.drwg_code; WHEN 'HQI' THEN --housing item l_addons := l_addons || ', Housing'; --Set up the costs p_quote_data.quote_costs(l_counter).cost_description := 'Housing Materials cost'; p_quote_data.quote_costs(l_counter).cost_price := quote_item_rec.selling_price; IF NOT (quote_item_rec.delivery_price IS NULL) THEN l_counter := l_counter + 1; p_quote_data.quote_costs(l_counter).cost_description := 'Housing Delivery cost'; p_quote_data.quote_costs(l_counter).cost_price := quote_item_rec.delivery_price; END IF; --get housing technical details p_quote_data.house_dimensions(1) := l_housing_row.dim_l; p_quote_data.house_dimensions(2) := l_housing_row.dim_w; p_quote_data.house_dimensions(3) := l_housing_row.dim_h; p_quote_data.house_dimensions(4) := l_housing_row.weight; p_quote_data.house_diagram := l_housing_row.drwg_code; WHEN 'AQI' THEN --add-on item --Get costs l_add_item_row := get_additional_item(quote_item_rec.adit_code); --only show the lifting gear/purging description, not the materials bit IF quote_item_rec.adit_code = 'LIFTING GEAR' THEN IF quote_item_rec.selling_price IS NULL THEN p_quote_data.quote_costs(l_counter).cost_description := l_add_item_row.description || ' (if required)(On Time and Materials Basis)'; ELSE p_quote_data.quote_costs(l_counter).cost_description := l_add_item_row.description; p_quote_data.quote_costs(l_counter).cost_price := quote_item_rec.selling_price; END IF; ELSIF quote_item_rec.adit_code = 'PURGING' THEN --If AH's build quote items has left the cost as null then the additional item --must be costed on time and materials (as part of purging changes '09) IF quote_item_rec.selling_price IS NULL THEN p_quote_data.quote_costs(l_counter).cost_description := l_add_item_row.description || ' (On Time and Materials Basis)'; ELSE p_quote_data.quote_costs(l_counter).cost_description := l_add_item_row.description; p_quote_data.quote_costs(l_counter).cost_price := quote_item_rec.selling_price; END IF; ELSIF quote_item_rec.adit_code <> 'AMR' THEN p_quote_data.quote_costs(l_counter).cost_description := l_add_item_row.description || ' Materials cost'; p_quote_data.quote_costs(l_counter).cost_price := quote_item_rec.selling_price; END IF; IF NOT (quote_item_rec.delivery_price IS NULL) THEN l_counter := l_counter + 1; p_quote_data.quote_costs(l_counter).cost_description := l_add_item_row.description || ' Delivery cost'; p_quote_data.quote_costs(l_counter).cost_price := quote_item_rec.delivery_price; END IF; --set the list of add-ons for this quote, but don't add lifting gear IF quote_item_rec.adit_code <> 'LIFTING GEAR' AND NOT quote_item_rec.adit_code IS NULL THEN l_addons := l_addons || ', ' || l_add_item_row.description; END IF; WHEN 'MQI' THEN --module item --get costs p_quote_data.quote_costs(l_counter).cost_description := 'Module Materials cost'; p_quote_data.quote_costs(l_counter).cost_price := quote_item_rec.selling_price; IF NOT (quote_item_rec.delivery_price IS NULL) THEN l_counter := l_counter + 1; p_quote_data.quote_costs(l_counter).cost_description := 'Module Delivery cost'; p_quote_data.quote_costs(l_counter).cost_price := quote_item_rec.delivery_price; END IF; --other module details l_module_row := get_module_row(quote_item_rec.modu_code); l_works(3) := 'Meter Type: ' || get_meter_type_code_desc(l_meter_type) || ' ' || p_quote_data.meter_reference; p_quote_data.outlet_termninal_size := l_module_row.outlet_size; --module technical details p_quote_data.module_dimensions(1) := l_module_row.dim_a; p_quote_data.module_dimensions(2) := l_module_row.dim_b; p_quote_data.module_dimensions(3) := l_module_row.dim_c; p_quote_data.module_dimensions(4) := l_module_row.dim_d; p_quote_data.module_dimensions(5) := l_module_row.dim_e; p_quote_data.module_dimensions(6) := l_module_row.dim_h; p_quote_data.module_dimensions(7) := l_module_row.inlet_height; p_quote_data.module_dimensions(8) := l_module_row.outlet_height; p_quote_data.module_dimensions(9) := l_module_row.weight; p_quote_data.module_reference := l_module_row.code; p_quote_data.meter_reference := l_module_row.metr_code; p_quote_data.module_inlet_height := l_module_row.inlet_height; p_quote_data.module_outlet_height := l_module_row.outlet_height; p_quote_data.module_inlet_size := l_module_row.inlet_size; p_quote_data.module_outlet_size := l_module_row.outlet_size; p_quote_data.module_inlet_type := l_module_row.inlet_cnty_code; p_quote_data.module_outlet_type := l_module_row.outlet_cnty_code; p_quote_data.module_inlet_orientation := l_module_row.inlet_cnor_code; p_quote_data.module_outlet_orientation := l_module_row.outlet_cnor_code; p_quote_data.module_diagram := l_module_row.drwg_code; --get meters qmax/qmin tech specs l_meter_row := get_meter_row(l_module_row.metr_code); p_quote_data.module_qmax := l_module_row.qmax; p_quote_data.module_qmin := l_meter_row.qmin; p_quote_data.mety_code := l_meter_row.mety_code; --get the min base details for this module l_base_row := get_base_row(l_module_row.bas_code); p_quote_data.base_length := l_base_row.dim_a; p_quote_data.base_depth := l_base_row.dim_b; p_quote_data.base_height := l_base_row.depth; --get the min housing details for this module l_housing_row := get_housing_row(l_module_row.hou_code); p_quote_data.house_length := l_housing_row.dim_l; p_quote_data.house_depth := l_housing_row.dim_w; p_quote_data.house_height := l_housing_row.dim_h; p_quote_data.house_ventilation := ((l_housing_row.dim_l * l_housing_row.dim_w) / 100) * 3; WHEN 'LQI' THEN --Labour cost --get costs p_quote_data.quote_costs(l_counter).cost_description := 'Labour Costs'; p_quote_data.quote_costs(l_counter).cost_price := quote_item_rec.selling_price; IF NOT (quote_item_rec.delivery_price IS NULL) THEN l_counter := l_counter + 1; p_quote_data.quote_costs(l_counter).cost_description := 'Labour Delivery cost'; p_quote_data.quote_costs(l_counter).cost_price := quote_item_rec.delivery_price; END IF; END CASE; --get existing meter if appropriate IF quote_item_rec.enty_code IS NOT NULL THEN IF quote_item_rec.enty_code <> 'INSTALL' AND quote_item_rec.enty_code <> 'STD INSTALL' THEN l_works(5) := 'Existing Meter Type: ' || p_enqu_row.existing_mesc_code || ' ' || get_meter_type_code_desc(p_enqu_row.existing_mety_code) || ', Model: ' || p_enqu_row.existing_metr_code || ', MSN: ' || p_enqu_row.existing_meter_serial_no; END IF; --if it's not an install or exchange get the existing meter type (will overwrite --current value if already set in the code above) IF quote_item_rec.enty_code NOT IN ('STD EXCHANGE' ,'EXCHANGE' ,'INSTALL' ,'STD INSTALL') THEN p_quote_data.mety_code := p_enqu_row.existing_mety_code; END IF; IF quote_item_rec.enty_code <> 'OFMAT' AND quote_item_rec.enty_code <> 'ADVERSARIAL' THEN l_total_cost := p_quote_data.total_cost; IF l_total_cost <= 1000 THEN p_quote_data.liquid_damage_day := 20; p_quote_data.liquid_damage_cap := 200; ELSE p_quote_data.liquid_damage_day := (l_total_cost / 100) * 2.5; p_quote_data.liquid_damage_cap := (l_total_cost / 100) * 25; END IF; END IF; END IF; END LOOP; --get type of enquiry to display as works type IF NOT c_get_enquiry_type%ISOPEN THEN OPEN c_get_enquiry_type(l_enqu_type); END IF; FETCH c_get_enquiry_type INTO l_enqu_type_row; CLOSE c_get_enquiry_type; l_works(1) := 'Works Type: ' || l_enqu_type_row.description; --get service pressure l_works(2) := 'Service Pressure: ' || l_service_pressure; -- --add up all the addons and format the string IF l_addons IS NOT NULL THEN l_works(4) := 'Add-Ons: ' || ltrim(l_addons ,','); END IF; --tidy up l_works so there are no blank entries --create an l_works_tidy variable and copy all --non null array entries into it l_works_counter := l_works.first; l_works_tidy_counter := 1; LOOP EXIT WHEN l_works_counter IS NULL; IF NOT l_works(l_works_counter) IS NULL THEN l_works_tidy(l_works_tidy_counter) := l_works(l_works_counter); l_works_tidy_counter := l_works_tidy_counter + 1; END IF; l_works_counter := l_works.next(l_works_counter); END LOOP; p_quote_data.quote_works := l_works_tidy; --tidy up quote costs -- -- l_costs_counter := p_quote_data.quote_costs.first; l_quote_cost_tidy_counter := 1; LOOP EXIT WHEN l_costs_counter IS NULL; IF NOT p_quote_data.quote_costs(l_costs_counter) .cost_description IS NULL THEN l_costs_tidy(l_quote_cost_tidy_counter) := p_quote_data.quote_costs(l_costs_counter); l_quote_cost_tidy_counter := l_quote_cost_tidy_counter + 1; END IF; l_costs_counter := p_quote_data.quote_costs.next(l_costs_counter); END LOOP; p_quote_data.quote_costs := l_costs_tidy; END set_quote_items_data; /* FUNCTION get_detailed_quote_data --This function should return all required data for the quotation. --The return value could be a type variable or perhaps an array? %param p_quoteid - the quotation we want to build a pdf for. %param possibly a few more params to get the required data in or change format of pdf %return return the quote data in the quote_data reocrd type */ FUNCTION get_detailed_quote_data(p_quoteid IN NUMBER) RETURN quote_data IS --Quote data l_quote_data quote_data; l_quote_row quotes%ROWTYPE; --Enquiry data l_enquiry_id NUMBER; l_enqu_row enquiries%ROWTYPE; --Address data l_addr_row v_current_party_addresses%ROWTYPE; l_supplier_id NUMBER; l_agent_id NUMBER; --The caveats --Agent Name l_agent_first_name parties.first_name%TYPE; l_agent_last_name parties.last_name%TYPE; --suppler name l_supplier_name parties.name%TYPE; --caveat counters l_dw_counter NUMBER; l_tc_counter NUMBER; l_cs_counter NUMBER; l_csqa_counter NUMBER; BEGIN --get the quote's data record l_quote_row := get_quote_row(p_quoteid); --get the enquiry data l_enquiry_id := l_quote_row.enqu_id; l_enqu_row := get_enquiry_row(l_enquiry_id); --get current supplier and agent ids for enquiry l_supplier_id := mip_enquiry.get_enquiry_role(l_enqu_row.id ,'ENQ SUPP'); l_agent_id := mip_enquiry.get_enquiry_role(l_enqu_row.id ,'ENQ OWN'); --get the latest agent address BEGIN SELECT * INTO l_addr_row FROM v_current_party_addresses WHERE id = l_agent_id AND rt_code = 'OFFICE'; EXCEPTION WHEN no_data_found THEN NULL; END; --supplier BEGIN SELECT NAME INTO l_supplier_name FROM parties WHERE id = l_supplier_id; EXCEPTION WHEN no_data_found THEN NULL; END; --agent BEGIN SELECT first_name ,last_name INTO l_agent_first_name ,l_agent_last_name FROM parties WHERE id = l_agent_id; EXCEPTION WHEN no_data_found THEN NULL; END; l_quote_data.enquiry_ref := l_enquiry_id; l_quote_data.quote_ref := l_quote_row.id; l_quote_data.transaction_ref := l_enqu_row.transaction_reference; l_quote_data.mprn := l_enqu_row.mprn; l_quote_data.supplier_address(1) := l_agent_first_name || ' ' || l_agent_last_name; l_quote_data.supplier_address(2) := l_supplier_name; l_quote_data.supplier_address(3) := l_addr_row.sub_building; l_quote_data.supplier_address(4) := l_addr_row.building; l_quote_data.supplier_address(5) := l_addr_row.street; l_quote_data.supplier_address(6) := l_addr_row.city; l_quote_data.supplier_address(7) := l_addr_row.postcode; l_quote_data.current_date := SYSDATE; l_quote_data.agent_first_name := l_agent_first_name; l_quote_data.site_address(1) := l_enqu_row.install_sub_building; l_quote_data.site_address(2) := l_enqu_row.install_building; l_quote_data.site_address(3) := l_enqu_row.install_street; l_quote_data.site_address(4) := l_enqu_row.install_city; l_quote_data.site_address(5) := l_enqu_row.install_postcode; --need get the mam l_quote_data.mam := get_mam(mip_regions.get_region_for_postcode(l_enqu_row.install_postcode)); l_quote_data.lead_time := get_max_lead_time(l_quote_row.id); l_quote_data.total_cost := get_total_cost(l_quote_row.id); l_quote_data.requested_qmax := l_enqu_row.qmax; IF l_enqu_row.required_svcp_code = 'LP' THEN l_quote_data.svcpt_code := 'LP'; ELSE l_quote_data.svcpt_code := 'MP'; END IF; --get individual quote item details set_quote_items_data(l_quote_data ,l_quote_row.id ,l_enqu_row); --get caveats l_dw_counter := 1; l_tc_counter := 1; l_cs_counter := 1; l_csqa_counter := 1; FOR rec IN (SELECT t.document_position ,t.text ,t.sort_order FROM caveat_texts t ,quote_items qi WHERE t.enty_code = l_enqu_row.enty_code AND t.mety_code = l_quote_data.mety_code AND t.svcpt_code = l_quote_data.svcpt_code AND qi.qute_id = p_quoteid AND qi.adit_code IS NULL AND t.adit_code IS NULL UNION SELECT t.document_position ,t.text ,t.sort_order FROM caveat_texts t ,quote_items qi WHERE t.enty_code = l_enqu_row.enty_code AND t.mety_code = l_quote_data.mety_code AND t.svcpt_code = l_quote_data.svcpt_code AND qi.qute_id = p_quoteid AND qi.adit_code IS NOT NULL AND t.adit_code IS NOT NULL AND t.adit_code = qi.adit_code AND regexp_like(decode(qi.selling_price ,NULL ,'NULL' ,qi.selling_price) ,t.condition) --consider the condition for this caveat (allows user to input regular expression against the cost) ORDER BY document_position ,sort_order ) LOOP CASE rec.document_position WHEN 'TERM_COND' THEN --terms and conditions/specialfeatures caveat point l_quote_data.caveat_term_cond(l_tc_counter) := rec.text; l_tc_counter := l_tc_counter + 1; WHEN 'DESC_WORK' THEN --description of works caveat point l_quote_data.caveat_desc_works(l_dw_counter) := rec.text; l_dw_counter := l_dw_counter + 1; WHEN 'CONT_SUM' THEN --description of works caveat point l_quote_data.caveat_cont_sum(l_cs_counter) := rec.text; l_cs_counter := l_cs_counter + 1; WHEN 'CONT_SUM_QA' THEN --description of works caveat point l_quote_data.caveat_cont_sum_qa(l_csqa_counter) := rec.text; l_csqa_counter := l_csqa_counter + 1; END CASE; --need to add in the condition to determine if the additional item should be --displayed or not here(ish) END LOOP; --phew, lets return all that lovely data we captured then... RETURN l_quote_data; END get_detailed_quote_data; /* PROCEDURE build_covering_letter --This procedure builds the covering letter for the quotation, it writes data --to an existing plpdf document %param p_quote_data in - The current data for this quote %param p_font - the type of font to use - typically 'Arial'. %param p_indent - the left margin measurement. %param p_vertical_offset - the top margin measurement. %param p_logo_blob - the logo(image) to display at the top of the page %param p_signature_blob - the signature(image) to display at the bottom of the page */ PROCEDURE build_covering_letter(p_quote_data IN quote_data ,p_font IN VARCHAR2 ,p_indent IN NUMBER ,p_vertical_offset IN NUMBER ,p_logo_blob BLOB ,p_signature_blob BLOB ,p_watermark_blob BLOB) IS l_note_text VARCHAR2(500); l_cell_margin NUMBER; BEGIN plpdf.newpage; --set watermark if it exists IF p_watermark_blob IS NOT NULL THEN pl('watermark IS NOT null' ,$$PLSQL_LINE); plpdf.putimage('test watermark' ,p_watermark_blob ,50 ,50 ,200 ,200); ELSE pl('watermark IS null' ,$$PLSQL_LINE); END IF; -- set margins plpdf.setleftmargin(31.7); plpdf.setrightmargin(31.7); plpdf.settopmargin(25.4); plpdf.setprintfont(p_font ,NULL ,7); -- Set header stuff up plpdf.putimage('ngmlogo' ,p_logo_blob ,p_indent ,10 ,52 ,18); plpdf.printtext(140 ,10 ,'4 Abbotts Lane '); plpdf.printtext(140 ,13 ,'Coventry'); plpdf.printtext(140 ,16 ,'CV1 4AY'); plpdf.printtext(170 ,10 ,'T +44 (0) 24 7628 6000'); plpdf.printtext(170 ,13 ,'F +44 (0) 24 7628 6022'); plpdf.printtext(170 ,16 ,'www.nationalgrid.com'); -- And Footer stuff plpdf.printtext(50 ,280 ,'National Grid Metering is the trading name for National Grid Metering Ltd.'); plpdf.printtext(50 ,283 ,'Registered Office: 1-3 Strand, London, WCZN 5EH. Registered in England and Wales, No. 3705992'); plpdf.setprintfont(p_font ,NULL ,10); -- set back to 10 pt plpdf.printtext(p_indent ,p_vertical_offset + 10 ,'Online Quotation Reference: ' || TO_CHAR(p_quote_data.enquiry_ref)); plpdf.printtext(p_indent ,p_vertical_offset + 14 ,'Customer Reference: ' || p_quote_data.transaction_ref); plpdf.printtext(p_indent ,p_vertical_offset + 18 ,'MPRN: ' || TO_CHAR(p_quote_data.mprn)); --print supplier address with no blank lines FOR addr_count IN 1 .. 7 LOOP IF NOT (p_quote_data.supplier_address(addr_count) IS NULL) THEN plpdf.printtext(p_indent ,p_vertical_offset + 22 + (addr_count * 4) ,p_quote_data.supplier_address(addr_count)); END IF; END LOOP; plpdf.printtext(p_indent ,p_vertical_offset + 58 ,'Date: ' || p_quote_data.current_date); plpdf.printtext(p_indent ,p_vertical_offset + 66 ,'Quotation Contact: Non Standard Customer Service Team'); plpdf.printtext(p_indent ,p_vertical_offset + 70 ,'Mailbox: ic.nonstandard1@uk.ngrid.com'); plpdf.printtext(p_indent ,p_vertical_offset + 74 ,'Hunt Group: 02476 286322'); plpdf.printtext(p_indent ,p_vertical_offset + 78 ,'Fax: 02476 286044'); -- -- start of letter body -- plpdf.printtext(p_indent ,p_vertical_offset + 86 ,'Dear ' || p_quote_data.agent_first_name || ','); --agent first name plpdf.setprintfont(p_font ,'B' ,10); --set bold plpdf.printtext(p_indent ,p_vertical_offset + 94 ,'Re: ' || rtrim(ltrim(p_quote_data.site_address(1) || ', ' || p_quote_data.site_address(2) || ', ' || p_quote_data.site_address(3) || ', ' || p_quote_data.site_address(4) || ', ' || p_quote_data.site_address(5) || ', ' || p_quote_data.site_address(6) || ', ' || p_quote_data.site_address(7) ,', ') ,', ')); --site address l_note_text := 'Note: National Grid Metering are a service provider working on behalf of '; l_note_text := l_note_text || p_quote_data.mam; --mam l_note_text := l_note_text || ', please direct all enquiries regarding this quote to National Grid Metering.'; l_cell_margin := plpdf.getcellmargin; plpdf.setleftmargin(33.7); plpdf.setcellmargin(-2); plpdf.setcurrenty(p_vertical_offset + 102); plpdf.printflowingtext(4 ,l_note_text); plpdf.linebreak; plpdf.linebreak; plpdf.setprintfont(p_font ,NULL ,10); --unset bold plpdf.printflowingtext(4 ,'I am pleased to provide you with a quotation for works '); plpdf.setprintfont(p_font ,'B' ,10); --set bold plpdf.printflowingtext(4 ,' on behalf of ' || p_quote_data.mam); plpdf.setprintfont(p_font ,NULL ,10); --unset bold plpdf.printflowingtext(4 ,' and in accordance with their General Conditions of Contract for Transactional Meter Works Not Exceeding 7 Bar.'); plpdf.setprintfont(p_font ,'B' ,10); --set bold plpdf.printflowingtext(4 ,' Please note, if you accept this quotation you are agreeing to be bound by the terms of the ' || p_quote_data.mam || ' and General Conditions of Contract for Transactional Meter Works Not Exceeding 7 Bar, and all subsequent work will be performed in accordance with that contract.'); -- plpdf.setcellmargin(l_cell_margin); plpdf.setleftmargin(33.7); --31.7 plpdf.setprintfont(p_font ,NULL ,10); --unset bold plpdf.linebreak; plpdf.linebreak; plpdf.printflowingtext(p_h => 4 ,p_txt => 'This quotation is produced on the basis that the information provided in the request is correct. ' || 'Your acceptance of the quotation will be taken to mean that you also accept that the stated ' || 'assumptions are correct. If it is later determined, by either party prior to works commencing on ' || 'site, that any stated assumption is significantly incorrect, National Grid Metering will determine ' || 'whether the quotation shall be varied or withdrawn. Works will only then commence if any ' || 'variation is agreed in line with the relevant General Conditions of Contract.'); plpdf.linebreak; plpdf.linebreak; plpdf.printflowingtext(p_h => 4 ,p_txt => 'To accept the quotation please submit acceptance using the Online Quotation System, as ' || 'outlined in the Rainbow Manual, or complete the enclosed Acceptance Form and return it to ' || 'the above National Grid Metering'' office.'); plpdf.linebreak; plpdf.linebreak; plpdf.printflowingtext(p_h => 4 ,p_txt => 'Please note that this quotation is valid for 90 days from the date specified in the quotation.' || ' Please use the Online Quotation Reference, which is at the top of the letter, on any future ' || 'correspondence relating to this request.'); -- plpdf.printtext(p_indent ,p_vertical_offset + 204 ,'If you have any queries, please contact the team on the number above.'); plpdf.printtext(p_indent ,p_vertical_offset + 212 ,'Yours sincerely'); --put on signature plpdf.putimage('signature' ,p_signature_blob ,p_indent ,248 ,44 ,11); plpdf.printtext(p_indent ,p_vertical_offset + 230 ,'Hilary Parry'); plpdf.printtext(p_indent ,p_vertical_offset + 234 ,'Order Fulfilment Manager'); plpdf.printtext(p_indent ,p_vertical_offset + 238 ,'Customer Operations'); plpdf.printtext(p_indent ,p_vertical_offset + 242 ,'National Grid Metering'); END build_covering_letter; /* PROCEDURE build_costs_page --This procedure builds the costs page for the quotation, it writes data --to an existing plpdf document %param p_quote_data in - The current data for this quote %param p_font - the type of font to use - typically 'Arial'. %param p_indent - the left margin measurement. %param p_vertical_offset - the top margin measurement. */ PROCEDURE build_costs_page(p_quote_data IN quote_data ,p_font IN VARCHAR2 ,p_indent IN NUMBER ,p_vertical_offset IN NUMBER ,p_watermark_blob BLOB) IS l_cost_line_counter NUMBER; l_vertical_offset_for_costs NUMBER := p_vertical_offset + 126; l_works_counter NUMBER; l_vertical_offset_for_works NUMBER := p_vertical_offset + 52; l_ybefore NUMBER := 0; --used to adjust the vertical offest after contract sum caveat l_cost_totals_offset NUMBER; --used to position the cost totals after the cost line items l_caveat_desc_works_offset NUMBER; --used to position caveat_desc_works as running calculation in --function parameter causes error on pdf BEGIN --Page 2 plpdf.newpage; --set watermark if it exists IF p_watermark_blob IS NOT NULL THEN plpdf.putimage('test watermark' ,p_watermark_blob ,50 ,50 ,200 ,200); END IF; -- set margins plpdf.setleftmargin(31.7); plpdf.setrightmargin(31.7); plpdf.settopmargin(25.4); plpdf.setprintfont(p_font ,'B' ,10); --set bold plpdf.printtext(p_indent ,p_vertical_offset + 10 ,'QUOTATION'); plpdf.setprintfont(p_font ,NULL ,10); --unset bold plpdf.printtext(p_indent ,p_vertical_offset + 18 ,'Online Quotation Reference: ' || TO_CHAR(p_quote_data.enquiry_ref)); plpdf.printtext(p_indent ,p_vertical_offset + 22 ,'Customer Reference: ' || p_quote_data.transaction_ref); plpdf.printtext(p_indent ,p_vertical_offset + 26 ,'MPRN: ' || TO_CHAR(p_quote_data.mprn)); plpdf.printtext(p_indent ,p_vertical_offset + 30 ,'Date: ' || p_quote_data.current_date); plpdf.setprintfont(p_font ,'B' ,10); --set bold plpdf.printtext(p_indent ,p_vertical_offset + 38 ,'Re: ' || rtrim(ltrim(p_quote_data.site_address(1) || ', ' || p_quote_data.site_address(2) || ', ' || p_quote_data.site_address(3) || ', ' || p_quote_data.site_address(4) || ', ' || p_quote_data.site_address(5) || ', ' || p_quote_data.site_address(6) || ', ' || p_quote_data.site_address(7) ,', ') ,', ')); --site address plpdf.setprintfont(p_font ,'U' ,10); --set underline plpdf.printtext(p_indent ,p_vertical_offset + 48 ,'Full Description of Works to be carried out by National Grid Metering:'); plpdf.setprintfont(p_font ,'B' ,10); --set bold l_works_counter := p_quote_data.quote_works.first; LOOP EXIT WHEN l_works_counter IS NULL; IF NOT p_quote_data.quote_works(l_works_counter) IS NULL THEN plpdf.printtext(p_indent ,l_vertical_offset_for_works + (l_works_counter * 4) ,p_quote_data.quote_works(l_works_counter)); l_caveat_desc_works_offset := l_vertical_offset_for_works + (l_works_counter * 4); END IF; l_works_counter := p_quote_data.quote_works.next(l_works_counter); END LOOP; -- DESC_WORK caveat here IF p_quote_data.caveat_desc_works IS NOT NULL THEN print_caveats(p_quote_data.caveat_desc_works ,l_caveat_desc_works_offset + 1); END IF; plpdf.setprintfont(p_font ,NULL ,10); --unset bold plpdf.printtext(p_indent ,p_vertical_offset + 106 ,'Indicative Lead Time from Acceptance to Physical Commencement: '); plpdf.setprintfont(p_font ,'B' ,10); --set bold plpdf.printtext(140 ,p_vertical_offset + 106 ,p_quote_data.lead_time || ' working days'); plpdf.setprintfont(p_font ,NULL ,10); --unset bold l_ybefore := plpdf.getcurrenty; l_vertical_offset_for_costs := l_vertical_offset_for_costs + (plpdf.getcurrenty - l_ybefore); plpdf.setprintfont(p_font ,NULL ,10); --unset bold plpdf.setcurrenty(p_vertical_offset + 114); print_costs(p_description => 'Contract sum (excluding V.A.T):' ,p_cost => p_quote_data.total_cost ,p_suffix => glue_one_line_caveat(p_quote_data.caveat_cont_sum)); -- CONT_SUM caveat here plpdf.linebreak(20); -- line break, height is 20 print_costs(p_description => 'Analysis of Costs (all costs exclude V.A.T)'); plpdf.setprintfont(p_font ,'B' ,10); --set bold plpdf.linebreak(20); -- line break, height is 20 -- l_cost_line_counter := 1; WHILE p_quote_data.quote_costs(l_cost_line_counter) .cost_description IS NOT NULL LOOP print_costs(p_description => p_quote_data.quote_costs(l_cost_line_counter) .cost_description ,p_cost => p_quote_data.quote_costs(l_cost_line_counter) .cost_price); l_cost_line_counter := l_cost_line_counter + 1; END LOOP; -- l_cost_totals_offset := l_vertical_offset_for_costs + l_cost_line_counter * 4; print_costs(p_description => 'Total costs:' ,p_cost => p_quote_data.total_cost ,p_border => 'T' ,p_suffix => glue_one_line_caveat(p_quote_data.caveat_cont_sum)); -- CONT_SUM caveat here END build_costs_page; /* PROCEDURE build_caveats_page --This procedure builds the caveats page for the quotation, it writes data --to an existing plpdf document %param p_quote_data in - The current data for this quote %param p_font - the type of font to use - typically 'Arial'. %param p_indent - the left margin measurement. %param p_vertical_offset - the top margin measurement. */ PROCEDURE build_caveats_page(p_quote_data IN quote_data ,p_font IN VARCHAR2 ,p_indent IN NUMBER ,p_vertical_offset IN NUMBER ,p_watermark_blob BLOB ,p_logger_caveat_required IN BOOLEAN) IS l_cell_margin NUMBER; BEGIN --Page 3 plpdf.newpage; --set watermark if it exists IF p_watermark_blob IS NOT NULL THEN plpdf.putimage('test watermark' ,p_watermark_blob ,50 ,50 ,200 ,200); END IF; -- set margins plpdf.setleftmargin(31.7); plpdf.setrightmargin(31.7); plpdf.settopmargin(25.4); plpdf.setprintfont(p_font ,NULL ,10); --set font to plain --house plpdf.printtext(p_indent ,p_vertical_offset + 10 ,'Meter Housing Details (if required):'); plpdf.printtext(p_indent ,p_vertical_offset + 18 ,'Length: ' || p_quote_data.house_length || ' mm'); plpdf.printtext(p_indent + 40 ,p_vertical_offset + 18 ,'Depth: ' || p_quote_data.house_depth || ' mm'); plpdf.printtext(p_indent + 80 ,p_vertical_offset + 18 ,'Height: ' || p_quote_data.house_height || ' mm'); --plpdf.PrintText(p_indent,p_vertical_offset+26,'Minimum Ventilation: '||p_quote_data.house_ventilation/10||' sq. cm'); --base plpdf.printtext(p_indent ,p_vertical_offset + 34 ,'Meter Housing Base (if required):'); plpdf.printtext(p_indent ,p_vertical_offset + 42 ,'Length: ' || p_quote_data.base_length || ' mm'); plpdf.printtext(p_indent + 40 ,p_vertical_offset + 42 ,'Depth: ' || p_quote_data.base_depth || ' mm'); plpdf.printtext(p_indent + 80 ,p_vertical_offset + 42 ,'Height: ' || p_quote_data.base_height || ' mm'); --plpdf.PrintText(p_indent,p_vertical_offset+58,'Minimum Ventilation: '||p_quote_data.outlet_termninal_size||' mm'); plpdf.printtext(p_indent ,p_vertical_offset + 58 ,'Special Features/Terms/Conditions:'); plpdf.setprintfont(p_font ,'B' ,10); --set bold -- TERM_COND caveat here IF p_quote_data.caveat_term_cond IS NOT NULL THEN print_caveats(p_quote_data.caveat_term_cond ,p_vertical_offset + 62); END IF; IF p_logger_caveat_required THEN --set up the screen so we can have our size 4 spacing l_cell_margin := plpdf.getcellmargin; plpdf.setleftmargin(33.7); plpdf.setcellmargin(-2); plpdf.printflowingtext(4 ,'This quote does not include the removal of the Datalogger. Please make the necessary arrangements with the Gas Transporter.'); --revert back to the original screen settings plpdf.setcellmargin(l_cell_margin); plpdf.setleftmargin(31.7); END IF; --the caveats will be looped in so the positioning of the the following items will --need to be dynamic (see the quote costs code above for an example) plpdf.setprintfont(p_font ,NULL ,10); --unset bold plpdf.linebreak; print_costs(p_description => 'Liquidated Damages (sum per day)(excluding V.A.T):' ,p_description_width => 100 ,p_cost => p_quote_data.liquid_damage_day); print_costs(p_description => 'Liquidated Damages (monetary cap)(excluding V.A.T):' ,p_description_width => 100 ,p_cost => p_quote_data.liquid_damage_cap); END build_caveats_page; /* PROCEDURE build_drawings_page --This procedure builds the drawings page for the quotation, it writes data --to an existing plpdf document %param p_quote_data in - The current data for this quote %param p_font - the type of font to use - typically 'Arial'. %param p_indent - the left margin measurement. %param p_vertical_offset - the top margin measurement. %param p_base_blob - the image of the base %param p_house_blob - the image of the house %param p_module_blob - the image of the module */ PROCEDURE build_drawings_page(p_quote_data IN quote_data ,p_font IN VARCHAR2 ,p_indent IN NUMBER ,p_vertical_offset IN NUMBER ,p_base_blob BLOB ,p_house_blob BLOB ,p_module_blob BLOB ,p_watermark_blob BLOB) IS l_img_props img_props; BEGIN --Okay here come the pretty pictures, the technical spec for the module, house & base --this will be page 4 for the quotation plpdf.newpage; --set watermark if it exists IF p_watermark_blob IS NOT NULL THEN plpdf.putimage('test watermark' ,p_watermark_blob ,50 ,50 ,200 ,200); END IF; -- set margins plpdf.setleftmargin(31.7); plpdf.setrightmargin(31.7); plpdf.settopmargin(25.4); plpdf.setprintfont(p_font ,'B' ,18); --set bold and 18pt plpdf.printtext(p_indent ,p_vertical_offset ,'Technical Specification for ' || p_quote_data.enquiry_ref); plpdf.setprintfont(p_font ,'B' ,10); --set back to 10pt plpdf.printtext(p_indent ,p_vertical_offset + 6 ,'Re: ' || rtrim(ltrim(p_quote_data.site_address(1) || ', ' || p_quote_data.site_address(2) || ', ' || p_quote_data.site_address(3) || ', ' || p_quote_data.site_address(4) || ', ' || p_quote_data.site_address(5) || ', ' || p_quote_data.site_address(6) || ', ' || p_quote_data.site_address(7) ,', ') ,', ')); --site address --Base Details --Base Details plpdf.setprintfont(p_font ,'BU' ,12); --set bold,underline and 12pt plpdf.printtext(p_indent ,p_vertical_offset + 12 ,'Floor Area/Base Requirements'); plpdf.setprintfont(p_font ,NULL ,10); --set back to 10pt plain plpdf.setcurrentxy(p_indent ,p_vertical_offset + 25); plpdf.printcell(15 ,6 ,'Depth:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.base_dimensions(1) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim A:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.base_dimensions(2) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim B:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.base_dimensions(3) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim C:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.base_dimensions(4) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim D:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.base_dimensions(5) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim E:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.base_dimensions(6) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim F:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.base_dimensions(7) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim G:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.base_dimensions(8) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim H:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.base_dimensions(9) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim I:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.base_dimensions(10) ,1 ,1 ,'R' ,0); IF p_base_blob IS NULL THEN plpdf.printtext(p_indent + 50 ,p_vertical_offset + 50 ,'No Base Diagram Available'); ELSE l_img_props := scale_image_dimensions(100 ,60 ,p_base_blob); plpdf.putimage('base' ,p_base_blob ,p_indent + 50 ,p_vertical_offset + 25 ,l_img_props.width ,l_img_props.height); END IF; --House Details plpdf.setprintfont(p_font ,'BU' ,12); --set bold,underline and 12pt plpdf.printtext(p_indent ,p_vertical_offset + 100 ,'Housing / Work Area'); plpdf.setprintfont(p_font ,NULL ,10); --set back to 10pt plain plpdf.setcurrentxy(p_indent ,p_vertical_offset + 108); plpdf.printcell(15 ,6 ,'Length:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.house_dimensions(1) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Width:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.house_dimensions(2) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Height:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.house_dimensions(3) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Weight:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.house_dimensions(4) ,1 ,1 ,'R' ,0); IF p_house_blob IS NULL THEN plpdf.printtext(p_indent + 50 ,p_vertical_offset + 132 ,'No Housing Diagram Available'); ELSE l_img_props := scale_image_dimensions(100 ,60 ,p_house_blob); plpdf.putimage('house' ,p_house_blob ,p_indent + 50 ,p_vertical_offset + 108 ,l_img_props.width ,l_img_props.height); END IF; --Module details plpdf.setprintfont(p_font ,'BU' ,12); --set bold,underline and 12pt plpdf.printtext(p_indent ,p_vertical_offset + 168 ,'Module Dimensions'); plpdf.setprintfont(p_font ,NULL ,10); --set back to 10pt plain plpdf.setcurrentxy(p_indent ,p_vertical_offset + 180); plpdf.printcell(15 ,6 ,'Dim A:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.module_dimensions(1) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim B:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.module_dimensions(2) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim C:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.module_dimensions(3) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim D:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.module_dimensions(4) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim E:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.module_dimensions(5) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim H:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.module_dimensions(6) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim I:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.module_dimensions(7) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Dim O:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.module_dimensions(8) ,1 ,1 ,'R' ,0); plpdf.printcell(15 ,6 ,'Weight:' ,1 ,0 ,'L' ,0); plpdf.printcell(15 ,6 ,p_quote_data.module_dimensions(9) ,1 ,1 ,'R' ,0); IF p_module_blob IS NULL THEN plpdf.printtext(p_indent + 50 ,p_vertical_offset + 205 ,'No Module Diagram Available'); ELSE l_img_props := scale_image_dimensions(100 ,60 ,p_module_blob); plpdf.putimage('module' ,p_module_blob ,p_indent + 50 ,p_vertical_offset + 180 ,l_img_props.width ,l_img_props.height); END IF; plpdf.setprintfont(p_font ,NULL ,9); --set to 9pt plpdf.printtext(p_indent ,p_vertical_offset + 245 ,'Note: All weights are in kg and all dimensions in mm Module Ref: ' || p_quote_data.module_reference); plpdf.printtext(p_indent ,p_vertical_offset + 260 ,'National Grid Metering, Abbotts Lane, Coventry, West Midlands, CV1 4AY Tel 02476 286000 Fax 02476 286022'); END build_drawings_page; /* PROCEDURE build_module_specs_page --This procedure builds the module specification page for the quotation, it writes data --to an existing plpdf document %param p_quote_data in - The current data for this quote %param p_font - the type of font to use - typically 'Arial'. %param p_indent - the left margin measurement. %param p_vertical_offset - the top margin measurement. */ PROCEDURE build_module_specs_page(p_quote_data IN quote_data ,p_font IN VARCHAR2 ,p_indent IN NUMBER ,p_vertical_offset IN NUMBER ,p_watermark_blob BLOB) IS BEGIN --this will be page 5 (part of the technical spec sheet) for the quotation plpdf.newpage; --set watermark if it exists IF p_watermark_blob IS NOT NULL THEN plpdf.putimage('test watermark' ,p_watermark_blob ,50 ,50 ,200 ,200); END IF; -- set margins plpdf.setleftmargin(31.7); plpdf.setrightmargin(31.7); plpdf.settopmargin(25.4); plpdf.setprintfont(p_font ,'B' ,18); --set bold and 18pt plpdf.printtext(p_indent ,p_vertical_offset ,'Technical Specification for ' || p_quote_data.enquiry_ref); plpdf.setprintfont(p_font ,'B' ,10); --set back to 10pt plpdf.printtext(p_indent ,p_vertical_offset + 6 ,'Re: ' || rtrim(ltrim(p_quote_data.site_address(1) || ', ' || p_quote_data.site_address(2) || ', ' || p_quote_data.site_address(3) || ', ' || p_quote_data.site_address(4) || ', ' || p_quote_data.site_address(5) || ', ' || p_quote_data.site_address(6) || ', ' || p_quote_data.site_address(7) ,', ') ,', ')); --site address plpdf.setprintfont(p_font ,NULL ,10); --set back to plain plpdf.printtext(p_indent ,p_vertical_offset + 14 ,'The supply point must be of a suitable size and capacity to provide the specified Lowest'); plpdf.printtext(p_indent ,p_vertical_offset + 18 ,'Operating Pressure(LOP-from table1) at the Emergency Control Valve(ECV) outlet'); plpdf.printtext(p_indent ,p_vertical_offset + 22 ,'under the requested Q Max load as detailed below in table 2'); --table 1 plpdf.setcurrentxy(p_indent ,p_vertical_offset + 30); plpdf.setprintfont(p_font ,'B' ,10); --set to bold plpdf.printcell(90 ,6 ,'Table 1' ,1 ,0 ,'L' ,0); plpdf.printcell(30 ,6 ,'ECV Outlet (u)' ,1 ,0 ,'C' ,0); plpdf.printcell(40 ,6 ,'Consumer Outlet (c)' ,1 ,1 ,'C' ,0); plpdf.setprintfont(p_font ,NULL ,10); --set back to plain IF p_quote_data.svcpt_code = 'LP' THEN plpdf.printcell(90 ,6 ,'Design Minimum Pressure (DMP)' ,1 ,0 ,'L' ,0); plpdf.printcell(30 ,6 ,'19 mbar' ,1 ,0 ,'C' ,0); plpdf.printcell(40 ,6 ,'15 mbar' ,1 ,1 ,'C' ,0); plpdf.printcell(90 ,6 ,'Lowest Operating Pressure (LOP)' ,1 ,0 ,'L' ,0); plpdf.printcell(30 ,6 ,'25 mbar' ,1 ,0 ,'C' ,0); plpdf.printcell(40 ,6 ,'21 mbar' ,1 ,1 ,'C' ,0); plpdf.printcell(90 ,6 ,'Pressure Tier' ,1 ,0 ,'L' ,0); plpdf.printcell(30 ,6 ,'75 mbar' ,1 ,0 ,'C' ,0); plpdf.printcell(40 ,6 ,'21 mbar' ,1 ,1 ,'C' ,0); ELSE --for MP plpdf.printcell(90 ,6 ,'Design Minimum Pressure (DMP)' ,1 ,0 ,'L' ,0); plpdf.printcell(30 ,6 ,'270 mbar' ,1 ,0 ,'C' ,0); plpdf.printcell(40 ,6 ,'21 mbar' ,1 ,1 ,'C' ,0); plpdf.printcell(90 ,6 ,'Lowest Operating Pressure (LOP)' ,1 ,0 ,'L' ,0); plpdf.printcell(30 ,6 ,'270 mbar' ,1 ,0 ,'C' ,0); plpdf.printcell(40 ,6 ,'21 mbar' ,1 ,1 ,'C' ,0); plpdf.printcell(90 ,6 ,'Pressure Tier' ,1 ,0 ,'L' ,0); plpdf.printcell(30 ,6 ,'2000 mbar' ,1 ,0 ,'C' ,0); plpdf.printcell(40 ,6 ,'21 mbar' ,1 ,1 ,'C' ,0); END IF; --table 2 plpdf.setcurrentxy(p_indent ,p_vertical_offset + 60); plpdf.setprintfont(p_font ,'B' ,10); --set to bold plpdf.printcell(90 ,6 ,'Table 2' ,1 ,0 ,'L' ,0); plpdf.printcell(70 ,6 ,'Meter Module Design' ,1 ,1 ,'C' ,0); plpdf.setprintfont(p_font ,NULL ,10); --set back to plain plpdf.printcell(90 ,6 ,'Requested Q Max (kw/h)' ,1 ,0 ,'L' ,0); plpdf.printcell(70 ,6 ,p_quote_data.requested_qmax ,1 ,1 ,'C' ,0); plpdf.printcell(90 ,6 ,'Q Max of the meter module (kw/h)' ,1 ,0 ,'L' ,0); plpdf.printcell(70 ,6 ,p_quote_data.module_qmax ,1 ,1 ,'C' ,0); plpdf.printcell(90 ,6 ,'Q Min of the meter module (kw/h)' ,1 ,0 ,'L' ,0); plpdf.printcell(70 ,6 ,p_quote_data.module_qmin ,1 ,1 ,'C' ,0); --table 3 plpdf.setcurrentxy(p_indent ,p_vertical_offset + 90); plpdf.setprintfont(p_font ,'B' ,10); --set to bold plpdf.printcell(90 ,6 ,'Table 3' ,1 ,0 ,'L' ,0); plpdf.printcell(70 ,6 ,'Module Design Parameters' ,1 ,1 ,'C' ,0); plpdf.setprintfont(p_font ,NULL ,10); --set back to plain plpdf.printmultilinecell(60 ,6 ,'Note: Inlet connection size and location details must be checked against supply point details supplied by GT to ensure compatibility ' ,1 ,'L' ,0); --Multi line cell thing is a bit annoying the printcell will not wrap to --the edge of the multi-line cell so we have to set the cursor for the --remaining parts of the table, have found a fix for this will do if we --have any time plpdf.setcurrentxy(91.7 ,p_vertical_offset + 96); plpdf.printcell(30 ,6 ,'' ,1 ,0 ,'C' ,0); plpdf.printcell(35 ,6 ,'Inlet' ,1 ,0 ,'C' ,0); plpdf.printcell(35 ,6 ,'Outlet' ,1 ,1 ,'C' ,0); plpdf.setcurrentx(91.7); plpdf.printcell(30 ,6 ,'Height' ,1 ,0 ,'C' ,0); plpdf.printcell(35 ,6 ,p_quote_data.module_inlet_height || 'mm' ,1 ,0 ,'C' ,0); plpdf.printcell(35 ,6 ,p_quote_data.module_outlet_height || 'mm' ,1 ,1 ,'C' ,0); plpdf.setcurrentx(91.7); plpdf.printcell(30 ,6 ,'Size' ,1 ,0 ,'C' ,0); plpdf.printcell(35 ,6 ,p_quote_data.module_inlet_size || 'mm' ,1 ,0 ,'C' ,0); plpdf.printcell(35 ,6 ,p_quote_data.module_outlet_size || 'mm' ,1 ,1 ,'C' ,0); plpdf.setcurrentx(91.7); plpdf.printcell(30 ,6 ,'Type' ,1 ,0 ,'C' ,0); plpdf.printcell(35 ,6 ,p_quote_data.module_inlet_type ,1 ,0 ,'C' ,0); plpdf.printcell(35 ,6 ,p_quote_data.module_outlet_type ,1 ,1 ,'C' ,0); plpdf.setcurrentx(91.7); plpdf.printcell(30 ,6 ,'Orientation' ,1 ,0 ,'C' ,0); plpdf.printcell(35 ,6 ,p_quote_data.module_inlet_orientation ,1 ,0 ,'C' ,0); plpdf.printcell(35 ,6 ,p_quote_data.module_outlet_orientation ,1 ,1 ,'C' ,0); plpdf.printtext(p_indent ,p_vertical_offset + 134 ,'The meter module offered is a single stream supply with only a nominal maintenance'); plpdf.printtext(p_indent ,p_vertical_offset + 138 ,'bypass facility. The bypass connections are for use during maintenance, and are only'); plpdf.printtext(p_indent ,p_vertical_offset + 142 ,'sized to maintain gas pressure downstream under no load conditions. Therefore'); plpdf.printtext(p_indent ,p_vertical_offset + 146 ,'during maintenance it will be necessary to disrupt supplies.'); --next para plpdf.printtext(p_indent ,p_vertical_offset + 154 ,'Electric Connections to gas meters are subject to the assesment of the hazardous'); plpdf.printtext(p_indent ,p_vertical_offset + 158 ,'area around the meter, this is largely affected by the ventilation of the housing. Should'); plpdf.printtext(p_indent ,p_vertical_offset + 162 ,'the ventilation be found to be inadequate, the connection will not be made and the'); plpdf.printtext(p_indent ,p_vertical_offset + 166 ,'requirements to allow the connection reported to you. The quotation does not include'); plpdf.printtext(p_indent ,p_vertical_offset + 170 ,'the provision of a separate instrumentation cabinet.'); plpdf.setprintfont(p_font ,NULL ,7); --set to 7 pt plpdf.printtext(p_indent ,p_vertical_offset + 178 ,'Definitions'); plpdf.printtext(p_indent ,p_vertical_offset + 182 ,'DMP - The minimum pressure that may occur at the point of reference at the time of system design flow rate under extreme gas supply conditions'); plpdf.printtext(p_indent ,p_vertical_offset + 186 ,'LOP - The lowest pressure that may occur under normal operating conditions'); plpdf.printtext(p_indent ,p_vertical_offset + 190 ,'Conversion calculations are based on an average CV of 38.4 MJ/m3'); plpdf.setprintfont(p_font ,NULL ,9); --set to 9 pt plpdf.printtext(p_indent ,p_vertical_offset + 260 ,'National Grid Metering, Abbotts Lane, Coventry, West Midlands, CV1 4AY Tel 02476 286000 Fax 02476 286022'); END build_module_specs_page; /* PROCEDURE build_acceptance_page --This procedure builds the acceptance form page for the quotation, it writes data --to an existing plpdf document %param p_quote_data in - The current data for this quote %param p_font - the type of font to use - typically 'Arial'. %param p_indent - the left margin measurement. %param p_vertical_offset - the top margin measurement. %param p_logo_blob - the logo(image) to display at the top of the page */ PROCEDURE build_acceptance_page(p_quote_data IN quote_data ,p_font IN VARCHAR2 ,p_indent IN NUMBER ,p_vertical_offset IN NUMBER ,p_logo_blob BLOB ,p_watermark_blob BLOB) IS l_vertical_offset NUMBER := 0; l_ybefore NUMBER := 0; BEGIN ---weeeeee last page plpdf.newpage; --set watermark if it exists IF p_watermark_blob IS NOT NULL THEN plpdf.putimage('test watermark' ,p_watermark_blob ,50 ,50 ,200 ,200); END IF; -- set margins plpdf.setleftmargin(31.7); plpdf.setrightmargin(31.7); plpdf.settopmargin(25.4); -- Set header stuff up plpdf.putimage('ngmlogo' ,p_logo_blob ,p_indent ,10 ,52 ,18); plpdf.setprintfont(p_font ,NULL ,7); plpdf.printtext(140 ,10 ,'4 Abbotts Lane '); plpdf.printtext(140 ,13 ,'Coventry'); plpdf.printtext(140 ,16 ,'CV1 4AY'); plpdf.printtext(170 ,10 ,'T +44 (0) 24 7628 6000'); plpdf.printtext(170 ,13 ,'F +44 (0) 24 7628 6022'); plpdf.printtext(170 ,16 ,'www.nationalgrid.com'); -- And Footer stuff plpdf.printtext(50 ,280 ,'National Grid Metering is the trading name for National Grid Metering Ltd.'); plpdf.printtext(50 ,283 ,'Registered Office: 1-3 Strand, London, WCZN 5EH. Registered in England and Wales, No. 3705992'); plpdf.setprintfont(p_font ,NULL ,10); -- big text please plpdf.printtext(p_indent ,p_vertical_offset + 10 ,'Online Quotation Reference: ' || TO_CHAR(p_quote_data.enquiry_ref)); plpdf.printtext(p_indent ,p_vertical_offset + 14 ,'Customer Reference: ' || p_quote_data.transaction_ref); plpdf.printtext(p_indent ,p_vertical_offset + 18 ,'MPRN: ' || TO_CHAR(p_quote_data.mprn)); plpdf.printtext(p_indent ,p_vertical_offset + 26 ,'F.A.O'); plpdf.printtext(p_indent ,p_vertical_offset + 30 ,'I&C Work Planning Team'); plpdf.printtext(p_indent ,p_vertical_offset + 34 ,'National Grid Metering Ltd'); plpdf.printtext(p_indent ,p_vertical_offset + 38 ,'Abbott''s Lane'); plpdf.printtext(p_indent ,p_vertical_offset + 42 ,'Coventry'); plpdf.printtext(p_indent ,p_vertical_offset + 46 ,'CV1 4AY'); plpdf.setprintfont(p_font ,'B' ,10); --set bold plpdf.printtext(p_indent ,p_vertical_offset + 54 ,'Re: ' || rtrim(ltrim(p_quote_data.site_address(1) || ', ' || p_quote_data.site_address(2) || ', ' || p_quote_data.site_address(3) || ', ' || p_quote_data.site_address(4) || ', ' || p_quote_data.site_address(5) || ', ' || p_quote_data.site_address(6) || ', ' || p_quote_data.site_address(7) ,', ') ,', ')); --site address plpdf.setprintfont(p_font ,NULL ,10); --unset bold plpdf.printtext(p_indent ,p_vertical_offset + 62 ,'Contract sum (excluding V.A.T): '); plpdf.setprintfont(p_font ,'B' ,10); --set bold plpdf.printtext(85 ,p_vertical_offset + 62 ,TO_CHAR(p_quote_data.total_cost ,'FML999999D90')); plpdf.setcurrenty(66); l_ybefore := plpdf.getcurrenty; -- CONT_SUM_QA caveat here IF p_quote_data.caveat_cont_sum_qa IS NOT NULL THEN print_one_line_caveats(p_quote_data.caveat_cont_sum_qa ,p_vertical_offset + 59 ,plpdf.getcurrenty + 40 ,4); END IF; l_vertical_offset := l_vertical_offset + (plpdf.getcurrenty - l_ybefore); plpdf.setprintfont(p_font ,NULL ,10); --unset bold plpdf.printtext(p_indent ,l_vertical_offset + 74 ,'* I confirm on behalf of my Company that I accept the above referenced quotation for the conduct'); plpdf.printtext(p_indent ,l_vertical_offset + 78 ,'of works as detailed therein, and here by certify on behalf of my Company that no additional'); plpdf.printtext(p_indent ,l_vertical_offset + 82 ,'terms and conditions (other than those set out in the quotation) are required.'); plpdf.printtext(p_indent ,l_vertical_offset + 90 ,'OR'); plpdf.printtext(p_indent ,l_vertical_offset + 98 ,'* I confirm on behalf of my Company that the above referenced quotation for the conduct or works'); plpdf.printtext(p_indent ,l_vertical_offset + 102 ,'as detailed therein is acceptable to my Company provided that (in addition to the conditions set'); plpdf.printtext(p_indent ,l_vertical_offset + 106 ,'out in the quotation [if any]) the General Conditions of Contract for Transactional Meter Works'); plpdf.printtext(p_indent ,l_vertical_offset + 110 ,'Not Exceeding 7 Bar in respect of the works are modified by the incorporation of the terms and'); plpdf.printtext(p_indent ,l_vertical_offset + 114 ,'conditions annexed hereto.'); plpdf.printtext(p_indent ,l_vertical_offset + 122 ,'(* Delete as appropriate)'); plpdf.printtext(p_indent ,l_vertical_offset + 130 ,'Save as set out above, I confirm that my Company agrees to be bound in connection with the'); plpdf.printtext(p_indent ,l_vertical_offset + 134 ,'works by the General Conditions of Contract for Transactional Meter Works Not'); plpdf.printtext(p_indent ,l_vertical_offset + 138 ,'Exceeding 7 Bar (as ammended by the quotation).'); plpdf.printtext(p_indent ,l_vertical_offset + 146 ,'Commencement'); plpdf.printtext(p_indent ,l_vertical_offset + 154 ,'Permission to organise directly with site contact'); plpdf.printtext(p_indent + 120 ,l_vertical_offset + 154 ,'Yes / No'); plpdf.printtext(p_indent ,l_vertical_offset + 162 ,'Earliest date site ready for work to commence'); plpdf.printtext(p_indent + 120 ,l_vertical_offset + 162 ,'___/___/___'); plpdf.printtext(p_indent ,l_vertical_offset + 170 ,'Anticipated date gas required on site'); plpdf.printtext(p_indent + 120 ,l_vertical_offset + 170 ,'___/___/___'); plpdf.printtext(p_indent ,l_vertical_offset + 178 ,'Signed on behalf of the Company'); plpdf.printtext(p_indent ,l_vertical_offset + 186 ,'Name:________________________________'); plpdf.printtext(p_indent + 85 ,l_vertical_offset + 186 ,'Position:____________________________'); plpdf.printtext(p_indent ,l_vertical_offset + 194 ,'Company:_____________________________'); plpdf.printtext(p_indent + 85 ,l_vertical_offset + 194 ,'Date:_______________________________'); plpdf.printtext(p_indent ,l_vertical_offset + 202 ,'Signature:_____________________________________________________________________'); END build_acceptance_page; /* FUNCTION generate_detailed_quote_pdf --The generate_detailed_quote_pdf builds the pdf document for the quotation from --the supplied data and stores the resulting pdf document in the database. %param p_quote_data - the data to build into the quote. %return - l_pdf_id the id of the pdf file we have created */ FUNCTION generate_detailed_quote_pdf(p_quote_data IN quote_data ,p_quote_id IN NUMBER) RETURN VARCHAR2 IS l_blob BLOB; l_enty_code VARCHAR2(80); --the type of enquiry l_logo_blob BLOB; l_signature_blob BLOB; l_watermark_blob BLOB; l_success BOOLEAN; --holds whether the quote was saved in the docuemnts tables or not l_base_blob BLOB; --the base drawing l_house_blob BLOB; --the house drawing l_module_blob BLOB; --the module drawing l_pdf_name VARCHAR2(90); -- the id of the quote we generate l_indent NUMBER := 31.7; l_vertical_offset NUMBER := 30; l_font VARCHAR2(40) := 'Arial'; --arial not daz l_quote_row quotes%ROWTYPE; l_enqu_row enquiries%ROWTYPE; CURSOR c_get_logo(cp_logo VARCHAR2) IS SELECT blob_content FROM wwv_flow_files WHERE filename = cp_logo; CURSOR c_get_signature(cp_signature VARCHAR2) IS SELECT blob_content FROM wwv_flow_files WHERE filename = cp_signature; CURSOR c_get_watermark(cp_watermark VARCHAR2) IS SELECT blob_content FROM wwv_flow_files WHERE filename = cp_watermark AND flow_id = apex_application.g_flow_id; BEGIN IF NOT c_get_logo%ISOPEN THEN OPEN c_get_logo('quote_logo.jpg'); END IF; FETCH c_get_logo INTO l_logo_blob; CLOSE c_get_logo; IF NOT c_get_signature%ISOPEN THEN OPEN c_get_signature('quote_signature.jpg'); END IF; FETCH c_get_signature INTO l_signature_blob; CLOSE c_get_signature; IF NOT c_get_watermark%ISOPEN THEN OPEN c_get_watermark('test_watermark.jpg'); END IF; FETCH c_get_watermark INTO l_watermark_blob; CLOSE c_get_watermark; l_quote_row := get_quote_row(p_quote_id); l_enqu_row := get_enquiry_row(l_quote_row.enqu_id); l_enty_code := l_enqu_row.enty_code; --get the quote diagrams l_base_blob := get_drawing(p_quote_data.base_diagram); l_house_blob := get_drawing(p_quote_data.house_diagram); l_module_blob := get_drawing(p_quote_data.module_diagram); -- Initialize PDF plpdf.init; --build the pages for the quote build_covering_letter(p_quote_data ,l_font ,l_indent ,l_vertical_offset ,l_logo_blob ,l_signature_blob ,l_watermark_blob); --1 build_costs_page(p_quote_data ,l_font ,l_indent ,l_vertical_offset ,l_watermark_blob); --2 --only display the data logger caveat if the user has selected it IF (l_enty_code = 'REMOVE' OR l_enty_code = 'STD REMOVE' OR l_enty_code = 'ADVERSARIAL') AND l_enqu_row.existing_logger = 'YES' THEN build_caveats_page(p_quote_data ,l_font ,l_indent ,l_vertical_offset ,l_watermark_blob ,TRUE); --3 ELSE build_caveats_page(p_quote_data ,l_font ,l_indent ,l_vertical_offset ,l_watermark_blob ,FALSE); --3 END IF; --OFMAT, Addon jobs, Std removal, removal, adversarials don't have module diagrams IF NOT (l_enty_code = 'OFMAT' OR l_enty_code = 'AMR' OR l_enty_code = 'EMS' OR l_enty_code = 'REMOVE' OR l_enty_code = 'STD REMOVE' OR l_enty_code = 'ADVERSARIAL') THEN build_drawings_page(p_quote_data ,l_font ,l_indent ,l_vertical_offset ,l_base_blob ,l_house_blob ,l_module_blob ,l_watermark_blob); --4 END IF; --No need for 2nd tech specs page for removal type jobs IF NOT (l_enty_code = 'REMOVE' OR l_enty_code = 'STD REMOVE' OR l_enty_code = 'ADVERSARIAL') THEN build_module_specs_page(p_quote_data ,l_font ,l_indent ,l_vertical_offset ,l_watermark_blob); --5 END IF; build_acceptance_page(p_quote_data ,l_font ,l_indent ,l_vertical_offset ,l_logo_blob ,l_watermark_blob); --6 --get our beautiful pdf into the local var l_blob plpdf.senddoc(l_blob); --punt the created pdf into the APEX files table INSERT INTO wwv_flow_files (NAME ,title ,mime_type ,flow_id ,doc_size ,description ,blob_content) VALUES (sys_guid() || '/quote_' || p_quote_data.quote_ref || '.pdf' ,'Quotation - ' || p_quote_data.quote_ref ,'application/pdf' ,apex_application.g_flow_id ,dbms_lob.getlength(l_blob) ,'this is an auto generated quotation from mip_quotation_document.generate_detailed_quote for quotation ' || p_quote_data.quote_ref ,l_blob) RETURNING NAME INTO l_pdf_name; --set up the file associations within our documents tables l_success := mip_files.set_file_association(l_pdf_name ,'Automatically Generated Quotation for quote ' || p_quote_data.quote_ref ,'INDO' ,'GENERATED QUOTATION' ,p_quote_data.quote_ref ,NULL ,NULL ,'QUDO'); RETURN l_pdf_name; -- return the id of the newly created blob pdf record END generate_detailed_quote_pdf; /* FUNCTION generate_quote_pdf --The generate_detailed_quote_pdf builds the pdf document for the quotation from --the supplied quote id and stores the resulting pdf document in the database. %param p_quote_id - the id of the quote you want to build a pdf for. %return - the name of the pdf file we have created. This is a unique value within the wwv_flow_files table */ FUNCTION generate_quote_pdf(p_quote_id IN NUMBER) RETURN VARCHAR2 IS l_quote_data quote_data; BEGIN l_quote_data := get_detailed_quote_data(p_quote_id); RETURN generate_detailed_quote_pdf(l_quote_data ,p_quote_id); END generate_quote_pdf; BEGIN -- Initialization NULL; END mip_quotation_document; /