wmakeev
10/2/2015 - 9:54 AM

Скрипты МойСклад #moysklad #script

Скрипты МойСклад #moysklad #script

// Удаление в корзину всех перемещений внутри одного склада

(function () {
  "use strict"

  const step = 10

  function markDelete (entity) {
    entity.deleted = new Date()
    entity.applicable = false
    return entity
  }

  let moves
  let total = 0

  do {

    moves = client.from('move').sort('moment').select({
      applicable: true,
      sourceStoreUuid: 'eed5fae7-c949-4258-8e27-69f306d7166c',
      targetStoreUuid: 'eed5fae7-c949-4258-8e27-69f306d7166c'
    }).count(10).load()

    total = moves.total
    let trashedMoves = moves.map(markDelete)

    console.log(trashedMoves.map(m => m.name), total)

    client.save(trashedMoves)
  
  } while (total > 10)

})()
// Отправить товар в распродажу

(function () {
    "use strict"
    let tools = moysklad.tools

    let salesFolderUuid = 'acca8044-d95f-11e5-7a69-97110041a0a8'
    let posSrcDocumentType = 'purchaseOrder'
    let posSrcDocumentUuid = '487beded-d954-11e5-7a69-8f55003fb247'
    let newBuyPrice = 1200 * 100
    let oldPrice = 1580 * 100

    let doc = client.load(posSrcDocumentType, posSrcDocumentUuid)
    let goodUuids = tools.getPositions(doc).map(p => p.goodUuid)

    let goods = client.from('good').uuids(goodUuids).load()
    
    goods.forEach(good => {
        if (good.name.slice(-6) !== '- sale') { 
            good.name += ' - sale' 
        }
        
        good.minPrice = good.buyPrice = newBuyPrice 
        
        tools.getPrice(good, '9b29b27d-d100-11e3-090f-002590a28eca').value // Цена старая
            = oldPrice
        
        tools.getPrice(good, 'e0b4a992-f9c5-44aa-8cee-afa0257a95e6').value // Цена продажи
            = good.salePrice = Math.round(newBuyPrice * 1.1)

        good.parentUuid = salesFolderUuid  
    })

    client.save(goods)
})()
// Поставить выбранные товары в распродажу

(function() {
  'use strict'

  const { OK, CANCEL } = MODAL_DIALOG_BUTTONS
  const tools = moysklad.tools
  const client = moysklad.createClient()

  client.options.flowControl = 'async'

  function clientLoadAsync (query) {
    return new Promise((resolve, reject) => {
      query.load((err, data) => err ? reject(err) : resolve(data))
    })
  }

  function clientSaveAsync (entities) {
    return new Promise((resolve, reject) => {
      client.save(entities, (err, data) => err ? reject(err) : resolve(data))
    })
  }
  
  co(function * () {
    let dialogResult = yield showModalForm('Отправить в распродажу', {
      supplierDiscount: {
        caption: 'Скидка поставщика (руб)',
        type: 'number'
      },
      margin: {
        caption: 'Наценка (%)',
        type: 'number',
        value: 10
      }
    }, {
      buttons: [OK, CANCEL]
    })

    if (!dialogResult) { return false }

    let supplierDiscount = Number.parseInt(dialogResult.supplierDiscount)
    if (isNaN(supplierDiscount) || supplierDiscount <= 0) {
      throw new Error('Некорректно указана скидка поставщика')
    }

    let margin = Number.parseInt(dialogResult.margin)
    if (isNaN(margin) || margin <= 0) {
      throw new Error('Некорректно указана наценка')
    }

    let codes = Utils.getSelectedGoodsCodes()
    if (codes.length === 0) {
      throw new Error('Необходимо выбрать товары')
    }
    
    let query = client.from('good').filter('code', codes).count(300)
    let goods = yield clientLoadAsync(query)
  
    let goodsToUpdate = goods.map(good => {
      if (good.name.slice(-6) !== '- sale') {
        good.name += ' - sale'
      } else {
        return null
      }
      
      // Закупочная цена
      let newBuyPrice = good.buyPrice - (supplierDiscount * 100)
      good.minPrice = good.buyPrice = newBuyPrice

      // Цена продажи
      let goodPrice = tools.getPrice(good, 'e0b4a992-f9c5-44aa-8cee-afa0257a95e6')

      // Цена старая  
      tools.getPrice(good, '9b29b27d-d100-11e3-090f-002590a28eca').value =
        goodPrice.value
      
      goodPrice.value = good.salePrice = Math.round(newBuyPrice * (1 + margin / 100))
      
      return good
    }).filter(good => good)

    if (goodsToUpdate.length) {
      clientSaveAsync(goodsToUpdate)
    }
    
    return yield showModalDialog('Отправить в распродажу',
      `Обновлено ${goodsToUpdate.length} из ${goods.length} товаров`)
  })
    .then((res) => { if (res) { router.refresh() } })
    .catch(err => console.error(err))
})()
// Выборка всех замшевых товаров в наличии на сайте

