1. Introduction
GR8 CRM is a set of Grails Web Application Framework plugins that makes it easy to develop web applications with CRM functionality.
You can find more information about GR8 CRM on the main documentation site http://gr8crm.github.io.
1.1. Customer Relationship Management
Customer relationship management (CRM) is a system for managing a company’s interactions with current and future customers. It involves using technology to organize, automate and synchronize sales, marketing, customer service, and technical support. Wikipedia
The GR8 CRM "Ecosystem" currently contains over 40 Grails plugins. For a complete list of plugins see http://gr8crm.github.io.
Each GR8 CRM plugin defines a Bounded Context that focus on one specific domain, for example contact, project or document.
2. Product Management Plugin
This plugin provide storage and services for managing products in GR8 CRM applications. A product is an item that you sell or have in your inventory. A product have properties like identification number, name, description and product group. The following features are supported by the crm-product plugin.
-
Multiple prices, specified by price lists
-
Staggered prices
-
Product compositions (includes, replaces, equivalent, etc.)
-
Attachments (images, brochures) if combined with the crm-content plugin
-
Reference to product suppliers if combined with the crm-contact plugin
Note that this plugin does not contain any user interface components. This plugin contains domain classes and services only. The plugin crm-product-ui provides a Twitter Bootstrap based user interface for managing products and price lists. crm-product-ui depends on crm-product so you only need to include crm-product-ui in your BuildConfig.groovy if you want end-user product management features.
3. Domain Model
3.1. CrmProduct
Property | Type | Description |
---|---|---|
number |
String |
Product ID / Item Number |
displayNumber |
String |
Secondary Item Number |
name |
String |
Product name |
displayName |
String |
Secondary product name, typically displayed in web shop or catalogues |
description |
String |
A longer description of the product (max 2000 characters) |
suppliersNumber |
String |
The supplier’s item number |
supplierId |
Long |
Supplier identity (primary key), if supplier exists as a CrmContact |
supplierName |
String |
Name of the product’s supplier |
group |
CrmProductGroup |
Product group |
barcode |
String |
The product’s bar code |
customsCode |
String |
The product’s customs code |
weight |
Double |
The product’s weight |
enabled |
boolean |
Flag that tells if the product is enabled/active or disabled |
4. CrmProductService
Like most other GR8 CRM plugins this plugin have a main service with methods for creating, searching and updating products.
4.1. Create a product group
CrmProductGroup createProductGroup(Map params, boolean save = false)
A product belongs to a product group. Product groups can be created with createProductGroup().
4.2. Create a price list
CrmPriceList createPriceList(Map params, boolean save = false)
A product can have multiple prices. Each product price references a price list. A price list can be created with a call to createPriceList().
4.3. Create a new product
CrmProduct createProduct(Map params, boolean save = false)
To create a product you call the createProduct method with a map of property values.
def hardware = crmProductService.createProductGroup(name: "Hardware", true)
def std = crmProductService.createPriceList(param: 'standard', name: 'Standard price list', true)
def product = crmProductService.createProduct(number: "USB18", name: "USB Cable 1.8 meter", group: hardware, true)
product.addToPrices(priceList: std, unit: 'pcs', outPrice: 6.99, vat: 0.20)
println "The price for $product is €${product.price} excl. VAT"
4.4. Search for products
As usual in GR8 CRM plugins the main service has a list() method that performs a query.
The list() method is @Selectable which means you can use the selection plugin to query for products. |
def list(Map query, Map params)
To search for products you initialize the query map with query values. With the params map you can specify things like sort order and pagination. The following query keys can be used in the query map.
Key | Description | Type |
---|---|---|
number |
Product number |
String (wildcard supported) |
name |
Product name |
String (wildcard supported) |
group |
Product group |
String (wildcard supported) |
supplier |
Name of supplier |
String (wildcard supported) |
suppliersNumber |
Supplier’s item number |
String (wildcard supported) |
barcode |
Bar code |
String (wildcard supported) |
customsCode |
Customs code |
String (wildcard supported) |
weight |
Weight |
Double |
price |
Product price |
Double |
enabled |
Enabled/disabled |
boolean |
The following example will find all enabled products in the hardware product group that has usb in the product name. As you can see you can combine several query values when you search for domain instances.
def result = crmProductService.list([group: 'hardware', name: '*usb*', enabled: true], [:])
println "Found ${result.size()} USB products"
4.5. Product price
Double getPrice(String productNumber, Integer amount = null, Object priceList = null, String unit = null)
Because a product can have many prices depending on different price lists or how many items you want to buy, retrieving the product price can be complicated. However there is a price property on CrmProduct that makes it easier. The price property returns the first available price on the product instance. This works well if you only have one price per product. If you have multiple prices per product you can use CrmProduct#getPrice(...) with optional parameters or use CrmProductService#getPrice(...).
CrmProductService#getPrice() parameters
-
productNumber Product number to get price for
-
amount Amount to base price on
-
priceList CrmPriceList instance or CrmPriceList.param string
-
unit unit to get price for
def pc = crmProductService.createProductGroup(name: "PC", true)
def priceList = crmProductService.createPriceList(param: "b2b", name: "Small Businesses", true)
def p = crmProductService.createProduct(number: "dellxps15", name: "Dell XPS 15\"", group: pc)
p.addToPrices(priceList: priceList, unit: 'pcs', fromAmount: 1, inPrice: 0, outPrice: 1299.99, vat: 0.20)
p.addToPrices(priceList: priceList, unit: 'pcs', fromAmount: 10, inPrice: 0, outPrice: 1199.99, vat: 0.20)
p.addToPrices(priceList: priceList, unit: 'pcs', fromAmount: 100, inPrice: 0, outPrice: 999.99, vat: 0.20)
p.save(flush: true)
assert crmProductService.getPrice("dellxps15") == 1299.99
assert crmProductService.getPrice("dellxps15", 1) == 1299.99
assert crmProductService.getPrice("dellxps15", 5) == 1299.99
assert crmProductService.getPrice("dellxps15", 15) == 1199.99
assert crmProductService.getPrice("dellxps15", 50) == 1199.99
assert crmProductService.getPrice("dellxps15", 150) == 999.99
4.6. Delete a product
String deleteProduct(CrmProduct crmProduct)
A product can be deleted with a call to deleteProduct. If the operation succeeds the name of the deleted product will be returned. Otherwise an exception will be thrown.
Before the product is deleted the crmProduct.delete event will be sent and after the deletion crmProduct.deleted will be sent.
5. Changes
- 2.4.1
-
Plugin upgraded to Grails 2.4.5
- 2.4.0
-
First version to support Grails 2.4.x
- 2.0.1
-
Fixed cascading problem when deleting a product with relations
- 2.0.0
-
First public release
6. License
This plugin is licensed with Apache License version 2.0
7. Source Code
The source code for this plugin is available at https://github.com/goeh/grails-crm-product
8. Contributing
Please report issues or suggestions.
Want to improve the plugin: Fork the repository and send a pull request.