Bootstrap Invoice Builder

Bootstrap Invoice Builder

This post is an ongoing article and demonstration of my abilities as I go to production using this application for my own invoicing purposes.   The basics of the project were to create all of the development as rapidly as possible, use the least amount of code, documentation, or spec, and get the system working cleanly.   This project also includes taking the application to production using dockers amazing deployment & automation abilities.  Bootstrap Invoice Builder is online now with the following:

  1.  hosted dev Lamp Stack
  2. a github repo
  3. a staging Ubuntu 14 w. nginx
  4. docker
  5. digital ocean deploy node
  6. a free docker hub repository
  7. a free docker application

GitHub Repo:

Docker Hub Repo:


If you are brave enough, continue to read on…..


[1] I spent a bit of time working with the Bootstrap Invoice Template and created the start of this app.  So far I have setup the app url, created an invoices and invoices_items database table, setup the default query to get the next invoice #, adjusted the view html to have form inputs, added Save, See, and Send buttons, setup the See and Send Modal, and finally setup the SEE buttons invoice_view.   Next steps are to make save work, make add work, build post data handling, and last but not least work on the Send action.

[ insert 2 teen taxi trips to highschool and back]

[2] I was able to sit down and start to write code for posting the Save button with some of the main invoice information.  I also created some .htaccess to route /invoice/1003/ back to Invoice Number 1003 while showing this invoice in an editable manner within the invoice template.  For form post data handling I created a function to compare post keys with allowed columns with the values escaped.  I then had to do some logical work to see if the invoice was new (inserting) or existing (updating) and build the mysql query accordingly.  I will need to come back and do some client side form field validation, more post sanitation on the server side, and maybe some kind of wysiwig editor for the content blocks.    I also intend to do some security improvements to ensure that only the builder’s IP address sees the editable bootstrap invoice template.   While someone else who views the invoice, needs to only see the finished view of  the bootstrap invoice template.

Now that the meat of the invoice is saveable I can focus on Add button for adding invoice items.

[3] This morning I spent the time necessary to make the ADD item button operational, get the added items coming out of the database, and make the X (delete item) action.  I was very happy that all the work I did for the See button and invoice view worked properly once item data was in the database.   I made a few adjustments to the post data handling to satisfy adding a new item.  I still need to build post data handling for editing existing inventory item(s).

[4] 10.11.2016 – Added ability to edit invoice number.  Did some research into how I can format the email with bootstrap styles or at least get something close as a shorted invoice, with a link to the online full invoice.  It was not that easy to get this whole view of code into the email.  More on this later.

[5] 10.14.2016 –  I have finished a basic SEND action to deliver the message with a link to the invoice.   Adjusted the insert to include the ip address.  When the invoice link is used, and the IP address is not the owner, the url will seamlessly include the view and no form control.

[6]12.14.2016 –  I have been busy elsewhere.  Today I got time to go through re-testing. I made a few adjustments as well as finished editing the items names after they are added.  I also spent some time designing the settings modal and figuring out the database needs for settings and invoice automation.

[7] 01.06.2016 – Yesterday I turned off WHMCS billing.  NO more billing software.  I only have one invoice I have to make monthly, so I must finish the Boostrap Invoice Builder application.    My plan for today is:

  1. Make an invoice.
  2. Finish all the automation settings.
  3. prepare to send first test invoice 1.20.2017

Things i need to accomplish:   jquery date time picker, settings database, image uploader, automation script.    At end of sitting,  settings modal is fully operational to insert and save image.  Need to handle pre-loading the modal with current settings.   Did not start automation script.

[8] 01.09.2017 – This morning I started an invoice and made the necessary improvements to display the Invoice Settings; company name, link, logo, and prefill settings modal based on values stored in the database.   For some reason the ajax upload was not passing the new hidden logo value and was storing the local c:/ path to the file in the database.  The ajax call did parse the image html so not sure why the hidden tag html was not available for jquery to get the remote file url.    I found a way around and I can now start to focus on the automation script.   I want this job to run every morning at 5am, check for any invoices needing automated today.  When a result exists, the original invoice will be delivered.  If the invoice is repeated it will be duplicated for the next interval.   I also took time to add an invoices_sent table to record when each invoice is sent.  Will need to back track the insert for u/i triggered sends.

