Greasy Fork is available in English.

Virtonomica:GosSnab

Добавляет кнопки автоматического выставления количества заказываемого товара

La data de 23-05-2014. Vezi ultima versiune.

// ==UserScript==
// @name            Virtonomica:GosSnab
// @namespace      virtonomica
// @version        1.60
// @include        http://*virtonomic*.*/*/main/unit/view/*/supply
// @include        http://igra.aup.ru/*/main/unit/view/*/supply
// @description Добавляет кнопки автоматического выставления количества заказываемого товара
// ==/UserScript==

var run = function() {

// Версия минимального снабжения (прописать цифру 1)
var minimal = 0;
// особые условия закупки при занятии данной доли рынка
var limit = 10;

var win = (typeof(unsafeWindow) != 'undefined' ? unsafeWindow : top.window);
$ = win.$;


function SetAmount( up) {

	var n_row = 0;
	var change = 0;
	var up_count = 0;
	var down_count = 0;
	var prc_count = 0;
	$("tr.product_row").each( function() {
		var el_info = $("td:eq(3)", this);

		img = $("img[src*='/img/products']", this);

		//alert(" !!! " + img.attr("src") + "("+market[ img.attr("src") ] + ")" );

		// на складе
		var col =	parseInt ( $("tr td:contains('Количество')", this).next().text().replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '') );
		//продано в магазине
		var sale =	parseInt ( $("tr td:contains('Продано')", this).next().text().replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '') );
		// зауплено в этот ход
		var amount = parseInt ( $("td:eq(15)", this).text().replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '') );

		console.log("COL= " +col + " SALE = "+ sale + " AMOUNT = " + amount);

		// поле для ввода количества заказываемого товара
		var input = $("input[name^='supplyContractData']:eq(1)", this);

		// если больше одного поставщика, то пропускаем
		var test = $("td[id^='name']",this).attr('id');
		pos = test.indexOf('_');
		pos2 = test.indexOf('_', pos+1);
		var id = test.substr(pos+1, pos2-pos -1);
		if ( gaMaterialProduct[ id ]['subRowCount'] > 1) {
			//нашли несколько строк
			return;
		}
		
		set = sale; // закупить то, что было продано
		console.log ("1.set = "+ set);
		// если нет двухкратного запаса
		if ( col/2 < sale)  {
			set = Math.round( sale*1.2);
		}
		if ( col < sale ) {
			set  = sale * up;
		}else if ( col > sale*14) {
			// если продажи не существенные
			set = 0;
		}  else if ( col > sale*8) {
			// если продажи не существенные
			set = Math.round( sale /4);
		}  else if ( col > sale*4) {
			// если запасы слишком большие
			set = Math.round( sale /2);
		} else if ( col > sale*3) {
			set = Math.round( sale *0.8);
		} else if ( col > sale*2) {
			set = Math.round( sale *0.95);
		} else if ( col > sale*1.5) {
			set = Math.round( sale *up / (col/ sale ) );
		} else if ( col > sale ) {
			set = Math.round( (up+1)*sale - col );
		}
		console.log ("2.set = "+ set);
		// попробовать пробную партию
		if ( (sale == 0) && (col == 0) && (amount==0) ){
			// пробная закупка
			set = 1;
			console.log ("new.set = "+ set);
                }

		if( !( (sale == 0) && (amount==0) ) ) {
		    // если на складе запас равен закупке, то значит, все что было продано, уменьшать нельзя
		    if ( amount == col) {
			set = amount;
			if ( sale > amount) set = sale * up ; // если продали больше чем купили, то делаем запас на будущее
			if ( sale <= amount) set = amount * up;
		    }
		    // первая закупка
		    if ((sale == 0) && (col == amount)){
			set = amount;
		    }
	
		    console.log ("3.set = "+ set);

		    // Версия минимального снабжения
		    if (minimal == 1){
			if ( sale == col) {
				if (sale <= amount) set = sale;
				if (sale > amount) set = Math.round(amount*1.25);
			}

			if (amount > sale) {
				if (col <= sale) {
				 	set = Math.round(sale*1.25);
					//alert("2 sale = " + sale);
				}
			}
			if (sale < col*0.8) {
				set1 = Math.round(sale*0.8);
				set2 = Math.round(set*0.8);
				if (set1 > set2) set = set2;
				else set = set1;
			}

			if (sale < col*0.5) {
				set1 = Math.round(sale*0.2);
				set2 = Math.round(set*0.2);
				if (set1 > set2) set = set2;
				else set = set1;
			}

			if ( amount == col) {
				set = Math.round(sale*1.25);
			}
		    }
		    console.log ("4.set = "+ set);


   		    if (limit > 0) {
			prc = market[ img.attr("src") ];
			if (prc > limit) {
				prc_count++;
				all = Math.round(100*sale/prc);
				// Не закупать больше рынка
				if (set > all*1.1) {
					set = Math.round(all*1.1);
				}  else  if ( (col+set -sale) > all*1.1 ) {
                                        // прогноз тгго, что будет на складе через персчет
                                        new_sklad = col+set - sale;  
					if (new_sklad > all*14) {// ух ты запасов хватит еще на 2 недели торговли
						set = 0;
					} else if (new_sklad > all*8) {
						set = Math.round( sale /4);
					} else if (new_sklad > all*4) {
						set = Math.round( sale /2);
					} else if (new_sklad > all*2) {
						set = Math.round( sale *0.75);
					} else if (new_sklad > all) {
						set = Math.round( sale *0.9);
					} else {
  						// не держать запасов больше рынка
						set = Math.round(all*1.1 - col +sale);
						if (set <0) set = 0;
					}
				} 
				// уменьшить прирост закупок до 25% если превышен лимит рынка
				if ( amount != col) {
					if ( set/sale > 1.25) {
						set = Math.round(sale*1.25);
					}
				} else {
					set = Math.round(amount*1.25);
				}
			}
		    }
		    console.log ("5.set = "+ set);
		}
		if (set != input.attr("value") ) {
			change++;
			if ( set > input.attr("value") ){
				up_count ++;
			} else {
				down_count ++;
			}
		}
		input.attr("value", set) ;	// пишем новое значение
		n_row++;

	});
	$("#gossnab").append("Обработано строк: " + n_row + ", изменено: "+ change+ " (up:" + up_count + "; down:" + down_count+ ")");
	if ( (limit > 0) && (prc_count >0) ){
		$("#gossnab").append("<br>Больших долей рынка: " + prc_count+ "");
	}
}

