Merge pull request #284 from eReuse/bugfix/3385-bug-date-allocate

fixed bugs of allocate
This commit is contained in:
cayop 2022-05-26 18:11:37 +02:00 committed by GitHub
commit 776c27a082
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 315 additions and 17 deletions

View File

@ -1,4 +1,5 @@
import copy import copy
import datetime
import json import json
from json.decoder import JSONDecodeError from json.decoder import JSONDecodeError
@ -667,6 +668,10 @@ class AllocateForm(ActionFormMix):
self.start_time.errors = ['Not a valid date value.!'] self.start_time.errors = ['Not a valid date value.!']
return False return False
if start_time > datetime.datetime.now().date():
self.start_time.errors = ['Not a valid date value.!']
return False
if start_time and end_time and end_time < start_time: if start_time and end_time and end_time < start_time:
error = ['The action cannot finish before it starts.'] error = ['The action cannot finish before it starts.']
self.end_time.errors = error self.end_time.errors = error
@ -679,23 +684,100 @@ class AllocateForm(ActionFormMix):
def check_devices(self): def check_devices(self):
if self.type.data == 'Allocate': if self.type.data == 'Allocate':
return self.check_allocate()
if self.type.data == 'Deallocate':
return self.check_deallocate()
return True
def check_allocate(self):
txt = "You need deallocate before allocate this device again" txt = "You need deallocate before allocate this device again"
for device in self._devices: for device in self._devices:
if device.allocated: # | Allo - Deallo | Allo - Deallo |
allocates = [
ac for ac in device.actions if ac.type in ['Allocate', 'Deallocate']
]
allocates.sort(key=lambda x: x.start_time)
allocates.reverse()
last_deallocate = None
last_allocate = None
for ac in allocates:
if (
ac.type == 'Deallocate'
and ac.start_time.date() < self.start_time.data
):
# allow to do the action
break
# check if this action is between an old allocate - deallocate
if ac.type == 'Deallocate':
last_deallocate = ac
continue
if (
ac.type == 'Allocate'
and ac.start_time.date() > self.start_time.data
):
last_deallocate = None
last_allocate = None
continue
if ac.type == 'Allocate':
last_allocate = ac
if last_allocate or not last_deallocate:
self.devices.errors = [txt] self.devices.errors = [txt]
return False return False
device.allocated = True device.allocated = True
return True
if self.type.data == 'Deallocate': def check_deallocate(self):
txt = "Sorry some of this devices are actually deallocate" txt = "Sorry some of this devices are actually deallocate"
for device in self._devices: for device in self._devices:
if not device.allocated: allocates = [
ac for ac in device.actions if ac.type in ['Allocate', 'Deallocate']
]
allocates.sort(key=lambda x: x.start_time)
allocates.reverse()
last_deallocate = None
last_allocate = None
for ac in allocates:
# check if this action is between an old allocate - deallocate
# | Allo - Deallo | Allo - Deallo |
# | Allo |
if (
ac.type == 'Allocate'
and ac.start_time.date() > self.start_time.data
):
last_allocate = None
last_deallocate = None
continue
if ac.type == 'Allocate' and not last_deallocate:
last_allocate = ac
break
if (
ac.type == 'Deallocate'
and ac.start_time.date() > self.start_time.data
):
last_deallocate = ac
continue
if ac.type == 'Deallocate':
last_allocate = None
if last_deallocate or not last_allocate:
self.devices.errors = [txt]
return False
if not last_deallocate and not last_allocate:
self.devices.errors = [txt] self.devices.errors = [txt]
return False return False
device.allocated = False device.allocated = False
return True return True

View File

@ -1,6 +1,5 @@
import copy import copy
import pathlib import pathlib
import time
from contextlib import suppress from contextlib import suppress
from fractions import Fraction from fractions import Fraction
from itertools import chain from itertools import chain
@ -358,7 +357,6 @@ class Device(Thing):
from ereuse_devicehub.resources.device import states from ereuse_devicehub.resources.device import states
with suppress(LookupError, ValueError): with suppress(LookupError, ValueError):
# import pdb; pdb.set_trace()
return self.last_action_of(*states.Physical.actions()) return self.last_action_of(*states.Physical.actions())
@property @property
@ -407,7 +405,7 @@ class Device(Thing):
def tradings(self): def tradings(self):
return {str(x.id): self.trading(x.lot) for x in self.actions if x.t == 'Trade'} return {str(x.id): self.trading(x.lot) for x in self.actions if x.t == 'Trade'}
def trading(self, lot, simple=None): def trading(self, lot, simple=None): # noqa: C901
"""The trading state, or None if no Trade action has """The trading state, or None if no Trade action has
ever been performed to this device. This extract the posibilities for to do. ever been performed to this device. This extract the posibilities for to do.
This method is performed for show in the web. This method is performed for show in the web.

