简体   繁体   English

NetSuite - 使用 SuiteScript 创建按钮以在转移单上打印装箱单

[英]NetSuite - Using SuiteScript to Create Button to Print Packing List on Transfer Order

I'm trying to follow SuiteAnswers 41269 (which is for adding a Packing List to an Item Fulfillment) to add a button to print a packing list to a Transfer Order.我正在尝试按照 SuiteAnswers 41269(用于将装箱单添加到项目履行)添加一个按钮以将装箱单打印到转移单。 This is essentially a test to try and be able to print more forms on more transactions that aren't native to NetSuite (VRMAs, etc.).这本质上是一个测试,旨在尝试并能够在更多非 NetSuite 本地事务(VRMA 等)上打印更多表单。

Note that the SuiteAnswers above seems to be out of date, because it references SS1.0 and SS2.0, but some of the code for SS2.0 also appears to use SS1.0 code.请注意,上面的 SuiteAnswers 似乎已经过时,因为它引用了 SS1.0 和 SS2.0,但 SS2.0 的一些代码似乎也使用了 SS1.0 代码。 Since that SA was a little off, I've gone through a lot of the NetSuite help files on the different parts of the render and url modules to help build out these scripts.由于 SA 有点偏离,我浏览了很多 NetSuite 帮助文件,这些文件涉及渲染和 url 模块的不同部分,以帮助构建这些脚本。

My issue is that I keep getting thrown back an error when the "Print 1" button is clicked:我的问题是,单击“打印 1”按钮时,我不断收到错误消息:

Uncaught ReferenceError: print1 is not defined
    at trnfrord.nl?id=658266&whence=&cmid=1652279684591_1868:1132:30
    at Object.execCb (NsRequire.js:2047:26)
    at Ma.check (NsRequire.js:1193:28)
    at Ma.enable (NsRequire.js:1475:10)
    at Ma.init (NsRequire.js:1106:11)
    at NsRequire.js:1771:18

I'm using a UserEvent Script, a Client Script, and a Suitelet Script.我正在使用 UserEvent 脚本、客户端脚本和 Suitelet 脚本。 I'm currently using a static entity ID of the Transfer Order while I'm testing this, and will add a dynamic one once I get this working.我目前正在使用转移订单的静态实体 ID,而我正在测试这个,一旦我得到这个工作,我会添加一个动态实体 ID。

UPDATE: After taking in the suggestion below, I realized I had the deploymentID set to the actual internal ID of the deployment, not the ID that matched the scriptID field.更新:接受下面的建议后,我意识到我将 deploymentID 设置为部署的实际内部 ID,而不是与 scriptID 字段匹配的 ID。 I also realized my beforeLoad function was using scriptContext instead of context, which was inside the function.我还意识到我的 beforeLoad 函数使用的是 scriptContext 而不是函数内部的上下文。

After fixing these issues, I started getting a "You are not allowed to navigate directly to this page" error.解决这些问题后,我开始收到“不允许您直接导航到此页面”错误。 My script deployments were set to testing, so I changed them to released, and I still got this error.我的脚本部署设置为测试,所以我将它们更改为已发布,但仍然出现此错误。

I changed the returnExternalUrl from true to false and received an "Invalid PDF Layout" error.我将 returnExternalUrl 从 true 更改为 false 并收到“无效的 PDF 布局”错误。

I looked online and realized that part of my mistake was using the formID of the actual PDF, not create a new Custom Transaction Form and assign the PDF to print from that form.我在网上查看并意识到我的部分错误是使用实际 PDF 的 formID,而不是创建新的自定义交易表单并分配 PDF 以从该表单打印。

Having done that, I am now receiving this error:完成后,我现在收到此错误:

{"type":"error.SuiteScriptError","name":"UNEXPECTED_ERROR","message":null,"stack":["renderPackingSlip(N/render)","onRequest(/SuiteScripts/buttonTest2/print_suitelet_script.js:18)"],"cause":{"type":"internal error","code":"UNEXPECTED_ERROR","details":null,"userEvent":null,"stackTrace":["renderPackingSlip(N/render)","onRequest(/SuiteScripts/buttonTest2/print_suitelet_script.js:18)"],"notifyOff":false},"id":"7fb1b24b-b66f-44bf-b6f3-282444013ca5-2d323032322e30352e3133","notifyOff":false,"userFacing":false}

Here are the the updated scripts as they stand now, which throw the above error:这是现在更新的脚本,它们会引发上述错误:

UPDATED UE SCRIPT:更新的 UE 脚本:

/**
 * @NApiVersion 2.x
 * @NScriptType UserEventScript
 * @NModuleScope SameAccount
 */

define([
    'N/url',
    'N/ui/serverWidget',
],

    function (url) {

        function beforeLoad(scriptContext) {

            try {
                if (scriptContext.type == 'view') {
                    const href = url.resolveScript({
                        scriptId: 699,
                        deploymentId: 3,
                        returnExternalUrl: true
                    });
                    scriptContext.form.addButton({
                        id: 'custpage_print1',
                        label: 'Print 1',
                        functionName: "(window.location='" + href + "')"
                    });

                }
            } catch (error) {
                log.debug('ERROR', error);
            }
        }

        return {
            beforeLoad: beforeLoad
        };

    });

UPDATED SS SCRIPT:更新的 SS 脚本:

/**
 * @NApiVersion 2.x
 * @NScriptType Suitelet
 */

 define(['N/render'],

 function(render) {

     function onRequest(context) {
     
       var total = 0;

          if (context.request.method == 'GET'){

         var ifid = context.request.parameters.custparam_ifid;

           var fileObj = render.packingSlip({
                    entityId: 658266,
                    printMode: render.PrintMode.PDF,
                    formId: 129
             });

                 fileObj.save()
          }
     }

     return {

         onRequest: onRequest
     };

  });

PDF: PDF:

