Skip to content

Commit d5615ca

Browse files
committed
when we allocate a resource, there is no need to specify capability
1 parent 4167f4d commit d5615ca

13 files changed

Lines changed: 147 additions & 53 deletions

smartschedule/allocation/allocated_capability.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
from smartschedule.allocation.capabilityscheduling.allocatable_capability_id import (
44
AllocatableCapabilityId,
55
)
6-
from smartschedule.shared.capability.capability import Capability
6+
from smartschedule.shared.capability_selector import CapabilitySelector
77
from smartschedule.shared.timeslot.time_slot import TimeSlot
88

99

1010
@dataclass(frozen=True)
1111
class AllocatedCapability:
1212
allocated_capability_id: AllocatableCapabilityId
13-
capability: Capability
13+
capability: CapabilitySelector
1414
time_slot: TimeSlot

smartschedule/allocation/allocation_facade.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
from smartschedule.allocation.capabilityscheduling.allocatable_capability_id import (
1010
AllocatableCapabilityId,
1111
)
12+
from smartschedule.allocation.capabilityscheduling.allocatable_capability_summary import (
13+
AllocatableCapabilitySummary,
14+
)
1215
from smartschedule.allocation.capabilityscheduling.capability_finder import (
1316
CapabilityFinder,
1417
)
@@ -28,6 +31,7 @@
2831
from smartschedule.availability.owner import Owner
2932
from smartschedule.availability.resource_id import ResourceId
3033
from smartschedule.shared.capability.capability import Capability
34+
from smartschedule.shared.capability_selector import CapabilitySelector
3135
from smartschedule.shared.events_publisher import EventsPublisher
3236
from smartschedule.shared.timeslot.time_slot import TimeSlot
3337

