Subversion Repositories munaweb

Rev

Rev 30 | Rev 180 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
<!DOCTYPE html>
2
<html lang="en">
3
 
4
<head>
5
    <title>eBay Listings Price Check</title>
6
    <meta charset="UTF-8">
7
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
    <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
9
    <link rel="icon" href="favicon.ico" type="image/x-icon">
10
 
30 - 11
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
12
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
13
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
14
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
15
    <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
16
    <script src="js/XMLWriter.js"></script>
17
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
18
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.23.0/moment.min.js"></script>
19
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.23/moment-timezone-with-data-2012-2022.min.js"></script>
2 - 20
    <link rel="stylesheet" href="css/style.css">
21
    <script src="js/muna-tools.js"></script>
22
</head>
23
 
24
<body onload="return initConfig();">
30 - 25
    <div>
26
        <div>
27
            <div class="container-fluid bg-secondary">
28
                <div class="clearfix">
29
                    <img class="img-fluid float-right" src="images/MUNA%20-%20Logo%20100x100.png" alt="MUNA Trading Logo" />
30
                    <h1 id="connected">eBay Listings Price Check
31
                    <input id="login" type="button" class="btn bg-success mb-2 w3-hide" onclick="eBayLogin();" value="Login" /></h1>
32
                </div>
2 - 33
            </div>
34
 
30 - 35
            <div class="border col">
2 - 36
                <div>
30 - 37
                    <form id="searchForm" class="container-fluid bg-light" onsubmit="return checkListingPrices();">
38
                        <input id="startButton" type="button" class="btn btn-dark" onclick="checkListingPrices();" value="Start" />
2 - 39
                    </form>
40
                </div>
30 - 41
                <div class="modal" id="progressBarDiv">
42
                    <div class="modal-dialog">
43
                        <div class="modal-content">
44
                            <div class="modal-header">
45
                                <h4 id="progressBarHeader"></h4>
46
                            </div>
47
                            <div class="modal-body">
48
                                <div class="progress">
49
                                    <div id="progressBar" class="progress-bar" style="width:0%">0%</div>
50
                                </div>
51
                            </div>
52
                        </div>
2 - 53
                    </div>
54
                </div>
30 - 55
                <div id="results" class="border bg-info w3-hide"></div>
56
                <div id="logging"></div>
2 - 57
            </div>
58
        </div>
59
 
30 - 60
        <footer class="container-fluid text-center border border-bottom-0 border-left-0 border-right-0">
17 - 61
            <div w3-include-html="php/footer.php"></div>
2 - 62
        </footer>
63
 
64
    </div>
6 - 65
 
2 - 66
    <script>
67
 
68
// Config
69
var configMinPrice = "5.99";
70
var configDifference = 2.00;
71
var configPercentage = 20.00;
72
var configAbsoluteMinPrice = 5.00;
73
var configAdjMinPrice = 5.48;
72 - 74
var configSearchUrl = 'https://munatrading.linkpc.net/ebay/search.html?keyword=';
2 - 75
var configSearchUrlPart2 = '&hideDuplicateItems=on&locatedIn=WorldWide&sortOrder=PricePlusShippingLowest&results=100';
76
 
77
var pagesToProcess = 0;
78
var maxPagesToProcess = 0;
79
var pagesProcessed = 0;
80
var productIdsToProcess = 0;
81
var maxProductIdsToProcess = 0;
82
var productIdsProcessed = 0;
83
var productsToPrice = 0;
84
var maxProductsToPrice = 0;
85
var productsPriced = 0;
86
var html = [];
87
 
88
// Initialize Configuration Variables
89
function initConfig() {
90
    eBayAuthToken = readCookie();
91
    if (eBayAuthToken.length > 0) {
92
        connected();
93
    }
94
 
95
    if (eBayAuthTokenFlag === false) {
96
        var x = document.getElementById("login");
97
        if (x.className.indexOf("w3-show") == -1) {
98
            x.className += " w3-show";
99
        }
100
    }
101
}
102
 
103
function requireNewLogin() {
104
    // dummy
105
}
106
 
107
function checkListingPrices() {
108
    var x;
109
 
110
    document.getElementById("logging").innerHTML = '';
111
 
112
    x = document.getElementById("results");
113
    if (x.className.indexOf("w3-show") == -1) {
114
        x.className += " w3-show";
115
    }
116
    x.className = x.className.replace(" process-errors", "");
117
    x.innerHTML = '';
118
 
119
    initProgressBar('Retrieving Active Listings (1/3)');
120
 
121
    pagesToProcess = 1;
122
    maxPagesToProcess = 1;
123
    pagesProcessed = 0;
124
    eBaySearch(1);
125
 
126
    function checkpagesToProcess() {
127
        if (pagesToProcess > 0) {
128
            window.setTimeout(checkpagesToProcess, 100); // wait 100 milliseconds
129
        } else {
130
            findMissingProductIds();
131
        }
132
    }
133
 
134
    checkpagesToProcess();
135
}
136
 
137
// item filters for request
138
var filterarray = [];
139
var urlfilter = [];
140
 
141
// Fill the array of item filters from input form
142
function fillFilterArray() {
143
    filterarray = [];
144
    var obj = [];
145
 
146
    obj = {
147
        "name": "Seller",
148
        "value": configeBaySellerName,
149
        "paramName": "",
150
        "paramValue": ""
151
    };
152
    filterarray.push(obj);
153
 
154
    obj = {
155
        "name": "MinPrice",
156
        "value": Number(configMinPrice).toFixed(2),
157
        "paramName": "Currency",
158
        "paramValue": "USD"
159
    };
160
    filterarray.push(obj);
161
 
162
    obj = {
163
        "name": "ListingType",
164
        "value": "FixedPrice",
165
        "paramName": "",
166
        "paramValue": ""
167
    };
168
    filterarray.push(obj);
169
 
170
    urlfilter = "";
171
    // Iterate through each filter in the array
172
    for (var i = 0; i < filterarray.length; i++) {
173
        //Index each item filter in filterarray
174
        var itemfilter = filterarray[i];
175
        // Iterate through each parameter in each item filter
176
        for (var index in itemfilter) {
177
            // Check to see if the paramter has a value (some don't)
178
            if (itemfilter[index] !== "") {
179
                if (itemfilter[index] instanceof Array) {
180
                    for (var r = 0; r < itemfilter[index].length; r++) {
181
                        var value = itemfilter[index][r];
182
                        urlfilter += "&itemFilter\(" + i + "\)." + index + "\(" + r + "\)=" + value;
183
                    }
184
                } else {
185
                    urlfilter += "&itemFilter\(" + i + "\)." + index + "=" + itemfilter[index];
186
                }
187
            }
188
        }
189
    }
190
} // End fillFilterArray() function
191
 
