InsertInvoicePayment failing for a valid invoice number

Discussion in 'Developers Forum' started by Oisin Mulvihill, Jan 15, 2012.

  1. Oisin Mulvihill New Member

    Hi There,

    I'm writing a small tool that will mark a series of receipts as paid. I'm using python and SUDS against your WSDL for this. I am get an existing receipt from my system 483 (KF00483) and then attempt to add a Payment for this. The receipt is recovered ok, but the payment creation fails for the valid invoice number 483. I'm beginning to think the error is a red herring.

    The following the the SOAP debug and resultant Purchase Invoice I get which is work fine:

    Code:
    DEBUG:suds.transport.http:sending:
    URL:https://securedwebapp.com/api/service.asmx
    HEADERS: {'SOAPAction': u'"KashFlow/GetReceipt"', 'Content-Type': 'text/xml; charset=utf-8', 'Content-type': 'text/xml; charset=utf-8', 'Soapaction': u'"KashFlow/GetReceipt"'}
    MESSAGE:
    <?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="KashFlow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><ns0:Body><ns1:GetReceipt><ns1:UserName>highfalcon</ns1:UserName><ns1:Password>--password-removed--</ns1:Password><ns1:ReceiptNumber>483</ns1:ReceiptNumber></ns1:GetReceipt></ns0:Body></SOAP-ENV:Envelope>
    DEBUG:suds.transport.http:received:
    CODE: 200
    HEADERS: {'content-length': '1624', 'x-powered-by': 'ASP.NET', 'x-aspnet-version': '2.0.50727', 'server': 'Microsoft-IIS/7.0', 'connection': 'close', 'cache-control': 'private, max-age=0', 'date': 'Sun, 15 Jan 2012 13:26:35 GMT', 'content-type': 'text/xml; charset=utf-8'}
    MESSAGE:
    <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetReceiptResponse xmlns="KashFlow"><GetReceiptResult><InvoiceDBID>6783570</InvoiceDBID><InvoiceNumber>483</InvoiceNumber><InvoiceDate>2011-10-08T00:00:00</InvoiceDate><DueDate>2011-11-07T00:00:00</DueDate><Customer>MINI01</Customer><CustomerID>1159240</CustomerID><Paid>0</Paid><CustomerReference /><SuppressTotal>0</SuppressTotal><ProjectID>0</ProjectID><CurrencyCode>GBP</CurrencyCode><ExchangeRate>1.0000</ExchangeRate><ReadableString>Invoice Number : 483
    DBID: 6783570
    Date: 08/10/2011 00:00:00
    Due: 07/11/2011 00:00:00
    Customer: MINI01
    Paid: 0
    Cust Ref:
    Line 1 : 2621754,Python Ireland Conference - Taxi journeys 8 and 9 Oct
    EUR48.75/1.140 (exchange rate) =GBP42.76, --password-removed-- paid for by cash.,8064808,1.0000,42.7600,0.0000
    </ReadableString><Lines><anyType xsi:type="InvoiceLine"><Quantity>1.0000</Quantity><Description>Python Ireland Conference - Taxi journeys 8 and 9 Oct
    EUR48.75/1.140 (exchange rate) =GBP42.76,  paid for by cash.</Description><Rate>42.7600</Rate><ChargeType>2621754</ChargeType><VatRate>0.0000</VatRate><VatAmount>0.0000</VatAmount><ProductID>0</ProductID><Sort>0</Sort><ProjID>0</ProjID><LineID>8064808</LineID></anyType></Lines><NetAmount>42.7600</NetAmount><VATAmount>0.0000</VATAmount><AmountPaid>0.0000</AmountPaid><CustomerName>Mini Cab (Taxi)</CustomerName></GetReceiptResult><Status>OK</Status><StatusDetail /></GetReceiptResponse></soap:Body></soap:Envelope>
     
    Success
     
    rc:  (reply){
      GetReceiptResult =
          (Invoice){
            InvoiceDBID = 6783570
            InvoiceNumber = 483
            InvoiceDate = 2011-10-08 00:00:00
            DueDate = 2011-11-07 00:00:00
            Customer = "MINI01"
            CustomerID = 1159240
            Paid = 0
            CustomerReference = None
            SuppressTotal = 0
            ProjectID = 0
            CurrencyCode = "GBP"
            ExchangeRate = 1.0
            ReadableString = "Invoice Number : 483
    DBID: 6783570
    Date: 08/10/2011 00:00:00
    Due: 07/11/2011 00:00:00
    Customer: MINI01
    Paid: 0
    Cust Ref:
    Line 1 : 2621754,Python Ireland Conference - Taxi journeys 8 and 9 Oct
    EUR48.75/1.140 (exchange rate) =GBP42.76,  paid for by cash.,8064808,1.0000,42.7600,0.0000
    "
            Lines =
                (ArrayOfAnyType){
                  anyType[] =
                      (InvoiceLine){
                        Quantity = 1.0
                        Description = "Python Ireland Conference - Taxi journeys 8 and 9 Oct
    EUR48.75/1.140 (exchange rate) =GBP42.76,  paid for by cash."
                        Rate = 42.76
                        ChargeType = 2621754
                        VatRate = 0.0
                        VatAmount = 0.0
                        ProductID = 0
                        Sort = 0
                        ProjID = 0
                        LineID = 8064808
                      },
                }
            NetAmount = 42.76
            VATAmount = 0.0
            AmountPaid = 0.0
            CustomerName = "Mini Cab (Taxi)"
          }
      Status = "OK"
      StatusDetail = None
    }
    So far so good. The problem comes when I try to InsertInvoicePayment for this same invoice 483. I keep getting the error:

    You provided an invalid invoice number. at KashFlow.wsDb.InsertInvoicePayment(Payment InvoicePayment, Int32 UserID) in c:\Data\wwwroot\sec.kf\api\App_Code\DataClasses\wsDb.cs:line 2814
    at KashFlow.KashFlowAPI.InsertInvoicePayment(String UserName, String Password, String& Status, String& StatusDetail, Payment InvoicePayment) in c:\Data\wwwroot\sec.kf\api\App_Code\Service.cs:line 1535


    The debug output I send to you is:

    Code:
    Adding Payment to Purchase Invoice<483>: - (Payment){
      PayID = 0
      PayInvoice = 483
      PayDate = "2012-01-15T13:27:55"
      PayNote = "Paid as part of 223.96 expenses to Oisin. "
      PayMethod = 234026
      PayAccount = 85424
      PayAmount = 42.76
    }
    DEBUG:suds.transport.http:sending:
    URL:https://securedwebapp.com/api/service.asmx
    HEADERS: {'SOAPAction': u'"KashFlow/InsertInvoicePayment"', 'Content-Type': 'text/xml; charset=utf-8', 'Content-type': 'text/xml; charset=utf-8', 'Soapaction': u'"KashFlow/InsertInvoicePayment"'}
    MESSAGE:
    <?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="KashFlow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><ns0:Body><ns1:InsertInvoicePayment><ns1:UserName>highfalcon</ns1:UserName><ns1:Password>--password-removed--</ns1:Password><ns1:InvoicePayment><ns1:PayID>0</ns1:PayID><ns1:PayInvoice>483</ns1:PayInvoice><ns1:PayDate>2012-01-15T13:27:55</ns1:PayDate><ns1:PayNote>Paid as part of 223.96 expenses to Oisin. </ns1:PayNote><ns1:PayMethod>234026</ns1:PayMethod><ns1:PayAccount>85424</ns1:PayAccount><ns1:PayAmount>42.76</ns1:PayAmount></ns1:InvoicePayment></ns1:InsertInvoicePayment></ns0:Body></SOAP-ENV:Envelope>
    DEBUG:suds.transport.http:received:
    CODE: 200
    HEADERS: {'content-length': '829', 'x-powered-by': 'ASP.NET', 'x-aspnet-version': '2.0.50727', 'server': 'Microsoft-IIS/7.0', 'connection': 'close', 'cache-control': 'private, max-age=0', 'date': 'Sun, 15 Jan 2012 13:26:35 GMT', 'content-type': 'text/xml; charset=utf-8'}
    MESSAGE:
    <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><InsertInvoicePaymentResponse xmlns="KashFlow"><InsertInvoicePaymentResult>0</InsertInvoicePaymentResult><Status>NO</Status><StatusDetail>You provided an invalid invoice number.  at KashFlow.wsDb.InsertInvoicePayment(Payment InvoicePayment, Int32 UserID) in c:\Data\wwwroot\sec.kf\api\App_Code\DataClasses\wsDb.cs:line 2814
      at KashFlow.KashFlowAPI.InsertInvoicePayment(String UserName, String Password, String&amp; Status, String&amp; StatusDetail, Payment InvoicePayment) in c:\Data\wwwroot\sec.kf\api\App_Code\Service.cs:line 1535</StatusDetail></InsertInvoicePaymentResponse></soap:Body></soap:Envelope>
    (reply){
      InsertInvoicePaymentResult = 0
      Status = "NO"
      StatusDetail = "You provided an invalid invoice number.  at KashFlow.wsDb.InsertInvoicePayment(Payment InvoicePayment, Int32 UserID) in c:\Data\wwwroot\sec.kf\api\App_Code\DataClasses\wsDb.cs:line 2814
      at KashFlow.KashFlowAPI.InsertInvoicePayment(String UserName, String Password, String& Status, String& StatusDetail, Payment InvoicePayment) in c:\Data\wwwroot\sec.kf\api\App_Code\Service.cs:line 1535"
    }
    
    Can you see where I'm going wrong? I just cannot see what is wrong. I've tried using the database id of the invoice and this gives the same error.
  2. Oisin Mulvihill New Member

    For completeness I include my markaspaid.py script:

    Code:
    import logging
    import datetime
    import configobj
     
    from suds.client import Client
     
    KASHFLOW_WSDL = "https://securedwebapp.com/api/service.asmx?WSDL"
     
    logging.basicConfig()
    logging.basicConfig(level=logging.INFO)
    #logging.getLogger('suds.client').setLevel(logging.DEBUG)
    logging.getLogger('suds.transport').setLevel(logging.DEBUG)
    #logging.getLogger('suds.xsd.schema').setLevel(logging.DEBUG)
    #logging.getLogger('suds.wsdl').setLevel(logging.DEBUG)
     
     
    class Kashflow(object):
        def __init__(self, username, password, wsdl=KASHFLOW_WSDL):
            self.username = username
            self.password = password
            self.client = Client(wsdl) #, faults=False)
            self.cache = self.client.options.cache
            self.cache.setduration(seconds=0) #180)
     
        def create(self, name):
            return self.client.factory.create(name)
     
        def GetReceipt(self, receipt_number):
            return self.client.service.GetReceipt(self.username, self.password, receipt_number)
     
        def GetInvoice(self, kf_number):
            return self.client.service.GetInvoice(self.username, self.password, kf_number)
     
        def GetReceipts(self):
            return self.client.service.GetReceipts(self.username, self.password)
     
        def GetReceiptPayment(self, kf_number):
            return self.client.service.GetReceiptPayment (self.username, self.password, kf_number)
     
        def InsertInvoicePayment(self, payment):
            return self.client.service.InsertInvoicePayment(self.username, self.password, payment)
     
     
    def datetime_to_str(dt):
        """Return a string formatted via strftime('%Y-%m-%dT%H:%M:%S')."""
        return dt.strftime('%Y-%m-%dT%H:%M:%S')
     
     
    # Company debit card, recovered by look at account output:
    COMPANY_DEBIT_CARD = 234026
    CURRENT_ACCOUNT = 85424
     
     
    def add_payment(kf, invoice_number, amount, note, pay_date=None, pay_method=COMPANY_DEBIT_CARD, pay_account=CURRENT_ACCOUNT):
        """Add a payment to a receipt.
     
        http://accountingapi.com/manual_class_payment.asp
     
            <s:element minOccurs="1" maxOccurs="1" name="PayID" type="s:int"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayInvoice" type="s:int"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayDate" type="s:dateTime"/>
            <s:element minOccurs="0" maxOccurs="1" name="PayNote" type="s:string"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayMethod" type="s:int"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayAccount" type="s:int"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayAmount" type="s:decimal"/>
     
        """
        if not pay_date:
            pay_date = datetime_to_str(datetime.datetime.now())
     
        Payment = kf.create("Payment")
        Payment.PayID = 0
        Payment.PayInvoice = invoice_number #int(invoice_number)
        Payment.PayDate = pay_date
        Payment.PayNote = note
        Payment.PayMethod = pay_method
        Payment.PayAccount = pay_account
        Payment.PayAmount = amount
     
        print "Adding Payment to Purchase Invoice<%s>: - %s" % (invoice_number, Payment)
        rc = kf.InsertInvoicePayment(Payment)
        print rc
     
     
    def main():
        cfg = configobj.ConfigObj(infile="config.ini")
        user = cfg['default']['user']
        password = cfg['default']['password']
     
        kf = Kashflow(user, password)
        kf_number = 483
     
        rc = kf.GetReceipt(kf_number)
        print "rc: ", rc
     
        add_payment(kf, kf_number, 42.76, note="Paid as part of 223.96 expenses to Oisin. ")
     
        return
     
        # What I'm wokring toward:
        #
        for kf_number in range(483, 520):
            rc = kf.GetReceipt(kf_number)
            if rc.Status == "OK":
                receipt = rc.GetReceiptResult
     
                if not receipt.Paid:
                    print "receipt not paid:\n%s\n\n" % receipt
                    amount = receipt.NetAmount + receipt.VATAmount
                    try:
                        add_payment(kf, receipt.InvoiceNumber, amount, note="Paid as part of 223.96 expenses to Oisin. ")
                    except ValueError as e:
                        print "Failed to add payment for Invoice <%s>. Error:\n%s\n\n" % (kf_number, e)
     
                else:
                    print "Receipt for Invoice <%s> is paid already." % receipt.InvoiceNumber
                    rc = kf.GetReceiptPayment(kf_number)
                    if rc.Status == "OK":
                        print "Payment Details: "
                        for i in rc.GetReceiptPaymentResult:
                            print i[1]
     
            else:
                print "KF receipt number <%s> was not found!" % kf_number
     
     
    if __name__ == "__main__":
        main()
     
     
    
  3. monaghan Member

    Have you tried passing the InvoiceDBID rather than the invoice number, some of the API calls require the internal ID rather than the customer facing ID.

    I'd be interested in your findings as I'm just starting on a purchase order module for an existing development so will need to be adding payments shortly.
  4. Oisin Mulvihill New Member

    Yes, I tried using the InvoiceDBID which for kf00483 is 6783570 with no success. In fact I can put any number, valid or invalid and I get the same result. This is why I think the error message is a red herring and that the problem might lie elsewhere.

    Code:
    $python markaspaid.py
    :
    etc
    :
    Adding Payment to Purchase Invoice<6783570>: - (Payment){
      PayID = 0
      PayInvoice = 6783570
      PayDate = "2012-01-16T12:02:34"
      PayNote = "Paid as part of 223.96 expenses to Oisin. "
      PayMethod = 234026
      PayAccount = 85424
      PayAmount = 42.76
    }
    DEBUG:suds.transport.http:sending:
    URL:https://securedwebapp.com/api/service.asmx
    HEADERS: {'SOAPAction': u'"KashFlow/InsertInvoicePayment"', 'Content-Type': 'text/xml; charset=utf-8', 'Content-type': 'text/xml; charset=utf-8', 'Soapaction': u'"KashFlow/InsertInvoicePayment"'}
    MESSAGE:
    <?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="KashFlow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><ns0:Body><ns1:InsertInvoicePayment><ns1:UserName>highfalcon</ns1:UserName><ns1:Password>--removed--</ns1:Password><ns1:InvoicePayment><ns1:PayID>0</ns1:PayID><ns1:PayInvoice>6783570</ns1:PayInvoice><ns1:PayDate>2012-01-16T12:02:34</ns1:PayDate><ns1:PayNote>Paid as part of 223.96 expenses to Oisin. </ns1:PayNote><ns1:PayMethod>234026</ns1:PayMethod><ns1:PayAccount>85424</ns1:PayAccount><ns1:PayAmount>42.76</ns1:PayAmount></ns1:InvoicePayment></ns1:InsertInvoicePayment></ns0:Body></SOAP-ENV:Envelope>
    DEBUG:suds.transport.http:received:
    CODE: 200
    HEADERS: {'content-length': '829', 'x-powered-by': 'ASP.NET', 'x-aspnet-version': '2.0.50727', 'server': 'Microsoft-IIS/7.0', 'connection': 'close', 'cache-control': 'private, max-age=0', 'date': 'Mon, 16 Jan 2012 12:01:11 GMT', 'content-type': 'text/xml; charset=utf-8'}
    MESSAGE:
    <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><InsertInvoicePaymentResponse xmlns="KashFlow"><InsertInvoicePaymentResult>0</InsertInvoicePaymentResult><Status>NO</Status><StatusDetail>You provided an invalid invoice number.  at KashFlow.wsDb.InsertInvoicePayment(Payment InvoicePayment, Int32 UserID) in c:\Data\wwwroot\sec.kf\api\App_Code\DataClasses\wsDb.cs:line 2814
      at KashFlow.KashFlowAPI.InsertInvoicePayment(String UserName, String Password, String&amp; Status, String&amp; StatusDetail, Payment InvoicePayment) in c:\Data\wwwroot\sec.kf\api\App_Code\Service.cs:line 1535</StatusDetail></InsertInvoicePaymentResponse></soap:Body></soap:Envelope>
    (reply){
      InsertInvoicePaymentResult = 0
      Status = "NO"
      StatusDetail = "You provided an invalid invoice number.  at KashFlow.wsDb.InsertInvoicePayment(Payment InvoicePayment, Int32 UserID) in c:\Data\wwwroot\sec.kf\api\App_Code\DataClasses\wsDb.cs:line 2814
      at KashFlow.KashFlowAPI.InsertInvoicePayment(String UserName, String Password, String& Status, String& StatusDetail, Payment InvoicePayment) in c:\Data\wwwroot\sec.kf\api\App_Code\Service.cs:line 1535"
    }
  5. monaghan Member

    Hmm,

    I'd lean on the support guys, they probably won't be able to help directly but can and do escalate to a developer when I've thrown API questions at them.
  6. Oisin Mulvihill New Member

    After talking to the support guys, they managed to point me in the right direction. I had confused the invoice and purchase invoice and was using the wrong insert payment method. The correct method to use is InsertReceiptPayment and not InsertInvoicePayment.

    So my working "add_payment" function is now:

    Code:
    def add_payment(kf, invoice_number, amount, note, pay_date=None, pay_method=COMPANY_DEBIT_CARD, pay_account=CURRENT_ACCOUNT):
        """Add a payment to a receipt.
     
        http://accountingapi.com/manual_class_payment.asp
     
            <s:element minOccurs="1" maxOccurs="1" name="PayID" type="s:int"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayInvoice" type="s:int"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayDate" type="s:dateTime"/>
            <s:element minOccurs="0" maxOccurs="1" name="PayNote" type="s:string"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayMethod" type="s:int"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayAccount" type="s:int"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayAmount" type="s:decimal"/>
     
        """
        if not pay_date:
            pay_date = datetime_to_str(datetime.datetime.now())
     
        Payment = kf.create("Payment")
        Payment.PayID = 0
        Payment.PayInvoice = int(invoice_number)
        Payment.PayDate = pay_date
        Payment.PayNote = note
        Payment.PayMethod = pay_method
        Payment.PayAccount = pay_account
        Payment.PayAmount = amount
     
        print "Adding Payment to Purchase Invoice<%s>: - %s" % (invoice_number, Payment)
        rc = kf.InsertReceiptPayment(Payment)
        if rc.Status != "OK":
            raise ValueError("Failed to add Receipt payment for %s: %s" % (invoice_number, rc))
     
    
    I've now successfully marked groups of receipts as being paid. This will greatly reduce the amount of time I spend doing this. Hopefully others will benefit from my Doh! moment.
  7. Oisin Mulvihill New Member

    For completeness and to help future Python developers along, the following is the working markaspaid.py. Now, I just need to convert this into a "bulk load payments from spreadsheet".

    Code:
    #!/usr/bin/env python
    #
    # python markaspaid.py
    #
    # Requires:
    #  CondfigObj: http://www.voidspace.org.uk/python/configobj.html
    #  SUDS: https://fedorahosted.org/suds/
    #
    # easy_install -U configobj SUDS
    #
    # This looks for a config.ini in the current directory. The contents
    # of the configuration file look like:
    #
    # [default]
    # user = YOUR_USERNAME
    # password = YOUR_PASSWORD
    #
    # Set the user & password for your own kashflow account and allow
    # access via Kashflow.com Login->Settings->External Services->API Settings
    # ->Tick "Enable the API for my KashFlow account".
    #
    # (c) Oisin Mulvihill, http://www.sourceweaver.com, 2012-01-16.
    # Released under the BSD license. 
    #
    import logging
    import datetime
     
    import configobj
    from suds.client import Client
     
    KASHFLOW_WSDL = "https://securedwebapp.com/api/service.asmx?WSDL"
     
    logging.basicConfig()
    logging.basicConfig(level=logging.INFO)
    #logging.getLogger('suds.client').setLevel(logging.DEBUG)
    #logging.getLogger('suds.transport').setLevel(logging.DEBUG)
    #logging.getLogger('suds.xsd.schema').setLevel(logging.DEBUG)
    #logging.getLogger('suds.wsdl').setLevel(logging.DEBUG)
     
     
    class Kashflow(object):
     
        def __init__(self, username, password, wsdl=KASHFLOW_WSDL):
            self.username = username
            self.password = password
            self.client = Client(wsdl) #, faults=False)
            self.cache = self.client.options.cache
            self.cache.setduration(seconds=0) #180)
     
        def create(self, name):
            return self.client.factory.create(name)
     
        def GetReceipt(self, receipt_number):
            return self.client.service.GetReceipt(self.username, self.password, receipt_number)
     
        def GetInvoice(self, kf_number):
            return self.client.service.GetInvoice(self.username, self.password, kf_number)
     
        def GetReceipts(self):
            return self.client.service.GetReceipts(self.username, self.password)
     
        def GetReceiptPayment(self, kf_number):
            return self.client.service.GetReceiptPayment (self.username, self.password, kf_number)
     
        def InsertInvoicePayment(self, payment):
            return self.client.service.InsertInvoicePayment(self.username, self.password, payment)
     
        def InsertReceiptPayment(self, payment):
            return self.client.service.InsertReceiptPayment(self.username, self.password, payment)
     
     
    def datetime_to_str(dt):
        """Return a iso8601 compatible string formatted."""
        return dt.strftime('%Y-%m-%dT%H:%M:%S')
     
     
    def add_payment(kf, invoice_number, amount, note, pay_method, pay_account, pay_date=None):
        """Add a payment to a receipt.
     
        http://accountingapi.com/manual_class_payment.asp
     
            <s:element minOccurs="1" maxOccurs="1" name="PayID" type="s:int"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayInvoice" type="s:int"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayDate" type="s:dateTime"/>
            <s:element minOccurs="0" maxOccurs="1" name="PayNote" type="s:string"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayMethod" type="s:int"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayAccount" type="s:int"/>
            <s:element minOccurs="1" maxOccurs="1" name="PayAmount" type="s:decimal"/>
     
        """
        if not pay_date:
            pay_date = datetime_to_str(datetime.datetime.now())
     
        Payment = kf.create("Payment")
        Payment.PayID = 0
        Payment.PayInvoice = int(invoice_number)
        Payment.PayDate = pay_date
        Payment.PayNote = note
        Payment.PayMethod = pay_method
        Payment.PayAccount = pay_account
        Payment.PayAmount = amount
     
        print "Adding Payment to Purchase Invoice<%s>: - %s" % (invoice_number, Payment)
        rc = kf.InsertReceiptPayment(Payment)
        if rc.Status != "OK":
            raise ValueError("Failed to add Receipt payment for %s: %s" % (invoice_number, rc))
     
     
    def main():
        """
        """
        cfg = configobj.ConfigObj(infile="config.ini")
     
        user = cfg['default']['user']
        password = cfg['default']['password']
     
        kf = Kashflow(user, password)
     
        # Company debit card, recovered by look at account output:
        COMPANY_DEBIT_CARD = 234026
        CURRENT_ACCOUNT = 85424
     
        note = "Paid as part of 223.96 expenses to Oisin."
        method = COMPANY_DEBIT_CARD
        account = CURRENT_ACCOUNT
        first_receipt = 483
        last_receipt =  520 # not included in range, add +1 to include.
     
        for kf_number in range(first_receipt, last_receipt):
            rc = kf.GetReceipt(kf_number)
            if rc.Status == "OK":
                receipt = rc.GetReceiptResult
                if not receipt.Paid:
                    print "receipt not paid:\n%s\n\n" % receipt
                    amount = receipt.NetAmount + receipt.VATAmount
                    try:
                        add_payment(kf, receipt.InvoiceNumber, amount, note=note, pay_method=method, pay_account=account)
                    except ValueError as e:
                        print "Failed to add payment for Invoice <%s>. Error:\n%s\n\n" % (kf_number, e)
     
                else:
                    print "Receipt for Invoice <%s> is paid already." % receipt.InvoiceNumber
                    rc = kf.GetReceiptPayment(kf_number)
                    if rc.Status == "OK":
                        print "Payment Details: "
                        for i in rc.GetReceiptPaymentResult:
                            print i[1]
     
            else:
                print "KF receipt number <%s> was not found!" % kf_number
     
     
     
    if __name__ == "__main__":
        main()
    
  8. monaghan Member

    Thanks for the update, I've called the wrong function many times wondering why it wasn't giving me the right output :)

Share This Page