erDiagram
ALLOCATION_LINE_ITEM {
int id
int line_item_id
string line_item_field "[base_amount, discount_amount, tax_amount]"
int amount "A positive or negative value"
int unallocated_amount "initialized as `amount`"
int allocated_amount "initialized as 0"
}
LINE_ITEM {
int id
string added_or_removed
int base_amount
int discount_amount
int tax_amount
}
LINE_ITEM ||--|{ ALLOCATION_LINE_ITEM : "becomes exactly three of"
PAYMENT_ALLOCATION_ATTRS {
ref allocation_line_item
float percentage_of_total
float unrounded_allocation_amount
int rounded_allocation_amount
float dropped_allocation_amount
}
TODO: Object with the tmp
values that contains a reference to the allocation_line_item
flowchart TD
li[line_item] --> aor{{line_item.added_or_removed}}
aor --Added--> lifa{{line_item_field}}
aor --Removed--> lifr{{line_item_field}}
lifa --Base Amount-->
ab[value * 1]
lifa --Discount Amount--> ad[value * -1]
lifa --Tax Amount--> at[value * 1]
lifr --Base Amount--> rb[value * -1]
lifr --Discount Amount--> rd[value * 1]
lifr --Tax Amount--> rt[value * -1]
- Each line item becomes exactly three allocation line items (base, discount, and tax).
- The amount and unallocated amount are
line_item.value
times the calculated sign.
E --> F[]
F --> G[]
G --> H[]
flowchart TD
ps[Payments] --each--> p[Payment]
p --> A[[map: allocation_line_item]]
A --> B
subgraph Calculate Percentage of Total
B{{payment.positive_or_negative?}} --positive --> C[line_item.unallocated_amount /<br/>sum of line_item.unallocated_amounts]
B --negative--> D[line_item.allocated_amount /<br/>sum of line_item.allocated_amounts]
D --> E[percentage_of_total]
C --> E
end
E --> F[PAYMENT_ALLOCATION_ATTRS.new:<br/><b>allocation_line_item:</b><br/>allocation_line_item<br/><b>unrounded_allocation_amount:</b><br/>payment.amount * percentage_of_total<br/><b>rounded_allocation_amount:</b><br/>Math.floor of unrounded_allocation_amount<br/><b>dropped_allocation_amount:</b><br/>unrounded_allocation_amount - rounded_allocation_amount]
F --> G[[map: output array of payment_allocation_attrs]]
G --> H[sum_rounded: sum of rounded_allocation_amounts]
H --> I[rounded_remainder: payment.amount - sum_rounded]
I --rounded_remainder == 0--> J[[map over: array_of_payment_allocation_attrs]]
I --rounded_remainder != 0--> K[[map over: array_of_payment_allocation_attrs]]
J <--> L[final_allocation: rounded_allocation_amount]
K --> M[sort DESC by dropped_allocation_amount]
M --> N[for rounded_remainder]
N --> O[ranking bit]
TODO: elaborate on sort details from excel spreadsheet - sort by TRUNC_AMOUNT desc, LINE_ITEM_ID asc, LINE_ITEM_FIELD asc - that gives us the rankings for allocation
TODO: accumulate cents to allocate