function ClearAmount( ) {
	var n_row = 0;
	$("tr[id^='product_']").each( function() {
		var input = $("input[name^='supplyContractData']:eq(1)", this);
		input.attr("value", 0);
		n_row++;
	});
	$("#gossnab").append("Обнулили: " + n_row );
}

function SetFactory( mode ) {
	var n_row = 0;
	$("tr[id^='product_row']").each( function() {
		// Требуется
		var require = parseInt ( $("tr td:contains('Требуется')", this).next().text().replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '') );

		var warehouse = parseInt ( $("tr td:contains('Количество')", this).next().text().replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '') );

		// поле для ввода количества заказываемого товара
		var input = $("input[name^='supplyContractData']:eq(1)", this);

		// если больше одного поставщика, то пропускаем
		var test = $("td[id^='name']",this).attr('id');
		pos = test.indexOf('_');
		pos2 = test.indexOf('_', pos+1);
		var id = test.substr(pos+1, pos2-pos -1);
		if ( gaMaterialProduct[ id ]['subRowCount'] > 1) {
			//нашли несколько строк
			return;
		}
		k_zak = 0;
		switch ( mode )
		{
		  case 1:
			set = require; // закупить то, что требуется
		    break;
		  case 2:
			k_zak = 1;
		    	set = 2 * require - warehouse;
			if (set < 0) set =0;
			if (warehouse < require) set = require;
		    break;
		  case 3:
			k_zak = 2;
		    break;
		  case 4:
			k_zak = 2.5;
		    break;
		}
		if (k_zak > 0){
		    	set = (k_zak +1) * require - warehouse;
			if (set < 0) set =0;
			if (warehouse < require) set = k_zak * require;
		}

		input.attr("value", set) ;	// пишем новое значение
		n_row++;
	});
	$("#gossnab").append("Обработано строк: " + n_row );
}

var out = '<td><span id=gossnab style="color:yellow"></span>';

var input_clear = $('<button id=b_clear>Clear</button>').click(function() {
		ClearAmount();
});