<?xml version="1.0"?><!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">
<pdf>
<head>
    <link name="NotoSans" type="font" subtype="truetype" src="${nsfont.NotoSans_Regular}" src-bold="${nsfont.NotoSans_Bold}" src-italic="${nsfont.NotoSans_Italic}" src-bolditalic="${nsfont.NotoSans_BoldItalic}" bytes="2" />
    <#if .locale == "zh_CN">
        <link name="NotoSansCJKsc" type="font" subtype="opentype" src="${nsfont.NotoSansCJKsc_Regular}" src-bold="${nsfont.NotoSansCJKsc_Bold}" bytes="2" />
    <#elseif .locale == "zh_TW">
        <link name="NotoSansCJKtc" type="font" subtype="opentype" src="${nsfont.NotoSansCJKtc_Regular}" src-bold="${nsfont.NotoSansCJKtc_Bold}" bytes="2" />
    <#elseif .locale == "ja_JP">
        <link name="NotoSansCJKjp" type="font" subtype="opentype" src="${nsfont.NotoSansCJKjp_Regular}" src-bold="${nsfont.NotoSansCJKjp_Bold}" bytes="2" />
    <#elseif .locale == "ko_KR">
        <link name="NotoSansCJKkr" type="font" subtype="opentype" src="${nsfont.NotoSansCJKkr_Regular}" src-bold="${nsfont.NotoSansCJKkr_Bold}" bytes="2" />
    <#elseif .locale == "th_TH">
        <link name="NotoSansThai" type="font" subtype="opentype" src="${nsfont.NotoSansThai_Regular}" src-bold="${nsfont.NotoSansThai_Bold}" bytes="2" />
    </#if>
    <macrolist>
        <macro id="nlheader">
            <table style="width: 100%; font-size: 10pt;"><tr>
    <td rowspan="3" style="padding: 0px; width: 222px;"><#if companyInformation.logoUrl?length != 0><img src="${companyInformation.logoUrl}" style="margin: 5px; width: 120px; height: 60px; float: left;" /> </#if></td>
    <td rowspan="3" style="padding: 0px; width: 248px;">${companyInformation.addressText}</td>
    <td align="right" style="padding: 0px; width: 323px;"><span style="font-size: 28pt;">${record@title}</span></td>
    </tr>
    <tr>
    <td align="right" style="width: 337px;"><span class="number">#${record.tranid}</span></td>
    </tr>
    <tr>
    <td align="right" style="width: 337px;">${record.trandate}</td>
    </tr></table>
        </macro>
        <macro id="nlfooter">
            <table class="footer"><tr><#if preferences.PRINT_BARCODES>
    <td><barcode codetype="code128" showtext="true" value="${record.tranid}"/></td>
    </#if>
    <td align="right"><pagenumber/> of <totalpages/></td>
    </tr></table>
        </macro>
    </macrolist>
    <style type="text/css">* {
        <#if .locale == "zh_CN">
            font-family: NotoSans, NotoSansCJKsc, sans-serif;
        <#elseif .locale == "zh_TW">
            font-family: NotoSans, NotoSansCJKtc, sans-serif;
        <#elseif .locale == "ja_JP">
            font-family: NotoSans, NotoSansCJKjp, sans-serif;
        <#elseif .locale == "ko_KR">
            font-family: NotoSans, NotoSansCJKkr, sans-serif;
        <#elseif .locale == "th_TH">
            font-family: NotoSans, NotoSansThai, sans-serif;
        <#else>
            font-family: NotoSans, sans-serif;
        </#if>
        }
        table {
            font-size: 9pt;
            table-layout: fixed;
        }
        th {
            font-weight: bold;
            font-size: 8pt;
            vertical-align: middle;
            padding: 5px 6px 3px;
            background-color: #e3e3e3;
            color: #333333;
        }
        td {
            padding: 4px 6px;
        }
        td p { align:left }
        b {
            font-weight: bold;
            color: #333333;
        }
        table.header td {
            padding: 0;
            font-size: 10pt;
        }
        table.footer td {
            padding: 0;
            font-size: 8pt;
        }
        table.itemtable th {
            padding-bottom: 10px;
            padding-top: 10px;
        }
        table.body td {
            padding-top: 2px;
        }
        td.addressheader {
            font-size: 8pt;
            font-weight: bold;
            padding-top: 6px;
            padding-bottom: 2px;
        }
        td.address {
            padding-top: 0;
        }
        span.title {
            font-size: 28pt;
        }
        span.number {
            font-size: 16pt;
        }
        span.itemname {
            font-weight: bold;
            line-height: 150%;
        }
        div.returnform {
            width: 100%;
            /* To ensure minimal height of return form */
            height: 200pt;
            page-break-inside: avoid;
            page-break-after: avoid;
        }
        hr {
            border-top: 1px dashed #d3d3d3;
            width: 100%;
            color: #ffffff;
            background-color: #ffffff;
            height: 1px;
        }
</style>
</head>
<body header="nlheader" header-height="10%" footer="nlfooter" footer-height="20pt" padding="0.5in 0.5in 0.5in 0.5in" size="Letter">
    <table style="width: 100%; margin-top: 10px;"><tr>
    </tr>
    <tr>
    </tr></table>

<table class="body" style="width: 100%; margin-top: 10px;"><tr>
    <th style="width: 160px;">${record.shipmethod@label}</th>
    <th>${record.shipphone@label}</th>
    </tr>
    <tr>
    <td style="width: 160px;">${record.shipmethod}</td>
    <td>${record.shipphone}</td>
    </tr></table>
<#if record.item?has_content>

<table class="itemtable" style="margin-top:10px;width:100%;">
<thead>
    <tr>
    <th colspan="12" style="width: 264px;">Item</th>
    <th colspan="4" style="width: 165px;">UPC / ISBN</th>
    <th colspan="3" style="width: 90px;">Options</th>
    <th colspan="3" style="width: 90px;">Retail</th>
    <th align="right" colspan="2" style="width: 89px;">Remaining</th>
    <th align="right" colspan="2" style="width: 64px;">Shipped</th>
    </tr>
