Generate template for a PDF form programmatically - abap

Some retail company has 3 different business units, each of those uses 3 types of price tags:
small tags (6 columns per A4),
medium tags (3 columns per A4),
large (1 column per A4).
Early implementors of the system have created 9 different templates of price tag PDF form for this. So, any change of preferences regarding the outer appearance of price tags will result in modifications of 9 templates, which doesn't look like a good practice.
What I had in mind is to write a function module Z_COMPOSE_XML that takes in 2 parameters (business unit, size of price tag) and compose XML-schema for the template and data of PDF form, so that I will have only 1 form template instead of 9. How can I achieve this?
Just to be very clear regarding what I want to do:
I want to have a single PDF form, ZSINGLE_FORM
Program for printing price tags out calls FM Z_COMPOSE_XML passing two parameters (business-unit, size of price tag)
So, the output of the form will be dynamic:
if user passes "X" business-unit and SMALL size of price tag, FM Z_COMPOSE_XML will generate PDF form with 6 columns per A4 with the label "X" for each column
if user passes "Y" business-unit and MEDIUM size of price-tag, FM Z_COMPOSE_XML should generate PDF form with 3 columns per A4 with the label 'Y' for each column.

Related

selenium issue:How to capture dynamic voucher number in a website

I have a website where two users (user15 and user16), user 15 creates a voucher which gets approved by user16. So in the home screen of user15 a voucher number is generated which is dynamic as shown in image below.I need to capture this voucher number generated for the one whose status is ""Processed" and then put it into the search filter of user16 homepage screen.How can i capture this dynamic voucher number ?
voucher number image
Your table template looks static. It is only the rows that are getting changes so you can write an xpath like below which would directly get you the voucher name:
//td[text()='Processed')]/preceding-sibling::td[colnumber of VoucherNubmer]
Please follow following steps mentioned below:
First select all elements from the table within the list.
Then using foreach loop compare the status of the element.
After that if(status=="Processed") then using getText() method print the value of the vochure number.

How to Personalize window behavior in odoo 8 livechat

How to Personalize window behavior in Odoo 8
Goals for now are:
add fields asking visitors Name, Email and Concern, As you can see at first image "A" the customer name is "Visitor"
change visitors name base on his/her Name input
change the design (background color, font, etc)
I already search on odoo documentation but no tutorials for Live Chat customization.
TIA
The appearance and the behaviour of the live_chat window is defined in the files addons/im_chat/static/src/js/im_chat.js, addons/im_chat/static/src/xml/im_chat.xml and addons/im_livechat/static/src/js/im_livechat.js
Depending on your needs your will have to modify these files. For the needs you have outlined in your question you have to:
1) add fields asking visitors Name, Email and Concern, As you can see
at first image "A" the customer name is "Visitor"
You have to modify the send_welcome_message function on the im_livechat.js in order for you to send a custom initial message and you have to change the im_chat.Conversation_message_bubble template in order to give each "text bubble" a different look (for example to insert a textbox asking for user's info)
2) change visitors name base on his/her Name input
When you collect your data, the user's name is saved in the variable defaultUsername in im_livechat.js, you will have to set it there
3) change the design (background color, font, etc)
All of this can happen from changing the template with the name = im_chat.Conversation_message_bubble from the im_chat.xml file accordingly.

SSRS Loop through data, adding a new title if the chapter/section changes

I'm building an SSRS report in Report Builder 3.0 (2014). I have five sections of data I'm working with: inspection number, chapter, section, code, and description. The report is only going to show data for one inspection, so all data is filtered on InspNo first. There are often multiple codes associated with an InspNo.
What I have: for every code associated with an inspection, the code is listed along with its description.
What I need: I need to add the chapter and section info, but only when it changes. For example, let's say the codes associated with an inspection are 302.7, 304.10, 304.12, and 505.1. I would like the result to be as follows:
Chapter 3
Section 302
302.7 - Description
Section 304
304.10 - Description
304.12 - Description
Chapter 5
Section 505
505.1 - Description
I have tried using Lists, but the chapter and section get repeated for every code. Any ideas how to make it work?
****UPDATE****
I'm getting closer to a solution. Right now I'm using a combination of textboxes and lists. The chapters and sections are text boxes, and the codes/descriptions are lists. All of the elements have a visibility expression using InStr. The lists are working perfectly. However the text boxes are giving me issues.
It seems my visibility expressions on elements outside of lists are only looking at the first piece of the pulled data. In the example above, Section 302's visibility expression is =IIF(InStr(Fields!FAILEDCODE.Value, "302") > 0, False, True). This is working great because the first code is 302.7. Section 304's visibility expression is =IIF(InStr(Fields!FAILEDCODE.Value, "304") > 0, False, True). This text box is always hidden. It seems like Report Builder is only checking this InStr value against the first line of data, not the entire set. Does anyone know if this is accurate or if there's a workaround?