192
var url = "";
193
 
194
function eBaySearch(pageNumber) {
195
    // Fill the filter array from form input
196
    if (pageNumber == 1) {
197
        fillFilterArray();
198
    }
199
 
200
    // Construct the request
201
    url = configeBayFinding + "?";
202
    url += "OPERATION-NAME=findItemsAdvanced";
203
    url += "&SERVICE-VERSION=" + configeBayFindingVersion;
204
    url += "&SECURITY-APPNAME=" + configAppid;
205
    url += "&GLOBAL-ID=EBAY-US";
206
    url += "&RESPONSE-DATA-FORMAT=JSON";
207
    url += "&REST-PAYLOAD";
208
    url += "&paginationInput.entriesPerPage=100";
209
    url += "&paginationInput.pageNumber=";
210
    url += pageNumber;
211
    url += urlfilter;
212
 
213
    var xhttp = new XMLHttpRequest();
214
 
215
    xhttp.onreadystatechange = function() {
216
        if (this.readyState == 4) {
217
            _cb_findItemsAdvanced(JSON.parse(this.responseText));
218
        }
219
    };
220
 
221
    xhttp.open("GET", configProxyUrl, true);
222
    xhttp.setRequestHeader("X-Proxy-Url", encodeURI(url));
223
    xhttp.send();
224
 
225
    return false;
226
}
227
 
4 - 228
function printeBayAPIError(str, root) {
2 - 229
    var x = document.getElementById("results");
230
    x.className += " process-errors";
4 - 231
    x.innerHTML += "<h2>eBay API Error (" + str + ")<h2>";
2 - 232
    x.innerHTML += "<p>Id: " + root.errorMessage[0].error[0].errorId + "<br/>";
233
    x.innerHTML += "<p>Severity: " + root.errorMessage[0].error[0].severity + "<br/>";
234
    x.innerHTML += "<p>Message: " + root.errorMessage[0].error[0].message + "</p>";
235
}
236
 
237
// Parse the response and build an HTML table to display search results
238
function _cb_findItemsAdvanced(root) {
239
    // Error Handling
240
    var response = root.findItemsAdvancedResponse[0];
241
    var ack = response.ack;
242
    if (ack != 'Success') {
4 - 243
        printeBayAPIError('Find Item', response);
2 - 244
 
245
        if (ack == 'Failure' || ack == 'PartialFailure') {
246
            --pagesToProcess;
247
            return;
248
        }
249
    }
250
 
251
    createTable(response.searchResult[0].item || [], Number(response.paginationOutput[0].pageNumber), Number(response.paginationOutput[0].totalPages));
252
 
6 - 253
    if (Number(response.paginationOutput[0].totalPages) > Number(response.paginationOutput[0].pageNumber)) {
254
        ++maxPagesToProcess;
255
        ++pagesToProcess;
256
        eBaySearch(Number(response.paginationOutput[0].pageNumber) + 1);
257
    }
2 - 258
 
259
    document.getElementById("logging").innerHTML = html.join('');
260
    --pagesToProcess;
261
    ++pagesProcessed;
262
    updateProgressBar(maxPagesToProcess, pagesProcessed);
263
} // End _cb_findItemsAdvanced() function
264
 
265
 
266
function createTable(obj, pageNumber, totalPages) {
267
    if (pageNumber == 1) {
268
        document.getElementById("logging").innerHTML = '';
269
        html = [];
270
 
30 - 271
        html.push('<div class="border table-responsive">');
2 - 272
        html.push('<h3>Price Validation</h3>');
30 - 273
        html.push('<table id="itemTable" class="table table-hover table-striped table-bordered small css-serial">');
274
        html.push('<thead class="thead-dark">');
2 - 275
        html.push('<tr>');
276
 
277
        html.push(tableHeader('#'));
278
        html.push(tableHeader('Item Id'));
279
        html.push(tableHeader('Thumbnail'));
280
        html.push(tableHeader('Title'));
281
        html.push(tableHeader('Product Id'));
282
        html.push(tableHeader('Price'));
283
        html.push(tableHeader('# Active Listings'));
284
        html.push(tableHeader('# Priced Lower'));
285
        html.push(tableHeader('Lowest Price'));
286
        html.push(tableHeader('Highest Price'));
287
        html.push(tableHeader('Above/Below Lowest'));
288
        html.push(tableHeader('Views'));
289
        html.push(tableHeader('Watchers'));
290
        html.push(tableHeaderHidden('Condition'));
291
        html.push(tableHeaderHidden('# Better Condition'));
292
        html.push(tableHeader('Price Adj.'));
293
        html.push(tableHeaderHidden('Best Offer'));
294
        html.push(tableHeaderHidden('MinBetterCondition'));
295
        html.push(tableHeaderHidden('BetterConditionBreakdown'));
296
        html.push(tableHeaderHidden('SameConditionBreakdown'));
297
 
298
        html.push('</tr>');
299
        html.push('</thead>');
300
        html.push('<tbody>');
301
    }
302
 
303
    for (var entry = 0; entry < obj.length; entry++) {
304
        html.push('<tr>');
305
        html.push(tableCell(''));
306
        html.push(tableCell('<a href="' + obj[entry].viewItemURL + '" target="_blank">' + obj[entry].itemId + '</a>'));
307
        html.push(tableCell('<img src="' + obj[entry].galleryURL[0].replace('http:', 'https:') + '">'));
308
        html.push(tableCell(obj[entry].title));
309
        if (obj[entry].productId !== undefined) {
310
            var str = '<a href="' + configSearchUrl;
311
            str += 'ReferenceID%3A' + obj[entry].productId[0].__value__;
312
            str += configSearchUrlPart2 + '" target="_blank">';
313
            str += obj[entry].productId[0]["@type"] + ' ' + obj[entry].productId[0].__value__;
314
            str += '</a>';
315
            html.push(tableCell(str));
316
        } else {
317
            html.push(tableCellLabel('ProductId' + obj[entry].itemId));
318
        }
319
 
320
        html.push(tableCell('$' + Number(obj[entry].sellingStatus[0].convertedCurrentPrice[0].__value__).toFixed(2)));
321
        html.push(tableCell(1));
322
        html.push(tableCell(0));
323
        html.push(tableCell('$0.00'));
324
        html.push(tableCell('$0.00'));
325
        html.push(tableCell('$0.00 (0.00%)'));
326
 
327
        html.push(tableCell(0));
328
        html.push(tableCell(obj[entry].listingInfo[0].watchCount === undefined ? 0 : Number(obj[entry].listingInfo[0].watchCount)));
329
        html.push(tableCellHidden(obj[entry].condition === undefined ? 4000 : Number(obj[entry].condition[0].conditionId)));
330
        html.push(tableCellHidden(0));
30 - 331
        html.push(tableCell('<input id="PriceAdj' + obj[entry].itemId + '" type="text" size="10"><br><input type="button" class="btn btn-dark" onclick="changePrice(' + obj[entry].itemId + ');" value="Adjust Price" />'));
2 - 332
        html.push(tableCellLabelHidden('BestOffer' + obj[entry].itemId, obj[entry].listingInfo[0].bestOfferEnabled));
333
        html.push(tableCellHidden('0'));
334
        html.push(tableCellHidden('[]'));
335
        html.push(tableCellHidden('[]'));
336
 
337
        html.push('</tr>');
338
    }
339
 
340
    if (pageNumber == totalPages) {
341
        html.push('</tbody>');
342
        html.push('</table>');
343
        html.push('</div>');
344
    }
345
}
346
 
