Billy is an open source Java library developed by Premium Minds. Billy's aim is to be a billing library for applications providing them with ability to create, manage, store and export billing related artifacts such as invoices and credit notes. Billy supports the creation and exportation of SAF-T PT files (Standard Audit File for Tax - portuguese version).
Billy is currently at version 6, and is now available to the open source community.

Get Billy

You can obtain Billy by downloading the latest release or by cloning the latest sources from GitHub

Maven projects

Add the following maven dependency to your project pom.xml:

<dependency>
    <groupId>com.premiumminds</groupId>
    <artifactId>billy-portugal</artifactId>
    <version>9.5.0</version>
</dependency>
Check out sonatype repository for latest snapshots and releases.

Some dependencies are in provided scope, so you have to add them to your project

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.6.11.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-envers</artifactId>
    <version>5.6.11.Final</version>
</dependency>
<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-jpa</artifactId>
    <version>5.0.0</version>
</dependency>

Bootstrap Billy

Bootstrap incorporates entities that are essential for any application using Billy, for instance, the billy-portugal bootstrap provides you with all the contexts and taxes available for Portuguese legislation, providing an easy and quick start for new applications using Billy. Just runmain() from PortugalBootstrap to bootstrap Billy.

Demomonstration Application

There is a demomonstration project in how to use billy at github.com/premium-minds/billy-demo-app.


Get Started Guide

This guide combines an overview of Billy with a quick tutorial that helps you to get started. We'll follow the process of creating and issuing an invoice and then export it to PDF and to SAF-T(PT) xml format.

Initiating Billy

Start by creating a new instance of Billy:

BillyPortugal billyPortugal = new BillyPortugal();
This provides access to builders, issuing services, persistence services and export services for each available entity in Billy.

Creating the new application

First obtain the application builder:

PTApplication.Builder applicationBuilder = billyPortugal.applications().builder();
Populate it with the application's information:
applicationBuilder.setDeveloperCompanyName("Premium Minds")
    .setDeveloperCompanyTaxIdentifier("12345789","PT")
    .setSoftwareCertificationNumber(123)
    .setName("Billy")
    .setVersion("1.0")
    .setApplicationKeysPath(new URL("http://www.keys.path"));
Each application will need to have at least one contact, so we'll start by creating it.

Create a new contact

Obtain the builder and fill it with the required values:

PTContact.Builder contactBuilder = billyPortugal.contacts().builder();
contactBuilder.setName("Bob Conner")
              .setTelephone("219211231");
Now you can add the customer to the new application:
applicationBuilder.addContact(contactBuilder)
                  .setMainContact(contactBuilder);

And finally persist the application builder to Billy's database

PTApplication application = billyPortugal.applications().persistence().create(applicationBuilder);

Creating a new invoice

Billy's main focus is to manage invoices, so to create a new invoice, we'll start by getting the appropriate builder:

PTInvoice.Builder invoiceBuilder = billyPortugal.invoices().builder();
Lets define the simple parameters of the invoice:
invoiceBuilder.setSelfBilled(false)
              .setCancelled(false)
              .setBilled(false)
              .setDate(new Date())
              .setSourceId("Source ID")
              .setSourceBilling(SourceBilling.P);
Naturally, an invoice requires a business and a customer. These entities need to be first persisted and then their UID is set in the invoice.

Creating a new Business

As always we first obtain the builder and populated with the required values:

PTBusiness.Builder businessBuilder = billyPortugal.businesses().builder();

businessBuilder.addApplication(applicationBuilder)
               .addContact(contactBuilder, true)
               .setMainContactUID(contactBuilder.build().getUID())
               .setName("Business")
               .setCommercialName("Business, INC")
               .setFinancialID("500003564", "PT");

Creating a new address

You'll notice that the new business requires an address builder!

PTAddress.Builder addressBuilder = billyPortugal.addresses().builder();

addressBuilder.setStreetName("Av. 5 de Outubro")
              .setNumber("2")
              .setPostalCode("1000-100")
              .setCity("Lisbon")
              .setISOCountry("Portugal")
              .setDetails("Av. 5 de Outubro NÂș 2 1000-100 Lisboa");

Add the new address to the business

businessBuilder.setAddress(addressBuilder)
               .setBillingAddress(addressBuilder);
After populating the businessBuilder we can persist it in Billy's database:
PTBusiness business = billyPortugal.businesses().persistence().create(businessBuilder);