@@ -74,25 +78,26 @@ def allocate_to_project(
7478
self,
7579
project_id: ProjectAllocationsId,
7680
allocatable_capability_id: AllocatableCapabilityId,
77-
capability: Capability,
81+
# capability: Capability, # NIE MA TEGO JUSH
7882
time_slot: TimeSlot,
7983
) -> UUID | None:
80-
owner = Owner(project_id.id)
8184
# yes, one transaction crossing 2 modules.
82-
if not self._capability_finder.is_present(allocatable_capability_id):
85+
capabilities = self._capability_finder.find_by_id(allocatable_capability_id)
86+
capability = next(iter(capabilities.all), None)
87+
if capability is None:
8388
return None
84-
if (
89+
90+
if not (
8591
self._availability_facade.block(
8692
allocatable_capability_id.to_availability_resource_id(),
8793
time_slot,
88-
owner,
94+
Owner(project_id.id),
8995
)
90-
is False
9196
):
9297
return None
9398

9499
event = self._allocate(
95-
project_id, allocatable_capability_id, capability, time_slot
100+
project_id, allocatable_capability_id, capability.capabilities, time_slot
96101
)
97102
return event.allocated_capability_id if event is not None else None
98103

@@ -124,14 +129,16 @@ def allocate_capability_to_project_for_period(
124129
if not to_allocate:
125130
return False
126131

127-
allocated_event = self._allocate(project_id, to_allocate, capability, time_slot)
132+
allocated_event = self._allocate(
133+
project_id, to_allocate.id, to_allocate.capabilities, time_slot
134+
)
128135
return allocated_event is not None
129136

130137
def _allocate(
131138
self,
132139
project_id: ProjectAllocationsId,
133140
allocatable_capability_id: AllocatableCapabilityId,
134-
capability: Capability,
141+
capability: CapabilitySelector,
135142
time_slot: TimeSlot,
136143
) -> CapabilitiesAllocated | None:
137144
allocations = self._project_allocations_repository.get(project_id)
@@ -144,9 +151,9 @@ def _allocate(
144151

145152
def _find_chosen_allocatable_capability(
146153
self, proposed_capabilities: AllocatableCapabilitiesSummary, chosen: ResourceId
147-
) -> AllocatableCapabilityId | None:
154+
) -> AllocatableCapabilitySummary | None:
148155
matching = [
149-
ac.id
156+
ac
150157
for ac in proposed_capabilities.all
151158
if ac.id.to_availability_resource_id() == chosen
152159
]

smartschedule/allocation/capabilityscheduling/capability_finder.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,21 @@ def find_available_capabilities(
3434
capability.name, capability.type, time_slot.from_, time_slot.to
3535
)
3636
found = self._filter_availability_in_time_slot(found, time_slot)
37-
return self._create_summary(found)
37+
return self._create_summary(*found)
3838

3939
def find_capabilities(
4040
self, capability: Capability, time_slot: TimeSlot
4141
) -> AllocatableCapabilitiesSummary:
4242
found = self._repository.find_by_capability_within(
4343
capability.name, capability.type, time_slot.from_, time_slot.to
4444
)
45-
return self._create_summary(found)
45+
return self._create_summary(*found)
4646

4747
def find_by_id(
48-
self, allocatable_capability_ids: list[AllocatableCapabilityId]
48+
self, *allocatable_capability_ids: AllocatableCapabilityId
4949
) -> AllocatableCapabilitiesSummary:
50-
found = self._repository.get_all(allocatable_capability_ids)
51-
return self._create_summary(list(found))
52-
53-
def is_present(self, allocatable_capability_id: AllocatableCapabilityId) -> bool:
54-
return self._repository.exists(allocatable_capability_id)
50+
found = self._repository.get_all(list(allocatable_capability_ids))
51+
return self._create_summary(*list(found))
5552

5653
def _filter_availability_in_time_slot(
5754
self, allocatable_capabilities: list[AllocatableCapability], time_slot: TimeSlot
@@ -73,7 +70,7 @@ def _filter_availability_in_time_slot(
7370
]
7471

7572
def _create_summary(
76-
self, found: list[AllocatableCapability]
73+
self, *found: AllocatableCapability
7774
) -> AllocatableCapabilitiesSummary:
7875
summaries = [
7976
AllocatableCapabilitySummary(

smartschedule/allocation/demands.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def missing_demands(self, allocations: Allocations) -> Demands:
4343

4444
def _satisfied_by(self, demand: Demand, allocations: Allocations) -> bool:
4545
return any(
46-
allocation.capability == demand.capability
46+
allocation.capability.can_perform(demand.capability)
4747
and demand.time_slot.within(allocation.time_slot)
4848
for allocation in allocations.all
4949
)

smartschedule/allocation/potential_transfers.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
from dataclasses import dataclass
55

66
from smartschedule.allocation.allocated_capability import AllocatedCapability
7+
from smartschedule.allocation.capabilityscheduling.allocatable_capability_id import (
8+
AllocatableCapabilityId,
9+
)
10+
from smartschedule.allocation.capabilityscheduling.allocatable_capability_summary import (
11+
AllocatableCapabilitySummary,
12+
)
713
from smartschedule.allocation.cashflow.earnings import Earnings
814
from smartschedule.allocation.project_allocations_id import ProjectAllocationsId
915
from smartschedule.allocation.projects_allocations_summary import (
@@ -50,6 +56,38 @@ def transfer(
5056
self.summary.project_allocations[project_to] = new_allocations_project_to
5157
return PotentialTransfers(self.summary, self.earnings)
5258

59+
def transfer_capabilities(
60+
self,
61+
project_to: ProjectAllocationsId,
62+
capability_to_transfer: AllocatableCapabilitySummary,
63+
for_slot: TimeSlot,
64+
) -> PotentialTransfers:
65+
project_to_move_from = self._find_project_to_move_from(
66+
capability_to_transfer.id, for_slot
67+
)
68+
if project_to_move_from is None:
69+
return self
70+
71+
allocated_capability = AllocatedCapability(
72+
capability_to_transfer.id,
73+
capability_to_transfer.capabilities,
74+
capability_to_transfer.time_slot,
75+
)
76+
return self.transfer(
77+
project_to_move_from, project_to, allocated_capability, for_slot
78+
)
79+
80+
def _find_project_to_move_from(
81+
self, capability_id: AllocatableCapabilityId, for_slot: TimeSlot
82+
) -> ProjectAllocationsId | None:
83+
for (
84+
project_allocations_id,
85+
allocations,
86+
) in self.summary.project_allocations.items():
87+
if allocations.find(capability_id) is not None:
88+
return project_allocations_id
89+
return None
90+
5391
def to_simulated_projects(self) -> list[SimulatedProject]:
5492
return [
5593
SimulatedProject(

smartschedule/allocation/project_allocations.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
ProjectAllocationsDemandsScheduled,
2020
)
2121
from smartschedule.allocation.project_allocations_id import ProjectAllocationsId
22-
from smartschedule.shared.capability.capability import Capability
22+
from smartschedule.shared.capability_selector import CapabilitySelector
2323
from smartschedule.shared.sqlalchemy_extensions import AsJSON, EmbeddedUUID, registry
2424
from smartschedule.shared.timeslot.time_slot import TimeSlot
2525

@@ -64,7 +64,7 @@ def with_demands(
6464
def allocate(
6565
self,
6666
allocatable_capability_id: AllocatableCapabilityId,
67-
capability: Capability,
67+
capability: CapabilitySelector,
6868
requested_slot: TimeSlot,
6969
when: datetime,
7070
) -> CapabilitiesAllocated | None:

tests/smartschedule/allocation/capabilityscheduling/test_capability_scheduling.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def test_schedule_allocatable_capabilities(
5757
AllocatableResourceId.new_one(), [java_skill, rust_skill], one_day
5858
)
5959

60-
loaded = capability_finder.find_by_id(allocatable)
60+
loaded = capability_finder.find_by_id(*allocatable)
6161
assert len(allocatable) == len(loaded.all)
6262
for allocatable_capability_id in allocatable:
6363
availability_assert.assert_availability_slots_created(

0 commit comments

Comments
 (0)