347
function setCellsAttribute(table, row, col, label) {
348
    table.rows[row].cells[col].setAttribute("id", label);
349
}
350
 
351
function sortTableDesc(tableName, column) {
352
    var table, rows, switching, i, x, y, shouldSwitch;
353
    --column; // column parameter starts with 1
354
    table = document.getElementById(tableName);
355
    switching = true;
356
    /*Make a loop that will continue until
357
    no switching has been done:*/
358
    while (switching) {
359
        //start by saying: no switching is done:
360
        switching = false;
361
        rows = table.getElementsByTagName("TR");
362
        /*Loop through all table rows (except the
363
        first, which contains table headers:*/
364
        for (i = 1; i < (rows.length - 1); i++) {
365
            //start by saying there should be no switching:
366
            shouldSwitch = false;
367
            /*Get the two elements you want to compare,
368
            one from current row and one from the next:*/
369
            x = rows[i].getElementsByTagName("TD")[column];
370
            y = rows[i + 1].getElementsByTagName("TD")[column];
371
            //check if the two rows should switch place:
372
            if (x !== undefined && (Number(x.innerHTML.substr(1)) < Number(y.innerHTML.substr(1)))) {
373
                //if so, mark as a switch and break the loop:
374
                shouldSwitch = true;
375
                break;
376
            }
377
        }
378
        if (shouldSwitch) {
379
            /*If a switch has been marked, make the switch
380
            and mark that a switch has been done:*/
381
            rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
382
            switching = true;
383
        }
384
    }
385
}
386
 
387
function findMissingProductIds() {
388
    var i;
389
    var x = document.getElementById("itemTable");
390
    var missingList = [];
391
    var viewList = [];
392
    var maxItems = 20;
393
 
394
    initProgressBar('Retrieving Product Ids (2/3)');
395
 
396
    productIdsToProcess = 0;
397
    maxProductIdsToProcess = 0;
398
    productIdsProcessed = 0;
399
 
400
    for (i = 1; i < x.rows.length; i++) {
401
        if (x.rows[i].cells[4] !== undefined && x.rows[i].cells[4].innerText.length < 1) {
402
            missingList.push(x.rows[i].cells[1].innerText);
403
        } else {
404
            var p = x.rows[i].cells[4].innerText.substr(x.rows[i].cells[4].innerText.indexOf(" ") + 1);
405
            setCellsAttribute(x, i, 5, "Price" + p);
406
            setCellsAttribute(x, i, 6, "Active" + p);
407
            setCellsAttribute(x, i, 7, "Lower" + p);
408
            setCellsAttribute(x, i, 8, "Minimum" + p);
409
            setCellsAttribute(x, i, 9, "Maximum" + p);
410
            setCellsAttribute(x, i, 11, "Views" + x.rows[i].cells[1].innerText);
411
            setCellsAttribute(x, i, 13, "Condition" + p);
412
            setCellsAttribute(x, i, 14, "BetterCondition" + p);
413
            setCellsAttribute(x, i, 17, "MinBetterCondition" + p);
414
            setCellsAttribute(x, i, 18, "BetterConditionBreakdown" + p);
415
            setCellsAttribute(x, i, 19, "SameConditionBreakdown" + p);
416
            viewList.push(x.rows[i].cells[1].innerText);
417
        }
418
    }
419
 
420
    for (i = 0;
421
        (i * maxItems) < missingList.length; i++) {
422
        ++productIdsToProcess;
423
        ++maxProductIdsToProcess;
424
        findMissingProductId(missingList.slice(i * maxItems, (i + 1) * maxItems));
425
    }
426
 
427
    for (i = 0;
428
        (i * maxItems) < viewList.length; i++) {
429
        ++productIdsToProcess;
430
        ++maxProductIdsToProcess;
431
        findViews(viewList.slice(i * maxItems, (i + 1) * maxItems));
432
    }
433
 
434
    function checkproductIdsToProcess() {
435
        if (productIdsToProcess > 0) {
436
            window.setTimeout(checkproductIdsToProcess, 100); // wait 100 milliseconds
437
        } else {
438
            priceProductIds();
439
        }
440
    }
441
 
442
    checkproductIdsToProcess();
443
}
444
 
