fixes #4927 supplier.fiscal-data permitir 'Razón social' duplicada #1230

Merged
joan merged 24 commits from 4927-permitir-razonSocial-duplicada into dev 2023-02-02 07:47:39 +00:00
25 changed files with 144 additions and 150 deletions
Showing only changes of commit 7d7e1a74da - Show all commits

View File

@ -12,11 +12,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- (Trabajadores -> Nuevo trabajador) Nueva sección - (Trabajadores -> Nuevo trabajador) Nueva sección
### Changed ### Changed
- (Entradas -> Compras) Cambiados los campos "Precio Grouping/Packing" por "PVP" y "Precio" por "Coste"
- (Artículos -> Últimas entradas) Cambiados los campos "P.P.U." y "P.P.P." por "PVP"
- (Proveedores -> Crear/Editar) Permite añadir Proveedores con la misma razón social pero con países distintos - (Proveedores -> Crear/Editar) Permite añadir Proveedores con la misma razón social pero con países distintos
### Fixed ### Fixed
- (Artículos -> Etiquetas) Permite intercambiar la relevancia entre dos etiquetas. - (Artículos -> Etiquetas) Permite intercambiar la relevancia entre dos etiquetas.
- (Tickets -> Añadir pago) Eliminado "null" en las referencias
## [2302.01] - 2023-01-26 ## [2302.01] - 2023-01-26

View File

