Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- var self,
- RegistrationController = require(PATHS.CONTROLLERS + '/RegistrationController'),
- validator = require('validator');
- module.exports = self = {
- getFields: function() {
- var d = Q.defer();
- if (!self.fieldsScheme) {
- Q.resolve().then(function() {
- return prepareData();
- }).then(function(data) {
- return buildFields(data);
- }).then(function(fieldsScheme) {
- self.fieldsScheme = fieldsScheme;
- d.resolve(__.deepExtend({}, fieldsScheme));
- }).fail(function(err) {
- d.reject(err);
- }).done();
- }
- else {
- d.resolve(__.deepExtend({}, self.fieldsScheme));
- }
- function prepareData() {
- var i,
- d = Q.defer(),
- bodyTypesD = Q.defer(),
- bodyTypesData = Helpers.fileToLinesSync(PATHS.MOCKS + '/bodyTypes.txt', true),
- vtKeys = Object.keys(V.db.vehicleType.types),
- vehicleTypesSorting = vtKeys,
- bodyTypesSorting = [],
- bodyTypeLine = [],
- years = [];
- bodyTypesData.forEach(function(btLine) {
- if (!/^\s*$/.test(btLine)) {
- bodyTypeLine.push(btLine.split('|')[1]);
- }
- else {
- bodyTypesSorting.push(bodyTypeLine);
- bodyTypeLine = [];
- }
- });
- bodyTypesSorting.push(bodyTypeLine);
- models.BodyType.find(function(err, result) {
- var vehicleTypes = [],
- bodyTypes = {};
- if (!err) {
- vtKeys.forEach(function(vtKey) {
- vehicleTypes.push({
- key: vtKey,
- display: Helpers.capitalize(V.db.vehicleType.types[vtKey])
- });
- bodyTypes[vtKey] = [];
- });
- vehicleTypes.sort(function(a, b) {
- var aInd = vehicleTypesSorting.indexOf(a.key),
- bInd = vehicleTypesSorting.indexOf(b.key);
- return aInd > bInd ? 1 : (aInd === bInd ? 0 : -1);
- });
- result.forEach(function(bt) {
- bodyTypes[bt.vehicleType].push({
- id: bt._id,
- key: bt.key,
- display: Helpers.capitalize(bt.display).replace(' / ', ' ')
- });
- });
- Object.keys(bodyTypes).forEach(function(vtKey) {
- var baseInd = vehicleTypesSorting.indexOf(vtKey);
- bodyTypes[vtKey].sort(function(a, b) {
- var aInd = bodyTypesSorting[baseInd] ? bodyTypesSorting[baseInd].indexOf(a.key) : -1,
- bInd = bodyTypesSorting[baseInd] ? bodyTypesSorting[baseInd].indexOf(b.key) : -1;
- return aInd > bInd ? 1 : (aInd === bInd ? 0 : -1);
- });
- });
- bodyTypesD.resolve({
- vehicleTypes: vehicleTypes,
- bodyTypes: bodyTypes
- });
- }
- else {
- bodyTypesD.reject(err);
- }
- });
- for (i = (new Date).getFullYear() - 1; i>=1950; i--) {
- years.push(i);
- }
- Q.allSettled([bodyTypesD.promise]).then(function(data) {
- var btData = data[0];
- if (btData.state != 'fulfilled') {
- throw new Error('Error at prepareData for AdFormController.');
- }
- d.resolve({
- vehicleTypes: (btData && btData.value && btData.value.vehicleTypes) || [],
- bodyTypes: (btData && btData.value && btData.value.bodyTypes) || {},
- currencies: Helpers.getDataFromV('currency', 'ad'),
- years: Helpers.toSimpleOptions(years),
- colors: Helpers.getDataFromV('colors'),
- colorOptions: Helpers.getDataFromV('colorOptions'),
- fuels: Helpers.getDataFromV('fuels', 'carCore'),
- transmissions: Helpers.getDataFromV('transmissions', 'carCore'),
- drives: Helpers.getDataFromV('drives', 'carCore'),
- states: Helpers.getDataFromV('states'),
- });
- }).fail(function(err) {
- d.reject(err);
- }).done();
- return d.promise;
- }
- function buildFields(data) {
- var d = Q.defer();
- d.resolve({
- vehicleTypes: data.vehicleTypes,
- bodyTypes: data.bodyTypes,
- currencies: data.currencies,
- fields: {
- brand: {
- type: 'select',
- name: 'brand',
- label: 'Марка',
- disabled: true,
- options: [],
- defaultOption: {
- value: '',
- label: 'Выберите марку'
- },
- required: true,
- priority: 0
- },
- model: {
- type: 'select',
- name: 'model',
- label: 'Модель',
- disabled: true,
- options: [],
- defaultOption: {
- value: '',
- label: 'Выберите модель'
- },
- priority: 1
- },
- generation: {
- type: 'select',
- name: 'generation',
- label: 'Поколение',
- disabled: true,
- options: [],
- defaultOption: {
- value: '',
- label: 'Выберите поколение'
- },
- priority: 2
- },
- modification: {
- type: 'select',
- name: 'modification',
- label: 'Модификация',
- disabled: true,
- options: [],
- defaultOption: {
- value: '',
- label: 'Выберите модификацию'
- },
- priority: 3
- },
- year: {
- type: 'select',
- name: 'year',
- label: 'Год выпуска',
- options: data.years,
- defaultOption: {
- value: (new Date).getFullYear(),
- label: (new Date).getFullYear()
- },
- required: true,
- size: 's',
- priority: 4
- },
- mileage: {
- type: 'number',
- name: 'mileage',
- label: 'Пробег',
- mask: '{"mask": "9[9][9][.9]", "greedy": false}',
- appendix: 'тыс. км',
- required: true,
- priority: 5
- },
- color: {
- type: 'complex-list',
- name: 'color',
- label: 'Цвет',
- selects: data.colors,
- checks: data.colorOptions,
- defaultSelectOption: {
- value: '',
- label: 'Выберите цвет'
- },
- priority: 6
- },
- fuel: {
- type: 'select',
- name: 'fuel',
- label: 'Топливо',
- options: data.fuels,
- defaultOption: {
- value: '',
- label: 'Выберите тип топлива'
- },
- priority: 7
- },
- engineVolume: {
- type: 'number',
- name: 'engineVolume',
- label: 'Объем двигателя',
- mask: '{"mask": "9[9][.9]", "greedy": false}',
- appendix: 'л.',
- priority: 8
- },
- enginePower: {
- type: 'number',
- name: 'enginePower',
- label: 'Мощность двигателя',
- mask: '{"mask": "99[9]", "greedy": false}',
- appendix: 'л.с.',
- priority: 9
- },
- transmission: {
- type: 'select',
- name: 'transmission',
- label: 'Коробка передач',
- options: data.transmissions,
- defaultOption: {
- value: '',
- label: 'Выберите тип КПП'
- },
- priority: 10
- },
- drive: {
- type: 'push-buttons',
- name: 'drive',
- label: 'Привод',
- buttons: data.drives,
- priority: 11
- },
- state: {
- type: 'push-buttons',
- name: 'state',
- label: 'Состояние',
- buttons: data.states,
- priority: 12
- },
- owners: {
- type: 'number',
- name: 'owners',
- label: 'Количество владельцев',
- mask: '{"mask": "9[9]", "greedy": false}',
- appendix: 'чел.',
- priority: 13
- }
- }
- });
- return d.promise;
- }
- return d.promise;
- },
- getBasePageData: function() {
- var d = Q.defer();
- self.getFields().then(function(scheme) {
- d.resolve({
- vehicleTypes: scheme.vehicleTypes,
- bodyTypes: scheme.bodyTypes,
- currencies: scheme.currencies,
- tokens: _.union(Helpers.getDataFromV('tokens'), Helpers.getDataFromV('tokens', 'ad')),
- equipment: Equipment.getData4AddPage(),
- fields: scheme.fields,
- pData: {
- fieldsByVT: __.deepExtend({}, FieldsByVT.fields)
- }
- });
- }).fail(function(err) {
- d.reject(err);
- }).done();
- return d.promise;
- },
- createPage: function(req, res) {
- self.getBasePageData().then(function(data) {
- data.pageName = 'ad-create';
- res.view('ad-form/base', data);
- }).fail(function(err) {
- res.serverError(err);
- }).done();
- Stat.updateUserStats(req);
- },
- updatePage: function(req, res) {
- var adID = req.params.id;
- self.getBasePageData().then(function(data) {
- data.adID = adID;
- data.pData.adID = adID;
- data.isUpdate = true;
- data.pData.isUpdate = true;
- data.pageName = 'ad-update';
- models.Ad.findById(adID).populate('car.photos').exec(function(err, ad) {
- if (!err && ad) {
- data.pData.ad = ad.toJSON({ virtuals: true });
- if (data.pData.ad.car.photos) {
- data.pData.ad.car.photos.forEach(function(photo) {
- photo.url = File.getFilePath(photo.name, 'ad', 'small');
- });
- }
- res.view('ad-form/base', data);
- }
- else if (!err) {
- res.notFound();
- }
- else {
- sails.log.error('Error 345345345', err);
- res.notFound();
- }
- });
- }).fail(function(err) {
- res.serverError(err);
- }).done();
- Stat.updateUserStats(req);
- },
- save: function(req, res) {
- var data = JSON.parse(req.body.data || '{}');
- Q.resolve().then(function() {
- return self.validateAccepted(data, req);
- }).then(function() {
- return self.processUserOnSave(data, req);
- }).then(function(_data) {
- Object.keys(_data).forEach(function(k) {
- data[k] = _data[k];
- });
- return self.saveAd(data);
- }).then(function(result) {
- res.ok(result);
- }).fail(function(err) {
- if (err.isValidation) {
- res.badRequest(err.errors);
- }
- else {
- res.serverError(err);
- }
- }).done();
- },
- validateAccepted: function(data, req) {
- var userPhone, userEmail,
- d = Q.defer(),
- acceptValues = req.session.acceptValues || [],
- errors = [];
- if (req.isAuthenticated()) {
- userPhone = req.user.phones[0] || {};
- userEmail = req.user.email || {};
- if (!(userPhone.value == data.phone && userPhone.accepted)) checkPhone();
- if (!(userEmail.value == data.email && userEmail.accepted)) checkEmail();
- }
- else {
- checkPhone();
- checkEmail();
- }
- function checkPhone() {
- if (acceptValues.indexOf(data.phone) == -1) {
- sails.log.error('Accepted value for phone isn\'t found in storage', req.user && req.user.id, data.phone);
- errors.push('Телефон не прошел подтверждение.');
- }
- }
- function checkEmail() {
- if (data.email) {
- if (acceptValues.indexOf(data.email) == -1) {
- sails.log.error('Accepted value for email isn\'t found in storage', req.user && req.user.id, data.email);
- errors.push('Email не прошел подтверждение.');
- }
- }
- }
- if (!errors.length) {
- d.resolve();
- }
- else {
- d.reject({
- isValidation: true,
- errors: errors
- });
- }
- return d.promise;
- },
- processUserOnSave: function(data, req) {
- var d = Q.defer(),
- contacts = self.buildContactsForSave(data);
- if (!data.isUpdate) {
- if (req.isAuthenticated()) {
- d.resolve({
- userId: req.user.id,
- contacts: contacts
- });
- }
- else {
- models.User.findOne({ 'phones.0.value': data.phone }, function(err, _user) {
- var newPassword;
- if (!err) {
- if (_user) {
- // Существующий пользователь добавил объявление, но он незалогинен.
- // Transports.sendPhone(data.phone, 'Под вашим аккаунтом создано новое объявление.');
- if (data.email) {
- Transports.sendMail(data.email, 'newAd');
- }
- d.resolve({
- userId: _user.id,
- contacts: contacts
- });
- }
- else {
- newPassword = Helpers.randomString(6, true);
- // Аноним добавил объявление.
- /*
- Transports.sendPhone(data.phone, 'Спасибо, что воспользовались нашим сервисом.'
- + 'Добавленное объявление привязано в вашему номеру телефона.'
- + 'Мы сгенерировали вам временный пароль для входа на uautos: ' + newPassword);
- */
- sails.log.info('New user:', data.name, data.phone, newPassword);
- Transports.sendPhone(data.phone, 'silentRegistration', {
- pass: newPassword
- });
- RegistrationController.regInside({
- name: data.name,
- login: data.phone,
- password: newPassword,
- skype: data.skype || undefined,
- email: data.email && data.isEmailAccepted ? data.email : undefined
- }).then(function(data) {
- d.resolve({
- userId: data.user.id,
- contacts: contacts
- });
- }, function(err) {
- d.reject(err);
- });
- }
- }
- else {
- d.reject(err);
- }
- });
- }
- }
- else {
- d.resolve({
- userId: req.user.id,
- contacts: contacts
- });
- }
- return d.promise;
- },
- buildContactsForSave: function(data) {
- return {
- name: data.name,
- phones: [{
- value: data.phone,
- description: data['phone-description']
- }],
- email: data.email ? {
- value: data.email
- } : {},
- skype: data.skype,
- location: data.location || null
- };
- },
- saveAd: function(data) {
- var Fields,
- d = Q.defer(),
- fieldHadlers = [],
- ad = {},
- isUpdate = data.isUpdate;
- ad.car = {};
- ad.car.carCore = {};
- // Все руками, никакой автоматизации, так как нужно проверить и обработать каждое поле.
- // Все через замыкание.
- /*
- Fields:
- Goal: validate -> transform -> save (CREATE + UPDATE, update changed only (todo))
- return null || undefined - success
- return 'Error' || ['Error 1', 'Error 2'] - validate error
- d.reject || throw new Error - common error
- */
- // В этом контроллере есть дублирующая валидация.
- Fields = {
- // ad
- author: function() {
- // ! update changed only
- if (data.userId) {
- ad.author = data.userId;
- }
- else {
- return 'Не найдены данные о пользователе.';
- }
- },
- contacts: function() {
- // ! update changed only
- var contacts = {};
- // todo: По сути тут идет та же валидация, которая используется при регистрации.
- // todo: Нужно переиспользовать ее. Пока же тут простейшая валидация.
- if (data.contacts) {
- if (!data.contacts.name) {
- return 'Введите имя пользователя';
- }
- else {
- contacts.name = data.contacts.name.substr(0, 128);
- }
- if (!data.contacts.phones || !data.contacts.phones.length) {
- return 'Введите номер телефона';
- }
- else {
- contacts.phones = data.contacts.phones;
- }
- if (!data.contacts.location) {
- return 'Выберите город.';
- }
- contacts.email = data.contacts.email;
- contacts.skype = data.contacts.skype;
- contacts.location = data.contacts.location;
- ad.contacts = contacts;
- }
- else {
- return 'Не найдены данные пользователя.';
- }
- },
- adTokens: function() {
- var tokens = Helpers.getArray(data.tokens || []),
- adTokens = [];
- Object.keys(V.db.ad.tokens).forEach(function(token) {
- if (tokens.indexOf(token) !== -1) {
- adTokens.push(token);
- }
- });
- ad.tokens = adTokens;
- },
- price: function() {
- var price = data.price;
- // Убираем маску из значения цены;
- price.value = price.value.replace(/\s*/g, '');
- if (!price || !price.hasOwnProperty('value') || !price.hasOwnProperty('currency') || !price.hasOwnProperty('isNegotiated')) {
- return 'Вы не ввели цену.';
- }
- else if (!price.isNegotiated && !price.value) {
- return 'Вы не ввели цену.';
- }
- if (price.isNegotiated) {
- ad.price = {
- value: null,
- isContract: true
- };
- }
- else {
- ad.price = {
- value: price.value,
- currency: price.currency,
- isContract: false
- };
- }
- },
- decription: function() {
- ad.description = data.description ? ('' + data.description).substr(0, 5000) : '';
- },
- // ad.car
- vehicleType: function() {
- if (data.vehicleType) {
- ad.car.vehicleType = data.vehicleType;
- }
- else {
- return 'Вы не заполнили поле "Тип ТС".';
- }
- },
- bodyType: function() {
- if (data.bodyType) {
- ad.car.bodyType = data.bodyType;
- }
- else {
- return 'Вы не заполнили поле "Тип кузова".';
- }
- },
- brand: function() {
- if (data.brand) {
- ad.car.brand = {
- id: data.brand,
- name: data.brandName,
- key: Helpers.name2Key(data.brandName)
- }
- }
- else {
- return 'Вы не заполнили поле "Марка".';
- }
- },
- model: function() {
- if (data.model) {
- ad.car.model = {
- id: data.model,
- name: data.modelName,
- key: Helpers.name2Key(data.modelName)
- };
- }
- else if (data.customModel) {
- ad.car.customModel = data.customModel;
- }
- },
- generation: function() {
- if (data.generation) {
- ad.car.generation = {
- id: data.generation,
- name: data.generationName
- };
- }
- },
- modification: function() {
- if (data.modification) {
- ad.car.modification = {
- id: data.modification,
- name: data.modificationName
- };
- }
- },
- year: function() {
- if (data.year) {
- ad.car.year = data.year;
- }
- else {
- return 'Вы не заполнили поле "Год выпуска".';
- }
- },
- mileage: function() {
- if (data.mileage) {
- ad.car.mileage = data.mileage;
- }
- else if (data.isNewVehicle) {
- ad.car.mileage = -1;
- }
- else {
- return 'Вы не заполнили поле "Пробег".';
- }
- },
- color: function() {
- var color = {};
- if (data.color && data.color.select) color.value = data.color.select;
- if (data.color && data.color.checks) color.options = data.color.checks;
- ad.car.color = color;
- },
- state: function() {
- if (data.state) {
- ad.car.state = data.state;
- }
- },
- owners: function() {
- if (data.owners) {
- ad.car.owners = data.owners;
- }
- },
- carTokens: function() {
- var tokens = Helpers.getArray(data.tokens || []),
- carTokens = [];
- Object.keys(V.db.car.tokens).forEach(function(token) {
- if (tokens.indexOf(token) !== -1) {
- carTokens.push(token);
- }
- });
- ad.car.tokens = carTokens;
- },
- photos: function() {
- if (data.photos && data.photos.files && data.photos.files.length > 15) {
- return 'Вы можете загрузить максимум 15 файлов.';
- }
- ad.car.photos = [];
- },
- video: function() {
- if (data.video) {
- if (/*validator.isFQDN(data.video) &&*/ data.video.indexOf('youtube.com/embed/') !== -1) {
- ad.car.video = data.video;
- }
- else {
- return 'Неверный формат видео.'
- }
- }
- },
- equipment: function() {
- ad.car.equipment = Helpers.getArray(data.equipment);
- },
- // ad.car.carCore
- fuel: function() {
- if (data.fuel) {
- ad.car.carCore.fuel = data.fuel;
- }
- },
- engine: function() {
- var engine = {};
- if (data.engineVolume) engine.volume = data.engineVolume;
- if (data.enginePower) engine.power = data.enginePower;
- if (data.isTurbo) engine.options = ['turbo'];
- ad.car.carCore.engine = engine;
- },
- transmission: function() {
- if (data.transmission) {
- ad.car.carCore.transmission = data.transmission;
- }
- },
- drive: function() {
- if (data.drive) {
- ad.car.carCore.drive = data.drive;
- }
- }
- };
- Object.keys(Fields).forEach(function(fieldName) {
- fieldHadlers.push(Fields[fieldName]());
- });
- Q.all(fieldHadlers).then(function(results) {
- var errors = [];
- results.forEach(function(result) {
- if (result) { // is Error
- errors.push(result);
- }
- });
- errors = __.flatten(errors);
- if (!errors.length) {
- if (!isUpdate) {
- self.savePhotos(data).then(function(adPhotos) { // always fulfilled
- ad.car.photos = adPhotos;
- models.Ad.create(ad, function(err, doc) {
- if (!err) {
- if (doc.car.customModel) {
- Transports.sendMail(null, 'customModelOnCreate', { adId: doc.id });
- }
- d.resolve({
- id: doc.id,
- url: Helpers.generateAdUrl(doc)
- });
- }
- else {
- d.reject({
- isValidation: true,
- errors: Helpers.fromMongooseError(err)
- });
- }
- });
- });
- }
- else {
- models.Ad.findById(data.adID, function(err, adDB) {
- if (!err && adDB) {
- self.updatePhotos(data).then(function(photos) { // always fulfilled
- var addedPhotos = Helpers.getArray(photos.added),
- removedPhotos = Helpers.getArray(photos.removed);
- adDB.car.photos = (adDB.car.photos || []).map(function(photo) {
- return photo.toString();
- }).filter(function(photoId) {
- return removedPhotos.indexOf(photoId) == -1;
- });
- addedPhotos.forEach(function(photoId) {
- if (photoId) adDB.car.photos.push(photoId);
- });
- Object.keys(ad).forEach(function(key) {
- if (key !== 'car') {
- adDB[key] = ad[key];
- }
- });
- Object.keys(ad.car).forEach(function(key) {
- if (key !== 'carCore' && key !== 'photos') {
- adDB.car[key] = ad.car[key];
- }
- });
- // fixme
- // возможно, потому, что в объекте car.color используется ключ 'value'
- // срабатывает только, если пытаешься сменить { value: null } на {}
- if (adDB.car.color == null) {
- adDB.car.color = {};
- }
- Object.keys(ad.car.carCore).forEach(function(key) {
- adDB.car.carCore[key] = ad.car.carCore[key];
- });
- adDB.save(function(err, doc) {
- if (!err) {
- if (doc.car.customModel) {
- Transports.sendMail(null, 'customModelOnCreate', { adId: doc.id });
- }
- d.resolve({
- id: doc.id,
- url: Helpers.generateAdUrl(doc)
- });
- }
- else {
- d.reject({
- isValidation: true,
- errors: Helpers.fromMongooseError(err)
- });
- }
- });
- });
- }
- else if (!err) {
- d.reject('Ad not found.');
- }
- else {
- d.reject(err);
- }
- });
- }
- }
- else {
- d.reject({
- isValidation: true,
- errors: errors
- });
- }
- }, function(err) {
- d.reject(err);
- });
- return d.promise;
- },
- updatePhotos: function(data) {
- var d = Q.defer(),
- saveD = self.savePhotos(data), // always fulfilled
- removeD = self.removePhotos(data); // always fulfilled
- Q.spread([saveD, removeD], function(newPhotos, removedPhotos) {
- d.resolve({
- added: newPhotos || [],
- removed: removedPhotos || []
- });
- });
- return d.promise;
- },
- savePhotos: function(data) {
- var attachmentToken,
- d = Q.defer(),
- defers = [];
- if (data.photos) {
- attachmentToken = data.photos.attachmentToken;
- (data.photos.files || []).forEach(function(photoId) {
- var photoD = Q.defer();
- defers.push(photoD.promise);
- Q.resolve().then(function() {
- return File.getFileModel(photoId, attachmentToken);
- }).then(function(model) {
- return File.updateFileStatusToStable(model);
- }).then(function(photoId) {
- photoD.resolve(photoId);
- }).fail(function(err) {
- photoD.reject(err);
- }).done();
- });
- }
- Q.allSettled(defers).then(function(results) {
- var adPhotos = [];
- results.forEach(function(result) {
- if (result.state === 'fulfilled') {
- adPhotos.push(result.value);
- }
- else {
- sails.log.error('Error 62953', result.reason);
- }
- });
- d.resolve(adPhotos);
- });
- return d.promise;
- },
- removePhotos: function(data) {
- var d = Q.defer(),
- defers = [];
- if (data.photos && data.photos.removed && data.photos.removed.length) {
- data.photos.removed.forEach(function(fileId) {
- var removeD = Q.defer();
- defers.push(removeD.promise);
- Q.resolve().then(function() {
- var dbRemoveD = Q.defer();
- models.File.findByIdAndRemove(fileId, function(err, doc) {
- if (!err) dbRemoveD.resolve(doc.name);
- else dbRemoveD.reject(err);
- });
- return dbRemoveD.promise;
- }).then(function(fileName) {
- return File.removeFile(fileName, 'ad');
- }).then(function() {
- removeD.resolve(fileId);
- }).fail(function(err) {
- removeD.reject(err);
- }).done();
- });
- }
- Q.allSettled(defers).then(function(results) {
- results.forEach(function(result) {
- if (result.state !== 'fulfilled') {
- sails.log.error('Error 62954', result.reason);
- }
- });
- d.resolve(data.photos.removed);
- });
- return d.promise;
- }
- };
Add Comment
Please, Sign In to add comment