var img =  $("#unitImage").html();
img = img.substr(0,img.length-8);
// Проверить, что это магазин
if ( img =='<img src="/img/v2/units/shop') {
	// кнопки
	 var input_2 = $('<button id=b2>1:1 up2</button>').click(function() {
		SetAmount(2);
	});
	 var input_5 = $('<button id=b5>1:1 up4</button>').click(function() {
		SetAmount(4);
	});
	var container = $('#topblock');
	container.append( $('<table><tr>').append('<td>').append(input_2).append('<td>').append(input_5).append('<td>').append(input_clear).append( out)   );

	// найти "свободно"
	$("td[id^='free']").attr('title','Закупить весь остаток').live('dblclick', function(){ 
		var free = $(this).text().replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '') ; 
		var td = $("td[id^='quantityField']",  $(this).parent().parent().parent().parent().parent() ) ;
		var input = $("input[name^='supplyContractData']:eq(0)", td );
		input.attr("value", free) ;
	});

	var market = new Array();
	if (limit > 0) {
		// Формируем ссылку на торговый зал
		var url = /^http:\/\/virtonomic[as]\.(\w+)\/\w+\//.exec(location.href)[0];
		//var id = /\/unit\/view\/(\d+)/.exec(location.href)[0];
		var id = /\/unit\/view\/(\d+)/.exec(location.href)[0];
		url = url + "main" + id + "/trading_hall";
		//alert(url);
	   	$.get(url, function(data) {
			//alert("read");
	        	var td = $("td:contains('%')", data);
			for (i=1; i< td.length; i++) {
				td_pr = td.eq(i);
				tr = td_pr.parent();
				img = $("img[src*='/img/products']", tr);
				market[ img.attr('src') ] = parseFloat( td_pr.text().replace('%', '') );
			}
	   	});
		//alert('post read');
	}

}
// Проверить не завод ли это 
function checkType()
{
   var head = $("#unitImage");
   var img = $("img", head);
   link = img.attr('src');

   n = link.indexOf('workshop');
   if (n > 0) return true;

   n = link.indexOf('mill');
   if (n > 0) return true;

   n = link.indexOf('animalfarm');
   if (n > 0) return true;

   return false; 
}

var wc_factory = $("<li><div id=factory_supply style='float:left;cursor:pointer; color: white;'> <img title='Рассчитать снабжение' alt='Расчет снабжения' src=http://www.iconsearch.ru/uploads/icons/iconslandtransport/24x24/lorrygreen.png> </div>").click( function() { 

//---------------------------------------------------------------------
// работа с локальным хранилищем
//---------------------------------------------------------------------
/**
* записать данные в локальнео хранилище, с проверкой ошибок
*/
function ToStorage(name,  val)
{
    try {
      window.localStorage.setItem( name,  JSON.stringify( val ) );
    } catch(e) {
      out = "Ошибка добавления в локальное хранилище";
      //console.log(out);
    }
}

function getFromStorage(obj, id_shop)
{
    if (obj[id_shop] == null) return '';
    return JSON.stringify(obj[id_shop]);
}

/**
* Добавить заметку к предприятию
*/
function addNotes( msg ){
    // объект для хранения сообщений
    notes = JSON.parse( window.localStorage.getItem('notes') );
    if ( notes == null ) notes = new Object();

    // Идентификатор подразделения
    var id = /(\d+)/.exec(location.href)[0];
     
    var head = $("#headerInfo");
    var title = $("h1", head).text();

    head = $("div.officePlace");
    var type = head.text();
    var nn = type.indexOf("компании");
    if (nn > 0){
    type = type.substring(0, nn);
    var ptrn = /\s*((\S+\s*)*)/;
    type = type.replace(ptrn, "$1");
    ptrn = /((\s*\S+)*)\s*/;
    type = type.replace(ptrn, "$1");
    } else {
    type = '';
    }

    if ( notes[id] == null ) notes[id] = new Object();

    var d = new Date();

    if ( notes[id]['text'] != null) {
     // сообщение для этого подраздления уже есть
     msg = notes[id]['text'] + "<br>" + msg;
    }

    notes[id]['text'] = msg;
    // Количество миллисекунд
    notes[id]['time'] = d.getTime();
    notes[id]['name'] = title;
    notes[id]['type'] = type;

    ToStorage('notes', notes);
}
//---------------------------------------------------------------------
// работа с локальным хранилищем
//---------------------------------------------------------------------

    var table  = $("table.list");

    // список товаров на заказ
    var tr = $("tr[id^='product_row']", table);
    console.log("product_row = " + tr.length);
    for(i=0; i<tr.length; i++) {
       table2 = $("td:contains('Количество')", tr.eq(i) );
       console.log("-----------------");
       //console.log(table2.html());
       td = $("td:contains('Количество')", table2 ).next();
       // сколько есть на складе
       number = parseInt( td.text().replace(" ", "").replace(" ", "").replace(" ", "").replace(" ", "").replace(" ", "").replace(" ", "") );
       console.log("number = " + number);

       table2 = $("td:contains('Требуется')", tr.eq(i) );
       td = $("td:contains('Требуется')", table2 ).next();
     
       // на одного посетителя
       require = parseInt( td.text().replace(" ", "").replace(" ", "").replace(" ", "").replace(" ", "").replace(" ", "").replace(" ", "") );
       console.log( "require = " + require);

       //img = $("img[src^='/img/products']", tr.eq(i));
       //console.log("IMG= " + img.length) ;

       // сколько заказать
       add = require;

       // поиск дополнительных поставщиков
       tr_id = tr.eq(i).attr('id') ;
       console.log( "tr_id = " + tr_id);

       tr_sub_id = tr_id.replace("product_row", "product_sub_row");
       console.log( "tr_sub_id = " + tr_sub_id);
       str = "tr[id^='" + tr_sub_id + "']";
       sr_tr = $(str, table);
       if (sr_tr.length == 0) {
           // У нас только один поставщик
           // проверить свободные     
           free = $("td:contains('Свободно')", tr.eq(i) ).next().text();
           free = parseInt( free.replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","") );

           // ограничение про заказу со склада
	   max = 0;
	   max_info = $("span:contains('Max:')", tr.eq(i) );
           if (max_info.length > 0) {
                max =  parseInt( max_info.text().replace("Max:","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","") );
		console.log( "max_info = " + max );
           }

           if (isNaN(free) ) {
                error_str = "<img src=" + img.attr('src') + " width=16> Отсутствует поставщик";
                addNotes( "<font color=red>" + error_str +"</font>" );
                console.log( error_str );
                continue;
           } else if ( (add > free) || ( (add > max) && (max > 0) ) ) {
                error_str = "<img src=" + img.attr('src') + " width=16> Недостаточно свободного товара у поставщика";
                addNotes( "<font color=red>" + error_str +"</font>" );
                console.log( error_str );
                continue;
           }

           $("input[name^='supplyContractData[party_quantity]']", tr.eq(i) ).val(add);
           //input.val(add);
           continue;
       }

       // несколько поставщиков
       var stat = new Array();
       stat[0] = new Object();
       var inp = new Array();

       free = $("td:contains('Свободно')", tr.eq(i) ).next().text();
       free = parseInt( free.replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","") );
           // ограничение про заказу со склада
	   max = 0;
	   max_info = $("span:contains('Max:')", tr.eq(i) );
           if (max_info.length > 0) {
                max =  parseInt( max_info.text().replace("Max:","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","") );
		console.log( "max_info = " + max );
           }

       if (max > 0) free = max;
       stat[0]['free'] = free;
       stat[0]['add'] = 0;
       inp[0] = $("input[name^='supplyContractData[party_quantity]']", tr.eq(i) );
       console.log(inp[0].val() + " = " + inp[0].length);

       for(j=0; j<sr_tr.length; j++){
           row = sr_tr.eq(j) ;
           stat[j+1] = new Object();
           free = $("td:contains('Свободно')", row ).next().text();
           free = parseInt( free.replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","") );
           // ограничение про заказу со склада
	   max = 0;
	   max_info = $("span:contains('Max:')", row );
           console.log( "max_info = " + max_info.length );

           if (max_info.length > 0) {
                max =  parseInt( max_info.text().replace("Max:","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","") );
		console.log( "max_info = " + max );
           }
	   if (max > 0) free = max;
           console.log( "............." );

           stat[j+1]['free'] = free;
           stat[j+1]['add'] = 0;

           inp[j+1] = $("input[name^='supplyContractData[party_quantity]']", row) ;
           console.log(j + ". " +inp[j+1].val() + " = " + inp[j+1].length);

       }
       console.log( JSON.stringify(stat) );

       // простейший вариант - первый паопавшийся поставщик выбирается по максимуму
       add_left = add ;
       for(j=0; j<stat.length; j++) {
           if ( add_left <= stat[j]['free'] ) {
                stat[j]['add'] = add_left;
                add_left = 0;
                break;
           }
           stat[j]['add'] = stat[j]['free'];
           add_left -= stat[j]['free'];
       }
       console.log( JSON.stringify(stat) + " = " + add_left);
       // выставляем цифры в интерфейс
       for(j=0; j<stat.length; j++) {
           inp[j].val( stat[j]['add'] );
           console.log( inp[j].attr("name") );
       }
       if ( add_left > 0) {
            error_str = "<img src=" + img.attr('src') + " width=16> Нехватка товара у поставщиков (мультизаказ) ";
            addNotes( "<font color=red>" + error_str +"</font>" );
       }

    
    }// цикл по товарам (компонентам)
    // нажать кнопку изменить
    $("input[name='applyChanges']").click();
    $("#factory_supply_info").html("поменяли цифры");

});


if ( checkType() == true ){
	// кнопки
	 var input_100 = $('<button id=b100>1:1</button>').click(function() {
		SetFactory(1);
	});
	 var input_200 = $('<button id=b200>х1</button>').click(function() {
		SetFactory(2);
	});
	 var input_х2 = $('<button id=bх2>х2</button>').click(function() {
		SetFactory(3);
	});
	 var input_х25 = $('<button id=bх25>х2.5</button>').click(function() {
		SetFactory(4);
	});

	var container = $('#topblock');
	container.append( $('<table><tr>').append('<td>').append(input_100) .append('<td>').append(input_200).append('<td>').append(input_х2).append('<td>').append(input_х25).append('<td>').append(input_clear).append( out)  );

	container = $('#topblock').next();
	container = $("li:last", container).prev().parent();
	container.append(wc_factory) ;
	$("table.infoblock").before("<span id=factory_supply_info></span>");

}
// склады
var wc_warehouse = $("<li><div id=factory_supply style='float:left;cursor:pointer; color: white;'> <img title='Рассчитать снабжение' alt='Расчет снабжения' src=http://www.iconsearch.ru/uploads/icons/iconslandtransport/24x24/lorrygreen.png> </div>").click( function() { 
    var table  = $("table.list");

    // список товаров на заказ
    var tr = $("tr.p_title, tr.odd, tr.even", table);
    console.log("TR = " + tr.length);
    var all = 0;
    var require = 0;
    var left = 0; // осталось
    for(i=0; i<tr.length; i++) {
       row = tr.eq(i);
       //console.log("row = " + row.html() );
       if (row.hasClass('p_title') ) {
            // Начало нового товра 
            console.log("----------\nNEW"  );
            title = $("td.p_title_l", row);

            all = $("td:contains('На складе:')", title ).next().text();
            all = parseInt( all.replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","") );
            console.log("all = " + all  );

            require = $("td:contains('по контрактам')", title ).next().text();
            require = parseInt( require.replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","") );
            console.log("require = " + require  );

            left = require;
            continue;
       }
       
       td = $("td.num:last", row);
       str = $("span" , td);
       n = str.html().indexOf("<br>");
       // такого быть не должно 
       if (n ==0 ) continue;

       free = parseInt( str.html().substring(0, n).replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(" ","") );

       console.log("free = " + free  );

       // поле для ввода
       input = $("input", row);
       
       add = free;
       if (left < free) add = left;
       input.val(add);        
       left -= add;

    }


});

// warehouse
head = $("#unitImage");
img = $("img", head);
link = img.attr('src');

n = link.indexOf('warehouse');
if (n > 0) {
	container = $('#topblock').next();
	container = $("li:last", container).prev().parent();
	container.append(wc_warehouse) ;
}

}

// Хак, что бы получить полноценный доступ к DOM >:]
var script = document.createElement("script");
script.textContent = '(' + run.toString() + ')();';
document.documentElement.appendChild(script);