Skip to content

Commit f43f2a8

Browse files
authored
Merge pull request CCI-MOC#73 from QuanMPhm/52.5/refactor_pi_specific
Refactored PI-specific invoices
2 parents 19ca40b + 6a36c24 commit f43f2a8

File tree

4 files changed

+107
-56
lines changed

4 files changed

+107
-56
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import os
2+
from dataclasses import dataclass
3+
4+
import pandas
5+
6+
import process_report.invoices.invoice as invoice
7+
import process_report.util as util
8+
9+
10+
@dataclass
11+
class PIInvoice(invoice.Invoice):
12+
def _prepare(self):
13+
self.pi_list = self.data[invoice.PI_FIELD].unique()
14+
15+
def export(self):
16+
def _export_pi_invoice(pi):
17+
if pandas.isna(pi):
18+
return
19+
pi_projects = self.data[self.data[invoice.PI_FIELD] == pi]
20+
pi_instituition = pi_projects[invoice.INSTITUTION_FIELD].iat[0]
21+
pi_projects.to_csv(
22+
f"{self.name}/{pi_instituition}_{pi} {self.invoice_month}.csv"
23+
)
24+
25+
if not os.path.exists(
26+
self.name
27+
): # self.name is name of folder storing invoices
28+
os.mkdir(self.name)
29+
30+
for pi in self.pi_list:
31+
_export_pi_invoice(pi)
32+
33+
def export_s3(self, s3_bucket):
34+
def _export_s3_pi_invoice(pi_invoice):
35+
pi_invoice_path = os.path.join(self.name, pi_invoice)
36+
striped_invoice_path = os.path.splitext(pi_invoice_path)[0]
37+
output_s3_path = f"Invoices/{self.invoice_month}/{striped_invoice_path}.csv"
38+
output_s3_archive_path = f"Invoices/{self.invoice_month}/Archive/{striped_invoice_path} {util.get_iso8601_time()}.csv"
39+
s3_bucket.upload_file(pi_invoice_path, output_s3_path)
40+
s3_bucket.upload_file(pi_invoice_path, output_s3_archive_path)
41+
42+
for pi_invoice in os.listdir(self.name):
43+
_export_s3_pi_invoice(pi_invoice)

process_report/process_report.py

+7-39
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import argparse
2-
import os
32
import sys
43
import datetime
54

@@ -14,6 +13,7 @@
1413
billable_invoice,
1514
NERC_total_invoice,
1615
bu_internal_invoice,
16+
pi_specific_invoice,
1717
)
1818

1919

@@ -262,17 +262,13 @@ def main():
262262
subsidy_amount=args.BU_subsidy_amount,
263263
)
264264

265-
process_and_export_invoices([nerc_total_inv, bu_internal_inv], args.upload_to_s3)
266-
267-
export_pi_billables(billable_inv.data.copy(), args.output_folder, invoice_month)
268-
269-
if args.upload_to_s3:
270-
invoice_list = list()
271-
272-
for pi_invoice in os.listdir(args.output_folder):
273-
invoice_list.append(os.path.join(args.output_folder, pi_invoice))
265+
pi_inv = pi_specific_invoice.PIInvoice(
266+
name=args.output_folder, invoice_month=invoice_month, data=billable_inv.data
267+
)
274268

275-
upload_to_s3(invoice_list, invoice_month)
269+
process_and_export_invoices(
270+
[nerc_total_inv, bu_internal_inv, pi_inv], args.upload_to_s3
271+
)
276272

277273

278274
def fetch_s3_invoices(invoice_month):
@@ -390,33 +386,5 @@ def export_billables(dataframe, output_file):
390386
dataframe.to_csv(output_file, index=False)
391387

392388

393-
def export_pi_billables(dataframe: pandas.DataFrame, output_folder, invoice_month):
394-
if not os.path.exists(output_folder):
395-
os.mkdir(output_folder)
396-
397-
pi_list = dataframe[PI_FIELD].unique()
398-
399-
for pi in pi_list:
400-
if pandas.isna(pi):
401-
continue
402-
pi_projects = dataframe[dataframe[PI_FIELD] == pi]
403-
pi_instituition = pi_projects[INSTITUTION_FIELD].iat[0]
404-
pi_projects.to_csv(
405-
output_folder + f"/{pi_instituition}_{pi}_{invoice_month}.csv", index=False
406-
)
407-
408-
409-
def upload_to_s3(invoice_list: list, invoice_month):
410-
invoice_bucket = get_invoice_bucket()
411-
for invoice_filename in invoice_list:
412-
striped_filename = os.path.splitext(invoice_filename)[0]
413-
invoice_s3_path = (
414-
f"Invoices/{invoice_month}/{striped_filename} {invoice_month}.csv"
415-
)
416-
invoice_s3_path_archive = f"Invoices/{invoice_month}/Archive/{striped_filename} {invoice_month} {get_iso8601_time()}.csv"
417-
invoice_bucket.upload_file(invoice_filename, invoice_s3_path)
418-
invoice_bucket.upload_file(invoice_filename, invoice_s3_path_archive)
419-
420-
421389
if __name__ == "__main__":
422390
main()

process_report/tests/unit_tests.py

+31-16
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,13 @@ def setUp(self):
182182

