Skip to content

Skvare/com.skvare.inventory

Repository files navigation

com.skvare.inventory

Screenshot

The Inventory System extension manages a mobile hotspot/device lending program built on top of CiviCRM Membership. It tracks physical devices (hotspots, SIMs) from warehouse stock through assignment to a member, shipping (with label purchase/tracking via a companion Shippo integration), warranty replacement, and eventual expiration/return. It also handles membership-linked device eligibility, recurring billing plans, and member-to-member referral codes that extend membership.

The extension is licensed under AGPL-3.0.

Requirements

  • PHP v7.2+
  • CiviCRM 5.51+

Installation (Web UI)

Learn more about installing CiviCRM extensions in the CiviCRM Sysadmin Guide.

Installation (CLI, Zip)

Sysadmins and developers may download the .zip file for this extension and install it with the command-line tool cv.

cd <extension-dir>
cv dl com.skvare.inventory@https://github.com/FIXME/com.skvare.inventory/archive/master.zip

Installation (CLI, Git)

Sysadmins and developers may clone the Git repo for this extension and install it with the command-line tool cv.

git clone https://github.com/FIXME/com.skvare.inventory.git
cv en inventory

Getting Started

After enabling the extension, a new Inventory menu appears in the CiviCRM navigation (visible to users holding the access Inventory permission), with:

  • Dashboard (civicrm/inventory) — tabs for Devices, Orders, Shipping, and Settings, plus summary stats.
  • Shipping (civicrm/inventory/shipments) — shipment batches, label printing, tracking.
  • Inventory Settings (civicrm/inventory/setting, admin only) — stock reorder lead time and related configuration.

It also adds a devices/orders tab to contact records, and extra fields (renewal allowed, shippable countries, fair value, category) plus a Product ↔ Membership mapping screen on Membership Type admin pages, since devices are tied to membership types.

Key concepts:

  • Product — a general device model/catalog entry (e.g. a specific hotspot model), with pricing, stock thresholds, and warehouse location.
  • Device (product variant) — one specific physical unit (identified by MEID/IMEI) assigned to a member; this is what gets created/assigned/suspended/terminated/replaced day to day.

Three scheduled jobs run automatically once installed: an hourly job that recalculates reorder points and flags low/out-of-stock products, a daily job that expires devices past their end date and flags "problem" devices, and an hourly job that cancels stale unpaid orders and sends shipping/tracking notification emails.

Access is gated by a set of custom permissions (access Inventory, administer Inventory, access shipment, access My Contact Product / access All Contact Product, and create/edit/access/delete permissions per entity — see CRM/Inventory/Permission.php), so what a given user sees in the Inventory menu depends on their role.

Database Schema & Entity Relationships

The extension defines 19 custom tables (all prefixed civicrm_inventory_) and extends 2 core CiviCRM tables. Grouped by area:

Catalog & stock

Table Purpose Relates to
civicrm_inventory_category Product category, hierarchical (e.g. Mobile, Hotspot, Donation, T-Shirt) parent_id → self
civicrm_inventory_product A device model in the catalog — pricing, stock thresholds, reorder point, warehouse/shelf location product_category_id → Category; warehouse_id → Warehouse
civicrm_inventory_product_meta (Not in Use) Free-form key/value metadata attached to a product product_id → Product
civicrm_inventory_product_variant One physical device unit (MEID/IMEI), its lifecycle status, and who it's assigned to product_id → Product; contact_id → Contact; membership_id → Membership; sales_id → Sales; replaced_product_id → self (previous unit, if replaced)
civicrm_inventory_product_variant_replacement Records a warranty replacement (old unit → new unit) old_product_id/new_product_id → Product Variant; contact_id → Contact
civicrm_inventory_product_changelog Audit trail of device status changes, grouped into batches product_variant_id → Product Variant; batch_id → Batch; contact_id → Contact
civicrm_inventory_batch A named/exportable run of changelog entries created_id → Contact
civicrm_inventory_warehouse Physical warehouse location address_id → Address
civicrm_inventory_warehouse_transfer Stock transfer of a device between warehouses/contacts product_variant_id → Product Variant; from_warehouse_id/to_warehouse_id → Warehouse; from_contact_id/to_contact_id → Contact

