Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 14 Next »

Objective :

The objective of PDF generation service is to bulk generate pdf as per requirement.

Requirements :

  • Prior knowledge of JavaScript.

  • Prior knowledge of Node.js platform.

  • JSONPath for filtering required data from json objects.

Setup :

Step 1: Write data configuration file and format configuration file as per your requirement.

Step 2: Check-in both the config file to a remote location preferably  git hub. Currently we check in the data config file in : https://github.com/egovernments/configs/tree/master/pdf-service/data-config and format config file in : https://github.com/egovernments/configs/tree/master/pdf-service/format-config

Step 3:  The file which are created earlier, their absolute path has to mention in dev.yaml and qa.yaml Before editing the file create another branch and edit the dev.yaml file and qa.yaml file , mentioned proper file path like

data-config-urls: file:///work-dir/configs/pdf-service/data-config/consolidatedbill.json
format-config-urls: file:///work-dir/configs/pdf-service/format-config/consolidatedbill.json

After editing the file, raise the pull request to DevOPS, so they can merge the branch to master.

Step 4: Before starting the PDF generation service, persister and filestore service has to be running. First make sure that  pdf-generator.yml persister file is present in  https://github.com/egovernments/configs/tree/master/egov-persister If not present then add the file and raise the pull request to Devops. Run the Persister service present in the link given below:  https://github.com/egovernments/core-services/tree/master/egov-persister Run the Filestore service present in the link : https://github.com/egovernments/core-services/tree/master/egov-filestore

Step 5: Run the PDF generation service application, use the file-name as path parameters in the URL of the requests for pdf generation service with required request body for which PDF has to generate.


Definitions :

Config file: A json config file which contains the configuration for pdf requirement. For any pdf requirements we have to add two configs file to the service.

  • Format Config file: This config file define the format of PDF. In format config we define the UI structure ex: css, layout etc. for pdf as per PDFMake syntax of pdf. In PDF UI, the places where values are to be picked from request body are written as “{{variableName}}” as per ‘mustache.js’ standard and are replaced by this templating engine. ex: https://github.com/egovernments/configs/tree/master/pdf-service/format-config

  • Data Config file: This file contains mapping to pick data from request body, external service call body if there is any and the variable which defines where this value is to be replaced in format by the templating engines (mustache.js). The variable which is declared in format config file must be defined in data config file. ex: https://github.com/egovernments/configs/tree/master/pdf-service/data-config

API : A REST endpoint to fetch data based on the configuration.

Functionality :

  • Provide common framework to generate PDF.

  • Provide flexibility to customize the PDF as per the requirement.

  • Provide functionality to add an image, Qr Code in PDF.

  • Provide functionality to generate pdf in bulk.

  • Provide functionality to specify maximum number of records to be written in one PDF.

Feature List :

  • Currently supports the generation of  payment receipts,bill,certificate and acknowledgement pdf for TL, PT,NOC and BPA.

  • Functionality to generate PDFs in bulk.

  • Avoid regeneration.

  • Support QR codes.

  • Functionality to specify maximum number of records to be written in one PDF.

  • Uploading generated PDF to filestore and return filestore id for easy access.

  • For large request generate PDF in multiple files due to upload size restriction by file-store service.

  • Supports localisation.

External Libraries used :

Impact :

  • Use by Trade License module for all its PDF.

  • Use by Property Tax Module for Bill and Payment receipt PDF.

  • Use by BPA module for Payment Receipt.

Impacted By :

  • Changes in the format of response from external libraries.

  • Filestore service request format changes.

Config Details :

As mentioned earlier, We provide two config files for a pdf generation requirement, one defining format as per PDFMake syntax of pdf and other to fill format of pdf to prepare final object which will go to PDFMake and will be converted into PDF. This pdf will be upload to the file store.

PDF generation service read these such files at start-up to support PDF generation for all configured module.

The data config file  contains the following aspects :

  • key:  The key for the pdf, it is used as a path parameter in URL to identify for which PDF has to generate.

  • baseKeyPath: The json path for the array object that we need to process. 

  • entityIdPath: The json path for the unique field which is stored in DB. And that unique field value is mapped to file-store id, so we can directly search the pdf which was created earlier with the unique field value and there will be no need to create PDF again.

  • mapping: There are three mapping object for variable which are direct mapping, externalApi mapping and derived mapping.

    • Direct Mapping: In direction mapping we define the variable whose value can be fetched from the array object which we extracted using baseKeyPath.

    • ExternalApi Mapping: We use the externalApi mapping only if there is a need of values from other service response. In externalApi mapping, API endpoint has to be set properly with correct query parameter.

    • Derived mapping: In derived mapping, the estimation of variable characterize here is equivalent to esteem which acquired from the arithmetic operation between variable of direct mapping and externalApi mapping.

Sample structure of variable definition in data config :

