11import _ from 'underscore' ;
2- import { markdownTable as Table } from 'markdown-table' ;
2+ import { markdownTable as Table } from 'markdown-table'
33import Base from './base.js' ;
44import { SwissQRBill } from "swissqrbill/svg" ;
55
@@ -18,7 +18,9 @@ class invoice extends Base {
1818 this . invoiceCurrency = this . config . get ( 'invoiceCurrency' ) ;
1919 this . invoiceCurrencyPerHour = this . config . get ( 'invoiceCurrencyPerHour' ) ;
2020 this . invoiceVAT = this . config . get ( 'invoiceVAT' ) ;
21+ this . invoiceText = this . config . get ( 'invoiceText' ) ? this . config . get ( 'invoiceText' ) : '' ;
2122 this . invoicePositionText = this . config . get ( 'invoicePositionText' ) ;
23+ this . invoicePositionExtra = this . config . get ( 'invoicePositionExtra' ) ;
2224 this . invoicePositionExtraTexts = this . config . get ( 'invoicePositionExtraText' ) ;
2325 this . invoicePositionExtraValues = this . config . get ( 'invoicePositionExtraValue' ) . map (
2426 ( v ) => {
@@ -28,14 +30,33 @@ class invoice extends Base {
2830 this . invoicePositionExtraTotal = 0.0 ;
2931 this . invoicePositionExtraValues . forEach ( v => ( this . invoicePositionExtraTotal += v ) ) ;
3032
33+ this . invoiceCurrencyMaxUnit = this . config . get ( 'invoiceCurrencyMaxUnit' ) ;
34+ this . invoiceTimeMaxUnit = this . config . get ( 'invoiceTimeMaxUnit' ) ;
3135
36+ this . invoicePositions = { } ; //key=iid, value=[text, total H, Rate, Total]
3237
33- this . invoiceCurrencyMaxUnit = this . config . get ( 'invoiceCurrencyMaxUnit' ) ;
34- this . totalhForInvoice = ( this . spent - this . spentFree - ( this . spentHalfPrice * 0.5 ) ) / 3600.0 ;
35- // round subtotals to 0.01 and total to invoiceCurrencyMaxUnit.
36- let invoiceTotal = this . totalhForInvoice * this . invoiceCurrencyPerHour + this . invoicePositionExtraTotal ;
37- this . totalForInvoiceH = Math . round ( this . totalhForInvoice * this . invoiceCurrencyPerHour * 100 ) * 0.01 ;
38- this . totalForInvoiceExkl = Math . round ( invoiceTotal * 100 ) * 0.01 ;
38+ Object . keys ( this . daysNew ) . forEach (
39+ k => {
40+ let day = this . daysNew [ k ] ;
41+ day . forEach (
42+ ( dayReport ) => {
43+ let iid = dayReport . getIid ( ) ;
44+ if ( ! this . invoicePositions [ iid ] ) {
45+ this . invoicePositions [ iid ] = [ dayReport . getTitle ( ) , 0.0 , this . invoiceCurrencyPerHour * dayReport . getChargeRatio ( ) , 0.0 ] ;
46+ }
47+ this . invoicePositions [ iid ] [ 1 ] += dayReport . getSpent ( this . invoiceTimeMaxUnit ) / 3600 ;
48+ this . invoicePositions [ iid ] [ 3 ] = Math . round ( ( this . invoicePositions [ iid ] [ 1 ] * this . invoicePositions [ iid ] [ 2 ] ) * 100 ) * 0.01 ;
49+ }
50+ ) ;
51+ } ) ;
52+
53+ let invoiceTotal = this . invoicePositionExtraTotal ;
54+ Object . keys ( this . invoicePositions ) . forEach (
55+ k => {
56+ invoiceTotal += this . invoicePositions [ k ] [ 3 ] ;
57+ }
58+ )
59+ this . totalForInvoiceExkl = invoiceTotal ;
3960 this . totalForInvoiceMwst = Math . round ( invoiceTotal * this . invoiceVAT * 100 ) * 0.01 ;
4061 this . totalForInvoice = Math . round ( ( this . totalForInvoiceExkl + this . totalForInvoiceMwst ) / this . invoiceCurrencyMaxUnit ) * this . invoiceCurrencyMaxUnit ;
4162 }
@@ -135,16 +156,32 @@ class invoice extends Base {
135156 svg . instance . viewBox ( 0 , 0 , 740 , 420 )
136157 svg . instance . height ( "" ) ;
137158 svg . instance . width ( "" ) ;
159+ let positions = "" ;
160+ let positionIids = Object . keys ( this . invoicePositions ) ;
161+ positionIids . sort ( ) ;
162+ positionIids . forEach (
163+ k => {
164+ // text, total H, Rate, Total
165+ let position = this . invoicePositions [ k ] ;
166+ positions +=
167+ `<div class="positionDesc">${ position [ 0 ] } : ${ position [ 1 ] . toFixed ( 2 ) } h (${ position [ 2 ] } ${ this . invoiceCurrency } /h)</div>
168+ <div class="positionValue">${ this . invoiceCurrency } ${ position [ 3 ] . toFixed ( 2 ) } </div>
169+ ` ;
170+ }
171+ ) ;
172+
138173 let extra = "" ;
139- if ( this . invoicePositionExtraTotal > 0 ) {
174+ if ( this . invoicePositionExtra || this . invoicePositionExtraTotal > 0 ) {
175+ if ( this . invoicePositionExtra ) {
176+ extra += `<div class="position">${ this . invoicePositionExtra } </div>` ;
177+ }
140178 for ( var i in this . invoicePositionExtraTexts ) {
141179 extra +=
142180 `
143181 <div class="positionDesc">${ this . invoicePositionExtraTexts [ i ] } </div>
144182 <div class="positionValue">${ this . invoiceCurrency } ${ this . invoicePositionExtraValues [ i ] . toFixed ( 2 ) } </div>
145183 ` ;
146184 }
147-
148185 }
149186
150187 this . out +=
@@ -158,12 +195,14 @@ class invoice extends Base {
158195
159196# ${ this . config . get ( 'invoiceTitle' ) }
160197
161- ${ opening }
198+ ${ opening } ${ this . invoiceText }
162199
163200<div class="positionBox">
164- <div class="positionDesc ">${ this . invoicePositionText } ( ${ this . totalhForInvoice . toFixed ( 2 ) } Stunden zu ${ this . invoiceCurrencyPerHour } ${ this . invoiceCurrency } ) </div>
165- <div class="positionValue"> ${ this . invoiceCurrency } ${ this . totalForInvoiceH . toFixed ( 2 ) } </div>
201+ <div class="position ">${ this . invoicePositionText } </div>
202+ ${ positions }
166203${ extra }
204+ <div class="positionDescTot">Summe Netto</div>
205+ <div class="positionValueTot">${ this . invoiceCurrency } ${ this . totalForInvoiceExkl . toFixed ( 2 ) } </div>
167206<div class="positionDesc">MWST (${ this . invoiceVAT * 100 } %)</div>
168207<div class="positionValue">${ this . invoiceCurrency } ${ this . totalForInvoiceMwst . toFixed ( 2 ) } </div>
169208<div class="positionDescTot">Rechnungsbetrag inkl. MWST</div>
@@ -175,16 +214,52 @@ ${this.config.get('invoiceSettings').bankAccount}
175214${ closing }
176215
177216
178- <div class="qr-div">${ svg . toString ( ) } </div>
217+ <div class="qr-div">${ svg . toString ( ) } </div>`
179218
219+ }
220+
221+ makeIssues ( ) {
222+ }
223+
224+ makeMergeRequests ( ) {
225+ }
226+
227+ makeRecords ( ) {
228+ this . out += `
180229
181230<h1 style="page-break-before: always;"><br/><br/>Stundenrapport</h1>` ;
182231
183- this . headline ( 'Total' ) ;
184- //this.write(stats.substr(1));
185- this . write ( this . config . toHumanReadable ( this . spent , 'stats' ) ) ;
186- this . write ( this . config . toHumanReadable ( this . spentHalfPrice , 'statsHalfPrice' ) ) ;
187- this . write ( this . config . toHumanReadable ( this . spentFree , 'statsFree' ) ) ;
232+ let timesNew = [ [ 'Datum' , 'Beschreibung' , 'Stunden' ] ] ;
233+ let daysNew = Object . keys ( this . daysNew ) ;
234+ daysNew . sort ( ) ;
235+ daysNew . forEach (
236+ k => {
237+ let day = this . daysNew [ k ] ;
238+ day . forEach (
239+ ( dayReport ) => {
240+ let notesLi = "" ;
241+
242+ dayReport . getNotes ( ) . forEach (
243+ ( note ) => ( notesLi += `<li>${ note } </li>` ) ) ;
244+ if ( notesLi !== "" ) {
245+ notesLi = `<ul>${ notesLi } </ul>` ;
246+ }
247+ timesNew . push ( [ dayReport . getDate ( ) . format ( this . config . get ( 'dateFormat' ) ) ,
248+ dayReport . getTitle ( ) + notesLi ,
249+ this . config . toHumanReadable ( dayReport . getSpent ( this . invoiceTimeMaxUnit ) , 'records' )
250+ ] ) ;
251+ }
252+ ) ;
253+ } ) ;
254+ this . write ( `<style>
255+ table th:first-of-type { width: 12%; }
256+ table th:nth-of-type(2) { width: 78%; }
257+ table th:nth-of-type(3) { width: 10%; }
258+ </style>` ) ;
259+
260+ this . write ( Table ( timesNew , { align : [ 'l' , 'l' , 'r' ] } ) ) ;
261+
262+
188263
189264 // warnings
190265 let warnings = '' ;
@@ -201,58 +276,6 @@ ${closing}
201276 }
202277 }
203278
204- makeIssues ( ) {
205- this . headline ( 'Issues' ) ;
206-
207- if ( this . report . issues . length === 0 )
208- return this . warning ( 'No issues found' ) ;
209-
210- let issues = [ this . config . get ( 'issueColumns' ) . map ( c => c . replace ( '_' , ' ' ) ) ] ;
211- this . report . issues . forEach ( issue => issues . push ( this . prepare ( issue , this . config . get ( 'issueColumns' ) ) ) ) ;
212-
213- this . write ( Table ( issues ) ) ;
214- }
215-
216- makeMergeRequests ( ) {
217- this . headline ( 'Merge Requests' ) ;
218-
219- if ( this . report . mergeRequests . length === 0 )
220- return this . warning ( 'No merge requests found' ) ;
221-
222- let mergeRequests = [ this . config . get ( 'mergeRequestColumns' ) . map ( c => c . replace ( '_' , ' ' ) ) ] ;
223- this . report . mergeRequests . forEach ( mergeRequest => mergeRequests . push ( this . prepare ( mergeRequest , this . config . get ( 'mergeRequestColumns' ) ) ) ) ;
224-
225- this . write ( Table ( mergeRequests ) ) ;
226- }
227-
228- makeRecords ( ) {
229- this . out += `
230-
231- <h1 style="page-break-before: always;"><br/><br/>Stundenrapport detailliert</h1>` ;
232- this . headline ( 'Details' ) ;
233-
234- let times = [ [ 'date' , 'iid' , 'time' ] ] ;
235- let days = Object . keys ( this . days ) ;
236- days . sort ( ) ;
237- days . forEach (
238- k => {
239- let day = this . days [ k ] ;
240- let refD = this . daysMoment [ k ] . format ( this . config . get ( 'dateFormat' ) ) ;
241- let projects = Object . keys ( day ) ;
242- projects . forEach (
243- p => {
244- let iids = Object . keys ( day [ p ] ) ;
245- iids . sort ( ) ;
246- iids . forEach (
247- iid => {
248- times . push ( [ refD , iid , this . config . toHumanReadable ( day [ p ] [ iid ] , 'records' ) ] ) ;
249- } ) ;
250- } ) ;
251- } ) ;
252- //let times = [this.config.get('recordColumns').map(c => c.replace('_', ' '))];
253- //this.times.forEach(time => times.push(this.prepare(time, this.config.get('recordColumns'))));
254- this . write ( Table ( times ) ) ;
255- }
256279}
257280
258281export default invoice ;
0 commit comments