Skip to content

Releases: pabloalvarez99/pharma-server

v0.1.23 — Fase 5-full COMPLETE + post_sale fix

Choose a tag to compare

@pabloalvarez99 pabloalvarez99 released this 18 May 11:17
ab0a85f

Fase 5-full COMPLETE (BACKLOG #8)

Three pooled slices merged on this branch since v0.1.22:

  • PO receipt + WAC (PR #38, slice 2) — POST /api/v1/purchase-orders/{id}/receive atomically increments product.stock, recomputes product.cost_price via weighted-average cost, emits stock_movement(reason='purchase_receipt', ref=<po_id>), flips PO draft → received. Mirrors sales::apply_sale's BEGIN/COMMIT atomicity.
  • Accounts payable (PR #40, slice 3) — purchase_payment ledger (migration 0016). Closes Fase 5-full.
  • Latent bug fix in sales::post_sale (PR #43) — stock pre-check now indexes loaded products by id instead of zipping positionally against IN $ids results. Caused spurious InsufficientStock under load when stocks differed across the cart; no production data was at risk (the atomic tx's product_batch.stock ASSERT >= 0 would have aborted any oversell). Surfaced by the v0.1.22 stock-rotation test on serialized runs.

Additive. No schema breaking changes.

MSI

pharma-server-0.1.23-x86_64.msi — 12,304,384 bytes
sha256: 4a2c61c395d8f848bf3d5e6bda8f12cf2ea0f59f47c9bdf06233c567cc4d4a24

Smoke-verified: MajorUpgrade over v0.1.22, service Running, / {"version":"0.1.23"}, /health/ready 200 db:ok.

🤖 Generated with Claude Code

v0.1.22 — stock-rotation report (Fase 6 reports complete)

Choose a tag to compare

@pabloalvarez99 pabloalvarez99 released this 18 May 01:37
7a03259

stock-rotation report — closes BACKLOG #9

GET /api/v1/reports/stock-rotation?from&to — inventory turnover = qty_sold / current_stock. No historical stock snapshots are kept, so current product.stock is the documented proxy denominator (same honesty stance as items_without_cost). turnover/days_of_inventory are null when current stock ≤ 0 — the product still surfaces with qty_sold so fast-mover stockouts stay visible. days_of_inventory = window_days / turnover, only when both from/to given. Sorted turnover desc (null last). refunded/cancelled excluded, tenant-scoped.

Fase 6 report set is now complete: sales-daily, margins-daily, top-products+ABC, near-expiry, stock-rotation (+ caja/gastos). Additive, no migration.

Note: this 0.1.22 MSI binary carries the report endpoint set through stock-rotation. Local purchase-orders (PR #35, version-less) is merged on the branch and ships in the next MSI.

MSI

pharma-server-0.1.22-x86_64.msi — 12,234,752 bytes
sha256: 36e3b6b00f6fc7a048ea90c93245d8984221bae0e176f5bee6015d2b948bfd4c

Smoke-verified: MajorUpgrade over v0.1.21, service Running, / {"version":"0.1.22"}, /health/ready 200 db:ok.

🤖 Generated with Claude Code

v0.1.21 — top-products + ABC ranking

Choose a tag to compare

@pabloalvarez99 pabloalvarez99 released this 18 May 01:06
619ca3b

top-products report (ABC / Pareto)

GET /api/v1/reports/top-products?from&to&limit — product sales ranking. qty_sold = Σ order_item.quantity; revenue = Σ order_item.subtotal; revenue_pct (2dp); abc_class from cumulative revenue of the full ranking (A ≤80%, B ≤95%, C rest); 1-based rank. limit (default 50, 1..=500) truncates output after ABC is computed over the full ranking, so a top-N still reports each product's true ABC class. refunded/cancelled excluded, tenant-scoped.

ABC shows which SKUs move the till — the base for assortment/purchasing calls. Closes BACKLOG #9 nearly (only stock-rotation remains). Additive, no migration.

MSI

pharma-server-0.1.21-x86_64.msi — 12,214,272 bytes
sha256: d1a6f86734f4b15053e55f578c6ae453c84039241e09ab5c12b9625e12e2ba5d

Smoke-verified: MajorUpgrade over v0.1.20, service Running, / {"version":"0.1.21"}, /health/ready 200 db:ok.

🤖 Generated with Claude Code

v0.1.20 — daily gross-margin report

Choose a tag to compare

@pabloalvarez99 pabloalvarez99 released this 17 May 22:29
c4243dd

margins-daily report

GET /api/v1/reports/margins-daily?from&to — daily gross-margin rollup over order/order_item. revenue = Σ order_item.subtotal; cost = Σ quantity × product.cost_price for items with a known cost; plus margin, margin_pct (revenue-relative, 2dp), and an honest items_without_cost count for lines whose product or cost_price is unset. refunded/cancelled excluded, tenant-scoped, UTC-day buckets.

Lets the owner see real margin, not just turnover. Closes BACKLOG #9 partial (rotation/ABC/top-products remain). Additive, no migration.

MSI

pharma-server-0.1.20-x86_64.msi — 12,193,792 bytes
sha256: 1307888d92ca7670fc8e0116754f1409a5765fe8e309b1d915734fb428ca8f5c

Smoke-verified: MajorUpgrade over v0.1.19, service Running, / {"version":"0.1.20"}, /health/ready 200 db:ok.

🤖 Generated with Claude Code

v0.1.19 — near-expiry batch report

Choose a tag to compare

@pabloalvarez99 pabloalvarez99 released this 17 May 22:03
748ea99

near-expiry report

GET /api/v1/reports/near-expiry?days=N (default 30) — per-batch list of stock expiring soon or already expired, sorted by expiry ascending (most urgent first). Tenant-scoped; active batches with stock>0. Each row: product_id, product_name, batch_id, batch_code, expiry_date, stock, days_to_expiry (signed; negative = expired), expired.

Operationally critical for CL pharmacies — expiring stock is money lost. Closes BACKLOG #9 partial (margins/rotation/ABC remain).

Additive, no migration. Reuses the proven sales-daily report pattern.

MSI

pharma-server-0.1.19-x86_64.msi — 12,177,408 bytes
sha256: a00a40c66da826adffa256fc8458f958a0800cb3ba1a48d998a9d709309c7166

Smoke-verified on Windows: MajorUpgrade over v0.1.18, service Running, / reports {"version":"0.1.19"}, /health/ready 200 db:ok.

🤖 Generated with Claude Code

pharma-server v0.1.18

Choose a tag to compare

@pabloalvarez99 pabloalvarez99 released this 17 May 18:36
bd6c679

ERP Rust on-prem para farmacia.

Novedad — Farmacia auto-cuidada

  • Cron horario de purga: la tabla idempotency_key ya no crece monotónicamente. Cada hora el servidor borra automáticamente las claves con TTL vencido (24h post-venta). Sin acción del operador.
  • Scheduler hub unificado: backup nocturno + purga horaria viven en un mismo JobScheduler dentro del proceso. Sin Windows Task Scheduler, sin scripts externos.

Acumulado

  • v0.1.17 scheduler nocturno de backup · v0.1.16 backup on-demand · multi-lot split traceability completo (sales + agent_fulfill).

Instalar

msiexec /i pharma-server-0.1.18-x86_64.msi /qn

Activar backup nocturno

setx PHARMA__BACKUP__SCHEDULE "0 0 3 * * *" /M
setx PHARMA__BACKUP__RETENTION_DAYS "14" /M
Restart-Service PharmaServer

(El cron de purga corre solo, sin config.)

Artefacto

  • pharma-server-0.1.18-x86_64.msi · 12,165,120 bytes
  • sha256 1da935e93b8fed7b289fed117b3174482d9057ce01b291740c953ed11280760d

pharma-server v0.1.17

Choose a tag to compare

@pabloalvarez99 pabloalvarez99 released this 17 May 18:18
e7d6725

ERP Rust on-prem para farmacia.

Novedad — Backup automático nocturno

  • Scheduler nocturno: configurando PHARMA__BACKUP__SCHEDULE (cron UTC, ej 0 0 3 * * *) el servidor genera un .tar.gz automático todas las noches. PHARMA__BACKUP__RETENTION_DAYS purga respaldos viejos (0 = retención infinita, default).
  • El scheduler vive dentro del proceso pharma-service — zero-config, sin Windows Task Scheduler.
  • POST /api/v1/admin/backup (v0.1.16) sigue disponible para respaldos on-demand.

Acumulado

  • v0.1.16 backup on-demand · multi-lot split traceability en POS (BACKLOG #3) · multi-lot FEFO split en agent_fulfill (BACKLOG #2 remainder).

Instalar

msiexec /i pharma-server-0.1.17-x86_64.msi /qn

Activar scheduler (ejemplo, 03:00 UTC, retención 14 días)

setx PHARMA__BACKUP__SCHEDULE "0 0 3 * * *" /M
setx PHARMA__BACKUP__RETENTION_DAYS "14" /M
Restart-Service PharmaServer

Artefacto

  • pharma-server-0.1.17-x86_64.msi · 12,144,640 bytes
  • sha256 cd6daeac9da17e530b3c1f3b8417b37429abcac960bd0d273822db99a0dabbfc

pharma-server v0.1.16

Choose a tag to compare

@pabloalvarez99 pabloalvarez99 released this 17 May 17:46
2aaf60b

ERP Rust on-prem para farmacia.

Novedad — Backup vendible

  • POST /api/v1/admin/backup (role admin/owner): el operador genera un respaldo on-demand del data directory completo + la identidad federada (agent.key) en un único .tar.gz timestamped bajo <data_dir>/backups/. Respuesta incluye path, bytes, sha256, duration_ms. No detiene el servicio (LSM tolera lecturas concurrentes, snapshot crash-recoverable al restaurar). Para un backup totalmente quiesced detener PharmaServer antes.

Acumulado

  • v0.1.15 gastos + reporte ventas/día · v0.1.14 caja apertura/cierre/arqueo · v0.1.13 preview live interacciones · v0.1.12 ruleset Beers + Vademécum.

Instalar

msiexec /i pharma-server-0.1.16-x86_64.msi /qn

Artefacto

  • pharma-server-0.1.16-x86_64.msi · 11,984,896 bytes
  • sha256 2f372d3285c24a7af9598b685167759254e313cb93911a4b35ebcfbc316e3482

pharma-server v0.1.15

Choose a tag to compare

@pabloalvarez99 pabloalvarez99 released this 17 May 04:18
8bbfa15

ERP Rust on-prem para farmacia.

Novedad

  • Gastos: POST/GET /api/v1/expenses — categoría, monto, método de pago (efectivo/banco/tarjeta/transferencia), opcionalmente ligado a un turno de caja o un proveedor.
  • Reporte ventas por día: GET /api/v1/reports/sales-daily[?from&to] — facturación, efectivo, tarjeta y número de órdenes bucketeados por fecha UTC. Excluye órdenes refunded/cancelled.

Acumulado

  • v0.1.14 caja apertura/cierre/arqueo · v0.1.13 preview live interacciones · v0.1.12 ruleset Beers + Vademécum · v0.1.11 receta desde POS · v0.1.10 lazo federado cerrado.

Instalar

msiexec /i pharma-server-0.1.15-x86_64.msi /qn

Artefacto

  • pharma-server-0.1.15-x86_64.msi · 11,984,896 bytes
  • sha256 6055ca2a70da2ec114b6ee18ef18d0ce135c7c9512896f152d4bea813c596daf

pharma-server v0.1.14

Choose a tag to compare

@pabloalvarez99 pabloalvarez99 released this 17 May 03:58
037c63b

ERP Rust on-prem para farmacia.

Novedad — Caja (apertura / cierre / arqueo)

  • POST /api/v1/cash-sessions: el cajero abre la caja con el monto inicial.
  • GET /api/v1/cash-sessions/{id}/arqueo: arqueo en vivo — el sistema calcula el efectivo esperado (opening + ventas en efectivo + ingresos − retiros) sin congelar la sesión.
  • POST /api/v1/cash-sessions/{id}/movements: ingreso (vuelto extra, préstamo) o retiro (depósito caja fuerte) durante el turno.
  • POST /api/v1/cash-sessions/{id}/close: cierre. El cajero ingresa el efectivo contado; el sistema computa discrepancia = counted − expected (negativa = falta, positiva = sobra) y congela el estado.
  • Invariantes: una caja abierta por (tenant, cajero) — segundo open es conflicto; movimiento en caja cerrada rechazado.

Acumulado

  • v0.1.13 preview live interacciones · v0.1.12 ruleset Beers + Vademécum CL · v0.1.11 receta desde POS · v0.1.10 lazo federado cerrado · v0.1.7 devoluciones.

Instalar

msiexec /i pharma-server-0.1.14-x86_64.msi /qn

Verificar: Get-Service PharmaServer Running · curl http://localhost:8080/{"version":"0.1.14"} · /health/ready → 200.

Artefacto

  • pharma-server-0.1.14-x86_64.msi · 11,943,936 bytes
  • sha256 6f75d3cfe87b6bb2e09c9d3c6a960219b9a7ce99755244ab9bddb204107c7fc5