You need to do three steps: Upload static resource Create Apex Class + Test class Create Visualforce page
Upload the following static resource with the name ‘invoice’ classClass Ctrl_InvoiceLayout : Code Block |
---|
public with sharing class Ctrl_InvoiceLayout {
private Subscription25__Invoice__c invoice;
public InvoiceItem[] items {get; private set;}
public Id companyLogoId {get; private set;}
public Decimal sum {get; private set;}
public Decimal total {get; private set;}
public Decimal taxAmount {get; private set;}
public Boolean hasICP {get; private set;}
public Ctrl_InvoiceLayout(ApexPages.StandardController stdController) {
this.invoice = (Subscription25__Invoice__c)stdController.getRecord();
List<Order> orders = this.getOrders();
this.items = new InvoiceItem[]{};
this.hasICP = false;
for (Order order : orders) {
for (OrderItem item : order.OrderItems) {
this.items.add(new InvoiceItem(item));
this.hasICP = this.hasICP || item.Subscription25__Use_ICP__c;
}
}
this.taxAmount = 0;
this.sum = 0;
for (InvoiceItem item : this.items) {
this.sum += item.price * item.quantity;
this.taxAmount += item.price * item.quantity * item.tax / 100;
}
this.sum = Ctrl_InvoiceLayout.format(this.sum);
this.taxAmount = Ctrl_InvoiceLayout.format(this.taxAmount);
this.total = Ctrl_InvoiceLayout.format(this.sum + this.taxAmount);
//try to load an attachment of the administration that starts with logo, if present, use that as a logo, otherwise, fall back
//to the company logo as defined in the custom setting
List<Attachment> atts = this.getAttachments();
this.companyLogoId = atts.size() > 0 ? atts.get(0).Id : Ctrl_InvoiceLayout.getSubscription25LogoIdgetLogoId();
}
private List<Attachment> getAttachments() {
Id adminId = this.invoice.Subscription25__Administration__c;
String query = 'SELECT Name FROM Attachment WHERE ParentId = :adminId AND Name LIKE \'Logo%\'';
return Database.query(query);
}
private List<Order> getOrders() {
Id invoiceId = this.invoice.Id;
return [
SELECT Name, AccountId, Account.Name,
Subscription25__Reseller_Customer__c, Subscription25__Reseller_Customer__r.Name,
Subscription25__Invoice__r.Subscription25__Account__r.Name,
(
SELECT Id, Subscription25__VAT_Percentage__c, Quantity,
UnitPrice, Description, Subscription25__Use_ICP__c,
Subscription25__Hide_VAT_On_Invoice__c, Subscription25__Product__c, Subscription25__Product__r.Name,
OrderId, Order.Name, Order.Id, Order.AccountId, Order.Account.Name,
Order.Subscription25__Reseller_Customer__c, Order.Subscription25__Reseller_Customer__r.Name,
Order.Subscription25__Invoice__c, Order.Subscription25__Invoice__r.Subscription25__Account__c, Order.Subscription25__Invoice__r.Subscription25__Account__r.Name
FROM OrderItemOrderItems
)
FROM Order
WHERE Subscription25__Invoice__c = :invoiceId
];
}
private static Decimal format(Decimal amount) {
return amount.setScale(2, RoundingMode.HALF_UP);
}
private static Id getLogoId(){
String query = 'SELECT Id FROM Document WHERE DeveloperName LIKE \'%Subscription25_Logo\' LIMIT 1';
List<Document> docs = Database.query(query);
return docs.size() > 0 ? docs[0].Id : null;
}
private class InvoiceItem {
public Decimal quantity {get; private set;}
public String accountLabel {get; private set;} //used for resellers and bill to parent
public String label {get; private set;}
public Decimal price {get; private set;}
public Decimal tax {get; private set;}
public String description {get; private set;}
public InvoiceItem(OrderItem oi) {
this.quantity = oi.Quantity;
this.label = oi.Subscription25__Product__r.Name;
this.price = oi.UnitPrice;
this.tax = oi.Subscription25__VAT_Percentage__c;
this.description = oi.Description;
if(oi.Order.Subscription25__Reseller_Customer__c != null){
this.accountLabel = oi.Order.Subscription25__Reseller_Customer__r.Name;
}
if(oi.Order.AccountId != oi.Order.Subscription25__Invoice__r.Subscription25__Account__c){
this.accountLabel = oi.Order.Account.Name;
}
}
public Decimal getTotal() {
Decimal total = this.price * this.quantity;
return Ctrl_InvoiceLayout.format(total);
}
}
} |
Test Class Test_Ctrl_InvoiceLayout : Code Block |
---|
@isTest
private class Test_Ctrl_InvoiceLayout {
@testSetup static void setup(){
String entity = 'GoMeddo Subscription Management';
Subscription25__Administration__c admin = new Subscription25__Administration__c(
Subscription25__Billing_Email_Address__c = 's25@test.com',
Subscription25__Billing_Name__c = entity,
Subscription25__Billing_Street__c = 'teststraat',
Subscription25__Billing_Postal_Code__c = '1234ab',
Subscription25__Billing_City__c = 'Amsterdam',
Subscription25__Billing_Country__c = 'Netherlands',
Subscription25__Bank__c = 'Test Bank',
Subscription25__BIC__c = 'test bic',
Subscription25__IBAN__c = 'test iban',
Subscription25__VAT_Number__c = '21',
Subscription25__Chamber_Of_Commerce_Number__c = 'test cocn',
Subscription25__Website__c = 'www.test.com'
);
admin.Name = entity;
admin.Subscription25__Invoice_Number_Prefix__c = '123';
Database.insert(admin);
Account acc = new Account();
acc.Name = 'Test Account';
acc.BillingStreet = 'Hoogte Kadijk 38-1';
acc.BillingPostalCode = '1018BM';
acc.BillingCity = 'Amsterdam';
acc.BillingCountry = 'Netherlands';
acc.ShippingStreet = 'Hoogte Kadijk 38-1';
acc.ShippingPostalCode = '1018BM';
acc.ShippingCity = 'Amsterdam';
acc.ShippingCountry = 'Netherlands';
Database.insert(acc);
Contact con = new Contact();
con.LastName = 'van Test';
con.FirstName = 'Testje';
con.Email = 'test@test.com';
Database.insert(con);
Product2 prod = new Product2();
prod.Name = 'Test Product';
Database.insert(prod);
PricebookEntry pbe = new PricebookEntry();
pbe.Pricebook2Id = Test.getStandardPricebookId();
pbe.Product2Id = prod.Id;
pbe.UnitPrice = 1;
Database.insert(pbe);
Subscription25__Invoice__c i = new Subscription25__Invoice__c();
i.Subscription25__Account__c = acc.Id;
i.Subscription25__Administration__c = admin.Id;
i.Subscription25__Invoice_Date__c = Date.today();
i.Subscription25__Description__c = 'invoice description';
i.Subscription25__Purchase_Order_Number__c = '1234';
i.Subscription25__Billing_Country__c = 'NLD';
Database.insert(i);
Subscription25__VATRate__c vatRate = new Subscription25__VATRate__c();
vatRate.Subscription25__Active__c = true;
vatRate.Subscription25__Default__c = true;
vatRate.Subscription25__VAT_Percentage__c = 19;
Database.insert(vatRate);
Subscription25__VAT_Code__c vatCode = new Subscription25__VAT_Code__c();
vatCode.Subscription25__Administration__c = admin.Id;
vatCode.Subscription25__VATRate__c = vatRate.Id;
vatCode.Subscription25__VAT_Code__c = 'VH';
Database.insert(vatCode);
Subscription25__Administration_Product__c ap = new Subscription25__Administration_Product__c();
ap.Subscription25__Administration__c = admin.id;
ap.Subscription25__Product__c = prod.Id;
ap.Subscription25__VATRate__c = vatRate.Id;
ap.Subscription25__Ledger_Account__c = '1000';
Database.insert(ap);
Subscription25__Debtor_Number__c dbNmbr = new Subscription25__Debtor_Number__c();
dbNmbr.Subscription25__Administration__c = admin.Id;
dbNmbr.Subscription25__Debtor_Number__c = '123';
dbNmbr.Subscription25__Account__c = acc.Id;
Database.insert(dbNmbr);
Order ord = new Order();
ord.AccountId = acc.Id;
ord.Subscription25__Administration__c = admin.Id;
ord.Pricebook2Id = Test.getStandardPricebookId();
ord.status = 'draft';
ord.Subscription25__Invoice__c = i.Id;
ord.EffectiveDate = Date.today();
Database.insert(ord);
OrderItem ordItem = new OrderItem();
ordItem.UnitPrice = 12;
ordItem.Quantity = 1;
ordItem.OrderId = ord.Id;
ordItem.Product2Id = prod.Id;
ordItem.Subscription25__Product__c = prod.Id;
ordItem.Subscription25__VAT_Code__c = 'VH';
ordItem.Subscription25__VAT_Percentage__c = 12;
Database.insert(ordItem);
}
@IsTest
static void test_constructor(){
PageReference pageRef = Page.Invoice; //name of visualforce page
Test.setCurrentPage(pageRef);
ApexPages.StandardController sc = new ApexPages.StandardController([
SELECT Id, Subscription25__Account__c,Subscription25__Administration__c,Subscription25__Invoice_Date__c,
Subscription25__Description__c,Subscription25__Purchase_Order_Number__c,Subscription25__Billing_Country__c
FROM Subscription25__Invoice__c
LIMIT 1
]);
Ctrl_InvoiceLayout ctrl = new Ctrl_InvoiceLayout(sc);
}
} |
Visualforce Invoice : Code Block |
---|
<apex:page standardController="Subscription25__Invoice__c" extensions="Ctrl_InvoiceLayout" renderAs="pdf" sidebar="false" showHeader="false" applyBodyTag="false">
<head>
<link media="print" rel="stylesheet" type="text/css" href="{!URLFOR($Resource.invoice, 'css/invoice.css')}" />
</head>
<body>
<div class="header">
<apex:image value="/servlet/servlet.FileDownload?file={!companyLogoId}" styleClass="logo"/>
</div>
<div class="header">
<div class="logoContainer">
<apex:image value="/servlet/servlet.FileDownload?file={!companyLogoId}" styleClass="logo" />
</div>
<table class="invoiceRulesHeader">
<thead>
<tr>
<th class="number">Quantity</th>
<th class="description">Description</th>
<th class="price right">Price</th>
<th class="total right">Total</th>
<th class="vat right">VAT</th>
</tr>
</thead>
</table>
</div>
<div class="footer">
<div class="container">
<ul>
<li>
<apex:outputField value="{!Subscription25__Invoice__c.Subscription25__Administration__r.Subscription25__Billing_Name__c}" />
</li>
<li>
<apex:outputText value="{!Subscription25__Invoice__c.Subscription25__Administration__r.Subscription25__Billing_Street__c}" />
</li>
<li>
<apex:outputText value="{!Subscription25__Invoice__c.Subscription25__Administration__r.Subscription25__Billing_Postal_Code__c} {!Subscription25__Invoice__c.Subscription25__Administration__r.Subscription25__Billing_City__c}" />
</li>
<li class="last">
<apex:outputText value="{!Subscription25__Invoice__c.Subscription25__Administration__r.Subscription25__Billing_Country__c}" />
</li>
</ul>
<ul>
<li>
<apex:outputText value="VAT {!Subscription25__Invoice__c.Subscription25__Administration__r.Subscription25__VAT_Number__c}" />
</li>
<li>
<apex:outputText value="Bank {!Subscription25__Invoice__c.Subscription25__Administration__r.Subscription25__Bank__c}" />
</li>
<li>
<apex:outputText value="IBAN {!Subscription25__Invoice__c.Subscription25__Administration__r.Subscription25__IBAN__c}" />
</li>
<li class="last">
<apex:outputText value="BIC_Swift {!Subscription25__Invoice__c.Subscription25__Administration__r.Subscription25__BIC__c}" />
</li>
</ul>
</div>
<div class="pageNumbers">Page <span class="pagenumber"/> Of <span class="pagecount"/></div>
</div>
<div class="container">
<div class="invoicevat">
<apex:outputText value="INVOICE" />
</div>
<table class="contactDetails">
<tr>
<td class="contactName"><apex:outputText value="{!Subscription25__Invoice__c.Subscription25__Account__r.Name}" /></td>
</tr>
<apex:outputPanel layout="none" rendered="true">
<tr>
<td>
<apex:outputText value="Attn {!Subscription25__Invoice__c.Subscription25__Contact_Person__r.Name}" rendered="{!Subscription25__Invoice__c.Subscription25__Contact_Person__c != null}"/>
</td>
</tr>
</apex:outputPanel>
<tr>
<td><apex:outputText value="{!Subscription25__Invoice__c.Subscription25__Billing_Street__c}" /></td>
</tr>
<tr>
<td><apex:outputText value="{!Subscription25__Invoice__c.Subscription25__Billing_Postal_Code__c} {!Subscription25__Invoice__c.Subscription25__Billing_City__c}" /></td>
</tr>
<tr>
<td><apex:outputText value="{!Subscription25__Invoice__c.Subscription25__Billing_Country__c}" /></td>
</tr>
<tr>
<td><apex:outputText value="{!Subscription25__Invoice__c.Subscription25__VAT_Number__c}" /></td>
</tr>
</table>
<table class="invoiceDetails">
<tr>
<td class="leftColumn">InvoiceDate:</td>
<td><apex:outputField value="{!Subscription25__Invoice__c.Subscription25__Invoice_Date__c}" /></td>
</tr>
<tr>
<td>DueDate:</td>
<td><apex:outputField value="{!Subscription25__Invoice__c.Subscription25__Due_Date__c}" /></td>
</tr>
<tr>
<td>InvoiceNumber:</td>
<td><apex:outputField value="{!Subscription25__Invoice__c.Subscription25__Invoice_Number__c}" /></td>
</tr>
</table>
<apex:outputPanel rendered="{!NOT(ISBLANK(Subscription25__Invoice__c.Subscription25__Description__c))}" layout="none">
<div class="subject">
<apex:outputText value="Regarding: {!Subscription25__Invoice__c.Subscription25__Description__c}" />
</div>
</apex:outputPanel>
<table class="invoiceRules">
<thead>
<tr>
<th class="number">Quantity</th>
<th class="description">Description</th>
<th class="price right">Price</th>
<th class="total right">Total</th>
<th class="vat right">VAT</th>
</tr>
</thead>
<tbody>
<apex:repeat var="item" value="{!items}">
<tr>
<td class="number right">
<apex:outputText value="{0, number,###,###,##0.00}">
<apex:param value="{!item.quantity}" />
</apex:outputText>
</td>
<td class="description">
<div><apex:outputText value="{!item.accountLabel}" /></div>
<apex:outputText value="{!item.label}" />
<div class="subText"><apex:outputText value="{!item.description}" /></div>
</td>
<td class="price right">
<apex:outputText value="€{0, number,###,###,##0.00}">
<apex:param value="{!item.price}" />
</apex:outputText>
</td>
<td class="total right">
<apex:outputText value="€{0, number,###,###,##0.00}">
<apex:param value="{!item.total}" />
</apex:outputText>
</td>
<td class="vat right">
<apex:outputText value="{0, number,###,###,##0.00}%">
<apex:param value="{!item.tax}" />
</apex:outputText>
</td>
</tr>
</apex:repeat>
</tbody>
</table>
<div class="paymentDetails">
<table class="invoiceRulesFooter">
<tbody>
<tr>
<td class="number"></td>
<td colspan="2" class="totalText">Subtotal (ExclTax)</td>
<td class="total right">
<apex:outputText value="€{0, number,###,###,##0.00}">
<apex:param value="{!sum}" />
</apex:outputText>
</td>
<td class="vat"></td>
</tr>
<tr>
<td class="number"></td>
<td colspan="2" class="totalText">Tax</td>
<td class="total right">
<apex:outputText value="€{0, number,###,###,##0.00}">
<apex:param value="{!taxAmount}" />
</apex:outputText>
</td>
<td class="vat"></td>
</tr>
</tbody>
<tfoot>
<tr>
<td class="number"></td>
<td colspan="2" class="totalText">Total (InclTax)</td>
<td class="total right">
<apex:outputText value="€{0, number,###,###,##0.00}">
<apex:param value="{!total}" />
</apex:outputText>
</td>
<td class="vat"></td>
</tr>
</tfoot>
</table>
<apex:outputPanel styleClass="timeleyPayment" rendered="{!hasICP}">
ICPLawMessage
</apex:outputPanel>
<div class="timeleyPayment">
Please reference invoice number <strong>{!Subscription25__Invoice__c.Subscription25__Invoice_Number__c}</strong> with your payment. We appreciate your timely payment.
</div>
<table class="paymentInfo">
<tr>
<td class="first">Wire transfer to:</td>
<td></td>
</tr>
<tr>
<td>Bank Name:</td>
<td><apex:outputField value="{!Subscription25__Invoice__c.Subscription25__Administration__r.Subscription25__Bank__c}" /></td>
</tr>
<tr>
<td>Bank Account Name:</td>
<td><apex:outputField value="{!Subscription25__Invoice__c.Subscription25__Administration__r.Subscription25__Billing_Name__c}" /></td>
</tr>
<tr>
<td>BIC Swift:</td>
<td><apex:outputField value="{!Subscription25__Invoice__c.Subscription25__Administration__r.Subscription25__BIC__c}" /></td>
</tr>
<tr>
<td>IBAN:</td>
<td><apex:outputField value="{!Subscription25__Invoice__c.Subscription25__Administration__r.Subscription25__IBAN__c}" /></td>
</tr>
</table>
<apex:outputPanel rendered="{!NOT(ISBLANK(Subscription25__Invoice__c.Subscription25__Foot_Note__c))}" layout="none">
<div class="via-email">
<apex:outputField value="{!Subscription25__Invoice__c.Subscription25__Foot_Note__c}" />
</div>
</apex:outputPanel>
</div>
</div>
</body>
<apex:outputText rendered="none" value="Subscription25__Invoice__c.Subscription25__Administration__c}" />
</apex:page> |
|