Merge branch 'dev' into 3290-entry_latest-buys
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Carlos Jimenez Ruiz 2021-11-22 15:34:55 +00:00
commit 1f2417b55e
20 changed files with 193 additions and 19 deletions

View File

@ -2,8 +2,7 @@ DROP PROCEDURE IF EXISTS `vn`.`item_getBalance`;
DELIMITER $$
$$
CREATE
definer = root@`%` procedure `vn`.`item_getBalance`(IN vItemId int, IN vWarehouse int)
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`item_getBalance`(IN vItemId int, IN vWarehouse int)
BEGIN
DECLARE vDateInventory DATETIME;
DECLARE vCurdate DATE DEFAULT CURDATE();
@ -116,7 +115,7 @@ BEGIN
s.id,
st.`order`,
ct.code,
cl.id
cb.claimFk
FROM sale s
JOIN ticket t ON t.id = s.ticketFk
LEFT JOIN ticketState ts ON ts.ticket = t.id
@ -132,6 +131,7 @@ BEGIN
LEFT JOIN state stPrep ON stPrep.`code` = 'PREPARED'
LEFT JOIN saleTracking stk ON stk.saleFk = s.id AND stk.stateFk = stPrep.id
LEFT JOIN claim cl ON cl.ticketFk = t.id
LEFT JOIN claimBeginning cb ON cl.id = cb.claimFk AND s.id = cb.saleFk
WHERE t.shipped >= vDateInventory
AND s.itemFk = vItemId
AND vWarehouse =t.warehouseFk
@ -141,4 +141,3 @@ BEGIN
END;
$$
DELIMITER ;

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.payMethod CHANGE ibanRequiredForClients isIbanRequiredForClients tinyint(3) DEFAULT 0 NULL;
ALTER TABLE vn.payMethod CHANGE ibanRequiredForSuppliers isIbanRequiredForSuppliers tinyint(3) DEFAULT 0 NULL;

View File