Purchasing (Not in Use)

Table Purpose Relates to
civicrm_inventory_supplier Vendor/supplier contact_id → Contact; address_id → Address
civicrm_inventory_purchase_order A purchase order placed with a supplier contact_id → Contact; supplier_id → Supplier
civicrm_inventory_purchase_order_detail Line item of a purchase order order_id → Purchase Order; product_variant_id → Product Variant; supplier_id → Supplier; warehouse_id → Warehouse

Membership linkage

Table Purpose Relates to
civicrm_inventory_product_membership Which product models are available/allowed for which membership type product_id → Product; membership_type_id → Membership Type; contact_id → Contact
civicrm_inventory_billing_plans (Not in Use) Recurring billing plan (amount, frequency, installments) per membership type membership_type_id → Membership Type
civicrm_inventory_referrals Member-to-member referral code that extends membership on redemption creator_id/consumer_id → Membership

Sales & shipping

Table Purpose Relates to
civicrm_inventory_sales A customer order/sale contact_id → Contact; contribution_id → Contribution; product_id → Product; shipment_id → Shipment
civicrm_inventory_sales_detail Line item of a sale sales_id → Sales; product_variant_id → Product Variant; warehouse_id → Warehouse; membership_id → Membership; contribution_id → Contribution
civicrm_inventory_shipment A shipping batch grouping up to 50 sales contact_id/modified_id → Contact
civicrm_inventory_shipment_labels Purchased Shippo shipping label/tracking record for one sale sales_id → Sales; contact_id → Contact

Extended core CiviCRM tables

Table Added columns Purpose
civicrm_membership_type category, may_renew, shippable_to, fair_value Marks which membership types include a device, whether they auto-renew, which countries they can ship to, and the device's fair market value
civicrm_line_item product_id, product_variant_id, sale_id, membership_id, subtitle, type, additional_details Ties a CiviCRM contribution's line item back to the specific device/sale it paid for

How the pieces fit together

Supplier ──> Purchase Order ──> Purchase Order Detail ──> Product Variant (received into) ──> Warehouse
                                                                 │
Category ──> Product <───────────────────────────────────────────┘
   │            │
   │            ├──> Product ↔ Membership Type mapping ──> Membership Type ──> Billing Plan
   │            └──> Product Variant (Device) ──> Contact / Membership
   │                        │
   │                        ├──> Sales / Sales Detail ──> Contribution
   │                        ├──> Product Changelog ──> Batch  (status audit trail)
   │                        ├──> Warehouse Transfer          (moved between warehouses)
   │                        └──> Variant Replacement         (warranty swap: old unit → new unit)
   │
Sales ──> Shipment ──> Shipment Labels  (Shippo rate/label purchase, tracking)

Membership ──> Referral (creator/consumer) ──> extends Membership end date on redemption

In short: a Product (catalog model) is stocked into a Warehouse via a Purchase Order, becomes an individual Product Variant (physical device), gets sold/assigned to a Contact through a Sale tied to a Membership, is grouped into a Shipment for label purchase/tracking, and every status change along the way is recorded in the Changelog/Batch trail. Referrals and Billing Plans sit alongside this to extend membership and drive recurring pricing, independent of any specific device.

Known Issues

This extension is at alpha stage (v1.0) and is under active development:

  • The Dashboard's device-listing tab is explicitly marked "(WIP)" in the UI.
  • The Settings page links to a "Shippo Setting" page for configuring shipping label purchasing/rates; that page is provided by a separate, companion Shippo extension and only resolves where that extension is also installed.
  • International shipping: customs handling is incomplete for some EU countries (CRM/Inventory/BAO/InventoryShipmentLabels.php).
  • Referral codes: there is a known unhandled edge case where a membership could theoretically be extended twice from overlapping referrals (CRM/Inventory/BAO/InventoryReferrals.php).
  • The Order Sweeper scheduled job's legacy "remove expired enrollments" step is currently disabled/no-op, and has no automated test coverage.
  • There is no dedicated reporting module — reporting is done via the SearchKit-based list screens under the Inventory menu rather than CiviCRM's Report module.

About

CiviCRM Product Inventory

Resources

License

Stars

0 stars

Watchers

2 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors