3092-module_transactions #740

Merged
joan merged 41 commits from 3092-module_transactions into dev 2021-10-18 07:42:24 +00:00
14 changed files with 323 additions and 93 deletions
Showing only changes of commit b9460723f8 - Show all commits

View File

@ -19,28 +19,42 @@
ng-if="$ctrl.displayControls">
</vn-button>
</div>
<div class="weekdays">
<section
ng-repeat="day in ::$ctrl.weekDays"
translate-attr="::{title: day.name}"
ng-click="$ctrl.selectWeekDay($event, day.index)">
<span>{{::day.localeChar}}</span>
</section>
<div id="days-header" ng-class="{'hide-weeks': $ctrl.hideWeeks}">
<div class="week-numbers" ng-if="!$ctrl.hideWeeks"></div>
<div class="weekdays">
<section
ng-repeat="day in ::$ctrl.weekDays"
translate-attr="::{title: day.name}"
ng-click="$ctrl.selectWeekDay($event, day.index)">
<span>{{::day.localeChar}}</span>
</section>
</div>
</div>
<div
class="days"
ng-class="{'hide-contiguous': $ctrl.hideContiguous}">
<section
ng-repeat="day in $ctrl.days"
class="day"
ng-class="::$ctrl.getDayClasses(day)"
vn-repeat-last
on-last="$ctrl.repeatLast()">
<div
class="day-number"
ng-click="$ctrl.select($event, day)">
{{::day | date: 'd'}}
</div>
</section>
<div id="days-container" ng-class="{'hide-weeks': $ctrl.hideWeeks}">
<div class="weeks" ng-if="!$ctrl.hideWeeks">
<section ng-repeat="week in $ctrl.weekNumbers"
class="day">
<div class="day-number">
{{::week}}
</div>
</section>
</div>
<div
class="days"
ng-class="{'hide-contiguous': $ctrl.hideContiguous}">
<section
ng-repeat="day in $ctrl.days"
class="day"
ng-class="::$ctrl.getDayClasses(day)"
vn-repeat-last
on-last="$ctrl.repeatLast()">
<div
class="day-number"
ng-click="$ctrl.select($event, day)">
{{::day | date: 'd'}}
</div>
</section>
</div>
</div>
</div>

View File