445
function findMissingProductId(itemIdList) {
446
    var i;
447
    var xml;
448
 
449
    var xw = new XMLWriter('UTF-8', '1.0');
450
    var xhr = new XMLHttpRequest();
451
 
452
    xw.writeStartDocument();
453
    xw.writeStartElement("GetMultipleItemsRequest");
454
    xw.writeAttributeString('xmlns', 'urn:ebay:apis:eBLBaseComponents');
455
 
456
    for (i = 0; i < itemIdList.length; i++) {
457
        xw.writeElementString('ItemID', itemIdList[i]);
458
    }
459
 
460
    xw.writeElementString('IncludeSelector', 'Details');
461
    xw.writeElementString('ErrorLanguage', 'en_US');
462
    xw.writeElementString('Version', configeBayShoppingVersion);
463
    xw.writeElementString('WarningLevel', configWarningLevel);
464
 
465
    xw.writeEndElement(); /* xmlrequest */
466
    xw.writeEndDocument();
467
 
468
    xhr.open('POST', configProxyUrl, true);
469
    xhr.setRequestHeader('Content-Type', 'text/xml');
470
    xhr.setRequestHeader('X-EBAY-API-APP-NAME', configAppid);
471
    xhr.setRequestHeader('X-EBAY-API-VERSION', configeBayShoppingVersion);
472
    xhr.setRequestHeader('X-EBAY-API-CALL-NAME', 'GetMultipleItems');
473
    xhr.setRequestHeader('X-EBAY-API-SITEID', '0');
474
    xhr.setRequestHeader('X-EBAY-API-DEV-NAME', '');
475
    xhr.setRequestHeader('X-EBAY-API-CERT-NAME', '');
476
    xhr.setRequestHeader('X-EBAY-API-REQUEST-ENCODING', 'XML');
477
    xhr.setRequestHeader('X-Proxy-URL', configeBayShopping);
478
 
479
    xml = xw.flush();
480
    xw.close();
481
 
482
    xhr.onload = function() {
17 - 483
        var jsonObj = XMLparse(xhr.responseXML, false);
484
        var obj = jsonObj.GetMultipleItemsResponse;
2 - 485
        var returnCode = obj.Ack;
19 - 486
        var str;
2 - 487
 
488
        var x = document.getElementById("results");
489
 
490
        if (returnCode == 'Success') {
491
            for (i = 0; i < obj.Item.length; i++) {
492
                var ItemID = getJsonValue(obj.Item[i].ItemID);
493
                var SKU = getJsonValue(obj.Item[i].SKU);
494
                var HitCount = getJsonValue(obj.Item[i].HitCount);
495
                var n = (SKU === undefined ? 0 : SKU.indexOf(" - "));
496
                var row;
497
                var str;
498
                var code;
499
 
500
                if (n > 0) {
501
                    code = SKU.substr(n + 3);
502
                    code = code.substr(code.indexOf(" ") + 1);
503
                    str = '<a href="' + configSearchUrl;
504
                    str += code;
505
                    str += configSearchUrlPart2 + '" target="_blank">';
506
                    str += SKU.substr(n + 3);
507
                    str += '</a>';
508
                    document.getElementById('ProductId' + ItemID).innerHTML = str;
509
                    x = document.getElementById("itemTable");
510
                    row = document.getElementById('ProductId' + ItemID).parentNode.rowIndex;
511
                    setCellsAttribute(x, row, 5, "Price" + code);
512
                    setCellsAttribute(x, row, 6, "Active" + code);
513
                    setCellsAttribute(x, row, 7, "Lower" + code);
514
                    setCellsAttribute(x, row, 8, "Minimum" + code);
515
                    setCellsAttribute(x, row, 9, "Maximum" + code);
516
                    x.rows[row].cells[11].innerHTML = HitCount;
517
                    setCellsAttribute(x, row, 13, "Condition" + code);
518
                    setCellsAttribute(x, row, 14, "BetterCondition" + code);
519
                    setCellsAttribute(x, row, 17, "MinBetterCondition" + code);
520
                    setCellsAttribute(x, row, 18, "BetterConditionBreakdown" + code);
521
                    setCellsAttribute(x, row, 19, "SameConditionBreakdown" + code);
522
                } else {
523
                    row = document.getElementById('ProductId' + ItemID).parentNode.rowIndex;
524
                    document.getElementById("itemTable").deleteRow(row);
525
                }
526
            }
527
        } else {
528
            x.className += " process-errors";
30 - 529
            str += '<p class="text-danger"><strong>' + returnCode + ':</strong></p>';
2 - 530
 
6 - 531
            var errors = getJsonArray(obj.Errors);
19 - 532
            str += "<p>";
6 - 533
            for (i = 0; i < errors.length; i++) {
19 - 534
                str += errors[i].SeverityCode + " (" + errors[i].ErrorCode + "): " + escapeHtml(errors[i].LongMessage) + "<br/>";
2 - 535
            }
19 - 536
            str += "</p>";
537
            x.innerHTML += str;
2 - 538
        }
539
 
540
        --productIdsToProcess;
541
        ++productIdsProcessed;
542
        updateProgressBar(maxProductIdsToProcess, productIdsProcessed);
543
    };
544
 
545
    xhr.send(xml);
546
}
547
 