{
  “Variable”: “variable_name”,
  “Value”:{
      “path”: “$.propertyId”             -----> jsonpath to obtain value.
  }

}

 {
  “Variable”: “variable_name”,
  “Value”:{
    “path”: “$.propertyId”             -----> jsonpath to obtain value or key to obtain value from localisation.
  },
  “type”:  “label”,                    -----> this field is used to mark this variable as label.       
  “localisation”:{
      “required”: “false”,             -----> if this field is true then  localisation is used for this variable and vice versa.
      “prefix”: “null”,                -----> prefix of the key which is declared in path field.
      “module”: “rainmaker-tl”         -----> the module from which localisation entry is fetched
  }
}

Example to show date in PDF

{
  “Variable”: “variable_name”,
  “Value”:{
    “path”: “$.date”             -----> jsonpath to obtain epoch value of date
  },
  “type”: "date"                  -----> this field is used to mark this variable as date.       
  "format": "YYYY/MM/DD "
}

If the format field in not specified in date variable declaration then in PDF date is shown with default format of DD/MM/YYYY. For more details refer this page Unix-Timestamp

Example of external API calling to MDMS service

“externalAPI”: [
    “path”: “http://egov-mdms-service:8080/egov-mdms-service/v1/_get”,
    “queryParam”: “moduleName=tenant&masterName=tenants&tenantId=pb&filter=%5B?(@.code=='{$.tenantId}')%5D”,
    “apiRequest”: null,
    “responseMapping”:[
      {
          “variable”: “address”,
          “value”: “$.MdmsRes.tenant.tenants[0].address”
      },
      {
          “variable”: “phoneNumber”,
          “value”: “$.MdmsRes.tenant.tenants[0].contactNumber”
      }
    ]
  ]

The format config file contain the following aspect :

  • key: The key for the pdf, it is used as a path parameter in URL to identify for which PDF has to  generate.

  • Content: In this section, the view of pdf is set. What has to be appear on pdf is declared here, it  just like creating a static html page. The variable which are defined in data config are declared here and place in position as per the requirement. We can also create table here and set the variable as per requirement. 

  • Style: This section is used to style the component, set the alignment and many more. Basically it's like a CSS to style the html page.

Example of adding footer in PDF (adding page number in footer)

{
"key": "property-bill",
"config": {
"defaultStyle": {....},
"content": [....],
"style": {....},
"footer": "(function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; })"
}
}

The position of page number in footer is configurable. For more detail refer this document Header and Footer

API Call :

_create :

This API request to PDF generation service is made to generate pdf and return the filestore id and job id.

  • Endpoint:

/pdf-service/v1/_create?key={configFileName}&tenantId={tenantId}

  • Body:

The request body will have requestInfo and another json object depending on the requirement which will be converted to pdf as per requirement.

  • URL Instance :

https://egov-micro-dev.egovernments.org/pdf-service/v1/_create?key=tlcertificate&tenantId=pb

_createnosave :

This API request to PDF generation service, generate pdf and return the downloadable pdf file as response.

  • Endpoint:

/pdf-service/v1/_createnosave?key={configFileName}&tenantId={tenantId}

  • Body:

The request body will have requestInfo and another json object depending on the requirement which will be converted to pdf as per requirement.

  • URL Instance :

https://egov-micro-dev.egovernments.org/pdf-service/v1/_createnosave?key=tlcertificate&tenantId=pb

_search :

This API request to PDF generation service, search the already created pdf (based on job Id or entity id) for particular application number. This API can be called before the creation of PDF, and search if the particular pdf is created for that application number or not. If the PDF is created then its filestore id is fetched from DB and based on that filestore id, PDF Is shown. 

  • Endpoint:

/pdf-service/v1/_search?jobid={jobid}

/pdf-service/v1/_search?entityid={entityid}

  • Body:

The request body will have requestInfo.

  • URL Instance :

https://egov-micro-dev.egovernments.org/pdf-service/v1/_search?jobid=consolidatedbill1577335538347

https://egov-micro-dev.egovernments.org/pdf-service/v1/_search?entityid=BILL-000676

Postman collection

https://www.getpostman.com/collections/5a9bfd6fd03f9f2a6fad

Steps for running PDF Generation Service locally

Refer this doc : 

Steps for locally testing PDF-Generation Service

Steps for Integration of PDF in UI for download and print PDF

Following are the steps for integrating TL certificate in UI. Refer this same step for integrating other PDF in UI.

Step 1: In footer.js file which is present in /frontend/web/rainmaker/dev-packages/egov-tradelicence-dev/src/ui-config/screens/specs/tradelicence/applyResource , Create two object (download and print object) in footerReview function

example:

let tlCertificateDownloadObject = {
    label: { labelName: "TL Certificate", labelKey: "TL_CERTIFICATE" },
    link: () => {
      const { Licenses } = state.screenConfiguration.preparedFinalObject;
      downloadCertificateForm(Licenses);
    },
    leftIcon: "book"
  };
  let tlCertificatePrintObject = {
    label: { labelName: "TL Certificate", labelKey: "TL_CERTIFICATE" },
    link: () => {
      generateReceipt(state, dispatch, "certificate_print");
    },
    leftIcon: "book"
  };

In tlCertificateDownloadObject give the proper label name and key for the pdf. In link function get the object whose mapping is required for PDF, in this case we want license object. Call the function downloadCertificateForm (details about this function is describe in next step). Add icon details which we want to use in UI to represent that option. Same things for tlcertificatePrintObject only difference is we have to call generateReceipt function.

