update: bump 'common' version to 0.1.18
This commit is contained in:
+10
-17
@@ -130,12 +130,10 @@
|
|||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { default as $, Rpc2, LogRecord } from '/';
|
import { default as $, Rpc2, LogRecord } from '/';
|
||||||
if (performance.getEntriesByType('navigation')[0].type === 'reload') await Rpc2.invoke('exit');
|
if (performance.getEntriesByType('navigation')[0].type === 'reload') await Rpc2.notify('exit');
|
||||||
|
|
||||||
let error = null;
|
|
||||||
let status = null;
|
|
||||||
let { profiles, parameters } = await Rpc2.invoke('context');
|
let { profiles, parameters } = await Rpc2.invoke('context');
|
||||||
|
let status = null;
|
||||||
let date = new Date();
|
let date = new Date();
|
||||||
let day = date.getDay() || 7;
|
let day = date.getDay() || 7;
|
||||||
$('#datefrom').valueAsNumber = date.setHours(-24 * (day - 1)) - date.getTimezoneOffset() * 60 * 1000;
|
$('#datefrom').valueAsNumber = date.setHours(-24 * (day - 1)) - date.getTimezoneOffset() * 60 * 1000;
|
||||||
@@ -160,7 +158,7 @@ $.set('#begin', 'click', async () => {
|
|||||||
parameters[element.id] = element.valueAsNumber;
|
parameters[element.id] = element.valueAsNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
await Rpc2.invoke('begin', options, parameters);
|
await Rpc2.invoke('begin', { params: [options, parameters] });
|
||||||
break;
|
break;
|
||||||
case 'RUNNING':
|
case 'RUNNING':
|
||||||
await Rpc2.invoke('pause');
|
await Rpc2.invoke('pause');
|
||||||
@@ -180,12 +178,12 @@ $.set('#begin', 'click', () => {
|
|||||||
|
|
||||||
$.set('#cancel', 'click', async () => {
|
$.set('#cancel', 'click', async () => {
|
||||||
$('#cancel').disabled = true;
|
$('#cancel').disabled = true;
|
||||||
await Rpc2.invoke('cancel');
|
await Rpc2.notify('cancel');
|
||||||
});
|
});
|
||||||
|
|
||||||
$.set('#skip', 'click', async () => {
|
$.set('#skip', 'click', async () => {
|
||||||
$('#skip').disabled = true;
|
$('#skip').disabled = true;
|
||||||
await Rpcs.invoke('skip');
|
await Rpc2.notify('skip');
|
||||||
});
|
});
|
||||||
|
|
||||||
$.set('#logs', 'change', (e) => {
|
$.set('#logs', 'change', (e) => {
|
||||||
@@ -219,12 +217,12 @@ for (let item of $.all("input[type='number']")) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (await new Promise(o => setTimeout(o, 1000, true))) {
|
while (await new Promise(o => setTimeout(o, 1000, true))) {
|
||||||
let history = await Rpc2.invoke('history').catch(() => []);
|
let history = await Rpc2.invoke('logs').catch(() => []);
|
||||||
let logs = Array.from(history);
|
let logs = Array.from(history);
|
||||||
|
|
||||||
for (let record of logs) {
|
for (let record of logs) {
|
||||||
if ($('#messages').childNodes.length >= 500) $('#messages').childNodes.item(0)?.remove();
|
if ($('#messages').childNodes.length >= 500) $('#messages').childNodes.item(0)?.remove();
|
||||||
if (record.levelno >= 40) error = record;
|
if (record.levelno >= 40) alert(`(${record.levelname}) ` + [record.msg, record.exc_text].filter(Boolean).join('\n'));
|
||||||
let message = LogRecord.format(record);
|
let message = LogRecord.format(record);
|
||||||
let node = document.createTextNode(new String(message).concat('\n'));
|
let node = document.createTextNode(new String(message).concat('\n'));
|
||||||
$('#messages').appendChild(node);
|
$('#messages').appendChild(node);
|
||||||
@@ -247,22 +245,17 @@ while (await new Promise(o => setTimeout(o, 1000, true))) {
|
|||||||
$('#begin > span.text').innerText = 'Pause';
|
$('#begin > span.text').innerText = 'Pause';
|
||||||
$('#begin').classList.add('pulse');
|
$('#begin').classList.add('pulse');
|
||||||
|
|
||||||
let progress = await Rpc2.invoke('progress').catch(() => new Object());
|
let { task, number, index, limit } = await Rpc2.invoke('progress').catch(() => new Object());
|
||||||
let { task, number, index, limit } = progress;
|
|
||||||
$('#numberLabel').innerText = number ?? '';
|
$('#numberLabel').innerText = number ?? '';
|
||||||
$('#progressLabel').innerText = limit ? `${task}, ${parseFloat((index / limit * 100).toFixed(2))}% (${index}/${limit})` : task;
|
$('#progressLabel').innerText = limit ? `${task} — ${parseFloat((index / limit * 100).toFixed(2))}% (${index}/${limit})` : task;
|
||||||
|
|
||||||
let [t1, t2] = await Rpc2.invoke('uptime').catch(() => []);
|
let [t1, t2] = await Rpc2.invoke('uptime').catch(() => []);
|
||||||
$('#uptimeLabel').innerText = Temporal.Duration.from({ seconds: t1 ?? 0 }).round({ largestUnit: 'hours' }).toLocaleString('en', { style: 'digital' });
|
$('#uptimeLabel').innerText = Temporal.Duration.from({ seconds: t1 ?? 0 }).round({ largestUnit: 'hours' }).toLocaleString('en', { style: 'digital' });
|
||||||
|
|
||||||
let remaining = index && limit && t2 ? Math.floor((limit - index) / (index / t2)) : 0;
|
let remaining = index && limit && t2 ? Math.floor((limit - index) / (index / t2)) : 0;
|
||||||
$('#remainingLabel').innerHTML = remaining ? Temporal.Duration.from({ seconds: remaining }).round({ largestUnit: 'hours' }).toLocaleString('en') : '';
|
$('#remainingLabel').innerText = remaining > 0 ? Temporal.Duration.from({ seconds: remaining }).round({ largestUnit: 'hours' }).toLocaleString('en') : '';
|
||||||
break;
|
break;
|
||||||
case 'STANDBY':
|
case 'STANDBY':
|
||||||
if (error !== null) {
|
|
||||||
alert(`(${error.levelname}) ${error.msg}\n${error.exc_text ?? ''}`);
|
|
||||||
error = null;
|
|
||||||
}
|
|
||||||
$('#begin > span.text').innerText = 'Resume';
|
$('#begin > span.text').innerText = 'Resume';
|
||||||
$('#begin').classList.remove('pulse');
|
$('#begin').classList.remove('pulse');
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import unicodedata
|
|
||||||
import argparse
|
import argparse
|
||||||
import openpyxl
|
import openpyxl
|
||||||
import logging
|
import logging
|
||||||
@@ -20,7 +19,7 @@ from enum import Enum
|
|||||||
from wakepy import keep
|
from wakepy import keep
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from itertools import repeat, count
|
from itertools import count
|
||||||
from urllib3 import PoolManager
|
from urllib3 import PoolManager
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="Order Import")
|
parser = argparse.ArgumentParser(description="Order Import")
|
||||||
@@ -45,8 +44,8 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
class Status(Enum):
|
class Status(Enum):
|
||||||
IDLE = 0
|
IDLE = 0
|
||||||
READY = 1
|
READY = 1
|
||||||
RUNNING = 3
|
RUNNING = 2
|
||||||
STANDBY = 4
|
STANDBY = 3
|
||||||
|
|
||||||
class Profile:
|
class Profile:
|
||||||
def __init__(self, name, subdomain, token, remise, person=None, prefix=None, suffix=None):
|
def __init__(self, name, subdomain, token, remise, person=None, prefix=None, suffix=None):
|
||||||
@@ -88,9 +87,7 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
t1.start()
|
t1.start()
|
||||||
t2.start()
|
t2.start()
|
||||||
|
|
||||||
sp.set('begin', begin)
|
sp.add(begin, pause, resume)
|
||||||
sp.set('pause', pause)
|
|
||||||
sp.set('resume', resume)
|
|
||||||
sp.set('status', lambda: status.name)
|
sp.set('status', lambda: status.name)
|
||||||
sp.set('uptime', lambda: [t1.delta()])
|
sp.set('uptime', lambda: [t1.delta()])
|
||||||
|
|
||||||
@@ -120,7 +117,7 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
|
|
||||||
setup(driver, parameters)
|
setup(driver, parameters)
|
||||||
until(lambda x: 'loginProgress' in x.find_element(By.TAG_NAME, "body").get_attribute('class'), watch=False)
|
until(lambda x: 'loginProgress' in x.find_element(By.TAG_NAME, "body").get_attribute('class'), watch=False)
|
||||||
logger.info('Waiting for authentication to complete...')
|
logger.info('Waiting for authentication...')
|
||||||
|
|
||||||
if (account := parameters['account']) and (password := parameters['password']):
|
if (account := parameters['account']) and (password := parameters['password']):
|
||||||
try:
|
try:
|
||||||
@@ -186,8 +183,8 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
p = ProductInfo(file)
|
p = ProductInfo(file)
|
||||||
driver.close()
|
driver.close()
|
||||||
driver.switch_to.window(driver.window_handles[0])
|
driver.switch_to.window(driver.window_handles[0])
|
||||||
status = Status.READY
|
|
||||||
logger.info('Done')
|
logger.info('Done')
|
||||||
|
status = Status.READY
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.critical('Unable to load products', exc_info=e)
|
logger.critical('Unable to load products', exc_info=e)
|
||||||
return 4
|
return 4
|
||||||
@@ -200,7 +197,7 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
return result
|
return result
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning('Error while fetching data from %s, retrying... (%d)', url, attempt, exc_info=e)
|
logger.warning('Error while fetching data from %s, retrying... (%d)', url, attempt, exc_info=e)
|
||||||
assert attempt < retry
|
assert attempt < retry, "Exceeded maximum retry attempts"
|
||||||
|
|
||||||
class Wait(Action):
|
class Wait(Action):
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -247,18 +244,13 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
raise cls
|
raise cls
|
||||||
|
|
||||||
flow = ActionFlow()
|
flow = ActionFlow()
|
||||||
flow.append(Wait)
|
flow.stage(Wait, Sleep, Cancel, Skip)
|
||||||
flow.append(Sleep)
|
|
||||||
flow.append(Cancel)
|
|
||||||
flow.append(Skip)
|
|
||||||
|
|
||||||
profile = None
|
profile = None
|
||||||
progress = { 'task': '' }
|
progress = { 'task': '' }
|
||||||
selection = 0
|
selection = 0
|
||||||
|
|
||||||
|
sp.add(pairs=[ (k.lower(), v) for k, v in flow ])
|
||||||
sp.set('actions', lambda: flow.capabilities())
|
sp.set('actions', lambda: flow.capabilities())
|
||||||
sp.set('cancel', lambda: flow.queue(Cancel))
|
|
||||||
sp.set('skip', lambda: flow.queue(Skip))
|
|
||||||
sp.set('progress', lambda: progress)
|
sp.set('progress', lambda: progress)
|
||||||
|
|
||||||
while not flow.react(Wait):
|
while not flow.react(Wait):
|
||||||
@@ -303,7 +295,7 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
logger.info('Profile selected: %s', profile.name)
|
logger.info('Profile selected: %s', profile.name)
|
||||||
logger.info('Date from %s to %s', df, dt)
|
logger.info('Date from %s to %s', df, dt)
|
||||||
flow.allow(Cancel)
|
flow.allow(Cancel)
|
||||||
flow.allow(Skip, False)
|
flow.deter(Skip)
|
||||||
|
|
||||||
for page in count(1):
|
for page in count(1):
|
||||||
try:
|
try:
|
||||||
@@ -388,17 +380,17 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
if 'error' in (category := fetch(f'{base}/categories/{o}.json?api_token={profile.token}')):
|
if 'error' in (category := fetch(f'{base}/categories/{o}.json?api_token={profile.token}')):
|
||||||
error = category['error']
|
error = category['error']
|
||||||
code = category['code']
|
code = category['code']
|
||||||
logger.warning("Error while fetching 'category' (code: %s, message: %s); skipping", code, error)
|
logger.warning("Error while fetching field 'category' (code: %s, message: %s); skipping", code, error)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if (client := clients.get(o := item['client_id'])) is None:
|
if (client := clients.get(o := item['client_id'])) is None:
|
||||||
if 'error' in (client := fetch(f'{base}/clients/{o}.json?api_token={profile.token}')):
|
if 'error' in (client := fetch(f'{base}/clients/{o}.json?api_token={profile.token}')):
|
||||||
error = client['error']
|
error = client['error']
|
||||||
code = client['code']
|
code = client['code']
|
||||||
logger.warning("Error while fetching 'client' (code: %s, message: %s); skipping", code, error)
|
logger.warning("Error while fetching field 'client' (code: %s, message: %s); skipping", code, error)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
identity = client['external_id'] if client['company'] else profile.person
|
identity = client['shortcut'] if client['company'] else profile.person
|
||||||
date: str = item['issue_date']
|
date: str = item['issue_date']
|
||||||
kind: str = item['kind']
|
kind: str = item['kind']
|
||||||
total = float(item['price_net'])
|
total = float(item['price_net'])
|
||||||
@@ -453,7 +445,7 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
try:
|
try:
|
||||||
filename = f'Order-Import-{profile.name}-{datetime.now().strftime('%Y%m%d-%H%M%S-%f')}.xlsx'
|
filename = f'Order-Import-{profile.name}-{datetime.now().strftime('%Y%m%d-%H%M%S-%f')}.xlsx'
|
||||||
file = Path(parameters['directory']).joinpath(filename)
|
file = Path(parameters['directory']).joinpath(filename)
|
||||||
logger.info('Saving excel file to %s', str(file))
|
logger.info('Saving document at %s', str(file))
|
||||||
flow.react(Wait)
|
flow.react(Wait)
|
||||||
workbook.save(file)
|
workbook.save(file)
|
||||||
except Skip:
|
except Skip:
|
||||||
@@ -461,12 +453,12 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
except Cancel:
|
except Cancel:
|
||||||
continue
|
continue
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Error while saving excel file', exc_info=e)
|
logger.error('Error while saving document', exc_info=e)
|
||||||
status = Status.STANDBY
|
status = Status.STANDBY
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
logger.info('Uploading...')
|
logger.info('Uploading data...')
|
||||||
progress.clear()
|
progress.clear()
|
||||||
progress['task'] = 'Task 3 of 4'
|
progress['task'] = 'Task 3 of 4'
|
||||||
t2.clear()
|
t2.clear()
|
||||||
@@ -477,29 +469,26 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
click(".product-import-img-box .import-img-radio:nth-child(2) .mm-radio-group > label:nth-child(2) .mm-radio-input", condition=None)
|
click(".product-import-img-box .import-img-radio:nth-child(2) .mm-radio-group > label:nth-child(2) .mm-radio-input", condition=None)
|
||||||
click(".product-import-img-box .mm-selector-rendered")
|
click(".product-import-img-box .mm-selector-rendered")
|
||||||
click(".mm-outside.mm-select-dropdown ul li:nth-child(%d) span" % (1 if options.get('draft') else 6))
|
click(".mm-outside.mm-select-dropdown ul li:nth-child(%d) span" % (1 if options.get('draft') else 6))
|
||||||
|
|
||||||
flow.react(Wait)
|
|
||||||
locate(".big-file-upload input", wait=False).send_keys(str(file))
|
locate(".big-file-upload input", wait=False).send_keys(str(file))
|
||||||
click(".product-import-img-footer button")
|
click(".product-import-img-footer button")
|
||||||
click(".product-import-img-footer button.mm-button__primary")
|
|
||||||
|
|
||||||
while True:
|
while not flow.react(Wait, Sleep):
|
||||||
try:
|
try:
|
||||||
innerText = driver.find_element(By.CSS_SELECTOR, ".img-box-result-title").get_attribute('innerText')
|
err = locate(".mm-tbody table tbody tr:nth-child(1) td:nth-child(5) .okki-space-item:nth-child(1) button", wait=False)
|
||||||
if innerText == '导入完成': break
|
ok = locate(".mm-tbody table tbody tr:nth-child(1) td:nth-child(3) a", wait=False)
|
||||||
except:
|
break
|
||||||
flow.react(Sleep)
|
except: pass
|
||||||
|
try: click(".product-import-img-footer button.mm-button__primary", wait=False)
|
||||||
click(".mm-notification-container .mm-icon-close")
|
except: pass
|
||||||
click(".product-import-img-footer button.mm-button__primary")
|
try: click(".list-header-wrap button", wait=False)
|
||||||
err = locate(".mm-tbody table tbody tr:nth-child(1) td:nth-child(5) .okki-space-item:nth-child(1) button")
|
except: pass
|
||||||
|
|
||||||
if err.get_attribute('disabled') is None:
|
if err.get_attribute('disabled') is None:
|
||||||
logger.warning('Incomplete import detected; downloaded 1 related document')
|
click(err, condition=None)
|
||||||
err.click()
|
logger.warning('Incomplete import detected; downloading 1 related document')
|
||||||
flow.react(Sleep)
|
flow.react(Sleep)
|
||||||
|
|
||||||
click(".mm-tbody table tbody tr:nth-child(1) td:nth-child(3) a")
|
click(ok, condition=None)
|
||||||
flow.react(Sleep)
|
flow.react(Sleep)
|
||||||
logger.info('Done')
|
logger.info('Done')
|
||||||
except Skip:
|
except Skip:
|
||||||
@@ -507,7 +496,7 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
except Cancel:
|
except Cancel:
|
||||||
continue
|
continue
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Error while uploading excel file', exc_info=e)
|
logger.error('Error while uploading document', exc_info=e)
|
||||||
status = Status.STANDBY
|
status = Status.STANDBY
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -542,6 +531,7 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
while index < len(data):
|
while index < len(data):
|
||||||
try:
|
try:
|
||||||
attempts += 1
|
attempts += 1
|
||||||
|
if len(driver.window_handles) > 3: driver.close()
|
||||||
driver.switch_to.window(driver.window_handles[2])
|
driver.switch_to.window(driver.window_handles[2])
|
||||||
item = data[index]
|
item = data[index]
|
||||||
kind = item['kind']
|
kind = item['kind']
|
||||||
@@ -551,21 +541,16 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
opportunity = None
|
opportunity = None
|
||||||
|
|
||||||
if kind != 'vat':
|
if kind != 'vat':
|
||||||
logger.info('[%d/%d] Skipping %s', index+1, len(data), number)
|
logger.info('[%d/%d] Undesired invoice type; skipping %s', index+1, len(data), number)
|
||||||
index += 1
|
raise Skip()
|
||||||
attempts = 0
|
|
||||||
continue
|
|
||||||
|
|
||||||
if attempts > parameters['attempts']:
|
if attempts > parameters['attempts']:
|
||||||
logger.warning('Exhausted all allowed attempts; skipping %s', number)
|
logger.warning('Exhausted all allowed attempts; skipping %s', number)
|
||||||
index += 1
|
raise Skip()
|
||||||
attempts = 0
|
|
||||||
continue
|
|
||||||
|
|
||||||
progress['number'] = number
|
progress['number'] = number
|
||||||
progress['index'] = index
|
progress['index'] = index
|
||||||
flow.allow(Cancel)
|
flow.allow(Skip, Cancel)
|
||||||
flow.allow(Skip)
|
|
||||||
flow.react(Wait)
|
flow.react(Wait)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -597,17 +582,11 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
flow.react(Wait)
|
flow.react(Wait)
|
||||||
click(".sticky .okki-space-item:nth-child(1) button")
|
click(".sticky .okki-space-item:nth-child(1) button")
|
||||||
break
|
break
|
||||||
except Skip:
|
|
||||||
index += 1
|
|
||||||
attempts = 0
|
|
||||||
continue
|
|
||||||
except Cancel:
|
|
||||||
break
|
|
||||||
except NoSuchElementException:
|
except NoSuchElementException:
|
||||||
logger.warning("Could not find invoice '%s'; skipping", number)
|
logger.warning("Could not find invoice '%s'; skipping", number)
|
||||||
index += 1
|
raise Skip()
|
||||||
attempts = 0
|
except Action as e:
|
||||||
continue
|
raise e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error while looking up invoice '%s'", number, exc_info=e)
|
logger.error("Error while looking up invoice '%s'", number, exc_info=e)
|
||||||
status = Status.STANDBY
|
status = Status.STANDBY
|
||||||
@@ -638,16 +617,12 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
cell = locate(".virtual-list-wrap .vue-recycle-scroller .row-item > .cell:nth-child(3) .ow-serial-read-pretty_ellipsis", wait=False)
|
cell = locate(".virtual-list-wrap .vue-recycle-scroller .row-item > .cell:nth-child(3) .ow-serial-read-pretty_ellipsis", wait=False)
|
||||||
if cell.text != match: continue
|
if cell.text != match: continue
|
||||||
link = locate(".virtual-list-wrap .vue-recycle-scroller .row-item > .cell:nth-child(6) a", wait=False)
|
link = locate(".virtual-list-wrap .vue-recycle-scroller .row-item > .cell:nth-child(6) a", wait=False)
|
||||||
opportunity = unicodedata.normalize('NFKD', link.get_attribute('title'))
|
opportunity = link.text
|
||||||
break
|
break
|
||||||
except Skip:
|
|
||||||
index += 1
|
|
||||||
attempts = 0
|
|
||||||
continue
|
|
||||||
except Cancel:
|
|
||||||
break
|
|
||||||
except NoSuchElementException:
|
except NoSuchElementException:
|
||||||
logger.warning("Could not find opportunity '%s'; skipping", match)
|
logger.warning("Could not find opportunity '%s'", match)
|
||||||
|
except Action as e:
|
||||||
|
raise e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error while looking up opportunity '%s'", match, exc_info=e)
|
logger.error("Error while looking up opportunity '%s'", match, exc_info=e)
|
||||||
status = Status.STANDBY
|
status = Status.STANDBY
|
||||||
@@ -659,24 +634,29 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
if opportunity is not None:
|
if opportunity is not None:
|
||||||
try:
|
try:
|
||||||
flow.react(Wait)
|
flow.react(Wait)
|
||||||
|
label = locate("label.paas-form-item-label")
|
||||||
dropdown = locate("#rc_select_1")
|
dropdown = locate("#rc_select_1")
|
||||||
dropdown.clear()
|
|
||||||
dropdown.send_keys(opportunity)
|
|
||||||
|
|
||||||
menu = locate(".okki-select-dropdown")
|
for iteration in count(1):
|
||||||
menuitems = menu.find_elements(By.CSS_SELECTOR, ".rc-virtual-list-holder-inner > div")
|
dropdown.click()
|
||||||
|
dropdown.clear()
|
||||||
|
dropdown.send_keys(opportunity)
|
||||||
|
menu = locate(".okki-select-dropdown")
|
||||||
|
menuitems = menu.find_elements(By.CSS_SELECTOR, ".rc-virtual-list-holder-inner > div")
|
||||||
|
|
||||||
for menuitem in menuitems:
|
try:
|
||||||
if menuitem.get_attribute('label').strip().startswith(opportunity):
|
for menuitem in menuitems:
|
||||||
click(menuitem)
|
if menuitem.get_attribute('label') == opportunity:
|
||||||
except Skip:
|
click(menuitem)
|
||||||
index += 1
|
raise StopIteration()
|
||||||
attempts = 0
|
except StopIteration: break
|
||||||
continue
|
except: pass
|
||||||
except Cancel:
|
assert iteration < parameters['attempts'], "Exceeded maximum retry attempts"
|
||||||
break
|
click(label, condition=None)
|
||||||
|
except Action as e:
|
||||||
|
raise e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning('Could not select opportunity; skipping', exc_info=e)
|
logger.warning("Could not select opportunity '%s'", opportunity, exc_info=e)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pagination = 10
|
pagination = 10
|
||||||
@@ -730,12 +710,8 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
raise Exception('Product list imcomplete; expected %d, got %d' % (len(positions), len(ids)))
|
raise Exception('Product list imcomplete; expected %d, got %d' % (len(positions), len(ids)))
|
||||||
flow.react(Wait)
|
flow.react(Wait)
|
||||||
click(button)
|
click(button)
|
||||||
except Skip:
|
except Action as e:
|
||||||
index += 1
|
raise e
|
||||||
attempts = 0
|
|
||||||
continue
|
|
||||||
except Cancel:
|
|
||||||
break
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Error while modifying invoice', exc_info=e)
|
logger.error('Error while modifying invoice', exc_info=e)
|
||||||
status = Status.STANDBY
|
status = Status.STANDBY
|
||||||
@@ -745,30 +721,24 @@ def main(driver: WebDriver, logger = logging.getLogger('main')):
|
|||||||
click(".ow-box button.okki-btn-round", wait=False)
|
click(".ow-box button.okki-btn-round", wait=False)
|
||||||
flow.react(Sleep)
|
flow.react(Sleep)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning('Unable to unset additional fees; skipping', exc_info=e)
|
logger.warning('Unable to unset additional fees', exc_info=e)
|
||||||
|
|
||||||
try:
|
flow.react(Wait)
|
||||||
flow.react(Wait)
|
flow.deter(Skip, Cancel)
|
||||||
flow.allow(Cancel, False)
|
click(".sticky.bottom-0 button.okki-btn-primary", condition=None)
|
||||||
flow.allow(Skip, False)
|
flow.react(Sleep)
|
||||||
click(".sticky.bottom-0 button.okki-btn-primary", condition=None)
|
driver.close()
|
||||||
flow.react(Sleep)
|
except Skip:
|
||||||
except Skip:
|
pass
|
||||||
pass
|
except Cancel:
|
||||||
except Cancel:
|
break
|
||||||
break
|
|
||||||
except Exception as e:
|
|
||||||
logger.error('Error while saving document', exc_info=e)
|
|
||||||
status = Status.STANDBY
|
|
||||||
continue
|
|
||||||
finally:
|
|
||||||
driver.close()
|
|
||||||
|
|
||||||
index += 1
|
|
||||||
attempts = 0
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Unexpected error', exc_info=e)
|
logger.error('Unexpected error', exc_info=e)
|
||||||
status = Status.STANDBY
|
status = Status.STANDBY
|
||||||
|
continue
|
||||||
|
|
||||||
|
index += 1
|
||||||
|
attempts = 0
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
try:
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user