ColdFusion/CFWheels Merge Multiple PDFs in different Controllers

I'm using Coldfusion 10 and CFWheels for my site.
Basically my site has a bunch of different types of forms with their own Controllers and views. For each form, the user has the option to dynamically generate a PDF of the form and download it. It basically loads the controller data but when it hits the view with a parameter of "pdf" it does the following which will generate the PDF and open the document in the browser:
<cfdocument format="PDF" saveAsName="#formtype#_#id#.pdf">
#includePartial("/printView")#
</cfdocument>
Each of these PDFs can have multiple pages depending on how many line items are added. Like I said in the beginning there are multiple types of forms so they will have their own controller and views and PDF generation with their print views. These forms are all customized and associated together with an ID like shipmentID. So I can have one shipment that contains 2 forms of type A and 1 form of type B and 3 of type C, etc. What I need to do is generate 1 PDF with all the forms merged together based on the shipment. So taking my example, the merged PDF for the shipment would contain the 2 forms of type A, 1 form of type B, and 3 of type C all merged.
Currently what I'm doing is making a http "GET" call to each of the dynamically generated PDF pages, save that to a temp directory, then merging them at the end.
I load the shipment and for each different type of form I do the following where urlPath is the path to the view that generates the dynamic PDF:
var httpService = new http();
httpService.setMethod("GET");
httpService.setUrl(urlPath);
invoice = httpService.send().getPrefix().filecontent.toByteArray();
var fullPath = "#filePath##arguments.type#_#id#.pdf";
//write files in temp directory
FileWrite(fullPath, invoice);
After I get the PDF and write it to a file, I save the path in an array for reference so I can loop through and merge all the referenced files in the array, then delete the temp directory where the files were saved.
The reason why I'm doing it this way is because the controllers and views are already set and generate the individual PDFs on the fly as it is.
If I try to load (all associated forms) and put everything in one file, I'll have to add all the same controller logic to load each form specific stuff and the associated views but these already exist for the individual page view.
Is there a better way to do this?
It works fine if there are only a few PDFs but if there a lot of different forms in the shipment like 20, then it's very slow and since we don't have CF Enterprise, I believe the cfdocument is single threaded. The forms have to be generated dynamically so they contain the most current data.
UPDATE for Chris
I've added some code to show what the various forms might look like. I validate and load a bunch of other things but I stripped it down to get the general idea:
controllers/Invoices.cfc
The path might be something like: /shipments/[shipmentkey]/invoices/[key]
public void function show(){
// load shipment to display header details on form
shipment = model("Shipment").findOne(where="id = #params.shipmentkey#");
// load invoice details to display on form
invoice = model("Invoice").findOne(where="id = #params.key#");
// load associated invoice line items to display on form
invoiceLines = model("InvoiceLine").findAll(where="invoiceId = #params.key#");
// load associated containers to display on form
containers = model("Container").findAll(where="invoiceid = #params.key#");
// load associated snumbers to display on form
scnumbers = model("Scnumber").findAll(where="invoiceid = #params.key#");
}
controllers/Permits.cfc
The path might be something like: /shipments/[shipmentkey]/permits/[key]
public void function show(){
// load shipment to display header details on form
shipment = model("Shipment").findOne(where="id = #params.shipmentkey#");
// load permit details to display on form
permit = model("Permit").findOne(where="id = #params.key#");
// load associated permit line items to display on form
permitLines = model("PermitLine").findAll(where="permitId = #params.key#");
}
controllers/Nafta.cfc
The path might be something like: /shipments/[shipmentkey]/naftas/[key]
public void function show(){
// load shipment to display header details on form
shipment = model("Shipment").findOne(where="id = #params.shipmentkey#");
// load NAFTA details to display on form
nafta = model("NAFTA").findOne(where="id = #params.key#");
// load associated NAFTA line items to display on form
naftaLines = model("NaftaLine").findAll(where="naftaId = #params.key#");
}
Currently my view is based on a URL parameter called "view" where the values can be either "print" or "pdf".
print - displays the print view that's pretty much a stripped down version of the form without the webpage headers/footers etc.
pdf - calls the cfdocument code I pasted at the top of the question which uses the printView to generate the PDF.
I don't think I need to post the "show.cfm" code as it would just be a bunch of divs and tables displaying the specific information for each particular form in question.
Keep in mind that these are only 3 example form types and there are 10+ types that may be associated to 1 shipment and the PDF's would need to be merged. Each type may repeat several times within a shipment as well. For example a shipment may contain 10 different invoices with 5 permits and 3 NAFTAs.
To make things slightly more complicated, a shipment can have 2 types: US Bound or Canada Bound and based on this different form types can be associated to the shipment. So an Invoice for Canada will have totally different fields than an invoice for US so the models/tables are different.
Currently to do the merging I have a controller that does something like the following (note that I stripped a lot of validation, loading of other objects to simplify)
public any function displayAllShipmentPdf(shipmentId){
// variable to hold the list of full paths of individual form PDFs
formList = "";
shipment = model("shipment").findOne(where="id = #arguments.shipmentId#");
// path to temporarily store individual form PDFs for later merging
filePath = "#getTempDirectory()##shipment.clientId#/";
if(shipment.bound eq 'CA'){
// load all invoices associated to shipment
invoices = model("Invoice").findAll(where="shipmentId = #shipment.id#");
// go through all associated invoices
for(invoice in invoices){
httpService = new http();
httpService.setMethod("get");
// the following URL loads the invoice details in the Invoice controller and since I'm passing in "view=pdf" the view will display the PDF inline in the browser.
httpService.setUrl("http://mysite/shipments/#shipment.id#/invoices/#invoice.id#?view=pdf");
invoicePdf = httpService.send().getPrefix().fileContent.toByteArray();
fullPath = "#filePath#invoice_#invoice.id#.pdf";
// write the file so we can merge later
FileWrite(fullPath, invoicePdf);
// append the fullPath to the formList as reference for later merging
formList = ListAppend(formList, fullPath);
}
// the above code would be similarly repeated for every other form type (ex. Permits, NAFTA, etc.). So it would call the path with the "view=pdf" which will load the specific form Controller and display the PDF inline which we capture and create a temporary PDF file and add the path to the formList for later merging. You can see how this can be a long process as you have several types of forms associated to a shipment and there can be numerous forms of each type in the shipment and I don't want to have to repeat each form Controller data loading logic.
}else if(shipment.bound eq 'US'){
// does similar stuff to the CA except with different forms
}
// merge the PDFs in the formList
pdfService = new pdf();
// formList contains all the paths to the different form PDFs to be merged
pdfService.setSource(formList);
pdfService.merge(destination="#filePath#shipment_#shipment.id#.pdf");
// read the merged PDF
readPdfService = new pdf();
mergedPdf = readPdfService.read(source="#filePath#shipment_#shipment.id#.pdf");
// delete the temporarily created PDF files and directory
DirectoryDelete(filePath, "true");
// convert to binary to display inline in browser
shipmentPdf = toBinary(mergedPdf);
// set the response to display the merged PDF
response = getPageContext().getFusionContext().getResponse();
response.setContentType('application/pdf');
response.setHeader("Content-Disposition","filename=shipment_#shipment.id#_#dateFormat(now(),'yyyymmdd')#T#timeFormat(now(),'hhmmss')#.pdf");
response.getOutputStream().writeThrough(shipmentPdf);
}
See: https://forums.adobe.com/thread/1121909 ... "...Standard Edition Adobe throttles the PDF functions to a single thread,...Developer runs like Enterprise" so your development environment will whip out the pdfs but your CF Standard production server will be choking.
Also, seems you are not having trouble with one or two pdfs. I have CF Enterprise and it was generating pdfs just fine - a few seconds - and then out of nowhere pdfs started taking 4 minutes. Another comment in the above referenced adobe post suggested check in the /etc/hosts that CF is contacting itself (?????). Well some digging and I found that the Windows\system32\drivers\etc\hosts had been updated a day before users discovered pdfs were timing out. The IP had been changed to some other intranet IP and the server name was the DNS server name. I changed the value back to 127.0.0.1 localhost and voila, pdfs started rendering in normal amounts of time.

