|
|
|
|
@@ -1,18 +1,23 @@
|
|
|
|
|
/* © SRSoftware 2025 */
|
|
|
|
|
package de.srsoftware.umbrella.core.model;
|
|
|
|
|
|
|
|
|
|
import static de.srsoftware.tools.Optionals.isSet;
|
|
|
|
|
import static de.srsoftware.tools.Optionals.nullable;
|
|
|
|
|
import static de.srsoftware.umbrella.core.Constants.*;
|
|
|
|
|
import static de.srsoftware.umbrella.core.Util.markdown;
|
|
|
|
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.invalidFieldException;
|
|
|
|
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
|
|
|
|
|
|
|
|
|
|
import de.srsoftware.tools.Mappable;
|
|
|
|
|
import java.sql.ResultSet;
|
|
|
|
|
import java.sql.SQLException;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
|
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
|
|
|
|
import org.json.JSONObject;
|
|
|
|
|
|
|
|
|
|
public class Project implements Mappable {
|
|
|
|
|
private final Collection<Member> members;
|
|
|
|
|
private final Map<Long,Member> members;
|
|
|
|
|
private final boolean showClosed;
|
|
|
|
|
private final Long companyId;
|
|
|
|
|
private Status status;
|
|
|
|
|
@@ -21,7 +26,7 @@ public class Project implements Mappable {
|
|
|
|
|
private String description;
|
|
|
|
|
private final Set<String> dirtyFields = new HashSet<>();
|
|
|
|
|
|
|
|
|
|
public Project(long id, String name, String description, Status status, Long companyId, boolean showClosed, Collection<Member> members) {
|
|
|
|
|
public Project(long id, String name, String description, Status status, Long companyId, boolean showClosed, Map<Long,Member> members) {
|
|
|
|
|
this.id = id;
|
|
|
|
|
this.name = name;
|
|
|
|
|
this.description = description;
|
|
|
|
|
@@ -44,17 +49,15 @@ public class Project implements Mappable {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean hasMember(UmbrellaUser user) {
|
|
|
|
|
for (var member : members){
|
|
|
|
|
if (member.userId() == user.id()) return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
var member = members.get(user.id());
|
|
|
|
|
return isSet(member) && member.userId() == user.id();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public long id(){
|
|
|
|
|
return id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Collection<Member> members(){
|
|
|
|
|
public Map<Long,Member> members(){
|
|
|
|
|
return members;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -64,13 +67,14 @@ public class Project implements Mappable {
|
|
|
|
|
|
|
|
|
|
public static Project of(ResultSet rs) throws SQLException {
|
|
|
|
|
var companyId = rs.getLong(COMPANY_ID);
|
|
|
|
|
return new Project(rs.getLong(ID),rs.getString(NAME),rs.getString(DESCRIPTION),Status.of(rs.getInt(STATUS)),companyId == 0 ? null : companyId,rs.getBoolean(SHOW_CLOSED),new ArrayList<>());
|
|
|
|
|
return new Project(rs.getLong(ID),rs.getString(NAME),rs.getString(DESCRIPTION),Status.of(rs.getInt(STATUS)),companyId == 0 ? null : companyId,rs.getBoolean(SHOW_CLOSED),new HashMap<>());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Project patch(JSONObject json) {
|
|
|
|
|
for (var key : json.keySet()){
|
|
|
|
|
switch (key){
|
|
|
|
|
case DESCRIPTION: description = json.getString(key); break;
|
|
|
|
|
case MEMBERS: patchMembers(json.getJSONObject(MEMBERS)); break;
|
|
|
|
|
case NAME: name = json.getString(key); break;
|
|
|
|
|
case STATUS: status = json.get(key) instanceof Number number ? Status.of(number.intValue()) : Status.valueOf(json.getString(key)); break;
|
|
|
|
|
default: key = null;
|
|
|
|
|
@@ -80,6 +84,20 @@ public class Project implements Mappable {
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void patchMembers(JSONObject json) throws UmbrellaException {
|
|
|
|
|
for (var key : json.keySet()){
|
|
|
|
|
long userId;
|
|
|
|
|
try {
|
|
|
|
|
userId = Long.parseLong(key);
|
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
|
throw invalidFieldException(USER_ID,"long");
|
|
|
|
|
}
|
|
|
|
|
if (!(json.get(key) instanceof Number number)) throw invalidFieldException(PERMISSION,"int");
|
|
|
|
|
var permission = Permission.of(number.intValue());
|
|
|
|
|
members.put(userId,new Member(userId,permission));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean showClosed(){
|
|
|
|
|
return showClosed;
|
|
|
|
|
}
|
|
|
|
|
@@ -91,13 +109,17 @@ public class Project implements Mappable {
|
|
|
|
|
@Override
|
|
|
|
|
public Map<String, Object> toMap() {
|
|
|
|
|
var map = new HashMap<String, Object>();
|
|
|
|
|
var memberMap = new HashMap<Long,Map<String,Object>>();
|
|
|
|
|
if (members != null) for (var entry : members.entrySet()){
|
|
|
|
|
memberMap.put(entry.getKey(),entry.getValue().toMap());
|
|
|
|
|
}
|
|
|
|
|
map.put(ID,id);
|
|
|
|
|
map.put(NAME,name);
|
|
|
|
|
map.put(DESCRIPTION,Map.of(SOURCE,description,RENDERED,markdown(description)));
|
|
|
|
|
map.put(STATUS,Map.of(STATUS_CODE,status.code(), NAME,status.name()));
|
|
|
|
|
map.put(COMPANY_ID,companyId);
|
|
|
|
|
map.put(SHOW_CLOSED,showClosed);
|
|
|
|
|
map.put(MEMBERS,members == null ? List.of() : members.stream().map(Member::toMap).toList());
|
|
|
|
|
map.put(MEMBERS,memberMap);
|
|
|
|
|
return map;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|