Giter Club home page Giter Club logo

pymyob's Introduction

PyMYOB

PyPI version versions Downloads Test Lint

A Python API around the MYOB Business API (formerly AccountRight Live, and New Essentials).

Pre-getting started

Register for API Keys with MYOB. You'll find detailed instructions here.

Getting started

Install:

pip install pymyob

Create a PartnerCredentials instance and provide the Key, Secret and Redirect Uri as you've set up in MYOB:

from myob.credentials import PartnerCredentials

cred = PartnerCredentials(
    consumer_key=<Key>,
    consumer_secret=<Secret>,
    callback_uri=<Redirect Uri>,
)

Cache cred.state somewhere. You'll use this to rebuild the PartnerCredentials instance later. This object includes a datetime object, so if your cache does not serialise datetime objects, you'll need to find an alternative, such as pickling and saving to a binary database column.

Redirect the user to cred.url. There, they will need to log in to MYOB and authorise partnership with your app1. Once they do, they'll be redirected to the Redirect Uri you supplied.

At the url they're redirected to, rebuild the PartnerCredentials then pick the verifier out of the request and use it to verify the credentials.

from myob.credentials import PartnerCredentials

def myob_authorisation_complete_view(request):
    verifier = request.GET.get('code', None)
    if verifier:
        state = <cached_state_from_earlier>
        if state:
            cred = PartnerCredentials(**state)
            cred.verify(verifier)
            if cred.verified:
                messages.success(request, 'OAuth verification successful.')
            else:
                messages.error(request, 'OAuth verification failed: verifier invalid.')
        else:
            messages.error(request, 'OAuth verification failed: nothing to verify.')
    else:
        messages.error(request, 'OAuth verification failed: no verifier received.')

Save cred.state once more, but this time you want it in persistent storage. So plonk it somewhere in your database.

With your application partnered with MYOB, you can now create a Myob instance, supplying the verified credentials:

from myob import Myob
from myob.credentials import PartnerCredentials

cred = PartnerCredentials(**<persistently_saved_state_from_verified_credentials>)
myob = Myob(cred)

You're almost there! MYOB has this thing called company files. Even though you've authorised against a user now, you need to collect a further set of credentials for getting into the company file.

companyfiles = myob.companyfiles.all()

# Each company file has the following attrs:
comp.id  # Company Id
comp.name  # Company Name
comp.data  # Remaining data as a raw dict.

Tip: the companyfiles object specifies all supported managers (that is, endpoints).

