InventoryDTO.java

/*
 * Copyright 2026 Global Crop Diversity Trust
 * Licensed under the Apache License, Version 2.0
 * See LICENSE file in project root folder or http://www.apache.org/licenses/LICENSE-2.0
 */

package org.gringlobal.api.model;

import static org.gringlobal.model.community.CommunityCodeValues.CODE_VALUE_LENGTH;

import java.util.Date;
import javax.validation.constraints.Min;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Positive;
import javax.validation.constraints.Size;

import org.genesys.java.annotations.BulkEditable;
import org.genesys.java.annotations.FormReadOnly;
import org.genesys.java.annotations.SingleEditable;

import org.gringlobal.api.NestedEntityFullUpdate;
import org.gringlobal.custom.validation.javax.CodeValueField;
import org.gringlobal.custom.validation.javax.SimpleString;
import org.gringlobal.model.community.CommunityCodeValues;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import com.fasterxml.jackson.annotation.JsonProperty;

@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
public class InventoryDTO extends CooperatorOwnedDTO {

	/** Site where this inventory is maintained */
	private SiteInfo site;

	/** The accession */
	@BulkEditable(false)
	@SingleEditable(false)
	private AccessionInfo accession;

	/** Complete inventory number, composed of {@link inventoryNumberPart1} + {@link inventoryNumberPart2} + optional {@link inventoryNumberPart3} */
	@FormReadOnly
	@Size(max = 128) @JsonProperty(access = JsonProperty.Access.READ_ONLY)
	private String inventoryNumber;

	/** Inventory number: prefix */
	@Size(max = 50) @SimpleString
	private String inventoryNumberPart1;

	/** Inventory number: sequential part */
	private Long inventoryNumberPart2;

	/** Inventory number: optional suffix */
	@Size(max = 50) @SimpleString
	private String inventoryNumberPart3;

	/** Germplasm type, mandatory. */
	@Size(max = CODE_VALUE_LENGTH) @CodeValueField(CommunityCodeValues.GERMPLASM_FORM)
	private String formTypeCode;

	/** Barcode that uniquely refers to this inventory */
	@BulkEditable(false)
	@Size(max = 100) private String barcode;

	/** DOI assigned to the inventory, not the same as that of the accession! */
	@BulkEditable(false)
	@Pattern(regexp = "^10\\.[0-9]+(\\.[0-9]+)*/.+")
	private String doi;

	/** Preferred name of this germplasm */
	@FormReadOnly
	private String preferredName;

	private Long parentInventoryId;

	@FormReadOnly
	private String parentInventoryNumber;

	/** Generation number */
	private Long generation;

	/** Date of propagation of this material */
	private Date propagationDate;

	/** Precision of {@link propagationDate} */
	@Size(max = CODE_VALUE_LENGTH) @CodeValueField(CommunityCodeValues.DATE_FORMAT)
	private String propagationDateCode;

	/** Geography where this material was produced */
	private GeographyInfo productionLocationGeography;

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

	/** Unit of quantity on hand {@link quantityOnHand} */
	@Size(max = CODE_VALUE_LENGTH) @CodeValueField(CommunityCodeValues.UNIT_OF_QUANTITY)
	private String quantityOnHandUnitCode;

	/** Weight of 100 seed in grams */
	@Positive private Double hundredSeedWeight;

	@Size(max = CODE_VALUE_LENGTH) @CodeValueField(CommunityCodeValues.CONTAINER_TYPE)
	private String containerTypeCode;

	@Size(max = 20) private String storageLocationPart1;

	@Size(max = 20) private String storageLocationPart2;

	@Size(max = 20) private String storageLocationPart3;

	@Size(max = 20) private String storageLocationPart4;

	private InventoryMaintenancePolicyInfo inventoryMaintenancePolicy;

	private Boolean isAutoDeducted;
	private Boolean isAvailable;
	private Boolean isDistributable;

	@Size(max = CODE_VALUE_LENGTH) @CodeValueField(CommunityCodeValues.GERMPLASM_FORM)
	private String distributionDefaultFormCode;

	@Size(max = CODE_VALUE_LENGTH) @CodeValueField(CommunityCodeValues.UNIT_OF_QUANTITY)
	private String distributionUnitCode;

	@Min(0) private Double distributionCriticalQuantity;

	@Min(0) private Double distributionDefaultQuantity;

	@Min(0) private Double regenerationCriticalQuantity;

	private Double latitude;
	private Double longitude;

	@Size(max = CODE_VALUE_LENGTH) @CodeValueField(value = CommunityCodeValues.PATHOGEN_STATUS, indexed = true)
	private String pathogenStatusCode;

	@Size(max = CODE_VALUE_LENGTH) @CodeValueField("INVENTORY_PLANT_SEX")
	private String plantSexCode;

	@Size(max = CODE_VALUE_LENGTH) @CodeValueField("INVENTORY_POLLINATION_METHOD")
	private String pollinationMethodCode;

	@Size(max = CODE_VALUE_LENGTH) @CodeValueField("INVENTORY_POLLINATION_VECTOR")
	private String pollinationVectorCode;

	private MethodInfo preservationMethod;

	private MethodInfo regenerationMethod;

	private Date availabilityEndDate;

	private Date availabilityStartDate;

	/** Availability Status: Status of the inventory availability. Uses INVENTORY_AVAILABILITY_STATUS vocabulary. */
	@Size(max = CODE_VALUE_LENGTH) @CodeValueField(CommunityCodeValues.INVENTORY_AVAILABILITY_STATUS)
	private String availabilityStatusCode;

	private String availabilityStatusNote;

	@CodeValueField("INVENTORY_AVAILABILITY_REASON")
	@Size(max = CODE_VALUE_LENGTH) private String availabilityReasonCode;

	private Integer distributionRank;

	@NestedEntityFullUpdate
	private InventoryExtraDTO extra;

	@BulkEditable(false)
	private InventoryInfo backupInventory;

	private String rootstock;

	private String webAvailabilityNote;

	/** General remarks about the inventory. */
	private String note;

	@FormReadOnly
	private Boolean isSystemInventory;

	public InventoryDTO(Long id) {
		this.id = id;
	}
}