Skip to content

Commit

Permalink
Merge pull request CCI-MOC#113 from QuanMPhm/102/proc_bu_subsidy
Browse files Browse the repository at this point in the history
Implemented processor for BU Subsidy
  • Loading branch information
knikolla authored Jan 6, 2025
2 parents c979154 + c81622d commit 1eea5b9
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 226 deletions.
48 changes: 12 additions & 36 deletions process_report/invoices/bu_internal_invoice.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
from dataclasses import dataclass
from decimal import Decimal

import process_report.invoices.invoice as invoice
import process_report.invoices.discount_invoice as discount_invoice


@dataclass
class BUInternalInvoice(discount_invoice.DiscountInvoice):
class BUInternalInvoice(invoice.Invoice):
"""
This invoice operates on data processed by these Processors:
- ValidateBillablePIsProcessor
Expand All @@ -20,39 +18,32 @@ class BUInternalInvoice(discount_invoice.DiscountInvoice):
invoice.COST_FIELD,
invoice.CREDIT_FIELD,
invoice.SUBSIDY_FIELD,
invoice.BALANCE_FIELD,
invoice.PI_BALANCE_FIELD,
]

subsidy_amount: int

def _prepare(self):
def get_project(row):
project_alloc = row[invoice.PROJECT_FIELD]
if project_alloc.rfind("-") == -1:
return project_alloc
else:
return project_alloc[: project_alloc.rfind("-")]
exported_columns_map = {invoice.PI_BALANCE_FIELD: "Balance"}

def _prepare_export(self):
self.data = self.data[
self.data[invoice.IS_BILLABLE_FIELD] & ~self.data[invoice.MISSING_PI_FIELD]
]
self.data = self.data[
self.data[invoice.INSTITUTION_FIELD] == "Boston University"
].copy()
self.data["Project"] = self.data.apply(get_project, axis=1)
self.data[invoice.SUBSIDY_FIELD] = Decimal(0)

def _process(self):
data_summed_projects = self._sum_project_allocations(self.data)
self.data = self._apply_subsidy(data_summed_projects, self.subsidy_amount)
]
self.data = self._sum_project_allocations(self.data)

def _sum_project_allocations(self, dataframe):
"""A project may have multiple allocations, and therefore multiple rows
in the raw invoices. For BU-Internal invoice, we only want 1 row for
each unique project, summing up its allocations' costs"""
project_list = dataframe["Project"].unique()
data_no_dup = dataframe.drop_duplicates("Project", inplace=False)
sum_fields = [invoice.COST_FIELD, invoice.CREDIT_FIELD, invoice.BALANCE_FIELD]
sum_fields = [
invoice.COST_FIELD,
invoice.CREDIT_FIELD,
invoice.SUBSIDY_FIELD,
invoice.PI_BALANCE_FIELD,
]
for project in project_list:
project_mask = dataframe["Project"] == project
no_dup_project_mask = data_no_dup["Project"] == project
Expand All @@ -61,18 +52,3 @@ def _sum_project_allocations(self, dataframe):
data_no_dup.loc[no_dup_project_mask, sum_fields] = sum_fields_sums

return data_no_dup

def _apply_subsidy(self, dataframe, subsidy_amount):
pi_list = dataframe[invoice.PI_FIELD].unique()

for pi in pi_list:
pi_projects = dataframe[dataframe[invoice.PI_FIELD] == pi]
self.apply_flat_discount(
dataframe,
pi_projects,
subsidy_amount,
invoice.SUBSIDY_FIELD,
invoice.BALANCE_FIELD,
)

return dataframe
79 changes: 0 additions & 79 deletions process_report/invoices/discount_invoice.py

This file was deleted.

1 change: 1 addition & 0 deletions process_report/invoices/invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
IS_BILLABLE_FIELD = "Is Billable"
MISSING_PI_FIELD = "Missing PI"
PI_BALANCE_FIELD = "PI Balance"
PROJECT_NAME_FIELD = "Project"
###


Expand Down
9 changes: 7 additions & 2 deletions process_report/process_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
lenovo_processor,
validate_billable_pi_processor,
new_pi_credit_processor,
bu_subsidy_processor,
)

### PI file field names
Expand Down Expand Up @@ -242,7 +243,12 @@ def main():
)
new_pi_credit_proc.process()

processed_data = new_pi_credit_proc.data
bu_subsidy_proc = bu_subsidy_processor.BUSubsidyProcessor(
"", invoice_month, new_pi_credit_proc.data.copy(), args.BU_subsidy_amount
)
bu_subsidy_proc.process()

processed_data = bu_subsidy_proc.data

### Initialize invoices

Expand Down Expand Up @@ -280,7 +286,6 @@ def main():
name=args.BU_invoice_file,
invoice_month=invoice_month,
data=processed_data.copy(),
subsidy_amount=args.BU_subsidy_amount,
)

pi_inv = pi_specific_invoice.PIInvoice(
Expand Down
56 changes: 56 additions & 0 deletions process_report/processors/bu_subsidy_processor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from dataclasses import dataclass
from decimal import Decimal

from process_report.invoices import invoice
from process_report.processors import discount_processor


@dataclass
class BUSubsidyProcessor(discount_processor.DiscountProcessor):
IS_DISCOUNT_BY_NERC = False

subsidy_amount: int

def _prepare(self):
def get_project(row):
project_alloc = row[invoice.PROJECT_FIELD]
if project_alloc.rfind("-") == -1:
return project_alloc
else:
return project_alloc[: project_alloc.rfind("-")]

self.data[invoice.PROJECT_NAME_FIELD] = self.data.apply(get_project, axis=1)
self.data[invoice.SUBSIDY_FIELD] = Decimal(0)

def _process(self):
self.data = self._apply_subsidy(self.data, self.subsidy_amount)

@staticmethod
def _get_subsidy_eligible_projects(data):
filtered_data = data[
data[invoice.IS_BILLABLE_FIELD] & ~data[invoice.MISSING_PI_FIELD]
]
filtered_data = filtered_data[
filtered_data[invoice.INSTITUTION_FIELD] == "Boston University"
].copy()

return filtered_data

def _apply_subsidy(self, dataframe, subsidy_amount):
subsidy_eligible_projects = self._get_subsidy_eligible_projects(dataframe)
pi_list = subsidy_eligible_projects[invoice.PI_FIELD].unique()

for pi in pi_list:
pi_projects = subsidy_eligible_projects[
subsidy_eligible_projects[invoice.PI_FIELD] == pi
]
self.apply_flat_discount(
dataframe,
pi_projects,
invoice.PI_BALANCE_FIELD,
subsidy_amount,
invoice.SUBSIDY_FIELD,
invoice.BALANCE_FIELD,
)

return dataframe
Loading

0 comments on commit 1eea5b9

Please sign in to comment.