Process invoice data vectors for analytics and charting. Includes functions for retrieval, filtering, and aggregation based on date, client, service type, and amount.
Scanned 5/30/2026
Install via CLI
openskills install gabrielmoreira/agent-skills-mirror---
id: "d95c8066-e2e9-4bff-be24-23a89669b280"
name: "ClojureScript Invoice Data Processor"
description: "Process invoice data vectors for analytics and charting. Includes functions for retrieval, filtering, and aggregation based on date, client, service type, and amount."
version: "0.1.0"
tags:
- "clojurescript"
- "data-processing"
- "invoices"
- "analytics"
- "aggregation"
- "filtering"
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"
---
# 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 `js/parseInt` to parse the year from the date string (e.g., (subs (:date invoice) 0 4)).
- Use `reduce` with `update` and `fnil` to safely aggregate values into a map.
- Use `filter` to select subsets of data.
- When using `reduce` to aggregate, ensure you return the accumulator in both branches of an `if` statement to prevent returning `nil`.
- The `invoices` variable is a vector named `invoices`.
# Required Functions
Write the following functions based on the user's requests and the established patterns:
1. `get-invoice`
- Input: invoice-number (Integer).
- Logic: Filter the `invoices` vector for the map where `:invoice-number` matches the input.
- Output: The first matching map.
2. `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 `reduce +` the `:amount` values.
3. `invoices-for-year`
- Input: year (Integer).
- Logic: Filter `invoices` vector where the year (parsed from `:date`) matches the input.
- Output: A vector of matching invoice maps.
4. `invoices-for-client`
- Input: year (Integer), client-name (String).
- Logic: Filter `invoices` vector where year matches AND `:client-name` matches the input.
- Output: A vector of matching invoice maps.
5. `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 `if` instead of `when` to ensure the accumulator is always returned.
6. `average-invoice-amount`
- Input: year (Integer).
- Logic: Filter invoices by year, calculate average of `:amount`.
- Output: Number or nil.
7. `unique-clients`
- Input: year (Integer).
- Logic: Filter invoices by year, map `:client-name`, then `distinct`.
- Output: A vector of unique client names.
8. `monthly-revenue`
- Input: year (Integer).
- Logic: Filter invoices by year, then aggregate `:amount` by month (parsed from `:date`).
- Output: A map of {month -> total-revenue}.
- Logic: Use `if` instead of `when` to ensure the accumulator is always returned.
9. `total-amount-per-client`
- Input: None.
- Logic: Reduce over all invoices, aggregating `:amount` by `:client-name`.
- Output: A map of {client-name -> total-revenue}.
- Logic: Use `reduce` with `update` and `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
No comments yet. Be the first to comment!