InventoryService.java
/*
* Copyright 2020 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gringlobal.service;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.genesys.blocks.model.filters.NumberFilter;
import org.gringlobal.custom.validation.javax.CodeValueField;
import org.gringlobal.custom.validation.javax.SimpleString;
import org.gringlobal.model.Accession;
import org.gringlobal.model.AccessionInvAttach;
import org.gringlobal.model.AccessionInvGroup;
import org.gringlobal.model.AccessionInvName;
import org.gringlobal.model.Cooperator;
import org.gringlobal.model.DateVersionEntityId.EntityIdAndModifiedDate;
import org.gringlobal.model.Inventory;
import org.gringlobal.model.InventoryAction;
import org.gringlobal.model.InventoryQualityStatus;
import org.gringlobal.model.InventoryViability;
import org.gringlobal.model.OrderRequest;
import org.gringlobal.model.SeedInventoryExtra;
import org.gringlobal.model.Site;
import org.gringlobal.model.community.CommunityCodeValues;
import org.gringlobal.persistence.InventoryRepositoryCustom;
import org.gringlobal.service.filter.AccessionFilter;
import org.gringlobal.service.filter.InventoryFilter;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import lombok.Data;
/**
* The Interface InventoryService.
*/
public interface InventoryService extends FilteredCRUDService2<Inventory, InventoryFilter> {
Inventory assureSystemInventory(Accession accession);
int ensureSystemInventories();
InventoryDetails getInventoryDetails(Inventory inventory);
/**
* Set inventory quantity on hand
*
* @param inventoryQuantity Inventory quantity
* @return the updated inventory
*/
Inventory setInventoryQuantity(@Valid InventoryQuantityRequest inventoryQuantity);
/**
* Generate barcode for Inventory based on a template
*
* @param inventory the inventory
* @return the barcode
*/
String assignBarcode(Inventory inventory);
/**
* Discard the specified quantities for inventories.
*
* @param discardQuantities A map of `inventoryId` and `quantity` to discard.
*/
void discardMaterial(@NotNull Map<Long, Integer> discardQuantities);
/**
* Get the aggregated `quantityOnHand` for specified inventories.
*
* @param filter inventory filters
* @param page pagination and sort options
*
* @return a {@link Page} of {@link InventoryRepositoryCustom.AggregatedInventoryQuantity}.
*/
Page<InventoryRepositoryCustom.AggregatedInventoryQuantity> aggregateQuantity(@NotNull InventoryFilter filter, Pageable page);
List<Inventory> splitInventory(@Valid SplitInventoryRequest splitInventoryRequest);
List<Inventory> assignLocation(@Valid AssignLocationRequest assignLocationRequest);
List<Inventory> assignLocations(@Valid @Size(min = 1) List<AssignLocationRequest> assignLocationRequests);
/**
* Get inventory by barcode value
*
* @param barcode the barcode
* @return the inventory
*/
Inventory getByBarcode(String barcode);
class AssignLocationRequest {
@NotNull
public Location location;
@NotNull
@Size(min = 1)
public Set<EntityIdAndModifiedDate> inventories;
public static class Location {
@NotNull
public Long siteId;
public String storageLocationPart1;
public String storageLocationPart2;
public String storageLocationPart3;
public String storageLocationPart4;
}
}
class InventoryDetails {
@JsonUnwrapped
public Inventory inventory;
public List<AccessionInvName> names;
public List<AccessionInvAttach> attachments;
public List<AccessionInvGroup> groups;
public List<InventoryAction> actions;
public List<InventoryViability> viability;
public List<InventoryQualityStatus> qualityStatus;
}
class InventoryQuantityRequest {
@NotNull
public long id; // inventory id
@Min(value = 0)
public double quantityOnHand; // Required new quantity
@CodeValueField("UNIT_OF_QUANTITY")
public String quantityOnHandUnitCode;
@Min(value = 0)
public Double hundredSeedWeight;
public String note;
}
static class SplitInventoryRequest {
public SourceSplitInventory sourceSplitInventory;
public List<SplitInventory> splits;
public static class SourceSplitInventory extends EntityIdAndModifiedDate {
public String note; // note to add to split action
@Min(value = 0)
public Double quantityOnHand; // optionally update quantity
@CodeValueField("UNIT_OF_QUANTITY")
public String quantityOnHandUnitCode;
@CodeValueField("CONTAINER_TYPE")
public String containerTypeCode;
}
public static class SplitInventory {
public InventoryMaintenancePolicyId inventoryMaintenancePolicy;
@NotNull @SimpleString
public String inventoryNumberPart1;
@Min(-1)
public Long inventoryNumberPart2;
public String inventoryNumberPart3;
@Min(value = 0)
public Double quantityOnHand; // optional quantity of the new inventory
@CodeValueField("UNIT_OF_QUANTITY")
public String quantityOnHandUnitCode; // optional unit code
@CodeValueField("CONTAINER_TYPE")
public String containerTypeCode; // optional container type
public String note;
public static class InventoryMaintenancePolicyId {
@NotNull
public Long id; // inventory maintenance policy id
}
}
}
/**
* Inventory overview.
*
* @param groupBy Group by property of Inventory
* @param filter the inventory filters
* @return the map with statistics
*/
Map<?, ?> inventoryOverview(String groupBy, InventoryFilter filter);
/**
* Recalculate all inventory_number fields in the DB for existing records.
*/
void recalculateAllInventoryNumbers();
/**
* Calculate {@link Inventory#inventoryNumber} if null
*/
void assignMissingInventoryNumbers();
/**
* Create multiplication OrderRequest for inventories.
*/
OrderRequest multiplicationOrder(Site site, Set<Long> inventoryIds, Cooperator multiplicationCooperator, String orderType, String intendedUseCode);
/**
* Share attachment for inventories.
*/
void shareAttachment(Long attachId, List<Long> inventoryIds);
/**
* Update moisture content for SeedInventoryExtra.
*/
SeedInventoryExtra updateMoistureContent(SeedInventoryExtra extra, MoistureContentRequest request);
class MoistureContentRequest {
@Min(0) @Max(100)
public Float moistureContent;
public Date moistureContentDate;
@CodeValueField(CommunityCodeValues.DATE_FORMAT)
public String moistureContentDateCode;
}
/**
* Compare the number of inventories across sites
*/
Page<ComparedSitesResponse> compareSites(AccessionFilter filter, Map<Long, NumberFilter<Long>> sites, Pageable page);
@Data
public static class ComparedSitesResponse {
private Long accessionId;
private String accessionNumber;
private Map<String, Long> siteInventories;
}
}