From 87f30a1391521a463cd5a13394d3ae2cd10a5d2e Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Tue, 19 Oct 2021 18:19:25 +0200 Subject: [PATCH] adding metrics for tradeDocuments --- ereuse_devicehub/resources/action/models.py | 2 +- ereuse_devicehub/resources/device/metrics.py | 52 ++++++- .../resources/documents/device_row.py | 2 + .../resources/documents/documents.py | 21 ++- tests/test_metrics.py | 129 ++++++++++++++---- 5 files changed, 156 insertions(+), 50 deletions(-) diff --git a/ereuse_devicehub/resources/action/models.py b/ereuse_devicehub/resources/action/models.py index ce6e4e70..fbc05234 100644 --- a/ereuse_devicehub/resources/action/models.py +++ b/ereuse_devicehub/resources/action/models.py @@ -1640,7 +1640,7 @@ class Trade(JoinedTableMixin, ActionWithMultipleTradeDocuments): metrics = [] for doc in self.documents: m = TradeMetrics(document=doc, Trade=self) - metrics.append(m.get_metrics()) + metrics.extend(m.get_metrics()) return metrics def __repr__(self) -> str: diff --git a/ereuse_devicehub/resources/device/metrics.py b/ereuse_devicehub/resources/device/metrics.py index 80840b87..62500b8d 100644 --- a/ereuse_devicehub/resources/device/metrics.py +++ b/ereuse_devicehub/resources/device/metrics.py @@ -5,7 +5,6 @@ class MetricsMix: """we want get the data metrics of one device""" def __init__(self, *args, **kwargs): - self.actions = copy.copy(device.actions) self.actions.sort(key=lambda x: x.created) self.rows = [] self.lifetime = 0 @@ -53,10 +52,11 @@ class Metrics(MetricsMix): """we want get the data metrics of one device""" def __init__(self, *args, **kwargs): - device = kwargs.pop('device') + self.device = kwargs.pop('device') + self.actions = copy.copy(self.device.actions) super().__init__(*args, **kwargs) - self.hid = device.hid - self.devicehub_id = device.devicehub_id + self.hid = self.device.hid + self.devicehub_id = self.device.devicehub_id def get_action_status(self): """ @@ -196,8 +196,46 @@ class TradeMetrics(MetricsMix): """we want get the data metrics of one device""" def __init__(self, *args, **kwargs): - document = kwargs.pop('document') - super().__init__(*args, **kwargs) - self.hid = document.hash + self.document = kwargs.pop('document') + self.actions = copy.copy(self.document.actions) + self.hid = self.document.file_hash self.devicehub_id = '' + super().__init__(*args, **kwargs) + def get_metrics(self): + self.last_trade = next(x for x in self.actions if x.t == 'Trade') + self.act = self.last_trade + row = self.get_template_row() + + row['type'] = 'Trade-Document' + row['action_type'] = 'Trade-Document' + if self.document.weight: + row['type'] = 'Trade-Container' + row['action_type'] = 'Trade-Document' + + row['document_name'] = self.document.file_name + row['trade_supplier'] = self.last_trade.user_from.email + row['trade_receiver'] = self.last_trade.user_to.email + row['trade_confirmed'] = self.get_confirms() + row['self.status_receiver'] = '' + row['self.status_supplier'] = '' + row['trade_weight'] = self.document.weight + if self.last_trade.author == self.last_trade.user_from: + row['action_create_by'] = 'Supplier' + elif self.last_trade.author == self.last_trade.user_to: + row['action_create_by'] = 'Receiver' + + self.rows.append(row) + + return self.rows + + def get_confirms(self): + """ + if the action is one trade action, is possible than have a list of confirmations. + Get the doble confirm for to know if this trade is confirmed or not. + """ + if hasattr(self.last_trade, 'acceptances'): + accept = self.last_trade.acceptances[-1] + if accept.t == 'Confirm' and accept.user == self.last_trade.user_to: + return True + return False diff --git a/ereuse_devicehub/resources/documents/device_row.py b/ereuse_devicehub/resources/documents/device_row.py index 36c93819..fe021c3d 100644 --- a/ereuse_devicehub/resources/documents/device_row.py +++ b/ereuse_devicehub/resources/documents/device_row.py @@ -414,6 +414,8 @@ def none2str(string): return '' return format(string) + + def get_action(component, action): """ Filter one action from a component or return None """ result = [a for a in component.actions if a.type == action] diff --git a/ereuse_devicehub/resources/documents/documents.py b/ereuse_devicehub/resources/documents/documents.py index 41606d0b..4e25c007 100644 --- a/ereuse_devicehub/resources/documents/documents.py +++ b/ereuse_devicehub/resources/documents/documents.py @@ -32,6 +32,8 @@ from ereuse_devicehub.resources.documents.device_row import (DeviceRow, StockRow InternalStatsRow) from ereuse_devicehub.resources.lot import LotView from ereuse_devicehub.resources.lot.models import Lot +from ereuse_devicehub.resources.action.models import Trade +from ereuse_devicehub.resources.device.models import Device from ereuse_devicehub.resources.hash_reports import insert_hash, ReportHash, verify_hash @@ -168,21 +170,16 @@ class ActionsDocumentView(DeviceView): cw.writerow(d.keys()) first = False cw.writerow(d.values()) - from ereuse_devicehub.resources.action.models import Trade - from ereuse_devicehub.resources.device.models import Device - # import pdb; pdb.set_trace() query_trade = Trade.query.filter(Trade.devices.any(Device.id.in_(devs_id))).all() - doc_metrics = [] for trade in query_trade: - doc_metrics.extend(trade.get_metrics()) - - for data_row in doc_metrics: - row = ActionRow(data_row) - if first: - cw.writerow(row.keys()) - first = False - cw.writerow(row.values()) + data_rows = trade.get_metrics() + for row in data_rows: + d = ActionRow(row) + if first: + cw.writerow(d.keys()) + first = False + cw.writerow(d.values()) bfile = data.getvalue().encode('utf-8') output = make_response(bfile) diff --git a/tests/test_metrics.py b/tests/test_metrics.py index 70c728d2..c8641e3f 100644 --- a/tests/test_metrics.py +++ b/tests/test_metrics.py @@ -3,6 +3,8 @@ import pytest from ereuse_devicehub.client import UserClient from ereuse_devicehub.resources.action import models as ma from ereuse_devicehub.resources.documents import documents +from ereuse_devicehub.resources.lot.models import Lot +from ereuse_devicehub.resources.tradedocument.models import TradeDocument from tests import conftest from tests.conftest import file, yaml2json, json_encode @@ -21,8 +23,7 @@ def test_simple_metrics(user: UserClient): "finalUserCode": "abcdefjhi", "devices": [device_id], "description": "aaa", "startTime": "2020-11-01T02:00:00+00:00", - "endTime": "2020-12-01T02:00:00+00:00" - } + "endTime": "2020-12-01T02:00:00+00:00"} # Create Allocate user.post(res=ma.Allocate, data=post_request) @@ -66,8 +67,7 @@ def test_second_hdd_metrics(user: UserClient): "finalUserCode": "abcdefjhi", "devices": [device_id], "description": "aaa", "startTime": "2020-11-01T02:00:00+00:00", - "endTime": "2020-12-01T02:00:00+00:00" - } + "endTime": "2020-12-01T02:00:00+00:00"} # Create Allocate user.post(res=ma.Allocate, data=post_request) @@ -110,8 +110,7 @@ def test_metrics_with_live_null(user: UserClient): "finalUserCode": "abcdefjhi", "devices": [device_id], "description": "aaa", "startTime": "2020-11-01T02:00:00+00:00", - "endTime": "2020-12-01T02:00:00+00:00" - } + "endTime": "2020-12-01T02:00:00+00:00"} # Create Allocate user.post(res=ma.Allocate, data=post_request) @@ -125,18 +124,16 @@ def test_metrics_with_live_null(user: UserClient): @pytest.mark.mvp @pytest.mark.usefixtures(conftest.app_context.__name__) def test_metrics_action_status(user: UserClient, user2: UserClient): - """ Checks one standard query of metrics """ + """ Checks one standard query of metrics.""" # Insert computer lenovo = yaml2json('desktop-9644w8n-lenovo-0169622.snapshot') snap, _ = user.post(json_encode(lenovo), res=ma.Snapshot) action = {'type': ma.Use.t, 'devices': [snap['device']['id']]} action_use, _ = user.post(action, res=ma.Action) - # res, _ = user.get("/metrics/") csv_str, _ = user.get(res=documents.DocumentDef.t, item='actions/', accept='text/csv', query=[('filter', {'type': ['Computer']})]) - # import pdb; pdb.set_trace() head = 'DHID;Hid;Document-Name;Action-Type;Action-User-LastOwner-Supplier;Action-User-LastOwner-Receiver;Action-Create-By;Trade-Confirmed;Status-Supplier;Status-Receiver;Status Supplier – Created Date;Status Receiver – Created Date;Trade-Weight;Allocate-Start;Allocate-User-Code;Allocate-NumUsers;UsageTimeAllocate;Type;LiveCreate;UsageTimeHdd\n' body = '93652;desktop-lenovo-9644w8n-0169622-00:1a:6b:5e:7f:10;;Status;;foo@foo.com;Receiver;;;Use;;' assert head in csv_str @@ -145,8 +142,8 @@ def test_metrics_action_status(user: UserClient, user2: UserClient): @pytest.mark.mvp @pytest.mark.usefixtures(conftest.app_context.__name__) -def test_complet_metrics(user: UserClient, user2: UserClient): - """ Checks one standard query of metrics """ +def test_complet_metrics_with_trade(user: UserClient, user2: UserClient): + """ Checks one standard query of metrics in a trade enviroment.""" # Insert computer lenovo = yaml2json('desktop-9644w8n-lenovo-0169622.snapshot') acer = yaml2json('acer.happy.battery.snapshot') @@ -154,28 +151,100 @@ def test_complet_metrics(user: UserClient, user2: UserClient): snap2, _ = user.post(json_encode(acer), res=ma.Snapshot) lot, _ = user.post({'name': 'MyLot'}, res=Lot) devices = [('id', snap1['device']['id']), - ('id', snap2['device']['id']) - ] + ('id', snap2['device']['id'])] lot, _ = user.post({}, res=Lot, item='{}/devices'.format(lot['id']), query=devices) - # import pdb; pdb.set_trace() - # request_post = { - # 'type': 'Trade', - # 'devices': [span1['device']['id'], snap2['device']['id']], - # 'userFromEmail': user2.email, - # 'userToEmail': user.email, - # 'price': 10, - # 'date': "2020-12-01T02:00:00+00:00", - # 'lot': lot['id'], - # 'confirms': True, - # } + request_post = { + 'type': 'Trade', + 'devices': [snap1['device']['id'], snap2['device']['id']], + 'userFromEmail': user.email, + 'userToEmail': user2.email, + 'price': 10, + 'date': "2020-12-01T02:00:00+00:00", + 'lot': lot['id'], + 'confirms': True, + } - # user.post(res=models.Action, data=request_post) + user.post(res=ma.Action, data=request_post) - # ============================== - # Check metrics - metrics = {'allocateds': 1, 'live': 1} - res, _ = user.get("/metrics/") - assert res == metrics + action = {'type': ma.Refurbish.t, 'devices': [snap1['device']['id']]} + action_use, _ = user.post(action, res=ma.Action) + csv_str, _ = user.get(res=documents.DocumentDef.t, + item='actions/', + accept='text/csv', + query=[('filter', {'type': ['Computer']})]) + + body1_lenovo = '93652;desktop-lenovo-9644w8n-0169622-00:1a:6b:5e:7f:10;;Trade;foo@foo.com;foo2@foo.com;Supplier;False;Refurbish;Use;' + body2_lenovo = ';;0;0;Trade;0;0\n' + + body1_acer = 'J2MA2;laptop-acer-aohappy-lusea0d010038879a01601-00:26:c7:8e:cb:8c;;Trade;foo@foo.com;foo2@foo.com;Supplier;False;;Use;;;0;' + body2_acer = ';;0;0;Trade;0;4692.0\n' + + assert body1_lenovo in csv_str + assert body2_lenovo in csv_str + assert body1_acer in csv_str + assert body2_acer in csv_str + + # User2 mark this device as Refurbish + action = {'type': ma.Refurbish.t, 'devices': [snap1['device']['id']]} + action_use2, _ = user2.post(action, res=ma.Action) + csv_str, _ = user.get(res=documents.DocumentDef.t, + item='actions/', + accept='text/csv', + query=[('filter', {'type': ['Computer']})]) + + body2_lenovo = ';Refurbish;0;0;Trade;0;0\n' + body2_acer = ';Refurbish;0;0;Trade;0;4692.0\n' + + +@pytest.mark.mvp +@pytest.mark.usefixtures(conftest.app_context.__name__) +def test_metrics_action_status_for_containers(user: UserClient, user2: UserClient): + """ Checks one standard query of metrics for a container.""" + # Insert computer + lenovo = yaml2json('desktop-9644w8n-lenovo-0169622.snapshot') + snap, _ = user.post(json_encode(lenovo), res=ma.Snapshot) + lot, _ = user.post({'name': 'MyLot'}, res=Lot) + devices = [('id', snap['device']['id'])] + lot, _ = user.post({}, + res=Lot, + item='{}/devices'.format(lot['id']), + query=devices) + request_post = { + 'type': 'Trade', + 'devices': [snap['device']['id']], + 'userFromEmail': user.email, + 'userToEmail': user2.email, + 'price': 10, + 'date': "2020-12-01T02:00:00+00:00", + 'lot': lot['id'], + 'confirms': True, + } + + user.post(res=ma.Action, data=request_post) + + request_post = { + 'filename': 'test.pdf', + 'hash': 'bbbbbbbb', + 'url': 'http://www.ereuse.org/', + 'weight': 150, + 'lot': lot['id'] + } + tradedocument, _ = user.post(res=TradeDocument, data=request_post) + action = {'type': ma.Recycling.t, 'devices': [], 'documents': [tradedocument['id']]} + action, _ = user.post(action, res=ma.Action) + trade = TradeDocument.query.one() + + assert str(trade.actions[-1].id) == action['id'] + + csv_str, _ = user.get(res=documents.DocumentDef.t, + item='actions/', + accept='text/csv', + query=[('filter', {'type': ['Computer']})]) + + body1 = '\n;bbbbbbbb;test.pdf;Trade-Document;foo@foo.com;foo2@foo.com;Supplier;False;;Use;;;150.0;' + body2 = ';;0;0;Trade-Container;0;0\n' + assert body1 in csv_str + assert body2 in csv_str