Create Invoice PO base on Packing Slip/Product Receipt by X++

This code will created pending invoice base on VendPackingSlipJour data and posting that’s pending invoice at the end of code.

PurchFormLetter             purchFormLetter;

    PurchTable                  purchTable;
    PurchLine                   purchLine;

    VendPackingSlipJour         vendPackingSlipJour;
    VendPackingSlipTrans        vendPackingSlipTrans;

    VendInvoiceInfoTable        vendInvoiceInfoTable;
    VendInvoiceInfoLine         vendInvoiceInfoLine;
    VendInvoiceInfoSubTable     vendInvoiceInfoSubTable;
    VendInvoiceInfoSubLine      vendInvoiceInfoSubLine;

    PurchId                     purchId;
    PackingSlipId               packingSlipId;
    ;

    purchId = '9001-PO-16-000745';
    packingSlipId = '9001-PO-16-000745-2';

    ttsBegin;
    purchTable = PurchTable::find(purchId);

    while select vendPackingSlipJour
        where vendPackingSlipJour.PurchId == purchTable.PurchId
        && vendPackingSlipJour.PackingSlipId == packingSlipId
    {

        //Generate Pending Invoice Header
        vendInvoiceInfoTable.clear();
        vendInvoiceInfoTable.initValue();
        vendInvoiceInfoTable.initFromPurchTable(purchTable);

        vendInvoiceInfoTable.DocumentOrigin  = DocumentOrigin::Manual;
        vendInvoiceInfoTable.CurrencyCode = purchTable.CurrencyCode;
        vendInvoiceInfoTable.DeliveryName = purchTable.DeliveryName;
        vendInvoiceInfoTable.Num = "INV-" + vendPackingSlipJour.PackingSlipId; //add invoice number in here
        vendInvoiceInfoTable.PurchName = purchTable.PurchName;
        vendInvoiceInfoTable.VendInvoiceSaveStatus = VendInvoiceSaveStatus::Pending;
        vendInvoiceInfoTable.DocumentDate = systemDateGet();
        vendInvoiceInfoTable.LastMatchVariance = LastMatchVarianceOptions::OK;
        vendInvoiceInfoTable.ParmJobStatus = ParmJobStatus::Waiting;
        vendInvoiceInfoTable.Approved = NoYes::Yes;
        vendInvoiceInfoTable.Approver = DirPersonUser::currentWorker();

        vendInvoiceInfoTable.DefaultDimension = vendInvoiceInfoTable.copyDimension(purchTable.DefaultDimension);

        vendInvoiceInfoTable.defaultField(fieldNum(VendInvoiceInfoTable,RemittanceLocation),null,purchTable);
        vendInvoiceInfoTable.defaultField(fieldNum(VendInvoiceInfoTable,FixedDueDate),null,purchTable);
        vendInvoiceInfoTable.defaultField(fieldNum(VendInvoiceInfoTable,ExchRate),null,purchTable);
        vendInvoiceInfoTable.defaultField(fieldNum(VendInvoiceInfoTable,TransDate),null,purchTable);
        vendInvoiceInfoTable.defaultField(fieldNum(VendInvoiceInfoTable,PaymMode),null,purchTable);

        vendInvoiceInfoTable.insert();

        //Generate Vend Invoice Info reference
        if(vendInvoiceInfoTable)
        {
            vendInvoiceInfoSubTable.clear();
            vendInvoiceInfoSubTable.initValue();
            vendInvoiceInfoSubTable.defaultRow();

            vendInvoiceInfoSubTable.ParmId = vendInvoiceInfoTable.ParmId;
            vendInvoiceInfoSubTable.OrigPurchId = vendInvoiceInfoTable.PurchId;
            vendInvoiceInfoSubTable.PurchName = vendInvoiceInfoTable.PurchName;
            vendInvoiceInfoSubTable.TableRefId = vendInvoiceInfoTable.TableRefId;

            vendInvoiceInfoSubTable.insert();
        }

        //select all packing slip line
        while select vendPackingSlipTrans
            where vendPackingSlipTrans.PackingSlipId == vendPackingSlipJour.PackingSlipId
            && vendPackingSlipTrans.VendPackingSlipJour == vendPackingSlipJour.RecId
        {
            //Generate Pending Invoice Line
            purchLine = vendPackingSlipTrans.purchLine();
            vendInvoiceInfoLine.clear();
            vendInvoiceInfoLine.initValue();
            vendInvoiceInfoLine.defaultRow(null,purchLine);
            vendInvoiceInfoLine.initFromPurchLine(purchLine);

            vendInvoiceInfoLine.DeliveryName = vendInvoiceInfoTable.DeliveryName;
            vendInvoiceInfoLine.ParmId = vendInvoiceInfoTable.ParmId;
            vendInvoiceInfoLine.TableRefId = vendInvoiceInfoTable.TableRefId;
            vendInvoiceInfoLine.currencyCode = vendInvoiceInfoTable.CurrencyCode;
            vendInvoiceInfoLine.LineNum = any2int(purchLine.LineNumber);

            vendInvoiceInfoLine.InvoiceAccount = vendInvoiceInfoTable.InvoiceAccount;
            vendInvoiceInfoLine.InventDimId = vendPackingSlipTrans.InventDimId;
            vendInvoiceInfoLine.OrderAccount  = vendInvoiceInfoTable.OrderAccount;
            vendInvoiceInfoLine.ItemId = vendPackingSlipTrans.ItemId;
            vendInvoiceInfoLine.InventTransId = vendPackingSlipTrans.InventTransId;

            vendInvoiceInfoLine.DocumentOrigin = DocumentOrigin::Manual;

            vendInvoiceInfoLine.ReceiveNow = vendPackingSlipTrans.Qty;
            vendInvoiceInfoLine.RemainBefore = vendPackingSlipTrans.Qty;
            vendInvoiceInfoLine.RemainBeforeInvent = vendPackingSlipTrans.Qty;

            vendInvoiceInfoLine.PurchPrice = purchLine.PurchPrice;
            vendInvoiceInfoLine.InventNow = vendPackingSlipTrans.Qty;
            vendInvoiceInfoLine.LineAmount = (purchLine.LineAmount / purchLine.QtyOrdered) * vendPackingSlipTrans.Qty;

            vendInvoiceInfoLine.DefaultDimension = purchLine.DefaultDimension;

            vendInvoiceInfoLine.insert();

            //Generate Vend Invoice Info reference from packing slip
            if(vendInvoiceInfoLine.RecId)
            {
                vendInvoiceInfoSubLine.clear();
                vendInvoiceInfoSubLine.initValue();
                vendInvoiceInfoSubLine.defaultRow();
                vendInvoiceInfoSubLine.ParmId = vendInvoiceInfoTable.ParmId;
                vendInvoiceInfoSubLine.LineRefRecId = vendInvoiceInfoLine.RecId;
                vendInvoiceInfoSubLine.ReceiveNow = vendPackingSlipTrans.Qty;
                vendInvoiceInfoSubLine.InventNow = vendPackingSlipTrans.Qty;
                vendInvoiceInfoSubLine.JournalRefRecId = vendPackingSlipTrans.RecId;
                vendInvoiceInfoSubLine.JournalRefTableId = vendPackingSlipTrans.TableId;
                vendInvoiceInfoSubLine.DocumentId = vendPackingSlipTrans.PackingSlipId;
                vendInvoiceInfoSubLine.insert();
            }
        }

        //Posting pending invoice invoice
        purchFormLetter = PurchFormLetter_Invoice::newFromSavedInvoice(vendInvoiceInfoTable);
        purchFormLetter.update(vendInvoiceInfoTable.purchTable(),vendInvoiceInfoTable.Num);
    }

    ttsCommit;

    info(strFmt('Purchase Order %1 invoiced',purchTable.PurchId));
