diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e7fe7c3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,28 @@ +name: CI + +on: + push: + branches: + - main + - develop + pull_request: + branches: + - main + - develop + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup .NET Core SDK '3.1' + uses: actions/setup-dotnet@v1.7.2 + with: + dotnet-version: '3.1' + - name: Install dependencies + run: dotnet restore + - name: Build + run: dotnet build --configuration Release --no-restore + - name: Test + run: dotnet test --no-restore --verbosity normal \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..bd59b8f --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,32 @@ +name: Release + +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+" + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Set VERSION variable from tag + run: echo "VERSION=${GITHUB_REF/refs\/tags\/v/}" >> $GITHUB_ENV + - name: Set VERSION_NUMBER + run: echo "VERSION_NUMBER=$(echo $VERSION | grep -i -P -o '^\d+\.\d+\.\d+')" >> $GITHUB_ENV + - name: Build artifacts + run: dotnet build --configuration Release /p:Version=${{ env.VERSION }} /p:FileVersion=${{ env.VERSION_NUMBER }}.${{ github.run_number }} + - name: Package + run: mkdir -p ./dist; nuget pack ./AgGatewayShippedItemInstancePlugin.nuspec -outputdirectory ./dist -version ${{ env.VERSION }} + - name: Push release to Github + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ./dist/AgGatewayShippedItemInstancePlugin.${{ env.VERSION }}.nupkg + tag: ${{ github.ref }} + - name: Push release to public Nuget + run: dotnet nuget push ./dist/AgGatewayShippedItemInstancePlugin.${{ env.VERSION }}.nupkg --source https://api.nuget.org/v3/index.json --api-key ${NUGET_API_KEY} + env: + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} diff --git a/AgGatewayShippedItemInstancePlugin.nuspec b/AgGatewayShippedItemInstancePlugin.nuspec new file mode 100644 index 0000000..e3ca6b9 --- /dev/null +++ b/AgGatewayShippedItemInstancePlugin.nuspec @@ -0,0 +1,25 @@ + + + + AgGatewayShippedItemInstancePlugin + 0.0.0 + AgGateway and ADAPT Contributors + AgGateway and ADAPT Contributors + https://www.eclipse.org/legal/epl-v10.html + https://github.com/ADAPT/ShippedItemInstancePlugin + true + AgGateway Shipped Item Instance Plugin for the ADAPT framework + Copyright (C) 2015-21 AgGateway and ADAPT Contributors + agriculture aggateway adapt shippediteminstance + + + + + + + + + + + + \ No newline at end of file diff --git a/ISO_ADM_Exporter/ISO_ADM_Exporter.csproj b/ISO_ADM_Exporter/ISO_ADM_Exporter.csproj new file mode 100644 index 0000000..338283c --- /dev/null +++ b/ISO_ADM_Exporter/ISO_ADM_Exporter.csproj @@ -0,0 +1,15 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + diff --git a/ISO_ADM_Exporter/Program.cs b/ISO_ADM_Exporter/Program.cs new file mode 100644 index 0000000..17d6053 --- /dev/null +++ b/ISO_ADM_Exporter/Program.cs @@ -0,0 +1,36 @@ +using AgGateway.ADAPT.ApplicationDataModel.ADM; +using System; +using System.Collections.Generic; +using System.IO; + +namespace ISO_ADM_Exporter +{ + class Program + { + static void Main(string[] args) + { + if (args.Length < 2) + { + Console.WriteLine("Usage: {inputPath} {outputPath}"); + } + string inputPath = args[0]; + string outputPath = args[1]; + + AgGateway.ADAPT.ShippedItemInstancePlugin.Plugin sPlugin = new AgGateway.ADAPT.ShippedItemInstancePlugin.Plugin(); + IList models = sPlugin.Import(inputPath); + + AgGateway.ADAPT.ISOv4Plugin.Plugin isoPlugin = new AgGateway.ADAPT.ISOv4Plugin.Plugin(); + AgGateway.ADAPT.ADMPlugin.Plugin admPlugin = new AgGateway.ADAPT.ADMPlugin.Plugin(); + for (int i = 0; i < models.Count; i++) + { + Properties p = new Properties(); + string folder = Path.Combine(outputPath, i.ToString()); + Directory.CreateDirectory(folder); + isoPlugin.Export(models[i], folder, p); + + admPlugin.Export(models[i], folder, p); + } + + } + } +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3260e4f --- /dev/null +++ b/LICENSE @@ -0,0 +1,204 @@ +Eclipse Public License - v 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC +LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM +CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + +a) in the case of the initial Contributor, the initial code and documentation + distributed under this Agreement, and +b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + + where such changes and/or additions to the Program originate from and are + distributed by that particular Contributor. A Contribution 'originates' + from a Contributor if it was added to the Program by such Contributor + itself or anyone acting on such Contributor's behalf. Contributions do not + include additions to the Program which: (i) are separate modules of + software distributed in conjunction with the Program under their own + license agreement, and (ii) are not derivative works of the Program. + +"Contributor" means any person or entity that distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which are +necessarily infringed by the use or sale of its Contribution alone or when +combined with the Program. + +"Program" means the Contributions distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement, +including all Contributors. + +2. GRANT OF RIGHTS + a) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free copyright license to + reproduce, prepare derivative works of, publicly display, publicly + perform, distribute and sublicense the Contribution of such Contributor, + if any, and such derivative works, in source code and object code form. + b) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free patent license under + Licensed Patents to make, use, sell, offer to sell, import and otherwise + transfer the Contribution of such Contributor, if any, in source code and + object code form. This patent license shall apply to the combination of + the Contribution and the Program if, at the time the Contribution is + added by the Contributor, such addition of the Contribution causes such + combination to be covered by the Licensed Patents. The patent license + shall not apply to any other combinations which include the Contribution. + No hardware per se is licensed hereunder. + c) Recipient understands that although each Contributor grants the licenses + to its Contributions set forth herein, no assurances are provided by any + Contributor that the Program does not infringe the patent or other + intellectual property rights of any other entity. Each Contributor + disclaims any liability to Recipient for claims brought by any other + entity based on infringement of intellectual property rights or + otherwise. As a condition to exercising the rights and licenses granted + hereunder, each Recipient hereby assumes sole responsibility to secure + any other intellectual property rights needed, if any. For example, if a + third party patent license is required to allow Recipient to distribute + the Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + d) Each Contributor represents that to its knowledge it has sufficient + copyright rights in its Contribution, if any, to grant the copyright + license set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code form under +its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; and + b) its license agreement: + i) effectively disclaims on behalf of all Contributors all warranties + and conditions, express and implied, including warranties or + conditions of title and non-infringement, and implied warranties or + conditions of merchantability and fitness for a particular purpose; + ii) effectively excludes on behalf of all Contributors all liability for + damages, including direct, indirect, special, incidental and + consequential damages, such as lost profits; + iii) states that any provisions which differ from this Agreement are + offered by that Contributor alone and not by any other party; and + iv) states that source code for the Program is available from such + Contributor, and informs licensees how to obtain it in a reasonable + manner on or through a medium customarily used for software exchange. + +When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + b) a copy of this Agreement must be included with each copy of the Program. + Contributors may not remove or alter any copyright notices contained + within the Program. + +Each Contributor must identify itself as the originator of its Contribution, +if +any, in a manner that reasonably allows subsequent Recipients to identify the +originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with +respect to end users, business partners and the like. While this license is +intended to facilitate the commercial use of the Program, the Contributor who +includes the Program in a commercial product offering should do so in a manner +which does not create potential liability for other Contributors. Therefore, +if a Contributor includes the Program in a commercial product offering, such +Contributor ("Commercial Contributor") hereby agrees to defend and indemnify +every other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits and +other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such Commercial +Contributor in connection with its distribution of the Program in a commercial +product offering. The obligations in this section do not apply to any claims +or Losses relating to any actual or alleged intellectual property +infringement. In order to qualify, an Indemnified Contributor must: +a) promptly notify the Commercial Contributor in writing of such claim, and +b) allow the Commercial Contributor to control, and cooperate with the +Commercial Contributor in, the defense and any related settlement +negotiations. The Indemnified Contributor may participate in any such claim at +its own expense. + +For example, a Contributor might include the Program in a commercial product +offering, Product X. That Contributor is then a Commercial Contributor. If +that Commercial Contributor then makes performance claims, or offers +warranties related to Product X, those performance claims and warranties are +such Commercial Contributor's responsibility alone. Under this section, the +Commercial Contributor would have to defend claims against the other +Contributors related to those performance claims and warranties, and if a +court requires any other Contributor to pay any damages as a result, the +Commercial Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each +Recipient is solely responsible for determining the appropriateness of using +and distributing the Program and assumes all risks associated with its +exercise of rights under this Agreement , including but not limited to the +risks and costs of program errors, compliance with applicable laws, damage to +or loss of data, programs or equipment, and unavailability or interruption of +operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY +CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION +LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of the +remainder of the terms of this Agreement, and without further action by the +parties hereto, such provision shall be reformed to the minimum extent +necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Program itself +(excluding combinations of the Program with other software or hardware) +infringes such Recipient's patent(s), then such Recipient's rights granted +under Section 2(b) shall terminate as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it fails to +comply with any of the material terms or conditions of this Agreement and does +not cure such failure in a reasonable period of time after becoming aware of +such noncompliance. If all Recipient's rights under this Agreement terminate, +Recipient agrees to cease use and distribution of the Program as soon as +reasonably practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall continue +and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in +order to avoid inconsistency the Agreement is copyrighted and may only be +modified in the following manner. The Agreement Steward reserves the right to +publish new versions (including revisions) of this Agreement from time to +time. No one other than the Agreement Steward has the right to modify this +Agreement. The Eclipse Foundation is the initial Agreement Steward. The +Eclipse Foundation may assign the responsibility to serve as the Agreement +Steward to a suitable separate entity. Each new version of the Agreement will +be given a distinguishing version number. The Program (including +Contributions) may always be distributed subject to the version of the +Agreement under which it was received. In addition, after a new version of the +Agreement is published, Contributor may elect to distribute the Program +(including its Contributions) under the new version. Except as expressly +stated in Sections 2(a) and 2(b) above, Recipient receives no rights or +licenses to the intellectual property of any Contributor under this Agreement, +whether expressly, by implication, estoppel or otherwise. All rights in the +Program not expressly granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and the +intellectual property laws of the United States of America. No party to this +Agreement will bring a legal action under this Agreement more than one year +after the cause of action arose. Each party waives its rights to a jury trial in +any resulting litigation. + diff --git a/SampleData/shippedItemInstance6452797.json b/SampleData/shippedItemInstance6452797.json new file mode 100644 index 0000000..21cca50 --- /dev/null +++ b/SampleData/shippedItemInstance6452797.json @@ -0,0 +1,544 @@ +{ + "shippedItemInstance": [ + { + "typeCode": "Seed", + "identifier": { + "content": "6452797-1", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC59-82RIB AF2 VT2P 80M ELT500 B-E", + "gtinid": "00190794191302", + "varietyName": "DKC59-82RI", + "productName": "DKC59-82RI" + }, + "quantity": { + "unitCode": "BG", + "content": 100 + }, + "description": { + "content": "DKC59-82RI-H26YJN7JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "VT2P-RIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H26YJN7JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452797" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-02-25T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2047233", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "COATS RON", + "location": { + "glnid": " 1100072746031" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "500+B360+ENHANCED DISEASE", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "500+B360+ENHANCED DISEASE", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6452797-6", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC63-57RIB AR VT2P SP50 ELT500 B-E", + "gtinid": "00190794139977", + "varietyName": "DKC63-57RI", + "productName": "DKC63-57RI" + }, + "quantity": { + "unitCode": "UN", + "content": 250 + }, + "description": { + "content": "DKC63-57RI-H35N9R9JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "VT2P-RIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H35N9R9JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452797" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-02-25T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2047233", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "COATS RON", + "location": { + "glnid": " 1100072746031" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "500+B360+ENHANCED DISEASE", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "500+B360+ENHANCED DISEASE", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6452797-11", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC63-90RIB AF SS RIB SP50 ELT500 B-E", + "gtinid": "00190794183635", + "varietyName": "DKC63-90RI", + "productName": "DKC63-90RI" + }, + "quantity": { + "unitCode": "UN", + "content": 50 + }, + "description": { + "content": "DKC63-90RI-H21HCC4JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "SSPRIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H21HCC4JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452797" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-02-25T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2047233", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "COATS RON", + "location": { + "glnid": " 1100072746031" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6452797-16", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC63-90RIB AF SS RIB SP50 ELT500 B-E", + "gtinid": "00190794183635", + "varietyName": "DKC63-90RI", + "productName": "DKC63-90RI" + }, + "quantity": { + "unitCode": "UN", + "content": 150 + }, + "description": { + "content": "DKC63-90RI-H21HVW4JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "SSPRIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H21HVW4JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452797" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-02-25T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2047233", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "COATS RON", + "location": { + "glnid": " 1100072746031" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6452797-21", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC63-91RIB AF VT2P SP50 ELT500 B-E", + "gtinid": "00190794191739", + "varietyName": "DKC63-91RI", + "productName": "DKC63-91RI" + }, + "quantity": { + "unitCode": "UN", + "content": 200 + }, + "description": { + "content": "DKC63-91RI-H35YET9JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "VT2P-RIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H35YET9JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452797" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-02-25T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2047233", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "COATS RON", + "location": { + "glnid": " 1100072746031" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "500+B360+ENHANCED DISEASE", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "500+B360+ENHANCED DISEASE", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6452797-26", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC65-95RIB AF VT2P SP50 ELT500 B-E", + "gtinid": "00190794140126", + "varietyName": "DKC65-95RI", + "productName": "DKC65-95RI" + }, + "quantity": { + "unitCode": "UN", + "content": 50 + }, + "description": { + "content": "DKC65-95RI-H18YHE9JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "VT2P-RIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H18YHE9JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452797" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-02-25T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2047233", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "COATS RON", + "location": { + "glnid": " 1100072746031" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "500+B360+ENHANCED DISEASE", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "500+B360+ENHANCED DISEASE", + "typeCode": "seed_treatment" + } + ] + } + ] +} \ No newline at end of file diff --git a/SampleData/shippedItemInstance6452810.json b/SampleData/shippedItemInstance6452810.json new file mode 100644 index 0000000..36b4820 --- /dev/null +++ b/SampleData/shippedItemInstance6452810.json @@ -0,0 +1,904 @@ +{ + "shippedItemInstance": [ + { + "typeCode": "Seed", + "identifier": { + "content": "6452810-1", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC66-17RIB AF2 SS RIB SP50 ELT500 B-E", + "gtinid": "00190794185011", + "varietyName": "DKC66-17RI", + "productName": "DKC66-17RI" + }, + "quantity": { + "unitCode": "UN", + "content": 500 + }, + "description": { + "content": "DKC66-17RI-H21NMM9JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "SSPRIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H21NMM9JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452810" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-03-05T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2011635", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "MCFATRIDGE ROB", + "location": { + "glnid": " 1100022651682" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6452810-6", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC66-17RIB AF2 SS RIB SP50 ELT500 B-E", + "gtinid": "00190794185011", + "varietyName": "DKC66-17RI", + "productName": "DKC66-17RI" + }, + "quantity": { + "unitCode": "UN", + "content": 100 + }, + "description": { + "content": "DKC66-17RI-786WVK3JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "SSPRIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "786WVK3JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452810" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-03-05T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2011635", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "MCFATRIDGE ROB", + "location": { + "glnid": " 1100022651682" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6452810-11", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC64-64RIB AF SS RIB SP50U ELT500 B-E", + "gtinid": "00190794334532", + "varietyName": "DKC64-64RI", + "productName": "DKC64-64RI" + }, + "quantity": { + "unitCode": "UN", + "content": 300 + }, + "description": { + "content": "DKC64-64RI-H39Y749JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "SSPRIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H39Y749JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452810" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-03-05T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2011635", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "MCFATRIDGE ROB", + "location": { + "glnid": " 1100022651682" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6452810-16", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC64-64RIB AF2 SS RIB SP50U ELT500 B-E", + "gtinid": "00190794334556", + "varietyName": "DKC64-64RI", + "productName": "DKC64-64RI" + }, + "quantity": { + "unitCode": "UN", + "content": 200 + }, + "description": { + "content": "DKC64-64RI-H39YT97JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "SSPRIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H39YT97JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452810" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-03-05T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2011635", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "MCFATRIDGE ROB", + "location": { + "glnid": " 1100022651682" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6452810-21", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC63-90RIB AF2 SS RIB SP50 ELT500 B-E", + "gtinid": "00190794183697", + "varietyName": "DKC63-90RI", + "productName": "DKC63-90RI" + }, + "quantity": { + "unitCode": "UN", + "content": 300 + }, + "description": { + "content": "DKC63-90RI-H21HWX4JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "SSPRIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H21HWX4JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452810" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-03-05T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2011635", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "MCFATRIDGE ROB", + "location": { + "glnid": " 1100022651682" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6452810-26", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC63-90RIB AF2 SS RIB SP50 ELT500 B-E", + "gtinid": "00190794183697", + "varietyName": "DKC63-90RI", + "productName": "DKC63-90RI" + }, + "quantity": { + "unitCode": "UN", + "content": 400 + }, + "description": { + "content": "DKC63-90RI-H21HAA4JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "SSPRIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H21HAA4JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452810" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-03-05T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2011635", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "MCFATRIDGE ROB", + "location": { + "glnid": " 1100022651682" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6452810-31", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC61-40RIB AR SS RIB SP50 ELT500 B-E", + "gtinid": "00190794183109", + "varietyName": "DKC61-40RI", + "productName": "DKC61-40RI" + }, + "quantity": { + "unitCode": "UN", + "content": 150 + }, + "description": { + "content": "DKC61-40RI-H39YJE9JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "SSPRIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H39YJE9JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452810" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-03-05T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2011635", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "MCFATRIDGE ROB", + "location": { + "glnid": " 1100022651682" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6452810-36", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC61-40RIB AR SS RIB SP50 ELT500 B-E", + "gtinid": "00190794183109", + "varietyName": "DKC61-40RI", + "productName": "DKC61-40RI" + }, + "quantity": { + "unitCode": "UN", + "content": 100 + }, + "description": { + "content": "DKC61-40RI-H21NLL4JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "SSPRIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H21NLL4JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452810" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-03-05T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2011635", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "MCFATRIDGE ROB", + "location": { + "glnid": " 1100022651682" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6452810-41", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC59-81RIB AF SS SP50 ELT500 B-E", + "gtinid": "00190794182270", + "varietyName": "DKC59-81RI", + "productName": "DKC59-81RI" + }, + "quantity": { + "unitCode": "UN", + "content": 200 + }, + "description": { + "content": "DKC59-81RI-H39YTH9JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "SS-RIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H39YTH9JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452810" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-03-05T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2011635", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "MCFATRIDGE ROB", + "location": { + "glnid": " 1100022651682" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6452810-46", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "DEKALB", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "DKC59-81RIB AF SS SP50 ELT500 B-E", + "gtinid": "00190794182270", + "varietyName": "DKC59-81RI", + "productName": "DKC59-81RI" + }, + "quantity": { + "unitCode": "UN", + "content": 200 + }, + "description": { + "content": "DKC59-81RI-H18Y447JX", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "C", + "listAgencyIdentifier": "AGIIS", + "typeCode": "CORN" + }, + { + "content": "SS-RIB", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "H18Y447JX", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6452810" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-03-05T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "2011635", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "MCFATRIDGE ROB", + "location": { + "glnid": " 1100022651682" + }, + "typeCode": "Grower" + }, + { + "name": "TEMPLETON SEED HUB", + "location": { + "glnid": "1100027907456" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "ACCELERON500+B300+ENHANCED DIS", + "typeCode": "seed_treatment" + } + ] + } + ] +} \ No newline at end of file diff --git a/SampleData/shippedItemInstance6734381.json b/SampleData/shippedItemInstance6734381.json new file mode 100644 index 0000000..ed063d4 --- /dev/null +++ b/SampleData/shippedItemInstance6734381.json @@ -0,0 +1,274 @@ +{ + "shippedItemInstance": [ + { + "typeCode": "Seed", + "identifier": { + "content": "6734381-1", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "ASGROW", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "AG38XF1 XF 40SCUMB UNTR", + "gtinid": "00190794332514", + "varietyName": "AG38XF1 XF", + "productName": "AG38XF1 XF" + }, + "quantity": { + "unitCode": "UN", + "content": 680 + }, + "description": { + "content": "AG38XF1 XF-CE0SFS2B", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "S", + "listAgencyIdentifier": "AGIIS", + "typeCode": "SOYBEANS" + }, + { + "content": "RR2Y/DC", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "CE0SFS2B", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6734381" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-01-11T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "3025867", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "SWALLS ALAN", + "location": { + "glnid": " 1100013727549" + }, + "typeCode": "Grower" + }, + { + "name": "NEW LEBANON SEED HUB", + "location": { + "glnid": "1100028417954" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "NO STANDARD OR SPECIAL TRTMT", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "NO STANDARD OR SPECIAL TRTMT", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6734381-6", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "ASGROW", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "AG35XF1 XF 40SCUMB UNTR", + "gtinid": "00190794332248", + "varietyName": "AG35XF1 XF", + "productName": "AG35XF1 XF" + }, + "quantity": { + "unitCode": "UN", + "content": 680 + }, + "description": { + "content": "AG35XF1 XF-ST0SB42E", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "S", + "listAgencyIdentifier": "AGIIS", + "typeCode": "SOYBEANS" + }, + { + "content": "RR2Y/DC", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "ST0SB42E", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6734381" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-01-11T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "3025867", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "SWALLS ALAN", + "location": { + "glnid": " 1100013727549" + }, + "typeCode": "Grower" + }, + { + "name": "NEW LEBANON SEED HUB", + "location": { + "glnid": "1100028417954" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "NO STANDARD OR SPECIAL TRTMT", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "NO STANDARD OR SPECIAL TRTMT", + "typeCode": "seed_treatment" + } + ] + }, + { + "typeCode": "Seed", + "identifier": { + "content": "6734381-11", + "typeCode": "shipment_line_identifier" + }, + "item": { + "brandName": "ASGROW", + "manufacturerItemIdentification": { + "identifier": "", + "typeCode": "" + }, + "description": "AG40XF0 XF 40SCUMB UNTR", + "gtinid": "00190794015172", + "varietyName": "AG40XF0 XF", + "productName": "AG40XF0 XF" + }, + "quantity": { + "unitCode": "UN", + "content": 280 + }, + "description": { + "content": "AG40XF0 XF-CE0SAU1D", + "typeCode": "mics_display" + }, + "classification": { + "typeCode": "Crop", + "codes": { + "code": [ + { + "content": "S", + "listAgencyIdentifier": "AGIIS", + "typeCode": "SOYBEANS" + }, + { + "content": "RR2Y/DC", + "typeCode": "Trait" + } + ] + } + }, + "lot": { + "identifier": { + "content": "CE0SAU1D", + "typeCode": "Lot" + } + }, + "documentReference": { + "identifier": { + "content": "6734381" + }, + "typeCode": "shipment_identifier", + "documentDateTime": "2021-01-11T00:00:00-04:00" + }, + "party": [ + { + "identifier": [ + { + "content": "3025867", + "typeCode": "retailer_grower_identifier" + } + ], + "name": "SWALLS ALAN", + "location": { + "glnid": " 1100013727549" + }, + "typeCode": "Grower" + }, + { + "name": "NEW LEBANON SEED HUB", + "location": { + "glnid": "1100028417954" + }, + "typeCode": "Retailer" + } + ], + "itemIdentifierSet": [ + { + "identifier": [ + { + "content": "NO STANDARD OR SPECIAL TRTMT", + "typeCode": "product" + } + ], + "schemeAgencyIdentifier": "manufacturer_seed_treatment_identifier", + "schemeIdentifier": "NO STANDARD OR SPECIAL TRTMT", + "typeCode": "seed_treatment" + } + ] + } + ] +} \ No newline at end of file diff --git a/ShippedItemInstancePlugin.sln b/ShippedItemInstancePlugin.sln new file mode 100644 index 0000000..ecfbb6b --- /dev/null +++ b/ShippedItemInstancePlugin.sln @@ -0,0 +1,33 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31005.135 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShippedItemInstancePlugin", "ShippedItemInstancePlugin\ShippedItemInstancePlugin.csproj", "{7D623C8B-1C52-4B08-8BA7-9537B1C84AD7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShippedItemInstancePluginTests", "ShippedItemInstancePluginTests\ShippedItemInstancePluginTests.csproj", "{77882E1D-79A7-4F69-8A1E-4F90FCAA0804}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SampleData", "SampleData", "{DEE80FA5-C78B-49AA-B03F-2D79C2119704}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7D623C8B-1C52-4B08-8BA7-9537B1C84AD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7D623C8B-1C52-4B08-8BA7-9537B1C84AD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7D623C8B-1C52-4B08-8BA7-9537B1C84AD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7D623C8B-1C52-4B08-8BA7-9537B1C84AD7}.Release|Any CPU.Build.0 = Release|Any CPU + {77882E1D-79A7-4F69-8A1E-4F90FCAA0804}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {77882E1D-79A7-4F69-8A1E-4F90FCAA0804}.Debug|Any CPU.Build.0 = Debug|Any CPU + {77882E1D-79A7-4F69-8A1E-4F90FCAA0804}.Release|Any CPU.ActiveCfg = Release|Any CPU + {77882E1D-79A7-4F69-8A1E-4F90FCAA0804}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {63F4561B-2213-48CA-A94B-3B7BBE4ACCA9} + EndGlobalSection +EndGlobal diff --git a/ShippedItemInstancePlugin/Error.cs b/ShippedItemInstancePlugin/Error.cs new file mode 100644 index 0000000..b2fc68a --- /dev/null +++ b/ShippedItemInstancePlugin/Error.cs @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (C) 2021 AgGateway and ADAPT Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Rob Cederberg, Kelly Nelson - initial implementation + *******************************************************************************/ + + +using AgGateway.ADAPT.ApplicationDataModel.ADM; + +namespace AgGateway.ADAPT.ShippedItemInstancePlugin +{ + public class Error : IError + { + public Error(string id, string source, string description, string stacktrace) + { + Id = id; + Source = source; + Description = description; + StackTrace = stacktrace; + } + + public string Id { get; set; } + + public string Source { get; set; } + + public string Description { get; set; } + + public string StackTrace { get; set; } + } +} diff --git a/ShippedItemInstancePlugin/Mapper.cs b/ShippedItemInstancePlugin/Mapper.cs new file mode 100644 index 0000000..1b83ba8 --- /dev/null +++ b/ShippedItemInstancePlugin/Mapper.cs @@ -0,0 +1,722 @@ +/******************************************************************************* + * Copyright (C) 2021 AgGateway and ADAPT Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Rob Cederberg, Kelly Nelson - initial implementation + *******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using AgGateway.ADAPT.ApplicationDataModel.ADM; +using AgGateway.ADAPT.ApplicationDataModel.Common; +using AgGateway.ADAPT.ApplicationDataModel.Products; +using AgGateway.ADAPT.ApplicationDataModel.Representations; +using AgGateway.ADAPT.ApplicationDataModel.Logistics; +using RepresentationSystem = AgGateway.ADAPT.Representation.RepresentationSystem; +using UnitSystem = AgGateway.ADAPT.Representation.UnitSystem; +using AgGateway.ADAPT.Representation.RepresentationSystem.ExtensionMethods; + +namespace AgGateway.ADAPT.ShippedItemInstancePlugin +{ + /// + /// Maps data from the OAGIS ShippedItemInstance document into the ADAPT ApplicationDataModel + /// + public class Mapper + { + #region Constructors + public Mapper(Catalog catalog) + { + Catalog = catalog; + } + + #endregion + + #region Properties + + /// + /// Catalog object that is to recieve the data to be mapped. + /// + private Catalog Catalog { get; set; } + private IList Errors { get; set; } + + #endregion + + #region Methods + + /// + /// Takes data from the specified document and adds it to the Catalog + /// + /// + /// + public IList MapDocument(Model.Document document) + { + Errors = new List(); + + foreach (Model.ShippedItemInstance shippedItemInstance in document.ShippedItemInstances) + { + MapShippedItemInstance(shippedItemInstance); + } + return Errors; + } + + private void MapShippedItemInstance(Model.ShippedItemInstance shippedItemInstance) + { + //----------------------- + //PackagedProductInstance + //----------------------- + //The PackagedProductInstance represents a single product shipment and maps 1:1 to the ShippedItemInstance + PackagedProductInstance packagedProductInstance = new PackagedProductInstance(); + + //Description and quantity are set on the related class properties + packagedProductInstance.Description = string.Format("Shipment {0}", shippedItemInstance.Identifier?.Content); + if (double.TryParse(shippedItemInstance.Quantity?.Content, out double quantity)) + { + packagedProductInstance.ProductQuantity = CreateRepresentationValue(quantity, shippedItemInstance.Quantity.UnitCode); + } + else + { + Errors.Add(new Error(string.Empty, "ShippedItemInstanceMapper.MapShippedItemInstance", $"Quantity {shippedItemInstance.Quantity?.Content} is invalid.", string.Empty)); + } + + //The remaining data is somewhat specific to the ShippedItemInstance and is persisted as ContextItems + //The ContextItem data generally is intended to be passed out of the ApplicationDataModel and passed back in unaltered, + //in order that the data may return, e.g., on a logged planting operation and reconcile that planting operation + //back to this ShippedItemInstance. + packagedProductInstance.ContextItems.AddRange(CreatePackagedProductInstanceContextItems(shippedItemInstance)); + + //----------------------- + //PackagedProduct + //----------------------- + //Packaged product is defined a product within a specific packaging. + //Multiple ShippedItemInstances may map to the same PackagedProduct + PackagedProduct packagedProduct = GetPackagedProduct(shippedItemInstance); + if (packagedProduct != null) + { + packagedProductInstance.PackagedProductId = packagedProduct.Id.ReferenceId; + } + else + { + Errors.Add(new Error(null, "Mapper.MapShippedItemInstance", $"Couldn't create PackagedProduct for PackageProductInstance {packagedProductInstance.Id.ReferenceId}", null)); + } + + //Add the PackagedProductInstance to the Catalog. The PackagedProduct is added in the subroutine above. + Catalog.PackagedProductInstances.Add(packagedProductInstance); + + //Set other contextual information from the ShippedItemInstance into relevant ADAPT classes + SetManufacturerAndBrand(shippedItemInstance); + SetCrop(shippedItemInstance); + SetGrower(shippedItemInstance); + } + + private NumericRepresentationValue CreateRepresentationValue(double value, string inputUnitOfMeasure) + { + //RepresentationValue + NumericRepresentationValue returnValue = new NumericRepresentationValue(); + + //Use vrSeedLoadQuantity Representation + RepresentationSystem.Representation representation = RepresentationSystem.RepresentationManager.Instance.Representations.First(r => r.DomainId == "vrSeedLoadQuantity"); + if (representation != null) + { + // Convert to ADAPT Numeric Representation object + returnValue.Representation = ((RepresentationSystem.NumericRepresentation)representation).ToModelRepresentation(); + } + + //Value + // Map bg to bag + string uomCode = inputUnitOfMeasure?.ToLower() == "bg" ? "bag" : inputUnitOfMeasure?.ToLower() ?? string.Empty; + if (!UnitSystem.InternalUnitSystemManager.Instance.UnitOfMeasures.Contains(uomCode)) + { + // Didn't find uom so just use unitless + uomCode = "unitless"; + + Errors.Add(new Error(string.Empty, "ShippedItemInstanceMapper.CreateRepresentationValue", $"Unit of Measure {uomCode} not found, using unitless instead.", string.Empty)); + } + UnitOfMeasure uom = UnitSystem.UnitSystemManager.GetUnitOfMeasure(uomCode); + returnValue.Value = new ApplicationDataModel.Representations.NumericValue(uom, value); + + return returnValue; + } + + private List CreatePackagedProductInstanceContextItems(Model.ShippedItemInstance shippedItemInstance) + { + List items = new List(); + + // Lot + if (shippedItemInstance.Lot?.Identifier?.Content != null) + { + items.Add(CreateContextItem("Lot", shippedItemInstance.Lot?.Identifier?.Content)); + } + + // Packaging + ContextItem contextItem = CreateContextItem("Packaging", null); + + // Add Packaging nested items + if (shippedItemInstance.Packaging?.TypeCode != null) + { + contextItem.NestedItems.Add(CreateContextItem("typeCode", shippedItemInstance.Packaging.TypeCode)); + } + if (shippedItemInstance.Packaging?.Identifier != null) + { + contextItem.NestedItems.Add(CreateContextItem("identifier", shippedItemInstance.Packaging.Identifier)); + } + if (contextItem.NestedItems.Count > 0) + { + items.Add(contextItem); + } + + // DocumentReference + contextItem = CreateContextItem("DocumentReference", null); + + // nested items + ContextItem nestedContextItem = CreateContextItem("Identifier", null); + + // This one has it's own nested items + if (shippedItemInstance.DocumentReference?.Identifier?.Content != null) + { + nestedContextItem.NestedItems.Add(CreateContextItem("content", shippedItemInstance.DocumentReference?.Identifier?.Content)); + } + if (shippedItemInstance.DocumentReference?.Identifier?.TypeCode != null) + { + nestedContextItem.NestedItems.Add(CreateContextItem("typeCode", shippedItemInstance.DocumentReference.Identifier.TypeCode)); + } + if (nestedContextItem.NestedItems.Count > 0) + { + contextItem.NestedItems.Add(nestedContextItem); + } + + if (shippedItemInstance.DocumentReference?.TypeCode != null) + { + contextItem.NestedItems.Add(CreateContextItem("typeCode", shippedItemInstance.DocumentReference.TypeCode)); + } + + if (shippedItemInstance.DocumentReference?.DocumentDateTime != null) + { + contextItem.NestedItems.Add(CreateContextItem("documentDateTime", shippedItemInstance.DocumentReference.DocumentDateTime)); + } + if (contextItem.NestedItems.Count > 0) + { + items.Add(contextItem); + } + + // Identifier + contextItem = CreateContextItem("Identifier", null); + + // nested items + if (shippedItemInstance.Identifier?.TypeCode != null) + { + contextItem.NestedItems.Add(CreateContextItem("typeCode", shippedItemInstance.Identifier.TypeCode)); + } + if (shippedItemInstance.Identifier?.Content != null) + { + contextItem.NestedItems.Add(CreateContextItem("content", shippedItemInstance.Identifier.Content)); + } + if (contextItem.NestedItems.Count > 0) + { + items.Add(contextItem); + } + + // ItemIdentifierSet + if (shippedItemInstance.ItemIdentifierSets?.Count > 0) + { + contextItem = CreateItemIdentifierSetsContextItem(shippedItemInstance); + if (contextItem.NestedItems.Count > 0) + { + items.Add(contextItem); + } + } + + // Uid + contextItem = CreateContextItem("uid", null); + if (shippedItemInstance.Uid?.Content != null) + { + contextItem.NestedItems.Add(CreateContextItem("content", shippedItemInstance.Uid.Content)); + } + if (shippedItemInstance.Uid?.SchemeIdentifier != null) + { + contextItem.NestedItems.Add(CreateContextItem("schemaIdentifier", shippedItemInstance.Uid.SchemeIdentifier)); + } + if (shippedItemInstance.Uid?.SchemeAgencyIdentifier != null) + { + contextItem.NestedItems.Add(CreateContextItem("schemaAgencyIdentifier", shippedItemInstance.Uid.SchemeAgencyIdentifier)); + } + if (shippedItemInstance.Uid?.TypeCode != null) + { + contextItem.NestedItems.Add(CreateContextItem("typeCode", shippedItemInstance.Uid.TypeCode)); + } + + if (contextItem.NestedItems.Count > 0) + { + items.Add(contextItem); + } + + // Quantitative Results + if (shippedItemInstance.Results?.Quantitative.Count > 0) + { + contextItem = CreateQuantitativeResultsContextItem(shippedItemInstance); + if (contextItem.NestedItems.Count > 0) + { + items.Add(contextItem); + } + } + + return items; + } + + private ContextItem CreateContextItem(string code, string value) + { + ContextItem item = new ContextItem() { Code = code }; + + if (value != null) + { + item.Value = value; + } + + return item; + } + + private ContextItem CreateItemIdentifierSetsContextItem(Model.ShippedItemInstance shippedItemInstance) + { + ContextItem itemIdentifierSetsContextItem = CreateContextItem("ItemIdentifierSets", null); + + int identifierSetIndex = 0; + foreach (Model.ItemIdentifierSet itemIdentifierSet in shippedItemInstance.ItemIdentifierSets) + { + ContextItem itemIdentifierSetContextItem = CreateContextItem((++identifierSetIndex).ToString(), null); + if (itemIdentifierSet.SchemeIdentifier != null) + { + itemIdentifierSetContextItem.NestedItems.Add(CreateContextItem("schemeIdentifier", itemIdentifierSet.SchemeIdentifier)); + } + if (itemIdentifierSet.SchemeVersionIdentifier != null) + { + itemIdentifierSetContextItem.NestedItems.Add(CreateContextItem("schemaVersionIdentifier", itemIdentifierSet.SchemeVersionIdentifier)); + } + if (itemIdentifierSet.SchemeAgencyIdentifier != null) + { + itemIdentifierSetContextItem.NestedItems.Add(CreateContextItem("schemaAgencyIdentifier", itemIdentifierSet.SchemeAgencyIdentifier)); + } + if (itemIdentifierSet.TypeCode != null) + { + itemIdentifierSetContextItem.NestedItems.Add(CreateContextItem("typeCode", itemIdentifierSet.TypeCode)); + } + + ContextItem identifiersContextItem = CreateContextItem("identifiers", null); + int identifierIndex = 0; + foreach (Model.ItemIdentifier identifier in itemIdentifierSet.Identifiers) + { + ContextItem identifierContextItem = CreateContextItem((++identifierIndex).ToString(), null); + if (identifier.Content != null) + { + identifierContextItem.NestedItems.Add(CreateContextItem("content", identifier.Content)); + } + if (identifier.SchemeIdentifier != null) + { + identifierContextItem.NestedItems.Add(CreateContextItem("schemaIdentifier", identifier.SchemeIdentifier)); + } + if (identifier.SchemeAgencyIdentifier != null) + { + identifierContextItem.NestedItems.Add(CreateContextItem("schemaAgencyIdentifier", identifier.SchemeAgencyIdentifier)); + } + if (identifier.TypeCode != null) + { + identifierContextItem.NestedItems.Add(CreateContextItem("typeCode", identifier.TypeCode)); + } + if (identifierContextItem.NestedItems.Count > 0) + { + identifiersContextItem.NestedItems.Add(identifierContextItem); + } + } + + if (identifiersContextItem.NestedItems.Count > 0) + { + itemIdentifierSetContextItem.NestedItems.Add(identifiersContextItem); + } + + if (itemIdentifierSetContextItem.NestedItems.Count > 0) + { + itemIdentifierSetsContextItem.NestedItems.Add(itemIdentifierSetContextItem); + } + } + + return itemIdentifierSetsContextItem; + } + + private ContextItem CreateQuantitativeResultsContextItem(Model.ShippedItemInstance shippedItemInstance) + { + ContextItem results = CreateContextItem("QuantitativeResults", null); + + int quantitateResultIndex = 0; + foreach (Model.Quantitative quantitativeResult in shippedItemInstance.Results.Quantitative) + { + ContextItem quantitativeResultContextItem = CreateContextItem((++quantitateResultIndex).ToString(), null); + + if (quantitativeResult.TypeCode != null) + { + quantitativeResultContextItem.NestedItems.Add(CreateContextItem("typeCode", quantitativeResult.TypeCode)); + } + if (quantitativeResult.Name != null) + { + quantitativeResultContextItem.NestedItems.Add(CreateContextItem("name", quantitativeResult.Name)); + } + + // Unit of Measure + ContextItem uomCodeContextItem = CreateContextItem("uomCode", null); + if (quantitativeResult.UomCode?.Content != null) + { + uomCodeContextItem.NestedItems.Add(CreateContextItem("content", quantitativeResult.UomCode.Content)); + } + if (quantitativeResult.UomCode?.ListIdentifier != null) + { + uomCodeContextItem.NestedItems.Add(CreateContextItem("listIdentifier", quantitativeResult.UomCode.ListIdentifier)); + } + if (quantitativeResult.UomCode?.ListAgencyIdentifier != null) + { + uomCodeContextItem.NestedItems.Add(CreateContextItem("listAgencyIdentifier", quantitativeResult.UomCode.ListAgencyIdentifier)); + } + if (uomCodeContextItem.NestedItems.Count > 0) + { + quantitativeResultContextItem.NestedItems.Add(uomCodeContextItem); + } + + //Significant Digits + if (quantitativeResult.SignificantDigitsNumber != null) + { + quantitativeResultContextItem.NestedItems.Add(CreateContextItem("significantDigitsNumber", quantitativeResult.SignificantDigitsNumber)); + } + + // Measurement + ContextItem measurementsContextItem = CreateContextItem("measurements", null); + int measurementIndex = 0; + foreach (Model.Measurement measurement in quantitativeResult.Measurements) + { + ContextItem measurementContextItem = CreateContextItem((++measurementIndex).ToString(), null); + if (measurement.DateTime != null) + { + measurementContextItem.NestedItems.Add(CreateContextItem("dateTime", measurement.DateTime)); + } + if (measurement.Measure != null) + { + measurementContextItem.NestedItems.Add(CreateContextItem("measure", measurement.Measure)); + } + + if (measurementContextItem.NestedItems.Count > 0) + { + measurementsContextItem.NestedItems.Add(measurementContextItem); + } + } + + if (measurementsContextItem.NestedItems.Count > 0) + { + quantitativeResultContextItem.NestedItems.Add(measurementsContextItem); + } + + // Add to results if any nested items were added + if (quantitativeResultContextItem.NestedItems.Count > 0) + { + results.NestedItems.Add(quantitativeResultContextItem); + } + } + + return results; + } + + private PackagedProduct GetPackagedProduct(Model.ShippedItemInstance shippedItemInstance) + { + PackagedProduct packagedProduct = null; + Model.Item item = shippedItemInstance.Item; + if (item?.ManufacturerItemIdentification?.Identifier == null && item?.Gtinid == null && item?.Upcid == null) + { + // No ids specified so use the descriptionn to find a PackageProduct that matches + packagedProduct = Catalog.PackagedProducts.FirstOrDefault(pp => pp.Description == item?.Description); + } + else + { + // Try to find a matching PackagedProduct based on the ManufacturerItemIdentifier, UPC Id or GTIN Id + if (!string.IsNullOrEmpty(item?.ManufacturerItemIdentification?.TypeCode) && !string.IsNullOrEmpty(item?.ManufacturerItemIdentification?.Identifier)) + { + packagedProduct = Catalog.PackagedProducts.FirstOrDefault(pp => pp.ContextItems.Any(i => (i.Code == item?.ManufacturerItemIdentification?.TypeCode && i.Value == item?.ManufacturerItemIdentification?.Identifier))); + } + else if (!string.IsNullOrEmpty(item?.Gtinid) && !string.IsNullOrEmpty(item?.Upcid)) + { + packagedProduct = Catalog.PackagedProducts.FirstOrDefault(pp => pp.ContextItems.Any(i => (i.Code == "UPC" && i.Value == item?.Upcid) || (i.Code == "GTIN" && i.Value == item?.Gtinid))); + } + } + + if (packagedProduct == null && item?.Description != null) + { + // Didn't find a match so create a new object + packagedProduct = new PackagedProduct(); + + packagedProduct.Description = item?.Description; + + // Set context items + + //Set description so that it can in theory persist as data for models (e.g., ISO) that do not have the PackagedProduct object. + if (item?.Description != null) + { + packagedProduct.ContextItems.Add( + new ContextItem() + { + Code = "Description", + Value = item?.Description + }); + + } + + //The below identifiers are set as ContextItems vs. UniqueIDs so that they can import/export hierarchically + //based on the logic in the ISO plugin to handle hierarchical PackagedProducts & PackagedProductInstances + if (item?.ManufacturerItemIdentification?.Identifier != null) + { + packagedProduct.ContextItems.Add( + new ContextItem() + { + Code = item?.ManufacturerItemIdentification?.TypeCode, + Value = item?.ManufacturerItemIdentification?.Identifier + }); + + } + + if (item?.Upcid != null) + { + packagedProduct.ContextItems.Add( + new ContextItem() + { + Code = "UPC", + Value = item?.Upcid + }); + } + + if (item?.Gtinid != null) + { + packagedProduct.ContextItems.Add( + new ContextItem() + { + Code = "GTIN", + Value = item?.Gtinid + }); + } + + Catalog.PackagedProducts.Add(packagedProduct); + + // Tie to a Product object + Product product = GetProduct(shippedItemInstance); + if (product != null) + { + packagedProduct.ProductId = product.Id.ReferenceId; + } + else + { + Errors.Add(new Error(null, "Mapper.GetPackagedProduct", $"Unable to create Product for Packaged Product {packagedProduct.Id.ReferenceId}", null)); + } + } + + return packagedProduct; + } + + private Product GetProduct(Model.ShippedItemInstance shippedItemInstance) + { + // Look for product with a description that matches the shipped item instance + Product product = Catalog.Products.FirstOrDefault(p => p.Description == shippedItemInstance.Description?.Content); + + if (product == null && shippedItemInstance.Description?.Content != null) + { + if (shippedItemInstance.TypeCode == null || shippedItemInstance.TypeCode.ToLower() == "seed") + { + product = new CropVarietyProduct(); + } + else + { + product = new GenericProduct(); + } + + product.Description = shippedItemInstance.Description?.Content; + product.ContextItems.AddRange(CreateProductContextItems(shippedItemInstance)); + + Catalog.Products.Add(product); + } + + return product; + } + + private List CreateProductContextItems(Model.ShippedItemInstance shippedItemInstance) + { + List contextItems = new List(); + + if (shippedItemInstance.TypeCode != null) + { + contextItems.Add(CreateContextItem("TypeCode", shippedItemInstance.TypeCode)); + } + if (shippedItemInstance.Item?.Description != null) + { + contextItems.Add(CreateContextItem("ItemDescription", shippedItemInstance.Item.Description)); + } + if (shippedItemInstance.Item?.ProductName != null) + { + contextItems.Add(CreateContextItem("ItemProductName", shippedItemInstance.Item.ProductName)); + } + if (shippedItemInstance.Item?.BrandName != null) + { + contextItems.Add(CreateContextItem("ItemBrandName", shippedItemInstance.Item.BrandName)); + } + if (shippedItemInstance.Item?.VarietyName != null) + { + contextItems.Add(CreateContextItem("ItemVarietyName", shippedItemInstance.Item.VarietyName)); + } + + // Classification + ContextItem classificationContextItem = CreateContextItem("Classification", null); + if (shippedItemInstance.Classification?.TypeCode != null) + { + classificationContextItem.NestedItems.Add(CreateContextItem("typeCode", shippedItemInstance.Classification.TypeCode)); + } + if (shippedItemInstance.Classification?.Codes?.Codes?.Count > 0) + { + ContextItem codesContextItem = CreateContextItem("codes", null); + int codeIndex = 0; + foreach (Model.Code code in shippedItemInstance.Classification.Codes.Codes) + { + ContextItem codeContextItem = CreateContextItem((++codeIndex).ToString(), null); + + if (code.Content != null) + { + codeContextItem.NestedItems.Add(CreateContextItem("content", code.Content)); + } + if (code.ListAgencyIdentifier != null) + { + codeContextItem.NestedItems.Add(CreateContextItem("listAgencyIdentifier", code.ListAgencyIdentifier)); + } + if (code.TypeCode != null) + { + codeContextItem.NestedItems.Add(CreateContextItem("typeCode", code.TypeCode)); + } + + if (codeContextItem.NestedItems.Count > 0) + { + codesContextItem.NestedItems.Add(codeContextItem); + } + } + + if (codesContextItem.NestedItems.Count > 0) + { + classificationContextItem.NestedItems.Add(codesContextItem); + } + } + if (classificationContextItem.NestedItems.Count > 0) + { + contextItems.Add(classificationContextItem); + } + + // ManufacturingParty + ContextItem manufacturingPartyContextItem = CreateContextItem("manufacturingParty", null); + if (shippedItemInstance.ManufacturingParty?.Name != null) + { + manufacturingPartyContextItem.NestedItems.Add(CreateContextItem("name", shippedItemInstance.ManufacturingParty.Name)); + } + ContextItem identifierContextItem = CreateContextItem("identifier", null); + if (shippedItemInstance.ManufacturingParty?.Identifier?.Content != null) + { + identifierContextItem.NestedItems.Add(CreateContextItem("content", shippedItemInstance.ManufacturingParty.Identifier.Content)); + } + if (shippedItemInstance.ManufacturingParty?.Identifier?.TypeCode != null) + { + identifierContextItem.NestedItems.Add(CreateContextItem("typeCode", shippedItemInstance.ManufacturingParty.Identifier.TypeCode)); + } + if (identifierContextItem.NestedItems.Count > 0) + { + manufacturingPartyContextItem.NestedItems.Add(identifierContextItem); + } + if (manufacturingPartyContextItem.NestedItems.Count > 0) + { + contextItems.Add(manufacturingPartyContextItem); + } + + return contextItems; + } + + private void SetManufacturerAndBrand(Model.ShippedItemInstance shippedItemInstance) + { + //Set Manufacturer & Brand as available + var product = GetProduct(shippedItemInstance); + if (product != null) + { + if (shippedItemInstance.ManufacturingParty?.Name != null) + { + var manufacturer = Catalog.Manufacturers.FirstOrDefault(m => m.Description == shippedItemInstance.ManufacturingParty.Name); + if (manufacturer == null) + { + manufacturer = new Manufacturer() { Description = shippedItemInstance.ManufacturingParty.Name }; + Catalog.Manufacturers.Add(manufacturer); + } + product.ManufacturerId = manufacturer.Id.ReferenceId; + } + + if (shippedItemInstance.Item?.BrandName != null) + { + var brand = Catalog.Brands.FirstOrDefault(b => b.Description == shippedItemInstance.Item.BrandName); + if (brand == null) + { + brand = new Brand() { Description = shippedItemInstance.Item.BrandName, ManufacturerId = product.ManufacturerId ?? 0}; + Catalog.Brands.Add(brand); + } + product.BrandId = brand.Id.ReferenceId; + } + } + } + + private void SetCrop(Model.ShippedItemInstance shippedItemInstance) + { + //Set Crop as available + if (shippedItemInstance.Classification?.TypeCode != null && + shippedItemInstance.Classification?.TypeCode.ToLower() == "crop") + { + var product = GetProduct(shippedItemInstance); + if (product != null && product is CropVarietyProduct) + { + var cropInformation = shippedItemInstance.Classification?.Codes?.Codes?.FirstOrDefault(); + if (cropInformation != null) + { + string cropName = cropInformation.TypeCode; + string cropID = cropInformation.Content; + string idAgency = cropInformation.ListAgencyIdentifier; + Crop crop = Catalog.Crops.FirstOrDefault(c => c.Name == cropName); + if (crop == null) + { + crop = new Crop() { Name = cropName }; + crop.Id.UniqueIds.Add(new UniqueId() { Source = idAgency, IdType = IdTypeEnum.String, Id = cropID }); + Catalog.Crops.Add(crop); + } + ((CropVarietyProduct)product).CropId = crop.Id.ReferenceId; + } + } + } + } + + + private void SetGrower(Model.ShippedItemInstance shippedItemInstance) + { + //Set Grower as available + Model.Party modelGrower = shippedItemInstance.Parties.FirstOrDefault(p => p.TypeCode != null && p.TypeCode.ToLower() == "grower"); + if (modelGrower != null) + { + Grower grower = Catalog.Growers.FirstOrDefault(c => c.Name == modelGrower.Name); + if (grower == null) + { + grower = new Grower() { Name = modelGrower.Name }; + if (modelGrower.Location?.Glnid != null) + { + UniqueId id = new UniqueId() { Id = modelGrower.Location.Glnid, Source = "GLN", IdType = IdTypeEnum.String }; + grower.Id.UniqueIds.Add(id); + } + Catalog.Growers.Add(grower); + } + } + } + + #endregion + } +} diff --git a/ShippedItemInstancePlugin/Model.cs b/ShippedItemInstancePlugin/Model.cs new file mode 100644 index 0000000..fd755cb --- /dev/null +++ b/ShippedItemInstancePlugin/Model.cs @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (C) 2021 AgGateway and ADAPT Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Rob Cederberg, Kelly Nelson - initial implementation + *******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Text; +using Newtonsoft.Json; + +namespace AgGateway.ADAPT.ShippedItemInstancePlugin.Model +{ + public class Document + { + [JsonProperty("ShippedItemInstance")] + public List ShippedItemInstances { get; set; } + } + + public class ShippedItemInstance + { + public string TypeCode { get; set; } + public Identifier Identifier { get; set; } + [JsonProperty("ItemIdentifierSet")] + public List ItemIdentifierSets { get; set; } + public ItemIdentifier Uid { get; set; } + public Lot Lot { get; set; } + public Item Item { get; set; } + public Quantity Quantity { get; set; } + public Identifier Description { get; set; } + public Classification Classification { get; set; } + public Packaging Packaging { get; set; } + public DocumentReference DocumentReference { get; set; } + public Attachment Attachment { get; set; } + public ManufacturingParty ManufacturingParty { get; set; } + [JsonProperty("Party")] + public List Parties { get; set; } + public Result Results { get; set; } + } + + public class Identifier + { + public string Content { get; set; } + public string TypeCode { get; set; } + } + + public class ItemIdentifier + { + public string Content { get; set; } + public string SchemeIdentifier { get; set; } + public string SchemeAgencyIdentifier { get; set; } + public string TypeCode { get; set; } + } + + public class ItemIdentifierSet + { + public string TypeCode { get; set; } + public string SchemeIdentifier { get; set; } + public string SchemeVersionIdentifier { get; set; } + public string SchemeAgencyIdentifier { get; set; } + [JsonProperty("Identifier")] + public List Identifiers { get; set; } + } + + public class Lot + { + public Identifier Identifier { get; set; } + [JsonProperty("SerialNumberIdentifier")] + public List SerialNumberIdentifiers { get; set; } + } + + public class Item + { + public ManufacturerItemIdentification ManufacturerItemIdentification { get; set; } + public string Upcid { get; set; } + public string Gtinid { get; set; } + public string Description { get; set; } + public string ProductName { get; set; } + public string BrandName { get; set; } + public string VarietyName { get; set; } + } + + public class ManufacturerItemIdentification + { + public string TypeCode { get; set; } + public string Identifier { get; set; } + } + + public class Quantity + { + public string Content { get; set; } + public string UnitCode { get; set; } + } + + public class Classification + { + public string TypeCode { get; set; } + public CodeList Codes { get; set; } + } + + public class Code + { + public string Content { get; set; } + public string ListAgencyIdentifier { get; set; } + public string TypeCode { get; set; } + } + + public class CodeList + { + [JsonProperty("Code")] + public List Codes { get; set; } + } + + public class Packaging + { + public string TypeCode { get; set; } + public string Identifier { get; set; } + } + + public class DocumentReference + { + public string TypeCode { get; set; } + public Identifier Identifier { get; set; } + public string DocumentDateTime { get; set; } + } + + public class Attachment + { + public string TypeCode { get; set; } + public string Uri { get; set; } + } + + public class ManufacturingParty + { + public Identifier Identifier { get; set; } + public string Name { get; set; } + } + + public class Party + { + public string TypeCode { get; set; } + [JsonProperty("Identifier")] + public List Identifiers { get; set; } + public string Name { get; set; } + public Location Location { get; set; } + } + + public class Location + { + public string Name { get; set; } + public string Glnid { get; set; } + } + + public class Result + { + public List Quantitative { get; set; } + } + + public class Quantitative + { + public string TypeCode { get; set; } + public string Name { get; set; } + public UomCode UomCode { get; set; } + public string SignificantDigitsNumber { get; set; } + [JsonProperty("Measurement")] + public Measurement[] Measurements { get; set; } + } + + public class UomCode + { + public string Content { get; set; } + public string ListIdentifier { get; set; } + public string ListAgencyIdentifier { get; set; } + } + + public class Measurement + { + public string DateTime { get; set; } + public string Measure { get; set; } + } +} diff --git a/ShippedItemInstancePlugin/Plugin.cs b/ShippedItemInstancePlugin/Plugin.cs new file mode 100644 index 0000000..2ce3597 --- /dev/null +++ b/ShippedItemInstancePlugin/Plugin.cs @@ -0,0 +1,141 @@ +/******************************************************************************* + * Copyright (C) 2021 AgGateway and ADAPT Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Rob Cederberg, Kelly Nelson - initial implementation + *******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using AgGateway.ADAPT.ApplicationDataModel.ADM; +using Newtonsoft.Json; + +namespace AgGateway.ADAPT.ShippedItemInstancePlugin +{ + public class Plugin : IPlugin + { + #region IPlugin implementation + public string Name => "Shipped_Item_Instance-Plugin"; + + public string Version => "1.0"; + + public string Owner => "AgGateway"; + + public IList Errors { get; set; } + + public void Export(ApplicationDataModel.ADM.ApplicationDataModel dataModel, string exportPath, Properties properties = null) + { + throw new NotImplementedException(); + } + + public Properties GetProperties(string dataPath) + { + throw new NotImplementedException(); + } + + public IList Import(string dataPath, Properties properties = null) + { + IList models = new List(); + + List errors = new List(); + + List fileNames = GetInputFiles(dataPath); + + fileNames.Sort(); // required to ensure OS file system sorting differences are handled + + foreach (string fileName in fileNames) + { + + try + { + string jsonText = File.ReadAllText(fileName); + + Model.Document document = JsonConvert.DeserializeObject(jsonText); + if (document.ShippedItemInstances != null) + { + //Each document will import as individual ApplicationDataModel + ApplicationDataModel.ADM.ApplicationDataModel adm = new ApplicationDataModel.ADM.ApplicationDataModel(); + adm.Catalog = new Catalog() { Description = fileName }; + + //Map the document data into the Catalog + Mapper mapper = new Mapper(adm.Catalog); + errors.AddRange(mapper.MapDocument(document)); + + models.Add(adm); + } + else + { + errors.Add(new Error(null, $"Importing {fileName}", "Couldn't parse ShippedItemInstances", null)); + } + } + catch (Exception ex) + { + errors.Add(new Error(null, $"Exception Importing {fileName}", ex.Message, ex.StackTrace)); + } + } + + //Read the Errors property after import to inspect any diagnostic messages. + Errors = errors; + + return models; + } + + public void Initialize(string args = null) + { + } + + public bool IsDataCardSupported(string dataPath, Properties properties = null) + { + List fileNames = GetInputFiles(dataPath); + + foreach (string fileName in fileNames) + { + string jsonText = File.ReadAllText(fileName); + if (jsonText.Contains("shippedItemInstance")) + { + return true; + } + } + + return false; + + } + + public IList ValidateDataOnCard(string dataPath, Properties properties = null) + { + throw new NotImplementedException(); + } + + #endregion + + #region Methods + + private List GetInputFiles(string dataPath) + { + try + { + if (Directory.Exists(dataPath)) + { + return Directory.GetFiles(dataPath, "*.json", SearchOption.TopDirectoryOnly).ToList(); + } + else + { + return new List(); + } + } + catch(Exception ex) + { + Errors.Add(new Error(null, "Plugin.GetInputFiles", "Unable to find data files", ex.StackTrace)); + return new List(); + } + } + + #endregion + } +} diff --git a/ShippedItemInstancePlugin/ShippedItemInstancePlugin.csproj b/ShippedItemInstancePlugin/ShippedItemInstancePlugin.csproj new file mode 100644 index 0000000..3ec3dc7 --- /dev/null +++ b/ShippedItemInstancePlugin/ShippedItemInstancePlugin.csproj @@ -0,0 +1,23 @@ + + + + netstandard2.0 + AgGateway.ADAPT.ShippedItemInstancePlugin + AgGateway.ADAPT.ShippedItemInstancePlugin + true + AgGateway and ADAPT Contributors + AgGateway + AgGateway ShippedItemInstancePlugin + Copyright (C) 2021 AgGateway and ADAPT Contributors + true + https://github.com/ADAPT/ShippedItemInstancePlugin + https://github.com/ADAPT/ShippedItemInstancePlugin + EPL-1.0 + + + + + + + + diff --git a/ShippedItemInstancePluginTests/ISOExportTest.cs b/ShippedItemInstancePluginTests/ISOExportTest.cs new file mode 100644 index 0000000..d264019 --- /dev/null +++ b/ShippedItemInstancePluginTests/ISOExportTest.cs @@ -0,0 +1,47 @@ +using AgGateway.ADAPT.ApplicationDataModel.ADM; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using Xunit; + +namespace ShippedItemInstancePluginTests +{ + [Collection("ShippedItemInstanceTestData")] + public class ISOExportTest + { + ShippedItemInstanceTestData _testData; + public ISOExportTest(ShippedItemInstanceTestData data) + { + _testData = data; + } + + [Fact] + public void ISOImportAndExport() + { + IList models = _testData.Models; + + //Export with the ISO Plugin and test that the data is unaltered upon re-import + string workingPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestOutput"); + Directory.CreateDirectory(workingPath); + AgGateway.ADAPT.ISOv4Plugin.Plugin isoPlugin = new AgGateway.ADAPT.ISOv4Plugin.Plugin(); + for (int i = 0; i < models.Count; i++) + { + Properties p = new Properties(); + string folder1 = Path.Combine(workingPath, "ISOExport1", i.ToString()); + Directory.CreateDirectory(folder1); + isoPlugin.Export(models[i], folder1, p); + + var isoPlugin2 = new AgGateway.ADAPT.ISOv4Plugin.Plugin(); + IList reImport = isoPlugin2.Import(folder1); + string folder2 = Path.Combine(workingPath, "ISOExport2", i.ToString()); + Directory.CreateDirectory(folder2); + isoPlugin.Export(reImport[0], folder2, p); + + string export1 = File.ReadAllText(Path.Combine(folder1, "TASKDATA", "LINKLIST.XML")); + string export2 = File.ReadAllText(Path.Combine(folder2, "TASKDATA", "LINKLIST.XML")); + Assert.Equal(export1, export2); + } + } + } +} diff --git a/ShippedItemInstancePluginTests/ShippedItemInstancePluginTests.csproj b/ShippedItemInstancePluginTests/ShippedItemInstancePluginTests.csproj new file mode 100644 index 0000000..cc1ac8f --- /dev/null +++ b/ShippedItemInstancePluginTests/ShippedItemInstancePluginTests.csproj @@ -0,0 +1,27 @@ + + + + netcoreapp3.1 + + false + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/ShippedItemInstancePluginTests/ShippedItemInstanceTest.cs b/ShippedItemInstancePluginTests/ShippedItemInstanceTest.cs new file mode 100644 index 0000000..3598265 --- /dev/null +++ b/ShippedItemInstancePluginTests/ShippedItemInstanceTest.cs @@ -0,0 +1,90 @@ +using AgGateway.ADAPT.ApplicationDataModel.ADM; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Xunit; + +namespace ShippedItemInstancePluginTests +{ + public class ShippedItemInstanceTestData + { + private IList _models; + internal IList Models + { + get + { + if (_models == null) + { + AgGateway.ADAPT.ShippedItemInstancePlugin.Plugin shippedItemInstancePlugin = new AgGateway.ADAPT.ShippedItemInstancePlugin.Plugin(); + + // use Path.Combine to ensure proper OS directory separator chars are applied + string sampleDataPath = Path.Combine("..", "..", "..", "..", "SampleData"); + _models = shippedItemInstancePlugin.Import(sampleDataPath); + } + return _models; + } + } + } + + [CollectionDefinition("ShippedItemInstanceTestData")] + public class TestData : ICollectionFixture + { + } + + [Collection("ShippedItemInstanceTestData")] + public class ShippedItemInstanceTest + { + ShippedItemInstanceTestData _testData; + public ShippedItemInstanceTest(ShippedItemInstanceTestData data) + { + _testData = data; + } + + [Fact] + public void Models() + { + Assert.Equal(3, _testData.Models.Count); + } + + [Fact] + public void Products() + { + Assert.Equal(6, _testData.Models[0].Catalog.Products.Count); + Assert.Equal(6, _testData.Models[0].Catalog.PackagedProducts.Count); + Assert.Equal(6, _testData.Models[0].Catalog.PackagedProductInstances.Count); + + Assert.Equal(10, _testData.Models[1].Catalog.Products.Count); + Assert.Equal(10, _testData.Models[1].Catalog.PackagedProducts.Count); + Assert.Equal(10, _testData.Models[1].Catalog.PackagedProductInstances.Count); + + Assert.Equal(3, _testData.Models[2].Catalog.Products.Count); + Assert.Equal(3, _testData.Models[2].Catalog.PackagedProducts.Count); + Assert.Equal(3, _testData.Models[2].Catalog.PackagedProductInstances.Count); + } + + [Fact] + public void Brands() + { + Assert.Single(_testData.Models[0].Catalog.Brands); + Assert.Single(_testData.Models[1].Catalog.Brands); + Assert.Single(_testData.Models[2].Catalog.Brands); + } + + [Fact] + public void Growers() + { + Assert.Single(_testData.Models[0].Catalog.Growers); + Assert.Single(_testData.Models[1].Catalog.Growers); + Assert.Single(_testData.Models[2].Catalog.Growers); + } + + [Fact] + public void Crops() + { + Assert.Single(_testData.Models[0].Catalog.Crops); + Assert.Single(_testData.Models[1].Catalog.Crops); + Assert.Single(_testData.Models[2].Catalog.Crops); + } + } +}