-
-
Notifications
You must be signed in to change notification settings - Fork 2
Extension Examples
This document describes a few examples of how Vino can be extended. As you can see, there are numerous ways to implement additional functionality on top of Vino and Vulpea.
To add extra fields to cellar entries, use the vino-entry-create-handle-functions
abnormal hook. For example, you can assign an externalId
like this:
(add-hook 'vino-entry-create-handle-functions #'my-vino-entry-assign-external-id)
(defun my-vino-entry-assign-external-id (note)
"Interactively assign extra meta for wine NOTE."
(let ((external-id (read-string "External ID: ")))
(unless (string-empty-p external-id)
(vulpea-utils-with-note note
(vulpea-buffer-meta-set "externalId" external-id)))))
The definition is straightforward. Just keep in mind that you should not save-buffer
unless necessary. Saving the buffer is not particularly slow, but Vulpea will take some time to sync the database, so be mindful of the performance implications.
To add extra fields to rating entries, use the vino-rating-create-handle-functions
abnormal hook.
For example, you can include the consumed bottle ID when writing a rating. As explained in Creating Extensions, the rating abnormal hook comes with extra-data
, and Inventory populates this argument with the consumed bottle ID.
(add-hook 'vino-rating-create-handle-functions #'my-vino-rating-assign-extra-meta)
(defun my-vino-rating-assign-extra-meta (rating extra-data)
"Assign extra meta for RATING note.
EXTRA-DATA contains bottle-id."
(let* ((wine (vulpea-note-meta-get rating "wine" 'note))
(bottle-id (assoc-default 'bottle-id extra-data))
(bottle (vino-inv-get-bottle bottle-id)))
(vulpea-utils-with-note rating
(vulpea-buffer-meta-set "bottle" bottle-id 'append))))
To record the location where the bottle was consumed and the people with whom it was shared:
(add-hook 'vino-rating-create-handle-functions #'my-vino-rating-assign-extra-meta)
(defun my-vino-rating-assign-extra-meta (rating extra-data)
"Assign extra meta for RATING note.
EXTRA-DATA contains bottle-id."
(let* ((wine (vulpea-note-meta-get rating "wine" 'note))
(location (vulpea-select-from "Location"
(vulpea-db-query-by-tags-some '("places" "people" "event"))
:require-match t)))
(vulpea-utils-with-note rating
(vulpea-buffer-meta-set "location" location 'append)
(vulpea-buffer-meta-set "convive"
(let ((people (vulpea-db-query-by-tags-every '("people"))))
(vulpea-utils-collect-while #'vulpea-select-from nil "Convive" people))
'append))))
To track expenses whenever a bottle is acquired, you can create a custom handler. Here is a rough example (this is similar to what I use in my private configuration):
(add-hook 'vino-inv-acquire-handle-functions #'my-vino-inv-acquire-bottle-handler)
(defun my-vino-inv-acquire-bottle-handler (bottle)
"Handle wine BOTTLE acquire event."
(let* ((wine (vino-inv-bottle-wine bottle))
(price (vino-inv-bottle-price bottle))
;; Ensure the price is in UAH (my preferred currency)
(price (cond
((s-suffix-p brb-currency price) (string-to-number price))
((= 0 (string-to-number price)) 0)
(t (read-number (format "Convert %s to UAH: " price))))))
(unless (= 0 price)
;; Record the spending
(brb-ledger-record-txn
:date (date-to-time (vino-inv-bottle-purchase-date bottle))
:comment (concat "[" (vulpea-note-id wine) "]")
:account-to "spending:wines"
:account-from "personal:account"
:amount price))))
You can mark bottles in vino-inv-ui
using the m
key by default. Here is a dummy implementation of a function that creates a spreadsheet for printing custom labels for each acquired bottle. My printer supports templates with data sourced from .xlsx
files.
(defun my-vino-inv-ui-print-info ()
"Save print info for the marked bottles."
(interactive)
(let (print-list bottle)
(save-excursion
(goto-char (point-min))
(while (not (eobp))
(setq cmd (char-after))
(when (eq cmd ?\*)
;; This is the key PKG-DESC.
(setq bottle (tabulated-list-get-id))
(push bottle print-list))
(forward-line)))
(when (seq-empty-p print-list)
(user-error "There are no marked bottles."))
(let* ((data (->> print-list
(--map
(let ((bottle-id (string-to-number (nth 1 (s-split ":" it)))))
(vino-inv-get-bottle bottle-id)))
(--sort (< (vino-inv-bottle-id it)
(vino-inv-bottle-id other)))
(--map
(list (format "#%s" (vino-inv-bottle-id it))
(vino-inv-bottle-purchase-date it)
(concat "https://barberry.io/wines/" (vulpea-note-id (vino-inv-bottle-wine it)))))))
(file (make-temp-file "vino-inv-" nil ".csv"))
(buffer (find-file-noselect file)))
(with-current-buffer buffer
(delete-region (point-min) (point-max))
(insert (string-join '("bottle" "date" "url") ",") "\n")
(--each data
(insert (string-join it ",") "\n")))
(switch-to-buffer buffer)
(when (y-or-n-p "Convert?")
(save-buffer)
(shell-command-to-string
(format "ssconvert '%s' '%s'"
file
(expand-file-name
"Documents/bottles.xlsx"
path-home-dir)))))))