The Vendors and Account are two important data points for Invoice Processing. Instead of requiring manual entry/upload the Vendors' and Accounts' information by our clients, it is great feature if we can directly import those data from the system which our clients already used. The Xero is the first specific platform which we are looking a and integreting in this project.
This current version built the main frame of the system and implemented the importing functions below, therefore prepared and supports for furthing invoice process development.
- to provide web page to acquire the Xero access permission of the client
- to import the Organization from Xero (our client)
- to import the Vendors of the Organization from Xero
- to import the Accounts of the Organization from Xero
- To deploy the application on public site (e.g invoice.beanworks.com) following Microsoft ASP.Net Core Deployment
- To create a free Xero developer account if you don't have one yet.
- To create an app on Xero Developer site: https://developer.xero.com/myapps/
- To choose Public App to create
- To input any app name and url you want
- To click
Add an OAuth 1.0a callback domain
with the domain (e.g invoice.beanworks.com) which you deployed on step 1 If you testing in local, you can just typelocalhost
- To check the agreement and click
Create App
- You will see
OAuth 1.0a Credentials
after creating app successful. - To copy two fields
Consumer Key
andConsumer Key
underOAuth 1.0a Credentials
and replace corresponding ones inappsettings.json
in published folder in step 1. - To replace the host part of
CallbackUrl
inappsettings.json
by the domain you deployed in step 1 (e.g invoice.beanworks.com). - To simplify the first version, the database have been hard coded as Sqlite and file location
{published-folder}/Data/Invoice.sqlite
- After deployed as above, when you navigate to the application website,
you will see the home page, and click the big blue button
Connect to Xero
- You will be redirect to the Xero login page if you haven't logged in before
- To log in by your credential of free developer account or other account you have in Xero
- After logged in successful, you will see the xero page which the application require your authorization to access your Xero data.
- To choose the organization which you want import data and click
Allow access for 30 mins
- You will be redirected back to the application site, and see message
Authorization success
- To click
Import Vendors/Accounts
, will import Organization, Vendors, Accounts into database. - To check database on published folder
/Data/Invoice.sqlite
to see if the data imported or not
The system heavily used Dependency Inject to decouple and isolate modules/packages. The domain module is the core which included all business logic related concepts and defined all infrastructure functions with interfaces. Then all other modules are consider as implementations or providers of the core functions. That is called the Onion Architecture.
Also trying to avoid too many third party dependencies, the system still instroduce some of them in order to focus on our own business and write clean code.
- XeroApiSDK: although there is some design problem inside of XeroApiSDK, but considering quick starting, it is used to authenticate and retrive data from Xero. And it is isolated in module Invoice.Integration.Xero and can easy be replaced later.
- NHibernate/Fluent NHinberate: used for persistent, with fluent automapping features, it is almost zero coding on database at all.
- Automapper: used for Xero to Domain, Domain to Domain object mapping, reduced duplicated codes and provide flexibly, it is a must-have for the adapter pattern.
- Machine.Specification and NSubstitue(Mocking): although they are only for test projects but they are so helpful and make writing tests easier and enjoyful.
More detail see Development Instruction
There are mainly 4 modules(vs projects):
- Invoice (as a core domain module): it include domain models and interfaces which representing functions of integration and persistent.
- Invoice UI (as a presentation layer to accept input and render data)
- Invoice.Integration.Xero: implemented Integreation functions(interfaces in domain) by Xero Api SDK.
- Invoice.Persistent.NHibernate: implemented Persistent functions(interfaces in domain) by Fluent NHibernate Here is dependency relationship between modules: The Invoice is the core module which is independent while all other modules depend on it.
Domain modle itself is simple and clear, while diagram shows the Vendor and the Account reference the Organization, actually the Organization is their constructor's argument which means the Vendor the Account rely on the Orgnaization.
Extenal Repository (Xero) is using Repository and Query pattern as well.
The queries GetCurrentOrganization
, SearchVendorsInOrganization
and SearchAccountsInOrganization
are abstrction queries
which implemented by Xero* ones calling XeroApiSDK finally, they can also be implemented without XeroApiSDK e.g. directly REST calling,
even implemented by other party platform than Xero at all.
- To clone source code from github: git clone https://github.com/SkightTeam/BW.Invoice.git
- To open the Invoice.sln in Visual Studio 2017 or later
- To set Inovice.UI as start up project if it is not yet.
- To complie and run from local and then follow the application guide.
This project used a different naming convention than "standard" C#
- Removed
I
prefix in interface naming to make clean and meaningful codes - Added
Impl
to the class of the interface if only a single implementation or specific provider name for multiple implementations.
- .Net Core 2.1
- Xero.Api.Core
- Automapper 8.0.0
- NHibernate 5.1.1 / Fluent NHibernate 2.1.2
- Machine.Specifications 0.12.0
- Machine.Specifications.Should 0.11.0
- Machine.Specifications.Runner.VisualStudio 2.8.0
- Machine.Specifications.Fakes 2.10.0
- Machine.Specifications.Fakes.NSubstitute 2.10.0
Also need install Resharper extension if want to run test from Resharper: machine.specifications.runner.resharper
The purpose of the first version is to set up main framework, so not wrote too many unit tests to cover all codes/paths. But the DI helped isolated pieces of code, that maked it easier to fullfill unit tests later
The two classes have lots duplicated code, which came from Xero.Api two base authenticators design. It can be improved by rewrite Xero.Api authenticators's code.
The UserID has been passed through XeroCoreApi down to XeroHttpClient, and finally used to look up token in Token Store. The whole process is complicated and hidden behavior. Need improve by rework on XeroApi itself.
The database configuration have been hard coded as Sqlite and Data/invoice.sqlite
for first version.
It can be easy to improve later
Haven't handled the duplicated record by check local repository if it existed before,
that is catched by TODO
in import service.
For sake of short time, the display imported the organizations, vendors and accounts are not impplemented yet. It will invovle define the abstract query object/interface and create NHibernate's implementations which is pretty straightforward.
The transaction has not include in the implementation. "# BW.Invoice"