Create a new Customer

The process of creating a new customer is similar to creating a business:

PTCustomer.Builder customerBuilder = billyPortugal.customers().builder();
For the sake of simplicity, we'll reuse the previously defined addressBuilder and contactBuilder used in the business creation:
customerBuilder.setName("John Conner")
               .setTaxRegistrationNumber("123456789", "PT")
               .addAddress(addressBuilder, true)
               .setBillingAddress(addressBuilder)
               .setShippingAddress(addressBuilder)
               .setHasSelfBillingAgreement(false)
               .addContact(contactBuilder);
Now we can persist it in Billy's database:
PTCustomer customer = billyPortugal.customers().persistence().create(customerBuilder);
After creating and persisting the customer and the business in the database, we must add them to the invoice:
invoiceBuilder.setBusinessUID(business.getUID())
              .setCustomerUID(customer.getUID());

Creating new Invoice Entries

An invoice has one or more entries. Each entry has all information about the good/product such as price, currency, description, etc. To create a new entry we first first obtain the builder:

PTInvoiceEntry.Builder entryBuilder = billyPortugal.invoices().entryBuilder();
Set the required fields:
entryBuilder.setAmountType(AmountType.WITH_TAX)
                    .setCurrency(Currency.getInstance("EUR"))
                    .setContextUID(billyPortugal.contexts().portugal().allRegions().getUID())
                    .setQuantity(new BigDecimal("10"))
                    .setTaxPointDate(new Date())
                    .setUnitAmount(AmountType.WITH_TAX, new BigDecimal("100"));

Creating a new Product

Again create and populate the product builder:

PTProduct.Builder productBuilder = billyPortugal.products().builder();

productBuilder.setDescription("description 1")
              .setNumberCode("1")
              .setProductCode("1")
              .setType(ProductType.GOODS)
              .setUnitOfMeasure("kg")
              .addTaxUID(billyPortugal.taxes().continent().normal().getUID());
Persiste the product:
PTProduct product = billyPortugal.products().persistence().create(productBuilder);
Now add the product to the invoice entry:
entryBuilder.setProductUID(product.getUID())
            .setDescription(product.getDescription())
            .setUnitOfMeasure(product.getUnitOfMeasure());
We can then add this entry to the invoice:
invoiceBuilder.addEntry(entryBuilder);

Issuing Service

To issue the new invoice you'll need to provide the issuing parameters.

Invoice parameters

This encapsulates the needed parameters to issue your invoice, such as PrivateKey, PublicKey, Series, etc.

PTIssuingParams invoiceParameters = PTIssuingParams.Util.newInstance();
You can use the provided KeyGenerator to generate your keys.
URL privateKey = getClass().getResource("private/key/dir/pkey.pem");
KeyGenerator gen = new KeyGenerator(privateKey);

invoiceParameters.setPrivateKey(gen.getPrivateKey());
invoiceParameters.setPublicKey(gen.getPublicKey());
invoiceParameters.setInvoiceSeries("New Series");

Issuing the document

After defining the all the parameters you simply issue the document:

PTInvoice invoice = billyPortugal.invoices().issue(invoiceBuilder, invoiceParameters);

SAFT-T export service

You can export the SAF-T(PT) xml file containing all the billing information for an application and a business during a given period. You'll need to specify the application's and the business's UID, the certificate number for the SAF-T(PT) file and the period of time that you wish to export.

// one month period
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
Date startDate = dateFormat.parse("01-01-2013");
Date endDate = dateFormat.parse("01-02-2013");

billyPortugal.saft().export(application.getUID(), business.getUID(),
        "Certification Number", startDate, endDate, PTSAFTFileGenerator.SAFTVersion.CURRENT);

Export invoice to PDF

You can export a previously issued invoice to pdf format. First you'll need to create a new instance of a TemplateBundle for an invoice. The TemplateBundle encapsulates the configuration details for your pdf:

InputStream xslInputStream = new FileInputStream("xsl/path/file.xsl");
PTInvoiceTemplateBundle templateBundle = new PTInvoiceTemplateBundle("logo/path/logo.png", xslInputStream,
"Software Certification ID");
Then you need to create a new PDFExportRequest with the issued invoice UID, the TemplateBundle and where you want to export the new pdf to:
billyPortugal.invoices().pdfExport(
     new PTInvoicePDFExportRequest(invoice.getUID(), templateBundle, "path/to/export.pdf" ));