This commit is contained in:
Vicente Falco 2018-03-13 10:48:29 +01:00
commit aad1d5d0f3
46 changed files with 1787 additions and 360 deletions

View File

@ -6,3 +6,4 @@ locator: []
production: [] production: []
salix: [] salix: []
route: [] route: []
ticket: []

View File

@ -8,5 +8,7 @@ export default {
locator: locator:
cb => require.ensure([], () => cb(require('locator'))), cb => require.ensure([], () => cb(require('locator'))),
item: item:
cb => require.ensure([], () => cb(require('item'))) cb => require.ensure([], () => cb(require('item'))),
ticket:
cb => require.ensure([], () => cb(require('ticket')))
}; };

1
client/ticket/index.js Normal file
View File

@ -0,0 +1 @@
export * from './src/ticket';

14
client/ticket/routes.json Normal file
View File

@ -0,0 +1,14 @@
{
"module": "ticket",
"name": "Tickets",
"icon": "receipt",
"validations": false,
"routes": [
{
"url": "/tickets",
"state": "tickets",
"component": "vn-ticket-index",
"acl": ["developer"]
}
]
}

View File

@ -0,0 +1,24 @@
<mg-ajax path="/client/api/Clients/filter" options="mgIndex"></mg-ajax>
<div margin-medium>
<div class="vn-list">
<vn-card>
<vn-horizontal pad-medium>
<vn-searchbar vn-one
index="index"
on-search="$ctrl.search(index)"
ignore-keys = "['page', 'size', 'search']">
</vn-searchbar>
</vn-horizontal>
</vn-card>
<vn-card margin-medium-top>
<vn-ticket-item
ng-repeat="ticket in index.model.instances"
ticket="ticket">
</vn-ticket-item>
</vn-card>
<vn-paging index="index" total="index.model.count"></vn-paging>
</div>
</div>
<a ui-sref="create" fixed-bottom-right>
<vn-float-button icon="person_add"></vn-float-button>
</a>

View File