(function() {
  'use strict'

  const client = moysklad.createClient()

  client.options.flowControl = 'async'
  
  const SUPPLIER_UUID = '46bf53af-e826-11e4-7a07-673d0008987c'
  const SALES_FOLDER_UUID = '297ea0ca-f197-11e5-7a69-9715001ebade'
  
  // Адаптер для Deffered
  function promiseAdapter(eshopPromise) {
    return new Promise((resolve,reject) =>
      eshopPromise.then(resolve).fail(reject))
  }

  function clientLoadAsync (query) {
    return new Promise((resolve, reject) => {
      query.load((err, data) => err ? reject(err) : resolve(data))
    })
  }

  function clientSaveAsync (entities) {
    return new Promise((resolve, reject) => {
      client.save(entities, (err, data) => err ? reject(err) : resolve(data))
    })
  }
  
  let eshop = new Entityes.EShopEntities({
    name: 'oData',
    oDataServiceHost: ESHOP_ODATA_ENDPOINT,
    enableJSONP: false
  })
  
  eshop.onReady(() => {
    co(function * () {
      let codes = yield promiseAdapter(
        eshop.ProductAttributeValues
          .filter(function(item) {
            return item.AttributeValueID === attributeValue && item.Product.Available
          }, { attributeValue: 14 }) // Замша
          .select(`it.ProductID`)
          .skip(0).take(1000)
          .toArray())

      let query = client.from('good')
        .select({
          code: codes,
          supplierUuid: SUPPLIER_UUID
        })
      
      let goods = yield clientLoadAsync(query)
         
      goods.forEach(good => { good.parentUuid = SALES_FOLDER_UUID })

      return yield clientSaveAsync(goods)
    })
      .catch(err => console.log(err))
      .then((res) => console.log(res))
  })
})()
// Отчет по продажам за прошлый день

(function () {
  "use strict"

  let client = require('moysklad-client').createClient()

  // Текущее время
  let now = new Date()
  
  // Конец прошлого дня
  let dayEnd = new Date(now.getFullYear(), now.getMonth(), now.getDate())

  // Начало прошлого дня
  let dayStart = new Date(dayEnd - 24*60*60*1000)

  // Получем все проведенные отгрузки созданные сегодня
  let demands = client.from('demand')
    .select({ 
      created: { $gt: dayStart, $lt: dayEnd }, 
      applicable: true 
    })
    //.count(2)
    .load()
    // Убираем удаленные документы
    .filter(demand => !demand.deleted)

  // Ленивая загрузка связанных товаров для получения имени товара
  client.createLazyLoader().attach(demands, ['shipmentOut.good'])

  let salesByGood = demands
    
    // Выделяем из всех отгрузок товарные позиции
    .reduce((res, demand) => 
      res.concat(demand.getPositions().map(pos => {
        return {
          name: pos.good.name,
          quantity: pos.quantity,
          price: pos.price.sum / 100,
          buyPrice: pos.good.buyPrice / 100
        }
      })), [])
    
    // Суммируем кол-во проданных товаров
    .reduce((res, pos) => {
      let report = res[pos.name]
      if (report) {
        report.quantity += pos.quantity
      } else {
        res[pos.name] = pos
      }
      return res
    }, {})

  // Прибыльность (относительно цены закупа)
  let totalProfit = 0
  
  // Строим отчет по продажам
  let report = Object.keys(salesByGood)
  	.map(key => {
  		let goodReport = salesByGood[key]
		let itemProfit = 
			(goodReport.price - goodReport.buyPrice) * goodReport.quantity
		totalProfit += itemProfit
		return [
			goodReport.name, 
			goodReport.price,
			goodReport.buyPrice,
			goodReport.quantity,
			Math.round(itemProfit)
		].join(';')
  	}).join('\n') 		

  console.log(report)
  console.log('Прибыль за период - ', Math.round(totalProfit))

})()
// Замена цены закупа минимальной ценой (по базе товаров, если эти цены отличаются)

