5334-editDepartment #1521

Merged
carlossa merged 84 commits from 5334-editDepartment into dev 2023-07-06 07:09:06 +00:00
13 changed files with 203 additions and 120 deletions
Showing only changes of commit 3d93043b98 - Show all commits

View File

@ -2842,7 +2842,8 @@ INSERT INTO `vn`.`workerConfig` (`id`, `businessUpdated`, `roleFk`, `payMethodFk
INSERT INTO `vn`.`ticketRefund`(`refundTicketFk`, `originalTicketFk`) INSERT INTO `vn`.`ticketRefund`(`refundTicketFk`, `originalTicketFk`)
VALUES VALUES
(1, 12); (1, 12),
(8, 10);
INSERT INTO `vn`.`deviceProductionModels` (`code`) INSERT INTO `vn`.`deviceProductionModels` (`code`)
VALUES VALUES

View File

@ -294,6 +294,7 @@
"Invalid NIF for VIES": "Invalid NIF for VIES", "Invalid NIF for VIES": "Invalid NIF for VIES",
"Ticket does not exist": "Este ticket no existe", "Ticket does not exist": "Este ticket no existe",
"Ticket is already signed": "Este ticket ya ha sido firmado", "Ticket is already signed": "Este ticket ya ha sido firmado",
"You can only add negative amounts in refund tickets": "Solo se puede añadir cantidades negativas en tickets abono",
"Fecha fuera de rango": "Fecha fuera de rango", "Fecha fuera de rango": "Fecha fuera de rango",
"Error while generating PDF": "Error al generar PDF", "Error while generating PDF": "Error al generar PDF",
"Error when sending mail to client": "Error al enviar el correo al cliente", "Error when sending mail to client": "Error al enviar el correo al cliente",

View File

@ -14,7 +14,7 @@ module.exports = Self => {
Self.validatesPresenceOf('street', { Self.validatesPresenceOf('street', {
message: 'Street cannot be empty' message: 'Street cannot be empty'
}); });
Self.validatesPresenceOf('city', { Self.validatesPresenceOf('city', {
message: 'City cannot be empty' message: 'City cannot be empty'
}); });
@ -282,7 +282,7 @@ module.exports = Self => {
await Self.changeCredit(ctx, finalState, changes); await Self.changeCredit(ctx, finalState, changes);
// Credit management changes // Credit management changes
if (orgData?.rating != changes.rating || orgData?.recommendedCredit != changes.recommendedCredit) if (changes?.rating || changes?.recommendedCredit)
await Self.changeCreditManagement(ctx, finalState, changes); await Self.changeCreditManagement(ctx, finalState, changes);
const oldInstance = {}; const oldInstance = {};

View File

@ -110,4 +110,53 @@ describe('sale updateQuantity()', () => {
throw e; throw e;
} }
}); });
it('should throw an error if the quantity is negative and it is not a refund ticket', async() => {
const ctx = {
req: {
accessToken: {userId: 1},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
const saleId = 17;
const newQuantity = -10;
const tx = await models.Sale.beginTransaction({});
let error;
try {
const options = {transaction: tx};
await models.Sale.updateQuantity(ctx, saleId, newQuantity, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error).toEqual(new Error('You can only add negative amounts in refund tickets'));
});
it('should update a negative quantity when is a ticket refund', async() => {
const tx = await models.Sale.beginTransaction({});
const saleId = 13;
const newQuantity = -10;
try {
const options = {transaction: tx};
await models.Sale.updateQuantity(ctx, saleId, newQuantity, options);
const modifiedLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, options);
expect(modifiedLine.quantity).toEqual(newQuantity);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
}); });

View File

@ -68,6 +68,13 @@ module.exports = Self => {
if (newQuantity > sale.quantity && !isRoleAdvanced) if (newQuantity > sale.quantity && !isRoleAdvanced)
throw new UserError('The new quantity should be smaller than the old one'); throw new UserError('The new quantity should be smaller than the old one');
const ticketRefund = await models.TicketRefund.findOne({
where: {refundTicketFk: sale.ticketFk},
fields: ['id']}
, myOptions);
if (newQuantity < 0 && !ticketRefund)
throw new UserError('You can only add negative amounts in refund tickets');
const oldQuantity = sale.quantity; const oldQuantity = sale.quantity;
const result = await sale.updateAttributes({quantity: newQuantity}, myOptions); const result = await sale.updateAttributes({quantity: newQuantity}, myOptions);

View File

@ -3,27 +3,35 @@
data="absenceTypes" data="absenceTypes"
auto-load="true"> auto-load="true">
</vn-crud-model> </vn-crud-model>
<div class="vn-w-lg"> <div ng-if="$ctrl.worker.hasWorkCenter">
<vn-card class="vn-pa-sm calendars"> <div class="vn-w-lg">
<vn-icon ng-if="::$ctrl.isSubordinate" icon="info" color-marginal <vn-card class="vn-pa-sm calendars">
vn-tooltip="To start adding absences, click an absence type from the right menu and then on the day you want to add an absence"> <vn-icon ng-if="::$ctrl.isSubordinate" icon="info" color-marginal
</vn-icon> vn-tooltip="To start adding absences, click an absence type from the right menu and then on the day you want to add an absence">
<vn-calendar </vn-icon>
ng-repeat="month in $ctrl.months" <vn-calendar
data="$ctrl.events" ng-repeat="month in $ctrl.months"
default-date="month" data="$ctrl.events"
format-day="$ctrl.formatDay($day, $element)" default-date="month"
display-controls="false" format-day="$ctrl.formatDay($day, $element)"
hide-contiguous="true" display-controls="false"
hide-year="true" hide-contiguous="true"
on-selection="$ctrl.onSelection($event, $days)"> hide-year="true"
</vn-calendar> on-selection="$ctrl.onSelection($event, $days)">
</vn-card> </vn-calendar>
</vn-card>
</div>
</div>
<div
ng-if="!$ctrl.worker.hasWorkCenter"
class="bg-title"
translate>
Autonomous worker
</div> </div>
<vn-side-menu side="right"> <vn-side-menu side="right">
<div class="vn-pa-md"> <div class="vn-pa-md">
<div class="totalBox vn-mb-sm" style="text-align: center;"> <div class="totalBox vn-mb-sm" style="text-align: center;">
<h6>{{'Contract' | translate}} #{{$ctrl.businessId}}</h6> <h6>{{'Contract' | translate}} #{{$ctrl.card.worker.hasWorkCenter}}</h6>
<div> <div>
{{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed || 0}} {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed || 0}}
{{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}} {{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}}
@ -63,7 +71,6 @@
ng-model="$ctrl.businessId" ng-model="$ctrl.businessId"
search-function="{businessFk: $search}" search-function="{businessFk: $search}"
value-field="businessFk" value-field="businessFk"
show-field="businessFk"
order="businessFk DESC" order="businessFk DESC"
limit="5"> limit="5">
<tpl-item> <tpl-item>
@ -103,3 +110,4 @@
message="This item will be deleted" message="This item will be deleted"
question="Are you sure you want to continue?"> question="Are you sure you want to continue?">
</vn-confirm> </vn-confirm>

View File

@ -64,8 +64,7 @@ class Controller extends Section {
set worker(value) { set worker(value) {
this._worker = value; this._worker = value;
if (value && value.hasWorkCenter) {
if (value) {
this.getIsSubordinate(); this.getIsSubordinate();
this.getActiveContract(); this.getActiveContract();
} }

View File

@ -74,7 +74,7 @@ describe('Worker', () => {
let yesterday = new Date(today.getTime()); let yesterday = new Date(today.getTime());
yesterday.setDate(yesterday.getDate() - 1); yesterday.setDate(yesterday.getDate() - 1);
controller.worker = {id: 1107}; controller.worker = {id: 1107, hasWorkCenter: true};
expect(controller.getIsSubordinate).toHaveBeenCalledWith(); expect(controller.getIsSubordinate).toHaveBeenCalledWith();
expect(controller.getActiveContract).toHaveBeenCalledWith(); expect(controller.getActiveContract).toHaveBeenCalledWith();

View File

@ -11,4 +11,5 @@ Choose an absence type from the right menu: Elige un tipo de ausencia desde el m
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 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 Current day: Día actual
Paid holidays: Vacaciones pagadas Paid holidays: Vacaciones pagadas
Autonomous worker: Trabajador autónomo

View File

@ -34,6 +34,10 @@ class Controller extends ModuleCard {
this.$http.get(`Workers/${this.$params.id}`, {filter}) this.$http.get(`Workers/${this.$params.id}`, {filter})
.then(res => this.worker = res.data); .then(res => this.worker = res.data);
this.$http.get(`Workers/${this.$params.id}/activeContract`)
.then(res => {
if (res.data) this.worker.hasWorkCenter = res.data.workCenterFk;
});
} }
} }

View File

@ -4,106 +4,114 @@
filter="::$ctrl.filter" filter="::$ctrl.filter"
data="$ctrl.hours"> data="$ctrl.hours">
</vn-crud-model> </vn-crud-model>
<vn-card class="vn-pa-lg vn-w-lg"> <div ng-if="$ctrl.worker.hasWorkCenter">
<vn-table model="model" auto-load="false"> <vn-card class="vn-pa-lg vn-w-lg">
<vn-thead> <vn-table model="model" auto-load="false">
<vn-tr> <vn-thead>
<vn-td ng-repeat="weekday in $ctrl.weekDays" center> <vn-tr>
<div class="weekday" translate>{{::$ctrl.weekdayNames[$index].name}}</div> <vn-td ng-repeat="weekday in $ctrl.weekDays" center>
<div> <div class="weekday" translate>{{::$ctrl.weekdayNames[$index].name}}</div>
<span>{{::weekday.dated | date: 'dd'}}</span>
<span title="{{::weekday.dated | date: 'MMMM' | translate}}" translate>
{{::weekday.dated | date: 'MMMM'}}
</span>
</div>
<vn-chip
title="{{::weekday.event.name}}"
ng-class="{invisible: !weekday.event}">
<vn-avatar
ng-style="::{backgroundColor: weekday.event.color}">
</vn-avatar>
<div> <div>
{{::weekday.event.name}} <span>{{::weekday.dated | date: 'dd'}}</span>
<span title="{{::weekday.dated | date: 'MMMM' | translate}}" translate>
{{::weekday.dated | date: 'MMMM'}}
</span>
</div> </div>
</vn-chip>
</vn-td>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr>
<vn-td ng-repeat="weekday in $ctrl.weekDays" class="hours vn-pa-none" expand>
<section ng-repeat="hour in weekday.hours">
<vn-icon
icon="{{
::hour.direction == 'in' ? 'arrow_forward' : 'arrow_back'
}}"
title="{{
::(hour.direction == 'in' ? 'In' : 'Out') | translate
}}"
ng-class="::{'invisible': hour.direction == 'middle'}">
</vn-icon>
<vn-chip <vn-chip
ng-class="::{'colored': hour.manual, 'clickable': true}" title="{{::weekday.event.name}}"
removable="::hour.manual" ng-class="{invisible: !weekday.event}">
on-remove="$ctrl.showDeleteDialog($event, hour)" <vn-avatar
ng-click="$ctrl.edit($event, hour)" ng-style="::{backgroundColor: weekday.event.color}">
> </vn-avatar>
<prepend> <div>
<vn-icon icon="edit" {{::weekday.event.name}}
vn-tooltip="Edit"> </div>
</vn-icon>
</prepend>
{{::hour.timed | date: 'HH:mm'}}
</vn-chip> </vn-chip>
</section> </vn-td>
</vn-td> </vn-tr>
</vn-tr> </vn-thead>
</vn-tbody> <vn-tbody>
<vn-tfoot> <vn-tr>
<vn-tr> <vn-td ng-repeat="weekday in $ctrl.weekDays" class="hours vn-pa-none" expand>
<vn-td ng-repeat="weekday in $ctrl.weekDays" center> <section ng-repeat="hour in weekday.hours">
{{$ctrl.formatHours(weekday.workedHours)}} h. <vn-icon
</vn-td> icon="{{
</vn-tr> ::hour.direction == 'in' ? 'arrow_forward' : 'arrow_back'
<vn-tr> }}"
<vn-td center ng-repeat="weekday in $ctrl.weekDays"> title="{{
<vn-icon-button ::(hour.direction == 'in' ? 'In' : 'Out') | translate
icon="add_circle" }}"
vn-tooltip="Add time" ng-class="::{'invisible': hour.direction == 'middle'}">
ng-click="$ctrl.showAddTimeDialog(weekday)"> </vn-icon>
</vn-icon-button> <vn-chip
</vn-td> ng-class="::{'colored': hour.manual, 'clickable': true}"
</vn-tr> removable="::hour.manual"
</vn-tfoot> on-remove="$ctrl.showDeleteDialog($event, hour)"
</vn-table> ng-click="$ctrl.edit($event, hour)"
</vn-card> >
<prepend>
<vn-icon icon="edit"
vn-tooltip="Edit">
</vn-icon>
</prepend>
{{::hour.timed | date: 'HH:mm'}}
</vn-chip>
</section>
</vn-td>
</vn-tr>
</vn-tbody>
<vn-tfoot>
<vn-tr>
<vn-td ng-repeat="weekday in $ctrl.weekDays" center>
{{$ctrl.formatHours(weekday.workedHours)}} h.
</vn-td>
</vn-tr>
<vn-tr>
<vn-td center ng-repeat="weekday in $ctrl.weekDays">
<vn-icon-button
icon="add_circle"
vn-tooltip="Add time"
ng-click="$ctrl.showAddTimeDialog(weekday)">
</vn-icon-button>
</vn-td>
</vn-tr>
</vn-tfoot>
</vn-table>
</vn-card>
<vn-button-bar ng-show="$ctrl.state" class="vn-w-lg"> <vn-button-bar ng-show="$ctrl.state" class="vn-w-lg">
<vn-button <vn-button
label="Satisfied" label="Satisfied"
disabled="$ctrl.state == 'CONFIRMED'" disabled="$ctrl.state == 'CONFIRMED'"
ng-if="$ctrl.isHimSelf" ng-if="$ctrl.isHimSelf"
ng-click="$ctrl.isSatisfied()"> ng-click="$ctrl.isSatisfied()">
</vn-button> </vn-button>
<vn-button <vn-button
label="Not satisfied" label="Not satisfied"
disabled="$ctrl.state == 'REVISE'" disabled="$ctrl.state == 'REVISE'"
ng-if="$ctrl.isHimSelf" ng-if="$ctrl.isHimSelf"
ng-click="reason.show()"> ng-click="reason.show()">
</vn-button> </vn-button>
<vn-button <vn-button
label="Reason" label="Reason"
ng-if="$ctrl.reason && ($ctrl.isHimSelf || $ctrl.isHr)" ng-if="$ctrl.reason && ($ctrl.isHimSelf || $ctrl.isHr)"
ng-click="reason.show()"> ng-click="reason.show()">
</vn-button> </vn-button>
<vn-button <vn-button
label="Resend" label="Resend"
ng-click="sendEmailConfirmation.show()" ng-click="sendEmailConfirmation.show()"
class="right" class="right"
vn-tooltip="Resend email of this week to the user" vn-tooltip="Resend email of this week to the user"
ng-show="::$ctrl.isHr"> ng-show="::$ctrl.isHr">
</vn-button> </vn-button>
</vn-button-bar> </vn-button-bar>
</div>
<div
ng-if="!$ctrl.worker.hasWorkCenter"
class="bg-title"
translate>
Autonomous worker
</div>
<vn-side-menu side="right"> <vn-side-menu side="right">
<div class="vn-pa-md"> <div class="vn-pa-md">

View File

@ -151,6 +151,7 @@ class Controller extends Section {
} }
getAbsences() { getAbsences() {
if (!this.worker.hasWorkerCenter) return;
const fullYear = this.started.getFullYear(); const fullYear = this.started.getFullYear();
let params = { let params = {
workerFk: this.$params.id, workerFk: this.$params.id,

View File

@ -16,6 +16,10 @@ describe('Component vnWorkerTimeControl', () => {
$scope = $rootScope.$new(); $scope = $rootScope.$new();
$element = angular.element('<vn-worker-time-control></vn-worker-time-control>'); $element = angular.element('<vn-worker-time-control></vn-worker-time-control>');
controller = $componentController('vnWorkerTimeControl', {$element, $scope}); controller = $componentController('vnWorkerTimeControl', {$element, $scope});
controller.worker = {
hasWorkerCenter: true
};
})); }));
describe('date() setter', () => { describe('date() setter', () => {