@ -217,7 +217,7 @@ UPDATE `vn`.`agencyMode` SET `web` = 1, `reportMail` = 'no-reply@gothamcity.com'
UPDATE `vn`.`agencyMode` SET `code` = 'refund' WHERE `id` = 23;
INSERT INTO `vn`.`payMethod`(`id`,`code`, `name`, `graceDays`, `outstandingDebt`, `ibanRequiredForClients`, `ibanRequiredForSuppliers`)
INSERT INTO `vn`.`payMethod`(`id`,`code`, `name`, `graceDays`, `outstandingDebt`, `isIbanRequiredForClients`, `isIbanRequiredForSuppliers`)
VALUES
(1, NULL, 'PayMethod one', 0, 001, 0, 0),
(2, NULL, 'PayMethod two', 10, 001, 0, 0),
@ -1882,6 +1882,7 @@ INSERT INTO `postgresql`.`calendar_state` (`calendar_state_id`, `type`, `rgb`, `
INSERT INTO `postgresql`.`calendar_employee` (`business_id`, `calendar_state_id`, `date`)
VALUES
(1, 6, IF(MONTH(CURDATE()) = 12 AND DAY(CURDATE()) > 10, DATE_ADD(CURDATE(), INTERVAL -10 DAY), DATE_ADD(CURDATE(), INTERVAL 10 DAY))),
(1106, 1, IF(MONTH(CURDATE()) = 12 AND DAY(CURDATE()) > 10, DATE_ADD(CURDATE(), INTERVAL -10 DAY), DATE_ADD(CURDATE(), INTERVAL 10 DAY))),
(1106, 1, IF(MONTH(CURDATE()) = 12 AND DAY(CURDATE()) > 10, DATE_ADD(CURDATE(), INTERVAL -11 DAY), DATE_ADD(CURDATE(), INTERVAL 11 DAY))),
(1106, 1, IF(MONTH(CURDATE()) = 12 AND DAY(CURDATE()) > 10, DATE_ADD(CURDATE(), INTERVAL -12 DAY), DATE_ADD(CURDATE(), INTERVAL 12 DAY))),

View File

@ -193,6 +193,7 @@
"Client assignment has changed": "He cambiado el comercial ~*\"<{{previousWorkerName}}>\"*~ por *\"<{{currentWorkerName}}>\"* del cliente [{{clientName}} ({{clientId}})]({{{url}}})",
"None": "Ninguno",
"The contract was not active during the selected date": "El contrato no estaba activo durante la fecha seleccionada",
"Cannot add more than one '1/2 day vacation'": "No puedes añadir más de un 'Vacaciones 1/2 dia'",
"This document already exists on this ticket": "Este documento ya existe en el ticket",
"Some of the selected tickets are not billable": "Algunos de los tickets seleccionados no son facturables",
"You can't invoice tickets from multiple clients": "No puedes facturar tickets de multiples clientes",

View File

@ -138,7 +138,8 @@ module.exports = Self => {
function hasIban(err, done) {
Self.app.models.PayMethod.findById(this.payMethodFk, (_, instance) => {
if (instance && instance.ibanRequiredForClients && !this.iban)
const isMissingIban = instance && instance.isIbanRequiredForClients && !this.iban;
if (isMissingIban)
err();
done();
});

View File

@ -25,10 +25,10 @@
"outstandingDebt": {
"type": "Number"
},
"ibanRequiredForClients": {
"isIbanRequiredForClients": {
"type": "boolean"
},
"ibanRequiredForSuppliers": {
"isIbanRequiredForSuppliers": {
"type": "boolean"
}
}

View File

@ -19,7 +19,7 @@
vn-acl="salesAssistant"
ng-model="$ctrl.client.payMethodFk"
data="paymethods"
fields="['ibanRequiredForClients']"
fields="['isIbanRequiredForClients']"
initial-data="$ctrl.client.payMethod">
</vn-autocomplete>
<vn-input-number

View File

@ -17,8 +17,8 @@
<slot-body>
<div class="attributes">
<vn-label-value
label="Phone"
value="{{$ctrl.client.phone | phone}}">
label="Pay method"
value="{{$ctrl.client.payMethod.name}}">
</vn-label-value>
<vn-label-value
label="Credit"

View File

@ -3,4 +3,5 @@ View consumer report: Ver informe de consumo
From date: Fecha desde
To date: Fecha hasta
Go to user: Ir al usuario
Client invoices list: Listado de facturas del cliente
Client invoices list: Listado de facturas del cliente
Pay method: Forma de pago

View File

@ -39,6 +39,11 @@ module.exports = Self => {
type: 'integer',
description: 'The buyer of the item',
},
{
arg: 'supplierFk',
type: 'integer',
description: 'The supplier of the item',
},
{
arg: 'active',
type: 'boolean',
@ -104,6 +109,8 @@ module.exports = Self => {
return {'ic.id': value};
case 'salesPersonFk':
return {'it.workerFk': value};
case 'supplierFk':
return {'s.id': value};
case 'code':
return {'it.code': value};
case 'active':
@ -179,7 +186,9 @@ module.exports = Self => {
LEFT JOIN itemCategory ic ON ic.id = it.categoryFk
LEFT JOIN itemType t ON t.id = i.typeFk
LEFT JOIN intrastat intr ON intr.id = i.intrastatFk
LEFT JOIN origin ori ON ori.id = i.originFk`
LEFT JOIN origin ori ON ori.id = i.originFk
LEFT JOIN entry e ON e.id = b.entryFk AND e.created >= DATE_SUB(CURDATE(),INTERVAL 1 YEAR)
LEFT JOIN supplier s ON s.id = e.supplierFk`
);
if (ctx.args.tags) {

View File

@ -160,5 +160,17 @@ describe('Buy latests buys filter()', () => {
expect(results.length).toBe(1);
});
it('should return results matching "supplierFk"', async() => {
let ctx = {
args: {
supplierFk: 1
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
expect(results.length).toBe(2);
});
});

View File

@ -46,6 +46,17 @@
where="{role: {inq: ['logistic', 'buyer']}}"
label="Buyer">
</vn-autocomplete>
<vn-autocomplete
vn-one
label="Supplier"
ng-model="filter.supplierFk"
url="Suppliers"
fields="['name','nickname']"
search-function="{or: [{nickname: {like: '%'+ $search +'%'}}, {name: {like: '%'+ $search +'%'}}]}"
show-field="name"
value-field="id">
<tpl-item>{{name}}: {{nickname}}</tpl-item>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-check

View File

@ -48,6 +48,11 @@ module.exports = Self => {
type: 'integer',
description: 'The buyer of the item',
},
{
arg: 'supplierFk',
type: 'integer',
description: 'The supplier of the item',
},
{
arg: 'description',
type: 'string',
@ -112,14 +117,15 @@ module.exports = Self => {
case 'isActive':
case 'typeFk':
case 'isFloramondo':
param = `i.${param}`;
return {[param]: value};
return {[`i.${param}`]: value};
case 'multiplier':
return {'i.stemMultiplier': value};
case 'categoryFk':
return {'ic.id': value};
case 'buyerFk':
return {'it.workerFk': value};
case 'supplierFk':
return {'s.id': value};
case 'origin':
return {'ori.code': value};
case 'intrastat':
@ -170,7 +176,9 @@ module.exports = Self => {
LEFT JOIN producer pr ON pr.id = i.producerFk
LEFT JOIN origin ori ON ori.id = i.originFk
LEFT JOIN cache.last_buy lb ON lb.item_id = i.id AND lb.warehouse_id = it.warehouseFk
LEFT JOIN vn.buy b ON b.id = lb.buy_id`
LEFT JOIN buy b ON b.id = lb.buy_id
LEFT JOIN entry e ON e.id = b.entryFk
LEFT JOIN supplier s ON s.id = e.supplierFk`
);
if (ctx.args.tags) {

View File

@ -79,4 +79,44 @@ describe('item filter()', () => {
throw e;
}
});
it('should return 2 result filtering by buyerFk', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const filter = {};
const ctx = {args: {filter: filter, buyerFk: 16}};
const result = await models.Item.filter(ctx, filter, options);
expect(result.length).toEqual(2);
expect(result[0].id).toEqual(16);
expect(result[1].id).toEqual(71);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return 2 result filtering by supplierFk', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const filter = {};
const ctx = {args: {filter: filter, supplierFk: 1}};
const result = await models.Item.filter(ctx, filter, options);
expect(result.length).toEqual(2);
expect(result[0].id).toEqual(1);
expect(result[1].id).toEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -36,4 +36,36 @@ describe('item getBalance()', () => {
throw e;
}
});
it('should show the claimFk only on the claimed item', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const firstFilter = {
where: {
itemFk: 1,
warehouseFk: 1
}
};
const secondFilter = {
where: {
itemFk: 2,
warehouseFk: 1
}
};
const firstItemBalance = await models.Item.getBalance(firstFilter, options);
const secondItemBalance = await models.Item.getBalance(secondFilter, options);
expect(firstItemBalance[9].claimFk).toEqual(null);
expect(secondItemBalance[5].claimFk).toEqual(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -43,10 +43,21 @@
ng-model="filter.buyerFk"
url="Items/activeBuyers"
show-field="nickname"
search-function="{firstName: $search}"
search-function="{nickname: {like: '%'+ $search +'%'}}"
value-field="workerFk"
label="Buyer">
</vn-autocomplete>
<vn-autocomplete
vn-one
label="Supplier"
ng-model="filter.supplierFk"
url="Suppliers"
fields="['name','nickname']"
search-function="{or: [{nickname: {like: '%'+ $search +'%'}}, {name: {like: '%'+ $search +'%'}}]}"
show-field="name"
value-field="id">
<tpl-item>{{name}}: {{nickname}}</tpl-item>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal class="vn-pt-sm">
<vn-one class="text-subtitle1" translate>

View File

@ -79,8 +79,9 @@ module.exports = Self => {
const payMethod = await Self.app.models.PayMethod.findById(this.payMethodFk);
const supplierAccount = await Self.app.models.SupplierAccount.findOne({where: {supplierFk: this.id}});
const hasIban = supplierAccount && supplierAccount.iban;
const isMissingIban = payMethod && payMethod.isIbanRequiredForSuppliers && !hasIban;
if (payMethod && payMethod.ibanRequiredForSuppliers && !hasIban)
if (isMissingIban)
err();
done();

View File

@ -24,7 +24,7 @@
vn-acl="salesAssistant"
ng-model="$ctrl.supplier.payMethodFk"
data="paymethods"
fields="['ibanRequiredForSuppliers']"
fields="['isIbanRequiredForSuppliers']"
initial-data="$ctrl.supplier.payMethod">
</vn-autocomplete>
<vn-autocomplete

View File

@ -65,6 +65,23 @@ module.exports = Self => {
if (args.dated < labour.started || (labour.ended != null && args.dated > labour.ended))
throw new UserError(`The contract was not active during the selected date`);
const result = await Self.rawSql(
`SELECT COUNT(*) halfHolidayCounter
FROM vn.calendar c
JOIN postgresql.business b ON b.business_id = c.businessFk
JOIN postgresql.profile p ON p.profile_id = b.client_id
JOIN vn.person pe ON pe.id = p.person_id
WHERE c.dayOffTypeFk = 6
AND pe.workerFk = ?
AND c.dated BETWEEN util.firstDayOfYear(CURDATE())
AND LAST_DAY(DATE_ADD(NOW(), INTERVAL 12-MONTH(NOW()) MONTH))`, [args.id]);
const hasHalfHoliday = result[0].halfHolidayCounter > 0;
const isHalfHoliday = args.absenceTypeId == 6;
if (isHalfHoliday && hasHalfHoliday)
throw new UserError(`Cannot add more than one '1/2 day vacation'`);
const absence = await models.Calendar.create({
businessFk: labour.businessFk,
dayOffTypeFk: args.absenceTypeId,

View File

@ -74,4 +74,32 @@ describe('Worker createAbsence()', () => {
throw e;
}
});
it(`should throw an error when adding a "Half holiday" absence if there's already one`, async() => {
const ctx = {
req: {accessToken: {userId: 19}},
args: {
id: 1,
businessFk: 1,
absenceTypeId: 6,
dated: new Date()
}
};
const tx = await app.models.Calendar.beginTransaction({});
let error;
try {
const options = {transaction: tx};
await app.models.Worker.createAbsence(ctx, workerId, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toEqual(`Cannot add more than one '1/2 day vacation'`);
});
});