初始上传
This commit is contained in:
79
addon/stock/config/cashier_auth.php
Executable file
79
addon/stock/config/cashier_auth.php
Executable file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
return [
|
||||
[
|
||||
'name' => 'stock',
|
||||
'title' => '库存',
|
||||
'type' => 'page',
|
||||
'url' => '',
|
||||
'children' => [
|
||||
[
|
||||
'name' => 'stock_wastage',
|
||||
'title' => '出库单',
|
||||
'type' => 'page',
|
||||
'url' => 'pages/stock/wastage',
|
||||
],
|
||||
[
|
||||
'name' => 'stock_storage',
|
||||
'title' => '入库单',
|
||||
'type' => 'page',
|
||||
'url' => 'pages/stock/storage',
|
||||
],
|
||||
[
|
||||
'name' => 'stock_allocate',
|
||||
'title' => '调拨单',
|
||||
'type' => 'page',
|
||||
'url' => 'pages/stock/allocate',
|
||||
],
|
||||
[
|
||||
'name' => 'stock_manage',
|
||||
'title' => '库存管理',
|
||||
'type' => 'page',
|
||||
'url' => 'pages/stock/manage',
|
||||
],
|
||||
[
|
||||
'name' => 'stock_check',
|
||||
'title' => '库存盘点',
|
||||
'type' => 'page',
|
||||
'url' => 'pages/stock/check',
|
||||
],
|
||||
[
|
||||
'name' => 'stock_records',
|
||||
'title' => '库存流水',
|
||||
'type' => 'page',
|
||||
'url' => 'pages/stock/records',
|
||||
],
|
||||
[
|
||||
'name' => 'storage_add',
|
||||
'title' => '创建入库单',
|
||||
'type' => 'api',
|
||||
'url' => 'stock/shopapi/storage/stockin',
|
||||
],
|
||||
[
|
||||
'name' => 'wastage_add',
|
||||
'title' => '创建出库单',
|
||||
'type' => 'api',
|
||||
'url' => 'stock/shopapi/wastage/stockout',
|
||||
],
|
||||
[
|
||||
'name' => 'check_add',
|
||||
'title' => '创建盘点单',
|
||||
'type' => 'api',
|
||||
'url' => 'stock/shopapi/check/add',
|
||||
],
|
||||
[
|
||||
'name' => 'stock_audit',
|
||||
'title' => '单据审核',
|
||||
'type' => 'api',
|
||||
'url' => 'stock/shopapi/manage/audit',
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
38
addon/stock/config/diy_view.php
Executable file
38
addon/stock/config/diy_view.php
Executable file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
return [
|
||||
|
||||
// 自定义模板页面类型,格式:[ 'title' => '页面类型名称', 'name' => '页面标识', 'path' => '页面路径', 'value' => '页面数据,json格式' ]
|
||||
'template' => [],
|
||||
|
||||
// 后台自定义组件——装修
|
||||
'util' => [],
|
||||
|
||||
// 自定义页面路径
|
||||
'link' => [],
|
||||
|
||||
// 自定义图标库
|
||||
'icon_library' => [],
|
||||
|
||||
// uni-app 组件,格式:[ 'name' => '组件名称/文件夹名称', 'path' => '文件路径/目录路径' ],多个逗号隔开,自定义组件名称前缀必须是diy-,也可以引用第三方组件
|
||||
'component' => [],
|
||||
|
||||
// uni-app 页面,多个逗号隔开
|
||||
'pages' => [],
|
||||
|
||||
// 模板信息,格式:'title' => '模板名称', 'name' => '模板标识', 'cover' => '模板封面图', 'preview' => '模板预览图', 'desc' => '模板描述'
|
||||
'info' => [],
|
||||
|
||||
// 主题风格配色,格式可以自由定义扩展,【在uni-app中通过:this.themeStyle... 获取定义的颜色字段,例如:this.themeStyle.main_color】
|
||||
'theme' => [],
|
||||
|
||||
// 自定义页面数据,格式:[ 'title' => '页面名称', 'name' => "页面标识", 'value' => [页面数据,json格式] ]
|
||||
'data' => []
|
||||
];
|
||||
24
addon/stock/config/event.php
Executable file
24
addon/stock/config/event.php
Executable file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
return [
|
||||
'bind' => [
|
||||
|
||||
],
|
||||
|
||||
'listen' => [
|
||||
//展示活动
|
||||
'ShowPromotion' => [
|
||||
'addon\stock\event\ShowPromotion',
|
||||
],
|
||||
],
|
||||
|
||||
'subscribe' => [
|
||||
],
|
||||
];
|
||||
21
addon/stock/config/info.php
Executable file
21
addon/stock/config/info.php
Executable file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
|
||||
* =========================================================
|
||||
*/
|
||||
return [
|
||||
'name' => 'stock',
|
||||
'title' => '库存管理',
|
||||
'description' => '库存管理功能',
|
||||
'type' => 'tool', //插件类型 system :系统插件 promotion:营销插件 tool:工具插件
|
||||
'status' => 1,
|
||||
'author' => '',
|
||||
'version' => '5.5.3',
|
||||
'version_no' => '553250709001',
|
||||
'content' => '',
|
||||
];
|
||||
222
addon/stock/config/menu_shop.php
Executable file
222
addon/stock/config/menu_shop.php
Executable file
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
return [
|
||||
[
|
||||
'name' => 'STOCK_LIST_INDEX',
|
||||
'title' => '库存管理',
|
||||
'url' => 'stock://shop/stock/manage',
|
||||
'is_show' => 1,
|
||||
'is_control' => 1,
|
||||
'parent' => 'GOODS_ROOT',
|
||||
'is_icon' => 0,
|
||||
'picture' => '',
|
||||
'picture_select' => '',
|
||||
'sort' => 3,
|
||||
'child_list' => [
|
||||
[
|
||||
'name' => 'STOCK_LIST',
|
||||
'title' => '库存管理',
|
||||
'url' => 'stock://shop/stock/manage',
|
||||
'is_show' => 1,
|
||||
'sort' => 1,
|
||||
'child_list' => [
|
||||
[
|
||||
'name' => 'STOCK_RECORDS',
|
||||
'title' => '库存流水',
|
||||
'url' => 'stock://shop/stock/records',
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_GOODS_EXPORT_LIST',
|
||||
'title' => '商品导出记录',
|
||||
'url' => 'stock://shop/stock/export',
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_INPUT',
|
||||
'title' => '入库管理',
|
||||
'url' => 'stock://shop/stock/storage',
|
||||
'is_show' => 1,
|
||||
'sort' => 2,
|
||||
'child_list' => [
|
||||
[
|
||||
'name' => 'STOCK_INPUT_DETAIL',
|
||||
'title' => '入库单详情',
|
||||
'url' => 'stock://shop/stock/inputdetail',
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_INPUT_ADD',
|
||||
'title' => '添加入库单',
|
||||
'url' => 'stock://shop/stock/stockin',
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_OUTPUT',
|
||||
'title' => '出库管理',
|
||||
'url' => 'stock://shop/stock/wastage',
|
||||
'is_show' => 1,
|
||||
'sort' => 3,
|
||||
'child_list' => [
|
||||
[
|
||||
'name' => 'STOCK_OUTPUT_ADD',
|
||||
'title' => '添加出库单',
|
||||
'url' => 'stock://shop/stock/stockout',
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_OUTPUT_DETAIL',
|
||||
'title' => '出库单详情',
|
||||
'url' => 'stock://shop/stock/outputdetail',
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_ALLOT',
|
||||
'title' => '库存调拨',
|
||||
'url' => 'stock://shop/stock/allocate',
|
||||
'is_show' => 1,
|
||||
'sort' => 4,
|
||||
'child_list' => [
|
||||
[
|
||||
'name' => 'STOCK_ALLOT_RECORDS',
|
||||
'title' => '调拨流水',
|
||||
'url' => 'stock://shop/stock/allotrecords',
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_ALLOT_ADD',
|
||||
'title' => '调拨',
|
||||
'url' => 'stock://shop/stock/editallocate',
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_INVENTORY',
|
||||
'title' => '库存盘点',
|
||||
'url' => 'stock://shop/stock/check',
|
||||
'is_show' => 1,
|
||||
'sort' => 5,
|
||||
'child_list' => [
|
||||
[
|
||||
'name' => 'STOCK_INVENTORY_EDIT',
|
||||
'title' => '添加盘点单',
|
||||
'url' => 'stock://shop/stock/editcheck',
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_INVENTORY_DETAIL',
|
||||
'title' => '盘点单详情',
|
||||
'url' => 'stock://shop/stock/inventorydetail',
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_INVENTORY_AGREE',
|
||||
'title' => '盘点单审核通过',
|
||||
'url' => 'stock://shop/stock/agree',
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_INVENTORY_REFUSE',
|
||||
'title' => '盘点单审核拒绝',
|
||||
'url' => 'stock://shop/stock/refuse',
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_INVENTORY_DELETE',
|
||||
'title' => '删除盘点单',
|
||||
'url' => 'stock://shop/stock/delete',
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_SET',
|
||||
'title' => '库存设置',
|
||||
'url' => 'stock://shop/stock/config',
|
||||
'is_show' => 1,
|
||||
'sort' => 6,
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_INVENTORY_DOCUMENT_AGREE',
|
||||
'title' => '单据审核通过',
|
||||
'url' => 'stock://shop/stock/agree',
|
||||
'is_show' => 0,
|
||||
'sort' => 7,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_INVENTORY_DOCUMENT_REFUSE',
|
||||
'title' => '单据审核拒绝',
|
||||
'url' => 'stock://shop/stock/refuse',
|
||||
'is_show' => 0,
|
||||
'sort' => 8,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_INVENTORY_DOCUMENT_DELETE',
|
||||
'title' => '删除单据',
|
||||
'url' => 'stock://shop/stock/delete',
|
||||
'is_show' => 0,
|
||||
'sort' => 9,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_TRANSFORM',
|
||||
'title' => '库存转换',
|
||||
'url' => 'stock://shop/transform/lists',
|
||||
'is_show' => 1,
|
||||
'sort' => 7,
|
||||
'child_list' => [
|
||||
[
|
||||
'name' => 'STOCK_TRANSFORM_ADD',
|
||||
'title' => '添加',
|
||||
'url' => 'stock://shop/transform/add',
|
||||
'is_show' => 0,
|
||||
'sort' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_TRANSFORM_EDIT',
|
||||
'title' => '编辑',
|
||||
'url' => 'stock://shop/transform/edit',
|
||||
'is_show' => 0,
|
||||
'sort' => 2,
|
||||
],
|
||||
[
|
||||
'name' => 'STOCK_TRANSFORM_DELETE',
|
||||
'title' => '删除',
|
||||
'url' => 'stock://shop/transform/delete',
|
||||
'is_show' => 0,
|
||||
'sort' => 3,
|
||||
],
|
||||
]
|
||||
],
|
||||
]
|
||||
],
|
||||
];
|
||||
7
addon/stock/config/menu_store.php
Executable file
7
addon/stock/config/menu_store.php
Executable file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 平台端菜单设置
|
||||
// +----------------------------------------------------------------------
|
||||
return [
|
||||
|
||||
];
|
||||
1
addon/stock/data/install.sql
Executable file
1
addon/stock/data/install.sql
Executable file
@@ -0,0 +1 @@
|
||||
SET NAMES 'utf8';
|
||||
1
addon/stock/data/uninstall.sql
Executable file
1
addon/stock/data/uninstall.sql
Executable file
@@ -0,0 +1 @@
|
||||
SET NAMES 'utf8';
|
||||
39
addon/stock/dict/StockDict.php
Executable file
39
addon/stock/dict/StockDict.php
Executable file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\dict;
|
||||
|
||||
|
||||
/**
|
||||
* 库存公共属性
|
||||
*/
|
||||
class StockDict
|
||||
{
|
||||
const input = 'input';
|
||||
const output = 'output';
|
||||
|
||||
/**
|
||||
* 出入库类型
|
||||
* @param $type
|
||||
* @return string|string[]
|
||||
*/
|
||||
public static function getType($type = ''){
|
||||
$list = [
|
||||
self::input => '入库',
|
||||
self::output => '出库',
|
||||
];
|
||||
|
||||
if($type) return $list[$type] ?? '';
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
30
addon/stock/event/Install.php
Executable file
30
addon/stock/event/Install.php
Executable file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
// +---------------------------------------------------------------------+
|
||||
// | NiuCloud | [ WE CAN DO IT JUST NiuCloud ] |
|
||||
// +---------------------------------------------------------------------+
|
||||
// | Copy right 2019-2029 www.niucloud.com |
|
||||
// +---------------------------------------------------------------------+
|
||||
// | Author | NiuCloud <niucloud@outlook.com> |
|
||||
// +---------------------------------------------------------------------+
|
||||
// | Repository | https://github.com/niucloud/framework.git |
|
||||
// +---------------------------------------------------------------------+
|
||||
|
||||
|
||||
namespace addon\stock\event;
|
||||
|
||||
use app\model\system\Menu;
|
||||
|
||||
/**
|
||||
* 应用安装
|
||||
*/
|
||||
class Install
|
||||
{
|
||||
/**
|
||||
* 执行安装
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
(new Menu())->refreshCashierAuth('stock');
|
||||
return success();
|
||||
}
|
||||
}
|
||||
47
addon/stock/event/ShowPromotion.php
Executable file
47
addon/stock/event/ShowPromotion.php
Executable file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
|
||||
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
|
||||
namespace addon\stock\event;
|
||||
|
||||
/**
|
||||
* 活动展示
|
||||
*/
|
||||
class ShowPromotion
|
||||
{
|
||||
|
||||
/**
|
||||
* 活动展示
|
||||
* @return array
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
return [
|
||||
'shop' => [
|
||||
[
|
||||
//插件名称
|
||||
'name' => 'stock',
|
||||
//店铺端展示分类 shop:营销活动 member:互动营销
|
||||
'show_type' => 'tool',
|
||||
//展示主题
|
||||
'title' => '库存管理',
|
||||
//展示介绍
|
||||
'description' => '库存管理功能',
|
||||
//展示图标
|
||||
'icon' => 'addon/stock/icon.png',
|
||||
//跳转链接
|
||||
'url' => 'stock://shop/stock/manage',
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
27
addon/stock/event/UnInstall.php
Executable file
27
addon/stock/event/UnInstall.php
Executable file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
// +---------------------------------------------------------------------+
|
||||
// | NiuCloud | [ WE CAN DO IT JUST NiuCloud ] |
|
||||
// +---------------------------------------------------------------------+
|
||||
// | Copy right 2019-2029 www.niucloud.com |
|
||||
// +---------------------------------------------------------------------+
|
||||
// | Author | NiuCloud <niucloud@outlook.com> |
|
||||
// +---------------------------------------------------------------------+
|
||||
// | Repository | https://github.com/niucloud/framework.git |
|
||||
// +---------------------------------------------------------------------+
|
||||
|
||||
|
||||
namespace addon\stock\event;
|
||||
|
||||
/**
|
||||
* 应用卸载
|
||||
*/
|
||||
class UnInstall
|
||||
{
|
||||
/**
|
||||
* 执行卸载
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
return success();
|
||||
}
|
||||
}
|
||||
BIN
addon/stock/icon.png
Executable file
BIN
addon/stock/icon.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
39
addon/stock/model/Store.php
Executable file
39
addon/stock/model/Store.php
Executable file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\model;
|
||||
|
||||
|
||||
use app\model\store\Store as StoreCommonModel;
|
||||
use app\model\BaseModel;
|
||||
|
||||
/**
|
||||
* 库存model
|
||||
*
|
||||
* @author Administrator
|
||||
*
|
||||
*/
|
||||
class Store extends BaseModel
|
||||
{
|
||||
/**
|
||||
* 库存用门店列表
|
||||
* @param $site_id
|
||||
* @return mixed
|
||||
*/
|
||||
public function getStoreList($site_id)
|
||||
{
|
||||
$condition = [
|
||||
[ 'site_id', '=', $site_id ],
|
||||
[ 'stock_type', '=', 'store' ]
|
||||
];
|
||||
$store_model = new StoreCommonModel();
|
||||
return $store_model->getStoreList($condition);
|
||||
}
|
||||
}
|
||||
621
addon/stock/model/stock/Allot.php
Executable file
621
addon/stock/model/stock/Allot.php
Executable file
@@ -0,0 +1,621 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\model\stock;
|
||||
|
||||
|
||||
use addon\stock\dict\StockDict;
|
||||
use addon\stock\model\stock\Stock as StockModel;
|
||||
use app\model\store\Store;
|
||||
use app\model\BaseModel;
|
||||
use app\model\system\User;
|
||||
use app\dict\goods\GoodsDict;
|
||||
|
||||
/**
|
||||
* 调拨
|
||||
* Class Allot
|
||||
* @package addon\stock\model\stock
|
||||
*/
|
||||
class Allot extends BaseModel
|
||||
{
|
||||
|
||||
public function getAllotNo()
|
||||
{
|
||||
return 'ALLOT' . date('ymdhis', time()) . rand(1111, 9999);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增库存调拨
|
||||
* @param $params
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function addAllot($params)
|
||||
{
|
||||
model('stock_allot')->startTrans();
|
||||
try {
|
||||
$output_store_id = $params[ 'output_store_id' ];//出库门店
|
||||
$input_store_id = $params[ 'input_store_id' ];//入库门店
|
||||
$site_id = $params[ 'site_id' ];
|
||||
$allot_time = $params[ 'allot_time' ] ?? time();
|
||||
$remark = $params[ 'remark' ] ?? '';
|
||||
$goods_sku_list = $params[ 'goods_sku_list' ];
|
||||
|
||||
//查询门店名称信息
|
||||
$store_model = new Store();
|
||||
$output_store_condition = [
|
||||
[ 'store_id', '=', $output_store_id ]
|
||||
];
|
||||
$output_store_info = $store_model->getStoreInfo($output_store_condition)[ 'data' ] ?? [];
|
||||
if (empty($output_store_info))
|
||||
return $this->success([], '找不到所选的门店');
|
||||
|
||||
$output_store_name = $output_store_info[ 'store_name' ] ?? '';
|
||||
$input_store_condition = [
|
||||
[ 'store_id', '=', $input_store_id ]
|
||||
];
|
||||
$input_store_info = $store_model->getStoreInfo($input_store_condition)[ 'data' ] ?? [];
|
||||
if (empty($input_store_info))
|
||||
return $this->success([], '找不到所选的门店');
|
||||
|
||||
$operater = $params[ 'operater' ];
|
||||
|
||||
$goods_sku_list_array_result = $this->getSkuArray($goods_sku_list, $output_store_id);
|
||||
|
||||
if ($goods_sku_list_array_result[ 'code' ] < 0) {
|
||||
model('stock_allot')->rollback();
|
||||
return $goods_sku_list_array_result;
|
||||
}
|
||||
$goods_sku_list_array = $goods_sku_list_array_result[ 'data' ];
|
||||
$input_store_name = $input_store_info[ 'store_name' ] ?? '';
|
||||
$allot_no = isset($params['allot_no']) && $params['allot_no'] ? $params['allot_no'] : $this->getAllotNo();
|
||||
|
||||
$count = model('stock_allot')->getCount([ ['allot_no', '=', $allot_no] ]);
|
||||
if($count > 0) return $this->error([], '录入失败,单号重复');
|
||||
|
||||
$user_model = new User();
|
||||
$user_info = $user_model->getUserInfo([ [ 'uid', '=', $operater ] ])[ 'data' ] ?? [];
|
||||
$goods_money = getArraySum($goods_sku_list, 'cost_price', 'goods_num');
|
||||
$data = [
|
||||
'site_id' => $site_id,
|
||||
'output_store_id' => $output_store_id,
|
||||
'output_store_name' => $output_store_name,
|
||||
'input_store_id' => $input_store_id,
|
||||
'input_store_name' => $input_store_name,
|
||||
'allot_time' => $allot_time,
|
||||
'goods_money' => $goods_money,
|
||||
'allot_no' => $allot_no,
|
||||
'remark' => $remark,
|
||||
'status' => 1,
|
||||
'create_time' => time(),
|
||||
'operater' => $operater,
|
||||
'operater_name' => $user_info[ 'username' ] ?? ''
|
||||
];
|
||||
$allot_id = model('stock_allot')->add($data);
|
||||
$common_data = [
|
||||
'site_id' => $site_id,
|
||||
'allot_id' => $allot_id,
|
||||
'create_time' => time()
|
||||
];
|
||||
foreach ($goods_sku_list_array as $k => $v) {
|
||||
$item_data = array_merge($common_data, $v);
|
||||
model('stock_allot_goods')->add($item_data);
|
||||
}
|
||||
|
||||
$is_auto_audit = $params[ 'is_auto_audit' ] ?? true;
|
||||
if ($is_auto_audit) {
|
||||
//主动调用审核
|
||||
$result = $this->audit([
|
||||
'allot_id' => $allot_id,
|
||||
'site_id' => $site_id
|
||||
]);
|
||||
if ($result[ 'code' ] < 0) {
|
||||
model('stock_allot')->rollback();
|
||||
return $result;
|
||||
}
|
||||
} else {
|
||||
$stock_model = new Stock();
|
||||
$stock_config = $stock_model->getStockConfig($site_id)[ 'data' ][ 'value' ];
|
||||
$is_audit = $stock_config[ 'is_audit' ];
|
||||
if (!$is_audit) {
|
||||
$result = $this->audit([
|
||||
'allot_id' => $allot_id,
|
||||
'site_id' => $site_id
|
||||
]);
|
||||
if ($result[ 'code' ] < 0) {
|
||||
model('stock_allot')->rollback();
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model('stock_allot')->commit();
|
||||
return $this->success();
|
||||
} catch (\Exception $e) {
|
||||
model('stock_allot')->rollback();
|
||||
return $this->error([$e->getFile(),$e->getLine(),$e->getMessage()], $e->getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 修改库存调拨
|
||||
* @param $params
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function editAllot($params)
|
||||
{
|
||||
model('stock_allot')->startTrans();
|
||||
try {
|
||||
$output_store_id = $params[ 'output_store_id' ];//出库门店
|
||||
$input_store_id = $params[ 'input_store_id' ];//入库门店
|
||||
$site_id = $params[ 'site_id' ];
|
||||
$allot_time = $params[ 'allot_time' ] ?? time();
|
||||
$remark = $params[ 'remark' ] ?? '';
|
||||
$goods_sku_list = $params[ 'goods_sku_list' ];
|
||||
$allot_id = $params['allot_id'];
|
||||
$user_info = $params['user_info'];
|
||||
|
||||
$condition = [
|
||||
[ 'allot_id', '=', $allot_id ],
|
||||
[ 'site_id', '=', $site_id ],
|
||||
];
|
||||
$allot_info = model('stock_allot')->getInfo($condition);
|
||||
|
||||
if ($allot_info[ 'status' ] == 2) {
|
||||
model('stock_allot')->rollback();
|
||||
return $this->error([], '已审核的单据不能编辑');
|
||||
}
|
||||
if ($allot_info[ 'operater' ] != $user_info[ 'uid' ]) {
|
||||
model('stock_allot')->rollback();
|
||||
return $this->error([], '只有单据创建者可以编辑单据');
|
||||
}
|
||||
|
||||
//查询门店名称信息
|
||||
$store_model = new Store();
|
||||
$output_store_condition = [
|
||||
[ 'store_id', '=', $output_store_id ]
|
||||
];
|
||||
$output_store_info = $store_model->getStoreInfo($output_store_condition)[ 'data' ] ?? [];
|
||||
if (empty($output_store_info))
|
||||
return $this->success([], '找不到所选的门店');
|
||||
|
||||
$output_store_name = $output_store_info[ 'store_name' ] ?? '';
|
||||
$input_store_condition = [
|
||||
[ 'store_id', '=', $input_store_id ]
|
||||
];
|
||||
$input_store_info = $store_model->getStoreInfo($input_store_condition)[ 'data' ] ?? [];
|
||||
if (empty($input_store_info))
|
||||
return $this->success([], '找不到所选的门店');
|
||||
|
||||
$goods_sku_list_array_result = $this->getSkuArray($goods_sku_list, $output_store_id);
|
||||
|
||||
if ($goods_sku_list_array_result[ 'code' ] < 0) {
|
||||
model('stock_allot')->rollback();
|
||||
return $goods_sku_list_array_result;
|
||||
}
|
||||
$goods_sku_list_array = $goods_sku_list_array_result[ 'data' ];
|
||||
$input_store_name = $input_store_info[ 'store_name' ] ?? '';
|
||||
$allot_no = isset($params['allot_no']) && $params['allot_no'] ? $params['allot_no'] : $this->getAllotNo();
|
||||
|
||||
$count = model('stock_allot')->getCount([ ['allot_no', '=', $allot_no], ['allot_id', '<>', $allot_id] ]);
|
||||
if($count > 0) return $this->error([], '录入失败,单号重复');
|
||||
$goods_money = getArraySum($goods_sku_list, 'cost_price', 'goods_num');
|
||||
|
||||
$data = [
|
||||
'output_store_id' => $output_store_id,
|
||||
'output_store_name' => $output_store_name,
|
||||
'input_store_id' => $input_store_id,
|
||||
'input_store_name' => $input_store_name,
|
||||
'allot_time' => $allot_time,
|
||||
'allot_no' => $allot_no,
|
||||
'remark' => $remark,
|
||||
'status' => 1,
|
||||
'goods_money' => $goods_money
|
||||
];
|
||||
model('stock_allot')->update($data, [ ['site_id', '=', $site_id], ['allot_id', '=', $allot_id] ]);
|
||||
//删除原有的单据商品
|
||||
model('stock_allot_goods')->delete([ 'allot_id' => $allot_id ]);
|
||||
$common_data = [
|
||||
'site_id' => $site_id,
|
||||
'allot_id' => $allot_id,
|
||||
'create_time' => time()
|
||||
];
|
||||
foreach ($goods_sku_list_array as $k => $v) {
|
||||
$item_data = array_merge($common_data, $v);
|
||||
model('stock_allot_goods')->add($item_data);
|
||||
}
|
||||
|
||||
$is_auto_audit = $params[ 'is_auto_audit' ] ?? true;
|
||||
|
||||
if ($is_auto_audit) {
|
||||
//主动调用审核
|
||||
$result = $this->audit([
|
||||
'allot_id' => $allot_id,
|
||||
'site_id' => $site_id
|
||||
]);
|
||||
if ($result[ 'code' ] < 0) {
|
||||
model('stock_allot')->rollback();
|
||||
return $result;
|
||||
}
|
||||
} else {
|
||||
$stock_model = new Stock();
|
||||
$stock_config = $stock_model->getStockConfig($site_id)[ 'data' ][ 'value' ];
|
||||
$is_audit = $stock_config[ 'is_audit' ];
|
||||
if (!$is_audit) {
|
||||
$result = $this->audit([
|
||||
'allot_id' => $allot_id,
|
||||
'site_id' => $site_id
|
||||
]);
|
||||
if ($result[ 'code' ] < 0) {
|
||||
model('stock_allot')->rollback();
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model('stock_allot')->commit();
|
||||
return $this->success();
|
||||
} catch (\Exception $e) {
|
||||
model('stock_allot')->rollback();
|
||||
return $this->error('', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function getSkuArray($goods_sku_list, $store_id)
|
||||
{
|
||||
$sku_ids = array_column($goods_sku_list, 'goods_sku_id');
|
||||
$goods_nums = array_column($goods_sku_list, 'goods_num', 'goods_sku_id');
|
||||
$stock_model = new StockModel();
|
||||
$condition = [
|
||||
['gs.sku_id', 'in', $sku_ids],
|
||||
];
|
||||
$field = 'g.goods_class,gs.sku_id,gs.goods_id,gs.sku_image,gs.sku_name,gs.unit,gs.sku_no,gs.spec_name,sgs.stock,sgs.real_stock,sgs.price,gs.cost_price';
|
||||
$goods_sku_list = $stock_model->getStoreGoodsSkuPage($condition, $field, 'gs.create_time desc, gs.sku_id desc', $store_id, 1, 0)['data']['list'];
|
||||
|
||||
$goods_sku_list_array = [];
|
||||
foreach ($goods_sku_list as $goods_sku_info) {
|
||||
$goods_sku_id = $goods_sku_info[ 'sku_id' ];
|
||||
$goods_num = $goods_nums[$goods_sku_id] ?? 0;
|
||||
$goods_class = $goods_sku_info['goods_class'];
|
||||
if($goods_class == GoodsDict::weigh && !preg_match(config('regexp.>0float3'), $goods_num)){
|
||||
return $this->error(null, '[' . $goods_sku_info[ 'sku_name' ] . ']调拨数量必须为正数且最多保留三位小数!');
|
||||
}else if($goods_class != GoodsDict::weigh && !preg_match(config('regexp.>0num'), $goods_num)){
|
||||
return $this->error(null, '[' . $goods_sku_info[ 'sku_name' ] . ']调拨数量必须为正整数!');
|
||||
}else if($goods_num > $goods_sku_info['real_stock']){
|
||||
return $this->error(null, '[' . $goods_sku_info[ 'sku_name' ] . ']可调拨数量不足!');
|
||||
}
|
||||
|
||||
$goods_sku_list_array[] = [
|
||||
'goods_id' => $goods_sku_info[ 'goods_id' ],
|
||||
'goods_sku_id' => $goods_sku_info[ 'sku_id' ],
|
||||
'goods_sku_name' => $goods_sku_info[ 'sku_name' ],
|
||||
'goods_sku_no' => $goods_sku_info[ 'sku_no' ],
|
||||
'goods_sku_img' => $goods_sku_info[ 'sku_image' ],
|
||||
'goods_sku_spec' => $goods_sku_info[ 'spec_name' ],
|
||||
'goods_unit' => $goods_sku_info[ 'unit' ] ? $goods_sku_info[ 'unit' ] : '件',
|
||||
'goods_num' => $goods_num,
|
||||
'goods_price' => $goods_sku_info[ 'cost_price' ],
|
||||
'goods_remark' => '',
|
||||
];
|
||||
}
|
||||
|
||||
return $this->success($goods_sku_list_array);
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核
|
||||
* @param $params
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function audit($params)
|
||||
{
|
||||
$site_id = $params[ 'site_id' ];
|
||||
$allot_id = $params[ 'allot_id' ];
|
||||
$condition = [
|
||||
[ 'site_id', '=', $site_id ],
|
||||
[ 'allot_id', '=', $allot_id ]
|
||||
];
|
||||
$info = model('stock_allot')->getInfo($condition);
|
||||
if (empty($info)) {
|
||||
return $this->error([], '调拨单据不存在');
|
||||
}
|
||||
|
||||
$allot_data = [
|
||||
'verify_time' => time(),
|
||||
'status' => 2
|
||||
];
|
||||
|
||||
model('stock_allot')->update($allot_data, $condition);
|
||||
$result = $this->complete($params);
|
||||
if ($result[ 'code' ] < 0)
|
||||
return $result;
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 拒绝审核
|
||||
* @param $params
|
||||
* @return array
|
||||
*/
|
||||
public function refuse($params)
|
||||
{
|
||||
$allot_id = $params[ 'allot_id' ];
|
||||
$site_id = $params[ 'site_id' ];
|
||||
$user_info = $params[ 'user_info' ];
|
||||
$condition = [
|
||||
[ 'allot_id', '=', $allot_id ],
|
||||
[ 'site_id', '=', $site_id ]
|
||||
];
|
||||
$info = model('stock_allot')->getInfo($condition);
|
||||
if (empty($info))
|
||||
return $this->error([], '找不到可审核的单据');
|
||||
|
||||
if ($info[ 'status' ] == 2)
|
||||
return $this->error([], '当前单据已审核');
|
||||
|
||||
$data = [
|
||||
'status' => -1,
|
||||
'verify_time' => time(),
|
||||
'refuse_reason' => $params[ 'refuse_reason' ],
|
||||
'verifier' => $user_info[ 'uid' ] ?? 0,//审核人
|
||||
'verifier_name' => $user_info[ 'username' ] ?? '系统'
|
||||
];
|
||||
model('stock_allot')->update($data, $condition);
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除单据
|
||||
* @param $params
|
||||
* @return array
|
||||
*/
|
||||
public function delete($params)
|
||||
{
|
||||
$site_id = $params[ 'site_id' ];
|
||||
$allot_id = $params[ 'allot_id' ];
|
||||
$user_info = $params[ 'user_info' ];
|
||||
$store_id = $params[ 'store_id' ] ?? 0;
|
||||
//查询单据
|
||||
$condition = [
|
||||
[ 'allot_id', '=', $allot_id ],
|
||||
[ 'site_id', '=', $site_id ],
|
||||
];
|
||||
if ($store_id > 0) {
|
||||
$condition[] = [ 'store_id', '=', $store_id ];
|
||||
}
|
||||
$allot_info = model('stock_allot')->getInfo($condition);
|
||||
//被拒绝也可以删除
|
||||
if ($allot_info[ 'status' ] == 2) {
|
||||
return $this->error('已审核的单据不能删除');
|
||||
}
|
||||
if ($allot_info[ 'operater' ] != $user_info[ 'uid' ]) {
|
||||
return $this->error('只有单据创建者可以删除单据');
|
||||
}
|
||||
model('stock_allot')->delete($condition);
|
||||
model('stock_allot_goods')->delete($condition);
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
public function complete($params)
|
||||
{
|
||||
$allot_id = $params[ 'allot_id' ];
|
||||
$condition = [
|
||||
[ 'allot_id', '=', $allot_id ]
|
||||
];
|
||||
$info = model('stock_allot')->getInfo($condition);
|
||||
if (empty($info)) {
|
||||
return $this->error([], '调拨单据不存在');
|
||||
}
|
||||
$result = $this->setStock($info);
|
||||
if ($result[ 'code' ] < 0)
|
||||
return $result;
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 整理调拨单据
|
||||
* @param $params
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function setStock($params)
|
||||
{
|
||||
$site_id = $params[ 'site_id' ];
|
||||
$allot_id = $params[ 'allot_id' ];
|
||||
$allot_goods_condition = [
|
||||
[ 'allot_id', '=', $allot_id ]
|
||||
];
|
||||
$allot_goods_list = model('stock_allot_goods')->getList($allot_goods_condition);
|
||||
$output_store_id = $params[ 'output_store_id' ];
|
||||
$input_store_id = $params[ 'input_store_id' ];
|
||||
$remark = $params[ 'remark' ];
|
||||
$allot_time = $params[ 'allot_time' ];
|
||||
$operater = $params[ 'operater' ];
|
||||
$operater_name = $params[ 'operater_name' ];
|
||||
foreach ($allot_goods_list as $k => $goods_sku_item) {
|
||||
$allot_goods_id = $goods_sku_item[ 'allot_goods_id' ];
|
||||
$item_sku_id = $goods_sku_item[ 'goods_sku_id' ];
|
||||
$item_goods_id = $goods_sku_item[ 'goods_id' ];
|
||||
|
||||
$goods_num = numberFormat($goods_sku_item[ 'goods_num' ]);
|
||||
|
||||
$sku_condition = [
|
||||
[ 'sku_id', '=', $item_sku_id ]
|
||||
];
|
||||
$goods_sku_info = model('goods_sku')->getInfo($sku_condition);
|
||||
|
||||
$goods_price = $goods_sku_info[ 'cost_price' ];
|
||||
$output_store_sku_condition = [
|
||||
[ 'store_id', '=', $output_store_id ],
|
||||
[ 'goods_id', '=', $item_goods_id ],
|
||||
[ 'sku_id', '=', $item_sku_id ]
|
||||
];
|
||||
$output_store_sku_info = model('store_goods_sku')->getInfo($output_store_sku_condition);
|
||||
|
||||
$output_store_stock = $output_store_sku_info[ 'real_stock' ] ?? 0;
|
||||
$input_store_sku_condition = [
|
||||
[ 'store_id', '=', $input_store_id ],
|
||||
[ 'goods_id', '=', $item_goods_id ],
|
||||
[ 'sku_id', '=', $item_sku_id ]
|
||||
];
|
||||
$input_store_sku_info = model('store_goods_sku')->getInfo($input_store_sku_condition);
|
||||
|
||||
$input_store_stock = $input_store_sku_info[ 'real_stock' ] ?? 0;
|
||||
$total_goods_money = $goods_num * $goods_price;
|
||||
$update_data = [
|
||||
'output_store_stock' => numberFormat($output_store_stock),
|
||||
'input_store_stock' => numberFormat($input_store_stock),
|
||||
'goods_price' => $goods_price,
|
||||
'total_goods_money' => $total_goods_money,
|
||||
];
|
||||
$update_condition = [
|
||||
[ 'allot_goods_id', '=', $allot_goods_id ]
|
||||
];
|
||||
model('stock_allot_goods')->update($update_data, $update_condition);
|
||||
|
||||
$goods_money = model('stock_allot_goods')->getSum([ [ 'site_id', '=', $site_id ], [ 'allot_id', '=', $allot_id ] ], 'total_goods_money');
|
||||
|
||||
model('stock_allot')->update([ 'goods_money' => $goods_money ], [
|
||||
[ 'site_id', '=', $site_id ],
|
||||
[ 'allot_id', '=', $allot_id ]
|
||||
]);
|
||||
|
||||
//新增门店出库
|
||||
$goods_sku_list = [
|
||||
[
|
||||
'goods_sku_id' => $item_sku_id,
|
||||
'goods_id' => $item_goods_id,
|
||||
'goods_num' => $goods_num,
|
||||
'goods_price' => $goods_price
|
||||
]
|
||||
];
|
||||
|
||||
$user_info = [
|
||||
'uid' => $operater,
|
||||
'username' => $operater_name,
|
||||
];
|
||||
$document_model = new Document();
|
||||
$document_params = [
|
||||
'allot_id' => $allot_id,
|
||||
'store_id' => $output_store_id,
|
||||
'user_info' => $user_info,
|
||||
'site_id' => $site_id,
|
||||
'is_auto_audit' => false,//调拨的单据如果开始审核开关的话就需要审核
|
||||
];
|
||||
$document_params[ 'document_type' ] = 'ALLOTPUT';
|
||||
$document_params[ 'goods_sku_list' ] = $goods_sku_list;
|
||||
$document_params[ 'is_auto_audit' ] = 1;
|
||||
|
||||
$out_result = $document_model->addDocument(array_merge($document_params, [ 'is_out_stock' => 1 ]));
|
||||
if ($out_result[ 'code' ] < 0) {
|
||||
return $out_result;
|
||||
}
|
||||
|
||||
$document_params[ 'store_id' ] = $input_store_id;
|
||||
$document_params[ 'document_type' ] = 'ALLOTIN';
|
||||
$out_result = $document_model->addDocument($document_params);
|
||||
if ($out_result[ 'code' ] < 0) {
|
||||
return $out_result;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取调拨单分页列表
|
||||
* @param array $condition
|
||||
* @param int $page
|
||||
* @param int $page_size
|
||||
* @param string $order
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getStockAllotPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '*', $alias = '', $join = '')
|
||||
{
|
||||
$document_list = model('stock_allot')->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
|
||||
return $this->success($document_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 单据详情
|
||||
* @param array $condition
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getAllotInfo($condition = [], $field = '*')
|
||||
{
|
||||
$info = model('stock_allot')->getInfo($condition, $field);
|
||||
if (!empty($info)) {
|
||||
|
||||
$document_model = new Document();
|
||||
|
||||
// 查询入库单
|
||||
$info[ 'input_info' ] = $document_model->getDocumentInfo([ [ 'site_id', '=', $info[ 'site_id' ] ], [ 'allot_id', '=', $info[ 'allot_id' ] ], [ 'type', '=', StockDict::input ], [ 'store_id', '=', $info[ 'input_store_id' ] ] ], 'operater_name,verifier_name,status,refuse_reason,create_time,audit_time')[ 'data' ];
|
||||
|
||||
// 查询出库单
|
||||
$info[ 'out_info' ] = $document_model->getDocumentInfo([ [ 'site_id', '=', $info[ 'site_id' ] ], [ 'allot_id', '=', $info[ 'allot_id' ] ], [ 'type', '=', StockDict::output ], [ 'store_id', '=', $info[ 'output_store_id' ] ] ], 'operater_name,verifier_name,status,refuse_reason,create_time,audit_time')[ 'data' ];
|
||||
|
||||
//单据产品项
|
||||
$goods_list = model('stock_allot_goods')->getList([
|
||||
'allot_id' => $info[ 'allot_id' ]
|
||||
]);
|
||||
foreach ($goods_list as $k => $v) {
|
||||
$goods_list[ $k ][ 'goods_num' ] = numberFormat($v[ 'goods_num' ]);
|
||||
$goods_list[ $k ][ 'output_store_stock' ] = numberFormat($goods_list[ $k ][ 'output_store_stock' ]);
|
||||
$goods_list[ $k ][ 'input_store_stock' ] = numberFormat($goods_list[ $k ][ 'input_store_stock' ]);
|
||||
$info[ 'goods_unit' ] = $v[ 'goods_unit' ];
|
||||
}
|
||||
$info[ 'goods_sku_list_array' ] = $goods_list;
|
||||
$info[ 'goods_price' ] = 0;
|
||||
$info[ 'goods_total_price' ] = 0.00;
|
||||
foreach ($goods_list as $key => $value) {
|
||||
$info[ 'goods_sku_list_array' ][ $key ][ 'goods_sum' ] = floatval($value[ 'goods_num' ] * $value[ 'goods_price' ]);
|
||||
$info[ 'goods_price' ] += numberFormat($value[ 'goods_num' ]);
|
||||
$info[ 'goods_total_price' ] += $info[ 'goods_sku_list_array' ][ $key ][ 'goods_sum' ];
|
||||
}
|
||||
$info[ 'goods_count' ] = count($info[ 'goods_sku_list_array' ]);
|
||||
}
|
||||
return $this->success($info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取编辑单据数据
|
||||
* @param array $condition
|
||||
* @return array
|
||||
*/
|
||||
public function getAllotEditData($condition = [])
|
||||
{
|
||||
$field = 'site_id,allot_id,output_store_id,input_store_id,allot_no,remark,allot_time';
|
||||
$allot_info = $this->getAllotInfo($condition, $field)[ 'data' ];
|
||||
if (!empty($allot_info)) {
|
||||
$goods_field = 'gs.sku_id,gs.sku_image,gs.sku_name,gs.unit,gs.sku_no,
|
||||
sgs.stock,sgs.real_stock,sgs.price,sgs.cost_price,
|
||||
ig.goods_num,ig.goods_sku_id';
|
||||
|
||||
$join = [
|
||||
[ 'goods_sku gs', 'ig.goods_sku_id = gs.sku_id', 'left' ],
|
||||
[
|
||||
'store_goods_sku sgs',
|
||||
'sgs.sku_id = gs.sku_id and (sgs.store_id is null or sgs.store_id = ' . $allot_info[ 'output_store_id' ] . ')',
|
||||
'left'
|
||||
]
|
||||
];
|
||||
|
||||
$allot_goods_list = model('stock_allot_goods')->getList([
|
||||
[ 'allot_id', '=', $allot_info[ 'allot_id' ] ]
|
||||
], $goods_field, '', 'ig', $join);
|
||||
foreach ($allot_goods_list as $k => $v) {
|
||||
$allot_goods_list[ $k ][ 'stock' ] = numberFormat($v[ 'stock' ]);
|
||||
$allot_goods_list[ $k ][ 'goods_num' ] = numberFormat($allot_goods_list[ $k ][ 'goods_num' ]);
|
||||
}
|
||||
$allot_info[ 'goods_list' ] = array_column($allot_goods_list, null, 'goods_sku_id');
|
||||
}
|
||||
return $this->success($allot_info);
|
||||
}
|
||||
|
||||
}
|
||||
1057
addon/stock/model/stock/Document.php
Executable file
1057
addon/stock/model/stock/Document.php
Executable file
File diff suppressed because it is too large
Load Diff
307
addon/stock/model/stock/Export.php
Executable file
307
addon/stock/model/stock/Export.php
Executable file
@@ -0,0 +1,307 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\model\stock;
|
||||
|
||||
use app\model\BaseModel;
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* 导出
|
||||
* @author Administrator
|
||||
*/
|
||||
class Export extends BaseModel
|
||||
{
|
||||
|
||||
public $field = [
|
||||
'store_name' => '门店名称',
|
||||
'sku_no' => '商品编码',
|
||||
'sku_name' => '商品名称',
|
||||
'stock' => '销售库存',
|
||||
'real_stock' => '实物库存',
|
||||
'price' => '销售价',
|
||||
'cost_price' => '成本价',
|
||||
'sale_num' => '销量',
|
||||
'goods_state' => '商品状态'
|
||||
];
|
||||
|
||||
public $store_name = '';
|
||||
|
||||
|
||||
/**
|
||||
* 查询商品项数据并导出
|
||||
* @param $condition
|
||||
* @param $condition_desc
|
||||
* @param $site_id
|
||||
* @param $store_id
|
||||
* @param $store_name
|
||||
* @return array
|
||||
*/
|
||||
public function export($condition, $condition_desc, $site_id, $store_id, $store_name)
|
||||
{
|
||||
try {
|
||||
// 预先创建导出的记录
|
||||
$data = [
|
||||
'condition' => json_encode($condition_desc),
|
||||
'create_time' => time(),
|
||||
'status' => 0,
|
||||
'site_id' => $site_id
|
||||
];
|
||||
$records_result = $this->addExport($data);
|
||||
|
||||
$export_id = $records_result[ 'data' ] ?? 0;
|
||||
if ($export_id <= 0) {
|
||||
return $this->error();
|
||||
}
|
||||
|
||||
$alias = 'gs';
|
||||
|
||||
$field = $this->field;
|
||||
|
||||
if ($store_id > 0) {
|
||||
$this->store_name = $store_name;
|
||||
} else {
|
||||
unset($field[ 'store_name' ]);
|
||||
}
|
||||
|
||||
// 通过分批次执行数据导出(防止内存超出配置设置的)
|
||||
|
||||
set_time_limit(0);
|
||||
$file_name = date('YmdHis');// csv文件名
|
||||
$file_path = 'upload/goods_csv/';
|
||||
if (dir_mkdir($file_path)) {
|
||||
$file_path = $file_path . $file_name . '.csv';
|
||||
//创建一个临时csv文件
|
||||
$fp = fopen($file_path, 'w'); // 生成临时文件
|
||||
fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF)); // 添加 BOM
|
||||
$field_value = [];
|
||||
$field_key = [];
|
||||
$field_key_array = [];
|
||||
// 为了防止部分代码被筛选中替换, 给变量前后两边增加字符串
|
||||
foreach ($field as $k => $v) {
|
||||
$field_value[] = $v;
|
||||
$field_key[] = "{\$$k}";
|
||||
$field_key_array[] = $k;
|
||||
}
|
||||
|
||||
$table_field = 'gs.sku_id, gs.sku_no, gs.sku_name, gs.goods_state';
|
||||
$join = [
|
||||
[ 'goods g', 'g.goods_id = gs.goods_id', 'left' ]
|
||||
];
|
||||
|
||||
$group = '';
|
||||
if ($store_id > 0) {
|
||||
$table_field .= ',sgs.price, sgs.sale_num,sgs.cost_price,ifnull(sgs.stock,0) as stock, ifnull(sgs.real_stock, 0) as real_stock,s.store_name';
|
||||
$join[] = [ 'store_goods_sku sgs', 'sgs.sku_id = gs.sku_id and (sgs.store_id is null or sgs.store_id = ' . $store_id . ')', 'left' ];
|
||||
$join[] = [ 'store s', 's.store_id = sgs.store_id', 'left' ];
|
||||
} else {
|
||||
$join[] = [ 'store_goods_sku sgs', 'sgs.sku_id = gs.sku_id or sgs.sku_id is null', 'left' ];
|
||||
$table_field .= ',gs.price, gs.sale_num,gs.cost_price,gs.stock, ifnull(sum(sgs.real_stock),0) as real_stock';
|
||||
$group = 'gs.sku_id';
|
||||
}
|
||||
|
||||
$table = Db::name('goods_sku')->where($condition)->alias($alias)->group($group)->order('g.create_time desc');
|
||||
|
||||
$table = $this->parseJoin($table, $join);
|
||||
|
||||
$first_line = implode(',', $field_value);
|
||||
// 写入第一行表头
|
||||
fwrite($fp, $first_line . "\n");
|
||||
|
||||
$temp_line = implode(',', $field_key) . "\n";
|
||||
|
||||
$table->field($table_field)->chunk(5000, function($item_list) use ($fp, $temp_line, $field_key_array) {
|
||||
// 写入导出信息
|
||||
$this->itemExport($item_list, $field_key_array, $temp_line, $fp);
|
||||
unset($item_list);
|
||||
}, 'gs.sku_id');
|
||||
|
||||
$table->removeOption();
|
||||
fclose($fp); // 每生成一个文件关闭
|
||||
unset($table);
|
||||
|
||||
// 将同步导出记录状态
|
||||
$records_data = [
|
||||
'path' => $file_path,
|
||||
'status' => 1
|
||||
];
|
||||
$records_condition = [
|
||||
[ 'export_id', '=', $export_id ]
|
||||
];
|
||||
$this->editExport($records_data, $records_condition);
|
||||
return $this->success();
|
||||
} else {
|
||||
return $this->error();
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return $this->error([], $e->getMessage() . $e->getFile() . $e->getLine());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $db_obj
|
||||
* @param $join
|
||||
* @return mixed
|
||||
*/
|
||||
public function parseJoin($db_obj, $join)
|
||||
{
|
||||
foreach ($join as $item) {
|
||||
list($table, $on, $type) = $item;
|
||||
$type = strtolower($type);
|
||||
switch ( $type ) {
|
||||
case 'left':
|
||||
$db_obj = $db_obj->leftJoin($table, $on);
|
||||
break;
|
||||
case 'inner':
|
||||
$db_obj = $db_obj->join($table, $on);
|
||||
break;
|
||||
case 'right':
|
||||
$db_obj = $db_obj->rightjoin($table, $on);
|
||||
break;
|
||||
case 'full':
|
||||
$db_obj = $db_obj->fulljoin($table, $on);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $db_obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给csv写入新的数据
|
||||
* @param $item_list
|
||||
* @param $field_key
|
||||
* @param $temp_line
|
||||
* @param $fp
|
||||
*/
|
||||
public function itemExport($item_list, $field_key, $temp_line, $fp)
|
||||
{
|
||||
$item_list = $item_list->toArray();
|
||||
foreach ($item_list as $k => $item_v) {
|
||||
$new_line_value = $temp_line;
|
||||
|
||||
if (!empty($this->store_name)) {
|
||||
$item_v[ 'store_name' ] = $this->store_name;
|
||||
}
|
||||
|
||||
if (isset($item_v[ 'num' ])) {
|
||||
$item_v[ 'num' ] = numberFormat($item_v[ 'num' ]);
|
||||
}
|
||||
|
||||
if (isset($item_v[ 'stock' ])) {
|
||||
$item_v[ 'stock' ] = numberFormat($item_v[ 'stock' ]);
|
||||
}
|
||||
|
||||
if (isset($item_v[ 'sale_num' ])) {
|
||||
$item_v[ 'sale_num' ] = numberFormat($item_v[ 'sale_num' ]);
|
||||
}
|
||||
if (isset($item_v[ 'real_stock' ])) {
|
||||
$item_v[ 'real_stock' ] = numberFormat($item_v[ 'real_stock' ]);
|
||||
}
|
||||
|
||||
$item_v[ 'goods_state' ] = $item_v[ 'goods_state' ] == 1 ? '销售中' : '仓库中';
|
||||
|
||||
foreach ($item_v as $key => $value) {
|
||||
$value = trim($value);
|
||||
|
||||
//CSV比较简单,记得转义 逗号就好
|
||||
$values = str_replace(',', '\\', $value . "\t");
|
||||
$values = str_replace("\n", '', $values);
|
||||
$values = str_replace("\r", '', $values);
|
||||
$new_line_value = str_replace("{\$$key}", $values, $new_line_value);
|
||||
}
|
||||
|
||||
// 写入第一行表头
|
||||
fwrite($fp, $new_line_value);
|
||||
|
||||
// 销毁变量, 防止内存溢出
|
||||
unset($new_line_value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加导出记录
|
||||
* @param $data
|
||||
* @return array
|
||||
*/
|
||||
public function addExport($data)
|
||||
{
|
||||
$res = model('stock_goods_export')->add($data);
|
||||
return $this->success($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新导出记录
|
||||
* @param $data
|
||||
* @param $condition
|
||||
* @return array
|
||||
*/
|
||||
public function editExport($data, $condition)
|
||||
{
|
||||
$res = model('stock_goods_export')->update($data, $condition);
|
||||
return $this->success($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除导出记录
|
||||
* @param $condition
|
||||
* @return array
|
||||
*/
|
||||
public function deleteExport($condition)
|
||||
{
|
||||
// 先查询数据
|
||||
$list = model('stock_goods_export')->getList($condition, '*');
|
||||
if (!empty($list)) {
|
||||
foreach ($list as $k => $v) {
|
||||
if (file_exists($v[ 'path' ])) {
|
||||
// 删除物理文件路径
|
||||
if (!unlink($v[ 'path' ])) {
|
||||
// 失败
|
||||
} else {
|
||||
// 成功
|
||||
}
|
||||
}
|
||||
}
|
||||
$res = model('stock_goods_export')->delete($condition);
|
||||
}
|
||||
|
||||
return $this->success($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导出记录
|
||||
* @param $condition
|
||||
* @param string $field
|
||||
* @param string $order
|
||||
* @return array
|
||||
*/
|
||||
public function getExport($condition, $field = '*', $order = '')
|
||||
{
|
||||
$list = model('stock_goods_export')->getList($condition, $field, $order);
|
||||
return $this->success($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出记录
|
||||
* @param array $condition
|
||||
* @param int $page
|
||||
* @param int $page_size
|
||||
* @param string $order
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getExportPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '*')
|
||||
{
|
||||
$list = model('stock_goods_export')->pageList($condition, $field, $order, $page, $page_size);
|
||||
return $this->success($list);
|
||||
}
|
||||
}
|
||||
67
addon/stock/model/stock/Import.php
Executable file
67
addon/stock/model/stock/Import.php
Executable file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\model\stock;
|
||||
|
||||
use app\model\BaseModel;
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* 导入
|
||||
* @author Administrator
|
||||
*/
|
||||
class Import extends BaseModel
|
||||
{
|
||||
|
||||
/**
|
||||
* 单据导入
|
||||
* @param $path
|
||||
* @param $type
|
||||
*/
|
||||
public function import($path, $type)
|
||||
{
|
||||
|
||||
$PHPReader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
|
||||
|
||||
//载入文件
|
||||
$PHPExcel = $PHPReader->load($path);
|
||||
|
||||
//获取表中的第一个工作表,如果要获取第二个,把0改为1,依次类推
|
||||
$currentSheet = $PHPExcel->getSheet(0);
|
||||
|
||||
//获取总行数
|
||||
$allRow = $currentSheet->getHighestRow();
|
||||
|
||||
$time = $PHPExcel->getActiveSheet()->getCell('A2')->getValue();
|
||||
$time = trim(str_replace('入库时间:', '', $time));
|
||||
$time = $time ? date_to_time($time) : time();
|
||||
|
||||
$document_no = $PHPExcel->getActiveSheet()->getCell('C2')->getValue();
|
||||
$document_no = trim(str_replace('编号:', '', $document_no));
|
||||
|
||||
$remark = $PHPExcel->getActiveSheet()->getCell('A3')->getValue();
|
||||
$remark = trim(str_replace('备注:', '', $remark));
|
||||
|
||||
dump($time, $document_no, $remark);
|
||||
|
||||
dd($allRow);
|
||||
|
||||
|
||||
// switch ($type){
|
||||
// case 'PURCHASE'://采购入库单
|
||||
//
|
||||
//
|
||||
// break;
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
798
addon/stock/model/stock/Inventory.php
Executable file
798
addon/stock/model/stock/Inventory.php
Executable file
@@ -0,0 +1,798 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\model\stock;
|
||||
|
||||
|
||||
use app\model\store\Store;
|
||||
use app\model\BaseModel;
|
||||
use app\model\storegoods\StoreGoods;
|
||||
use think\facade\Log;
|
||||
|
||||
/**
|
||||
* 盘点
|
||||
* Class Inventory
|
||||
* @package addon\stock\model\stock
|
||||
*/
|
||||
class Inventory extends BaseModel
|
||||
{
|
||||
|
||||
const AUDIT = 1; // 待审核
|
||||
|
||||
const REFUSE = -1;// 审核被拒绝
|
||||
|
||||
const AUDITED = 2; // 审核通过
|
||||
|
||||
public $status = [
|
||||
|
||||
self::AUDIT => [
|
||||
'status' => self::AUDIT,
|
||||
'name' => '待审核'
|
||||
],
|
||||
self::AUDITED => [
|
||||
'status' => self::AUDITED,
|
||||
'name' => '已审核'
|
||||
],
|
||||
self::REFUSE => [
|
||||
'status' => self::REFUSE,
|
||||
'name' => '已拒绝'
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* 获取审核状态
|
||||
* @return array
|
||||
*/
|
||||
public function getStatus()
|
||||
{
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
public function inventoryNo()
|
||||
{
|
||||
return 'PD' . date('ymdhis', time()) . rand(1111, 9999);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加盘点单
|
||||
* @param $params
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function addInventory($params)
|
||||
{
|
||||
$site_id = $params[ 'site_id' ];
|
||||
$store_id = $params[ 'store_id' ];
|
||||
//是否限制只能有一个盘点单据
|
||||
$is_limit = $params['is_limit'] ?? true;
|
||||
if($is_limit){
|
||||
//同商品同时只能存在一个盘点单据
|
||||
$count = model('stock_inventory')->getCount([
|
||||
[ 'store_id', '=', $store_id ],
|
||||
[ 'site_id', '=', $site_id ],
|
||||
[ 'status', '=', self::AUDIT ]
|
||||
]);
|
||||
if ($count > 0) {
|
||||
return $this->error([], '一段时间内只能存在一个待审核的盘点单据');
|
||||
}
|
||||
}
|
||||
|
||||
model('stock_inventory')->startTrans();
|
||||
try {
|
||||
$sku_list = $params[ 'sku_list' ];
|
||||
$user_info = $params[ 'user_info' ];
|
||||
$inventory_no = isset($params['inventory_no']) && $params['inventory_no'] ? $params['inventory_no'] : $this->inventoryNo();
|
||||
|
||||
$count = model('stock_inventory')->getCount([ ['inventory_no', '=', $inventory_no] ]);
|
||||
if($count > 0) return $this->error([], '录入失败,单号重复');
|
||||
|
||||
//查询门店名称信息
|
||||
$store_model = new Store();
|
||||
$store_condition = [
|
||||
[ 'store_id', '=', $store_id ]
|
||||
];
|
||||
$store_info = $store_model->getStoreInfo($store_condition, 'store_name')[ 'data' ] ?? [];
|
||||
if (empty($store_info)) {
|
||||
model('stock_inventory')->rollback();
|
||||
return $this->success([], '找不到所选的门店');
|
||||
}
|
||||
$store_name = $store_info[ 'store_name' ];
|
||||
$common_data = [
|
||||
'site_id' => $site_id,
|
||||
'create_time' => time(),
|
||||
'store_id' => $store_id
|
||||
];
|
||||
$data = [
|
||||
'operater' => $user_info[ 'uid' ] ?? 0,
|
||||
'operater_name' => $user_info[ 'username' ] ?? '系统',
|
||||
'create_time' => time(),
|
||||
'inventory_no' => $inventory_no,
|
||||
'store_name' => $store_name,
|
||||
'remark' => $params[ 'remark' ] ?? '',
|
||||
'action_time' => $params[ 'action_time' ] ?? time(),
|
||||
'status' => self::AUDIT
|
||||
];
|
||||
//盘点单据
|
||||
$inventory_data = array_merge($data, $common_data);
|
||||
$inventory_id = model('stock_inventory')->add($inventory_data);
|
||||
$common_data[ 'inventory_id' ] = $inventory_id;
|
||||
$temp_goods_list = model('goods_sku')->getList(
|
||||
[
|
||||
['gs.sku_id', 'in', array_column($sku_list, 'goods_sku_id')]
|
||||
],
|
||||
'gs.sku_id,gs.goods_id,gs.sku_name,gs.sku_no,gs.sku_image,gs.spec_name,
|
||||
sgs.real_stock',
|
||||
'',
|
||||
'gs',
|
||||
[
|
||||
[
|
||||
'store_goods_sku sgs',
|
||||
'gs.sku_id = sgs.sku_id and sgs.store_id = '.$store_id,
|
||||
'left'
|
||||
]
|
||||
]
|
||||
);
|
||||
$temp_goods_list = array_column($temp_goods_list, null, 'sku_id');
|
||||
$insert_data = [];
|
||||
foreach ($sku_list as $k => $goods_sku) {
|
||||
$goods_sku_id = $goods_sku[ 'goods_sku_id' ];
|
||||
$goods_num = numberFormat($goods_sku[ 'goods_num' ]);
|
||||
$item_temp_item = $temp_goods_list[$goods_sku_id] ?? [];
|
||||
$goods_remark = '';
|
||||
//具体业务尚未调试,表结构不一致
|
||||
// $goods_sku_info = model('goods_sku')->getInfo([ [ 'sku_id', '=', $goods_sku_id ] ], 'sku_id,goods_id,sku_name,sku_no,sku_image,spec_name');
|
||||
// $goods_sku_data_info = model('store_goods_sku')->getInfo([ [ 'sku_id', '=', $goods_sku_id ], [ 'store_id', '=', $store_id ] ], '*');
|
||||
$goods_stock = $item_temp_item[ 'real_stock' ] ?? 0;
|
||||
$goods_sku_data = [];
|
||||
$goods_sku_data[ 'inventory_num' ] = $goods_num;
|
||||
$goods_sku_data[ 'inventory_remark' ] = $goods_remark;
|
||||
$goods_sku_data[ 'goods_id' ] = $item_temp_item[ 'goods_id' ];
|
||||
$goods_sku_data[ 'goods_sku_id' ] = $goods_sku_id;
|
||||
$goods_sku_data[ 'goods_sku_name' ] = $item_temp_item[ 'sku_name' ];
|
||||
$goods_sku_data[ 'goods_sku_no' ] = $item_temp_item[ 'sku_no' ];
|
||||
$goods_sku_data[ 'goods_sku_spec' ] = $item_temp_item[ 'spec_name' ];
|
||||
$goods_sku_data[ 'goods_img' ] = $item_temp_item[ 'sku_image' ];
|
||||
$goods_sku_data[ 'stock' ] = numberFormat($goods_stock);
|
||||
$insert_data[] = array_merge($goods_sku_data, $common_data);
|
||||
}
|
||||
model('stock_inventory_goods')->addList($insert_data);
|
||||
$is_auto_audit = $params[ 'is_auto_audit' ] ?? true;
|
||||
if ($is_auto_audit) {
|
||||
//主动调用审核
|
||||
$inventory_params = [
|
||||
'inventory_id' => $inventory_id,
|
||||
'site_id' => $site_id,
|
||||
'user_info' => $user_info
|
||||
];
|
||||
$audit_result = $this->audit($inventory_params);
|
||||
if ($audit_result[ 'code' ] < 0) {
|
||||
model('stock_inventory')->rollback();
|
||||
return $audit_result;
|
||||
}
|
||||
} else {
|
||||
$stock_model = new Stock();
|
||||
$stock_config = $stock_model->getStockConfig($site_id)[ 'data' ][ 'value' ];
|
||||
$is_audit = $stock_config[ 'is_audit' ];
|
||||
if (!$is_audit) {
|
||||
//主动调用审核
|
||||
$inventory_params = [
|
||||
'inventory_id' => $inventory_id,
|
||||
'site_id' => $site_id,
|
||||
'user_info' => $user_info
|
||||
];
|
||||
$audit_result = $this->audit($inventory_params);
|
||||
if ($audit_result[ 'code' ] < 0) {
|
||||
model('stock_inventory')->rollback();
|
||||
return $audit_result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model('stock_inventory')->commit();
|
||||
return $this->success();
|
||||
} catch (\Exception $e) {
|
||||
model('stock_inventory')->rollback();
|
||||
return $this->error($e->getMessage() . $e->getFile() . $e->getLine());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过审核
|
||||
* @param $params
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function audit($params)
|
||||
{
|
||||
$inventory_id = $params[ 'inventory_id' ];
|
||||
$site_id = $params[ 'site_id' ];
|
||||
$user_info = $params[ 'user_info' ];
|
||||
$condition = [
|
||||
[ 'inventory_id', '=', $inventory_id ],
|
||||
[ 'site_id', '=', $site_id ]
|
||||
];
|
||||
$info = model('stock_inventory')->getInfo($condition);
|
||||
if (empty($info))
|
||||
return $this->error([], '找不到可审核的单据');
|
||||
|
||||
if ($info[ 'status' ] == self::AUDITED)
|
||||
return $this->error([], '当前单据已审核');
|
||||
$data = [
|
||||
'status' => self::AUDITED,
|
||||
'audit_time' => time(),
|
||||
'verifier' => $user_info[ 'uid' ] ?? 0,//审核人
|
||||
'verifier_name' => $user_info[ 'username' ] ?? '系统'
|
||||
];
|
||||
model('stock_inventory')->update($data, $condition);
|
||||
$store_id = $info[ 'store_id' ];
|
||||
return $this->complete([ 'inventory_id' => $inventory_id, 'site_id' => $site_id, 'store_id' => $store_id, 'user_info' => $user_info ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 单据通过审核
|
||||
* @param $params
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function complete($params)
|
||||
{
|
||||
$inventory_id = $params[ 'inventory_id' ];
|
||||
$user_info = $params[ 'user_info' ] ?? [];
|
||||
$site_id = $params[ 'site_id' ];
|
||||
$condition = [
|
||||
[ 'inventory_id', '=', $inventory_id ],
|
||||
[ 'site_id', '=', $site_id ]
|
||||
];
|
||||
$info = model('stock_inventory')->getInfo($condition);
|
||||
if (empty($info))
|
||||
return $this->error([], '找不到可审核的单据');
|
||||
|
||||
$stock_inventory_goods_list = model('stock_inventory_goods')->getList($condition, '*');
|
||||
if (empty($stock_inventory_goods_list))
|
||||
return $this->error([], '找不到可审核的单据');
|
||||
|
||||
$store_id = $info[ 'store_id' ];
|
||||
$stat_data = $this->stat([ 'inventory_id' => $inventory_id, 'store_id' => $store_id ])[ 'data' ] ?? [];
|
||||
|
||||
$data = [
|
||||
'kinds_num' => $stat_data[ 'kinds_num' ],
|
||||
'kinds_profit_num' => $stat_data[ 'kinds_profit_num' ],
|
||||
'kinds_loss_num' => $stat_data[ 'kinds_loss_num' ],
|
||||
'kinds_even_num' => $stat_data[ 'kinds_even_num' ],
|
||||
'num' => $stat_data[ 'num' ],
|
||||
'profit_num' => $stat_data[ 'profit_num' ],
|
||||
'loss_num' => $stat_data[ 'loss_num' ],
|
||||
'even_num' => $stat_data[ 'even_num' ],
|
||||
'profitloss_num' => $stat_data[ 'profitloss_num' ],
|
||||
'inventory_cost_money' => $stat_data[ 'inventory_cost_money' ],
|
||||
'profitloss_sale_money' => $stat_data[ 'profitloss_sale_money' ],
|
||||
];
|
||||
model('stock_inventory')->update($data, $condition);
|
||||
$inventory_goods_list = $stat_data[ 'inventory_goods_list' ] ?? [];
|
||||
|
||||
$store_goods_model = new StoreGoods();
|
||||
$store_goods_sku_list_condition = [
|
||||
[ 'sgs.sku_id', 'in', array_column($inventory_goods_list, 'goods_sku_id') ],
|
||||
[ 'sgs.store_id', '=', $store_id ]
|
||||
];
|
||||
$store_sku_list = $store_goods_model->getStoreGoodsSkuList($store_goods_sku_list_condition, 'sgs.*, gs.sku_name, gs.unit', '', 'sgs',
|
||||
[
|
||||
[
|
||||
'goods_sku gs',
|
||||
'gs.sku_id = sgs.sku_id',
|
||||
'left'
|
||||
]
|
||||
]
|
||||
)['data'] ?? [];
|
||||
$store_sku_list_column = array_column($store_sku_list, null, 'sku_id');
|
||||
$document = new Document();
|
||||
$input_array = [];
|
||||
$output_array = [];
|
||||
foreach ($inventory_goods_list as $v) {
|
||||
$item_sku_id = $v[ 'goods_sku_id' ];
|
||||
$item_goods_id = $v[ 'goods_id' ];
|
||||
$item_condition = [
|
||||
[ 'inventory_id', '=', $inventory_id ],
|
||||
[ 'goods_sku_id', '=', $item_sku_id ]
|
||||
];
|
||||
$item_data = [
|
||||
'inventory_id' => $inventory_id,
|
||||
'goods_id' => $v[ 'goods_id' ],
|
||||
'goods_sku_id' => $v[ 'goods_sku_id' ],
|
||||
'stock' => $v[ 'stock' ],
|
||||
'inventory_num' => $v[ 'inventory_num' ],
|
||||
'inventory_remark' => $v[ 'inventory_remark' ] ?? '',
|
||||
'profitloss_num' => $v[ 'profitloss_num' ],
|
||||
'inventory_cost_money' => $v[ 'inventory_cost_money' ],
|
||||
'profitloss_sale_money' => $v[ 'profitloss_sale_money' ],
|
||||
];
|
||||
model('stock_inventory_goods')->update($item_data, $item_condition);
|
||||
|
||||
$store_sku_info = $store_sku_list_column[$item_sku_id] ?? [];
|
||||
$store_sku_stock = $store_sku_info[ 'real_stock' ] ?? 0;
|
||||
$inventory_num = $v[ 'inventory_num' ];
|
||||
$item_price = $store_sku_info[ 'cost_price' ] ?? 0;
|
||||
$item_unit = $store_sku_info[ 'unit' ] ?? '件';
|
||||
$diff = abs($inventory_num - $store_sku_stock);
|
||||
if ($diff != 0) {
|
||||
if ($inventory_num > $store_sku_stock) {
|
||||
$input_array[] = [
|
||||
'goods_id' => $item_goods_id,
|
||||
'goods_sku_id' => $item_sku_id,
|
||||
'goods_sku_name' => $store_sku_info[ 'sku_name' ],
|
||||
'goods_unit' => $item_unit,
|
||||
'goods_num' => $diff,
|
||||
'goods_price' => $item_price,
|
||||
];
|
||||
} else if ($inventory_num < $store_sku_stock) {
|
||||
$output_array[] = [
|
||||
'goods_id' => $item_goods_id,
|
||||
'goods_sku_id' => $item_sku_id,
|
||||
'goods_sku_name' => $store_sku_info[ 'sku_name' ],
|
||||
'goods_unit' => $item_unit,
|
||||
'goods_num' => $diff,
|
||||
'goods_price' => $item_price,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
$document_params = [
|
||||
'inventory_id' => $inventory_id,
|
||||
'store_id' => $store_id,
|
||||
'user_info' => $user_info,
|
||||
'site_id' => $site_id,
|
||||
'remark' => $info['remark'],
|
||||
];
|
||||
|
||||
if (!empty($input_array)) {
|
||||
$document_params[ 'document_type' ] = 'PANYING';
|
||||
$document_params[ 'goods_sku_list' ] = $input_array;
|
||||
$result = $document->addDocument($document_params);
|
||||
}
|
||||
if (!empty($output_array)) {
|
||||
$document_params[ 'document_type' ] = 'PANKUI';
|
||||
$document_params[ 'goods_sku_list' ] = $output_array;
|
||||
$document_params[ 'is_out_stock' ] = 1;
|
||||
$result = $document->addDocument($document_params);
|
||||
}
|
||||
|
||||
if (isset($result) && $result[ 'code' ] < 0) {
|
||||
return $result;
|
||||
}
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据统计以及整理
|
||||
* @param $params
|
||||
* @return array
|
||||
*/
|
||||
public function stat($params)
|
||||
{
|
||||
$inventory_id = $params[ 'inventory_id' ];
|
||||
$condition = [
|
||||
[ 'inventory_id', '=', $inventory_id ]
|
||||
];
|
||||
$info = model('stock_inventory')->getInfo($condition);
|
||||
$store_id = $info[ 'store_id' ];
|
||||
$kinds_num = $kinds_profit_num = $kinds_loss_num = $kinds_even_num = $num = $profit_num = $loss_num = $even_num = $profitloss_num = $inventory_cost_money = $profitloss_sale_money = 0;
|
||||
|
||||
$stock_inventory_goods_list = model('stock_inventory_goods')->getList($condition, '*');
|
||||
|
||||
$temp_goods_sku_list = model('goods_sku')->getList(
|
||||
[
|
||||
['gs.sku_id', 'in', array_column($stock_inventory_goods_list, 'goods_sku_id')]
|
||||
],
|
||||
'gs.sku_id, gs.sku_name, gs.sku_no, gs.unit, sgs.price, sgs.cost_price, sgs.real_stock',
|
||||
'',
|
||||
'gs',
|
||||
[
|
||||
[
|
||||
'store_goods_sku sgs',
|
||||
'gs.sku_id = sgs.sku_id and sgs.store_id = '.$store_id,
|
||||
'left'
|
||||
]
|
||||
]
|
||||
);
|
||||
$goods_list_column = array_column($temp_goods_sku_list, null, 'sku_id');
|
||||
$store_goods_model = new StoreGoods();
|
||||
$inventory_goods_list = [];
|
||||
foreach ($stock_inventory_goods_list as $k => $v) {
|
||||
$kinds_num++;
|
||||
$sku_id = $v[ 'goods_sku_id' ];
|
||||
$goods_id = $v[ 'goods_id' ];
|
||||
$store_sku_condition = [
|
||||
[ 'store_id', '=', $store_id ],
|
||||
[ 'sku_id', '=', $sku_id ]
|
||||
];
|
||||
|
||||
$v[ 'stock' ] = numberFormat($v[ 'stock' ]);
|
||||
$v[ 'inventory_num' ] = numberFormat($v[ 'inventory_num' ]);
|
||||
$v[ 'profitloss_num' ] = numberFormat($v[ 'profitloss_num' ]);
|
||||
$item_info = $goods_list_column[$sku_id] ?? [];
|
||||
$item_price = $item_info[ 'price' ] ?? 0;//销售价
|
||||
$item_cost_price = $item_info[ 'cost_price' ] ?? 0;// 成本价
|
||||
$item_stock = $item_info[ 'real_stock' ] ?? 0;//实物库存
|
||||
$item_total_sale_money = $item_price * $item_stock;//总销售价
|
||||
|
||||
$inventory_num = $v[ 'inventory_num' ];//盘点数量
|
||||
$item_inventory_cost_money = $inventory_num * $item_cost_price;
|
||||
$inventory_cost_money += $item_inventory_cost_money;//盘点总成本价
|
||||
$ing_total_sale_money = $inventory_num * $item_price;//盘点总销售价
|
||||
$num += $inventory_num;//盘点总数
|
||||
$item_profitloss_num = $inventory_num - $item_stock;
|
||||
$item_profitloss_sale_money = 0;
|
||||
if ($item_profitloss_num == 0) {//持平
|
||||
$kinds_even_num++;
|
||||
$even_num += abs($item_profitloss_num);
|
||||
} else if ($item_profitloss_num > 0) {//盘盈数
|
||||
$kinds_profit_num++;
|
||||
$profit_num += abs($item_profitloss_num);
|
||||
$item_profitloss_sale_money = $ing_total_sale_money - $item_total_sale_money;
|
||||
} else {//盘亏数
|
||||
$kinds_loss_num++;
|
||||
$loss_num += abs($item_profitloss_num);
|
||||
}
|
||||
$profitloss_num += $item_profitloss_num;
|
||||
$profitloss_sale_money += $item_profitloss_sale_money;
|
||||
|
||||
$inventory_goods_list[ $sku_id ] = [
|
||||
'goods_id' => $goods_id,
|
||||
'goods_sku_id' => $sku_id,
|
||||
'goods_sku_name' => $item_info[ 'sku_name' ],
|
||||
'goods_sku_no' => $item_info[ 'sku_no' ],
|
||||
'goods_unit' => $item_info[ 'unit' ],
|
||||
'stock' => numberFormat($item_stock),
|
||||
'inventory_num' => numberFormat($inventory_num),
|
||||
'profitloss_num' => numberFormat($item_profitloss_num),
|
||||
'inventory_cost_money' => $item_inventory_cost_money,
|
||||
'profitloss_sale_money' => $item_profitloss_sale_money,
|
||||
];
|
||||
}
|
||||
$data = [
|
||||
'kinds_num' => $kinds_num,
|
||||
'kinds_profit_num' => $kinds_profit_num,
|
||||
'kinds_loss_num' => $kinds_loss_num,
|
||||
'kinds_even_num' => $kinds_even_num,
|
||||
'num' => $num,
|
||||
'profit_num' => $profit_num,
|
||||
'loss_num' => $loss_num,
|
||||
'even_num' => $even_num,
|
||||
'profitloss_num' => $profitloss_num,
|
||||
'inventory_cost_money' => $inventory_cost_money,
|
||||
'profitloss_sale_money' => $profitloss_sale_money,
|
||||
'inventory_goods_list' => $inventory_goods_list
|
||||
];
|
||||
|
||||
return $this->success($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 库存盘点单列表
|
||||
* @param array $condition
|
||||
* @param int $page
|
||||
* @param int $page_size
|
||||
* @param string $order
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getInventoryPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '*')
|
||||
{
|
||||
$res = model('stock_inventory')->pageList($condition, $field, $order, $page, $page_size);
|
||||
foreach ($res[ 'list' ] as $k => $v) {
|
||||
if (isset($v[ 'num' ])) {
|
||||
$res[ 'list' ][ $k ][ 'num' ] = numberFormat($res[ 'list' ][ $k ][ 'num' ]);
|
||||
}
|
||||
if (isset($v[ 'profit_num' ])) {
|
||||
$res[ 'list' ][ $k ][ 'profit_num' ] = numberFormat($res[ 'list' ][ $k ][ 'profit_num' ]);
|
||||
}
|
||||
if (isset($v[ 'loss_num' ])) {
|
||||
$res[ 'list' ][ $k ][ 'loss_num' ] = numberFormat($res[ 'list' ][ $k ][ 'loss_num' ]);
|
||||
}
|
||||
if (isset($v[ 'even_num' ])) {
|
||||
$res[ 'list' ][ $k ][ 'even_num' ] = numberFormat($res[ 'list' ][ $k ][ 'even_num' ]);
|
||||
}
|
||||
if (isset($v[ 'profitloss_num' ])) {
|
||||
$res[ 'list' ][ $k ][ 'profitloss_num' ] = numberFormat($res[ 'list' ][ $k ][ 'profitloss_num' ]);
|
||||
}
|
||||
if (isset($v[ 'status' ])) {
|
||||
$res[ 'list' ][ $k ][ 'status_name' ] = $this->status[ $v[ 'status' ] ][ 'name' ];
|
||||
}
|
||||
}
|
||||
return $this->success($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 单据详情
|
||||
* @param array $condition
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getInventoryInfo($condition = [], $field = '*')
|
||||
{
|
||||
$inventory_info = model('stock_inventory')->getInfo($condition, $field);
|
||||
if (!empty($inventory_info)) {
|
||||
|
||||
if (isset($inventory_info[ 'status' ])) {
|
||||
$inventory_info[ 'status_name' ] = $this->status[ $inventory_info[ 'status' ] ][ 'name' ];
|
||||
}
|
||||
|
||||
if (isset($inventory_info[ 'num' ])) {
|
||||
$inventory_info[ 'num' ] = numberFormat($inventory_info[ 'num' ]);
|
||||
}
|
||||
if (isset($inventory_info[ 'profit_num' ])) {
|
||||
$inventory_info[ 'profit_num' ] = numberFormat($inventory_info[ 'profit_num' ]);
|
||||
}
|
||||
if (isset($inventory_info[ 'loss_num' ])) {
|
||||
$inventory_info[ 'loss_num' ] = numberFormat($inventory_info[ 'loss_num' ]);
|
||||
}
|
||||
if (isset($inventory_info[ 'even_num' ])) {
|
||||
$inventory_info[ 'even_num' ] = numberFormat($inventory_info[ 'even_num' ]);
|
||||
}
|
||||
if (isset($inventory_info[ 'profitloss_num' ])) {
|
||||
$inventory_info[ 'profitloss_num' ] = numberFormat($inventory_info[ 'profitloss_num' ]);
|
||||
}
|
||||
|
||||
//单据产品项
|
||||
$inventory_goods_list = model('stock_inventory_goods')->getList([
|
||||
[ 'inventory_id', '=', $inventory_info[ 'inventory_id' ] ]
|
||||
]);
|
||||
foreach ($inventory_goods_list as $k => $v) {
|
||||
$inventory_goods_list[ $k ][ 'stock' ] = numberFormat($v[ 'stock' ]);
|
||||
$inventory_goods_list[ $k ][ 'inventory_num' ] = numberFormat($inventory_goods_list[ $k ][ 'inventory_num' ]);
|
||||
$inventory_goods_list[ $k ][ 'profitloss_num' ] = numberFormat($inventory_goods_list[ $k ][ 'profitloss_num' ]);
|
||||
}
|
||||
$inventory_info[ 'goods_sku_list_array' ] = $inventory_goods_list;
|
||||
$inventory_info[ 'goods_count' ] = count($inventory_info[ 'goods_sku_list_array' ]);
|
||||
$inventory_info[ 'create_time' ] = date('Y-m-d H:i:s', $inventory_info[ 'create_time' ]);
|
||||
if ($inventory_info[ 'audit_time' ]) $inventory_info[ 'audit_time' ] = date('Y-m-d H:i:s', $inventory_info[ 'audit_time' ]);
|
||||
if ($inventory_info[ 'action_time' ]) $inventory_info[ 'action_time' ] = date('Y-m-d H:i:s', $inventory_info[ 'action_time' ]);
|
||||
}
|
||||
return $this->success($inventory_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取编辑单据数据
|
||||
* @param array $condition
|
||||
* @return array
|
||||
*/
|
||||
public function getInventoryEditData($condition = [])
|
||||
{
|
||||
$field = 'inventory_id, store_id,inventory_no,action_time,remark';
|
||||
$inventory_info = model('stock_inventory')->getInfo($condition, $field);
|
||||
if (!empty($inventory_info)) {
|
||||
$goods_field = 'gs.sku_id,gs.sku_image,gs.sku_name,gs.unit,gs.sku_no,
|
||||
sgs.stock,sgs.real_stock,sgs.price,sgs.cost_price,
|
||||
ig.inventory_num as goods_num,ig.goods_sku_id';
|
||||
|
||||
$join = [
|
||||
[ 'goods_sku gs', 'ig.goods_sku_id = gs.sku_id', 'left' ],
|
||||
[
|
||||
'store_goods_sku sgs',
|
||||
'sgs.sku_id = gs.sku_id and (sgs.store_id is null or sgs.store_id = ' . $inventory_info[ 'store_id' ] . ')',
|
||||
'left'
|
||||
]
|
||||
];
|
||||
|
||||
$inventory_goods_list = model('stock_inventory_goods')->getList([
|
||||
[ 'inventory_id', '=', $inventory_info[ 'inventory_id' ] ]
|
||||
], $goods_field, '', 'ig', $join);
|
||||
foreach ($inventory_goods_list as $k => $v) {
|
||||
$inventory_goods_list[ $k ][ 'stock' ] = numberFormat($v[ 'stock' ]);
|
||||
$inventory_goods_list[ $k ][ 'goods_num' ] = numberFormat($inventory_goods_list[ $k ][ 'goods_num' ]);
|
||||
}
|
||||
$inventory_info[ 'goods_list' ] = array_column($inventory_goods_list, null, 'goods_sku_id');
|
||||
}
|
||||
return $this->success($inventory_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拒绝审核
|
||||
* @param $params
|
||||
* @return array
|
||||
*/
|
||||
public function refuse($params)
|
||||
{
|
||||
$inventory_id = $params[ 'inventory_id' ];
|
||||
$site_id = $params[ 'site_id' ];
|
||||
$user_info = $params[ 'user_info' ];
|
||||
$condition = [
|
||||
[ 'inventory_id', '=', $inventory_id ],
|
||||
[ 'site_id', '=', $site_id ]
|
||||
];
|
||||
$info = model('stock_inventory')->getInfo($condition);
|
||||
if (empty($info))
|
||||
return $this->error([], '找不到可审核的单据');
|
||||
|
||||
if ($info[ 'status' ] == self::AUDITED)
|
||||
return $this->error([], '当前单据已审核');
|
||||
$data = [
|
||||
'status' => self::REFUSE,
|
||||
'audit_time' => time(),
|
||||
'refuse_reason' => $params[ 'refuse_reason' ],
|
||||
'verifier' => $user_info[ 'uid' ] ?? 0,//审核人
|
||||
'verifier_name' => $user_info[ 'username' ] ?? '系统'
|
||||
];
|
||||
model('stock_inventory')->update($data, $condition);
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除单据
|
||||
* @param $params
|
||||
* @return array
|
||||
*/
|
||||
public function delete($params)
|
||||
{
|
||||
$site_id = $params[ 'site_id' ];
|
||||
$inventory_id = $params[ 'inventory_id' ];
|
||||
$user_info = $params[ 'user_info' ];
|
||||
$store_id = $params[ 'store_id' ] ?? 0;
|
||||
//查询单据
|
||||
$condition = [
|
||||
[ 'inventory_id', '=', $inventory_id ],
|
||||
[ 'site_id', '=', $site_id ]
|
||||
];
|
||||
if ($store_id > 0) {
|
||||
$condition[] = [ 'store_id', '=', $store_id ];
|
||||
}
|
||||
$info = model('stock_inventory')->getInfo($condition);
|
||||
if (empty($info)) {
|
||||
return $this->error([], '找不到盘点单据');
|
||||
}
|
||||
//被拒绝也可以删除
|
||||
if ($info[ 'status' ] == self::AUDITED) {
|
||||
return $this->error('已审核的单据不能删除');
|
||||
}
|
||||
if ($info[ 'operater' ] != $user_info[ 'uid' ]) {
|
||||
return $this->error('只有单据创建者可以删除单据');
|
||||
}
|
||||
model('stock_inventory')->delete($condition);
|
||||
model('stock_inventory_goods')->delete($condition);
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑盘点单
|
||||
* @param $params
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function editInventory($params)
|
||||
{
|
||||
$inventory_id = $params[ 'inventory_id' ];
|
||||
$site_id = $params[ 'site_id' ];
|
||||
$store_id = $params[ 'store_id' ];
|
||||
$user_info = $params[ 'user_info' ];
|
||||
//同商品同时只能存在一个盘点单据
|
||||
$info = model('stock_inventory')->getInfo([
|
||||
[ 'site_id', '=', $site_id ],
|
||||
[ 'inventory_id', '=', $inventory_id ],
|
||||
]);
|
||||
|
||||
if (empty($info)) {
|
||||
return $this->error([], '找不到盘点单据');
|
||||
}
|
||||
|
||||
if ($info[ 'status' ] == self::AUDITED) {
|
||||
return $this->error('已审核的单据不能编辑');
|
||||
}
|
||||
if ($info[ 'operater' ] != $user_info[ 'uid' ]) {
|
||||
return $this->error('只有单据创建者可以编辑单据');
|
||||
}
|
||||
|
||||
$inventory_no = isset($params['inventory_no']) && $params['inventory_no'] ? $params['inventory_no'] : $this->inventoryNo();
|
||||
|
||||
$count = model('stock_inventory')->getCount([ ['inventory_no', '=', $inventory_no], ['inventory_id', '<>', $inventory_id] ]);
|
||||
if($count > 0) return $this->error([], '录入失败,单号重复');
|
||||
|
||||
model('stock_inventory')->startTrans();
|
||||
try {
|
||||
$sku_list = $params[ 'sku_list' ];
|
||||
|
||||
//查询门店名称信息
|
||||
$store_model = new Store();
|
||||
$store_condition = [
|
||||
[ 'store_id', '=', $store_id ]
|
||||
];
|
||||
$store_info = $store_model->getStoreInfo($store_condition, 'store_name')[ 'data' ] ?? [];
|
||||
if (empty($store_info)) {
|
||||
model('stock_inventory')->rollback();
|
||||
return $this->success([], '找不到所选的门店');
|
||||
}
|
||||
$store_name = $store_info[ 'store_name' ];
|
||||
|
||||
$common_data = [
|
||||
'site_id' => $info[ 'site_id' ],
|
||||
'create_time' => $info[ 'create_time' ],
|
||||
'store_id' => $store_id
|
||||
];
|
||||
$data = [
|
||||
'remark' => $params[ 'remark' ] ?? '',
|
||||
'status' => self::AUDIT,
|
||||
'action_time' => $params[ 'action_time' ] ?? time(),
|
||||
'inventory_no' => $inventory_no,
|
||||
'store_name' => $store_name
|
||||
];
|
||||
//盘点单据
|
||||
$inventory_data = array_merge($data, $common_data);
|
||||
|
||||
$inventory_goods_condition = [
|
||||
[ 'site_id', '=', $site_id ],
|
||||
[ 'inventory_id', '=', $inventory_id ]
|
||||
];
|
||||
//编辑盘点单据
|
||||
model('stock_inventory')->update($inventory_data, $inventory_goods_condition);
|
||||
|
||||
$common_data[ 'inventory_id' ] = $inventory_id;
|
||||
|
||||
//删除原来的盘点商品单据
|
||||
model('stock_inventory_goods')->delete($inventory_goods_condition);
|
||||
foreach ($sku_list as $k => $goods_sku) {
|
||||
$goods_sku_id = $goods_sku[ 'goods_sku_id' ];
|
||||
$goods_num = numberFormat($goods_sku[ 'goods_num' ]);
|
||||
$goods_remark = '';
|
||||
//具体业务尚未调试,表结构不一致
|
||||
$goods_sku_info = model('goods_sku')->getInfo([ [ 'sku_id', '=', $goods_sku_id ] ], 'sku_id,goods_id,sku_name,sku_no,sku_image,spec_name');
|
||||
$goods_sku_data_info = model('store_goods_sku')->getInfo([ [ 'sku_id', '=', $goods_sku_id ], [ 'store_id', '=', $store_id ] ], '*');
|
||||
$goods_stock = $goods_sku_data_info[ 'real_stock' ] ?? 0;
|
||||
$goods_sku_data = [];
|
||||
$goods_sku_data[ 'inventory_num' ] = $goods_num;
|
||||
$goods_sku_data[ 'inventory_remark' ] = $goods_remark;
|
||||
$goods_sku_data[ 'goods_id' ] = $goods_sku_info[ 'goods_id' ];
|
||||
$goods_sku_data[ 'goods_sku_id' ] = $goods_sku_id;
|
||||
$goods_sku_data[ 'goods_sku_name' ] = $goods_sku_info[ 'sku_name' ];
|
||||
$goods_sku_data[ 'goods_sku_no' ] = $goods_sku_info[ 'sku_no' ];
|
||||
$goods_sku_data[ 'goods_sku_spec' ] = $goods_sku_info[ 'spec_name' ];
|
||||
$goods_sku_data[ 'goods_img' ] = $goods_sku_info[ 'sku_image' ];
|
||||
$goods_sku_data[ 'stock' ] = numberFormat($goods_stock);
|
||||
model('stock_inventory_goods')->add(array_merge($goods_sku_data, $common_data));
|
||||
}
|
||||
|
||||
$stock_model = new Stock();
|
||||
$stock_config = $stock_model->getStockConfig($site_id)[ 'data' ][ 'value' ];
|
||||
$is_audit = $stock_config[ 'is_audit' ];
|
||||
if (!$is_audit) {
|
||||
//主动调用审核
|
||||
$inventory_params = [
|
||||
'inventory_id' => $inventory_id,
|
||||
'site_id' => $site_id,
|
||||
'user_info' => $user_info
|
||||
];
|
||||
$audit_result = $this->audit($inventory_params);
|
||||
if ($audit_result[ 'code' ] < 0) {
|
||||
model('stock_inventory')->rollback();
|
||||
return $audit_result;
|
||||
}
|
||||
}
|
||||
model('stock_inventory')->commit();
|
||||
return $this->success();
|
||||
} catch (\Exception $e) {
|
||||
model('stock_inventory')->rollback();
|
||||
return $this->error($e->getMessage() . $e->getFile() . $e->getLine());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询商品盘点单据
|
||||
* @param $condition
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getInventoryGoodsInfo($condition, $field = '*')
|
||||
{
|
||||
//关联单据主表
|
||||
$join = [
|
||||
[ 'stock_inventory si', 'si.inventory_id = sig.inventory_id', 'inner' ],
|
||||
];
|
||||
$info = model('stock_inventory_goods')->getInfo($condition, $field, 'sig', $join);
|
||||
|
||||
return $this->success($info);
|
||||
|
||||
}
|
||||
}
|
||||
402
addon/stock/model/stock/Stock.php
Executable file
402
addon/stock/model/stock/Stock.php
Executable file
@@ -0,0 +1,402 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\model\stock;
|
||||
|
||||
|
||||
use addon\stock\dict\StockDict;
|
||||
use app\model\BaseModel;
|
||||
use app\model\store\Store;
|
||||
use app\model\system\Config as ConfigModel;
|
||||
|
||||
/**
|
||||
* 库存model
|
||||
*
|
||||
* @author Administrator
|
||||
*
|
||||
*/
|
||||
class Stock extends BaseModel
|
||||
{
|
||||
public $document_type_list = [
|
||||
'PURCHASE' => [
|
||||
'name' => '采购入库单',
|
||||
'type' => StockDict::input,
|
||||
'prefix' => 'CGRK',
|
||||
'key' => 'PURCHASE',
|
||||
],
|
||||
'REFUND' => [
|
||||
'name' => '退货入库单',
|
||||
'type' => StockDict::input,
|
||||
'prefix' => 'THRK',
|
||||
'key' => 'REFUND',
|
||||
],
|
||||
'OTHERRK' => [
|
||||
'name' => '其他入库单',
|
||||
'type' => StockDict::input,
|
||||
'prefix' => 'QTRK',
|
||||
'key' => 'OTHERRK',
|
||||
],
|
||||
'TRANSFORMRK' => [
|
||||
'name' => '其他入库单',
|
||||
'type' => StockDict::input,
|
||||
'prefix' => 'ZHRK',
|
||||
'key' => 'TRANSFORMRK',
|
||||
],
|
||||
'SEAILCK' => [
|
||||
'name' => '销售出库单',
|
||||
'type' => StockDict::output,
|
||||
'prefix' => 'XSCK',
|
||||
'key' => 'SEAILCK',
|
||||
],
|
||||
'OTHERCK' => [
|
||||
'name' => '其他出库单',
|
||||
'type' => StockDict::output,
|
||||
'prefix' => 'QTCK',
|
||||
'key' => 'OTHERCK',
|
||||
],
|
||||
'TRANSFORMCK' => [
|
||||
'name' => '转换出库单',
|
||||
'type' => StockDict::output,
|
||||
'prefix' => 'ZHCK',
|
||||
'key' => 'TRANSFORMCK',
|
||||
],
|
||||
'PDD' => [
|
||||
'name' => '盘点单',
|
||||
'type' => 'pandian',
|
||||
'prefix' => 'PDD',
|
||||
'key' => 'PDD',
|
||||
],
|
||||
'PANYING' => [
|
||||
'name' => '盘盈入库单',
|
||||
'type' => StockDict::input,
|
||||
'prefix' => 'PYRK',
|
||||
'key' => 'PANYING',
|
||||
],
|
||||
'PANKUI' => [
|
||||
'name' => '盘亏出库单',
|
||||
'type' => StockDict::output,
|
||||
'prefix' => 'PKCK',
|
||||
'key' => 'PANKUI',
|
||||
],
|
||||
'ALLOTIN' => [
|
||||
'name' => '调拨入库单',
|
||||
'type' => StockDict::input,
|
||||
'prefix' => 'DBRK',
|
||||
'key' => 'ALLOTIN',
|
||||
],
|
||||
'ALLOTPUT' => [
|
||||
'name' => '调拨出库单',
|
||||
'type' => StockDict::output,
|
||||
'prefix' => 'DBCK',
|
||||
'key' => 'ALLOTPUT',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* 设置库存
|
||||
* @param $params
|
||||
*/
|
||||
public function changeStock($params)
|
||||
{
|
||||
$user_info = $params[ 'user_info' ] ?? [];
|
||||
$site_id = $params[ 'site_id' ] ?? 1;
|
||||
|
||||
$store_id = $params[ 'store_id' ] ?? 0;
|
||||
if ($store_id == 0) {
|
||||
$store_model = new Store();
|
||||
$store_info = $store_model->getDefaultStore()[ 'data' ] ?? [];
|
||||
$store_id = $store_info[ 'store_id' ];
|
||||
}
|
||||
$key = $params[ 'key' ];
|
||||
$remark = $params[ 'remark' ] ?? '';
|
||||
$is_out_stock = $params[ 'is_out_stock' ] ?? 0;
|
||||
$time = $params[ 'time' ] ?? time();
|
||||
$document_model = new Document();
|
||||
if (!empty($params[ 'goods_sku_list' ])) {
|
||||
foreach ($params[ 'goods_sku_list' ] as $k => $v) {
|
||||
$params[ 'goods_sku_list' ][ $k ] = [
|
||||
'goods_sku_id' => $v[ 'sku_id' ],
|
||||
'goods_id' => $v[ 'goods_id' ] ?? 0,
|
||||
'goods_num' => $v[ 'num' ] ?? $v[ 'stock' ],
|
||||
'goods_price' => $v[ 'price' ] ?? 0
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$sku_id = $params[ 'sku_id' ] ?? 0;
|
||||
$goods_id = $params[ 'goods_id' ] ?? 0;
|
||||
$goods_num = $params[ 'num' ] ?? $params[ 'stock' ];
|
||||
$goods_price = $params[ 'price' ] ?? 0;
|
||||
}
|
||||
$goods_sku_list = $params[ 'goods_sku_list' ] ?? [
|
||||
[
|
||||
'goods_sku_id' => $sku_id,
|
||||
'goods_id' => $goods_id,
|
||||
'goods_num' => $goods_num,
|
||||
'goods_price' => $goods_price
|
||||
]
|
||||
];
|
||||
|
||||
$document_params = [
|
||||
'store_id' => $store_id,
|
||||
'site_id' => $site_id,
|
||||
'remark' => $remark,
|
||||
'goods_sku_list' => $goods_sku_list,
|
||||
'user_info' => $user_info,
|
||||
'time' => $time,
|
||||
'is_out_stock' => $is_out_stock
|
||||
];
|
||||
switch ( $key ) {
|
||||
case 'PURCHASE'://采购入库单
|
||||
$result = $document_model->addPurchase($document_params);
|
||||
break;
|
||||
case 'REFUND'://退货入库单
|
||||
$result = $document_model->addRefundInput($document_params);
|
||||
break;
|
||||
case 'OTHERRK'://其他入库单
|
||||
$result = $document_model->addOtherInput($document_params);
|
||||
break;
|
||||
case 'TRANSFORMRK'://转换入库单
|
||||
$result = $document_model->addTransformInput($document_params);
|
||||
break;
|
||||
case 'SEAILCK'://销售出库单
|
||||
$result = $document_model->addSell($document_params);
|
||||
break;
|
||||
case 'OTHERCK'://其他出库单
|
||||
$result = $document_model->addOtherOutput($document_params);
|
||||
break;
|
||||
case 'TRANSFORMCK'://转换出库单
|
||||
$result = $document_model->addTransformput($document_params);
|
||||
break;
|
||||
case 'PANYING'://盘盈入库单
|
||||
$result = $document_model->addDocument($document_params);
|
||||
break;
|
||||
case 'PANKUI'://盘亏出库单
|
||||
$result = $document_model->addDocument($document_params);
|
||||
break;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置商品库存(比对差值,得出)
|
||||
* @param $params
|
||||
* @return array
|
||||
*/
|
||||
public function setGoodsStock($params)
|
||||
{
|
||||
|
||||
$site_id = $params[ 'site_id' ];
|
||||
$remark = $params[ 'remark' ] ?? '';
|
||||
$store_id = $params[ 'store_id' ];
|
||||
|
||||
$goods_sku_list = $params[ 'goods_sku_list' ] ?? [];
|
||||
|
||||
//todo 这儿可以查询商品信息类型 来定义可能只有实物商品才需要出入库记录
|
||||
if (!empty($goods_sku_list)) {
|
||||
foreach ($goods_sku_list as $k => $v) {
|
||||
$sku_list[] = [
|
||||
'goods_sku_id' => $v[ 'sku_id' ],
|
||||
'goods_num' => $v[ 'stock' ],
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$goods_id = $params[ 'goods_id' ] ?? 0;//只要传递就必然是与sku_id匹配的
|
||||
$sku_id = $params[ 'sku_id' ];
|
||||
$stock = $params[ 'stock' ];//设置的新库存
|
||||
$sku_list = [
|
||||
[
|
||||
'goods_sku_id' => $sku_id,
|
||||
'goods_num' => $stock,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
//同步整理, 将要设置的销售库存转化为实际库存
|
||||
$sku_ids = array_column($sku_list, 'goods_sku_id');
|
||||
// $sku_key_list = array_column($sku_list, null, 'goods_sku_id');
|
||||
$sku_info_list = model('store_goods_sku')->getList([ [ 'sku_id', 'in', $sku_ids ], [ 'store_id', '=', $store_id ] ]);
|
||||
foreach ($sku_info_list as $k => $v) {
|
||||
$sku_info_list[ $k ][ 'stock' ] = numberFormat($v[ 'stock' ]);
|
||||
$sku_info_list[ $k ][ 'sale_num' ] = numberFormat($sku_info_list[ $k ][ 'sale_num' ]);
|
||||
$sku_info_list[ $k ][ 'real_stock' ] = numberFormat($sku_info_list[ $k ][ 'real_stock' ]);
|
||||
}
|
||||
$sku_info_column_list = array_column($sku_info_list, null, 'sku_id');
|
||||
$stock_sku_list = [];
|
||||
|
||||
foreach ($sku_list as $k => $item) {
|
||||
$item_sku_id = $item[ 'goods_sku_id' ];
|
||||
$temp_item = $sku_info_column_list[ $item_sku_id ] ?? [];
|
||||
$item_stock = $temp_item[ 'stock' ] ?? 0;
|
||||
$item_real_stock = $temp_item[ 'real_stock' ] ?? 0;
|
||||
if($item_stock > $item_real_stock){
|
||||
$item_stock = $item_real_stock;
|
||||
}
|
||||
if ($item_stock != $item_real_stock) {
|
||||
$item[ 'goods_num' ] = $item[ 'goods_num' ] + ( $item_real_stock - $item_stock );
|
||||
}
|
||||
$stock_sku_list[] = $item;
|
||||
}
|
||||
|
||||
$inventory_params = [
|
||||
'site_id' => $site_id,
|
||||
'store_id' => $store_id,
|
||||
'sku_list' => $stock_sku_list,
|
||||
'user_info' => $params[ 'user_info' ] ?? [],
|
||||
'remark' => $remark,
|
||||
'is_limit' => false
|
||||
];
|
||||
$inventory_model = new Inventory();
|
||||
return $inventory_model->addInventory($inventory_params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品sku列表
|
||||
* @param array $condition
|
||||
* @param string $field
|
||||
* @param string $order
|
||||
* @param int $store_id
|
||||
* @return array
|
||||
*/
|
||||
public function getStoreGoodsSkuList($condition = [], $field = '*', $order = 'gs.create_time desc', $store_id = 0)
|
||||
{
|
||||
$alias = 'gs';
|
||||
$join = [
|
||||
[ 'goods g', 'g.goods_id = gs.goods_id', 'left' ],
|
||||
[
|
||||
'store_goods_sku sgs',
|
||||
'sgs.sku_id = gs.sku_id and (sgs.store_id is null or sgs.store_id = ' . $store_id . ')',
|
||||
'left'
|
||||
]
|
||||
];
|
||||
$list = model('goods_sku')->getList($condition, $field, $order, $alias, $join, '', 15);
|
||||
foreach ($list as $k => $v) {
|
||||
if (isset($v[ 'goods_stock' ])) {
|
||||
$list[ $k ][ 'goods_stock' ] = numberFormat($v[ 'goods_stock' ]);
|
||||
}
|
||||
if (isset($v[ 'stock' ])) {
|
||||
$list[ $k ][ 'stock' ] = numberFormat($list[ $k ][ 'stock' ]);
|
||||
}
|
||||
if (isset($v[ 'sale_num' ])) {
|
||||
$list[ $k ][ 'sale_num' ] = numberFormat($list[ $k ][ 'sale_num' ]);
|
||||
}
|
||||
if (isset($v[ 'virtual_sale' ])) {
|
||||
$list[ $k ][ 'virtual_sale' ] = numberFormat($list[ $k ][ 'virtual_sale' ]);
|
||||
}
|
||||
|
||||
if (isset($v[ 'real_stock' ])) {
|
||||
$list[ $k ][ 'real_stock' ] = numberFormat($list[ $k ][ 'real_stock' ]);
|
||||
}
|
||||
}
|
||||
return $this->success($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置库存配置
|
||||
* @param $data
|
||||
* @param $site_id
|
||||
* @return array
|
||||
*/
|
||||
public function setStockConfig($data, $site_id)
|
||||
{
|
||||
$config = new ConfigModel();
|
||||
return $config->setConfig($data, '库存配置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'STOCK_CONFIG' ] ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取库存配置
|
||||
* @param $site_id
|
||||
* @return array
|
||||
*/
|
||||
public function getStockConfig($site_id)
|
||||
{
|
||||
$config = new ConfigModel();
|
||||
$res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'STOCK_CONFIG' ] ]);
|
||||
|
||||
if (empty($res[ 'data' ][ 'value' ])) {
|
||||
$res[ 'data' ][ 'value' ] = [
|
||||
'is_audit' => 0
|
||||
];
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询商品是否存在盘点单据
|
||||
* @param $goods_id
|
||||
* @param $site_id
|
||||
* @return array
|
||||
*/
|
||||
public function getGoodsIsHasStockRecords($goods_id, $site_id){
|
||||
$stock_model = new Stock();
|
||||
$stock_config = $stock_model->getStockConfig($site_id)[ 'data' ][ 'value' ];
|
||||
$is_audit = $stock_config[ 'is_audit' ];
|
||||
if ($is_audit) {
|
||||
//查询商品是否存在盘点单据
|
||||
$inventory_model = new Inventory();
|
||||
$info = $inventory_model->getInventoryGoodsInfo([
|
||||
['sig.site_id', '=', $site_id],
|
||||
['sig.goods_id', '=', $goods_id],
|
||||
['si.status', '=', Inventory::AUDIT],
|
||||
])['data'] ?? [];
|
||||
if (empty($info)) {
|
||||
return $this->success();
|
||||
} else {
|
||||
return $this->error();
|
||||
}
|
||||
}else{
|
||||
return $this->success();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品sku列表
|
||||
* @param array $condition
|
||||
* @param string $field
|
||||
* @param string $order
|
||||
* @param int $store_id
|
||||
* @return array
|
||||
*/
|
||||
public function getStoreGoodsSkuPage($condition = [], $field = '*', $order = 'gs.create_time desc', $store_id = 0, $page = 1, $page_size = 10)
|
||||
{
|
||||
$alias = 'gs';
|
||||
$join = [
|
||||
[ 'goods g', 'g.goods_id = gs.goods_id', 'left' ],
|
||||
[
|
||||
'store_goods_sku sgs',
|
||||
'sgs.sku_id = gs.sku_id and (sgs.store_id is null or sgs.store_id = ' . $store_id . ')',
|
||||
'left'
|
||||
]
|
||||
];
|
||||
$list = model('goods_sku')->pageList($condition, $field, $order, $page, $page_size, $alias, $join, '');
|
||||
// $list = model('goods_sku')->getList($condition, $field, $order, $alias, $join, '', 15);
|
||||
|
||||
foreach ($list['list'] as $k => $v) {
|
||||
if (isset($v[ 'goods_stock' ])) {
|
||||
$list['list'][ $k ][ 'goods_stock' ] = numberFormat($list['list'][ $k ][ 'goods_stock' ]);
|
||||
}
|
||||
if (isset($v[ 'stock' ])) {
|
||||
$list['list'][ $k ][ 'stock' ] = numberFormat($list['list'][ $k ][ 'stock' ]);
|
||||
}
|
||||
if (isset($v[ 'sale_num' ])) {
|
||||
$list['list'][ $k ][ 'sale_num' ] = numberFormat($list['list'][ $k ][ 'sale_num' ]);
|
||||
}
|
||||
if (isset($v[ 'virtual_sale' ])) {
|
||||
$list['list'][ $k ][ 'virtual_sale' ] = numberFormat($list['list'][ $k ][ 'virtual_sale' ]);
|
||||
}
|
||||
|
||||
if (isset($v[ 'real_stock' ])) {
|
||||
$list['list'][ $k ][ 'real_stock' ] = numberFormat($list['list'][ $k ][ 'real_stock' ]);
|
||||
}
|
||||
}
|
||||
// $data = [];
|
||||
// $data['list'] = $list['list'];
|
||||
return $this->success($list);
|
||||
}
|
||||
}
|
||||
391
addon/stock/model/stock/Transform.php
Executable file
391
addon/stock/model/stock/Transform.php
Executable file
@@ -0,0 +1,391 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\model\stock;
|
||||
|
||||
use app\dict\goods\GoodsDict;
|
||||
use app\model\BaseModel;
|
||||
|
||||
/**
|
||||
* 库存转换
|
||||
* Class Transform
|
||||
* @package addon\stock\model\stock
|
||||
*/
|
||||
class Transform extends BaseModel
|
||||
{
|
||||
/**
|
||||
* 添加库存转换
|
||||
* @param $data
|
||||
* @return array
|
||||
*/
|
||||
public function addTransform($data)
|
||||
{
|
||||
try{
|
||||
//数据检测
|
||||
if(count($data['goods_list']) < 2){
|
||||
return $this->error(null, '转换商品至少要有两种');
|
||||
}
|
||||
$sku_ids = array_column($data['goods_list'], 'sku_id');
|
||||
$sku_count = model('stock_transform_goods')->getCount([['sku_id', 'in', $sku_ids]]);
|
||||
if($sku_count > 0){
|
||||
return $this->error(null, '转换商品在其他转换组已存在');
|
||||
}
|
||||
$transform_id = 0;
|
||||
|
||||
//转换组和转换商品数据
|
||||
$transform_data = [
|
||||
'name' => $data['name'],
|
||||
'create_time' => time(),
|
||||
];
|
||||
$transform_goods_data = [];
|
||||
foreach($data['goods_list'] as $goods_info){
|
||||
$transform_goods_data[] = [
|
||||
'transform_id' => &$transform_id,
|
||||
'sku_id' => $goods_info['sku_id'],
|
||||
'num' => $goods_info['num'],
|
||||
];
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
return $this->error(exceptionData($e), '添加库存转换错误');
|
||||
}
|
||||
|
||||
|
||||
model('stock_transform')->startTrans();
|
||||
try{
|
||||
$transform_id = model('stock_transform')->add($transform_data);
|
||||
model('stock_transform_goods')->addList($transform_goods_data);
|
||||
|
||||
model('stock_transform')->commit();
|
||||
return $this->success();
|
||||
}catch(\Exception $e){
|
||||
model('stock_transform')->rollback();
|
||||
return $this->error(exceptionData($e), '添加库存转换错误');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改库存转换
|
||||
* @param $data
|
||||
* @return array
|
||||
*/
|
||||
public function editTransform($data)
|
||||
{
|
||||
try{
|
||||
//数据检测
|
||||
if(count($data['goods_list']) < 2){
|
||||
return $this->error(null, '转换商品至少要有两种');
|
||||
}
|
||||
$transform_id = $data['transform_id'];
|
||||
$sku_ids = array_column($data['goods_list'], 'sku_id');
|
||||
$sku_count = model('stock_transform_goods')->getCount([['sku_id', 'in', $sku_ids], ['transform_id', '<>', $transform_id]]);
|
||||
if($sku_count > 0){
|
||||
return $this->error(null, '转换商品在其他转换组已存在');
|
||||
}
|
||||
|
||||
//转换组和转换商品数据
|
||||
$transform_data = [
|
||||
'name' => $data['name'],
|
||||
'update_time' => time(),
|
||||
];
|
||||
$transform_goods_data = [];
|
||||
foreach($data['goods_list'] as $goods_info){
|
||||
$transform_goods_data[] = [
|
||||
'transform_id' => $transform_id,
|
||||
'sku_id' => $goods_info['sku_id'],
|
||||
'num' => $goods_info['num'],
|
||||
];
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
return $this->error(exceptionData($e), '修改库存转换错误');
|
||||
}
|
||||
|
||||
model('stock_transform')->startTrans();
|
||||
try{
|
||||
model('stock_transform')->update($transform_data, [['transform_id', '=', $transform_id]]);
|
||||
model('stock_transform_goods')->delete([['transform_id', '=', $transform_id]]);
|
||||
model('stock_transform_goods')->addList($transform_goods_data);
|
||||
|
||||
model('stock_transform')->commit();
|
||||
return $this->success();
|
||||
}catch(\Exception $e){
|
||||
model('stock_transform')->rollback();
|
||||
return $this->error(exceptionData($e), '修改库存转换错误');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除库存转换
|
||||
* @param $transform_ids
|
||||
* @return array
|
||||
*/
|
||||
public function deleteTransform($transform_ids)
|
||||
{
|
||||
model('stock_transform')->startTrans();
|
||||
try{
|
||||
model('stock_transform')->delete([['transform_id', 'in', $transform_ids]]);
|
||||
model('stock_transform_goods')->delete([['transform_id', 'in', $transform_ids]]);
|
||||
|
||||
model('stock_transform')->commit();
|
||||
return $this->success();
|
||||
}catch(\Exception $e){
|
||||
model('stock_transform')->rollback();
|
||||
return $this->error(exceptionData($e), '删除库存转换错误');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取库存转换分页列表
|
||||
* @param array $condition
|
||||
* @param int $page
|
||||
* @param int $page_size
|
||||
* @param string $order
|
||||
* @param string $field
|
||||
* @param string $alias
|
||||
* @param array $join
|
||||
* @param null $group
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getTransformPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '*', $alias = 'a', $join = [], $group = null)
|
||||
{
|
||||
$res = model('stock_transform')->pageList($condition, $field, $order, $page, $page_size, $alias, $join, $group);
|
||||
return $this->success($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取库存转换列表
|
||||
* @param array $condition
|
||||
* @param string $field
|
||||
* @param string $order
|
||||
* @param string $alias
|
||||
* @param array $join
|
||||
* @param null $group
|
||||
* @param null $limit
|
||||
* @return array
|
||||
*/
|
||||
public function getTransformList($condition = [], $field = '', $order = '', $alias = '', $join = [], $group = null, $limit = null)
|
||||
{
|
||||
$list = model('stock_transform')->getList($condition, $field, $order, $alias, $join, $group, $limit);
|
||||
return $this->success($list);
|
||||
}
|
||||
|
||||
public function getTransformInfo($condition, $field = '*')
|
||||
{
|
||||
$info = model('stock_transform')->getInfo($condition, $field);
|
||||
return $this->success($info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取库存转换商品数据
|
||||
* @param $list
|
||||
* @return array
|
||||
*/
|
||||
public function getTransformGoodsData(Array $list)
|
||||
{
|
||||
$list = array_column($list, null, 'transform_id');
|
||||
$transform_ids = array_column($list, 'transform_id');
|
||||
$alias = 'stg';
|
||||
$join = [['goods_sku gs', 'gs.sku_id = stg.sku_id', 'inner']];
|
||||
$condition = [['stg.transform_id', 'in', $transform_ids]];
|
||||
$field = 'stg.*,gs.sku_name,gs.sku_image,gs.sku_no,gs.stock,gs.goods_class';
|
||||
$order = 'stg.transform_id asc,stg.num asc';
|
||||
$goods_list = model('stock_transform_goods')->getList($condition, $field, $order, $alias, $join);
|
||||
foreach($goods_list as $goods_info){
|
||||
$transform_id = $goods_info['transform_id'];
|
||||
if(!isset($list[$transform_id])){
|
||||
$list[$transform_id]['goods_list'] = [];
|
||||
}
|
||||
$goods_info['stock'] = numberFormat($goods_info['stock']);
|
||||
$goods_info['transform_stock'] = $goods_info['stock'] * $goods_info['num'];
|
||||
$list[$transform_id]['goods_list'][] = $goods_info;
|
||||
}
|
||||
|
||||
foreach($list as &$info){
|
||||
$info['transform_stock'] = array_sum(array_column($info['goods_list'], 'transform_stock'));
|
||||
foreach($info['goods_list'] as &$goods_info){
|
||||
$transform_stock = $info['transform_stock'] / $goods_info['num'];
|
||||
if($goods_info['goods_class'] == GoodsDict::weigh){
|
||||
$transform_stock = numberFormat($transform_stock);
|
||||
}else{
|
||||
$transform_stock = floor($transform_stock);
|
||||
}
|
||||
$goods_info['transform_stock'] = $transform_stock;
|
||||
}
|
||||
}
|
||||
return array_values($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品转换后库存数据
|
||||
* @param $param
|
||||
* @return array
|
||||
*/
|
||||
public function getGoodsStockTransformData($param)
|
||||
{
|
||||
$sku_ids = $param['sku_ids'];
|
||||
$store_id = $param['store_id'];
|
||||
$store_business = $param['store_business'];
|
||||
|
||||
//获取库存转换设置和商品类型数据
|
||||
$alias = 'stg';
|
||||
$join = [
|
||||
['goods_sku gs', 'gs.sku_id = stg.sku_id', 'inner'],
|
||||
];
|
||||
$condition = [
|
||||
['stg.sku_id', 'in', $sku_ids],
|
||||
];
|
||||
$field = 'stg.*,gs.goods_class';
|
||||
$goods_list = model('stock_transform_goods')->getList($condition, $field, '', $alias, $join);
|
||||
$transform_ids = array_unique(array_column($goods_list, 'transform_id'));
|
||||
|
||||
$transform_stock_data = [];
|
||||
if(!empty($transform_ids)){
|
||||
//所有涉及的库存转换商品
|
||||
$alias = 'stg';
|
||||
$join = [
|
||||
['goods_sku gs', 'gs.sku_id = stg.sku_id', 'inner'],
|
||||
['goods g', 'g.goods_id = gs.goods_id', 'inner'],
|
||||
];
|
||||
$condition = [
|
||||
['stg.transform_id', 'in', $transform_ids],
|
||||
];
|
||||
$field = 'stg.transform_id,stg.sku_id,stg.num,gs.stock,gs.unit,gs.sku_name,gs.cost_price';
|
||||
$order = 'stg.transform_id asc,stg.num asc';
|
||||
if($store_business == 'store'){
|
||||
$join[] = [ 'store_goods_sku sgs', 'gs.sku_id = sgs.sku_id and sgs.store_id=' . $store_id, 'left' ];
|
||||
//TODO 这里不需要加可售门店的条件,但是还需要进一步的思考
|
||||
//$condition[] = [ 'g.sale_store', 'like', [ '%all%', '%,' . $store_id . ',%' ], 'or' ];
|
||||
$store_info = model('store')->getInfo([['store_id', '=', $store_id]], 'stock_type');
|
||||
if ($store_info[ 'stock_type' ] == 'store') {
|
||||
$field = str_replace('gs.stock', 'IFNULL(sgs.stock, 0) as stock', $field);
|
||||
$field = str_replace('gs.cost_price', 'IFNULL(sgs.cost_price, gs.cost_price) as cost_price', $field);
|
||||
}
|
||||
}
|
||||
$all_goods_list = model('stock_transform_goods')->getList($condition, $field, $order, $alias, $join);
|
||||
//库存按照转换设置汇总
|
||||
$transform_list = [];
|
||||
foreach($all_goods_list as $goods_info){
|
||||
if(!isset($transform_list[$goods_info['transform_id']])){
|
||||
$transform_list[$goods_info['transform_id']] = [
|
||||
'total_transform_stock' => 0,
|
||||
'goods_list' => [],
|
||||
];
|
||||
}
|
||||
$transform_list[$goods_info['transform_id']]['total_transform_stock'] += $goods_info['num']*$goods_info['stock'];
|
||||
$transform_list[$goods_info['transform_id']]['goods_list'][] = $goods_info;
|
||||
}
|
||||
//组装数据
|
||||
foreach($goods_list as $goods_info){
|
||||
$total_transform_stock = $transform_list[$goods_info['transform_id']]['total_transform_stock'] ?? null;
|
||||
if(!is_null($total_transform_stock)){
|
||||
$transform_stock = $total_transform_stock / $goods_info['num'];
|
||||
if($goods_info['goods_class'] == GoodsDict::weigh){
|
||||
$transform_stock = numberFormat($transform_stock);
|
||||
}else{
|
||||
$transform_stock = floor($transform_stock);
|
||||
}
|
||||
$goods_info['transform_stock'] = $transform_stock;
|
||||
$goods_info['transform_info'] = $transform_list[$goods_info['transform_id']];
|
||||
$transform_stock_data[$goods_info['sku_id']] = $goods_info;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $transform_stock_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动库存转换
|
||||
* @param $param
|
||||
* @return array|int
|
||||
*/
|
||||
public function autoGoodsStockTransform($param)
|
||||
{
|
||||
$transform_data = $param['transform_data'];
|
||||
$buy_num = $param['buy_num'];
|
||||
$site_id = $param['site_id'];
|
||||
$store_id = $param['store_id'];
|
||||
$sku_id = $transform_data['sku_id'];
|
||||
|
||||
$goods_list = $transform_data['transform_info']['goods_list'];
|
||||
$goods_list = array_column($goods_list, null, 'sku_id');
|
||||
$curr_goods_info = $goods_list[$sku_id] ?? null;
|
||||
unset($goods_list[$sku_id]);
|
||||
if(is_null($curr_goods_info)){
|
||||
return $this->error(null, '库存转换商品查找失败');
|
||||
}
|
||||
|
||||
//如果是门店独立库存,是当前门店转换库存;否则就是总部转换库存。
|
||||
$default_store_info = model('store')->getInfo([['is_default', '=', 1]], 'store_id');
|
||||
$store_info = model('store')->getInfo([['store_id', '=', $store_id]], 'stock_type');
|
||||
$stock_store_id = $store_info['stock_type'] == 'store' ? $store_id : $default_store_info['store_id'];
|
||||
|
||||
$need_transform_num = $buy_num - $curr_goods_info['stock'];
|
||||
if($need_transform_num > 0){
|
||||
$document_model = new Document();
|
||||
foreach($goods_list as $goods_info){
|
||||
if($goods_info['stock'] > 0){
|
||||
$least_common_multiple = getLeastCommonMultiple($curr_goods_info['num'], $goods_info['num']);
|
||||
$least_input_num = $least_common_multiple / $curr_goods_info['num'];
|
||||
$least_output_num = $least_common_multiple / $goods_info['num'];
|
||||
if($need_transform_num/$least_input_num <= $goods_info['stock']/$least_output_num){
|
||||
$num_multiple = ceil($need_transform_num/$least_input_num);
|
||||
}else{
|
||||
$num_multiple = floor($goods_info['stock']/$least_output_num);
|
||||
}
|
||||
if($num_multiple > 0){
|
||||
$input_num = $num_multiple*$least_input_num;
|
||||
$output_num = $num_multiple*$least_output_num;
|
||||
$input_unit = $curr_goods_info['unit'] ?: '件';
|
||||
$output_unit = $goods_info['unit'] ?: '件';
|
||||
//转换入库
|
||||
$document_params = [
|
||||
'site_id' => $site_id,
|
||||
'store_id' => $stock_store_id,
|
||||
'user_info' => [],
|
||||
'goods_sku_list' => [
|
||||
['goods_sku_id' => $curr_goods_info['sku_id'], 'goods_num' => $input_num, 'goods_price' => $curr_goods_info['cost_price']],
|
||||
],
|
||||
'remark' => "用{$output_num}{$output_unit}[{$goods_info['sku_name']}]自动转换",
|
||||
'time' => time(),
|
||||
];
|
||||
$document_params[ 'is_auto_audit' ] = true;
|
||||
$result = $document_model->addTransformInput($document_params);
|
||||
|
||||
if($result['code'] < 0) return $result;
|
||||
//转换出库
|
||||
$document_params = [
|
||||
'site_id' => $site_id,
|
||||
'store_id' => $stock_store_id,
|
||||
'user_info' => [],
|
||||
'goods_sku_list' => [
|
||||
['goods_sku_id' => $goods_info['sku_id'], 'goods_num' => $output_num, 'goods_price' => $goods_info['cost_price']],
|
||||
],
|
||||
'remark' => "自动转换为{$input_num}{$input_unit}[{$curr_goods_info['sku_name']}]",
|
||||
'time' => time(),
|
||||
'is_out_stock' => 1,
|
||||
];
|
||||
$document_params[ 'is_auto_audit' ] = true;
|
||||
$result = $document_model->addTransformOutput($document_params);
|
||||
if($result['code'] < 0) return $result;
|
||||
//判断是否继续转换
|
||||
$need_transform_num -= $input_num;
|
||||
if($need_transform_num <= 0) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if($need_transform_num > 0){
|
||||
return $this->error(null, '库存转换失败');
|
||||
}
|
||||
return $this->success();
|
||||
}
|
||||
}
|
||||
49
addon/stock/shop/controller/Base.php
Executable file
49
addon/stock/shop/controller/Base.php
Executable file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
|
||||
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\shop\controller;
|
||||
|
||||
use addon\stock\dict\StockDict;
|
||||
use addon\stock\model\stock\Allot;
|
||||
use addon\stock\model\stock\Document;
|
||||
use addon\stock\model\stock\Export;
|
||||
use addon\stock\model\stock\Import;
|
||||
use addon\stock\model\stock\Inventory;
|
||||
use addon\stock\model\stock\Stock as StockModel;
|
||||
use addon\stock\model\Store;
|
||||
use app\dict\goods\GoodsDict;
|
||||
use app\model\goods\GoodsCategory;
|
||||
use app\model\goods\GoodsCategory as GoodsCategoryModel;
|
||||
use app\model\goods\GoodsLabel;
|
||||
use app\model\upload\Upload as UploadModel;
|
||||
use app\shop\controller\BaseShop;
|
||||
use app\model\goods\Goods;
|
||||
use think\App;
|
||||
|
||||
/**
|
||||
* 库存管理
|
||||
* Class Stock
|
||||
* @package addon\stock\shop\controller
|
||||
*/
|
||||
class Base extends BaseShop
|
||||
{
|
||||
public function __construct(App $app = null)
|
||||
{
|
||||
$this->replace = [
|
||||
'ADDON_STOCK_CSS' => __ROOT__ . '/addon/stock/shop/view/public/css',
|
||||
'ADDON_STOCK_JS' => __ROOT__ . '/addon/stock/shop/view/public/js',
|
||||
'ADDON_STOCK_IMG' => __ROOT__ . '/addon/stock/shop/view/public/img',
|
||||
'ADDON_STOCK_FILE' => __ROOT__ . '/addon/stock/shop/view/public/file',
|
||||
];
|
||||
parent::__construct($app);
|
||||
}
|
||||
}
|
||||
1207
addon/stock/shop/controller/Stock.php
Executable file
1207
addon/stock/shop/controller/Stock.php
Executable file
File diff suppressed because it is too large
Load Diff
98
addon/stock/shop/controller/Transform.php
Executable file
98
addon/stock/shop/controller/Transform.php
Executable file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
|
||||
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\shop\controller;
|
||||
|
||||
use addon\stock\model\stock\Transform as TransformModel;
|
||||
|
||||
/**
|
||||
* 库存转换
|
||||
* Class Transform
|
||||
* @package addon\stock\shop\controller
|
||||
*/
|
||||
class Transform extends Base
|
||||
{
|
||||
/**
|
||||
* 列表
|
||||
*/
|
||||
public function lists()
|
||||
{
|
||||
if (request()->isJson()) {
|
||||
$page = input('page', 1);
|
||||
$page_size = input('page_size', PAGE_LIST_ROWS);
|
||||
$search_text = input('search_text', ''); // 名称或编码
|
||||
|
||||
$condition = [];
|
||||
if(!empty($search_text)){
|
||||
$condition[] = ['name', 'like', '%'.$search_text.'%'];
|
||||
}
|
||||
$transform_model = new TransformModel();
|
||||
$res = $transform_model->getTransformPageList($condition, $page, $page_size, 'create_time desc', '*');
|
||||
$res['data']['list'] = $transform_model->getTransformGoodsData($res['data']['list']);
|
||||
return $res;
|
||||
} else {
|
||||
return $this->fetch('transform/lists');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
if(request()->isJson()){
|
||||
$data = [
|
||||
'name' => input('name', ''),
|
||||
'goods_list' => json_decode(input('goods_list', ''), true),
|
||||
];
|
||||
$transform_model = new TransformModel();
|
||||
return $transform_model->addTransform($data);
|
||||
}else{
|
||||
return $this->fetch('transform/add_or_edit');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$transform_id = input('transform_id', 0);
|
||||
$transform_model = new TransformModel();
|
||||
if(request()->isJson()){
|
||||
$data = [
|
||||
'transform_id' => $transform_id,
|
||||
'name' => input('name', ''),
|
||||
'goods_list' => json_decode(input('goods_list', ''), true),
|
||||
];
|
||||
return $transform_model->editTransform($data);
|
||||
}else{
|
||||
$transform_info = $transform_model->getTransformInfo([['transform_id', '=', $transform_id]], '*')['data'];
|
||||
if(empty($transform_info)) $this->error('转换组信息有误');
|
||||
$transform_info = $transform_model->getTransformGoodsData([$transform_info])[0];
|
||||
$this->assign('transform_info', $transform_info);
|
||||
return $this->fetch('transform/add_or_edit');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
if(request()->isJson()){
|
||||
$transform_ids = input('transform_ids', '');
|
||||
$transform_model = new TransformModel();
|
||||
return $transform_model->deleteTransform($transform_ids);
|
||||
}
|
||||
}
|
||||
}
|
||||
52
addon/stock/shop/view/public/css/stock.css
Executable file
52
addon/stock/shop/view/public/css/stock.css
Executable file
@@ -0,0 +1,52 @@
|
||||
.stock-body tr:first-child:hover td {
|
||||
background-color: #FFF;
|
||||
}
|
||||
|
||||
.stock-body, .stock-body tr, .stock-body tr td {
|
||||
background-color: #FFF;
|
||||
}
|
||||
|
||||
.stock-view {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.stock-search-block {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.empty-data {
|
||||
text-align: center;
|
||||
padding: 30px !important;
|
||||
color: rgba(0, 0, 0, .25);
|
||||
}
|
||||
|
||||
.total-data {
|
||||
padding: 15px !important;
|
||||
background: #fafafa;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.goods-money {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.store-view {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.store-view .layui-form-label {
|
||||
width: 97px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.store-view .layui-input-block {
|
||||
margin-left: 97px;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
BIN
addon/stock/shop/view/public/file/stockin_template.xlsx
Executable file
BIN
addon/stock/shop/view/public/file/stockin_template.xlsx
Executable file
Binary file not shown.
230
addon/stock/shop/view/public/js/goods_select.js
Executable file
230
addon/stock/shop/view/public/js/goods_select.js
Executable file
@@ -0,0 +1,230 @@
|
||||
// 商品选择弹出框
|
||||
var form, laytpl, element, table;
|
||||
var goodsSelectObj = {
|
||||
store_id: 0,
|
||||
selectList: [], // 选中商品所有数据res
|
||||
maxNum: 0, // 最大商品数量
|
||||
minNum: 0, // 最小商品数量
|
||||
disabled: 0, // 不可选中
|
||||
cols: [], // 列名数据源
|
||||
filterData: { goods_name: '' }, //筛选数据
|
||||
goodsIdArr: []
|
||||
};
|
||||
$(function () {
|
||||
|
||||
$('.select-goods input[type="hidden"]').each(function () {
|
||||
goodsSelectObj[$(this).attr('name')] = $(this).val();
|
||||
});
|
||||
|
||||
setCols();
|
||||
|
||||
layui.use(['form', 'laytpl', 'element'], function () {
|
||||
form = layui.form, laytpl = layui.laytpl, element = layui.element;
|
||||
element.init();
|
||||
var where = {
|
||||
goods_class: goodsSelectObj.goods_class,
|
||||
search_text: goodsSelectObj.search_text,
|
||||
store_id: goodsSelectObj.store_id,
|
||||
callback: function () {
|
||||
// goodsSelectObj.selectList = [];
|
||||
// goodsSelectObj.goodsIdArr = [];
|
||||
$('div[lay-id="goods_list"] th[data-field="0"] input[type="checkbox"]').prop('checked', false);
|
||||
$('div[lay-id="goods_list"] th[data-field="0"] .layui-unselect').removeClass('layui-form-checked');
|
||||
}
|
||||
}
|
||||
|
||||
table = new Table({
|
||||
elem: '#goods_list',
|
||||
url: ns.url('stock://shop/stock/goodsSelect'),
|
||||
cols: goodsSelectObj.cols,
|
||||
where
|
||||
});
|
||||
|
||||
//修改一级分类箭头切换
|
||||
element.on('collapse(oneCategory)', function (data) {
|
||||
$(".layui-colla-title").removeClass("active");
|
||||
console.log(data.show)
|
||||
if (data.show) {
|
||||
$(data.title).addClass("active");
|
||||
}
|
||||
});
|
||||
|
||||
//修改二级分类箭头切换
|
||||
element.on('collapse(twoCategory)', function (data) {
|
||||
$(".select-goods-classification .select-goods-classification .layui-colla-title").removeClass("active");
|
||||
if (data.show) {
|
||||
$(data.title).addClass("active");
|
||||
}
|
||||
});
|
||||
|
||||
//搜索商品名称或编码
|
||||
form.on('submit(search)', function (data) {
|
||||
formSearch();
|
||||
});
|
||||
|
||||
// 勾选商品
|
||||
form.on('checkbox(goods_checkbox_all)', function (data) {
|
||||
var all_checked = data.elem.checked;
|
||||
$("input[name='goods_checkbox']").each(function () {
|
||||
var checked = $(this).prop('checked');
|
||||
if (all_checked != checked) {
|
||||
$(this).next().click();
|
||||
}
|
||||
});
|
||||
dealWithTableSelectedNum();
|
||||
});
|
||||
|
||||
// 勾选商品
|
||||
form.on('checkbox(goods_checkbox)', function (data) {
|
||||
var sku_id = $(data.elem).attr("data-sku-id"),
|
||||
json = {};
|
||||
|
||||
form.render();
|
||||
|
||||
var spuLen = $("input[name='goods_checkbox'][data-sku-id=" + sku_id + "]:checked").length;
|
||||
if (spuLen) {
|
||||
json = JSON.parse($("input[name='goods_json'][data-sku-id=" + sku_id + "]").val());
|
||||
|
||||
delete json.LAY_INDEX;
|
||||
delete json.LAY_TABLE_INDEX;
|
||||
|
||||
goodsSelectObj.selectList.push(json);
|
||||
goodsSelectObj.goodsIdArr.push(sku_id);
|
||||
|
||||
} else {
|
||||
|
||||
for (var i = 0; i < goodsSelectObj.selectList.length; i++) {
|
||||
if (goodsSelectObj.selectList[i].sku_id == sku_id) {
|
||||
goodsSelectObj.selectList.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < goodsSelectObj.goodsIdArr.length; i++) {
|
||||
if (goodsSelectObj.goodsIdArr[i] == sku_id) {
|
||||
goodsSelectObj.goodsIdArr.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$.unique(goodsSelectObj.goodsIdArr);
|
||||
dealWithTableSelectedNum();
|
||||
});
|
||||
|
||||
$(".select-goods .select-goods-left dd").hover(function () {
|
||||
$(this).addClass("active");
|
||||
}, function () {
|
||||
$(this).removeClass("active");
|
||||
});
|
||||
|
||||
$("body").off("click", ".select-goods-left dl").on("click", ".select-goods-left dl", function () {
|
||||
if ($(this).hasClass("fold")) {
|
||||
$(this).removeClass("fold");
|
||||
} else {
|
||||
$(this).addClass("fold");
|
||||
}
|
||||
});
|
||||
|
||||
$("body").off("click", ".select-goods-left dd").on("click", ".select-goods-left dd", function (event) {
|
||||
$(this).parents("dl").removeClass("fold");
|
||||
$(this).parents("dl").siblings().addClass("fold");
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
//分类切换
|
||||
$("body").off("click", ".classification-item").on("click", ".classification-item", function (event) {
|
||||
var categoryId = $(this).attr("data-category_id");
|
||||
$(".classification-item").removeClass("text-color border-after-color");
|
||||
$(this).addClass("text-color border-after-color");
|
||||
$("input[name='category_id']").val(categoryId);
|
||||
formSearch();
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// 设置列名
|
||||
function setCols() {
|
||||
goodsSelectObj.cols = [
|
||||
[
|
||||
{
|
||||
title: '<input type="checkbox" name="goods_checkbox_all" lay-skin="primary" lay-filter="goods_checkbox_all">',
|
||||
unresize: 'false',
|
||||
width: '8%',
|
||||
templet: '#checkbox',
|
||||
},
|
||||
{
|
||||
title: '商品',
|
||||
unresize: 'false',
|
||||
width: '62%',
|
||||
templet: '#goods_info'
|
||||
},
|
||||
{
|
||||
templet: `<span>{{d.real_stock||0}}</span>`,
|
||||
title: '库存',
|
||||
unresize: 'false',
|
||||
width: '15%'
|
||||
},
|
||||
|
||||
{
|
||||
title: '单位',
|
||||
unresize: 'false',
|
||||
width: '15%',
|
||||
templet: `<span>{{d.unit||'件'}}</span>`
|
||||
},
|
||||
]
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
//公共搜索方法
|
||||
function formSearch() {
|
||||
var data = {};
|
||||
data.search_text = $("input[name='search_text']").val();
|
||||
data.label_id = $("select[name='label_id']").val();
|
||||
data.goods_class = $("select[name='goods_class']").val();
|
||||
data.category_id = $("input[name='category_id']").val();
|
||||
data.goods_ids = goodsSelectObj.goodsIdArr.toString();
|
||||
table.reload({
|
||||
page: {
|
||||
curr: 1
|
||||
},
|
||||
where: data
|
||||
});
|
||||
|
||||
}
|
||||
//在表格底部增加了一个容器
|
||||
function dealWithTableSelectedNum() {
|
||||
$(".layui-table-bottom-left-container").html('已选择 ' + goodsSelectObj.goodsIdArr.length + ' 个商品');
|
||||
}
|
||||
|
||||
function selectGoodsListener(callback) {
|
||||
var res = goodsSelectObj.selectList;
|
||||
var num = goodsSelectObj.goodsIdArr.length;
|
||||
if (num == 0) {
|
||||
layer.msg('请选择商品');
|
||||
return;
|
||||
}
|
||||
if (goodsSelectObj.maxNum && goodsSelectObj.maxNum > 0 && num > goodsSelectObj.maxNum) {
|
||||
layer.msg("所选商品数量不能超过" + goodsSelectObj.maxNum + '件');
|
||||
return;
|
||||
}
|
||||
|
||||
if (goodsSelectObj.minNum && goodsSelectObj.minNum > 0 && num < goodsSelectObj.minNum) {
|
||||
layer.msg("所选商品数量不能少于" + goodsSelectObj.minNum + '件');
|
||||
return;
|
||||
}
|
||||
callback(res);
|
||||
}
|
||||
|
||||
// 清除选中项
|
||||
function clearSelection() {
|
||||
table.reload({
|
||||
selected: false
|
||||
});
|
||||
goodsSelectObj.selectList = [];
|
||||
goodsSelectObj.goodsIdArr = [];
|
||||
dealWithTableSelectedNum()
|
||||
}
|
||||
447
addon/stock/shop/view/public/js/stock_action.js
Executable file
447
addon/stock/shop/view/public/js/stock_action.js
Executable file
@@ -0,0 +1,447 @@
|
||||
var laytpl, form, repeat_flag = false, laydate;
|
||||
|
||||
layui.use(['form', 'laytpl', 'table', 'util', 'laydate'], function () {
|
||||
form = layui.form, laytpl = layui.laytpl, table = layui.table, util = layui.util, laydate = layui.laydate;
|
||||
form.render();
|
||||
fetch()
|
||||
$('.stock-search').focus()
|
||||
//门店选择
|
||||
form.on('select(store_list)', function (data) {
|
||||
var store_id = data.value;
|
||||
if (defaultStoreId > 0) {
|
||||
layer.confirm('更改门店,将清除已录入的单报明细,确定吗?\n', {
|
||||
title: '操作提示',
|
||||
btn: ['是', '否'],
|
||||
closeBtn: 0,
|
||||
yes: function () {
|
||||
defaultStoreId = store_id;
|
||||
reset();
|
||||
layer.closeAll()
|
||||
stockData = []
|
||||
fetch()
|
||||
},
|
||||
btn2: function () {
|
||||
form.val("formTest", {store_id: defaultStoreId})
|
||||
}
|
||||
});
|
||||
} else {
|
||||
defaultStoreId = store_id
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
form.render('select');
|
||||
|
||||
var timeTemplate = 'yyyy-MM-dd HH:mm:ss'
|
||||
laydate.render({
|
||||
elem: '#date_time'
|
||||
, type: 'datetime'
|
||||
, btns: ['now', 'confirm']
|
||||
, max: util.toDateString(new Date(), timeTemplate)
|
||||
, value: $('#date_time').val() ? $('#date_time').val() : util.toDateString(new Date(), timeTemplate)
|
||||
});
|
||||
|
||||
form.on('submit(save)', function (data) {
|
||||
if (stockData.length === 0) {
|
||||
layer.msg('请选择产品');
|
||||
return;
|
||||
}
|
||||
|
||||
var check_return = false;
|
||||
for (var i = 0; i < stockData.length; i++) {
|
||||
if (stockData[i].goods_num <= 0) {
|
||||
check_return = true;
|
||||
layer.msg('产品:' + stockData[i].sku_name + '数量不能为空');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (check_return) return;
|
||||
|
||||
if (stockConfig.is_audit == 1) {
|
||||
var temp_index = layer.confirm('单据保存后将处于"待审核"状态,只有经办人可以编辑或删除等操作!是否确认保存?', {
|
||||
title: '操作提示',
|
||||
btn: ['确定', '取消'],
|
||||
yes: function () {
|
||||
layer.close(temp_index);
|
||||
save();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
save();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function backStockAction() {
|
||||
location.hash = ns.hash("stock://shop/stock/" + stockAction.listRoute)
|
||||
}
|
||||
|
||||
$(".stock-search").on('keyup', function (e) {//空白行回车
|
||||
if (e.keyCode == 13) {
|
||||
var val = $(this).val();
|
||||
$('.stock-search').blur()
|
||||
if (carriage(-1, val)) {
|
||||
goodsSelectByStockAction(function (res) {
|
||||
res.forEach(el => {
|
||||
el.goods_num = 1
|
||||
if (stockAction.listRoute === 'check') {
|
||||
el.goods_num = el.real_stock ? el.real_stock + 0 : 0
|
||||
}
|
||||
el.goods_price = el.price || 0
|
||||
//库存盘点空白行无需判断是否替换某行,只需判断是否存在
|
||||
var index = stockData.length ? stockData.findIndex(v => v.sku_id === el.sku_id) : -1
|
||||
if (index != -1) {
|
||||
stockData[index].goods_num += 1
|
||||
} else {
|
||||
stockData.push(el)
|
||||
}
|
||||
});
|
||||
fetch()
|
||||
}, [], {minNum: 1, search_text: val, store_id: defaultStoreId,})
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
//数据渲染(任何来源)
|
||||
function fetch() {
|
||||
//重新渲染
|
||||
var template = $("#stock_goods_info").html();
|
||||
$('.stock-body tr').not('.stock-search-line').remove();
|
||||
|
||||
if (ns.checkIsNotNull(stockData)) {
|
||||
$.each(stockData, function (index, value) {
|
||||
value.index = index
|
||||
laytpl(template).render(value, function (html) {
|
||||
$('.stock-search-line').before(html);
|
||||
$(".stock-search-" + value.sku_id).on('keyup', function (e) {//更新dom事件需要重新绑定
|
||||
if (e.keyCode == 13) {
|
||||
var val = $(this).val();
|
||||
$('.stock-search-' + value.sku_id).blur()
|
||||
$('.stock-search').blur()
|
||||
if (carriage(index, val)) {
|
||||
goodsSelectByStockAction(function (res) {
|
||||
res.forEach((el, resIndex) => {
|
||||
el.goods_num = 1
|
||||
if (stockAction.listRoute === 'check') {
|
||||
el.goods_num = el.real_stock ? el.real_stock + 0 : 0
|
||||
}
|
||||
el.goods_price = el.price || 0
|
||||
//库存盘点
|
||||
var indexs = stockData.findIndex(v => v.sku_id === el.sku_id)
|
||||
if (indexs != -1) {//库存不可出现相同类目
|
||||
stockData[indexs].goods_num += 1//列表已有数量加一
|
||||
} else if (!resIndex) {//选择的数据第一条在没有相同类目的情况下才替换列表选中行
|
||||
stockData.splice(index, 1, el)
|
||||
} else {
|
||||
stockData.push(el)//非第一条并且列表不存在直接加入列表
|
||||
}
|
||||
});
|
||||
fetch()
|
||||
}, [], {minNum: 1, search_text: val, store_id: defaultStoreId,})
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
$('.stock-search').val('').focus()
|
||||
form.render();
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
form.render();
|
||||
syncData();
|
||||
}
|
||||
|
||||
//输入回车后的处理,查询到单条的处理
|
||||
function carriage(index, val) {
|
||||
var num = true
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/getskulist"),
|
||||
data: {search: val, store_id: defaultStoreId},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
async: false,
|
||||
success: function (res) {
|
||||
|
||||
if (res.data.length != 1) {//不是一条数据返回true,打开弹框
|
||||
num = true
|
||||
return false
|
||||
}
|
||||
num = false
|
||||
var data = res.data[0]
|
||||
data.goods_num = 1
|
||||
data.goods_price = data.price || 0
|
||||
var indexs = stockData.length ? stockData.findIndex(v => v.sku_id === data.sku_id) : -1
|
||||
if (index != -1) {//数据行
|
||||
|
||||
|
||||
if (indexs != -1) {//库存盘点/先判断是否存在
|
||||
stockData[indexs].goods_num += 1//存在数量累加
|
||||
} else {
|
||||
stockData.splice(index, 1, data)
|
||||
}
|
||||
|
||||
} else {//空白行
|
||||
var indexs = stockData.length ? stockData.findIndex(v => v.sku_id === data.sku_id) : -1
|
||||
if (indexs != -1) {//库存盘点/先判断是否存在
|
||||
stockData[indexs].goods_num += 1//存在数量累加
|
||||
} else {
|
||||
stockData.push(data)
|
||||
}
|
||||
|
||||
}
|
||||
fetch()
|
||||
}
|
||||
})
|
||||
return num
|
||||
}
|
||||
|
||||
function dataChange(obj) {
|
||||
syncData();
|
||||
}
|
||||
|
||||
function syncData() {
|
||||
var count_num = 0, goods_money = 0;
|
||||
var goods_up = 0, goods_down = 0, goods_same = 0;
|
||||
var kinds_data = [];
|
||||
$('.stock-tr').each(function (index) {
|
||||
var obj = $(this);
|
||||
var goods_sku_id = stockData[index].sku_id;
|
||||
var goods_num = parseFloat(obj.find('input[name=goods_num]').val()) || 0;
|
||||
var goods_price = parseFloat(obj.find('input[name=goods_price]').val()) || 0;
|
||||
if (kinds_data.indexOf(goods_sku_id) == -1) {
|
||||
kinds_data.push(goods_sku_id)
|
||||
}
|
||||
//重新采集数据
|
||||
stockData[index].goods_num = goods_num;//库存数量
|
||||
stockData[index].goods_price = goods_price;//库存价格
|
||||
count_num += goods_num;
|
||||
goods_money += goods_num * goods_price;
|
||||
obj.find('.total-cost-money').text(parseFloat(goods_num * goods_price).toFixed(2));
|
||||
if (stockAction.listRoute === 'check') {
|
||||
$('.compare-num').eq(index).html(`<span style="color:${stockData[index].goods_num - stockData[index].real_stock > 0 ? '#15eb26' : stockData[index].goods_num - stockData[index].real_stock < 0 ? 'red' : ''}">${parseInt(stockData[index].goods_num - stockData[index].real_stock)}</span>`)
|
||||
if (stockData[index].goods_num - stockData[index].real_stock > 0) goods_up++
|
||||
if (stockData[index].goods_num - stockData[index].real_stock < 0) goods_down++
|
||||
if (stockData[index].goods_num - stockData[index].real_stock == 0) goods_same++
|
||||
|
||||
}
|
||||
});
|
||||
$(".kinds-num").text(parseInt(kinds_data.length));
|
||||
$(".count-num").text(parseFloat(count_num));
|
||||
$(".goods-money").text(parseFloat(goods_money).toFixed(2));
|
||||
$(".goods-up").text(parseInt(goods_up));
|
||||
$(".goods-down").text(parseInt(goods_down));
|
||||
$(".goods-same").text(parseInt(goods_same));
|
||||
|
||||
}
|
||||
|
||||
function reset() {
|
||||
stockData = [];
|
||||
fetch();
|
||||
syncData();
|
||||
}
|
||||
|
||||
function delTr(obj) {
|
||||
var parent = $(obj).parents('.stock-tr');
|
||||
// parent.remove();
|
||||
|
||||
var key = parent.data('key');//唯一值 (sku_id不承担)
|
||||
stockData.splice(key, 1);//由于key使用index,index不会随dom操作变换移除行会出错需要在删除时重新渲染
|
||||
fetch()
|
||||
}
|
||||
|
||||
function editBtn(val) {
|
||||
goodsSelectByStockAction(function (res) {
|
||||
if (val === 'btn') {//空白行btn选择
|
||||
res.forEach(el => {
|
||||
el.goods_num = 1
|
||||
if (stockAction.listRoute === 'check') {
|
||||
el.goods_num = el.real_stock ? el.real_stock + 0 : 0
|
||||
}
|
||||
el.goods_price = el.price || 0
|
||||
|
||||
var index = stockData.length ? stockData.findIndex(v => v.sku_id === el.sku_id) : -1
|
||||
if (index != -1) {//库存盘点/先判断是否存在
|
||||
//stockData[index].goods_num += 1//存在数量累加
|
||||
} else {
|
||||
stockData.push(el)
|
||||
}
|
||||
});
|
||||
} else {//数据行btn选择
|
||||
var parent = $(val).parents('.stock-tr');
|
||||
var key = parent.data('key');//唯一值 (sku_id不承担)
|
||||
res.forEach((el, index) => {//循环选中的数据
|
||||
el.goods_num = 1
|
||||
if (stockAction.listRoute === 'check') {
|
||||
el.goods_num = el.real_stock ? el.real_stock + 0 : 0
|
||||
}
|
||||
el.goods_price = el.price || 0
|
||||
//库存盘点
|
||||
var indexs = stockData.length ? stockData.findIndex(v => v.sku_id === el.sku_id) : -1
|
||||
if (indexs != -1) {//优先判断是否存在
|
||||
//stockData[indexs].goods_num += 1
|
||||
} else if (!index) {//不存在选中数据第一条替换btn点击行
|
||||
stockData.splice(key, 1, el)
|
||||
} else {
|
||||
stockData.push(el)//其它直接加入
|
||||
}
|
||||
});
|
||||
}
|
||||
fetch()
|
||||
}, [], {minNum: 1, search_text: '', store_id: defaultStoreId,})
|
||||
|
||||
|
||||
}
|
||||
|
||||
function save() {
|
||||
let obj = {}
|
||||
let stock_check = true;
|
||||
stockData.forEach((el,key) => {
|
||||
if (ns.checkIsNotNull(obj[el.sku_id])) {
|
||||
obj[el.sku_id].goods_num += el.goods_num
|
||||
obj[el.sku_id].goods_price += el.goods_price
|
||||
} else {
|
||||
obj[el.sku_id] = el
|
||||
obj[el.sku_id].goods_sku_id = el.sku_id
|
||||
}
|
||||
//出库库存检测
|
||||
var error_msg = '';
|
||||
var goods_class = obj[el.sku_id].goods_class;
|
||||
if(goods_class == 6 && !(ns.getRegexp('>0float3')).test(obj[el.sku_id].goods_num)){
|
||||
error_msg = '数量必须为正数且最多保留三位小数';
|
||||
}else if(goods_class != 6 && !(ns.getRegexp('>0num')).test(obj[el.sku_id].goods_num)){
|
||||
error_msg = '数量必须为正整数';
|
||||
}else if(stockAction.saveRoute == 'stockout' && obj[el.sku_id].goods_num > obj[el.sku_id].real_stock){
|
||||
error_msg = '['+obj[el.sku_id].sku_name+']库存不足';
|
||||
}
|
||||
if(error_msg){
|
||||
stock_check = false;
|
||||
$("tbody.stock-body tr[data-key='"+key+"'] input[name='goods_num']").focus();
|
||||
layer.msg(error_msg);
|
||||
}
|
||||
})
|
||||
if(stock_check === false) return false;
|
||||
|
||||
var data = {
|
||||
stock_json: JSON.stringify(obj),
|
||||
store_id: defaultStoreId,
|
||||
};
|
||||
data[stockAction.id] = $('input[name="' + stockAction.id + '"]').val() || 0;
|
||||
|
||||
if (stockAction.params) {
|
||||
$.each(stockAction.params, (i, e) => {
|
||||
data[i] = $(e).val();
|
||||
})
|
||||
}
|
||||
|
||||
if (repeat_flag) return false;
|
||||
repeat_flag = true;
|
||||
var btn = $('button[lay-filter="save"]')
|
||||
btn.addClass('layui-btn-disabled');
|
||||
btn.find('.layui-icon').addClass('layui-icon-loading');
|
||||
btn.prop('disabled', true);
|
||||
|
||||
$.ajax({
|
||||
type: 'post',
|
||||
dataType: 'JSON',
|
||||
url: ns.url("stock://shop/stock/" + stockAction.saveRoute),
|
||||
async: true,
|
||||
data: data,
|
||||
success: function (res) {
|
||||
if (res.code >= 0) {
|
||||
repeat_flag = false;
|
||||
btn.removeClass('layui-btn-disabled');
|
||||
btn.find('.layui-icon').removeClass('layui-icon-loading');
|
||||
btn.prop('disabled', false);
|
||||
layer.confirm($('input[name="' + stockAction.id + '"]').val() ? '编辑成功' : '添加成功', {
|
||||
title: '操作提示',
|
||||
btn: ['返回列表', $('input[name="' + stockAction.id + '"]').val() ? '继续编辑' : '继续添加'],
|
||||
closeBtn: 0,
|
||||
yes: function (index, layero) {
|
||||
location.hash = ns.hash("stock://shop/stock/" + stockAction.listRoute);
|
||||
layer.close(index);
|
||||
},
|
||||
btn2: function (index, layero) {
|
||||
repeat_flag = false;
|
||||
listenerHash(); // 刷新页面
|
||||
layer.close(index);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
repeat_flag = false;
|
||||
btn.removeClass('layui-btn-disabled');
|
||||
btn.find('.layui-icon').removeClass('layui-icon-loading');
|
||||
btn.prop('disabled', false);
|
||||
layer.msg(res.message);
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品选择器
|
||||
* @param callback 回调函数
|
||||
* @param selectId 已选商品id
|
||||
* @param params mode:模式(spu、sku), max_num:最大数量,min_num 最小数量, is_virtual 是否虚拟 0 1, disabled: 开启禁用已选 0 1,promotion:营销活动标识 pintuan、groupbuy、fenxiao (module 表示组件) goods_class: 1 实物商品 2虚拟商品 3电子商品 不传查全部
|
||||
*/
|
||||
function goodsSelectByStockAction(callback, selectId, params = {}) {
|
||||
layui.use(['layer'], function () {
|
||||
localStorage.removeItem('goods_select_id'); // 删除选中id 本地缓存
|
||||
if (selectId.length) {
|
||||
localStorage.setItem('goods_select_id', selectId.toString());
|
||||
}
|
||||
|
||||
params.mode = params.mode ? params.mode : 'spu';
|
||||
if (params.disabled == undefined || params.disabled == 0) {
|
||||
params.disabled = 0;
|
||||
} else {
|
||||
params.disabled = 1;
|
||||
}
|
||||
params.site_id = ns_url.siteId;
|
||||
params.app_module = ns_url.appModule;
|
||||
params.goods_class = params.goods_class || "";
|
||||
params.max_num = params.max_num || 200; // 最多选择数量
|
||||
params.search_text = params.search_text || ''
|
||||
// if(!params.post) params.post = 'shop';
|
||||
|
||||
// if (params.post == 'store') params.post += '://store';
|
||||
|
||||
var url = ns.url("stock://shop/stock/goodsSelect?request_mode=iframe", params);
|
||||
layer.open({
|
||||
title: "商品选择",
|
||||
type: 2,
|
||||
area: ['1000px', '720px'],
|
||||
fixed: false, //不固定
|
||||
btn: ['选中', '返回'],
|
||||
content: url,
|
||||
btn1: function (index, layero) {
|
||||
var iframeWin = document.getElementById(layero.find('iframe')[0]['name']).contentWindow;//得到iframe页的窗口对象,执行iframe页的方法:
|
||||
iframeWin.selectGoodsListener(function (obj) {
|
||||
if (typeof callback == "string") {
|
||||
try {
|
||||
eval(callback + '(obj)');
|
||||
if (!obj.length) return false
|
||||
layer.close(index);
|
||||
} catch (e) {
|
||||
console.error('回调函数' + callback + '未定义');
|
||||
}
|
||||
} else if (typeof callback == "function") {
|
||||
callback(obj);
|
||||
if (!obj.length) return false
|
||||
layer.close(index);
|
||||
}
|
||||
|
||||
});
|
||||
return false
|
||||
},
|
||||
btn2: function (index, layero) {
|
||||
layer.close(index);
|
||||
return false
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
264
addon/stock/shop/view/stock/allocate.html
Executable file
264
addon/stock/shop/view/stock/allocate.html
Executable file
@@ -0,0 +1,264 @@
|
||||
<div class="main-wrap">
|
||||
<div class="single-filter-box">
|
||||
<button type="button" class="layui-btn bg-color" onclick="add()">添加调拨单</button>
|
||||
</div>
|
||||
|
||||
<!-- 搜索框 -->
|
||||
<div class="screen layui-collapse search-nav" lay-filter="selection_panel">
|
||||
<div class="layui-colla-item">
|
||||
<form class="layui-colla-content layui-form layui-show">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">调拨单号:</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="allot_no" placeholder="请输入调拨单号" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">出库门店:</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="output_store_id" class="len-mid">
|
||||
<option value="">全部</option>
|
||||
{foreach $store_list as $store_k => $store_v}
|
||||
<option value="{$store_v.store_id}">{$store_v.store_name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">入库门店:</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="input_store_id" class="len-mid">
|
||||
<option value="">全部</option>
|
||||
{foreach $store_list as $store_k => $store_v}
|
||||
<option value="{$store_v.store_id}">{$store_v.store_name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<button class="layui-btn bg-color" lay-submit lay-filter="search">筛选</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-tab table-tab" lay-filter="doc_tab">
|
||||
<div class="layui-tab-content">
|
||||
<!-- 列表 -->
|
||||
<table id="doc_list" lay-filter="doc_list"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 操作 -->
|
||||
<script type="text/html" id="operation">
|
||||
<div class="table-btn">
|
||||
<a class="layui-btn" lay-event="detail">查看</a>
|
||||
<!-- 待审核状态下进行审核操作 -->
|
||||
{{# if(d.status == 1 && {$is_audit} == 0){ }}
|
||||
<!-- 只有管理员和拥有调拨单审核权限的才能审核 -->
|
||||
<a class="layui-btn" lay-event="audit_agree">审核通过</a>
|
||||
<a class="layui-btn" lay-event="audit_refuse">审核拒绝</a>
|
||||
{{# } }}
|
||||
|
||||
{{# if(d.status == -1){ }}
|
||||
<a class="layui-btn" lay-event="detail_refuse">拒绝理由</a>
|
||||
{{# } }}
|
||||
|
||||
<!-- 只有经办人才能操作入库单 -->
|
||||
{{# if((d.status == 1 || d.status == -1) && d.operater == {$user_info['uid']} ){ }}
|
||||
<a class="layui-btn" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn" lay-event="delete">删除</a>
|
||||
{{# } }}
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var table, form, laytpl, element, layer_pass;
|
||||
layui.use(['form', 'laytpl', 'element'], function() {
|
||||
form = layui.form;
|
||||
laytpl = layui.laytpl;
|
||||
element = layui.element;
|
||||
form.render();
|
||||
|
||||
table = new Table({
|
||||
elem: '#doc_list',
|
||||
url: ns.url("stock://shop/stock/allocate"),
|
||||
cols: [
|
||||
[{
|
||||
field: 'allot_no',
|
||||
title: '调拨单号',
|
||||
width: '20%',
|
||||
}, {
|
||||
field: 'output_store_name',
|
||||
title: '出库门店',
|
||||
width: '15%',
|
||||
}, {
|
||||
field: 'input_store_name',
|
||||
title: '入库门店',
|
||||
width: '15%',
|
||||
}, {
|
||||
field: 'goods_money',
|
||||
title: '商品金额',
|
||||
width: '10%',
|
||||
}, {
|
||||
field: 'allot_time',
|
||||
title: '调拨时间',
|
||||
width: '20%',
|
||||
templet: function(data) {
|
||||
return ns.time_to_date(data.allot_time); //创建时间转换方法
|
||||
}
|
||||
}, {
|
||||
title: '操作',
|
||||
align: 'right',
|
||||
toolbar: '#operation',
|
||||
}]
|
||||
]
|
||||
});
|
||||
|
||||
/**
|
||||
* 监听工具栏操作
|
||||
*/
|
||||
table.tool(function(obj) {
|
||||
var data = obj.data;
|
||||
switch (obj.event) {
|
||||
case 'audit_agree':
|
||||
// 审核通过
|
||||
agree(data.allot_id);
|
||||
break;
|
||||
case 'audit_refuse':
|
||||
// 审核拒绝
|
||||
refuse(data.allot_id);
|
||||
break;
|
||||
case 'edit':
|
||||
// 编辑
|
||||
edit(data.allot_id);
|
||||
break;
|
||||
case 'delete':
|
||||
// 删除
|
||||
deleteAllot(data.allot_id);
|
||||
break;
|
||||
case 'detail': //查看
|
||||
window.open(ns.href("stock://shop/stock/allotrecords?allot_id="+ data.allot_id));
|
||||
break;
|
||||
case 'detail_refuse':
|
||||
layer.open({
|
||||
title: '拒绝理由',
|
||||
content: data.refuse_reason,
|
||||
})
|
||||
break;
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 搜索功能
|
||||
*/
|
||||
form.on('submit(search)', function(data){
|
||||
table.reload({
|
||||
page: {
|
||||
curr: 1
|
||||
},
|
||||
where: data.field
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function add() {
|
||||
location.hash = ns.hash("stock://shop/stock/editallocate");
|
||||
}
|
||||
|
||||
function edit(allot_id) {
|
||||
location.hash = ns.hash("stock://shop/stock/editallocate",{allot_id});
|
||||
}
|
||||
|
||||
// 同意
|
||||
var agree_repeat_flag = false;
|
||||
function agree(allot_id) {
|
||||
layer.confirm('确定要通过该调拨单吗?', function(index) {
|
||||
if(agree_repeat_flag) return;
|
||||
agree_repeat_flag = true;
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/allocateAgree"),
|
||||
data: {allot_id},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
agree_repeat_flag = false;
|
||||
if (res.code >= 0) {
|
||||
listenerHash(); // 刷新页面
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// 拒绝
|
||||
var refuse_repeat_flag = false;
|
||||
function refuse(allot_id) {
|
||||
layer.prompt({
|
||||
title: '拒绝理由',
|
||||
formType: 2,
|
||||
yes: function (index, layero) {
|
||||
var refuse_reason = layero.find(".layui-layer-input").val();
|
||||
if (!refuse_reason) {
|
||||
layer.msg('请输入拒绝理由!', {icon: 5, anim: 6});
|
||||
return;
|
||||
}
|
||||
if (refuse_repeat_flag) return;
|
||||
refuse_repeat_flag = true;
|
||||
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/allocateRefuse"),
|
||||
data: {allot_id, refuse_reason},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function (res) {
|
||||
layer.msg(res.message);
|
||||
refuse_repeat_flag = false;
|
||||
|
||||
if (res.code >= 0) {
|
||||
listenerHash(); // 刷新页面
|
||||
}
|
||||
}
|
||||
});
|
||||
layer.close(index);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 删除调拨单
|
||||
var delete_repeat_flag = false;
|
||||
function deleteAllot(allot_id) {
|
||||
layer.confirm('确定要删除该调拨单吗?', function(index) {
|
||||
if(delete_repeat_flag) return;
|
||||
delete_repeat_flag = true;
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/allocateDelete"),
|
||||
data: {allot_id},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
delete_repeat_flag = false;
|
||||
if (res.code >= 0) {
|
||||
listenerHash(); // 刷新页面
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
193
addon/stock/shop/view/stock/allot_records.html
Executable file
193
addon/stock/shop/view/stock/allot_records.html
Executable file
@@ -0,0 +1,193 @@
|
||||
<style>
|
||||
.layui-table .layui-btn {
|
||||
justify-content: flex-end;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.name {
|
||||
display: flex;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.name img {
|
||||
max-width: inherit;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="layui-form" lay-filter="storeform">
|
||||
<div class="layui-card card-common card-brief">
|
||||
<div class="layui-card-header">
|
||||
<span class="card-title">基本信息</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-row">
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">操作人:</label>
|
||||
<div class="layui-input-block">{$detail.operater_name}</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">调拨时间:</label>
|
||||
<div class="layui-input-block">{:time_to_date($detail.allot_time)}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">调拨单号:</label>
|
||||
<div class="layui-input-block">{$detail.allot_no}</div>
|
||||
</div>
|
||||
{if $detail.status == -1}
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">拒绝理由:</label>
|
||||
<div class="layui-input-block">{$detail.refuse_reason}</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="layui-col-md3">
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">出库门店:</label>
|
||||
<div class="layui-input-block">{$detail.output_store_name}</div>
|
||||
</div>
|
||||
{notempty name="$detail.out_info"}
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">出库时间:</label>
|
||||
<div class="layui-input-block">{$detail.out_info.create_time}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">经办人:</label>
|
||||
<div class="layui-input-block">{$detail.out_info.operater_name}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态:</label>
|
||||
<div class="layui-input-block">{$detail.out_info.status_name}</div>
|
||||
</div>
|
||||
{if $detail.out_info.verifier_name }
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">审核人:</label>
|
||||
<div class="layui-input-block">{$detail.out_info.verifier_name}</div>
|
||||
</div>
|
||||
{/if}
|
||||
{if $detail.out_info.audit_time }
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">审核时间:</label>
|
||||
<div class="layui-input-block">{$detail.out_info.audit_time}</div>
|
||||
</div>
|
||||
{/if}
|
||||
{if $detail.out_info.status == -1}
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">拒绝理由:</label>
|
||||
<div class="layui-input-block">{$detail.out_info.refuse_reason}</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/notempty}
|
||||
</div>
|
||||
|
||||
<div class="layui-col-md3">
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">入库门店:</label>
|
||||
<div class="layui-input-block">{$detail.input_store_name}</div>
|
||||
</div>
|
||||
{notempty name="$detail.input_info"}
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">入库时间:</label>
|
||||
<div class="layui-input-block">{$detail.input_info.create_time}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">经办人:</label>
|
||||
<div class="layui-input-block">{$detail.input_info.operater_name}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态:</label>
|
||||
<div class="layui-input-block">{$detail.input_info.status_name}</div>
|
||||
</div>
|
||||
{if $detail.input_info.verifier_name }
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">审核人:</label>
|
||||
<div class="layui-input-block">{$detail.input_info.verifier_name}</div>
|
||||
</div>
|
||||
{/if}
|
||||
{if $detail.input_info.audit_time }
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">审核时间:</label>
|
||||
<div class="layui-input-block">{$detail.input_info.audit_time}</div>
|
||||
</div>
|
||||
{/if}
|
||||
{if $detail.input_info.status == -1}
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">拒绝理由:</label>
|
||||
<div class="layui-input-block">{$detail.input_info.refuse_reason}</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/notempty}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-card card-common card-brief">
|
||||
<div class="layui-card-header">
|
||||
<span class="card-title">商品明细</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<table class="layui-table order_goods_list" lay-filter="order_goods" lay-skin="line" lay-filter="order_goods_list">
|
||||
<colgroup>
|
||||
<col width="30%"/>
|
||||
<col width="10%"/>
|
||||
<col width="10%"/>
|
||||
<col width="10%"/>
|
||||
<col width="10%"/>
|
||||
<col width="10%"/>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>商品名称/条形码</th>
|
||||
<th>商品规格</th>
|
||||
<th>单位</th>
|
||||
<th>数量</th>
|
||||
<th>成本价(元)</th>
|
||||
<th>金额(元)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<table class="layui-table order_goods_list order_goods_list-bottom" lay-filter="order_goods" lay-skin="line" lay-filter="order_goods_list">
|
||||
<colgroup>
|
||||
<col width="30%"/>
|
||||
<col width="10%"/>
|
||||
<col width="10%"/>
|
||||
<col width="10%"/>
|
||||
<col width="10%"/>
|
||||
<col width="10%"/>
|
||||
</colgroup>
|
||||
<tbody>
|
||||
{foreach $detail.goods_sku_list_array as $k => $v}
|
||||
<tr class="table-tr">
|
||||
<td class="name">
|
||||
<img src="{:img($v.goods_sku_img,'small')}" alt="">
|
||||
<span>{$v.goods_sku_name}</span>
|
||||
</td>
|
||||
{if $v.goods_sku_spec && $v.goods_sku_spec !=''}
|
||||
<td>{$v.goods_sku_spec}</td>
|
||||
{else/}
|
||||
<td>-</td>
|
||||
{/if}
|
||||
{if $v.goods_unit && $v.goods_unit !=''}
|
||||
<td>{$v.goods_unit}</td>
|
||||
{else/}
|
||||
<td>件</td>
|
||||
{/if}
|
||||
<td>{$v.goods_num}</td>
|
||||
<td>{$v.goods_price}</td>
|
||||
<td>{$v.total_goods_money}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
<label style="display: flex;justify-content: flex-end;padding-right: 13px;">合计:共{$detail.goods_count}种商品{$detail.goods_price}件,合计金额:<span style="color: #ff0000;">{$detail.goods_total_price}</span></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
269
addon/stock/shop/view/stock/check.html
Executable file
269
addon/stock/shop/view/stock/check.html
Executable file
@@ -0,0 +1,269 @@
|
||||
<div class="main-wrap">
|
||||
<div class="single-filter-box">
|
||||
<button type="button" class="layui-btn bg-color" onclick="add()">添加盘点单</button>
|
||||
</div>
|
||||
|
||||
<!-- 搜索框 -->
|
||||
<div class="screen layui-collapse search-nav" lay-filter="selection_panel">
|
||||
<div class="layui-colla-item">
|
||||
<form class="layui-colla-content layui-form layui-show">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">盘点单号:</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="search_text" placeholder="请输入入库单号" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">门店:</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="store_id" class="len-mid">
|
||||
<option value="">全部</option>
|
||||
{foreach $store_list as $store_k => $store_v}
|
||||
<option value="{$store_v.store_id}">{$store_v.store_name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">审核状态:</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="status" lay-filter="status" class="len-mid">
|
||||
<option value="">全部</option>
|
||||
{foreach name="$status_list" item="vo"}
|
||||
<option value="{$vo.status}">{$vo.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<button class="layui-btn bg-color" lay-submit lay-filter="search">筛选</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-tab table-tab">
|
||||
<div class="layui-tab-content">
|
||||
<table id="doc_list" lay-filter="doc_list"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 操作 -->
|
||||
<script type="text/html" id="operation">
|
||||
<div class="table-btn">
|
||||
<a class="layui-btn" lay-event="detail">查看</a>
|
||||
|
||||
<!-- 待审核状态下进行审核操作 -->
|
||||
{{# if(d.status == 1 && {$is_audit} == 0){ }}
|
||||
<!-- 只有管理员和拥有盘点单审核权限的才能审核 -->
|
||||
<a class="layui-btn" lay-event="audit_agree">审核通过</a>
|
||||
<a class="layui-btn" lay-event="audit_refuse">审核拒绝</a>
|
||||
{{# } }}
|
||||
|
||||
{{# if(d.status == -1){ }}
|
||||
<a class="layui-btn" lay-event="detail_refuse">拒绝理由</a>
|
||||
{{# } }}
|
||||
|
||||
<!-- 只有经办人才能操作入库单 -->
|
||||
{{# if((d.status == 1 || d.status == -1) && d.operater == {$user_info['uid']} ){ }}
|
||||
<a class="layui-btn" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn" lay-event="delete">删除</a>
|
||||
{{# } }}
|
||||
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var table, form, laytpl, element, layer_pass;
|
||||
layui.use(['form', 'laytpl', 'element'], function() {
|
||||
form = layui.form;
|
||||
laytpl = layui.laytpl;
|
||||
element = layui.element;
|
||||
form.render();
|
||||
|
||||
table = new Table({
|
||||
elem: '#doc_list',
|
||||
url: ns.url("stock://shop/stock/check"),
|
||||
cols: [
|
||||
[{
|
||||
field: 'inventory_no',
|
||||
title: '盘点单号',
|
||||
width: '20%',
|
||||
}, {
|
||||
field: 'store_name',
|
||||
title: '盘点门店',
|
||||
}, {
|
||||
field: 'status_name',
|
||||
title: '审核状态',
|
||||
width: '10%',
|
||||
}, {
|
||||
title: '操作人',
|
||||
width: '15%',
|
||||
templet: function(data) {
|
||||
var html = '';
|
||||
html += '盘点人:' + data.operater_name + '<br/>';
|
||||
if(data.verifier_name) html += '审核人:' + data.verifier_name;
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
title: '操作时间',
|
||||
width: '15%',
|
||||
templet: function(data) {
|
||||
var html = '';
|
||||
html += '制单时间:' + ns.time_to_date(data.create_time) + '<br/>';
|
||||
if(data.action_time) html += '盘点时间:' + ns.time_to_date(data.action_time) + '<br/>';
|
||||
if (data.audit_time) html += '审核时间:' + ns.time_to_date(data.audit_time);
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
title: '操作',
|
||||
toolbar: '#operation',
|
||||
align: 'right',
|
||||
}]
|
||||
]
|
||||
});
|
||||
|
||||
/**
|
||||
* 监听工具栏操作
|
||||
*/
|
||||
table.tool(function(obj) {
|
||||
var data = obj.data;
|
||||
switch (obj.event) {
|
||||
case 'audit_agree':
|
||||
// 审核通过
|
||||
agree(data.inventory_id);
|
||||
break;
|
||||
case 'audit_refuse':
|
||||
// 审核拒绝
|
||||
refuse(data.inventory_id);
|
||||
break;
|
||||
case 'edit':
|
||||
// 编辑
|
||||
edit(data.inventory_id);
|
||||
break;
|
||||
case 'delete':
|
||||
// 删除
|
||||
deleteInventory(data.inventory_id);
|
||||
break;
|
||||
case 'detail': //查看
|
||||
location.hash = ns.hash("stock://shop/stock/inventorydetail?inventory_no="+ data.inventory_no);
|
||||
break;
|
||||
case 'detail_refuse':
|
||||
layer.open({
|
||||
title: '拒绝理由',
|
||||
content: data.refuse_reason,
|
||||
})
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// 搜索功能
|
||||
form.on('submit(search)', function(data){
|
||||
table.reload({
|
||||
page: {
|
||||
curr: 1
|
||||
},
|
||||
where: data.field
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function add() {
|
||||
location.hash = ns.hash("stock://shop/stock/editcheck");
|
||||
}
|
||||
|
||||
function edit(inventory_id) {
|
||||
location.hash = ns.hash("stock://shop/stock/editcheck",{inventory_id});
|
||||
}
|
||||
|
||||
// 同意
|
||||
var agree_repeat_flag = false;
|
||||
function agree(inventory_id) {
|
||||
layer.confirm('确定要通过该盘点单吗?', function(index) {
|
||||
if(agree_repeat_flag) return;
|
||||
agree_repeat_flag = true;
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/inventoryAgree"),
|
||||
data: {inventory_id},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
agree_repeat_flag = false;
|
||||
if (res.code >= 0) {
|
||||
listenerHash(); // 刷新页面
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// 拒绝
|
||||
var refuse_repeat_flag = false;
|
||||
function refuse(inventory_id) {
|
||||
layer.prompt({
|
||||
title: '拒绝理由',
|
||||
formType: 2,
|
||||
yes: function (index, layero) {
|
||||
var refuse_reason = layero.find(".layui-layer-input").val();
|
||||
if (!refuse_reason) {
|
||||
layer.msg('请输入拒绝理由!', {icon: 5, anim: 6});
|
||||
return;
|
||||
}
|
||||
if (refuse_repeat_flag) return;
|
||||
refuse_repeat_flag = true;
|
||||
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/inventoryRefuse"),
|
||||
data: {inventory_id, refuse_reason},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function (res) {
|
||||
layer.msg(res.message);
|
||||
refuse_repeat_flag = false;
|
||||
|
||||
if (res.code >= 0) {
|
||||
listenerHash(); // 刷新页面
|
||||
}
|
||||
}
|
||||
});
|
||||
layer.close(index);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 删除盘点单
|
||||
var delete_repeat_flag = false;
|
||||
function deleteInventory(inventory_id) {
|
||||
layer.confirm('确定要删除该盘点单吗?', function(index) {
|
||||
if(delete_repeat_flag) return;
|
||||
delete_repeat_flag = true;
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/inventoryDelete"),
|
||||
data: {inventory_id},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
delete_repeat_flag = false;
|
||||
if (res.code >= 0) {
|
||||
listenerHash(); // 刷新页面
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
40
addon/stock/shop/view/stock/config.html
Executable file
40
addon/stock/shop/view/stock/config.html
Executable file
@@ -0,0 +1,40 @@
|
||||
<div class="layui-form form-wrap">
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">是否开启单据审核:</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="is_audit" value="1" title="是" {if $stock_config.is_audit eq '1'}checked{/if} >
|
||||
<input type="radio" name="is_audit" value="0" title="否" {if $stock_config.is_audit eq '0'}checked{/if}>
|
||||
</div>
|
||||
<div class="word-aux">开启后,如果存在盘点单据,实物、称重商品将无法编辑库存、规格项(可以新增规格值),操作出入库、调拨、盘点等操作将会进行审核流程</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
layui.use(['form'], function() {
|
||||
var form = layui.form,
|
||||
repeat_flag = false; //防重复标识
|
||||
form.render();
|
||||
|
||||
form.on('submit(save)', function(data) {
|
||||
if (repeat_flag) return;
|
||||
repeat_flag = true;
|
||||
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/config"),
|
||||
data: data.field,
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
repeat_flag = false;
|
||||
layer.msg(res.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
661
addon/stock/shop/view/stock/edit_allocate.html
Executable file
661
addon/stock/shop/view/stock/edit_allocate.html
Executable file
@@ -0,0 +1,661 @@
|
||||
<style>
|
||||
.stock-body tr:first-child:hover td {
|
||||
background-color: #fff
|
||||
}
|
||||
|
||||
.stock-body,
|
||||
.stock-body tr,
|
||||
.stock-body tr td {
|
||||
background-color: #fff
|
||||
}
|
||||
|
||||
.stock-view {
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
.stock-search-block {
|
||||
position: relative
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
.total-data {
|
||||
padding: 15px !important;
|
||||
background: #fafafa;
|
||||
color: #333
|
||||
}
|
||||
|
||||
.goods-money {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.store-view {
|
||||
margin-top: 10px
|
||||
}
|
||||
|
||||
.store-view .layui-form-label {
|
||||
width: 100px;
|
||||
text-align: center
|
||||
}
|
||||
|
||||
.store-view .layui-input-block {
|
||||
margin-left: 100px
|
||||
}
|
||||
|
||||
.stock-title-body {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.stock-title-body span {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
background-color: #fff;
|
||||
z-index: 10;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stock-title-body input {
|
||||
padding-right: 25px;
|
||||
}
|
||||
|
||||
input.stock-search {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
input.stock-search:focus {
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.layui-table th,
|
||||
.layui-table td {
|
||||
padding: 7px 30px !important;
|
||||
}
|
||||
|
||||
.layui-table .layui-input {
|
||||
height: 28px !important;
|
||||
}
|
||||
button[lay-filter='save'] .layui-icon-loading {
|
||||
animation: loding-rotate 1s linear infinite; /* 设置动画效果 */
|
||||
transform-origin: center;
|
||||
display: inline-block;
|
||||
}
|
||||
.remark{
|
||||
width: 614px;
|
||||
}
|
||||
@keyframes loding-rotate {
|
||||
0% { transform: rotate(0); } /* 起始位置 */
|
||||
100% { transform: rotate(360deg); } /* 结束位置,旋转一周 */
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="layui-form form" lay-filter="formTest">
|
||||
|
||||
<div class="stock-view">
|
||||
|
||||
<div class="store-view">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">调拨单号:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
{if isset($allot_info)}
|
||||
<input type="text" value="{$allot_info['allot_no']}" name="allot_no" class="layui-input len-mid">
|
||||
{else /}
|
||||
<input type="text" value="{$allot_no}" name="allot_no" class="layui-input len-mid">
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label"><span class="required">*</span>出库门店:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
<select name="output_store_id" lay-verify="required" lay-filter="store_list" class="len-mid">
|
||||
{foreach $store_list as $store_k => $store_v}
|
||||
{if isset($allot_info)}
|
||||
<option value="{$store_v.store_id}" {if $allot_info['output_store_id']==$store_v['store_id']} {php} $default_store_id=$store_v['store_id']; {/php} selected {/if}>{$store_v.store_name}</option>
|
||||
{else /}
|
||||
<option value="{$store_v.store_id}" {if $store_k==0} {php} $default_store_id=$store_v['store_id']; {/php} selected {/if}>{$store_v.store_name}</option>
|
||||
{/if}
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">当前操作人:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
<span>{$user_info['username']}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label"><span class="required">*</span>入库门店:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
<select name="input_store_id" class="len-mid"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label"><span class="required">*</span>调拨时间:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
<input type="text" name="allot_time" class="layui-input" id="allot_time" placeholder="调拨日期" value="{$allot_info ? time_to_date($allot_info['allot_time']) : date('Y-m-d H:i:s')}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label"><span class="required"></span>备注:</label>
|
||||
<div class="layui-input-block remark">
|
||||
<textarea class="layui-textarea" maxlength="100" name="remark" placeholder="请输入备注">{$allot_info['remark'] ?? ''}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="layui-table" lay-size="lg">
|
||||
<colgroup>
|
||||
<col width="350">
|
||||
<col width="120">
|
||||
<col width="90">
|
||||
<col width="110">
|
||||
<col width="110">
|
||||
<col width="120">
|
||||
<col width="90">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>产品名称/规格/编码</th>
|
||||
<th>当前库存</th>
|
||||
<th>单位</th>
|
||||
<th>数量</th>
|
||||
<th>成本价</th>
|
||||
<th>总金额</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="stock-body">
|
||||
<tr class="stock-search-line">
|
||||
<td class="stock-search-block">
|
||||
<div class="stock-title-body">
|
||||
<input type="text" class="layui-input stock-search" placeholder="请输入产品名称/规格/编码" />
|
||||
<span class="iconfont icontuodong" onclick="editBtn('btn')"></span>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="7" class="total-data">合计: 共<span class="kinds-num">0</span>种,<span class="count-num">0</span>件产品,合计金额:<span class="goods-money">0</span></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
{notempty name="$allot_info"}
|
||||
<input type="hidden" name="allot_id" value="{$allot_info['allot_id']}">
|
||||
<input type="hidden" name="allot_goods_list" value='{:json_encode($allot_info["goods_list"])}'>
|
||||
{/notempty}
|
||||
|
||||
<div class="form-row">
|
||||
<button class="layui-btn" lay-submit lay-filter="save"><span class="layui-icon"></span>确认调拨</button>
|
||||
<button class="layui-btn layui-btn-primary" onclick="backStockAllocate()">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="stock_goods_info">
|
||||
<tr class="stock-tr" data-key='{{ d.index }}' >
|
||||
<td>
|
||||
{{d.sku_name}}
|
||||
</td>
|
||||
<!-- 库存 -->
|
||||
<td>{{ d.real_stock || 0 }}</td>
|
||||
<!-- 单位 -->
|
||||
<td>{{ d.unit || '件' }}</td>
|
||||
<!-- 数量 -->
|
||||
<td>
|
||||
<input type="number" class="layui-input stock-num" name="goods_num" value="{{ d.goods_num || 0 }}" placeholder="0" onchange="dataChange(this)"/>
|
||||
</td>
|
||||
<!-- 成本价 -->
|
||||
<td>
|
||||
<span>{{ d.cost_price || 0 }}</span>
|
||||
</td>
|
||||
<!-- 成本总价 -->
|
||||
<td>
|
||||
<span class="total-cost-money">{{ d.goods_money || 0 }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<a class="text-color action-btn" onclick="delTr(this)">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var count = 0;
|
||||
var stockDataObj = JSON.parse($("input[name='allot_goods_list']").val() || '{}');// 库存数据
|
||||
var stockData = Object.values(stockDataObj)
|
||||
var laytpl, form, laydate;
|
||||
var defaultStoreId = {$default_store_id ?? 0};
|
||||
var store_list = {:json_encode($store_list, true) };
|
||||
|
||||
layui.use(['form', 'laytpl', 'table', 'laydate'], function () {
|
||||
form = layui.form, laytpl = layui.laytpl, table = layui.table, laydate = layui.laydate;
|
||||
form.render();
|
||||
fetch()
|
||||
var repeat_flag = false;
|
||||
laydate.render({
|
||||
elem: '#allot_time'
|
||||
, type: 'datetime'
|
||||
, max: '{$start_time}'
|
||||
, value: $('#allot_time').val() ? $('#allot_time').val() : '{$default_time}'
|
||||
});
|
||||
|
||||
setStore();
|
||||
|
||||
{if isset($allot_info)}
|
||||
$('[name="input_store_id"]').val("{$allot_info['input_store_id']}");
|
||||
{/if}
|
||||
|
||||
$('.stock-search').focus()
|
||||
form.render('select');
|
||||
//门店选择
|
||||
form.on('select(store_list)', function (data) {
|
||||
var store_id = data.value;
|
||||
if (defaultStoreId > 0) {
|
||||
layer.confirm('更改门店,将清除已录入的单报明细,确定吗?\n', {
|
||||
title: '操作提示',
|
||||
btn: ['是', '否'],
|
||||
closeBtn: 0,
|
||||
yes: function () {
|
||||
defaultStoreId = store_id;
|
||||
reset();
|
||||
layer.closeAll()
|
||||
stockData = []
|
||||
fetch()
|
||||
setStore()
|
||||
},
|
||||
btn2: function () {
|
||||
form.val("formTest", { output_store_id: defaultStoreId })
|
||||
}
|
||||
});
|
||||
} else {
|
||||
defaultStoreId = store_id
|
||||
}
|
||||
|
||||
});
|
||||
form.render('select');
|
||||
form.on('submit(save)', function (data) {
|
||||
|
||||
var field = data.field;
|
||||
if (!field.input_store_id) {
|
||||
layer.msg('请选择入库门店');
|
||||
return false;
|
||||
}
|
||||
var stock_json = [];
|
||||
var check_return = true;
|
||||
if ($('.stock-tr').length <= 0) {
|
||||
layer.msg('请选择产品');
|
||||
return false;
|
||||
}
|
||||
|
||||
$('.stock-tr').each(function (index) {
|
||||
var obj = $(this);
|
||||
var goods_num = Number(obj.find('input[name=goods_num]').val() || 0);
|
||||
var real_stock = Number(stockData[index].real_stock);
|
||||
var goods_class = stockData[index].goods_class;
|
||||
var error_msg = '';
|
||||
if(goods_class == 6 && !(ns.getRegexp('>0float3')).test(goods_num)){
|
||||
error_msg = '称重商品调拨数量必须为正数且最多保留三位小数';
|
||||
}else if(goods_class != 6 && !(ns.getRegexp('>0num')).test(goods_num)){
|
||||
error_msg = '调拨数量必须为正整数';
|
||||
}else if (goods_num > real_stock) {
|
||||
error_msg = '可调拨数量不足';
|
||||
}
|
||||
if(error_msg){
|
||||
check_return = false;
|
||||
obj.find('input[name=goods_num]').focus();
|
||||
layer.msg(error_msg);
|
||||
return false;
|
||||
}
|
||||
stockData[index].goods_sku_id = stockData[index].sku_id;
|
||||
});
|
||||
|
||||
if (!check_return) return false;
|
||||
|
||||
if (repeat_flag) return false;
|
||||
repeat_flag = true;
|
||||
|
||||
field.goods_sku_list = JSON.stringify(stockData);
|
||||
var btn = $('button[lay-filter="save"]')
|
||||
btn.addClass('layui-btn-disabled');
|
||||
btn.find('.layui-icon').addClass('layui-icon-loading');
|
||||
btn.prop('disabled', true);
|
||||
$.ajax({
|
||||
type: 'post',
|
||||
dataType: 'JSON',
|
||||
url: ns.url("stock://shop/stock/editallocate"),
|
||||
async: true,
|
||||
data: field,
|
||||
success: function (res) {
|
||||
if (res.code >= 0) {
|
||||
location.hash = ns.hash("stock://shop/stock/allocate");
|
||||
} else {
|
||||
repeat_flag = false;
|
||||
btn.removeClass('layui-btn-disabled');
|
||||
btn.find('.layui-icon').removeClass('layui-icon-loading');
|
||||
btn.prop('disabled', false);
|
||||
layer.msg(res.message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function backStockAllocate() {
|
||||
location.hash = ns.hash("stock://shop/stock/allocate")
|
||||
}
|
||||
|
||||
$(".stock-search").on('keyup', function (e) {
|
||||
//空白行回车
|
||||
if (e.keyCode == 13) {
|
||||
var val = $(this).val();
|
||||
$('.stock-search').blur()
|
||||
if (carriage(-1, val)) {
|
||||
goodsSelectByAllocate(function (res) {
|
||||
res.forEach(el => {
|
||||
el.goods_num = 1
|
||||
el.goods_price = el.cost_price || 0
|
||||
//库存盘点空白行无需判断是否替换某行,只需判断是否存在
|
||||
var index = stockData.length ? stockData.findIndex(v => v.sku_id === el.sku_id) : -1
|
||||
if (index != -1) {
|
||||
stockData[index].goods_num += 1
|
||||
} else {
|
||||
stockData.push(el)
|
||||
}
|
||||
});
|
||||
fetch()
|
||||
}, [], { minNum: 1, search_text: val, store_id: defaultStoreId, })
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
//数据渲染(任何来源)
|
||||
function fetch() {
|
||||
//重新渲染
|
||||
var template = $("#stock_goods_info").html();
|
||||
$('.stock-body tr').not('.stock-search-line').remove();
|
||||
|
||||
if (ns.checkIsNotNull(stockData)) {
|
||||
$.each(stockData, function (index, value) {
|
||||
value.index = index
|
||||
laytpl(template).render(value, function (html) {
|
||||
$('.stock-search-line').before(html);
|
||||
$(".stock-search-" + value.sku_id).on('keyup', function (e) {
|
||||
//更新dom事件需要重新绑定
|
||||
if (e.keyCode == 13) {
|
||||
var val = $(this).val();
|
||||
if (val != '') {
|
||||
|
||||
$('.stock-search').blur()
|
||||
if (carriage(index, val)) {
|
||||
goodsSelectByAllocate(function (res) {
|
||||
res.forEach((el, resIndex) => {
|
||||
el.goods_num = 1
|
||||
el.goods_price = el.cost_price || 0
|
||||
//库存盘点
|
||||
var indexs = stockData.findIndex(v => v.sku_id === el.sku_id)
|
||||
if (indexs != -1) {
|
||||
//库存不可出现相同类目
|
||||
stockData[indexs].goods_num += 1
|
||||
//列表已有数量加一
|
||||
} else if (!resIndex) {
|
||||
//选择的数据第一条在没有相同类目的情况下才替换列表选中行
|
||||
stockData.splice(index, 1, el)
|
||||
} else {
|
||||
stockData.push(el)
|
||||
//非第一条并且列表不存在直接加入列表
|
||||
}
|
||||
});
|
||||
fetch()
|
||||
}, [], { minNum: 1, search_text: val, store_id: defaultStoreId, })
|
||||
}
|
||||
} else {
|
||||
layer.msg('请输入内容');
|
||||
}
|
||||
}
|
||||
});
|
||||
$('.stock-search').val('').focus()
|
||||
form.render();
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
form.render();
|
||||
syncData();
|
||||
}
|
||||
//输入回车后的处理,查询到单条的处理
|
||||
function carriage(index, val) {
|
||||
var num = true
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/getskulist"),
|
||||
data: { search: val, store_id: defaultStoreId },
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
async: false,
|
||||
success: function (res) {
|
||||
|
||||
if (res.data.length != 1) {
|
||||
//不是一条数据返回true,打开弹框
|
||||
num = true
|
||||
return false
|
||||
}
|
||||
num = false
|
||||
var data = res.data[0]
|
||||
data.goods_num = 1
|
||||
data.goods_price = data.cost_price || 0
|
||||
var indexs = stockData.length ? stockData.findIndex(v => v.sku_id === data.sku_id) : -1
|
||||
if (index != -1) {
|
||||
//数据行
|
||||
if (indexs != -1) {
|
||||
//库存盘点/先判断是否存在
|
||||
stockData[indexs].goods_num += 1
|
||||
//存在数量累加
|
||||
} else {
|
||||
stockData.splice(index, 1, data)
|
||||
}
|
||||
|
||||
} else {
|
||||
//空白行
|
||||
var indexs = stockData.length ? stockData.findIndex(v => v.sku_id === data.sku_id) : -1
|
||||
if (indexs != -1) {
|
||||
//库存盘点/先判断是否存在
|
||||
stockData[indexs].goods_num += 1
|
||||
//存在数量累加
|
||||
} else {
|
||||
stockData.push(data)
|
||||
}
|
||||
|
||||
}
|
||||
fetch()
|
||||
}
|
||||
})
|
||||
return num
|
||||
}
|
||||
function dataChange(obj) {
|
||||
syncData();
|
||||
}
|
||||
|
||||
function syncData() {
|
||||
var count_num = 0, goods_money = 0;
|
||||
var kinds_data = [];
|
||||
$('.stock-tr').each(function (index) {
|
||||
var obj = $(this);
|
||||
var goods_sku_id = stockData[index].sku_id;
|
||||
|
||||
var goods_num = parseFloat(obj.find('input[name=goods_num]').val()) || 0;
|
||||
if (kinds_data.indexOf(goods_sku_id) == -1) {
|
||||
kinds_data.push(goods_sku_id)
|
||||
}
|
||||
//重新采集数据
|
||||
//库存数量
|
||||
|
||||
stockData[index].goods_num = goods_num;
|
||||
//库存价格
|
||||
var goods_price = stockData[index].cost_price;
|
||||
|
||||
count_num += goods_num;
|
||||
goods_money += goods_num * goods_price;
|
||||
obj.find('.total-cost-money').text(parseFloat(goods_num * goods_price).toFixed(2));
|
||||
});
|
||||
$(".kinds-num").text(parseInt(kinds_data.length));
|
||||
$(".count-num").text(parseFloat(count_num));
|
||||
$(".goods-money").text(parseFloat(goods_money).toFixed(2));
|
||||
}
|
||||
|
||||
function reset() {
|
||||
stockData = [];
|
||||
fetch();
|
||||
syncData();
|
||||
}
|
||||
|
||||
function delTr(obj) {
|
||||
var parent = $(obj).parents('.stock-tr');
|
||||
// parent.remove();
|
||||
|
||||
var key = parent.data('key');
|
||||
//唯一值 (sku_id不承担)
|
||||
stockData.splice(key, 1);
|
||||
//由于key使用index,index不会随dom操作变换移除行会出错需要在删除时重新渲染
|
||||
fetch()
|
||||
}
|
||||
function editBtn(val) {
|
||||
goodsSelectByAllocate(function (res) {
|
||||
if (val === 'btn') {
|
||||
//空白行btn选择
|
||||
res.forEach(el => {
|
||||
el.goods_num = 1
|
||||
el.goods_price = el.price || 0
|
||||
|
||||
var index = stockData.length ? stockData.findIndex(v => v.sku_id === el.sku_id) : -1
|
||||
if (index != -1) {
|
||||
//库存盘点/先判断是否存在
|
||||
stockData[index].goods_num += 1
|
||||
//存在数量累加
|
||||
} else {
|
||||
stockData.push(el)
|
||||
}
|
||||
});
|
||||
} else {
|
||||
//数据行btn选择
|
||||
var parent = $(val).parents('.stock-tr');
|
||||
var key = parent.data('key');
|
||||
//唯一值 (sku_id不承担)
|
||||
res.forEach((el, index) => {
|
||||
//循环选中的数据
|
||||
el.goods_num = 1
|
||||
el.goods_price = el.price || 0
|
||||
//库存盘点
|
||||
var indexs = stockData.length ? stockData.findIndex(v => v.sku_id === el.sku_id) : -1
|
||||
if (indexs != -1) {
|
||||
//优先判断是否存在
|
||||
stockData[indexs].goods_num += 1
|
||||
} else if (!index) {
|
||||
//不存在选中数据第一条替换btn点击行
|
||||
stockData.splice(key, 1, el)
|
||||
} else {
|
||||
stockData.push(el)
|
||||
//其它直接加入
|
||||
}
|
||||
});
|
||||
}
|
||||
fetch()
|
||||
}, [], { minNum: 1, search_text: '', store_id: defaultStoreId, })
|
||||
|
||||
}
|
||||
/**
|
||||
* 商品选择器
|
||||
* @param callback 回调函数
|
||||
* @param selectId 已选商品id
|
||||
* @param params mode:模式(spu、sku), max_num:最大数量,min_num 最小数量, is_virtual 是否虚拟 0 1, disabled: 开启禁用已选 0 1,promotion:营销活动标识 pintuan、groupbuy、fenxiao (module 表示组件) is_disabled_goods_type: 1表示关闭商品类型筛选 0表示开启商品类型筛选 goods_type: 1 实物商品 2虚拟商品 3电子商品 不传查全部
|
||||
*/
|
||||
function goodsSelectByAllocate(callback, selectId, params = {}) {
|
||||
layui.use(['layer'], function () {
|
||||
localStorage.removeItem('goods_select_id'); // 删除选中id 本地缓存
|
||||
if (selectId.length) {
|
||||
localStorage.setItem('goods_select_id', selectId.toString());
|
||||
}
|
||||
|
||||
params.mode = params.mode ? params.mode : 'spu';
|
||||
if (params.disabled == undefined || params.disabled == 0) {
|
||||
params.disabled = 0;
|
||||
} else {
|
||||
params.disabled = 1;
|
||||
}
|
||||
params.site_id = ns_url.siteId;
|
||||
params.app_module = ns_url.appModule;
|
||||
params.is_disabled_goods_type = params.is_disabled_goods_type || 0;
|
||||
params.goods_type = params.goods_type || "";
|
||||
params.max_num = params.max_num || 200; // 最多选择数量
|
||||
params.search_text = params.search_text || ''
|
||||
// if(!params.post) params.post = 'shop';
|
||||
|
||||
// if (params.post == 'store') params.post += '://store';
|
||||
|
||||
var url = ns.url("stock://shop/stock/goodsSelect?request_mode=iframe", params);
|
||||
layer.open({
|
||||
title: "商品选择",
|
||||
type: 2,
|
||||
area: ['1000px', '720px'],
|
||||
fixed: false, //不固定
|
||||
btn: ['选中', '返回'],
|
||||
content: url,
|
||||
btn1: function (index, layero) {
|
||||
var iframeWin = document.getElementById(layero.find('iframe')[0]['name']).contentWindow;//得到iframe页的窗口对象,执行iframe页的方法:
|
||||
iframeWin.selectGoodsListener(function (obj) {
|
||||
if (typeof callback == "string") {
|
||||
try {
|
||||
eval(callback + '(obj)');
|
||||
if (!obj.length) return false
|
||||
layer.close(index);
|
||||
} catch (e) {
|
||||
console.error('回调函数' + callback + '未定义');
|
||||
}
|
||||
} else if (typeof callback == "function") {
|
||||
callback(obj);
|
||||
if (!obj.length) return false
|
||||
layer.close(index);
|
||||
}
|
||||
|
||||
});
|
||||
return false
|
||||
},
|
||||
btn2: function (index, layero) {
|
||||
layer.close(index);
|
||||
return false
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function setStore() {
|
||||
var output_store_id = $('[name="output_store_id"]').val();
|
||||
let html = '';
|
||||
$.each(store_list, function (i, e) {
|
||||
if (e.store_id != output_store_id) {
|
||||
html += '<option value="' + e.store_id + '">' + e.store_name + '</option>';
|
||||
}
|
||||
});
|
||||
|
||||
$('[name="input_store_id"]').html(html);
|
||||
form.render();
|
||||
}
|
||||
</script>
|
||||
204
addon/stock/shop/view/stock/edit_check.html
Executable file
204
addon/stock/shop/view/stock/edit_check.html
Executable file
@@ -0,0 +1,204 @@
|
||||
<link rel="stylesheet" type="text/css" href="ADDON_STOCK_CSS/stock.css" />
|
||||
<style>
|
||||
.stock-title-body{
|
||||
position: relative;
|
||||
}
|
||||
.stock-title-body span{
|
||||
position: absolute;
|
||||
top:5px;
|
||||
right:5px;
|
||||
background-color: #fff;
|
||||
z-index: 10;
|
||||
cursor: pointer;
|
||||
}
|
||||
.stock-title-body input{
|
||||
padding-right: 25px;
|
||||
}
|
||||
input.stock-search{
|
||||
border-width: 0;
|
||||
}
|
||||
input.stock-search:focus{
|
||||
border-width: 1px;
|
||||
}
|
||||
.layui-table th,.layui-table td{
|
||||
padding: 7px 30px !important;
|
||||
}
|
||||
.layui-table .layui-input{
|
||||
height: 28px !important;
|
||||
}
|
||||
/* input.stock-search:focus+span{
|
||||
display: block;
|
||||
} */
|
||||
.goods-up{
|
||||
color: #15eb26;
|
||||
}
|
||||
.goods-down{
|
||||
color: red;
|
||||
}
|
||||
button[lay-filter='save'] .layui-icon-loading {
|
||||
animation: loding-rotate 1s linear infinite; /* 设置动画效果 */
|
||||
transform-origin: center;
|
||||
display: inline-block;
|
||||
}
|
||||
.remark{
|
||||
width: 611px;
|
||||
}
|
||||
@keyframes loding-rotate {
|
||||
0% { transform: rotate(0); } /* 起始位置 */
|
||||
100% { transform: rotate(360deg); } /* 结束位置,旋转一周 */
|
||||
}
|
||||
</style>
|
||||
<div class="layui-form form" lay-filter="formTest">
|
||||
<div class="stock-view">
|
||||
{if $stock_config.is_audit == 1}
|
||||
<div class="tips text-color">说明:待审核状态下只有经办人允许修改,只有变为已审核状态后才会使库存发生变化,已审核状态的单据不允许再修改。</div>
|
||||
{/if}
|
||||
<div class="store-view">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">盘点单号:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
{if isset($inventory_info)}
|
||||
<input type="text" value="{$inventory_info['inventory_no']}" name="inventory_no" class="layui-input len-mid">
|
||||
{else /}
|
||||
<input type="text" value="{$inventory_no}" name="inventory_no" class="layui-input len-mid">
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label"><span class="required">*</span>门店:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
<select name="store_id" lay-verify="required" lay-filter="store_list" class="len-mid" >
|
||||
<option value="">请选择</option>
|
||||
{foreach $store_list as $store_k => $store_v}
|
||||
{if isset($inventory_info)}
|
||||
<option value="{$store_v.store_id}" {if $inventory_info['store_id']==$store_v['store_id']}selected {php} $default_store_id=$store_v['store_id']; {/php}{/if}>{$store_v.store_name}</option>
|
||||
{else /}
|
||||
<option value="{$store_v.store_id}" {if $store_k == 0}selected {php} $default_store_id = $store_v['store_id']; {/php}{/if}>{$store_v.store_name}</option>
|
||||
{/if}
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">盘点时间:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
<input type="text" class="layui-input" name="date_time" value="{$inventory_info ? time_to_date($inventory_info['action_time']) : date('Y-m-d H:i:s')}" placeholder="盘点时间" id="date_time" readonly>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">当前操作人:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
<span>{$user_info['username']}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label"><span class="required"></span>备注:</label>
|
||||
<div class="layui-input-block remark">
|
||||
<textarea class="layui-textarea" maxlength="100" name="remark" placeholder="请输入备注">{$inventory_info['remark'] ?? ''}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="layui-table" lay-size="lg">
|
||||
<colgroup>
|
||||
<col width="450">
|
||||
<col width="120">
|
||||
<col width="120">
|
||||
<col>
|
||||
<col width="200">
|
||||
<col width="120">
|
||||
<col width="90">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>商品名称/规格/编码</th>
|
||||
<th>当前库存</th>
|
||||
<th>销售库存</th>
|
||||
<th>单位</th>
|
||||
<th>实盘数量</th>
|
||||
<th>盈亏数量</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="stock-body">
|
||||
<tr class="stock-search-line">
|
||||
<td class="stock-search-block">
|
||||
<div class="stock-title-body">
|
||||
<input type="text" class="layui-input stock-search" placeholder="请输入产品名称/规格/编码" />
|
||||
<span class="iconfont icontuodong" onclick="editBtn('btn')"></span>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="8" class="total-data">合计: 共<span class="kinds-num">0</span>种商品, 盘盈:<span class="goods-up">0</span>种, 盘亏:<span class="goods-down">0</span>种, 持平:<span class="goods-same">0</span>种</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
{notempty name="$inventory_info"}
|
||||
<input type="hidden" name="inventory_id" value="{$inventory_info['inventory_id']}">
|
||||
<input type="hidden" name="inventory_goods_list" value='{:json_encode($inventory_info["goods_list"])}'>
|
||||
{/notempty}
|
||||
|
||||
<div class="form-row">
|
||||
<button class="layui-btn" lay-submit lay-filter="save"><span class="layui-icon"></span>提交</button>
|
||||
<button class="layui-btn layui-btn-primary" onclick="backStockAction()">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="stock_goods_info">
|
||||
<tr class="stock-tr" data-key='{{ d.index }}'>
|
||||
<td>
|
||||
{{d.sku_name}}
|
||||
</td>
|
||||
<!-- 库存 -->
|
||||
<td>{{ d.real_stock || 0 }}</td>
|
||||
<td>{{ d.stock || 0 }}</td>
|
||||
<!-- 单位 -->
|
||||
<td>{{ d.unit || '件' }}</td>
|
||||
<!-- 数量 -->
|
||||
<td>
|
||||
<input type="number" class="layui-input stock-num" name="goods_num" value="{{ d.goods_num || '' }}" placeholder="0" onchange="dataChange(this)"/>
|
||||
</td>
|
||||
|
||||
<!-- 成本总价 -->
|
||||
<td>
|
||||
<span class="compare-num">0</span>
|
||||
</td>
|
||||
<td>
|
||||
<a class="text-color action-btn" onclick="delTr(this)">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var stockDataObj = JSON.parse($("input[name='inventory_goods_list']").val() || '{}');// 库存数据
|
||||
var stockData = Object.values(stockDataObj)
|
||||
var defaultStoreId = {$default_store_id ?? 0};
|
||||
var stockConfig = {:json_encode($stock_config)};
|
||||
var stockAction = {
|
||||
id:'inventory_id',
|
||||
listRoute: 'check', // 库存操作标识,storage:入库,wastage:出库
|
||||
saveRoute: 'editcheck', // 保存地址
|
||||
params:{
|
||||
'inventory_no':$('input[name="inventory_no"]'),
|
||||
'time':$('input[name="date_time"]'),
|
||||
'remark':$('textarea[name="remark"]')
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<script src="ADDON_STOCK_JS/stock_action.js?time=20250111"></script>
|
||||
201
addon/stock/shop/view/stock/export.html
Executable file
201
addon/stock/shop/view/stock/export.html
Executable file
@@ -0,0 +1,201 @@
|
||||
<style>
|
||||
.layui-card-header{background-color:#f8f8f8}
|
||||
.apply-time{
|
||||
float:left;
|
||||
}
|
||||
.export-select{float:left;}
|
||||
.download-button{
|
||||
float:right;
|
||||
}
|
||||
.export-list-view{
|
||||
font-size:12px;
|
||||
}
|
||||
.export-foot-operation{overflow:hidden;margin-top:15px;}
|
||||
|
||||
.export-page{
|
||||
float:right;
|
||||
}
|
||||
.export-content-bar{
|
||||
float:left;
|
||||
padding-top: 6px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
.export-foot-operation .layui-btn {
|
||||
padding: 0px 5px;
|
||||
font-size: 12px;
|
||||
line-height: 2 !important;
|
||||
height: auto;
|
||||
display: inline-block;
|
||||
}
|
||||
.layui-unselect.layui-form-checkbox{
|
||||
margin-top:-5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="layui-layout layui-layout-admin">
|
||||
<div class="body-content">
|
||||
<div id="export_list"></div>
|
||||
|
||||
<div class="export-foot-operation">
|
||||
<div class="export-content-bar layui-form bg-color-light-gray">
|
||||
<input type="checkbox" name="export_select" lay-filter="allChoose" lay-skin="primary" title="全选">
|
||||
</div>
|
||||
<button class="layui-btn layui-btn-primary" onclick="deleteExport()">批量删除</button>
|
||||
<div class='export-page' id="export_page"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="exportHtml">
|
||||
{{# layui.each(d.data.list, function(index, item){ }}
|
||||
<div class="layui-card export-list-view">
|
||||
<div class="layui-card-header">
|
||||
|
||||
<div class="layui-form export-select">
|
||||
<input type="checkbox" name="check[]" value="{{item.export_id}}" lay-skin="primary" title="">
|
||||
</div>
|
||||
<div class="apply-time">序号:{{ item.export_id }} 导出时间:{{ ns.time_to_date(item.create_time) }}</div>
|
||||
<div class="download-button">
|
||||
{{# if(item.status == 0){ }}
|
||||
<span>正在导出中,请耐心等待…</span>
|
||||
{{# }else{ }}
|
||||
{{# if(item.path != ''){ }}
|
||||
<a class="text-color" href="{{ ns.img(item.path) }}" target="_blank">下载</a>
|
||||
{{#}}}
|
||||
{{#}}}
|
||||
<a class="text-color" href="javascript:void(0)" data-export_id ="{{item.export_id}}" onclick="deleteExport(this)">删除</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-row layui-col-space10">
|
||||
{{# layui.each(JSON.parse(item.condition), function(condition_index, condition_item){ }}
|
||||
<div class="layui-col-md3">
|
||||
{{condition_item.name}}:{{condition_item.value || '-'}}
|
||||
</div>
|
||||
{{# }); }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{# }); }}
|
||||
{{# if(d.data.list.length === 0){ }}
|
||||
<div class="layui-card export-list-view">
|
||||
<div class="layui-card-header">
|
||||
<div class="apply-time">商品导出记录</div>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-row layui-col-space10">
|
||||
<div class="layui-col-md3">暂无导出记录</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{# } }}
|
||||
|
||||
</script>
|
||||
<script>
|
||||
var laypage,form;
|
||||
layui.use(['form', 'laytpl', 'laypage'], function() {
|
||||
form = layui.form;
|
||||
laytpl = layui.laytpl;
|
||||
form.render();
|
||||
exportList(1,10);
|
||||
|
||||
laypage = layui.laypage;
|
||||
|
||||
/**
|
||||
* 全选
|
||||
*/
|
||||
form.on("checkbox(allChoose)", function(data) {
|
||||
$("input[name='check[]']").each(function() {
|
||||
this.checked = data.elem.checked;
|
||||
});
|
||||
form.render('checkbox');
|
||||
})
|
||||
});
|
||||
|
||||
function exportList(page, limit){
|
||||
$.ajax({
|
||||
url: '{:addon_url("stock://shop/stock/export")}',
|
||||
data: {
|
||||
limit,
|
||||
page
|
||||
},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
var export_template = $("#exportHtml").html();
|
||||
|
||||
if(res.code >= 0){
|
||||
laytpl(export_template).render(res, function (html) {
|
||||
$("#export_list").html(html);
|
||||
})
|
||||
}
|
||||
laypage.render({
|
||||
elem: 'export_page',
|
||||
count: res.data.count,
|
||||
curr: page, //当前页
|
||||
limit: limit,
|
||||
jump: function(obj, first){
|
||||
//obj包含了当前分页的所有参数,比如:
|
||||
//首次不执行
|
||||
if(!first){
|
||||
exportList(obj.curr, obj.limit);
|
||||
form.render();
|
||||
}
|
||||
}
|
||||
});
|
||||
form.render();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除导出记录
|
||||
*/
|
||||
var flag_delete = false;
|
||||
function deleteExport(data) {
|
||||
var export_ids = [];
|
||||
|
||||
if (!data) {
|
||||
$("input[name='check[]']:checked").each(function (index, item) {
|
||||
export_ids.push($(item).val());
|
||||
});
|
||||
} else {
|
||||
export_ids.push($(data).attr("data-export_id"));
|
||||
}
|
||||
|
||||
if (export_ids.length == 0) {
|
||||
layer.msg('请选择要操作的数据');
|
||||
return;
|
||||
}
|
||||
|
||||
export_ids = export_ids.toString();
|
||||
|
||||
layer.confirm('确定要删除选择的商品导出记录吗?', {
|
||||
btn: ['确定', '取消']
|
||||
}, function (index) {
|
||||
if (flag_delete) return;
|
||||
flag_delete = true;
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
async: true,
|
||||
url: ns.url("stock://shop/stock/deleteExport"),
|
||||
data: {
|
||||
export_ids: export_ids,
|
||||
},
|
||||
dataType: "JSON",
|
||||
success: function (data) {
|
||||
layer.msg(data.message);
|
||||
if (data.code == 0) {
|
||||
listenerHash(); // 刷新页面
|
||||
} else {
|
||||
flag_delete = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}, function () {
|
||||
layer.close();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
84
addon/stock/shop/view/stock/goods_select.html
Executable file
84
addon/stock/shop/view/stock/goods_select.html
Executable file
@@ -0,0 +1,84 @@
|
||||
<link rel="stylesheet" href="SHOP_CSS/goods_select.css">
|
||||
|
||||
<div class="select-goods">
|
||||
|
||||
<!-- 左侧固定展示商品分类 -->
|
||||
<div class="select-goods-left">
|
||||
<div class="select-goods-classification layui-collapse" lay-accordion lay-filter="oneCategory">
|
||||
<div class="layui-colla-item">
|
||||
<h2 class="layui-colla-title classification-item text-color" data-category_id="">全部分类</h2>
|
||||
</div>
|
||||
{foreach $category_list as $category_one_item}
|
||||
<div class="layui-colla-item">
|
||||
<h2 class="layui-colla-title classification-item {notempty name="$category_one_item.children"}arrow{/notempty}" data-category_id="{$category_one_item.category_id}">{$category_one_item.title}</h2>
|
||||
{notempty name="category_one_item.children"}
|
||||
{foreach $category_one_item.children as $category_two_item}
|
||||
<div class="layui-colla-content">
|
||||
<div class="select-goods-classification layui-collapse" lay-accordion lay-filter="twoCategory">
|
||||
<div class="layui-colla-item">
|
||||
<h2 class="layui-colla-title classification-item {notempty name="category_two_item.children"}arrow{/notempty}" data-category_id="{$category_two_item.category_id}">{$category_two_item.title}</h2>
|
||||
{notempty name="category_two_item.children"}
|
||||
{foreach $category_two_item.children as $category_three_item}
|
||||
<div class="layui-colla-content classification-item" data-category_id="{$category_three_item.category_id}">{$category_three_item.title}</div>
|
||||
{/foreach}
|
||||
{/notempty}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/foreach}
|
||||
{/notempty}
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧固定展示筛选和商品列表 -->
|
||||
<div class="select-goods-right">
|
||||
|
||||
<!-- 筛选 -->
|
||||
<div class="single-filter-box">
|
||||
<div></div>
|
||||
<div class="layui-form">
|
||||
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" value="{$search_text}" name="search_text" placeholder="请输入商品名称或编码" autocomplete="off" class="layui-input len-mid">
|
||||
<button type="button" class="layui-btn layui-btn-primary" lay-filter="search" lay-submit>
|
||||
<i class="layui-icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- 分类id -->
|
||||
<input type="hidden" name="category_id" value=""/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 列表 -->
|
||||
<table id="goods_list" lay-filter="goods_list"></table>
|
||||
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="maxNum" value="{$max_num}" title="最大商品数量" />
|
||||
<input type="hidden" name="minNum" value="{$min_num}" title="最小商品数量" />
|
||||
<input type="hidden" name="disabled" value="{$disabled}" title="不可选中" />
|
||||
<input type="hidden" name="search_text" value="{$search_text}" title="请输入商品名称或编码" />
|
||||
<input type="hidden" name="store_id" value="{$store_id}" title="store_id" />
|
||||
<input type="hidden" name="goods_class" value="{$goods_class}" title="商品类型" />
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="checkbox">
|
||||
<input type="checkbox" data-sku-id="{{d.sku_id}}" name="goods_checkbox" lay-skin="primary" lay-filter="goods_checkbox" {{goodsSelectObj.goodsIdArr.indexOf(d.sku_id.toString()) > -1 ? 'checked' : ''}}>
|
||||
<input type="hidden" data-sku-id="{{d.sku_id}}" name="goods_json" value='{{ JSON.stringify(d) }}' />
|
||||
</script>
|
||||
|
||||
<!-- 商品信息 -->
|
||||
<script type="text/html" id="goods_info">
|
||||
<div class="table-title">
|
||||
<div class="title-pic" id="goods_img_{{d.goods_id}}">
|
||||
<img layer-src src="{{ns.img(d.sku_image, 'small')}}"/>
|
||||
</div>
|
||||
<div class="title-content">
|
||||
<a href="javascript:;" class="multi-line-hiding text-color" title="{{d.sku_name}}">{{d.sku_name}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script src="ADDON_STOCK_JS/goods_select.js?time=2"></script>
|
||||
153
addon/stock/shop/view/stock/input_detail.html
Executable file
153
addon/stock/shop/view/stock/input_detail.html
Executable file
@@ -0,0 +1,153 @@
|
||||
<style>
|
||||
.layui-table .layui-btn{
|
||||
justify-content: flex-end;
|
||||
padding-right: 0px;
|
||||
}
|
||||
.name{
|
||||
display: flex;
|
||||
align-content: center;
|
||||
}
|
||||
.name img{
|
||||
max-width: inherit;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="layui-form" lay-filter="storeform">
|
||||
<div class="layui-card card-common card-brief">
|
||||
<div class="layui-card-header">
|
||||
<span class="card-title">基本信息</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-row">
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">制单人:</label>
|
||||
<div class="layui-input-block">{$document_detail.operater_name}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">关联单据:</label>
|
||||
<div class="layui-input-block">{$document_detail.type_name}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">制单时间:</label>
|
||||
<div class="layui-input-block">{$document_detail.create_time}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注:</label>
|
||||
<div class="layui-input-block">{$document_detail.remark}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-col-md3">
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态:</label>
|
||||
<div class="layui-input-block">{$document_detail.status_data.name}</div>
|
||||
</div>
|
||||
{if !empty($document_detail.verifier_name) }
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">审核人:</label>
|
||||
<div class="layui-input-block">{$document_detail.verifier_name}</div>
|
||||
</div>
|
||||
{/if}
|
||||
{if !empty($document_detail.audit_time) }
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">审核时间:</label>
|
||||
<div class="layui-input-block">{$document_detail.audit_time}</div>
|
||||
</div>
|
||||
{/if}
|
||||
{if $document_detail.status == -1}
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">拒绝理由:</label>
|
||||
<div class="layui-input-block">{$document_detail.refuse_reason}</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">入库门店:</label>
|
||||
<div class="layui-input-block">{$document_detail.store_name}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">入库单号:</label>
|
||||
<div class="layui-input-block">{$document_detail.document_no}</div>
|
||||
</div>
|
||||
|
||||
{if $document_detail.time > 0}
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">入库时间:</label>
|
||||
<div class="layui-input-block">{$document_detail.time}</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-card card-common card-brief">
|
||||
<div class="layui-card-header">
|
||||
<span class="card-title">商品明细</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<table class="layui-table order_goods_list" lay-filter="order_goods" lay-skin="line">
|
||||
<colgroup>
|
||||
<col width="30%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>商品名称/条形码</th>
|
||||
<th>规格</th>
|
||||
<th>单位</th>
|
||||
<th>数量</th>
|
||||
<th>成本价(元)</th>
|
||||
<th>金额(元)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<table class="layui-table order_goods_list order_goods_list-bottom" lay-skin="line" lay-filter="order_goods_list">
|
||||
<colgroup>
|
||||
<col width="30%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
{foreach $document_detail.goods_sku_list_array as $k => $v}
|
||||
<tr class="table-tr">
|
||||
<td class="name">
|
||||
<img src="{:img($v.goods_sku_img,'small')}" alt="">
|
||||
<span>{$v.goods_sku_name}</span>
|
||||
</td>
|
||||
{if $v.goods_sku_spec && $v.goods_sku_spec !=''}
|
||||
<td>{$v.goods_sku_spec}</td>
|
||||
{else/}
|
||||
<td>-</td>
|
||||
{/if}
|
||||
{if $v.goods_unit && $v.goods_unit !=''}
|
||||
<td>{$v.goods_unit}</td>
|
||||
{else/}
|
||||
<td>件</td>
|
||||
{/if}
|
||||
<td>{$v.goods_num}</td>
|
||||
<td>{$v.goods_price}</td>
|
||||
<td>{$v.goods_sum}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
<label style="display: flex;justify-content: flex-end;padding-right: 13px;">合计:共{$document_detail.goods_count}种商品{$document_detail.goods_price}件,合计金额:<span style="color: #ff0000;">{$document_detail.goods_total_price}</span></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
190
addon/stock/shop/view/stock/inventory_detail.html
Executable file
190
addon/stock/shop/view/stock/inventory_detail.html
Executable file
@@ -0,0 +1,190 @@
|
||||
<style>
|
||||
.name {
|
||||
display: flex;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.name img {
|
||||
max-width: inherit;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="layui-form" lay-filter="storeform">
|
||||
<div class="layui-card card-common card-brief">
|
||||
<div class="layui-card-header">
|
||||
<span class="card-title">基本信息</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-row">
|
||||
|
||||
<div class="layui-col-md6">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">制单人:</label>
|
||||
<div class="layui-input-block">{$inventory_detail.operater_name}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-col-md6">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态:</label>
|
||||
<div class="layui-input-block">{$inventory_detail.status_name}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-col-md6">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">盘点单号:</label>
|
||||
<div class="layui-input-block">{$inventory_detail.inventory_no}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{if $inventory_detail.verifier_name }
|
||||
<div class="layui-col-md6">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">审核人:</label>
|
||||
<div class="layui-input-block">{$inventory_detail.verifier_name}</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="layui-col-md6">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">制单时间:</label>
|
||||
<div class="layui-input-block">{$inventory_detail.create_time}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-col-md6">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">盘点时间:</label>
|
||||
<div class="layui-input-block">{$inventory_detail.action_time}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md6">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注:</label>
|
||||
<div class="layui-input-block">{$inventory_detail.remark}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{if $inventory_detail.audit_time }
|
||||
<div class="layui-col-md6">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">审核时间:</label>
|
||||
<div class="layui-input-block">{$inventory_detail.audit_time}</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if $inventory_detail.status == -1 }
|
||||
<div class="layui-col-md6">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">拒绝理由:</label>
|
||||
<div class="layui-input-block">{$inventory_detail.refuse_reason}</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-card card-common card-brief">
|
||||
<div class="layui-card-header">
|
||||
<span class="card-title">商品明细</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<table class="layui-table order_goods_list" lay-filter="order_goods" lay-skin="line" lay-filter="order_goods_list">
|
||||
<div class="layui-tab-content layui-tab" lay-filter="list_tab">
|
||||
<ul class="layui-tab-title tab-status">
|
||||
<li id="all" data-type="state" class="layui-this">全部</li>
|
||||
<li id="1" data-type="state">盘盈</li>
|
||||
<li id="-1" data-type="state">盘亏</li>
|
||||
<li id="0" data-type="state">持平</li>
|
||||
</ul>
|
||||
</div>
|
||||
<colgroup>
|
||||
<col width="20%"/>
|
||||
<col width="8%"/>
|
||||
<col width="8%"/>
|
||||
<col width="8%"/>
|
||||
<col width="8%"/>
|
||||
<col width="8%"/>
|
||||
<col width="10%"/>
|
||||
<!--<col width="10%" />-->
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>商品名称/条形码</th>
|
||||
<th style="text-align: right;">商品规格</th>
|
||||
<th style="text-align: right;">单位</th>
|
||||
<th style="text-align: right;">实物库存</th>
|
||||
<th style="text-align: right;">实盘数量</th>
|
||||
<th style="text-align: right;">盈亏数量</th>
|
||||
<th style="text-align: right;">盈亏成本总额(元)</th>
|
||||
<!--<th style="text-align: right;">盈亏销售总额(元)</th>-->
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<table class="layui-table order_goods_list order_goods_list-bottom" lay-skin="line" lay-filter="order_goods_list">
|
||||
<colgroup>
|
||||
<col width="20%"/>
|
||||
<col width="8%"/>
|
||||
<col width="8%"/>
|
||||
<col width="8%"/>
|
||||
<col width="8%"/>
|
||||
<col width="8%"/>
|
||||
<col width="10%"/>
|
||||
<!--<col width="10%" />-->
|
||||
</colgroup>
|
||||
<tbody>
|
||||
{foreach $inventory_detail.goods_sku_list_array as $k => $v}
|
||||
<tr class="table-tr" data-state="{if $v.profitloss_num == 0}0{/if}{if $v.profitloss_num > 0}1{/if}{if $v.profitloss_num < 0}-1{/if}">
|
||||
<td class="name">
|
||||
<img src="{:img($v.goods_img,'small')}" alt="">
|
||||
<span>{$v.goods_sku_name}</span>
|
||||
</td>
|
||||
{if $v.goods_sku_spec && $v.goods_sku_spec !=''}
|
||||
<td>{$v.goods_sku_spec}</td>
|
||||
{else/}
|
||||
<td>-</td>
|
||||
{/if}
|
||||
{if $v.goods_unit && $v.goods_unit !=''}
|
||||
<td style="text-align: right;">{$v.goods_unit}</td>
|
||||
{else/}
|
||||
<td style="text-align: right;">件</td>
|
||||
{/if}
|
||||
<td style="text-align: right;">{$v.stock}</td>
|
||||
<td style="text-align: right;">{$v.inventory_num}</td>
|
||||
<td style="text-align: right;" id="profitloss_num">{$v.profitloss_num}</td>
|
||||
<td style="text-align: right;">{$v.inventory_cost_money}</td>
|
||||
<!--<td style="text-align: right;">{$v.profitloss_sale_money}</td>-->
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
<label style="display: flex;justify-content: flex-end;padding-right: 13px;">合计:共{$inventory_detail.goods_count}种商品,实盘{$inventory_detail.kinds_num}种, 盘盈:<span style="color: #ff0000;">{$inventory_detail.kinds_profit_num}</span>, 盘亏:<span style="color: #15eb26;">{$inventory_detail.kinds_loss_num}</span>,持平:{$inventory_detail.kinds_even_num}种</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
layui.use(['form', 'laytpl', 'element'], function () {
|
||||
var form = layui.form;
|
||||
laytpl = layui.laytpl;
|
||||
element = layui.element;
|
||||
|
||||
element.on('tab(list_tab)', function () {
|
||||
var state = $(this).attr('id');
|
||||
if (state == 'all') {
|
||||
$(".table-tr").show();
|
||||
} else {
|
||||
$(".table-tr").hide();
|
||||
$(".table-tr[data-state='" + state + "']").show();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
286
addon/stock/shop/view/stock/manage.html
Executable file
286
addon/stock/shop/view/stock/manage.html
Executable file
@@ -0,0 +1,286 @@
|
||||
<link rel="stylesheet" type="text/css" href="STATIC_EXT/searchable_select/searchable_select.css" />
|
||||
<link rel="stylesheet" type="text/css" href="__STATIC__/ext/layui/extend/cascader/cascader.css"/>
|
||||
<link rel="stylesheet" href="__ADDON__/stock/site/css/goods_lists.css">
|
||||
|
||||
<div class="main-wrap">
|
||||
<div class="content_full">
|
||||
<div class="screen layui-collapse margin-bot" lay-filter="selection_panel">
|
||||
<div class="layui-colla-item">
|
||||
<div class="layui-colla-content layui-form layui-show" lay-filter="order_list">
|
||||
<div class="layui-form-item">
|
||||
<div class="classification">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">商品名称/编码:</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="search_text" autocomplete="off" placeholder="请输入商品名称/编码" class="layui-input" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">商品分类</label>
|
||||
<div class="layui-input-inline category-wrap">
|
||||
<input type="text" autocomplete="off" show="false" class="layui-input select-category" placeholder="请选择" readonly="">
|
||||
<input type="hidden" name="category_id">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="classification">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">库存:</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="number" name="min_stock" id="start_sale" lay-verify="int" min="0" placeholder="最低库存" class="layui-input" autocomplete="off">
|
||||
</div>
|
||||
<div class="layui-form-mid">-</div>
|
||||
<div class="layui-input-inline">
|
||||
<input type="number" name="max_stock" id="end_sale" lay-verify="int" min="0" placeholder="最高库存" class="layui-input" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">门店:</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="store_id" lay-filter="store_list" class="len-mid">
|
||||
<option value="">全部</option>
|
||||
{foreach $store_list as $store_k => $store_v}
|
||||
<option value="{$store_v.store_id}">{$store_v.store_name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
<input type="hidden" name="store_name"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="goods_state" value="{$goods_state}"/>
|
||||
<div class="form-row">
|
||||
<button class="layui-btn" lay-submit lay-filter="search">筛选</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
<button class="layui-btn layui-btn-primary" lay-submit lay-filter="batch_export_stock">导出商品</button>
|
||||
<a class="layui-btn layui-btn-primary" href="{:href_url('stock://shop/stock/export')}" target="_blank">查看导出记录</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 批量操作时判断是否为当前选项,防止重复点击 -->
|
||||
<input type="hidden" name="openSwitch" lay-type="grouping" value="">
|
||||
</div>
|
||||
|
||||
<div class="layui-tab table-tab" lay-filter="goods_list_tab">
|
||||
<ul class="layui-tab-title">
|
||||
<li {if $goods_state=='' }class="layui-this" {/if} lay-id="">全部</li>
|
||||
<li {if $goods_state=='1' }class="layui-this" {/if} lay-id="1">销售中</li>
|
||||
<li {if $goods_state=='0' }class="layui-this" {/if} lay-id="0">仓库中</li>
|
||||
</ul>
|
||||
<div class="layui-tab-content" style="margin-top: 15px;">
|
||||
<table id="goods_list" lay-filter="goods_list"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/html" id="goods_detail">
|
||||
<div class='table-title'>
|
||||
<div class='title-pic'>
|
||||
<img layer-src src="{{ns.img(d.sku_image, 'small')}}">
|
||||
</div>
|
||||
<div class='title-content'>
|
||||
<p class="layui-elip" style="color: #333;" title="{{d.goods_name}}">{{d.goods_name}}</p>
|
||||
<p class="layui-elip">{{d.spec_name}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="operation">
|
||||
<div class="table-btn">
|
||||
<a class="layui-btn" lay-event="records">查看记录</a>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script src="STATIC_EXT/searchable_select/searchable_select.js"></script>
|
||||
<script>
|
||||
var table,form,layCascader;
|
||||
layui.use(['form', 'element','layCascader'], function() {
|
||||
form = layui.form;
|
||||
layCascader = layui.layCascader;
|
||||
element = layui.element;
|
||||
form.render();
|
||||
|
||||
var store_name = $('select[name="store_id"] option:selected').text()
|
||||
$('input[name="store_name"]').val(store_name);
|
||||
|
||||
table = new Table({
|
||||
elem: '#goods_list',
|
||||
url: ns.url("stock://shop/stock/manage"),
|
||||
cols: [
|
||||
[{
|
||||
type: 'checkbox',
|
||||
unresize: 'false',
|
||||
width: '3%'
|
||||
},{
|
||||
field: 'sku_name',
|
||||
title: '商品信息',
|
||||
width: '30%',
|
||||
templet: '#goods_detail'
|
||||
}, {
|
||||
field: 'sku_no',
|
||||
title: '编码',
|
||||
width: '10%',
|
||||
}, {
|
||||
field: 'stock',
|
||||
title: '销售库存',
|
||||
width: '9%',
|
||||
templet: function (data){
|
||||
if(!data.stock){
|
||||
return 0;
|
||||
}
|
||||
return data.stock;
|
||||
}
|
||||
}, {
|
||||
field: 'stock',
|
||||
title: '实物库存',
|
||||
width: '9%',
|
||||
templet: function (data){
|
||||
if(!data.real_stock){
|
||||
return 0;
|
||||
}
|
||||
return data.real_stock;
|
||||
}
|
||||
}, {
|
||||
field: 'cost_price',
|
||||
title: '成本价',
|
||||
width: '9%',
|
||||
}, {
|
||||
title: '状态',
|
||||
unresize: 'false',
|
||||
width: '8%',
|
||||
templet: function (data) {
|
||||
var str = '';
|
||||
if (data.goods_state == 1) {
|
||||
str = '销售中';
|
||||
} else if (data.goods_state == 0) {
|
||||
str = '仓库中';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}, {
|
||||
field: 'create_time',
|
||||
title: '添加时间',
|
||||
width: '15%',
|
||||
templet: function (data) {
|
||||
return ns.time_to_date(data.create_time);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: '7%',
|
||||
toolbar: '#operation',
|
||||
align: 'right',
|
||||
}
|
||||
]
|
||||
],
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* 监听工具栏操作
|
||||
*/
|
||||
table.tool(function (obj) {
|
||||
var data = obj.data;
|
||||
switch (obj.event) {
|
||||
case 'records': //查看
|
||||
window.open(ns.href("stock://shop/stock/records?sku_id=" + data.sku_id));
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
element.on('tab(goods_list_tab)', function () {
|
||||
var id = this.getAttribute('lay-id');
|
||||
$('input[name="goods_state"]').val(id)
|
||||
table.reload({
|
||||
page: {
|
||||
curr: 1
|
||||
},
|
||||
where: {
|
||||
search_text: $('input[name="search_text"]').val(),
|
||||
category_id: $('input[name="category_id"]').val(),
|
||||
min_stock: $('input[name="min_stock"]').val(),
|
||||
max_stock: $('input[name="max_stock"]').val(),
|
||||
store_id: $('select[name="store_id"]').val(),
|
||||
goods_state: $('input[name="goods_state"]').val()
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
form.on('select(store_list)', function (data) {
|
||||
var store_name = $('select[name="store_id"] option:selected').text()
|
||||
$('input[name="store_name"]').val(store_name);
|
||||
})
|
||||
|
||||
//监听筛选事件
|
||||
form.on('submit(search)', function (data) {
|
||||
table.reload({
|
||||
page: {
|
||||
curr: 1
|
||||
},
|
||||
where: data.field
|
||||
});
|
||||
});
|
||||
|
||||
// 商品导出
|
||||
form.on('submit(batch_export_stock)', function(data){
|
||||
var id_array = [];
|
||||
var checkedData = table.checkStatus('goods_list').data;
|
||||
for (var i in checkedData) id_array.push(checkedData[i].goods_id);
|
||||
|
||||
data.field.goods_ids = id_array.toString(); // 选择要导出的商品
|
||||
|
||||
$.ajax({
|
||||
type: 'post',
|
||||
dataType: 'json',
|
||||
url: ns.url("stock://shop/stock/exportGoods"),
|
||||
data: data.field,
|
||||
success: function (res) {
|
||||
}
|
||||
})
|
||||
window.open(ns.href("stock://shop/stock/export",{}));
|
||||
});
|
||||
|
||||
var goodsCategory = [];
|
||||
fetchCategory('.select-category', function (value, node) {
|
||||
$('[name="category_id"]').val(value)
|
||||
});
|
||||
|
||||
/**
|
||||
* 渲染分类选择
|
||||
* @param elem
|
||||
* @param callback
|
||||
*/
|
||||
function fetchCategory(elem, callback){
|
||||
if (!goodsCategory.length) {
|
||||
$.ajax({
|
||||
url : ns.url("shop/goodscategory/lists"),
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
async: false,
|
||||
success: function(res) {
|
||||
goodsCategory = res.data;
|
||||
}
|
||||
})
|
||||
}
|
||||
if($(elem).length) {
|
||||
var _cascader = layCascader({
|
||||
elem: elem,
|
||||
options: goodsCategory,
|
||||
props: {
|
||||
value: 'category_id',
|
||||
label: 'category_name',
|
||||
children: 'child_list'
|
||||
}
|
||||
});
|
||||
_cascader.changeEvent(function (value, node) {
|
||||
typeof callback == 'function' && callback(value, node)
|
||||
});
|
||||
|
||||
$("form").unbind().bind("reset", function (event) {
|
||||
_cascader.clearCheckedNodes()
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
151
addon/stock/shop/view/stock/output_detail.html
Executable file
151
addon/stock/shop/view/stock/output_detail.html
Executable file
@@ -0,0 +1,151 @@
|
||||
<style>
|
||||
.layui-table .layui-btn{
|
||||
justify-content: flex-end;
|
||||
padding-right: 0px;
|
||||
text-align: right;
|
||||
}
|
||||
.name{
|
||||
display: flex;
|
||||
align-content: center;
|
||||
}
|
||||
.name img{
|
||||
max-width: inherit;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="layui-form" lay-filter="storeform">
|
||||
<div class="layui-card card-common card-brief">
|
||||
<div class="layui-card-header">
|
||||
<span class="card-title">基本信息</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-row">
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">制单人:</label>
|
||||
<div class="layui-input-block">{$document_detail.operater_name}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">关联单据:</label>
|
||||
<div class="layui-input-block">{$document_detail.type_name}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">制单时间:</label>
|
||||
<div class="layui-input-block">{$document_detail.create_time}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注:</label>
|
||||
<div class="layui-input-block">{$document_detail.remark}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态:</label>
|
||||
<div class="layui-input-block">{$document_detail.status_data.name}</div>
|
||||
</div>
|
||||
{if !empty($document_detail.verifier_name) }
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">审核人:</label>
|
||||
<div class="layui-input-block">{$document_detail.verifier_name}</div>
|
||||
</div>
|
||||
{/if}
|
||||
{if !empty($document_detail.audit_time) }
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">审核时间:</label>
|
||||
<div class="layui-input-block">{$document_detail.audit_time}</div>
|
||||
</div>
|
||||
{/if}
|
||||
{if $document_detail.status == -1}
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">拒绝理由:</label>
|
||||
<div class="layui-input-block">{$document_detail.refuse_reason}</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">出库门店:</label>
|
||||
<div class="layui-input-block">{$document_detail.store_name}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">出库单号:</label>
|
||||
<div class="layui-input-block">{$document_detail.document_no}</div>
|
||||
</div>
|
||||
|
||||
{if $document_detail.time > 0}
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">出库时间:</label>
|
||||
<div class="layui-input-block">{$document_detail.time}</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-card card-common card-brief">
|
||||
<div class="layui-card-header">
|
||||
<span class="card-title">商品明细</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<table class="layui-table order_goods_list" lay-filter="order_goods" lay-skin="line">
|
||||
<colgroup>
|
||||
<col width="30%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>商品名称/条形码</th>
|
||||
<th>规格</th>
|
||||
<th>单位</th>
|
||||
<th>数量</th>
|
||||
<th>成本价(元)</th>
|
||||
<th>金额(元)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<table class="layui-table order_goods_list order_goods_list-bottom" lay-filter="order_goods_list" lay-skin="line">
|
||||
<colgroup>
|
||||
<col width="30%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
<col width="10%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
{foreach $document_detail.goods_sku_list_array as $k => $v}
|
||||
<tr class="table-tr">
|
||||
<td class="name">
|
||||
<img src="{:img($v.goods_sku_img,'small')}" alt="">
|
||||
<span>{$v.goods_sku_name}</span>
|
||||
</td>
|
||||
{if $v.goods_sku_spec && $v.goods_sku_spec !=''}
|
||||
<td>{$v.goods_sku_spec}</td>
|
||||
{else/}
|
||||
<td>-</td>
|
||||
{/if}
|
||||
{if $v.goods_unit && $v.goods_unit !=''}
|
||||
<td>{$v.goods_unit}</td>
|
||||
{else/}
|
||||
<td>件</td>
|
||||
{/if}
|
||||
<td>{$v.goods_num}</td>
|
||||
<td>{$v.goods_price}</td>
|
||||
<td>{$v.goods_sum}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
<label style="display: flex;justify-content: flex-end;padding-right: 13px;">合计:共{$document_detail.goods_count}种商品{$document_detail.goods_price}件,合计金额:
|
||||
<span style="color: #ff0000;">{$document_detail.goods_total_price}</span></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
198
addon/stock/shop/view/stock/records.html
Executable file
198
addon/stock/shop/view/stock/records.html
Executable file
@@ -0,0 +1,198 @@
|
||||
<style>
|
||||
#records_list{
|
||||
margin-top: 14px;
|
||||
}
|
||||
.layui-icon-next{
|
||||
font-size:14px;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
<div class="main-wrap">
|
||||
|
||||
<div class="screen layui-collapse margin-bot ">
|
||||
<div class="layui-colla-item">
|
||||
<form class="layui-colla-content layui-form layui-show" lay-filter="screen">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">业务类型:</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="type">
|
||||
<option value="">全部</option>
|
||||
{foreach $type_list as $k => $v}
|
||||
<option value="{$v.key}">{$v.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">门店:</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="store_id" class="len-mid">
|
||||
<option value="">全部</option>
|
||||
{foreach $store_list as $store_k => $store_v}
|
||||
<option value="{$store_v.store_id}">{$store_v.store_name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">时间:</label>
|
||||
<div class="layui-inline layui-inline-margin" id="time_fission">
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" id="start_time" name="start_time" class="layui-input" placeholder="请输入开始时间" autocomplete="off">
|
||||
<i class="iconfont iconriqi"></i>
|
||||
</div>
|
||||
<div class="layui-form-mid">-</div>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" id="end_time" name="end_time" class="layui-input" placeholder="请输入结束时间" autocomplete="off">
|
||||
<i class="iconfont iconriqi"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="state" value="all">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<button class="layui-btn bg-color" lay-submit lay-filter="search">筛选</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<table id="records_list" lay-filter="records_list"></table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- 操作 -->
|
||||
<script type="text/html" id="operation">
|
||||
<div class="table-btn">
|
||||
<a class="layui-btn" lay-event="detail">查看</a>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var laytpl,table,form,element, laydate;
|
||||
layui.use(['form','element','laytpl', 'laydate'], function() {
|
||||
form = layui.form;
|
||||
laydate = layui.laydate;
|
||||
element = layui.element;
|
||||
laytpl = layui.laytpl;
|
||||
form.render();
|
||||
|
||||
//日期时间选择器
|
||||
laydate.render({
|
||||
elem: '#start_time'
|
||||
,type: 'datetime'
|
||||
});
|
||||
|
||||
//日期时间选择器
|
||||
laydate.render({
|
||||
elem: '#end_time'
|
||||
,type: 'datetime'
|
||||
});
|
||||
|
||||
table = new Table({
|
||||
elem: '#records_list',
|
||||
url: ns.url("stock://shop/stock/records"),
|
||||
where:{sku_id:'{$sku_id}'},
|
||||
cols: [
|
||||
[{
|
||||
title: '时间',
|
||||
width: '12%',
|
||||
templet: function(data) {
|
||||
return '<div class="text">'+ns.time_to_date(data.create_time)+'</div>'; //创建时间转换方法
|
||||
}
|
||||
}, {
|
||||
field: 'operater_name',
|
||||
title: '操作人',
|
||||
width: '6%',
|
||||
templet: function(data) {
|
||||
return '<div class="text">'+data.operater_name+'</div>';
|
||||
}
|
||||
}, {
|
||||
field: 'store_name',
|
||||
title: '门店',
|
||||
width: '10%',
|
||||
templet: function(data) {
|
||||
return '<div class="text">'+data.store_name+'</div>';
|
||||
}
|
||||
},{
|
||||
title: '业务类型',
|
||||
field: 'name',
|
||||
width: '8%',
|
||||
templet: function(data) {
|
||||
return '<div class="text">'+data.name+'</div>';
|
||||
}
|
||||
},{
|
||||
title: '原库存',
|
||||
field: 'before_store_stock',
|
||||
},{
|
||||
title: '库存变化',
|
||||
templet: function(data) {
|
||||
var change = data.type == 'input' ? '+' : '-';
|
||||
return change + data.goods_num; //创建时间转换方法
|
||||
}
|
||||
},{
|
||||
title: '现库存',
|
||||
field: 'after_store_stock',
|
||||
},{
|
||||
title: '成本价',
|
||||
templet: function(data) {
|
||||
return data.goods_price; //创建时间转换方法
|
||||
}
|
||||
},{
|
||||
title: '成本价变化',
|
||||
width: '12%',
|
||||
templet: function(data) {
|
||||
return '<div class="text">'+data.before_store_goods_price + ' <i class="layui-icon layui-icon-next"></i> ' + data.after_store_goods_price+'</div>';
|
||||
}
|
||||
},{
|
||||
title: '备注',
|
||||
field: 'remark',
|
||||
width:'10%',
|
||||
templet: function(data) {
|
||||
return '<div class="text">'+data.remark+'</div>';
|
||||
}
|
||||
},{
|
||||
title: '操作',
|
||||
toolbar: '#operation',
|
||||
align:'right'
|
||||
}]
|
||||
]
|
||||
});
|
||||
|
||||
/**
|
||||
* 监听工具栏操作
|
||||
*/
|
||||
table.tool(function(obj) {
|
||||
var data = obj.data;
|
||||
switch (obj.event) {
|
||||
case 'detail': //查看详情
|
||||
if(data.type == "input"){
|
||||
location.hash = ns.hash("stock://shop/stock/inputdetail?document_id="+ data.document_id);
|
||||
}else{
|
||||
location.hash = ns.hash("stock://shop/stock/outputdetail?document_id="+ data.document_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 搜索功能
|
||||
*/
|
||||
form.on('submit(search)', function(data) {
|
||||
table.reload({
|
||||
page: {
|
||||
curr: 1
|
||||
},
|
||||
where: data.field
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
213
addon/stock/shop/view/stock/stockin.html
Executable file
213
addon/stock/shop/view/stock/stockin.html
Executable file
@@ -0,0 +1,213 @@
|
||||
<link rel="stylesheet" type="text/css" href="ADDON_STOCK_CSS/stock.css" />
|
||||
<style>
|
||||
.stock-title-body {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.stock-title-body span {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
background-color: #fff;
|
||||
z-index: 10;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stock-title-body input {
|
||||
padding-right: 25px;
|
||||
}
|
||||
|
||||
input.stock-search {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
input.stock-search:focus {
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.layui-table th,
|
||||
.layui-table td {
|
||||
padding: 7px 30px !important;
|
||||
}
|
||||
|
||||
.layui-table .layui-input {
|
||||
height: 28px !important;
|
||||
}
|
||||
.remark{
|
||||
width: 611px;
|
||||
}
|
||||
button[lay-filter='save'] .layui-icon-loading {
|
||||
animation: loding-rotate 1s linear infinite;
|
||||
/* 设置动画效果 */
|
||||
transform-origin: center;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@keyframes loding-rotate {
|
||||
0% {
|
||||
transform: rotate(0);
|
||||
}
|
||||
|
||||
/* 起始位置 */
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
|
||||
/* 结束位置,旋转一周 */
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="layui-form form" lay-filter="formTest">
|
||||
|
||||
<div class="stock-view">
|
||||
{if $stock_config.is_audit == 1}
|
||||
<div class="tips text-color">说明:待审核状态下只有经办人允许修改,只有变为已审核状态后才会使库存发生变化,已审核状态的单据不允许再修改。</div>
|
||||
{/if}
|
||||
<div class="store-view">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">入库单号:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
{if isset($document_info)}
|
||||
<input type="text" value="{$document_info['document_no']}" name="document_no" class="layui-input len-mid">
|
||||
{else /}
|
||||
<input type="text" value="{$document_no}" name="document_no" class="layui-input len-mid">
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label"><span class="required">*</span>入库门店:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
<select name="store_id" lay-verify="required" lay-filter="store_list" class="len-mid">
|
||||
{foreach $store_list as $store_k => $store_v}
|
||||
{if isset($document_info)}
|
||||
<option value="{$store_v.store_id}" {if $document_info['store_id']==$store_v['store_id']}selected {php} $default_store_id=$store_v['store_id']; {/php}{/if}>{$store_v.store_name}</option>
|
||||
{else /}
|
||||
<option value="{$store_v.store_id}" {if $store_k==0}selected {php} $default_store_id=$store_v['store_id']; {/php}{/if}>{$store_v.store_name}</option>
|
||||
{/if}
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">入库时间:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
<input type="text" class="layui-input" name="date_time" value="{$document_info ? time_to_date($document_info['time']) : date('Y-m-d H:i:s')}" placeholder="入库时间" id="date_time" readonly>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">当前操作人:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
<span>{$user_info['username']}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label"><span class="required"></span>备注:</label>
|
||||
<div class="layui-input-block remark">
|
||||
<textarea class="layui-textarea" maxlength="100" name="remark" placeholder="请输入备注">{$document_info['remark'] ?? ''}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="layui-table" lay-size="lg">
|
||||
<colgroup>
|
||||
<col width="350">
|
||||
<col width="120">
|
||||
<col width="90">
|
||||
<col>
|
||||
<col>
|
||||
<col width="120">
|
||||
<col width="90">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>产品名称</th>
|
||||
<th>当前库存</th>
|
||||
<th>单位</th>
|
||||
<th>数量</th>
|
||||
<th>成本价</th>
|
||||
<th>总金额</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="stock-body">
|
||||
<tr class="stock-search-line">
|
||||
<td class="stock-search-block">
|
||||
<div class="stock-title-body">
|
||||
<input type="text" class="layui-input stock-search" placeholder="请输入产品名称/规格/编码" />
|
||||
<span class="iconfont icontuodong" onclick="editBtn('btn')"></span>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="7" class="total-data">合计: 共<span class="kinds-num">0</span>种,<span class="count-num">0</span>件产品,合计金额:<span class="goods-money">0</span></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
{notempty name="$document_info"}
|
||||
<input type="hidden" name="document_id" value="{$document_info['document_id']}">
|
||||
<input type="hidden" name="document_goods_list" value='{:json_encode($document_info["goods_list"])}'>
|
||||
{/notempty}
|
||||
|
||||
<div class="form-row">
|
||||
<button class="layui-btn" lay-submit lay-filter="save"><span class="layui-icon"></span>入库</button>
|
||||
<button class="layui-btn layui-btn-primary" onclick="backStockAction()">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script type="text/html" id="stock_goods_info">
|
||||
<tr class="stock-tr" data-key='{{ d.index }}'>
|
||||
<td>
|
||||
{{d.sku_name}}
|
||||
</td>
|
||||
<!-- 库存 -->
|
||||
<td>{{ d.real_stock || 0 }}</td>
|
||||
<!-- 单位 -->
|
||||
<td>{{ d.unit || '件' }}</td>
|
||||
<!-- 数量 -->
|
||||
<td>
|
||||
<input type="number" class="layui-input stock-num" name="goods_num" value="{{ d.goods_num || 0 }}" placeholder="0" onchange="dataChange(this)"/>
|
||||
</td>
|
||||
<!-- 成本价 -->
|
||||
<td>
|
||||
<input type="number" class="layui-input stock-cost-price" name="goods_price" value="{{ d.goods_price || 0 }}" onchange="dataChange(this)"/>
|
||||
</td>
|
||||
<!-- 成本总价 -->
|
||||
<td>
|
||||
<span class="total-cost-money">{{ d.goods_money || 0 }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<a class="text-color action-btn" onclick="delTr(this)">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var stockDataObj = JSON.parse($("input[name='document_goods_list']").val() || '{}');// 库存数据
|
||||
var stockData = Object.values(stockDataObj)
|
||||
var defaultStoreId = {$default_store_id ?? 0};
|
||||
var stockConfig = {:json_encode($stock_config) };
|
||||
var stockAction = {
|
||||
id: 'document_id',
|
||||
listRoute: 'storage', // 库存操作标识,storage:入库,wastage:出库
|
||||
saveRoute: 'stockin', // 保存地址
|
||||
params:{
|
||||
'document_no':$('input[name="document_no"]'),
|
||||
'time':$('input[name="date_time"]'),
|
||||
'remark':$('textarea[name="remark"]')
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<script src="ADDON_STOCK_JS/stock_action.js?time=20250113"></script>
|
||||
191
addon/stock/shop/view/stock/stockout.html
Executable file
191
addon/stock/shop/view/stock/stockout.html
Executable file
@@ -0,0 +1,191 @@
|
||||
<link rel="stylesheet" type="text/css" href="ADDON_STOCK_CSS/stock.css" />
|
||||
<style>
|
||||
.stock-title-body{
|
||||
position: relative;
|
||||
}
|
||||
.stock-title-body span{
|
||||
position: absolute;
|
||||
top:5px;
|
||||
right:5px;
|
||||
background-color: #fff;
|
||||
z-index: 10;
|
||||
cursor: pointer;
|
||||
}
|
||||
.stock-title-body input{
|
||||
padding-right: 25px;
|
||||
}
|
||||
input.stock-search{
|
||||
border-width: 0;
|
||||
}
|
||||
input.stock-search:focus{
|
||||
border-width: 1px;
|
||||
}
|
||||
.layui-table th,.layui-table td{
|
||||
padding: 7px 30px !important;
|
||||
}
|
||||
.layui-table .layui-input{
|
||||
height: 28px !important;
|
||||
}
|
||||
.remark{
|
||||
width: 611px;
|
||||
}
|
||||
button[lay-filter='save'] .layui-icon-loading {
|
||||
animation: loding-rotate 1s linear infinite; /* 设置动画效果 */
|
||||
transform-origin: center;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@keyframes loding-rotate {
|
||||
0% { transform: rotate(0); } /* 起始位置 */
|
||||
100% { transform: rotate(360deg); } /* 结束位置,旋转一周 */
|
||||
}
|
||||
</style>
|
||||
<div class="layui-form form" lay-filter="formTest">
|
||||
|
||||
<div class="stock-view">
|
||||
{if $stock_config.is_audit == 1}
|
||||
<div class="tips text-color">说明:待审核状态下只有经办人允许修改,只有变为已审核状态后才会使库存发生变化,已审核状态的单据不允许再修改。</div>
|
||||
{/if}
|
||||
<div class="store-view">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">出库单号:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
{if isset($document_info)}
|
||||
<input type="text" value="{$document_info['document_no']}" name="document_no" class="layui-input len-mid">
|
||||
{else /}
|
||||
<input type="text" value="{$document_no}" name="document_no" class="layui-input len-mid">
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label"><span class="required">*</span>门店:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
<select name="store_id" lay-verify="required" lay-filter="store_list" class="len-mid">
|
||||
{foreach $store_list as $store_k => $store_v}
|
||||
{if isset($document_info)}
|
||||
<option value="{$store_v.store_id}" {if $document_info['store_id']==$store_v['store_id']}selected {php} $default_store_id=$store_v['store_id']; {/php}{/if}>{$store_v.store_name}</option>
|
||||
{else /}
|
||||
<option value="{$store_v.store_id}" {if $store_k==0}selected {php} $default_store_id=$store_v['store_id']; {/php}{/if}>{$store_v.store_name}</option>
|
||||
{/if}
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">出库时间:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
<input type="text" class="layui-input" name="date_time" value="{$document_info ? time_to_date($document_info['time']) : date('Y-m-d H:i:s')}" placeholder="出库时间" id="date_time" readonly>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">当前操作人:</label>
|
||||
<div class="layui-input-block len-mid">
|
||||
<span>{$user_info['username']}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label"><span class="required"></span>备注:</label>
|
||||
<div class="layui-input-block remark">
|
||||
<textarea class="layui-textarea" maxlength="100" name="remark" placeholder="请输入备注">{$document_info['remark'] ?? ''}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<table class="layui-table" lay-size="lg">
|
||||
<colgroup>
|
||||
<col width="25%">
|
||||
<col width="10%">
|
||||
<col width="10%">
|
||||
<col width="25%">
|
||||
<col width="20%">
|
||||
<col width="10%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>产品名称/规格/编码</th>
|
||||
<th>当前库存</th>
|
||||
<th>单位</th>
|
||||
<th>成本价</th>
|
||||
<th>数量</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="stock-body">
|
||||
<tr class="stock-search-line">
|
||||
<td class="stock-search-block">
|
||||
<div class="stock-title-body">
|
||||
<input type="text" class="layui-input stock-search" placeholder="请输入产品名称/规格/编码" />
|
||||
<span class="iconfont icontuodong" onclick="editBtn('btn')"></span>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="7" class="total-data">合计: 共<span class="kinds-num">0</span>种,<span class="count-num">0</span>件产品,合计金额:<span class="goods-money">0</span></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
{notempty name="$document_info"}
|
||||
<input type="hidden" name="document_id" value="{$document_info['document_id']}">
|
||||
<input type="hidden" name="document_goods_list" value='{:json_encode($document_info["goods_list"])}'>
|
||||
{/notempty}
|
||||
|
||||
<div class="form-row">
|
||||
<button class="layui-btn" lay-submit lay-filter="save"><span class="layui-icon"></span>出库</button>
|
||||
<button class="layui-btn layui-btn-primary" onclick="backStockAction()">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="stock_goods_info">
|
||||
<tr class="stock-tr" data-key='{{ d.index }}'>
|
||||
<td>
|
||||
{{d.sku_name}}
|
||||
</td>
|
||||
<!-- 库存 -->
|
||||
<td>{{ d.real_stock || 0 }}</td>
|
||||
<!-- 单位 -->
|
||||
<td>{{ d.unit || '件' }}</td>
|
||||
<td>
|
||||
{{ d.cost_price || 0.00 }}
|
||||
<input type="hidden" name="goods_price" value="{{ d.cost_price || 0 }}" />
|
||||
</td>
|
||||
<!-- 数量 -->
|
||||
<td>
|
||||
<input type="number" class="layui-input stock-num" name="goods_num" value="{{ d.goods_num || 0 }}" placeholder="0" onchange="dataChange(this)"/>
|
||||
</td>
|
||||
<td>
|
||||
<a class="text-color action-btn" onclick="delTr(this)">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var stockDataObj = JSON.parse($("input[name='document_goods_list']").val() || '{}');// 库存数据
|
||||
var stockData = Object.values(stockDataObj)
|
||||
var defaultStoreId = {$default_store_id ?? 0};
|
||||
var stockConfig = {:json_encode($stock_config)};
|
||||
var stockAction = {
|
||||
id: 'document_id',
|
||||
listRoute: 'wastage', // 库存操作标识,storage:入库,wastage:出库
|
||||
saveRoute: 'stockout', // 保存地址
|
||||
params:{
|
||||
'document_no':$('input[name="document_no"]'),
|
||||
'time':$('input[name="date_time"]'),
|
||||
'remark':$('textarea[name="remark"]')
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<script src="ADDON_STOCK_JS/stock_action.js?time=20250111"></script>
|
||||
373
addon/stock/shop/view/stock/storage.html
Executable file
373
addon/stock/shop/view/stock/storage.html
Executable file
@@ -0,0 +1,373 @@
|
||||
<style>
|
||||
.single-filter-box {justify-content: left;line-height: 34px}
|
||||
.single-filter-box a{cursor:pointer;margin-left: 10px}
|
||||
</style>
|
||||
|
||||
<div class="main-wrap">
|
||||
<div class="single-filter-box">
|
||||
<button type="button" class="layui-btn bg-color" onclick="add()">添加入库单</button>
|
||||
</div>
|
||||
|
||||
<!-- 搜索框 -->
|
||||
<div class="screen layui-collapse search-nav" lay-filter="selection_panel">
|
||||
<div class="layui-colla-item">
|
||||
<form class="layui-colla-content layui-form layui-show">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">入库单号:</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="search_text" placeholder="请输入入库单号" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">门店:</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="store_id" class="len-mid">
|
||||
<option value="">全部</option>
|
||||
{foreach $store_list as $store_k => $store_v}
|
||||
<option value="{$store_v.store_id}">{$store_v.store_name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">审核状态:</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="status" lay-filter="status" class="len-mid">
|
||||
<option value="">全部</option>
|
||||
{foreach name="$status_list" item="vo"}
|
||||
<option value="{$vo.status}">{$vo.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<button class="layui-btn bg-color" lay-submit lay-filter="search">筛选</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-tab table-tab">
|
||||
<div class="layui-tab-content">
|
||||
<table id="doc_list" lay-filter="doc_list"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type='text/html' id="import_document">
|
||||
<div class="layui-form import-document">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label ">文件上传:</label>
|
||||
<div class="layui-input-block ">
|
||||
<div class="upload-file sub-text disabled-click">
|
||||
<div class="upload-img-block" id="addFile">
|
||||
<div class="upload-img-box">
|
||||
<div class="upload-default">
|
||||
<div class="upload">
|
||||
<i class="iconfont iconshangchuan"></i>
|
||||
<p>导入模版</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="word-aux">需按照指定模板导入,支持格式xls、xlsx。下载<a href="ADDON_STOCK_FILE/stockin_template.xlsx" class="text-color"> 导入模板</a></div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<button class="layui-btn confirm-auto">确定</button>
|
||||
<button class="layui-btn layui-btn-primary cancel">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- 操作 -->
|
||||
<script type="text/html" id="operation">
|
||||
<div class="table-btn">
|
||||
<a class="layui-btn" lay-event="detail">查看</a>
|
||||
|
||||
<!-- 待审核状态下进行审核操作 -->
|
||||
{{# if(d.status == 1 && {$is_audit} == 0){ }}
|
||||
<!-- 只有管理员和拥有单据审核权限的才能审核 -->
|
||||
<a class="layui-btn" lay-event="audit_agree">审核通过</a>
|
||||
<a class="layui-btn" lay-event="audit_refuse">审核拒绝</a>
|
||||
{{# } }}
|
||||
|
||||
{{# if(d.status == -1){ }}
|
||||
<a class="layui-btn" lay-event="detail_refuse">拒绝理由</a>
|
||||
{{# } }}
|
||||
|
||||
<!-- 只有经办人才能操作入库单 -->
|
||||
{{# if((d.status == 1 || d.status == -1) && d.operater == {$user_info['uid']} ){ }}
|
||||
<a class="layui-btn" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn" lay-event="delete">删除</a>
|
||||
{{# } }}
|
||||
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var table, form, laytpl, element, layer_pass, repeat_flag = false, upload; //防重复标识
|
||||
layui.use(['form', 'laytpl', 'element', 'upload'], function() {
|
||||
form = layui.form;
|
||||
laytpl = layui.laytpl;
|
||||
element = layui.element;
|
||||
upload = layui.upload;
|
||||
form.render();
|
||||
|
||||
table = new Table({
|
||||
elem: '#doc_list',
|
||||
url: ns.url("stock://shop/stock/storage"),
|
||||
cols: [
|
||||
[{
|
||||
field: 'document_no',
|
||||
title: '入库单号',
|
||||
width: '15%',
|
||||
}, {
|
||||
field: 'store_name',
|
||||
title: '门店',
|
||||
width: '15%',
|
||||
}, {
|
||||
field: 'type_name',
|
||||
title: '单据类型',
|
||||
width: '10%',
|
||||
}, {
|
||||
field: 'document_money',
|
||||
title: '单据金额',
|
||||
width: '10%',
|
||||
}, {
|
||||
field: 'status_name',
|
||||
title: '审核状态',
|
||||
width: '10%',
|
||||
}, {
|
||||
title: '操作人',
|
||||
width: '15%',
|
||||
templet: function(data) {
|
||||
var html = '';
|
||||
html += '经办人:' + data.operater_name + '<br/>';
|
||||
if(data.verifier_name) html += '审核人:' + data.verifier_name;
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
title: '操作时间',
|
||||
width: '15%',
|
||||
templet: function(data) {
|
||||
var html = '';
|
||||
html += '制单时间:' + ns.time_to_date(data.create_time) + '<br/>';
|
||||
if (data.time) html += '入库时间:' + ns.time_to_date(data.time) + '<br/>';
|
||||
if (data.audit_time) html += '审核时间:' + ns.time_to_date(data.audit_time);
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
title: '操作',
|
||||
width: '10%',
|
||||
align: 'right',
|
||||
toolbar: '#operation',
|
||||
}]
|
||||
]
|
||||
});
|
||||
|
||||
// 监听工具栏操作
|
||||
table.tool(function(obj) {
|
||||
var data = obj.data;
|
||||
switch (obj.event) {
|
||||
case 'audit_agree':
|
||||
// 审核通过
|
||||
agree(data.document_id);
|
||||
break;
|
||||
case 'audit_refuse':
|
||||
// 审核拒绝
|
||||
refuse(data.document_id);
|
||||
break;
|
||||
case 'edit':
|
||||
// 编辑
|
||||
edit(data.document_id);
|
||||
break;
|
||||
case 'delete':
|
||||
// 删除
|
||||
deleteDocument(data.document_id);
|
||||
break;
|
||||
case 'detail':
|
||||
// 查看
|
||||
window.open(ns.href("stock://shop/stock/inputdetail?document_id=" + data.document_id));
|
||||
break;
|
||||
case 'detail_refuse':
|
||||
layer.open({
|
||||
title: '拒绝理由',
|
||||
content: data.refuse_reason,
|
||||
})
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// 搜索功能
|
||||
form.on('submit(search)', function(data){
|
||||
table.reload({
|
||||
page: {
|
||||
curr: 1
|
||||
},
|
||||
where: data.field
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function importExcel() {
|
||||
laytpl($("#import_document").html()).render({}, function (html) {
|
||||
cardPup = layer.open({
|
||||
type: 1,
|
||||
title:"导入入库单",
|
||||
area:['700px','350px'],
|
||||
content: html,
|
||||
success: function(layero, index){
|
||||
form.render();
|
||||
|
||||
// 上传文件
|
||||
var uploadInst = upload.render({
|
||||
elem: '#addFile' //绑定元素
|
||||
,url: ns.url("stock://shop/stock/file") //上传接口
|
||||
,accept:'file'
|
||||
,acceptMime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
,acceptMime: 'xlsx'
|
||||
,exts: 'xlsx'
|
||||
,data:{
|
||||
type: 'import',
|
||||
},
|
||||
done: function(res){
|
||||
if (res.code >= 0) {
|
||||
importing(res.data.path);
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$(".import-document .form-row .cancel,.import-document .form-row .confirm-auto").click(function(){
|
||||
layer.closeAll();
|
||||
});
|
||||
|
||||
function importing(path){
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/import"),
|
||||
data: {
|
||||
path: path,
|
||||
type : 'PURCHASE'
|
||||
},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function (res) {
|
||||
if(res.code == 0){
|
||||
// table.reload();
|
||||
}else{
|
||||
layer.msg(res.message)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function add() {
|
||||
location.hash = ns.hash("stock://shop/stock/stockin");
|
||||
}
|
||||
|
||||
function edit(document_id) {
|
||||
location.hash = ns.hash("stock://shop/stock/stockin",{document_id});
|
||||
}
|
||||
|
||||
// 同意
|
||||
var agree_repeat_flag = false;
|
||||
function agree(document_id) {
|
||||
layer.confirm('确定要通过该单据吗?', function(index) {
|
||||
if(agree_repeat_flag) return;
|
||||
agree_repeat_flag = true;
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/agree"),
|
||||
data: {document_id},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
agree_repeat_flag = false;
|
||||
if (res.code >= 0) {
|
||||
listenerHash(); // 刷新页面
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
layer.closeAll();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// 拒绝
|
||||
var refuse_repeat_flag = false;
|
||||
function refuse(document_id) {
|
||||
layer.prompt({
|
||||
title: '拒绝理由',
|
||||
formType: 2,
|
||||
yes: function (index, layero) {
|
||||
var refuse_reason = layero.find(".layui-layer-input").val();
|
||||
if (!refuse_reason) {
|
||||
layer.msg('请输入拒绝理由!', {icon: 5, anim: 6});
|
||||
return;
|
||||
}
|
||||
if (refuse_repeat_flag) return;
|
||||
refuse_repeat_flag = true;
|
||||
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/refuse"),
|
||||
data: {document_id, refuse_reason},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function (res) {
|
||||
layer.msg(res.message);
|
||||
refuse_repeat_flag = false;
|
||||
|
||||
if (res.code >= 0) {
|
||||
listenerHash(); // 刷新页面
|
||||
}
|
||||
}
|
||||
});
|
||||
layer.close(index);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 删除单据
|
||||
var delete_repeat_flag = false;
|
||||
function deleteDocument(document_id) {
|
||||
layer.confirm('确定要删除该单据吗?', function(index) {
|
||||
if(delete_repeat_flag) return;
|
||||
delete_repeat_flag = true;
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/delete"),
|
||||
data: {document_id},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
delete_repeat_flag = false;
|
||||
if (res.code >= 0) {
|
||||
listenerHash(); // 刷新页面
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
layer.closeAll();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
279
addon/stock/shop/view/stock/wastage.html
Executable file
279
addon/stock/shop/view/stock/wastage.html
Executable file
@@ -0,0 +1,279 @@
|
||||
<div class="main-wrap">
|
||||
<div class="single-filter-box">
|
||||
<button type="button" class="layui-btn bg-color" onclick="add()">添加出库单</button>
|
||||
</div>
|
||||
|
||||
<!-- 搜索框 -->
|
||||
<div class="screen layui-collapse search-nav" lay-filter="selection_panel">
|
||||
<div class="layui-colla-item">
|
||||
<form class="layui-colla-content layui-form layui-show">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">出库单号:</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="search_text" placeholder="请输入出库单号" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">门店:</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="store_id" class="len-mid">
|
||||
<option value="">全部</option>
|
||||
{foreach $store_list as $store_k => $store_v}
|
||||
<option value="{$store_v.store_id}">{$store_v.store_name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">审核状态:</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="status" lay-filter="status" class="len-mid">
|
||||
<option value="">全部</option>
|
||||
{foreach name="$status_list" item="vo"}
|
||||
<option value="{$vo.status}">{$vo.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<button class="layui-btn bg-color" lay-submit lay-filter="search">筛选</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-tab table-tab">
|
||||
<div class="layui-tab-content">
|
||||
<table id="wastage_list" lay-filter="wastage_list"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 操作 -->
|
||||
<script type="text/html" id="operation">
|
||||
<div class="table-btn">
|
||||
<a class="layui-btn" lay-event="detail">查看</a>
|
||||
|
||||
<!-- 待审核状态下进行审核操作 -->
|
||||
{{# if(d.status == 1 && {$is_audit} == 0){ }}
|
||||
<!-- 只有管理员和拥有单据审核权限的才能审核 -->
|
||||
<a class="layui-btn" lay-event="audit_agree">审核通过</a>
|
||||
<a class="layui-btn" lay-event="audit_refuse">审核拒绝</a>
|
||||
{{# } }}
|
||||
|
||||
{{# if(d.status == -1){ }}
|
||||
<a class="layui-btn" lay-event="detail_refuse">拒绝理由</a>
|
||||
{{# } }}
|
||||
|
||||
<!-- 只有经办人才能操作入库单 -->
|
||||
{{# if((d.status == 1 || d.status == -1) && d.operater == {$user_info['uid']} ){ }}
|
||||
<a class="layui-btn" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn" lay-event="delete">删除</a>
|
||||
{{# } }}
|
||||
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var table, form, laytpl, element, layer_pass;
|
||||
layui.use(['form', 'laytpl', 'element'], function() {
|
||||
form = layui.form;
|
||||
laytpl = layui.laytpl;
|
||||
element = layui.element;
|
||||
form.render();
|
||||
|
||||
table = new Table({
|
||||
elem: '#wastage_list',
|
||||
url: ns.url("stock://shop/stock/wastage"),
|
||||
cols: [
|
||||
[{
|
||||
field: 'document_no',
|
||||
title: '出库单号',
|
||||
width: '15%',
|
||||
}, {
|
||||
field: 'store_name',
|
||||
title: '门店',
|
||||
width: '15%',
|
||||
}, {
|
||||
field: 'type_name',
|
||||
title: '单据类型',
|
||||
width: '10%',
|
||||
}, {
|
||||
field: 'document_money',
|
||||
title: '单据金额',
|
||||
width: '10%',
|
||||
}, {
|
||||
field: 'status_name',
|
||||
title: '审核状态',
|
||||
width: '10%',
|
||||
}, {
|
||||
title: '操作人',
|
||||
width: '15%',
|
||||
templet: function(data) {
|
||||
var html = '';
|
||||
html += '经办人:' + data.operater_name + '<br/>';
|
||||
if(data.verifier_name) html += '审核人:' + data.verifier_name;
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
title: '操作时间',
|
||||
width: '15%',
|
||||
templet: function(data) {
|
||||
var html = '';
|
||||
html += '制单时间:' + ns.time_to_date(data.create_time) + '<br/>';
|
||||
if (data.time) html += '出库时间:' + ns.time_to_date(data.time) + '<br/>';
|
||||
if (data.audit_time) html += '审核时间:' + ns.time_to_date(data.audit_time);
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
title: '操作',
|
||||
width: '10%',
|
||||
align: 'right',
|
||||
toolbar: '#operation',
|
||||
}]
|
||||
]
|
||||
});
|
||||
|
||||
// 监听工具栏操作
|
||||
table.tool(function(obj) {
|
||||
var data = obj.data;
|
||||
switch (obj.event) {
|
||||
case 'audit_agree':
|
||||
// 审核通过
|
||||
agree(data.document_id);
|
||||
break;
|
||||
case 'audit_refuse':
|
||||
// 审核拒绝
|
||||
refuse(data.document_id);
|
||||
break;
|
||||
case 'edit':
|
||||
// 编辑
|
||||
edit(data.document_id);
|
||||
break;
|
||||
case 'delete':
|
||||
// 删除
|
||||
deleteDocument(data.document_id);
|
||||
break;
|
||||
case 'detail': //查看
|
||||
window.open(ns.href("stock://shop/stock/outputdetail?document_id="+ data.document_id));
|
||||
break;
|
||||
case 'detail_refuse':
|
||||
layer.open({
|
||||
title: '拒绝理由',
|
||||
content: data.refuse_reason,
|
||||
})
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// 搜索功能
|
||||
form.on('submit(search)', function(data){
|
||||
table.reload({
|
||||
page: {
|
||||
curr: 1
|
||||
},
|
||||
where: data.field
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function add() {
|
||||
location.hash = ns.hash("stock://shop/stock/stockout");
|
||||
}
|
||||
|
||||
function edit(document_id) {
|
||||
location.hash = ns.hash("stock://shop/stock/stockout",{document_id});
|
||||
}
|
||||
|
||||
// 同意
|
||||
var agree_repeat_flag = false;
|
||||
function agree(document_id) {
|
||||
layer.confirm('确定要通过该单据吗?', function(index) {
|
||||
if(agree_repeat_flag) return;
|
||||
agree_repeat_flag = true;
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/agree"),
|
||||
data: {document_id},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
agree_repeat_flag = false;
|
||||
if (res.code >= 0) {
|
||||
listenerHash(); // 刷新页面
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
layer.closeAll();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// 拒绝
|
||||
var refuse_repeat_flag = false;
|
||||
function refuse(document_id) {
|
||||
layer.prompt({
|
||||
title: '拒绝理由',
|
||||
formType: 2,
|
||||
yes: function (index, layero) {
|
||||
var refuse_reason = layero.find(".layui-layer-input").val();
|
||||
if (!refuse_reason) {
|
||||
layer.msg('请输入拒绝理由!', {icon: 5, anim: 6});
|
||||
return;
|
||||
}
|
||||
if (refuse_repeat_flag) return;
|
||||
refuse_repeat_flag = true;
|
||||
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/refuse"),
|
||||
data: {document_id, refuse_reason},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function (res) {
|
||||
layer.msg(res.message);
|
||||
refuse_repeat_flag = false;
|
||||
|
||||
if (res.code >= 0) {
|
||||
listenerHash(); // 刷新页面
|
||||
}
|
||||
}
|
||||
});
|
||||
layer.close(index);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 删除单据
|
||||
var delete_repeat_flag = false;
|
||||
function deleteDocument(document_id) {
|
||||
layer.confirm('确定要删除该单据吗?', function(index) {
|
||||
if(delete_repeat_flag) return;
|
||||
delete_repeat_flag = true;
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/stock/delete"),
|
||||
data: {document_id},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
delete_repeat_flag = false;
|
||||
if (res.code >= 0) {
|
||||
listenerHash(); // 刷新页面
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
layer.closeAll();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
233
addon/stock/shop/view/transform/add_or_edit.html
Executable file
233
addon/stock/shop/view/transform/add_or_edit.html
Executable file
@@ -0,0 +1,233 @@
|
||||
<style>
|
||||
#goods thead th{ background-color: #f7f7f7;}
|
||||
/* 优惠商品 */
|
||||
.goods-title{display: flex;align-items: center;}
|
||||
.goods-title .goods-img{display: flex;align-items: center;justify-content: center;width: 55px;height: 55px;margin-right: 5px;}
|
||||
.goods-title .goods-img img{max-height: 100%;max-width: 100%;}
|
||||
.goods-title .goods-name{flex: 1;line-height: 1.6;}
|
||||
.goods_num {padding-left: 20px;}
|
||||
</style>
|
||||
|
||||
<div class="layui-form form-wrap">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><span class="required">*</span>转换名称:</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="name" lay-verify="required" autocomplete="off" class="layui-input len-long" maxlength="255" value="{$transform_info.name ?? ''}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><span class="required">*</span>转换商品:</label>
|
||||
<div class="layui-input-block">
|
||||
<table class="layui-table" id="goods" lay-skin="line" lay-size="lg">
|
||||
<colgroup>
|
||||
<col width="60%">
|
||||
<col width="30%">
|
||||
<col width="10%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>商品名称</th>
|
||||
<th>基本单位数量</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody">
|
||||
</tbody>
|
||||
</table>
|
||||
<script type="text/html" id="tbody_tpl" >
|
||||
{{# d.forEach(function(item, index){ }}
|
||||
<tr data-index="{{ index }}">
|
||||
<td>
|
||||
<div class="goods-title">
|
||||
<div class="goods-img">
|
||||
<img layer-src="{{ns.img(item.sku_image, 'big')}}" src="{{ns.img(item.sku_image, 'small')}}" alt="">
|
||||
</div>
|
||||
<p class="multi-line-hiding goods-name">{{item.sku_name}}</p>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<input name="num" type="number" lay-verify="num" placeholder="请输入基本单位数量" autocomplete="off" class="layui-input len-mid" value="{{item.num}}">
|
||||
</td>
|
||||
<td class='operation'>
|
||||
<div class='table-btn'>
|
||||
<a href='javascript:;' class='layui-btn' data-action="delete">删除</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{# }) }}
|
||||
{{# if(d.length == 0){ }}
|
||||
<tr class="goods-empty">
|
||||
<td colspan="3">
|
||||
<div>未选择商品</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{# } }}
|
||||
</script>
|
||||
<button class="layui-btn" id="select_goods">选择商品</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
|
||||
<button class="layui-btn layui-btn-primary" onclick="back()">返回</button>
|
||||
</div>
|
||||
<input type="hidden" name="transform_id" value="{$transform_info.transform_id ?? 0}">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var form, selectGoodsSkuId = [];
|
||||
var data_table;
|
||||
var transform_id = Number($("input[name='transform_id']").val());
|
||||
var goods_list = [];
|
||||
if(transform_id > 0){
|
||||
goods_list = {:json_encode($transform_info.goods_list ?? [])};
|
||||
}
|
||||
layui.use("form", function() {
|
||||
form = layui.form;
|
||||
var repeat_flag = false; //防重复标识
|
||||
|
||||
/**
|
||||
* 监听提交
|
||||
*/
|
||||
form.on('submit(save)', function(data) {
|
||||
let goods_list = data_table.getData();
|
||||
if(goods_list.length < 2){
|
||||
layer.msg('请至少选择两种商品');
|
||||
return;
|
||||
}
|
||||
data.field.goods_list = JSON.stringify(goods_list);
|
||||
|
||||
let action = 'add';
|
||||
let action_name = '添加';
|
||||
if(transform_id > 0){
|
||||
action = 'edit';
|
||||
action_name = '编辑';
|
||||
}
|
||||
|
||||
if (repeat_flag) return;
|
||||
repeat_flag = true;
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
dataType: 'JSON',
|
||||
url: ns.url("stock://shop/transform/"+action),
|
||||
data: data.field,
|
||||
async: false,
|
||||
success: function(res) {
|
||||
repeat_flag = false;
|
||||
if (res.code == 0) {
|
||||
layer.confirm(action_name+'成功', {
|
||||
title: '操作提示',
|
||||
btn: ['返回列表', '继续'+action_name],
|
||||
closeBtn: 0,
|
||||
yes: function(index, layero) {
|
||||
location.hash = ns.hash("stock://shop/transform/lists");
|
||||
layer.close(index);
|
||||
},
|
||||
btn2: function(index, layero) {
|
||||
listenerHash(); // 刷新页面
|
||||
layer.close(index);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
form.verify({
|
||||
num: function(value) {
|
||||
if(value === ''){
|
||||
return '请输入基本单位数量';
|
||||
}
|
||||
if(!ns.getRegexp('>0num').test(value)){
|
||||
return '基本单位数量必须为正整数';
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
function back() {
|
||||
location.hash = ns.hash("stock://shop/transform/lists");
|
||||
}
|
||||
|
||||
function DataTable(param){
|
||||
param = param || {};
|
||||
let that = this;
|
||||
that.data = param.data || [];
|
||||
that.layui = null;
|
||||
|
||||
that.init();
|
||||
}
|
||||
DataTable.prototype = {
|
||||
select : function (){
|
||||
let that = this;
|
||||
let num_data = {};
|
||||
that.data.forEach((item)=>{
|
||||
num_data[item.sku_id] = item.num;
|
||||
})
|
||||
goodsSelect(function (data) {
|
||||
that.data = [];
|
||||
Object.values(data).forEach((goods_item)=>{
|
||||
Object.values(goods_item.selected_sku_list).forEach((sku_item,index)=>{
|
||||
sku_item.num = num_data[sku_item.sku_id] || 1;
|
||||
that.data.push(sku_item);
|
||||
})
|
||||
})
|
||||
that.render();
|
||||
}, Object.keys(num_data).toString(), {mode: "sku",goods_class:'1,6'});
|
||||
},
|
||||
delete : function (index){
|
||||
let that = this;
|
||||
that.data.splice(index, 1);
|
||||
that.render();
|
||||
},
|
||||
render : function (){
|
||||
let that = this;
|
||||
that.layui.laytpl($('#tbody_tpl').html()).render(that.data,function(html){
|
||||
$('#tbody').html(html);
|
||||
})
|
||||
},
|
||||
bindEvent : function (){
|
||||
let that = this;
|
||||
$('#tbody').on('click', 'a[data-action=delete]', function (){
|
||||
let index = $(this).parents('tr').data('index');
|
||||
that.delete(index);
|
||||
})
|
||||
$('#tbody').on('blur', 'input[type=text],input[type=number]', function (){
|
||||
let index = $(this).parents('tr').data('index');
|
||||
let field = $(this).attr('name');
|
||||
let value = $(this).val();
|
||||
that.data[index][field] = value;
|
||||
|
||||
})
|
||||
$("#select_goods").click(function (){
|
||||
that.select();
|
||||
})
|
||||
},
|
||||
getData:function (){
|
||||
let that = this;
|
||||
let data = [];
|
||||
that.data.forEach((item, index)=>{
|
||||
data.push({
|
||||
sku_id:item.sku_id,
|
||||
num:item.num,
|
||||
})
|
||||
})
|
||||
return data;
|
||||
},
|
||||
init: function (){
|
||||
let that = this;
|
||||
layui.use("laytpl", function() {
|
||||
that.layui = layui;
|
||||
that.bindEvent();
|
||||
that.render();
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
data_table = new DataTable({
|
||||
data:goods_list,
|
||||
})
|
||||
</script>
|
||||
156
addon/stock/shop/view/transform/lists.html
Executable file
156
addon/stock/shop/view/transform/lists.html
Executable file
@@ -0,0 +1,156 @@
|
||||
<style>
|
||||
.goods-title-box{display: flex;flex-wrap: wrap;}
|
||||
.goods-title{display: flex;align-items: center;border: 1px solid #ccc;border-radius: 4px;margin: 4px;padding:4px 4px;}
|
||||
.goods-title .goods-img{display: flex;align-items: center;justify-content: center;width: 55px;height: 55px;margin-right: 5px;}
|
||||
.goods-title .goods-img img{max-height: 100%;max-width: 100%;}
|
||||
.goods-title .goods-name{width: 150px;}
|
||||
.goods-title .goods-name .name{line-height: 19px !important;}
|
||||
.goods-title .goods-name .other{color:#999;}
|
||||
</style>
|
||||
<div class="layui-collapse tips-wrap" style="margin-bottom: 15px;">
|
||||
<div class="layui-colla-item">
|
||||
<h2 class="layui-colla-title">操作提示</h2>
|
||||
<ul class="layui-colla-content layui-show">
|
||||
<li>1、一个转换关系中可以添加多个商品规格,可以是同一个商品的不同规格,也可以是不同商品的规格</li>
|
||||
<li>2、商品类型可以是实物商品和称重商品两种,请根据商品的实际销售包装设置合适的基本单位数量</li>
|
||||
<li>3、前台购买商品时可以下单的数量为转换后的库存</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 搜索框 -->
|
||||
<div class="single-filter-box">
|
||||
<button class="layui-btn" onclick="add()">添加转换关系</button>
|
||||
|
||||
<div class="layui-form">
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="search_text" placeholder="请输入关键词" autocomplete="off" class="layui-input">
|
||||
<button type="button" class="layui-btn layui-btn-primary" lay-filter="search" lay-submit>
|
||||
<i class="layui-icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table id="supplier_list" lay-filter="supplier_list"></table>
|
||||
|
||||
<script type="text/html" id="goods_list">
|
||||
<div class="goods-title-box">
|
||||
{{# d.goods_list.forEach((item)=>{ }}
|
||||
<div class="goods-title">
|
||||
<div class="goods-img">
|
||||
<img layer-src="{{ns.img(item.sku_image, 'big')}}" src="{{ns.img(item.sku_image, 'small')}}" alt="">
|
||||
</div>
|
||||
<div class="goods-name">
|
||||
<p class="multi-line-hiding name">{{item.sku_name}}</p>
|
||||
<p class="multi-line-hiding other">基本单位:{{item.num}}</p>
|
||||
<p class="multi-line-hiding other">原始库存:{{item.stock}}</p>
|
||||
<p class="multi-line-hiding other">转换库存:{{item.transform_stock}}</p>
|
||||
</div>
|
||||
</div>
|
||||
{{# }) }}
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- 操作 -->
|
||||
<script type="text/html" id="operation">
|
||||
<div class="table-btn">
|
||||
<a class="layui-btn" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn" lay-event="delete">删除</a>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var form, table;
|
||||
layui.use(['table', 'form'], function() {
|
||||
form = layui.form;
|
||||
form.render();
|
||||
table = new Table({
|
||||
elem: '#supplier_list',
|
||||
url: ns.url("stock://shop/transform/lists"),
|
||||
cols: [
|
||||
[{
|
||||
title: '转换名称',
|
||||
field: 'name',
|
||||
width: '12%',
|
||||
unresize: 'false',
|
||||
templet: function (data){
|
||||
return '<div class="text">'+ data.name +'</div>';
|
||||
},
|
||||
},{
|
||||
title: '基本单位总数',
|
||||
field: 'transform_stock',
|
||||
width: '10%',
|
||||
unresize: 'false',
|
||||
templet: function (data){
|
||||
return data.transform_stock;
|
||||
},
|
||||
},{
|
||||
title: '转换商品',
|
||||
field: 'goods_list',
|
||||
width: '68%',
|
||||
unresize: 'false',
|
||||
templet: '#goods_list',
|
||||
}, {
|
||||
title: '操作',
|
||||
width: '10%',
|
||||
toolbar: '#operation',
|
||||
unresize: 'false',
|
||||
align : 'right'
|
||||
}]
|
||||
],
|
||||
});
|
||||
|
||||
/**
|
||||
* 监听工具栏操作
|
||||
*/
|
||||
table.tool(function(obj) {
|
||||
var data = obj.data;
|
||||
switch (obj.event) {
|
||||
case 'edit':
|
||||
location.hash = ns.hash("stock://shop/transform/edit", {transform_id: data.transform_id});
|
||||
break;
|
||||
case 'delete':
|
||||
deleteTransform(data);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
function deleteTransform(data) {
|
||||
layer.confirm('确定要删除该库存转换吗?', function(index) {
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
url: ns.url("stock://shop/transform/delete"),
|
||||
data: {transform_ids: data.transform_id},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function (res) {
|
||||
layer.msg(res.message);
|
||||
if (res.code == 0) {
|
||||
table.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索功能
|
||||
*/
|
||||
form.on('submit(search)', function(data){
|
||||
table.reload({
|
||||
page: {
|
||||
curr: 1
|
||||
},
|
||||
where: data.field
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function add() {
|
||||
location.hash = ns.hash("stock://shop/transform/add");
|
||||
}
|
||||
</script>
|
||||
281
addon/stock/storeapi/controller/Allocate.php
Executable file
281
addon/stock/storeapi/controller/Allocate.php
Executable file
@@ -0,0 +1,281 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
|
||||
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\storeapi\controller;
|
||||
|
||||
use addon\stock\model\stock\Allot;
|
||||
use addon\stock\model\stock\Document;
|
||||
use app\storeapi\controller\BaseStoreApi;
|
||||
|
||||
/**
|
||||
* 库存调拨
|
||||
*/
|
||||
class Allocate extends BaseStoreApi
|
||||
{
|
||||
|
||||
/**
|
||||
* 调拨单
|
||||
* @return mixed
|
||||
*/
|
||||
public function lists()
|
||||
{
|
||||
$allot_model = new Allot();
|
||||
$page = $this->params['page'] ?? 1;
|
||||
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
|
||||
$allot_no = $this->params['allot_no'] ?? '';
|
||||
$store_id = $this->store_id;
|
||||
|
||||
$condition = [
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
];
|
||||
$condition[] = [ 'output_store_id|input_store_id', '=', $store_id ];
|
||||
|
||||
if ($allot_no) {
|
||||
$condition[] = [ 'allot_no', '=', $allot_no ];
|
||||
}
|
||||
$result = $allot_model->getStockAllotPageList($condition, $page, $page_size, 'create_time desc');
|
||||
return $this->response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情
|
||||
*/
|
||||
public function detail()
|
||||
{
|
||||
$allot_id = $this->params['allot_id'] ?? 0;
|
||||
$condition = [
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
[ 'allot_id', '=', $allot_id ],
|
||||
[ 'output_store_id|input_store_id', '=', $this->store_id ]
|
||||
];
|
||||
$allot_model = new Allot();
|
||||
$detail = $allot_model->getAllotInfo($condition);
|
||||
$detail[ 'data' ][ 'uid' ] = $this->user_info[ 'uid' ];
|
||||
$document_model = new Document();
|
||||
|
||||
$detail[ 'data' ][ 'is_audit' ] = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' => $this->app_module,
|
||||
'is_admin' => $this->user_info[ 'is_admin' ],
|
||||
'menu_array' => $this->menu_array
|
||||
]
|
||||
)[ 'code' ];
|
||||
return $this->response($detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建调拨单
|
||||
*/
|
||||
public function addAllocate()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$audit_result = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' =>'store',
|
||||
'is_admin'=>$this->user_info['is_admin'],
|
||||
'menu_array'=>$this->menu_array
|
||||
]
|
||||
);
|
||||
if($audit_result['code'] < 0)
|
||||
return $this->response($audit_result);
|
||||
|
||||
$type = $this->params[ 'allot_type' ] ?? '';//in out
|
||||
$store_id = $this->params[ 'temp_store_id' ] ?? 0;
|
||||
if ($type == 'in') {
|
||||
$output_store_id = $store_id;
|
||||
$input_store_id = $this->store_id;
|
||||
} else {
|
||||
$output_store_id = $this->store_id;
|
||||
$input_store_id = $store_id;
|
||||
}
|
||||
$allot_model = new Allot();
|
||||
$data = [
|
||||
'output_store_id' => $output_store_id,
|
||||
'input_store_id' => $input_store_id,
|
||||
'remark' => $this->params[ 'remark' ] ?? '',
|
||||
'allot_no' => $this->params[ 'allot_no' ] ?? '',
|
||||
'goods_sku_list' => !empty($this->params[ 'goods_sku_list' ]) ? json_decode($this->params[ 'goods_sku_list' ], true) : [],
|
||||
'allot_time' => !empty($this->params[ 'allot_time' ]) ? date_to_time($this->params[ 'allot_time' ]) : 0,
|
||||
'is_auto_audit' => false,
|
||||
'operater' => $this->uid,
|
||||
'site_id' => $this->site_id
|
||||
];
|
||||
|
||||
$result = $allot_model->addAllot($data);
|
||||
return $this->response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑盘点记录
|
||||
* @return mixed
|
||||
*/
|
||||
public function editAllocate()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$audit_result = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' =>$this->app_module,
|
||||
'is_admin'=>$this->user_info['is_admin'],
|
||||
'menu_array'=>$this->menu_array
|
||||
]
|
||||
);
|
||||
if($audit_result['code'] < 0)
|
||||
return $this->response($audit_result);
|
||||
|
||||
$type = $this->params[ 'allot_type' ] ?? '';//in out
|
||||
$store_id = $this->params[ 'temp_store_id' ] ?? 0;
|
||||
if ($type == 'in') {
|
||||
$output_store_id = $store_id;
|
||||
$input_store_id = $this->store_id;
|
||||
} else {
|
||||
$output_store_id = $this->store_id;
|
||||
$input_store_id = $store_id;
|
||||
}
|
||||
$allot_model = new Allot();
|
||||
$data = [
|
||||
'output_store_id' => $output_store_id,
|
||||
'input_store_id' => $input_store_id,
|
||||
'remark' => $this->params[ 'remark' ] ?? '',
|
||||
'allot_no' => $this->params[ 'allot_no' ] ?? '',
|
||||
'allot_id' => $this->params[ 'allot_id' ] ?? '',
|
||||
'goods_sku_list' => !empty($this->params[ 'goods_sku_list' ]) ? json_decode($this->params[ 'goods_sku_list' ], true) : [],
|
||||
'allot_time' => !empty($this->params[ 'allot_time' ]) ? date_to_time($this->params[ 'allot_time' ]) : 0,
|
||||
'operater' => $this->uid,
|
||||
'user_info' => $this->user_info,
|
||||
'is_auto_audit' => false,
|
||||
'site_id' => $this->site_id
|
||||
];
|
||||
|
||||
$result = $allot_model->editAllot($data);
|
||||
return $this->response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取编辑调拨单数据
|
||||
* @return false|string
|
||||
*/
|
||||
public function editData()
|
||||
{
|
||||
$allot_id = $this->params['allot_id'] ?? 0;
|
||||
|
||||
$allot_model = new Allot();
|
||||
$condition = [
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
[ 'allot_id', '=', $allot_id ],
|
||||
[ 'output_store_id|input_store_id', '=', $this->store_id ],
|
||||
];
|
||||
$allot_info = $allot_model->getAllotEditData($condition);
|
||||
return $this->response($allot_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过审核
|
||||
* @return false|string
|
||||
*/
|
||||
public function agree()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$audit_result = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' => $this->app_module,
|
||||
'is_admin' => $this->user_info[ 'is_admin' ],
|
||||
'menu_array' => $this->menu_array
|
||||
]
|
||||
);
|
||||
if ($audit_result[ 'code' ] < 0) {
|
||||
return $this->response($audit_result);
|
||||
}
|
||||
|
||||
$allot_id = $this->params['allot_id'] ?? 0;
|
||||
$allot_model = new Allot();
|
||||
$res = $allot_model->audit([
|
||||
'site_id' => $this->site_id,
|
||||
'user_info' => $this->user_info,
|
||||
'allot_id' => $allot_id,
|
||||
]);
|
||||
return $this->response($res);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核拒绝
|
||||
* @return false|string
|
||||
*/
|
||||
public function refuse()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$audit_result = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' => $this->app_module,
|
||||
'is_admin' => $this->user_info[ 'is_admin' ],
|
||||
'menu_array' => $this->menu_array
|
||||
]
|
||||
);
|
||||
if ($audit_result[ 'code' ] < 0) {
|
||||
return $this->response($audit_result);
|
||||
}
|
||||
|
||||
$allot_id = $this->params['allot_id'] ?? 0;
|
||||
$allot_model = new Allot();
|
||||
$refuse_reason = $this->params['refuse_reason'] ?? '';
|
||||
|
||||
$res = $allot_model->refuse([
|
||||
'site_id' => $this->site_id,
|
||||
'user_info' => $this->user_info,
|
||||
'allot_id' => $allot_id,
|
||||
'refuse_reason' => $refuse_reason
|
||||
]);
|
||||
return $this->response($res);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除单据
|
||||
* @return false|string
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
|
||||
$document_model = new Document();
|
||||
$audit_result = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' => $this->app_module,
|
||||
'is_admin' => $this->user_info[ 'is_admin' ],
|
||||
'menu_array' => $this->menu_array
|
||||
]
|
||||
);
|
||||
if ($audit_result[ 'code' ] < 0) {
|
||||
return $this->response($audit_result);
|
||||
}
|
||||
$allot_id = $this->params['allot_id'] ?? 0;
|
||||
$allot_model = new Allot();
|
||||
$res = $allot_model->delete([
|
||||
'site_id' => $this->site_id,
|
||||
'user_info' => $this->user_info,
|
||||
'allot_id' => $allot_id,
|
||||
]);
|
||||
return $this->response($res);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取调拨单号
|
||||
* @return false|string
|
||||
*/
|
||||
public function getAllotNo()
|
||||
{
|
||||
$allot_model = new Allot();
|
||||
$allot_no = $allot_model->getAllotNo();
|
||||
return $this->response($this->success($allot_no));
|
||||
}
|
||||
|
||||
}
|
||||
259
addon/stock/storeapi/controller/Check.php
Executable file
259
addon/stock/storeapi/controller/Check.php
Executable file
@@ -0,0 +1,259 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
|
||||
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\storeapi\controller;
|
||||
|
||||
use addon\stock\model\stock\Document;
|
||||
use addon\stock\model\stock\Inventory;
|
||||
use app\storeapi\controller\BaseStoreApi;
|
||||
|
||||
/**
|
||||
* 库存盘点
|
||||
*/
|
||||
class Check extends BaseStoreApi
|
||||
{
|
||||
|
||||
/**
|
||||
* 库存盘点
|
||||
* @return mixed
|
||||
*/
|
||||
public function lists()
|
||||
{
|
||||
$page = $this->params['page'] ?? 1;
|
||||
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
|
||||
$inventory_no = $this->params['inventory_no'] ?? '';
|
||||
$store_id = $this->store_id;
|
||||
$condition = [
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
];
|
||||
if ($store_id > 0) {
|
||||
$condition[] = [ 'store_id', '=', $store_id ];
|
||||
}
|
||||
if (!empty($inventory_no)) {
|
||||
$condition[] = [ 'inventory_no', 'like', '%' . $inventory_no . '%' ];
|
||||
}
|
||||
$inventory_model = new Inventory();
|
||||
$list = $inventory_model->getInventoryPageList($condition, $page, $page_size, 'create_time desc');
|
||||
return $this->response($list);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 库存盘点详情
|
||||
*/
|
||||
public function detail()
|
||||
{
|
||||
$inventory_id = $this->params['inventory_id'] ?? 0;
|
||||
$inventory_model = new Inventory();
|
||||
$condition = [
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
[ 'inventory_id', '=', $inventory_id ],
|
||||
[ 'store_id', '=', $this->store_id ],
|
||||
];
|
||||
$inventory_detail = $inventory_model->getInventoryInfo($condition);
|
||||
if (empty($inventory_detail)) {
|
||||
return $this->response($this->error('盘点单不存在'));
|
||||
}
|
||||
|
||||
$document_model = new Document();
|
||||
$inventory_detail[ 'data' ][ 'is_audit' ] = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' => $this->app_module,
|
||||
'is_admin' => $this->user_info[ 'is_admin' ],
|
||||
'menu_array' => $this->menu_array
|
||||
]
|
||||
)[ 'code' ];
|
||||
$inventory_detail[ 'data' ][ 'uid' ] = $this->user_info[ 'uid' ];
|
||||
|
||||
return $this->response($inventory_detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增盘点记录
|
||||
* @return mixed
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
$inventory_model = new Inventory();
|
||||
$store_id = $this->store_id;
|
||||
$stock_list = $this->params['stock_json'] ?? '';//商品库存映照json {{'sku_id':1, 'stock' : 10, 'cost_price':10,'source':'来源'}}
|
||||
$remark = $this->params['remark'] ?? '';
|
||||
$inventory_no = $this->params['inventory_no'] ?? '';
|
||||
$time = isset($this->params[ 'time' ]) ? date_to_time($this->params[ 'time' ]) : date('Y-m-d H:i:s');
|
||||
$stock_list = json_decode($stock_list, true);
|
||||
$params = [
|
||||
'site_id' => $this->site_id,
|
||||
'store_id' => $store_id,
|
||||
'sku_list' => $stock_list,
|
||||
'user_info' => $this->user_info,
|
||||
'is_auto_audit' => false,
|
||||
'remark' => $remark,
|
||||
'inventory_no' => $inventory_no,
|
||||
'action_time' => $time,
|
||||
];
|
||||
|
||||
|
||||
$result = $inventory_model->addInventory($params);
|
||||
return $this->response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑盘点记录
|
||||
* @return mixed
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$inventory_id = $this->params['inventory_id'] ?? 0;
|
||||
$stock_list = $this->params['stock_json'] ?? '';//商品库存映照json {{'sku_id':1, 'stock' : 10, 'cost_price':10,'source':'来源'}}
|
||||
$remark = $this->params['remark'] ?? '';
|
||||
$inventory_no = $this->params['inventory_no'] ?? '';
|
||||
$time = isset($this->params[ 'time' ]) ? date_to_time($this->params[ 'time' ]) : date('Y-m-d H:i:s');
|
||||
$store_id = $this->store_id;
|
||||
$stock_list = json_decode($stock_list, true);
|
||||
|
||||
$inventory_model = new Inventory();
|
||||
$params = [
|
||||
'site_id' => $this->site_id,
|
||||
'store_id' => $store_id,
|
||||
'sku_list' => $stock_list,
|
||||
'user_info' => $this->user_info,
|
||||
'is_auto_audit' => false,
|
||||
'inventory_id' => $inventory_id,
|
||||
'remark' => $remark,
|
||||
'inventory_no' => $inventory_no,
|
||||
'action_time' => $time,
|
||||
];
|
||||
$result = $inventory_model->editInventory($params);
|
||||
return $this->response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取编辑盘点单数据
|
||||
* @return false|string
|
||||
*/
|
||||
public function editData()
|
||||
{
|
||||
$inventory_id = $this->params['inventory_id'] ?? 0;
|
||||
|
||||
|
||||
$inventory_model = new Inventory();
|
||||
$condition = [
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
[ 'inventory_id', '=', $inventory_id ],
|
||||
[ 'store_id', '=', $this->store_id ]
|
||||
];
|
||||
$inventory_info = $inventory_model->getInventoryEditData($condition);
|
||||
return $this->response($inventory_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 盘点单据通过审核
|
||||
* @return false|string
|
||||
*/
|
||||
public function agree()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$audit_result = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' => $this->app_module,
|
||||
'is_admin' => $this->user_info[ 'is_admin' ],
|
||||
'menu_array' => $this->menu_array
|
||||
]
|
||||
);
|
||||
if ($audit_result[ 'code' ] < 0) {
|
||||
return $this->response($audit_result);
|
||||
}
|
||||
|
||||
$inventory_id = $this->params['inventory_id'] ?? 0;
|
||||
|
||||
$inventory_model = new Inventory();
|
||||
$res = $inventory_model->audit([
|
||||
'site_id' => $this->site_id,
|
||||
'user_info' => $this->user_info,
|
||||
'inventory_id' => $inventory_id
|
||||
]);
|
||||
return $this->response($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 盘点单据审核拒绝
|
||||
* @return false|string
|
||||
*/
|
||||
public function refuse()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$audit_result = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' => $this->app_module,
|
||||
'is_admin' => $this->user_info[ 'is_admin' ],
|
||||
'menu_array' => $this->menu_array
|
||||
]
|
||||
);
|
||||
if ($audit_result[ 'code' ] < 0) {
|
||||
return $this->response($audit_result);
|
||||
}
|
||||
|
||||
$inventory_id = $this->params['inventory_id'] ?? 0;
|
||||
$refuse_reason = $this->params['refuse_reason'] ?? '';
|
||||
|
||||
$inventory_model = new Inventory();
|
||||
$res = $inventory_model->refuse([
|
||||
'site_id' => $this->site_id,
|
||||
'user_info' => $this->user_info,
|
||||
'inventory_id' => $inventory_id,
|
||||
'refuse_reason' => $refuse_reason
|
||||
]);
|
||||
return $this->response($res);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除盘点单据【待审核状态】
|
||||
* @return false|string
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$audit_result = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' => $this->app_module,
|
||||
'is_admin' => $this->user_info[ 'is_admin' ],
|
||||
'menu_array' => $this->menu_array
|
||||
]
|
||||
);
|
||||
if ($audit_result[ 'code' ] < 0) {
|
||||
return $this->response($audit_result);
|
||||
}
|
||||
|
||||
$inventory_id = $this->params['inventory_id'] ?? 0;
|
||||
|
||||
$inventory_model = new Inventory();
|
||||
$res = $inventory_model->delete([
|
||||
'site_id' => $this->site_id,
|
||||
'user_info' => $this->user_info,
|
||||
'inventory_id' => $inventory_id
|
||||
]);
|
||||
return $this->response($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取盘点单号
|
||||
* @return false|string
|
||||
*/
|
||||
public function getInventoryNo()
|
||||
{
|
||||
$inventory_model = new Inventory();
|
||||
$inventory_no = $inventory_model->inventoryNo();
|
||||
return $this->response($this->success($inventory_no));
|
||||
}
|
||||
|
||||
}
|
||||
238
addon/stock/storeapi/controller/Manage.php
Executable file
238
addon/stock/storeapi/controller/Manage.php
Executable file
@@ -0,0 +1,238 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
|
||||
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\storeapi\controller;
|
||||
|
||||
use addon\stock\model\stock\Document;
|
||||
use addon\stock\model\stock\Stock as StockModel;
|
||||
use app\dict\goods\GoodsDict;
|
||||
use app\model\goods\Goods;
|
||||
use app\model\goods\GoodsCategory;
|
||||
use app\storeapi\controller\BaseStoreApi;
|
||||
|
||||
/**
|
||||
* 库存管理
|
||||
*/
|
||||
class Manage extends BaseStoreApi
|
||||
{
|
||||
|
||||
/**
|
||||
* 库存管理
|
||||
*/
|
||||
public function lists()
|
||||
{
|
||||
$page = $this->params['page'] ?? 1;
|
||||
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
|
||||
$search = $this->params['search'] ?? '';
|
||||
$category_id = $this->params['category_id'] ?? '';
|
||||
$min_stock = $this->params['min_stock'] ?? 0;
|
||||
$max_stock = $this->params['max_stock'] ?? 0;
|
||||
|
||||
$store_id = $this->store_id;
|
||||
|
||||
$condition = [];
|
||||
$condition[] = [ 'gs.site_id', '=', $this->site_id ];
|
||||
$condition[] = [ 'g.is_delete', '=', 0 ];
|
||||
|
||||
$condition[] = [ 'g.goods_class', 'in', [ GoodsDict::real, GoodsDict::weigh ] ];
|
||||
if (!empty($search)) {
|
||||
$condition[] = [ 'gs.sku_name|sku_no', 'like', '%' . $search . '%' ];
|
||||
}
|
||||
|
||||
if (!empty($category_id)) {
|
||||
$condition[] = [ 'g.category_id', 'like', '%,' . $category_id . ',%' ];
|
||||
}
|
||||
if ($min_stock > 0 && $max_stock > 0) {
|
||||
$condition[] = [ 'sgs.real_stock', 'between', [ $min_stock, $max_stock ] ];
|
||||
} else if ($min_stock > 0 && $max_stock == 0) {
|
||||
$condition[] = [ 'sgs.real_stock', '>', $min_stock ];
|
||||
} else if ($min_stock == 0 && $max_stock > 0) {
|
||||
$condition[] = [ 'sgs.real_stock', '<', $max_stock ];
|
||||
}
|
||||
|
||||
$field = 'gs.stock,gs.*,g.unit';
|
||||
$join = [
|
||||
[ 'goods g', 'g.goods_id = gs.goods_id', 'left' ],
|
||||
];
|
||||
|
||||
if ($store_id > 0) {
|
||||
$join[] = [
|
||||
'store_goods_sku sgs',
|
||||
'sgs.sku_id = gs.sku_id and (sgs.store_id is null or sgs.store_id = ' . $store_id . ')',
|
||||
'left'
|
||||
];
|
||||
$field .= ',sgs.stock, sgs.real_stock';
|
||||
}
|
||||
|
||||
$goods_model = new \app\model\goods\Goods();
|
||||
$list = $goods_model->getGoodsSkuPageList($condition, $page, $page_size, 'g.create_time desc', $field, 'gs', $join);
|
||||
return $this->response($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 库存流水
|
||||
*/
|
||||
public function records()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$sku_id = $this->params['sku_id'] ?? 0;
|
||||
$goods_id = $this->params['goods_id'] ?? 0;
|
||||
$page = $this->params['page'] ?? 1;
|
||||
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
|
||||
$start_time = $this->params['start_time'] ?? 0;
|
||||
$end_time = $this->params['end_time'] ?? 0;
|
||||
$type = $this->params['type'] ?? '';
|
||||
|
||||
$condition = [
|
||||
[ 'dg.site_id', '=', $this->site_id ],
|
||||
[ 'd.store_id', '=', $this->store_id ],
|
||||
];
|
||||
if ($sku_id > 0) {
|
||||
$condition[] = [ 'dg.goods_sku_id', '=', $sku_id ];
|
||||
}
|
||||
if (!empty($type)) {
|
||||
$condition[] = [ 'dt.key', '=', $type ];
|
||||
}
|
||||
//注册时间
|
||||
if ($start_time != '' && $end_time != '') {
|
||||
$condition[] = [ 'dg.create_time', 'between', [ strtotime($start_time), strtotime($end_time) ] ];
|
||||
} else if ($start_time != '' && $end_time == '') {
|
||||
$condition[] = [ 'dg.create_time', '>=', strtotime($start_time) ];
|
||||
} else if ($start_time == '' && $end_time != '') {
|
||||
$condition[] = [ 'dg.create_time', '<=', strtotime($end_time) ];
|
||||
}
|
||||
|
||||
if ($sku_id > 0) {
|
||||
$condition[] = [ 'dg.goods_sku_id', '=', $sku_id ];
|
||||
}
|
||||
if ($goods_id > 0) {
|
||||
$condition[] = [ 'dg.goods_id', '=', $goods_id ];
|
||||
}
|
||||
|
||||
$result = $document_model->getDocumentGoodsPageList($condition, $page, $page_size, 'dg.create_time desc');
|
||||
return $this->response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品规格列表(仅作临时用)
|
||||
*/
|
||||
public function getSkuList()
|
||||
{
|
||||
$page = $this->params['page'] ?? 1;
|
||||
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
|
||||
$goods_id = $this->params['goods_id'] ?? 0;
|
||||
$search = $this->params['search'] ?? '';
|
||||
|
||||
$temp_store_id = $this->params[ 'temp_store_id' ] ?? 0;
|
||||
|
||||
$store_id = $temp_store_id > 0 ? $temp_store_id : $this->store_id;
|
||||
$stock_model = new StockModel();
|
||||
$condition = [
|
||||
[ 'gs.site_id', '=', $this->site_id ],
|
||||
[ 'g.goods_class', 'in', [ GoodsDict::real, GoodsDict::weigh ] ],
|
||||
[ 'g.is_delete', '=', 0 ]
|
||||
];
|
||||
if (!empty($search)) {
|
||||
$condition[] = [ 'gs.sku_name|gs.spec_name|g.goods_name|gs.sku_no', 'like', '%' . $search . '%' ];
|
||||
}
|
||||
if (!empty($goods_id)) {
|
||||
$condition[] = [ 'g.goods_id', '=', $goods_id ];
|
||||
}
|
||||
if ($store_id > 0) {
|
||||
//查询商品支持门店(支持当前门店或全部)
|
||||
$condition[] = [ 'g.sale_store', 'like', [ '%,' . $store_id . ',%', '%all%'], 'or' ];
|
||||
}
|
||||
$field = 'gs.sku_id, gs.goods_id, gs.sku_name, gs.sku_no, gs.price, gs.discount_price,gs.goods_class, gs.goods_name, gs.spec_name, sgs.stock,sgs.real_stock,sgs.price,sgs.cost_price';
|
||||
$sku_list = $stock_model->getStoreGoodsSkuList($condition, $field, 'gs.create_time desc', $store_id, $page, $page_size);
|
||||
return $this->response($sku_list);
|
||||
}
|
||||
|
||||
public function getDocumentType()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$type_list = $document_model->getDocumentTypeList();
|
||||
return $this->response($type_list);
|
||||
}
|
||||
|
||||
public function getGoodsCategory()
|
||||
{
|
||||
$goods_model = new Goods();
|
||||
$category_id_arr = $goods_model->getGoodsCategoryIds([
|
||||
[ 'is_delete', '=', 0 ],
|
||||
[ 'goods_state', '=', 1 ],
|
||||
[ 'goods_stock', '>', 0 ],
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
])[ 'data' ];
|
||||
|
||||
$goods_category_model = new GoodsCategory();
|
||||
$field = 'category_id,category_name as title,pid';
|
||||
$list = $goods_category_model->getCategoryList([
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
[ 'category_id', 'in', $category_id_arr ]
|
||||
], $field)[ 'data' ];
|
||||
$tree['data'] = list_to_tree($list, 'category_id', 'pid', 'children', 0);
|
||||
return $this->response($tree);
|
||||
}
|
||||
|
||||
public function getStoreGoods()
|
||||
{
|
||||
$page = $this->params['page'] ?? 1;
|
||||
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
|
||||
$goods_id = $this->params['goods_id'] ?? 0;
|
||||
$search = $this->params['search_text'] ?? '';
|
||||
$category_id = $this->params['category_id'] ?? '';
|
||||
$temp_store_id = $this->params[ 'temp_store_id' ] ?? 0;
|
||||
$goods_class = $this->params['goods_class'] ?? '';
|
||||
$brand_id = $this->params['brand_id'] ?? '';
|
||||
$supplier_id = $this->params['supplier_id'] ?? '';
|
||||
|
||||
$store_id = $temp_store_id > 0 ? $temp_store_id : $this->store_id;
|
||||
$stock_model = new StockModel();
|
||||
|
||||
$condition = [
|
||||
[ 'g.is_delete', '=', 0 ],
|
||||
[ 'g.goods_state', '=', 1 ],
|
||||
// [ 'g.goods_stock', '>', 0 ],
|
||||
[ 'g.goods_class', 'in', [ GoodsDict::real, GoodsDict::weigh ] ],
|
||||
[ 'gs.site_id', '=', $this->site_id ],
|
||||
[ 'g.is_virtual', '=', 0]
|
||||
];
|
||||
|
||||
if (!empty($search)) {
|
||||
$condition[] = [ 'gs.sku_name|gs.spec_name|g.goods_name|gs.sku_no', 'like', '%' . $search . '%' ];
|
||||
}
|
||||
if (!empty($goods_id)) {
|
||||
$condition[] = [ 'g.goods_id', '=', $goods_id ];
|
||||
}
|
||||
if ($store_id > 0) {
|
||||
//查询商品支持门店(支持当前门店或全部)
|
||||
$condition[] = [ 'g.sale_store', 'like', [ '%,' . $store_id . ',%', '%all%'], 'or' ];
|
||||
}
|
||||
|
||||
if (!empty($category_id)) {
|
||||
$condition[] = [ 'g.category_id', 'like', '%,' . $category_id . ',%' ];
|
||||
}
|
||||
if(!empty($goods_class)){
|
||||
$condition[] = ['g.goods_class', '=', $goods_class];
|
||||
}
|
||||
if(!empty($brand_id)){
|
||||
$condition[] = ['g.brand_id', '=', $brand_id];
|
||||
}
|
||||
if(!empty($supplier_id)){
|
||||
$condition[] = ['g.supplier_id', '=', $supplier_id];
|
||||
}
|
||||
|
||||
$field = 'gs.sku_id, gs.goods_id, gs.sku_name, gs.sku_no, gs.price, gs.discount_price,gs.goods_class, gs.goods_name, gs.spec_name, gs.sku_image,gs.unit, sgs.stock,sgs.real_stock,sgs.store_id, sgs.price,sgs.cost_price';
|
||||
$sku_list = $stock_model->getStoreGoodsSkuPage($condition, $field, 'gs.goods_id desc, gs.create_time desc, gs.sku_id desc', $store_id, $page, $page_size);
|
||||
return $this->response($sku_list);
|
||||
}
|
||||
}
|
||||
240
addon/stock/storeapi/controller/Storage.php
Executable file
240
addon/stock/storeapi/controller/Storage.php
Executable file
@@ -0,0 +1,240 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
|
||||
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\storeapi\controller;
|
||||
|
||||
use addon\stock\dict\StockDict;
|
||||
use addon\stock\model\stock\Document;
|
||||
use app\storeapi\controller\BaseStoreApi;
|
||||
|
||||
/**
|
||||
* 入库管理
|
||||
*/
|
||||
class Storage extends BaseStoreApi
|
||||
{
|
||||
|
||||
/**
|
||||
* 入库管理(应该豁免盘点)
|
||||
* @return mixed
|
||||
*/
|
||||
public function lists()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$page = $this->params['page'] ?? 1;
|
||||
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
|
||||
$search_text = $this->params['search_text'] ?? '';
|
||||
$status = $this->params['status'] ?? '';
|
||||
$store_id = $this->store_id;
|
||||
$condition = [
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
[ 'type', '=', StockDict::input ]
|
||||
];
|
||||
if ($store_id > 0) {
|
||||
$condition[] = [ 'store_id', 'in', $store_id ];
|
||||
}
|
||||
if (!empty($status)) {
|
||||
$condition[] = [ 'document_no', 'like', '%' . $status . '%' ];
|
||||
}
|
||||
|
||||
if ($status !== '') {
|
||||
$condition[] = [ 'status', '=', $status ];
|
||||
}
|
||||
|
||||
$field = 'document_id, document_no, key, goods_money, promotion_money, invoice_money, document_money, remark, status, create_time, store_id, store_name, operater, operater_name, verifier, verifier_name, inventory_id,refuse_reason,audit_time';
|
||||
$result = $document_model->getDocumentPageList($condition, $page, $page_size, 'create_time desc', $field);
|
||||
return $this->response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加/编辑入库单
|
||||
*/
|
||||
public function stockin()
|
||||
{
|
||||
$stock_json = $this->params['stock_json'] ?? '';
|
||||
$document_id = isset($this->params[ 'document_id' ]) ? (int) $this->params[ 'document_id' ] : 0;
|
||||
$remark = $this->params['remark'] ?? '';
|
||||
$document_no = $this->params['document_no'] ?? '';
|
||||
$time = isset($this->params[ 'time' ]) ? date_to_time($this->params[ 'time' ]) : date('Y-m-d H:i:s');
|
||||
$store_id = $this->store_id;
|
||||
$stock_array = json_decode($stock_json, true);
|
||||
|
||||
$document_model = new Document();
|
||||
|
||||
$document_params = [
|
||||
'site_id' => $this->site_id,
|
||||
'store_id' => $store_id,
|
||||
'user_info' => $this->user_info,
|
||||
'remark' => $remark,
|
||||
'document_no' => $document_no,
|
||||
'goods_sku_list' => $stock_array,
|
||||
'time' => $time
|
||||
];
|
||||
|
||||
if (!empty($document_id)) {
|
||||
$document_params[ 'document_id' ] = $document_id;
|
||||
$result = $document_model->editDocument($document_params);
|
||||
} else {
|
||||
$document_params[ 'is_auto_audit' ] = false;
|
||||
$result = $document_model->addPurchase($document_params);
|
||||
}
|
||||
return $this->response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取编辑入库单据数据
|
||||
*/
|
||||
public function editData()
|
||||
{
|
||||
$document_id = isset($this->params[ 'document_id' ]) ? (int) $this->params[ 'document_id' ] : 0;
|
||||
|
||||
$document_model = new Document();
|
||||
$condition = [
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
[ 'document_id', '=', $document_id ],
|
||||
[ 'type', '=', StockDict::input ],
|
||||
[ 'store_id', '=', $this->store_id ],
|
||||
];
|
||||
$document_info = $document_model->getDocumentEditData($condition);
|
||||
return $this->response($document_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 入库单详情
|
||||
*/
|
||||
public function detail()
|
||||
{
|
||||
$document_id = isset($this->params[ 'document_id' ]) ? (int) $this->params[ 'document_id' ] : 0;
|
||||
$document_model = new Document();
|
||||
$condition = [
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
[ 'document_id', '=', $document_id ],
|
||||
[ 'type', '=', StockDict::input ],
|
||||
[ 'store_id', '=', $this->store_id ],
|
||||
];
|
||||
$document_detail = $document_model->getDocumentDetail($condition);
|
||||
|
||||
$document_model = new Document();
|
||||
$document_detail[ 'data' ][ 'is_audit' ] = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' => $this->app_module,
|
||||
'is_admin' => $this->user_info[ 'is_admin' ],
|
||||
'menu_array' => $this->menu_array
|
||||
]
|
||||
)[ 'code' ];
|
||||
$document_detail[ 'data' ][ 'uid' ] = $this->user_info[ 'uid' ];
|
||||
return $this->response($document_detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 出入库单据通过审核
|
||||
* @return false|string
|
||||
*/
|
||||
public function agree()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$audit_result = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' => $this->app_module,
|
||||
'is_admin' => $this->user_info[ 'is_admin' ],
|
||||
'menu_array' => $this->menu_array
|
||||
]
|
||||
);
|
||||
if ($audit_result[ 'code' ] < 0) {
|
||||
return $this->response($audit_result);
|
||||
}
|
||||
|
||||
$document_id = $this->params['document_id'] ?? 0;
|
||||
|
||||
$res = $document_model->audit([
|
||||
'site_id' => $this->site_id,
|
||||
'user_info' => $this->user_info,
|
||||
'document_id' => $document_id,
|
||||
]);
|
||||
return $this->response($res);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 出入库单据审核拒绝
|
||||
* @return false|string
|
||||
*/
|
||||
public function refuse()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$audit_result = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' => $this->app_module,
|
||||
'is_admin' => $this->user_info[ 'is_admin' ],
|
||||
'menu_array' => $this->menu_array
|
||||
]
|
||||
);
|
||||
if ($audit_result[ 'code' ] < 0) {
|
||||
return $this->response($audit_result);
|
||||
}
|
||||
|
||||
$document_id = $this->params['document_id'] ?? 0;
|
||||
$refuse_reason = $this->params['refuse_reason'] ?? '';
|
||||
|
||||
$res = $document_model->refuse([
|
||||
'site_id' => $this->site_id,
|
||||
'user_info' => $this->user_info,
|
||||
'document_id' => $document_id,
|
||||
'refuse_reason' => $refuse_reason
|
||||
]);
|
||||
return $this->response($res);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除单据
|
||||
* @return false|string
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$document_id = $this->params['document_id'] ?? 0;
|
||||
|
||||
$document_model = new Document();
|
||||
$audit_result = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' => $this->app_module,
|
||||
'is_admin' => $this->user_info[ 'is_admin' ],
|
||||
'menu_array' => $this->menu_array
|
||||
]
|
||||
);
|
||||
if ($audit_result[ 'code' ] < 0) {
|
||||
return $this->response($audit_result);
|
||||
}
|
||||
|
||||
$res = $document_model->delete([
|
||||
'site_id' => $this->site_id,
|
||||
'user_info' => $this->user_info,
|
||||
'document_id' => $document_id,
|
||||
]);
|
||||
return $this->response($res);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取入库单号
|
||||
* @return false|string
|
||||
*/
|
||||
public function getDocumentNo()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$document_type_info = $document_model->getDocumentTypeInfo([ 'key' => 'PURCHASE' ]);
|
||||
$prefix = $document_type_info[ 'prefix' ];
|
||||
$document_no = $document_model->createDocumentNo($prefix);
|
||||
return $this->response($this->success($document_no));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
35
addon/stock/storeapi/controller/Store.php
Executable file
35
addon/stock/storeapi/controller/Store.php
Executable file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
|
||||
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\storeapi\controller;
|
||||
|
||||
use addon\stock\model\Store as StoreModel;
|
||||
use app\storeapi\controller\BaseStoreApi;
|
||||
|
||||
|
||||
/**
|
||||
* 库存调拨
|
||||
*/
|
||||
class Store extends BaseStoreApi
|
||||
{
|
||||
|
||||
/**
|
||||
* 获取门店
|
||||
* @return false|string
|
||||
*/
|
||||
public function lists()
|
||||
{
|
||||
$store_list = ( new StoreModel )->getStoreList($this->site_id);
|
||||
return $this->response($store_list);
|
||||
}
|
||||
|
||||
}
|
||||
159
addon/stock/storeapi/controller/Wastage.php
Executable file
159
addon/stock/storeapi/controller/Wastage.php
Executable file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
|
||||
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\stock\storeapi\controller;
|
||||
|
||||
use addon\stock\dict\StockDict;
|
||||
use addon\stock\model\stock\Document;
|
||||
use app\storeapi\controller\BaseStoreApi;
|
||||
|
||||
/**
|
||||
* 出库管理
|
||||
*/
|
||||
class Wastage extends BaseStoreApi
|
||||
{
|
||||
/**
|
||||
* 出库管理(应该豁免盘点)
|
||||
* @return mixed
|
||||
*/
|
||||
public function lists()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$page = $this->params['page'] ?? 1;
|
||||
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
|
||||
$search_text = $this->params['search_text'] ?? '';
|
||||
$status = $this->params['status'] ?? '';
|
||||
|
||||
$store_id = $this->store_id;
|
||||
$condition = [
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
[ 'type', '=', StockDict::output ]
|
||||
];
|
||||
if ($store_id > 0) {
|
||||
$condition[] = [ 'store_id', '=', $store_id ];
|
||||
}
|
||||
if (!empty($search_text)) {
|
||||
$condition[] = [ 'document_no', 'like', '%' . $search_text . '%' ];
|
||||
}
|
||||
|
||||
if ($status !== '') {
|
||||
$condition[] = [ 'status', '=', $status ];
|
||||
}
|
||||
$field = 'document_id, document_no, key, goods_money, promotion_money, invoice_money, document_money, remark, status, create_time, store_id, store_name, operater, operater_name, verifier, verifier_name, inventory_id,refuse_reason,audit_time';
|
||||
$result = $document_model->getDocumentPageList($condition, $page, $page_size, 'create_time desc', $field);
|
||||
|
||||
return $this->response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加/编辑出库单
|
||||
*/
|
||||
public function stockout()
|
||||
{
|
||||
$stock_json = $this->params['stock_json'] ?? '';
|
||||
$document_id = isset($this->params[ 'document_id' ]) ? (int) $this->params[ 'document_id' ] : 0;
|
||||
$remark = $this->params['remark'] ?? '';
|
||||
$document_no = $this->params['document_no'] ?? '';
|
||||
$time = isset($this->params[ 'time' ]) ? date_to_time($this->params[ 'time' ]) : date('Y-m-d H:i:s');
|
||||
$store_id = $this->store_id;
|
||||
$stock_array = json_decode($stock_json, true);
|
||||
|
||||
$document_model = new Document();
|
||||
|
||||
if (!empty($document_id)) {
|
||||
$result = $document_model->editDocument([
|
||||
'document_id' => $document_id,
|
||||
'site_id' => $this->site_id,
|
||||
'store_id' => $store_id,
|
||||
'user_info' => $this->user_info,
|
||||
'goods_sku_list' => $stock_array,
|
||||
'remark' => $remark,
|
||||
'time' => $time,
|
||||
]);
|
||||
} else {
|
||||
$result = $document_model->addOtherOutput([
|
||||
'site_id' => $this->site_id,
|
||||
'store_id' => $store_id,
|
||||
'user_info' => $this->user_info,
|
||||
'goods_sku_list' => $stock_array,
|
||||
'is_out_stock' => 1,
|
||||
'is_auto_audit' => false,
|
||||
'remark' => $remark,
|
||||
'time' => $time,
|
||||
'document_no' => $document_no,
|
||||
|
||||
]);
|
||||
}
|
||||
return $this->response($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取编辑出库单据数据
|
||||
*/
|
||||
public function editData()
|
||||
{
|
||||
$document_id = isset($this->params[ 'document_id' ]) ? (int) $this->params[ 'document_id' ] : 0;
|
||||
|
||||
$document_model = new Document();
|
||||
$condition = [
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
[ 'document_id', '=', $document_id ],
|
||||
[ 'type', '=', StockDict::output ],
|
||||
[ 'store_id', '=', $this->store_id ],
|
||||
];
|
||||
$document_info = $document_model->getDocumentEditData($condition);
|
||||
return $this->response($document_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 出库单详情
|
||||
*/
|
||||
public function detail()
|
||||
{
|
||||
$document_id = isset($this->params[ 'document_id' ]) ? (int) $this->params[ 'document_id' ] : 0;
|
||||
|
||||
$document_model = new Document();
|
||||
$condition = [
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
[ 'document_id', '=', $document_id ],
|
||||
[ 'type', '=', StockDict::output ],
|
||||
[ 'store_id', '=', $this->store_id ],
|
||||
];
|
||||
$document_detail = $document_model->getDocumentDetail($condition);
|
||||
|
||||
$document_model = new Document();
|
||||
$document_detail[ 'data' ][ 'is_audit' ] = $document_model->checkAudit(
|
||||
[
|
||||
'app_module' => $this->app_module,
|
||||
'is_admin' => $this->user_info[ 'is_admin' ],
|
||||
'menu_array' => $this->menu_array
|
||||
]
|
||||
)[ 'code' ];
|
||||
$document_detail[ 'data' ][ 'uid' ] = $this->user_info[ 'uid' ];
|
||||
return $this->response($document_detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取出库单号
|
||||
* @return false|string
|
||||
*/
|
||||
public function getDocumentNo()
|
||||
{
|
||||
$document_model = new Document();
|
||||
$document_type_info = $document_model->getDocumentTypeInfo([ 'key' => 'OTHERCK' ]);
|
||||
$prefix = $document_type_info[ 'prefix' ];
|
||||
$document_no = $document_model->createDocumentNo($prefix);
|
||||
return $this->response($this->success($document_no));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user