Merge branch 'dev' into 5640-mayusFiscalDate
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Carlos Satorres 2023-06-29 08:39:34 +00:00
commit dc73dc2cb4
13 changed files with 203 additions and 120 deletions

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

@ -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

@ -12,3 +12,4 @@ To start adding absences, click an absence type from the right menu and then on
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', () => {