-
Notifications
You must be signed in to change notification settings - Fork 16
Home
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.
You can obtain Billy by downloading the latest release or by cloning the latest sources from GitHub
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 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.
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.
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.
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.
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);
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.
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!
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);
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());
.addPayment(paymentBuilder) // need to create a payment builder first
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);
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());
To issue the new invoice you'll need to provide the issuing 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");
After defining the all the parameters you simple issue the document:
billyPortugal.invoices().issue(invoiceBuilder, paramaters);
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);
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));