@ -12,11 +12,12 @@ import './style.scss';
* @event move Emitted when month changes
*/
export default class Calendar extends FormInput {
constructor($element, $scope, vnWeekDays) {
constructor($element, $scope, vnWeekDays, moment) {
super($element, $scope);
this.weekDays = vnWeekDays.locales;
this.defaultDate = new Date();
this.displayControls = true;
this.moment = moment;
}
/**
@ -54,15 +55,23 @@ export default class Calendar extends FormInput {
);
}
lastDay() {
return new Date(
this.defaultDate.getFullYear(),
this.defaultDate.getMonth() + 1,
0
).getDate();
}
/**
* Repaints the calendar.
*/
repaint() {
const firstWeekday = this.firstDay(this.defaultDate).getDay() - 1;
let weekdayOffset = firstWeekday >= 0 ? firstWeekday : 6;
this.weekdayOffset = firstWeekday >= 0 ? firstWeekday : 6;
let dayIndex = new Date(this.defaultDate.getTime());
dayIndex.setDate(1 - weekdayOffset);
dayIndex.setDate(1 - this.weekdayOffset);
this.days = [];
@ -70,27 +79,55 @@ export default class Calendar extends FormInput {
this.days.push(new Date(dayIndex.getTime()));
dayIndex.setDate(dayIndex.getDate() + 1);
}
this.getWeekdays();
}
getWeekdays() {
if (!this.moment) return;
const totalSlots = this.lastDay() + this.weekdayOffset;
const weeks = Math.ceil(totalSlots / 7);
const dated = this.moment(this.defaultDate);
const firstWeekNumber = dated.set('date', 1).isoWeek();
const weekNumbers = [];
for (let w = 0; w < weeks; w++) {
let weekNumber = firstWeekNumber;
if (dated.get('month') == 0 && firstWeekNumber > 1 && w > 0)
weekNumber = 0;
weekNumbers.push(weekNumber + w);
}
this.weekNumbers = weekNumbers;
}
/**
* Gets CSS classes to apply to the specified day.
*
* @param {Date} day The day
* @param {Date} date The date
* @return {Object} The CSS classes to apply
*/
getDayClasses(day) {
let wday = day.getDay();
let month = day.getMonth();
getDayClasses(date) {
let day = date.getDate();
let wday = date.getDay();
let month = date.getMonth();
const currentDay = new Date().getDate();
const currentMonth = new Date().getMonth();
let classes = {
today: day === currentDay && month === currentMonth,
weekend: wday === 6 || wday === 0,
previous: month < this.month,
current: month == this.month,
next: month > this.month,
event: this.hasEvents({$day: day})
event: this.hasEvents({$day: date})
};
let userClass = this.getClass({$day: day});
let userClass = this.getClass({$day: date});
if (userClass) classes[userClass] = true;
return classes;
@ -181,7 +218,7 @@ export default class Calendar extends FormInput {
}
}
}
Calendar.$inject = ['$element', '$scope', 'vnWeekDays'];
Calendar.$inject = ['$element', '$scope', 'vnWeekDays', 'moment'];
ngModule.vnComponent('vnCalendar', {
template: require('./index.html'),
@ -193,6 +230,7 @@ ngModule.vnComponent('vnCalendar', {
formatDay: '&?',
displayControls: '<?',
hideYear: '<?',
hideContiguous: '<?'
hideContiguous: '<?',
hideWeeks: '<?'
}
});

View File

@ -19,7 +19,14 @@
color: inherit;
}
}
& > .weekdays {
& #days-header {
flex-direction: row;
display: flex
}
& #days-header > .week-numbers {
width: 10%
}
& #days-header > .weekdays {
display: flex;
color: $color-font-secondary;
margin-bottom: 8px;
@ -27,17 +34,49 @@
font-weight: bold;
font-size: .8rem;
text-align: center;
width: 90%;
& > section {
width: 14.28%;
cursor: pointer;
}
}
& > .days {
& #days-header.hide-weeks {
& > .weekdays {
width: 100%
}
}
& > #days-container {
flex-direction: row;
display: flex
}
& > #days-container > .weeks {
display: flex;
flex-direction: column;
color: $color-font-secondary;
font-weight: bold;
font-size: .8rem;
width: 10%;
& > .day {
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
}
& #days-container.hide-weeks {
& > .days {
width: 100%
}
}
#days-container > .days {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
flex-wrap: wrap;
width: 90%;
& > .day {
width: 14.28%;
@ -46,6 +85,17 @@
justify-content: center;
align-items: center;
&.today {
color: $color-font-bg;
& > .day-number {
border: 2px solid $color-font-link;
&:hover {
background-color: lighten($color-font-link, 20%);
opacity: .8
}
}
}
&.weekend {
color: $color-font-secondary;
}

View File

@ -9,13 +9,15 @@ import 'angular-translate-loader-partial';
import '@uirouter/angularjs';
import 'mg-crud';
import 'oclazyload';
import 'angular-moment';
export const ngDeps = [
'ngAnimate',
'pascalprecht.translate',
'ui.router',
'mgCrud',
'oc.lazyLoad'
'oc.lazyLoad',
'angularMoment'
];
import * as validator from 'validator';

View File

@ -12,6 +12,7 @@
"@uirouter/angularjs": "^1.0.20",
"angular": "^1.7.5",
"angular-animate": "^1.7.8",
"angular-moment": "^1.3.0",
"angular-translate": "^2.18.1",
"angular-translate-loader-partial": "^2.18.1",
"croppie": "^2.6.5",
@ -51,6 +52,17 @@
"resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.8.2.tgz",
"integrity": "sha512-Jbr9+grNMs9Kj57xuBU3Ju3NOPAjS1+g2UAwwDv7su1lt0/PLDy+9zEwDiu8C8xJceoTbmBNKiWGPJGBdCQLlA=="
},
"node_modules/angular-moment": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/angular-moment/-/angular-moment-1.3.0.tgz",
"integrity": "sha512-KG8rvO9MoaBLwtGnxTeUveSyNtrL+RNgGl1zqWN36+HDCCVGk2DGWOzqKWB6o+eTTbO3Opn4hupWKIElc8XETA==",
"dependencies": {
"moment": ">=2.8.0 <3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/angular-translate": {
"version": "2.18.4",
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.18.4.tgz",
@ -115,6 +127,14 @@
"angular": "^1.6.1"
}
},
"node_modules/moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
"engines": {
"node": "*"
}
},
"node_modules/oclazyload": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/oclazyload/-/oclazyload-0.6.3.tgz",
@ -182,6 +202,14 @@
"resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.8.2.tgz",
"integrity": "sha512-Jbr9+grNMs9Kj57xuBU3Ju3NOPAjS1+g2UAwwDv7su1lt0/PLDy+9zEwDiu8C8xJceoTbmBNKiWGPJGBdCQLlA=="
},
"angular-moment": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/angular-moment/-/angular-moment-1.3.0.tgz",
"integrity": "sha512-KG8rvO9MoaBLwtGnxTeUveSyNtrL+RNgGl1zqWN36+HDCCVGk2DGWOzqKWB6o+eTTbO3Opn4hupWKIElc8XETA==",
"requires": {
"moment": ">=2.8.0 <3.0.0"
}
},
"angular-translate": {
"version": "2.18.4",
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.18.4.tgz",
@ -233,6 +261,11 @@
"angular": "^1.6.1"
}
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"oclazyload": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/oclazyload/-/oclazyload-0.6.3.tgz",

