Skip to content

Palmira: Additional models and endpoints

@1cgiar/palmira is requesting additional models and CRUD API endpoints to enhance existing GGCE schema.

Please add the following entities to org.gringlobal.model.community package:

  • Location represents a physical place (the original name CONTAINER is easily confused with material container (Alu pack, Glass jar)). Location#parentLocation allows to organize places into a highly dynamic tree structure.
  • LocationData allows for attaching user-defined attributes (originally named CONTAINER_DATA)
  • LocationReservation keeps track of "bookings" at one location (proposed name was STORAGE_CONTAINER_MAP)
/**
 * Location represents a physical place at a {@link Site}: buildings - rooms - racks, fields, greenhouses, etc.
 * 
 * Locations are organized into a tree structure where
 * each location with <code>parentLocation == null</code> starts a new tree at the {#link Site}.
 *
 * Location may declare its {@link #capacity} and {@link #capacityUnitCode}, specifying
 * its total available area/volume/length/duration.
 */
class Location extends CooperatorOwnedModel implements SelfCleaning {
 @ManyToOne(required = false)
 private Location parentLocation; // Locations have a hierarchical structure
 @NotNull @ManyToOne(required = true)
 private Site site; // Needs index

 @NotNull @SimpleString
 private String locationNumberPart1;
 private Long locationNumberPart2;
 @SimpleString
 private String locationNumberPart3;
 @NotNull @CodeValueField("LOCATION_TYPE")
 private String locationTypeCode;
 @ManyToOne(required=false)
 private Geography geography;
 @NotNull
 private String barcode; // in @PrePersist use UUID.randomUUID().toString() if blank
 @Min(0)
 private int capacity = 0; // The capacity of this location, may be 0
 @CodeValueField("UNIT_OF_CAPACITY")
 private String capacityUnitCode; // If capacity != 0 then it must be provided
}

/**
 * LocationData allows for attaching user-defined attributes to each {#link Location}.
 */
class LocationData extends CooperatorOwnedModel implements SelfCleaning {
 private Location location;
 @NotNull @CodeValueField("LOCATION_PROPERTY")
 private String locationPropertyCode;
 @NotNull
 private String value;
}

/**
 * Actions are performed on {@link Location}s.
 */
class LocationAction extends AbstractAction<LocationAction> {
 // No extra fields for now
 @Override
 @CodeValueField("LOCATION_ACTION")
 public String getActionNameCode() {
  return this.actionNameCode;
 }
}

/**
 * Describes a reservation of capacity at a {@link Location} for the specified
 * time frame (start and end date). A reservation is PENDING if the start date is
 * in the future, it is ACTIVE if `startDate < now < endDate`
 */
class LocationReservation extends CooperatorOwnedModel implements SelfCleaning {
 @NotNull @ManyToOne(required = true)
 private Location location;
 @NotNull @ManyToOne(required = false)
 private Inventory inventory; // Does not require an inventory to reserve a location
 @NotNull @Column(name = "start_date") @Temporal(TemporalType.DATE)
 protected LocalDate startDate; // inclusive
 @NotNull @Column(name = "end_date") @Temporal(TemporalType.DATE)
 protected LocalDate endDate; // inclusive, must be greater or equal to startDate!
 @IgnoreField
 @Formula("datediff( day, start_date, end_date )") // FIXME or datediff() + 1?
 private Integer reservedDays; // calculated field
 @Min(1)
 private int size; // The amount of reserved capacity at Location expressed in Location's capacityUnitCode
 @Min(0)
 private int offset = 0; // The offset is used to indicate where at the Location's capacity the space is reserved
}

We will need LocationFilter and LocationReservationFilter. Use sensible filtering options, we'll update later on demand.

Please add the following services:

LocationServiceImpl extends FilteredCRUDService<Location> implements LocationService {

  protected static class ActionSupport extends BaseActionSupport<> {...
  class LocationDataService extends CRUDService<LocationData> {...
}

LocationReservationServiceImpl extends FilteredCRUDService<Location> implements LocationService {
...
}

Add the basic controllers: LocationController extends CRUDController at /location and LocationReservationController at /location/reservation.

Note to self: These POJOs are based on several teleconferences around the excel file Prueba_escritorio_contenedores.xlsx.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information