Advertisements

Get tax amount through x++

static void TIDgetTax(Args _args)
{
    TaxAmount           tax;
    CustInvoiceTrans    CustInvoiceTrans;
    ;

    CustInvoiceTrans =  CustInvoiceTrans::findRecId(5637155209);
    tax = Tax::calcTaxAmount(CustInvoiceTrans.TaxGroup, CustInvoiceTrans.TaxItemGroup, CustInvoiceTrans.InvoiceDate,
                            CustInvoiceTrans.CurrencyCode, CustInvoiceTrans.LineAmount, TaxModuleType::FreeTxtInvoice);

    info(strfmt('%1', tax));
}

Consuming webservices (SOAP) from AX example code

public static container UserInfoByIDRequest(str _storeName, str _idType, str _idNo, str _extRef,str _username = "",str _password = "")
{
    TIDIDSSIMPONI.ServiceReferences.TIDIDSSR.Summary summary;
    TIDIDSSIMPONI.ServiceReferences.TIDIDSSR.RemittanceClient svcClient;
    TIDIDSSIMPONI.ServiceReferences.TIDIDSSR.UserInfoByIDRequest request;
    TIDIDSSIMPONI.ServiceReferences.TIDIDSSR.UserInfoByIDResponse response;

    CLRObject clrObject;
    System.Exception ex;
    str errorCode, errorMesg;
    container  returnCon;
    boolean    canConnectAPI;
    str        errorCanConnectAPI;

    new InteropPermission(InteropKind::ClrInterop).assert();
    try
    {
        clrObject = CLRInterop::getType("TIDIDSSIMPONI.ServiceReferences.TIDIDSSR.RemittanceClient");
        svcClient = AifUtil::createServiceClient(clrObject);

        request = new TIDIDSSIMPONI.ServiceReferences.TIDIDSSR.UserInfoByIDRequest();

        //if no username or password provided, get from AX
        if(!_username || !_password)
        {
            _username = TIDIDSSimponiWebConsumeMethod::getUserNamePasswordStore(_storeName).IPMS_GaleriUserName;
            _password = TIDIDSSimponiWebConsumeMethod::getUserNamePasswordStore(_storeName).IPMS_GaleriPassword;
        }

        request.set_Username(_username);
        request.set_Password(_password);
        request.set_StoreName(_storeName);
        request.set_IdType(_idType);
        request.set_IdNo(_idNo);
        request.set_ExtRef(_extRef);

        //consuming webservice API
        response = svcClient.GetUserInfoByID(request);
        summary = response.get_Summary();

        //unpack to variable
        errorCode = summary.get_ErrorCode();
        errorMesg = summary.get_ErrorMessage();

        //packing all variable to container and return it
        returnCon += errorCode;
        returnCon += errorMesg;



        //sucess connect to webAPI
        canConnectAPI = true;

    }
    catch(Exception::CLRError)
    {
        ex = CLRInterop::getLastException();
        info(ex.ToString());

        canConnectAPI = false;
        errorCanConnectAPI =ex.ToString();
    }

    return [canConnectAPI, errorCanConnectAPI, returnCon];
}

