Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 3314-invoice-out_summary
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Alex Moreno 2021-11-10 14:54:15 +01:00
commit 7880fb8de9
29 changed files with 235 additions and 81 deletions

View File

@ -25,6 +25,9 @@
},
"isAutoConciliated": {
"type": "boolean"
},
"maxAmount": {
"type": "number"
}
},
"acls": [{

View File

@ -0,0 +1,3 @@
ALTER TABLE vn.accountingType ADD maxAmount INT DEFAULT NULL NULL;
UPDATE vn.accountingType SET maxAmount = 1000 WHERE code = 'cash';

View File

@ -154,16 +154,16 @@ INSERT INTO `vn`.`shelving` (`code`, `parkingFk`, `isPrinted`, `priority`, `park
('GVC', '1', '0', '1', '0', '1106'),
('HEJ', '2', '0', '1', '0', '1106');
INSERT INTO `vn`.`accountingType`(`id`, `description`, `receiptDescription`,`code`)
INSERT INTO `vn`.`accountingType`(`id`, `description`, `receiptDescription`,`code`, `maxAmount`)
VALUES
(1, 'CC y Polizas de crédito', NULL, NULL),
(2, 'Cash', 'Cash', 'cash'),
(3, 'Credit card', 'Credit Card', 'creditCard'),
(4, 'Finalcial lines', NULL, NULL),
(5, 'Other products', NULL, NULL),
(6, 'Loans', NULL, NULL),
(7, 'Leasing', NULL, NULL),
(8, 'Compensations', 'Compensations', 'compensation');
(1, 'CC y Polizas de crédito', NULL, NULL, NULL),
(2, 'Cash', 'Cash', 'cash', 1000),
(3, 'Credit card', 'Credit Card', 'creditCard', NULL),
(4, 'Finalcial lines', NULL, NULL, NULL),
(5, 'Other products', NULL, NULL, NULL),
(6, 'Loans', NULL, NULL, NULL),
(7, 'Leasing', NULL, NULL, NULL),
(8, 'Compensations', 'Compensations', 'compensation', NULL);
INSERT INTO `vn`.`bank`(`id`, `bank`, `account`, `cash`, `entityFk`, `isActive`, `currencyFk`)
VALUES
@ -1285,11 +1285,11 @@ INSERT INTO `vn`.`supplierAddress`(`id`, `supplierFk`, `nickname`, `street`, `pr
(5, 442, 'GCR building', 'Bristol district', 1, '46000', 'Gotham', '111111111', '222222222'),
(6, 442, 'The Gotham Tonight building', 'Bristol district', 1, '46000', 'Gotham', '111111111', '222222222');
INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`,`isFarmer`,`commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`, `workerFk`, `supplierActivityFk`)
INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`,`isFarmer`,`commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`, `workerFk`, `supplierActivityFk`, `isPayMethodChecked`)
VALUES
(1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, 0, CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants'),
(2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 1, 0, CURDATE(), 1, 'supplier address 2', 'SILLA', 2, 43022, 1, 2, 10, 93, 2, 8, 18, 'animals'),
(442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, 0, CURDATE(), 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'flowerPlants');
(1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, 0, CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants', 1),
(2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 1, 0, CURDATE(), 1, 'supplier address 2', 'SILLA', 2, 43022, 1, 2, 10, 93, 2, 8, 18, 'animals', 1),
(442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, 0, CURDATE(), 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'flowerPlants', 1);
INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email`, `observation`, `name`)
VALUES

View File

@ -1147,6 +1147,7 @@ export default {
alias: 'vn-supplier-basic-data vn-textfield[ng-model="$ctrl.supplier.nickname"]',
isSerious: 'vn-supplier-basic-data vn-check[ng-model="$ctrl.supplier.isSerious"]',
isActive: 'vn-supplier-basic-data vn-check[ng-model="$ctrl.supplier.isActive"]',
isPayMethodChecked: 'vn-supplier-basic-data vn-check[ng-model="$ctrl.supplier.isPayMethodChecked"]',
notes: 'vn-supplier-basic-data vn-textarea[ng-model="$ctrl.supplier.note"]',
saveButton: 'vn-supplier-basic-data button[type="submit"]',
},

View File

@ -105,7 +105,23 @@ describe('Client balance path', () => {
expect(result).toContain('-€100.00');
});
it('should create a new payment and check the cash exceeded the maximum', async() => {
const amountPaid = '1001';
await page.closePopup();
await page.waitToClick(selectors.clientBalance.newPaymentButton);
await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Cash');
await page.write(selectors.clientBalance.newPaymentAmount, amountPaid);
await page.clearInput(selectors.clientBalance.newDescription);
await page.write(selectors.clientBalance.newDescription, 'Payment');
await page.waitToClick(selectors.clientBalance.saveButton);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Amount exceeded');
});
it('should create a new payment that sets the balance back to the original negative value', async() => {
await page.closePopup();
await page.waitToClick(selectors.clientBalance.newPaymentButton);
await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Pay on receipt');
await page.overwrite(selectors.clientBalance.newPaymentAmount, '-150');

View File

@ -22,6 +22,7 @@ describe('Supplier basic data path', () => {
await page.write(selectors.supplierBasicData.alias, 'Plants Nick SL');
await page.waitToClick(selectors.supplierBasicData.isSerious);
await page.waitToClick(selectors.supplierBasicData.isActive);
await page.waitToClick(selectors.supplierBasicData.isPayMethodChecked);
await page.write(selectors.supplierBasicData.notes, 'Some notes');
await page.waitToClick(selectors.supplierBasicData.saveButton);
@ -52,6 +53,12 @@ describe('Supplier basic data path', () => {
expect(result).toBe('unchecked');
});
it('should check the isPayMethodChecked checkbox is now unchecked', async() => {
const result = await page.checkboxState(selectors.supplierBasicData.isPayMethodChecked);
expect(result).toBe('unchecked');
});
it('should check the notes were edited', async() => {
const result = await page.waitToGetProperty(selectors.supplierBasicData.notes, 'value');

View File

@ -44,7 +44,8 @@
label="Amount"
ng-model="$ctrl.amountPaid"
step="0.01"
required="true">
required="true"
max="$ctrl.maxAmount">
</vn-input-number>
</vn-horizontal>
<vn-horizontal>

View File

@ -61,8 +61,14 @@ class Controller extends Dialog {
if (value) {
const accountingType = value.accountingType;
this.receipt.description =
if (this.originalDescription) {
this.receipt.description =
`${accountingType && accountingType.receiptDescription}, ${this.originalDescription}`;
} else {
this.receipt.description =
`${accountingType && accountingType.receiptDescription}`;
}
this.maxAmount = accountingType && accountingType.maxAmount;
}
}
@ -123,6 +129,11 @@ class Controller extends Dialog {
if (response !== 'accept')
return super.responseHandler(response);
const exceededAmount = this.receipt.amountPaid > this.maxAmount;
if (this.bankSelection.accountingType.code == 'cash' && exceededAmount)
return this.vnApp.showError(this.$t('Amount exceeded', {maxAmount: this.maxAmount}));
let receiptId;
return this.$http.post(`Clients/${this.clientFk}/createReceipt`, this.receipt)
.then(res => {

View File

@ -23,6 +23,7 @@ describe('Client', () => {
clientFk: 1101,
companyFk: 442
};
controller.bankSelection = {accountingType: {code: 'myCode'}};
}));
describe('bankSelection() setter', () => {

View File

@ -1 +1,2 @@
View receipt: Ver recibo
Amount exceeded: Según ley contra el fraude no se puede recibir cobros por importe igual o superior a {{maxAmount}}

View File

@ -6,7 +6,7 @@ class Controller extends Section {
super($element, $);
const from = new Date();
from.setDate(from.getDate());
from.setDate(from.getDate() - 75);
from.setHours(0, 0, 0, 0);
const to = new Date();

View File

@ -101,7 +101,10 @@
"mysql": {
"columnName": "withholdingSageFk"
}
}
},
"isPayMethodChecked": {
"type": "boolean"
}
},
"relations": {
"payMethod": {

View File

@ -36,6 +36,10 @@
label="Active"
ng-model="$ctrl.supplier.isActive">
</vn-check>
<vn-check
label="PayMethodChecked"
ng-model="$ctrl.supplier.isPayMethodChecked">
</vn-check>
</vn-horizontal>
<vn-horizontal>
<vn-textarea

View File

@ -1,4 +1,5 @@
Notes: Notas
Active: Activo
Verified: Verificado
PayMethodChecked: Método de pago validado
Responsible for approving invoices: Responsable de aprobar las facturas

View File

@ -42,27 +42,21 @@ module.exports = Self => {
const stmts = [];
const startedMinusOne = new Date(started);
startedMinusOne.setDate(started.getDate() - 1);
const endedPlusOne = new Date(ended);
endedPlusOne.setDate(ended.getDate() + 1);
stmts.push(`
DROP TEMPORARY TABLE IF EXISTS
tmp.timeControlCalculate,
tmp.timeBusinessCalculate
`);
stmts.push(new ParameterizedSQL('CALL vn.timeControl_calculateByUser(?, ?, ?)', [userId, startedMinusOne, endedPlusOne]));
stmts.push(new ParameterizedSQL('CALL vn.timeControl_calculateByUser(?, ?, ?)', [userId, started, ended]));
stmts.push(new ParameterizedSQL('CALL vn.timeBusiness_calculateByUser(?, ?, ?)', [userId, startedMinusOne, endedPlusOne]));
stmts.push(new ParameterizedSQL('CALL vn.timeBusiness_calculateByUser(?, ?, ?)', [userId, started, ended]));
const resultIndex = stmts.push(new ParameterizedSQL(`
SELECT tbc.dated, tbc.timeWorkSeconds expectedHours, tcc.timeWorkSeconds workedHours
FROM tmp.timeBusinessCalculate tbc
LEFT JOIN tmp.timeControlCalculate tcc ON tcc.dated = tbc.dated
WHERE tbc.dated BETWEEN ? AND ?
SELECT tcc.dated, tbc.timeWorkSeconds expectedHours, tcc.timeWorkSeconds workedHours
FROM tmp.timeControlCalculate tcc
LEFT JOIN tmp.timeBusinessCalculate tbc ON tcc.dated = tbc.dated
WHERE tcc.dated BETWEEN DATE(?) AND DATE(?)
`, [started, ended])) - 1;
stmts.push(`

View File

@ -1,17 +1,17 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('Worker getWorkedHours()', () => {
it(`should return the expected hours and the worked hours of a given date`, async() => {
const workerID = 1106;
let started = new Date();
const started = new Date();
started.setHours(0, 0, 0, 0);
let ended = new Date();
ended.setHours(0, 0, 0, 0);
const ended = new Date();
ended.setHours(23, 59, 59, 999);
const [result] = await app.models.Worker.getWorkedHours(workerID, started, ended);
const [result] = await models.Worker.getWorkedHours(workerID, started, ended);
expect(result.expectedHours).toEqual(28800); // 8:00 hours seconds
expect(result.expectedHours).toEqual(28800); // 8:00 hours in seconds
expect(result.workedHours).toEqual(29400); // 8:10 hours in seconds
});
});

View File

@ -171,7 +171,6 @@ class Controller extends Section {
from: from,
to: to
};
const query = `Workers/${this.$params.id}/getWorkedHours`;
return this.$http.get(query, {params}).then(res => {
const workDays = res.data;
@ -212,7 +211,8 @@ class Controller extends Section {
let todayInWeek = this.weekDays.find(day => day.dated.getTime() === today.getTime());
if (todayInWeek && todayInWeek.hours && todayInWeek.hours.length) {
const remainingTime = todayInWeek.workedHours ? ((todayInWeek.expectedHours - todayInWeek.workedHours) * 1000) : null;
const remainingTime = todayInWeek.workedHours ?
((todayInWeek.expectedHours - todayInWeek.workedHours) * 1000) : null;
const lastKnownEntry = todayInWeek.hours[todayInWeek.hours.length - 1];
const lastKnownTime = new Date(lastKnownEntry.timed).getTime();
const finishTimeStamp = lastKnownTime && remainingTime ? lastKnownTime + remainingTime : null;

View File

@ -0,0 +1,63 @@
module.exports = Self => {
Self.remoteMethod('getEventsFiltered', {
description: 'Get events filtered for zone and date',
accepts: [
{
arg: 'zoneFk',
type: 'number',
description: 'The zone id',
required: true
},
{
arg: 'started',
type: 'date',
description: 'The date calendar start',
},
{
arg: 'ended',
type: 'date',
description: 'The date calendar end',
}
],
returns: {
type: 'object',
root: true
},
http: {
path: `/getEventsFiltered`,
verb: 'GET'
}
});
Self.getEventsFiltered = async(zoneFk, started, ended, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
query = `
SELECT *
FROM vn.zoneEvent
WHERE zoneFk = ?
AND ((type = 'indefinitely')
OR (type = 'day' AND dated BETWEEN ? AND ?)
OR (type = 'range'
AND (
(started BETWEEN ? AND ?)
OR (ended BETWEEN ? AND ?)
)
)
)
ORDER BY type='indefinitely' DESC, type='range' DESC, type='day' DESC;`;
const events = await Self.rawSql(query, [zoneFk, started, ended, started, ended, started, ended], myOptions);
query = `
SELECT *
FROM vn.zoneExclusion
WHERE zoneFk = ?
AND dated BETWEEN ? AND ?;`;
const exclusions = await Self.rawSql(query, [zoneFk, started, ended], myOptions);
return {events, exclusions};
};
};

View File

@ -1,12 +1,12 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('agency clone()', () => {
it('should clone a zone', async() => {
const tx = await app.models.Zone.beginTransaction({});
const tx = await models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
const newZone = await app.models.Zone.clone(1, options);
const newZone = await models.Zone.clone(1, options);
expect(newZone.name).toEqual('Zone pickup A');

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context');
describe('zone deletezone()', () => {
@ -16,13 +16,13 @@ describe('zone deletezone()', () => {
active: activeCtx
});
try {
const originalTickets = await app.models.Ticket.find({
const originalTickets = await models.Ticket.find({
where: {
zoneFk: zoneId
}
});
ticketIDs = originalTickets.map(ticket => ticket.id);
originalTicketStates = await app.models.TicketState.find({where: {
originalTicketStates = await models.TicketState.find({where: {
ticketFk: {inq: ticketIDs},
code: 'FIXING'}});
} catch (error) {
@ -31,16 +31,16 @@ describe('zone deletezone()', () => {
});
it('should delete a zone and update their tickets', async() => {
const tx = await app.models.Zone.beginTransaction({});
const tx = await models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
await app.models.Zone.deleteZone(ctx, zoneId, options);
await models.Zone.deleteZone(ctx, zoneId, options);
const updatedZone = await app.models.Zone.findById(zoneId, null, options);
const anUpdatedTicket = await app.models.Ticket.findById(ticketIDs[0], null, options);
const updatedZone = await models.Zone.findById(zoneId, null, options);
const anUpdatedTicket = await models.Ticket.findById(ticketIDs[0], null, options);
const updatedTicketStates = await app.models.TicketState.find({
const updatedTicketStates = await models.TicketState.find({
where: {
ticketFk: {inq: ticketIDs},
code: 'FIXING'

View File

@ -1,13 +1,13 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('zone getEvents()', () => {
it('should return all events for the specified geo and agency mode', async() => {
const tx = await app.models.Zone.beginTransaction({});
const tx = await models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
let result = await app.models.Zone.getEvents(20, 1, options);
let result = await models.Zone.getEvents(20, 1, options);
expect(result.events.length).toEqual(10);

View File

@ -0,0 +1,21 @@
const models = require('vn-loopback/server/server').models;
describe('zone getEventsFiltered()', () => {
it('should return events and exclusions for the specified zoneFk in a range of dates', async() => {
const tx = await models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
let result = await models.Zone.getEventsFiltered(10, '2021-10-01', '2021-10-02', options);
expect(result.events.length).toEqual(1);
expect(result.exclusions.length).toEqual(0);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,13 +1,13 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('zone getLeaves()', () => {
it('should return the country and the childs containing the search value', async() => {
const tx = await app.models.Zone.beginTransaction({});
const tx = await models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
let result = await app.models.Zone.getLeaves(1, null, '46000', options);
let result = await models.Zone.getLeaves(1, null, '46000', options);
expect(result.length).toEqual(1);

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('zone includingExpired()', () => {
const inhousePickupId = 1;
@ -6,14 +6,14 @@ describe('zone includingExpired()', () => {
const warehouseId = 1;
it('should return an array containing all zones', async() => {
const tx = await app.models.Zone.beginTransaction({});
const tx = await models.Zone.beginTransaction({});
const ctx = {req: {accessToken: {userId: 1}}};
const where = {};
try {
const options = {transaction: tx};
const result = await app.models.Zone.includingExpired(ctx, {where}, options);
const result = await models.Zone.includingExpired(ctx, {where}, options);
expect(result.length).toBeGreaterThan(2);
@ -28,12 +28,12 @@ describe('zone includingExpired()', () => {
const ctx = {req: {accessToken: {userId: 1}}};
const where = {agencyModeFk: inhousePickupId};
const tx = await app.models.Zone.beginTransaction({});
const tx = await models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
const result = await app.models.Zone.includingExpired(ctx, {where}, options);
const result = await models.Zone.includingExpired(ctx, {where}, options);
const validAgency = result.every(zone => zone.agencyModeFk = inhousePickupId);
@ -56,12 +56,12 @@ describe('zone includingExpired()', () => {
warehouseFk: warehouseId
};
const tx = await app.models.Zone.beginTransaction({});
const tx = await models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
const result = await app.models.Zone.includingExpired(ctx, {where}, options);
const result = await models.Zone.includingExpired(ctx, {where}, options);
const firstZone = result[0];
expect(firstZone.name).toEqual('Zone pickup A');

View File

@ -1,13 +1,13 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('zone toggleIsIncluded()', () => {
it('should return the created location with isIncluded true', async() => {
const tx = await app.models.Zone.beginTransaction({});
const tx = await models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
let result = await app.models.Zone.toggleIsIncluded(1, 20, true, options);
let result = await models.Zone.toggleIsIncluded(1, 20, true, options);
expect(result.isIncluded).toBeTrue();
@ -19,12 +19,12 @@ describe('zone toggleIsIncluded()', () => {
});
it('should return the created location with isIncluded false', async() => {
const tx = await app.models.Zone.beginTransaction({});
const tx = await models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
let result = await app.models.Zone.toggleIsIncluded(1, 20, false, options);
let result = await models.Zone.toggleIsIncluded(1, 20, false, options);
expect(result.isIncluded).toBeFalse();
@ -36,14 +36,14 @@ describe('zone toggleIsIncluded()', () => {
});
it('should return the amount of deleted locations', async() => {
const tx = await app.models.Zone.beginTransaction({});
const tx = await models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
await app.models.Zone.toggleIsIncluded(1, 20, false, options);
await models.Zone.toggleIsIncluded(1, 20, false, options);
let result = await app.models.Zone.toggleIsIncluded(1, 20, undefined, options);
let result = await models.Zone.toggleIsIncluded(1, 20, undefined, options);
expect(result).toEqual({count: 1});

View File

@ -2,6 +2,7 @@ module.exports = Self => {
require('../methods/zone/clone')(Self);
require('../methods/zone/getLeaves')(Self);
require('../methods/zone/getEvents')(Self);
require('../methods/zone/getEventsFiltered')(Self);
require('../methods/zone/toggleIsIncluded')(Self);
require('../methods/zone/getUpcomingDeliveries')(Self);
require('../methods/zone/deleteZone')(Self);

View File

@ -1,5 +1,6 @@
<vn-zone-calendar
id="calendar"
vn-id="calendar"
data="data"
on-selection="$ctrl.onSelection($days, $type, $weekday, $events, $exclusions)"
class="vn-w-md">

View File

@ -21,14 +21,18 @@ class Controller extends Section {
}
refresh() {
let data = {};
this.$q.all([
this.$http.get(this.path)
.then(res => data.events = res.data),
this.$http.get(this.exclusionsPath)
.then(res => data.exclusions = res.data)
]).finally(() => {
this.$.data = data;
this.$.data = null;
this.$.$applyAsync(() => {
const params = {
zoneFk: this.$params.id,
started: this.$.calendar.firstDay,
ended: this.$.calendar.lastDay
};
this.$http.get(`Zones/getEventsFiltered`, {params}).then(res => {
const data = res.data;
this.$.data = data;
});
});
}

View File

@ -17,8 +17,26 @@ describe('component vnZoneEvents', () => {
describe('refresh()', () => {
it('should set the zone and then call both getSummary() and getWarehouses()', () => {
$httpBackend.expectGET(`Zones/1/events`).respond({id: 1});
$httpBackend.expectGET(`Zones/1/exclusions`).respond({id: 1});
const date = '2021-10-01';
controller.$params.id = 999;
controller.$.calendar = {
firstDay: date,
lastDay: date
};
const params = {
zoneFk: controller.$params.id,
started: date,
ended: date
};
const query = `Zones/getEventsFiltered?ended=${date}&started=${date}&zoneFk=${params.zoneFk}`;
const response = {
events: 'myEvents',
exclusions: 'myExclusions'
};
$httpBackend.whenGET(query).respond(response);
controller.refresh();
$httpBackend.flush();