Author | Olamide Kolawole/Serhii Nosko |
---|
JIRA task | Folijet:
UXPROD-185
-
Getting issue details...
STATUS
Thunderjet Support: TBD |
Business Requirements | |
Architects Review | |
PO review | |
Revision History
Version | Date | Owner | Description | Reason |
---|
v1.0 | 06.26.2022 | | Initial version |
|
v1.1 | 06.28.2022 | | Add model schemas |
|
v1.2 | 06.30.2022 | | Add diagrams for Inventory creation |
|
v1.3 | 06.30.2022 | | Add diagrams for creating and opening orders |
|
The basic question here, do we need to create Instance, Holdings, Item by DI in mod-inventory using full power of marc file and Order mapping profile to map Instance, Holdings, Item, or use standard mapping capabilities provided by mod-orders.
Benefits of this approach:
- Inventory Instance, Holdings, Item can be mapped separately from mod-orders. In this case Orders field mapping profile can be adjusted with new Inventory field to map easily. Mod-orders creates Inventory from predefined set of fields from template on Create Orders UI and does not satisfy powerful mapping capabilities, that possible if mapping from the marc file
- Instance create post processing logic invoked in the same manner as in common DI flow to connect Inventory instance with source marc record
Drawbacks of this approach:
- More amount of work needed to create Inventory instance, holding, item, because not using approach from the box when mod-orders create these entities automatically during openning of the order
- New story for mod-orders needed to support new parameter: inventoryFlow with allowed values[Synchronized, Independent]. In this approach this param value should be set to Independent
Creating of Inventory Instance, Holdings, Item from Order basically is optional step, it's possible the library is ordering something that they do not want represented in Inventory (like a database that they maybe want to handle through the ERM app), or other random things that they do not plan to keep in their permanent collection.
This diagram shows scenario when user chooses to create Instance and/or Holdings and/or Item on the Orders field mapping profile.
This diagram shows sceanario when users chooses to NOT create Instance and/or Holdings and/or Item on the Orders field mapping profile.
Since for order mapping we use single mapping profile - we don't need separate topics for each Inventory type. So when DI_SRS_MARC_BIB_RECORD_CREATED event comes, data-import-processing-core will chose new CreateOrdersInventoryDataHandler based on action profile Create Orders.
CreateOrdersInventoryDataHandler will invoke Inventory Storage REST APIs to create Instance, Holdings, Item one by one based on Orders mapping profile configuration
@startuml
!pragma teoz true
!theme cerulean
skinparam backgroundColor white
autonumber "<b>[0]"
actor User as user
participant "mod-data-import" as mdi
participant "mod-srm" as srm
participant "mod-srs" as srs
participant "mod-inventory" as inv
participant "mod-inventory-storage" as invs
participant "mod-orders" as ord
user -> srm: create job definition (profile, type)
activate srm
srm -> srm: create job
srm --> user: jobId
deactivate srm
user -> mdi: upload MARC file and jobId
activate mdi
mdi -> srm: start DI initialization <<DI_INITIALIZATION_STARTED>>
srm -> srm: start job progress
mdi -> mdi: split to chunks, store in memory
mdi -> srm: export chunks to <<DI_RAW_RECORDS_CHUNK_READ>>
return
deactivate mdi
activate srm
srm -> srm: persist source chunks records
srm -> srs: parse chunks to <<DI_RAW_RECORDS_CHUNK_PARSED>>
deactivate srm
activate srs
srs -> srs: persist to database
srs -> srm: <<DI_PARSED_RECORDS_CHUNK_SAVED>>
deactivate srs
activate srm
srm -> srm: create JSON payload (profile, parsed MARC, mapping parameters)
deactivate srm
alt Order Mapping Profile has INVENTORY creation
srm -> inv: <<DI_SRS_MARC_BIB_RECORD_CREATED>>
activate inv
inv -> invs: OKAPI: create INSTANCE
activate invs
invs -> invs: persist to database
invs --> inv: result
deactivate invs
inv -> srs: <<DI_INVENTORY_INSTANCE_CREATED_READY_FOR_POST_PROCESSING>>
deactivate inv
activate srs
srs -> srs: Instance HRID is set to '001' MARC_BIB field,\nthe value from '001' is moved to '035',\nInstance ID is set to '999 ff i' field
srs -> inv: <<DI_SRS_MARC_BIB_INSTANCE_HRID_SET>>
deactivate srs
activate inv
inv -> invs: update INSTANCE
activate invs
invs -> invs: persist to DB
invs --> inv: result
deactivate invs
inv -> invs: OKAPI: create HOLDING
activate invs
invs -> invs: persist to DB
invs --> inv: result
deactivate invs
inv -> invs: OKAPI: create ITEMS
activate invs
invs -> invs: persist to DB
invs --> inv: result
deactivate invs
inv -> ord: <<DI_ORDER_READY_TO_CREATE>>
deactivate inv
else
srm -> ord: <<DI_ORDER_READY_TO_CREATE>>
end
Link to the standard flow of creating Instance, Holdings, Item in DI: 1. Create MARC Bib, create Instance, Holdings, Item
Benefits of this approach:
- Easy to implement, just use functionality to create Instance, Holdings, Item by mod-orders from the box. Dont need to implement any new functionality to create Inventory entities by DI. It can be suitable if it's enought mapping capabilities for creating Instance, Holdings, Item provided by UI Create Orders screen. If we are not going to add new fields to Orders mapping profile than Create orders UI has - in this case this approach is a good candidate.
Drawbacks of this approach:
- This approach not allows to use powerful mapping capabilities, that possible when creating Instance, Holdings, Item from marc file. So if new fields on the Order mapping profile would be added - this requires changes in mod-orders implementation
Example of Instance created by mod-orders:
{
"source":"FOLIO",
"title":"Nod",
"editions":[
""
],
"statusId":"daf2681c-25af-4202-a3fa-e58fdf806183",
"instanceTypeId":"30fffe0e-e985-4144-b2e2-1e8179bdb41f",
"publication":[
{
"publisher":"",
"dateOfPublication":""
}
],
"contributors":[
{
"contributorNameTypeId":"2b94c631-fca9-4892-a730-03ee529ffe2a",
"name":"Barnes, Adrian"
}
],
"identifiers":[
{
"identifierTypeId":"8261054f-be78-422d-bd51-4ed9f33c3422",
"value":"978-3-16-148410-0"
}
]
}
Java code to build Instance from mod-orders:
public JsonObject buildInstanceRecordJsonObject(CompositePoLine compPOL, JsonObject lookupObj) {
JsonObject instance = new JsonObject();
// MODORDERS-145 The Source and source code are required by schema
instance.put(INSTANCE_SOURCE, SOURCE_FOLIO);
instance.put(INSTANCE_TITLE, compPOL.getTitleOrPackage());
if (compPOL.getEdition() != null) {
instance.put(INSTANCE_EDITIONS, new JsonArray(singletonList(compPOL.getEdition())));
}
instance.put(INSTANCE_STATUS_ID, lookupObj.getString(INSTANCE_STATUSES));
instance.put(INSTANCE_TYPE_ID, lookupObj.getString(INSTANCE_TYPES));
if (compPOL.getPublisher() != null || compPOL.getPublicationDate() != null) {
JsonObject publication = new JsonObject();
publication.put(INSTANCE_PUBLISHER, compPOL.getPublisher());
publication.put(INSTANCE_DATE_OF_PUBLICATION, compPOL.getPublicationDate());
instance.put(INSTANCE_PUBLICATION, new JsonArray(singletonList(publication)));
}
if (isNotEmpty(compPOL.getContributors())) {
List<JsonObject> contributors = compPOL.getContributors().stream().map(compPolContributor -> {
JsonObject invContributor = new JsonObject();
invContributor.put(CONTRIBUTOR_NAME_TYPE_ID, compPolContributor.getContributorNameTypeId());
invContributor.put(CONTRIBUTOR_NAME, compPolContributor.getContributor());
return invContributor;
}).collect(toList());
instance.put(INSTANCE_CONTRIBUTORS, contributors);
}
if (isProductIdsExist(compPOL)) {
List<JsonObject> identifiers =
compPOL.getDetails()
.getProductIds()
.stream()
.map(pId -> {
JsonObject identifier = new JsonObject();
identifier.put(INSTANCE_IDENTIFIER_TYPE_ID, pId.getProductIdType());
identifier.put(INSTANCE_IDENTIFIER_TYPE_VALUE, pId.getProductId());
return identifier;
})
.collect(toList());
instance.put(INSTANCE_IDENTIFIERS, new JsonArray(identifiers));
}
return instance;
}
Example of Holdings created by mod-orders:
{
"instanceId":"d72102d6-093d-41e7-841f-2842c153e669",
"permanentLocationId":"53cf956f-c1df-410b-8bea-27f712cca7c0"
}
Java code to build Holdings from mod-orders:
private <T> CompletableFuture<T> createHoldingsRecord(String instanceId, String locationId, PostResponseType responseType,
Class<T> clazz, RequestContext requestContext) {
return getSourceId(requestContext)
.thenCompose(sourceId -> {
JsonObject holdingsRecJson = new JsonObject();
holdingsRecJson.put(HOLDING_INSTANCE_ID, instanceId);
holdingsRecJson.put(HOLDING_PERMANENT_LOCATION_ID, locationId);
holdingsRecJson.put(HOLDING_SOURCE, sourceId);
RequestEntry requestEntry = new RequestEntry(INVENTORY_LOOKUP_ENDPOINTS.get(HOLDINGS_RECORDS));
return restClient.post(requestEntry, holdingsRecJson, responseType, clazz, requestContext);
});
}
Example of Item created by mod-orders
{
"holdingsRecordId":"ae5eb95b-03f7-4ea4-ba4d-f8600343613a",
"status":{
"name":"On order"
},
"permanentLoanTypeId":"2b94c631-fca9-4892-a730-03ee529ffe27",
"purchaseOrderLineIdentifier":"d0ce84ab-5b62-4b78-8459-c4bc222ec33b",
"materialTypeId":"1a54b431-2e4f-452d-9cae-9cee66c9a892"
}
Java code to build Item from mod-orders:
/**
* Builds JsonObject representing inventory item minimal data. The schema is located directly in 'mod-inventory-storage' module.
*
* @param compPOL PO line to create Item Records for
* @param holdingId holding uuid from the inventory
* @return item data to be used as request body for POST operation
*/
private CompletableFuture<JsonObject> buildBaseItemRecordJsonObject(CompositePoLine compPOL, String holdingId, RequestContext requestContext) {
return getLoanTypeId(requestContext)
.thenApply(loanTypeId -> {
JsonObject itemRecord = new JsonObject();
itemRecord.put(ITEM_HOLDINGS_RECORD_ID, holdingId);
itemRecord.put(ITEM_STATUS, new JsonObject().put(ITEM_STATUS_NAME, ReceivedItem.ItemStatus.ON_ORDER.value()));
itemRecord.put(ITEM_PERMANENT_LOAN_TYPE_ID, loanTypeId);
itemRecord.put(ITEM_PURCHASE_ORDER_LINE_IDENTIFIER, compPOL.getId());
return itemRecord;
});
}
private void updateItemWithPieceFields(Piece piece, JsonObject item) {
Optional.ofNullable(piece.getEnumeration())
.ifPresentOrElse(enumeration -> item.put(ITEM_ENUMERATION, enumeration), () -> item.remove(ITEM_ENUMERATION));
Optional.ofNullable(piece.getChronology())
.ifPresentOrElse(chronology -> item.put(ITEM_CHRONOLOGY, chronology), () -> item.remove(ITEM_CHRONOLOGY));
Optional.ofNullable(piece.getDiscoverySuppress())
.ifPresentOrElse(discSup -> item.put(ITEM_DISCOVERY_SUPPRESS, discSup), () -> item.remove(ITEM_DISCOVERY_SUPPRESS));
}
@startuml
!pragma teoz true
!theme cerulean
skinparam backgroundColor white
autonumber "<b>[0]"
actor di as di
participant "mod-orders" as ord
participant "mod-orders-storage" as ords
participant "mod-source-record-manager" as srm
di -> ord: <<DI_ORDER_READY_TO_CREATE>>
activate ord
alt #White
ord -> ord: validate order payload
ord -> ords: persist order
ords --> ord: created order dto
ord -> ords: persist order lines
ords --> ord: created order lines dto
ord -> srm: <<DI_COMPLETED>>
else #Pink Creation Failed
ord -> srm: <<DI_ERROR>>
end
deactivate ord
@enduml
In this diagram assuming that aproach to create Inventory from mod-orders service chosen and user selects Create Instance, Holdings, Item from Order mapping profile
@startuml
!pragma teoz true
!theme cerulean
skinparam backgroundColor white
autonumber "<b>[0]"
actor di as di
participant "mod-orders" as ord
participant "mod-orders-storage" as ords
participant "mod-inventory" as inv
participant "mod-finance" as finance
participant "mod-source-record-manager" as srm
di -> ord: <<DI_ORDER_READY_TO_CREATE>>
activate ord
alt #White
ord -> ord: validate order payload
ord -> ords: persist order
ord -> ords: persist order lines
ord -> inv: create Instance, Holdings, Item
ord -> ords: persist Pieces
ord -> ord: connect Pieces with Inventory items
ord -> inv: update Invenory items with pieces connection
ord -> finance: create Encumbrances
ord -> ords: update order status to Open
ord -> srm: <<DI_COMPLETED>>
else #Pink Creation Failed
ord -> srm: <<DI_ERROR>>
end
deactivate ord
@enduml
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "composite purchase order with dereferenced/expanded orders fields",
"type": "object",
"properties": {
"id": {
"description": "UUID of this purchase order",
"type": "string",
"$ref": "../../common/schemas/uuid.json"
},
"approved": {
"description": "whether or not the purchase order has been approved",
"type": "boolean",
"default": false
},
"approvedById": {
"description": "UUID of the user approving the order",
"type": "object",
"$ref": "../../common/schemas/uuid.json"
},
"approvalDate": {
"description": "Date and time when purchase order was approved",
"type": "string",
"format": "date-time"
},
"assignedTo": {
"description": "UUID of the user this purchase order his assigned to",
"type": "string",
"$ref": "../../common/schemas/uuid.json"
},
"billTo": {
"description": "UUID of the billing address",
"type": "string",
"$ref": "../../common/schemas/uuid.json"
},
"closeReason": {
"description": "Close reason for purchase order. Some values are predefined and can trigger actions, such as Cancelled. See mod-orders-storage/src/main/resources/data/system/reasons-for-closure",
"type": "object",
"$ref": "../../mod-orders-storage/schemas/close_reason.json"
},
"dateOrdered": {
"description": "Date and time when purchase order was opened",
"type": "string",
"format": "date-time",
"readonly": true
},
"manualPo": {
"description": "if true, order cannot be sent automatically, e.g. via EDI",
"type": "boolean"
},
"notes": {
"description": "free-form notes associated with this purchase order",
"id": "notes",
"type": "array",
"items": {
"type": "string"
}
},
"poNumber": {
"description": "A human readable ID assigned to this purchase order",
"type": "string",
"pattern": "^[a-zA-Z0-9]{1,22}$"
},
"poNumberPrefix": {
"description": "Purchase order number prefix",
"type": "string"
},
"poNumberSuffix": {
"description": "Purchase order number suffix",
"type": "string"
},
"orderType": {
"description": "the purchase order type",
"type": "string",
"enum": [
"One-Time",
"Ongoing"
]
},
"reEncumber": {
"description": "indicates this purchase order should be re-encumbered each fiscal year. Only applies to ongoing orders",
"type": "boolean",
"default": false
},
"ongoing": {
"description": "Ongoing information associated with this order",
"type": "object",
"$ref": "../../mod-orders-storage/schemas/ongoing.json"
},
"shipTo": {
"description": "UUID of the shipping address",
"type": "string",
"$ref": "../../common/schemas/uuid.json"
},
"template": {
"description": "The ID of the order template used for this order. Applies to both PO and POL",
"type": "string",
"$ref": "../../common/schemas/uuid.json"
},
"totalEstimatedPrice": {
"description": "total estimated price of this purchase order",
"type": "number"
},
"totalEncumbered": {
"description": "Total encumbered for the order",
"type": "number",
"readonly": true
},
"totalExpended": {
"description": "Total expended for the order",
"type": "number",
"readonly": true
},
"totalItems": {
"description": "total number of items included in the purchase order",
"type": "integer"
},
"vendor": {
"description": "UUID of the vendorDetails record",
"type": "string",
"$ref": "../../common/schemas/uuid.json"
},
"workflowStatus": {
"description": "the workflow status for this purchase order",
"type": "string",
"$ref": "../../mod-orders-storage/schemas/workflow_status.json"
},
"compositePoLines": {
"description": "a list of completely de-referenced purchase order lines",
"id": "compositePoLines",
"type": "array",
"items": {
"type": "object",
"$ref": "composite_po_line.json"
}
},
"acqUnitIds": {
"description": "acquisition unit ids associated with this purchase order",
"type": "array",
"items": {
"$ref": "../../common/schemas/uuid.json"
}
},
"tags": {
"type": "object",
"description": "arbitrary tags associated with this purchase order",
"$ref": "../../../raml-util/schemas/tags.schema"
},
"metadata": {
"type": "object",
"$ref": "../../../raml-util/schemas/metadata.schema",
"readonly": true
},
"needReEncumber": {
"description": "Indicates that order needs to be re-encumbered",
"type": "boolean",
"readonly": true
}
},
"additionalProperties": false,
"required": [
"vendor",
"orderType"
]
}
Field name | Allowed values | Description |
---|
orderType | [One-Time, Ongoing] | DI will setup only One-Time order type |
vendor | - | Vendor that user chooses on Order field mapping profile |
Business requirements to anxwer why provided fields do not necessary to populate
Field name | Allowed values | Description |
---|
reEncumber | [True, False] | Indicates this purchase order should be re-encumbered each fiscal year |
needReEncumber | [True, False] | Indicates that order needs to be re-encumbered |
ongoing | - | Ongoing object includes these fields: interval, isSubscription, manualRenewal, notes, reviewPeriod, renewalDate, reviewDate All these fields should not be populated from DI, because DI does not support ongoing orders. |
template | - | Predefined template to create order from |
notes | - | Free-form notes associated with this purchase order |
tags | - | List of simple tags that can be added to the purchase order |
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "composite purchase order line with dereferenced/expanded orders fields",
"type": "object",
"properties": {
"id": {
"description": "UUID identifying this purchase order line",
"type": "string",
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
},
"edition": {
"description": "edition of the material",
"type": "string"
},
"checkinItems": {
"description": "if true this will toggle the Check-in workflow for details associated with this PO line",
"type": "boolean",
"default": false
},
"instanceId": {
"description": "UUID of the instance record this purchase order line is related to",
"type": "string",
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
},
"agreementId": {
"description": "UUID of the agreement this purchase order line is related to",
"type": "string",
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
},
"acquisitionMethod": {
"description": "UUID of the acquisition method for this purchase order line",
"type": "string",
"$ref": "../../common/schemas/uuid.json"
},
"automaticExport": {
"description": "if true then line will be marked as available to export in the EDIFACT format or other format",
"type": "boolean",
"default": false
},
"alerts": {
"description": "alerts associated with this purchase order line",
"id": "alerts",
"type": "array",
"items": {
"description": "an alert record",
"type": "object",
"$ref": "../../mod-orders-storage/schemas/alert.json"
}
},
"cancellationRestriction": {
"description": "whether or not there are cancellation restrictions for this purchase order line",
"type": "boolean"
},
"cancellationRestrictionNote": {
"description": "free-form notes related to cancellation restrictions",
"type": "string"
},
"claims": {
"description": "claims associated with this purchase order line",
"id": "claims",
"type": "array",
"items": {
"description": "a claim record",
"type": "object",
"$ref": "../../mod-orders-storage/schemas/claim.json"
}
},
"collection": {
"description": "whether or not this purchase order line is for a collection",
"type": "boolean"
},
"contributors": {
"description": "list of contributors to the material",
"id": "contributors",
"type": "array",
"items": {
"type": "object",
"$ref": "../../mod-orders-storage/schemas/contributor.json"
}
},
"cost": {
"description": "cost details associated with this purchase order line",
"type": "object",
"$ref": "../../mod-orders-storage/schemas/cost.json"
},
"description": {
"description": "description of the material",
"type": "string"
},
"details": {
"description": "details about this purchase order line",
"type": "object",
"$ref": "../../mod-orders-storage/schemas/details.json"
},
"donor": {
"description": "the donor contributing to this purchase order line",
"type": "string"
},
"eresource": {
"description": "eresource-related details of this purchase order line",
"type": "object",
"$ref": "../../mod-orders-storage/schemas/eresource.json"
},
"fundDistribution": {
"description": "the UUIDs of the fund distribution records for this purchase order line",
"id": "fundDistribution",
"type": "array",
"items": {
"description": "a fund distribution record",
"type": "object",
"$ref": "../../mod-orders-storage/schemas/fund_distribution.json"
}
},
"isPackage": {
"description": "Indicates that this POL is for a package",
"type": "boolean",
"default": false
},
"locations": {
"description": "a list of the location records for this purchase order line",
"id": "locations",
"type": "array",
"items": {
"description": "The location details",
"type": "object",
"$ref": "../../mod-orders-storage/schemas/location.json"
}
},
"lastEDIExportDate": {
"description": "The last date when line was exported in the EDIFACT file",
"type": "string",
"format": "date-time"
},
"orderFormat": {
"description": "The purchase order line format",
"type": "object",
"$ref": "../../mod-orders-storage/schemas/order_format.json"
},
"packagePoLineId": {
"description": "UUID referencing the poLine that represents the package that this POLs title belongs to",
"$ref": "../../common/schemas/uuid.json"
},
"paymentStatus": {
"description": "The purchase order line payment status",
"type": "string",
"$ref": "../../mod-orders-storage/schemas/payment_status.json"
},
"physical": {
"description": "details of this purchase order line relating to physical materials",
"type": "object",
"$ref": "../../mod-orders-storage/schemas/physical.json"
},
"poLineDescription": {
"description": "purchase order line description",
"type": "string"
},
"poLineNumber": {
"description": "A human readable number assigned to this PO line",
"type": "string",
"pattern": "^[a-zA-Z0-9]{1,22}-[0-9]{1,3}$",
"readonly": true
},
"publicationDate": {
"description": "date (year) of the material's publication",
"type": "string"
},
"publisher": {
"description": "publisher of the material",
"type": "string"
},
"purchaseOrderId": {
"description": "UUID of this parent purchase order",
"type": "string",
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
},
"receiptDate": {
"description": "date the purchase order line was received",
"type": [
"null",
"string"
],
"format": "date-time"
},
"receiptStatus": {
"description": "The purchase order line receipt status",
"type": "object",
"$ref": "../../mod-orders-storage/schemas/receipt_status.json"
},
"renewalNote": {
"description": "Renewal note for this purchase order line",
"type": "string"
},
"reportingCodes": {
"description": "a list of reporting codes associated with this purchase order line",
"id": "reportingCodes",
"type": "array",
"items": {
"type": "object",
"$ref": "../../mod-orders-storage/schemas/reporting_code.json"
}
},
"requester": {
"description": "who requested this purchase order line",
"type": "string"
},
"rush": {
"description": "whether or not this is a rush order",
"type": "boolean"
},
"selector": {
"description": "who selected this material",
"type": "string"
},
"source": {
"description": "the source of this purchase order line",
"type": "object",
"$ref": "../../mod-orders-storage/schemas/source.json"
},
"tags": {
"description": "arbitrary tags associated with this purchase order line",
"id": "tags",
"type": "object",
"$ref": "../../../raml-util/schemas/tags.schema"
},
"titleOrPackage": {
"description": "title of the material",
"type": "string"
},
"vendorDetail": {
"description": "details related to the vendor of this purchase order line",
"type": "object",
"$ref": "../../mod-orders-storage/schemas/vendor_detail.json"
},
"metadata": {
"type": "object",
"$ref": "../../../raml-util/schemas/metadata.schema",
"readonly": true
}
},
"additionalProperties": false,
"required": [
"acquisitionMethod",
"cost",
"orderFormat",
"source",
"titleOrPackage"
]
}
Field name | Allowed values | Description |
---|
acquisitionMethod | - | The UUID format string |
cost | - | The purchase order line cost. Includes fields: "listUnitPrice", "listUnitPriceElectronic", "currency", "additionalCost", "discount", "discountType", "exchangeRate", "quantityPhysical", "quantityElectronic", "poLineEstimatedPrice", "fyroAdjustmentAmount" Currency field is required. |
orderFormat | [Electronic Resource, P/E Mix, Physical Resource, Other] | The purchase order line format |
source | [User, API, EDI, MARC, EBSCONET] | The source of the order |
titleOrPackage | - | The title of the materials |
Business requirements to answer why provided fields do not necessary to populate
Field name | Allowed values | Description |
---|
isPackage | [True, False] | Indicates that this POL is for a package. Default - false |
packagePoLineId | - | Specify package po line id, applicable only package orders |
renewalNote | - | Specify renewal note, applicable only for ongoing orders |
This schema represents a field 'physcal' of PO line in order. To disable creating Inventory records need to set createInventory field to 'None'
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "purchase order line physical material details",
"type": "object",
"properties": {
"createInventory": {
"description": "Shows what inventory objects need to be created for physical resource",
"type": "string",
"enum": [
"Instance, Holding, Item",
"Instance, Holding",
"Instance",
"None"
]
},
"materialType": {
"description": "UUID of the material Type",
"type": "string",
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
},
"materialSupplier": {
"description": "UUID of the material supplier record",
"type": "string",
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
},
"expectedReceiptDate": {
"description": "vendor agreed date prior to the Receipt Due date item is expected to be received by",
"type": [
"string",
"null"
],
"format": "date-time"
},
"receiptDue": {
"description": "date item should be received by",
"type": [
"string",
"null"
],
"format": "date-time"
},
"volumes": {
"description": "list of volumes included to the physical material",
"type": "array",
"items": {
"description": "the identifier of volume",
"type": "string"
}
}
},
"additionalProperties": false,
"required": [
"volumes"
]
}
This schema represents a field 'eresource' of PO line in order. To disable creating Inventory records need to set createInventory field to 'None'
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "purchase order line e-resource details",
"type": "object",
"properties": {
"activated": {
"description": "whether or not this resource is activated",
"type": "boolean",
"default": false
},
"activationDue": {
"description": "number of days until activation, from date of order placement",
"type": "integer"
},
"createInventory": {
"description": "Shows what inventory objects need to be created for electronic resource",
"type": "string",
"enum": [
"Instance, Holding, Item",
"Instance, Holding",
"Instance",
"None"
]
},
"trial": {
"description": "whether or not this is a trial",
"type": "boolean",
"default": false
},
"expectedActivation": {
"description": "expected date the resource will be activated",
"type": "string",
"format": "date-time"
},
"userLimit": {
"description": "the concurrent user-limit",
"type": "integer"
},
"accessProvider": {
"description": "UUID of the access provider",
"type": "string",
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
},
"license": {
"description": "License record",
"type": "object",
"$ref": "license.json"
},
"materialType": {
"description": "UUID of the material Type",
"type": "string",
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
},
"resourceUrl": {
"description": "Electronic resource can be access via this URL",
"type": "string",
"pattern": "\\b((?:[a-z][\\w-]+:(?:\/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}\/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?]))"
}
},
"additionalProperties": false
}
DI will communicate with mod-orders using messaging(the same approach as for mod-invoices)
Applies when user choses to create pending order on the field mapping profile screen.
There is field in compositePurchaseOrder request payload named workflowStatus, it will be PENDING by default.
For creating orders CreateOrderEventHandler will use the same implementation as corresponding endpoint uses.
Method | Url | Request parameters | Request payload | Description |
---|
POST | /orders/composite-orders | lang | compositePurchaseOrder | Post a purchase order (PO) and a number of PO lines; record fund transactions corresponding to the order. Only in case an acquisition unit has to be assigned to the Order it is required that user should have extra permission orders.acquisitions-units-assignments.item.post to create an purchase order. |
Applies when user choses to create open order on the field mapping profile screen.
There is field in compositePurchaseOrder request payload named workflowStatus, it should be set as OPEN.
For creating orders CreateOrderEventHandler will use the same implementation as corresponding endpoint uses.
Method | Url | Request parameters | Request payload | Description |
---|
POST | /orders/composite-orders | lang | compositePurchaseOrder | Post a purchase order (PO) and a number of PO lines; record fund transactions corresponding to the order. Only in case an acquisition unit has to be assigned to the Order it is required that user should have extra permission orders.acquisitions-units-assignments.item.post to create an purchase order. |
Question | Status | Answer |
---|
Oder payload has field 'approved', that is false by default. What value for this field DI should populate? | | |
When we have situation that max order lines limit is 10, but have 15 order lines and 2 orders in marc file, how they should be mapped? | | |
PO number can be auto generated by mod-orders system. Does it necessary to place this field on Order mapping profile? | | |
When creating order lines - its necessary to specify order source from these allowed values: [User, API, EDI, MARC, EBSCONET]. For our case it should be MARC? | | MARC value should be used. |
Do we need to support orders check-in after receiving? | | No, we dont need to support check-in |
Is it possible scenario when DI going to open order, but not create any Instance, Holdings. Item? | | Yes, it's possible the library is ordering something that they do not want represented in Inventory (like a database that they maybe want to handle through the ERM app), or other random things that they do not plan to keep in their permanent collection. |
Question | Status | Answer |
---|
We use database tables for DI handlers deduplication. Mod-orders does not have schema in DB and any DB related code. Do we need to follow the same approach with introducing schema as we did in mod-inventory | |
|
If we are going to create Inventory Instance, Holdings, Item separately - need to discuss with Thunderjet possibility to indroduce new order parameter inventoryFlow with allowed values: [Synchronized, Independent], the same as did in Order Receiving flow | |
|
Description | Module | Story |
---|
Create default order mapping profile | data-import-converter-storage | TBD |
Extend mapping engine with ability to create order and multiple order lines from the same MARC record. | data-import-processing-core | TBD |
Adjust mor-orders to validate purchase order lines limit from Orders mapping profile |
|
|
Add kafka handlers in mod-orders | mod-orders | TBD |