miércoles, 16 de diciembre de 2015

Posting Packing Slip Examples

I have been investigating the use of the chooseLinesQuery parameter in order to create a packing slip from multiple sales order lines.  Note the requirement to call chooseLines after having associated the query, which incidentally is called 'SalesUpdate'.  There are other parameters in the SalesFormLetter that can be used to avoid doing the heavy work of generating a query, such as relying on an array of Shipment IDs.

Example 1, from Experts-Exchange.  Multiple sales orders in one document.
  SalesFormLetter salesFormLetter;
  QueryRun queryRun;
  Query query;
  str strSalesTable = "V683904, V683905, V683906";
  ;
    
  salesFormLetter = SalesFormLetter::construct(DocumentStatus::PackingSlip);

  query = new Query(QueryStr(SalesUpdate));
  query.dataSourceTable(tablenum(SalesTable)).addRange(fieldnum(SalesTable, SalesId)).value(strSalesTable);
  queryRun = new QueryRun(query);

  salesFormLetter.chooseLinesQuery(queryRun);
  salesFormLetter.transDate(systemdateget());
  salesFormLetter.specQty(SalesUpdate::All);
  salesFormLetter.printFormLetter(false);
  salesFormLetter.createParmUpdate();
  salesFormLetter.chooseLines(null,true);
  salesFormLetter.reArrangeNow(true);
  salesFormLetter.run();

Example 2, using the WMSShipmentId (Shipment ID in the warehouse system) as the base for our packing slip.  Source here, and note the non-recommended way of instantiating the SalesFormLetter class.
  SalesFormLetter salesFormLetter;
  WMSShipment shipment;
  WMSShipmentId shipmentId = '008431_113';
  Set wmsShipmentSet = new Set(Types::String);
  ;
  wmsShipmentSet.add(shipmentId);

  salesFormLetter = SalesFormLetter_PackingSlip::newPackingSlip();
  salesFormLetter.allowEmptyTable(salesFormLetter.initAllowEmptyTable(true));
  salesFormLetter.multiForm(true);
  salesFormLetter.getLast();
  salesFormLetter.parmLineIdSet(wmsShipmentSet.pack());
  shipment = WMSShipment::find(shipmentId);
  salesFormLetter.update(shipment, systemDateGet(), SalesUpdate::PickingList, AccountOrder::None, false, true);

Example 3, the most versatile of all, is to create a query filtering on some RecIds via multiple OR values.
    SalesFormLetter         salesFormLetter;
    salesParmUpdate         salesParmUpdate;

    SysQueryRun calcQuery()
    {
        RefRecId                salesLineRecId;
        Query                   qry = new Query(QueryStr(SalesUpdatePackingSlip));
        QueryBuildDataSource    queryBuildDataSource = qry.dataSourceTable(tableNum(SalesLine));
        QueryBuildRange         queryBuildRange;
        SalesLine               salesLine;

        // Dummy Query to generate a series of SalesLine.RecId
        while select RecId from salesLine
            where salesLine.CustomerRef == 'XXX'
        {
            salesLineRecId = salesLine.RecId;
            queryBuildRange = queryBuildDataSource.addRange(fieldnum(SalesLine, RecId));
            queryBuildRange.value(SysQuery::value(salesLineRecId));
        }
        return new QueryRun(qry);
    }
    ;

    salesFormLetter = SalesFormLetter::construct(DocumentStatus::PackingSlip);

    salesFormLetter.getLast();
    salesFormLetter.resetParmListCommonCS();
    salesFormLetter.transDate(systemdateget());
    salesFormLetter.proforma(false);

    // Let's create that ParmId
    salesFormLetter.createParmUpdateFromParmUpdateRecord(
        SalesFormletterParmData::initSalesParmUpdateFormletter(
            DocumentStatus::PackingSlip, salesFormLetter.pack()));
    salesParmUpdate = salesFormLetter.salesParmUpdate();
    salesParmUpdate.SpecQty         = SalesUpdate::DeliverNow;
    salesParmUpdate.Proforma        = NoYes::No;
    salesParmUpdate.update();
    salesFormLetter.salesParmUpdate(salesParmUpdate);

    salesFormLetter.chooseLinesQuery(calcQuery());
    salesFormLetter.reArrangeNow(true);
    salesFormLetter.validateAll(false);
    salesFormLetter.printout(Printout::After);
    salesFormLetter.printFormLetter(NoYes::Yes);
    salesFormLetter.chooseLines();
    salesFormLetter.run();

Example 4.  Let's apply the user's printing options previously selected from the Sales form, and copy the settings to send it via X++.  Idea copied from here.
SalesFormLetter salesFormLetter; QueryRun queryRun; Query query; str strSalesTable = "V683904, V683905, V683906"; SalesFormLetter_PackingSlip salesFormLetter_PackingSlip; Counter iCnt = 0; SRSPrintDestinationSettings printSettingsOrig, printSettingsCopy; container lastValues; ; salesFormLetter = SalesFormLetter::construct(DocumentStatus::PackingSlip); query = new Query(QueryStr(SalesUpdate)); query.dataSourceTable(tablenum(SalesTable)).addRange(fieldnum(SalesTable, SalesId)).value(strSalesTable); queryRun = new QueryRun(query); salesFormLetter.chooseLinesQuery(queryRun); salesFormLetter.transDate(systemdateget()); salesFormLetter.specQty(SalesUpdate::All); salesFormLetter.printFormLetter(true); salesFormLetter.printout(Printout::After); // User print settings from Sales order form if (iCnt == 0) { salesFormLetter_PackingSlip = SalesFormLetter::construct(DocumentStatus::PackingSlip); lastValues = xSysLastValue::getValue(curext(), curUserId(), UtilElementType::Class, classStr(SalesFormLetter_PackingSlip), formStr(SalesTable)); salesFormLetter_PackingSlip.unpack(lastValues); printSettingsOrig = new SRSPrintDestinationSettings(salesFormLetter_PackingSlip.printerSettingsFormletter(PrintSetupOriginalCopy::Original)); printSettingsCopy = new SRSPrintDestinationSettings(salesFormLetter_PackingSlip.printerSettingsFormletter(PrintSetupOriginalCopy::Copy)); } iCnt++; salesFormLetter.updatePrinterSettingsFormLetter(printSettingsOrig.pack(), PrintSetupOriginalCopy::Original); salesFormLetter.updatePrinterSettingsFormLetter(printSettingsCopy.pack(), PrintSetupOriginalCopy::Copy); salesFormLetter.usePrintManagement(true); //End salesFormLetter.createParmUpdate(); //AX2009? salesFormLetter.chooseLines(null,true); salesFormLetter.reArrangeNow(true); salesFormLetter.run();