Add support for custom fields in billing invoices

Customers (especially in Europe) need the ability to add Tax IDs, VAT IDs, and other custom fields to their invoices.

Fixes #106
This commit is contained in:
Joseph Schorr 2015-06-12 12:32:41 -04:00
parent 683d5080d8
commit e7fa560787
9 changed files with 426 additions and 8 deletions

View file

@ -1,3 +1,6 @@
.billing-invoices-element .fields-menu {
float: right;
}
.billing-invoices-element .invoice-title {
padding: 6px;
@ -22,4 +25,20 @@
.billing-invoices-element .fa-download {
color: #aaa;
}
.billing-invoices-element .fa-trash-o {
float: right;
margin-top: -3px;
margin-right: -14px !important;
font-size: 14px;
padding: 2px;
padding-left: 6px;
padding-right: 6px;
border-radius: 4px;
}
.billing-invoices-element .invoice-field {
padding-top: 6px;
padding-bottom: 6px;
}

View file

@ -9,6 +9,30 @@
</div>
<div ng-show="!loading && invoices.length">
<div class="dropdown fields-menu" data-title="Custom Invoice Fields" bs-tooltip>
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">
<i class="fa fa-bars"></i>
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right" role="menu">
<li role="presentation" ng-repeat="invoiceField in invoiceFields">
<a class="invoice-field" role="menuitem" tabindex="-1" href="javascript:void(0)" >
{{ invoiceField.title }}: {{ invoiceField.value }}
<i class="fa fa-trash-o btn btn-danger" ng-click="askDeleteField(invoiceField)"></i>
</a>
</li>
<li role="presentation" class="disabled" ng-if="!invoiceFields.length">
<a role="menuitem" tabindex="-1" href="javascript:void(0)">No Custom Fields Defined</a>
</li>
<li role="presentation" class="divider"></li>
<li role="presentation">
<a role="menuitem" tabindex="-1" href="javascript:void(0)" ng-click="showCreateField()">
<i class="fa fa-plus"></i>Add Custom Invoice Field
</a>
</li>
</ul>
</div>
<table class="co-table">
<thead>
<td>Billing Date/Time</td>
@ -39,4 +63,23 @@
</table>
</div>
<!-- Delete Tag Confirm -->
<div class="cor-confirm-dialog"
dialog-context="createFieldInfo"
dialog-action="createCustomField(info.title, info.value, callback)"
dialog-title="Create Custom Field"
dialog-action-title="Create Field">
<form>
<div class="form-group">
<label for="titleInput">Enter Field Title</label>
<input id="titleInput" type="text" class="form-control"ng-model="createFieldInfo.title" placeholder="Field Title">
</div>
<div class="form-group">
<label for="valueInput">Enter Field Value</label>
<input id="valueInput" type="text" class="form-control" ng-model="createFieldInfo.value" placeholder="Field Value">
</div>
</form>
</div>
</div>
</div>

View file

@ -15,6 +15,8 @@ angular.module('quay').directive('billingInvoices', function () {
},
controller: function($scope, $element, $sce, ApiService) {
$scope.loading = false;
$scope.showCreateField = null;
$scope.invoiceFields = [];
var update = function() {
var hasValidUser = !!$scope.user;
@ -34,11 +36,59 @@ angular.module('quay').directive('billingInvoices', function () {
$scope.invoices = [];
$scope.loading = false;
});
ApiService.listInvoiceFields($scope.organization).then(function(resp) {
$scope.invoiceFields = resp.fields || [];
}, function() {
$scope.invoiceFields = [];
});
};
$scope.$watch('organization', update);
$scope.$watch('user', update);
$scope.$watch('makevisible', update);
$scope.showCreateField = function() {
$scope.createFieldInfo = {
'title': '',
'value': ''
};
};
$scope.askDeleteField = function(field) {
bootbox.confirm('Are you sure you want to delete field ' + field.title + '?', function(r) {
if (r) {
var params = {
'field_uuid': field.uuid
};
ApiService.deleteInvoiceField($scope.organization, null, params).then(function(resp) {
$scope.invoiceFields = $.grep($scope.invoiceFields, function(current) {
return current.uuid != field.uuid
});
}, ApiService.errorDisplay('Could not delete custom field'));
}
});
};
$scope.createCustomField = function(title, value, callback) {
var data = {
'title': title,
'value': value
};
if (!title || !value) {
callback(false);
bootbox.alert('Missing title or value');
return;
}
ApiService.createInvoiceField($scope.organization, data).then(function(resp) {
$scope.invoiceFields.push(resp);
callback(true);
}, ApiService.errorDisplay('Could not create custom field'));
};
}
};