Again create the same two object with similar content in downloadPrintContainer function,

Step 2: Mention the function name “downloadCertificateForm“ and “generateReceipt“ in import , because the functions is define in /frontend/web/rainmaker/dev-packages/egov-tradelicence-dev/src/ui-config/screens/specs/utils/index.js and /frontend/web/rainmaker/dev-packages/egov-tradelicence-dev/src/ui-config/screens/specs/utils/receiptPDF.js

Step 3: In index.js define the function which is responsible for calling the Create API of PDF service to create respective PDF. In that function you have to mentioned the tenant ID and proper key value which is same as key mentioned in data and format config. Also mentioned the URL : /pdf-service/v1/_create and action as get and also call the function downloadReceiptFromFilestoreID which is responsile to call filestore service with filestoreid and return the URL for pdf.

example of function downloadCertificateForm

export const downloadCertificateForm = (Licenses) => {
  const queryStr = [
    { key: "key", value: "tlcertificate" },
    { key: "tenantId", value: "pb" }
  ]
  const DOWNLOADRECEIPT = {
    GET: {
      URL: "/pdf-service/v1/_create",
      ACTION: "_get",
    },
  };
  try {
    httpRequest("post", DOWNLOADRECEIPT.GET.URL, DOWNLOADRECEIPT.GET.ACTION, queryStr, { Licenses }, { 'Accept': 'application/json' }, { responseType: 'arraybuffer' })
      .then(res => {
        res.filestoreIds[0]
        if (res && res.filestoreIds && res.filestoreIds.length > 0) {
          res.filestoreIds.map(fileStoreId => {
            downloadReceiptFromFilestoreID(fileStoreId)
          })
        } else {
          console.log("Error In Acknowledgement form Download");
        }
      });
  } catch (exception) {
    alert('Some Error Occured while downloading Acknowledgement form!');
  }
}

example of function generateReceipt

const generateReceipt = async (state, dispatch, type) => {
//  console.log("Transformed Data--",transformedData);
  pdfMakeCustom.vfs = pdfFonts.vfs;
  pdfMakeCustom.fonts = {
    Camby:{
            normal: 'Cambay-Regular.ttf',
            bold: 'Cambay-Regular.ttf',
            italics: 'Cambay-Regular.ttf',
            bolditalics: 'Cambay-Regular.ttf'
    },
  
  };
  let data1 = _.get(
    state.screenConfiguration.preparedFinalObject,
    "applicationDataForReceipt",
    {}
  );
  let data2 = _.get(
    state.screenConfiguration.preparedFinalObject,
    "receiptDataForReceipt",
    {}
  );
  let data3 = _.get(
    state.screenConfiguration.preparedFinalObject,
    "mdmsDataForReceipt",
    {}
  );
  let data4 = _.get(
    state.screenConfiguration.preparedFinalObject,
    "userDataForReceipt",
    {}
  );
  let data5 = _.get(
    state.screenConfiguration.preparedFinalObject.Licenses[0].tradeLicenseDetail,
    "address",
    {}
  );

  let ulbLogo = _.get(
    state.screenConfiguration.preparedFinalObject,
    "base64UlbLogo",
    ""
  );
  if (_.isEmpty(data1)) {
    console.log("Error in application data");
    return;
  } else if (_.isEmpty(data2)) {
    console.log("Error in receipt data");
    return;
  } else if (_.isEmpty(data3)) {
    console.log("Error in mdms data");
    return;
  } else if (_.isEmpty(data4)) {
    console.log("Error in auditor user data");
    return;
  } else if (_.isEmpty(ulbLogo)) {
    console.log("Error in image data");
    return;
  }
  let transformedData = {
    ...data1,
    ...data2,
    ...data3,
    ...data4,
    actualAddress:data5
  };
  switch (type) {
    case "certificate_download":
   
      let certificate_data = getCertificateData(transformedData, ulbLogo);
      certificate_data &&
     //  pdfMakeCustom.createPdf(certificate_data).download("tl_certificate.pdf");
      pdfMakeCustom.createPdf(certificate_data).open();
      break;
    case "certificate_print":
      certificate_data = getCertificateData(transformedData, ulbLogo);
      certificate_data && pdfMakeCustom.createPdf(certificate_data).print();
      break;
    case "receipt_download":
      let receipt_data = getReceiptData(transformedData, ulbLogo);
      
      receipt_data &&
     //   pdfMakeCustom.createPdf(receipt_data).download("tl_receipt.pdf");
        pdfMakeCustom.createPdf(receipt_data).open();
      break;
    case "receipt_print":
      receipt_data = getReceiptData(transformedData, ulbLogo);
      receipt_data && pdfMakeCustom.createPdf(receipt_data).print();
      break;
    default:
      break;
  }
};

Above are the following steps to integrate certificate in TL module, where certificate is available to download when the payment is done for a particular application number.

Steps to integrate other pdf may varies, but this above example for tlcertificate integration is just to give a basic idea.

  • No labels