-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial economic model for tracking purchases (#1177)
* wip * acct bill/payment * tweaks for a purchase of multiple items * more tweaks * remove jupyter notebook fail on new form * remove jupyter notebook fail on model changes * model tweaks from discussion and more tests * docs/speeeling tweaks * limit MII and IIN value range
- Loading branch information
1 parent
b2c5ed4
commit 9ce1f0a
Showing
5 changed files
with
219 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
import synapse.lib.module as s_module | ||
|
||
class EconModule(s_module.CoreModule): | ||
|
||
def getModelDefs(self): | ||
return (('econ', { | ||
|
||
'types': ( | ||
|
||
('econ:pay:cvv', ('str', {'regex': '^[0-9]{1,6}$'}), { | ||
'doc': 'A Card Verification Value (CVV).'}), | ||
|
||
('econ:pay:pin', ('str', {'regex': '^[0-9]{3,6}$'}), { | ||
'doc': 'A Personal Identification Number.'}), | ||
|
||
('econ:pay:mii', ('int', {'min': 0, 'max': 9}), { | ||
'doc': 'A Major Industry Identifier (MII).'}), | ||
|
||
('econ:pay:pan', ('str', {'regex': '^(?<iin>(?<mii>[0-9]{1})[0-9]{5})[0-9]{1,13}$'}), { | ||
'doc': 'A Primary Account Number (PAN) or card number.'}), | ||
|
||
('econ:pay:iin', ('int', {'min': 0, 'max': 999999}), { | ||
'doc': 'An Issuer Id Number (IIN).'}), | ||
|
||
('econ:pay:card', ('guid', {}), { | ||
'doc': 'A single payment card.'}), | ||
|
||
('econ:purchase', ('guid', {}), { | ||
'doc': 'A purchase event.'}), | ||
|
||
('econ:acquired', ('comp', {'fields': (('purchase', 'econ:purchase'), ('item', 'ndef'))}), { | ||
'doc': 'A relationship between a purchase event and a purchased item.'}), | ||
|
||
('econ:acct:payment', ('guid', {}), { | ||
'doc': 'A payment moving currency from one monetary instrument to another.'}), | ||
|
||
# TODO currency / monetary units / crypto currency | ||
# econ:acct:bill | ||
# econ:goods econ:services | ||
|
||
# econ:bank:us:aba:rtn ( ABA Routing Number ) | ||
# econ:bank:us:account = (econ:bank:us:aba:rtn, acct) | ||
# econ:bank:swift:... | ||
), | ||
|
||
'forms': ( | ||
|
||
('econ:pay:iin', {}, ( | ||
|
||
('org', ('ou:org', {}), { | ||
'doc': 'The issuer organization.'}), | ||
|
||
('name', ('str', {'lower': True}), { | ||
'doc': 'The registered name of the issuer.'}), | ||
)), | ||
|
||
('econ:pay:card', {}, ( | ||
|
||
('pan', ('econ:pay:pan', {}), { | ||
'doc': 'The payment card number.'}), | ||
|
||
('pan:mii', ('econ:pay:mii', {}), { | ||
'doc': 'The payment card MII.'}), | ||
|
||
('pan:iin', ('econ:pay:iin', {}), { | ||
'doc': 'The payment card IIN.'}), | ||
|
||
('name', ('ps:name', {}), { | ||
'doc': 'The name as it appears on the card.'}), | ||
|
||
('expr', ('time', {}), { | ||
'doc': 'The expiration date for the card.'}), | ||
|
||
('cvv', ('econ:pay:cvv', {}), { | ||
'doc': 'The Card Verification Value on the card.'}), | ||
|
||
('pin', ('econ:pay:pin', {}), { | ||
'doc': 'The Personal Identification Number on the card.'}), | ||
)), | ||
|
||
('econ:purchase', {}, ( | ||
|
||
('by:contact', ('ps:contact', {}), { | ||
'doc': 'The contact information used to make the purchase.'}), | ||
|
||
('from:contact', ('ps:contact', {}), { | ||
'doc': 'The contact information used to sell the item.'}), | ||
|
||
('time', ('time', {}), { | ||
'doc': 'The time of the purchase.'}), | ||
|
||
('place', ('geo:place', {}), { | ||
'doc': 'The place where the purchase took place.'}), | ||
|
||
('paid', ('bool', {}), { | ||
'doc': 'Set to True if the purchase has been paid in full.'}), | ||
|
||
('paid:time', ('time', {}), { | ||
'doc': 'The point in time where the purchase was paid in full.'}), | ||
|
||
# TODO price | ||
)), | ||
|
||
('econ:acquired', {}, ( | ||
('purchase', ('econ:purchase', {}), { | ||
'doc': 'The purchase event which acquired an item.'}), | ||
('item', ('ndef', {}), { | ||
'doc': 'A reference to the item that was acquired.'}), | ||
('item:form', ('str', {}), { | ||
'doc': 'The form of item purchased.'}), | ||
)), | ||
|
||
('econ:acct:payment', {}, ( | ||
|
||
('from:pay:card', ('econ:pay:card', {}), { | ||
'doc': 'The payment card making the payment.'}), | ||
|
||
('to:contact', ('ps:contact', {}), { | ||
'doc': 'Contact information for the person/org being paid.'}), | ||
|
||
('from:contact', ('ps:contact', {}), { | ||
'doc': 'Contact information for the person/org being paid.'}), | ||
|
||
('time', ('time', {}), { | ||
'doc': 'The time the payment was processed.'}), | ||
|
||
('purchase', ('econ:purchase', {}), { | ||
'doc': 'The purchase which the payment was paying for.'}), | ||
)), | ||
), | ||
}),) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import synapse.tests.utils as s_utils | ||
|
||
import synapse.common as s_common | ||
|
||
class EconTest(s_utils.SynTest): | ||
|
||
async def test_model_econ(self): | ||
|
||
async with self.getTestCore() as core: | ||
|
||
# test card number 4024007150779444 | ||
card = (await core.nodes('[ econ:pay:card="*" :expr=201802 :name="Bob Smith" :cvv=123 :pin=1234 :pan=4024007150779444 ]'))[0] | ||
self.eq('bob smith', card.get('name')) | ||
self.eq(1517443200000, card.get('expr')) | ||
self.eq('4024007150779444', card.get('pan')) | ||
self.eq(4, card.get('pan:mii')) | ||
self.eq(402400, card.get('pan:iin')) | ||
|
||
place = s_common.guid() | ||
bycont = s_common.guid() | ||
fromcont = s_common.guid() | ||
|
||
text = f'''[ | ||
econ:purchase="*" | ||
:by:contact={bycont} | ||
:from:contact={fromcont} | ||
:time=20180202 | ||
:place={place} | ||
:paid=true | ||
:paid:time=20180202 | ||
]''' | ||
|
||
perc = (await core.nodes(text))[0] | ||
|
||
self.eq(bycont, perc.get('by:contact')) | ||
self.eq(fromcont, perc.get('from:contact')) | ||
|
||
self.eq(True, perc.get('paid')) | ||
self.eq(1517529600000, perc.get('paid:time')) | ||
|
||
self.eq(1517529600000, perc.get('time')) | ||
self.eq(place, perc.get('place')) | ||
|
||
self.len(1, await core.nodes('econ:purchase -> geo:place')) | ||
self.len(2, await core.nodes('econ:purchase -> ps:contact | uniq')) | ||
|
||
acqu = (await core.nodes(f'[ econ:acquired=({perc.ndef[1]}, (inet:fqdn,vertex.link)) ]'))[0] | ||
self.eq(perc.ndef[1], acqu.get('purchase')) | ||
|
||
self.len(1, await core.nodes('econ:acquired:item:form=inet:fqdn')) | ||
|
||
self.eq(('inet:fqdn', 'vertex.link'), acqu.get('item')) | ||
|
||
text = f'''[ | ||
econ:acct:payment="*" | ||
:to:contact={bycont} | ||
:from:contact={fromcont} | ||
:from:pay:card={card.ndef[1]} | ||
:time=20180202 | ||
:purchase={perc.ndef[1]} | ||
]''' | ||
await core.nodes(text) | ||
|
||
self.len(1, await core.nodes('econ:acct:payment +:time@=(2017,2019) +{-> econ:pay:card +:name="bob smith"}')) | ||
|
||
self.len(1, await core.nodes('econ:acct:payment -> econ:purchase')) | ||
self.len(1, await core.nodes('econ:acct:payment -> econ:pay:card')) | ||
self.len(2, await core.nodes('econ:acct:payment -> ps:contact | uniq')) |