ساخت اپلیکیشن مدیریت موجودی انبار با PHP و MySQL — از صفر تا صد
بسیاری از شرکتها برای مدیریت موثر موجودی انبار خود به یک نرمافزار پیچیده سازمانی نیاز ندارند. در این راهنما شیوه توسعه یک اپلیکیشن مدیریت موجودی انبار (به صورت سفارشی شده) شرح داده شده است، تا بتوان این موجودی و دادههای مرتبط به آن را دقیقتر دنبال و مدیریت کرد و بر همین مبنا تصمیمهای هوشمندانهتری گرفت.
الزامات سیستم
سیستم موجودی انبار ما نیازمند phpGrid و phpChart با لایسنس استاندارد تجاری است. ما در واقع به برخی ویژگیهای پیشرفته هر دو کامپوننت نیاز داریم.
- +PHP 5.6 (البته PHP 7.x اکنون قویاً توصیه میشود)
- MySQL / MariaDB
- (phpGrid Lite (subgrid یا phpGrid Enterprise با امکانات (Master detail ،Grouping)
- phpChart (برای گزارشها)
سیستم مدیریت موجودی انبار چیست؟
یک سیستم مدیریت موجودی انبار چند کامپوننت خیلی مهم دارد. این سیستم در هسته مرکزی خود باید امکان کنترل موجودی داشته باشد که با ردگیری دو کارکرد اصلی یک انبار کالا یعنی دریافت (ورودی) و ارسال (خروجی) کار میکند. فعالیتهای دیگر مانند جابجایی یا تغییر مکان موجودی نیز ممکن است رخ دهند. مواد خام کاهش مییابند و محصولات نهایی افزایش پیدا میکنند.
- ورود محمولهها
- خروج سفارشها
- موجودی
- تأمینکنندگان
- اسکنر بارکد
طراحی پایگاه داده سیستم مدیریت موجودی انبار
به طور معمول یک سیستم مدیریت موجودی، چهار جزء اساسی به صورت محصولات، خریدها، سفارشها و تأمینکنندگان دارد. هر عنصر باید بر اساس مکان خود، SKU و کمّیت ردگیری شود. موجودی فعلی یا محصولات موجود با ردگیری تحویل ورودیها و سفارشهای خروجی صورت میپذیرد. هشدارهای سفارشی میتوانند طوری تنظیم شوند که وقتی سطوح موجود به کمتر از مقادیر کمینه تعریف شده سفارشی رسیدند، فعال شوند.
راهاندازی پایگاه داده مدیریت موجودی
اسکریپت SQL به نام InventoryManager.sql را از این ریپازیتوری گیتهاب این راهنما (+) دانلود کنید و سپس اسکریپت را با استفاده از یک ابزار MySQL مانند MySQL Workbench اجرا کنید. بدین ترتیب پایگاه داده جدیدی به نام InventoryManager و همچنین جداول مورد نیاز این راهنما ایجاد خواهند شد.
راهاندازی phpGrid
ما از یک کامپوننت datagrid که به وسیله phpGrid ارائه شده برای مدیریت همه عملیات CRUD داخلی پایگاه داده استفاده میکنیم. منظور از عملیات CRUD چهار عملیات ایجاد، خواندن، بهروزرسانی و حذف (create ،read ،update و delete) است.
مطمئن شوید که پیش از ادامه یک کپی از phpGrid (+) را دانلود کردهاید.
برای نصب phpGrid مراحل زیر را طی کنید:
- فایل دانلود phpGrid را از حالت فشرده خارج کنید.
- phpGrid را به پوشه phpGrid خود کپی کنید.
- فرایند نصب را با پیکربندی فایل conf.php به پایان ببرید.
پیش از آغاز کدنویسی باید اطلاعات زیر را در فایل پیکربندی conf.php قرار دهیم.
1define('PHPGRID_DB_HOSTNAME', 'localhost'); // host name
2define('PHPGRID_DB_USERNAME', 'root'); // database user name
3define('PHPGRID_DB_PASSWORD', ''); // database password
4define('PHPGRID_DB_NAME', 'InventoryManager'); // our donation manager database name
5define('PHPGRID_DB_TYPE', 'mysql'); // database type
6define('PHPGRID_DB_CHARSET','utf8'); // always 'utf8' in MySQL
ایجاد رابط کاربری (UI)
سیستم مدیریت موجودی انبار ما شامل چهار صفحه است:
- موجودی فعلی
- خریدهای ورودی
- سفارشهای خروجی
- گزارشها
منوها
فایل include برای منو در پوشه inc به نام menu.php ذخیره شده است. کد منو نیز سرراست است. به منظور ایجاد تمرکز بیشتر وارد جزییات زیاد نمیشویم. شما میتوانید به کد درون پوشه inc نگاه کنید. همچنین یک آیتم منوی به نام Reports اضافه کردهایم.
صفحات
ما در این راهنما از یک قالب صفحه عمومی استفاده میکنیم.
موجودی فعلی
ما کار خود را با کدنویسی صفحه موجودی فعلی آغاز میکنیم. خریدهای ورودی موجب افزایش موجودی انبار میشوند، در حالی که سفارشها موجودی را کاهش میدهند. از چشمانداز کلی-جزئی (Master-Detail)، صفحه موجودی فعلی نه دارای 1 بلکه دارای 2 datagrid است، یعنی یکی Purchases (خریدهای ورودی) و دیگری Orders (سفارشیهای خروجی) را شامل میشود.
بنابراین صفحه موجودی فعلی از یک شبکه کلی (موجودی فعلی در انبار) و دو شبکه جزئی تفصیلی (خریدهای ورودی و سفارشیهای خروجی) تشکیل یافته است. ما میتوانیم روابط را با استفاده از یک phpGrid اصلی و چند datagrid جزئی نمایش دهیم.
phpGrid Lite در برابر نسخههای Professional و Enterprise
ویژگیهای مستر/دیتیل و گروهبندی نیازمند نسخههای phpGrid Professional یا Enterprise هستند. اگر از نسخه phpGrid Lite استفاده میکنید همچنان میتوانید از subgrid به جای ویژگی Master Detail استفاده کنید؛ اما البته سادهتر است. استفاده از نسخههای حرفهای یا سازمانی قویاً توصیه میشود. برای قالببندی اعداد صحیح نیز میتوانید از تابع ()set_col_format به صورت زیر استفاده کنید:
1$dgProd = new C_DataGrid('SELECT * FROM products', 'id', 'products');
2$dgProd->set_col_hidden('id', false);
3$dgProd->enable_autowidth(true)->set_dimension('auto', '200px')->set_pagesize(100);
4
5$dgProd->set_col_title('ProductName', 'Name');
6$dgProd->set_col_title('PartNumber', 'Part Number');
7$dgProd->set_col_title('ProductLabel', 'Label');
8$dgProd->set_col_title('StartingInventory', 'Starting Inventory');
9$dgProd->set_col_title('InventoryReceived', 'Inventory Received');
10$dgProd->set_col_title('InventoryShipped', 'Inventory Shipped');
11$dgProd->set_col_title('InventoryOnHand', 'Inventory On Hand');
12$dgProd->set_col_title('MinimumRequired', 'Minimum Required');
13
14$dgProd->set_col_format('StartingInventory', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
15$dgProd->set_col_format('InventoryReceived', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
16$dgProd->set_col_format('InventoryShipped', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
17$dgProd->set_col_format('InventoryOnHand', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
18$dgProd->set_col_format('MinimumRequired', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
19$dgProd->enable_edit('FORM');
این کد به datagrid موجودی فعلی مربوط است. فرایند کار تاکنون به صورت زیر بوده است:
اکنون تغییرات معدودی اعمال میکنیم تا datagrid به نام Product را بهبود ببخشیم.
قبل از هر چیز مقداری قالببندی شرطی اضافه میکنیم. هر زمان که InventoryOnHand برابر با صفر یا مقدار منفی تنظیم شود، با استفاده از رنگ پسزمینه متفاوت نمایش پیدا میکند. ما از تابع ()set_conditional_format به این منظور استفاده میکنیم.
1$dgProd->set_conditional_format(
2 'InventoryOnHand', 'CELL',
3 array("condition"=>"lt",
4 "value"=>"1",
5 "css"=> array("color"=>"red","background-color"=>"#DCDCDC")));
کد فوق یک شرط نمایش اضافه میکند که هر زمان فیلد InventoryOnHand مقداری کمتر (lt) از یک داشته باشد، رنگ متن به قرمز (red) تغییر مییابد و رنگ پسزمینه نیز خاکستری تیره (DCDCDC#) میشود.
در ادامه زمانی که InventoryOnHand کمتر از مقدار نمایش یافته در MinimumRequired باشد، میخواهیم هشداری به کاربر نمایش داده شود که رنگ پسزمینه آن چیزی مانند طلایی باشد. برای مقایسه مقادیر بین دو فیلد باید به جاوا اسکریپت سوئیچ کنیم، زیرا ()set_conditional_format تنها روی یک تابع کار میکند.
در کد زیر از یک حلقه for برای تکرار روی همه ردیفها در datagrid به نام Products استفاده شده است. این حلقه به مقایسه inventoryOnHand با theminimumRequired میپردازد و زمانی که شرط برقرار باشد، از تابع setCall برای تغییر رنگ پسزمینه استفاده میکند.
1$onGridLoadComplete = <<<ONGRIDLOADCOMPLETE
2function(status, rowid)
3{
4 var ids = jQuery("#products").jqGrid('getDataIDs');
5 for (var i = 0; i < ids.length; i++)
6 {
7 var rowId = ids[i];
8 var rowData = jQuery('#products').jqGrid ('getRowData', rowId);
9
10 var inventoryOnHand = $("#products").jqGrid("getCell", rowId, "InventoryOnHand");
11 var minimumRequired = $("#products").jqGrid("getCell", rowId, "MinimumRequired");
12
13 // compare two dates and set custom display in another field "status"
14 console.log(inventoryOnHand + " | " + minimumRequired);
15 if(parseInt(inventoryOnHand) < parseInt(minimumRequired)){
16
17 $("#products").jqGrid("setCell", rowId, "PartNumber", '', {'background-color':'gold'});
18
19 }
20 }
21
22}
23ONGRIDLOADCOMPLETE;
24$dgProd->add_event("jqGridLoadComplete", $onGridLoadComplete);
سپس در همان صفحه، باید خریدهای ورودی (Incoming) و سفارشیهای خروجی (Outgoing) را برای یک محصول خاص ببینیم.
Grid تفصیلی خریدها (ورودی)
1// Purchases detail grid
2$dgPur = new C_DataGrid('SELECT id, PurchaseDate, ProductId, NumberReceived, SupplierId FROM purchases', 'id', 'purchases');
3$dgPur->set_col_hidden('id', false)->set_caption('Incoming Purchases');
4$dgPur->set_col_edittype('ProductId', 'select', "select id, ProductLabel from products");
5$dgPur->set_col_edittype('SupplierId', 'select', "select id, supplier from suppliers");
6$dgPur->set_dimension('800px');