Skip to content

Commit

Permalink
Merge pull request #16 from softwareone-platform/bugfix/225488-new-to…
Browse files Browse the repository at this point in the history
…ken-format

225488 225489 Fix pricelist update, add new token format support
  • Loading branch information
d3rky authored May 27, 2024
2 parents 9ba2a15 + 5c78f16 commit ed18fed
Show file tree
Hide file tree
Showing 19 changed files with 184 additions and 127 deletions.
15 changes: 12 additions & 3 deletions swo/mpt/cli/core/accounts/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,20 @@ def _wrap_active(is_active: bool) -> str: # pragma: no cover
return ""

def _wrap_token(account: Account, to_wrap_secret: bool) -> str:
token_id, token = account.token.split(":")
is_new_token = "idt:TKN-" in account.token

if is_new_token:
token = account.token
else:
token = f"{account.token_id}:{account.token}"

if to_wrap_secret:
token = f"{token[0:][:4]}*****{token[:4]}"
if is_new_token:
token = f"{token[0:][:22]}*****{token[:4]}"
else:
token = f"{token[0:][:4]}*****{token[:4]}"

return f"{token_id}:{token}"
return token

for account in accounts:
table.add_row(
Expand Down
3 changes: 2 additions & 1 deletion swo/mpt/cli/core/accounts/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ def from_token(token: Token, environment: str) -> Account:
id=token.account.id,
name=token.account.name,
type=token.account.type,
token=f"{token.id}:{token.token}",
token=token.token,
token_id=token.id,
environment=environment,
is_active=True,
)
Expand Down
1 change: 1 addition & 0 deletions swo/mpt/cli/core/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ class Account(BaseModel):
name: str
type: str
token: str
token_id: str
environment: str
is_active: bool = False
3 changes: 1 addition & 2 deletions swo/mpt/cli/core/mpt/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,4 @@ def join_url(self, url: str) -> str:


def client_from_account(account: Account) -> MPTClient:
_, secret = account.token.split(":")
return MPTClient(account.environment, secret)
return MPTClient(account.environment, account.token)
2 changes: 1 addition & 1 deletion swo/mpt/cli/core/mpt/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def create_parameter(


@wrap_http_error
def create_item(mpt_client: MPTClient, product: Product, item_json: dict) -> Item:
def create_item(mpt_client: MPTClient, item_json: dict) -> Item:
response = mpt_client.post("/items", json=item_json)
response.raise_for_status()

Expand Down
25 changes: 13 additions & 12 deletions swo/mpt/cli/core/pricelists/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,19 @@ def sync_pricelists(
),
],
):
file_paths = []
for pricelist_path in pricelists_paths:
path = Path(pricelist_path)

if path.is_file():
file_paths.append(pricelist_path)
elif path.is_dir():
file_paths.extend(glob(str(path / "*")))
else:
file_paths.extend(glob(pricelist_path))

file_paths = list(filter(lambda p: p.endswith(".xlsx"), file_paths))
with console.status("Fetching pricelist files..."):
file_paths = []
for pricelist_path in pricelists_paths:
path = Path(pricelist_path)

if path.is_file():
file_paths.append(pricelist_path)
elif path.is_dir():
file_paths.extend(glob(str(path / "*")))
else:
file_paths.extend(glob(pricelist_path))

file_paths = list(filter(lambda p: p.endswith(".xlsx"), file_paths))

if not len(file_paths):
console.print(
Expand Down
129 changes: 71 additions & 58 deletions swo/mpt/cli/core/pricelists/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
find_value_for,
get_values_for_general,
get_values_for_table,
status_step_text,
)


Expand Down Expand Up @@ -79,33 +80,34 @@ def sync_pricelist(
stats: PricelistStatsCollector,
console: Console,
) -> tuple[PricelistStatsCollector, Optional[Pricelist]]:
general_ws = wb[constants.TAB_GENERAL]
general_values = get_values_for_general(general_ws, constants.GENERAL_FIELDS)
with console.status("Sync Pricelist..."):
general_ws = wb[constants.TAB_GENERAL]
general_values = get_values_for_general(general_ws, constants.GENERAL_FIELDS)

if active_account.type == "Operations":
pricelist_json = to_operations_pricelist_json(general_values)
else:
pricelist_json = to_vendor_pricelist_json(general_values)

