Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/spaceone/cost_analysis/model/cost_report/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class CostReport(MongoModel):
cost_report_id = StringField(max_length=40, generate_id="cost-report", unique=True)
cost = DictField(default={})
status = StringField(
max_length=20, choices=["IN_PROGRESS", "ADJUSTING", "DONE"], required=True
max_length=20, choices=["IN_PROGRESS", "ADJUSTING", "DONE", "EXPIRED"], required=True
)
report_number = StringField(max_length=255)
currency = StringField(choices=["KRW", "USD", "JPY"], required=True)
Expand Down
2 changes: 1 addition & 1 deletion src/spaceone/cost_analysis/model/cost_report/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"CostReportDataStatQueryRequest",
]

Status = Literal["IN_PROGRESS", "ADJUSTING", "DONE"]
Status = Literal["IN_PROGRESS", "ADJUSTING", "DONE", "EXPIRED"]


class CostReportSendRequest(BaseModel):
Expand Down
94 changes: 29 additions & 65 deletions src/spaceone/cost_analysis/service/cost_report_serivce.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
from dateutil.relativedelta import relativedelta
from datetime import datetime, timezone
from typing import Tuple, Union
from datetime import timedelta

from mongoengine import QuerySet
from spaceone.core import config
from spaceone.core.plugin import serve
from spaceone.core.service import *

from spaceone.cost_analysis.manager import DataSourceAccountManager
Expand Down Expand Up @@ -265,8 +263,6 @@ def create_cost_report(self, params: dict):
metadata["is_last_day"],
current_date,
adjustment_options,
domain_id,
cost_report_config_id,
)
)

Expand Down Expand Up @@ -310,6 +306,27 @@ def create_cost_report(self, params: dict):
def _get_all_cost_report_configs(self) -> QuerySet:
return self.cost_report_config_mgr.filter_cost_report_configs(state="ENABLED")

def _change_status_to_expired(
self,
report_month: str,
domain_id: str,
cost_report_config_id: str,
):
cost_report_update_query = {
"filter": [
{"k": "cost_report_config_id", "v": cost_report_config_id, "o": "eq"},
{"k": "report_month", "v": report_month, "o": "eq"},
{"k": "domain_id", "v": domain_id, "o": "eq"},
]
}

cost_reports_vos, total_count = self.cost_report_mgr.list_cost_reports(
cost_report_update_query
)

for cost_report_vo in cost_reports_vos:
Copy link

Copilot AI Jun 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Iterating and updating each report one by one may be inefficient for large datasets; consider using a bulk update query if supported by the manager.

Copilot uses AI. Check for mistakes.
self.cost_report_mgr.update_cost_report_by_vo({"status": "EXPIRED"}, cost_report_vo)

def _delete_old_cost_reports(
self,
report_month: str,
Expand All @@ -321,8 +338,8 @@ def _delete_old_cost_reports(
"filter": [
{"k": "cost_report_config_id", "v": cost_report_config_id, "o": "eq"},
{"k": "report_month", "v": report_month, "o": "eq"},
# {"k": "status", "v": "DONE", "o": "not"},
{"k": "domain_id", "v": domain_id, "o": "eq"},
{"k": "status", "v": ["DONE","EXPIRED"], "o": "not"},
{"k": "created_at", "v": cost_report_created_at, "o": "lt"},
]
}
Expand Down Expand Up @@ -489,18 +506,16 @@ def _calculate_report_flags_and_report_month(
is_last_day: bool,
current_date: datetime,
adjustment_options: dict,
domain_id: str,
cost_report_config_id: str,
) -> Tuple[bool, bool, str]:
create_in_progress_report = False
create_adjusting_report = False

adjustment_state = adjustment_options.get("enabled", False)
adjustment_period = adjustment_options.get("period", 0)
self.is_within_adjustment_period = adjustment_state and adjustment_period > 0

retry_days = min(config.get_global("COST_REPORT_RETRY_DAYS", 7), 10)
total_retry_days = max(adjustment_period, retry_days)
retry_start_date = current_date - relativedelta(days=total_retry_days)
retry_start_date = current_date - relativedelta(days=retry_days)

if retry_start_date.month != current_date.month:
issue_base_date = current_date - relativedelta(months=1)
Expand All @@ -517,67 +532,13 @@ def _calculate_report_flags_and_report_month(

if current_date < issue_date:
create_in_progress_report = True
elif issue_date <= current_date < done_date:
else:
create_adjusting_report = True
elif current_date >= done_date:
if not self._check_done_cost_report_exist(domain_id, cost_report_config_id, report_month):
create_adjusting_report = True
if current_date >= done_date:
self.is_done_report = True

self.is_within_adjustment_period = adjustment_state and adjustment_period > 0

return create_in_progress_report, create_adjusting_report, report_month

# adjustment_state = adjustment_options.get("enabled", False)
# adjustment_period = adjustment_options.get("period", 0)
# retry_days = min(config.get_global("COST_REPORT_RETRY_DAYS", 7), 10)
# current_day = current_date.day
#
# total_retry_days = retry_days + adjustment_period
# retry_start_date = current_date - relativedelta(days=total_retry_days)
#
# if retry_start_date.month != current_date.month:
# issue_month = current_date - relativedelta(months=1)
# issue_day = self.get_issue_day(is_last_day, issue_day, issue_month)
# issue_date = issue_month.replace(day=issue_day)
# report_date = current_date - relativedelta(months=2)
# else:
# issue_date = current_date.replace(day=issue_day)
# report_date = current_date - relativedelta(months=1)
#
# report_month = report_date.strftime("%Y-%m")
# done_date = issue_date + relativedelta(days=adjustment_period)
#
# create_adjusting_report = False
#
# # check the retry process
# if retry_start_date < done_date <= current_date:
# create_adjusting_report = True
# if adjustment_state and adjustment_period > 0:
# self.is_within_adjustment_period = True
# self.is_done_report = True
#
# if create_adjusting_report and self._check_done_cost_report_exist(
# domain_id, cost_report_config_id, report_month
# ):
# create_adjusting_report = False
#
# # check the normal process
# if issue_date == current_date:
# create_adjusting_report = True
# report_month = (current_date - relativedelta(months=1)).strftime("%Y-%m")
#
# if current_date == done_date:
# self.is_done_report = True
# self.is_within_adjustment_period = True
# create_adjusting_report = True
#
# if issue_date <= current_date <= done_date:
# if adjustment_state and adjustment_period > 0:
# self.is_within_adjustment_period = True
#
# return create_adjusting_report, report_month

def _check_done_cost_report_exist(
self,
domain_id: str,
Expand Down Expand Up @@ -706,6 +667,9 @@ def _persist_cost_reports_by_status(
cost_report_vo = self._update_cost_report_done_status(cost_report_vo)
self.send_cost_report(cost_report_vo)

if self._check_done_cost_report_exist(domain_id, cost_report_config_id, report_month):
self._change_status_to_expired(domain_id, cost_report_config_id, report_month)
Copy link

Copilot AI Jun 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The argument order for _change_status_to_expired doesn’t match its signature (report_month, domain_id, cost_report_config_id). Swap them to (report_month, domain_id, cost_report_config_id).

Suggested change
self._change_status_to_expired(domain_id, cost_report_config_id, report_month)
self._change_status_to_expired(report_month, domain_id, cost_report_config_id)

Copilot uses AI. Check for mistakes.

self._delete_old_cost_reports(
report_month,
domain_id,
Expand Down
Loading