Permalink
Browse files

Implemented invoice template (including vat)

  • Loading branch information...
allanmc committed Sep 26, 2015
1 parent 72ac49c commit e0b889820c0e63f83800d675b46bc05356c69abd
View
@@ -1,6 +1,31 @@
{
- "DK": {"name": "Denmark", "rate": 25.00},
- "NO": {"name": "Germany", "rate": 22.00},
- "DE": {"name": "Germany", "rate": 19.00},
- "?": {"name": "Non-EU", "rate": 0.00}
+ "BE": {"name":"Belgium","rate": 0.21},
+ "BG": {"name":"Bulgaria","rate": 0.20},
+ "CZ": {"name":"Czech Republic","rate": 0.21},
+ "DK": {"name":"Denmark","rate": 0.25},
+ "DE": {"name":"Germany","rate": 0.19},
+ "EE": {"name":"Estonia","rate": 0.20},
+ "EL": {"name":"Greece","rate": 0.23},
+ "ES": {"name":"Spain","rate": 0.21},
+ "FR": {"name":"France","rate": 0.20},
+ "HR": {"name":"Croatia","rate": 0.25},
+ "IE": {"name":"Ireland","rate": 0.23},
+ "IT": {"name":"Italy","rate": 0.22},
+ "CY": {"name":"Cyprus","rate": 0.19},
+ "LV": {"name":"Latvia","rate": 0.21},
+ "LT": {"name":"Lithuania","rate": 0.21},
+ "LU": {"name":"Luxembourg","rate": 0.17},
+ "HU": {"name":"Hungary","rate": 0.27},
+ "MT": {"name":"Malta","rate": 0.18},
+ "NL": {"name":"Netherlands","rate": 0.21},
+ "AT": {"name":"Austria","rate": 0.20},
+ "PL": {"name":"Poland","rate": 0.23},
+ "PT": {"name":"Portugal","rate": 0.23},
+ "RO": {"name":"Romania","rate": 0.24},
+ "SI": {"name":"Slovenia","rate": 0.22},
+ "SK": {"name":"Slovakia","rate": 0.20},
+ "FI": {"name":"Finland","rate": 0.24},
+ "SE": {"name":"Sweden","rate": 0.25},
+ "UK": {"name":"United Kingdom","rate": 0.20},
+ "?": {"name":"Outside EU","rate": 0.0}
}
View
@@ -8,6 +8,7 @@ var webshot = require('webshot');
var lwip = require('lwip');
var Document = require('../models/document.js').Document;
var Styleset = require('../models/styleset.js').Styleset;
+var Id = require('../models/id.js').Id;
function getEmbeddedDocument(arr, queryField, search) {
var len = arr.length;
@@ -287,4 +288,14 @@ exports.generatePreview = function (project, imagePath, next) {
exports.cleanUrlPart = function (part) {
return part.replace(/[\s\/\\#?-]+/g, "")
+}
+
+exports.getNextId = function (idName, next) {
+ Id.findOneAndUpdate({id: idName}, { $inc: { seq: 1 } }, {new: true, upsert: true}, function (err, id) {
+ if (err) {
+ //console.log(err);
+ return next(err);
+ }
+ next(null, 1000 + id.seq);
+ })
}
View
@@ -0,0 +1,10 @@
+var mongoose = require('mongoose');
+var Schema = mongoose.Schema;
+
+var IdSchema = new Schema({
+ id: { type: String, required: true },
+ seq: { type: Number, required: true }
+});
+
+
+exports.Id = mongoose.model('Id', IdSchema);
View
@@ -48,6 +48,8 @@ var UserSchema = new Schema({
amount: { type: String },
date: { type: Date, default: Date.now },
type: { type: String, enum: ['recurring', 'single'] },
+ countryCode: { type: String},
+ vatRate: { type: Number, default: 0},
description: { type: String}
}],
cancelled: { type: Boolean, default: false }
View
@@ -117,10 +117,36 @@ <h2>Upgrade to Premium</h2>
<span><p class="top-text-card">Billing country</p></span>
<p class="input-label">
<select id="billingCountry" ng-model="payment.billingCountryCode" class="billingCountry">
+ <option value="AT">Austria</option>
+ <option value="BE">Belgium</option>
+ <option value="BG">Bulgaria</option>
+ <option value="HR">Croatia</option>
+ <option value="CY">Cyprus</option>
+ <option value="CZ">Czech Republic</option>
<option value="DK">Denmark</option>
+ <option value="EE">Estonia</option>
+ <option value="FI">Finland</option>
+ <option value="FR">France</option>
<option value="DE">Germany</option>
- <option value="NO">Norway</option>
- <option value="?" class="fadedOption">Non-EU</option>
+ <option value="EL">Greece</option>
+ <option value="HU">Hungary</option>
+ <option value="IE">Ireland</option>
+ <option value="IT">Italy</option>
+ <option value="LV">Latvia</option>
+ <option value="LT">Lithuania</option>
+ <option value="LU">Luxembourg</option>
+ <option value="MT">Malta</option>
+ <option value="NL">Netherlands</option>
+ <option value="PL">Poland</option>
+ <option value="PT">Portugal</option>
+ <option value="RO">Romania</option>
+ <option value="ES">Spain</option>
+ <option value="SE">Sweden</option>
+ <option value="SK">Slovakia</option>
+ <option value="SI">Slovenia</option>
+ <option value="UK">United Kingdom</option>
+ <option disabled>──────────</option>
+ <option value="?">Outside EU</option>
</select>
</p>
<p>
@@ -639,6 +639,7 @@ li.typo .style-copy-options p {
.menu-right .insertOption {
margin: 0 0 10px 10px;
}
+
.insertOption.expanded {
height: 128px;
margin-bottom: 0;
@@ -937,10 +937,6 @@ div.m-modals.ng-hide > .modal.ng-enter.ng-enter-active {
font-family: 'Roboto', Arial, sans-serif;
}
-.fadedOption {
- color: gray;
-}
-
.paymentExpiresCVC{
width: 161px;
padding: 10px;
@@ -136,23 +136,15 @@
<div class="left-menu-options">
<form name="insertHyperlinks" class="insertHyperlinks" novalidate>
- <span class="menu-box inputfield">
- <!-- Morten's comments: Since our experiments and a bit of Googling showed that it is
- apparently (https://github.com/angular/angular.js/issues/5226) not possible to store the
- regex in the JavaScript code (controller) (this trick: http://stackoverflow.com/questions/17384909/directive-to-dynamically-create-an-ng-pattern
- only worked partially: error message was not shown for URLs like "ydyfuyydufdf"), we should at least add a comment
- explaining that this regex is the same as the one being used in project_controller.js (https://github.com/Scripler/scripler/blob/beta1/public/create/scripts/project_controller.js#L1610). -->
- <input id="hyperlinkTarget" name="hyperlinkTarget" type="text" data-ng-model="linkAddress" ng-pattern="/doc_.|^((https?):\/\/)?([w|W]{3}\.)*[a-zA-Z0-9\-\.]{1,}\.[a-zA-Z]{1,}(\.[a-zA-Z]{2,})?$/" placeholder="Target" required>
- </span>
- <div role="alert">
- <span class="nameError urlError" ng-show="insertHyperlinks.$submitted && insertHyperlinks.hyperlinkTarget.$error.pattern && !insertHyperlinks.hyperlinkTarget.$untouched">Not a valid URL</span>
- </div>
<span class="menu-box inputfield margin-top">
- <input id="hyperlinkInputBox" name="hyperlinkInputBox" type="text" data-ng-model="linkText" placeholder="Text" required>
+ <input id="linkText" type="text" data-ng-model="linkText" placeholder="Text" required>
</span>
- <span class="menu-box inputfield margin-top">
- <select data-ng-model="linkAnchor" data-ng-options="anchor.text for anchor in toc">
- <option value="">Choose internal target</option>
+ <span class="menu-box inputfield">
+ <input id="linkAddress" type="text" data-ng-model="linkAddress" data-ng-change="linkAddressChanged()" placeholder="External link" />
+ </span>
+ <span class="menu-box inputfield">
+ <select id="linkAnchor" data-ng-model="linkAnchor" data-ng-change="linkAnchorChanged()" data-ng-options="anchor.text for anchor in toc">
+ <option value="">or Choose internal target</option>

This comment has been minimized.

Show comment
Hide comment
@mortengf

mortengf Sep 27, 2015

Contributor

"Choose" -> "choose"

@mortengf

mortengf Sep 27, 2015

Contributor

"Choose" -> "choose"

</select>
</span>
<input type="submit" value="Insert hyperlink" class="button margin-top" data-ng-click="insertNewLink();">
@@ -218,6 +218,14 @@ function projectController( $scope, $location, userService, projectsService, $ht
return deferred.promise;
}
+ $scope.linkAnchorChanged = function () {
+ $scope.linkAddress = '';
+ }
+
+ $scope.linkAddressChanged = function () {
+ $scope.linkAnchor = '';
+ }
+
$scope.move = function(array, from, to) {
if (to === from) return;
@@ -480,8 +488,9 @@ function projectController( $scope, $location, userService, projectsService, $ht
if ( $scope.leftMenuShowItem != 'design' && $scope.styleEditorVisible ) {
$scope.hideStyleEditor();
}
-
- $scope.selectedStyle.scroll = true;
+ if ($scope.leftMenuShowItem == 'design') {
+ $scope.selectedStyle.scroll = true;
+ }
}
else {
$scope.hideLeftMenu();
@@ -1416,7 +1425,12 @@ function projectController( $scope, $location, userService, projectsService, $ht
$scope.insertNewLink = function() {
var type = "link";
- var link = '<a href="' + $scope.linkAddress + '">link_text</a>';
+ var link;
+ if ($scope.linkAnchor) {
+ link = '<a href="' + $scope.linkAnchor.target + '">link_text</a>';
+ } else {
+ link = '<a href="' + $scope.linkAddress + '">link_text</a>';
+ }
editorInsert( link, type);
$scope.updateProjectDocument();
$scope.linkAddress = '';
@@ -1590,27 +1604,27 @@ function projectController( $scope, $location, userService, projectsService, $ht
if(!isHyperlink){
document.getElementById("anchorInputBox").value = range;
- document.getElementById("hyperlinkInputBox").value = range;
- document.getElementById("hyperlinkTarget").value = "";
+ document.getElementById("linkText").value = range;
+ document.getElementById("linkAddress").value = "";
}
}
// onselectionchange doesn't work for Firefox, so instead we update with the old selectedContent returned by CKEditor
if(navigator.userAgent.search("Firefox")>-1){
document.getElementById("anchorInputBox").value = selectedContent;
- document.getElementById("hyperlinkInputBox").value = selectedContent;
- document.getElementById("hyperlinkTarget").value = "";
+ document.getElementById("linkText").value = selectedContent;
+ document.getElementById("linkAddress").value = "";
}
return selectedContent;
}
function editorInsert( insert, type ) {
var anchorInputContent = document.getElementById("anchorInputBox").value;
- var hyperlinkInputContent = document.getElementById("hyperlinkInputBox").value;
+ var hyperlinkInputContent = document.getElementById("linkText").value;
var editor = getEditor();
- var selectedContentRequired = (type == "anchor" || type == "link");
+ var selectedContentRequired = (type == "anchor" || type == "link");
var selectedContent = returnSelectedContent();
var validURL = true;
@@ -1622,12 +1636,12 @@ function projectController( $scope, $location, userService, projectsService, $ht
else if(type=="link" && hyperlinkInputContent!=""){
selectedContent = hyperlinkInputContent;
- }
+ }
}
// if no hyperlink text is provided, take the targetURL as the text
if(selectedContent == ""){
- selectedContent = $scope.linkAddress;
+ selectedContent = $scope.linkAddress;
}
@@ -1650,20 +1664,22 @@ function projectController( $scope, $location, userService, projectsService, $ht
}
insert = insert.replace('link_text', title);
- var regExpValidUrl = /^((https?):\/\/)?([w|W]{3}\.)*[a-zA-Z0-9\-\.]{1,}\.[a-zA-Z]{1,}(\.[a-zA-Z]{2,})?$/;
+ var regExpValidUrl = /^(https?:\/\/)?[^ "]+$/;
var isInternal = false;
var toc = $scope.toc;
- toc.forEach(function(entry) {
- if($scope.linkAddress == entry.target)isInternal = true;
- });
+ if (toc && $scope.linkAnchor && $scope.linkAnchor.target) {
+ toc.forEach(function (entry) {
+ if ($scope.linkAnchor.target == entry.target)isInternal = true;
+ });
+ }
- if($scope.linkAddress!=undefined && $scope.linkAddress.substring(0,4)!="http" && !isInternal){
+ if(!isInternal && $scope.linkAddress!=undefined && $scope.linkAddress.substring(0,4)!="http"){
insert = insert.replace($scope.linkAddress, "http://" + $scope.linkAddress);
}
- validURL = (regExpValidUrl.test($scope.linkAddress) || isInternal);
- }
+ validURL = (isInternal || regExpValidUrl.test($scope.linkAddress));

This comment has been minimized.

Show comment
Hide comment
@mortengf

mortengf Sep 27, 2015

Contributor

Could we improve this by extending the check to check that, if the link is internal, then check that the link text starts with "doc_"?

@mortengf

mortengf Sep 27, 2015

Contributor

Could we improve this by extending the check to check that, if the link is internal, then check that the link text starts with "doc_"?

+ }
//create and insert anchor/hyperlink element on the caret
if(validURL){
@@ -1692,9 +1708,9 @@ function projectController( $scope, $location, userService, projectsService, $ht
}
- $scope.$watch('linkAnchor', function(newValue, oldValue) {
+ /*$scope.$watch('linkAnchor', function(newValue, oldValue) {

This comment has been minimized.

Show comment
Hide comment
@mortengf

mortengf Sep 27, 2015

Contributor

Remove commented-out code?

@mortengf

mortengf Sep 27, 2015

Contributor

Remove commented-out code?

var hasText = false;
- if(hyperlinkInputBox.value!=""){
+ if(linkText.value!=""){
hasText = true;
}
if (newValue !== oldValue) {
@@ -1703,10 +1719,10 @@ function projectController( $scope, $location, userService, projectsService, $ht
if(!hasText){
$scope.linkText = newValue.text;
}
- }
+ }
$scope.focusEditor();
- });
+ });*/
$scope.$onRootScope('user:registered', function( event, user ) {
if ( user._id ) {
@@ -1796,8 +1812,33 @@ function projectController( $scope, $location, userService, projectsService, $ht
// fetching content of anchor
content = element.$.innerHTML;
- document.getElementById("hyperlinkInputBox").value = content;
- document.getElementById("hyperlinkTarget").value = target;
+ var toc = $scope.toc;
+ var tocEntry = -1;
+ if (toc) {
+ for (var i = 0; i < toc.length; i++) {
+ if (toc[i].target == target) {
+ tocEntry = i;
+ break;
+ }
+ }
+ }
+
+ //$scope.$apply(function(){

This comment has been minimized.

Show comment
Hide comment
@mortengf

mortengf Sep 27, 2015

Contributor

Do you know why this was inside a $scope.apply() call before? How can it not matter that it is not anymore?

@mortengf

mortengf Sep 27, 2015

Contributor

Do you know why this was inside a $scope.apply() call before? How can it not matter that it is not anymore?

+ if (tocEntry>=0) {
+ //scope.linkAddress = "";
+ $scope.linkAnchor = target;
+ document.getElementById("linkAnchor").value = tocEntry;
+ document.getElementById("linkAddress").value = "";
+ } else {
+ //scope.linkAddress = target;
+ $scope.linkAnchor = "";
+ document.getElementById("linkAnchor").value = "";
+ document.getElementById("linkAddress").value = target;
+ }
+ //scope.linkText = content;
+ document.getElementById("linkText").value = content;
+
+ //});
return false;
}
Oops, something went wrong.

0 comments on commit e0b8898

Please sign in to comment.