RENDER ADVANCED PDF VIA SUITELET

define(['N/record', 'N/render', 'N/search'],
(record, render, search) => {
    "use strict";


    const TEMPLATE_MAP = {
        salesorder: 'CUSTTMPL_JJ_SO_HIDE_LINE_ITEM_STBUK154',
        estimate: 'CUSTTMPL_JJ_QUOTE_HIDE_LINE_ITEM_STBUK154',
        invoice: 'CUSTTMPL_JJ_INV_HIDE_LINE_ITEM_STBUK154',
        itemfulfillment: 'CUSTTMPL_JJ_IF_HIDE_LINE_ITEM_STBUK154'
    };


    /**
     * Searches and maps SO lines to fulfillment lines using orderline references.
     * @param {number} createdFromId - Sales Order internal ID
     * @param {Array<Object>} orderLineRefs - Array of { line: number, shipped: number }
     * @returns {Array<Object>} - Enriched line-level data
     */
    function getMatchedSalesOrderLines(createdFromId, orderLineRefs) {
        try {
            const matchedLines = [];
            const lineMap = {};


            const soSearch = search.create({
                type: search.Type.SALES_ORDER,
                filters: [['internalid', 'is', createdFromId]],
                columns: [
                    'line',
                    'item',
                    'item.name',
                    'quantity',
                    'custcol_partno',
                    'custcol_labeldoornumber',
                    'custcol_ezdoorheight',
                    'custcol_doorwidth',
                    'custcol_ezfirerated',
                    'custcol_ezhingehand',
                    'custcol_ezhingeprep',
                    'custcol_ezstriketype',
                    'custcol_ezwallthickness'
                ]
            });


            soSearch.run().each(result => {
                const lineNum = parseInt(result.getValue({ name: 'line' }));
                lineMap[lineNum] = {
                    custcol_partno: result.getValue('custcol_partno'),
                    custcol_labeldoornumber: result.getValue('custcol_labeldoornumber'),
                    description: result.getText('item') || '',
                    custcol_ezwallthickness: result.getValue('custcol_ezwallthickness'),
                    custcol_doorwidth: result.getValue('custcol_doorwidth'),
                    custcol_ezdoorheight: result.getValue('custcol_ezdoorheight'),
                    custcol_ezstriketype: result.getValue('custcol_ezstriketype'),
                    custcol_ezhingehand: result.getValue('custcol_ezhingehand'),
                    custcol_ezfirerated: result.getValue('custcol_ezfirerated'),
                    custcol_ezhingeprep: result.getValue('custcol_ezhingeprep'),
                    quantityordered: result.getValue('quantity')
                };
                return true;
            });


            for (const ref of orderLineRefs) {
                const soLine = lineMap[ref.line];
                if (soLine) {
                    matchedLines.push({
                        ...soLine,
                        quantityshipped: ref.shipped
                    });
                }
            }


            return matchedLines;
        } catch (e) {
            log.error("Error@getMatchedSalesOrderLines", e);
            return [];
        }
    }


    const onRequest = (scriptContext) => {
        try {
            if (scriptContext.request.method === 'GET') {
                const reqParams = scriptContext.request.parameters;
                const transRecId = reqParams.transRecId;
                const transRecType = reqParams.transRecType;
                const mainRecord = record.load({ type: transRecType, id: transRecId });


                const templateId = TEMPLATE_MAP[transRecType];
                if (!templateId) throw new Error(`No template configured for transaction type: ${transRecType}`);


                const renderTemp = render.create();
                renderTemp.setTemplateByScriptId({ scriptId: templateId });


                if (transRecType === 'itemfulfillment') {
                    const createdFromId = mainRecord.getValue({ fieldId: 'createdfrom' });
                    const fulfillmentLineCount = mainRecord.getLineCount({ sublistId: 'item' });


                    const orderLineRefs = [];


                    for (let i = 0; i < fulfillmentLineCount; i++) {
                        const line = mainRecord.getSublistValue({ sublistId: 'item', fieldId: 'orderline', line: i });
                        const shipped = mainRecord.getSublistValue({ sublistId: 'item', fieldId: 'quantity', line: i });
                        if (line != null) {
                            orderLineRefs.push({ line: parseInt(line), shipped });
                        }
                    }


                    if (orderLineRefs.length && createdFromId) {
                        const enrichedData = getMatchedSalesOrderLines(createdFromId, orderLineRefs);
                        renderTemp.addCustomDataSource({
                            format: render.DataSource.OBJECT,
                            alias: 'salesorder',
                            data: { item: enrichedData }
                        });
                    }
                }


                renderTemp.addRecord({
                    templateName: 'record',
                    record: mainRecord
                });


                const transPdf = renderTemp.renderAsPdf();
                scriptContext.response.writeFile(transPdf, true);
            }
        } catch (err) {
            log.error("error @ onRequest", err);
            scriptContext.response.write(`Error: ${err.message}`);
        }
    };


    return { onRequest };
});

This suitelet script runs the search with transaction id and gets the necessary fields and uses these result in the pdf

Leave a comment

Your email address will not be published. Required fields are marked *