@ -23,6 +23,7 @@ describe('Worker time control path', () => {
it('should go to the next month, go to current month and go 1 month in the past', async() => { it('should go to the next month, go to current month and go 1 month in the past', async() => {
let date = new Date(); let date = new Date();
date.setDate(1);
date.setMonth(date.getMonth() + 1); date.setMonth(date.getMonth() + 1);
let month = date.toLocaleString('default', {month: 'long'}); let month = date.toLocaleString('default', {month: 'long'});
@ -32,6 +33,7 @@ describe('Worker time control path', () => {
expect(result).toContain(month); expect(result).toContain(month);
date = new Date(); date = new Date();
date.setDate(1);
month = date.toLocaleString('default', {month: 'long'}); month = date.toLocaleString('default', {month: 'long'});
await page.click(selectors.workerTimeControl.previousMonthButton); await page.click(selectors.workerTimeControl.previousMonthButton);
@ -40,6 +42,7 @@ describe('Worker time control path', () => {
expect(result).toContain(month); expect(result).toContain(month);
date = new Date(); date = new Date();
date.setDate(1);
date.setMonth(date.getMonth() - 1); date.setMonth(date.getMonth() - 1);
const timestamp = Math.round(date.getTime() / 1000); const timestamp = Math.round(date.getTime() / 1000);
month = date.toLocaleString('default', {month: 'long'}); month = date.toLocaleString('default', {month: 'long'});

View File

@ -87,6 +87,7 @@ ngModule.vnComponent('vnButtonMenu', {
selectFields: '<?', selectFields: '<?',
initialData: '<?', initialData: '<?',
showFilter: '<?', showFilter: '<?',
fields: '<?',
field: '=?', field: '=?',
url: '@?', url: '@?',
data: '<?', data: '<?',

View File

@ -42,6 +42,7 @@ vn-log {
& > td.after, & > td.after,
& > th.after { & > th.after {
width: 40%; width: 40%;
white-space: pre-line;
} }
} }
} }

View File

@ -67,7 +67,7 @@
"Changed client paymethod": "I have changed the pay method for client [{{clientName}} ({{clientId}})]({{{url}}})", "Changed client paymethod": "I have changed the pay method for client [{{clientName}} ({{clientId}})]({{{url}}})",
"Sent units from ticket": "I sent *{{quantity}}* units of [{{concept}} ({{itemId}})]({{{itemUrl}}}) to *\"{{nickname}}\"* coming from ticket id [{{ticketId}}]({{{ticketUrl}}})", "Sent units from ticket": "I sent *{{quantity}}* units of [{{concept}} ({{itemId}})]({{{itemUrl}}}) to *\"{{nickname}}\"* coming from ticket id [{{ticketId}}]({{{ticketUrl}}})",
"Change quantity": "{{concept}} change of {{oldQuantity}} to {{newQuantity}}", "Change quantity": "{{concept}} change of {{oldQuantity}} to {{newQuantity}}",
"Claim will be picked": "The product from the claim [({{claimId}})]({{{claimUrl}}}) from the client *{{clientName}}* will be picked", "Claim will be picked": "The product from the claim [({{claimId}})]({{{claimUrl}}}) from the client *{{clientName}}* will be picked",
"Claim state has changed to incomplete": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *incomplete*", "Claim state has changed to incomplete": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *incomplete*",
"Claim state has changed to canceled": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *canceled*", "Claim state has changed to canceled": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *canceled*",
"Customs agent is required for a non UEE member": "Customs agent is required for a non UEE member", "Customs agent is required for a non UEE member": "Customs agent is required for a non UEE member",
@ -137,15 +137,18 @@
"Password does not meet requirements": "Password does not meet requirements", "Password does not meet requirements": "Password does not meet requirements",
"You don't have privileges to change the zone": "You don't have privileges to change the zone or for these parameters there are more than one shipping options, talk to agencies", "You don't have privileges to change the zone": "You don't have privileges to change the zone or for these parameters there are more than one shipping options, talk to agencies",
"Not enough privileges to edit a client": "Not enough privileges to edit a client", "Not enough privileges to edit a client": "Not enough privileges to edit a client",
"Claim pickup order sent": "Claim pickup order sent [{{claimId}}]({{{claimUrl}}}) to client *{{clientName}}*", "Claim pickup order sent": "Claim pickup order sent [{{claimId}}]({{{claimUrl}}}) to client *{{clientName}}*",
"You don't have grant privilege": "You don't have grant privilege", "You don't have grant privilege": "You don't have grant privilege",
"You don't own the role and you can't assign it to another user": "You don't own the role and you can't assign it to another user", "You don't own the role and you can't assign it to another user": "You don't own the role and you can't assign it to another user",
"Email verify": "Email verify", "Email verify": "Email verify",
"Ticket merged": "Ticket [{{originId}}]({{{originFullPath}}}) ({{{originDated}}}) merged with [{{destinationId}}]({{{destinationFullPath}}}) ({{{destinationDated}}})", "Ticket merged": "Ticket [{{originId}}]({{{originFullPath}}}) ({{{originDated}}}) merged with [{{destinationId}}]({{{destinationFullPath}}}) ({{{destinationDated}}})",
"Sale(s) blocked, please contact production": "Sale(s) blocked, please contact production",
"App locked": "App locked by user {{userId}}", "App locked": "App locked by user {{userId}}",
"The sales of the receiver ticket can't be modified": "The sales of the receiver ticket can't be modified", "The sales of the receiver ticket can't be modified": "The sales of the receiver ticket can't be modified",
"Receipt's bank was not found": "Receipt's bank was not found", "Receipt's bank was not found": "Receipt's bank was not found",
"This receipt was not compensated": "This receipt was not compensated", "This receipt was not compensated": "This receipt was not compensated",
"Client's email was not found": "Client's email was not found" "Client's email was not found": "Client's email was not found",
"It is not possible to modify tracked sales": "It is not possible to modify tracked sales",
"It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo",
"It is not possible to modify cloned sales": "It is not possible to modify cloned sales",
"Valid priorities: 1,2,3": "Valid priorities: 1,2,3"
} }

View File

@ -84,7 +84,6 @@
"The current ticket can't be modified": "El ticket actual no puede ser modificado", "The current ticket can't be modified": "El ticket actual no puede ser modificado",
"The current claim can't be modified": "La reclamación actual no puede ser modificada", "The current claim can't be modified": "La reclamación actual no puede ser modificada",
"The sales of this ticket can't be modified": "Las lineas de este ticket no pueden ser modificadas", "The sales of this ticket can't be modified": "Las lineas de este ticket no pueden ser modificadas",
"Sale(s) blocked, contact production": "Linea(s) bloqueada(s), contacte con produccion",
"Please select at least one sale": "Por favor selecciona al menos una linea", "Please select at least one sale": "Por favor selecciona al menos una linea",
"All sales must belong to the same ticket": "Todas las lineas deben pertenecer al mismo ticket", "All sales must belong to the same ticket": "Todas las lineas deben pertenecer al mismo ticket",
"NO_ZONE_FOR_THIS_PARAMETERS": "Para este día no hay ninguna zona configurada", "NO_ZONE_FOR_THIS_PARAMETERS": "Para este día no hay ninguna zona configurada",
@ -259,7 +258,10 @@
"Try again": "Vuelve a intentarlo", "Try again": "Vuelve a intentarlo",
"Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9", "Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9",
"Failed to upload file": "Error al subir archivo", "Failed to upload file": "Error al subir archivo",
"The DOCUWARE PDF document does not exists": "The DOCUWARE PDF document does not exists", "The DOCUWARE PDF document does not exists": "El documento PDF Docuware no existe",
"It is not possible to modify tracked sales": "No es posible modificar líneas de pedido que se hayan empezado a preparar",
"It is not possible to modify sales that their articles are from Floramondo": "No es posible modificar líneas de pedido cuyos artículos sean de Floramondo",
"It is not possible to modify cloned sales": "No es posible modificar líneas de pedido clonadas",
"A supplier with the same name already exists. Change the country.": "Un proveedor con el mismo nombre ya existe. Cambie el país." "A supplier with the same name already exists. Change the country.": "Un proveedor con el mismo nombre ya existe. Cambie el país."
} }

View File

@ -59,13 +59,11 @@ class Controller extends Dialog {
if (value) { if (value) {
const accountingType = value.accountingType; const accountingType = value.accountingType;
if (this.originalDescription) { if (accountingType.receiptDescription != null) {
this.receipt.description = this.receipt.description = accountingType.receiptDescription;
`${accountingType && accountingType.receiptDescription}, ${this.originalDescription}`; if (this.originalDescription) this.receipt.description += `, ${this.originalDescription}`;
} else { } else if (this.originalDescription)
this.receipt.description = this.receipt.description = this.originalDescription;
`${accountingType && accountingType.receiptDescription}`;
}
this.maxAmount = accountingType && accountingType.maxAmount; this.maxAmount = accountingType && accountingType.maxAmount;
this.receipt.payed = new Date(); this.receipt.payed = new Date();

View File

@ -1,5 +1,5 @@
Edit buy(s): Editar compra(s) Edit buy(s): Editar compra(s)
Buying value: Precio Buying value: Coste
Freight value: Porte Freight value: Porte
Commission value: Comisión Commission value: Comisión
Package value: Embalaje Package value: Embalaje

View File

@ -114,8 +114,7 @@
<th translate center field="grouping">Grouping</th> <th translate center field="grouping">Grouping</th>
<th translate center field="buyingValue">Buying value</th> <th translate center field="buyingValue">Buying value</th>
<th translate center field="price3">Import</th> <th translate center field="price3">Import</th>
<th translate center expand field="price2">Grouping price</th> <th translate center expand field="price">PVP</th>
<th translate center expand field="price3">Packing price</th>
</tr> </tr>
</thead> </thead>
<tbody ng-repeat="line in buys"> <tbody ng-repeat="line in buys">
@ -136,8 +135,7 @@
</vn-td> </vn-td>
<td center title="{{::line.buyingValue | currency: 'EUR':2}}">{{::line.buyingValue | currency: 'EUR':2}}</td> <td center title="{{::line.buyingValue | currency: 'EUR':2}}">{{::line.buyingValue | currency: 'EUR':2}}</td>
<td center title="{{::line.quantity * line.buyingValue | currency: 'EUR':2}}">{{::line.quantity * line.buyingValue | currency: 'EUR':2}}</td> <td center title="{{::line.quantity * line.buyingValue | currency: 'EUR':2}}">{{::line.quantity * line.buyingValue | currency: 'EUR':2}}</td>
<td center title="{{::line.price2 | currency: 'EUR':2}}">{{::line.price2 | currency: 'EUR':2}}</td> <td center title="Grouping / Packing">{{::line.price2 | currency: 'EUR':2 | dashIfEmpty}} / {{::line.price3 | currency: 'EUR':2 | dashIfEmpty}}</td>
<td center title="{{::line.price3 | currency: 'EUR':2}}">{{::line.price3 | currency: 'EUR':2}}</td>
</tr> </tr>
<tr class="dark-row"> <tr class="dark-row">
<td shrink> <td shrink>

View File

@ -47,44 +47,32 @@ module.exports = function(Self) {
} }
try { try {
const promises = [];
if (args.deletes) { if (args.deletes) {
for (const itemTagId of args.deletes) { for (const itemTagId of args.deletes)
const itemTagDeleted = models.ItemTag.destroyById(itemTagId, myOptions); await models.ItemTag.destroyById(itemTagId, myOptions);
promises.push(itemTagDeleted);
}
} }
if (args.updates) { if (args.updates) {
for (const row of args.updates) { for (const row of args.updates) {
if (row.data.priority) { if (row.data.priority) {
const itemTag = await models.ItemTag.findById(row.where.id, null, myOptions); const itemTag = await models.ItemTag.findById(row.where.id, null, myOptions);
const itemTagUpdatedPriority = itemTag.updateAttributes({ await itemTag.updateAttributes({
priority: row.data.priority + args.maxPriority priority: row.data.priority + args.maxPriority
}, myOptions); }, myOptions);
promises.push(itemTagUpdatedPriority);
} }
} }
for (const row of args.updates) { for (const row of args.updates) {
const itemTag = await models.ItemTag.findById(row.where.id, null, myOptions); const itemTag = await models.ItemTag.findById(row.where.id, null, myOptions);
const itemTagUpdated = itemTag.updateAttributes(row.data, myOptions); await itemTag.updateAttributes(row.data, myOptions);
promises.push(itemTagUpdated);
} }
} }
if (args.creates) { if (args.creates) {
for (const itemTag of args.creates) { for (const itemTag of args.creates)
const newItemTag = models.ItemTag.create(itemTag, myOptions); await models.ItemTag.create(itemTag, myOptions);
promises.push(newItemTag);
}
} }
const resolvedPromises = await Promise.all(promises);
if (tx) await tx.commit(); if (tx) await tx.commit();
return resolvedPromises;
} catch (e) { } catch (e) {
if (tx) await tx.rollback(); if (tx) await tx.rollback();
throw e; throw e;

View File

@ -12,9 +12,8 @@ describe('tag onSubmit()', () => {
deletes: deletes deletes: deletes
} }
}; };
const result = await models.Tag.onSubmit(ctx, options); await models.Tag.onSubmit(ctx, options);
expect(result.length).toEqual(1);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();
@ -33,9 +32,8 @@ describe('tag onSubmit()', () => {
updates: updates updates: updates
} }
}; };
const result = await models.Tag.onSubmit(ctx, options); await models.Tag.onSubmit(ctx, options);
expect(result.length).toEqual(1);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();
@ -62,9 +60,8 @@ describe('tag onSubmit()', () => {
creates: creates creates: creates
} }
}; };
const result = await models.Tag.onSubmit(ctx, options); await models.Tag.onSubmit(ctx, options);
expect(result.length).toEqual(1);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();
@ -88,9 +85,8 @@ describe('tag onSubmit()', () => {
} }
}; };
const result = await models.Tag.onSubmit(ctx, options); await models.Tag.onSubmit(ctx, options);
expect(result.length).toEqual(4);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();

View File

@ -35,8 +35,7 @@
<vn-th field="warehouseFk">Warehouse</vn-th> <vn-th field="warehouseFk">Warehouse</vn-th>
<vn-th field="landed">Landed</vn-th> <vn-th field="landed">Landed</vn-th>
<vn-th number>Entry</vn-th> <vn-th number>Entry</vn-th>
<vn-th number vn-tooltip="Price Per Unit">P.P.U</vn-th> <vn-th vn-tooltip="Grouping / Packing">PVP</vn-th>
<vn-th number vn-tooltip="Price Per Package">P.P.P</vn-th>
<vn-th number class="expendable">Label</vn-th> <vn-th number class="expendable">Label</vn-th>
<vn-th number>Packing</vn-th> <vn-th number>Packing</vn-th>
<vn-th number>Grouping</vn-th> <vn-th number>Grouping</vn-th>
@ -65,8 +64,9 @@
{{::entry.entryFk | dashIfEmpty}} {{::entry.entryFk | dashIfEmpty}}
</span> </span>
</vn-td> </vn-td>
<vn-td number>{{::entry.price2 | dashIfEmpty}}</vn-td> <vn-td title="{{::entry.price2 | currency: 'EUR':2 | dashIfEmpty}} / {{::entry.price3 | currency: 'EUR':2 | dashIfEmpty}}">
<vn-td number>{{::entry.price3 | dashIfEmpty}}</vn-td> {{::entry.price2 | currency: 'EUR':2 | dashIfEmpty}} / {{::entry.price3 | currency: 'EUR':2 | dashIfEmpty}}
</vn-td>
<vn-td number class="expendable">{{entry.stickers | dashIfEmpty}}</vn-td> <vn-td number class="expendable">{{entry.stickers | dashIfEmpty}}</vn-td>
<vn-td number> <vn-td number>
<vn-chip translate-attr="{title: 'Packing'}" ng-class="{'message': entry.groupingMode == 2}"> <vn-chip translate-attr="{title: 'Packing'}" ng-class="{'message': entry.groupingMode == 2}">
@ -84,11 +84,11 @@
class="expendable"> class="expendable">
<span <span
vn-tooltip=" vn-tooltip="
{{::$ctrl.$t('Cost')}}: {{::entry.buyingValue| dashIfEmpty}}<br> {{::$ctrl.$t('Cost')}}: {{::entry.buyingValue | currency: 'EUR':2 | dashIfEmpty}}<br>
{{::$ctrl.$t('Package')}}: {{::entry.packageValue| dashIfEmpty}}<br> {{::$ctrl.$t('Package')}}: {{::entry.packageValue | currency: 'EUR':2 | dashIfEmpty}}<br>
{{::$ctrl.$t('Freight')}}: {{::entry.freightValue| dashIfEmpty}}<br> {{::$ctrl.$t('Freight')}}: {{::entry.freightValue | currency: 'EUR':2 | dashIfEmpty}}<br>
{{::$ctrl.$t('Comission')}}: {{::entry.comissionValue| dashIfEmpty}}"> {{::$ctrl.$t('Comission')}}: {{::entry.comissionValue | currency: 'EUR':2 | dashIfEmpty}}">
{{::entry.cost | dashIfEmpty}} {{::entry.cost | currency: 'EUR':2 | dashIfEmpty}}
</span> </span>
</vn-td> </vn-td>
<vn-td number>{{::entry.weight | dashIfEmpty}}</vn-td> <vn-td number>{{::entry.weight | dashIfEmpty}}</vn-td>

View File

@ -24,36 +24,42 @@
</vn-textfield> </vn-textfield>
<vn-input-number <vn-input-number
type="number" type="number"
step="0.01"
label="Minimum M3" label="Minimum M3"
ng-model="supplierAgencyTerm.minimumM3" ng-model="supplierAgencyTerm.minimumM3"
rule> rule>
</vn-input-number> </vn-input-number>
<vn-input-number <vn-input-number
type="number" type="number"
step="0.01"
label="Package Price" label="Package Price"
ng-model="supplierAgencyTerm.packagePrice" ng-model="supplierAgencyTerm.packagePrice"
rule> rule>
</vn-input-number> </vn-input-number>
<vn-input-number <vn-input-number
type="number" type="number"
step="0.01"
label="Km Price" label="Km Price"
ng-model="supplierAgencyTerm.kmPrice" ng-model="supplierAgencyTerm.kmPrice"
rule> rule>
</vn-input-number> </vn-input-number>
<vn-input-number <vn-input-number
type="number" type="number"
step="0.01"
label="M3 Price" label="M3 Price"
ng-model="supplierAgencyTerm.m3Price" ng-model="supplierAgencyTerm.m3Price"
rule> rule>
</vn-input-number> </vn-input-number>
<vn-input-number <vn-input-number
type="number" type="number"
step="0.01"
label="Route Price" label="Route Price"
ng-model="supplierAgencyTerm.routePrice" ng-model="supplierAgencyTerm.routePrice"
rule> rule>
</vn-input-number> </vn-input-number>
<vn-input-number <vn-input-number
type="number" type="number"
step="0.01"
label="Minimum Km" label="Minimum Km"
ng-model="supplierAgencyTerm.minimumKm" ng-model="supplierAgencyTerm.minimumKm"
rule> rule>

View File

@ -56,6 +56,13 @@ module.exports = Self => {
const shouldEditCloned = canEditCloned || !hasSaleCloned; const shouldEditCloned = canEditCloned || !hasSaleCloned;
const shouldEditFloramondo = canEditFloramondo || !hasSaleFloramondo; const shouldEditFloramondo = canEditFloramondo || !hasSaleFloramondo;
return shouldEditTracked && shouldEditCloned && shouldEditFloramondo; if (!shouldEditTracked)
throw new UserError('It is not possible to modify tracked sales');
if (!shouldEditCloned)
throw new UserError('It is not possible to modify cloned sales');
if (!shouldEditFloramondo)
throw new UserError('It is not possible to modify sales that their articles are from Floramondo');
return true;
}; };
}; };

