Here is another post on App creation using Hypi’s low code API!
In the previous post, we quickly built up a Customer Support Model App clone. Now we will accelerate to building Invoice Creation App (Your own Quickbooks clone)!
We will create a Customer Account Information System and create an Invoice for sale of products or services. At last, we will send the Invoice to the customer’s email address.
So, here are the features of Quickbooks clone app:
- Store Customer Information
- Store Product / Service Sale information
- Create Orders and calculate Bill amount
- Store Invoice details
- Send Invoice to customer’s Email Address
Here is your sample schema for the Invoice Creation App
A) Customer data type stores Customer Information. In-built data type Account from core tables stores the customer details.
B) Product data type stores the sale details of each product or service to a customer.
C) Invoice data type stores the Invoice details.
D) Enum Terms
has values for the term of the bill payment. (15/30/60 days or due on receipt)
type Customer {
account: Account
company: String
taxRegistrationNo: String
}
enum Terms {
NET15
NET30
NET60
DUEONRECEIPT
}
type Invoice {
customer: Customer
terms: Terms
invoiceDate: DateTime
dueDate: DateTime
invoiceNo: Int
supplyPlace: String
product:[Product]
total: Float
message: String
attachment: File
}
type Product {
name: String
description: String
quantity: Int
rate: Float
amount: Float
tax: Float
total: Float
customer: Customer
username: String
}
Create an Invoice Creation App
on Hypi’s low code platform. Create a release and an instance. Enter the above schema in the release.
Now, let’s implement the following use cases in the Invoice Creation App.
=============================================================
A) Store Customer Information
i) Create Customer Objects to store customer information. Use this guide on how to insert data in an instance. .
You may write your own User defined function to create objects or use the variables method of Object creation as shown below.
mutation Upsert($values: HypiUpsertInputUnion!) {
upsert(values: $values) {
id
}
}
#input
{
"values": {
"Customer": [
{
"account": {"hypi":{"id": "01FP05XKXM2R5V5WYWBPKV96YH"}},
"company": "Tink",
"taxRegistrationNo": "ABC12345678"
}
]
}
}
#result
{
"data": {
"upsert": [
{
"id": "01FP06RY86KMV4VQN8JD0RD9V3"
}
]
}
}
=============================================================
B) Store Product / Service Sale information
Let’s say you have sold a product/service to a customer. So you should store the details in a Product object. (The details of the Product, how much quantity sold, what is the rate, what is the tax on the sale and to whom the product is sold etc.)
Let’s create Product Objects…
mutation Upsert($values: HypiUpsertInputUnion!) {
upsert(values: $values) {
id
}
}
#input A
{
"values": {
"Product": [
{
"name": "Hypi",
"description": "Low Code Backend",
"quantity": 2,
"rate": 150,
"tax": 10,
"customer": {"hypi":{"id": "01FP06RY86KMV4VQN8JD0RD9V3"}}
}
]
}
}
#result
{
"data": {
"upsert": [
{
"id": "01FP07MS88YFP54FMTT85SEXFJ"
}
]
}
}
#input B
{
"values": {
"Product": [
{
"name": "Hypi Tink",
"description": "No Code",
"quantity": 1,
"rate": 200,
"tax": 15,
"customer": {"hypi":{"id": "01FP06RY86KMV4VQN8JD0RD9V3"}}
}
]
}
}
#result
{
"data": {
"upsert": [
{
"id": "01FP07RQ96K56863Q9TPJTYQ4H"
}
]
}
}
==============================================================
C) Calculate Bill amount of the Orders of each Product
Customers may buy different products or services with varying rates. So, we will write a user defined function to calculate subtotal for the sale of each product to a particular customer.
Edit schema and write below User Defined Function under the Mutation data type. Below function multiplies rate with the quantity. It is assumed that tax was stored in terms of percentages. So the function calculates the tax amount and adds it to the result of previous multiplication. It also stores the subtotal in the Product data type.
type Mutation {
calculateAmount(a: ID):Json @tan(type:Groovy, inline: """
def rate = gql(\"""{get(type:Product,id:"$a"){...on Product{rate}}}\""").data.get.rate
def quantity = gql(\"""{get(type: Product,id:"$a"){...on Product {quantity}}}\""").data.get.quantity
float subtotal = (float)rate * (float)quantity
def tax = gql(\"""{get(type: Product,id:"$a"){...on Product {tax}}}\""").data.get.tax
def taxAmount = (float)subtotal * (float)tax / 100
def user = gql(\"""{get(type:Product,id:"$a"){...on Product{customer{account{username}}}}}\""").data.get.customer.account.username
subtotal = subtotal + taxAmount
return upsert([
Product: [
amount: subtotal,
username: user,
hypi:
[
id: a
]
]
]
)
""")
#sample query :
mutation {
calculateAmount(a: "01FP07MS88YFP54FMTT85SEXFJ")
}
mutation {
calculateAmount(a: "01FP07RQ96K56863Q9TPJTYQ4H")
}
================================================================
D) Store Invoice details
i) Create an Invoice object. Pass on the values as variables or create User Defined Function.
{
"values": {
"Invoice": [
{
"customer": {"hypi":{"id": "01FP06RY86KMV4VQN8JD0RD9V3"}},
"terms": "DUEONRECEIPT",
"invoiceDate": "2021-12-03",
"dueDate":"2022-01-01",
"invoiceNo": 12323,
"supplyPlace": "Mumbai",
"message": "This is an invoice from Hypi",
"product": [
{"hypi": {"id": "01FP07MS88YFP54FMTT85SEXFJ"}},
{"hypi": {"id": "01FP07RQ96K56863Q9TPJTYQ4H"}}
]
}
]
}
}
{
"data": {
"upsert": [
{
"id": "01FP0FRR5R4G1VVVDER89AQKDE"
}
]
}
}
ii) Calculate Invoice Total.
Calculate the Invoice Total amount by aggregating the subtotal amount of each product sold. calculateInvoiceTotal
calculates the sum total by using aggregation API and stores the total amount in the Invoice object (created in the previous step)
calculateInvoiceTotal(a:ID):Json @tan(type:Groovy, inline: """
def user = gql(\"""{get(type:Invoice,id:"$a"){...on Invoice{customer{account{username}}}}}\""").data.get.customer.account.username
def sumAmount = gql(\"""{
aggregate {
product(where: "username='$user'") {
amount {
sum
}
}
}
}\""").data.aggregate.product.amount.sum
return upsert([
Invoice: [
total: sumAmount,
hypi:
[
id: a
]
]
]
)
""")
}
#Sample Query:
mutation {
calculateInvoiceTotal(a: "01FP0FRR5R4G1VVVDER89AQKDE")
}
Here are the Final Invoice details retrieved using find function.
{
"data": {
"find": {
"edges": [
{
"cursor": "01FP0FRR5R4G1VVVDER89AQKDE",
"node": {
"hypi": {
"id": "01FP0FRR5R4G1VVVDER89AQKDE",
"created": "2021-12-03T15:49:23Z"
},
"customer": {
"account": {
"username": "[email protected]",
"emails": [
{
"value": "[email protected]"
}
],
"owner": {
"addresses": [
{
"street": "17",
"town": "Pasir Ris",
"city": "Singapore",
"country": {
"name": "Singapore"
},
"postCode": "123456"
}
]
}
}
},
"product": [
{
"name": "Hypi",
"description": "Low Code Backend",
"quantity": 2,
"rate": 150,
"tax": 10,
"amount": 330
},
{
"name": "Hypi Tink",
"description": "No Code",
"quantity": 1,
"rate": 200,
"tax": 15,
"amount": 230
}
],
"terms": "DUEONRECEIPT",
"invoiceDate": "2021-12-03T00:00:00Z",
"dueDate": "2022-01-01T00:00:00Z",
"invoiceNo": 12323,
"supplyPlace": "Mumbai",
"total": 560,
"message": "This is an invoice from Hypi"
}
}
]
}
}
}
===============================================================
E) Send Invoice to customer Email Address
Invoice details stored on the Hypi’s low code backend can be retrieved using the find/get function. Frontend can do the job of creating a pdf/doc file out of those details. This file can be sent as an email attachment to the customer.
Let’s see how to send the email using Hypi’s serverless function!
We can use Mailgun service to send the emails programmatically.
****Please note you need to sign up for MailGun Services to send emails.
i) Create an OpenWhisk action using below JavaScript code. Invoke the action and configure the Hypi’s serverless function to send the Email.
require('mailgun-js');
function main(args) {
return new Promise(function (resolve, reject) {
//Your api key, from Mailgun's Control Panel
var api_key = 'c2e4684382525364004c8d7e425722f8-64574a68-2bfc27ed';
//Your domain, from the Mailgun Control Panel
var domain = 'sandbox610e68e5b1884eaaa6f85026860b0a6b.mailgun.org';
//Your sending email address
var from_who = 'Your_Email_ID';
// Store the invoice file in the current directory
var path = require("path");
var fp = path.join(__dirname, 'invoice.txt');
var mailgun = require('mailgun-js')({ apiKey: api_key, domain: domain });
var data = {
from: from_who,
to: args.toid,
subject: 'Confirmation email',
text: "You've got an Invoice from Hypi!",
attachment: fp
};
mailgun.messages().send(data, function (error, body) {
console.log(body);
});
var result = 1;
resolve({ result: 'Success' });
});
}
exports.main = main
Put the above code into a file called index.js
. Then in the same directory run following command to create node_modules directory
npm install mailgun-js -g --prefix ./mailgun/node_modules
Add them to a zip file. Invoice.txt
is the invoice file to be sent as an attachment.
zip -r action.zip index.js node_modules invoice.txt
Now, create the action using the zip file.
>wsk action create emailconfirm --kind nodejs:12 action.zip
ok: created action emailconfirm
>wsk action invoke emailconfirm --param toid [email protected] --result
{
"result": "Success"
}
Use the OpenWhisk Action in Hypi’s Serverless function.
#schema
type Query {
sendConfirmationEmail(toid: String): Json @tan(type:OpenWhisk, name:"emailconfirm")
}
#query
{
sendConfirmationEmail(toid:"[email protected]")
}
#result
{
"data": {
"sendConfirmationEmail": {
"result": "Success"
}
}
}
This way you can build your own Invoice Creation App using Hypi’s low code APIs.
You may explore further to develop your own bookkeeping use cases (Like Quickbooks!)
Hypi is happy to help with the implementation!