Only foreign key constraints are allowed on this table.

Best Practice Error

Only foreign key constraints are allowed on this table

Capture

How to rectify this best practice error.

For Custom Table

  1. Export table to XPO
  2. Edit it with text editor, and change
    • from: EnforceFKRelation 1
    • to: EnforceFKRelation 0
  3. delete table in AX, synchronize
  4. import  xpo file

Capture

For Standard  Table

Some custom relation table may have some error on standard table, we can fix this  best practice error using same trick as above, but for this one lets check on XPO file and change REFERENCETYPE value.

  1. Export table to XPO
  2. Edit it with text editor, and change
    • from: REFERENCETYPE  NORMAL
    • to: REFERENCETYPE PKFK
  3. delete table in AX, synchronize
  4. import  xpo file

Capture.

Running Batch Job from X++ example code

static void TID_ExecuteBatchJobDistribution(Args _args)
{
    BatchHeader header;
    SysRecurrenceData sysRecurrenceData;
    Batch batch;
    BatchJob batchJob;
    RetailConnScheduleRunner _RetailConnScheduleRunner; // Class extends RunBaseBatch
    BatchInfo processBatchInfo;
    BatchRetries noOfRetriesOnFailure = 4;
    ;

    // Setup the RunBaseBatch Job
    header = BatchHeader::construct();
    _RetailConnScheduleRunner = new RetailConnScheduleRunner();
    processBatchInfo = _RetailConnScheduleRunner.batchInfo();
    processBatchInfo.parmRetriesOnFailure(noOfRetriesOnFailure);
    processBatchInfo.parmCaption(_RetailConnSchedule.Name); // Description Batch Job
    processBatchInfo.parmGroupId('RTL'); // Batch Gorup
    processBatchInfo.parmBatchExecute(NoYes::Yes);
    header.addTask(_RetailConnScheduleRunner);

    // Set the recurrence data
    sysRecurrenceData = SysRecurrence::defaultRecurrence();
    SysRecurrence::setRecurrenceStartDateTime(sysRecurrenceData, DateTimeUtil::addSeconds(DateTimeUtil::utcNow(), 20)); // Set range of recurrence
    SysRecurrence::setRecurrenceNoEnd(sysRecurrenceData);
    SysRecurrence::setRecurrenceUnit(sysRecurrenceData, SysRecurrenceUnit::Minute); // Set reccurence pattern
    header.parmRecurrenceData(sysRecurrenceData);
    // Set the batch alert configurations
    header.parmAlerts(NoYes::No, NoYes::Yes, NoYes::No, NoYes::Yes, NoYes::Yes);
    header.save();

    // Update the frequency to run the job to every two minutes
    ttsbegin;
    select forupdate batchJob
    join batch
    where batchJob.RecId == batch.BatchJobId
    && batch.ClassNumber == classnum(RetailConnScheduleRunner);

    sysRecurrenceData = batchJob.RecurrenceData;
    sysRecurrenceData = conpoke(sysRecurrenceData, 8, [10]);
    batchJob.RecurrenceData = sysRecurrenceData;
    batchJob.update();
    ttscommit;
}