View File

@ -43,9 +43,7 @@ module.exports = Self => {
try { try {
const saleIds = sales.map(sale => sale.id); const saleIds = sales.map(sale => sale.id);
const canEditSales = await models.Sale.canEdit(ctx, saleIds, myOptions); await models.Sale.canEdit(ctx, saleIds, myOptions);
if (!canEditSales)
throw new UserError(`Sale(s) blocked, please contact production`);
const ticket = await models.Ticket.findById(ticketId, { const ticket = await models.Ticket.findById(ticketId, {
include: { include: {

View File

@ -37,9 +37,7 @@ module.exports = Self => {
try { try {
const salesIds = sales.map(sale => sale.id); const salesIds = sales.map(sale => sale.id);
const canEditSale = await models.Sale.canEdit(ctx, salesIds, myOptions); await models.Sale.canEdit(ctx, salesIds, myOptions);
if (!canEditSale)
throw new UserError(`Sale(s) blocked, please contact production`);
const query = ` const query = `
DROP TEMPORARY TABLE IF EXISTS tmp.recalculateSales; DROP TEMPORARY TABLE IF EXISTS tmp.recalculateSales;

View File

@ -51,9 +51,7 @@ module.exports = Self => {
try { try {
const salesIds = sales.map(sale => sale.id); const salesIds = sales.map(sale => sale.id);
const canEditSale = await models.Sale.canEdit(ctx, salesIds, myOptions); await models.Sale.canEdit(ctx, salesIds, myOptions);
if (!canEditSale)
throw new UserError(`Sale(s) blocked, please contact production`);
let changesMade = ''; let changesMade = '';
const promises = []; const promises = [];

View File

@ -50,7 +50,7 @@ describe('sale canEdit()', () => {
it('should return false if any of the sales has a saleTracking record', async() => { it('should return false if any of the sales has a saleTracking record', async() => {
const tx = await models.Sale.beginTransaction({}); const tx = await models.Sale.beginTransaction({});
let error;
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
@ -59,15 +59,15 @@ describe('sale canEdit()', () => {
const sales = [31]; const sales = [31];
const result = await models.Sale.canEdit(ctx, sales, options); await models.Sale.canEdit(ctx, sales, options);
expect(result).toEqual(false);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();
throw e; error = e;
} }
expect(error).toEqual(
new Error('It is not possible to modify tracked sales'));
}); });
}); });
@ -75,22 +75,22 @@ describe('sale canEdit()', () => {
const saleCloned = [29]; const saleCloned = [29];
it('should return false if any of the sales is cloned', async() => { it('should return false if any of the sales is cloned', async() => {
const tx = await models.Sale.beginTransaction({}); const tx = await models.Sale.beginTransaction({});
let error;
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
const buyerId = 35; const buyerId = 35;
const ctx = {req: {accessToken: {userId: buyerId}}}; const ctx = {req: {accessToken: {userId: buyerId}}};
const result = await models.Sale.canEdit(ctx, saleCloned, options); await models.Sale.canEdit(ctx, saleCloned, options);
expect(result).toEqual(false);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();
throw e; error = e;
} }
expect(error).toEqual(
new Error('It is not possible to modify cloned sales'));
}); });
it('should return true if any of the sales is cloned and has the correct role', async() => { it('should return true if any of the sales is cloned and has the correct role', async() => {
@ -130,7 +130,7 @@ describe('sale canEdit()', () => {
it('should return false if any of the sales isFloramondo', async() => { it('should return false if any of the sales isFloramondo', async() => {
const tx = await models.Sale.beginTransaction({}); const tx = await models.Sale.beginTransaction({});
const sales = [26]; const sales = [26];
let error;
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
@ -140,15 +140,15 @@ describe('sale canEdit()', () => {
const saleToEdit = await models.Sale.findById(sales[0], null, options); const saleToEdit = await models.Sale.findById(sales[0], null, options);
await saleToEdit.updateAttribute('itemFk', 9, options); await saleToEdit.updateAttribute('itemFk', 9, options);
const result = await models.Sale.canEdit(ctx, sales, options); await models.Sale.canEdit(ctx, sales, options);
expect(result).toEqual(false);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();
throw e; error = e;
} }
expect(error).toEqual(
new Error('It is not possible to modify sales that their articles are from Floramondo'));
}); });
it('should return true if any of the sales is of isFloramondo and has the correct role', async() => { it('should return true if any of the sales is of isFloramondo and has the correct role', async() => {

View File

@ -40,10 +40,7 @@ module.exports = Self => {
try { try {
const currentLine = await models.Sale.findById(id, null, myOptions); const currentLine = await models.Sale.findById(id, null, myOptions);
const canEditSale = await models.Sale.canEdit(ctx, [id], myOptions); await models.Sale.canEdit(ctx, [id], myOptions);
if (!canEditSale)
throw new UserError(`Sale(s) blocked, please contact production`);
const line = await currentLine.updateAttributes({concept: newConcept}, myOptions); const line = await currentLine.updateAttributes({concept: newConcept}, myOptions);

View File

@ -66,9 +66,7 @@ module.exports = Self => {
const sale = await models.Sale.findById(id, filter, myOptions); const sale = await models.Sale.findById(id, filter, myOptions);
const canEditSale = await models.Sale.canEdit(ctx, [id], myOptions); await models.Sale.canEdit(ctx, [id], myOptions);
if (!canEditSale)
throw new UserError(`Sale(s) blocked, please contact production`);
const oldPrice = sale.price; const oldPrice = sale.price;
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;

View File

@ -41,9 +41,7 @@ module.exports = Self => {
} }
try { try {
const canEditSale = await models.Sale.canEdit(ctx, [id], myOptions); await models.Sale.canEdit(ctx, [id], myOptions);
if (!canEditSale)
throw new UserError(`Sale(s) blocked, please contact production`);
const filter = { const filter = {
include: { include: {

View File

@ -24,7 +24,7 @@ module.exports = Self => {
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
let statesList = await models.State.find({where: filter.where}, myOptions); let statesList = await models.State.find(filter, myOptions);
const isProduction = await models.Account.hasRole(userId, 'production', myOptions); const isProduction = await models.Account.hasRole(userId, 'production', myOptions);
const isSalesPerson = await models.Account.hasRole(userId, 'salesPerson', myOptions); const isSalesPerson = await models.Account.hasRole(userId, 'salesPerson', myOptions);
const isAdministrative = await models.Account.hasRole(userId, 'administrative', myOptions); const isAdministrative = await models.Account.hasRole(userId, 'administrative', myOptions);

View File

@ -22,6 +22,7 @@
disabled="!$ctrl.isEditable" disabled="!$ctrl.isEditable"
label="State" label="State"
value-field="code" value-field="code"
fields="['id', 'name', 'alertLevel', 'code']"
url="States/editableStates" url="States/editableStates"
on-change="$ctrl.changeState(value)"> on-change="$ctrl.changeState(value)">
</vn-button-menu> </vn-button-menu>

View File

@ -16,6 +16,7 @@
class="message" class="message"
label="Change state" label="Change state"
value-field="code" value-field="code"
fields="['id', 'name', 'alertLevel', 'code']"
url="States/editableStates" url="States/editableStates"
on-change="$ctrl.changeState(value)"> on-change="$ctrl.changeState(value)">
</vn-button-menu> </vn-button-menu>

View File

@ -4,7 +4,7 @@
<div class="content"> <div class="content">
<h1 class="title centered uppercase">{{$t('title')}}</h1> <h1 class="title centered uppercase">{{$t('title')}}</h1>
<p class="centered"> <p class="centered">
Recibo de <strong class="uppercase">{{client.socialName}}</strong>, Recibo #{{receipt.id}} de <strong class="uppercase">{{client.socialName}}</strong>,
la cantidad de <strong>{{receipt.amountPaid}} €</strong> la cantidad de <strong>{{receipt.amountPaid}} €</strong>
en concepto de 'entrega a cuenta'. en concepto de 'entrega a cuenta'.
</p> </p>