Artigo original: How to Make an Awesome Inventory Management Application in PHP and MySQL
Escrito por: Richard
Você não precisa de software corporativo inchado para rastrear seu estoque com eficiência. Este tutorial ajudará você a desenvolver sua própria aplicação de rastreamento de estoque personalizada para que você possa tomar decisões de inventário inteligentes com base em dados de estoque precisos e oportunos.
Requisitos do sistema
Nosso sistema de estoque requer a licença comercial padrão do phpGrid e do phpChart. Ele precisa de alguns recursos avançados de ambos os componentes.
- PHP 5.6+(PHP 7.x é agora altamente recomendado!)
- MySQL / MariaDB
- phpGrid Lite (subgrid) -ou- phpGrid Enterprise (Master detail, Grouping)
- phpChart (para relatórios)
O que é um sistema de gerenciamento de estoque
Também conhecido como sistema de gerenciamento de inventário, esse sistema tem vários componentes críticos. Em sua essência, o controle de estoque funciona rastreando as duas principais funções de um armazém: recebimento (entrada) e expedição (saída). Outras atividades, como a movimentação ou a realocação de estoque, também ocorrem. As matérias-primas são decrementadas e os produtos acabados são incrementados.
- Remessas recebidas
- Pedidos enviados
- Estoque
- Fornecedores
- Leitor de código de barras (atualização de janeiro de 2019)
Projeto de banco de dados do sistema de estoque
Normalmente, um sistema de estoque tem quatro elementos básicos: produtos, compras, pedidos e fornecedores. Cada elemento deve ser rastreado com base em sua localização, SKU (sigla de Stock Keeping Unit – unidade de manutenção de estoque, em português) e quantidade. O estoque atual (os produtos disponíveis) é atualizado rastreando as remessas recebidas e os pedidos enviados. Os alertas de pedidos podem ser configurados para serem acionados quando os níveis de estoque ficarem abaixo dos níveis mínimos definidos pelo cliente.

Configurando o banco de dados do gerenciador de estoque
Baixe o script de SQL InventoryManager.sql do repositório do GitHub deste tutorial e execute o script usando uma ferramenta de MySQL, como o MySQL Workbench. Isso criará um banco de dados chamado InventoryManager, bem como as tabelas necessárias para este tutorial.
Uma nota sobre o ZenBase
O sistema de gerenciamento de estoque é um dos muitos modelos de aplicações disponíveis no ZenBase (construído sobre o phpGrid) para qualquer pessoa – com ou sem habilidades em programação – usar e personalizar para suas próprias necessidades.Configurar phpGrid
Vamos continuar.
Usaremos um componente de datagrid (em português, grade de dados) do phpGrid para lidar com todas as operações CRUD (Criar, Remover, Atualizar e Excluir) do banco de dados interno.
Não se esqueça de baixar uma cópia do phpGrid antes de continuar.
Para instalar o phpGrid, siga estes passos:
- Descompacte o arquivo de download do phpGrid.
- Carregue a pasta
phpGridpara a pasta do phpGrid. - Conclua a instalação configurando o arquivo
conf.php.
Antes de começarmos, devemos incluir as seguintes informações no arquivo conf.php de configuração do phpGrid.
define('PHPGRID_DB_HOSTNAME', 'localhost'); // nome do host
define('PHPGRID_DB_USERNAME', 'root'); // nome de usuário do banco de dados
define('PHPGRID_DB_PASSWORD', ''); // senha do banco de dados
define('PHPGRID_DB_NAME', 'InventoryManager'); // nome do banco de dados do gerenciador de estoque
define('PHPGRID_DB_TYPE', 'mysql'); // tipo de banco de dados
define('PHPGRID_DB_CHARSET','utf8'); // sempre 'utf8' no MySQLCriando a interface de usuário (UI)
Nosso sistema de inventário é composto por quatro páginas (nomes em inglês, seguidos pela respectiva tradução):
- Current Inventory (Estoque atual)
- Incoming Purchases (Compras recebidas)
- Outgoing Orders (Encomendas a enviar)
- Reports (Relatórios)

Menus
O arquivo de inclusão do menu é armazenado em uma pasta inc com o nome de menu.php. O código para o menu é simples. Por uma questão de foco, não entraremos em grandes detalhes. Sinta-se à vontade para olhar o código dentro da pasta inc.
Também adicionamos um item de menu chamado Reports.

