Skip to content
Hugo Correia edited this page Sep 10, 2013 · 44 revisions

Billy is a billing library for applications providing them with ability to create, manage, and store billing artifacts such as invoices and credit notes. It also supports the export of the persisted data in PDF and SAF-T formats.

Billy was built to be easily extended to support additional taxing systems for different countries. Billy's core module was based on the OECD's SAF-T schema, providing a standard module from which one can extend and further develop to support new modules for different legislation.

The objective is for all modules to be compliant with the existing regulations for their country/region. However, we do intend to provide a certified library. This should be the responsibility of any application that uses or will use Billy.

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>1.0-SNAPSHOT</version> <!-- UPDATE THIS -->
</dependency>

Check out sonatype repository for latest snapshots and releases.


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 run main() from PortugalBootstrap to bootstrap Billy.

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")
                  .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 it to the application:

applicationBuilder.addContact(contactBuilder)
                  .setMainContact(contactBuilder);

Creating 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 added to the invoice.

Creating a new Business

PTBusiness.Builder businessBuilder = billyPortugal.businesses().builder();
businessBuilder.addApplication(applicationBuilder) 
               .addContact(contactBuilder, true) 
               .setMainContactUID(contactBuilder.build().getUID())
               .setName("Business")
               .setCommercialName("Business, INC")
               .setFinancialID("500003564", "PT");

The business needs an address!

Creating a new address

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());

NOT DONE

.addPayment(paymentBuilder) // need to create a payment builder first

Builders as arguments

Some arguments of the invoice are other entities builders, example of this is the invoice entry. First get the builder:

PTInvoiceEntry.Builder entryBuilder = billyPortugal.invoices().entryBuilder();

Set the required fields:

entryBuilder.setAmountType(AmountType.WITH_TAX)
            .setCurrency(Currency.getInstance("EUR"))
            .setDescription(product.getDescription())
            .setProductUID(product.getUID())
            .setContextUID(billyPortugal.contexts().portugal().allRegions().getUID())
            .setQuantity("10")
            .setTaxPointDate(new Date())
            .setUnitAmount(AmountType.WITH_TAX, "100")
            .setUnitOfMeasure(product.getUnitOfMeasure());

Now we can add this entry to the invoice:

invoiceBuilder.addEntry(entryBuilder);

Previously persisted entities.

Some cases we need to build the new entity with with previously persisted entities, case of the business and customer fields of the invoice.

Let's create a new business. First we get the builder:

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

Populate it with required values:

businessBuilder.setCommercialName("Some Business, INC")
               // etc...
              .setName("Business");
businessBuilder.addApplication(application)
               .addContact(contactBuilder, true)
               .setAddress(addressBuilder)
               .setBillingAddress(addressBuilder)
               .setMainContactUID(contactBuilder.build().getUID())
               .setName("Business")
               .setCommercialName("Business, Inc")
               .setFinancialID("123456789", "PT");

Then just set the new invoice builder with the business UID(unique identifier).

invoiceBuilder.setBusinessUID(business.getUID());

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 paramaters = PTIssuingParams.Util.newInstance();

You can use the provided KeyGenerator to generate your keys.

KeyGenerator gen = new KeyGenerator("private/key/dir/pkey.pem");
invoiceParameters.setPrivateKey(gen.getPrivateKey());
invoiceParameters.setPublicKey(gen.getPublicKey());
invoiceParameters.setSeries("New Series");

Issuing the document

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

billyPortugal.invoices().issue(invoiceBuilder, paramaters);

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 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);

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:

InputStream xslInputStream = new FileInputStream("xsl/path/file.xsl");
PTInvoiceTemplateBundle templateBundle = new PTInvoiceTemplateBundle("logo/path/logo.png", xslInputStream,
                                                        "file/to/export.pdf", "Software Certification ID");

The TemplateBundle encapsulates the configuration details for your pdf.

Then you need to create a new PDFExportRequest with the issued invoices' UID:

billyPortugal.invoices().pdfExport(new PTInvoicePDFExportRequest(invoice.getUID(), templateBundle));
Clone this wiki locally