Guest User

Untitled

a guest
Oct 22nd, 2018
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 36.31 KB | None | 0 0
  1. var self,
  2. RegistrationController = require(PATHS.CONTROLLERS + '/RegistrationController'),
  3. validator = require('validator');
  4.  
  5. module.exports = self = {
  6.  
  7. getFields: function() {
  8. var d = Q.defer();
  9.  
  10. if (!self.fieldsScheme) {
  11. Q.resolve().then(function() {
  12. return prepareData();
  13. }).then(function(data) {
  14. return buildFields(data);
  15. }).then(function(fieldsScheme) {
  16. self.fieldsScheme = fieldsScheme;
  17.  
  18. d.resolve(__.deepExtend({}, fieldsScheme));
  19. }).fail(function(err) {
  20. d.reject(err);
  21. }).done();
  22. }
  23. else {
  24. d.resolve(__.deepExtend({}, self.fieldsScheme));
  25. }
  26.  
  27. function prepareData() {
  28. var i,
  29. d = Q.defer(),
  30. bodyTypesD = Q.defer(),
  31. bodyTypesData = Helpers.fileToLinesSync(PATHS.MOCKS + '/bodyTypes.txt', true),
  32. vtKeys = Object.keys(V.db.vehicleType.types),
  33. vehicleTypesSorting = vtKeys,
  34. bodyTypesSorting = [],
  35. bodyTypeLine = [],
  36. years = [];
  37.  
  38. bodyTypesData.forEach(function(btLine) {
  39. if (!/^\s*$/.test(btLine)) {
  40. bodyTypeLine.push(btLine.split('|')[1]);
  41. }
  42. else {
  43. bodyTypesSorting.push(bodyTypeLine);
  44. bodyTypeLine = [];
  45. }
  46. });
  47. bodyTypesSorting.push(bodyTypeLine);
  48.  
  49. models.BodyType.find(function(err, result) {
  50. var vehicleTypes = [],
  51. bodyTypes = {};
  52.  
  53. if (!err) {
  54. vtKeys.forEach(function(vtKey) {
  55. vehicleTypes.push({
  56. key: vtKey,
  57. display: Helpers.capitalize(V.db.vehicleType.types[vtKey])
  58. });
  59.  
  60. bodyTypes[vtKey] = [];
  61. });
  62.  
  63. vehicleTypes.sort(function(a, b) {
  64. var aInd = vehicleTypesSorting.indexOf(a.key),
  65. bInd = vehicleTypesSorting.indexOf(b.key);
  66.  
  67. return aInd > bInd ? 1 : (aInd === bInd ? 0 : -1);
  68. });
  69.  
  70. result.forEach(function(bt) {
  71. bodyTypes[bt.vehicleType].push({
  72. id: bt._id,
  73. key: bt.key,
  74. display: Helpers.capitalize(bt.display).replace(' / ', ' ')
  75. });
  76. });
  77.  
  78. Object.keys(bodyTypes).forEach(function(vtKey) {
  79. var baseInd = vehicleTypesSorting.indexOf(vtKey);
  80.  
  81. bodyTypes[vtKey].sort(function(a, b) {
  82. var aInd = bodyTypesSorting[baseInd] ? bodyTypesSorting[baseInd].indexOf(a.key) : -1,
  83. bInd = bodyTypesSorting[baseInd] ? bodyTypesSorting[baseInd].indexOf(b.key) : -1;
  84.  
  85. return aInd > bInd ? 1 : (aInd === bInd ? 0 : -1);
  86. });
  87. });
  88.  
  89. bodyTypesD.resolve({
  90. vehicleTypes: vehicleTypes,
  91. bodyTypes: bodyTypes
  92. });
  93. }
  94. else {
  95. bodyTypesD.reject(err);
  96. }
  97. });
  98.  
  99. for (i = (new Date).getFullYear() - 1; i>=1950; i--) {
  100. years.push(i);
  101. }
  102.  
  103. Q.allSettled([bodyTypesD.promise]).then(function(data) {
  104. var btData = data[0];
  105.  
  106. if (btData.state != 'fulfilled') {
  107. throw new Error('Error at prepareData for AdFormController.');
  108. }
  109.  
  110. d.resolve({
  111. vehicleTypes: (btData && btData.value && btData.value.vehicleTypes) || [],
  112. bodyTypes: (btData && btData.value && btData.value.bodyTypes) || {},
  113. currencies: Helpers.getDataFromV('currency', 'ad'),
  114. years: Helpers.toSimpleOptions(years),
  115. colors: Helpers.getDataFromV('colors'),
  116. colorOptions: Helpers.getDataFromV('colorOptions'),
  117. fuels: Helpers.getDataFromV('fuels', 'carCore'),
  118. transmissions: Helpers.getDataFromV('transmissions', 'carCore'),
  119. drives: Helpers.getDataFromV('drives', 'carCore'),
  120. states: Helpers.getDataFromV('states'),
  121. });
  122. }).fail(function(err) {
  123. d.reject(err);
  124. }).done();
  125.  
  126. return d.promise;
  127. }
  128.  
  129. function buildFields(data) {
  130. var d = Q.defer();
  131.  
  132. d.resolve({
  133. vehicleTypes: data.vehicleTypes,
  134. bodyTypes: data.bodyTypes,
  135. currencies: data.currencies,
  136. fields: {
  137. brand: {
  138. type: 'select',
  139. name: 'brand',
  140. label: 'Марка',
  141. disabled: true,
  142. options: [],
  143. defaultOption: {
  144. value: '',
  145. label: 'Выберите марку'
  146. },
  147. required: true,
  148. priority: 0
  149. },
  150. model: {
  151. type: 'select',
  152. name: 'model',
  153. label: 'Модель',
  154. disabled: true,
  155. options: [],
  156. defaultOption: {
  157. value: '',
  158. label: 'Выберите модель'
  159. },
  160. priority: 1
  161. },
  162. generation: {
  163. type: 'select',
  164. name: 'generation',
  165. label: 'Поколение',
  166. disabled: true,
  167. options: [],
  168. defaultOption: {
  169. value: '',
  170. label: 'Выберите поколение'
  171. },
  172. priority: 2
  173. },
  174. modification: {
  175. type: 'select',
  176. name: 'modification',
  177. label: 'Модификация',
  178. disabled: true,
  179. options: [],
  180. defaultOption: {
  181. value: '',
  182. label: 'Выберите модификацию'
  183. },
  184. priority: 3
  185. },
  186. year: {
  187. type: 'select',
  188. name: 'year',
  189. label: 'Год выпуска',
  190. options: data.years,
  191. defaultOption: {
  192. value: (new Date).getFullYear(),
  193. label: (new Date).getFullYear()
  194. },
  195. required: true,
  196. size: 's',
  197. priority: 4
  198. },
  199. mileage: {
  200. type: 'number',
  201. name: 'mileage',
  202. label: 'Пробег',
  203. mask: '{"mask": "9[9][9][.9]", "greedy": false}',
  204. appendix: 'тыс. км',
  205. required: true,
  206. priority: 5
  207. },
  208. color: {
  209. type: 'complex-list',
  210. name: 'color',
  211. label: 'Цвет',
  212. selects: data.colors,
  213. checks: data.colorOptions,
  214. defaultSelectOption: {
  215. value: '',
  216. label: 'Выберите цвет'
  217. },
  218. priority: 6
  219. },
  220. fuel: {
  221. type: 'select',
  222. name: 'fuel',
  223. label: 'Топливо',
  224. options: data.fuels,
  225. defaultOption: {
  226. value: '',
  227. label: 'Выберите тип топлива'
  228. },
  229. priority: 7
  230. },
  231. engineVolume: {
  232. type: 'number',
  233. name: 'engineVolume',
  234. label: 'Объем двигателя',
  235. mask: '{"mask": "9[9][.9]", "greedy": false}',
  236. appendix: 'л.',
  237. priority: 8
  238. },
  239. enginePower: {
  240. type: 'number',
  241. name: 'enginePower',
  242. label: 'Мощность двигателя',
  243. mask: '{"mask": "99[9]", "greedy": false}',
  244. appendix: 'л.с.',
  245. priority: 9
  246. },
  247. transmission: {
  248. type: 'select',
  249. name: 'transmission',
  250. label: 'Коробка передач',
  251. options: data.transmissions,
  252. defaultOption: {
  253. value: '',
  254. label: 'Выберите тип КПП'
  255. },
  256. priority: 10
  257. },
  258. drive: {
  259. type: 'push-buttons',
  260. name: 'drive',
  261. label: 'Привод',
  262. buttons: data.drives,
  263. priority: 11
  264. },
  265. state: {
  266. type: 'push-buttons',
  267. name: 'state',
  268. label: 'Состояние',
  269. buttons: data.states,
  270. priority: 12
  271. },
  272. owners: {
  273. type: 'number',
  274. name: 'owners',
  275. label: 'Количество владельцев',
  276. mask: '{"mask": "9[9]", "greedy": false}',
  277. appendix: 'чел.',
  278. priority: 13
  279. }
  280. }
  281. });
  282.  
  283. return d.promise;
  284. }
  285.  
  286. return d.promise;
  287. },
  288.  
  289. getBasePageData: function() {
  290. var d = Q.defer();
  291.  
  292. self.getFields().then(function(scheme) {
  293. d.resolve({
  294. vehicleTypes: scheme.vehicleTypes,
  295. bodyTypes: scheme.bodyTypes,
  296. currencies: scheme.currencies,
  297. tokens: _.union(Helpers.getDataFromV('tokens'), Helpers.getDataFromV('tokens', 'ad')),
  298. equipment: Equipment.getData4AddPage(),
  299. fields: scheme.fields,
  300. pData: {
  301. fieldsByVT: __.deepExtend({}, FieldsByVT.fields)
  302. }
  303. });
  304. }).fail(function(err) {
  305. d.reject(err);
  306. }).done();
  307.  
  308. return d.promise;
  309. },
  310.  
  311. createPage: function(req, res) {
  312. self.getBasePageData().then(function(data) {
  313. data.pageName = 'ad-create';
  314.  
  315. res.view('ad-form/base', data);
  316. }).fail(function(err) {
  317. res.serverError(err);
  318. }).done();
  319.  
  320. Stat.updateUserStats(req);
  321. },
  322.  
  323. updatePage: function(req, res) {
  324. var adID = req.params.id;
  325.  
  326. self.getBasePageData().then(function(data) {
  327.  
  328. data.adID = adID;
  329. data.pData.adID = adID;
  330. data.isUpdate = true;
  331. data.pData.isUpdate = true;
  332. data.pageName = 'ad-update';
  333.  
  334. models.Ad.findById(adID).populate('car.photos').exec(function(err, ad) {
  335. if (!err && ad) {
  336. data.pData.ad = ad.toJSON({ virtuals: true });
  337.  
  338. if (data.pData.ad.car.photos) {
  339. data.pData.ad.car.photos.forEach(function(photo) {
  340. photo.url = File.getFilePath(photo.name, 'ad', 'small');
  341. });
  342. }
  343.  
  344. res.view('ad-form/base', data);
  345. }
  346. else if (!err) {
  347. res.notFound();
  348. }
  349. else {
  350. sails.log.error('Error 345345345', err);
  351. res.notFound();
  352. }
  353. });
  354. }).fail(function(err) {
  355. res.serverError(err);
  356. }).done();
  357.  
  358. Stat.updateUserStats(req);
  359. },
  360.  
  361. save: function(req, res) {
  362. var data = JSON.parse(req.body.data || '{}');
  363.  
  364. Q.resolve().then(function() {
  365. return self.validateAccepted(data, req);
  366. }).then(function() {
  367. return self.processUserOnSave(data, req);
  368. }).then(function(_data) {
  369. Object.keys(_data).forEach(function(k) {
  370. data[k] = _data[k];
  371. });
  372.  
  373. return self.saveAd(data);
  374. }).then(function(result) {
  375. res.ok(result);
  376. }).fail(function(err) {
  377. if (err.isValidation) {
  378. res.badRequest(err.errors);
  379. }
  380. else {
  381. res.serverError(err);
  382. }
  383. }).done();
  384. },
  385.  
  386. validateAccepted: function(data, req) {
  387. var userPhone, userEmail,
  388. d = Q.defer(),
  389. acceptValues = req.session.acceptValues || [],
  390. errors = [];
  391.  
  392. if (req.isAuthenticated()) {
  393. userPhone = req.user.phones[0] || {};
  394. userEmail = req.user.email || {};
  395.  
  396. if (!(userPhone.value == data.phone && userPhone.accepted)) checkPhone();
  397. if (!(userEmail.value == data.email && userEmail.accepted)) checkEmail();
  398. }
  399. else {
  400. checkPhone();
  401. checkEmail();
  402. }
  403.  
  404. function checkPhone() {
  405. if (acceptValues.indexOf(data.phone) == -1) {
  406. sails.log.error('Accepted value for phone isn\'t found in storage', req.user && req.user.id, data.phone);
  407. errors.push('Телефон не прошел подтверждение.');
  408. }
  409. }
  410.  
  411. function checkEmail() {
  412. if (data.email) {
  413. if (acceptValues.indexOf(data.email) == -1) {
  414. sails.log.error('Accepted value for email isn\'t found in storage', req.user && req.user.id, data.email);
  415. errors.push('Email не прошел подтверждение.');
  416. }
  417. }
  418. }
  419.  
  420. if (!errors.length) {
  421. d.resolve();
  422. }
  423. else {
  424. d.reject({
  425. isValidation: true,
  426. errors: errors
  427. });
  428. }
  429.  
  430. return d.promise;
  431. },
  432.  
  433. processUserOnSave: function(data, req) {
  434. var d = Q.defer(),
  435. contacts = self.buildContactsForSave(data);
  436.  
  437. if (!data.isUpdate) {
  438. if (req.isAuthenticated()) {
  439. d.resolve({
  440. userId: req.user.id,
  441. contacts: contacts
  442. });
  443. }
  444. else {
  445. models.User.findOne({ 'phones.0.value': data.phone }, function(err, _user) {
  446. var newPassword;
  447.  
  448. if (!err) {
  449. if (_user) {
  450. // Существующий пользователь добавил объявление, но он незалогинен.
  451. // Transports.sendPhone(data.phone, 'Под вашим аккаунтом создано новое объявление.');
  452.  
  453. if (data.email) {
  454. Transports.sendMail(data.email, 'newAd');
  455. }
  456.  
  457. d.resolve({
  458. userId: _user.id,
  459. contacts: contacts
  460. });
  461. }
  462. else {
  463. newPassword = Helpers.randomString(6, true);
  464.  
  465. // Аноним добавил объявление.
  466. /*
  467. Transports.sendPhone(data.phone, 'Спасибо, что воспользовались нашим сервисом.'
  468. + 'Добавленное объявление привязано в вашему номеру телефона.'
  469. + 'Мы сгенерировали вам временный пароль для входа на uautos: ' + newPassword);
  470. */
  471.  
  472. sails.log.info('New user:', data.name, data.phone, newPassword);
  473.  
  474. Transports.sendPhone(data.phone, 'silentRegistration', {
  475. pass: newPassword
  476. });
  477.  
  478. RegistrationController.regInside({
  479. name: data.name,
  480. login: data.phone,
  481. password: newPassword,
  482. skype: data.skype || undefined,
  483. email: data.email && data.isEmailAccepted ? data.email : undefined
  484. }).then(function(data) {
  485. d.resolve({
  486. userId: data.user.id,
  487. contacts: contacts
  488. });
  489. }, function(err) {
  490. d.reject(err);
  491. });
  492. }
  493. }
  494. else {
  495. d.reject(err);
  496. }
  497. });
  498. }
  499. }
  500. else {
  501. d.resolve({
  502. userId: req.user.id,
  503. contacts: contacts
  504. });
  505. }
  506.  
  507. return d.promise;
  508. },
  509.  
  510. buildContactsForSave: function(data) {
  511.  
  512. return {
  513. name: data.name,
  514. phones: [{
  515. value: data.phone,
  516. description: data['phone-description']
  517. }],
  518. email: data.email ? {
  519. value: data.email
  520. } : {},
  521. skype: data.skype,
  522. location: data.location || null
  523. };
  524.  
  525. },
  526.  
  527. saveAd: function(data) {
  528. var Fields,
  529. d = Q.defer(),
  530. fieldHadlers = [],
  531. ad = {},
  532. isUpdate = data.isUpdate;
  533.  
  534. ad.car = {};
  535. ad.car.carCore = {};
  536.  
  537. // Все руками, никакой автоматизации, так как нужно проверить и обработать каждое поле.
  538. // Все через замыкание.
  539.  
  540. /*
  541. Fields:
  542. Goal: validate -> transform -> save (CREATE + UPDATE, update changed only (todo))
  543.  
  544. return null || undefined - success
  545. return 'Error' || ['Error 1', 'Error 2'] - validate error
  546. d.reject || throw new Error - common error
  547. */
  548.  
  549. // В этом контроллере есть дублирующая валидация.
  550.  
  551. Fields = {
  552.  
  553. // ad
  554.  
  555. author: function() {
  556. // ! update changed only
  557.  
  558. if (data.userId) {
  559. ad.author = data.userId;
  560. }
  561. else {
  562. return 'Не найдены данные о пользователе.';
  563. }
  564. },
  565. contacts: function() {
  566. // ! update changed only
  567.  
  568. var contacts = {};
  569.  
  570. // todo: По сути тут идет та же валидация, которая используется при регистрации.
  571. // todo: Нужно переиспользовать ее. Пока же тут простейшая валидация.
  572.  
  573. if (data.contacts) {
  574. if (!data.contacts.name) {
  575. return 'Введите имя пользователя';
  576. }
  577. else {
  578. contacts.name = data.contacts.name.substr(0, 128);
  579. }
  580.  
  581. if (!data.contacts.phones || !data.contacts.phones.length) {
  582. return 'Введите номер телефона';
  583. }
  584. else {
  585. contacts.phones = data.contacts.phones;
  586. }
  587.  
  588. if (!data.contacts.location) {
  589. return 'Выберите город.';
  590. }
  591.  
  592. contacts.email = data.contacts.email;
  593. contacts.skype = data.contacts.skype;
  594. contacts.location = data.contacts.location;
  595.  
  596. ad.contacts = contacts;
  597. }
  598. else {
  599. return 'Не найдены данные пользователя.';
  600. }
  601. },
  602. adTokens: function() {
  603. var tokens = Helpers.getArray(data.tokens || []),
  604. adTokens = [];
  605.  
  606. Object.keys(V.db.ad.tokens).forEach(function(token) {
  607. if (tokens.indexOf(token) !== -1) {
  608. adTokens.push(token);
  609. }
  610. });
  611.  
  612. ad.tokens = adTokens;
  613. },
  614. price: function() {
  615. var price = data.price;
  616.  
  617. // Убираем маску из значения цены;
  618. price.value = price.value.replace(/\s*/g, '');
  619.  
  620. if (!price || !price.hasOwnProperty('value') || !price.hasOwnProperty('currency') || !price.hasOwnProperty('isNegotiated')) {
  621. return 'Вы не ввели цену.';
  622. }
  623. else if (!price.isNegotiated && !price.value) {
  624. return 'Вы не ввели цену.';
  625. }
  626.  
  627. if (price.isNegotiated) {
  628. ad.price = {
  629. value: null,
  630. isContract: true
  631. };
  632. }
  633. else {
  634. ad.price = {
  635. value: price.value,
  636. currency: price.currency,
  637. isContract: false
  638. };
  639. }
  640. },
  641. decription: function() {
  642. ad.description = data.description ? ('' + data.description).substr(0, 5000) : '';
  643. },
  644.  
  645. // ad.car
  646.  
  647. vehicleType: function() {
  648. if (data.vehicleType) {
  649. ad.car.vehicleType = data.vehicleType;
  650. }
  651. else {
  652. return 'Вы не заполнили поле "Тип ТС".';
  653. }
  654. },
  655. bodyType: function() {
  656. if (data.bodyType) {
  657. ad.car.bodyType = data.bodyType;
  658. }
  659. else {
  660. return 'Вы не заполнили поле "Тип кузова".';
  661. }
  662. },
  663. brand: function() {
  664. if (data.brand) {
  665. ad.car.brand = {
  666. id: data.brand,
  667. name: data.brandName,
  668. key: Helpers.name2Key(data.brandName)
  669. }
  670. }
  671. else {
  672. return 'Вы не заполнили поле "Марка".';
  673. }
  674. },
  675. model: function() {
  676. if (data.model) {
  677. ad.car.model = {
  678. id: data.model,
  679. name: data.modelName,
  680. key: Helpers.name2Key(data.modelName)
  681. };
  682. }
  683. else if (data.customModel) {
  684. ad.car.customModel = data.customModel;
  685. }
  686. },
  687. generation: function() {
  688. if (data.generation) {
  689. ad.car.generation = {
  690. id: data.generation,
  691. name: data.generationName
  692. };
  693. }
  694. },
  695. modification: function() {
  696. if (data.modification) {
  697. ad.car.modification = {
  698. id: data.modification,
  699. name: data.modificationName
  700. };
  701. }
  702. },
  703. year: function() {
  704. if (data.year) {
  705. ad.car.year = data.year;
  706. }
  707. else {
  708. return 'Вы не заполнили поле "Год выпуска".';
  709. }
  710. },
  711. mileage: function() {
  712. if (data.mileage) {
  713. ad.car.mileage = data.mileage;
  714. }
  715. else if (data.isNewVehicle) {
  716. ad.car.mileage = -1;
  717. }
  718. else {
  719. return 'Вы не заполнили поле "Пробег".';
  720. }
  721. },
  722. color: function() {
  723. var color = {};
  724.  
  725. if (data.color && data.color.select) color.value = data.color.select;
  726. if (data.color && data.color.checks) color.options = data.color.checks;
  727.  
  728. ad.car.color = color;
  729. },
  730. state: function() {
  731. if (data.state) {
  732. ad.car.state = data.state;
  733. }
  734. },
  735. owners: function() {
  736. if (data.owners) {
  737. ad.car.owners = data.owners;
  738. }
  739. },
  740. carTokens: function() {
  741. var tokens = Helpers.getArray(data.tokens || []),
  742. carTokens = [];
  743.  
  744. Object.keys(V.db.car.tokens).forEach(function(token) {
  745. if (tokens.indexOf(token) !== -1) {
  746. carTokens.push(token);
  747. }
  748. });
  749.  
  750. ad.car.tokens = carTokens;
  751. },
  752. photos: function() {
  753. if (data.photos && data.photos.files && data.photos.files.length > 15) {
  754. return 'Вы можете загрузить максимум 15 файлов.';
  755. }
  756.  
  757. ad.car.photos = [];
  758. },
  759. video: function() {
  760. if (data.video) {
  761. if (/*validator.isFQDN(data.video) &&*/ data.video.indexOf('youtube.com/embed/') !== -1) {
  762. ad.car.video = data.video;
  763. }
  764. else {
  765. return 'Неверный формат видео.'
  766. }
  767. }
  768. },
  769. equipment: function() {
  770. ad.car.equipment = Helpers.getArray(data.equipment);
  771. },
  772.  
  773. // ad.car.carCore
  774.  
  775. fuel: function() {
  776. if (data.fuel) {
  777. ad.car.carCore.fuel = data.fuel;
  778. }
  779. },
  780. engine: function() {
  781. var engine = {};
  782.  
  783. if (data.engineVolume) engine.volume = data.engineVolume;
  784. if (data.enginePower) engine.power = data.enginePower;
  785. if (data.isTurbo) engine.options = ['turbo'];
  786.  
  787. ad.car.carCore.engine = engine;
  788. },
  789. transmission: function() {
  790. if (data.transmission) {
  791. ad.car.carCore.transmission = data.transmission;
  792. }
  793. },
  794. drive: function() {
  795. if (data.drive) {
  796. ad.car.carCore.drive = data.drive;
  797. }
  798. }
  799. };
  800.  
  801. Object.keys(Fields).forEach(function(fieldName) {
  802. fieldHadlers.push(Fields[fieldName]());
  803. });
  804.  
  805. Q.all(fieldHadlers).then(function(results) {
  806. var errors = [];
  807.  
  808. results.forEach(function(result) {
  809. if (result) { // is Error
  810. errors.push(result);
  811. }
  812. });
  813.  
  814. errors = __.flatten(errors);
  815.  
  816. if (!errors.length) {
  817. if (!isUpdate) {
  818. self.savePhotos(data).then(function(adPhotos) { // always fulfilled
  819. ad.car.photos = adPhotos;
  820.  
  821. models.Ad.create(ad, function(err, doc) {
  822. if (!err) {
  823. if (doc.car.customModel) {
  824. Transports.sendMail(null, 'customModelOnCreate', { adId: doc.id });
  825. }
  826.  
  827. d.resolve({
  828. id: doc.id,
  829. url: Helpers.generateAdUrl(doc)
  830. });
  831. }
  832. else {
  833. d.reject({
  834. isValidation: true,
  835. errors: Helpers.fromMongooseError(err)
  836. });
  837. }
  838. });
  839. });
  840. }
  841. else {
  842. models.Ad.findById(data.adID, function(err, adDB) {
  843. if (!err && adDB) {
  844. self.updatePhotos(data).then(function(photos) { // always fulfilled
  845. var addedPhotos = Helpers.getArray(photos.added),
  846. removedPhotos = Helpers.getArray(photos.removed);
  847.  
  848. adDB.car.photos = (adDB.car.photos || []).map(function(photo) {
  849. return photo.toString();
  850. }).filter(function(photoId) {
  851. return removedPhotos.indexOf(photoId) == -1;
  852. });
  853.  
  854. addedPhotos.forEach(function(photoId) {
  855. if (photoId) adDB.car.photos.push(photoId);
  856. });
  857.  
  858. Object.keys(ad).forEach(function(key) {
  859. if (key !== 'car') {
  860. adDB[key] = ad[key];
  861. }
  862. });
  863.  
  864. Object.keys(ad.car).forEach(function(key) {
  865. if (key !== 'carCore' && key !== 'photos') {
  866. adDB.car[key] = ad.car[key];
  867. }
  868. });
  869.  
  870. // fixme
  871. // возможно, потому, что в объекте car.color используется ключ 'value'
  872. // срабатывает только, если пытаешься сменить { value: null } на {}
  873. if (adDB.car.color == null) {
  874. adDB.car.color = {};
  875. }
  876.  
  877. Object.keys(ad.car.carCore).forEach(function(key) {
  878. adDB.car.carCore[key] = ad.car.carCore[key];
  879. });
  880.  
  881. adDB.save(function(err, doc) {
  882. if (!err) {
  883. if (doc.car.customModel) {
  884. Transports.sendMail(null, 'customModelOnCreate', { adId: doc.id });
  885. }
  886.  
  887. d.resolve({
  888. id: doc.id,
  889. url: Helpers.generateAdUrl(doc)
  890. });
  891. }
  892. else {
  893. d.reject({
  894. isValidation: true,
  895. errors: Helpers.fromMongooseError(err)
  896. });
  897. }
  898. });
  899. });
  900. }
  901. else if (!err) {
  902. d.reject('Ad not found.');
  903. }
  904. else {
  905. d.reject(err);
  906. }
  907. });
  908. }
  909. }
  910. else {
  911. d.reject({
  912. isValidation: true,
  913. errors: errors
  914. });
  915. }
  916. }, function(err) {
  917. d.reject(err);
  918. });
  919.  
  920. return d.promise;
  921. },
  922.  
  923. updatePhotos: function(data) {
  924. var d = Q.defer(),
  925. saveD = self.savePhotos(data), // always fulfilled
  926. removeD = self.removePhotos(data); // always fulfilled
  927.  
  928. Q.spread([saveD, removeD], function(newPhotos, removedPhotos) {
  929. d.resolve({
  930. added: newPhotos || [],
  931. removed: removedPhotos || []
  932. });
  933. });
  934.  
  935. return d.promise;
  936. },
  937.  
  938. savePhotos: function(data) {
  939. var attachmentToken,
  940. d = Q.defer(),
  941. defers = [];
  942.  
  943. if (data.photos) {
  944. attachmentToken = data.photos.attachmentToken;
  945.  
  946. (data.photos.files || []).forEach(function(photoId) {
  947. var photoD = Q.defer();
  948.  
  949. defers.push(photoD.promise);
  950.  
  951. Q.resolve().then(function() {
  952. return File.getFileModel(photoId, attachmentToken);
  953. }).then(function(model) {
  954. return File.updateFileStatusToStable(model);
  955. }).then(function(photoId) {
  956. photoD.resolve(photoId);
  957. }).fail(function(err) {
  958. photoD.reject(err);
  959. }).done();
  960. });
  961. }
  962.  
  963. Q.allSettled(defers).then(function(results) {
  964. var adPhotos = [];
  965.  
  966. results.forEach(function(result) {
  967. if (result.state === 'fulfilled') {
  968. adPhotos.push(result.value);
  969. }
  970. else {
  971. sails.log.error('Error 62953', result.reason);
  972. }
  973. });
  974.  
  975. d.resolve(adPhotos);
  976. });
  977.  
  978. return d.promise;
  979. },
  980.  
  981. removePhotos: function(data) {
  982. var d = Q.defer(),
  983. defers = [];
  984.  
  985. if (data.photos && data.photos.removed && data.photos.removed.length) {
  986. data.photos.removed.forEach(function(fileId) {
  987. var removeD = Q.defer();
  988.  
  989. defers.push(removeD.promise);
  990.  
  991. Q.resolve().then(function() {
  992. var dbRemoveD = Q.defer();
  993.  
  994. models.File.findByIdAndRemove(fileId, function(err, doc) {
  995. if (!err) dbRemoveD.resolve(doc.name);
  996. else dbRemoveD.reject(err);
  997. });
  998.  
  999. return dbRemoveD.promise;
  1000. }).then(function(fileName) {
  1001. return File.removeFile(fileName, 'ad');
  1002. }).then(function() {
  1003. removeD.resolve(fileId);
  1004. }).fail(function(err) {
  1005. removeD.reject(err);
  1006. }).done();
  1007. });
  1008. }
  1009.  
  1010. Q.allSettled(defers).then(function(results) {
  1011. results.forEach(function(result) {
  1012. if (result.state !== 'fulfilled') {
  1013. sails.log.error('Error 62954', result.reason);
  1014. }
  1015. });
  1016.  
  1017. d.resolve(data.photos.removed);
  1018. });
  1019.  
  1020. return d.promise;
  1021. }
  1022.  
  1023. };
Add Comment
Please, Sign In to add comment