I was able to get the automation to send a invoice started today very fast.  I then went to work to duplicate the invoice.  Everything here went very well too, was able to write a function duplicateInvoice to copy the invoice, copy its items, and copy its settings.  Now i need to increment the new invoices start date.   I ran into a problem here with Invoice Number.  This is something the user can type, or change from the actual invoice ID.  If this is a #, incrementing it will be no problem.  If Invoice Number is a true string (Inv # DS100345),  then incrementing it will be impossible without doing STRING-1 STRING-2, etc (Inv # DS100345-1, DS100345-2)  or STRING-ID or some other nonesense.  This doesnt really make sense either if a user is expecting  DS100346 and  DS100347…  The logic for this will be dealt with later, and for now will make Invoice Number an actual # as part of the validation requirements.

At end of my sitting, I have executed automation for a monthly invoice started today, 5 times, making 5 duplicates.  I then manually updated the start date on all of the duplicates for next 5 days (1-9 / 1/14)  If everything goes will I will have a new invoice email everyday this week, and 5 new invoices ready for automation in one month.

Day 9 – 1/10/2017:          .5 hrs

Today is a light day for this project.  I started out testing cron.php making sure it operated. I ran the automation and got my email at gmail as expected. I then turned the automation on starting tomorrow morning.  I then went to test the link from my iphone (different ip) to ensure the recipient gets a good invoice.  Everything is NOT editable, and the layout looks pretty good in my phone browser too.  I really need a way to get the invoice in the email now….

Day 10 – 1/11/2017:          1.5 hrs

