-
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 the customer to the new application:
applicationBuilder.addContact(contactBuilder)
.setMainContact(contactBuilder);
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.
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");
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);
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());
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("10")
.setTaxPointDate(new Date())
.setUnitAmount(AmountType.WITH_TAX, "100");
Again create and populate the product builder:
PTProduct.Builder productBuilder = billyPortugal.products().builder();
productBuilder.setDescription(description)
.setNumberCode("1")
.setProductCode("1")
.setType(ProductType.GOODS)
.setUnitOfMeasure("kg")
.addTaxUID(billyPortugal.taxes().continent().normal().getUID());
Pesiste the product:
PTProduct product = billyPortugal.products().persistence().create(product);
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);
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 simply 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'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);
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" ));