Click or drag to resize

clsImportProjectContractPosition Class

Data holder to import the contract positions to contracts.

Used by the MS Access Table MARIProjektImportProjectContractPositions

Used with clsImportProjectContract

See optionally the property CollectionAccountingPos to add directly accounting positions clsImportProjectContractPositionAccountingPos

Use MPInterface.bImportContractPosition(clsImportProjectContractPosition, clsImportBaseeImportMode) to import.

Inheritance Hierarchy
SystemObject
  MARIInterfaceclsImportBase
    MARIInterfaceclsImportProjectContractPosition
      MARIInterfaceclsImportProjectPurchaseProcessPositions

Namespace:  MARIInterface
Assembly:  MARIInterface (in MARIInterface.dll) Version: 8.0.0.100
Syntax
public class clsImportProjectContractPosition : clsImportBase

The clsImportProjectContractPosition type exposes the following members.

Constructors
  NameDescription
Public methodclsImportProjectContractPosition
Initializes a new instance of the clsImportProjectContractPosition class
Top
Properties
  NameDescription
Public propertyAccrualRuleID
Link to an accrual rule for accrual bookings
Public propertyBaseQuantity
Base Quantity for Bill of Material lines (10 per BOM, when 3 times the BOM ContractQuantity has 30. BaseQuantity=10). Also used, when UseQuantityFromFixPrice is enabled.
Public propertyCode exampleCollectionAccountingPos
(Optionally) Add a list of clsImportProjectContractPositionAccountingPos accounting positions definine the installmentplan of one position. (Mainly for fixed price positions)
Public propertyCode exampleCollectionBOM
Using this List will allows to create a Bill Of Material Hierarchy. The base line (this object) must be of the type SubContractPosition underneath a FixedPrice or BOMHeader (ParentContractPosition>0).

The quantity of this SubContractPosition will be calculated down into all sub positions. The quantity of the sub positions will be used as base quantity and the Quantity is the multiplication with the Quantity of the base position

The hiearchy can have multi levels.
PositionTypeContractQuantityBaseQuantityRemark
FixedPrice   1not usedInitial position in the main contract.
  SubContractPosition   5not usedThis object, where the CollectionBOM is used.
    BOMHeader   5not usedThis Position Type is automatically created reading the childs in the CollectionBOM. The quantity is also aligned with the parent.
      ItemAtFixedPrice  15  3ContractQuantity=3 is the input. 3 is stored in BaseQuantity and 15 in ContractQuantity
      ItemAtFixedPrice  20  4ContractQuantity=4 is the input. 4 is stored in BaseQuantity and 20 in ContractQuantity
      ServiceAtFixedPrice  20  4ContractQuantity=4 is the input. 4 is stored in BaseQuantity and 20 in ContractQuantity