This morning my automated invoice arrived as expected.  The Invoice Number came linked as 23 but it sent the correct invoice ID (26).  When I copied the invoices I did not change the number.    I adjusted the test data to have more relevant and different Invoice Numbers.  For tomorrow the next invoice ID (27) should arrive with invoice number 2700, and create next Invoice Number for next month as 2701.   After that I added the u/i input validation (required text fields, require Invoice Number to be a number, require Quantity, and Price to be a number.  Requiring Invoice # to be a number allows me to avoid STRING issues above by input design.  I then adjusted the settings API to return the ID (for new settings) and the logo html source.  Assuming the settings have changed the company name, link, or logo,  clicking the save button will now update the logo on the main invoice screen, and the See Invoice modal.   No page reloading required to see those changes.

Day 11 – 1/16/2017:          1.0 hrs

Today I decided to adjust the email automation so that a PDF copy of the invoice is delivered versus a link to the invoice.     I tried out a few online apis to do this, but eventually fell back on a free php class ( that will take a url and convert to local PDF.  I then needed to adjust the automation to attach the pdf to the email.   I used phpMailer to do that and quickly had pdfs in my inbox.   Next I wiped out all the testing invoices and setup my first real invoice.   I quickly realized that I needed to add a due date before this invoice could be sent so I added that to the database, u/i, javascript, validation, and posting handling.  I then adjusted the automation to increment the due date.

Day 12 – 1/17/2017:          .25 hrs

Today I set the first real invoice to run on friday.  I then adjusted the cron so it would send an internal copy of that message for my records.

Day 13 – 1/19/2017:          4+ hrs

Yesterday evening I got off into playing with docker.  Today I totally started dockerizing the Bootstrap Invoice Builder application.  This takes the repository in a bit of a different direction.  I go into a further detail about moving the project from LAMP to Ubuntu and Nginx, and getting started deploying with docker in a separate post.  You can see the Docker post here:

Docker Docker Docker

Once I am done with the work for deploying the application dynamically,  I will repost again here.  At that time I will I move my live invoice from the current implementation (now defunk in the repo lifecycle).  This docker was a major fork in the road.  For the sake of learning docker,  this application was a perfect to convert from traditional methods of deploying a website.

Day 14 – 1/20/2017:

Today was a long morning of working with the repo and docker setups.  Although my test build was completing, it would not start as a service.  By lunch I am now working on a php5 dockerfile as docker will only deploy to ubuntu 14.04 nodes.   In the name of eliminating variables I am going to do the work to adjust mysqli_ back to php5, testing the application on ubuntu 14.04.5, and hopefully have better luck in docker.  With 3 different ubuntu-14 builds I was able to get the application hosted and working with 11 shell commands, 5 of which should not be needed for docker (ssh-keygen, apt-get install git, git clone, and restarting nginx and php5-fpm).

So once I have the ubuntu-14 build and app working i check the docker build and cant find “php5-fpm”.  This is nice..  docker build works fine with php 7.0 in latest build but wont deploy because could not install php7.  I guess I need to change my Dockerfile’s “ubuntu:latest”  to “ubuntu:trusty”.

Day 15 – 1/24/2017:          .5 hrs  then < 1 hrs

With the change in direction for docker last week,  I did NOT get my real invoice delivered on 1.20.2017.   I needed that to happen today so I spent some time working with the repo on the original dev stack.   I just had to make 2 slight commits adjusting paths so that everything is relative to the $path and $url variables in the config file.    In order to keep my dev stack working,  I had to make some local adjustments to the config file that did not get pushed to the repo.   I need to handle the config security part very soon.

So after lunch I went to work on my ubuntu-14 build to improve my dockerfile and the repository so that the config file no longer has login credentials.  My task is make a call to  If the call is expected, I will send a notification back to myself, log the request, return the values for:


$host = “db host”;

$user = “db user”;

$pass = “db pass”;

$db = “db table”;,

and save them to a local file which can then be used within the application.    For testing the full application to deploy I have the api returning the necessary file output, and have tested that to work on the local system.   I am now going to make that commit and hopefully we can deploy out to the final production docker node without any errors.   Once this works I will further improve the /api/auth/ for all of its logic.   I also took a moment to change my mysql user password as it has been public part of the repo during the docker discovery.

After 4 commits my repo is updated and my docker application successfully launched.  I am now going to go work on the /api/auth/ which fortunately for me is not blog material or part of this post.  Later!!


Day 16: 2/23/2017:      < 1 hr

I finally got off cpanel in the last 30 days so the invoice builder was moved to a digital ocean slice. Although the app was operating on the new ip,  it was not automating.  I did some work to get my automation working and mostly had some path changes and permissions issues.  It should be ready to cron again for next month.


Day 17: 3/21/2017:  < 1 hr

Today I needed to run my automation.  When I did it, re-automated past automated invoices, re-sent 2 manually created invoices, and properly sent current due, and made the most newest invoice.   To fix the re-automation, i slightly adjusted the cron so that after an invoice is automated and sent, that its parent setting is marked automate false.   It has already created its next child invoice, so its okay to un automate the parent.   I then adjusted the automation query so it will never pick up invoices that are not automated.

I am happy to report that docker properly deployed with all commits during the work here.  Having the LAMP stack back in order of the repo is good too.

Day 18: 2/16/2018:  < 1 hr

Today I needed to make an invoice.  Thankfully I have this system to use.   I had a few issues, but was able to get an invoice created and sent pretty quickly.  Those issues are:

1.  SSL (this is still “sceneserver”, so want to pull it out to its own url + https)
2.  issue with url not having ending slash
3.  Change URL to invoice # url on save
4.  Start Date, when empty breaks setting modal on Save:
Error in query: INSERT INTO `invoices_settings`(`invoiceid`,`company`,`logo`,`link`,`repeat`,`interval`,`start`) VALUES (72,’Steven Matison’,’logo.png’,’’,0,’None’,”). Incorrect date value: ” for column ‘start’ at row 1
5.  It is possible to hit send button twice,  hide button after clicking it

I intend to continue improving this application in 2018 so hopefully can get the above items sorted and some of the ideas I didn’t finish from last year.



Things to do:

  1. User and Invoice Ownership
    1. cookie, user login/register, lost password system
  2. Invoice Settings Modal
    1. Need to adjust Save event to only post changed values.
    2. Need to adjust Api Save event to only update what is posted.  (currently full insert/update statement)
  3. Add X buttons to hide footer sections from displaying in the invoice.  If only one section remains it should go full width.
  4. Add “tax” on/off and “tax_amount” to invoice settings.
  5. Invoice SubTotal, Tax, Total in database as 0.00

Future Wants:

  1. Create payment methods.
  2. Implement third party mail delivery.
  3. WYSIWIG content block editor.