Skip to content

Commit 5f8a1ab

Browse files
committed
Support for summary output in csv format
1 parent c24ca7d commit 5f8a1ab

File tree

6 files changed

+80
-6
lines changed

6 files changed

+80
-6
lines changed

casparser/cli.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from . import read_cas_pdf
1717
from .enums import CASFileType
1818
from .exceptions import ParserException
19-
from .parsers.utils import is_close, cas2json, cas2csv
19+
from .parsers.utils import is_close, cas2json, cas2csv, cas2csv_summary
2020

2121
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
2222

@@ -95,9 +95,7 @@ def print_summary(data, tablefmt="fancy_grid", output_filename=None, include_zer
9595
if scheme["close"] < 1e-3 and not include_zero_folios:
9696
continue
9797

98-
calc_close = scheme["open"] + sum(
99-
[x["units"] for x in scheme["transactions"] if x["units"] is not None]
100-
)
98+
calc_close = scheme.get("close_calculated", "open")
10199
valuation = scheme["valuation"]
102100

103101
# Check is calculated close (i.e. open + units from all transactions) is same as
@@ -230,8 +228,15 @@ def cli(output, summary, password, include_all, force_pdfminer, filename):
230228
include_zero_folios=include_all,
231229
output_filename=None if output_ext in (".csv", ".json") else output,
232230
)
231+
233232
if output_ext in (".csv", ".json"):
234-
conv_fn = cas2json if output_ext == ".json" else cas2csv
233+
if output_ext == ".csv":
234+
if summary or data["cas_type"] == CASFileType.SUMMARY.name:
235+
conv_fn = cas2csv_summary
236+
else:
237+
conv_fn = cas2csv
238+
else:
239+
conv_fn = cas2json
235240
with open(output, "w", newline="", encoding="utf-8") as fp:
236241
fp.write(conv_fn(data))
237242
click.echo("File saved : " + click.style(output, bold=True))

casparser/parsers/utils.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,51 @@ def cas2json(data: CASParserDataType) -> str:
2626
return json.dumps(data, cls=CASDataEncoder)
2727

2828

29+
def cas2csv_summary(data: CASParserDataType) -> str:
30+
with io.StringIO() as csv_fp:
31+
header = [
32+
"amc",
33+
"folio",
34+
"advisor",
35+
"registrar",
36+
"pan",
37+
"scheme",
38+
"isin",
39+
"amfi",
40+
"open",
41+
"close",
42+
"value",
43+
"date",
44+
"transactions",
45+
]
46+
writer = csv.DictWriter(csv_fp, fieldnames=header)
47+
writer.writeheader()
48+
current_amc = None
49+
for folio in data.get("folios", []):
50+
if current_amc != folio.get("amc", ""):
51+
current_amc = folio["amc"]
52+
for scheme in folio["schemes"]:
53+
row = {
54+
"amc": current_amc.replace("\n", " "),
55+
"folio": folio["folio"],
56+
"advisor": scheme["advisor"],
57+
"registrar": scheme["rta"],
58+
"pan": folio["PAN"],
59+
"scheme": scheme["scheme"].replace("\n", " "),
60+
"isin": scheme["isin"],
61+
"amfi": scheme["amfi"],
62+
"open": scheme["open"],
63+
"close": scheme["close"],
64+
"value": scheme["valuation"]["value"],
65+
"date": scheme["valuation"]["date"],
66+
"transactions": len(scheme["transactions"]),
67+
}
68+
writer.writerow(row)
69+
csv_fp.seek(0)
70+
csv_data = csv_fp.read()
71+
return csv_data
72+
73+
2974
def cas2csv(data: CASParserDataType) -> str:
3075
with io.StringIO() as csv_fp:
3176
header = [

casparser/process/cas_detailed.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,15 @@ def process_detailed_text(text):
131131
"amfi": amfi,
132132
"open": Decimal(0.0),
133133
"close": Decimal(0.0),
134+
"close_calculated": Decimal(0.0),
134135
"valuation": {"date": None, "value": 0, "nav": 0},
135136
"transactions": [],
136137
}
137138
if not curr_scheme_data:
138139
continue
139140
if m := re.search(OPEN_UNITS_RE, line):
140141
curr_scheme_data["open"] = Decimal(m.group(1).replace(",", "_"))
142+
curr_scheme_data["close_calculated"] = curr_scheme_data["open"]
141143
continue
142144
if m := re.search(CLOSE_UNITS_RE, line):
143145
curr_scheme_data["close"] = Decimal(m.group(1).replace(",", "_"))
@@ -165,6 +167,8 @@ def process_detailed_text(text):
165167
nav = Decimal(m.group(5).replace(",", "_"))
166168
balance = Decimal(m.group(6).replace(",", "_").replace("(", "-"))
167169
txn_type, dividend_rate = get_transaction_type(desc, units)
170+
if units is not None:
171+
curr_scheme_data["close_calculated"] += units
168172
curr_scheme_data["transactions"].append(
169173
{
170174
"date": date,

casparser/types.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class SchemeType(TypedDict, total=False):
4949
amfi: Optional[str]
5050
open: Union[Decimal, float]
5151
close: Union[Decimal, float]
52+
close_calculated: Union[Decimal, float]
5253
valuation: SchemeValuationType
5354
transactions: List[TransactionDataType]
5455

@@ -72,4 +73,5 @@ class CASParserDataType(TypedDict):
7273
statement_period: StatementPeriod
7374
folios: List[FolioType]
7475
investor_info: InvestorInfoType
76+
cas_type: str
7577
file_type: FileType

tests/test_mupdf.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,22 @@ def test_cli(self, tmpdir):
5050
assert result.exit_code != 1
5151
assert "File saved" in result.output
5252

53+
fpath = tmpdir.join("output.csv")
54+
result = runner.invoke(
55+
cli,
56+
[
57+
self.kfintech_file_name,
58+
"-p",
59+
self.kfintech_password,
60+
"-o",
61+
fpath.strpath,
62+
"-s",
63+
"fancy_grid",
64+
],
65+
)
66+
assert result.exit_code != 1
67+
assert "File saved" in result.output
68+
5369
result = runner.invoke(
5470
cli, [self.kfintech_file_name, "-p", self.kfintech_password, "-s", "html"]
5571
)

tests/test_process.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ def test_transaction_type(self):
4848
)
4949

5050
def test_isin_search(self):
51-
isin, amfi = isin_search("Axis Long Term Equity Fund - Direct Growth", "KFINTECH" ,"128TSDGG")
51+
isin, amfi = isin_search(
52+
"Axis Long Term Equity Fund - Direct Growth", "KFINTECH", "128TSDGG"
53+
)
5254
assert isin == "INF846K01EW2"
5355
assert amfi == "120503"
5456

0 commit comments

Comments
 (0)