View File

@ -12,6 +12,7 @@
"@uirouter/angularjs": "^1.0.20",
"angular": "^1.7.5",
"angular-animate": "^1.7.8",
"angular-moment": "^1.3.0",
"angular-translate": "^2.18.1",
"angular-translate-loader-partial": "^2.18.1",
"croppie": "^2.6.5",

View File

@ -78,6 +78,11 @@
</vn-avatar>
<span translate>Festive</span>
</vn-chip>
<vn-chip>
<vn-avatar class="today">
</vn-avatar>
<span translate>Current day</span>
</vn-chip>
</div>
</div>
</vn-side-menu>

View File

@ -7,4 +7,5 @@ of: de
days: días
Choose an absence type from the right menu: Elige un tipo de ausencia desde el menú de la derecha
To start adding absences, click an absence type from the right menu and then on the day you want to add an absence: Para empezar a añadir ausencias, haz clic en un tipo de ausencia desde el menu de la derecha y después en el día que quieres añadir la ausencia
You can just add absences within the current year: Solo puedes añadir ausencias dentro del año actual
You can just add absences within the current year: Solo puedes añadir ausencias dentro del año actual
Current day: Día actual

View File

@ -41,12 +41,20 @@ vn-worker-calendar {
border-color: rgba(0, 0, 0, 0.3);
border-bottom: 1px solid rgba(0, 0, 0, 0.3);
}
.festive {
background-color:white;
border: 2px solid $color-alert;
vn-avatar.festive,
vn-avatar.today {
background-color: $color-font-dark;
width: 24px;
min-width: 24px;
height: 24px
}
vn-avatar.festive {
border: 2px solid $color-alert
}
vn-avatar.today {
border: 2px solid $color-font-link
}
}

View File

@ -118,20 +118,20 @@
</table>
<!-- End of sales block -->
<div class="columns">
<div class="columns vn-mb-ml">
<!-- Services block-->
<div class="size100 no-page-break" v-if="services.length > 0">
<h2>{{$t('services')}}</h2>
<h2>{{$t('services.title')}}</h2>
<table class="column-oriented">
<thead>
<tr>
<th width="5%"></th>
<th class="number">{{$t('quantity')}}</th>
<th width="50%">{{$t('concept')}}</th>
<th class="number">{{$t('price')}}</th>
<th class="number">{{$t('services.theader.quantity')}}</th>
<th width="50%">{{$t('services.theader.concept')}}</th>
<th class="number">{{$t('services.theader.price')}}</th>
<th class="centered" width="5%"></th>
<th class="centered">{{$t('vat')}}</th>
<th class="number">{{$t('amount')}}</th>
<th class="centered">{{$t('services.theader.vat')}}</th>
<th class="number">{{$t('services.theader.amount')}}</th>
</tr>
</thead>
<tbody>
@ -148,25 +148,26 @@
<tfoot>
<tr>
<td colspan="6" class="font bold">
<span class="pull-right">{{$t('subtotal')}}</span>
<span class="pull-right">{{$t('services.tfoot.subtotal')}}</span>
</td>
<td class="number">{{serviceTotal | currency('EUR', $i18n.locale)}}</td>
</tr>
</tfoot>
</table>
<span class="font gray">* {{ $t('services.warning') }}</span>
</div>
<!-- End of services block -->
</div>
<div class="columns">
<!-- Packages block -->
<div id="packagings" class="size100 no-page-break" v-if="packagings.length > 0">
<h2>{{$t('packagings')}}</h2>
<h2>{{$t('packagings.title')}}</h2>
<table class="column-oriented">
<thead>
<tr>
<th>{{$t('reference')}}</th>
<th class="number">{{$t('quantity')}}</th>
<th wihth="75%">{{$t('concept')}}</th>
<th>{{$t('packagings.theader.reference')}}</th>
<th class="number">{{$t('packagings.theader.quantity')}}</th>
<th wihth="75%">{{$t('packagings.theader.concept')}}</th>
</tr>
</thead>
<tbody>
@ -183,21 +184,18 @@
<div class="columns vn-mt-xl">
<!-- Taxes block -->
<div id="taxes" class="size50 pull-right no-page-break" v-if="taxes">
<!-- <h2>{{$t('taxBreakdown')}}</h2> -->
<table class="column-oriented">
<thead>
<tr>
<th colspan="4">{{$t('taxBreakdown')}}</th>
<th colspan="4">{{$t('taxes.title')}}</th>
</tr>
</thead>
<thead class="light">
<tr>
<th width="45%">{{$t('type')}}</th>
<th width="25%" class="number">
{{$t('taxBase')}}
</th>
<th>{{$t('tax')}}</th>
<th class="number">{{$t('fee')}}</th>
<th width="45%">{{$t('taxes.theader.type')}}</th>
<th width="25%" class="number">{{$t('taxes.theader.taxBase')}}</th>
<th>{{$t('taxes.theader.tax')}}</th>
<th class="number">{{$t('taxes.theader.fee')}}</th>
</tr>
</thead>
<tbody>