@ -0,0 +1,14 @@
import ngModule from '../module';
import './item';
export default class Controller {
search(index) {
index.accept();
}
}
Controller.$inject = [];
ngModule.component('vnTicketIndex', {
template: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,17 @@
<a
ui-sref="clientCard.basicData({ id: {{::$ctrl.ticket.id}} })"
translate-attr="{title: 'View client'}"
class="vn-list-item">
<vn-horizontal ng-click="$ctrl.onClick($event)">
<vn-one>
<h6>{{::$ctrl.ticket.name}}</h6>
<div><vn-label translate>Id</vn-label> {{::$ctrl.ticket.id}}</div>
</vn-one>
<vn-horizontal class="buttons">
<vn-icon
vn-tooltip="Preview"
icon="icon-preview">
</vn-icon>
</vn-horizontal>
</vn-horizontal>
</a>

View File

@ -0,0 +1,20 @@
import ngModule from '../module';
class Controller {
onClick(event) {
if (event.defaultPrevented)
event.stopImmediatePropagation();
}
preview(event) {
event.preventDefault();
}
}
ngModule.component('vnTicketItem', {
controller: Controller,
template: require('./item.html'),
bindings: {
ticket: '<'
}
});

View File

@ -0,0 +1,3 @@
vn-ticket-item {
display: block;
}

View File

@ -0,0 +1 @@
Tickets: Tickets

View File

@ -0,0 +1 @@
Tickets: Tickets

View File

@ -0,0 +1,5 @@
import {ng} from 'vendor';
import 'core';
const ngModule = ng.module('ticket', ['vnCore']);
export default ngModule;

View File

@ -0,0 +1,4 @@
export * from './module';
import './index/index';

File diff suppressed because it is too large Load Diff

View File

@ -24,8 +24,6 @@ INSERT INTO `account`.`user`(`id`,`name`,`password`,`role`,`active`,`email`)
(109, 'BruceBanner', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'BruceBanner@verdnatura.es'), (109, 'BruceBanner', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'BruceBanner@verdnatura.es'),
(110, 'JessicaJones', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'JessicaJones@verdnatura.es'); (110, 'JessicaJones', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'JessicaJones@verdnatura.es');
INSERT INTO `vn`.`worker`(`workerCode`, `id`, `firstName`, `name`, `userFk`) INSERT INTO `vn`.`worker`(`workerCode`, `id`, `firstName`, `name`, `userFk`)
VALUES VALUES
('LGN', 106, 'David Charles', 'Haller', 106), ('LGN', 106, 'David Charles', 'Haller', 106),
@ -273,6 +271,12 @@ INSERT INTO `vn2008`.`empresa`(`id`, `abbreviation`, `registro`, `gerente_id`, `
(9, 5, 5, NULL, CURDATE(), 105, 'Hulk', 109), (9, 5, 5, NULL, CURDATE(), 105, 'Hulk', 109),
(10, 6, 5, NULL, CURDATE(), 105, 'Jessica Jones', 110); (10, 6, 5, NULL, CURDATE(), 105, 'Jessica Jones', 110);
INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`)
VALUES
( 1, 1 , 1, 'ready' ),
( 2, 2 , 2, 'do it fast please'),
( 3, 3 , 3, '');
INSERT INTO `vn`.`ticketTracking`(`id`, `ticketFk`, `stateFk`, `workerFk`, `created`) INSERT INTO `vn`.`ticketTracking`(`id`, `ticketFk`, `stateFk`, `workerFk`, `created`)
VALUES VALUES
(1, 1, 1, 5, CURDATE()), (1, 1, 1, 5, CURDATE()),
@ -393,6 +397,24 @@ INSERT INTO `vn`.`item`(`id`, `name`,`typeFk`,`size`,`inkFk`,`category`,`stems`,
(4, 'Mark I', 1, 60, 'AMR', 'EXT', 1, 1, 'Iron Mans first armor', 1, 05080000, 1, 2, 0, NULL, 0, 66090, 2), (4, 'Mark I', 1, 60, 'AMR', 'EXT', 1, 1, 'Iron Mans first armor', 1, 05080000, 1, 2, 0, NULL, 0, 66090, 2),
(5, 'Mjolnir', 3, 30, 'AZR', 'EXT', 1, 2, 'Thors hammer!', 2, 06021010, 1, 2, 0, NULL, 0, 67350, 2); (5, 'Mjolnir', 3, 30, 'AZR', 'EXT', 1, 2, 'Thors hammer!', 2, 06021010, 1, 2, 0, NULL, 0, 67350, 2);
INSERT INTO `vn`.`packaging`(`id`, `volume`, `width`, `height`, `depth`, `isPackageReturnable`, `created`, `itemFk`, `price`)
VALUES
(1, 0.00, 10, 10, 0, 0, CURDATE(), 1, 1.50),
(2, 100.00, 20, 20, 0, 0, CURDATE(), 2, 1.00),
('a', 50.00, 30, 30, 0, 1, CURDATE(), 3, 0.00);
INSERT INTO `vn`.`ticketPackaging`(`id`, `ticketFk`, `packagingFk`, `quantity`, `created`, `pvp`)
VALUES
( 1, 1, 1, 2, CURDATE(), NULL),
( 2, 2, 2, 1, CURDATE(), NULL),
( 3, 3, 'a', 4, CURDATE(), NULL);
INSERT INTO `vn`.`sale`(`id`, `itemFk`, `ticketFk`, `concept`, `quantity`, `price`, `discount`, `reserved`, `isPicked`, `created`)
VALUES
( 1, 1, 1, 'Gem of Time', 5 , 1.5, 0, 0, 0, CURDATE()),
( 2, 1, 1, 'Gem of Time', 2 , 1.5, 0, 0, 0, CURDATE()),
( 3, 2, 2, 'Mjolnir' , 10, 4 , 0, 0, 0, CURDATE());
INSERT INTO `vn`.`itemBarcode`(`id`, `itemFk`, `code`) INSERT INTO `vn`.`itemBarcode`(`id`, `itemFk`, `code`)
VALUES VALUES
(1, 1 ,1 ), (1, 1 ,1 ),

View File

@ -0,0 +1,9 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Ticket', '*', '*', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('TicketObservation', '*', '*', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Route', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Sale', '*', '*', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('TicketTracking', '*', '*', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('TicketState', '*', '*', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('TicketPackaging', '*', '*', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Packaging', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Packaging', '*', 'WRITE', 'ALLOW', 'ROLE', 'logistic');

View File

@ -0,0 +1,18 @@
USE `vn`;
CREATE
OR REPLACE ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `vn`.`packaging` AS
SELECT
`c`.`Id_Cubo` AS `id`,
`c`.`Volumen` AS `volume`,
`c`.`X` AS `width`,
`c`.`Y` AS `height`,
`c`.`Z` AS `depth`,
`c`.`Retornable` AS `isPackageReturnable`,
`c`.`odbc_date` AS `created`,
`c`.`item_id` AS `itemFk`,
`c`.`pvp` AS `price`
FROM
`vn2008`.`Cubos` `c`;

View File

@ -1,2 +1,2 @@
mysqldump --defaults-file=connect.ini --default-character-set=utf8 --no-data --triggers --routines --events --databases account util vn2008 vn edi bs bi pbx cache salix vncontrol hedera > 01-structure.sql mysqldump --defaults-file=connect.ini --default-character-set=utf8 --no-data --triggers --routines --events --databases account util vn2008 vn edi bs bi pbx cache salix vncontrol hedera stock > 01-structure.sql

View File

@ -1,13 +1,6 @@
module.exports = function(Ticket) { module.exports = function(Ticket) {
Ticket.remoteMethod('list', { Ticket.remoteMethod('list', {
description: 'List tickets for production', description: 'List tickets for production',
/* accepts: {
arg: 'id',
type: 'number',
required: true,
description: 'Model id',
http: {source: 'path'}
},*/
returns: { returns: {
arg: 'tickets', arg: 'tickets',
type: 'object' type: 'object'
@ -19,19 +12,8 @@ module.exports = function(Ticket) {
}); });
Ticket.list = function(cb) { Ticket.list = function(cb) {
// list();
};
function list() {
var params = [1, 0]; var params = [1, 0];
var query = 'CALL production_control_source(?, ?)'; var query = 'CALL production_control_source(?, ?)';
var cb = function(error, res) {
if (error) console.log(error);
else console.log(res);
};
Ticket.rawSql(query, params, cb); Ticket.rawSql(query, params, cb);
}; };
}; };

View File

@ -50,10 +50,22 @@ module.exports = function(Self) {
allowBlank: true allowBlank: true
}); });
let validateDni = require('../validations/validateDni'); Self.validateAsync('fi', fiIsValid, {
Self.validateBinded('fi', validateDni, {
message: 'DNI Incorrecto' message: 'DNI Incorrecto'
}); });
let validateDni = require('../validations/validateDni');
async function fiIsValid(err, done) {
let filter = {
fields: ['code'],
where: {id: this.countryFk}
};
let country = await Self.app.models.Country.findOne(filter);
let code = country ? country.code.toLowerCase() : null;
if (!validateDni(this.fi, code))
err();
done();
}
Self.validate('payMethod', hasSalesMan, { Self.validate('payMethod', hasSalesMan, {
message: 'No se puede cambiar la forma de pago si no hay comercial asignado' message: 'No se puede cambiar la forma de pago si no hay comercial asignado'

View File

@ -0,0 +1,76 @@
{
"name": "Ticket",
"base": "VnModel",
"options": {
"mysql": {
"table": "ticket"
}
},
"properties": {
"id": {
"id": true,
"type": "Number",
"description": "Identifier"
},
"shipped": {
"type": "date",
"required": true
},
"landed": {
"type": "date"
},
"nickname": {
"type": "String"
},
"location": {
"type": "String"
},
"solution": {
"type": "String"
},
"packages": {
"type": "Number"
},
"created": {
"type": "date"
}
},
"relations": {
"client": {
"type": "belongsTo",
"model": "Client",
"foreignKey": "clientFk"
},
"warehouse": {
"type": "belongsTo",
"model": "Warehouse",
"foreignKey": "warehouseFk"
},
"invoiceOut": {
"type": "belongsTo",
"model": "InvoiceOut",
"foreignKey": "refFk"
},
"address": {
"type": "belongsTo",
"model": "Address",
"foreignKey": "addressFk"
},
"route": {
"type": "belongsTo",
"model": "Route",
"foreignKey": "routeFk"
},
"company": {
"type": "belongsTo",
"model": "Company",
"foreignKey": "companyFk"
},
"agencyMode": {
"type": "belongsTo",
"model": "AgencyMode",
"foreignKey": "agencyModeFk",
"required": true
}
}
}

View File

@ -14,7 +14,7 @@ describe('DNI validation', () => {
expect(isValid).toBeTruthy(); expect(isValid).toBeTruthy();
}); });
it('should return true for spanish DNI with exceeded digits', () => { it('should return false for spanish DNI with exceeded digits', () => {
let isValid = validateDni('208497563239A'); let isValid = validateDni('208497563239A');
expect(isValid).toBeFalsy(); expect(isValid).toBeFalsy();
@ -41,19 +41,19 @@ describe('DNI validation', () => {
describe('French', () => { describe('French', () => {
it('should return true for valid french DNI', () => { it('should return true for valid french DNI', () => {
let isValid = validateDni('FR1B123456789'); let isValid = validateDni('1B123456789', 'fr');
expect(isValid).toBeTruthy(); expect(isValid).toBeTruthy();
}); });
it('should return true for french DNI with exceeded digits', () => { it('should return false for french DNI with exceeded digits', () => {
let isValid = validateDni('FR1B12345678910'); let isValid = validateDni('1B12345678910', 'fr');
expect(isValid).toBeFalsy(); expect(isValid).toBeFalsy();
}); });
it('should return true for french DNI with bad syntax', () => { it('should return false for french DNI with bad syntax', () => {
let isValid = validateDni('FR1B12345678A'); let isValid = validateDni('1B12345678A', 'fr');
expect(isValid).toBeFalsy(); expect(isValid).toBeFalsy();
}); });
@ -61,19 +61,19 @@ describe('DNI validation', () => {
describe('Italian', () => { describe('Italian', () => {
it('should return true for valid italian DNI', () => { it('should return true for valid italian DNI', () => {
let isValid = validateDni('IT12345678911'); let isValid = validateDni('12345678911', 'it');
expect(isValid).toBeTruthy(); expect(isValid).toBeTruthy();
}); });
it('should return true for italian DNI with exceeded digits', () => { it('should return false for italian DNI with exceeded digits', () => {
let isValid = validateDni('IT123456789112'); let isValid = validateDni('123456789112', 'it');
expect(isValid).toBeFalsy(); expect(isValid).toBeFalsy();
}); });
it('should return true for italian DNI with bad syntax', () => { it('should return false for italian DNI with bad syntax', () => {
let isValid = validateDni('IT1234567891A'); let isValid = validateDni('1234567891A', 'it');
expect(isValid).toBeFalsy(); expect(isValid).toBeFalsy();
}); });
@ -81,19 +81,19 @@ describe('DNI validation', () => {
describe('Portuguese', () => { describe('Portuguese', () => {
it('should return true for valid portuguese DNI', () => { it('should return true for valid portuguese DNI', () => {
let isValid = validateDni('PT123456789'); let isValid = validateDni('123456789', 'pt');
expect(isValid).toBeTruthy(); expect(isValid).toBeTruthy();
}); });
it('should return true for portuguese DNI with exceeded digits', () => { it('should return false for portuguese DNI with exceeded digits', () => {
let isValid = validateDni('PT12345678910'); let isValid = validateDni('12345678910', 'pt');
expect(isValid).toBeFalsy(); expect(isValid).toBeFalsy();
}); });
it('should return true for portuguese DNI with bad syntax', () => { it('should return false for portuguese DNI with bad syntax', () => {
let isValid = validateDni('PT12345678A'); let isValid = validateDni('12345678A', 'pt');
expect(isValid).toBeFalsy(); expect(isValid).toBeFalsy();
}); });

View File

@ -1,14 +1,10 @@
module.exports = function(fiWithCountry) { module.exports = function(fi, country) {
if (fiWithCountry == null) return true; if (fi == null) return true;
if (typeof fiWithCountry != 'string') return false; if (typeof fi != 'string') return false;
fiWithCountry = fiWithCountry.toUpperCase(); fi = fi.toUpperCase();
country = country ? country.toLowerCase() : 'es';
if (!/^[A-Z]{2}/.test(fiWithCountry))
fiWithCountry = `ES${fiWithCountry}`;
let country = fiWithCountry.substring(0, 2).toLowerCase();
let fi = fiWithCountry.substring(2);
let len = fi.length; let len = fi.length;
let validators = { let validators = {
@ -38,7 +34,7 @@ module.exports = function(fiWithCountry) {
let sum = (pairSum + oddSum).toString(); let sum = (pairSum + oddSum).toString();
let units = parseInt(sum.charAt(sum.length - 1)); let units = parseInt(sum.charAt(sum.length - 1));
let control = units != 0 ? 10 - units : 0; let control = units == 0 ? 0 : 10 - units;
let index = 'JABCDEFGHI'.indexOf(lastDigit); let index = 'JABCDEFGHI'.indexOf(lastDigit);
computedDigit = index == -1 ? control.toString() : index; computedDigit = index == -1 ? control.toString() : index;
} else { } else {
@ -67,7 +63,7 @@ module.exports = function(fiWithCountry) {
let validator = validators[country]; let validator = validators[country];
if (!validator) if (!validator)
return false; return true;
return validator.regExp.test(fi) return validator.regExp.test(fi)
&& (!validator.validate || validator.validate()); && (!validator.validate || validator.validate());

View File

@ -56,5 +56,17 @@
}, },
"Worker": { "Worker": {
"dataSource": "vn" "dataSource": "vn"
} },
"Ticket": {
"dataSource": "vn"
},
"Route": {
"dataSource": "vn"
},
"State":{
"dataSource": "vn"
},
"TicketState":{
"dataSource": "vn"
}
} }

View File

@ -1,19 +0,0 @@
{
"name": "Ticket",
"base": "VnModel",
"options": {
"mysql": {
"table": "ticket"
}
},
"properties": {
"id": {
"id": true,
"type": "Number",
"forceId": false
},
"shipped": {
"type": "date"
}
}
}

View File

@ -7,20 +7,5 @@
}, },
"MessageInbox": { "MessageInbox": {
"dataSource": "vn" "dataSource": "vn"
},
"Route": {
"dataSource": "vn"
},
"State":{
"dataSource": "vn"
},
"Ticket": {
"dataSource": "vn"
},
"TicketState":{
"dataSource": "vn"
},
"TicketTracking": {
"dataSource": "vn"
} }
} }

View File

@ -0,0 +1,12 @@
FROM node:8.9.4
COPY ticket /app
COPY loopback /loopback
WORKDIR /app
RUN npm install
RUN npm -g install pm2
CMD ["pm2-docker", "./server/server.js"]

View File

@ -0,0 +1,28 @@
{
"name": "ObservationType",
"base": "VnModel",
"options": {
"mysql": {
"table": "observationType"
}
},
"properties": {
"id": {
"id": true,
"type": "Number",
"description": "Identifier"
},
"description": {
"type": "String",
"required": true
}
},
"acls": [
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
]
}

View File

@ -0,0 +1,45 @@
{
"name": "Packaging",
"base": "VnModel",
"options": {
"mysql": {
"table": "packaging"
}
},
"properties": {
"id": {
"id": true,
"type": "Number",
"description": "Identifier"
},
"volume": {
"type": "Number"
},
"X": {
"type": "Date"
},
"Y": {
"type": "Number"
},
"Z": {
"type": "Number"
},
"isPackageReturnable": {
"type": "Number"
},
"created": {
"type": "Date"
},
"price": {
"type": "Number"
}
},
"relations": {
"item": {
"type": "belongsTo",
"model": "Iicket",
"foreignKey": "itemFk"
}
}
}

View File

@ -0,0 +1,51 @@
{
"name": "Sale",
"base": "VnModel",
"options": {
"mysql": {
"table": "sale"
}
},
"properties": {
"id": {
"id": true,
"type": "Number",
"description": "Identifier"
},
"concept": {
"type": "String"
},
"quantity": {
"type": "Number"
},
"price": {
"type": "Number"
},
"discount": {
"type": "Number"
},
"reserved": {
"type": "Number"
},
"isPicked": {
"type": "Number"
},
"created": {
"type": "date"
}
},
"relations": {
"item": {
"type": "belongsTo",
"model": "Item",
"foreignKey": "itemFk",
"required": true
},
"ticket": {
"type": "belongsTo",
"model": "Ticket",
"foreignKey": "ticketFk",
"required": true
}
}
}

View File

@ -0,0 +1,34 @@
{
"name": "TicketObservation",
"base": "VnModel",
"options": {
"mysql": {
"table": "ticketObservation"
}
},
"properties": {
"id": {
"id": true,
"type": "Number",
"description": "Identifier"
},
"description": {
"type": "String",
"required": true
}
},
"relations": {
"ticket": {
"type": "belongsTo",
"model": "Ticket",
"foreignKey": "ticketFk",
"required": true
},
"observationType": {
"type": "belongsTo",
"model": "ObservationType",
"foreignKey": "observationTypeFk",
"required": true
}
}
}

View File

@ -0,0 +1,38 @@
{
"name": "TicketPackaging",
"base": "VnModel",
"options": {
"mysql": {
"table": "ticketPackaging"
}
},
"properties": {
"id": {
"id": true,
"type": "Number",
"description": "Identifier"
},
"quantity": {
"type": "Number"
},
"created": {
"type": "Date"
},
"pvp": {
"type": "Number"
}
},
"relations": {
"ticket": {
"type": "belongsTo",
"model": "Ticket",
"foreignKey": "ticketFk"
},
"packaging": {
"type": "belongsTo",
"model": "Packaging",
"foreignKey": "packagingFk"
}
}
}

View File

@ -30,7 +30,7 @@
}, },
"worker": { "worker": {
"type": "belongsTo", "type": "belongsTo",
"model": "worker", "model": "Worker",
"foreignKey": "workerFk" "foreignKey": "workerFk"
} }
} }

View File

@ -0,0 +1,16 @@
{
"name": "vn-ticket",
"version": "1.0.0",
"main": "server/server.js",
"scripts": {
"lint": "eslint .",
"start": "node .",
"posttest": "npm run lint && nsp check"
},
"repository": {
"type": "git",
"url": "https://git.verdnatura.es/salix"
},
"license": "GPL-3.0",
"description": "vn-ticket"
}

View File

@ -0,0 +1,20 @@
{
"TicketObservation": {
"dataSource": "vn"
},
"ObservationType": {
"dataSource": "vn"
},
"Sale": {
"dataSource": "vn"
},
"TicketTracking": {
"dataSource": "vn"
},
"TicketPackaging": {
"dataSource": "vn"
},
"Packaging": {
"dataSource": "vn"
}
}

View File

@ -0,0 +1,5 @@
var vnLoopback = require('../../loopback/server/server.js');
var app = module.exports = vnLoopback.loopback();
vnLoopback.boot(app, __dirname, module);