D365 electronic reporting

Add a transformation with double quotes

Formula

CONCATENATE(CHAR(34), TEXT(parameter), CHAR(34))

or if you want it not to show quotes when the parameter is blank, you can use the code below

IF(parameter = “”,
parameter,
CONCATENATE(CHAR(34), TEXT(parameter), CHAR(34))
)

D365 How to get a dimension value based on the dimension name

    str projAttrJV  = this.getDimensionDisplayValue_DEV(_projTable.DefaultDimension,#dimAttr );

    if (projAttrJV == #dimRangeValue)
    {
   /// <summary>
    /// Get Dimension Display value
    /// </summary>
    /// <param name = "defaultDimension"></param>
    /// <param name = "dimName"></param>
    /// <returns></returns>
    public str getDimensionDisplayValue_DEV(RecId defaultDimension, Name dimName)
    {
        DimensionAttributeValueSetStorage dimStorage;

        dimStorage = DimensionAttributeValueSetStorage::find(defaultDimension);
        return dimStorage.getDisplayValueByDimensionAttribute(DimensionAttribute::findByName(dimName).RecId);
    }

D365 Data Entity Import Default Dimension using the DimensionDisplayValue and converting to a DefaultDimension

/// <summary>
    /// Map entity to data source
    /// </summary>
    /// <param name = "_entityCtx"></param>
    /// <param name = "_dataSourceCtx"></param>
    public void mapEntityToDataSource(DataEntityRuntimeContext _entityCtx, DataEntityDataSourceRuntimeContext _dataSourceCtx)
    {
        next mapEntityToDataSource(_entityCtx, _dataSourceCtx);

        if (_dataSourceCtx.name() == dataEntityDataSourceStr(AssetFixedAssetEntity, AssetTable))
        {
            AssetTable assetTable = _dataSourceCtx.getBuffer();
            
            assetTable.DefaultDimension_DEV = this.getDefaultDimensionFromDisplayValues_DEV(DimensionDataEntityStructureType::DataEntityDefaultDimensionFormat, this.DimensionDisplayValue_DEV);

        }
    }

	/// <summary>
    /// Get default dimension from display value
    /// </summary>
    /// <param name = "_structureType"></param>
    /// <param name = "_dimensionDisplayValue"></param>
    /// <returns></returns>
    public DimensionDefault getDefaultDimensionFromDisplayValues_DEV(DimensionDataEntityStructureType _structureType, DimensionDisplayValue  _dimensionDisplayValue)
    {
        str                     displayValueDelimiter                           = DimensionParameters::getDimensionSegmentDelimiter();
        container               integrationDefaultDimensionDisplayValueSegments = DimensionHierarchy::getDisplayStringDimensionIntegrationStructureSegments(_structureType);
        container				conDimensionDisplayValue = str2con_RU(_dimensionDisplayValue, displayValueDelimiter);
        Name					dimensionAttributeName;
        DimensionValue			dimensionValue;

        DimensionAttributeValueSetStorage invoiceDAVSStorage = new DimensionAttributeValueSetStorage();

        void addItem(DimensionAttributeValue _dav)
        {
            if (_dav)
                invoiceDAVSStorage.addItem(_dav);
        }

        for (int i = 1; i <= conLen(integrationDefaultDimensionDisplayValueSegments); i++)
        {
            dimensionAttributeName = conPeek(integrationDefaultDimensionDisplayValueSegments, i);
            dimensionValue = conPeek(conDimensionDisplayValue, i);
            
            addItem(DimensionAttributeValue::findByDimensionAttributeAndValue(DimensionAttribute::findByName(dimensionAttributeName), dimensionValue));
		}

        return invoiceDAVSStorage.save();
    }

D365 How to create intercompany invoice

/// /// This class generates customer invoices automatically for intercompany project transactions. ///
class ProjIntercompanyInvoicePeriodic_DEV extends RunBaseBatch
{
Dialog dialogRunBase;
CompanyId interEntityLE;
DialogField dflInterEntityLE;

QueryRun                            projectQueryRun;

ProjParameters                        projParameters;
ProjInterEntityParameters_DEV        projInterEntityParameters;
ProjTable                            projTable;
ProjPostedTransTable                projPostedTransTable;
CustInvoiceTable                    custInvoiceTable;
TransDate                            todaysDate, invoiceDate;
ProjCategory                        projCategory;
ProjTransType                        currentTransType;
MonthOfYearId                       todaysMonthOfYear, currentMonthOfYear;  
Year                                todaysYear;

#define.CurrentVersion(2)
#localMacro.CurrentList
interEntityLE
#endmacro

/// <summary>
/// Returns an object that contains the methods that are described by the <c>RunBaseDialogable</c>
/// interface.
/// </summary>
/// <returns>
/// An object that contains the methods that are described by the <c>RunBaseDialogable</c> interface.
/// </returns>
/// <remarks>
/// A dialog box can be either built by using the <c>Dialog</c> class or by using a class that is
/// created in the Application Object Tree (AOT).
/// </remarks>
Object dialog()
{
    DialogGroup     selectTransactionsGroup;

    dialogRunBase = super();

    selectTransactionsGroup = dialogRunBase.addGroup("@INT:LegalEntityForBilling");
    dflInterEntityLE                    = dialogRunBase.addFieldValue(extendedTypeStr(SelectableDataArea), interentityLE);
    selectTransactionsGroup.addFieldname(dflInterEntityLE.name());

    return dialogRunBase;
}

/// <summary>
/// Stores the value entered by users into local variables.
/// </summary>
/// <returns>
/// True if the values were stored successfully; otherwise false.
/// </returns>
boolean getFromDialog()
{
    interEntityLE     = dflInterEntityLE.value();

    return super();
}

/// <summary>
/// Initializes the query to be used for fetching records to be processed.
/// </summary>
protected void initQuery()
{
    QueryBuildDataSource qbds;
    Query                query = new Query();
    QueryBuildRange         qbrStatus;

    //do not allow cross company
    //query.allowCrossCompany(true);
    qbds = query.addDataSource(tableNum(ProjTable));
    qbds.addRange(fieldNum(ProjTable, ProjInvoiceProjId));
    qbds.addRange(fieldNum(ProjTable, ProjId));

    qbrStatus = qbds.addRange(fieldNum(ProjTable, Status));
    qbrStatus.value(queryValue(ProjStatus::InProcess));
    qbrStatus.status(RangeStatus::Locked);

    #define.dimAttr('JV_Flag')
    #define.dimRangeValue('JV')

    DimensionProvider dimensionProvider = new DimensionProvider();

    dimensionProvider.addAttributeRangeToQuery(
    query,
    qbds.name(),
    identifierStr(DefaultDimension),
        DimensionComponent::DimensionAttribute,
    #dimRangeValue,
    #dimAttr,
    true);

    projectQueryRun = new QueryRun(query);
}

protected void new()
{
    super();
    this.initQuery();
}

public container pack()
{
    return [#CurrentVersion,#CurrentList, projectQueryRun.pack()];
}

public QueryRun queryRun()
{
    return projectQueryRun;
}

public boolean validate(Object _calledFrom = null)
{
    projParameters = ProjParameters::find();
    projInterEntityParameters = ProjInterEntityParameters_DEV::find(interEntityLE);

    boolean ret = true;

    if (!interEntityLE)
    {
        ret = false;
    }

    if (!projInterEntityParameters.IntercompanyCustAccount)
    {
        ret = checkFailed(strFmt("@INT:InterEntityBillingCustomerNotDefined", interEntityLE));
    }

    if (!projParameters.IEBDefaultExpenseCategory_DEV)
    {
        ret = checkFailed(strFmt("@SYS331078", fieldPName(ProjParameters,IEBDefaultExpenseCategory_DEV)));
    }

    if (!projParameters.IEBDefaultHoursCategory_DEV)
    {
        ret = checkFailed(strFmt("@SYS331078", fieldPName(ProjParameters,IEBDefaultHoursCategory_DEV)));
    }

    if (!projParameters.IEBDefaultItemCategory_DEV)
    {
        ret = checkFailed(strFmt("@SYS331078", fieldPName(ProjParameters,IEBDefaultItemCategory_DEV)));
    }

    return ret;
}

public void update()
{
    int counter;

    while (projectQueryRun.next())
    {
        projTable = projectQueryRun.get(tablenum(ProjTable));

        while select * from projPostedTransTable
        order by ProjTransType, TransDate, ProjId
        where projPostedTransTable.InterEntityProcessedRecId_DEV == NoYes::No
        && projPostedTransTable.InterEntityCustInvoiceId_DEV == ""
        && projPostedTransTable.InterEntityCostReversal_DEV == NoYes::No
        && projPostedTransTable.InterEntityVendInvoiceId_DEV == ""
        && projPostedTransTable.ProjId == projTable.ProjId
        && (projPostedTransTable.ProjTransType == ProjTransType::Cost
        || projPostedTransTable.ProjTransType == ProjTransType::Hour
        || projPostedTransTable.ProjTransType == ProjTransType::Item)
        {
            this.createInvoice();
            counter++;
        }

    }

    info(strFmt("@INT:RecordsProcessed", counter));
}

/// <summary>
/// Contains the code that does the actual job of the class.
/// </summary>
public void run()
{
    #OCCRetryCount

    if (! this.validate())
        throw error("@WMHE:WMHE229");

    try
    {
        ttsbegin;

        this.update();

        ttscommit;
    }
    catch (Exception::Deadlock)
    {
        retry;
    }
    catch (Exception::UpdateConflict)
    {
        if (appl.ttsLevel() == 0)
        {
            if (xSession::currentRetryCount() >= #RetryNum)
            {
                throw Exception::UpdateConflictNotRecovered;
            }
            else
            {
                retry;
            }
        }
        else
        {
            throw Exception::UpdateConflict;
        }
    }
}

/// <summary>
///    Determines whether to add a select button to the dialog.
/// </summary>
/// <returns>
///    Always returns true.
/// </returns>
/// <remarks>
///    If you click this button, it will show the query form. Therefore, the <c>queryRun</c> method has to
///    return a valid <c>queryRun</c> class.If you change the return value to false, the button will no
///    longer be added.
/// </remarks>
public boolean showQueryValues()
{
    return true;
}

boolean unpack(container packedClass)
{
    Integer     version  = conPeek(packedClass,1);
    container   packedQueryRun;

    switch (version)
    {
        case #CurrentVersion:
            [version, #CurrentList, packedQueryRun] = packedClass;
            projectQueryRun = new QueryRun(packedQueryRun);
            break;
        default:
            return false;
    }

    return true;
}

/// <summary>
/// Constructs an instance of <c>ProjIntercompanyInvoicePeriodic</c> class.
/// </summary>
/// <returns>
/// Instance of <c>ProjIntercompanyInvoicePeriodic</c> class.
/// </returns>
public static ProjIntercompanyInvoicePeriodic_DEV construct()
{
    return new ProjIntercompanyInvoicePeriodic_DEV();
}

static ClassDescription description()
{
    return "@INT:ProcessInterEntityBilling";
}

public static void main(Args _args)
{
    ProjIntercompanyInvoicePeriodic_DEV    projIntercompanyInvoicePeriodic = ProjIntercompanyInvoicePeriodic_DEV::construct();

    if (projIntercompanyInvoicePeriodic.prompt())
    {
        projIntercompanyInvoicePeriodic.runOperation();
    }
}

protected boolean canRunInNewSession()
{
    return false;
}

public CustInvoiceTable createInvoice()
{
    MonthOfYearId projTransMonthOfYear;
    Year          projTransYear;

    todaysDate = DateTimeUtil::getSystemDate(DateTimeUtil::getUserPreferredTimeZone());
    todaysMonthOfYear = mthOfYr(todaysDate);
    todaysYear = year(todaysDate);

    projTransMonthOfYear = mthOfYr(projPostedTransTable.TransDate);
    projTransYear = year(projPostedTransTable.TransDate);

    if (currentTransType != projPostedTransTable.ProjTransType 
        || currentMonthOfYear != projTransMonthOfYear)
    {
        //must create a new invoice for each TransType/Month so make this null
        custInvoiceTable = null;


        if (todaysMonthOfYear == projTransMonthOfYear
            && todaysYear == projTransYear)
        {
            invoiceDate = todaysDate;
        }
        else
        {
            invoiceDate = endMth(projPostedTransTable.TransDate);
        }

        currentTransType = projPostedTransTable.ProjTransType;
        currentMonthOfYear = projTransMonthOfYear;
    }

    if (!custInvoiceTable)
    {
        custInvoiceTable = this.createInvoiceHeader();
    }
    this.createInvoiceLine();

    return custInvoiceTable;
}

private CustInvoiceTable createInvoiceHeader()
{
    CustTable custTable = CustTable::find(projInterEntityParameters.IntercompanyCustAccount);
    WorkflowTable workflowTable = WorkflowTable::findActiveTemplate('CustFreeTextInvoiceTemplate');

    custInvoiceTable.initFromCustTable(custTable);
    custInvoiceTable.InvoiceDate = invoiceDate;
    custInvoiceTable.ProjIntercompany = curExt();

    if (workflowTable && workflowTable.DataArea == curExt())
    {
        custInvoiceTable.WorkflowApprovalStatus = CustFreeInvoiceWFApprovalStatus::Draft;
    }
    custInvoiceTable.setListCode();
    custInvoiceTable.InterEntityBilling_DEV = NoYes::Yes;
    custInvoiceTable.insert();

    return custInvoiceTable;
}

/// <summary>
/// Creates the intercompany invoice line.
/// </summary>
/// <param name = "_origTrans">
/// An instance of the <c>ProjIntercompanyInvoiceOrigTrans</c>.
/// </param>
/// <param name = "_invoice">
/// An instance of <c>CustInvoiceTable</c> buffer.
/// </param>
/// <returns>
/// returns the created customer invoice line.
/// </returns>
protected CustInvoiceLine createInvoiceLine()
{
    int                            lineNum;
    CustInvoiceLine                newLine;
    CustInvoiceLineInterProj    newLineProj;
    LedgerDimensionAccount        lineLedgerDimension;
    AmountCur                    transferPrice;
    ProjLinePropertyId            projLinePropertyId;
    ProjTransferPriceTransType    projTransferPriceTransType = this.getTransferPriceTransType(projPostedTransTable.ProjTransType);

    projCategory = this.getDefaultIEBProjCategory();

    if (projTable.ProjId && ProjCategory.CategoryId)
    {
        projLinePropertyId = ProjLinePropertySetup::findLinePropertyId(projTable.ProjId, ProjCategory.CategoryId);
    }

    transferPrice = ProjTransferPrice::findTransferPrice(projPostedTransTable.Resource,
                                projInterEntityParameters.LegalEntityForBilling,
                                projTable.RecId,
                                projCategory.RecId,
                                projLinePropertyId,
                                invoiceDate,
                                projInterEntityParameters.LegalEntityForBilling,
                                Ledger::accountingCurrency(),
                                0,
                                projPostedTransTable.TotalCostAmountCur,
                                ExchangeRateHelper::curPrice2CurPrice(projPostedTransTable.TotalSalesAmountCur, projPostedTransTable.CurrencyId, Ledger::accountingCurrency()),
                                projTransferPriceTransType);

    if (transferPrice == 0)
    {
        transferPrice = projPostedTransTable.TotalCostAmountCur;
    }

    lineNum++;
    newLine.initFromCustInvoiceTable(custInvoiceTable);
    newLine.LineNum = lineNum;
    newLine.ParentRecId = custInvoiceTable.RecId;
    newLine.Quantity = 1;
    //newLine.UnitPrice = ExchangeRateHelper::curPrice2CurPrice(projPostedTransTable.TotalCostAmountCur, projPostedTransTable.CurrencyIdCost, custInvoiceTable.CurrencyCode, invoiceDate);
    newLine.UnitPrice = transferPrice;
    newLine.AmountCur = newLine.Quantity * newLine.UnitPrice;

    // Swapping the negative sign for the negative expense report
    if (newLine.Quantity > 0 && newLine.UnitPrice < 0)
    {
        newLine.Quantity = -newLine.Quantity;
        newLine.UnitPrice = -newLine.UnitPrice;
    }

    newLine.Description = projParameters.IEBDefaultLineDesc_DEV;
    newLine.InvoiceTxt  = projParameters.IEBDefaultLineDesc_DEV;
    newLine.TaxItemGroup = projCategory.TaxItemGroupId;
    lineLedgerDimension = this.getLedgerDimensionForProjPosting(custInvoiceTable);
    newLine.LedgerDimension = lineLedgerDimension;
    newLine.DefaultDimension = custInvoiceTable.mergeDimension(projPostedTransTable.DefaultDimension, custInvoiceTable.DefaultDimension);
    newLine.OriginatingActivityId_DEV = projPostedTransTable.ActivityNumber;
    newLine.insert();

    newLineProj.CustInvoiceLine                = newLine.RecId;
    newLineProj.TransDate                   = invoiceDate;
    newLineProj.ProjDataArea                = projInterEntityParameters.LegalEntityForBilling;
    newLineProj.ProjId                      = projPostedTransTable.ProjId;
    newLineProj.ProjCategoryId                = projCategory.CategoryId;
    newLineProj.ProjLinePropertyId            = projLinePropertyId;
    newLineProj.HcmWorker                   = 0;
    newLineProj.TransType                   = projPostedTransTable.ProjTransType;
    newLineProj.TransactionOrigin            = ProjOrigin::ProjPostedTrans_DEV;
    newLineProj.OrigTransRecId              = projPostedTransTable.RecId;
    newLineProj.OrigTransCurrency           = Ledger::accountingCurrency();
    newLineProj.OrigTransSourceDocumentLine = 0;
    newLineProj.CostPrice                   = abs(projPostedTransTable.TotalCostAmountCur);
    newLineProj.SalesPrice                  = abs(transferPrice);
    newLineProj.SalesPriceCurrency          = Ledger::accountingCurrency();

    newLineProj.ActivityNumber              = "";
    if (projPostedTransTable.OriginatingActivityId_DEV)
    {
        newLineProj.ActivityNumber    = projPostedTransTable.OriginatingActivityId_DEV;
    }

    newLineProj.insert();

    //set inter entity processed field
    projPostedTransTable.selectForUpdate(true);
    projPostedTransTable.InterEntityProcessedRecId_DEV = newLine.RecId;
    projPostedTransTable.doUpdate();

    return newLine;
}

public ProjCategory getDefaultIEBProjCategory()
{
    ProjCategoryId              categoryId;
    ProjCategory                category;

    categoryId  = ProjParameters::getDefaultIEBCategory_DEV(projPostedTransTable.ProjTransType);
    category    = ProjCategory::find(categoryId);

    return category;
}

protected final LedgerDimensionAccount getLedgerDimensionForProjPosting(CustInvoiceTable _invoice)
{
    LedgerDimensionAccount ledgerDimension = ProjPosting::findprojPosting(ProjAccountType::IntercompanyRevenue, projPostedTransTable.ProjId, projCategory.CategoryId, 0, false, '', curExt(), interEntityLE ).LedgerDimension;

    return ledgerDimension;
}

protected ProjTransferPriceTransType getTransferPriceTransType(ProjTransType _transType)
{
    ProjTransferPriceTransType transferPriceType;

    switch(_transType)
    {
        case ProjTransType::Hour:
            transferPriceType = ProjTransferPriceTransType::Timesheet;
            break;
        case ProjTransType::Cost:
            transferPriceType = ProjTransferPriceTransType::Expense;
            break;
        case ProjTransType::Item:
            transferPriceType = ProjTransferPriceTransType::VendInvoiceLine;
            break;
    }

    return transferPriceType;
}

}

For posting of the vendor invoice, this class must be populated

public class CustInvoiceLineInterProjEventHandler_DEV
{
/// /// Get inter entity billing original transaction ///
///
///
[SubscribesTo(tableStr(CustInvoiceLineInterProj), staticDelegateStr(CustInvoiceLineInterProj, retrieveGetOrigTransDelegate))]
public static void CustInvoiceLineInterProj_retrieveGetOrigTransDelegate(RefRecId _origTransRecId, EventHandlerResult _result)
{
ProjIntercompanyInvoiceOrigTrans origTrans;

    origTrans = ProjIntercompanyInvoiceOrigPostedTrans_DEV::newFromProjPostedTransRecId(_origTransRecId);

    _result.result(origTrans);
}

}

Also we need to create a new interface class:

/// /// This class maps the values from an intercompany proj posted trans line to be used when generating an /// invoice against the borrowing legal entity. ///
public class ProjIntercompanyInvoiceOrigPostedTrans_DEV implements ProjIntercompanyInvoiceOrigTrans
{
ProjPostedTransTable projPostedTransTable;
AmountCur costPrice;
/// /// Returns the activity number of the posted line. ///
/// /// The activity number of the posted line. ///
public ProjActivityNumber getActivityNumber()
{
return “”;
}

/// <summary>
/// Retrieves the total line amount to be invoiced to the other legal entity.
/// </summary>
/// <returns>
/// The line amount to be invoiced to the other legal entity.
/// </returns>
public AmountCur getAmountCur()
{
    if (this.getQuantity() > 0)
    {
        return this.getQuantity() * this.getSalesPrice();
    }
    else
    {
        return this.getSalesPrice();
    }
}

/// <summary>
/// Retrieves the currency code in which the cost is incurred in the lending company.
/// </summary>
/// <returns>
/// The currency code in which the cost is incurred in the lending company.
/// </returns>
public CurrencyCode getCostCurrency()
{
    return projPostedTransTable.CurrencyIdCost;
}

/// <summary>
/// Retrieves the cost price of the transaction incurred in the lending company.
/// </summary>
/// <returns>
/// The cost price of the transaction incurred in the lending company.
/// </returns>
public Amount getCostPrice()
{
    return 0;
}

/// <summary>
/// Retrieves the currency code of the transaction, which is the one that the borrowing legal entity will be invoiced.
/// </summary>
/// <returns>
/// The currency code that the transaction should be invoiced.
/// </returns>
public CurrencyCode getCurrencyCode()
{
    return projPostedTransTable.CurrencyIdCost;
}

/// <summary>
/// Retrieves the data area ID of the lending legal entity.
/// </summary>
/// <returns>
/// The data area ID of the lending legal entity.
/// </returns>
public DataAreaId getDataAreaId()
{
    return projPostedTransTable.DataAreaId;
}

/// <summary>
/// Retrieves a default dimension set of the transaction.
/// </summary>
/// <returns>
/// A description of the transaction.
/// </returns>
public LedgerDefaultDimensionValueSet getDefaultDimension()
{
    return 0;
}

/// <summary>
/// Retrieves a description of the transaction.
/// </summary>
/// <returns>
/// A description of the transaction.
/// </returns>
public Description getDescription()
{
    return "";
}

/// <summary>
/// Retrieves the currency in which the sales price to the end customer is expressed in.
/// </summary>
/// <returns>
/// The currency in which the sales price to the end customer is expressed in.
/// </returns>
public CurrencyCode getFinalSalesCurrencyCode()
{
    return "";
}

/// <summary>
/// Retrieves the sales price that the final customer will be charged for this item.
/// </summary>
/// <returns>
/// The sales price that the final customer will be charged for this item.
/// </returns>
public AmountCur getFinalSalesPrice()
{
    CustInvoiceLine custInvoiceLine;

    select firstonly AmountCur from custInvoiceLine
        where custInvoiceLine.RecId == projPostedTransTable.InterEntityProcessedRecId_DEV;

    return custInvoiceLine.AmountCur;
}

/// <summary>
/// Retrieves the invoice indirect component amount.
/// </summary>
/// <returns>
/// The invoice indirect component amount of the transaction.
/// </returns>
public Amount getIndirectCost()
{
    return 0;
}

/// <summary>
/// Retrieves the line property ID of the transaction.
/// </summary>
/// <returns>
/// The line property ID of the transaction.
/// </returns>
public ProjLinePropertyId getLinePropertyId()
{
    return "";
}

/// <summary>
/// Retrieves the project category ID of the transaction.
/// </summary>
/// <returns>
/// The project category ID of the transaction.
/// </returns>
public ProjCategoryId getProjectCategoryId()
{
    return "";
}

/// <summary>
/// Retrieves the data area ID of the borrowing legal entity.
/// </summary>
/// <returns>
/// The data area ID of the borrowing legal entity.
/// </returns>
public DataAreaId getProjectDataAreaId()
{
    return "";
}

/// <summary>
/// Retrieves the ID of the related project in the borrowing legal entity.
/// </summary>
/// <returns>
/// The ID of the related project in the borrowing legal entity.
/// </returns>
/// <remarks>
/// This is the project where the costs will be incurred at the borrowing legal entity side.
/// </remarks>
public ProjId getProjectId()
{
    return projPostedTransTable.ProjId;
}

/// <summary>
/// Retrieves the number of items in this transaction.
/// </summary>
/// <returns>
/// The number of items in this transactions.
/// </returns>
public Qty getQuantity()
{
    return 0;
}

/// <summary>
/// Retrieves the record ID of the expense line.
/// </summary>
/// <returns>
/// The record ID of the intercompany transaction.
/// </returns>
public RefRecId getRecId()
{
    return projPostedTransTable.RecId;
}

/// <summary>
/// Gets the sales price that the other legal entity is expected to pay for the expense.
/// </summary>
/// <returns>
/// The sales price that the other legal entity is expected to pay for the expense.
/// </returns>
public Amount getSalesPrice()
{
    return 0;
}

/// <summary>
/// Retrieves the record ID of the source document line associated with the transaction.
/// </summary>
/// <returns>
/// The record ID of the source document line associated with the transaction.
/// </returns>
public SourceDocumentLineRecId getSourceDocumentLine()
{
    return 0;
}

/// <summary>
/// Retrieves the item sales tax group that will be used in the invoice line for this transaction.
/// </summary>
/// <returns>
/// The item sales tax group that will be used in the invoice line for this transaction.
/// </returns>
public TaxItemGroup getTaxItemGroup()
{
    ProjCategoryId              categoryId;
    ProjCategory                category;

    categoryId = ProjIntercompanyParameters::getValidCategory(this.getProjectCategoryId(), this.getProjectDataAreaId(), this.getTransType());
    category   = ProjCategory::find(categoryId);

    return category.TaxItemGroupId;
}

/// <summary>
/// Retrieves the transaction date.
/// </summary>
/// <returns>
/// The transaction date.
/// </returns>
public TransDate getTransDate()
{
    return projPostedTransTable.TransDate;
}

/// <summary>
/// Retrieves the origin of the transaction.
/// </summary>
/// <returns>
/// The origin of the transaction.
/// </returns>
public ProjTransactionOrigin getTransOrigin()
{
    return ProjOrigin::ProjPostedTrans_DEV;
}

/// <summary>
/// Retrieves the type of the project transaction.
/// </summary>
/// <returns>
/// The type of the project transaction.
/// </returns>
public ProjTransType getTransType()
{
    return ProjTransType::None;
}

/// <summary>
/// Retrieves the symbol of the unit of measure in which the quantity of this item is expressed.
/// </summary>
/// <returns>
/// The symbol of the unit of measure in which the quantity of this item is expressed.
/// </returns>
public UnitOfMeasureSymbol getUnitOfMeasureSymbol()
{
    UnitOfMeasure  unitOfMeasure;

    unitOfMeasure = UnitOfMeasure::findByInternalCode(UnitOfMeasureCodeSymbol::Pieces);
    if (!unitOfMeasure)
    {
        throw error(strFmt("@SYS4005066", UnitOfMeasureCodeSymbol::Pieces));
    }

    return unitOfMeasure.Symbol;
}

/// <summary>
/// Retrieves the unit price of the resource being invoiced.
/// </summary>
/// <returns>
/// The unit price of the resource being invoiced.
/// </returns>
public AmountCur getUnitPrice()
{
    return 0;
}

/// <summary>
/// Retrieves the record ID of the worker related to this transaction.
/// </summary>
/// <returns>
/// The record ID of the worker related to this transaction.
/// </returns>
public HcmWorkerRecId getWorker()
{
    return 0;
}

/// <summary>
/// Creates a new instance based on a <c>ProjPostedTransTable</c> record.
/// </summary>
/// <param name="_projPostedTransTable">
/// The <c>ProjPostedTransTable</c> record to be used in the intercompany invoicing process.
/// </param>
protected void new(ProjPostedTransTable _projPostedTransTable)
{
    projPostedTransTable                = _projPostedTransTable.data();
}

/// <summary>
/// Updates the billing status of the transaction being invoiced.
/// </summary>
/// <param name="_billed">
/// true if the transaction was included in some intercompany invoice; false if it should be available to be invoiced.
/// </param>
public void setBilled(boolean _billed)
{
}

/// <summary>
/// Displays the transaction in a form.
/// </summary>
/// <remarks>
/// Used for auditing purposes.
/// </remarks>
public void showTrans()
{
}

public static ProjIntercompanyInvoiceOrigPostedTrans_DEV construct(ProjPostedTransTable _projPostedTransTable)
{
    return new ProjIntercompanyInvoiceOrigPostedTrans_DEV(_projPostedTransTable);
}

/// <summary>
/// Creates a new instance of <c>ProjIntercompanyInvoiceOrigPostedTrans_DEV</c> for a given expense trans record ID.
/// </summary>
/// <param name="_projPostedTransRecId">
/// The record ID of the <c>ProjPostedTransTable</c> record that will be mapped.
/// </param>
/// <returns>
/// A new instance of <c>ProjIntercompanyInvoiceOrigPostedTrans_DEV</c>.
/// </returns>
public static ProjIntercompanyInvoiceOrigPostedTrans_DEV newFromProjPostedTransRecId(RefRecId _projPostedTransRecId)
{
    return new ProjIntercompanyInvoiceOrigPostedTrans_DEV(ProjPostedTransTable::findByRecId_DEV(_projPostedTransRecId));
}

}

D365 How to create project expense / hour / item journal

/// /// This class reverses the posted customer invoice into hour/expense/item journals ///
public class ProjInterEntityCostReversal_DEV
{
CustInvoiceJour custInvoiceJour;
CustInvoiceTable custInvoiceTable;
ProjParameters projParameters;
InventTable inventTable;

/// <summary>
/// Creates a new instance of <c>ProjInterEntityCostReversal_DEV</c>.
/// </summary>
/// <param name="_custInvoiceJour">
/// A mandatory <c>CustInvoiceJour</c> where the source data will come from
/// </param>
/// <param name="_custInvoiceTable">
/// A mandatory <c>CustInvoiceTable</c> where the source data will come from
/// </param>
protected void new(CustInvoiceJour _custInvoiceJour, CustInvoiceTable _custInvoiceTable)
{
    Debug::assert(_custInvoiceJour != null);

    custInvoiceJour        = _custInvoiceJour;
    custInvoiceTable    = _custInvoiceTable;

    projParameters = ProjParameters::find();
}

/// <summary>
/// Creates a new instance of <c>ProjInterEntityCostReversal_DEV</c>.
/// </summary>
/// <param name="_custInvoiceJour">
/// A mandatory <c>CustInvoiceJour</c> where the source data will come from
/// </param>
/// <param name="_custInvoiceTable">
/// A mandatory <c>CustInvoiceTable</c> where the source data will come from
/// </param>
/// <returns>
/// <c>ProjInterEntityCostReversal_DEV</c> created from the given parameters.
/// </returns>
public static ProjInterEntityCostReversal_DEV construct(CustInvoiceJour _custInvoiceJour, CustInvoiceTable _custInvoiceTable)
{
    return new ProjInterEntityCostReversal_DEV(_custInvoiceJour, _custInvoiceTable);
}

 public void reverseInterEntityCosts()
 {
     ProjTransType    projTransType;

     if (!this.validate())
        throw error("@INT:InterEntityCostReversalPostingCancelled");

     inventTable = InventTable::find(projParameters.IEBDefaultReversalItemId_DEV);

     CustInvoiceLineInterProj   custInvoiceLineInterProj;
     CustInvoiceLine                custInvoiceLineLocal;

     select firstonly TransType from custInvoiceLineInterProj
            order by TransType, TransDate
            join custInvoiceLineLocal
            where custInvoiceLineInterProj.CustInvoiceLine == custInvoiceLineLocal.RecId
            && custInvoiceLineLocal.ParentRecId == custInvoiceTable.RecId;

     projTransType = custInvoiceLineInterProj.TransType;

     switch (projTransType)
     {
         case ProjTransType::Hour:
             this.createReversalHourJournal();
             break;

         case ProjTransType::Cost:
             this.createReversalCostJournal();
             break;

         case ProjTransType::Item:
             this.createReversalItemJournal();
             break;

         default:
             throw error(Error::wrongUseOfFunction(funcName()));
             break;
     }
}

protected boolean validate()
{
    boolean ret = true;

    if (!projParameters.IEBDefaultReversalItemId_DEV)
    {
        ret = checkFailed(strFmt("@SYS331078", fieldPName(ProjParameters,IEBDefaultReversalItemId_DEV)));
    }

    if (!projParameters.IEBDefaultExpenseCategory_DEV)
    {
        ret = checkFailed(strFmt("@SYS331078", fieldPName(ProjParameters,IEBDefaultExpenseCategory_DEV)));
    }

    if (!projParameters.IEBDefaultHoursCategory_DEV)
    {
        ret = checkFailed(strFmt("@SYS331078", fieldPName(ProjParameters,IEBDefaultHoursCategory_DEV)));
    }

    if (!projParameters.IEBDefaultItemCategory_DEV)
    {
        ret = checkFailed(strFmt("@SYS331078", fieldPName(ProjParameters,IEBDefaultItemCategory_DEV)));
    }

    return ret;
}

protected void createReversalItemJournal()
{
    CustInvoiceLineInterProj    custInvoiceLineInterProj;
    CustInvoiceLine                custInvoiceLineLocal;
    InventJournalTable            inventJournalTable;
    JournalCheckPost            journalCheckPost;

    while select * from custInvoiceLineInterProj
        order by TransType, TransDate
        join custInvoiceLineLocal
        where custInvoiceLineInterProj.CustInvoiceLine == custInvoiceLineLocal.RecId
        && custInvoiceLineLocal.ParentRecId == custInvoiceTable.RecId
    {
        //create journal header
        if (!inventJournalTable)
        {
            inventJournalTable = this.createItemJournalHeader();
        }
        this.createItemJournalLine(inventJournalTable, custInvoiceLineInterProj, custInvoiceLineLocal);
    }

    ttsbegin;
    inventJournalTable.reread();
    InventJournalTable::initTotal(inventJournalTable);
    inventJournalTable.doUpdate();
    ttscommit;

    journalCheckPost = this.postItemJournal(inventJournalTable);

    inventJournalTable.reread();

    if (!inventJournalTable.Posted)
    {
        throw Error("@INT:InterEntityCostReversalPostingCancelled");
    }
}

protected InventJournalTable createItemJournalHeader()
{
    InventJournalName inventJournalName;
    InventJournalTable inventJournalTable;

    inventJournalName = InventJournalName::find(projParameters.inventJournalNameId);

    if (!inventJournalName)
    {
        throw error(strfmt("@GLS115420", projParameters.inventJournalNameId));
    }

    inventJournalTable.initValue();
    inventJournalTable.initFromInventJournalName(inventJournalName);

    inventJournalTable.JournalId = JournalTableData::newTable(inventJournalTable).nextJournalId();
    inventJournalTable.Description = projParameters.IEBDefaultLineDesc_DEV;
    inventJournalTable.SystemBlocked = NoYes::Yes;
    inventJournalTable.insert();

    return inventJournalTable;
}

protected void createItemJournalLine(InventJournalTable _inventJournalTable, CustInvoiceLineInterProj _custInvoiceLineInterProj, CustInvoiceLine _custInvoiceLine)
{
    InventJournalTrans          inventJournalTrans;
    InventJournalTableData        journalTableData = JournalTableData::newTable(_inventJournalTable);
    InventJournalTransData      journalTransData = journalTableData.journalStatic().newJournalTransData(inventJournalTrans, journalTableData);

    journalTransData.initFromJournalTable();

    inventJournalTrans.TransDate            = _custInvoiceLineInterProj.TransDate;
    inventJournalTrans.ProjId                = _custInvoiceLineInterProj.ProjId;
    inventJournalTrans.ProjCategoryId       = _custInvoiceLineInterProj.ProjCategoryId;
    inventJournalTrans.ProjSalesCurrencyId  = _custInvoiceLineInterProj.SalesPriceCurrency;
    inventJournalTrans.DefaultDimension     = _custInvoiceLine.DefaultDimension;
    inventJournalTrans.ProjLinePropertyId   = _custInvoiceLineInterProj.ProjLinePropertyId;
    inventJournalTrans.ProjTaxGroupId       = _custInvoiceLine.TaxGroup;

    inventJournalTrans.initFromInventTable(inventTable);

    inventJournalTrans.Qty              = -1;
    inventJournalTrans.PriceUnit        = 1;

    inventJournalTrans.ProjUnitID       = inventTable.inventTableModuleInvent().UnitId;
    inventJournalTrans.Worker           = HcmWorkerLookup::currentWorker();
    /*
    LedgerDimensionDefaultAccount defaultLedgerDimension = ProjPosting::getLedgerDimension(ProjAccountType::OffsetAccountItem, _custInvoiceLineInterProj.ProjId, _custInvoiceLineInterProj.ProjCategoryId , 0);
    LedgerDimensionAccount mergedLedgerDimension = LedgerDimensionFacade::serviceCreateLedgerDimension(defaultLedgerDimension, _custInvoiceLine.DefaultDimension);

    inventJournalTrans.LedgerDimension  = mergedLedgerDimension;
    */
    inventJournalTrans.ActivityNumber    = _custInvoiceLineInterProj.ActivityNumber;
    inventJournalTrans.activityNumberModified();
    inventJournalTrans.InterEntityCostReversal_DEV = NoYes::Yes;
    //other fields
    journalTransData.create();
}

protected JournalCheckPost postItemJournal(InventJournalTable _inventJournalTable)
{
    JournalCheckPost journalCheckPost;

    journalCheckPost = InventJournalCheckPost::newJournalCheckPost(JournalCheckPostType::Post, _inventJournalTable);
    journalCheckPost.run();

    return journalCheckPost;
}

protected void createReversalCostJournal()
{
    CustInvoiceLineInterProj    custInvoiceLineInterProj;
    CustInvoiceLine                custInvoiceLineLocal;
    LedgerJournalName            ledgerJournalName;
    LedgerJournalTable            ledgerJournalTable;
    LedgerJournalCheckPost        ledgerJournalCheckPost;

    ledgerJournalName = LedgerJournalName::find(projParameters.ExpenseJournalNameId);

    if (!ledgerJournalName)
    {
        throw error(strfmt("@GLS115420", projParameters.ExpenseJournalNameId));
    }

    while select * from custInvoiceLineInterProj
        order by TransType, TransDate
        join custInvoiceLineLocal
        where custInvoiceLineInterProj.CustInvoiceLine == custInvoiceLineLocal.RecId
        && custInvoiceLineLocal.ParentRecId == custInvoiceTable.RecId
    {
        //create journal header
        if (!ledgerJournalTable)
        {
            ledgerJournalTable = this.createCostJournalHeader(ledgerJournalName);
        }
        this.createCostJournalLine(ledgerJournalName, ledgerJournalTable, custInvoiceLineInterProj, custInvoiceLineLocal);
    }

    ledgerJournalCheckPost = this.postCostJournal(ledgerJournalTable);

    ledgerJournalTable.reread();

    if (!ledgerJournalTable.Posted)
    {
        throw Error("@INT:InterEntityCostReversalPostingCancelled");
    }
}

protected LedgerJournalTable createCostJournalHeader(LedgerJournalName _ledgerJournalName)
{
    LedgerJournalTable ledgerJournalTable;

    ledgerJournalTable.JournalName = _ledgerJournalName.JournalName;
    ledgerJournalTable.initFromLedgerJournalName();
    ledgerJournalTable.JournalNum = JournalTableData::newTable(ledgerJournalTable).nextJournalId();
    //ledgerJournalTable.Name = _ledgerJournalName.Name;
    ledgerJournalTable.Name = projParameters.IEBDefaultLineDesc_DEV;
    ledgerJournalTable.JournalType = LedgerJournalType::Cost;
    ledgerJournalTable.insert();

    return ledgerJournalTable;
}

protected void createCostJournalLine(LedgerJournalName _ledgerJournalName, LedgerJournalTable _ledgerJournalTable, CustInvoiceLineInterProj _custInvoiceLineInterProj, CustInvoiceLine _custInvoiceLine)
{
    LedgerJournalTrans ledgerJournalTrans;
    LedgerJournalTrans_Project ledgerJournalTrans_Project;
    NumberSequenceTable numberSequenceTable;
    NumberSeq numberseq;
    AmountCur costPrice = -_custInvoiceLineInterProj.CostPrice;
    boolean priceFound = false;
    CostPrice costPriceMST;
    ProjTable projTable = ProjTable::find(_custInvoiceLineInterProj.ProjId);
    ProjGroup projGroup = ProjGroup::find(projTable.ProjGroupId);

    select NumberSequence from numberSequenceTable
                where NumberSequenceTable.RecId == _ledgerJournalName.NumberSequenceTable;

    numberseq = NumberSeq::NewGetVoucherFromCode(numberSequenceTable.NumberSequence);

    ledgerJournalTrans.initValue();
    ledgerJournalTrans.JournalNum = _ledgerJournalTable.JournalNum;
    ledgerJournalTrans.Voucher = numberseq.voucher();
    ledgerJournalTrans.TransDate = _custInvoiceLineInterProj.TransDate;
    ledgerJournalTrans.Qty = 1;
    ledgerJournalTrans.AccountType = LedgerJournalACType::Project;
    ledgerJournalTrans.parmAccount(projTable.ProjId,LedgerJournalACType::Project);
    ledgerJournalTrans.OffsetAccountType = LedgerJournalACType::Ledger;
    LedgerDimensionDefaultAccount defaultLedgerDimension = ProjPosting::getLedgerDimension(ProjAccountType::CostAccount, projTable.ProjId, _custInvoiceLineInterProj.ProjCategoryId , 0);
    LedgerDimensionAccount mergedLedgerDimension = LedgerDimensionFacade::serviceCreateLedgerDimension(defaultLedgerDimension, _custInvoiceLine.DefaultDimension);
    ledgerJournalTrans.parmOffsetLedgerDimension(mergedLedgerDimension);
    ledgerJournalTrans.TransactionType = LedgerTransType::Payment;
    ledgerJournalTrans.CurrencyCode = _custInvoiceLineInterProj.OrigTransCurrency;
    ledgerJournalTrans.Txt = projParameters.IEBDefaultLineDesc_DEV;
    ledgerJournalTrans.Approved = NoYes::Yes;
    if(costPrice > 0)
    {
        ledgerJournalTrans.AmountCurDebit = costPrice;
    }
    else
    {
        ledgerJournalTrans.AmountCurCredit = abs(costPrice);
    }
    ledgerJournalTrans.Company = strUpr(curExt());
    ledgerJournalTrans.OffsetCompany = strUpr(curExt());
    ledgerJournalTrans.Approver = HcmWorkerLookup::currentWorker();
    ledgerJournalTrans.DefaultDimension = _custInvoiceLine.DefaultDimension;
    ledgerJournalTrans.insert();

    ledgerJournalTrans_Project.initValue();
    ledgerJournalTrans_Project.ActivityNumber = _custInvoiceLine.OriginatingActivityId_DEV;
    ledgerJournalTrans_Project.CategoryId = _custInvoiceLineInterProj.ProjCategoryId;
    ledgerJournalTrans_Project.categoryModified();
    ledgerJournalTrans_Project.SalesCurrencyId = _custInvoiceLineInterProj.OrigTransCurrency;
    ledgerJournalTrans_Project.ProjTransDate = _custInvoiceLineInterProj.TransDate;
    ledgerJournalTrans_Project.Resource = ResourceFacade::findOrCreateByWorker(HcmWorkerLookup::currentWorker());
    ledgerJournalTrans_Project.ProjId = _custInvoiceLineInterProj.ProjId;
    ledgerJournalTrans_Project.RefRecId = ledgerJournalTrans.RecId;
    ledgerJournalTrans_Project.Worker = ledgerJournalTrans.Approver;
    ledgerJournalTrans_Project.Qty = -1;
    ledgerJournalTrans_Project.CostPrice = _custInvoiceLineInterProj.CostPrice;

    costPriceMST = ProjCostSalesPrice::costPrice(ledgerJournalTrans, ledgerJournalTrans_Project, false);
    [ledgerJournalTrans_Project.SalesPrice, priceFound] = ProjCostSalesPrice::findCostSalesPrice(ledgerJournalTrans_Project.ProjId,
                ledgerJournalTrans_Project.Resource,
                ledgerJournalTrans_Project.CategoryId,
                costPriceMST,
                Ledger::accountingCurrency(),
                ledgerJournalTrans_Project.SalesCurrencyId,
                ledgerJournalTrans_Project.ProjTransDate,
                ledgerJournalTrans_Project.ProjPriceGroupID,
                false);

    ledgerJournalTrans_Project.InterEntityCostReversal_DEV = NoYes::Yes;
    ledgerJournalTrans_Project.insert();
}

protected LedgerJournalCheckPost postCostJournal(LedgerJournalTable _ledgerJournalTable)
{
    LedgerJournalCheckPost ledgerJournalCheckPost;

    ledgerJournalCheckPost = ledgerJournalCheckPost::newLedgerJournalTable(_ledgerJournalTable,NoYes::Yes);
    ledgerJournalCheckPost.run();

    return ledgerJournalCheckPost;
}

protected void createReversalHourJournal()
{
    CustInvoiceLineInterProj    custInvoiceLineInterProj;
    CustInvoiceLine                custInvoiceLineLocal;
    ProjJournalTable            projJournalTable;
    ProjJournalCheckPost        jourPost;

    while select * from custInvoiceLineInterProj
        order by TransType, TransDate
        join custInvoiceLineLocal
        where custInvoiceLineInterProj.CustInvoiceLine == custInvoiceLineLocal.RecId
        && custInvoiceLineLocal.ParentRecId == custInvoiceTable.RecId
    {
        //create journal header
        if (!projJournalTable)
        {
            projJournalTable = this.createHourJournalHeader();
        }

        this.createHourJournalLine(projJournalTable, custInvoiceLineInterProj, custInvoiceLineLocal);
    }

    ttsbegin;
    projJournalTable.reread();
    ProjJournalTable::initTotal(projJournalTable);

    if (projJournalTable.validateWrite())
    {
        projJournalTable.update();
    }
    else
    {
        throw error(strfmt("@SYS4007721", tablePname(ProjJournalTable)));
    }
    ttscommit;

    jourPost = this.postHourJournal(projJournalTable);

    projJournalTable.reread();

    if (!projJournalTable.Posted)
    {
        throw Error("@INT:InterEntityCostReversalPostingCancelled");
    }
}

protected ProjJournalTable createHourJournalHeader()
{
    ProjJournalName                projJournalName;
    ProjJournalType                projJournalType;
    ProjJournalTable            projJournalTable;

    projJournalName = ProjJournalName::find(projParameters.EmplJournalNameId);

    if (!projJournalName)
    {
        throw error(strfmt("@GLS115420", projParameters.EmplJournalNameId));
    }

    projJournalType = ProjJournalType::Hour;

    projJournalTable.clear();
    projJournalTable.initValue();
    projJournalTable.initFromProjJournalName(projJournalName);
    projJournalTable.JournalId      = JournalTableData::newTable(projJournalTable).nextJournalId();
    projJournalTable.StatusNameId   = projJournalName.StatusNameId;
    projJournalTable.JournalType    = projJournalType;
    projJournalTable.Description    = projParameters.IEBDefaultLineDesc_DEV;

    if (projJournalTable.validateWrite())
    {
        projJournalTable.insert();
    }
    else
    {
        throw error(strfmt("@SYS4007721", tablePname(ProjJournalTable)));
    }

    return projJournalTable;
}

protected ProjJournalCheckPost postHourJournal(ProjJournalTable _projJournalTable)
{
    ProjJournalCheckPost jourPost;

    // Posting the journal
    jourPost = ProjJournalCheckPost::newJournalCheckPost(true,true,JournalCheckPostType::Post,tableNum(ProjJournalTable),
        _projJournalTable.JournalId);

    jourPost.run();

    return jourPost;
}

protected void createHourJournalLine(ProjJournalTable _projJournalTable, CustInvoiceLineInterProj _custInvoiceLineInterProj, CustInvoiceLine _custInvoiceLine)
{
    ProjJournalTrans projJournalTransHour;

    projJournalTransHour.clear();
    projJournalTransHour.initValue();

    projJournalTransHour.JournalId          = _projJournalTable.JournalId;
    projJournalTransHour.ProjTransDate      = _custInvoiceLineInterProj.TransDate;
    projJournalTransHour.Resource           = ResourceFacade::findOrCreateByWorker(HcmWorkerLookup::currentWorker());
    projJournalTransHour.setResourceCategory();

    JournalTableData journalTableData = JournalTableData::newTable(_projJournalTable);
    ProjJournalTransData journalTransData = new ProjJournalTransData(projJournalTransHour, journalTableData);

    projJournalTransHour.setTransDate();
    projJournalTransHour.setPeriodDate();

    projJournalTransHour.initFromProjJournalTable(_projJournalTable);

    projJournalTransHour.ProjId             = _custInvoiceLineInterProj.ProjId;
    ProjTable projTable                     = ProjTable::find(projJournalTransHour.ProjId);

    projJournalTransHour.initFromProjTable(projTable);

    projJournalTransHour.ActivityNumber     = _custInvoiceLine.OriginatingActivityId_DEV;
    projJournalTransHour.DefaultDimension   = _custInvoiceLine.DefaultDimension;
    projJournalTransHour.CategoryId         = _custInvoiceLineInterProj.ProjCategoryId;
    projJournalTransHour.LinePropertyId        = _custInvoiceLineInterProj.ProjLinePropertyId;
    projJournalTransHour.Qty                = -1;
    projJournalTransHour.Txt                = projParameters.IEBDefaultLineDesc_DEV;
    projJournalTransHour.TaxItemGroupId  = "";
    projJournalTransHour.TaxGroupId      = "";
    projJournalTransHour.CurrencyId         = Ledger::accountingCurrency();
    projJournalTransHour.CostPrice          = _custInvoiceLineInterProj.CostPrice;
    projJournalTransHour.SalesPrice         = _custInvoiceLineInterProj.CostPrice;

    //projJournalTransHour.FromTime           = serviceOrderLine.TimeSheetStartTime;
    //projJournalTransHour.ToTime             = serviceOrderLine.TimeSheetEndTime;

    if (journalTransData.findVoucher())
    {
        projJournalTransHour.Voucher        = journalTransData.findVoucher();
    }
    else
    {
        if (journalTableData.journalVoucherNum() && journalTableData.journalTable().VoucherDraw == JournalVoucherDraw::Entering)
        {
            journalTransData.initVoucher('', false, false);
        }
    }

    projJournalTransHour.InterEntityCostReversal_DEV = NoYes::Yes;

    if (projJournalTransHour.validateWrite())
    {
        projJournalTransHour.insert();
    }
    else
    {
        throw Error("@INT:InterEntityCostReversalPostingCancelled");
    }
}

}

D365 How to run a direct SQL statement

public AmountCur getCommittedCosts_DEV(ProjId _projId, ProjTransIdBase _projTransId)
{
AmountCur totalCosts;
str sqlStatement;
str sqlQuery;
str sqlUncommitted; //= 'set transaction isolation level READ UNCOMMITTED';    
UserConnection  connection = new UserConnection();
    Statement       statement = connection.createStatement();
    ResultSet       resSet;

    sqlQuery = strFmt(@"select sum(AmountMST) from COSTCONTROLTRANSCOMMITTEDCOST
                        where ProjId = '%1' 
                        and DATAAREAID = '%2' 
                        and [Open_] = %3 
                        and ProjTransId !=  '%3'", _projId, curExt(), 1, _projTransId);

    sqlStatement = strFmt('%1\n%2', sqlUncommitted, sqlQuery);

    new SqlStatementExecutePermission(sqlStatement).assert();

    resSet = statement.executeQuery(sqlStatement);

    CodeAccessPermission::revertAssert();

    // Loop and read the result set
    while (resSet.next())
    {
        // If the indexes in the resSet variable match the column indexes, use the next statements
        totalCosts = resSet.getReal(1);
    }

    return totalCosts;
}

D365 How to filter a query with a dimension

Here is an example of how to filter a query with a dimension.

 /// /// Initializes the query to be used for fetching records to be processed. ///
protected void initQuery()
{
QueryBuildDataSource qbds;
Query query = new Query();
QueryBuildRange qbrStatus;

//do not allow cross company
    //query.allowCrossCompany(true);
    qbds = query.addDataSource(tableNum(ProjTable));
    qbds.addRange(fieldNum(ProjTable, ProjInvoiceProjId));
    qbds.addRange(fieldNum(ProjTable, ProjId));

    qbrStatus = qbds.addRange(fieldNum(ProjTable, Status));
    qbrStatus.value(queryValue(ProjStatus::InProcess));
    qbrStatus.status(RangeStatus::Locked);

    #define.dimAttr('CostCenter')
    #define.dimRangeValue('xxxx')

    DimensionProvider dimensionProvider = new DimensionProvider();

    dimensionProvider.addAttributeRangeToQuery(
    query,
    qbds.name(),
    identifierStr(DefaultDimension),
        DimensionComponent::DimensionAttribute,
    #dimRangeValue,
    #dimAttr,
    true);

    projectQueryRun = new QueryRun(query);
}

D365 Lookup Event Handler example

/// <summary>
/// Lookup list of projects on an another legal entity
/// <param name="sender"></param>
/// <param name="e"></param>
[FormControlEventHandler(formControlStr(ProjParameters, ProjInterEntityParametersGrid_DEV_ProjId), FormControlEventType::Lookup)]
public static void ProjInterEntityParametersGrid_DEV_ProjId_OnLookup(FormControl sender, FormControlEventArgs e)
{
    ProjInterEntityParameters_INT projInterEntityParameters = sender.formRun().dataSource(formDataSourceStr(ProjParameters, ProjInterEntityParameters_INT)).cursor();

    if (projInterEntityParameters.LegalEntityForBilling)
    {
        changecompany(projInterEntityParameters.LegalEntityForBilling)
        {
            Query query = new Query();
            QueryBuildDataSource queryBuildDataSource;
            QueryBuildRange queryBuildRange;

            SysTableLookup sysTableLookup = SysTableLookup::newParameters(tableNum(ProjTable), sender);

            sysTableLookup.addLookupField(fieldNum(ProjTable, ProjId));
            sysTableLookup.addLookupField(fieldNum(ProjTable, Name));
            sysTableLookup.addLookupField(fieldNum(ProjTable, Type));

            queryBuildDataSource = query.addDataSource(tableNum(ProjTable));

            sysTableLookup.parmQuery(query);
            sysTableLookup.performFormLookup();
        }
    }

    FormControlCancelableSuperEventArgs ce = e as FormControlCancelableSuperEventArgs;
    //cancel super() to prevent error.
    if (ce)
    {
        ce.CancelSuperCall();
    }
}

D365 How to get the current record in an event handler

[FormControlEventHandler(formControlStr(ProjParameters, ProjCopyProjParametersGrid_DEV_ProjGroupId), FormControlEventType::Lookup)]
public static void ProjCopyProjParametersGrid_DEV_ProjGroupId_OnLookup(FormControl sender, FormControlEventArgs e)
{
ProjCopyProjParameters_DEVprojCopyProjParameters = sender.formRun().dataSource(formDataSourceStr(ProjParameters, ProjCopyProjParameters_DEV)).cursor();
info(projCopyProjParameters.DestinationLegalEntity);
}