try:
if action == PricelistAction.CREATE:
pricelist = create_pricelist(
mpt_client,
pricelist_json,
)
if active_account.type == "Operations":
pricelist_json = to_operations_pricelist_json(general_values)
else:
pricelist_id = find_value_for(
constants.GENERAL_PRICELIST_ID, general_values
)[2]
pricelist = update_pricelist(
mpt_client,
pricelist_id,
pricelist_json,
)
except Exception as e:
add_or_create_error(general_ws, general_values, e)
stats.add_error(constants.TAB_GENERAL)
return stats, None
pricelist_json = to_vendor_pricelist_json(general_values)

try:
if action == PricelistAction.CREATE:
pricelist = create_pricelist(
mpt_client,
pricelist_json,
)
else:
pricelist_id = find_value_for(
constants.GENERAL_PRICELIST_ID, general_values
)[2]
pricelist = update_pricelist(
mpt_client,
pricelist_id,
pricelist_json,
)
except Exception as e:
add_or_create_error(general_ws, general_values, e)
stats.add_error(constants.TAB_GENERAL)
return stats, None

index, _, _ = find_value_for(constants.GENERAL_PRICELIST_ID, general_values)
general_ws[index] = pricelist.id
Expand All @@ -127,9 +129,14 @@ def to_operations_priceitem_json(values: list[SheetValue]) -> dict:
status = find_value_for(constants.PRICELIST_ITEMS_STATUS, values)[2]
priceitem_json = {
"markup": find_value_for(constants.PRICELIST_ITEMS_MARKUP, values)[2],
"unitSP": find_value_for(constants.PRICELIST_ITEMS_UNIT_SP, values)[2],
"unitLP": find_value_for(constants.PRICELIST_ITEMS_UNIT_LP, values)[2],
"unitPP": find_value_for(constants.PRICELIST_ITEMS_UNIT_PP, values)[2],
}

unit_sp = find_value_for(constants.PRICELIST_ITEMS_UNIT_SP, values)
if unit_sp and unit_sp[2] is not None:
priceitem_json["unitSP"] = unit_sp[2]

if status != "Draft":
priceitem_json["status"] = status

Expand All @@ -152,37 +159,43 @@ def sync_pricelist_items(
stats: PricelistStatsCollector,
console: Console,
) -> PricelistStatsCollector:
values = get_values_for_table(ws, constants.PRICELIST_ITEMS_FIELDS)

for sheet_value in values:
try:
action = PricelistItemAction(
find_value_for(constants.PRICELIST_ITEMS_ACTION, sheet_value)[2]
)

if action != PricelistItemAction.UPDATE:
stats.add_skipped(constants.TAB_PRICE_ITEMS)
continue

vendor_id = find_value_for(
constants.PRICELIST_ITEMS_ITEM_VENDOR_ID, sheet_value
)[2]
pricelist_item = get_pricelist_item(mpt_client, pricelist_id, vendor_id)

if active_account.type == "Operations":
pricelist_item_json = to_operations_priceitem_json(sheet_value)
else:
pricelist_item_json = to_vendor_priceitem_json(sheet_value)

pricelist_item = update_pricelist_item(
mpt_client, pricelist_id, pricelist_item.id, pricelist_item_json
)

index_id, _, _ = find_value_for(constants.PRICELIST_ITEMS_ID, sheet_value)
ws[index_id] = pricelist_item.id
stats.add_synced(constants.TAB_PRICE_ITEMS)
except Exception as e:
add_or_create_error(ws, sheet_value, e)
stats.add_error(constants.TAB_PRICE_ITEMS)
with console.status("Sync Pricelist Items...") as status:
values = get_values_for_table(ws, constants.PRICELIST_ITEMS_FIELDS)

for sheet_value in values:
try:
action = PricelistItemAction(
find_value_for(constants.PRICELIST_ITEMS_ACTION, sheet_value)[2]
)

if action != PricelistItemAction.UPDATE:
stats.add_skipped(constants.TAB_PRICE_ITEMS)
continue

vendor_id = find_value_for(
constants.PRICELIST_ITEMS_ITEM_VENDOR_ID, sheet_value
)[2]
pricelist_item = get_pricelist_item(mpt_client, pricelist_id, vendor_id)

if active_account.type == "Operations":
pricelist_item_json = to_operations_priceitem_json(sheet_value)
else:
pricelist_item_json = to_vendor_priceitem_json(sheet_value)

pricelist_item = update_pricelist_item(
mpt_client, pricelist_id, pricelist_item.id, pricelist_item_json
)

index_id, _, _ = find_value_for(
constants.PRICELIST_ITEMS_ID, sheet_value
)
ws[index_id] = pricelist_item.id
stats.add_synced(constants.TAB_PRICE_ITEMS)
except Exception as e:
add_or_create_error(ws, sheet_value, e)
stats.add_error(constants.TAB_PRICE_ITEMS)
finally:
step_text = status_step_text(stats, ws.title)
status.update(f"Syncing {ws.title}: {step_text}")

