Billys_Billing_Invoicer - Version 1.0.0

Version Notes

First stable release.

Download this release

Release Info

Developer Billy's Billing
Extension Billys_Billing_Invoicer
Version 1.0.0
Comparing to
See all releases


Version 1.0.0

app/code/community/BillysBilling/.DS_Store ADDED
Binary file
app/code/community/BillysBilling/Invoicer/.DS_Store ADDED
Binary file
app/code/community/BillysBilling/Invoicer/Helper/Data.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+ class BillysBilling_Invoicer_Helper_Data extends Mage_Core_Helper_Abstract {
3
+ public static function printError($e, $msg = null) {
4
+ Mage::getSingleton("core/session")->addError("Billy Exception: " . $e->getMessage() . " (" . $e->getHelpUrl() . ")" . ($msg == null ? "" : "<br>Message: " . $msg));
5
+ }
6
+ }
app/code/community/BillysBilling/Invoicer/Model/.DS_Store ADDED
Binary file
app/code/community/BillysBilling/Invoicer/Model/Accounts.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class BillysBilling_Invoicer_Model_Accounts {
3
+ public function toOptionArray() {
4
+ if (!Mage::getStoreConfig("billy/api/api_key") || strlen(Mage::getStoreConfig("billy/api/api_key")) < 10) {
5
+ return array(
6
+ array(
7
+ "value" => "",
8
+ "label" => "Please enter API key above and Save Config"
9
+ )
10
+ );
11
+ }
12
+ // Include Billy's PHP SDK
13
+ if (!class_exists('Billy_Client', false)) {
14
+ require(dirname(__FILE__) . "/billysbilling-php/bootstrap.php");
15
+ }
16
+
17
+ // Create new client with API key
18
+ try {
19
+ $client = new Billy_Client(Mage::getStoreConfig("billy/api/api_key"));
20
+ } catch (Billy_Exception $e) {
21
+ BillysBilling_Invoicer_Helper_Data::printError($e);
22
+ return array(
23
+ array(
24
+ "value" => "",
25
+ "label" => "Please use a valid API key"
26
+ )
27
+ );
28
+ }
29
+
30
+ // Get all accounts
31
+ try {
32
+ $response = $client->get("accounts");
33
+ } catch (Billy_Exception $e) {
34
+ BillysBilling_Invoicer_Helper_Data::printError($e, "Error occurred on getting accounts data");
35
+ return array(
36
+ array(
37
+ "value" => "",
38
+ "label" => "Could not retrieve accounts from Billy API"
39
+ )
40
+ );
41
+ }
42
+
43
+ // Map accounts to account types and sort account types
44
+ $results = array();
45
+ foreach ($response->accounts AS $account) {
46
+ $results[$account->accountType->name][$account->name] = array(
47
+ "value" => $account->id,
48
+ "label" => $account->name
49
+ );
50
+ }
51
+ ksort($results);
52
+
53
+ // Create optgroups and options containing account types and accounts
54
+ $options = array();
55
+ foreach ($results AS $accountType => $accounts) {
56
+ ksort($accounts);
57
+ $options[] = array(
58
+ "value" => $accounts,
59
+ "label" => $accountType
60
+ );
61
+ }
62
+
63
+ return $options;
64
+ }
65
+ }
app/code/community/BillysBilling/Invoicer/Model/Observer.php ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class BillysBilling_Invoicer_Model_Observer {
3
+
4
+ private $testMode = false;
5
+
6
+ private $apiKey = "";
7
+ private $shippingId = "";
8
+ private $accountId = "";
9
+ private $vatModelId = "";
10
+
11
+ private $client;
12
+
13
+ /**
14
+ * Save invoice to BB with contact and product details.
15
+ *
16
+ * @event sales_model_service_quote_submit_success
17
+ *
18
+ * @param $observer
19
+ */
20
+ public function saveInvoiceOnSuccess($observer) {
21
+ if (Mage::getStoreConfig("billy/invoicer/mode") && Mage::getStoreConfig("billy/invoicer/mode") == "test") {
22
+ $this->testMode = true;
23
+ }
24
+
25
+ // Set variables
26
+ $this->apiKey = Mage::getStoreConfig("billy/api/api_key");
27
+ $this->shippingId = Mage::getStoreConfig("billy/invoicer/shipping_account");
28
+ $this->accountId = Mage::getStoreConfig("billy/invoicer/sales_account");
29
+ $this->vatModelId = Mage::getStoreConfig("billy/invoicer/vat_model");
30
+
31
+ // Include Billy's PHP SDK
32
+ if (!class_exists('Billy_Client', false)) {
33
+ require(dirname(__FILE__) . "/billysbilling-php/bootstrap.php");
34
+ }
35
+
36
+ // Create new client with API key
37
+ try {
38
+ $this->client = new Billy_Client($this->apiKey);
39
+ } catch (Billy_Exception $e) {
40
+ BillysBilling_Invoicer_Helper_Data::printError($e);
41
+ return false;
42
+ }
43
+
44
+ return $this->createInvoice($observer->getOrder());
45
+ }
46
+
47
+ /**
48
+ * Process contacts and products, and create the invoice.
49
+ *
50
+ * @param $order
51
+ * @return array Response from API for invoice creation
52
+ */
53
+ private function createInvoice($order) {
54
+ // Get contact ID
55
+ $contactId = $this->insertIgnore("contacts", $order->getBillingAddress());
56
+ if ($contactId == null) {
57
+ return false;
58
+ }
59
+
60
+ // Run through each order item
61
+ $items = $order->getItemsCollection(array(), true);
62
+ $products = array();
63
+ foreach ($items as $item) {
64
+ // Get product ID
65
+ $productId = $this->insertIgnore("products", $item);
66
+ if ($productId == null) {
67
+ return false;
68
+ }
69
+
70
+ // Add item to product array
71
+ $product = array(
72
+ "productId" => $productId,
73
+ "quantity" => $item->getQtyInvoiced(),
74
+ "unitPrice" => $item->getPrice()
75
+ );
76
+ // Apply discounts
77
+ if ($item->getDiscountPercent() > 0) {
78
+ $product["discountMode"] = "percent";
79
+ $product["discountValue"] = $item->getDiscountPercent();
80
+ } else if ($item->getDiscountAmount() > 0) {
81
+ $product["discountMode"] = "cash";
82
+ $product["discountValue"] = $item->getDiscountAmount();
83
+ }
84
+
85
+ $products[] = $product;
86
+ }
87
+ // Add shipping costs to product array
88
+ $products[] = array(
89
+ "productId" => $this->shippingId,
90
+ "quantity" => 1,
91
+ "unitPrice" => $order->getShippingAmount()
92
+ );
93
+
94
+ // Order date
95
+ $date = date("Y-m-d", $order->getCreatedAtDate()->getTimestamp());
96
+ // Set invoice data
97
+ $invoice = array(
98
+ "type" => "invoice",
99
+ "contactId" => $contactId,
100
+ "entryDate" => $date,
101
+ "dueDate" => $date,
102
+ "currencyId" => Mage::app()->getStore()->getCurrentCurrencyCode(),
103
+ "state" => "approved",
104
+ "lines" => $products
105
+ );
106
+
107
+ // Create new invoice
108
+ try {
109
+ if ($this->testMode) {
110
+ return $this->client->fakePost(Mage::getBaseDir() . "/tests/output.log", "invoices", $invoice);
111
+ }
112
+ return $this->client->post("invoices", $invoice);
113
+ } catch (Billy_Exception $e) {
114
+ BillysBilling_Invoicer_Helper_Data::printError($e, "Error occurred on invoice creation.");
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Take a data object from Magento, use it to either search for existing entries in BB and return ID of that, or
120
+ * insert a new entry in BB and return ID of that.
121
+ *
122
+ * @param $type string "contacts" or "products"
123
+ * @param $data BillingAddress object or Item object
124
+ *
125
+ * @return int ID of inserted or found entry
126
+ */
127
+ private function insertIgnore($type, $data) {
128
+ // Format data
129
+ $data = $this->formatArray($type, $data);
130
+
131
+ // Check for existing contact
132
+ $responseArray = array();
133
+ $id = null;
134
+ try {
135
+ $address = $type . "?q=" . urlencode($data['name']);
136
+ if ($this->testMode) {
137
+ $response = $this->client->fakeGet(Mage::getBaseDir() . "/tests/output.log", $address);
138
+ } else {
139
+ $response = $this->client->get($address);
140
+ }
141
+ $responseArray = $response->$type;
142
+ } catch (Billy_Exception $e) {
143
+ BillysBilling_Invoicer_Helper_Data::printError($e, "Error occurred on getting " . $type . " data");
144
+ }
145
+ if (count($responseArray) > 0) {
146
+ // If existing contact, then save ID
147
+ $id = $responseArray[0]->id;
148
+ } else {
149
+ // Create new contact and contact person, then save ID
150
+ try {
151
+ if ($this->testMode) {
152
+ $response = $this->client->fakePost(Mage::getBaseDir() . "/tests/output.log", $type, $data);
153
+ } else {
154
+ $response = $this->client->post($type, $data);
155
+ }
156
+ $id = $response->id;
157
+ } catch (Billy_Exception $e) {
158
+ BillysBilling_Invoicer_Helper_Data::printError($e, "Error occurred on posting " . $type . " data");
159
+ }
160
+ }
161
+ return $id;
162
+ }
163
+
164
+ /**
165
+ * Take a data object from Magento and convert it into something usable by BB API.
166
+ *
167
+ * @param $type string "contacts" or "products"
168
+ * @param $data BillingAddress object or Item object
169
+ * @return array of either contact or product
170
+ */
171
+ private function formatArray($type, $data) {
172
+ if ($type == "contacts") {
173
+ // Set name depending on company or not
174
+ if ($data->getCompany()) {
175
+ $name = $data->getCompany();
176
+ } else {
177
+ $name = $data->getName();
178
+ }
179
+
180
+ return array(
181
+ 'name' => $name,
182
+ 'street' => $data->getStreetFull(),
183
+ 'zipcode' => $data->getPostcode(),
184
+ 'city' => $data->getCity(),
185
+ 'countryId' => $data->getCountry_id(),
186
+ 'state' => $data->getRegion(),
187
+ 'phone' => $data->getTelephone(),
188
+ 'fax' => $data->getFax(),
189
+ 'persons' => array(
190
+ array(
191
+ 'name' => $data->getName(),
192
+ 'email' => $data->getEmail(),
193
+ 'phone' => $data->getTelephone()
194
+ )
195
+ )
196
+ );
197
+ } else if ($type == "products") {
198
+ return array(
199
+ "name" => $data->getName(),
200
+ "accountId" => $this->accountId,
201
+ "vatModelId" => $this->vatModelId,
202
+ "productType" => "product",
203
+ "productNo" => $data->product_id,
204
+ "suppliersProductNo" => $data->sku,
205
+ "prices" => array(
206
+ array(
207
+ "currencyId" => Mage::app()->getStore()->getCurrentCurrencyCode(),
208
+ "unitPrice" => $data->getPrice()
209
+ )
210
+ )
211
+ );
212
+ }
213
+ return null;
214
+ }
215
+ }
app/code/community/BillysBilling/Invoicer/Model/Products.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class BillysBilling_Invoicer_Model_Products {
3
+ public function toOptionArray() {
4
+ if (!Mage::getStoreConfig("billy/api/api_key") || strlen(Mage::getStoreConfig("billy/api/api_key")) < 10) {
5
+ return array(
6
+ array(
7
+ "value" => "",
8
+ "label" => "Please enter API key above and Save Config"
9
+ )
10
+ );
11
+ }
12
+ // Include Billy's PHP SDK
13
+ if (!class_exists('Billy_Client', false)) {
14
+ require(dirname(__FILE__) . "/billysbilling-php/bootstrap.php");
15
+ }
16
+
17
+ // Create new client with API key
18
+ try {
19
+ $client = new Billy_Client(Mage::getStoreConfig("billy/api/api_key"));
20
+ } catch (Billy_Exception $e) {
21
+ BillysBilling_Invoicer_Helper_Data::printError($e);
22
+ return array(
23
+ array(
24
+ "value" => "",
25
+ "label" => "Please use a valid API key"
26
+ )
27
+ );
28
+ }
29
+
30
+ // Get all products
31
+ try {
32
+ $response = $client->get("products");
33
+ } catch (Billy_Exception $e) {
34
+ BillysBilling_Invoicer_Helper_Data::printError($e, "Error occurred on getting products data");
35
+ return array(
36
+ array(
37
+ "value" => "",
38
+ "label" => "Could not retrieve products from Billy API"
39
+ )
40
+ );
41
+ }
42
+
43
+ // Map accounts to account types and sort account types
44
+ $options = array();
45
+ foreach ($response->products AS $product) {
46
+ $options[] = array(
47
+ "value" => $product->id,
48
+ "label" => $product->name
49
+ );
50
+ }
51
+
52
+ return $options;
53
+ }
54
+ }
app/code/community/BillysBilling/Invoicer/Model/VatModels.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class BillysBilling_Invoicer_Model_VatModels {
3
+ public function toOptionArray() {
4
+ if (!Mage::getStoreConfig("billy/api/api_key") || strlen(Mage::getStoreConfig("billy/api/api_key")) < 10) {
5
+ return array(
6
+ array(
7
+ "value" => "",
8
+ "label" => "Please enter API key above and Save Config"
9
+ )
10
+ );
11
+ }
12
+ // Include Billy's PHP SDK
13
+ if (!class_exists('Billy_Client', false)) {
14
+ require(dirname(__FILE__) . "/billysbilling-php/bootstrap.php");
15
+ }
16
+
17
+ // Create new client with API key
18
+ try {
19
+ $client = new Billy_Client(Mage::getStoreConfig("billy/api/api_key"));
20
+ } catch (Billy_Exception $e) {
21
+ BillysBilling_Invoicer_Helper_Data::printError($e);
22
+ return array(
23
+ array(
24
+ "value" => "",
25
+ "label" => "Please use a valid API key"
26
+ )
27
+ );
28
+ }
29
+
30
+ // Get all VAT models
31
+ try {
32
+ $response = $client->get("vatModels");
33
+ } catch (Billy_Exception $e) {
34
+ BillysBilling_Invoicer_Helper_Data::printError($e, "Error occurred on getting vat models data");
35
+ return array(
36
+ array(
37
+ "value" => "",
38
+ "label" => "Could not retrieve vat models from Billy API"
39
+ )
40
+ );
41
+ }
42
+
43
+ // Create options containing VAT models
44
+ $options = array();
45
+ foreach ($response->vatModels AS $vatModel) {
46
+ $options[] = array(
47
+ "value" => $vatModel->id,
48
+ "label" => $vatModel->name
49
+ );
50
+ }
51
+
52
+ return $options;
53
+ }
54
+ }
app/code/community/BillysBilling/Invoicer/Model/billysbilling-php/.DS_Store ADDED
Binary file
app/code/community/BillysBilling/Invoicer/Model/billysbilling-php/Billy/Client.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Billy_Client {
3
+
4
+ private $request;
5
+
6
+ /**
7
+ * Construct a Billy Client with an API key and optionally an API version.
8
+ *
9
+ * @param string $apiKey API key from Billy
10
+ * @param string $apiVersion Optional (currently v1)
11
+ */
12
+ public function __construct($apiKey, $apiVersion = "v1") {
13
+ // Only accept a string of 32 characters containing only lowercase and uppercase letters and numbers
14
+ if (!preg_match("/^([a-zA-Z0-9]{32})/", $apiKey)) {
15
+ throw new Billy_Exception("Billy has encountered an invalid API key");
16
+ }
17
+
18
+ $this->request = new Billy_Request($apiKey, $apiVersion);
19
+ }
20
+
21
+ /**
22
+ * Run a GET request on Billy API on a specific address and receive an array as return.
23
+ *
24
+ * @param string $address Sub-address to call, e.g. invoices or invoices/ID_NUMBER
25
+ *
26
+ * @return array Response from Billy API, e.g. invoice object
27
+ */
28
+ public function get($address) {
29
+ return $this->request->call("GET", $address);
30
+ }
31
+
32
+ /**
33
+ * Run a POST request on Billy API on a specific address with parameters and receive an array as return.
34
+ *
35
+ * @param string $address Sub-address to call, e.g. invoices or contacts
36
+ * @param array $params Parameters to be sent to Billy API on the specified address
37
+ *
38
+ * @return array Response from Billy API, e.g. id and success
39
+ */
40
+ public function post($address, $params) {
41
+ return $this->request->call("POST", $address, $params);
42
+ }
43
+
44
+ /**
45
+ * Run a fake GET request.
46
+ *
47
+ * @param string $address Sub-address to call, e.g. invoices or invoices/ID_NUMBER
48
+ *
49
+ * @return array Response from Billy API, e.g. invoice object
50
+ */
51
+ public function fakeGet($outputFile, $address) {
52
+ return $this->request->fakeCall($outputFile, "GET", $address);
53
+ }
54
+
55
+ /**
56
+ * Run a fake POST request.
57
+ *
58
+ * @param string $address Sub-address to call, e.g. invoices or contacts
59
+ * @param array $params Parameters to be sent to Billy API on the specified address
60
+ *
61
+ * @return array Response from Billy API, e.g. id and success
62
+ */
63
+ public function fakePost($outputFile, $address, $params) {
64
+ return $this->request->fakeCall($outputFile, "POST", $address, $params);
65
+ }
66
+
67
+ }
app/code/community/BillysBilling/Invoicer/Model/billysbilling-php/Billy/Exception.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Billy_Exception extends Exception {
3
+ public function __construct($message = null, $help_url = null, $json_body = null) {
4
+ parent::__construct($message);
5
+ $this->help_url = $help_url;
6
+ $this->json_body = $json_body;
7
+ }
8
+
9
+ public function getHelpUrl() {
10
+ return $this->help_url;
11
+ }
12
+
13
+ public function getJsonBody() {
14
+ return $this->json_body;
15
+ }
16
+ }
app/code/community/BillysBilling/Invoicer/Model/billysbilling-php/Billy/Request.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Billy_Request {
3
+
4
+ private $apiKey;
5
+ private $apiVersion;
6
+
7
+ /**
8
+ * Construct a Billy Request with an API key and an API version.
9
+ *
10
+ * @param string $apiKey API key from Billy
11
+ * @param string $apiVersion API version from Billy
12
+ */
13
+ public function __construct($apiKey, $apiVersion) {
14
+ $this->apiKey = $apiKey;
15
+ $this->apiVersion = $apiVersion;
16
+ }
17
+
18
+ /**
19
+ * Run a custom request on Billy API on a specific address with possible parameters and receive a response array as
20
+ * return.
21
+ *
22
+ * @param string $method Either GET or POST
23
+ * @param string $address Sub-address to call, e.g. invoices or invoices/ID_NUMBER
24
+ * @param OPTIONAL array $params Parameters to be sent to Billy API on the specified address
25
+ *
26
+ * @return array Response from Billy API, e.g. id and success or invoice object
27
+ */
28
+ public function call($method, $address, $params = null) {
29
+ $ch = curl_init();
30
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
31
+ // Authentication
32
+ curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
33
+ curl_setopt($ch, CURLOPT_USERPWD, $this->apiKey . ":");
34
+ // Request method
35
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
36
+ // POST parameters
37
+ if ($method == "POST" && $params != null) {
38
+ curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
39
+ }
40
+ // URL including API version and sub-address
41
+ curl_setopt($ch, CURLOPT_URL, "https://api.billysbilling.dk/" . $this->apiVersion . "/" . $address);
42
+ $rawResponse = curl_exec($ch);
43
+ curl_close($ch);
44
+
45
+ // Return response array
46
+ return $this->interpretResponse($rawResponse);
47
+ }
48
+
49
+ /**
50
+ * Run a fake custom request.
51
+ *
52
+ * @param string $method Either GET or POST
53
+ * @param string $address Sub-address to call, e.g. invoices or invoices/ID_NUMBER
54
+ * @param OPTIONAL array $params Parameters to be sent to Billy API on the specified address
55
+ *
56
+ * @return array Response from Billy API, e.g. id and success or invoice object
57
+ */
58
+ public function fakeCall($outputFile, $method, $address, $params = null) {
59
+ $call = array(
60
+ "mode" => $method,
61
+ "address" => $address
62
+ );
63
+ if ($params) {
64
+ $call["params"] = $params;
65
+ }
66
+
67
+ $handle = fopen($outputFile, "a");
68
+ fwrite($handle, json_encode($call) . "\n");
69
+ fclose($handle);
70
+
71
+ $response = new StdClass();
72
+ if ($method == "POST") {
73
+ $response->id = "12345-ABCDEFGHIJKLMNOP";
74
+ $response->success = true;
75
+ } else {
76
+ $addressParts = explode("?", $address);
77
+ $type = $addressParts[0];
78
+ $response->$type = array();
79
+ }
80
+ return $response;
81
+ }
82
+
83
+ /**
84
+ * Takes a raw JSON response and decodes it. If an error is met, throw an exception. Else return array.
85
+ *
86
+ * @param string $rawResponse JSON encoded array
87
+ *
88
+ * @return array Response from Billy API, e.g. id and success or invoice object
89
+ * @throws Billy_Exception Error, Help URL and response
90
+ */
91
+ private function interpretResponse($rawResponse) {
92
+ $response = json_decode($rawResponse);
93
+ if (!$response->success) {
94
+ throw new Billy_Exception($response->error, $response->helpUrl, $rawResponse);
95
+ }
96
+
97
+ return $response;
98
+ }
99
+
100
+ }
app/code/community/BillysBilling/Invoicer/Model/billysbilling-php/bootstrap.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!function_exists("curl_init")) {
3
+ throw new Exception("Billy needs the CURL PHP extension.");
4
+ }
5
+ if (!function_exists("json_decode")) {
6
+ throw new Exception("Billy needs the JSON PHP extension.");
7
+ }
8
+
9
+ require(dirname(__FILE__) . "/Billy/Client.php");
10
+ require(dirname(__FILE__) . "/Billy/Exception.php");
11
+ require(dirname(__FILE__) . "/Billy/Request.php");
app/code/community/BillysBilling/Invoicer/etc/config.xml ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <config>
2
+ <modules>
3
+ <BillysBilling_Invoicer>
4
+ <version>1.0.0</version>
5
+ </BillysBilling_Invoicer>
6
+ </modules>
7
+ <global>
8
+ <events>
9
+ <sales_order_invoice_register>
10
+ <observers>
11
+ <billysbilling_save_invoice_on_success>
12
+ <class>BillysBilling_Invoicer_Model_Observer</class>
13
+ <method>saveInvoiceOnSuccess</method>
14
+ </billysbilling_save_invoice_on_success>
15
+ </observers>
16
+ </sales_order_invoice_register>
17
+ </events>
18
+ <models>
19
+ <billysbilling>
20
+ <class>BillysBilling_Invoicer_Model</class>
21
+ </billysbilling>
22
+ </models>
23
+ <helpers>
24
+ <billysbilling>
25
+ <class>BillysBilling_Invoicer_Helper</class>
26
+ </billysbilling>
27
+ </helpers>
28
+ </global>
29
+ <adminhtml>
30
+ <acl>
31
+ <resources>
32
+ <all>
33
+ <title>Allow Everything</title>
34
+ </all>
35
+ <admin>
36
+ <children>
37
+ <system>
38
+ <children>
39
+ <config>
40
+ <children>
41
+ <billy>
42
+ <title>Billy - All</title>
43
+ </billy>
44
+ </children>
45
+ </config>
46
+ </children>
47
+ </system>
48
+ </children>
49
+ </admin>
50
+ </resources>
51
+ </acl>
52
+ </adminhtml>
53
+ </config>
app/code/community/BillysBilling/Invoicer/etc/system.xml ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <sections>
4
+ <billy translate="label" module="billysbilling">
5
+ <label>Billy's Billing</label>
6
+ <tab>service</tab>
7
+ <frontend_type>text</frontend_type>
8
+ <sort_order>400</sort_order>
9
+ <show_in_default>1</show_in_default>
10
+ <show_in_website>1</show_in_website>
11
+ <show_in_store>1</show_in_store>
12
+ <groups>
13
+ <api translate="label">
14
+ <label>API Settings</label>
15
+ <frontend_type>text</frontend_type>
16
+ <sort_order>200</sort_order>
17
+ <show_in_default>1</show_in_default>
18
+ <show_in_website>0</show_in_website>
19
+ <show_in_store>0</show_in_store>
20
+ <fields>
21
+ <api_key translate="label">
22
+ <label>API key</label>
23
+ <frontend_type>text</frontend_type>
24
+ <comment>Create or get your API key in Billy's web interface under (Danish) Indstillinger -> Organisationsindstillinger -> API. You have to enter API key and Save Config before you can choose shipping product, sales account and VAT model below.</comment>
25
+ <sort_order>10</sort_order>
26
+ <show_in_default>1</show_in_default>
27
+ <show_in_website>0</show_in_website>
28
+ <show_in_store>0</show_in_store>
29
+ </api_key>
30
+ </fields>
31
+ </api>
32
+ <invoicer translate="label">
33
+ <label>Invoice Settings</label>
34
+ <frontend_type>text</frontend_type>
35
+ <sort_order>300</sort_order>
36
+ <show_in_default>1</show_in_default>
37
+ <show_in_website>0</show_in_website>
38
+ <show_in_store>0</show_in_store>
39
+ <fields>
40
+ <shipping_account translate="label">
41
+ <label>Shipping Product</label>
42
+ <frontend_type>select</frontend_type>
43
+ <source_model>BillysBilling_Invoicer_Model_Products</source_model>
44
+ <sort_order>10</sort_order>
45
+ <show_in_default>1</show_in_default>
46
+ <show_in_website>0</show_in_website>
47
+ <show_in_store>0</show_in_store>
48
+ </shipping_account>
49
+ <sales_account translate="label">
50
+ <label>Sales Account</label>
51
+ <frontend_type>select</frontend_type>
52
+ <source_model>BillysBilling_Invoicer_Model_Accounts</source_model>
53
+ <sort_order>20</sort_order>
54
+ <show_in_default>1</show_in_default>
55
+ <show_in_website>0</show_in_website>
56
+ <show_in_store>0</show_in_store>
57
+ </sales_account>
58
+ <vat_model translate="label">
59
+ <label>VAT Model</label>
60
+ <frontend_type>select</frontend_type>
61
+ <source_model>BillysBilling_Invoicer_Model_VatModels</source_model>
62
+ <sort_order>30</sort_order>
63
+ <show_in_default>1</show_in_default>
64
+ <show_in_website>0</show_in_website>
65
+ <show_in_store>0</show_in_store>
66
+ </vat_model>
67
+ </fields>
68
+ </invoicer>
69
+ </groups>
70
+ </billy>
71
+ </sections>
72
+ </config>
app/etc/modules/BillysBilling_Invoicer.xml ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <config>
2
+ <modules>
3
+ <BillysBilling_Invoicer>
4
+ <active>true</active>
5
+ <codePool>community</codePool>
6
+ </BillysBilling_Invoicer>
7
+ </modules>
8
+ </config>
package.xml ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Billys_Billing_Invoicer</name>
4
+ <version>1.0.0</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL)</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Billy's Billing Invoicer for Magento enables you to automatically submit invoices to Billy's Billing.</summary>
10
+ <description>Billy's Billing Invoicer for Magento uses Billy's Billing's API to submit invoices to Billy's Billing automatically from orders created in the Magento shop. When orders are invoiced in Magento, they are automatically send to Billy's Billing with:&#xD;
11
+ - General information about the order,&#xD;
12
+ - Information about the customer, and&#xD;
13
+ - Information about each product including shipping.&#xD;
14
+ &#xD;
15
+ This extension has been testing with the latest releases of version 1.5, 1.6 and 1.7.&#xD;
16
+ &#xD;
17
+ When this extension has been installed, you should go to System Configuration and access the Billy's Billing configuration page. From here you enter an API key (you can get this from organization settings in Billy's Billing) and save the configuration. When this is done, you will be able to change the dropdown boxes for shipping product, sales account and VAT model. After they have been selected, you are ready to use the extension.</description>
18
+ <notes>First stable release.</notes>
19
+ <authors><author><name>Billy's Billing</name><user>billysbilling</user><email>michael@billysbilling.com</email></author></authors>
20
+ <date>2013-03-21</date>
21
+ <time>12:10:53</time>
22
+ <contents><target name="magecommunity"><dir name="BillysBilling"><dir name="Invoicer"><dir name="Helper"><file name="Data.php" hash="2e73f30c86e3cb150b91856d2efeebf4"/></dir><dir name="Model"><file name="Accounts.php" hash="a6861ea516d74d199d52be6e4a8eeb1c"/><file name="Observer.php" hash="63da9b1b6c03202ecc2b3f0abe9496b9"/><file name="Products.php" hash="86953a3321a191587b6da1ab57626c53"/><file name="VatModels.php" hash="e87151fe22f857340476d1d4ebaeb31c"/><dir name="billysbilling-php"><dir name="Billy"><file name="Client.php" hash="b947948ae0063e2a121751782f44c751"/><file name="Exception.php" hash="239b2ecc8821b6e55faef561d0f3089c"/><file name="Request.php" hash="60d6c8d0661ff97cfc828cc785e7c942"/></dir><file name="bootstrap.php" hash="95d828828c4fdf4d338407f4a270c397"/><file name=".DS_Store" hash="ac8ffff9277a5c8cfaa12d9a1e52ef3e"/></dir><file name=".DS_Store" hash="e78a22cf29e6201ef29c5f0981c55604"/></dir><dir name="etc"><file name="config.xml" hash="1bbf2701ae5cd06789f24499b2ff65e7"/><file name="system.xml" hash="5bf923d3297151b518e5e484c9e36f2f"/></dir><file name=".DS_Store" hash="3fad5b10a22595598493fd98e0879784"/></dir><file name=".DS_Store" hash="099e78847f139a18fba02cd92135dd9a"/></dir></target><target name="mageetc"><dir name="modules"><file name="BillysBilling_Invoicer.xml" hash="4b11b30f403a358332323f04da27d1d4"/></dir></target></contents>
23
+ <compatible/>
24
+ <dependencies><required><php><min>5.3.0</min><max>5.4.4</max></php></required></dependencies>
25
+ </package>