文件
xionggeshop/application/admin/controller/shopro/operating_company/Settlement.php

505 行
19 KiB
PHP

<?php
namespace app\admin\controller\shopro\operating_company;
use app\admin\controller\shopro\Base;
use app\admin\model\shopro\operating_company\Company as CompanyModel;
use app\admin\model\shopro\operating_company\SettlementItem;
use app\admin\model\shopro\operating_company\SettlementLog;
use addons\shopro\library\Export;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use think\Db;
class Settlement extends Base
{
protected $model = null;
protected $companyModel = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\shopro\operating_company\Settlement;
$this->companyModel = new CompanyModel;
}
public function index()
{
$this->request->filter(['strip_tags']);
if ($this->request->isAjax()) {
$nobuildfields = ['company_name', 'period_range'];
list($where, $sort, $order, $offset, $limit) = $this->custombuildparams(null, $nobuildfields);
$query = $this->buildSearch()->where($where);
$total = $query->count();
$list = $this->buildSearch()
->with(['company'])
->where($where)
->order($sort, $order)
->limit($offset, $limit)
->select();
return $this->success('结算列表', null, ['total' => $total, 'rows' => $list]);
}
return $this->view->fetch();
}
protected function buildSearch()
{
$filter = $this->request->get('filter', '');
$filter = (array) json_decode($filter, true);
$query = $this->model;
if (!empty($filter['company_name'])) {
$query = $query->where('company_name', 'like', '%' . $filter['company_name'] . '%');
}
if (!empty($filter['period_range'])) {
$range = explode(' - ', $filter['period_range']);
if (count($range) === 2) {
$query = $query->where('period_start', '>=', $range[0])
->where('period_end', '<=', $range[1]);
}
}
return $query;
}
public function add()
{
if ($this->request->isPost()) {
$params = $this->request->post('row/a');
$this->validateSettlement($params);
Db::startTrans();
try {
$company = $this->companyModel->get($params['company_id']);
if (!$company) {
throw new \Exception('运营公司不存在');
}
$settlement = $this->model->create([
'settlement_sn' => $this->generateSn(),
'company_id' => $company->id,
'company_name' => $company->name,
'amount' => $params['amount'],
'period_start' => $params['period_start'],
'period_end' => $params['period_end'],
'audit_status' => isset($params['submit']) ? 1 : 0,
'pay_status' => 0,
'admin_id' => $this->auth->id,
'source' => 'manual',
]);
$this->saveItems($settlement->id, $params);
SettlementLog::record($settlement->id, 'create', $this->auth->id, $settlement->toArray());
if (isset($params['submit'])) {
SettlementLog::record($settlement->id, 'submit', $this->auth->id);
}
Db::commit();
} catch (\Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
$this->success('添加成功');
}
return $this->view->fetch();
}
public function edit($ids = null)
{
$row = $this->model->with('items')->get($ids);
if (!$row) {
$this->error('记录不存在');
}
if (!in_array($row->audit_status, [0, 3])) {
$this->error('当前状态不可编辑');
}
if ($this->request->isPost()) {
$params = $this->request->post('row/a');
$this->validateSettlement($params);
Db::startTrans();
try {
$company = $this->companyModel->get($params['company_id']);
if (!$company) {
throw new \Exception('运营公司不存在');
}
$row->save([
'company_id' => $company->id,
'company_name' => $company->name,
'amount' => $params['amount'],
'period_start' => $params['period_start'],
'period_end' => $params['period_end'],
'audit_status' => isset($params['submit']) ? 1 : ($row->audit_status == 3 ? 0 : $row->audit_status),
]);
SettlementItem::where('settlement_id', $row->id)->delete();
$this->saveItems($row->id, $params);
SettlementLog::record($row->id, 'edit', $this->auth->id);
if (isset($params['submit'])) {
SettlementLog::record($row->id, 'submit', $this->auth->id);
}
Db::commit();
} catch (\Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
$this->success('保存成功');
}
$this->view->assign('row', $row);
return $this->view->fetch();
}
public function del($ids = null)
{
$row = $this->model->get($ids);
if (!$row) {
$this->error('记录不存在');
}
if (!in_array($row->audit_status, [0, 3])) {
$this->error('仅草稿或已驳回状态可删除');
}
Db::startTrans();
try {
SettlementItem::where('settlement_id', $row->id)->delete();
SettlementLog::where('settlement_id', $row->id)->delete();
$row->delete();
Db::commit();
} catch (\Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
$this->success('删除成功');
}
public function submit()
{
$id = $this->request->post('id');
$row = $this->model->get($id);
if (!$row) {
$this->error('记录不存在');
}
if (!in_array($row->audit_status, [0, 3])) {
$this->error('当前状态不可提交');
}
$row->audit_status = 1;
$row->save();
SettlementLog::record($row->id, 'submit', $this->auth->id);
$this->success('已提交审核');
}
public function audit()
{
$id = $this->request->post('id');
$action = $this->request->post('action');
$remark = $this->request->post('remark', '');
$row = $this->model->get($id);
if (!$row) {
$this->error('记录不存在');
}
if ($row->audit_status != 1) {
$this->error('当前状态不可审核');
}
if ($action === 'approve') {
$row->audit_status = 2;
$row->audit_remark = $remark;
$row->audit_admin_id = $this->auth->id;
$row->save();
SettlementLog::record($row->id, 'approve', $this->auth->id, ['remark' => $remark]);
$this->success('审核通过');
} elseif ($action === 'reject') {
$row->audit_status = 3;
$row->audit_remark = $remark;
$row->audit_admin_id = $this->auth->id;
$row->save();
SettlementLog::record($row->id, 'reject', $this->auth->id, ['remark' => $remark]);
$this->success('已驳回');
}
$this->error('无效操作');
}
public function markPay()
{
$id = $this->request->post('id');
$payStatus = (int) $this->request->post('pay_status');
$remark = $this->request->post('remark', '');
$row = $this->model->get($id);
if (!$row) {
$this->error('记录不存在');
}
if ($row->audit_status != 2) {
$this->error('仅审核通过的结算单可标记打款');
}
if (!in_array($payStatus, [1, 2])) {
$this->error('无效的打款状态');
}
$row->pay_status = $payStatus;
$row->pay_remark = $remark;
$row->pay_time = $payStatus == 1 ? time() : null;
$row->save();
SettlementLog::record($row->id, $payStatus == 1 ? 'pay' : 'pay_fail', $this->auth->id, [
'remark' => $remark,
]);
$this->success('操作成功');
}
public function import()
{
if (!$this->request->isPost()) {
return $this->view->fetch();
}
$file = $this->request->request('file');
if (!$file) {
$this->error('请上传文件');
}
$filePath = ROOT_PATH . 'public' . DS . $file;
if (!is_file($filePath)) {
$this->error('文件不存在');
}
$ext = pathinfo($filePath, PATHINFO_EXTENSION);
if (!in_array($ext, ['csv', 'xls', 'xlsx'])) {
$this->error('不支持的文件格式');
}
$rows = $this->readImportFile($filePath, $ext);
if (count($rows) < 2) {
$this->error('导入数据为空');
}
$header = array_map('trim', $rows[0]);
$map = $this->getImportColumnMap($header);
$batch = 'IMP' . date('YmdHis');
$success = 0;
$errors = [];
Db::startTrans();
try {
for ($i = 1; $i < count($rows); $i++) {
$line = $rows[$i];
if (!$line || !array_filter($line)) {
continue;
}
try {
$data = $this->parseImportRow($line, $map);
$company = $this->companyModel->where('name', $data['company_name'])->find();
if (!$company) {
$company = $this->companyModel->create([
'name' => $data['company_name'],
'status' => 'normal',
]);
}
$settlement = $this->model->create([
'settlement_sn' => $this->generateSn(),
'company_id' => $company->id,
'company_name' => $company->name,
'amount' => $data['amount'],
'period_start' => $data['period_start'],
'period_end' => $data['period_end'],
'audit_status' => 1,
'pay_status' => 0,
'admin_id' => $this->auth->id,
'source' => 'import',
'import_batch' => $batch,
]);
if (!empty($data['order_sn']) || !empty($data['remark'])) {
SettlementItem::create([
'settlement_id' => $settlement->id,
'order_sn' => $data['order_sn'] ?? '',
'item_name' => '分成导入',
'amount' => $data['amount'],
'remark' => $data['remark'] ?? '',
]);
}
SettlementLog::record($settlement->id, 'create', $this->auth->id, ['source' => 'import']);
SettlementLog::record($settlement->id, 'submit', $this->auth->id);
$success++;
} catch (\Exception $e) {
$errors[] = '第' . ($i + 1) . '行:' . $e->getMessage();
}
}
Db::commit();
} catch (\Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
$msg = '成功导入 ' . $success . ' 条';
if ($errors) {
$msg .= ',失败 ' . count($errors) . ' 条:' . implode(';', array_slice($errors, 0, 5));
}
$this->success($msg);
}
public function export()
{
list($where, $sort, $order) = $this->custombuildparams(null, ['company_name', 'period_range']);
$list = $this->buildSearch()->where($where)->order($sort, $order)->select();
$list = collection($list)->toArray();
$expCellName = [
'settlement_sn' => '结算单号',
'company_name' => '结算对象',
'amount' => '金额',
'period_start' => '周期开始',
'period_end' => '周期结束',
'audit_status_text' => '审核状态',
'pay_status_text' => '打款状态',
'audit_remark' => '审核备注',
'pay_remark' => '打款备注',
'createtime' => '创建时间',
];
$newList = [];
foreach ($list as $item) {
$newList[] = [
'settlement_sn' => $item['settlement_sn'],
'company_name' => $item['company_name'],
'amount' => $item['amount'],
'period_start' => $item['period_start'],
'period_end' => $item['period_end'],
'audit_status_text' => $this->model->getAuditStatusList()[$item['audit_status']] ?? '',
'pay_status_text' => $this->model->getPayStatusList()[$item['pay_status']] ?? '',
'audit_remark' => $item['audit_remark'],
'pay_remark' => $item['pay_remark'],
'createtime' => date('Y-m-d H:i:s', $item['createtime']),
];
}
$export = new Export();
$export->exportExcel('运营公司结算-' . date('Y-m-d'), $expCellName, $newList);
}
public function downloadTemplate()
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$headers = ['运营公司名称', '结算金额', '周期开始', '周期结束', '订单号', '备注'];
foreach ($headers as $col => $title) {
$sheet->setCellValueByColumnAndRow($col + 1, 1, $title);
}
$sheet->setCellValueByColumnAndRow(1, 2, '示例运营公司');
$sheet->setCellValueByColumnAndRow(2, 2, '1000.00');
$sheet->setCellValueByColumnAndRow(3, 2, date('Y-m-01'));
$sheet->setCellValueByColumnAndRow(4, 2, date('Y-m-d'));
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="运营公司结算导入模板.xlsx"');
header('Cache-Control: max-age=0');
$writer = new Xlsx($spreadsheet);
$writer->save('php://output');
exit;
}
public function logs()
{
$id = $this->request->get('id');
$logs = SettlementLog::where('settlement_id', $id)->order('id desc')->select();
return $this->success('操作成功', null, $logs);
}
protected function generateSn()
{
$prefix = 'OCS' . date('Ymd');
$last = $this->model->where('settlement_sn', 'like', $prefix . '%')
->order('id desc')->value('settlement_sn');
$seq = $last ? ((int) substr($last, -6)) + 1 : 1;
return $prefix . str_pad($seq, 6, '0', STR_PAD_LEFT);
}
protected function validateSettlement($params)
{
if (empty($params['company_id']) || empty($params['amount'])
|| empty($params['period_start']) || empty($params['period_end'])) {
throw new \Exception('请填写完整结算信息');
}
if ($params['period_start'] > $params['period_end']) {
throw new \Exception('结算周期开始不能晚于结束');
}
if ($params['amount'] <= 0) {
throw new \Exception('结算金额必须大于0');
}
}
protected function saveItems($settlementId, $params)
{
if (empty($params['items']) || !is_array($params['items'])) {
return;
}
foreach ($params['items'] as $item) {
if (empty($item['amount'])) {
continue;
}
SettlementItem::create([
'settlement_id' => $settlementId,
'order_sn' => $item['order_sn'] ?? '',
'item_name' => $item['item_name'] ?? '',
'amount' => $item['amount'],
'remark' => $item['remark'] ?? '',
]);
}
}
protected function getImportColumnMap($header)
{
$aliases = [
'company_name' => ['运营公司名称', '结算对象'],
'amount' => ['结算金额', '金额'],
'period_start' => ['周期开始', '结算周期起'],
'period_end' => ['周期结束', '结算周期止'],
'order_sn' => ['订单号'],
'remark' => ['备注'],
];
$map = [];
foreach ($header as $idx => $title) {
foreach ($aliases as $key => $names) {
if (in_array($title, $names)) {
$map[$key] = $idx;
}
}
}
if (!isset($map['company_name'], $map['amount'], $map['period_start'], $map['period_end'])) {
throw new \Exception('模板表头不正确');
}
return $map;
}
protected function parseImportRow($line, $map)
{
$companyName = trim($line[$map['company_name']] ?? '');
$amount = trim($line[$map['amount']] ?? '');
$periodStart = trim($line[$map['period_start']] ?? '');
$periodEnd = trim($line[$map['period_end']] ?? '');
if (!$companyName || !$amount || !$periodStart || !$periodEnd) {
throw new \Exception('必填项不能为空');
}
if (!is_numeric($amount) || $amount <= 0) {
throw new \Exception('结算金额无效');
}
return [
'company_name' => $companyName,
'amount' => $amount,
'period_start' => date('Y-m-d', strtotime($periodStart)),
'period_end' => date('Y-m-d', strtotime($periodEnd)),
'order_sn' => isset($map['order_sn']) ? trim($line[$map['order_sn']] ?? '') : '',
'remark' => isset($map['remark']) ? trim($line[$map['remark']] ?? '') : '',
];
}
protected function readImportFile($filePath, $ext)
{
if ($ext === 'csv') {
$rows = [];
$handle = fopen($filePath, 'r');
while (($data = fgetcsv($handle)) !== false) {
$rows[] = $data;
}
fclose($handle);
return $rows;
}
$reader = $ext === 'xls'
? new \PhpOffice\PhpSpreadsheet\Reader\Xls()
: new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
$spreadsheet = $reader->load($filePath);
return $spreadsheet->getActiveSheet()->toArray();
}
}