-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TDL-13967: Add ProfitAndLoss report stream #37
base: master
Are you sure you want to change the base?
Conversation
8f786ff
to
b7b19cd
Compare
tap_quickbooks/streams.py
Outdated
params["end_date"] = end_tm_str | ||
|
||
resp = self.client.get(self.endpoint, params=params) | ||
self.parse_report_metadata(resp) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think having parse_report_metadata()
be recursive is excessive. The resp
onse object here is just three keys, Header
(which we ignore), Rows
, and Columns
.
Parsing resp['Columns']
seems like a loop over resp['Columns']['Column']
and filtering the 'Metadata'
.
Parsing resp['Rows']
is the only recursive part, so we can repurpose most of the logic in parse_report_metadata()
into parse_rows()
or something
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Split down parse_report_metadata()
into two functions parse_report_columns()
and parse_report_rows()
.
parse_report_columns()
will parse resp['Columns']
with a loop over resp['Columns']['Column']
and filters Metadata
.
parse_report_rows()
is the recursive one which will parse resp['Rows']
.
tap_quickbooks/streams.py
Outdated
'data': [] | ||
} | ||
|
||
start_tm_str = strftime(start_dttm)[0:10] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use str(start_dttm.date()) to get date
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated date retrieval as per suggestion.
tap_quickbooks/streams.py
Outdated
columns = pileOfColumns.get('Column', []) | ||
for column in columns: | ||
metadatas = column.get('MetaData', []) | ||
for md in metadatas: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer instead of using md have more descriptive variable name like metadata
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated md
with proper variable name metadata
tap_quickbooks/streams.py
Outdated
''' | ||
|
||
if isinstance(pileOfRows, list): | ||
for x in pileOfRows: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stop using variable names like x. Please provide more descriptive
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated x with descriptive name row
tap_quickbooks/streams.py
Outdated
self.parse_report_rows(pileOfRows['Summary']) | ||
|
||
if 'ColData' in pileOfRows.keys(): | ||
d = dict() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stop using variable names like d. Provide more descriptive variable name. Bad coding practice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will keep in mind using descriptive variable names and updated above d with a proper name.
tap_quickbooks/streams.py
Outdated
for x in pileOfRows['ColData'][1:]: | ||
vals.append(x['value']) | ||
d['values'] = vals | ||
self.parsed_metadata['data'].append(d) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No x, d variable names. Provide descriptive names
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated x,d types of variables with proper descriptive names.
reports = self.day_wise_reports() | ||
if reports: | ||
for report in reports: | ||
yield report |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the difference between yield report and yield from report? I've seen in many places using yield from report
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
yield from reports
andyield
inside for loops, both return generators with every element ofreports
. -
The python generator will flush out after iteration over it and here,
reports
is a generator, and tap use last report fromreports
for storing bookmark. -
If we use
yield from reports
then no way to retrieve the last report after it so we usedyield with for loop
here to utilize the loop's local variablereport
to retrieve the last report.
tap-quickbooks/tap_quickbooks/streams.py
Line 260 in b6e8e4a
self.state = singer.write_bookmark(self.state, self.stream_name, 'LastUpdatedTime', strptime_to_utc(report.get('ReportDate')).isoformat()) |
@@ -193,6 +198,151 @@ class Vendors(Stream): | |||
table_name = 'Vendor' | |||
additional_where = "Active IN (true, false)" | |||
|
|||
class ReportStream(Stream): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add more comments to the code to explain at each section what is being done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added more comments to the code for better code explanation.
if 'Rows' in pileOfRows.keys(): | ||
self.parse_report_rows(pileOfRows['Rows']) | ||
|
||
if 'Row' in pileOfRows.keys(): | ||
self.parse_report_rows(pileOfRows['Row']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the difference between Rows and Row here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rows
is top-level information about profit and loss reports while Row
is information about entries of reports. Documentation of the profit and loss report's metadata: documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a suggestion.
@@ -230,3 +244,14 @@ def minimum_record_count_by_stream(self): | |||
record_counts["vendors"] = 26 | |||
|
|||
return record_counts | |||
|
|||
def dt_to_ts(self, dtime): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Raising an exception after this for loop would prevent the test from getting back a None and failing in a confusing way in the case where the datetime format is unaccounted for.
Description of change
TDL-13967: Add ProfitAndLoss report stream
Finalized approach:
Manual QA steps
Risks
Rollback steps