View File

@ -1,4 +1,5 @@
import csv import csv
import datetime
import json import json
from io import BytesIO from io import BytesIO
from pathlib import Path from pathlib import Path
@ -686,6 +687,34 @@ def test_action_allocate_error_dates(user3: UserClientFlask):
assert dev.actions[-1].type != 'Allocate' assert dev.actions[-1].type != 'Allocate'
@pytest.mark.mvp
@pytest.mark.usefixtures(conftest.app_context.__name__)
def test_action_allocate_error_future_dates(user3: UserClientFlask):
snap = create_device(user3, 'real-eee-1001pxd.snapshot.12.json')
dev = snap.device
uri = '/inventory/device/'
user3.get(uri)
start_time = (datetime.datetime.now() + datetime.timedelta(1)).strftime('%Y-%m-%d')
end_time = (datetime.datetime.now() + datetime.timedelta(10)).strftime('%Y-%m-%d')
data = {
'csrf_token': generate_csrf(),
'type': "Allocate",
'severity': "Info",
'devices': "{}".format(dev.id),
'start_time': start_time,
'end_time': end_time,
'end_users': 2,
}
uri = '/inventory/action/allocate/add/'
body, status = user3.post(uri, data=data)
assert status == '200 OK'
assert 'Action Allocate error' in body
assert 'Not a valid date value.!' in body
assert dev.actions[-1].type != 'Allocate'
@pytest.mark.mvp @pytest.mark.mvp
@pytest.mark.usefixtures(conftest.app_context.__name__) @pytest.mark.usefixtures(conftest.app_context.__name__)
def test_action_deallocate(user3: UserClientFlask): def test_action_deallocate(user3: UserClientFlask):
@ -707,7 +736,7 @@ def test_action_deallocate(user3: UserClientFlask):
uri = '/inventory/action/allocate/add/' uri = '/inventory/action/allocate/add/'
user3.post(uri, data=data) user3.post(uri, data=data)
assert dev.actions[-1].type == 'Allocate' assert dev.allocated_status.type == 'Allocate'
data = { data = {
'csrf_token': generate_csrf(), 'csrf_token': generate_csrf(),
@ -720,11 +749,200 @@ def test_action_deallocate(user3: UserClientFlask):
} }
body, status = user3.post(uri, data=data) body, status = user3.post(uri, data=data)
assert status == '200 OK' assert status == '200 OK'
assert dev.actions[-1].type == 'Deallocate' assert dev.allocated_status.type == 'Deallocate'
assert 'Action &#34;Deallocate&#34; created successfully!' in body assert 'Action &#34;Deallocate&#34; created successfully!' in body
assert dev.devicehub_id in body assert dev.devicehub_id in body
@pytest.mark.mvp
@pytest.mark.usefixtures(conftest.app_context.__name__)
def test_action_deallocate_error(user3: UserClientFlask):
snap = create_device(user3, 'real-eee-1001pxd.snapshot.12.json')
dev = snap.device
uri = '/inventory/device/'
user3.get(uri)
data = {
'csrf_token': generate_csrf(),
'type': "Allocate",
'severity': "Info",
'devices': "{}".format(dev.id),
'start_time': '2000-05-01',
'end_time': '2000-06-01',
'end_users': 2,
}
uri = '/inventory/action/allocate/add/'
user3.post(uri, data=data)
assert dev.allocated_status.type == 'Allocate'
data = {
'csrf_token': generate_csrf(),
'type': "Deallocate",
'severity': "Info",
'devices': "{}".format(dev.id),
'start_time': '2000-01-01',
'end_time': '2000-02-01',
'end_users': 2,
}
body, status = user3.post(uri, data=data)
assert status == '200 OK'
assert dev.allocated_status.type != 'Deallocate'
assert 'Action Deallocate error!' in body
assert 'Sorry some of this devices are actually deallocate' in body
@pytest.mark.mvp
@pytest.mark.usefixtures(conftest.app_context.__name__)
def test_action_allocate_deallocate_error(user3: UserClientFlask):
snap = create_device(user3, 'real-eee-1001pxd.snapshot.12.json')
dev = snap.device
uri = '/inventory/device/'
user3.get(uri)
data = {
'csrf_token': generate_csrf(),
'type': "Allocate",
'severity': "Info",
'devices': "{}".format(dev.id),
'start_time': '2000-01-01',
'end_time': '2000-01-01',
'end_users': 2,
}
uri = '/inventory/action/allocate/add/'
user3.post(uri, data=data)
assert dev.allocated_status.type == 'Allocate'
assert len(dev.actions) == 13
data = {
'csrf_token': generate_csrf(),
'type': "Deallocate",
'severity': "Info",
'devices': "{}".format(dev.id),
'start_time': '2000-02-01',
'end_time': '2000-02-01',
'end_users': 2,
}
body, status = user3.post(uri, data=data)
assert status == '200 OK'
assert dev.allocated_status.type == 'Deallocate'
assert len(dev.actions) == 14
# is not possible to do an allocate between an allocate and an deallocate
data = {
'csrf_token': generate_csrf(),
'type': "Allocate",
'severity': "Info",
'devices': "{}".format(dev.id),
'start_time': '2000-01-15',
'end_time': '2000-01-15',
'end_users': 2,
}
user3.post(uri, data=data)
assert dev.allocated_status.type == 'Deallocate'
# assert 'Action Deallocate error!' in body
# assert 'Sorry some of this devices are actually deallocate' in body
#
data = {
'csrf_token': generate_csrf(),
'type': "Deallocate",
'severity': "Info",
'devices': "{}".format(dev.id),
'start_time': '2000-01-15',
'end_time': '2000-01-15',
'end_users': 2,
}
user3.post(uri, data=data)
assert len(dev.actions) == 14
@pytest.mark.mvp
@pytest.mark.usefixtures(conftest.app_context.__name__)
def test_action_allocate_deallocate_error2(user3: UserClientFlask):
snap = create_device(user3, 'real-eee-1001pxd.snapshot.12.json')
dev = snap.device
uri = '/inventory/device/'
user3.get(uri)
data = {
'csrf_token': generate_csrf(),
'type': "Allocate",
'severity': "Info",
'devices': "{}".format(dev.id),
'start_time': '2000-01-10',
'end_users': 2,
}
uri = '/inventory/action/allocate/add/'
user3.post(uri, data=data)
assert len(dev.actions) == 13
data = {
'csrf_token': generate_csrf(),
'type': "Deallocate",
'severity': "Info",
'devices': "{}".format(dev.id),
'start_time': '2000-01-20',
'end_users': 2,
}
body, status = user3.post(uri, data=data)
assert status == '200 OK'
assert len(dev.actions) == 14
data = {
'csrf_token': generate_csrf(),
'type': "Allocate",
'severity': "Info",
'devices': "{}".format(dev.id),
'start_time': '2000-02-10',
'end_users': 2,
}
uri = '/inventory/action/allocate/add/'
user3.post(uri, data=data)
assert len(dev.actions) == 15
data = {
'csrf_token': generate_csrf(),
'type': "Deallocate",
'severity': "Info",
'devices': "{}".format(dev.id),
'start_time': '2000-02-20',
'end_users': 2,
}
user3.post(uri, data=data)
assert len(dev.actions) == 16
data = {
'csrf_token': generate_csrf(),
'type': "Allocate",
'severity': "Info",
'devices': "{}".format(dev.id),
'start_time': '2000-01-25',
'end_users': 2,
}
user3.post(uri, data=data)
assert len(dev.actions) == 17
data = {
'csrf_token': generate_csrf(),
'type': "Deallocate",
'severity': "Info",
'devices': "{}".format(dev.id),
'start_time': '2000-01-27',
'end_users': 2,
}
user3.post(uri, data=data)
assert len(dev.actions) == 18
@pytest.mark.mvp @pytest.mark.mvp
@pytest.mark.usefixtures(conftest.app_context.__name__) @pytest.mark.usefixtures(conftest.app_context.__name__)
def test_action_toprepare(user3: UserClientFlask): def test_action_toprepare(user3: UserClientFlask):