183183
def test_export_pi(self):
184184
output_dir = tempfile.TemporaryDirectory()
185-
process_report.export_pi_billables(
186-
self.dataframe, output_dir.name, self.invoice_month
185+
pi_inv = test_utils.new_pi_specific_invoice(
186+
output_dir.name, invoice_month=self.invoice_month, data=self.dataframe
187187
)
188-
189-
pi_csv_1 = f'{self.dataframe["Institution"][0]}_{self.dataframe["Manager (PI)"][0]}_{self.dataframe["Invoice Month"][0]}.csv'
190-
pi_csv_2 = f'{self.dataframe["Institution"][3]}_{self.dataframe["Manager (PI)"][3]}_{self.dataframe["Invoice Month"][3]}.csv'
188+
pi_inv.process()
189+
pi_inv.export()
190+
pi_csv_1 = f'{self.dataframe["Institution"][0]}_{self.dataframe["Manager (PI)"][0]} {self.dataframe["Invoice Month"][0]}.csv'
191+
pi_csv_2 = f'{self.dataframe["Institution"][3]}_{self.dataframe["Manager (PI)"][3]} {self.dataframe["Invoice Month"][3]}.csv'
191192
self.assertIn(pi_csv_1, os.listdir(output_dir.name))
192193
self.assertIn(pi_csv_2, os.listdir(output_dir.name))
193194
self.assertEqual(
@@ -789,32 +790,46 @@ def test_process_lenovo(self):
789790

790791
class TestUploadToS3(TestCase):
791792
@mock.patch("process_report.process_report.get_invoice_bucket")
792-
@mock.patch("process_report.process_report.get_iso8601_time")
793-
def test_remove_prefix(self, mock_get_time, mock_get_bucket):
793+
@mock.patch("process_report.util.get_iso8601_time")
794+
def test_upload_to_s3(self, mock_get_time, mock_get_bucket):
794795
mock_bucket = mock.MagicMock()
795796
mock_get_bucket.return_value = mock_bucket
796797
mock_get_time.return_value = "0"
797798

798799
invoice_month = "2024-03"
799-
filenames = ["test.csv", "test2.test.csv", "test3"]
800+
filenames = ["test-test", "test2.test", "test3"]
801+
sample_base_invoice = test_utils.new_base_invoice(invoice_month=invoice_month)
802+
800803
answers = [
801-
("test.csv", f"Invoices/{invoice_month}/test {invoice_month}.csv"),
802804
(
803-
"test.csv",
804-
f"Invoices/{invoice_month}/Archive/test {invoice_month} 0.csv",
805+
f"test-test {invoice_month}.csv",
806+
f"Invoices/{invoice_month}/test-test {invoice_month}.csv",
805807
),
806808
(
807-
"test2.test.csv",
809+
f"test-test {invoice_month}.csv",
810+
f"Invoices/{invoice_month}/Archive/test-test {invoice_month} 0.csv",
811+
),
812+
(
813+
f"test2.test {invoice_month}.csv",
808814
f"Invoices/{invoice_month}/test2.test {invoice_month}.csv",
809815
),
810816
(
811-
"test2.test.csv",
817+
f"test2.test {invoice_month}.csv",
812818
f"Invoices/{invoice_month}/Archive/test2.test {invoice_month} 0.csv",
813819
),
814-
("test3", f"Invoices/{invoice_month}/test3 {invoice_month}.csv"),
815-
("test3", f"Invoices/{invoice_month}/Archive/test3 {invoice_month} 0.csv"),
820+
(
821+
f"test3 {invoice_month}.csv",
822+
f"Invoices/{invoice_month}/test3 {invoice_month}.csv",
823+
),
824+
(
825+
f"test3 {invoice_month}.csv",
826+
f"Invoices/{invoice_month}/Archive/test3 {invoice_month} 0.csv",
827+
),
816828
]
817829

818-
process_report.upload_to_s3(filenames, invoice_month)
830+
for filename in filenames:
831+
sample_base_invoice.name = filename
832+
sample_base_invoice.export_s3(mock_bucket)
833+
819834
for i, call_args in enumerate(mock_bucket.upload_file.call_args_list):
820835
self.assertTrue(answers[i] in call_args)

process_report/tests/util.py

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
import pandas
22

3-
from process_report.invoices import billable_invoice, bu_internal_invoice
3+
from process_report.invoices import (
4+
invoice,
5+
billable_invoice,
6+
bu_internal_invoice,
7+
pi_specific_invoice,
8+
)
9+
10+
11+
def new_base_invoice(
12+
name="",
13+
invoice_month="0000-00",
14+
data=pandas.DataFrame(),
15+
):
16+
return invoice.Invoice(name, invoice_month, data)
417

518

619
def new_billable_invoice(
@@ -27,3 +40,15 @@ def new_bu_internal_invoice(
2740
return bu_internal_invoice.BUInternalInvoice(
2841
name, invoice_month, data, subsidy_amount
2942
)
43+
44+
45+
def new_pi_specific_invoice(
46+
name="",
47+
invoice_month="0000-00",
48+
data=pandas.DataFrame(),
49+
):
50+
return pi_specific_invoice.PIInvoice(
51+
name,
52+
invoice_month,
53+
data,
54+
)

0 commit comments

Comments
 (0)