548
function findViews(itemIdList) {
549
    var i;
550
    var xml;
551
 
552
    var xw = new XMLWriter('UTF-8', '1.0');
553
    var xhr = new XMLHttpRequest();
554
 
555
    xw.writeStartDocument();
556
    xw.writeStartElement("GetMultipleItemsRequest");
557
    xw.writeAttributeString('xmlns', 'urn:ebay:apis:eBLBaseComponents');
558
 
559
    for (i = 0; i < itemIdList.length; i++) {
560
        xw.writeElementString('ItemID', itemIdList[i]);
561
    }
562
 
563
    xw.writeElementString('ErrorLanguage', 'en_US');
564
    xw.writeElementString('Version', configeBayShoppingVersion);
565
    xw.writeElementString('WarningLevel', configWarningLevel);
566
 
567
    xw.writeEndElement(); /* xmlrequest */
568
    xw.writeEndDocument();
569
 
570
    xhr.open('POST', configProxyUrl, true);
571
    xhr.setRequestHeader('Content-Type', 'text/xml');
572
    xhr.setRequestHeader('X-EBAY-API-APP-NAME', configAppid);
573
    xhr.setRequestHeader('X-EBAY-API-VERSION', configeBayShoppingVersion);
574
    xhr.setRequestHeader('X-EBAY-API-CALL-NAME', 'GetMultipleItems');
575
    xhr.setRequestHeader('X-EBAY-API-SITEID', '0');
576
    xhr.setRequestHeader('X-EBAY-API-DEV-NAME', '');
577
    xhr.setRequestHeader('X-EBAY-API-CERT-NAME', '');
578
    xhr.setRequestHeader('X-EBAY-API-REQUEST-ENCODING', 'XML');
579
    xhr.setRequestHeader('X-Proxy-URL', configeBayShopping);
580
 
581
    xml = xw.flush();
582
    xw.close();
583
 
584
    xhr.onload = function() {
19 - 585
        var jsonObj = XMLparse(xhr.responseXML, false);
586
        var obj = jsonObj.GetMultipleItemsResponse;
2 - 587
        var returnCode = obj.Ack;
19 - 588
        var str;
2 - 589
 
590
        var x = document.getElementById("results");
591
 
592
        if (returnCode == 'Success') {
593
            for (i = 0; i < obj.Item.length; i++) {
594
                var ItemID = getJsonValue(obj.Item[i].ItemID);
595
                var HitCount = getJsonValue(obj.Item[i].HitCount);
596
 
597
                document.getElementById('Views' + ItemID).innerHTML = HitCount;
598
            }
599
        } else {
600
            x.className += " process-errors";
30 - 601
            str += '<p class="text-danger"><strong>' + returnCode + ':</strong></p>';
2 - 602
 
6 - 603
            var errors = getJsonArray(obj.Errors);
19 - 604
            str += "<p>";
6 - 605
            for (i = 0; i < errors.length; i++) {
19 - 606
                str += errors[i].SeverityCode + " (" + errors[i].ErrorCode + "): " + escapeHtml(errors[i].LongMessage) + "<br/>";
2 - 607
            }
19 - 608
            str += "</p>";
609
            x.innerHTML += str;
2 - 610
        }
611
 
612
        --productIdsToProcess;
613
        ++productIdsProcessed;
614
        updateProgressBar(maxProductIdsToProcess, productIdsProcessed);
615
    };
616
 
617
    xhr.send(xml);
618
}
619
 
620
function priceProductIds() {
621
    var i;
622
    var price;
623
    var lowest;
624
    var difference;
625
    var percentage;
626
    var noPricedLower;
627
    var noActive;
628
    var noBetterCondition;
629
    var percLower;
630
    var x = document.getElementById("itemTable");
631
 
632
    initProgressBar('Retrieving Prices (3/3)');
633
 
634
    productsToPrice = 0;
635
    maxProductsToPrice = 0;
636
    productsPriced = 0;
637
 
638
    for (i = 1; i < x.rows.length; i++) {
4 - 639
        if (x.rows[i].cells[4].innerText.length > 0) {
640
            ++productsToPrice;
641
            ++maxProductsToPrice;
642
            findProductPrices(x.rows[i].cells[4].innerText, 1);
643
        }
2 - 644
    }
645
 
646
    function checkProductsToPrice() {
647
        if (productsToPrice > 0) {
648
            window.setTimeout(checkProductsToPrice, 100); // wait 100 milliseconds
649
        } else {
650
            /*
651
                xxxxx
652
                Minimum of 5 comparison listings
653
                (Take out lowest and highest price before calculating the average)
654
                (Don't go under $4.98)
655
                (Price items below cheapest item with better condition)
656
                Price within the first 20-25% listing (by number)
657
                (Price below the average price)
658
                adjust BIN (buy it now) when changing the price: No BIN under $10; minimum accepted 65%, auto-accepted 85+%
659
                (disregard certain sellers (for now decluttr and zuber, list could be expanded))
660
            */
661
            for (i = (x.rows.length - 1); i > 0; i--) {
662
                noPricedLower = Number(x.rows[i].cells[7].innerHTML);
663
                noActive = Number(x.rows[i].cells[6].innerHTML);
664
 
665
                if (noActive < 6) {
666
                    document.getElementById("itemTable").deleteRow(i);
667
                    continue;
668
                }
669
 
670
                if (noPricedLower > 0) {
671
                    price = Number(x.rows[i].cells[5].innerHTML.substr(1));
672
                    lowest = Number(x.rows[i].cells[8].innerHTML.substr(1));
673
                    difference = price - lowest;
674
                    percentage = 100.00 - (lowest / price * 100.00);
675
                    x.rows[i].cells[10].innerHTML = "$" + difference.toFixed(2) + " (" + percentage.toFixed(2) + "%)";
676
 
677
                    percLower = (noPricedLower / noActive) * 100.00;
678
                    if (noPricedLower > 24.99) {
679
                        x.rows[i].cells[5].style.color = "red";
680
                        x.rows[i].cells[7].style.color = "red";
681
                    } else {
682
                        document.getElementById("itemTable").deleteRow(i);
683
                        continue;
684
                    }
685
 
686
                    if (difference < configDifference || percentage < configPercentage || price < configAbsoluteMinPrice) {
687
                        document.getElementById("itemTable").deleteRow(i);
688
                        continue;
689
                    } else {
690
                        x.rows[i].cells[5].style.color = "red";
691
                        x.rows[i].cells[10].style.color = "red";
692
                    }
693
                } else if (noPricedLower === 0) {
694
                    noBetterCondition = Number(x.rows[i].cells[14].innerHTML);
695
                    if (noActive == (noBetterCondition + 1)) {
696
                        document.getElementById("itemTable").deleteRow(i);
697
                        continue;
698
                    }
699
 
700
                    price = Number(x.rows[i].cells[5].innerHTML.substr(1));
701
                    lowest = Number(x.rows[i].cells[8].innerHTML.substr(1));
702
                    difference = price - lowest;
703
                    percentage = 100.00 - (lowest / price * 100.00);
704
                    x.rows[i].cells[10].innerHTML = "$" + difference.toFixed(2) + " (" + percentage.toFixed(2) + "%)";
705
 
706
                    if ((difference * -1.00) < configDifference && (percentage * -1.00) < configPercentage) {
707
                        document.getElementById("itemTable").deleteRow(i);
708
                        continue;
709
                    } else {
710
                        x.rows[i].cells[5].style.color = "green";
711
                        x.rows[i].cells[10].style.color = "green";
712
                    }
713
                    continue;
714
                }
715
            }
716
 
717
            endProgressBar();
718
 
719
            x = document.getElementById("results");
720
            x.innerHTML += '<p><strong>Sorting Report.....</strong></p>';
721
 
722
            sortTableDesc("itemTable", 6);
723
 
724
            x.innerHTML += '<p><strong>Report Finished!</strong></p>';
725
            if (!x.className.includes("process-errors")) {
726
                setTimeout(function() {
727
                    x.className = x.className.replace(" w3-show", "");
728
                }, 3000);
729
            }
730
        }
731
    }
732
 
733
    checkProductsToPrice();
734
}
735
 