return stats
13 changes: 1 addition & 12 deletions swo/mpt/cli/core/products/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
get_values_for_table,
set_dict_value,
set_value,
status_step_text,
)

T = TypeVar("T")
Expand Down Expand Up @@ -357,17 +358,6 @@ def to_template_json(
}


def status_step_text(stats: ProductStatsCollector, tab_name: str) -> str:
results = stats.tabs[tab_name]

return (
f"[green]{results['synced']}[/green] / "
f"[red bold]{results['error']}[/red bold] / "
f"[white bold]{results['skipped']}[/white bold] / "
f"[blue]{results['total']}[/blue]"
)


def sync_product_definition(
mpt_client: MPTClient,
definition_path: Path,
Expand Down Expand Up @@ -769,7 +759,6 @@ def sync_items(
sheet_value = setup_unit_of_measure(mpt_client, sheet_value)
item = create_item(
mpt_client,
product,
to_item_create_json(
product.id,
items_groups_mapping,
Expand Down
12 changes: 12 additions & 0 deletions swo/mpt/cli/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from openpyxl.utils import get_column_letter # type: ignore
from openpyxl.utils.cell import coordinate_from_string # type: ignore
from openpyxl.worksheet.worksheet import Worksheet # type: ignore
from swo.mpt.cli.core.stats import StatsCollector

SheetValue: TypeAlias = tuple[str, str, Any]
SheetValueGenerator: TypeAlias = Generator[list[SheetValue], None, None]
Expand Down Expand Up @@ -156,3 +157,14 @@ def add_or_create_error(
ws[f"{column_letter}{row_number}"] = str(exception)

return ws


def status_step_text(stats: StatsCollector, tab_name: str) -> str:
results = stats.tabs[tab_name]

return (
f"[green]{results['synced']}[/green] / "
f"[red bold]{results['error']}[/red bold] / "
f"[white bold]{results['skipped']}[/white bold] / "
f"[blue]{results['total']}[/blue]"
)
6 changes: 4 additions & 2 deletions tests/accounts_config/home/.swocli/accounts.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
"id": "ACC-12341",
"name": "Account 1",
"type": "Vendor",
"token": "TKN-0000-0000-0001:secret 1",
"token": "secret 1",
"token_id": "TKN-0000-0000-0001",
"environment": "https://example.com",
"is_active": true
}, {
"id": "ACC-12342",
"name": "Account 2",
"type": "Vendor",
"token": "TKN-0000-0000-0002:secret 2",
"token": "idt:TKN-0000-0000-0002:secret 2",
"token_id": "TKN-0000-0000-0002",
"environment": "https://example.com",
"is_active": false
}]
25 changes: 21 additions & 4 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,8 @@ def expected_account():
id="ACC-12341",
name="Account 1",
type="Vendor",
token="TKN-0000-0000-0001:secret 1",
token="secret 1",
token_id="TKN-0000-0000-0001",
environment="https://example.com",
is_active=True,
)
Expand All @@ -272,7 +273,8 @@ def another_expected_account():
id="ACC-12342",
name="Account 2",
type="Vendor",
token="TKN-0000-0000-0002:secret 2",
token="idt:TKN-0000-0000-0002:secret 2",
token_id="TKN-0000-0000-0002",
environment="https://example.com",
is_active=False,
)
Expand All @@ -284,7 +286,8 @@ def active_vendor_account():
id="ACC-12341",
name="Account 1",
type="Vendor",
token="TKN-0000-0000-0001:secret 1",
token="secret 1",
token_id="TKN-0000-0000-0001",
environment="https://example.com",
is_active=True,
)
Expand All @@ -296,7 +299,21 @@ def active_operations_account():
id="ACC-12341",
name="Account 1",
type="Operations",
token="TKN-0000-0000-0001:secret 1",
token="secret 1",
token_id="TKN-0000-0000-0001",
environment="https://example.com",
is_active=True,
)


@pytest.fixture()
def new_token_account():
return CLIAccount(
id="ACC-12341",
name="Account 1",
type="Vendor",
token="idt:TKN-0000-0000-0001:secret 1",
token_id="TKN-0000-0000-0001",
environment="https://example.com",
is_active=True,
)
Expand Down
Binary file modified tests/pricelist_files/PRC-1234-1234-1234.xlsx
Binary file not shown.
Loading

0 comments on commit ed18fed

Please sign in to comment.