InventoryApiService.java

/*
 * Copyright 2024 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.api.v2.facade;

import lombok.Data;

import org.genesys.blocks.model.filters.NumberFilter;
import org.gringlobal.api.FilteredPage;
import org.gringlobal.api.model.AccessionInfo;
import org.gringlobal.api.model.AuditLogDTO;
import org.gringlobal.api.model.CooperatorInfo;
import org.gringlobal.api.model.GeographyInfo;
import org.gringlobal.api.model.InventoryActionDTO;
import org.gringlobal.api.model.InventoryDTO;
import org.gringlobal.api.model.InventoryDetailsDTO;
import org.gringlobal.api.model.InventoryInfo;
import org.gringlobal.api.model.InventoryMaintenancePolicyInfo;
import org.gringlobal.api.model.OrderRequestDTO;
import org.gringlobal.api.model.SiteInfo;
import org.gringlobal.custom.validation.javax.CodeValueField;
import org.gringlobal.custom.validation.javax.SimpleString;
import org.gringlobal.model.DateVersionEntityId;
import org.gringlobal.model.Inventory;
import org.gringlobal.model.community.CommunityCodeValues;
import org.gringlobal.service.filter.AccessionFilter;
import org.gringlobal.service.filter.InventoryActionFilter;
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 javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.List;
import java.util.Map;
import java.util.Set;

public interface InventoryApiService extends APIFilteredServiceFacade<InventoryDTO, Inventory, InventoryFilter>, LabelGenerator {

	void shareAttachment(Long attachId, List<Long> inventoryIds);

	InventoryDetailsDTO getInventoryDetails(String barcode);

	InventoryDetailsDTO getInventoryDetails(long inventoryId);

	void discardMaterial(Map<Long, Integer> discardQuantities);

	InventoryDTO setInventoryQuantity(InventoryQuantityRequestDTO inventoryQuantity);

	@Data
	class InventoryQuantityRequestDTO {
		@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;
	}

	List<InventoryDTO> assignLocation(@Valid AssignLocationRequestDTO assignLocationRequest);

	List<InventoryDTO> assignLocations(@Valid @Size(min = 1) List<AssignLocationRequestDTO> assignLocationRequests);

	@Data
	class AssignLocationRequestDTO {
		@NotNull
		public Location location;
		@NotNull
		@Size(min = 1)
		public Set<DateVersionEntityId.EntityIdAndModifiedDate> inventories;

		public static class Location {
			@NotNull
			public Long siteId;
			public String storageLocationPart1;
			public String storageLocationPart2;
			public String storageLocationPart3;
			public String storageLocationPart4;
		}
	}

	Page<ComparedSitesResponseDTO> compareSites(CompareSitesRequestDTO requestDTO, Pageable toPageRequest);

	@Data
	class CompareSitesRequestDTO {
		public AccessionFilter filter;
		@NotNull
		@Size(min = 2)
		public Map<Long, NumberFilter<Long>> sites;
	}

	@Data
	class ComparedSitesResponseDTO {
		private Long accessionId;
		private String accessionNumber;
		private Map<String, Long> siteInventories;
	}

	String assignBarcode(Long inventoryId);

	Page<AuditLogDTO> listAuditLogs(Long inventoryId, Pageable toPageRequest);

	List<InventoryDTO> splitInventory(SplitInventoryRequestDTO request);

	@Data
	class SplitInventoryRequestDTO {
		public SourceSplitInventory sourceSplitInventory;
		public List<SplitInventory> splits;

		public static class SourceSplitInventory extends DateVersionEntityId.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
			}
		}
	}

	Map<?, ?> inventoryOverview(String groupBy, InventoryFilter filter);


	Page<InventoryApiService.AggregatedInventoryQuantityDTO> aggregateQuantity(InventoryFilter filter, Pageable pageable);

	@Data
	class AggregatedInventoryQuantityDTO {
		public AccessionInfo accession;
		public String formTypeCode;
		public String availabilityStatusCode;
		public String quantityOnHandUnitCode;
		public long inventoryMaintenancePolicyCount;
		public long parentInventoryCount;
		public long inventoryCount;
		public double quantityOnHand;
	}

	OrderRequestDTO multiplicationOrder(MultiplicationOrderRequestDTO request);

	@Data
	class MultiplicationOrderRequestDTO {
		public SiteInfo site;
		@NotNull
		public CooperatorInfo cooperator;
		@NotNull
		@Size(min = 1)
		public Set<Long> inventoryIds;
		@NotNull
		public String orderTypeCode;
		@NotNull
		public String intendedUseCode;
	}

	FilteredPage<InventoryHarvestDTO, InventoryActionFilter> listInventoryHarvest(InventoryActionFilter filter, Pageable page);

	/**
	 * Data on the planted inventory, the associated HARVEST action, and the resulting harvested inventory.
	 */
	@Data
	class InventoryHarvestDTO {

		/** The planted inventory */
		@JsonUnwrapped
		private InventoryDTO plantedInventory;

		/** The resulting harvested inventory */
		private InventoryDTO harvestedInventory;

		/** The associated harvest action */
		private InventoryActionDTO harvestAction;

	}

	InventoryHarvestDTO createHarvestedInventory(InventoryHarvestRequest request);

	/**
	 * Data on the planted inventory, the associated HARVEST action, and the resulting harvested inventory.
	 */
	@Data
	class InventoryHarvestRequest {
		/** The source, planted inventory */
		@NotNull
		private InventoryInfo plantedInventory;

		/** The target site for harvested inventory */
		@NotNull
		private SiteInfo site;
		/** Inventory maintenance policy of the resulting harvested inventory */
		@NotNull
		private InventoryMaintenancePolicyInfo inventoryMantenancePolicy;

		/** The prefix for the new inventory */
		private String inventoryNumberPart1;
		/** The suffix for the new inventory */
		private String inventoryNumberPart3;

		/** Quantity on hand of harvested material */
		@Min(0)
		private Double quantityOnHand;

		/** Unit of measure of quantity of harvested material */
		@CodeValueField(CommunityCodeValues.UNIT_OF_QUANTITY)
		private String quantityOnHandUnitCode;

		/** Container type */
		@CodeValueField(CommunityCodeValues.CONTAINER_TYPE)
		private String containerTypeCode;

		/** Production location */
		private GeographyInfo productionGeography;

		// Storage location
		private String storageLocationPart1;
		private String storageLocationPart2;
		private String storageLocationPart3;
		private String storageLocationPart4;

		/** Is this the final batch of harvest for this inventory? */
		private boolean finalBatch = false;
	}

}