736
function findProductPrices(productId, pageNumber) {
737
    var n = productId.indexOf(" ");
738
    var productIdType = productId.substr(0, n);
4 - 739
    var keyword = productId.substr(n + 1);
2 - 740
 
741
    url = configeBayFinding + "?";
742
    if (productIdType == 'ReferenceID') {
743
        url += "OPERATION-NAME=findItemsByProduct";
744
    } else {
745
        url += "OPERATION-NAME=findItemsAdvanced";
746
    }
747
    url += "&RESPONSE-DATA-FORMAT=JSON";
748
    url += "&SECURITY-APPNAME=" + configAppid;
749
    url += "&SERVICE-VERSION=" + configeBayFindingVersion;
750
    url += "&GLOBAL-ID=EBAY-US";
751
    url += "&buyerPostalCode=";
752
    url += configZip;
753
    url += "&paginationInput.entriesPerPage=100";
754
    url += "&paginationInput.pageNumber=";
755
    url += pageNumber;
756
 
757
    if (productIdType == 'ReferenceID') {
758
        url += "&productId.@type=";
759
        url += productIdType;
760
        url += "&productId=";
4 - 761
        url += keyword;
2 - 762
    } else {
763
        url += "&keywords=";
4 - 764
        url += keyword;
2 - 765
    }
766
 
767
    url += "&itemFilter(0).name=ExcludeSeller";
768
    url += "&itemFilter(0).value=";
769
    url += configeBaySellerName;
770
 
771
    var xhttp = new XMLHttpRequest();
772
 
773
    xhttp.onreadystatechange = function() {
774
        if (this.readyState == 4) {
775
            _cb_findProductPrices(JSON.parse(this.responseText));
776
        }
777
    };
778
 
779
 
780
    xhttp.open("GET", configProxyUrl, true);
781
    xhttp.setRequestHeader("X-Proxy-Url", encodeURI(url));
782
    xhttp.send();
6 - 783
 
2 - 784
}
785
 
