I would like to design a booking system using optaplanner, bellow my business model:
Customers (id, name) //Customer table
Services(id, name, description, duration) //services that a customer can book, duration can be 15min, 30min, ..., N x 15min
Employees(id, name) //Employee tables
Appointment(id, customerId, employeeId, serviceId, startTime, endTime)
To book an appointment, the customer will select:
The day of the appointment (mandatory)
A list of services (mandatory)
A list of employees (optional)
I would like to know I can design the model to return the list of availability for a given day, given list of services.
Bellow a basic pseudo-code model :
#Entity
public class Service extends PanacheEntityBase {
#Id
#GeneratedValue
#NotNull
private Long id;
#NotBlank
private String name;
private int durationInGrains;
}
public class TimeGrain {
public static final int GRAIN_LENGTH_IN_MINUTES = 15;
private int grainIndex; // unique
private int startingMinuteOfDay;
}
#Entity
public class Employee extends PanacheEntityBase {
#PlanningId
#Id
#GeneratedValue
#NotNull
private Long id;
#NotBlank
private String name;
}
#Entity
public class Appointment extends PanacheEntityBase {
#Id
#GeneratedValue
#NotNull
private Long id;
private Employee employee;
private Service service;
private LocalDateTime startTime;
private LocalDateTime endTime;
}
#PlanningEntity
public class Availability {
#PlanningVariable(valueRangeProviderRefs = { "timeGrainRange" })
private TimeGrain startingTimeGrain;
#PlanningVariable(valueRangeProviderRefs = "providerRange")
private Provider provider;
private Service service;
}
#PlanningSolution
public class AppointmentAvailability {
#ValueRangeProvider(id = "timeGrainRange")
#ProblemFactCollectionProperty
private List<TimeGrain> timeGrainList;
#ProblemFactCollectionProperty
#ValueRangeProvider(id = "providerRange")
private List<Provider> providerList;
#ProblemFactCollectionProperty
#ValueRangeProvider(id = "appointmentsRange")
private List<Appointment> appointmentList;
#PlanningEntityCollectionProperty
private List<Availability> availabilityList;
#PlanningScore
private HardMediumSoftScore score;
}
As I am new to optaplanner, could you please advise if this is the way to go?
UPDATE 1: I have simplified the problem to the minimum for design purposes.
Take a look at the meeting scheduling example in optaplanner-examples, to get inspired on how to model it. Also see the Time Grain pattern in the docs in the section Design Patterns. The school timetabling quickstart follows the Timeslot pattern instead.
Related
I'm making a Spring boot application with Hibernate ORM framework.
I have Employee entity there:
#Entity
public class Employee {
private String firstName;
private String position;
//// more than 30 private fields
//// fields related to one sublogic
private String category;
private LocalDate categoryAssignmentDate;
private LocalDate categoryAssignmentDeadlineDate;
private LocalDate docsSubmitDeadlineDate;
}
There are more than 30 private fields in Employee class.
And as you can see, I have 4 fields related to same sublogic Category.
So my question is: Is it a good practise to split my Employee entity into two entities Employee and Category, which will be connected as OnetoOne relationship?
Does it make the code clearer?
Use embedded and embeddable to prevent double table mapping and unnecessary OneToOne relations.
#Entity
public class Employee {
private String firstName;
private String position;
#Embedded
private Category category
}
#Embeddable
public class Category{
private String category;
private LocalDate categoryAssignmentDate;
private LocalDate categoryAssignmentDeadlineDate;
private LocalDate docsSubmitDeadlineDate;
}
You might need to add attribute overrides
i have a question,one order have many crafts, one of the crafts need two or many people to finish,so in the planning entity i usee a list object for planning variables,but when i start the application,it have a error,please give me some idea,thanks!
#PlanningSolution
public class ScheduleSolution extends AbstractPersistable {
#ProblemFactCollectionProperty
private List<Order> orderList;
#ProblemFactCollectionProperty
private List<ProductBom> productBomList;
#PlanningEntityCollectionProperty
private List<JobAssignment> jobAssignmentList;
#ProblemFactCollectionProperty
#ValueRangeProvider(id = "resourceRange")
List<Resource> resourceList;
#PlanningScore
private HardSoftScore score;
}
#PlanningEntity
public class JobAssignment extends AbstractPersistable {
private ProductBom productBom;
#PlanningVariable(valueRangeProviderRefs = { "resourceRange" })
private List<Resource> resourceList;
}
Caused by: java.lang.IllegalArgumentException: The entityClass (class com.demo.domain.reassign.JobAssignment) has a PlanningVariable annotated property (resourceList) that refers to a ValueRangeProvider annotated member (field java.util.List com.demo.domain.reassign.ScheduleSolution.resourceList) that returns a Collection with elements of type (class com.demo.domain.reassign.Resource) which cannot be assigned to the PlanningVariable's type (interface java.util.List). at org.optaplanner.core.impl.domain.valuerange.descriptor.AbstractFromPropertyValueRangeDescriptor.processValueRangeProviderAnnotation(AbstractFromPropertyValueRangeDescriptor.java:136)
A #PlanningVariable cannot be a List, not until we support #PlanningVariableCollection some day. Possible fix:
#PlanningEntity
public class JobAssignment extends AbstractPersistable {
private ProductBom productBom;
#PlanningVariable(valueRangeProviderRefs = { "resourceRange" })
private Resource resource;
}
I have the following Entity
#Entity
public class Project implements Serializable {
#Id
private Integer project_id;
private String project_name;
other attributes
#OneToOne
#JoinColumn(name = "lead_emp_no", referencedColumnName = "emp_no")
private Employee projectLead;
// but the following two relationships need to be a connect by:
#OneToOne
#JoinColumn(name = "lead_boss_emp_no", referencedColumnName = "emp_no")
private Employee projectLeadBoss;
#OneToOne
#JoinColumn(name = "lead_bosses_boss_emp_no", referencedColumnName = "emp_no")
private Employee projectLeadBossesBoss;
With this setup, we have to manually maintain the employee numbers for the Lead's boss and the Lead's Boss's boss. This relationship is [somewhat] already available knowing the projectLead employee:
The Employee Entity is as follows:
#Entity
public class Employee implements Serializable {
#Id
private Integer emp_no;
private Integer bosses_emp_no;
Is it possible to get my Project entity to connect to the boss and bosses Employee based on projectLead? In single query I'd like to get a table of all projects and their lead's hierarchy. I'm open to entity redesign.
You can replace the bosses_emp_no in Employee should with a more helpful boss:
#Entity
public class Employee implements Serializable {
#Id
private Integer emp_no;
#OneToOne
#JoinColumn(name = "boss_emp_no", referencedColumnName = "emp_no")
private Employee boss;
Then you simply add a couple of delegating methods to Project
public Employee getProjectLeadBoss() {
return this.projectLead.getBoss();
}
public Employee getProjectLeadBossesBoss() {
return this.getProjectLeadBoss().getBoss();
}
My project is in the form:
Class Persistant :
#Entity
public class Produit implements Serializable {
private static final long serialVersionUID = -3352484919001942398L;
#Id
#GeneratedValue
private Long id;
private String module;
private String produit;
//getter&&setter
Class Dao
public List<Entry<Integer, List<Produit>>> parProduit(String cat) {
.......
HashMap<Integer, List<Produit>> legaux = new HashMap<Integer, List<Produit>>();
........
List<Map.Entry<Integer, List<Produit>>> entries = new ArrayList<Entry<Integer, List<Produit>>>(legaux.entrySet());
return entries;
}
when i execute this code i get this error :
java.io.NotSerializableException: java.util.HashMap$Node
java.util.HashMap.EntrySet<K, V>
is not serializable.
legaux.entrySet()
probably returns set of type java.util.HashMap.EntrySet, you may want to check that.
this is my java code :three entity including CompanyTypeRelation ,CompanyType,Department
public class CompanyTypeRelation implements java.io.Serializable {
private static final long serialVersionUID = 4227115995926533087L;
// Fields
private long id;
private CompanyType companyType;
private Department department;
private long operator;
private String operateTime;
// the relationship
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="company_type_id", nullable=false)
public CompanyType getCompanyType() {
return this.companyType;
}
public void setCompanyType(CompanyType companyType) {
this.companyType = companyType;
}
// the relationship
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="company_id", nullable=false)
public Department getDepartment() {
return this.department;
}
public void setDepartment(Department department) {
this.department = department;
}
..............
other code:
}
this is my query sql :
SELECT c
FROM com.hna.dt.orm.CompanyTypeRelation c
LEFT JOIN c.companyType ct LEFT JOIN c.department cd
can I get departmentName from Department by the sql above?
assuming that the departmentName is in the department table, just add cd.name (or whatever the column name is) to your select list.