Xero App ******** .. highlight:: bash - https://gitlab.com/kb/xero_app - Log into your accounts package: https://go.xero.com/Dashboard/ - Developer: https://developer.xero.com/myapps - Connected apps: https://apps.xero.com/ Icon ==== :: Account ======= To set-up a new trial account: 1. https://go.xero.com/Dashboard/ 2. Click on your profile icon, then choose *Account* followed by *Home*. Click *Add an organisation*. 3. To delete the old test account, click on your profile icon, then choose *Account* followed by *Home*. Find your *Trial* account and click *Cancel*. .. tip:: (If you are testing), then don't forget to remove all records from the UUID models. API === From https://github.com/freakboy3742/pyxero#private-applications From https://developer.xero.com/documentation/api-guides/create-publicprivate-key :: ➤ openssl genrsa -out privatekey.pem 1024 Generating RSA private key, 1024 bit long modulus ➤ openssl req -new -x509 -key privatekey.pem -out publickey.cer -days 1825 Country Name (2 letter code) [AU]:GB State or Province Name (full name) [Some-State]:Devon Locality Name (eg, city) []:Okehampton Organization Name (eg, company) [Internet Widgits Pty Ltd]:KB Software Ltd Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:kbsoftware.co.uk Email Address []:patrick@kbsoftware.co.uk # just press enter for the password ➤ openssl pkcs12 -export -out public_privatekey.pfx -inkey privatekey.pem -in publickey.cer Enter Export Password: Verifying - Enter Export Password: https://developer.xero.com/myapps 1. *New app* 2. *Private app* 3. *App name* e.g. ``KB7`` 4. *Organisation* e.g. ``KB7`` 5. *Upload Certificate File*, upload ``publickey.cer`` (generated above)... 6. *Create App* .. image:: ./misc/xero-add-new-app-1.png .. note:: If you get *Failed to Create App*, then try logging out and back in again (or browse to some of the profile pages). .. image:: ./misc/xero-add-new-app-2.png Copy the *Consumer Key* from *OAuth 1.0a Credentials* to the ``.private`` file in your project e.g:: set -x XERO_CONSUMER_KEY="1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ" Add the consumer key to ``base.py`` in your settings:: XERO_CONSUMER_KEY = get_env_variable("XERO_CONSUMER_KEY") Click :ref:`django_generate_url` to see how to set-up ``HOST_NAME`` in your settings file. The ``HOST_NAME`` is used to build a URL to link back from Xero to your project. If you log into your Xero app, you can see the *Connected App* (not so easy to find) e.g: .. image:: ./misc/xero-add-new-app-3.png Management Commands =================== To upload a single invoice to Xero, pass in the primary key of the invoice e.g:: django-admin.py sync_invoice_to_xero 1234 Requirements ============ :: pip install pyxero Usage ===== For development, add the following to your ``.private`` file:: set -x XERO_CONSUMER_KEY "ABC123456123456" To ``.env``:: export XERO_KEY_FILE="privatekey.pem" To ``.env.fish``:: set -x XERO_KEY_FILE "privatekey.pem" Add the following to ``settings/base.py``:: XERO_CONSUMER_KEY = get_env_variable("XERO_CONSUMER_KEY") XERO_KEY_FILE = get_env_variable("XERO_KEY_FILE") For the live site, add the following to your Salt ``sites`` file:: env: xero_consumer_key: "ABC123456123456" xero_key_file: "/home/web/repo/files/www.hatherleigh.info/project/privatekey.pem" Testing ======= .. tip:: The pyxero_ module has a ``_parse_api_response`` method which extracts the ``data`` using the ``resource_name``. To properly construct mock data you need to know the ``resource_name``. (``_parse_api_response`` can be found in ``site-packages/xero/basemanager.py``). In the example below, ``Contacts`` and ``Invoices`` are the ``resource_name``. Use the ``responses`` library for mocking Xero. A good example of this can be found in the `mock Xero code`_ e.g:: import responses @pytest.mark.django_db @responses.activate def test_xero_sync_invoice(): invoice = InvoiceFactory() XeroCurrencyFactory(currency=invoice.currency) XeroSettingsFactory(invoice_account=AccountFactory(code="010203")) contact_uuid = str(uuid.uuid4()) invoice_uuid = str(uuid.uuid4()) responses.add( responses.PUT, "https://api.xero.com/api.xro/2.0/Contacts", json={"Status": "OK", "Contacts": [{"ContactID": contact_uuid}]}, status=HTTPStatus.OK, ) responses.add( responses.PUT, "https://api.xero.com/api.xro/2.0/Invoices", json={"Status": "OK", "Invoices": [{"InvoiceID": invoice_uuid}]}, status=HTTPStatus.OK, ) assert invoice.pk == xero_sync_invoice(invoice.pk) .. _`mock Xero code`: https://gitlab.com/kb/xero_app/blob/master/xero_app/tests/test_tasks.py .. _pyxero: https://github.com/freakboy3742/pyxero