786
function _cb_findProductPrices(root) {
787
    var array;
788
    var response;
789
    var ack;
790
    var productId;
791
    var i;
792
    var currentPrice;
793
    var Title = "";
794
    var noLower;
795
    var noActive;
796
    var minPrice;
797
    var maxPrice;
798
    var conditionId;
799
    var currentConditionId;
800
    var noBetterCondition;
801
    var myPrice;
802
    var currentPriceInt;
803
    var minBetterCondition;
804
    var betterConditionbBreakdown = [];
805
    var sameConditionbBreakdown = [];
806
 
807
    if (root.findItemsAdvancedResponse !== undefined) {
808
        response = root.findItemsAdvancedResponse[0];
809
    } else if (root.findItemsByProductResponse !== undefined) {
810
        response = root.findItemsByProductResponse[0];
811
    } else {
812
        --productsToPrice;
813
        ++productsPriced;
814
        updateProgressBar(maxProductsToPrice, productsPriced);
815
        return;
816
    }
817
 
818
    ack = response.ack;
819
    if (ack != 'Success') {
4 - 820
        printeBayAPIError('Get Prices', response);
2 - 821
 
822
        if (ack == 'Failure' || ack == 'PartialFailure') {
823
            --productsToPrice;
824
            ++productsPriced;
825
            updateProgressBar(maxProductsToPrice, productsPriced);
826
            return;
827
        }
828
    }
829
 
830
    if (root.findItemsAdvancedResponse !== undefined) {
831
        array = typeof root.findItemsAdvancedResponse[0] != 'object' ? JSON.parse(root.findItemsAdvancedResponse[0]) : root.findItemsAdvancedResponse[0].searchResult[0].item;
832
        response = root.findItemsAdvancedResponse[0];
833
        url = new URL(response.itemSearchURL);
834
        productId = url.searchParams.get("_nkw");
835
    } else {
836
        array = typeof root.findItemsByProductResponse[0] != 'object' ? JSON.parse(root.findItemsByProductResponse[0]) : root.findItemsByProductResponse[0].searchResult[0].item;
837
        url = new URL(response.itemSearchURL);
838
        productId = url.searchParams.get("_productid");
839
    }
840
 
841
    var items = response.searchResult[0].item || [];
842
    noActive = Number(document.getElementById('Active' + productId).innerHTML);
843
    noLower = Number(document.getElementById('Lower' + productId).innerHTML);
844
    myPrice = Number(document.getElementById('Price' + productId).innerHTML.substr(1));
845
    minPrice = Number(document.getElementById('Minimum' + productId).innerHTML.substr(1));
846
    maxPrice = Number(document.getElementById('Maximum' + productId).innerHTML.substr(1));
847
    conditionId = Number(document.getElementById('Condition' + productId).innerHTML);
848
    noBetterCondition = Number(document.getElementById('BetterCondition' + productId).innerHTML);
849
    minBetterCondition = Number(document.getElementById('MinBetterCondition' + productId).innerHTML);
850
    betterConditionbBreakdown = JSON.parse(document.getElementById('BetterConditionBreakdown' + productId).innerHTML);
851
    sameConditionbBreakdown = JSON.parse(document.getElementById('SameConditionBreakdown' + productId).innerHTML);
852
 
853
    for (i = 0; i < items.length; i++) {
854
        Title = items[i].title[0].toLowerCase();
855
        if (Title.includes("disc only") > 0 ||
856
            Title.includes("disk only") > 0 ||
857
            Title.includes("only disc") > 0 ||
858
            Title.includes("only disk") > 0 ||
859
            Title.search(/dis[ck].*only/) > 0) {
860
            continue; // exclude "disc only listing
861
        }
862
 
863
        currentConditionId = (items[i].condition === undefined ? 0 : Number(items[i].condition[0].conditionId));
864
        currentPrice = Number(items[i].sellingStatus[0].convertedCurrentPrice[0].__value__);
865
        currentPriceInt = Math.ceil(currentPrice);
866
 
867
        if (currentConditionId > conditionId) {
868
            continue; // Like for like conditions only
869
        } else if (currentConditionId > conditionId) {
870
            if (minBetterCondition < 0.01 || minBetterCondition > currentPrice) {
871
                minBetterCondition = currentPrice;
872
            }
873
 
874
            ++noBetterCondition;
875
        }
876
 
877
        if (items[i].sellingStatus[0].bidCount === 0 && items[i].listingInfo[0].convertedBuyItNowPrice !== undefined) {
878
            currentPrice = Number(items[i].listingInfo[0].convertedBuyItNowPrice[0].__value__);
879
        }
880
 
881
        if (items[i].shippingInfo[0].shippingServiceCost) {
882
            currentPrice += Number(items[i].shippingInfo[0].shippingServiceCost[0].__value__);
883
        }
884
 
885
        if (currentConditionId > conditionId) {
886
            if (betterConditionbBreakdown[currentPriceInt] === undefined) {
887
                betterConditionbBreakdown[currentPriceInt] = 0;
888
            }
889
            ++betterConditionbBreakdown[currentPriceInt];
890
        } else {
891
            if (sameConditionbBreakdown[currentPriceInt] === undefined) {
892
                sameConditionbBreakdown[currentPriceInt] = 0;
893
            }
894
            ++sameConditionbBreakdown[currentPriceInt];
895
        }
896
 
897
        if (currentPrice < myPrice) {
898
            ++noLower;
899
        }
900
 
901
        if (minPrice < 0.01 || minPrice > currentPrice) {
902
            minPrice = currentPrice;
903
        }
904
 
905
        if (maxPrice < 0.01 || maxPrice < currentPrice) {
906
            maxPrice = currentPrice;
907
        }
908
 
909
        ++noActive;
910
    }
911
 
912
    document.getElementById('Active' + productId).innerHTML = noActive;
913
    document.getElementById('Lower' + productId).innerHTML = noLower;
914
    document.getElementById('Minimum' + productId).innerHTML = '$' + minPrice.toFixed(2);
915
    document.getElementById('Maximum' + productId).innerHTML = '$' + maxPrice.toFixed(2);
916
    document.getElementById('BetterCondition' + productId).innerHTML = noBetterCondition;
917
    document.getElementById('MinBetterCondition' + productId).innerHTML = minBetterCondition;
918
    document.getElementById('BetterConditionBreakdown' + productId).innerHTML = JSON.stringify(betterConditionbBreakdown);
919
    document.getElementById('SameConditionBreakdown' + productId).innerHTML = JSON.stringify(sameConditionbBreakdown);
920
 
921
    if (Number(response.paginationOutput[0].totalPages) > Number(response.paginationOutput[0].pageNumber)) {
922
        ++productsToPrice;
923
        ++maxProductsToPrice;
924
        var row = document.getElementById('Lower' + productId).parentNode.rowIndex;
925
        findProductPrices(document.getElementById("itemTable").rows[row].cells[4].innerText, Number(response.paginationOutput[0].pageNumber) + 1);
926
    }
927
 
928
    --productsToPrice;
929
    ++productsPriced;
930
    updateProgressBar(maxProductsToPrice, productsPriced);
931
}
932
 
933
function changePrice(itemId) {
934
    var i;
935
    var newPrice = parseFloat(document.getElementById('PriceAdj' + itemId).value).toFixed(2);
936
 
937
    if (isNaN(newPrice) || newPrice < configAdjMinPrice) {
938
        document.getElementById('PriceAdj' + itemId).value = '';
939
        return;
940
    }
941
 
942
    document.getElementById('PriceAdj' + itemId).value = newPrice;
943
 
944
    if (eBayAuthTokenFlag === false) {
945
        return;
946
    }
947
 
948
    var xw = new XMLWriter('UTF-8', '1.0');
949
    var xhr = new XMLHttpRequest();
950
 
951
    if (!createAddXML(xw, xhr, 'ReviseItemRequest', 'ReviseItem', itemId, newPrice)) {
952
        return;
953
    }
954
 
955
    xml = xw.flush();
956
    xw.close();
957
 
958
    xhr.onload = function() {
19 - 959
        var jsonObj = XMLparse(xhr.responseXML, false);
960
        var obj = jsonObj.ReviseItemResponse;
2 - 961
        var returnCode = obj.Ack;
19 - 962
        var str = "";
2 - 963
 
964
        var x = document.getElementById("results");
965
        if (x.className.indexOf("w3-show") == -1) {
966
            x.className += " w3-show";
967
        }
968
        x.className = x.className.replace(" process-errors", "");
969
 
970
        if (returnCode == 'Success' || (returnCode == 'Warning' && (obj.Errors.ErrorCode == '21917108' || obj.Errors.ErrorCode == '23007'))) {
971
            document.getElementById('PriceAdj' + itemId).style.color = "green";
972
 
19 - 973
            str = '<p><strong>' + returnCode + '</strong></p>';
2 - 974
 
975
            if (returnCode == 'Warning') {
19 - 976
                str += "<p>" + obj.Errors.SeverityCode + " (" + obj.Errors.ErrorCode + "): " + escapeHtml(obj.Errors.LongMessage) + "</p>";
2 - 977
                x.className += " process-errors";
978
            }
19 - 979
            var fees = getJsonArray(obj.Fees.Fee);
980
            str += "<p>";
2 - 981
            for (i = 0; i < fees.length; i++) {
982
                if (fees[i].Fee.text !== "0.0") {
19 - 983
                    str += fees[i].Name + ": $" + Number(fees[i].Fee.text).toFixed(2) + "<br/>";
2 - 984
                }
985
            }
19 - 986
            str += "</p>";
2 - 987
 
988
            if (obj.DiscountReason) {
19 - 989
                str += "<p>Discount Reason: " + obj.DiscountReason + "</p>";
2 - 990
            }
991
 
30 - 992
            if (obj.ListingRecommendations !== undefined) {
993
                var recommendations = getJsonArray(obj.ListingRecommendations.Recommendation);
994
                for (i = 0; i < recommendations.length; i++) {
995
                    str += decode(recommendations[i]);
996
                }
2 - 997
            }
19 - 998
 
999
            x.innerHTML = str;
2 - 1000
        } else {
1001
            document.getElementById('PriceAdj' + itemId).style.color = "red";
19 - 1002
            str = "<p><strong>" + returnCode + ":</strong></p>";
2 - 1003
            x.className += " process-errors";
1004
 
6 - 1005
            var errors = getJsonArray(obj.Errors);
19 - 1006
            str += "<p>";
6 - 1007
            for (i = 0; i < errors.length; i++) {
19 - 1008
                str += errors[i].SeverityCode + " (" + errors[i].ErrorCode + "): " + escapeHtml(errors[i].LongMessage) + "<br/>";
2 - 1009
            }
19 - 1010
            str += "</p>";
1011
            x.innerHTML = str;
2 - 1012
        }
1013
 
1014
        if (obj.Message) {
1015
            x.innerHTML += obj.Message;
1016
        }
1017
 
1018
        if (!x.className.includes("process-errors")) {
1019
            setTimeout(function() {
1020
                x.className = x.className.replace(" w3-show", "");
1021
            }, 3000);
1022
        }
1023
    };
1024
 
1025
    xhr.send(xml);
1026
}
1027
 
