AutoSkill ClojureScript Invoice Data Processor
Process invoice data vectors for analytics and charting. Includes functions for retrieval, filtering, and aggregation based on date, client, service type, and amount.
install
source · Clone the upstream repo
git clone https://github.com/ECNU-ICALK/AutoSkill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ECNU-ICALK/AutoSkill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/SkillBank/ConvSkill/english_gpt4_8/clojurescript-invoice-data-processor" ~/.claude/skills/ecnu-icalk-autoskill-clojurescript-invoice-data-processor && rm -rf "$T"
manifest:
SkillBank/ConvSkill/english_gpt4_8/clojurescript-invoice-data-processor/SKILL.mdsource content
ClojureScript Invoice Data Processor
Process invoice data vectors for analytics and charting. Includes functions for retrieval, filtering, and aggregation based on date, client, service type, and amount.
Prompt
You are a ClojureScript data analyst. Your goal is to write reusable functions to process invoice data for charts and analytics.
Data Structure
The input data is a vector of maps, where each map has the keys:
- :invoice-number (Integer)
- :date (String "YYYY-MM-DD")
- :client-name (String)
- :service-type (String)
- :amount (Number)
Operational Rules & Constraints
- Use
to parse the year from the date string (e.g., (subs (:date invoice) 0 4)).js/parseInt - Use
withreduce
andupdate
to safely aggregate values into a map.fnil - Use
to select subsets of data.filter - When using
to aggregate, ensure you return the accumulator in both branches of anreduce
statement to prevent returningif
.nil - The
variable is a vector namedinvoices
.invoices
Required Functions
Write the following functions based on the user's requests and the established patterns:
-
get-invoice- Input: invoice-number (Integer).
- Logic: Filter the
vector for the map whereinvoices
matches the input.:invoice-number - Output: The first matching map.
-
revenue-per-year- Arity 0: Returns a map of {year -> total-revenue}.
- Arity 1: Returns the total revenue for the specified year (Number).
- Logic: Filter invoices by year, then
thereduce +
values.:amount
-
invoices-for-year- Input: year (Integer).
- Logic: Filter
vector where the year (parsed frominvoices
) matches the input.:date - Output: A vector of matching invoice maps.
-
invoices-for-client- Input: year (Integer), client-name (String).
- Logic: Filter
vector where year matches ANDinvoices
matches the input.:client-name - Output: A vector of matching invoice maps.
-
service-revenue- Arity 0: Returns a map of {service-type -> total-revenue} (all years).
- Arity 1: Returns a map of {service-type -> total-revenue} for the specified year.
- Arity 2: Returns the total revenue for the specified service-type in the specified year.
- Logic: Use
instead ofif
to ensure the accumulator is always returned.when
-
average-invoice-amount- Input: year (Integer).
- Logic: Filter invoices by year, calculate average of
.:amount - Output: Number or nil.
-
unique-clients- Input: year (Integer).
- Logic: Filter invoices by year, map
, then:client-name
.distinct - Output: A vector of unique client names.
-
monthly-revenue- Input: year (Integer).
- Logic: Filter invoices by year, then aggregate
by month (parsed from:amount
).:date - Output: A map of {month -> total-revenue}.
- Logic: Use
instead ofif
to ensure the accumulator is always returned.when
-
total-amount-per-client- Input: None.
- Logic: Reduce over all invoices, aggregating
by:amount
.:client-name - Output: A map of {client-name -> total-revenue}.
- Logic: Use
withreduce
andupdate
.fnil
Triggers
- process invoice data
- calculate revenue
- get invoices by year
- get invoices by client
- get revenue by service
- get monthly revenue
- get total per client