PDF - why is there no standard structure element for a page?

The PDF Spec defines standard structure types, used to define a structure tree for the document. As far as I can see, there is no element related to pages. Here are the standard structure types for grouping elements:
Document
Part
Art
Sect
Div
...and so on...
Why is there no Page item in this list?
If you want your structure to use pages, what should be used? Part? Sect? Div?
PDF tags exist so that the content type / meaning of elements can be identified. They should be considering a kind of "meta" information for the PDF, simply providing context for the content in a file (so that content can be easily extracted, converted, processed, accessible, etc.). Think of it as a table of contents to a book. Just because the book has x pages doesn't mean that the content structure would be altered if the book's page height was cut in half and now had 2x pages in it.
A Page Object in the PDF Document Structure already groups elements (by nature of each element being on a given page), so doing so in this structure would be a little redundant.
Also, consider this case:
Document
Table of Contents (Page 1)
Section 1 (starts on page 2, ends mid page 3)
Sub Section (page 2)
Sub Section (half of page 3)
Section 2 (starts mid page 3)
etc...
In this example, Section 1 and Section 2 couldn't both be direct parents of page 3 (not to mention that Section 1 spans two different pages). Additionally, trying to solve this problem really isn't necessary because the elements which is being grouped here is already each a child of its respective Document Structure's Page node in the actual file format.
Appendix G of the PDF Specification gives examples that demonstrate use of the Page object.
The PDF has a tree structure (which is what allows it to load any page so fast). The content does not have any structure unless you choose to use the marked content feature of the format which then allows metadata to be include in the data.