1028
function createAddXML(xw, xhr, xmlrequest, callname, itemId, newPrice) {
1029
    xw.writeStartDocument();
1030
    xw.writeStartElement(xmlrequest);
1031
    xw.writeAttributeString('xmlns', 'urn:ebay:apis:eBLBaseComponents');
1032
 
1033
    xw.writeStartElement('RequesterCredentials');
1034
    xw.writeElementString('eBayAuthToken', eBayAuthToken);
1035
    xw.writeEndElement(); /* RequesterCredentials */
1036
 
1037
    xw.writeStartElement('Item');
1038
 
1039
    xw.writeStartElement('StartPrice');
1040
    xw.writeAttributeString('currencyID', 'USD');
1041
    xw.writeString(newPrice);
1042
    xw.writeEndElement(); /* StartPrice */
1043
 
1044
    //xw.writeElementString('ItemID', itemId);
1045
    xw.writeString('<ItemID>' + itemId + '</ItemID>');
1046
 
1047
    if (document.getElementById('BestOffer' + itemId).innerHTML == 'true') {
1048
        if (newPrice >= 14.99) {
1049
            var autoAcceptPrice = newPrice * configAutoAcceptPrice;
1050
            var minBestOfferPrice = newPrice * configMinBestOfferPrice;
1051
 
1052
            xw.writeStartElement('BestOfferDetails');
1053
            xw.writeElementString('BestOfferEnabled', 'true');
1054
            xw.writeEndElement(); /* BestOfferDetails */
1055
            xw.writeStartElement('ListingDetails');
1056
            xw.writeStartElement('BestOfferAutoAcceptPrice');
1057
            xw.writeAttributeString('currencyID', 'USD');
1058
            xw.writeString(autoAcceptPrice.toFixed(2));
1059
            xw.writeEndElement(); /* BestOfferAutoAcceptPrice */
1060
            xw.writeStartElement('MinimumBestOfferPrice');
1061
            xw.writeAttributeString('currencyID', 'USD');
1062
            xw.writeString(minBestOfferPrice.toFixed(2));
1063
            xw.writeEndElement(); /* MinimumBestOfferPrice */
1064
            xw.writeEndElement(); /* ListingDetails */
1065
        } else {
1066
            xw.writeStartElement('BestOfferDetails');
1067
            xw.writeElementString('BestOfferEnabled', 'false');
1068
            xw.writeEndElement(); /* BestOfferDetails */
1069
        }
1070
    }
1071
 
1072
    xw.writeEndElement(); /* Item */
1073
 
1074
    xw.writeElementString('ErrorLanguage', 'en_US');
1075
    xw.writeElementString('Version', configeBayTradingVersion);
1076
    xw.writeElementString('WarningLevel', configWarningLevel);
1077
 
1078
    xw.writeEndElement(); /* xmlrequest */
1079
    xw.writeEndDocument();
1080
 
1081
    xhr.open('POST', configProxyUrl, true);
1082
    xhr.setRequestHeader('Content-Type', 'text/xml');
1083
    xhr.setRequestHeader('X-EBAY-API-APP-NAME', configAppid);
1084
    xhr.setRequestHeader('X-EBAY-API-COMPATIBILITY-LEVEL', configeBayTradingVersion);
1085
    xhr.setRequestHeader('X-EBAY-API-CALL-NAME', callname);
1086
    xhr.setRequestHeader('X-EBAY-API-SITEID', '0');
1087
    xhr.setRequestHeader('X-EBAY-API-DEV-NAME', '');
1088
    xhr.setRequestHeader('X-EBAY-API-CERT-NAME', '');
1089
    xhr.setRequestHeader('X-Proxy-URL', configServiceEndpoint);
1090
 
1091
    return true;
1092
}
1093
 
1094
function connected() {
1095
    var x;
1096
 
1097
    eBayAuthTokenFlag = true;
1098
    document.getElementById("connected").innerHTML += " (Connected)";
1099
 
1100
    x = document.getElementById("login");
1101
    x.className = x.className.replace(" w3-show", "");
1102
 
1103
    x = document.getElementById("results");
1104
    x.innerHTML = "";
1105
    x.className = x.className.replace(" w3-show", "");
1106
}
1107
 
1108
    </script>
17 - 1109
    <script>includeHTML();</script>
2 - 1110
 
1111
</body>
1112
</html>