View File

@ -12,17 +12,37 @@ price: PSP/u
discount: Disc.
vat: VAT
amount: Amount
type: Type
taxBase: Tax base
tax: Tax
fee: Fee
total: Total
subtotal: Subtotal
taxBreakdown: Tax breakdown
packagings: Buckets and packaging
services: Services
vatType: VAT Type
digitalSignature: Digital signature
ticket: Delivery note {0}
plantPassport: Plant passport
packages: Packages
packages: Packages
services:
title: Services
theader:
quantity: Qty.
concept: Concept
price: PSP/u
vat: VAT
amount: Amount
tfoot:
subtotal: Subtotal
warning: Deposit packaging will be invoiced if they have not been returned after 30 days of their delivery
packagings:
title: Buckets and packaging
theader:
reference: Reference
quantity: Quantity
concept: Concept
taxes:
title: Tax breakdown
theader:
type: Type
taxBase: Tax base
tax: Tax
fee: Fee
tfoot:
subtotal: Subtotal
total: Total

View File

@ -12,17 +12,37 @@ price: PVP/u
discount: Dto.
vat: IVA
amount: Importe
type: Tipo
taxBase: Base imp.
tax: Tasa
fee: Cuota
total: Total
subtotal: Subtotal
taxBreakdown: Desglose impositivo
packagings: Cubos y embalajes
services: Servicios
vatType: Tipo de IVA
digitalSignature: Firma digital
ticket: Albarán {0}
plantPassport: Pasaporte fitosanitario
packages: Bultos
packages: Bultos
services:
title: Servicios
theader:
quantity: Cantidad
concept: Concepto
price: PVP/u
vat: IVA
amount: Importe
tfoot:
subtotal: Subtotal
warning: Los embalajes en depósito se facturarán si no han sido devueltos pasados 30 dias de su entrega
packagings:
title: Cubos y embalajes
theader:
reference: Referencia
quantity: Cantidad
concept: Concepto
taxes:
title: Desglose impositivo
theader:
type: Tipo
taxBase: Base imp.
tax: Tasa
fee: Cuota
tfoot:
subtotal: Subtotal
total: Total

View File

@ -12,17 +12,37 @@ price: PRIX/u
discount: Remise
vat: TVA
amount: Montant
type: Type
taxBase: Base imposable
tax: Taxe
fee: Quote
total: Total
subtotal: Total partiel
taxBreakdown: Répartition taxes
packagings: Bacs et emballages
services: Service
vatType: Type de TVA
digitalSignature: Signature numérique
ticket: BL {0}
plantPassport: Passeport phytosanitaire
packages: Paquets
packages: Paquets
services:
title: Service
theader:
quantity: Quantité
concept: Concept
price: PRIX/u
vat: TVA
amount: Montant
tfoot:
subtotal: Total partiel
warning: Les emballages de consigne seront facturés s'ils n'ont pas été retournés après 30 jours de leur livraison
packagings:
title: Bacs et emballages
theader:
reference: Référence
quantity: Quantité
concept: Concept
taxes:
title: Répartition taxes
theader:
type: Type
taxBase: Base imposable
tax: Taxe
fee: Quote
tfoot:
subtotal: Total partiel
total: Total

View File

@ -12,17 +12,37 @@ price: PVP/u
discount: Dto.
vat: IVA
amount: Importe
type: Tipo
taxBase: Base imp.
tax: Taxa
fee: Quota
total: Total
subtotal: Sub-total
taxBreakdown: Desglose impositivo
packagings: Baldes e Embalagens
services: Serviços
vatType: Tipo de IVA
digitalSignature: Assinatura digital
ticket: Nota de Entrega {0}
plantPassport: Passaporte vegetal
packages: Pacotes
packages: Pacotes
services:
title: Serviços
theader:
quantity: Quantidade
concept: Conceito
price: PVP/u
vat: IVA
amount: Quantia
tfoot:
subtotal: Subtotal
warning: Os pacotes do armazém serão cobrados se não forem devolvidos 30 dias após a entrega
packagings:
title: Baldes e Embalagens
theader:
reference: Referência
quantity: Quantidade
concept: Conceito
taxes:
title: Repartição de impostos
theader:
type: Cara
taxBase: Tributável
tax: Taxa
fee: Compartilhado
tfoot:
subtotal: Subtotal
total: Total