Render a dropdown for your user to let them select which of the company files they wish to use. Usually there will only be one against their account, but best to check. If additional authentication against the company file is needed (ie when the company file account isn't tied via SSO to a my.myob account), prompt them for the username and password for that company file and save this as follows:

cred.authenticate_companyfile(<company_id>, <username>, <password>)

Save the new cred.state back to your persistent storage.

Now you can access stuff!

from myob import Myob
from myob.credentials import PartnerCredentials

cred = PartnerCredentials(**<persistently_saved_state_from_verified_credentials>)
myob = Myob(cred)

# Obtain list of company files. Here you will also find their IDs, which you'll need to retrieve a given company file later.
company_files = myob.companyfiles.all()

# Obtain a specific company file. Use `call=False` to just prep it for calling other endpoints without actually making a call yet at this stage.
comp = myob.companyfiles.get(<company_id>, call=False)

# Obtain a list of customers (two ways to go about this).
customers = comp.contacts.all(Type='Customer')
customers = comp.contacts.customer()

# Obtain a list of sale invoices (two ways to go about this).
invoices = comp.invoices.all(InvoiceType='Item', orderby='Number desc')
invoices = comp.invoices.item(orderby='Number desc')

# Create an invoice.
comp.invoices.post_item(data=data)

# Obtain a specific invoice.
invoice = comp.invoices.get_item(uid=<invoice_uid>)

# Download PDF for a specific invoice.
invoice_pdf = comp.invoices.get_item(uid=<invoice_uid>, headers={'Accept': 'application/pdf'})

# Obtain a list of tax codes.
taxcodes = comp.general_ledger.taxcode()

# Obtain a list of inventory items.
inventory = comp.inventory.item()

# Use endswith, startswith, or substringof filters
search_text = 'Acme'
customers = comp.contacts.customer(raw_filter=f"substringof('{search_text}', CompanyName)")

If you don't know what you're looking for, the reprs of most objects (eg. myob, comp, comp.invoices above) will yield info on what managers/methods are available. Each method corresponds to one API call to MYOB.

Note that not all endpoints are covered here yet; we've just been adding them on an as-needed basis. If there's a particular endpoint you'd like added, please feel free to throw it into the endpoints.py file and open up a PR. All contributions are welcome and will be reviewed promptly. :)

1: Your users can review their partner authorisations at https://secure.myob.com/. โ†ฉ

pymyob's People

Contributors

aldonald avatar bartondc avatar dependabot[bot] avatar furious-luke avatar jarekwg avatar jpmoral-factory avatar laurielounge avatar mattjegan avatar rmartin48 avatar seb-b avatar sticky-bits avatar theducvu avatar thegumbyman avatar timrichardson avatar wardy3 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pymyob's Issues

Company list returns blank

We have checked every step of the auth process, it passes the initial code, then the auth and refresh tokens are provided, we have output all data from the stored creds and it all looks good, when trying the same thing in postman (different keys) i get a company list back.

Any help would be great because this is all we get back

{
"company_files": []
}

Using this library with an access_token rather than creds

Hi there,

I've successfully got a flow working with OAuth 2.0 that gets me an MYOB Token.

However, the way this "creds" needs to be saved/stored, goes against my method of storing and refreshing tokens through a seperate OAuth flow. This is not ideal for me as I am also connecting to Xero and other accounting packages.

These other libraries use the token and expose methods to set the token for the SDK, and then from there I can query the endpoints.

Is there a possible way of doing this with this SDK?

Write tests

  • Test endpoints
  • Test request_kwarg building
  • Test __repr__ outputs.

Add Black CI check

Codebase is now linted w Black, but doesn't have a CI check to enforce.

company files

<EDIT - My bad, was using not the most recent version
Comment left so you know someone's checking out your work>

Hi there,

< cred.authenticate_companyfile(company_id, , )>

That's not really a thing, is it? Can't see it referred to in any of the code... is that for the version 1 of the myob API perhaps?

Or have I totally gone off on the wrong track here?

What I mean is, running through the instructions (which are a work in progress, no probs), I get to this point;

cred.authenticate_companyfile(company_id, , )

... and it all stops. Just looking at a php example that's working (AccountRight_OAUTH_sample_php) to see what can be done here.

Rethink repr usage

I've written the __repr__ methods in a way that makes it super quick to know what methods are available on a manager. However, when looking at a list of companyfiles, you end up getting something like this:

[CompanyFile:
     contacts
     general_ledger
     inventory
     invoices
     purchase_bills
     purchase_orders,
CompanyFile:
     contacts
     general_ledger
     inventory
     invoices
     purchase_bills
     purchase_orders]

This obviously (a) looks silly, and (b) provides no insight as to what each companyfile is. Should at the very least include the name and uid of the companyfile, and also consider moving the method list to a separate methods() function rather than having the repr list available endpoints.

Reponse 401

Hi Jarek,

I'm seeing response 401 whenever I try and grab data.

(Pdb) cred.verified
True
(Pdb) cred.refresh()
(Pdb) p comp.id
'c4040fe7-dbb9-4bb2-XXX-cc2ba4ccbe16'
(Pdb) p comp.data
{'Id': 'c4040fe7-dbb9-4bb2-XXX-cc2ba4ccbe16'}
(Pdb) inv = comp.inventory.item()
*** myob.exceptions.MyobUnauthorized: (<Response [401]>, 'Unauthorized')

Doesn't seem to matter what I'm trying for. Have you seen this? Any ideas?

regards,

Laurie

Unable to install master

I have tried to install from the last commit and it appears that pip doesn't know it needs to install requests-oauthlib.

I ran pip install git+https://github.com/uptick/pymyob.git@44b8c35444b73d6b35a7b79a9d60c4dd4ef7dd51#egg=pymyob

Here is my stacktrace:


Collecting pymyob
  Cloning https://github.com/uptick/pymyob.git (to revision 44b8c35444b73d6b35a7b79a9d60c4dd4ef7dd51) to /private/var/folders/75/8gmml8cd6rd5dswqq4sp4dr80000gn/T/pip-install-z8c919qt/pymyob
  Running command git clone -q https://github.com/uptick/pymyob.git /private/var/folders/75/8gmml8cd6rd5dswqq4sp4dr80000gn/T/pip-install-z8c919qt/pymyob
    ERROR: Command errored out with exit status 1:
     command: /Users/eganm/.local/share/virtualenvs/xyzproject-xqRGoeqW/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/75/8gmml8cd6rd5dswqq4sp4dr80000gn/T/pip-install-z8c919qt/pymyob/setup.py'"'"'; __file__='"'"'/private/var/folders/75/8gmml8cd6rd5dswqq4sp4dr80000gn/T/pip-install-z8c919qt/pymyob/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /private/var/folders/75/8gmml8cd6rd5dswqq4sp4dr80000gn/T/pip-install-z8c919qt/pymyob/pip-egg-info
         cwd: /private/var/folders/75/8gmml8cd6rd5dswqq4sp4dr80000gn/T/pip-install-z8c919qt/pymyob/
    Complete output (39 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/private/var/folders/75/8gmml8cd6rd5dswqq4sp4dr80000gn/T/pip-install-z8c919qt/pymyob/setup.py", line 3, in <module>
        setup()
      File "/Users/eganm/.local/share/virtualenvs/xyzproject-xqRGoeqW/lib/python3.6/site-packages/setuptools/__init__.py", line 144, in setup
        return distutils.core.setup(**attrs)
      File "/Users/eganm/.pyenv/versions/3.6.8/lib/python3.6/distutils/core.py", line 121, in setup
        dist.parse_config_files()
      File "/Users/eganm/.local/share/virtualenvs/xyzproject-xqRGoeqW/lib/python3.6/site-packages/_virtualenv.py", line 21, in parse_config_files
        result = old_parse_config_files(self, *args, **kwargs)
      File "/Users/eganm/.local/share/virtualenvs/xyzproject-xqRGoeqW/lib/python3.6/site-packages/setuptools/dist.py", line 690, in parse_config_files
        ignore_option_errors=ignore_option_errors)
      File "/Users/eganm/.local/share/virtualenvs/xyzproject-xqRGoeqW/lib/python3.6/site-packages/setuptools/config.py", line 121, in parse_configuration
        meta.parse()
      File "/Users/eganm/.local/share/virtualenvs/xyzproject-xqRGoeqW/lib/python3.6/site-packages/setuptools/config.py", line 426, in parse
        section_parser_method(section_options)
      File "/Users/eganm/.local/share/virtualenvs/xyzproject-xqRGoeqW/lib/python3.6/site-packages/setuptools/config.py", line 399, in parse_section
        self[name] = value
      File "/Users/eganm/.local/share/virtualenvs/xyzproject-xqRGoeqW/lib/python3.6/site-packages/setuptools/config.py", line 184, in __setitem__
        value = parser(value)
      File "/Users/eganm/.local/share/virtualenvs/xyzproject-xqRGoeqW/lib/python3.6/site-packages/setuptools/config.py", line 515, in _parse_version
        version = self._parse_attr(value, self.package_dir)
      File "/Users/eganm/.local/share/virtualenvs/xyzproject-xqRGoeqW/lib/python3.6/site-packages/setuptools/config.py", line 349, in _parse_attr
        module = import_module(module_name)
      File "/Users/eganm/.pyenv/versions/3.6.8/lib/python3.6/importlib/__init__.py", line 126, in import_module
        return _bootstrap._gcd_import(name[level:], package, level)
      File "<frozen importlib._bootstrap>", line 994, in _gcd_import
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "<frozen importlib._bootstrap_external>", line 678, in exec_module
      File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
      File "/private/var/folders/75/8gmml8cd6rd5dswqq4sp4dr80000gn/T/pip-install-z8c919qt/pymyob/myob/__init__.py", line 1, in <module>
        from .api import Myob  # noqa
      File "/private/var/folders/75/8gmml8cd6rd5dswqq4sp4dr80000gn/T/pip-install-z8c919qt/pymyob/myob/api.py", line 1, in <module>
        from .credentials import PartnerCredentials
      File "/private/var/folders/75/8gmml8cd6rd5dswqq4sp4dr80000gn/T/pip-install-z8c919qt/pymyob/myob/credentials.py", line 4, in <module>
        from requests_oauthlib import OAuth2Session
    ModuleNotFoundError: No module named 'requests_oauthlib'
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

x-myobapi-cftoken header not needed sometimes

So I think from googling, if you are attached to a CompanyFile via my.myob.com you do not require the x-myobapi-cftoken header, and in fact when I do try to use it, I get a 401 (???). When I manually delete the header from request_kwargs before hitting an endpoint everything works ok, but if don't authenticate with a CompanyFile I get a KeyError('There are no stored username-password credentials for this company id.')

Is it possible to make the CF authentication optional? This project is great for helping with the nasty oauth flow I'd love to keep using it for the CRUD operations too

Unable to setup with the package

unable to setup with the package. The documentation is not clear
It would be great if you can upload an example just for fetching the company names or something.

Originally posted by @rehmanjaffersayani in #6 (comment)

Hey @rehmanjaffersayani ,
Have you followed the steps in the readme? Where are you up to?

Yeah, I tried. Unable to sort this

InvalidClientIdError: (invalid_request) Invalid client_id parameter value.

I have attached the screenshot for your reference
Screen Shot 2019-11-19 at 11 51 44 am

Can you elaborate what you're doing here:
myob_authorisation_complete_view(cred)

You can't just pass these credentials directly into the view. You have to set up myob_authorisation_complete_view (or similar) as an endpoint that will receive the auth response from MYOB, then redirect user to MYOB where they authenticate themselves and approve the integration. Then MYOB will redirect to your designated callback_uri, where your view will be waiting to handle the request.

I called the same method as defined.
myob_authorisation_complete_view()

I am trying to do in a cron job so I am having issues. Is there any implementation for just starting the process or example.

It would be great

I have run MYOB pre-defined postman and it's working fine

Invalid client_id

Hi everyone.

Firstly thanks for the library!

I am intermittently receiving an invalid client_id value error when processing the callback from MYOB. It's a bit of a head scratcher as I don't have conditional logic so can't see why it's producing inconsistent results. Often I will get the error on the first try, but then if I reload it will pass. Then I wait a little while and try again and it fails, but on a reload it will pass.

I checked #21 but I can see that the PartnerCredentials.url is sending the client_id and I am on version 1.2.7 of pymyob.

Here's a simplified version of my processing view:

def get(self, request, *args, **kwargs):
    cred_state = cache.get('MYOB_creds')
    auth_secret = self.request.GET.get('code')
    creds = PartnerCredentials(**cred_state)
    creds.verify(auth_secret)
    myob = Myob(creds)
    files = myob.companyfiles.all()
    ....
File "/usr/local/lib/python3.6/dist-packages/oauthlib/oauth2/rfc6749/errors.py", line 405, in raise_from_error
    raise cls(**kwargs)
oauthlib.oauth2.rfc6749.errors.InvalidClientIdError: (invalid_request) Invalid client_id parameter value.

And inspecting the PartnerCredentials object

>>>creds.verify(auth_secret)
*** oauthlib.oauth2.rfc6749.errors.InvalidClientIdError: (invalid_request) Invalid client_id parameter value.
>>>creds.__dict__
{'consumer_key': '<>', 'consumer_secret': '<>', 'callback_uri': '<callback>', 'verified': True, 'companyfile_credentials': {}, 'oauth_token': '<token>', 'refresh_token': '<refresh>', 'oauth_expires_at': datetime.datetime(2020, 8, 17, 1, 36, 57, 324550), '_oauth': <requests_oauthlib.oauth2_session.OAuth2Session object at 0x7f5d50506780>, 'url': 'https://secure.myob.com/oauth2/account/authorize/?response_type=code&client_id=<client_id>&redirect_uri=<uri>&scope=CompanyFile'}

Empty string returned from API causes JSON error

Version 1.2.4
Sending a DELETE request to the Item/<uid> endpoint returns an empty 200 response. This results in an error when the Manager tries to return JSON. (myob/managers.py line 92):

response.headers.get('content-type')
#=> application/json
response.json()
#=> *** simplejson.errors.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
response.content
#=> b''

The problem is the API, since it specifies the content as application/json yet returns invalid JSON. But maybe the package can handle this somehow?

oauthlib dependencies

Just came across this, took some time to track down. On one deployment our dependencies were:

pymyob==1.1
oauthlib==3.0.1
requests-oauthlib==1.2.0

With these versions, verifying credentials did not work (credentials.verify(code) returned {"error":"invalid_request"}.

On a working deployment, the versions were:

pymyob==1.1
oauthlib==2.1.0
requests-oauthlib==1.1.0

The difference between the two requests bodies for the access token were:

(updated versions)

Request body was grant_type=authorization_code&code=<code>&redirect_uri=<callback uri>

vs
(older versions)

grant_type=authorization_code&code=<code>&client_id=<id>&redirect_uri=<callback uri>&client_secret=<secret>

I didn't dig much further, so not sure if this issue is resolvable in pymob or only in those required packes.

Update flow to not require companyfile credentials passed.

Users with SSO enabled are sufficiently authenticated after they've logged in with their my.myob credentials. Going further and collecting companyfile username & password is superfluous.

  • Update Manager to not expect credentials to exist under companyfile_credentials.
  • Update readme - suggest dropdown to still be rendered in case user has multiple companyfiles against their account, but don't force username and password to be provided.

How does one use $top, $filter, etc. ?

As per MYOB API documentation:
https://developer.myob.com/api/myob-business-api/api-overview/retrieving-data

I can see they have methods such as $top, $filter, etc. and for the life of me I can see in the manager.py there is handling of these, but since you can't send them directly with the '$' due to kwargs not liking that in the key, how do you access these params to the API?

I tried documentation, nothing, I tried tests, nothing (other than 'data' or 'uid').

Please help with an example!

ORM-ify

  • Remove the need to pass company_id in to every single function. It should get set once at some higher level. Also, this doesn't align with the fact that the credentials for a chosen company file (userpass) are stored in the credentials object already. Maybes we just store company_id in there too?
  • Make methods more django-like (i.e. .all(), .filter(), etc). This may require a bit more sophistication in the layout of the endpoints.py file.
  • Consider parsing responses a little, to return objects rather than raw JSON (not that JSON is that horrible)

Using 'ge' (greater than) and 'le' (less than) in GET filter

Hi, I recently found out how to use the filter option in my GET functions and it's very helpful:

compfiles.quotes.item(Number='1234')

But I'm trying to use 'ge' and 'le' to filter by fields greater than or less than a value. It's talked about here. Something like:

compfiles.inventory.item(Price='ge 10.0')

to get items with prices > 10.0.

I cannot find any documentation on this or anything related to it in the code. Is this possible in pymyob?

Write documentation

Current documenation is limited to the README (and perhaps tests), which is enough to get started, but would be nice to offer a little more..

Accessing Nested Resources

Hey!

Not sure what people's opinions are here for implementing access to nested resources. One such example is the Spend Money Attachments: /{cf_uri}/Banking/SpendMoneyTxn/{Spend_Money_UID}/Attachment

The current implementation is fantastic and delightfully extensible for top-level resources, but doesn't make for easy implementation (at least to me) when querying nested resources.

Did anyone have any implementation ideas to get around this issue? I have one but it would involve a very large refactoring which isn't by any means ideal.

This idea would just centre around the below (using python-ish pseudocode)


MYOB_URL = "..."

def post<R>(url: str, body:R ): T
    return requests.post(url, body)
    
def get<T>(url: str) -> T:
    return requests.get(url)    


class SpendMoneyTxn:

    def get_attachments(self) -> SpendMoneyAttachment:
        return get(url=f"{MYOBURL}/Banking/SpendMoneyTxn/{self.id}/Atachment")
    

I am open to a way of trying to include the current managers but I'm not sure how that would look.

Thanks!

company_files

company_files = myob.companyfiles.all()

Not getting anything in this code.

Following the debug, I can see the data in raw_companyfiles, but nothing seems to get returned except for

[CompanyFile:
contacts
general_ledger
inventory
invoices
purchase_bills
purchase_orders]

In

/usr/local/lib/python3.6/site-packages/myob/api.py(39)all()
-> return [CompanyFile(raw_companyfile, self.credentials) for raw_companyfile in raw_companyfiles]
(Pdb) p raw_companyfiles
[{'Id': '377a1687-408c-4647-a390-1b4c2ea1ff9d', 'Name': 'API Sandbox Demo 46', 'LibraryPath': 'API Sandbox Demo 46', 'ProductVersion': '2018.2', 'ProductLevel': {'Code': 30, 'Name': 'Plus'}, 'CheckedOutDate': None, 'CheckedOutBy': None, 'Uri': 'https://ar1.api.myob.com/accountright/377a1687-408c-4647-a390-1b4c2ea1ff9d', 'Country': 'AU', 'LauncherId': 'fd2874bb-9113-4c7d-afa6-4adeffd9d395', 'SerialNumber': '611837501826'}]

...and later...

/usr/local/lib/python3.6/site-packages/myob/api.py(57)init()
-> self.credentials = credentials
(Pdb) p self.data
{'Id': '377a1687-408c-4647-a390-XXXXXXXX', 'Name': 'API Sandbox Demo 46', 'LibraryPath': 'API Sandbox Demo 46', 'ProductVersion': '2018.2', 'ProductLevel': {'Code': 30, 'Name': 'Plus'}, 'CheckedOutDate': None, 'CheckedOutBy': None, 'Uri': 'https://ar1.api.myob.com/accountright/377a1687-408c-4647-a390-XXXXXXX', 'Country': 'AU', 'LauncherId': 'fd2874bb-9113-4c7d-afa6-XXXXXXX', 'SerialNumber': '1234'}

And, alternatively, this works:

(Pdb) p myob.companyfiles._manager.all()
[{'Id': '377a1687-408c-4647-a390-XXXXXXXX', 'Name': 'API Sandbox Demo 46', 'LibraryPath': 'API Sandbox Demo 46', 'ProductVersion': '2018.2', 'ProductLevel': {'Code': 30, 'Name': 'Plus'}, 'CheckedOutDate': None, 'CheckedOutBy': None, 'Uri': 'https://ar1.api.myob.com/accountright/377a1687-408c-4647-a390-XXXXXXX', 'Country': 'AU', 'LauncherId': 'fd2874bb-9113-4c7d-afa6-XXXXXXX', 'SerialNumber': '1234'}]

Any thoughts?

SyntaxError: invalid syntax Exited with code 1

from myob.credentials import PartnerCredentials

File "/home/circleci/repo/venv/lib/python3.4/site-packages/myob/init.py", line 1, in
from .api import Myob # noqa
File "/home/circleci/repo/venv/lib/python3.4/site-packages/myob/api.py", line 2, in
from .managers import Manager
File "/home/circleci/repo/venv/lib/python3.4/site-packages/myob/managers.py", line 70
**request_kwargs_raw,

endpoint request

Addition to the endpoints.py:

'Sale/Order/': {
    'name': 'orders',
    'methods': [
        (ALL, '', 'order invoice type'),
        (CRUD, 'Item/', 'item type sales order'),
        (CRUD, 'Service/', 'service type sales order'),
    ]
},

Cheers

KeyError: 'There are no stored username-password credentials for this company id.'

After verification, I get this error while trying to get company files.
KeyError: 'There are no stored username-password credentials for this company id.'

stored_values = mycache.get('myob_creds')
credentials = PartnerCredentials(**stored_values)

print("=================== Myob Verify =======================")
print(stored_values)

print("====================1==================")
myob = Myob(credentials)
print(credentials)
print("====================2==================")
company_files = myob.companyfiles.all()
print(company_files)
print("====================2==================")

if len(company_files) > 0:
    print("====================3==================")
    comp = company_files[0]
    print("====================4==================")
    customers = comp.contacts.all()
    print("========== customers ================")
    print(customers)
    return (jsonify(company_files=company_files,customers=customers), 201)

print("========== Companies ================")
print(company_files)

I got error at here:
customers = comp.contacts.all()

company_files returns this:
[CompanyFile:
banking
company
contacts
general_ledger
inventory
invoices
orders
purchase_bills
purchase_orders]

Modernise pipeline

  • Move from setup.py -> setup.cfg (pyproject.toml is still a little too young)
  • setup.py test (deprecated) -> tox
  • Travis -> Github actions
    • [Bonus] Automatically publish when version number changes.

Simplify MYOB endpoints file.

There's an awful lot of repetition going on in this file.
Most endpoints follow this same pattern of 5 possible actions:

            (ALL, 'Item/', 'Return inventory items for an AccountRight company file.'),
            (GET, 'Item/[uid]/', 'Return selected inventory item.'),
            (PUT, 'Item/[uid]/', 'Update selected inventory items.'),
            (POST, 'Item/', 'Create new inventory item.'),
            (DELETE, 'Item/[uid]/', 'Delete selected inventory item.'),

Let's compress each of these into a single entry.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.