[P25284-20] Initial commit with setup and first draft rest servcice
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.db.migration;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.ejb.Singleton;
|
||||
import jakarta.ejb.Startup;
|
||||
import jakarta.ejb.TransactionManagement;
|
||||
import jakarta.ejb.TransactionManagementType;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.flywaydb.core.Flyway;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 19 Jan 2026
|
||||
*/
|
||||
|
||||
@Singleton
|
||||
@Startup
|
||||
@TransactionManagement(TransactionManagementType.BEAN)
|
||||
public class DbMigrator {
|
||||
|
||||
@Resource(lookup = "java:/jdbc/fotoDocumentationDS")
|
||||
private DataSource dataSource;
|
||||
|
||||
@PostConstruct
|
||||
public void onStartup() {
|
||||
Flyway flyway = getFlyway();
|
||||
flyway.setDataSource(dataSource);
|
||||
flyway.setTable("DB_MIGRATION");
|
||||
flyway.setLocations(this.getClass().getPackage().getName());
|
||||
flyway.setBaselineOnMigrate(false);
|
||||
flyway.setValidateOnMigrate(false);
|
||||
flyway.setIgnoreFailedFutureMigration(true);
|
||||
|
||||
flyway.migrate();
|
||||
}
|
||||
|
||||
protected Flyway getFlyway() {
|
||||
return new Flyway();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.model;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 19 Jan 2026
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public abstract class AbstractDateEntity extends AbstractEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "JPA_CREATED", nullable = false)
|
||||
@JsonIgnore
|
||||
private Date jpaCreated;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "JPA_UPDATED", nullable = false)
|
||||
@JsonIgnore
|
||||
private Date jpaUpdated;
|
||||
|
||||
@Column(name = "JPA_ACTIVE", nullable = false)
|
||||
private boolean active = true;
|
||||
|
||||
@Version
|
||||
@Column(name = "JPA_VERSION", nullable = false)
|
||||
private int jpaVersion = 0;
|
||||
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
Date now = new Date();
|
||||
jpaCreated = now;
|
||||
jpaUpdated = now;
|
||||
}
|
||||
|
||||
@PreUpdate
|
||||
protected void onUpdate() {
|
||||
jpaUpdated = new Date();
|
||||
}
|
||||
|
||||
public Date getJpaCreated() {
|
||||
return jpaCreated;
|
||||
}
|
||||
|
||||
public Date getJpaUpdated() {
|
||||
return jpaUpdated;
|
||||
}
|
||||
|
||||
public int getJpaVersion() {
|
||||
return jpaVersion;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 19 Jan 2026
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public abstract class AbstractEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.model;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 19 Jan 2026
|
||||
*/
|
||||
|
||||
@Entity
|
||||
@Table(name = "customer")
|
||||
@NamedQuery(name = Customer.FIND_BY_NUMBER, query = "select c from Customer c where c.customerNumber = :cutomerNumber")
|
||||
public class Customer extends AbstractDateEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
public static final String SEQUENCE = "customer_seq";
|
||||
public static final String FIND_BY_NUMBER = "Customer.findByNumber";
|
||||
public static final String PARAM_NUMBER = "cutomerNumber";
|
||||
|
||||
@Id
|
||||
@Column(name = "customer_id", length = 22)
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
|
||||
@SequenceGenerator(name = SEQUENCE, sequenceName = SEQUENCE, allocationSize = 1)
|
||||
private Long customerId;
|
||||
|
||||
@Column(name = "customer_number", unique = true, nullable = false)
|
||||
private String customerNumber;
|
||||
|
||||
@Column(name = "name", nullable = false)
|
||||
private String name;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
@JoinColumn(name = "customer_id_fk")
|
||||
private Set<Picture> pictures = new HashSet<>();
|
||||
|
||||
public Long getCustomerId() {
|
||||
return customerId;
|
||||
}
|
||||
|
||||
public void setCustomerId(Long customerId) {
|
||||
this.customerId = customerId;
|
||||
}
|
||||
|
||||
public String getCustomerNumber() {
|
||||
return customerNumber;
|
||||
}
|
||||
|
||||
public void setCustomerNumber(String customerNumber) {
|
||||
this.customerNumber = customerNumber;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Set<Picture> getPictures() {
|
||||
return pictures;
|
||||
}
|
||||
|
||||
public void setPictures(Set<Picture> pictures) {
|
||||
this.pictures = pictures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder().append(customerNumber).toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || this.getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
return this.customerNumber.equals(((Customer) obj).getCustomerNumber());
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private Customer instance = new Customer();
|
||||
|
||||
public Builder customerNumber(String customerNumber) {
|
||||
instance.setCustomerNumber(customerNumber);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder name(String name) {
|
||||
instance.setName(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Customer build() {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.model;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 19 Jan 2026
|
||||
*/
|
||||
|
||||
@Entity
|
||||
@Table(name = "picture")
|
||||
public class Picture extends AbstractDateEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
public static final String SEQUENCE = "picture_seq";
|
||||
|
||||
@Id
|
||||
@Column(name = "picture_id", length = 22)
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
|
||||
@SequenceGenerator(name = SEQUENCE, sequenceName = SEQUENCE, allocationSize = 1)
|
||||
private Long pictureId;
|
||||
|
||||
// username from the person that shot the picture
|
||||
@Column(name = "username")
|
||||
private String username;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "picture_date", nullable = false)
|
||||
private Date pictureDate;
|
||||
|
||||
private String comment;
|
||||
|
||||
@Column(name = "image")
|
||||
private String image;
|
||||
|
||||
public Long getPictureId() {
|
||||
return pictureId;
|
||||
}
|
||||
|
||||
public void setPictureId(Long pictureId) {
|
||||
this.pictureId = pictureId;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Date getPictureDate() {
|
||||
return pictureDate;
|
||||
}
|
||||
|
||||
public void setPictureDate(Date pictureDate) {
|
||||
this.pictureDate = pictureDate;
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
public void setComment(String comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public String getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public void setImage(String image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder().append(pictureId).toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || this.getClass() != obj.getClass() || pictureId == null) {
|
||||
return false;
|
||||
}
|
||||
return this.pictureId.equals(((Picture) obj).getPictureId());
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private Picture instance = new Picture();
|
||||
|
||||
public Builder username(String username) {
|
||||
instance.setUsername(username);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder pictureDate(Date pictureDate) {
|
||||
instance.setPictureDate(pictureDate);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder comment(String comment) {
|
||||
instance.setComment(comment);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder image(String image) {
|
||||
instance.setImage(image);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Picture build() {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.model;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 19 Jan 2026
|
||||
*/
|
||||
|
||||
@Entity
|
||||
@Table(name = "x_right")
|
||||
public class Right extends AbstractDateEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
public static final String SEQUENCE = "right_seq";
|
||||
|
||||
@Id
|
||||
@Column(name = "right_id", length = 22)
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
|
||||
@SequenceGenerator(name = SEQUENCE, sequenceName = SEQUENCE, allocationSize = 1)
|
||||
private Long rightId;
|
||||
|
||||
@Column(nullable = false, unique = true)
|
||||
private String code;
|
||||
|
||||
@Column(nullable = false, unique = true)
|
||||
private String name;
|
||||
|
||||
@ManyToMany(mappedBy = "rights")
|
||||
private Set<User> roles = new HashSet<>();
|
||||
|
||||
public Long getRightId() {
|
||||
return rightId;
|
||||
}
|
||||
|
||||
public void setRightId(Long rightId) {
|
||||
this.rightId = rightId;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder().append(code).toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || this.getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
return this.code.equals(((Right) obj).getCode());
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private Right instance = new Right();
|
||||
|
||||
public Builder code(String code) {
|
||||
instance.setCode(code);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder name(String name) {
|
||||
instance.setName(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Right build() {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.model;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 19 Jan 2026
|
||||
*/
|
||||
|
||||
@Entity
|
||||
@Table(name = "x_user")
|
||||
public class User extends AbstractDateEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
public static final String SEQUENCE = "user_seq";
|
||||
|
||||
@Id
|
||||
@Column(name = "user_id", length = 22)
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
|
||||
@SequenceGenerator(name = SEQUENCE, sequenceName = SEQUENCE, allocationSize = 1)
|
||||
private Long userId;
|
||||
|
||||
@Column(name = "username", unique = true, nullable = false)
|
||||
private String username;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String password;
|
||||
|
||||
private String salt;
|
||||
|
||||
@Column(name = "title")
|
||||
private String title;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String firstname;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String lastname;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String email;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(name = "user_to_right", joinColumns = { @JoinColumn(name = "user_id_fk") }, inverseJoinColumns = { @JoinColumn(name = "right_id_fk") })
|
||||
private Set<Right> rights = new HashSet<>();
|
||||
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getSalt() {
|
||||
return salt;
|
||||
}
|
||||
|
||||
public void setSalt(String salt) {
|
||||
this.salt = salt;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
public void setFirstname(String firstname) {
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
public String getLastname() {
|
||||
return lastname;
|
||||
}
|
||||
|
||||
public void setLastname(String lastname) {
|
||||
this.lastname = lastname;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public Set<Right> getRights() {
|
||||
return rights;
|
||||
}
|
||||
|
||||
public void setRights(Set<Right> rights) {
|
||||
this.rights = rights;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder().append(username).toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || this.getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
return this.username.equals(((User) obj).getUsername());
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private User instance = new User();
|
||||
|
||||
public Builder email(String email) {
|
||||
instance.setEmail(email);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder firstname(String firstname) {
|
||||
instance.setFirstname(firstname);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder lastname(String lastname) {
|
||||
instance.setLastname(lastname);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder title(String title) {
|
||||
instance.setTitle(title);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder username(String username) {
|
||||
instance.setUsername(username);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder password(String password) {
|
||||
instance.setPassword(password);
|
||||
return this;
|
||||
}
|
||||
|
||||
public User build() {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.query;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 19 Jan 2026
|
||||
*/
|
||||
|
||||
public record Param(String name, Object value) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.query;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import jakarta.ejb.Stateless;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.NoResultException;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import jakarta.persistence.Query;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 19 Jan 2026
|
||||
*/
|
||||
@Stateless
|
||||
@SuppressWarnings("unchecked")
|
||||
@PermitAll
|
||||
public class QueryService {
|
||||
private static final Log LOG = LogFactory.getLog(QueryService.class);
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager eManager;
|
||||
|
||||
public int count(String namedQuery, Param... params) {
|
||||
Query query = eManager.createNamedQuery(namedQuery);
|
||||
for (Param param : params) {
|
||||
query.setParameter(param.name(), param.value());
|
||||
}
|
||||
return ((Number) query.getSingleResult()).intValue();
|
||||
}
|
||||
|
||||
public <T> Optional<T> callNamedQuerySingleResult(String namedQuery, Param... params) {
|
||||
return singleResult(eManager.createNamedQuery(namedQuery), Arrays.asList(params));
|
||||
}
|
||||
|
||||
private <T> Optional<T> singleResult(Query query, Collection<Param> params) {
|
||||
try {
|
||||
for (Param param : params) {
|
||||
query.setParameter(param.name(), param.value());
|
||||
}
|
||||
return Optional.ofNullable((T) query.getSingleResult());
|
||||
} catch (NoResultException nre) {
|
||||
LOG.debug("No entity found for query " + query + " with params " + params);
|
||||
LOG.trace("NoResultException", nre);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T callNamedQueryList(String namedQuery, Param... objects) {
|
||||
Query query = eManager.createNamedQuery(namedQuery);
|
||||
for (Param param : objects) {
|
||||
query.setParameter(param.name(), param.value());
|
||||
}
|
||||
return (T) query.getResultList();
|
||||
}
|
||||
|
||||
public <T> Optional<T> callQuerySingleResult(String sql, Param... objects) {
|
||||
Query query = eManager.createQuery(sql);
|
||||
for (Param param : objects) {
|
||||
query.setParameter(param.name(), param.value());
|
||||
}
|
||||
return Optional.of((T) query.getSingleResult());
|
||||
}
|
||||
|
||||
public <T> T callNativeQuery(String sql, Param... objects) {
|
||||
Query query = eManager.createNativeQuery(sql);
|
||||
for (Param param : objects) {
|
||||
query.setParameter(param.name(), param.value());
|
||||
}
|
||||
return (T) query.getResultList();
|
||||
}
|
||||
|
||||
public int callNativeQueryUpdate(String sql, Param... objects) {
|
||||
Query query = eManager.createNativeQuery(sql);
|
||||
for (Param param : objects) {
|
||||
query.setParameter(param.name(), param.value());
|
||||
}
|
||||
return query.executeUpdate();
|
||||
}
|
||||
|
||||
public int callNamedQueryUpdate(String namedQuery, Param... objects) {
|
||||
Query query = eManager.createNamedQuery(namedQuery);
|
||||
for (Param param : objects) {
|
||||
query.setParameter(param.name(), param.value());
|
||||
}
|
||||
return query.executeUpdate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.core.service;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import jakarta.ejb.EJB;
|
||||
import jakarta.ejb.LocalBean;
|
||||
import jakarta.ejb.Stateless;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.model.Customer;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.model.Picture;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.query.Param;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.query.QueryService;
|
||||
import marketing.heyday.hartmann.fotodocumentation.rest.vo.CustomerPictureValue;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 19 Jan 2026
|
||||
*/
|
||||
@Stateless
|
||||
@LocalBean
|
||||
public class CustomerPictureService {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager entityManager;
|
||||
|
||||
@EJB
|
||||
private QueryService queryService;
|
||||
|
||||
public boolean addCustomerPicture(CustomerPictureValue customerPictureValue) {
|
||||
Optional<Customer> customerOpt = queryService.callNamedQuerySingleResult(Customer.FIND_BY_NUMBER, new Param(Customer.PARAM_NUMBER, customerPictureValue.customerNumber()));
|
||||
Customer customer = customerOpt.orElseGet(() -> new Customer.Builder().customerNumber(customerPictureValue.customerNumber()).name(customerPictureValue.pharmacyName()).build());
|
||||
|
||||
Picture picture = new Picture.Builder().username(customerPictureValue.username()).comment(customerPictureValue.comment()).image(customerPictureValue.base64String()).pictureDate(customerPictureValue.date()).build();
|
||||
customer.getPictures().add(picture);
|
||||
|
||||
entityManager.persist(picture);
|
||||
entityManager.merge(customer);
|
||||
entityManager.flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.rest;
|
||||
|
||||
import org.jboss.resteasy.annotations.GZIP;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.ejb.EJB;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
import marketing.heyday.hartmann.fotodocumentation.core.service.CustomerPictureService;
|
||||
import marketing.heyday.hartmann.fotodocumentation.rest.jackson.JsonSchemaValidate;
|
||||
import marketing.heyday.hartmann.fotodocumentation.rest.vo.CustomerPictureValue;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 19 Jan 2026
|
||||
*/
|
||||
@RequestScoped
|
||||
@Path("customer-picture")
|
||||
public class CustomerPictureResource {
|
||||
|
||||
@EJB
|
||||
private CustomerPictureService customerPictureService;
|
||||
|
||||
@GZIP
|
||||
@POST
|
||||
@Path("")
|
||||
//@Authenticate(shouldBeInAllRoles = RightUtils.ADMIN_RIGHT)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "Add Customer Image to database")
|
||||
@ApiResponse(responseCode = "200", description = "Add successfull")
|
||||
public Response doAddCustomerPicture(@JsonSchemaValidate("schema/customer_picture_add.json") CustomerPictureValue customerPictureValue) {
|
||||
boolean success = customerPictureService.addCustomerPicture(customerPictureValue);
|
||||
|
||||
return success ? Response.ok().build() : Response.status(Status.BAD_REQUEST).build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.rest;
|
||||
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 14 Nov 2024
|
||||
*/
|
||||
@Path("monitoring")
|
||||
@RequestScoped
|
||||
public class MonitoringResource {
|
||||
|
||||
@GET
|
||||
@Path("check/{text}")
|
||||
@Produces(MediaType.TEXT_PLAIN)
|
||||
@Operation(summary = "Monitoring service for testing if the server is up and running.")
|
||||
@ApiResponse(responseCode = "200", description = "ok with as body the given path param text. ")
|
||||
public Response check(@PathParam("text") String text) {
|
||||
return Response.status(Status.OK).entity(text).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.rest.jackson;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource;
|
||||
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
|
||||
import io.swagger.v3.oas.annotations.info.Contact;
|
||||
import io.swagger.v3.oas.annotations.info.Info;
|
||||
import io.swagger.v3.oas.annotations.servers.Server;
|
||||
import jakarta.ws.rs.ApplicationPath;
|
||||
import jakarta.ws.rs.core.Application;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import marketing.heyday.hartmann.fotodocumentation.rest.CustomerPictureResource;
|
||||
import marketing.heyday.hartmann.fotodocumentation.rest.MonitoringResource;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2017</p>
|
||||
* <p>Company: heyday marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 18 Oct 2017
|
||||
*/
|
||||
@OpenAPIDefinition(info = @Info(title = "Hartmann Photo upload API", version = "1.0", description = "All available routes for the Hartmann Photo upload API", contact = @Contact(url = "https://localhost", name = "Patrick Verboom", email = "p.verboom@heyday.marketing")), servers = {
|
||||
@Server(description = "development", url = "http://localhost"),
|
||||
@Server(description = "integration", url = "http://localhost"),
|
||||
@Server(description = "production", url = "http://localhost")
|
||||
})
|
||||
@ApplicationPath("/api")
|
||||
public class ApplicationConfigApi extends Application {
|
||||
private static final Log LOG = LogFactory.getLog(ApplicationConfigApi.class);
|
||||
public static final String JSON_OUT = MediaType.APPLICATION_JSON + "; charset=utf-8";
|
||||
|
||||
@Override
|
||||
public Set<Class<?>> getClasses() {
|
||||
Set<Class<?>> retVal = new HashSet<>();
|
||||
retVal.add(OpenApiResource.class);
|
||||
retVal.add(ValidatedMessageBodyReader.class);
|
||||
//retVal.add(AuthenticateFilter.class);
|
||||
retVal.add(MonitoringResource.class);
|
||||
retVal.add(CustomerPictureResource.class);
|
||||
LOG.info("returning rest api classes " + retVal);
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.rest.jackson;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2017</p>
|
||||
* <p>Company: heyday marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: Feb 10, 2017
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value={ElementType.PARAMETER})
|
||||
public @interface JsonSchemaValidate {
|
||||
String value();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.rest.jackson;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2017</p>
|
||||
* <p>Company: heyday marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: Feb 10, 2017
|
||||
*/
|
||||
public interface SchemaValidated {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.rest.jackson;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.MultivaluedMap;
|
||||
import jakarta.ws.rs.ext.MessageBodyReader;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.networknt.schema.JsonSchema;
|
||||
import com.networknt.schema.JsonSchemaFactory;
|
||||
import com.networknt.schema.ValidationMessage;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 6 Dec 2024
|
||||
*/
|
||||
@Provider
|
||||
@Consumes(value = {
|
||||
MediaType.APPLICATION_JSON, "application/json; charset=utf-8"
|
||||
})
|
||||
public class ValidatedMessageBodyReader implements MessageBodyReader<SchemaValidated> {
|
||||
private static final Log LOG = LogFactory.getLog(ValidatedMessageBodyReader.class);
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see jakarta.ws.rs.ext.MessageBodyReader#isReadable(java.lang.Class, java.lang.reflect.Type, java.lang.annotation.Annotation[], jakarta.ws.rs.core.MediaType)
|
||||
*/
|
||||
@Override
|
||||
public boolean isReadable(Class<?> classType, Type type, Annotation[] annotations, MediaType mediaType) {
|
||||
if (mediaType.getType().contains("application/json")) {
|
||||
return false;
|
||||
}
|
||||
return Arrays.stream(annotations).anyMatch(a -> a.annotationType() == JsonSchemaValidate.class);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see jakarta.ws.rs.ext.MessageBodyReader#readFrom(java.lang.Class, java.lang.reflect.Type, java.lang.annotation.Annotation[], jakarta.ws.rs.core.MediaType, jakarta.ws.rs.core.MultivaluedMap, java.io.InputStream)
|
||||
*/
|
||||
@Override
|
||||
public SchemaValidated readFrom(Class<SchemaValidated> classType, Type type, Annotation[] annotations, MediaType mediaType,
|
||||
MultivaluedMap<String, String> httpHeaders, InputStream input) throws IOException {
|
||||
final String jsonData = read(input);
|
||||
|
||||
Optional<JsonSchemaValidate> annotation = Arrays.stream(annotations).filter(a -> a.annotationType() == JsonSchemaValidate.class).map(a -> (JsonSchemaValidate) a).findAny();
|
||||
if (annotation.isPresent()) {
|
||||
ValidationReply reply = validate(annotation.get(), jsonData);
|
||||
if (!reply.success) {
|
||||
throw new WebApplicationException(reply.getErrorResponse());
|
||||
}
|
||||
}
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
return objectMapper.readValue(new StringReader(jsonData), classType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param jsonSchema
|
||||
* @param jsonData
|
||||
* @return
|
||||
*/
|
||||
private ValidationReply validate(JsonSchemaValidate jsonSchema, String jsonData) {
|
||||
String schemaPath = jsonSchema.value();
|
||||
try {
|
||||
JsonSchema schema = getJsonSchema(schemaPath);
|
||||
JsonNode node = getJsonNode(jsonData);
|
||||
Set<ValidationMessage> errors = schema.validate(node);
|
||||
if (!errors.isEmpty()) {
|
||||
LOG.error("Failed to validate json to schema " + schemaPath);
|
||||
errors.stream().forEach(LOG::error);
|
||||
}
|
||||
return new ValidationReply.Builder().success(errors.isEmpty()).errors(errors).build();
|
||||
} catch (IOException e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
return new ValidationReply.Builder().success(false).build();
|
||||
}
|
||||
}
|
||||
|
||||
protected JsonSchema getJsonSchema(String name) throws IOException {
|
||||
JsonSchemaFactory factory = new JsonSchemaFactory();
|
||||
try (InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream(name);) {
|
||||
return factory.getSchema(input);
|
||||
}
|
||||
}
|
||||
|
||||
protected JsonNode getJsonNode(String content) throws IOException {
|
||||
return new ObjectMapper().readTree(content);
|
||||
}
|
||||
|
||||
private String read(InputStream input) throws IOException {
|
||||
try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input, Charset.forName("UTF-8")))) {
|
||||
return buffer.lines().collect(Collectors.joining("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.rest.jackson;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
|
||||
import com.networknt.schema.ValidationMessage;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2017</p>
|
||||
* <p>Company: heyday marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: Feb 14, 2017
|
||||
*/
|
||||
public final class ValidationReply {
|
||||
public final boolean success;
|
||||
public final Set<ValidationMessage> errors = new HashSet<>();
|
||||
|
||||
private ValidationReply(boolean success, Set<ValidationMessage> errors) {
|
||||
this.success = success;
|
||||
this.errors.addAll(errors);
|
||||
}
|
||||
|
||||
public Response getErrorResponse() {
|
||||
return Response.status(Status.BAD_REQUEST).entity(errors).build();
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private boolean success;
|
||||
private Set<ValidationMessage> errors = new HashSet<>();
|
||||
|
||||
public Builder success(boolean success) {
|
||||
this.success = success;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder errors(Set<ValidationMessage> errors) {
|
||||
this.errors = errors;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValidationReply build() {
|
||||
return new ValidationReply(success, errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package marketing.heyday.hartmann.fotodocumentation.rest.vo;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2024</p>
|
||||
* <p>Company: heyday Marketing GmbH</p>
|
||||
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
|
||||
* @version 1.0
|
||||
*
|
||||
* created: 19 Jan 2026
|
||||
*/
|
||||
|
||||
public record CustomerPictureValue(String username, String pharmacyName, String customerNumber, Date date, String comment, String base64String) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd"
|
||||
version="4.0" bean-discovery-mode="all">
|
||||
</beans>
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
<persistence version="3.0" xmlns="https://jakarta.ee/xml/ns/persistence"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence
|
||||
https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd">
|
||||
|
||||
<persistence-unit name="auth" transaction-type="JTA">
|
||||
<jta-data-source>java:/jdbc/fotoDocumentationDS</jta-data-source>
|
||||
|
||||
<class>marketing.heyday.hartmann.fotodocumentation.core.model.Right</class>
|
||||
<class>marketing.heyday.hartmann.fotodocumentation.core.model.User</class>
|
||||
<class>marketing.heyday.hartmann.fotodocumentation.core.model.Customer</class>
|
||||
<class>marketing.heyday.hartmann.fotodocumentation.core.model.Picture</class>
|
||||
|
||||
<properties>
|
||||
<property name="hibernate.format_sql" value="false" />
|
||||
<property name="hibernate.show_sql" value="false" />
|
||||
<!-- <property name="hibernate.archive.autodetection" value="class" /> -->
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
|
||||
<property name="hibernate.hbm2ddl.auto" value="none" />
|
||||
<property name="hibernate.jpa.compliance.query" value="false" />
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
@@ -0,0 +1,76 @@
|
||||
|
||||
-- Right
|
||||
|
||||
create sequence right_seq start 25;
|
||||
|
||||
create table x_right (
|
||||
right_id bigint PRIMARY KEY,
|
||||
code varchar(50) NOT NULL,
|
||||
name varchar(150) NOT NULL,
|
||||
jpa_active boolean NOT NULL,
|
||||
jpa_created timestamp NOT NULL,
|
||||
jpa_updated timestamp NOT NULL,
|
||||
jpa_version integer NOT NULL,
|
||||
CONSTRAINT unq_x_right_code UNIQUE(code)
|
||||
);
|
||||
|
||||
|
||||
-- user
|
||||
|
||||
create sequence user_seq start 25;
|
||||
|
||||
create table x_user (
|
||||
user_id bigint PRIMARY KEY,
|
||||
username varchar(150) NOT NULL,
|
||||
password varchar(150) NOT NULL,
|
||||
salt varchar(150) NOT NULL,
|
||||
title varchar(15) ,
|
||||
firstname varchar(150) NOT NULL,
|
||||
lastname varchar(150) NOT NULL,
|
||||
email varchar(150) NOT NULL,
|
||||
jpa_active boolean NOT NULL,
|
||||
jpa_created timestamp NOT NULL,
|
||||
jpa_updated timestamp NOT NULL,
|
||||
jpa_version integer NOT NULL,
|
||||
CONSTRAINT unq_x_user_username UNIQUE(username)
|
||||
);
|
||||
|
||||
create table user_to_right (
|
||||
user_id_fk bigint REFERENCES x_user,
|
||||
right_id_fk bigint REFERENCES x_right,
|
||||
PRIMARY KEY(user_id_fk, right_id_fk)
|
||||
);
|
||||
|
||||
|
||||
-- customer
|
||||
|
||||
create sequence customer_seq start 25;
|
||||
|
||||
create table customer (
|
||||
customer_id bigint PRIMARY KEY,
|
||||
customer_number varchar(150) NOT NULL,
|
||||
name varchar(150) NOT NULL,
|
||||
jpa_active boolean NOT NULL,
|
||||
jpa_created timestamp NOT NULL,
|
||||
jpa_updated timestamp NOT NULL,
|
||||
jpa_version integer NOT NULL,
|
||||
CONSTRAINT unq_customer_number UNIQUE(customer_number)
|
||||
);
|
||||
|
||||
|
||||
-- picture
|
||||
|
||||
create sequence picture_seq start 25;
|
||||
|
||||
create table picture (
|
||||
picture_id bigint PRIMARY KEY,
|
||||
username varchar(150),
|
||||
picture_date timestamp NOT NULL,
|
||||
comment TEXT,
|
||||
image TEXT,
|
||||
jpa_active boolean NOT NULL,
|
||||
jpa_created timestamp NOT NULL,
|
||||
jpa_updated timestamp NOT NULL,
|
||||
jpa_version integer NOT NULL,
|
||||
customer_id_fk bigint REFERENCES customer
|
||||
);
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "Add Customer Picture",
|
||||
"description": "Add a Customer Picture to the system",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"username": {
|
||||
"description": "The username from the user who uploads the picture",
|
||||
"type": "string"
|
||||
},
|
||||
"pharmacyName": {
|
||||
"description": "The Name from the pharmacy customer ",
|
||||
"type": "string"
|
||||
},
|
||||
"customerNumber": {
|
||||
"description": "The unique number from the pharmacy customer ",
|
||||
"type": "string"
|
||||
},
|
||||
"date": {
|
||||
"description": "The date when the picture is taken ",
|
||||
"type": "string"
|
||||
},
|
||||
"comment": {
|
||||
"description": "A free text comment field ",
|
||||
"type": "string"
|
||||
},
|
||||
"base64String": {
|
||||
"description": "The Picture content as base64 ",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"username",
|
||||
"pharmacyName",
|
||||
"customerNumber",
|
||||
"date",
|
||||
"comment",
|
||||
"base64String"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user