See example for more details.
Public propertyCompanyID
Inherited property of the company on the contract header. Field not required, becuase the company at the contract will be used.
Public propertyContractID
Contract Identifier [Mandantory] link to the MPVKVertraege.VertragsID
Public propertyContractPositionID
Internal Line number of the contract position (starting with 100000). Key value. This number is created during the import.
Public propertyContractPrice
Single sales price of this position (in contract currency). Use -1 for the reading the default price from item or service based on the sales price list in the contract, of if empty from the customer of the contract.
Public propertyContractQuantity
Standard quantity of the contract position. In sub contracts this is the resulting quantity. (3 Times the BOM of 10 times this line = ContractQuantity=30)
Public propertyDeliveryDate
Item delivery date. Normally inherited from PlanningDueDate of the contract.
Public propertyDescription1
Description1 for the customer
Public propertyDescription2
Description2 for the customer
Public propertyDescription3
Description3 for the customer for placeholders by each time booking line. Placeholders can be imported using the current user language place holder codes. For example [Posting information equipment].
Public propertyDescription4
TEXT: Description4 for the customer for placeholders for the position. Placeholders can be imported using the current user language place holder codes. For example [Posting information equipment].
Public propertyEquipmentCategory
Key field for Equipment Category Positions. Additionally the field EquipmentCostTypes have to have the cost type. You may use alternativly the property ItemServiceTravelEquipmentCode.
Public propertyEquipmentCostTypes
To avoid to import all equipment cost type it is possible to define here the cost types. Example value: CostTypeID;CostTypeID;CostTypeID (separator ';') Special handling to enter quantities and prices: CostTypeID|Quantity|Price;CostTypeID|Quantity|Price (separator '|' and ';') If empty all cost type will be imported
Public propertyEquipmentEndDate
Defines the requested rental day range (end date). Only relevant for EquipmentCategory types
Public propertyEquipmentMasterList
Optional filter an equpment rental contract position to one or many specific equipment master (of the same equipment category) add to this List<string> the EquipmentCodes.
Public propertyEquipmentQuantity
For Equipment Rental Positions, the ContractQuantity is the number of days(hours,monthes) the equipment is rented times EquipmentQuantity=number of equipment of this category to be rented. Default=1
Public propertyEquipmentQuantityEditable
Default: no. Enables the probability to change the number of days for one equpiment Booking line
Public propertyEquipmentStartDate
Defines the requested rental day range (start date). Only relevant for EquipmentCategory types
Public propertyERPResourceCode
Resource Code. ORSC.ResCode Only for Service Positions
Public propertyExternalNumber
TEXT: External nummer maby used as a unique key for BOM Import
Public propertyGLAccount
GLAccount overwriting the standard GL Account determination. Default=empty
Public propertyHelpPhaseName
Link one phase to the contract position (DTW supports only one phase (1:1)) Phase found by project specific phase name
Public propertyImportModeSBOBOMSource
When ItemCode is a Production bill of material OITM.TreeType='P' in SBO. This setting can define the behaviour, when importing this line with the childre. Should SBO ProductTree be updated?. See clsImportProjectContractPositioneImportModeSBOBOMSource
Public propertyInvoiceBookingsWithoutValue
For all chargeable positions. Determines whether postings are to be invoiced with the value 0.
Public propertyInvoicingType
The fines the document creation handling, when an invoice will be created. See ePositionInvoicingType
Public propertyIssueMethod
Issue Method for production lines (Manaul or backflush). Only used for positions in a contract BOM
Public propertyItemCode
[Mandantory for item/fixed price lines] Item number (OITM.ItemCode). You may use alternativly the property ItemServiceTravelEquipmentCode.
Public propertyItemMaster
Posibility to link directly the required properties for the item master. Based one the ItemMasterHandling setting, the import will also verify, update and/or create item master data.
Public propertyItemMasterHandling
Setting for the import to decide, if the properties of the ItemMaster object will be handled in the import of this line. See clsImportProjectContractPositioneItemMasterHandling
Public propertyItemServiceTravelEquipmentCode
Alternative key field for all position types. Instead of ItemCode, ServiceCode, TravelExpenseCode or EquipmentCategory.
Public propertyMaintenanceContractEndDate
End of the Maintenance Contract
Public propertyMaintenanceDueDateOffset
Sets the offset for the ServiceDueDateType = FirmDayWithinPeriodOfTime=3. MaintenanceDueDateType
Public propertyMaintenanceDueDateType
Public propertyMaintenanceEnd
Maintenance end date
Public propertyMaintenancePeriodic
Public propertyMaintenancePrice
Base price of the maintenance positions to calculate the position price (5% of 1.000)
Public propertyMaintenanceProRata
Reference to the contract pro rata rule.
Public propertyMaintenanceRate
Rate of the maintenance positions. Use 0.05 for 5%
Public propertyMaintenanceReference
Maintenance reference contract positions (5% of a license position)
Public propertyMaintenanceStart
Maintenance start date
Public propertyMatchcode
Internal name of the position visible to the users (time keeping, contract master etc.)
Public propertyMaximumQuantity
Maximum Quantity as a limit in the contract position. Only for positions with transactions (time, material, equipment)
Public propertyNoSubPriceCalculation
Do not calculate price from subpositions
Public propertyOcrCode1
OcrCode1/Profit Center. Can be set on contract position level, when company setting modified to use profit center from contract position
Public propertyOcrCode2
OcrCode2. Can be set on contract position level, when company setting modified to use profit center from contract position
Public propertyOcrCode3
OcrCode3. Can be set on contract position level, when company setting modified to use profit center from contract position
Public propertyOcrCode4
OcrCode4. Can be set on contract position level, when company setting modified to use profit center from contract position
Public propertyOcrCode5
OcrCode5. Can be set on contract position level, when company setting modified to use profit center from contract position
Public propertyParentContractPosition
ContractPositionID of the parent. Only to be used for clsImportProjectContractPositioneContractPositionType.ItemAtFixedPrice, ServiceAtFixedPrice, EquipmentTimeAtFixedPrice, TravelExpenseAtFixedPrice, ExternalServiceAtFixedPrice or BOMHeader

