calcinai / xero-php

A php library for the Xero API, with a cleaner OAuth interface and ORM-like abstraction.
MIT License
360 stars 260 forks source link

Item API couldn't update #528

Closed arivazhaganark closed 5 years ago

arivazhaganark commented 5 years ago

When updating an item unit price, it throws an error as "Price List Item Code must be supplied". I found the bug, on Application.php --> save() method line no 296, only send dirty attributes only. $data = [$object::getRootNodeName() => $object->toStringArray(true)];

So the <Code> doesn't dirty. that's why it's not send to API Body.

Even in the Xero Previewer, i try to manually update the Item with Code&ItemID.


<Item>
    <ItemID>XXXXXXXX-XXXX-XXXX-a31f-1f47e0487b6d</ItemID>
    <Code>ADRYPRESSEDM</Code>
    <SalesDetails>
        <UnitPrice>2</UnitPrice>
        <AccountCode>41100</AccountCode>
    </SalesDetails>
</Item>
</Items>```

But it won't update. still throwing the error as 
'Price List Item with Code 'ADRYPRESSEDM' already exists`
Billanthrop commented 5 years ago

I think I have experienced the same issue today. Writing a basic function to update an item I found that unless I changed the item code, I was getting the "Price List Item Code must be supplied" error.

After finding this note on the issue I implemented a crude workaround that forced the item code to always be dirty:

function UpdateItem($xero, $itemId, $itemCode, $itemName, $costPrice, $salePrice)
{

    $item = $xero->loadByGUID(Item::class, $itemId);

    $item->setCode('HACK') // Always setting the item code to this then back fixes the issue.
    ->setCode($itemCode)
    ->setName($itemName)
    ->setPurchaseDetails(
        (new Purchase())
        ->setUnitPrice($costPrice)
    )
    ->setSalesDetails(
        (new Sale())
        ->setUnitPrice($salePrice)
    )
    ->setApplication($xero)
    ->save();
}
arivazhaganark commented 5 years ago

Yes @Billanthrop the HACK resolved the issue. Thanks

emp-sean commented 2 years ago

@calcinai this appears to still be an issue today, is this xero-php issue or a Xero API issue? Be good to get a fix if it is this side rather than having to do this hack.

emp-sean commented 2 years ago

I think I have experienced the same issue today. Writing a basic function to update an item I found that unless I changed the item code, I was getting the "Price List Item Code must be supplied" error.

After finding this note on the issue I implemented a crude workaround that forced the item code to always be dirty:

function UpdateItem($xero, $itemId, $itemCode, $itemName, $costPrice, $salePrice)
{

    $item = $xero->loadByGUID(Item::class, $itemId);

    $item->setCode('HACK') // Always setting the item code to this then back fixes the issue.
    ->setCode($itemCode)
    ->setName($itemName)
    ->setPurchaseDetails(
        (new Purchase())
        ->setUnitPrice($costPrice)
    )
    ->setSalesDetails(
        (new Sale())
        ->setUnitPrice($salePrice)
    )
    ->setApplication($xero)
    ->save();
}

Thanks, was banging my head with this one for ages

calcinai commented 2 years ago

@empsean it's a bit of both probably. The Xero API allows partial updates of objects, but it looks like in this case, if you don't send the whole thing it complains. I suspect the only resolutions are 1, change the default behaviour to always send when whole object or 2, add some specific behaviour for this object to always return all properties in the dirty array.

emp-sean commented 2 years ago

Suppose the issue with 1 is that as you have the Sale and Purchase underneath have to retrieve that portion 2. 2 maybe better in that case, but is kind of dirty making a different process for this specific object