diff --git a/atst/domain/task_orders.py b/atst/domain/task_orders.py
index 0b449083..b8653af5 100644
--- a/atst/domain/task_orders.py
+++ b/atst/domain/task_orders.py
@@ -29,7 +29,7 @@ class TaskOrders(object):
to_data = TaskOrders._client().get_contract(order_number, status="y")
if to_data:
# TODO: we need to determine exactly what we're getting and storing from the EDA client
- return TaskOrders.create(number=to_data["contract_no"], source=Source.EDA)
+ return TaskOrders.create(source=Source.EDA, **to_data)
else:
raise NotFoundError("task_order")
diff --git a/atst/eda_client.py b/atst/eda_client.py
index 51b25522..fe56cd0a 100644
--- a/atst/eda_client.py
+++ b/atst/eda_client.py
@@ -5,6 +5,42 @@ import requests
from requests.auth import HTTPBasicAuth
+def parse_eda_xml(xml_string):
+ contract_et = ET.fromstring(xml_string)
+ handler = EDAXMLHandler(contract_et)
+ handler.parse()
+ return {
+ "clin_0001": handler.clins.get("0001"),
+ "clin_0003": handler.clins.get("0003"),
+ "clin_1001": handler.clins.get("1001"),
+ "clin_1003": handler.clins.get("1003"),
+ "clin_2001": handler.clins.get("2001"),
+ "clin_2003": handler.clins.get("2003"),
+ }
+
+
+class EDAXMLHandler:
+ def __init__(self, element_tree):
+ self.element_tree = element_tree
+ self.clins = {}
+
+ @property
+ def _line_items(self):
+ return self.element_tree.findall(".//LineItem[LineItemType='CLIN']/../../..")
+
+ def parse(self):
+ for line_item in self._line_items:
+ number_el = line_item.find(".//LineItemBase")
+ amount_details = line_item.find(
+ ".//ItemOtherAmounts[AmountDescription='Not to Exceed Amount (Funding)']/Amount"
+ )
+ if number_el is not None and amount_details is not None:
+ try:
+ self.clins[number_el.text] = float(amount_details.text)
+ except ValueError:
+ continue
+
+
class EDAClientBase(object):
def list_contracts(
self,
@@ -80,24 +116,16 @@ class MockEDAClient(EDAClientBase):
MOCK_CONTRACT_NUMBER = "DCA10096D0052"
- # TODO: It seems likely that this will have to supply CLIN data form the
- # EDA returnclinXML API call, in addition to the basic task order data
- # below. See the EDA docs.
def get_contract(self, contract_number, status):
if contract_number == self.MOCK_CONTRACT_NUMBER and status == "y":
return {
- "aco_mod": "01",
- "admin_dodaac": None,
- "cage_code": "1U305",
- "contract_no": "DCA10096D0052",
- "delivery_order": "0084",
- "duns_number": None,
- "issue_date": "20000228",
- "issue_dodaac": None,
- "location": "https://docsrv1.nit.disa.mil:443/eda/enforcer/C0414345.PDF?ver=1.4&loc=Y29udHJhY3RzL29nZGVuL3ZlbmRvci8xOTk4LzA5LzE0L0MwNDE0MzQ1LlBERg==&sourceurl=aHR0cHM6Ly9lZGE0Lm5pdC5kaXNhLm1pbC9wbHMvdXNlci9uZXdfYXBwLkdldF9Eb2M_cFRhYmxlX0lEPTImcFJlY29yZF9LZXk9OEE2ODExNjM2RUY5NkU2M0UwMzQwMDYwQjBCMjgyNkM=&uid=6CFC2B2322E86FD5E054002264936E3C&qid=19344159&signed=G&qdate=20180529194407GMT&token=6xQICrrrfIMciEJSpXmfsAYrToM=",
- "pay_dodaac": None,
- "pco_mod": "02",
- "amount": 2_000_000,
+ "number": "DCA10096D0052",
+ "clin_0001": 500,
+ "clin_0003": 600,
+ "clin_1001": 700,
+ "clin_1003": 800,
+ "clin_2001": 900,
+ "clin_2003": 1000,
}
else:
return None
@@ -150,7 +178,10 @@ class EDAClient(EDAClientBase):
)
if response.text.startswith("No data found"):
return None
- return ET.fromstring(response.text)
+
+ eda_data = {"number": contract_number}
+ eda_data.update(parse_eda_xml(response.text))
+ return eda_data
def get_clins(self, record_key, clins, cage_code="", duns_number=""):
response = self._get(
diff --git a/tests/fixtures/eda_contract.xml b/tests/fixtures/eda_contract.xml
new file mode 100644
index 00000000..14dad743
--- /dev/null
+++ b/tests/fixtures/eda_contract.xml
@@ -0,0 +1,239 @@
+
+ 2.5
+ DD 1155
+
+ 3244871
+
+ 00000431
+ 704331
+
+
+
+
+
+ Department of Defense
+ Delivery Order
+ 70433119F2644
+ Represented Contract
+
+
+ Department of Defense
+ Basic Ordering Agreement
+ W81K0419G0001
+ Ordering Instrument
+
+
+ false
+ Original
+ false
+
+ Firm Fixed Price
+
+
+
+
+ http://farsite.hill.af.mil/reghtml/regs/far2afmcfars/fardfars/far/52_220.htm#P810_149596
+
+
+ FAR
+ 52.222-50
+ Combating Trafficking in Persons.
+ 2015-05
+
+
+ [ lots of text ]
+
+
+
+
+
+ FAR
+ 52.245-1
+ Government Property.
+ 2012-04
+
+
+ [ lots of text ]
+
+
+
+
+
+
+ 2016-02-04
+
+ 2016-01-25
+
+ DALE WOLFE
+
+ Telephone
+ 520-533-9132
+
+
+
+
+
+ Contractor
+
+
+ 0Z7K0
+ 808152482
+
+
+ CACI TECHNOLOGIES, INC
+
+
+ 6933 Gateway Ct
+ Manassas VA, 20109
+
+
+
+
+
+
+ Contract Issuing Office
+
+
+ 704331
+
+
+ FEMA DISTRIBUTION CENTER
+
+
+ 3870 S. SIDE INDUSTRIAL CTR
+ ATLANTA GA, 30354
+
+
+
+
+
+ GENE BARBER
+
+ Telephone
+ (202) 646-2727
+
+
+
+
+ Contract Administrative Office
+
+
+ 704331
+
+
+ FEMA DISTRIBUTION CENTER
+
+
+ 3870 S. SIDE INDUSTRIAL CTR
+ ATLANTA GA, 30354
+
+
+
+
+
+
+ Paying Office
+
+
+ HQ0131
+
+
+ DEFENSE FINANCE AND ACCOUNTING SVC
+
+
+ P.O. BOX 369016
+ COLUMBUS OH, 43236
+
+
+
+
+
+
+ Ship To
+
+
+ S0302A
+
+
+ DCMA PHOENIX
+
+
+ 40 NORTH CENTRAL AVE, STE 400
+ TWO RENAISSANCE SQUARE
+ PHOENIX AZ, 85004
+
+
+
+
+
+
+
+ Header Only - Total Contract Value
+ 192000.00
+
+
+
+
+ Delivery Requested By
+
+ 2016-01-16
+
+
+
+
+
+ Defense Priorities Allocation System (DPAS) Priority Rating
+
+ DO-A7
+
+
+
+
+ Contractor
+ Origin (after Loading)
+
+
+
+
+
+
+
+
+ CLIN
+ 0001
+
+
+
+
+ false
+
+ Cost No Fee
+
+
+ Real Property
+ Radio Dishes
+ 3
+ false
+ Estimated
+ Each
+ 64000.00
+
+ Manufacturer's Part Number
+ 5L33M7730291DX081
+
+
+
+
+
+ Estimated Cost
+ 192000.00
+
+
+ Not to Exceed Amount (Funding)
+ 200000.00
+
+
+
+
+
+
diff --git a/tests/test_eda_client.py b/tests/test_eda_client.py
index 03380ee1..787ba8c8 100644
--- a/tests/test_eda_client.py
+++ b/tests/test_eda_client.py
@@ -1,20 +1,57 @@
-from atst.eda_client import MockEDAClient
+from atst.eda_client import MockEDAClient, parse_eda_xml
-client = MockEDAClient()
+mock_client = MockEDAClient()
def test_list_contracts():
- results = client.list_contracts()
+ results = mock_client.list_contracts()
assert len(results) == 3
def test_get_contract():
- result = client.get_contract("DCA10096D0052", "y")
- assert result["contract_no"] == "DCA10096D0052"
- assert result["amount"] == 2_000_000
+ result = mock_client.get_contract("DCA10096D0052", "y")
+ assert result["number"] == "DCA10096D0052"
def test_contract_not_found():
- result = client.get_contract("abc", "y")
+ result = mock_client.get_contract("abc", "y")
assert result is None
+
+
+def test_eda_xml_parser():
+ with open("tests/fixtures/eda_contract.xml") as contract:
+ eda_data = parse_eda_xml(contract.read())
+ assert eda_data["clin_0001"] == 200_000.00
+ assert not eda_data["clin_0003"]
+
+
+_EDA_XML_NO_NUMBER = """
+
+
+
+
+
+
+
+ CLIN
+ 0001
+
+
+
+
+
+ Not to Exceed Amount (Funding)
+ not a number
+
+
+
+
+
+
+"""
+
+
+def test_eda_xml_parser_with_bad_xml():
+ eda_data = parse_eda_xml(_EDA_XML_NO_NUMBER)
+ assert eda_data["clin_0001"] is None