</thead>
<#list record.item as tranline><tr>
    <td colspan="12" style="width: 264px;"><span style="font-size:11px;"><span class="itemname">${tranline.item}</span></span><br /><span style="font-size:10px;">${tranline.description}</span></td>
    <td colspan="4" style="width: 165px;"><span style="font-size:10px;">${tranline.custcol_nsts_csic_upc}</span></td>
    <td colspan="3" style="width: 90px;"><span style="font-size:10px;">${tranline.options} <#if (tranline.custcol_nsts_csre_rnt_guid?has_content)> Rental <#else> </#if> </span></td>
    <td colspan="3" style="width: 90px;"><span style="font-size:10px;">${tranline.custcol_retail}</span></td>
    <td align="right" colspan="2" style="width: 89px;"><span style="font-size:10px;">${tranline.quantityremaining}</span></td>
    <td align="right" colspan="2" style="width: 64px;"><span style="font-size:10px;">${tranline.quantity}</span></td>
    </tr>
    </#list></table>
&nbsp;

<table align="right" border="1" cellpadding="1" cellspacing="1" style="width:35%;">
  <tr>
    <td style="width: 114px;">Quantity Total</td>
    <td style="width: 97px;">${record.quantity.total}</td>
    </tr>
  <tr>
    <td style="width: 114px;">Subtotal</td>
    <td style="width: 97px;">${record.custbody_pack_slip_subtotal}</td>
    </tr>
    <tr>
    <td style="width: 114px;">Shipping &amp; Handling</td>
    <td style="width: 97px;">${record.custbody_pack_slip_shiptotal}</td>
    </tr>
    <tr>
    <td style="width: 114px;">Tax</td>
    <td style="width: 97px;">${record.custbody_pack_slip_taxtotal}</td>
    </tr>
    <tr>
    <td style="width: 114px;">Total</td>
    <td style="width: 97px;">${record.custbody_pack_slip_trxtotal}</td>
    </tr></table>
</#if>
</body>
</pdf>

You are not invoking the function or providing an eval argument (sort of).您没有调用该函数或提供 eval 参数(有点)。 The functionName argument should just be the exported function name from the client script without parens. functionName 参数应该只是从客户端脚本中导出的函数名称,不带括号。 eg:例如:

functionName: 'print1'

Also note that the client script doesn't have to be a ClientScript and that (IMO) your code is more portable if you use另请注意,客户端脚本不必是 ClientScript 并且(IMO)如果您使用,您的代码更具可移植性

 formObj.clientScriptModulePath = './custom_print_CS.js'; // or whatever you name it and save it besid your User Event script code. 

and your client script could look like:您的客户端脚本可能如下所示:

/**
 * @NApiVersion 2.x
 */

define([
    'N/url',
],

function(url) {


    function print1() {
        var output = url.resolveScript({
            scriptId: 698,
            deploymentId: 1695,
            returnExternalUrl: true
        });
       
        window.open(output);
   }
   
   return {
        print1: print1
   };
})

I know Suite Answer suggests this but there is an alternate solution that lets you skip the Client Script , by directly redirecting from the button to the Suitelet by directly putting the redirection on the button.我知道 Suite Answer 建议这样做,但有一个替代解决方案可以让您跳过 Client Script ,通过直接将重定向放在按钮上,直接从按钮重定向到 Suitelet。 The inside of your event script beforeLoad function would look like this事件脚本 beforeLoad 函数的内部看起来像这样

const href = url.resolveScript({
                    scriptId:698,
                    deploymentId:  1695,
                    returnExternalUrl: true
            });

context.form.addButton({
                    id:'custpage_print1',
                    label: 'Print 1',
                    functionName: "(window.location='"+href +"')"
            });

Don't forget to load the N/url module不要忘记加载 N/url 模块

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM