pyxero icon indicating copy to clipboard operation
pyxero copied to clipboard

Credit Note Allocations cannot be entered

Open jimfunk opened this issue 10 years ago • 4 comments

Looking at the code, it seems that Credit Note Allocations cannot be entered, since it's implemented on a separate endpoint:

http://developer.xero.com/documentation/api/credit-notes/#title8

jimfunk avatar Aug 29 '15 22:08 jimfunk

You'll be able to hack this together like so: https://github.com/freakboy3742/pyxero/issues/107

aidanlister avatar Oct 30 '15 01:10 aidanlister

This requires a little more hacking - #107 almost works with CreditNote Allocations, but the endpoint has to look like CreditNotes/{CreditNoteID}/Allocations.

If we re-set the base_url for xero.creditnotes.put then we end up calling CreditNotes/{CreditNoteID}/Allocations/CreditNotes because of how basemanager.py constructs the uri:

uri = '/'.join([self.base_url, self.name])

So we also need to swap out the name and singular like so:

    old_base_url = xero.creditnotes.base_url
    old_name = xero.creditnotes.name
    old_singular = xero.creditnotes.singular
    xero.creditnotes.base_url = '{}/CreditNotes/{}'.format(old_base_url, creditnoteid)
    xero.creditnotes.name = 'Allocations'
    xero.creditnotes.singular = 'Allocation'

MattHealy avatar Nov 04 '15 12:11 MattHealy

Thanks aidanlister and MattHealy. My version of this looks like this:

def allocate_credit_note_payment(credit_note_guid, allocations, xero):
    """
    Must pass in xero as it needs credentials if using public method.

    allocations should be an array of dictionaries containing amount, invoice:invoice idXero GUIDs for the contacts.

    The request should look like:
    PUT CreditNotes/a1665e41-719b-400d-ae59-bc92655d8366/Allocations
    <Allocations>
        <Allocation>
            <AppliedAmount>60.50</AppliedAmount>
            <Invoice>
                <InvoiceID>f5832195-5cd3-4660-ad3f-b73d9c64f263</InvoiceID>
            </Invoice>
        </Allocation>
    </Allocations>
    """

    # Store the original endpoint base_url
    old_base_url = xero.creditnotes.base_url
    old_name = xero.creditnotes.name
    old_singular = xero.creditnotes.singular

    # Call the API
    try:
        xero.creditnotes.base_url = '{}/CreditNotes/{}'.format(old_base_url, credit_note_guid)
        xero.creditnotes.name = 'Allocations'
        xero.creditnotes.singular = 'Allocation'
        xero.creditnotes.put(allocations)
    except:
        raise
    finally:
        # Reset the base_url
        xero.creditnotes.base_url = old_base_url
        xero.creditnotes.name = old_name
        xero.creditnotes.singular = old_singular

Which I called from something like this:

...
...
    def add_to_xero(self, xero):
        """ Going to allocate all to a single invoice."""
        cn = self.parent.xero_credit_notes(xero)[0]
        credit_note_guid = cn['CreditNoteID']
        allocations = []
        allocation = {}
        allocation['AppliedAmount'] = self.parent.gross_amount
        allocation['Invoice'] = {}
        allocation['Invoice']['InvoiceID'] = self.parent.invoice_id
        allocations.append(allocation)
        try:
            # Now add to Xero
            allocate_credit_note_payment(credit_note_guid, allocations, xero)
        except XeroBadRequest as e:
            print('Problem with add to xero, ? {}'.format(self))
            raise e
...
...

The double put method does need a general solution but I don't have one. Should we be looking for something like: xero.creditnotes(id={}).allocations.put(new_credit_note_allocations)

drummonds avatar Feb 20 '17 12:02 drummonds

Can confirm, @drummonds method is working nicely :ok_hand:

RadoRado avatar Dec 04 '17 14:12 RadoRado