This contract position ID is used to find the parend position. If it is not set, the first fixed price position is used in the contract, if it is set, it must be a valid contract position Id.

Public propertyPhaseID
Link one phase to the contract position (DTW supports only one phase (1:1)). Stored 1:n in sub table
Public propertyPositionAfterContractPos
Functionality to propose a position for the new or updated contract position. Please set the ContractPositionId of the line above new new line.

Use -1 to insert as a first position (infront of all other position)

Public propertyPositionID
Order Position of all contract positions. Read Only. New Positions will automatically be added at the end or at the end of the parent position child list.
Public propertyPositionText
Position text for the position. Read Only for import
Public propertyPositionTyp
INT [Mandantory] Position Type of the contract Position. Many properties of the position import depend on the corresponding PositionTyp. See eContractPositionType for details.
Public propertyPurchaseMode
Public propertyPurchasePriceChangable
Public propertyPurchasePriceManual
Public propertyPurchasePriceType
Public propertyQuantityType
QuantityType for the position (Only for Serices). if 0 standard will be used. See clsImportProjectContractPositioneQuantityType for details.
Public propertyRebateFlagg
RebateFlagg: (Yes/No): 0=false, 1=true, -1=true, all other = use default. See clsImportProjectContractPositioneYesNoDefault
Public propertyRetainageInterval
Only important for the retainage. Enum (Uses the same field as MaintenancePeriodic)
Public propertyRetainagePercentage
only important for the retainage and maintenance
Public propertyRetainageRefPosition
The retention request position must have a reference to the retention invoice position. (and vice versa)
Public propertySalesPositionRebatePercentage
Position rebate in percent: 100 = 100%
Public propertySalesPriceChangable
Price Changable by user (Yes/No): 0=false, 1=true, -1=true, all other = use default. Can only by true, when RebateFlagg is false. See clsImportProjectContractPositioneYesNoDefault
Public propertySalesPriceType
Public propertyServiceCode
[Mandantory for service lines] Service number MPLeistung.Leistungsnummer. You may use alternativly the property ItemServiceTravelEquipmentCode.
Public propertySourceWarehouse
Linked Warehouse SBO Code for Stock Transfer Processes
Public propertyStandardAccountingType
For Positions with more than one element in CollectionAccountingPos, this setting defines the splitting method
Public propertySubContractID
Public propertySubContractPositionID
Public propertyTravelExpenseCode
Link to the Travel Expense Category MPReise2KostenArten.Reisekostenart. You may use alternativly the property ItemServiceTravelEquipmentCode.
Public propertyUnitOfMeasurement
Unit Of Measurement (Textfield. Mapped to the OITM Sales unit
Public propertyUseQuantityFromFixPrice
For all positions at fixed price. It is possible to caclulate the quantity based on the fixed price Quantity * BaseQuantity. QuantityOption Flag 32.
Public propertyWarehouse
Linked Warehouse SBO Code
Top
Methods
  NameDescription
Public methodbReadFromDB
Reads the contract data from the database and copies the values to the class Only for internal use! To load data use your own SQL.
(Overrides clsImportBasebReadFromDB(MPInterface, String).)
Public methodbSaveRSToMDB (Overrides clsImportBasebSaveRSToMDB(MPInterface, DataRow, DataTable).)
Public methodGetListUserDefinedFields
Returns the user defined field definition for the dimension "Sales Contract Position". The fields have to be defined directly in MARIProject.
(Overrides clsImportBaseGetListUserDefinedFields(MPInterface).)
Public methodSetUserDefinedFieldValue
Fill user defined field with value
(Overrides clsImportBaseSetUserDefinedFieldValue(String, Object).)
Top
Remarks
Examples
Add Contract Position (fixed price) to existing contract
public clsImportProjectContractPosition CreateContractPositionFixedPrice(int lContractID, string sItemCode) {
    Log($"CreateContractPositionFixedPrice(lContractID={lContractID}, sItemCode=\"{sItemCode}\")");

    // create contract position
    clsImportProjectContractPosition oPos = new clsImportProjectContractPosition();
    oPos.PositionTyp = clsImportProjectContractPosition.eContractPositionType.FixedPrice;
    oPos.ContractID = lContractID;
    oPos.Matchcode = "Fix Price Position";
    oPos.Description1 = "FP: Created from the interface";
    oPos.ContractQuantity = 1;
    oPos.ContractPrice = 10000;
    oPos.ItemCode = sItemCode;
    oPos.SalesPriceType = clsImportProjectContractPosition.eSalesPriceType.SalesPriceByContract; //IN20220719
    oPos.SalesPositionRebatePercentage = 0;//IN20220719

    //two accounting details 30%, 70%
    oPos.CollectionAccountingPos = new List<clsImportProjectContractPositionAccountingPos>();
    clsImportProjectContractPositionAccountingPos oAcc1 = new clsImportProjectContractPositionAccountingPos();
    oAcc1.AccountingType = clsImportProjectContractPositionAccountingPos.ePosAccountingType.DueDate;
    oAcc1.DueDate = new DateTime(2015, 1, 15);
    oAcc1.AccountingValue = 3000;
    oAcc1.Percentage = 30;
    oAcc1.Description = "First 30%";
    oPos.CollectionAccountingPos.Add(oAcc1);
    clsImportProjectContractPositionAccountingPos oAcc2 = new clsImportProjectContractPositionAccountingPos();
    oAcc2.AccountingType = clsImportProjectContractPositionAccountingPos.ePosAccountingType.DueDate;
    oAcc2.DueDate = new DateTime(2015, 5, 15);
    oAcc2.AccountingValue = 7000;
    oAcc2.Percentage = 70;
    oAcc2.Description = "Last 70%";
    oPos.CollectionAccountingPos.Add(oAcc2);
    return oPos;
}
public int ImportContractPositionFixedPrice(clsImportProjectContractPosition oPos) {
    Log($"ImportContractPositionFixedPrice(lContractID={oPos.ContractID}, sItemCode=\"{oPos.ItemCode}\")");

    // import contract position
    if (oMPInterface.bImportContractPosition(oPos, clsImportBase.eImportMode.ValidateAndImport)) {
        Log($"ImportContractPositionFixedPrice ContractPositionID={oPos.ContractPositionID}");
        return oPos.ContractPositionID;
    } else {
        // read import error
        LogFail(oMPInterface.oErrors.PrintErrors(true));
        return 0;
    }
}
Add Contract Position (Service at cost) to existing contract
public clsImportProjectContractPosition CreateContractPositionService(int lContractID) {
    Log($"CreateContractPositionService({lContractID})");
    // Create contract position
    clsImportProjectContractPosition oPos = new clsImportProjectContractPosition();
    oPos.PositionTyp = clsImportProjectContractPosition.eContractPositionType.ServiceAtCost;
    // existing contract id (found from the code below):
    // SELECT ContractID FROM MARIContract WHERE Projectnumber=N'P123456' AND ContractNumber = N'C1010100101'
    // QM default result: ContractID: 100028
    oPos.ContractID = lContractID;
    oPos.ServiceCode = "1010"; // Valid Service Type: SELECT ServiceNumber FROM MARIServices
    oPos.Matchcode = "oMPInterface Service Position";
    oPos.Description1 = "Service: Created from the interface";
    oPos.ContractQuantity = 1;
    oPos.ContractPrice = 85.50m;
    return oPos;
}
public int ImportContractPositionService(clsImportProjectContractPosition oPos) {
    Log($"CreateContractPositionService({oPos.ContractID})");

    // import contract position
    if (oMPInterface.bImportContractPosition(oPos, clsImportBase.eImportMode.ValidateAndImport)) {
        Log($"CreateContractPositionService: ContractPositionID={oPos.ContractPositionID}");
        return oPos.ContractPositionID;
    } else {
        LogFail(oMPInterface.oErrors.PrintErrors(true));
        return 0;
    }
}
Add Contract Position (Equipment Rental) to existing contract
public int CreateContractPositionEquipmentRental(int lContractID, int lEqupmentCategory, string sFilterEqiupmentMaster) {
    Log($"CreateContractPositionEquipmentRental({lContractID}, lEqupmentCategory={lEqupmentCategory}, sFilterEqiupmentMaster=\"{sFilterEqiupmentMaster}\")");
    // create contract position
    clsImportProjectContractPosition oPos = new clsImportProjectContractPosition();
    oPos.PositionTyp = clsImportProjectContractPosition.eContractPositionType.EquipmentTimeAtCost;
    oPos.ContractID = lContractID;
    oPos.Matchcode = "Equipment At Cost";
    oPos.Description1 = "Eq at Cost: Created from the interface";
    oPos.ContractQuantity = 1; // Quantity will be re calculated based on the number of equipment * number of days
    oPos.ContractPrice = 12.5m; // per day
    oPos.EquipmentCategory = lEqupmentCategory; // SELECT EquipmentCategory FROM MARIEquipmentCategory
    oPos.EquipmentStartDate = new DateTime(2015, 02, 3);
    oPos.EquipmentEndDate = oPos.EquipmentStartDate.AddDays(15);
    oPos.DeliveryDate = oPos.EquipmentStartDate;
    oPos.EquipmentQuantity = 2; //rent two equipment (per day)

    // Optional: Filter contract position to one equipment master. Equipment transactions are then only allowed to this equipment master.
    if (sFilterEqiupmentMaster != "") {
        oPos.EquipmentMasterList = new List<string>();
        oPos.EquipmentMasterList.Add(sFilterEqiupmentMaster);
    }

    // import contract position
    if (oMPInterface.bImportContractPosition(oPos, clsImportBase.eImportMode.ValidateAndImport)) {
        Log($"CreateContractPositionEquipmentRental: ContractPositionID={oPos.ContractPositionID}");
        return oPos.ContractPositionID;
    } else {
        // on import error
        LogFail(oMPInterface.oErrors.PrintErrors(true));
        return 0;
    }
}
Create Sub Contract and a link position in the parent contract
/// <summary>
/// Example creates a sub contract with one header and two childs AND a position in the parent contract with the reference
/// </summary>
/// <param name="sProjectnumber">Example project to create this BOM hierarchy</param>
/// <returns></returns>
public int CreateSubContractWithLink(string sProjectnumber) {

    // Main Contract
    // 1.0 eContractPositionType.FixedPrice
    // 1.1 eContractPositionType.SubContractPosition [Link to the header position of the sub contract]
    // Sub Contract
    //    1.0 eContractPositionType.BOMHeader
    //    1.1 eContractPositionType.ItemAtFixedPrice
    //    1.2 eContractPositionType.ItemAtFixedPrice

    int lMainContractID = CreateContract(sProjectnumber, "Example with sub contracts " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString());
    int lFixPricePositionID = CreateContractPosition(lMainContractID, clsImportProjectContractPosition.eContractPositionType.FixedPrice, "220000", "All In One", 1, 0);

    decimal QuantityOfSub = 2M;
    int lSubContractID = CreateSubContract(sProjectnumber, "BOM 1 sub contract", lMainContractID);
    int lSubContractHeadPos = CreateContractPosition(lSubContractID, clsImportProjectContractPosition.eContractPositionType.BOMHeader, "220001", "BOM 1", QuantityOfSub, 1); // The header in the subcontract does have also the type FixedPrice
    int lSubContractPos1___ = CreateContractPosition(lSubContractID, clsImportProjectContractPosition.eContractPositionType.ItemAtFixedPrice, "220002", "Item 1", 5 * QuantityOfSub, 5, "UKey 1100", lSubContractHeadPos);
    int lSubContractPos2___ = CreateContractPosition(lSubContractID, clsImportProjectContractPosition.eContractPositionType.ItemAtFixedPrice, "220003", "Item 2", 4 * QuantityOfSub, 4, "UKey 1200", lSubContractHeadPos);

    // Create Position in the main (parent Contract) with the link to the sub contract
    clsImportProjectContractPosition oPosInMainContrctForSubContract = new clsImportProjectContractPosition();
    oPosInMainContrctForSubContract.PositionTyp = clsImportProjectContractPosition.eContractPositionType.SubContractPosition;
    oPosInMainContrctForSubContract.ContractID = lMainContractID;
    oPosInMainContrctForSubContract.Matchcode = "BOM 1";
    oPosInMainContrctForSubContract.Description1 = "BOM 1";
    oPosInMainContrctForSubContract.ContractQuantity = 1; // when you have more than one, consider to fill also BaseQuantity in the sub contract
    oPosInMainContrctForSubContract.ContractPrice = 10000;
    oPosInMainContrctForSubContract.ItemCode = "220001";
    oPosInMainContrctForSubContract.ParentContractPosition = lFixPricePositionID; // link to fix price position above
    oPosInMainContrctForSubContract.SubContractID = lSubContractID; // link to the sub contract
    oPosInMainContrctForSubContract.SubContractPositionID = lSubContractHeadPos; // link to the head position
    oPosInMainContrctForSubContract.ExternalNumber = "UKey 1000";
    oPosInMainContrctForSubContract.ContractQuantity = QuantityOfSub;

    // Import Position in Main contract with the link
    if (oMPInterface.bImportContractPosition(oPosInMainContrctForSubContract, clsImportBase.eImportMode.ValidateAndImport)) {
        return lMainContractID;
    } else {
        // read import error
        Assert.False(true, oMPInterface.oErrors.PrintErrors(true));
        return 0;
    }
}


private int CreateSubContract(string sProject, string sContractName, int lMainContractID) {
    clsImportProjectContract oContract = new clsImportProjectContract();
    oContract.ProjectNumber = sProject; // existing project  P100005
    oContract.ContractNumber = oMPInterface.sGetNewContractNumber(sProject);  // new number based on settings
    oContract.Description = sContractName;
    oContract.ContractDate = DateTime.Now;
    oContract.CompanyID = 1;
    oContract.CustomerCode = "10006"; // valid customer number OCRD.CardCode
    oContract.ContractType = clsImportProjectContract.eContractTypes.SubContract;
    oContract.ValidPeriodFrom = 2016001; // Starting period for the contract YYYYMMM 
    oContract.BaseContractID = lMainContractID; // Points to the main contract (IndividualContractType)

    if (oMPInterface.bImportContract(oContract, clsImportBase.eImportMode.ValidateAndImport)) {
        return oContract.ContractID;
    } else {
        Assert.False(true, oMPInterface.oErrors.PrintErrors(true));
        return 0;
    }
}
private int CreateContractPosition(int lContract, clsImportProjectContractPosition.eContractPositionType nType,
    string sItemCode, string sDescription, decimal Quantity, decimal BaseQuantity, string sUniqueKey = "", int lParent = 0) {
    clsImportProjectContractPosition oPos = new clsImportProjectContractPosition();
    oPos.PositionTyp = nType;
    oPos.ContractID = lContract;
    oPos.Matchcode = sDescription;
    oPos.Description1 = sDescription;
    oPos.ContractQuantity = Quantity;
    oPos.BaseQuantity = BaseQuantity;
    oPos.ContractPrice = 10000;
    oPos.ItemCode = sItemCode;
    oPos.SalesPriceType = clsImportProjectContractPosition.eSalesPriceType.SalesPriceByContract;
    oPos.ExternalNumber = sUniqueKey;
    oPos.ParentContractPosition = lParent;
    if (oMPInterface.bImportContractPosition(oPos, clsImportBase.eImportMode.ValidateAndImport)) {
        return oPos.ContractPositionID;
    } else {
        Assert.False(true, oMPInterface.oErrors.PrintErrors(true));
        return 0;
    }
}
Example using CollectionBOM to create a hierarchy
/// <summary>
/// Example creates a sub contract with one header and two childs AND a position in the parent contract with the reference
/// </summary>
/// <param name="lMainContractID"></param>
/// <param name="sItemCode"></param>
/// <returns></returns>
public int CreateSubContractWithBOMHierarchy(string sProjectnumber) {

    // Main Contract
    // 1.0 eContractPositionType.FixedPrice
    // 1.1 eContractPositionType.SubContractPosition [Link to the header position of the sub contract]
    // Sub Contract
    //    1.0 eContractPositionType.BOMHeader
    //    1.1 eContractPositionType.ItemAtFixedPrice
    //    1.2 eContractPositionType.ItemAtFixedPrice

    clsImportProjectContract MainContract = CreateNewContract(sProjectnumber, "Example with BOM Hierarchy");
    clsImportProjectContractPosition FixPos = NewContractPosition(MainContract, clsImportProjectContractPosition.eContractPositionType.FixedPrice, "220000", "All In One", 1);

    // 1. import fix price
    if (oMPInterface.bImportContractPosition(FixPos, clsImportBase.eImportMode.ValidateAndImport)) {

        //SubContract Position
        clsImportProjectContractPosition SubContractPos = NewContractPosition(MainContract, clsImportProjectContractPosition.eContractPositionType.SubContractPosition, "220001", "BOM 1", 2, "UKey 1000");
        SubContractPos.CollectionBOM = new List<clsImportProjectContractPosition>();
        SubContractPos.CollectionBOM.Add(NewContractPosition(MainContract, clsImportProjectContractPosition.eContractPositionType.ItemAtFixedPrice, "220002", "Item 1", 5, "UKey 1100"));
        SubContractPos.CollectionBOM.Add(NewContractPosition(MainContract, clsImportProjectContractPosition.eContractPositionType.ItemAtFixedPrice, "220003", "Item 2", 4, "UKey 1200"));

        // Store the reference to the fixed price position
        SubContractPos.ParentContractPosition = FixPos.ContractPositionID;

        //2. Import the SubContractPosition. Create a new sub contract and add all childs into the sub contract.
        if (oMPInterface.bImportContractPosition(SubContractPos, clsImportBase.eImportMode.ValidateAndImport)) {
            return MainContract.ContractID;
        } else {
            Assert.False(true, oMPInterface.oErrors.PrintErrors(true));
        }
    } else {
        Assert.False(true, oMPInterface.oErrors.PrintErrors(true));
    }
    return 0;
}

private clsImportProjectContract CreateNewContract(string sProject, string sContractName) {
    clsImportProjectContract oContract = new clsImportProjectContract();
    oContract.ProjectNumber = sProject; // existing project  P100005
    oContract.ContractNumber = oMPInterface.sGetNewContractNumber(sProject);  // new (visible) contract number based on automaric creation settings
    oContract.Description = sContractName + " " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString();
    oContract.ContractDate = DateTime.Now;
    oContract.CompanyID = 1;
    oContract.CustomerCode = "10006"; // valid customer number OCRD.CardCode
    oContract.ContractType = clsImportProjectContract.eContractTypes.IndividualContract;
    oContract.ValidPeriodFrom = 2016001; // Starting period for the contract YYYYMMM 

    if (oMPInterface.bImportContract(oContract, clsImportBase.eImportMode.ValidateAndImport)) {
        return oContract;
    } else {
        Assert.False(true, oContract.IMPORT_ErrorMessage);
        return null;
    }
}
private clsImportProjectContractPosition NewContractPosition(clsImportProjectContract Contract, clsImportProjectContractPosition.eContractPositionType nType,
                string sItemCode, string sDescription, decimal cQuantity = 1, string sExternalNumber = null) {
    clsImportProjectContractPosition oPos = new clsImportProjectContractPosition();
    oPos.PositionTyp = nType;
    oPos.ContractID = Contract.ContractID;
    oPos.Matchcode = sDescription;
    oPos.Description1 = sDescription;
    oPos.ContractQuantity = cQuantity;
    oPos.ItemCode = sItemCode;
    oPos.ExternalNumber = sExternalNumber;
    return oPos;
}
See Also