Páginas
Usaremos o mesmo modelo de página que usamos para os tutoriais de CRM e gerenciamento de projetos.
Current Inventory (Estoque atual)

Vamos começar com a página do estoque atual, Current Inventory.
As compras recebidas aumentam o estoque, enquanto os pedidos de saída o diminuem. De uma perspectiva mestre-detalhe, o Current Inventory não tem uma, mas duas grades de dados (datagrids, em inglês) de detalhes – Purchases (compras recebidas) e Orders (pedidos de saída).
Assim, a página Current Inventory é composta por uma grade mestre (o estoque atual) e duas grades de detalhes (Incoming Purchases e Outgoing Orders). Podemos apresentar facilmente esses relacionamentos usando o recurso do phpGrid de uma grade de dados mestre com várias grades de dados de detalhes.
phpGrid Lite Professional e Enterprise
Os recursos de agrupamento e detalhes mestre requerem a versão Professional ou Enterprise do phpGrid. Se você está na versão gratuita Lite, ainda pode usar o subgrid no lugar dos detalhes mestre, apesar de o subgrid ser menos avançado. As versões Professional ou Enterprise são altamente recomendadas.
Se você já leu o tutorial Building a Donation Manager from Scratch (em inglês), não terá problemas em seguir o código abaixo.
Observe o uso da função set_col_format() (em inglês) para formatar os números inteiros.
$dgProd = new C_DataGrid('SELECT * FROM products', 'id', 'products');
$dgProd->set_col_hidden('id', false);
$dgProd->enable_autowidth(true)->set_dimension('auto', '200px')->set_pagesize(100);
$dgProd->set_col_title('ProductName', 'Name');
$dgProd->set_col_title('PartNumber', 'Part Number');
$dgProd->set_col_title('ProductLabel', 'Label');
$dgProd->set_col_title('StartingInventory', 'Starting Inventory');
$dgProd->set_col_title('InventoryReceived', 'Inventory Received');
$dgProd->set_col_title('InventoryShipped', 'Inventory Shipped');
$dgProd->set_col_title('InventoryOnHand', 'Inventory On Hand');
$dgProd->set_col_title('MinimumRequired', 'Minimum Required');
$dgProd->set_col_format('StartingInventory', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('InventoryReceived', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('InventoryShipped', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('InventoryOnHand', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('MinimumRequired', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->enable_edit('FORM');Isso é tudo para a grade de dados de Current Inventory. Aqui está a aparência até agora:

Agora, vamos fazer algumas alterações para melhorar nossa grade de dados de produtos, Products.
Em primeiro lugar, adicionaremos uma formatação condicional: sempre que o estoque disponível, InventoryOnHand, for definido como zero ou um valor negativo, ele será exibido usando uma cor de fundo diferente. Usaremos a função set_conditional_format() para esse propósito.
$dgProd->set_conditional_format(
'InventoryOnHand', 'CELL',
array("condition"=>"lt",
"value"=>"1",
"css"=> array("color"=>"red","background-color"=>"#DCDCDC")));O código acima adiciona uma condição de exibição para que, sempre que o campo InventoryOnHand tiver um valor menor que (lt) um, a cor do texto mude para red e a cor de fundo para cinza escuro (#DCDCDC).
Em segundo lugar, sempre que InventoryOnHand for menor que o valor mostrado em MinimumRequired, gostaríamos de alertar o usuário com uma cor de fundo proeminente, como ouro. Para comparar valores entre dois campos, devemos mudar para Javascript porque a função set_conditional_format() só funciona com um único campo.
O código abaixo usa um laço for para iterar em cada linha na grade de dados Products. Ele compara o inventoryOnHand com o minimumRequired e, quando a condição for atendida, usará a função setCell para alterar a cor do plano de fundo.
$onGridLoadComplete = <<<ONGRIDLOADCOMPLETE
function(status, rowid)
{
var ids = jQuery("#products").jqGrid('getDataIDs');
for (var i = 0; i < ids.length; i++)
{
var rowId = ids[i];
var rowData = jQuery('#products').jqGrid ('getRowData', rowId);
var inventoryOnHand = $("#products").jqGrid("getCell", rowId, "InventoryOnHand");
var minimumRequired = $("#products").jqGrid("getCell", rowId, "MinimumRequired");
// compare two dates and set custom display in another field "status"
console.log(inventoryOnHand + " | " + minimumRequired);
if(parseInt(inventoryOnHand) < parseInt(minimumRequired)){
$("#products").jqGrid("setCell", rowId, "PartNumber", '', {'background-color':'gold'});
}
}
}
ONGRIDLOADCOMPLETE;
$dgProd->add_event("jqGridLoadComplete", $onGridLoadComplete);Você pode aprender mais sobre como comparar vários valores de células no site de suporte do phpGrid (em inglês).
Em seguida, na mesma página, precisamos ver as compras recebidas (Incoming) e os pedidos de saída (Outgoing) para um produto específico.
Grade de detalhes de compras (Incoming)
// Grade de detalhes de compras
$dgPur = new C_DataGrid('SELECT id, PurchaseDate, ProductId, NumberReceived, SupplierId FROM purchases', 'id', 'purchases');
$dgPur->set_col_hidden('id', false)->set_caption('Incoming Purchases');
$dgPur->set_col_edittype('ProductId', 'select', "select id, ProductLabel from products");
$dgPur->set_col_edittype('SupplierId', 'select', "select id, supplier from suppliers");
$dgPur->set_dimension('800px');Grade de detalhes de pedidos (Outgoing)
// Grade de detalhes dos pedidos
$dgOrd = new C_DataGrid('SELECT id, OrderDate, ProductId, NumberShipped, First, Last FROM orders', 'id', 'orders');
$dgOrd->set_sortname('OrderDate', 'DESC')->set_caption('Outgoing Orders');
$dgOrd->set_col_hidden('id', false);
$dgOrd->set_col_edittype('ProductId', 'select', "select id, ProductLabel from products");
$dgOrd->set_dimension('800px');As duas grades de detalhes usam a mesma chave estrangeira ProductId para vincular à grade de dados mestre (Products).
$dgProd->set_masterdetail($dgPur, 'ProductId', 'id');
$dgProd->set_masterdetail($dgOrd, 'ProductId', 'id');Finalmente, nosso código completo para gerenciar a página Current Inventory é:
$dgProd = new C_DataGrid('SELECT * FROM products', 'id', 'products');
$dgProd->set_col_hidden('id', false);
$dgProd->enable_autowidth(true)->set_dimension('auto', '200px')->set_pagesize(100);
$dgProd->set_col_title('ProductName', 'Name');
$dgProd->set_col_title('PartNumber', 'Part Number');
$dgProd->set_col_title('ProductLabel', 'Label');
$dgProd->set_col_title('StartingInventory', 'Starting Inventory');
$dgProd->set_col_title('InventoryReceived', 'Inventory Received');
$dgProd->set_col_title('InventoryShipped', 'Inventory Shipped');
$dgProd->set_col_title('InventoryOnHand', 'Inventory On Hand');
$dgProd->set_col_title('MinimumRequired', 'Minimum Required');
$dgProd->set_col_format('StartingInventory', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('InventoryReceived', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('InventoryShipped', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('InventoryOnHand', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('MinimumRequired', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_conditional_format('InventoryOnHand', 'CELL', array("condition"=>"lt",
"value"=>"1",
"css"=> array("color"=>"red","background-color"=>"#DCDCDC")));
$onGridLoadComplete = <<<ONGRIDLOADCOMPLETE
function(status, rowid)
{
var ids = jQuery("#products").jqGrid('getDataIDs');
for (var i = 0; i < ids.length; i++)
{
var rowId = ids[i];
var rowData = jQuery('#products').jqGrid ('getRowData', rowId);
var inventoryOnHand = $("#products").jqGrid("getCell", rowId, "InventoryOnHand");
var minimumRequired = $("#products").jqGrid("getCell", rowId, "MinimumRequired");
// compare two dates and set custom display in another field "status"
console.log(inventoryOnHand + " | " + minimumRequired);
if(parseInt(inventoryOnHand) < parseInt(minimumRequired)){
$("#products").jqGrid("setCell", rowId, "PartNumber", '', {'background-color':'gold'});
}
}
}
ONGRIDLOADCOMPLETE;
$dgProd->add_event("jqGridLoadComplete", $onGridLoadComplete);
$dgProd->enable_edit('FORM');
// Purchases detail grid
$dgPur = new C_DataGrid('SELECT id, PurchaseDate, ProductId, NumberReceived, SupplierId FROM purchases', 'id', 'purchases');
$dgPur->set_col_hidden('id', false)->set_caption('Incoming Purchases');
$dgPur->set_col_edittype('ProductId', 'select', "select id, ProductLabel from products");
$dgPur->set_col_edittype('SupplierId', 'select', "select id, supplier from suppliers");
$dgPur->set_dimension('800px');
// Orders detail grid
$dgOrd = new C_DataGrid('SELECT id, OrderDate, ProductId, NumberShipped, First, Last FROM orders', 'id', 'orders');
$dgOrd->set_sortname('OrderDate', 'DESC')->set_caption('Outgoing Orders');
$dgOrd->set_col_hidden('id', false);
$dgOrd->set_col_edittype('ProductId', 'select', "select id, ProductLabel from products");
$dgOrd->set_dimension('800px');
$dgProd->set_masterdetail($dgPur, 'ProductId', 'id');
$dgProd->set_masterdetail($dgOrd, 'ProductId', 'id');
$dgProd->display();Aqui, vemos uma captura de tela da página de estoque:

Compras recebidas (Incoming Purchases)

A próxima página é a de compras recebidas, ou Incoming Purchases. É similar à grade de detalhes de compras, Purchase Detail Grid, que nós vimos ao configurar a página de estoque atual, Current Inventory. Agrupamos as compras por ProductId e exibimos a soma em NumberReceived. Quaisquer compras recebidas vão aumentar o estoque.
$dgPur -> set_group_properties('ProductId', false, true, true, false);
$dgPur -> set_group_summary('NumberReceived','sum');Observação: o recurso de agrupamento está disponível apenas no phpGrid em suas versões Professional e Enterprise. Para filtrar sem o agrupamento, use a pesquisa por integração.
O código completo:
$dgPur = new C_DataGrid('SELECT id, PurchaseDate, ProductId, NumberReceived, SupplierId FROM purchases', 'id', 'purchases');
$dgPur->set_col_hidden('id', false);
$dgPur->set_col_title('PurchaseDate', 'Date of Purchase');
$dgPur->set_col_title('ProductId', 'Product');
$dgPur->set_col_title('NumberReceived', 'Number Received');
$dgPur->set_col_title('SupplierId', 'Supplier');
$dgPur->set_col_edittype('ProductId', 'select', "select id, ProductLabel from products");
$dgPur->set_col_edittype('SupplierId', 'select', "select id, supplier from suppliers");
// $dgPur->enable_edit('FORM');
$dgPur->set_pagesize(100);
$dgPur->set_col_width('PurchaseDate', '50px');
$dgPur->set_col_width('NumberReceived', '35px');
$dgPur -> set_group_properties('ProductId', false, true, true, false);
$dgPur -> set_group_summary('NumberReceived','sum');
$dgPur->enable_autowidth(true);
$dgPur->display();Aqui está uma captura de tela de nossa página Incoming Purchases com o agrupamento habilitado:

Pedidos enviados (Outgoing Orders)

A próxima página é a de pedidos enviados, Outgoing Orders. É semelhante à grade de detalhes dos pedidos, Orders Detail Grid, da página do estoque atual, Current Inventory. Aqui, apresentaremos uma função avançada chamada set_grid_method().
$dgOrd = new C_DataGrid('SELECT id, OrderDate, ProductId, NumberShipped, First, Last FROM orders', 'id', 'orders');
$dgOrd->set_sortname('OrderDate', 'DESC');
$dgOrd->set_col_hidden('id', false);
$dgOrd->set_col_title('OrderDate', 'Order Date');
$dgOrd->set_col_title('ProductId', 'Product');
$dgOrd->set_col_title('NumberShipped', 'Number Shipped');
$dgOrd->set_col_edittype('ProductId', 'select', "select id, ProductLabel from products");
// $dgOrd->enable_edit('FORM');
$dgOrd->set_pagesize(100);
$dgOrd->set_col_width('OrderDate', '30px');
$dgOrd->set_col_width('NumberShipped', '35px');
$dgOrd->set_col_width('First', '20px');
$dgOrd->set_col_width('Last', '20px');
$dgOrd->set_grid_method('setGroupHeaders', array(
array('useColSpanStyle'=>true),
'groupHeaders'=>array(
array('startColumnName'=>'First',
'numberOfColumns'=>2,
'titleText'=>'Customer Name') )));
$dgOrd->enable_autowidth(true);
$dgOrd->display();Resumo
Este tutorial cria um sistema de estoque, simples e extensível em pouco menos de 50 linhas de código. O estilo progressivo desses tutoriais também ajuda o leitor a ficar, no fim das contas, mais familiarizado e tranquilo com o phpGrid ao apresentar um número limitado de recursos novos do phpGrid em cada um.
O que vem a seguir
Esse é o final do código necessário para criar as grades de dados necessárias para o tutorial. Porém, ainda não terminamos. Ainda temos mais uma página que precisamos criar — a página dos relatórios, ou Reports. Trataremos dela em instantes.
Qual é a finalidade de um sistema de estoque sem algum tipo de relatório? Nesta seção, você aprenderá a usar o phpChart — que se integra de modo perfeito com o phpGrid — para criar relatórios que sejam visualmente agradáveis e úteis para sua aplicação de gerenciamento de estoque.
Esta será a aparência da página ao concluirmos:

Antes de iniciarmos, precisaremos instalar o phpChart. É recomendado que você obtenha a versão completa do phpChart, pois a versão gratuita (phpChart Lite) dá suporte apenas aos gráficos de linhas.
Configuração do phpChart
É importante que tenhamos o phpGrid e o phpChart em pastas separadas. Abaixo, vemos a hierarquia de pastas recomendada.
www
+-- Donation_Manager
| |-- phpGrid
| | +-- conf.php
| |-- phpChart
| | +-- conf.php
| +-- ...Design do relatório
Colocaremos o gráfico de pizza próximo à grade de resumo do estoque. A grade de dados fornece os dados em série para que o gráfico de pizza seja produzido.

Integração do phpGrid e do phpChart
Primeiro, inclua chamadas aos dois arquivos conf.php no início do código.
require_once("phpGrid/conf.php");
require_once("phpChart/conf.php");Abaixo, vemos o código completo para a criação de nosso gráfico de pizza:
$pc = new C_PhpChartX(array(array(null)), 'PieChart');
$pc->set_title(array('text'=>'Current Inventory Summary'));
$pc->set_series_default(array( 'shadow'=> false,
'renderer'=> 'plugin::PieRenderer',
'rendererOptions'=> array(
'showDataLabels' => true,
'highlightMouseOver' => true,
'startAngle'=> 180,
'sliceMargin'=> 4,
'showDataLabels'=> true )
));
$pc->set_legend(array('show'=>true,'location'=> 'w'));
// remove background
$pc->set_grid(array(
'background'=>'white',
'borderWidth'=>0,
'borderColor'=>'#000000',
'shadow'=>false));
$pc->add_custom_js("
$('#PieChart').bind('jqplotDataHighlight',
function (ev, seriesIndex, pointIndex, data) {
$('#label_info').text(data);
}
);
");
$pc->draw(660,400);Vamos ver o passo a passo do código.
A primeira linha é o construtor. Passamos array(null) como os dados em série, pois não queremos que os dados sejam exibidos no gráfico de pizza inicialmente. Os dados do estoque usados para fazer o gráfico ainda não estão disponíveis quando ele é inicializado pela primeira vez. Os dados serão recebidos da grade de dados mais tarde, em formato JSON.
Damos ao nosso gráfico um nome exclusivo, PieChart.
$pc = new C_PhpChartX(array(array(null)), 'PieChart');Em seguida, damos a ele um título. Nada muito complicado.
$pc->set_title(array('text'=>'Current Inventory Summary'));Ao termos o título, chamamos a função set_series_default para definir o renderer para PieRenderer. Diferente de um gráfico de barras, um gráfico de pizza não tem um eixo Y.
Também podemos definir a propriedade rendererOptions. Não entraremos em detalhes em cada uma das opções aqui, mas você poderá encontrar mais informações sobre elas na documentação on-line.
$pc->set_series_default(array( 'shadow'=> false,
'renderer'=> 'plugin::PieRenderer',
'rendererOptions'=> array(
'highlightMouseOver' => true,
'startAngle'=> 180,
'sliceMargin'=> 4,
'showDataLabels'=> true )
));Também queremos dar uma legenda ao gráfico. O comando set_legend abaixo mostra a legenda a oeste (o que sabemos em função do w) ou à esquerda do gráfico de pizza.
$pc->set_legend(array('show'=>true,'location'=> 'w'));Também removeremos a borda e o segundo plano.
$pc->set_grid(array(
'background'=>'white',
'borderWidth'=>0,
'borderColor'=>'#000000',
'shadow'=>false));Por fim, criaremos nosso gráfico dando a ele uma altura (height) e uma largura (width) em pixels.
$pc->draw(660,400);No entanto, se você executar o código agora, não verá o gráfico, pois os dados usados para rendererizá-lo ainda não estão disponíveis.
Grade de dados do resumo do estoque (Inventory Summary Datagrid)
Aqui, usaremos a mesma grade de dados de estoque que usamos na página Products. Apenas adicionaremos uma questão — um manipulador de eventos.
No phpGrid, podemos adicionar um manipulador de eventos com a função add_event(). add_event() vincula um manipulador de eventos, que é, essencialmente, uma função do JavaScript, a um evento específico do phpGrid. Uma lista de eventos possíveis pode ser encontrada aqui.
Como devemos aguardar até que a grade de dados termine de carregar antes que ela possa enviar os dados para criar o gráfico, usaremos o evento jqGridLoadComplete.
Introdução ao phpGrid — o evento jqGridLoadComplete
O evento jqGridLoadComplete é o último evento que ocorre quando todo o corpo da grade de dados terminou de carregar. Observe que o corpo da grade será recarregado se o usuário alterar a ordem de classificação de uma coluna ou se definir um filtro.
Enviando dados com o Javascript
A seguir vemos o manipulador de eventos em Javascript para jqGridLoadComplete.
<span class="hljs-function">function(status, rowid)
{</span>
var dataX = [];
var dataY = [];
d1 = $('#products').jqGrid('getCol', 'ProductLabel', false);
d2 = $('#products').jqGrid('getCol', 'InventoryReceived', false);
npoints = d1.length;
for(var i=0; i < npoints; i++){
dataX[i] = [i+1, d1[i]];
dataY[i] = [i+1, parseInt(d2[i])];
}
var pieData = [];
for(var j=0; j < dataX.length; j++)
{
pieData.push([dataX[j][1], dataY[j][1]]);
}
console.log(pieData);
_PieChart.series[0].data = pieData;
_PieChart.replot({resetAxes:true});
}O código completo:
$dgProd = new C_DataGrid('SELECT id, ProductLabel, InventoryReceived FROM products', 'id', 'products');
$dgProd->set_col_hidden('id', false);
$dgProd->set_dimension('auto', 'auto')->set_pagesize(100);
$onGridLoadComplete = <<<ONGRIDLOADCOMPLETE
function(status, rowid)
{
var dataX = [];
var dataY = [];
d1 = $('#products').jqGrid('getCol', 'ProductLabel', false);
d2 = $('#products').jqGrid('getCol', 'InventoryReceived', false);
d3 = $('#products').jqGrid('getCol', 'InventoryShipped', false);
d4 = $('#products').jqGrid('getCol', 'InventoryOnHand', false);
npoints = d1.length;
for(var i=0; i < npoints; i++){
dataX[i] = [i+1, d1[i]];
dataY[i] = [i+1, parseInt(d2[i])];
}
var pieData = [];
for(var j=0; j < dataX.length; j++)
{
pieData.push([dataX[j][1], dataY[j][1]]);
}
console.log(pieData);
_PieChart.series[0].data = pieData;
_PieChart.replot({resetAxes:true});
}
ONGRIDLOADCOMPLETE;
$dgProd->add_event("jqGridLoadComplete", $onGridLoadComplete);
$dgProd->display();Aí está. Você acaba de criar seu primeiro sistema de gerenciamento de estoque do zero usando o PHP e o MySQL!
É novo na programação? Sem problemas!
Se você é novo na programação e ainda não se sente confortável com ela, confira o ZenBase, que foi criado sobre o phpGrid. O sistema de gerenciamento de estoque é apenas um dos vários templates de aplicação disponíveis no ZenBase para quem quiser — com ou sem habilidade em programação — para usar e personalizar às suas próprias necessidades.
Demonstração on-line
- Current Inventory
- Incoming Purchases
- Outgoing orders
- Reports (com a grade de dados lado a lado)
A seguir: adicionar um leitor de código de barras
Adicione um leitor de código de barras ao nosso sistema de gerenciamento de estoque (texto em inglês)

Faça o download do código-fonte no GitHub
Problema comum:
Fatal error: Uncaught Error: Class ‘phpGrid\C_DataGrid’ not found
Como resolver:
Se estiver usando a versão Lite gratuita, você pode comentar a primeira linha de código
// use phpGrid\C_DataGrid;— OU —
Adicionar um símbolo de namespace global — backslash/barra invertida (\) única — ANTES do construtor
$dg = new \C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");É possível que você se interesse também pelos tutoriais a seguir (textos em inglês):
- Build a Project Management Application From Scratch
- Build a Simple CRM from Start to Finish
- Building a Donation Manager from Scratch in PHP