(function () {
  'use strict'
  
  let tools = moysklad.tools
  let page = 100
  let start = 0
  let total = 5000

  while (!start || start <= (total + page)) {
    console.log('start:', start)
    let goods = client.from('good')
      .select({
        supplierUuid: '49f3ea4c-9a55-4df7-9996-37b098d0b014'
      })
      .start(start)
      .count(page)
      .load()
    
    total = goods.total
    start += page
    
    let goodsToSave = []

    goods.forEach(good => {
      if (good.buyPrice !== good.minPrice) {
        console.log(`Code: ${good.code} buyPrice: ${good.buyPrice} minPrice: ${good.minPrice}`)

        // Цена минимальная
        good.buyPrice = 
          tools.getPrice(good, 'cbf605f6-16e5-11e4-add0-002590a28eca').value = 
            good.minPrice
        
        goodsToSave.push(good)
      }
    })

    if (goodsToSave.length) {
      // console.log(goodsToSave)
      client.save(goods)
    }

    //break
  }
})()
// Проверка соответсвия заказа отгрузке
// Все позиции должны совпадать по кол-ву и ценам

// TODO: Кол-во может быть разбито по разным позициям и разным отгрузкам
(function () {
    "use strict"

    let result = ''

    function log (msg) {
        result = result + '\n' + msg
    }

    let lazyBatch = ['Position.good', 'Position.consignment']

    let compare = position1 => {
        let selectors = ['goodUuid', 'consignmentUuid', 'price.sum']
            .map(prop => _.property(prop))
        return position2 => selectors.every(sel => sel(position1) === sel(position2))
    }

    let order = client.load('customerOrder', router.getState().query.id)

    let lazy = client.createLazyLoader()

    lazy.attach(order, lazyBatch)

    let demands = client.from('demand')
        .filter('applicable', true)
        .uuids(order.demandsUuid)
        .chain()
        .filter(demand => !demand.deleted)
        .value()

    lazy.attach(demands, lazyBatch)
    
    let orderPositions = order.getPositions()
    let orderPositionsSet = new Set(orderPositions)

    let demandsPositions = demands.map(demand => {
        let positions = demand.getPositions()
        return {
            name: demand.name,
            positions: positions,
            positionsSet: new Set(positions)
        }
    })

    demandsPositions.forEach(pos => {
        pos.positions.forEach(position => {
            let orderPosition = orderPositions.find(compare(position))
            if (orderPosition) {
                orderPositionsSet.delete(orderPosition)
                pos.positionsSet.delete(position)
            }
        })
    })

    let printPos = pos => log(`${pos.consignment.name} ${pos.price.sum / 100} - ${pos.quantity}`)

    log('Несовпадения позиций заказа:')
    orderPositionsSet.forEach(printPos)

    demandsPositions.forEach(data => {
        log(`\nНесовпадения позиций в отгрузке ${data.name}:`)
        data.positionsSet.forEach(printPos)
    })

    console.log(result)

})()
// Разложить папки

(function () {
  "use strict"

  let folderNameRegEx = /([\w\-]+)\s(\d{2}-\d{2}-\d{2})(?:\s(\S+))?/

  let toUpdate = []

  let newFolders = client.from('goodFolder')
    .filter('parentUuid', '28e1eb74-5884-11e4-90a2-8ecb005341f8') // Новинки
    .chain()
    .forEach(folder => {
      let match = folderNameRegEx.exec(folder.name)
      if (match && match.length) {
        let folderCode = match[1]
        let folderDate = match[2]
        let folderFlag = match[3]
        if (folderFlag != 'NEW!') {
          toUpdate.push({
            parentCode: folderCode,
            folderDate: folderDate,
            folder: folder
          })
        }
      }
    })

  console.log(toUpdate.map(item => `${item.folder.name} -> ${item.parentCode}`))

  let parentsByCode = client.from('goodFolder')
    .filter('code', _.uniq(toUpdate.map(item => item.parentCode)))
    .chain()
    .indexBy(folder => folder.code)
    .value()
  
  toUpdate = toUpdate.map(item => {
    let folder = item.folder
    let parent = parentsByCode[item.parentCode]
    folder.parentUuid = parent ? parent.uuid : null
    folder.name = item.parentCode + ' ' + item.folderDate
    return folder
  })

  // console.log(toUpdate)
  client.save(toUpdate)

})()