* How to handle billing in general ** Manual test flow / setting up bills - Needs orders - ** Orders - Orders are the heart of uncloud billing - Have a starting date - Have an ending date - Orders are immutable - Can usually not be cancelled / cancellation is not a refund - Customer/user commits on a certain period -> gets discount based on it - Can be upgraded - Create a new order - We link the new order to the old order and say this one replaces it - If the price of the new order is HIGHER than the OLD order, then we charge the difference until the end of the order period - In the next billing run we set the OLD order to not to bill anymore - And only the NEW order will be billed afterwards - Can be downgraded in the next period (but not for this period) - We create a new order, same as for upgrade - The new order starts directly after the OLD order - As the amount is LOWER than the OLD order, no additional charge is done during this order period - We might need to have an activate datetime - When to implement this - Order periods can be *** Statuses - CREATING/PREPARING - INACTIVE (?) - TO_BILL - NOT_TO_BILL: we use this to accelerate queries to the DB *** Updating status of orders - If has succeeding order and billing date is last month -> set inactive ** Bills - Are always for a month - Can be preliminary *** Which orders to include - Not the cancelled ones / not active ones ** Flows / Approach *** Finding all orders for a bill - Get all orders, state != NOT_TO_BILL; for each order do: - is it a one time order? - has it a bill assigned? - yes: set to NOT_TO_BILL - no: - get_or_create_bill_for_this_month - assign bill to this order - set to NOT_TO_BILL - is it a recurring order? - if it has a REPLACING order: - - First of month - Last of month *** Handling replacement of orders - The OLD order will appear in the month that it was cancelled on the bill - The OLD order needs to be set to NOT_TO_BILL after it was billed the last time - The NEW order will be added pro rata if the amount is higher in the same month - The NEW order will be used next month **** Disabling the old order - On billing run - If order.replacement_order (naming!) is set - if the order.replacement_order starts during THIS_MONTH - add order to bill - if NOT: - the order was already replaced in a previous billing period - set the order to NOT_TO_BILL **** Billing the new order - If order.previous_order *** Handling multiple times a recurring order - For each recurring order check the order.period - Find out when it was billed last - lookup latest bill - Calculate how many times it has been used until 2359, last day of month - For preliminary bill: until datetime.now() - Call the bill_end_datetime - Getting duration: bill_end_datetime - order.last_billed - Amount in seconds; duration_in_seconds - Divide duration_in_seconds by order.period; amount_used: - If >= 1: add amount_used * order.recurring_amount to bill