Netsuite: How to link Purchase Order to Sales Order

I don't have an answer, but hopefully I can contribute. First of all, I think you're approaching this from the wrong direction. Rather than creating the PO and then trying to link it to the SO, I think you'll have to initialize the PO via the native dropship process and then save the PO. For example, creating a drop ship PO is pretty easy in SuiteScript 2.0. Here's how it's done:

var purchaseOrder = record.create ({
    type: record.Type.PURCHASE_ORDER,
    isDynamic: true,
    defaultValues: {
        recordmode: 'dynamic',
        soid: '11111',
        dropship: true, 
        custid: '22222',
        entity: '33333'
    }
})

This new PO is populated with all valid items from the SO and when it's saved all the linking is done automatically (createdFrom is automatically set on the PO; createdPo is automatically set on the SO item). I tried to recreate this in SuiteTalk using two different methods, both of which failed. Here they are:

The first approach tries to emulate the SuiteScript method using the initialize() method. This is how you create an SO from an Estimate, or an IF from an SO, so it seems promising:

var initrec = new InitializeRecord
{
    type = InitializeType.purchaseOrder,
    reference = new InitializeRef
    {
        internalId = "11111",
        type = InitializeRefType.salesOrder,
        typeSpecified = true
    }
};
var res = NSBase.Client.Service.initialize(initrec);
// "You can not initialize purchaseOrder by referencing salesOrder."

The error is self-explanatory. It's not possible to create a PO from an SO using initialize(). This is very disheartening.

The second approach essentially tries to programmatically click the "drop ship" link on the line item. It fails with a similar error to the one you encountered before:

var objSO = new SalesOrder();
objSO.internalId = "11111";
objSO.itemList = new SalesOrderItemList
{
    item = new SalesOrderItem[]
    {
        new SalesOrderItem { line = 10, lineSpecified = true, createPo = SalesOrderItemCreatePo._dropShipment, createPoSpecified = true }
    },
    replaceAll = false
};
var result = Service.update(objSO);
// "You do not have permissions to set a value for element item.createpo due to one of the following reasons: 1) The field is read-only; 2) An associated feature is disabled; 3) The field is available either when a record is created or updated, but not in both cases."

Unfortunately, this is the best I can do. The initialization approach definitely seems like the most likely solution to the problem, and the fact that it fails makes me wonder if it is even possible to create a drop ship/special order PO using SuiteTalk.