package main

import (
	"encoding/csv"
	"fmt"
	"io"

	//	"sort"

	//	"io"
	"net/http"

	"encoding/json"

	"strconv"

	"io/ioutil"

	"time"

	"database/sql"

	"strings"

	_ "github.com/LukeMauldin/lodbc"
	_ "github.com/denisenkom/go-mssqldb"
	_ "github.com/mattn/go-adodb"

	"pp/ModulePath"

	"os"

	"sync"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"

	_ "github.com/mattn/go-sqlite3"
	uuid "github.com/satori/go.uuid"
	//_ "net/http/pprof"
	//	"runtime"
	//	"github.com/shopspring/decimal"
	//	"github.com/tealeg/xlsx"
)

/*
go-adodb ---cache leak

github.com/weigj/go-odbc  ---查询处理特殊字符有问题

github.com/alexbrainman/odbc ---sqlserver读取汉字乱码(编码格式没有转换)


*/

func testAdo() {
	var conf []string
	var db *sql.DB
	var err error
	conf = append(conf, "Provider=SQLOLEDB")
	conf = append(conf, "Data Source=127.0.0.1,1433")          // sqlserver IP 和 服务器名称
	conf = append(conf, "Initial Catalog=WellNameInformation") // 数据库名
	conf = append(conf, "user id=sa")                          // 登陆用户名
	conf = append(conf, "password=lh123456")                   // 登陆密码
	fmt.Println(strings.Join(conf, ";"))
	db, err = sql.Open("adodb", strings.Join(conf, ";"))
	if err != nil {
		fmt.Println("sql open:", err)
		return
	} else {

	}
	defer db.Close()

	beginTime := time.Now()
	// 执行SQL语句
	rows, err := db.Query("select [6506] from [AUTHINFO] order by ID")
	if err != nil {
		fmt.Println("query: ", err)
		return
	}
	for rows.Next() {
		var id float32

		rows.Scan(&id)
		fmt.Println("id: ", id)
	}

	defer rows.Close()

	fmt.Println(fmt.Sprintf("use time:%v", (time.Now().UnixNano()-beginTime.UnixNano())/1e6))
}

// 2008是要升级sqlserver数据库的补丁的，不建议使用。
func testMssqldb() {
	var server = "127.0.0.1"
	port := 1433
	var user = "sa"
	var password = "lh123456"
	var database = "WellNameInformation"

	//连接字符串
	connString := fmt.Sprintf("server=%s;port%d;database=%s;user id=%s;password=%s", server, port, database, user, password)
	fmt.Println(connString)

	//建立连接
	db, err := sql.Open("mssql", connString)
	if err != nil {
		fmt.Println("Open Connection failed:", err.Error())
	}
	defer db.Close()

	//通过连接对象执行查询
	rows, err := db.Query(`select ID from WellInformation order by ID`)
	if err != nil {
		fmt.Println("Query failed:", err.Error())
		return
	}
	defer rows.Close()

	for rows.Next() {
		var id int64

		rows.Scan(&id)
		fmt.Printf("id: %d \n", id)
	}

}

func testOdbc() {
	conn, err := sql.Open("odbc", "driver={SQL Server};SERVER=127.0.0.1;UID=sa;PWD=lh123456?;DATABASE=WellNameInformation")
	if err != nil {
		fmt.Println("Connecting Error", err.Error())
		return
	} else {
		fmt.Println("connect success!")
	}

	defer conn.Close()

	beginTime := time.Now()
	stmt, err := conn.Prepare("select ID from [WellNameInformation].[dbo].[WellInformation] order by ID")
	if err != nil {
		fmt.Println("Query Error", err)
		return
	}
	defer stmt.Close()
	row, err := stmt.Query()
	if err != nil {
		fmt.Println("Query Error", err)
		return
	}
	defer row.Close()

	cnt := 0
	for row.Next() {
		var id int
		if err := row.Scan(&id); err == nil {
			//fmt.Println(id)

			cnt++
		}
	}

	fmt.Println("record len:", cnt)

	fmt.Println(fmt.Sprintf("use time:%v", (time.Now().UnixNano()-beginTime.UnixNano())/1e6))

	fmt.Printf("%s\n", "finish")
	return
}

var (
	server   string
	port     int
	user     string
	password string
	database string

	sqlConn *sql.DB
	//odbcConn *sql.DB

	//user
	refreshSpan    int64
	ExpireTimeSpan time.Duration

	modelePath string

	mu sync.Mutex

	p_lock     sync.Mutex
	p_import_f int

	process_lock   sync.Mutex
	process_lock_n int

	ma_plan_lock   sync.Mutex
	ma_plan_lock_n int

	g_time_format string = "2006-01-02 15:04:05"

	g_date_format string = "2006-01-02"

	approve_m_lock   sync.Mutex
	approve_m_lock_n int

	material_map       map[string]material_info
	ch_material_notify chan int

	g_material_maxid int
)

func initLog() {

	beego.BeeLogger.DelLogger("console")

	var err error
	modelePath, err = ModulePath.GetModuleCurrentPath()
	if err != nil {
		fmt.Println("ModulePath.GetModuleCurrentPath() failed err:", err.Error())
		return
	}

	fmt.Println("modelePath:", modelePath)

	config := make(map[string]interface{})
	config["filename"] = modelePath + string("/logs/ma.log")
	config["level"] = 7
	config["maxlines"] = 0
	config["maxsize"] = 50 * 1024 * 1024 //50M
	config["daily"] = true
	config["maxdays"] = 10

	configJsonStr, err := json.Marshal(config)
	if err != nil {
		fmt.Println("package main init json.Marshal(config) failed,err:", err.Error())
		os.Exit(-1)
	}

	logs.SetLogger(logs.AdapterFile, string(configJsonStr))
}

func initSqlPool(driverType string) {

	if driverType == "ado" {
		var conf []string
		var err error
		conf = append(conf, "Provider=SQLOLEDB")
		conf = append(conf, fmt.Sprintf("Data Source=%s,%d", server, port)) // sqlserver IP 和 服务器名称
		conf = append(conf, fmt.Sprintf("Initial Catalog=%s", database))    // 数据库名
		conf = append(conf, fmt.Sprintf("user id=%s", user))                // 登陆用户名
		conf = append(conf, fmt.Sprintf("password=%s", password))           // 登陆密码
		fmt.Println(strings.Join(conf, ";"))
		sqlConn, err = sql.Open("adodb", strings.Join(conf, ";"))
		if err != nil {
			fmt.Println("sql open:", err.Error())
			os.Exit(0)
		} else {
			fmt.Println("connect success!")
		}

	} else {
		// dataSource := fmt.Sprintf("driver={SQL Server};SERVER=%s;UID=%s;PWD=%s;DATABASE=%s", server, user, password, database)
		// fmt.Println(dataSource)

		// var err error
		// sqlConn, err = sql.Open("lodbc", dataSource)
		// if err != nil {
		// 	fmt.Println("sql open:", err.Error())
		// 	os.Exit(0)
		// } else {
		// 	logs.Info("connect success!")
		// }
		dataSource := fmt.Sprintf(
			"server=%s;user id=%s;password=%s;database=%s;port=%d;encrypt=disable;TrustServerCertificate=true",
			server, // 仅服务器 IP 或域名（不包含端口）
			user,
			password,
			database,
			port, // 端口通过 port 参数单独指定
		)

		fmt.Println("lalalalala", dataSource)

		var err error
		// sqlConn, err = sql.Open("lodbc", dataSource)
		// sqlConn, err = sql.Open("odbc", dataSource)
		sqlConn, err = sql.Open("sqlserver", dataSource)
		if err = sqlConn.Ping(); err != nil {
			fmt.Println("sql open:", err.Error())
			os.Exit(0)
		} else {
			logs.Info("connect success!")
		}
	}

	sqlConn.SetMaxOpenConns(10)
	sqlConn.SetMaxIdleConns(3)
}

func getConn(db string) (conn *sql.DB, err error) {
	var conf []string
	conf = append(conf, "Provider=SQLOLEDB")
	conf = append(conf, fmt.Sprintf("Data Source=%s,%d", server, port)) // sqlserver IP 和 服务器名称
	conf = append(conf, fmt.Sprintf("Initial Catalog=%s", db))          // 数据库名
	conf = append(conf, fmt.Sprintf("user id=%s", user))                // 登陆用户名
	conf = append(conf, fmt.Sprintf("password=%s", password))           // 登陆密码
	//fmt.Println(strings.Join(conf, ";"))
	conn, err = sql.Open("adodb", strings.Join(conf, ";"))
	if err != nil {
		fmt.Println("sql open:", err.Error())
		logs.Error("sql open:", err.Error())
		return
	}

	conn.SetMaxIdleConns(1)
	conn.SetMaxOpenConns(2)

	return
}

func getOdbcConn(db string) (conn *sql.DB, err error) {

	dataSource := fmt.Sprintf("driver={SQL Server};SERVER=%s;UID=%s;PWD=%s;DATABASE=%s", server, user, password, db)
	fmt.Println(dataSource)

	conn, err = sql.Open("lodbc", dataSource)
	if err != nil {
		logs.Error("sql open:", err.Error())
		return
	}

	conn.SetMaxOpenConns(2)
	conn.SetMaxIdleConns(1)

	return
}

func init() {

	refreshSpan = 5 //5s

	ExpireTimeSpan = time.Second * 25

	initLog()

	server = beego.AppConfig.String("server")
	port, _ = beego.AppConfig.Int("port")
	user = beego.AppConfig.String("user")
	password = beego.AppConfig.String("password")
	database = beego.AppConfig.String("database")

	initSqlPool("odbc")

	material_map = make(map[string]material_info, 10000)
	ch_material_notify = make(chan int, 100)
}

func sync_material_map_ex() {
	resp := get_material_data_by_maxid(g_material_maxid)
	//fmt.Println(resp)
	for i := 0; i < len(resp.Data); i++ {
		v := resp.Data[i]
		material_map[v.Code] = v
	}

	//fmt.Println("物料", material_map)
}

func sync_material_map() {
	var req get_material_req
	req.Index = 1
	req.Count = 1000000
	resp := get_material_data(req, true)
	//fmt.Println(resp)
	for i := 0; i < len(resp.Data); i++ {
		v := resp.Data[i]
		material_map[v.Code] = v
	}

	//fmt.Println("物料", material_map)
}

func sync_material_map_G() {

	tick := time.NewTicker(time.Hour * 1)

	fmt.Println("sync_material_map_G collect begin")
	sync_material_map()
	fmt.Println("sync_material_map_G collect end")

	for {
		select {
		case <-tick.C:
			sync_material_map()
		case <-ch_material_notify:
			sync_material_map()
		default:
			time.Sleep(time.Second * 1)
		}
	}

}

func sync_plan_empty_price() {
	sel_sql := fmt.Sprintf(`select [ID],[data] FROM [plan] order by [ID] desc`)

	rows, err := sqlConn.Query(sel_sql)
	if err != nil {
		logs.Error(fmt.Sprintf(`sync_plan_empty_price err:%s`, err.Error()))
	}

	for rows.Next() {

		var s string
		var id int
		var d pp_plan
		if err = rows.Scan(&id, &s); err == nil {

			json.Unmarshal([]byte(s), &d)

			if d.Price == "" {
				for k, v := range material_map {
					if strings.Contains(k, d.Code) {
						d.Name = v.Name
						d.Specs = v.Spec
						d.Unit = v.Unit
						d.Price = v.Price
						d.Payment_type = v.Payment_type
						d.Purchasing_cycle = v.Procurement_cycle
						d.Supplier = v.Supplier

						d.Factory = v.Factory
						d.Factory_code = v.Factory_code
						d.Qs = v.Qs
						d.As = v.As

						js_data, _ := json.Marshal(d)
						update_sql := fmt.Sprintf(`UPDATE [plan] SET  [data] = '%s' WHERE [ID] = %d`, string(js_data), id)
						fmt.Println(update_sql)
						sqlConn.Exec(update_sql)
					}
				}
			}
		}
	}
	rows.Close()
}

func main() {

	go checkFileExpired()

	go sync_material_map_G()

	http.HandleFunc("/test", test)

	http.HandleFunc("/pp/login", Login)
	http.HandleFunc("/pp/loginOut", LoginOut)
	http.HandleFunc("/pp/refreshUser", refreshUser)

	http.HandleFunc("/pp/getMenu", getMenu)

	http.HandleFunc("/pp/getUsers", getUsers)
	http.HandleFunc("/pp/postUser", postUser)

	http.HandleFunc("/pp/download_file", download_file)

	http.HandleFunc("/pp/import_ma_plan", import_ma_plan)
	http.HandleFunc("/pp/get_ma_plan", get_ma_plan)
	http.HandleFunc("/pp/update_ma_plan_ex", update_ma_plan_ex)
	http.HandleFunc("/pp/remove_ma_plan", remove_ma_plan)
	http.HandleFunc("/pp/export_ma_plan", export_ma_plan)

	http.HandleFunc("/pp/get_p_id_options", get_p_id_options)
	http.HandleFunc("/pp/get_p_name", get_p_name)
	http.HandleFunc("/pp/get_ma_username", get_ma_username)

	http.HandleFunc("/pp/cal_completion_date", cal_completion_date)

	http.HandleFunc("/pp/get_material", get_material)
	http.HandleFunc("/pp/get_approve_m", get_approve_m)
	http.HandleFunc("/pp/import_approve_m", import_approve_m)
	http.HandleFunc("/pp/del_approve", del_approve)
	http.HandleFunc("/pp/approve_ok", approve_ok)

	http.HandleFunc("/pp/get_payment", get_payment)
	http.HandleFunc("/pp/update_payment", update_payment)

	http.HandleFunc("/pp/get_single_plan", get_single_plan)

	http.HandleFunc("/pp/get_payment_by_id", get_payment_by_id)
	http.HandleFunc("/pp/mul_update_pp_plan_num", mul_update_pp_plan_num)

	http.HandleFunc("/pp/export_ma_temp_plan", export_ma_temp_plan)

	http.HandleFunc("/pp/update_user_buyer", update_user_buyer)

	http.HandleFunc("/pp/export_plan", export_plan)

	http.HandleFunc("/pp/get_warning_plan", get_warning_plan)

	http.HandleFunc("/pp/upload_ds_file", upload_ds_file)
	http.HandleFunc("/pp/download_ds_file", download_ds_file)

	http.HandleFunc("/pp/del_material", remove_material)

	http.HandleFunc("/pp/import_sp_1", import_sp_1)
	http.HandleFunc("/pp/get_sp_1", get_sp_1)
	http.HandleFunc("/pp/update_sp_1", update_sp_1)
	http.HandleFunc("/pp/remove_sp_1", remove_sp_1)
	http.HandleFunc("/pp/mul_sp_1", mul_sp_1)

	http.HandleFunc("/pp/upload_sp_1_file", upload_sp_1_file)
	http.HandleFunc("/pp/download_sp_1_file", download_sp_1_file)

	http.HandleFunc("/pp/get_sp_2", get_sp_2)
	http.HandleFunc("/pp/update_sp_2", update_sp_2)
	http.HandleFunc("/pp/mul_sp_2", mul_sp_2)

	http.HandleFunc("/pp/mul_payment_application", mul_payment_application)
	http.HandleFunc("/pp/mul_contract_approval", mul_contract_approval)

	http.HandleFunc("/pp/del_contract_file", del_contract_file)

	http.HandleFunc("/pp/upload_sp_2_file", upload_sp_2_file)
	http.HandleFunc("/pp/download_sp_2_file", download_sp_2_file)

	http.HandleFunc("/pp/del_contract_ex_file", del_contract_ex_file)
	//	http.HandleFunc("/pp/get_sp_by_id", get_sp_by_id)
	//http.HandleFunc("/pp/get_sp2_by_id", get_sp2_by_id)
	http.HandleFunc("/pp/search_plan_by_code", search_plan_by_code)
	http.HandleFunc("/pp/export_plan_by_code", export_plan_by_code)
	http.HandleFunc("/pp/export_warning_plan", export_warning_plan)

	//监听服务
	fmt.Println("listen server ...")
	err := http.ListenAndServe("0.0.0.0:8874", nil)
	if err != nil {
		fmt.Println("服务器错误")
	}

}

// 删除正式合同
func del_contract_ex_file(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("del_contract_ex_file recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req update_sp_2_req
	var resp CommonResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintf(response, string(jdata))
		return
	}

	update_sql := fmt.Sprintf(`UPDATE [sp_2]
	   SET [contract_name] = ''
	 WHERE ID=%d`, req.Plan.ID)
	//fmt.Println(update_sql)
	_, err := sqlConn.Exec(update_sql)
	if err != nil {
		logs.Error(fmt.Sprintf(`del_contract_ex_file err:%s`, err.Error()))
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintf(response, string(jdata))
		return
	}

	base_file_path := modelePath + "/file/sp_1_ex/"
	os.Remove(base_file_path + req.Plan.Contract_name)

	resp.Ret = 0
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("del_contract_ex_file recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

// 下载文件
func download_sp_2_file(rw http.ResponseWriter, r *http.Request) {
	//获取请求参数
	/*var req download_file_req
	reqdata, _ := ioutil.ReadAll(r.Body)
	json.Unmarshal(reqdata, &req)

	fn := req.Filename*/

	id := r.FormValue("id")

	
	base_file_path := modelePath + "/file/sp_1_ex/"

	sel_sql := fmt.Sprintf(`select [contract_name] from [sp_2] where ID=%s`, id)
	fmt.Println(sel_sql)
	rows, err := sqlConn.Query(sel_sql)
	if err == nil {
		var contract_name string
		for rows.Next() {

			if err = rows.Scan(&contract_name); err == nil {

			}
		}
		rows.Close()

		if contract_name != "" {
			filename := strings.ReplaceAll(contract_name, `#`, "")
			if filename != "" {
				//设置响应头
				header := rw.Header()
				header.Add("Content-Type", "application/octet-stream")
				//header.Add("Content-Disposition", "attachment;filename="+fn)
				//使用ioutil包读取文件
				filepath := base_file_path + filename
				fmt.Println(filepath)
				b, _ := ioutil.ReadFile(filepath)

				//写入到响应流中
				rw.Write(b)
			}
		}
	}

}

// 上传文件
func upload_sp_2_file(w http.ResponseWriter, r *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("upload_sp_2_file recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp upload_resp
	var f *os.File
	var err error

	var sqlstr string

	//配置文件读取
	base_file_path := modelePath + "/file/sp_1_ex/"

	r.ParseMultipartForm(32 << 20)

	id, _ := strconv.Atoi(r.Form.Get("id"))
	//fmt.Println("id:", id)

	//	file_type := r.Form.Get("file_type")

	//读取文件信息
	file, handler, err := r.FormFile("file")
	if err != nil {
		fmt.Println(err)
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintln(w, string(jdata))
		return
	}
	defer file.Close()
	fmt.Println(handler.Filename)
	//logs.Info(base_file_path + handler.Filename)

	filename := strings.ReplaceAll(handler.Filename, `#`, ``)
	if filename == "" {
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintln(w, string(jdata))
		return
	}

	os.Remove(base_file_path + filename)
	f, err = os.OpenFile(base_file_path+filename, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println(err)
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintln(w, string(jdata))
		return
	}
	defer f.Close()
	io.Copy(f, file)

	sqlstr = fmt.Sprintf(`UPDATE [sp_2]
  				 SET [contract_name] = '%s'
				where ID=%d`, handler.Filename, id)
	fmt.Println(sqlstr)
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("upload_sp_2_file exec err:%v", err.Error()))
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintln(w, string(jdata))
		return
	}

	resp.Ret = 0

	jdata, _ := json.Marshal(resp)
	fmt.Fprintln(w, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("upload_sp_2_file recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

// 删除草稿合同
func del_contract_file(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("del_contract_file recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req update_sp_1_req
	var resp CommonResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintf(response, string(jdata))
		return
	}

	update_sql := fmt.Sprintf(`UPDATE [sp_1]
	   SET [contract_name] = ''
	 WHERE ID=%d`, req.Plan.ID)
	//fmt.Println(update_sql)
	_, err := sqlConn.Exec(update_sql)
	if err != nil {
		logs.Error(fmt.Sprintf(`update_sp_1 err:%s`, err.Error()))
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintf(response, string(jdata))
		return
	}

	base_file_path := modelePath + "/file/sp_1/"
	os.Remove(base_file_path + req.Plan.Contract_name)

	resp.Ret = 0
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("del_contract_file recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

// 合同审批请求
func mul_contract_approval(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("mul_contract_approval recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req mul_update_pp_plan_num_req
	var resp CommonResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintf(response, string(jdata))
		return
	}

	var data []sp_1
	//Contract_id_map := make(map[string]int)

	for i := 0; i < len(req.Plan); i++ {
		if req.Plan[i].Flag == "1" || req.Plan[i].Flag == "3" {
			v := req.Plan[i]
			var sp1_data sp_1
			sp1_data.ID = v.ID
			sp1_data.Amount = v.Total_p
			sp1_data.Applicant = req.OpUser
			sp1_data.Contract_id = v.Contract_id
			sp1_data.Rdm = v.RDM
			sp1_data.State = "待审批"
			sp1_data.Supplier = v.Supplier
			sp1_data.Time = time.Now().Format(g_date_format)

			data = append(data, sp1_data)

			/*
				if index, ok := Contract_id_map[v.Contract_id]; ok {
					data[index] = sp1_data
				} else {
					data = append(data, sp1_data)
					Contract_id_map[v.Contract_id] = len(data) - 1
				}
			*/
		}
	}

	for i := 0; i < len(data); i++ {
		v := data[i]

		del_sql := fmt.Sprintf(`delete from [sp_1] where [ID] =%d `, v.ID)
		fmt.Println(del_sql)
		sqlConn.Exec(del_sql)

		insert_sql := fmt.Sprintf(`INSERT INTO [dbo].[sp_1]
           ([ID],[supplier]
           ,[applicant]
           ,[time]
           ,[contract_id]
           ,[contract_name]
           ,[contract_name_ex]
           ,[rdm]
           ,[amount]
           ,[state])
     VALUES
           (%d,'%s'
           ,'%s'
           ,'%s'
           ,'%s'
           ,'%s'
           ,'%s'
           ,'%s'
           ,'%s'
           ,'%s')`, v.ID, v.Supplier, v.Applicant, v.Time, v.Contract_id, v.Contract_name, v.Contract_name_ex,
			v.Rdm, v.Amount, v.State)
		fmt.Println(insert_sql)
		_, err := sqlConn.Exec(insert_sql)
		if err != nil {
			logs.Error(fmt.Sprintf(`mul_contract_approval insert err:%s`, err.Error()))
			resp.Ret = -1
			jdata, _ := json.Marshal(resp)
			fmt.Fprintf(response, string(jdata))
			return
		}
	}

	resp.Ret = 0

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("mul_contract_approval recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

// 更新任务和父任务已付金额
func update_pp_plan_paid(req sp_2) (r int) {
	/*var task_id int
	if req.Task_ids != "" {
		task_id, _ = strconv.Atoi(req.Task_ids)
	}*/

	if req.ID > 0 {
		var pv pp_plan
		selsql := fmt.Sprintf(`select [data] FROM [plan] where ID=%d or [pre_id]=%d`, req.ID, req.ID)
		fmt.Println(selsql)
		rows, err := sqlConn.Query(selsql)
		if err == nil {
			for rows.Next() {
				var s string
				if err = rows.Scan(&s); err == nil {
					json.Unmarshal([]byte(s), &pv)
				}
			}
			rows.Close()
		}

		pv.Paid = pv.Total_p
		pv.Residual_p = "0.00"
		pv.State_1 = "待付款"
		pv.State = "待付款"
		js_data, _ := json.Marshal(pv)
		selsql = fmt.Sprintf(`UPDATE [plan] SET [data] = '%s',[state]='%s' where ID=%d`, string(js_data), pv.State, req.ID)
		fmt.Println(selsql)
		_, err = sqlConn.Exec(selsql)
		if err != nil {
			logs.Error(fmt.Sprintf(`update_payment err:%s`, err.Error()))
			return
		}

		/*
			if pv.Pre_id > 0 {
				var total_p, total_paid float64

				var d pp_plan
				selsql := fmt.Sprintf(`select [data] FROM [plan] where ID=%d`, pv.Pre_id)
				rows, err := sqlConn.Query(selsql)
				if err == nil {
					for rows.Next() {
						var s string
						if err = rows.Scan(&s); err == nil {
							json.Unmarshal([]byte(s), &d)
						}
					}
					rows.Close()
				}

				var treq get_single_plan_req
				treq.ID = append(treq.ID, d.Child_task_id...)
				//fmt.Println("子任务id：", treq)
				pdata := get_s_plan(treq)

				//fmt.Println("子任务：", pdata)
				for i := 0; i < len(pdata.Data); i++ {
					v := pdata.Data[i]

					t_total_p, _ := strconv.ParseFloat(strings.ReplaceAll(v.Total_p, ",", ""), 64)
					total_p += t_total_p

					paid, _ := strconv.ParseFloat(v.Paid, 64)
					total_paid += paid
				}
				d.Total_p = fmt.Sprintf(`%.2f`, total_p)
				//total_p, _ = strconv.ParseFloat(d.Total_p, 64)
				d.Paid = fmt.Sprintf(`%.2f`, total_paid)
				d.Residual_p = fmt.Sprintf(`%.2f`, total_p-total_paid)

				js_data, _ := json.Marshal(d)
				selsql = fmt.Sprintf(`UPDATE [plan] SET [data] = '%s' where ID=%d`, string(js_data), pv.Pre_id)
				_, err = sqlConn.Exec(selsql)
				if err != nil {
					logs.Error(fmt.Sprintf(`update_payment err:%s`, err.Error()))
					return
				}

			}*/
	}

	return
}

// 付款申请
func mul_payment_application(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("mul_payment_application recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req mul_update_pp_plan_num_req
	var resp CommonResp

	var js_data []byte
	var update_sql string
	//	var ids []int

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintf(response, string(jdata))
		return
	}

	/*for i := 0; i < len(req.Plan); i++ {
		if req.Plan[i].Flag == "1" {
			ids = append(ids, req.Plan[i].Child_task_id...)
		} else if req.Plan[i].Flag == "3" {
			ids = append(ids, req.Plan[i].ID)
		}
	}

	var err_context string
	//var pp_data []pp_plan
	for i := 0; i < len(ids); i++ {

		var d pp_plan
		selsql := fmt.Sprintf(`select ID,data FROM [plan] where ID=%d`, ids[i])
		rows, err := sqlConn.Query(selsql)
		if err == nil {
			for rows.Next() {

				var s string
				var id int
				if err = rows.Scan(&id, &s); err == nil {
					json.Unmarshal([]byte(s), &d)
					d.ID = id

					if d.Contract_state != "已审批" {
						if err_context == "" {
							err_context = d.Contract_id
						} else {
							err_context += "<br/><br/>" + d.Contract_id
						}
					}
				}
			}
			rows.Close()
		}
	}

	if err_context != "" {
		resp.Ret = 2
		resp.Context = fmt.Sprintf(`合同号:<br/><br/>%s<br/><br/> 未批准，付款申请必须合同已批准`, err_context)
		jdata, _ := json.Marshal(resp)
		fmt.Fprintf(response, string(jdata))
		return
	}*/

	for i := 0; i < len(req.Plan); i++ {
		d := req.Plan[i]
		fmt.Println(d.ID)
		if d.ID > 0 {

			var sp2_info sp_2
			sp2_info.ID = d.ID
			sp2_info.Contract_id = d.Contract_id
			sp2_info.Amount = d.Contract_amount
			sp2_info.Amount_1 = d.Total_p
			sp2_info.Buyer = d.Buyer
			sp2_info.Contract_name = ""
			sp2_info.Rdm = d.RDM
			sp2_info.State = d.Contract_state
			sp2_info.State_1 = "待审批"
			sp2_info.Supplier = d.Supplier
			sp2_info.Warehouse_entry_number = d.Warehouse_entry_number
			sp2_info.Task_ids = strconv.Itoa(d.ID)

			del_sql := fmt.Sprintf(`delete from [sp_2] where ID=%d `, d.ID)
			fmt.Println(del_sql)
			_, err := sqlConn.Exec(del_sql)
			if err != nil {
				resp.Ret = -1
				jdata, _ := json.Marshal(resp)
				fmt.Fprintf(response, string(jdata))
				return
			}

			insert_sql := fmt.Sprintf(`INSERT INTO [dbo].[sp_2]
			              ([ID],[contract_id]
			              ,[supplier]
			              ,[contract_name]
			              ,[rdm]
			              ,[state]
			              ,[amount]
			              ,[amount_1]
			              ,[warehouse_entry_number]
			              ,[buyer]
			              ,[state_1]
			              ,[task_ids])
			        VALUES
			              (%d,'%s'
			              ,'%s'
			              ,'%s'
			              ,'%s'
			              ,'%s'
			              ,'%s'
			              ,'%s'
			              ,'%s'
			              ,'%s'
			              ,'%s'
			              ,'%s')`,
				sp2_info.ID, sp2_info.Contract_id, sp2_info.Supplier, sp2_info.Contract_name, sp2_info.Rdm,
				sp2_info.State, sp2_info.Amount, sp2_info.Amount_1, sp2_info.Warehouse_entry_number,
				sp2_info.Buyer, sp2_info.State_1, sp2_info.Task_ids)

			_, err = sqlConn.Exec(insert_sql)
			if err != nil {
				logs.Error(err.Error())

				resp.Ret = -1
				jdata, _ := json.Marshal(resp)
				fmt.Fprintf(response, string(jdata))
				return
			}

			d.State_1 = "待审批"
			js_data, _ = json.Marshal(d)
			update_sql = fmt.Sprintf(`UPDATE [plan]
	   				SET [data] = '%s'
	 				WHERE ID=%d`, string(js_data), d.ID)
			fmt.Println(update_sql)
			_, err = sqlConn.Exec(update_sql)
			if err != nil {
				logs.Error(fmt.Sprintf(`mul_update_pp_plan_num err:%s`, err.Error()))
				resp.Ret = -1
				jdata, _ := json.Marshal(resp)
				fmt.Fprintf(response, string(jdata))
				return
			}

			if len(d.Child_task_id) > 0 {

				for k := 0; k < len(d.Child_task_id); k++ {
					tid := d.Child_task_id[k]

					t_sql := fmt.Sprintf(`select ID,data from [plan] where ID = %d`, tid)
					rows, err := sqlConn.Query(t_sql)
					if err != nil {
						continue
					}

					for rows.Next() {
						var t_pv pp_plan
						var t_s string
						var t_id int
						if err = rows.Scan(&t_id, &t_s); err == nil {
							json.Unmarshal([]byte(t_s), &t_pv)

							t_pv.ID = t_id

							t_pv.State_1 = "待审批"
							js_data, _ = json.Marshal(t_pv)
							update_sql = fmt.Sprintf(`UPDATE [plan]
						   				SET [data] = '%s'
						 				WHERE ID=%d`, string(js_data), t_id)
							fmt.Println(update_sql)
							_, err = sqlConn.Exec(update_sql)
							if err != nil {
								logs.Error(fmt.Sprintf(`mul_update_pp_plan_num err:%s`, err.Error()))
							}
						}

					}
					rows.Close()
				}
			}
		}

	}

	resp.Ret = 0

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("mul_payment_application recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func mul_sp_2(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("mul_sp_2 recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req mul_sp_2_req
	var resp CommonResp

	var update_sql string

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Plan); i++ {
		v := req.Plan[i]

		update_sql = fmt.Sprintf(`UPDATE [sp_2]
	   				SET [state_1] = '%s'
	 				WHERE [ID]=%d`, string("已审批"), v.ID)
		fmt.Println(update_sql)
		_, err := sqlConn.Exec(update_sql)
		if err != nil {
			logs.Error(fmt.Sprintf(`mul_sp_2 err:%s`, err.Error()))
			resp.Ret = -1
			goto exit
		}

		update_pp_plan_paid(v)
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("mul_sp_2 recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func update_sp_2(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("update_sp_2 recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req update_sp_2_req
	var resp CommonResp

	var update_sql string
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintf(response, string(jdata))
		return
	}

	req.Plan.Amount = strings.ReplaceAll(req.Plan.Amount, ",", "")

	update_sql = fmt.Sprintf(`UPDATE [sp_2]
	   SET [state_1] = '%s'
	 WHERE [ID]=%d`,
		req.Plan.State_1, req.Plan.ID)
	fmt.Println(update_sql)
	_, err = sqlConn.Exec(update_sql)
	if err != nil {
		logs.Error(fmt.Sprintf(`update_sp_2 err:%s`, err.Error()))
		resp.Ret = -1
		goto exit
	}

	if req.Plan.State_1 == "已审批" || req.Plan.State_1 == "批准" {
		fmt.Println("已审批", req.Plan)
		update_pp_plan_paid(req.Plan)
	} else if req.Plan.State_1 == "驳回" || req.Plan.State_1 == "拒绝" {

		task_id, _ := strconv.Atoi(req.Plan.Task_ids)

		sel_sql := fmt.Sprintf(`select [ID],[data] from [plan] where ID=%d `, task_id)
		rows, err := sqlConn.Query(sel_sql)
		if err == nil {
			var pv pp_plan
			for rows.Next() {
				var s string
				var id int
				if err = rows.Scan(&id, &s); err == nil {
					json.Unmarshal([]byte(s), &pv)
					pv.ID = id
				}
			}
			rows.Close()

			pv.State_1 = "拒绝"

			str, _ := json.Marshal(pv)
			update_sql := fmt.Sprintf(`
			UPDATE [dbo].[plan]
   			SET [data] = '%s'
 			WHERE [ID] = %d`, string(str), pv.ID)
			_, err = sqlConn.Exec(update_sql)
			if err != nil {
				logs.Error(fmt.Sprintf(`update_sp_2 update err:%s`, err.Error()))
			}
		}
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("update_sp_2 recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_sp_2_info(req get_sp_2_req) (resp get_sp_2_resp) {
	var sqlstr string
	var where_sql string
	var if_where bool

	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error

	user_info, _ := getUserInfo(req.OpUser)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.Contract_id != 0 {
		//likeStr := "%" + req.ID + "%"
		where_sql = fmt.Sprintf(" [contract_id] = %d", req.Contract_id)
		if_where = true
	}

	if req.Supplier != "" {
		likeStr := "%" + req.Supplier + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [supplier] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [supplier] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Contract_name != "" {
		likeStr := "%" + req.Contract_name + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [contract_name] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [contract_name] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Rdm != "" {
		likeStr := "%" + req.Rdm + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [rdm] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [rdm] like '%s'", likeStr)
		}

		if_where = true
	}
	if req.Buyer != "" {
		likeStr := "%" + req.Buyer + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [buyer] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [buyer] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.If_done {
		if if_where {
			where_sql += fmt.Sprintf(" and [state_1] != '%s'", "待审批")
		} else {
			where_sql += fmt.Sprintf(" [state_1] != '%s'", "待审批")
		}

		if_where = true
	} else {
		if if_where {
			where_sql += fmt.Sprintf(" and [state_1] = '%s'", "待审批")
		} else {
			where_sql += fmt.Sprintf(" [state_1] = '%s'", "待审批")
		}

		if_where = true
	}

	if if_where {
		sqlstr = fmt.Sprintf("select count(ID) from [sp_2] where %s ", where_sql)
	} else {
		sqlstr = fmt.Sprintf("select count(ID) from [sp_2] ")
	}

	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_sp_1_info query %s err:%v", sqlstr, err.Error()))
		goto exit
	}
	for cntRow.Next() {
		var cnt int
		if err = cntRow.Scan(&cnt); err != nil {
			logs.Error(fmt.Sprintf("get_sp_1_info scan %s err:%v", sqlstr, err.Error()))
			goto exit
		} else {
			resp.Total = cnt
		}
	}
	cntRow.Close()

	if !if_where {
		sqlstr = fmt.Sprintf("select top %v [ID],[contract_id],[supplier],[contract_name],[rdm],[state],[amount],[amount_1],[warehouse_entry_number],[buyer],[state_1],[task_ids] from [sp_2] where ID not in (select top %v ID from [sp_2] order by ID desc) order by ID desc", req.Count, (req.Index-1)*req.Count)
	} else {
		sqlstr = fmt.Sprintf("select top %v [ID],[contract_id],[supplier],[contract_name],[rdm],[state],[amount],[amount_1],[warehouse_entry_number],[buyer],[state_1],[task_ids] from [sp_2] where %s and ID not in (select top %v ID from [sp_2] where %s order by ID desc) order by ID desc", req.Count, where_sql, (req.Index-1)*req.Count, where_sql)
	}
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_sp_1_info Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d sp_2
		if err := rdRow.Scan(&d.ID, &d.Contract_id, &d.Supplier, &d.Contract_name, &d.Rdm, &d.State, &d.Amount, &d.Amount_1, &d.Warehouse_entry_number,
			&d.Buyer, &d.State_1, &d.Task_ids); err == nil {

			if d.Amount_1 != "" {
				d.Amount_1 = convert_price(d.Amount_1)
			}

			if d.State_1 == "" {
				d.State_1 = "未审核"
			}

			if user_info.RoleId == 1 {
				d.If_modify = true
			} else {
				if !req.If_done {
					d.If_modify = true
				}
			}

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_sp_1_info scan Error", err.Error())
		}
	}

exit:
	return
}

func get_sp_2(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("get_sp_2 recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_sp_2_req
	var resp get_sp_2_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	resp = get_sp_2_info(req)

	jdata, _ := json.Marshal(resp)

	str := string(jdata)
	str = strings.ReplaceAll(str, "%", "%%")
	fmt.Fprintf(response, str)

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_sp_2 recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

// 下载文件
func download_sp_1_file(rw http.ResponseWriter, r *http.Request) {
	//获取请求参数
	/*var req download_file_req
	reqdata, _ := ioutil.ReadAll(r.Body)
	json.Unmarshal(reqdata, &req)

	fn := req.Filename*/

	id := r.FormValue("id")
	fmt.Println(id)
	sel_sql := fmt.Sprintf(`select [contract_name] from [sp_1] where ID=%s`, id)
	fmt.Println(sel_sql)
	rows, err := sqlConn.Query(sel_sql)
	if err == nil {
		var contract_name string
		for rows.Next() {

			if err = rows.Scan(&contract_name); err == nil {

			}
		}
		rows.Close()

		if contract_name != "" {
			filename := strings.ReplaceAll(contract_name, `#`, ``)
			fmt.Println(filename)
			base_file_path := modelePath + "/file/sp_1/"

			if filename != "" {
				//设置响应头
				header := rw.Header()
				header.Add("Content-Type", "application/octet-stream")
				//header.Add("Content-Disposition", "attachment;filename="+fn)
				//使用ioutil包读取文件
				filepath := base_file_path + filename
				fmt.Println(filepath)
				b, _ := ioutil.ReadFile(filepath)

				//写入到响应流中
				rw.Write(b)
			}
		}
	}

}

// 上传文件
func upload_sp_1_file(w http.ResponseWriter, r *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("upload_sp_1_file recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp upload_resp
	var f *os.File
	var err error

	var sqlstr string

	//配置文件读取
	base_file_path := modelePath + "/file/sp_1/"

	r.ParseMultipartForm(32 << 20)

	id, _ := strconv.Atoi(r.Form.Get("id"))
	//fmt.Println("id:", id)

	//	file_type := r.Form.Get("file_type")

	//读取文件信息
	file, handler, err := r.FormFile("file")
	if err != nil {
		fmt.Println(err)
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintln(w, string(jdata))
		return
	}
	defer file.Close()

	filename := strings.ReplaceAll(handler.Filename, `#`, "")
	//logs.Info(base_file_path + filename)
	fmt.Println(filename)
	if filename == "" {
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintln(w, string(jdata))
		return
	}
	os.Remove(base_file_path + filename)
	f, err = os.OpenFile(base_file_path+filename, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println(err)
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintln(w, string(jdata))
		return
	}
	defer f.Close()
	io.Copy(f, file)

	sqlstr = fmt.Sprintf(`UPDATE [sp_1]
  				 SET [contract_name] = '%s'
				where ID=%d`, handler.Filename, id)
	fmt.Println(sqlstr)
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("upload_sp_1_file exec err:%v", err.Error()))
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintln(w, string(jdata))
		return
	}

	resp.Ret = 0

	jdata, _ := json.Marshal(resp)
	fmt.Fprintln(w, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("upload_sp_1_file recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func mul_sp_1(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("mul_sp_1 recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req mul_sp_1_req
	var resp CommonResp

	var update_sql string

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Plan); i++ {
		v := req.Plan[i]

		update_sql = fmt.Sprintf(`UPDATE [sp_1]
	   				SET [state] = '%s'
	 				WHERE ID=%d`, string("批准"), v.ID)
		fmt.Println(update_sql)
		_, err := sqlConn.Exec(update_sql)
		if err != nil {
			logs.Error(fmt.Sprintf(`mul_sp_1 err:%s`, err.Error()))
			resp.Ret = -1
			goto exit
		}

		v.State = "批准"
		update_pp_plan_state_1_by_sp1(v)
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("mul_sp_1 recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func remove_sp_1(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("remove_ma_plan recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var err error
	var sqlstr string
	var resp CommonResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req remove_ma_plan_req
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	if req.ID == 0 {
		logs.Info("remove_sp_1 req id ==0")
		resp.Ret = -1
		goto exit
	}

	sqlstr = fmt.Sprintf(`DELETE FROM [sp_1] WHERE ID=%d`, req.ID)
	fmt.Println(sqlstr)
	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("remove_sp_1 err:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("remove_sp_1 recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func update_pp_plan_state_1_by_sp1(req sp_1) (r int) {

	var child_task_ids []int
	sel_sql := fmt.Sprintf(`select [ID],[data] from [plan] where [ID]=%d`, req.ID)
	rows, err := sqlConn.Query(sel_sql)
	if err == nil {

		for rows.Next() {
			var pv pp_plan
			var s string
			var id int
			if err = rows.Scan(&id, &s); err == nil {
				json.Unmarshal([]byte(s), &pv)
				pv.ID = id

				pv.Contract_state = req.State

				str, _ := json.Marshal(pv)
				update_sql := fmt.Sprintf(`
				UPDATE [dbo].[plan]
   				SET [data] = '%s'
 				WHERE [ID] = %d`, string(str), id)
				fmt.Println(update_sql)
				_, err = sqlConn.Exec(update_sql)
				if err != nil {
					logs.Error(fmt.Sprintf(`update_pp_plan_state_1_by_sp1 err:%s`, err.Error()))
				}

				child_task_ids = append(child_task_ids, pv.Child_task_id...)
			}
		}
		rows.Close()
	}

	if len(child_task_ids) > 0 {

		for i := 0; i < len(child_task_ids); i++ {
			v := child_task_ids[i]

			sel_sql := fmt.Sprintf(`select [ID],[data] from [plan] where [ID]=%d`, v)
			rows, err := sqlConn.Query(sel_sql)
			if err == nil {

				for rows.Next() {
					var pv pp_plan
					var s string
					var id int
					if err = rows.Scan(&id, &s); err == nil {
						json.Unmarshal([]byte(s), &pv)
						pv.ID = id

						pv.Contract_state = req.State

						str, _ := json.Marshal(pv)
						update_sql := fmt.Sprintf(`
				UPDATE [dbo].[plan]
   				SET [data] = '%s'
 				WHERE [ID] = %d`, string(str), id)
						fmt.Println(update_sql)
						_, err = sqlConn.Exec(update_sql)
						if err != nil {
							logs.Error(fmt.Sprintf(`update_pp_plan_state_1_by_sp1 err:%s`, err.Error()))
						}
					}
				}
				rows.Close()
			}
		}
	}

	return
}

func update_sp_1(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("update_sp_1 recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req update_sp_1_req
	var resp CommonResp

	var update_sql string
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintf(response, string(jdata))
		return
	}

	req.Plan.Amount = strings.ReplaceAll(req.Plan.Amount, ",", "")

	update_sql = fmt.Sprintf(`UPDATE [sp_1]
	   SET [supplier] = '%s'
	      ,[applicant]='%s'
      ,[rdm] = '%s'
      ,[amount] = '%s'
      ,[state] = '%s'
	 WHERE ID=%d`,
		req.Plan.Supplier, req.Plan.Applicant, req.Plan.Rdm,
		req.Plan.Amount, req.Plan.State,
		req.Plan.ID)
	fmt.Println(update_sql)
	_, err = sqlConn.Exec(update_sql)
	if err != nil {
		logs.Error(fmt.Sprintf(`update_sp_1 err:%s`, err.Error()))
		resp.Ret = -1
		goto exit
	}

	resp.Ret = update_pp_plan_state_1_by_sp1(req.Plan)

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("update_sp_1 recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_sp_1_info(req get_sp_1_req) (resp get_sp_1_resp) {
	var sqlstr string
	var where_sql string
	var if_where bool

	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error

	user_info, _ := getUserInfo(req.OpUser)

	/*b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}*/

	if req.ID != 0 {
		//likeStr := "%" + req.ID + "%"
		where_sql = fmt.Sprintf(" [ID] = %d", req.ID)
		if_where = true
	}

	if req.Supplier != "" {
		likeStr := "%" + req.Supplier + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [supplier] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [supplier] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Applicant != "" {
		likeStr := "%" + req.Applicant + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [applicant] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [applicant] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Contract_name != "" {
		likeStr := "%" + req.Contract_name + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [contract_name] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [contract_name] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Rdm != "" {
		likeStr := "%" + req.Rdm + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [rdm] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [rdm] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.If_done {
		if if_where {
			where_sql += fmt.Sprintf(" and [state] != '%s'", "待审批")

		} else {
			where_sql += fmt.Sprintf(" [state] != '%s'", "待审批")

		}

		if_where = true
	} else {
		if if_where {
			where_sql += fmt.Sprintf(" and [state] = '%s'", "待审批")

		} else {
			where_sql += fmt.Sprintf(" [state] = '%s'", "待审批")

		}

		if_where = true
	}

	if if_where {
		sqlstr = fmt.Sprintf("select count(ID) from [sp_1] where %s ", where_sql)
	} else {
		sqlstr = fmt.Sprintf("select count(ID) from [sp_1] ")
	}

	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_sp_1_info query %s err:%v", sqlstr, err.Error()))
		goto exit
	}
	for cntRow.Next() {
		var cnt int
		if err = cntRow.Scan(&cnt); err != nil {
			logs.Error(fmt.Sprintf("get_sp_1_info scan %s err:%v", sqlstr, err.Error()))
			goto exit
		} else {
			resp.Total = cnt
		}
	}
	cntRow.Close()

	if !if_where {
		sqlstr = fmt.Sprintf("select top %v [ID],[supplier],[applicant],[time] ,[contract_id],[contract_name],[contract_name_ex],[rdm],[amount],[state] from [sp_1] where ID not in (select top %v ID from [sp_1] order by ID desc) order by ID desc", req.Count, (req.Index-1)*req.Count)
	} else {
		sqlstr = fmt.Sprintf("select top %v [ID],[supplier],[applicant],[time] ,[contract_id],[contract_name],[contract_name_ex],[rdm],[amount],[state] from [sp_1] where %s and ID not in (select top %v ID from [sp_1] where %s order by ID desc) order by ID desc", req.Count, where_sql, (req.Index-1)*req.Count, where_sql)
	}
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_sp_1_info Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d sp_1
		if err := rdRow.Scan(&d.ID, &d.Supplier, &d.Applicant, &d.Time, &d.Contract_id, &d.Contract_name, &d.Contract_name_ex, &d.Rdm, &d.Amount, &d.State); err == nil {

			//fmt.Println(d.Contract_name, d.Contract_id)
			if d.Amount != "" {
				d.Amount = convert_price(d.Amount)
			}

			if d.State == "" {
				d.State = "未审核"
			}

			if user_info.RoleId == 1 {
				d.If_modify = true
			} else {
				if !req.If_done {
					d.If_modify = true
				}
			}

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_sp_1_info scan Error", err.Error())
		}
	}

exit:
	return
}

func get_sp_1(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("get_sp_1 recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_sp_1_req
	var resp get_sp_1_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	resp = get_sp_1_info(req)

	jdata, _ := json.Marshal(resp)

	str := string(jdata)
	str = strings.ReplaceAll(str, "%", "%%")
	fmt.Fprintf(response, str)

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_sp_1 recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

// add by marcy
func get_sp_by_id(id int) (resp get_sp_1_resp) {
	var sqlstr string
	var cntRow *sql.Rows
	var err error
	beginTime := time.Now().UnixNano()
	logs.Info("get_sp_by_id recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	//	var req get_sp_1_req
	//var resp get_sp_1_resp

	// reqdata, _ := ioutil.ReadAll(request.Body)
	// json.Unmarshal(reqdata, &req)

	sqlstr = fmt.Sprintf("select  [ID],[supplier],[applicant],[time] ,[contract_id],[contract_name],[contract_name_ex],[rdm],[amount],[state] from [sp_1] where  [ID] =%d", id)
	fmt.Println(sqlstr)
	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_sp_1_info Query err:%v", err.Error()))
		return
	}
	defer cntRow.Close()

	for cntRow.Next() {
		var d sp_1
		if err := cntRow.Scan(&d.ID, &d.Supplier, &d.Applicant, &d.Time, &d.Contract_id, &d.Contract_name, &d.Contract_name_ex, &d.Rdm, &d.Amount, &d.State); err == nil {

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_sp_by_id scan Error", err.Error())
		}
	}

	//jdata, _ := json.Marshal(resp)
	//fmt.Fprintf(response, resp)

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_sp_by_id recv req end, use time: %v ms", (endTime-beginTime)/1e6))
	return
}
func get_sp2_by_id(id int) (resp get_sp_1_resp) {
	var sqlstr string
	var cntRow *sql.Rows
	var err error
	beginTime := time.Now().UnixNano()
	logs.Info("get_sp_by_id recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	//var req get_sp_1_req
	//var resp get_sp_1_resp

	//reqdata, _ := ioutil.ReadAll(request.Body)
	//json.Unmarshal(reqdata, &req)

	sqlstr = fmt.Sprintf("select  [ID],[supplier],[contract_id],[contract_name],[state] from [sp_2] where  [ID] =%d", id)
	fmt.Println(sqlstr)
	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_sp_2_info Query err:%v", err.Error()))
		return
	}
	defer cntRow.Close()

	for cntRow.Next() {
		var d sp_1
		if err := cntRow.Scan(&d.ID, &d.Supplier, &d.Contract_id, &d.Contract_name, &d.State); err == nil {

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_sp_by_id scan Error", err.Error())
		}
	}

	// jdata, _ := json.Marshal(resp)
	// fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_sp2_by_id recv req end, use time: %v ms", (endTime-beginTime)/1e6))
	return
}

// 导入合同审批
func import_sp_1(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("import_sp_1 recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var reqdata []byte
	var req import_sp_1_Req
	var resp CommonResp

	reqdata, _ = ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Plan); i++ {

		v := req.Plan[i]

		v.Time = strings.ReplaceAll(time.Now().Format(g_date_format), "-", "/")

		amount, _ := strconv.ParseFloat(strings.ReplaceAll(v.Amount, ",", ""), 64)
		v.Amount = fmt.Sprintf(`%.2f`, amount)

		sqlstr := fmt.Sprintf(`INSERT INTO [sp_1]
           ([supplier]
      ,[applicant]
      ,[time]
      ,[contract_name]
      ,[rdm]
      ,[amount]
      ,[state])
     VALUES
           ('%s'
           ,'%s'
           ,'%s'
           ,'%s'
           ,'%s'
           ,'%s'
           ,'%s')`,
			v.Supplier, v.Applicant, v.Time, v.Contract_name, v.Rdm, v.Amount, v.State)

		_, err := sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("import_sp_1 Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}

	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("import_sp_1 recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

// 下载文件
func download_ds_file(rw http.ResponseWriter, r *http.Request) {
	//获取请求参数
	/*var req download_file_req
	reqdata, _ := ioutil.ReadAll(r.Body)
	json.Unmarshal(reqdata, &req)

	fn := req.Filename*/

	filename := r.FormValue("id")
	base_file_path := modelePath + "/upload_file/"

	if filename != "" {
		//设置响应头
		header := rw.Header()
		header.Add("Content-Type", "application/octet-stream")
		//header.Add("Content-Disposition", "attachment;filename="+fn)
		//使用ioutil包读取文件
		filepath := base_file_path + filename
		fmt.Println(filepath)
		b, _ := ioutil.ReadFile(filepath)

		//写入到响应流中
		rw.Write(b)
	}

}

// 上传文件
func upload_ds_file(w http.ResponseWriter, r *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("upload_ds_file recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp upload_resp
	var f *os.File
	var err error

	var sqlstr string

	//配置文件读取
	base_file_path := modelePath + "/upload_file/"

	r.ParseMultipartForm(32 << 20)

	id, _ := strconv.Atoi(r.Form.Get("id"))
	//fmt.Println("id:", id)

	file_type := r.Form.Get("file_type")

	//读取文件信息
	file, handler, err := r.FormFile("file")
	if err != nil {
		fmt.Println(err)
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintln(w, string(jdata))
		return
	}
	defer file.Close()
	fmt.Println(handler.Filename)
	logs.Info(base_file_path + handler.Filename)
	if handler.Filename == "" {
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintln(w, string(jdata))
		return
	}
	os.Remove(base_file_path + handler.Filename)
	f, err = os.OpenFile(base_file_path+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println(err)
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintln(w, string(jdata))
		return
	}
	defer f.Close()
	io.Copy(f, file)

	resp.Ret = 0

	sqlstr = fmt.Sprintf(`select [data] FROM [material] where [ID]=%d `, id)
	rows, err := sqlConn.Query(sqlstr)
	if err != nil {
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintln(w, string(jdata))
		return
	}

	var d material_info
	var if_exist bool
	for rows.Next() {
		var s string
		if err = rows.Scan(&s); err == nil {
			json.Unmarshal([]byte(s), &d)
			if_exist = true
		}
	}
	rows.Close()

	if if_exist {
		if file_type == "1" {
			d.Qs = handler.Filename
		} else if file_type == "2" {
			d.As = handler.Filename
		} else {
			return
		}

		js_data, _ := json.Marshal(d)
		sqlstr = fmt.Sprintf(`UPDATE [material]
  				 SET [data] = '%s'
				where ID=%d`, string(js_data), id)
		fmt.Println(sqlstr)

		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Error(fmt.Sprintf("upload_ds_file exec err:%v", err.Error()))
			resp.Ret = -1
			jdata, _ := json.Marshal(resp)
			fmt.Fprintln(w, string(jdata))
			return
		}
	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintln(w, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("upload_ds_file recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func export_plan(response http.ResponseWriter, request *http.Request) {

	beginTime := time.Now().UnixNano()
	logs.Info("export_ma_temp_plan recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var csv_data [][]string
	var filename string
	filename = fmt.Sprintf(`./file/%v.csv`, beginTime)
	f, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	var req get_ma_plan_req
	var resp download_file_Resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	var where_sql string
	var if_where bool

	if req.ID != "" {
		likeStr := "%" + req.ID + "%"
		where_sql = fmt.Sprintf(" [ID] like '%s'", likeStr)
		if_where = true
	}

	if req.RDM != "" {
		likeStr := "%" + req.RDM + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [rdm] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [rdm] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Bt != "" {
		if if_where {
			where_sql += fmt.Sprintf(" and [op_time] > '%s'", req.Bt)
		} else {
			where_sql += fmt.Sprintf(" [op_time] > '%s'", req.Bt)
		}

		if_where = true
	}

	if req.Et != "" {
		if if_where {
			where_sql += fmt.Sprintf(" and [op_time] < '%s'", req.Et)
		} else {
			where_sql += fmt.Sprintf(" [op_time] < '%s'", req.Et)
		}

		if_where = true
	}

	if req.Code != "" {
		likeStr := "%" + req.Code + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [code] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [code] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Name != "" {
		likeStr := "%" + req.Name + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [name] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [name] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Supplier != "" {
		likeStr := "%" + req.Supplier + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [supplier] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [supplier] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.State != "" {
		likeStr := "%" + req.State + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [state] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [state] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Buyer != "" {
		likeStr := "%" + req.Buyer + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [buyer] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [buyer] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.If_done {
		if if_where {
			where_sql += " and [if_done]=1"
		} else {
			where_sql += " [if_done]=1"
		}

		if_where = true

	} else { //未处理
		if if_where {
			where_sql += " and [if_done]!=1 "
		} else {
			where_sql += " [if_done]!=1 "
		}

		if_where = true
	}

	if if_where {
		where_sql += fmt.Sprintf(" and [flag] !='1'")
	} else {
		where_sql += fmt.Sprintf(" [flag] !='1'")
	}

	if if_where {
		where_sql += fmt.Sprintf(" and [if_del] !=1")
	} else {
		where_sql += fmt.Sprintf(" [if_del] !=1")
	}

	sel_sql := fmt.Sprintf(`select [ID],[data] from [plan] where %s`, where_sql)
	rows, err := sqlConn.Query(sel_sql)
	if err != nil {
		return
	}

	var pp_data []pp_plan
	for rows.Next() {
		var s string
		var d pp_plan
		var id int
		if err := rows.Scan(&id, &s); err == nil {

			json.Unmarshal([]byte(s), &d)

			d.ID = id

			if d.Payment_type == "1" {
				d.Payment_type = "全款"
			} else if d.Payment_type == "2" {
				d.Payment_type = "分期"
			}

			if len(d.Child_task_id) == 0 {
				d.Child_task_id = []int{}
			}

			if d.Flag == "1" {
				d.Price = ""
			} else {
				d.Price = convert_price(d.Price)
			}

			if len(d.Demand_date) > 2 {
				if d.Demand_date[2] != byte('/') {
					d.Demand_date = d.Demand_date[2:]
				}
			}

			if len(d.Order_date) > 2 {
				d.Order_date = d.Order_date[2:]
			}

			if len(d.Actual_delivery_date) > 2 {
				if d.Actual_delivery_date[2] != byte('/') {
					d.Actual_delivery_date = d.Actual_delivery_date[2:]
				}
			}

			if d.Actual_delivery_date != "" {
				loc, _ := time.LoadLocation("Local")
				actual_delivery_date, _ := time.ParseInLocation(g_time_format, "20"+strings.ReplaceAll(d.Actual_delivery_date, "/", "-")+" 00:00:00", loc)
				demand_date, _ := time.ParseInLocation(g_time_format, "20"+strings.ReplaceAll(d.Demand_date, "/", "-")+" 00:00:00", loc)

				span := (actual_delivery_date.Sub(demand_date).Hours()) / 24
				if int(span) >= 1 {
					d.Over_due2 = fmt.Sprintf(`%d`, int(span))
				}
			}

			d.Total_p = convert_price(d.Total_p)
			d.Residual_p = convert_price(d.Residual_p)

			if d.Flag == "2" || d.Flag == "3" {
				d.Arrival_quantity_text = fmt.Sprintf(`%v/%v`, d.Arrival_quantity, d.Num)
			} else {
				d.Arrival_quantity_text = ""
			}

			if d.Flag == "1" && d.Code == "" {
				d.Name = ""
				d.Specs = ""
				d.Unit = ""
				d.Price = ""
				d.Payment_type = ""
				d.Purchasing_cycle = ""
				d.Supplier = ""

				d.Factory = ""
				d.Factory_code = ""
				d.Qs = ""
				d.As = ""
			}

			pp_data = append(pp_data, d)
		}
	}
	rows.Close()

	csv_data = append(csv_data,
		[]string{
			"序号", "RDM", "编号", "名称", "规格", "单位", "数量", "到货数量", "单价", "合计", "付款方式",
			"已付", "应付", "需求日期", "采购周期", "下单日期", "预计超期", "实际交付", "剩余", "超期",
			"采购记录", "状态", "入库单号", "供应商"})

	for i := 0; i < len(pp_data); i++ {
		v := pp_data[i]
		csv_data = append(csv_data,
			[]string{
				strconv.Itoa(v.ID), v.RDM, v.Code, v.Name, v.Specs, v.Unit, v.Num, v.Arrival_quantity, v.Price, v.Total_p, v.Payment_type,
				v.Paid, v.Residual_p, v.Demand_date, v.Purchasing_cycle, v.Order_date, v.Over_due1, v.Actual_delivery_date, v.Residue, v.Over_due2,
				v.Buy_record, v.State, v.Warehouse_entry_number, v.Supplier})
	}

	f.WriteString("\xEF\xBB\xBF") // 写入一个UTF-8 BOM 防止中文乱码
	w := csv.NewWriter(f)         //创建一个新的写入文件流
	w.WriteAll(csv_data)
	w.Flush()
	resp.FileId = fmt.Sprintf(`%v.csv`, beginTime)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("export_ma_temp_plan recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func export_ma_temp_plan(response http.ResponseWriter, request *http.Request) {

	beginTime := time.Now().UnixNano()
	logs.Info("export_ma_temp_plan recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var csv_data [][]string
	var filename string
	filename = fmt.Sprintf(`./file/%v.csv`, beginTime)
	f, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	var req get_ma_plan_req
	var resp download_file_Resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	req.Index = 1
	req.Count = 100000
	req.If_done = false
	resp_data := get_plan(req)

	csv_data = append(csv_data,
		[]string{
			"序号", "RDM", "编号", "名称", "规格", "单位", "数量", "单价", "合计", "付款方式",
			"已付", "应付", "需求日期", "采购周期", "下单日期", "预计超期", "实际交付", "剩余", "超期",
			"采购记录", "到货数量", "状态", "入库单号", "供应商"})

	for i := 0; i < len(resp_data.Data); i++ {
		v := resp_data.Data[i]
		rp, _ := strconv.ParseFloat(strings.ReplaceAll(v.Residual_p, ",", ""), 64)
		if rp > 0.01 {
			csv_data = append(csv_data,
				[]string{
					strconv.Itoa(v.ID), v.RDM, v.Code, v.Name, v.Specs, v.Unit, v.Num, v.Price, v.Total_p, v.Payment_type,
					v.Paid, v.Residual_p, v.Demand_date, v.Purchasing_cycle, v.Order_date, v.Over_due1, v.Actual_delivery_date, v.Residue, v.Over_due2,
					v.Buy_record, v.Arrival_quantity_text, v.State, v.Warehouse_entry_number, v.Supplier})
		} else {
			continue
		}
	}

	f.WriteString("\xEF\xBB\xBF") // 写入一个UTF-8 BOM 防止中文乱码
	w := csv.NewWriter(f)         //创建一个新的写入文件流
	w.WriteAll(csv_data)
	w.Flush()
	resp.FileId = fmt.Sprintf(`%v.csv`, beginTime)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("export_ma_temp_plan recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func mul_update_pp_plan_num(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("mul_update_pp_plan_num recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req mul_update_pp_plan_num_req
	var resp CommonResp

	var js_data []byte
	var update_sql string
	var ids []int

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Plan); i++ {
		if req.Plan[i].Flag == "1" {
			ids = append(ids, req.Plan[i].Child_task_id...)
		} else if req.Plan[i].Flag == "3" {
			ids = append(ids, req.Plan[i].ID)
		}
	}

	for i := 0; i < len(ids); i++ {

		var d pp_plan
		selsql := fmt.Sprintf(`select ID,data FROM [plan] where ID=%d`, ids[i])
		rows, err := sqlConn.Query(selsql)
		if err == nil {
			for rows.Next() {

				var s string
				var id int
				if err = rows.Scan(&id, &s); err == nil {
					json.Unmarshal([]byte(s), &d)
					d.ID = id
					d.Arrival_quantity = d.Num
					d.Arrival_quantity_text = fmt.Sprintf(`%v/%v`, d.Num, d.Num)
				}
			}
			rows.Close()
		}

		fmt.Println(d)
		if d.ID > 0 {
			js_data, _ = json.Marshal(d)
			update_sql = fmt.Sprintf(`UPDATE [plan]
	   				SET [data] = '%s'
	 				WHERE ID=%d`, string(js_data), d.ID)
			fmt.Println(update_sql)
			_, err = sqlConn.Exec(update_sql)
			if err != nil {
				logs.Error(fmt.Sprintf(`mul_update_pp_plan_num err:%s`, err.Error()))
				resp.Ret = -1
				goto exit
			}
		}

	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("mul_update_pp_plan_num recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_payment_data_by_id(req get_payment_by_id_req) (resp get_payment_by_id_resp) {
	var sqlstr string

	var rdRow *sql.Rows
	var err error

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.ID == 0 {
		goto exit
	}

	sqlstr = fmt.Sprintf("select [data] from [payment] where ID =%d", req.ID)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_payment_data Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d payment_info
		var s string
		if err := rdRow.Scan(&s); err == nil {
			json.Unmarshal([]byte(s), &d)

			if len(d.Payment_data) == 0 {
				d.Payment_data = []payment_month{}
			}

			resp.Data = d
		} else {
			logs.Error("get_payment_data scan Error", err.Error())
		}
	}

exit:
	resp.Data.ID = req.ID
	if len(resp.Data.Payment_data) == 0 {
		resp.Data.Payment_data = []payment_month{}
	}
	return
}

func get_payment_by_id(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("get_payment_by_id recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_payment_by_id_req
	var resp get_payment_by_id_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	resp = get_payment_data_by_id(req)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_payment_by_id recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func update_payment(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("update_payment recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req update_payment_req
	var resp CommonResp

	var js_data []byte
	var update_sql string
	var err error
	var sql_str string
	var rows *sql.Rows
	var if_exist bool

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}
	fmt.Println(string(reqdata))

	sql_str = fmt.Sprintf(`select ID FROM [payment] where ID=%d `, req.Data.ID)
	rows, err = sqlConn.Query(sql_str)
	if err == nil {
		for rows.Next() {
			var id int
			if err = rows.Scan(&id); err == nil {
				if_exist = true
			}
		}
		rows.Close()
	}

	if if_exist {
		js_data, _ = json.Marshal(req.Data)
		update_sql = fmt.Sprintf(`UPDATE [dbo].[payment]
		   SET [supplier] = '%s'
		      ,[code] = '%s'
		      ,[name] = '%s'
		      ,[data] = '%s'
		    ,[pre_id]=%d
		 WHERE ID=%d`, req.Data.Supplier, req.Data.Code, req.Data.Name, string(js_data), req.Data.Pre_id, req.Data.ID)
		_, err = sqlConn.Exec(update_sql)
		if err != nil {
			logs.Error(fmt.Sprintf(`update_payment err:%s`, err.Error()))
			resp.Ret = -1
			goto exit
		}
	} else {
		js_data, _ = json.Marshal(req.Data)
		update_sql = fmt.Sprintf(`INSERT INTO [payment]
           ([ID]
           ,[supplier]
           ,[code]
           ,[name]
           ,[data]
           ,[pre_id])
     VALUES
           (%d
           ,'%s'
           ,'%s'
           ,'%s'
           ,'%s'
           ,%d)`, req.Data.ID, req.Data.Supplier, req.Data.Code, req.Data.Name, string(js_data), req.Data.Pre_id)
		_, err = sqlConn.Exec(update_sql)
		if err != nil {
			logs.Error(fmt.Sprintf(`update_payment err:%s`, err.Error()))
			resp.Ret = -1
			goto exit
		}
	}

	{
		//更新任务付款信息
		var d pp_plan
		selsql := fmt.Sprintf(`select [data] FROM [plan] where ID=%d`, req.Data.ID)
		rows, err = sqlConn.Query(selsql)
		if err == nil {
			for rows.Next() {
				var s string
				if err = rows.Scan(&s); err == nil {
					json.Unmarshal([]byte(s), &d)
				}
			}
			rows.Close()

			d.Total_p = req.Data.Total_p
			d.Paid = req.Data.Paid
			d.Residual_p = req.Data.Residual_p
			js_data, _ := json.Marshal(d)
			selsql = fmt.Sprintf(`UPDATE [plan] SET [data] = '%s' where ID=%d`, string(js_data), req.Data.ID)
			fmt.Println(selsql)
			_, err = sqlConn.Exec(selsql)
			if err != nil {
				logs.Error(fmt.Sprintf(`update_payment err:%s`, err.Error()))
				resp.Ret = -1
				goto exit
			}
		}
	}

	//更新父任务金额
	if req.Data.Pre_id > 0 {
		var total_p, total_paid float64

		var d pp_plan
		selsql := fmt.Sprintf(`select [data] FROM [plan] where ID=%d`, req.Data.Pre_id)
		rows, err = sqlConn.Query(selsql)
		if err == nil {
			for rows.Next() {
				var s string
				if err = rows.Scan(&s); err == nil {
					json.Unmarshal([]byte(s), &d)
				}
			}
			rows.Close()
		}

		var treq get_single_plan_req
		treq.ID = append(treq.ID, d.Child_task_id...)
		//fmt.Println("子任务id：", treq)
		pdata := get_s_plan(treq)

		//fmt.Println("子任务：", pdata)
		for i := 0; i < len(pdata.Data); i++ {
			v := pdata.Data[i]

			paid, _ := strconv.ParseFloat(v.Paid, 64)
			total_paid += paid
		}
		//d.Total_p = fmt.Sprintf(`%.2f`, total_p)
		total_p, _ = strconv.ParseFloat(d.Total_p, 64)
		d.Paid = fmt.Sprintf(`%.2f`, total_paid)
		d.Residual_p = fmt.Sprintf(`%.2f`, total_p-total_paid)

		js_data, _ := json.Marshal(d)
		selsql = fmt.Sprintf(`UPDATE [plan] SET [data] = '%s' where ID=%d`, string(js_data), req.Data.Pre_id)
		_, err = sqlConn.Exec(selsql)
		if err != nil {
			logs.Error(fmt.Sprintf(`update_payment err:%s`, err.Error()))
			resp.Ret = -1
			goto exit
		}

	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("update_payment recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

//-----------------支付接口---------------------------//

func update_payment_data(req payment_info) (r int) {
	var js_data []byte
	var update_sql string
	var err error
	var sql_str string
	var rows *sql.Rows
	var if_exist bool

	var old_payment payment_info
	sql_str = fmt.Sprintf(`select [ID],[data] FROM [payment] where ID=%d `, req.ID)
	rows, err = sqlConn.Query(sql_str)
	if err == nil {
		for rows.Next() {
			var id int
			var s string
			if err = rows.Scan(&id, &s); err == nil {
				if_exist = true
				json.Unmarshal([]byte(s), &old_payment)
			}
		}
		rows.Close()
	}

	if if_exist {
		old_payment.Total_p = req.Total_p
		old_payment.Residual_p = req.Residual_p
		old_payment.Paid = req.Paid
		js_data, _ = json.Marshal(req)
		update_sql = fmt.Sprintf(`UPDATE [dbo].[payment]
		   SET [data] = '%s'
		 WHERE ID=%d`, string(js_data), req.ID)
		_, err = sqlConn.Exec(update_sql)
		if err != nil {
			logs.Error(fmt.Sprintf(`update_payment err:%s`, err.Error()))
			r = -1
			return
		}
	}

	r = 0

	return
}

// //更新父任务金额
func update_pre_task_paid(pre_id int) {
	//更新父任务金额
	if pre_id > 0 {
		var total_p, total_paid float64

		var d pp_plan
		selsql := fmt.Sprintf(`select [data] FROM [plan] where ID=%d`, pre_id)
		rows, err := sqlConn.Query(selsql)
		if err == nil {
			for rows.Next() {
				var s string
				if err = rows.Scan(&s); err == nil {
					json.Unmarshal([]byte(s), &d)
				}
			}
			rows.Close()
		}

		var treq get_single_plan_req
		treq.ID = append(treq.ID, d.Child_task_id...)
		//fmt.Println("子任务id：", treq)
		pdata := get_s_plan(treq)

		//fmt.Println("子任务：", pdata)
		for i := 0; i < len(pdata.Data); i++ {
			v := pdata.Data[i]

			t_total_p, _ := strconv.ParseFloat(strings.ReplaceAll(v.Total_p, ",", ""), 64)
			total_p += t_total_p

			paid, _ := strconv.ParseFloat(v.Paid, 64)
			total_paid += paid
		}
		d.Total_p = fmt.Sprintf(`%.2f`, total_p)
		//total_p, _ = strconv.ParseFloat(d.Total_p, 64)
		d.Paid = fmt.Sprintf(`%.2f`, total_paid)
		d.Residual_p = fmt.Sprintf(`%.2f`, total_p-total_paid)

		js_data, _ := json.Marshal(d)
		selsql = fmt.Sprintf(`UPDATE [plan] SET [data] = '%s' where ID=%d`, string(js_data), pre_id)
		_, err = sqlConn.Exec(selsql)
		if err != nil {
			logs.Error(fmt.Sprintf(`update_payment err:%s`, err.Error()))
			return
		}

	}
}

//-----------------支付接口---------------------------//

func get_payment_data(req get_payment_req) (resp get_payment_resp) {
	var sqlstr string
	var where_sql string
	var if_where bool

	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.Code != "" {
		likeStr := "%" + req.Code + "%"
		where_sql = fmt.Sprintf(" [code] like '%s'", likeStr)
		if_where = true
	}

	if req.Name != "" {
		likeStr := "%" + req.Name + "%"
		if if_where {
			where_sql = fmt.Sprintf(" and [name] like '%s'", likeStr)
		} else {
			where_sql = fmt.Sprintf(" [name] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Supplier != "" {
		likeStr := "%" + req.Supplier + "%"
		if if_where {
			where_sql = fmt.Sprintf(" and [supplier] like '%s'", likeStr)
		} else {
			where_sql = fmt.Sprintf(" [supplier] like '%s'", likeStr)
		}

		if_where = true
	}

	if if_where {
		sqlstr = fmt.Sprintf("select count(ID) from [payment] where %s ", where_sql)
	} else {
		sqlstr = fmt.Sprintf("select count(ID) from [payment] ")
	}

	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_payment_data query %s err:%v", sqlstr, err.Error()))
		goto exit
	}
	for cntRow.Next() {
		var cnt int
		if err = cntRow.Scan(&cnt); err != nil {
			logs.Error(fmt.Sprintf("get_payment_data scan %s err:%v", sqlstr, err.Error()))
			goto exit
		} else {
			resp.Total = cnt
		}
	}
	cntRow.Close()

	if !if_where {
		sqlstr = fmt.Sprintf("select top %v [ID],[data],[pre_id] from [payment] where ID not in (select top %v ID from [payment] order by ID desc) order by ID desc", req.Count, (req.Index-1)*req.Count)
	} else {
		sqlstr = fmt.Sprintf("select top %v [ID],[data],[pre_id] from [payment] where %s and ID not in (select top %v ID from [payment] where %s order by ID desc) order by ID desc", req.Count, where_sql, (req.Index-1)*req.Count, where_sql)
	}

	fmt.Println(sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_payment_data Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d payment_info
		var id, pre_id int
		var s string
		if err := rdRow.Scan(&id, &s, &pre_id); err == nil {
			json.Unmarshal([]byte(s), &d)
			d.ID = id
			d.Pre_id = pre_id
			fmt.Println(id, pre_id)

			if len(d.Payment_data) == 0 {
				d.Payment_data = []payment_month{}
			}

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_payment_data scan Error", err.Error())
		}
	}

exit:
	return
}

func get_payment(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("get_payment recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_payment_req
	var resp get_payment_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	resp = get_payment_data(req)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_payment recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func cal_effective_date(Update_date string, Validity_period_of_quotation string) (Effective_time string) {
	loc, _ := time.LoadLocation("Local")
	bt, _ := time.ParseInLocation(g_time_format, strings.ReplaceAll(Update_date, "/", "-")+" 00:00:00", loc)

	hour := bt.Sub(time.Now()).Hours()
	vp, _ := strconv.Atoi(Validity_period_of_quotation)
	Effective_time = fmt.Sprintf(`%d`, int(hour/24)+vp)

	return
}

func approve_ok(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("approve_ok recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req approve_ok_req
	var resp CommonResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	for i := 0; i < len(req.Data); i++ {
		req.Data[i].Code = strings.TrimSpace(req.Data[i].Code)
		v := req.Data[i]

		if v.Op_type == "新增" {
			var d material_info
			d.Code = v.Code
			d.Effective_time = v.Effective_time
			d.Name = v.Name
			d.Payment_type = v.Payment_type
			d.Price = v.Price
			d.Update_date = v.Update_date

			var dd price_update_info
			dd.Price_ = d.Price
			dd.Update_date_ = d.Update_date
			d.Price_arr = append(d.Price_arr, dd)

			d.Procurement_cycle = v.Procurement_cycle
			d.Spec = v.Spec
			d.Supplier = v.Supplier
			d.Supplier_code = v.Supplier_code
			d.Unit = v.Unit
			d.Validity_period_of_quotation = v.Validity_period_of_quotation

			d.Factory = v.Factory
			d.Factory_code = v.Factory_code
			d.Qs = v.Qs
			d.As = v.As

			js_data, _ := json.Marshal(d)

			insert_sql := fmt.Sprintf(`INSERT INTO [material]
           ([data]
           ,[code]
           ,[name]
           ,[supplier]
           ,[update_time])
     VALUES
           ('%s'
           ,'%s'
           ,'%s'
           ,'%s'
           ,'%s')`, string(js_data), d.Code, d.Name, d.Supplier, d.Update_date)

			fmt.Println(insert_sql)
			_, err := sqlConn.Exec(insert_sql)
			if err != nil {
				fmt.Println(err.Error())
				resp.Ret = -1
			}

		} else {
			sqlstr := fmt.Sprintf("select [ID],[data] from [material] where code ='%s'", v.Code)
			rdRow, err := sqlConn.Query(sqlstr)
			if err != nil {
				logs.Error(fmt.Sprintf("approve_ok Query err:%v", err.Error()))
				return
			}

			var mv material_info
			for rdRow.Next() {
				var id int
				var s string
				if err := rdRow.Scan(&id, &s); err == nil {
					json.Unmarshal([]byte(s), &mv)
					mv.ID = id
				} else {
					logs.Error("approve_ok scan Error", err.Error())
				}
			}
			rdRow.Close()

			mv.Supplier = v.Supplier
			mv.Supplier_code = v.Supplier_code
			mv.Payment_type = v.Payment_type

			mv.Name = v.Name
			mv.Spec = v.Spec
			mv.Unit = v.Unit
			//Price       string `json:"price"`       //单价
			//Update_date string `json:"update_date"` //更新日期

			mv.Procurement_cycle = v.Procurement_cycle
			mv.Validity_period_of_quotation = v.Validity_period_of_quotation
			mv.Effective_time = v.Effective_time

			var dd price_update_info
			dd.Price_ = v.Price
			dd.Update_date_ = v.Update_date

			var arr []price_update_info
			arr = append(arr, dd)
			arr = append(arr, mv.Price_arr...)
			mv.Price_arr = []price_update_info{}
			mv.Price_arr = append(mv.Price_arr, arr...)

			for k := 0; k < len(mv.Price_arr); k++ {
				if k == 0 {
					mv.Price = mv.Price_arr[k].Price_
					mv.Update_date = mv.Price_arr[k].Update_date_
				} else if k == 1 {
					mv.Price_2 = mv.Price_arr[k].Price_
					mv.Update_date_2 = mv.Price_arr[k].Update_date_
				} else if k == 2 {
					mv.Price_3 = mv.Price_arr[k].Price_
					mv.Update_date_3 = mv.Price_arr[k].Update_date_
				} else if k == 3 {
					mv.Price_4 = mv.Price_arr[k].Price_
					mv.Update_date_4 = mv.Price_arr[k].Update_date_
				} else if k == 4 {
					mv.Price_5 = mv.Price_arr[k].Price_
					mv.Update_date_5 = mv.Price_arr[k].Update_date_
				}
			}

			mv.Factory = v.Factory
			mv.Factory_code = v.Factory_code
			mv.Qs = v.Qs
			mv.As = v.As

			js_data, _ := json.Marshal(mv)

			update_sql := fmt.Sprintf(`UPDATE [dbo].[material]
   SET [data] = '%s'
      ,[code] = '%s'
      ,[name] = '%s'
      ,[supplier] = '%s'
      ,[update_time] = '%s'
 WHERE ID=%d`, string(js_data), mv.Code, mv.Name, mv.Supplier, mv.Update_date, mv.ID)

			_, err = sqlConn.Exec(update_sql)
			if err != nil {
				fmt.Println(err.Error())
				resp.Ret = -1
			}
		}
	}

	if resp.Ret == 0 {
		update_sql := fmt.Sprintf(`UPDATE [dbo].[m_approve]
   			SET [state] = '已批准' WHERE ID=%d`, req.ID)
		sqlConn.Exec(update_sql)

		sync_material_map_ex() //更新cache

		sqlstr := fmt.Sprintf(`select [ID],[applicant],[time],[record_cnt],[update_cnt],[add_cnt],[state],[data] from [m_approve] where [state]!='已批准'`)
		rdRow, err := sqlConn.Query(sqlstr)
		if err != nil {
			logs.Error(fmt.Sprintf("get_approve_m_data Query err:%v", err.Error()))
			//goto exit
		}
		defer rdRow.Close()

		for rdRow.Next() {
			var d approve_m_info
			if err := rdRow.Scan(&d.ID, &d.Applicant, &d.Time, &d.Record_cnt, &d.Update_cnt, &d.Add_cnt, &d.State, &d.Data); err == nil {

				d.Add_cnt = 0
				d.Update_cnt = 0

				var t_data []approve_m_detail
				json.Unmarshal([]byte(d.Data), &t_data)
				for i := 0; i < len(t_data); i++ {
					if _, ok := material_map[t_data[i].Code]; ok {
						d.Update_cnt++
						t_data[i].Op_type = "替换"

						t_data[i].Last_price = material_map[t_data[i].Code].Price

						last_price := strings.ReplaceAll(t_data[i].Last_price, ",", "")
						price := strings.ReplaceAll(t_data[i].Price, ",", "")
						p1, _ := strconv.ParseFloat(last_price, 64)
						p2, _ := strconv.ParseFloat(price, 64)

						t_data[i].Price_span = fmt.Sprintf(`%.2f`, p2-p1)
					} else {
						d.Add_cnt++
						t_data[i].Op_type = "新增"
					}

				}

				str, _ := json.Marshal(t_data)
				d.Data = string(str)

				update_sql := fmt.Sprintf(`UPDATE [dbo].[m_approve]
				   SET [update_cnt] = %d
				      ,[add_cnt] = %d
				       ,[data] = '%s'
				 WHERE ID=%d`, d.Update_cnt, d.Add_cnt, d.Data, d.ID)
				fmt.Println(update_sql)
				sqlConn.Exec(update_sql)

			} else {
				logs.Error("get_approve_m_data scan Error", err.Error())
			}
		}

	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("approve_ok recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func del_approve(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("del_approve recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req del_approve_req
	var resp CommonResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	for i := 0; i < len(req.Data); i++ {
		del_sql := fmt.Sprintf(`delete from [m_approve] where ID=%d`, req.Data[i].ID)
		_, err := sqlConn.Exec(del_sql)
		if err != nil {
			logs.Error(fmt.Sprintf(`del_approve err:%s`, err.Error()))
		}
	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("del_approve recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

// 导入审批物料
func import_approve_m(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("import_approve_m recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var err error
	var flag int

	var reqdata []byte
	var req import_approve_m_req
	var resp CommonResp
	var b bool
	var rdRow *sql.Rows

	var d approve_m_info
	var insert_sql string

	var if_ok bool
	var err_context string
	code_map := make(map[string]int)

	approve_m_lock.Lock()
	flag = ma_plan_lock_n
	approve_m_lock.Unlock()

	if flag == 1 {
		resp.Ret = 1
		goto exit
	} else {
		approve_m_lock.Lock()
		approve_m_lock_n = 1
		approve_m_lock.Unlock()
	}

	reqdata, _ = ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b = checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Data); i++ {
		if _, ok := code_map[req.Data[i].Code]; ok {
			if_ok = true
			if err_context == "" {
				err_context = req.Data[i].Code
			} else {
				err_context += " " + req.Data[i].Code
			}
		}

	}

	if if_ok {
		resp.Ret = 2
		resp.Context = fmt.Sprintf(`编号（%s）重复`, err_context)
		goto exit
	}

	d.Applicant = req.OpUser
	{
		year := time.Now().Year()
		month := int(time.Now().Month())
		day := time.Now().Day()

		d.Time = fmt.Sprintf(`%d/%02d/%02d`, year, month, day)
	}

	d.Record_cnt = len(req.Data)

	d.State = "待审批"

	for i := 0; i < len(req.Data); i++ {
		req.Data[i].Price = strings.TrimSpace(req.Data[i].Price)

		if req.Data[i].Update_date == "" {
			year := time.Now().Year()
			month := int(time.Now().Month())
			day := time.Now().Day()
			req.Data[i].Update_date = fmt.Sprintf(`%d/%02d/%02d`, year, month, day)
		}
		if req.Data[i].Update_date[2] == byte('/') {
			req.Data[i].Update_date = "20" + req.Data[i].Update_date
		}
		req.Data[i].Update_date = strings.ReplaceAll(req.Data[i].Update_date, "-", "/")
		t := strings.Split(req.Data[i].Update_date, "/")
		if len(t) == 3 {
			month, _ := strconv.Atoi(t[1])
			day, _ := strconv.Atoi(t[2])
			req.Data[i].Update_date = fmt.Sprintf(`%s/%02d/%02d`, t[0], month, day)
		}

		loc, _ := time.LoadLocation("Local")
		bt, _ := time.ParseInLocation(g_time_format, strings.ReplaceAll(req.Data[i].Update_date, "/", "-")+" 00:00:00", loc)

		hour := bt.Sub(time.Now()).Hours()
		vp, _ := strconv.Atoi(req.Data[i].Validity_period_of_quotation)
		req.Data[i].Effective_time = fmt.Sprintf(`%d`, int(hour/24)+vp)

		sqlstr := fmt.Sprintf("select [ID],[data] from [material] where code ='%s'", req.Data[i].Code)
		rdRow, err = sqlConn.Query(sqlstr)
		if err != nil {
			logs.Error(fmt.Sprintf("import_approve_m Query err:%v", err.Error()))
			goto exit
		}

		var mv material_info
		for rdRow.Next() {
			var id int
			var s string
			if err := rdRow.Scan(&id, &s); err == nil {
				json.Unmarshal([]byte(s), &mv)
				mv.ID = id
			} else {
				logs.Error("import_approve_m scan Error", err.Error())
			}
		}
		rdRow.Close()

		if mv.ID > 0 {
			req.Data[i].Op_type = "替换"
			req.Data[i].Last_price = mv.Price

			p1, _ := strconv.ParseFloat(mv.Price, 64)
			p2, _ := strconv.ParseFloat(req.Data[i].Price, 64)

			req.Data[i].Price_span = fmt.Sprintf(`%.2f`, p2-p1)
			d.Update_cnt++
		} else {
			req.Data[i].Op_type = "新增"
			d.Add_cnt++
		}
	}

	reqdata, _ = json.Marshal(req.Data)
	d.Data = string(reqdata)

	insert_sql = fmt.Sprintf(`INSERT INTO [dbo].[m_approve]
           ([applicant]
           ,[time]
           ,[record_cnt]
           ,[update_cnt]
           ,[add_cnt]
           ,[state]
           ,[data])
     VALUES
           ('%s'
           ,'%s'
           ,%d
           ,%d
           ,%d
           ,'%s'
           ,'%s')`, d.Applicant, d.Time, d.Record_cnt, d.Update_cnt, d.Add_cnt,
		d.State, d.Data)
	_, err = sqlConn.Exec(insert_sql)
	if err != nil {
		logs.Error(fmt.Sprintf("import_approve_m err:%v", err.Error()))
		goto exit
	}

	resp.Ret = 0

exit:

	if resp.Ret != 1 {
		approve_m_lock.Lock()
		approve_m_lock_n = 0
		approve_m_lock.Unlock()
	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("import_approve_m recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_approve_m_data(req get_approve_m_req) (resp get_approve_m_resp) {
	var sqlstr string
	var where_sql string
	var if_where bool

	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.Applicant != "" {
		likeStr := "%" + req.Applicant + "%"
		where_sql = fmt.Sprintf(" [applicant] like '%s'", likeStr)
		if_where = true
	}

	if if_where {
		sqlstr = fmt.Sprintf("select count(ID) from [m_approve] where %s ", where_sql)
	} else {
		sqlstr = fmt.Sprintf("select count(ID) from [m_approve] ")
	}

	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_approve_m_data query %s err:%v", sqlstr, err.Error()))
		goto exit
	}
	for cntRow.Next() {
		var cnt int
		if err = cntRow.Scan(&cnt); err != nil {
			logs.Error(fmt.Sprintf("get_approve_m_data scan %s err:%v", sqlstr, err.Error()))
			goto exit
		} else {
			resp.Total = cnt
		}
	}
	cntRow.Close()

	if !if_where {
		sqlstr = fmt.Sprintf("select top %v [ID],[applicant],[time],[record_cnt],[update_cnt],[add_cnt],[state],[data] from [m_approve] where ID not in (select top %v ID from [m_approve] order by ID desc) order by ID desc", req.Count, (req.Index-1)*req.Count)
	} else {
		sqlstr = fmt.Sprintf("select top %v [ID],[applicant],[time],[record_cnt],[update_cnt],[add_cnt],[state],[data] from [m_approve] where %s and ID not in (select top %v ID from [m_approve] where %s order by ID desc) order by ID desc", req.Count, where_sql, (req.Index-1)*req.Count, where_sql)
	}

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_approve_m_data Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d approve_m_info
		if err := rdRow.Scan(&d.ID, &d.Applicant, &d.Time, &d.Record_cnt, &d.Update_cnt, &d.Add_cnt, &d.State, &d.Data); err == nil {

			/*if d.State != "已批准" {
				d.Add_cnt = 0
				d.Update_cnt = 0

				var t_data []approve_m_detail
				json.Unmarshal([]byte(d.Data), &t_data)
				for i := 0; i < len(t_data); i++ {
					if _, ok := material_map[t_data[i].Code]; ok {
						d.Update_cnt++
						t_data[i].Op_type = "替换"

						t_data[i].Last_price = material_map[t_data[i].Code].Price

						last_price := strings.ReplaceAll(t_data[i].Last_price, ",", "")
						price := strings.ReplaceAll(t_data[i].Price, ",", "")
						p1, _ := strconv.ParseFloat(last_price, 64)
						p2, _ := strconv.ParseFloat(price, 64)

						t_data[i].Price_span = fmt.Sprintf(`%.2f`, p2-p1)
					} else {
						d.Add_cnt++
						t_data[i].Op_type = "新增"
					}

				}

				str, _ := json.Marshal(t_data)
				d.Data = string(str)
			}
			*/

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_approve_m_data scan Error", err.Error())
		}
	}

exit:
	return
}

func get_approve_m(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("get_approve_m recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_approve_m_req
	var resp get_approve_m_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	resp = get_approve_m_data(req)

	jdata, _ := json.Marshal(resp)

	str := string(jdata)
	str = strings.ReplaceAll(str, "%", "%%")
	fmt.Fprintf(response, str)

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_approve_m recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

// 删除物料
func remove_material(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("remove_material recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp CommonResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req remove_material_req
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintf(response, string(jdata))
		return
	}

	year := time.Now().Year()
	month := int(time.Now().Month())
	day := time.Now().Day()
	del_time := fmt.Sprintf(`%d/%02d/%02d`, year, month, day)

	for i := 0; i < len(req.ID); i++ {
		selsql := fmt.Sprintf(`update [material] SET [if_del] = 1,[del_time]='%s',[del_user]='%s' where ID=%d`,
			del_time, req.OpUser,
			req.ID[i])
		sqlConn.Exec(selsql)
	}

	resp.Ret = 0

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("remove_material recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_material_data_by_maxid(max_id int) (resp get_material_resp) {
	var sqlstr string
	var if_where bool

	var rdRow *sql.Rows
	var err error

	if !if_where {
		sqlstr = fmt.Sprintf("select [ID],[data] from [material] order by ID desc ")
	} else {
		sqlstr = fmt.Sprintf("select [ID],[data] from [material] where ID>%d order by ID desc", max_id)
	}

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_material_data Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d material_info
		var id int
		var s string
		if err := rdRow.Scan(&id, &s); err == nil {
			json.Unmarshal([]byte(s), &d)
			d.ID = id

			d.Effective_time = cal_effective_date(d.Update_date, d.Validity_period_of_quotation)

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_material_data scan Error", err.Error())
		}
	}

	if len(resp.Data) > 0 {
		g_material_maxid = resp.Data[0].ID
	}

exit:
	return
}

func get_material_data(req get_material_req, flag bool) (resp get_material_resp) {
	var sqlstr string
	var where_sql string
	var if_where bool

	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error

	if !flag {
		b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
		if !b {
			goto exit
		}
	}

	if req.Code != "" {
		likeStr := "%" + req.Code + "%"
		where_sql = fmt.Sprintf(" [code] like '%s'", likeStr)
		if_where = true
	}

	if req.Name != "" {
		likeStr := "%" + req.Name + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [name] like '%s'", likeStr)
		} else {
			where_sql = fmt.Sprintf(" [name] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Supplier != "" {
		likeStr := "%" + req.Supplier + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [supplier] like '%s'", likeStr)
		} else {
			where_sql = fmt.Sprintf(" [supplier] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Bt != "" {
		if if_where {
			where_sql += fmt.Sprintf(" and [update_time] > '%s'", req.Bt)
		} else {
			where_sql = fmt.Sprintf(" [update_time] > '%s'", req.Bt)
		}

		if_where = true
	}

	if req.Et != "" {
		if if_where {
			where_sql += fmt.Sprintf(" and [update_time] < '%s'", req.Et)
		} else {
			where_sql = fmt.Sprintf(" [update_time] < '%s'", req.Et)
		}

		if_where = true
	}

	if req.If_del {
		if if_where {
			where_sql += fmt.Sprintf(" and [if_del]=1 ")
		} else {
			where_sql = fmt.Sprintf(" [if_del]=1 ")
		}

		if_where = true
	} else {
		if if_where {
			where_sql += fmt.Sprintf(" and ([if_del]!=1 or if_del is null)")
		} else {
			where_sql = fmt.Sprintf(" ([if_del]!=1 or if_del is null) ")
		}

		if_where = true
	}

	if if_where {
		sqlstr = fmt.Sprintf("select count(ID) from [material] where %s ", where_sql)
	} else {
		sqlstr = fmt.Sprintf("select count(ID) from [material] ")
	}

	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_material_data query %s err:%v", sqlstr, err.Error()))
		goto exit
	}
	for cntRow.Next() {
		var cnt int
		if err = cntRow.Scan(&cnt); err != nil {
			logs.Error(fmt.Sprintf("get_material_data scan %s err:%v", sqlstr, err.Error()))
			goto exit
		} else {
			resp.Total = cnt
		}
	}
	cntRow.Close()

	if !if_where {
		sqlstr = fmt.Sprintf("select top %v [ID],[data],[del_time],[del_user] from [material] where ID not in (select top %v ID from [material] order by ID desc) order by ID desc", req.Count, (req.Index-1)*req.Count)
	} else {
		sqlstr = fmt.Sprintf("select top %v [ID],[data],[del_time],[del_user] from [material] where %s and ID not in (select top %v ID from [material] where %s order by ID desc) order by ID desc", req.Count, where_sql, (req.Index-1)*req.Count, where_sql)
	}

	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_material_data Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d material_info
		var id int
		var s, del_time, del_user string
		if err := rdRow.Scan(&id, &s, &del_time, &del_user); err == nil {
			json.Unmarshal([]byte(s), &d)
			d.ID = id
			d.Del_time = del_time
			d.Del_user = del_user

			if d.Validity_period_of_quotation != "长期" {
				if len(d.Update_date) > 2 && d.Update_date[2] != byte('/') {
					d.Update_date = d.Update_date[2:]
				}
				if len(d.Update_date_2) > 2 && d.Update_date_2[2] != byte('/') {
					d.Update_date_2 = d.Update_date_2[2:]
				}
				if len(d.Update_date_3) > 2 && d.Update_date_3[2] != byte('/') {
					d.Update_date_3 = d.Update_date_3[2:]
				}
				if len(d.Update_date_4) > 2 && d.Update_date_4[2] != byte('/') {
					d.Update_date_4 = d.Update_date_4[2:]
				}
				if len(d.Update_date_5) > 2 && d.Update_date_5[2] != byte('/') {
					d.Update_date_5 = d.Update_date_5[2:]
				}

				if d.Update_date != "" {
					d.Effective_time = cal_effective_date("20"+d.Update_date, d.Validity_period_of_quotation)
				}
			} else {
				d.Effective_time = ""
			}

			d.Price = convert_price(d.Price)

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_material_data scan Error", err.Error())
		}
	}

exit:
	return
}

func get_material(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("get_material recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_material_req
	var resp get_material_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	resp = get_material_data(req, false)

	jdata, _ := json.Marshal(resp)

	str := string(jdata)
	str = strings.ReplaceAll(str, "%", "%%")
	fmt.Fprintf(response, str)

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_material recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

func cal_completion_date(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("cal_completion_date recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var sqlstr string
	var resp cal_completion_date_resp
	var days int

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req cal_completion_date_req
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.Bt == "" {
		logs.Info("cal_completion_date req bt 为空")
		goto exit
	}

	req.Bt = strings.ReplaceAll(req.Bt, "/", "-") + " 00:00:00"
	days, _ = strconv.Atoi(req.Days)
	if days > 0 {
		m := make(map[int]int)
		var cnt int

		loc, _ := time.LoadLocation("Local")
		bt, _ := time.ParseInLocation(g_time_format, req.Bt, loc)

		fmt.Println(bt.Month())
		id := bt.Year()*10000 + int(bt.Month())*100 + bt.Day()

		sqlstr = fmt.Sprintf(`select [day],[type] FROM [holiday] where [day] >%d `, id)
		fmt.Println(sqlstr)
		rows, err := sqlConn.Query(sqlstr)
		if err != nil {
			logs.Info("cal_completion_date err:", err.Error())
			goto exit
		}

		for rows.Next() {
			var day, day_type int
			if err = rows.Scan(&day, &day_type); err == nil {
				m[day] = day_type
			}
		}
		rows.Close()
		fmt.Println(m)

		for {

			if cnt >= days {
				resp.Completion_date = bt.Format(g_time_format)
				if len(resp.Completion_date) >= 19 {
					resp.Completion_date = resp.Completion_date[:10]
				}
				break
			}

			bt = bt.Add(time.Hour * 24)
			key := bt.Year()*10000 + int(bt.Month())*100 + bt.Day()
			if _, ok := m[key]; ok {
				//1--假期  2--上班
				if m[key] == 1 {

				} else if m[key] == 2 {
					cnt++
				}
			} else {
				if int(bt.Weekday()) == 0 || int(bt.Weekday()) == 6 {

				} else {
					cnt++
				}
			}

		}
	} else {
		resp.Completion_date = req.Bt
		goto exit
	}

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("cal_completion_date recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func export_ma_plan(response http.ResponseWriter, request *http.Request) {

	/*beginTime := time.Now().UnixNano()
	logs.Info("export_ma_plan recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var csv_data [][]string
	var filename string
	filename = fmt.Sprintf(`./file/%v.csv`, beginTime)
	f, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	var req get_ma_plan_req
	var resp download_file_Resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	req.Index = 1
	req.Count = 100000
	resp_data := get_plan(req)

	csv_data = append(csv_data,
		[]string{
			"序号", "任务分配日期", "负责人", "需求R号", "申购R号",
			"物料编号", "物料名称", "物料规格描述", "单位", "数量", "单价", "金额", "税码",
			"供方编码及名称", "周期", "质量标准", "验收标准", "随货资料", "用途",
			"采购合同/订单号R号", "采购合同/订单号", "SAP订单号", "投产日期", "订单到期日",
			"已到货数量", "未到货数量", "SAP入库单号", "SAP入库日期", "订单是否超期", "备注"})

	for i := 0; i < len(resp_data.Data); i++ {
		v := resp_data.Data[i]

		csv_data = append(csv_data,
			[]string{
				strconv.Itoa(v.ID), v.Dispath_date, v.Header, v.R_id_1, v.R_id_2,
				v.Material_id, v.Material_name, v.Material_describe, v.Unit, v.Number, v.Unit_price, v.Amount_money, v.Tax_code,
				v.Supplier, v.Cycle, v.Quality_standard, v.Acceptance_criteria, v.Information, v.Purpose,
				v.Order_r_id, v.Procure_id, v.Sap_id, v.Production_date, v.Due_date,
				v.Arrival_quantity, v.Undelivered_quantity, v.SAP_Warehouse_entry_number, v.SAP_Warehouse_entry_date,
				v.Over_due, v.Note})
	}

	f.WriteString("\xEF\xBB\xBF") // 写入一个UTF-8 BOM 防止中文乱码
	w := csv.NewWriter(f)         //创建一个新的写入文件流
	w.WriteAll(csv_data)
	w.Flush()
	resp.FileId = fmt.Sprintf(`%v.csv`, beginTime)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("export_ma_plan recv req end, use time: %v ms", (endTime-beginTime)/1e6))
	*/
}

func remove_ma_plan(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("remove_ma_plan recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var err error
	var sqlstr string
	var resp CommonResp
	var selsql string
	var plan pp_plan
	var rows *sql.Rows
	//	var if_del bool = true
	var ids []int

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req remove_ma_plan_req
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	if req.ID == 0 {
		logs.Info("remove_ma_plan req id ==0")
		resp.Ret = -1
		goto exit
	}

	selsql = fmt.Sprintf(`SELECT [data] FROM [plan] where ID=%d`, req.ID)
	rows, err = sqlConn.Query(selsql)
	if err == nil {
		for rows.Next() {
			var s string
			if err = rows.Scan(&s); err == nil {
				json.Unmarshal([]byte(s), &plan)
			}
		}
		rows.Close()
	} else {
		resp.Ret = -1
		goto exit
	}

	if plan.ID == 0 {
		resp.Ret = -1
		goto exit
	}

	fmt.Println(plan.Child_task_id)
	/*for i := 0; i < len(plan.Child_task_id); i++ {
		selsql = fmt.Sprintf(`SELECT [if_del] FROM [plan] where ID=%d`, req.ID)
		rows, err = sqlConn.Query(selsql)
		if err == nil {
			var b int
			for rows.Next() {
				if err = rows.Scan(&b); err == nil {

				}
			}
			rows.Close()

			if b == 0 {
				if_del = false
				break
			}
		}
	}*/

	if len(plan.Child_task_id) > 0 {
		ids = append(ids, plan.Child_task_id...)
	}
	ids = append(ids, plan.ID)
	fmt.Println(ids)

	for i := 0; i < len(ids); i++ {
		sqlstr = fmt.Sprintf(`DELETE FROM [plan] WHERE ID=%d`, ids[i])
		fmt.Println(sqlstr)
		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("remove_ma_plan err:", err.Error())
			resp.Ret = -1
			goto exit
		}

		sqlstr = fmt.Sprintf(`DELETE FROM [payment] WHERE ID=%d`, ids[i])
		_, err = sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("remove_ma_plan err:", err.Error())
			resp.Ret = -1
			goto exit
		}
	}

	if plan.Pre_id > 0 {
		update_pre_task_paid(plan.Pre_id)
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("remove_ma_plan recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_ma_username(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("get_ma_username recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_ma_username_req
	var resp get_ma_username_resp

	var users []useInfo

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	users, _ = get_all_user()
	for i := 0; i < len(users); i++ {
		resp.Data = append(resp.Data, users[i].Username)
	}

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("get_ma_username recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_p_name(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("get_p_name recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_p_name_req
	var resp get_p_name_resp

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.P_id != "" {
		sqlstr = fmt.Sprintf("select [p_name] from [sap] where p_id = '%s' order by ID desc", req.P_id)
	} else {
		goto exit
	}

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_p_name Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d string
		if err := rdRow.Scan(&d); err == nil {
			resp.P_name = d
		} else {
			logs.Error("get_p_name scan Error", err.Error())
		}
	}

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("get_p_name recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_p_id_options(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("get_p_id_options recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_p_id_options_req
	var resp get_p_id_options_resp

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.P_like_id != "" {
		like_id := "%" + req.P_like_id + "%"
		sqlstr = fmt.Sprintf("select [p_id] from [sap] where p_id like '%s' order by ID desc", like_id)
	} else {
		sqlstr = fmt.Sprintf("select [p_id] from [sap] order by ID desc")
	}

	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_p_id_options Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d string

		if err := rdRow.Scan(&d); err == nil {
			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_p_id_options scan Error", err.Error())
		}
	}

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("get_p_id_options recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func update_ma_plan_ex(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("update_ma_plan_ex recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req update_ma_plan_req
	var resp CommonResp

	var js_data []byte
	var update_sql string
	var err error
	var if_done int

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintf(response, string(jdata))
		return
	}

	//req.Plan.Demand_date = "20" + req.Plan.Demand_date

	sel_sql := fmt.Sprintf(`select [data] from [plan] where ID=%d`, req.Plan.ID)
	rows, err := sqlConn.Query(sel_sql)
	if err != nil {
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintf(response, string(jdata))
		return
	}

	var old_data pp_plan
	for rows.Next() {
		var s string
		if err = rows.Scan(&s); err == nil {
			json.Unmarshal([]byte(s), &old_data)
		}
	}
	rows.Close()

	if old_data.ID == 0 {
		resp.Ret = -1
		jdata, _ := json.Marshal(resp)
		fmt.Fprintf(response, string(jdata))
		return
	}

	old_demand_date := convert_date(old_data.Demand_date)
	demand_date := convert_date(req.Plan.Demand_date)

	if old_demand_date != demand_date {
		old_data.Demand_date_update_cnt += 1
	}

	old_data.RDM = req.Plan.RDM
	old_data.Num = strings.ReplaceAll(req.Plan.Num, ",", "")
	old_data.Demand_date = req.Plan.Demand_date
	old_data.Buy_record = req.Plan.Buy_record
	old_data.Arrival_quantity = req.Plan.Arrival_quantity
	old_data.State = req.Plan.State
	old_data.Warehouse_entry_number = req.Plan.Warehouse_entry_number
	old_data.Buyer = req.Plan.Buyer
	old_data.Serial_num = req.Plan.Serial_num
	old_data.Contract_id = req.Plan.Contract_id
	old_data.Pay_Amount = req.Plan.Pay_Amount
	old_data.Batch_No = req.Plan.Batch_No
	old_data.Remark = req.Plan.Remark

	if old_data.State == "待收货" {
		old_data.Order_date = fmt.Sprintf(`%d/%02d/%02d`, time.Now().Year(), time.Now().Month(), time.Now().Day())
	}

	//预计超期
	if old_data.Order_date != "" && old_data.Demand_date != "" {
		fmt.Println(old_data.Demand_date, old_data.Order_date)
		t_order := convert_date(old_data.Order_date)
		t_demand := convert_date(old_data.Demand_date)
		fmt.Println(t_demand, t_order)
		if t_order != "" && t_demand != "" {
			loc, _ := time.LoadLocation("Local")
			order_date, _ := time.ParseInLocation(g_time_format, t_order+" 00:00:00", loc)
			demand_date, _ := time.ParseInLocation(g_time_format, t_demand+" 00:00:00", loc)

			span := (demand_date.Sub(order_date).Hours()) / 24
			cycle, _ := strconv.Atoi(old_data.Purchasing_cycle)
			if int(span)-cycle < 0 {
				old_data.Over_due1 = fmt.Sprintf(`%d`, cycle-int(span))
				//fmt.Println(req.Plan.Residue)
				old_data.Residue = ""
			} else {
				old_data.Residue = strconv.Itoa(int(span) - cycle)
				old_data.Over_due1 = ""
			}
		}

	}

	if old_data.State == "已收货" {
		old_data.Actual_delivery_date = fmt.Sprintf(`%d/%02d/%02d`, time.Now().Year(), time.Now().Month(), time.Now().Day())
	}

	if old_data.State == "交检" && old_data.Pre_id == 0 {
		if_done = 1
	} else if old_data.Pre_id == 0 && old_data.State != "交检" {
		if_done = 0
	}

	old_data.Arrival_quantity_text = fmt.Sprintf(`%v/%v`, old_data.Arrival_quantity, old_data.Num)

	if old_data.Flag == "2" || old_data.Flag == "3" {
		// num, _ := strconv.ParseFloat(old_data.Num, 64)
		numStr := strings.ReplaceAll(old_data.Num, ",", "")
		num, _ := strconv.ParseFloat(numStr, 64)
		price, _ := strconv.ParseFloat(strings.ReplaceAll(old_data.Price, ",", ""), 64)
		fmt.Println(old_data.Price)
		fmt.Println(num, price, num*price)
		old_data.Total_p = fmt.Sprintf(`%.2f`, num*price)

		paid, _ := strconv.ParseFloat(old_data.Paid, 64)

		old_data.Residual_p = fmt.Sprintf(`%.2f`, num*price-paid)

		var payment_data payment_info
		payment_data.Total_p = old_data.Total_p
		payment_data.Residual_p = old_data.Residual_p
		payment_data.Paid = old_data.Paid
		update_payment_data(payment_data)
	}

	js_data, _ = json.Marshal(old_data)
	update_sql = fmt.Sprintf(`UPDATE [plan]
	   SET [data] = '%s'
	      ,[state]='%s'
		,[rdm] = '%s'
      ,[op_time] = '%s'
      ,[code] = '%s'
      ,[name] = '%s'
      ,[supplier] = '%s'
    	,[if_done]=%d
		,[buyer]='%s',[order_date]='%s',[remark]='%s'
	 WHERE ID=%d`, string(js_data), old_data.State, old_data.RDM, time.Now().Format("2006-01-02 15:04:05"),
		old_data.Code, old_data.Name, old_data.Supplier, if_done, old_data.Buyer, old_data.Order_date, old_data.Remark,
		old_data.ID)
	fmt.Println(update_sql)
	_, err = sqlConn.Exec(update_sql)
	if err != nil {
		logs.Error(fmt.Sprintf(`update_ma_plan_ex err:%s`, err.Error()))
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

	if old_data.Pre_id > 0 {
		//主任务付款信息
		update_pre_task_paid(old_data.Pre_id)

		go func(pre_id int) {

			sel_sql := fmt.Sprintf(`select [state] from [plan] where [pre_id]=%d`, pre_id)
			fmt.Println(sel_sql)
			if_all_done := true
			rows, err := sqlConn.Query(sel_sql)
			if err == nil {
				for rows.Next() {
					var state string
					if err = rows.Scan(&state); err == nil {
						fmt.Println(state)
						if state != "交检" {
							if_all_done = false
						}
					} else {
						fmt.Println(err.Error())
						return
					}
				}
				rows.Close()
			} else {
				return
			}

			fmt.Println(if_all_done)
			if if_all_done {
				update_sql = fmt.Sprintf(`UPDATE [plan]
				   SET [if_done]=%d
				 WHERE [pre_id]=%d`, 1, pre_id)
				sqlConn.Exec(update_sql)

				update_sql = fmt.Sprintf(`UPDATE [plan]
				   SET [if_done]=%d
				 WHERE ID=%d`, 1, pre_id)
				sqlConn.Exec(update_sql)
			} else {
				update_sql = fmt.Sprintf(`UPDATE [plan]
				   SET [if_done]=%d
				 WHERE ID=%d`, 0, pre_id)
				sqlConn.Exec(update_sql)
			}

		}(old_data.Pre_id)

	}

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("update_ma_plan_ex recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_s_plan(req get_single_plan_req) (resp get_single_plan_resp) {
	var sqlstr string
	var where_sql string

	var rdRow *sql.Rows
	var err error

	user_info, _ := getUserInfo(req.OpUser)

	/*b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}*/

	if len(req.ID) == 0 {
		return
	}

	where_sql += " where ID in ( "
	for i := 0; i < len(req.ID); i++ {
		if i == 0 {
			where_sql += strconv.Itoa(req.ID[i])
		} else {
			where_sql += "," + strconv.Itoa(req.ID[i])
		}
	}
	where_sql += " ) and [if_del] !=1"

	sqlstr = fmt.Sprintf("select [ID],[data] from [plan] %s", where_sql)
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_s_plan Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d pp_plan
		var id int
		var s string
		if err := rdRow.Scan(&id, &s); err == nil {
			json.Unmarshal([]byte(s), &d)
			d.ID = id

			if d.Payment_type == "1" {
				d.Payment_type = "全款"
			} else if d.Payment_type == "2" {
				d.Payment_type = "分期"
			}

			if len(d.Child_task_id) == 0 {
				d.Child_task_id = []int{}
			}

			if d.Flag == "1" {
				d.Price = ""
			} else {
				d.Price = convert_price(d.Price)
			}

			if len(d.Demand_date) > 2 {
				if d.Demand_date[2] != byte('/') {
					d.Demand_date = d.Demand_date[2:]
				}
			}

			if len(d.Order_date) > 2 {
				if d.Order_date[2] != byte('/') {
					d.Order_date = d.Order_date[2:]
				}
			}

			if len(d.Actual_delivery_date) > 2 {
				if d.Actual_delivery_date[2] != byte('/') {
					d.Actual_delivery_date = d.Actual_delivery_date[2:]
				}
			}

			if d.Actual_delivery_date != "" && d.Demand_date != "" {

				t_actual_date := convert_date(d.Actual_delivery_date)
				t_demand := convert_date(d.Demand_date)
				if t_actual_date != "" && t_demand != "" {
					loc, _ := time.LoadLocation("Local")
					actual_delivery_date, _ := time.ParseInLocation(g_time_format, "20"+strings.ReplaceAll(d.Actual_delivery_date, "/", "-")+" 00:00:00", loc)
					demand_date, _ := time.ParseInLocation(g_time_format, "20"+strings.ReplaceAll(d.Demand_date, "/", "-")+" 00:00:00", loc)

					span := (actual_delivery_date.Sub(demand_date).Hours()) / 24
					if int(span) >= 1 {
						d.Over_due2 = fmt.Sprintf(`%d`, int(span))
					}
				}
			}

			d.Total_p = convert_price(d.Total_p)
			d.Paid = convert_price(d.Paid)
			d.Residual_p = convert_price(d.Residual_p)

			if d.Flag == "2" || d.Flag == "3" {
				if d.Arrival_quantity == "" {
					d.Arrival_quantity = "0"
				}
				d.Arrival_quantity_text = fmt.Sprintf(`%v/%v`, d.Arrival_quantity, d.Num)
			} else {
				d.Arrival_quantity_text = ""
			}

			if user_info.RoleId == 1 {
				d.If_modify = true
			} else {
				if !req.If_done {
					d.If_modify = true
				}
			}

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_ma_plan scan Error", err.Error())
		}
	}

exit:
	return
}

func get_single_plan(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("get_single_plan recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_single_plan_req
	var resp get_single_plan_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	resp = get_s_plan(req)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_single_plan recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

// 价格转换千分位显示
func convert_price(old_prive string) (price_t string) {

	var t_str string
	index := strings.Index(old_prive, ".")
	if index > 0 {
		t_str = old_prive[index:]
	}

	var price_str string
	price, _ := strconv.ParseFloat(strings.ReplaceAll(old_prive, ",", ""), 64)
	//fmt.Println("价格：", price)

	n := int(price)

	str := strconv.Itoa(n)

	var arr []byte
	var cnt int
	for i := len(str) - 1; i >= 0; i-- {
		cnt++
		if cnt%4 == 0 {
			arr = append(arr, byte(','))
			arr = append(arr, str[i])
			cnt = 1
		} else {
			arr = append(arr, str[i])
		}
	}
	//fmt.Println(string(arr))

	var t_arr []byte
	for i := len(arr) - 1; i >= 0; i-- {
		t_arr = append(t_arr, arr[i])
	}
	//fmt.Println(string(t_arr))

	price_str = string(t_arr)

	if price_str != "" {
		price_str += t_str
	} else {
		price_str += fmt.Sprintf(`0%s`, t_str)
	}

	/*n4 := (price - float64(int(price))) * 100
	fmt.Println(n4)
	n5 := int(n4) % 100
	if n5 >= 0 {
		if price_str != "" {
			price_str += fmt.Sprintf(`.%02d`, n5)
		} else {
			price_str += fmt.Sprintf(`0.%02d`, n5)
		}
	}*/

	price_t = price_str

	return
}

// 日期转成2006-04-05格式
func convert_date(old_date string) (date string) {
	old_date = strings.ReplaceAll(old_date, "/", "-")
	t_arr := strings.Split(old_date, "-")
	if len(t_arr) == 3 {
		year, _ := strconv.Atoi(t_arr[0])
		if year < 100 {
			year += 2000
		}
		month, _ := strconv.Atoi(t_arr[1])
		day, _ := strconv.Atoi(t_arr[2])
		date = fmt.Sprintf(`%d-%02d-%02d`, year, month, day)
	}

	return
}

func get_warning(req get_ma_plan_req) (resp get_ma_plan_resp) {
	var sqlstr string
	var where_sql string
	var if_where bool

	var rdRow *sql.Rows
	var err error

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	where_sql += " [if_done]!=1 and ([flag]='2' or [flag]='3')"
	if_where = true

	if if_where {
		where_sql += fmt.Sprintf(" and [if_del] !=1")
	} else {
		where_sql += fmt.Sprintf(" [if_del] !=1")
	}

	sqlstr = fmt.Sprintf("select [ID],[data] from [plan] where %s order by supplier desc,order_date desc", where_sql)
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_ma_plan Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d pp_plan
		var id int
		var s string
		if err := rdRow.Scan(&id, &s); err == nil {
			json.Unmarshal([]byte(s), &d)
			d.ID = id

			if d.Payment_type == "1" {
				d.Payment_type = "全款"
			} else if d.Payment_type == "2" {
				d.Payment_type = "分期"
			}

			if len(d.Child_task_id) == 0 {
				d.Child_task_id = []int{}
			}

			if d.Flag == "1" {
				d.Price = ""
			} else {
				d.Price = convert_price(d.Price)
			}

			d.Total_p = convert_price(d.Total_p)
			d.Residual_p = convert_price(d.Residual_p)

			var warning_flag bool

			date := strings.ReplaceAll(time.Now().Format("2006-01-02"), "-", "/")
			if date > d.Demand_date {
				warning_flag = true
			}

			if d.Order_date != "" {
				t_order := convert_date(d.Order_date)
				if t_order != "" {
					loc, _ := time.LoadLocation("Local")
					bt, _ := time.ParseInLocation(g_time_format, t_order+" 00:00:00", loc)

					if int(time.Now().Sub(bt).Hours()) > 96 && d.State == "待签署" {
						warning_flag = true
					}
				}
			}

			if d.Flag == "2" || d.Flag == "3" {
				d.Arrival_quantity_text = fmt.Sprintf(`%v/%v`, d.Arrival_quantity, d.Num)
			} else {
				d.Arrival_quantity_text = ""
			}

			if warning_flag {
				resp.Data = append(resp.Data, d)
			}

		} else {
			logs.Error("get_ma_plan scan Error", err.Error())
		}
	}

exit:
	if len(resp.Data) == 0 {
		resp.Data = []pp_plan{}
	}
	return
}

func get_warning_plan(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("get_ma_plan recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_ma_plan_req
	var resp get_ma_plan_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	resp = get_warning(req)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_ma_plan recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}
func export_warning_plan(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("export_ma_temp_plan recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var csv_data [][]string
	var filename string
	filename = fmt.Sprintf(`./file/%v.csv`, beginTime)
	f, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	var req get_ma_plan_req
	var resp download_file_Resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	resp_data := get_warning(req)

	csv_data = append(csv_data,
		[]string{
			"序号", "RDM", "编号", "名称", "规格", "单位", "数量", "单价", "合计", "状态", "交付日期",
			"下单日期", "预计超期", "供应商"})

	for i := 0; i < len(resp_data.Data); i++ {
		v := resp_data.Data[i]

		csv_data = append(csv_data,
			[]string{
				strconv.Itoa(v.ID), v.RDM, v.Code, v.Name, v.Specs, v.Unit, v.Num, v.Price, v.Total_p,
				v.State, v.Demand_date, v.Order_date, v.Over_due1, v.Supplier})

	}

	f.WriteString("\xEF\xBB\xBF") // 写入一个UTF-8 BOM 防止中文乱码
	w := csv.NewWriter(f)         //创建一个新的写入文件流
	w.WriteAll(csv_data)
	w.Flush()
	resp.FileId = fmt.Sprintf(`%v.csv`, beginTime)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("export_warning_plan recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func get_plan(req get_ma_plan_req) (resp get_ma_plan_resp) {
	var sqlstr string
	var where_sql string
	var if_where bool

	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error
	var sp_resp get_sp_1_resp
	var sp_2_resp get_sp_1_resp

	user_info, _ := getUserInfo(req.OpUser)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.ID != "" {
		//likeStr := "%" + req.ID + "%"
		where_sql = fmt.Sprintf(" [ID] = %s", req.ID)
		if_where = true
	}

	if req.RDM != "" {
		likeStr := "%" + req.RDM + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [rdm] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [rdm] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Bt != "" {
		if if_where {
			where_sql += fmt.Sprintf(" and [op_time] > '%s'", req.Bt)
		} else {
			where_sql += fmt.Sprintf(" [op_time] > '%s'", req.Bt)
		}

		if_where = true
	}

	if req.Et != "" {
		if if_where {
			where_sql += fmt.Sprintf(" and [op_time] < '%s'", req.Et)
		} else {
			where_sql += fmt.Sprintf(" [op_time] < '%s'", req.Et)
		}

		if_where = true
	}

	if req.Code != "" {
		likeStr := "%" + req.Code + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [code] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [code] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Name != "" {
		likeStr := "%" + req.Name + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [name] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [name] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Supplier != "" {
		likeStr := "%" + req.Supplier + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [supplier] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [supplier] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.State != "" {
		likeStr := "%" + req.State + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [state] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [state] like '%s'", likeStr)
		}

		if_where = true
	}

	if req.Buyer != "" {
		likeStr := "%" + req.Buyer + "%"
		if if_where {
			where_sql += fmt.Sprintf(" and [buyer] like '%s'", likeStr)
		} else {
			where_sql += fmt.Sprintf(" [buyer] like '%s'", likeStr)
		}

		if_where = true
	}

	if if_where { //有查询条件则全部查询
		where_sql += fmt.Sprintf(" ")
	} else {
		where_sql += fmt.Sprintf(" [flag] !='2'")
		if_where = true
	}

	if req.If_done {
		if if_where {
			where_sql += " and [if_done]=1"
		} else {
			where_sql += " [if_done]=1"
		}

		if_where = true

	} else { //未处理
		if if_where {
			where_sql += " and [if_done]!=1 "
		} else {
			where_sql += " [if_done]!=1 "
		}

		if_where = true
	}

	if if_where {
		where_sql += fmt.Sprintf(" and [if_del] !=1")
	} else {
		where_sql += fmt.Sprintf(" [if_del] !=1")
	}

	if if_where {
		sqlstr = fmt.Sprintf("select count(ID) from [plan] where %s ", where_sql)
	} else {
		sqlstr = fmt.Sprintf("select count(ID) from [plan] ")
	}

	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_ma_plan query %s err:%v", sqlstr, err.Error()))
		goto exit
	}
	for cntRow.Next() {
		var cnt int
		if err = cntRow.Scan(&cnt); err != nil {
			logs.Error(fmt.Sprintf("get_ma_plan scan %s err:%v", sqlstr, err.Error()))
			goto exit
		} else {
			resp.Total = cnt
		}
	}
	cntRow.Close()

	if !if_where {
		sqlstr = fmt.Sprintf("select top %v [ID],[remark],[data] from [plan] where ID not in (select top %v ID from [plan] order by ID desc) order by ID desc", req.Count, (req.Index-1)*req.Count)
	} else {
		sqlstr = fmt.Sprintf("select top %v [ID],[remark],[data] from [plan] where %s and ID not in (select top %v ID from [plan] where %s order by ID desc) order by ID desc", req.Count, where_sql, (req.Index-1)*req.Count, where_sql)
	}
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_ma_plan Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d pp_plan
		var id int
		var s string
		var remark string
		if err := rdRow.Scan(&id, &remark, &s); err == nil {
			json.Unmarshal([]byte(s), &d)
			d.ID = id
			d.Remark = remark

			if d.Payment_type == "1" {
				d.Payment_type = "全款"
			} else if d.Payment_type == "2" {
				d.Payment_type = "分期"
			}

			if len(d.Child_task_id) == 0 {
				d.Child_task_id = []int{}
			}

			if d.Flag == "1" {
				d.Price = ""
			} else {
				d.Price = convert_price(d.Price)
			}

			if len(d.Demand_date) > 2 {
				if d.Demand_date[2] != byte('/') {
					d.Demand_date = d.Demand_date[2:]
				}
			}

			if len(d.Order_date) > 2 {
				if d.Order_date[2] != byte('/') {
					d.Order_date = d.Order_date[2:]
				}
			}

			if len(d.Actual_delivery_date) > 2 {
				if d.Actual_delivery_date[2] != byte('/') {
					d.Actual_delivery_date = d.Actual_delivery_date[2:]
				}
			}

			if d.Actual_delivery_date != "" && d.Demand_date != "" {
				t_actual_date := convert_date(d.Actual_delivery_date)
				t_demand := convert_date(d.Demand_date)
				if t_actual_date != "" && t_demand != "" {
					loc, _ := time.LoadLocation("Local")
					actual_delivery_date, _ := time.ParseInLocation(g_time_format, t_actual_date+" 00:00:00", loc)
					demand_date, _ := time.ParseInLocation(g_time_format, t_demand+" 00:00:00", loc)

					span := (actual_delivery_date.Sub(demand_date).Hours()) / 24
					if int(span) >= 1 {
						d.Over_due2 = fmt.Sprintf(`%d`, int(span))
					}
				}
			}

			d.Total_p = convert_price(d.Total_p)
			d.Paid = convert_price(d.Paid)
			d.Residual_p = convert_price(d.Residual_p)

			if d.Flag == "2" || d.Flag == "3" {
				if d.Arrival_quantity == "" {
					d.Arrival_quantity = "0"
				}
				d.Arrival_quantity_text = fmt.Sprintf(`%v/%v`, d.Arrival_quantity, d.Num)
			} else {
				d.Arrival_quantity_text = ""
			}

			if d.Flag == "1" && d.Code == "" {
				d.Name = ""
				d.Specs = ""
				d.Unit = ""
				d.Price = ""
				d.Payment_type = ""
				d.Purchasing_cycle = ""
				d.Supplier = ""

				d.Factory = ""
				d.Factory_code = ""
				d.Qs = ""
				d.As = ""
			}

			if user_info.RoleId == 1 {
				d.If_modify = true
			} else {
				if !req.If_done {
					d.If_modify = true
				}
			}
			//查询原合同链接
			sp_resp = get_sp_by_id(id)
			fmt.Println("sp_resp", sp_resp.Data)
			if len(sp_resp.Data) > 0 {
				d.Contract_name = sp_resp.Data[0].Contract_name
			}
			//查询付款合同链接
			sp_2_resp = get_sp2_by_id(id)
			if len(sp_2_resp.Data) > 0 {
				d.Pay_Contract_name = sp_2_resp.Data[0].Contract_name
			}

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_ma_plan scan Error", err.Error())
		}
	}

exit:
	return
}

func get_ma_plan(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("get_ma_plan recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_ma_plan_req
	var resp get_ma_plan_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	resp = get_plan(req)

	jdata, _ := json.Marshal(resp)

	str := string(jdata)
	str = strings.ReplaceAll(str, "%", "%%")
	fmt.Fprintf(response, str)

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_ma_plan recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}
func export_plan_by_code(response http.ResponseWriter, request *http.Request) {

	beginTime := time.Now().UnixNano()
	logs.Info("export_plan_by_code recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var csv_data [][]string
	var filename string
	filename = fmt.Sprintf(`./file/%v.csv`, beginTime)
	f, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	var req get_ma_plan_req
	//var resp get_ma_plan_resp
	var resp download_file_Resp

	var pp_data []pp_plan

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	var sqlstr string
	var where_sql string
	var if_where bool

	var rdRow *sql.Rows
	//var err error
	var test_map map[string]int
	test_map = make(map[string]int)
	var count int

	if len(req.Codes) > 0 {

		var codes string
		for i := 0; i < len(req.Codes); i++ {
			if i == 0 {
				codes = "'" + req.Codes[i] + "'"
			} else {
				codes += ",'" + req.Codes[i] + "'"
			}
		}
		fmt.Println("---req.Codes", codes)

		if if_where {
			where_sql += fmt.Sprintf(" and [code] in (%s)", codes)
		} else {
			where_sql += fmt.Sprintf(" [code] in (%s)", codes)
		}

		if_where = true
	}

	if if_where { //有查询条件则全部查询
		where_sql += fmt.Sprintf(" ")
	} else {
		where_sql += fmt.Sprintf(" [flag] !='2'")
		if_where = true
	}

	if if_where {
		where_sql += fmt.Sprintf(" and [if_del] !=1")
	} else {
		where_sql += fmt.Sprintf(" [if_del] !=1")
	}

	sqlstr = fmt.Sprintf("select [ID],[code],[data] from [plan] where %s order by supplier, op_time desc", where_sql)
	fmt.Println("-----sqlstr", sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_ma_plan Query err:%v", err.Error()))
		return
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d pp_plan
		var id int
		var code string
		var s string
		if err := rdRow.Scan(&id, &code, &s); err == nil {
			json.Unmarshal([]byte(s), &d)
			d.ID = id

			if d.Flag == "1" {
				d.Price = ""
			} else {
				d.Price = convert_price(d.Price)
			}
			if _, ok := test_map[code]; ok {

				count = count + 1
				if count > 5 {
					continue
				}

			} else {
				count = 1
			}
			test_map[code] = id

			pp_data = append(pp_data, d)
		} else {
			logs.Error("get_ma_plan scan Error", err.Error())
		}
	}

	for i := 0; i < len(req.Codes); i++ {
		var dd pp_plan
		if _, ok := test_map[req.Codes[i]]; ok {

		} else {
			dd.Code = req.Codes[i]
			pp_data = append(pp_data, dd)
		}
	}

	csv_data = append(csv_data,
		[]string{
			"六合编号", "日期", "单价", "供应商", "需求任务"})

	for i := 0; i < len(pp_data); i++ {
		v := pp_data[i]
		csv_data = append(csv_data,
			[]string{
				v.Code, v.Order_date, v.Price, v.Supplier, v.RDM})
	}

	f.WriteString("\xEF\xBB\xBF") // 写入一个UTF-8 BOM 防止中文乱码
	w := csv.NewWriter(f)         //创建一个新的写入文件流
	w.WriteAll(csv_data)
	w.Flush()
	resp.FileId = fmt.Sprintf(`%v.csv`, beginTime)

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("export_ma_temp_plan recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}
func search_plan_by_code(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("search_plan_by_code recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req get_ma_plan_req
	var resp get_ma_plan_resp

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	fmt.Println("----req", req)

	resp = get_plan_by_code(req)

	jdata, _ := json.Marshal(resp)

	str := string(jdata)
	str = strings.ReplaceAll(str, "%", "%%")
	fmt.Fprintf(response, str)

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("get_ma_plan recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}
func get_plan_by_code(req get_ma_plan_req) (resp get_ma_plan_resp) {
	var sqlstr string
	var where_sql string
	var if_where bool

	var rdRow *sql.Rows
	var err error
	var test_map map[string]int
	test_map = make(map[string]int)
	var count int

	if len(req.Codes) > 0 {

		var codes string
		for i := 0; i < len(req.Codes); i++ {
			if i == 0 {
				codes = "'" + req.Codes[i] + "'"
			} else {
				codes += ",'" + req.Codes[i] + "'"
			}
		}
		fmt.Println("---req.Codes", codes)

		if if_where {
			where_sql += fmt.Sprintf(" and [code] in (%s)", codes)
		} else {
			where_sql += fmt.Sprintf(" [code] in (%s)", codes)
		}

		if_where = true
	}

	if if_where { //有查询条件则全部查询
		where_sql += fmt.Sprintf(" ")
	} else {
		where_sql += fmt.Sprintf(" [flag] !='2'")
		if_where = true
	}

	if if_where {
		where_sql += fmt.Sprintf(" and [if_del] !=1")
	} else {
		where_sql += fmt.Sprintf(" [if_del] !=1")
	}

	sqlstr = fmt.Sprintf("select [ID],[code],[data] from [plan] where %s order by supplier, op_time desc", where_sql)
	fmt.Println("-----sqlstr", sqlstr)
	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("get_ma_plan Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d pp_plan
		var id int
		var code string
		var s string

		if err := rdRow.Scan(&id, &code, &s); err == nil {
			json.Unmarshal([]byte(s), &d)
			d.ID = id

			if d.Flag == "1" {
				d.Price = ""
			} else {
				d.Price = convert_price(d.Price)
			}
			if _, ok := test_map[code]; ok {

				count = count + 1
				if count > 5 {
					continue
				}

			} else {
				count = 1
			}

			test_map[code] = id

			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("get_ma_plan scan Error", err.Error())
		}
	}

	for i := 0; i < len(req.Codes); i++ {
		var dd pp_plan
		if _, ok := test_map[req.Codes[i]]; ok {

		} else {
			dd.Code = req.Codes[i]
			resp.Data = append(resp.Data, dd)
		}
	}

exit:
	return
}

func import_ma_plan(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("import_ma_plan recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	m_map := make(map[string]material_info)
	m_pre_id := make(map[int]int)
	var flag int

	var reqdata []byte
	var req import_ma_plan_Req
	var resp CommonResp
	var b bool

	var total_p, total_paid, total_residual_p float64

	var sel_sql string
	var rows *sql.Rows
	var err error
	var max_id int
	var child_task_id []int

	var err_context string
	var if_ok bool

	//	var get_sp_1_req_data get_sp_1_req
	//	sp_1_map := make(map[int]sp_1)

	ma_plan_lock.Lock()
	flag = ma_plan_lock_n
	ma_plan_lock.Unlock()

	if flag == 1 {
		resp.Ret = 1
		goto exit
	} else {
		ma_plan_lock.Lock()
		ma_plan_lock_n = 1
		ma_plan_lock.Unlock()
	}

	reqdata, _ = ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b = checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	for i := 0; i < len(req.Plan); i++ {

		if req.Plan[i].Flag == "1" {
			continue
		}

		var if_exist bool
		sel_sql := fmt.Sprintf(`select [data] from [material] where [code]='%s' `, req.Plan[i].Code)
		rows, err := sqlConn.Query(sel_sql)
		if err == nil {
			for rows.Next() {

				var v material_info
				var s string
				if err = rows.Scan(&s); err == nil {
					json.Unmarshal([]byte(s), &v)

					m_map[strings.TrimSpace(v.Code)] = v
					if_exist = true
				}
			}
			rows.Close()
		}

		//导入编号不存在
		if !if_exist {
			if_ok = true
			if err_context == "" {
				err_context = req.Plan[i].Code
			} else {
				err_context += "<br/><br/>" + req.Plan[i].Code
			}
		}

		if req.Plan[i].Buyer == "" || req.Plan[i].Order_date == "" {
			resp.Ret = 2
			resp.Context = fmt.Sprintf(`编码:%s 采购人员（下单日期）不可为空！`, req.Plan[i].Code)
			goto exit
		}

		/*if req.Plan[i].Contract_id == "" {
			resp.Ret = 2
			resp.Context = fmt.Sprintf(`编码:%s 合同号不可为空！`, req.Plan[i].Code)
			goto exit
		}*/

		if len(req.Plan[i].Demand_date) > 2 && (req.Plan[i].Demand_date[2] == byte('/') || req.Plan[i].Demand_date[2] == byte('-')) {
			resp.Ret = 2
			resp.Context = fmt.Sprintf(`编码:%s 时间格式不对！`, req.Plan[i].Code)
			goto exit
		}

		if len(req.Plan[i].Order_date) > 2 && (req.Plan[i].Order_date[2] == byte('/') || req.Plan[i].Order_date[2] == byte('-')) {
			resp.Ret = 2
			resp.Context = fmt.Sprintf(`编码:%s 时间格式不对！`, req.Plan[i].Code)
			goto exit
		}
	}

	if if_ok {
		resp.Ret = 2
		resp.Context = fmt.Sprintf(`编码:<br/><br/>%s<br/><br/>对应的物料数据没有，请先导入物料数据！`, err_context)
		goto exit
	}

	/*{
		get_sp_1_req_data.Index = 1
		get_sp_1_req_data.Count = 1000000
		sp_1_data := get_sp_1_info(get_sp_1_req_data)
		for i := 0; i < len(sp_1_data.Data); i++ {
			sp_1_map[sp_1_data.Data[i].ID] = sp_1_data.Data[i]
		}
	}*/

	sel_sql = fmt.Sprintf(`select top 1 [ID] from [plan] order by [ID] desc`)
	rows, err = sqlConn.Query(sel_sql)
	if err != nil {
		resp.Ret = -1
		fmt.Println(err.Error())
		goto exit
	}

	for rows.Next() {
		if err = rows.Scan(&max_id); err != nil {
		}
	}
	rows.Close()

	for i := len(req.Plan) - 1; i >= 0; i-- {

		req.Plan[i].ID = max_id + 1
		max_id = req.Plan[i].ID

		req.Plan[i].Demand_date = strings.ReplaceAll(req.Plan[i].Demand_date, "-", "/")
		t := strings.Split(req.Plan[i].Demand_date, "/")
		if len(t) == 3 {
			month, _ := strconv.Atoi(t[1])
			day, _ := strconv.Atoi(t[2])
			req.Plan[i].Demand_date = fmt.Sprintf(`%s/%02d/%02d`, t[0], month, day)
		}

		req.Plan[i].Order_date = strings.ReplaceAll(req.Plan[i].Order_date, "-", "/")
		t = strings.Split(req.Plan[i].Order_date, "/")
		if len(t) == 3 {
			month, _ := strconv.Atoi(t[1])
			day, _ := strconv.Atoi(t[2])
			req.Plan[i].Order_date = fmt.Sprintf(`%s/%02d/%02d`, t[0], month, day)
		}

		code := strings.TrimSpace(req.Plan[i].Code)
		if v, ok := m_map[code]; ok {
			req.Plan[i].Name = v.Name
			req.Plan[i].Specs = v.Spec
			req.Plan[i].Unit = v.Unit
			req.Plan[i].Price = v.Price
			fmt.Println("单价：", v.Price)
			req.Plan[i].Payment_type = v.Payment_type
			req.Plan[i].Purchasing_cycle = v.Procurement_cycle
			req.Plan[i].Supplier = v.Supplier

			req.Plan[i].Factory = v.Factory
			req.Plan[i].Factory_code = v.Factory_code
			req.Plan[i].Qs = v.Qs
			req.Plan[i].As = v.As
		} else {
			fmt.Println("单价：0")

			js_data, _ := json.Marshal(m_map)
			fmt.Println(string(js_data))
		}

		req.Plan[i].Num = strings.TrimSpace(req.Plan[i].Num)
		num, _ := strconv.ParseFloat(req.Plan[i].Num, 64)
		price, _ := strconv.ParseFloat(strings.ReplaceAll(req.Plan[i].Price, ",", ""), 64)
		req.Plan[i].Total_p = fmt.Sprintf(`%.2f`, num*price)

		paid, _ := strconv.ParseFloat(req.Plan[i].Paid, 64)
		req.Plan[i].Residual_p = fmt.Sprintf(`%.2f`, num*price-paid)

		if req.Plan[i].Flag == "2" {
			total_p += num * price
			total_paid += paid
			total_residual_p += (num*price - paid)

			child_task_id = append(child_task_id, req.Plan[i].ID)
		} else {
			if len(child_task_id) > 0 {

				for j := 0; j < len(child_task_id); j++ {
					m_pre_id[child_task_id[j]] = req.Plan[i].ID
				}

				req.Plan[i].Total_p = fmt.Sprintf(`%.2f`, total_p)
				req.Plan[i].Paid = fmt.Sprintf(`%.2f`, total_paid)
				req.Plan[i].Residual_p = fmt.Sprintf(`%.2f`, total_residual_p)

				req.Plan[i].Child_task_id = append(req.Plan[i].Child_task_id, child_task_id...)
				child_task_id = []int{}

				total_p = 0
				total_paid = 0
				total_residual_p = 0
			}

		}

		if req.Plan[i].State == "待收货" {
			req.Plan[i].Order_date = fmt.Sprintf(`%d/%02d/%02d`, time.Now().Year(), time.Now().Month(), time.Now().Day())
		}

		//预计超期
		if req.Plan[i].Order_date != "" && req.Plan[i].Demand_date != "" {
			//fmt.Println(req.Plan[i].Demand_date, req.Plan[i].Order_date)
			t_order := convert_date(req.Plan[i].Order_date)
			t_demand := convert_date(req.Plan[i].Demand_date)
			//fmt.Println(t_demand, t_order)

			if t_order != "" && t_demand != "" {
				loc, _ := time.LoadLocation("Local")
				order_date, _ := time.ParseInLocation(g_time_format, t_order+" 00:00:00", loc)
				demand_date, _ := time.ParseInLocation(g_time_format, t_demand+" 00:00:00", loc)

				span := (demand_date.Sub(order_date).Hours()) / 24
				cycle, _ := strconv.Atoi(req.Plan[i].Purchasing_cycle)
				fmt.Println(fmt.Sprintf(`span:%v cycle:%v`, span, cycle))
				if int(span)-cycle < 0 {
					req.Plan[i].Over_due1 = fmt.Sprintf(`%d`, cycle-int(span))
				} else {
					req.Plan[i].Residue = fmt.Sprintf(`%d`, int(span)-cycle)
				}
			}

		}

		if req.Plan[i].State == "已收货" {
			req.Plan[i].Actual_delivery_date = fmt.Sprintf(`%d/%02d/%02d`, time.Now().Year(), time.Now().Month(), time.Now().Day())
		}

		if req.Plan[i].Actual_delivery_date != "" && req.Plan[i].Demand_date != "" {

			t_date := convert_date(req.Plan[i].Actual_delivery_date)
			t_demand := convert_date(req.Plan[i].Demand_date)
			if t_date != "" && t_demand != "" {
				loc, _ := time.LoadLocation("Local")
				actual_delivery_date, _ := time.ParseInLocation(g_time_format, t_date+" 00:00:00", loc)
				demand_date, _ := time.ParseInLocation(g_time_format, t_demand+" 00:00:00", loc)

				span := (actual_delivery_date.Sub(demand_date).Hours()) / 24
				if int(span) >= 1 {
					req.Plan[i].Over_due2 = fmt.Sprintf(`%d`, int(span))
				}
			}

		}

	}

	for i := 0; i < len(req.Plan); i++ {
		if _, ok := m_pre_id[req.Plan[i].ID]; ok {
			req.Plan[i].Pre_id = m_pre_id[req.Plan[i].ID]
		} else {
			req.Plan[i].Pre_id = 0
		}

		/*if contract_info, ok := sp_1_map[req.Plan[i].Contract_id]; ok {

			req.Plan[i].Contract_amount = contract_info.Amount
		}*/

		req.Plan[i].Contract_state = "待审批"
		req.Plan[i].State_1 = ""

		var if_done int
		if req.Plan[i].State == "交检" {
			if_done = 1
		}

		req.Plan[i].Arrival_quantity_text = fmt.Sprintf(`%v/%v`, req.Plan[i].Arrival_quantity, req.Plan[i].Num)

		jdata, _ := json.Marshal(req.Plan[i])
		sqlstr := fmt.Sprintf(`INSERT INTO [plan]
           ([ID],[data]
           ,[state]
           ,[rdm]
           ,[op_time]
           ,[code]
           ,[name]
           ,[supplier]
           ,[flag]
        ,[if_del]
        ,[pre_id]
        ,[if_done],[buyer],[order_date] ,[contract_id])
     VALUES
           (%d,'%s'
           ,'%s'
           ,'%s'
           ,'%s'
           ,'%s'
           ,'%s'
           ,'%s'
           ,'%s',%d,%d,%d,'%s','%s','%s')`,
			req.Plan[i].ID, string(jdata), req.Plan[i].State, req.Plan[i].RDM, time.Now().Format("2006-01-02 15:04:05"),
			req.Plan[i].Code, req.Plan[i].Name, req.Plan[i].Supplier, req.Plan[i].Flag, 0,
			req.Plan[i].Pre_id, if_done, req.Plan[i].Buyer, req.Plan[i].Order_date,
			req.Plan[i].Contract_id)

		_, err := sqlConn.Exec(sqlstr)
		if err != nil {
			logs.Info("import_ma_plan Exec Error:", err.Error())
			resp.Ret = -1
			goto exit
		}
	}

	resp.Ret = 0

exit:

	if resp.Ret != 1 {
		ma_plan_lock.Lock()
		ma_plan_lock_n = 0
		ma_plan_lock.Unlock()
	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("import_ma_plan recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func download_file(rw http.ResponseWriter, r *http.Request) {
	//获取请求参数
	/*var req download_file_req
	reqdata, _ := ioutil.ReadAll(r.Body)
	json.Unmarshal(reqdata, &req)

	fn := req.Filename*/

	filename := r.FormValue("id")
	base_file_path := modelePath + "/file/"

	if filename != "" {
		//设置响应头
		header := rw.Header()
		header.Add("Content-Type", "application/octet-stream")
		//header.Add("Content-Disposition", "attachment;filename="+fn)
		//使用ioutil包读取文件
		filepath := base_file_path + filename
		fmt.Println(filepath)
		b, _ := ioutil.ReadFile(filepath)

		//写入到响应流中
		rw.Write(b)
	}

}

func get_time_ex(search_time string) (st []string, b bool) {
	t := strings.Split(search_time, "-")
	if len(t) == 2 {
		t0 := strings.Split(t[0], "/")
		if len(t0) == 3 {
			year, _ := strconv.Atoi(t0[0])
			month, _ := strconv.Atoi(t0[1])
			day, _ := strconv.Atoi(t0[2])

			t0 := fmt.Sprintf(`20%02d/%02d/%02d`, year, month, day)
			st = append(st, t0)
		} else {
			b = true
		}

		t1 := strings.Split(t[1], "/")
		if len(t1) == 3 {
			year, _ := strconv.Atoi(t1[0])
			month, _ := strconv.Atoi(t1[1])
			day, _ := strconv.Atoi(t1[2])

			t0 := fmt.Sprintf(`20%02d/%02d/%02d`, year, month, day)
			st = append(st, t0)
		} else {
			b = true
		}

	} else if len(t) == 1 {
		tt := strings.Split(t[0], "/")
		if len(tt) == 3 {
			year, _ := strconv.Atoi(tt[0])
			month, _ := strconv.Atoi(tt[1])
			day, _ := strconv.Atoi(tt[2])

			bt := fmt.Sprintf(`20%02d/%02d/%02d`, year, month, day)
			et := fmt.Sprintf(`20%02d/%02d/%02d`, year, month, day)
			st = append(st, bt)
			st = append(st, et)
		} else {
			b = true
		}
	}

	if b {
		st = []string{}
	}

	return
}

func get_time(search_time string) (whereSql string) {
	t := strings.Split(search_time, "-")
	if len(t) == 2 {
		var if_where bool
		t0 := strings.Split(t[0], "/")
		if len(t0) == 2 {
			year, _ := strconv.Atoi(t0[0])
			month, _ := strconv.Atoi(t0[1])
			t := (year+2000)*100 + month
			whereSql += fmt.Sprintf(` [month] >= %d `, t)
			if_where = true
		} else if len(t0) == 3 {
			year, _ := strconv.Atoi(t0[0])
			month, _ := strconv.Atoi(t0[1])
			day, _ := strconv.Atoi(t0[2])

			t := fmt.Sprintf(`20%02d-%02d-%02d 00:00:00`, year, month, day)
			whereSql += fmt.Sprintf(` [time]>='%s' `, t)
			if_where = true
		}

		t1 := strings.Split(t[1], "/")
		if len(t1) == 2 {
			year, _ := strconv.Atoi(t1[0])
			month, _ := strconv.Atoi(t1[1])
			t := (year+2000)*100 + month
			if if_where {
				whereSql += fmt.Sprintf(` and [month] <= %d `, t)
			} else {
				whereSql += fmt.Sprintf(` [month] <= %d `, t)
			}
		} else if len(t1) == 3 {
			year, _ := strconv.Atoi(t1[0])
			month, _ := strconv.Atoi(t1[1])
			day, _ := strconv.Atoi(t1[2])

			t := fmt.Sprintf(`20%02d-%02d-%02d 23:59:59`, year, month, day)

			if if_where {
				whereSql += fmt.Sprintf(` and [time]<='%s' `, t)
			} else {
				whereSql += fmt.Sprintf(` [time]<='%s' `, t)
			}

			if_where = true
		}

	} else if len(t) == 1 {
		tt := strings.Split(t[0], "/")
		if len(tt) == 2 {
			year, _ := strconv.Atoi(tt[0])
			month, _ := strconv.Atoi(tt[1])
			search_month := (year+2000)*100 + month
			whereSql = fmt.Sprintf(` [month] = %d`, search_month)
		} else if len(tt) == 3 {
			year, _ := strconv.Atoi(tt[0])
			month, _ := strconv.Atoi(tt[1])
			day, _ := strconv.Atoi(tt[2])

			bt := fmt.Sprintf(`20%02d-%02d-%02d 00:00:00`, year, month, day)
			et := fmt.Sprintf(`20%02d-%02d-%02d 23:59:59`, year, month, day)
			whereSql = fmt.Sprintf(` [time]>='%s' and [time] <='%s' `, bt, et)
		}
	}

	return
}

//用户管理相关接口

func getUserNames(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	fmt.Println("getUserNames recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req getUserNamesReq
	var resp getUserNamesResp

	var sqlstr string
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkUserIfOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	sqlstr = fmt.Sprintf("select [username] from [user] order by ID asc")
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getUserNames Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var name string
		var v usernams
		if err := rdRow.Scan(&name); err == nil {
			v.Label = name
			v.Value = name
			resp.Names = append(resp.Names, v)
		} else {
			logs.Error("getUserNames scan Error", err.Error())
		}
	}

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	fmt.Println(fmt.Sprintf("getUserNames recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func checkIsSysUserOnline(username string, op_uuid string) bool {

	deesUserStatMaplck.RLock()
	if v, ok := deesUserStatMap[username]; ok {
		deesUserStatMaplck.RUnlock()

		v.RLock()
		refreshTime := v.RefreshTime
		userrole := v.UserRole
		uuid := v.Uuid
		v.RUnlock()
		if int64(time.Since(refreshTime).Seconds()) > int64(refreshSpan+1) {
			return false
		}

		if op_uuid != uuid {
			return false
		}

		if userrole != 1 {
			return false
		}

		return true
	} else {
		deesUserStatMaplck.RUnlock()

		return false
	}
}

func update_user_buyer(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("update_user_buyer recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var err error
	var sqlstr string
	var resp PostUserResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req PostUserReq
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	if req.Id == 0 {
		logs.Info("update userinfo req id ==0")
		resp.Ret = -1
		goto exit
	}

	sqlstr = fmt.Sprintf(`UPDATE [user] SET [if_buyer] = %d WHERE ID=%d`,
		req.If_buyer, req.Id)

	fmt.Println(sqlstr)

	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("update_user_buyer Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("update_user_buyer recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func postUser(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("postUser recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var roleid int
	var err error
	var sqlstr string
	var resp PostUserResp
	var departmentid int

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req PostUserReq
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		resp.Ret = -1
		goto exit
	}

	if (req.OperType == 2 || req.OperType == 3) && req.Id == 0 {
		logs.Info("update userinfo req id ==0")
		resp.Ret = -1
		goto exit
	}

	//add op check user for same username
	if req.OperType == 1 {
		var cnt int
		row, err := sqlConn.Query(fmt.Sprintf(`select ID from [user] where [username] = '%s'`, req.Username))
		if err != nil {
			logs.Error(fmt.Sprintf("postUser get user cnt err:%v", err.Error()))
			resp.Ret = -1
			goto exit
		}

		for row.Next() {
			cnt++
		}
		row.Close()

		if cnt > 0 {
			resp.Ret = 1
			goto exit
		}
	}

	roleid = 2
	if req.Role == "管理员" {
		roleid = 1
	}

	//1生产 2质检 3供应链 4交付 5研发 6 保温瓶
	/*if req.Department == "生产" {
		departmentid = 1
	} else if req.Department == "质检" {
		departmentid = 2
	} else if req.Department == "供应链" {
		departmentid = 3
	} else if req.Department == "交付" {
		departmentid = 4
	} else if req.Department == "研发" {
		departmentid = 5
	} else if req.Department == "保温瓶" {
		departmentid = 6
	} else if req.Department == "技术" {
		departmentid = 7
	} else {
		if req.OperType != 3 {
			goto exit
		}
	}*/

	if req.OperType == 1 { //add
		//opType = 10001
		//opContent = fmt.Sprintf(`新增用户%s`, req.Username)
		sqlstr = fmt.Sprintf(`INSERT INTO [user] ([username],[password],[role_name],[role_id],[department],[department_id],[state]) VALUES ('%s','%s','%s',%d,'%s',%d,'%s')`,
			req.Username, req.Password, req.Role, roleid, req.Department, departmentid,
			"")
	} else if req.OperType == 2 { //update
		//opType = 10002
		//opContent = fmt.Sprintf(`修改用户%s`, req.Username)
		sqlstr = fmt.Sprintf(`UPDATE [user] SET [username] = '%s',[password] = '%s',[role_name] = '%s',[role_id] = %d,[department]='%s',[department_id]=%d ,[state]='%s' WHERE ID=%d`,
			req.Username, req.Password, req.Role, roleid, req.Department, departmentid, "",
			req.Id)
	} else if req.OperType == 3 {
		//opType = 10003
		//		opContent = fmt.Sprintf(`删除用户%s`, req.Username)
		sqlstr = fmt.Sprintf(`DELETE FROM [user] WHERE ID=%d`, req.Id)
	} else {
		resp.Ret = -1
		goto exit
	}
	fmt.Println(sqlstr)

	_, err = sqlConn.Exec(sqlstr)
	if err != nil {
		logs.Info("postUser Exec Error:", err.Error())
		resp.Ret = -1
		goto exit
	}

	resp.Ret = 0

exit:

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("postUser recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func getUsers(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("getUsers recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req getUsersReq
	var resp GetUsersResp

	var sqlstr string
	var rcnt int
	var cntRow *sql.Rows
	var rdRow *sql.Rows
	var err error

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	b := checkIsSysUserOnline(req.OpUser, req.OpUserUuid)
	if !b {
		goto exit
	}

	if req.Id == "" {
		sqlstr = "select count(ID) from [user] "
	} else {
		likeStr := "%" + req.Id + "%"
		sqlstr = fmt.Sprintf("select count(ID) from [user] where [username] like '%s'", likeStr)
	}
	fmt.Println(sqlstr)

	cntRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getUsers query %s err:%v", sqlstr, err.Error()))
		goto exit
	}
	defer cntRow.Close()

	for cntRow.Next() {
		if err = cntRow.Scan(&rcnt); err != nil {
			logs.Error(fmt.Sprintf("getUsers scan %s err:%v", sqlstr, err.Error()))
			goto exit
		}
	}
	resp.Total = rcnt

	if req.Id == "" {
		sqlstr = fmt.Sprintf("select top %v [ID],[username],[password],[role_name],[role_id],[department] ,[state],[if_buyer] from [user] where ID not in (select top %v ID from [user] order by ID asc) order by ID asc", req.Count, (req.Index-1)*req.Count)
	} else {
		likeStr := "%" + req.Id + "%"
		sqlstr = fmt.Sprintf("select top %v [ID],[username],[password],[role_name],[role_id],[department] ,[state],[if_buyer] from [user] where username like '%s' and ID not in (select top %v ID from [user] where username like '%s' order by ID asc) order by ID asc", req.Count, likeStr, (req.Index-1)*req.Count, likeStr)
	}
	fmt.Println(sqlstr)

	rdRow, err = sqlConn.Query(sqlstr)
	if err != nil {
		logs.Error(fmt.Sprintf("getUsers Query err:%v", err.Error()))
		goto exit
	}
	defer rdRow.Close()

	for rdRow.Next() {
		var d useInfo

		if err := rdRow.Scan(&d.Userid, &d.Username, &d.Password, &d.RoleName, &d.RoleId,
			&d.Department, &d.State, &d.If_buyer); err == nil {
			resp.Data = append(resp.Data, d)
		} else {
			logs.Error("getUsers scan Error", err.Error())
		}
	}

exit:
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("getUsers recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func checkUserIfOnline(username string, uuid string) bool {

	deesUserStatMaplck.RLock()
	if v, ok := deesUserStatMap[username]; ok {
		deesUserStatMaplck.RUnlock()

		v.RLock()
		refreshTime := v.RefreshTime
		lastuuid := v.Uuid
		v.RUnlock()

		if uuid != lastuuid {
			return false
		}

		if int64(time.Since(refreshTime).Seconds()) > int64(refreshSpan+1) {
			return false
		}
		return true
	} else {
		deesUserStatMaplck.RUnlock()

		return false
	}
}

func getUserInfo(username string) (d useInfo, err error) {

	var sql string
	sql = fmt.Sprintf("select [username],[password],[role_name],[role_id],[department],[department_id] from [user] where [username] = '%s'", username)
	row, err := sqlConn.Query(sql)
	if err != nil {
		logs.Info("getUserInfo Query Error", err.Error())
		return
	}

	for row.Next() {

		if err = row.Scan(&d.Username, &d.Password, &d.RoleName, &d.RoleId, &d.Department, &d.DepartmentId); err == nil {
		} else {
			logs.Info("Query Error", err.Error())
		}
	}
	row.Close()

	return
}

func get_all_user() (resp []useInfo, err error) {

	var sql string
	sql = fmt.Sprintf("select [username],[password],[role_name],[role_id],[department],[department_id],[state] from [user] ")
	row, err := sqlConn.Query(sql)
	if err != nil {
		logs.Info("get_all_user Query Error", err.Error())
		return
	}

	for row.Next() {

		var d useInfo
		if err = row.Scan(&d.Username, &d.Password, &d.RoleName, &d.RoleId, &d.Department, &d.DepartmentId,
			&d.State); err == nil {
			resp = append(resp, d)
		} else {
			logs.Info("get_all_user scan Error", err.Error())
		}
	}
	row.Close()

	return
}

// 菜单
func getMenu(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("getMenu recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var err error
	var req GetMenuReq
	var resp GetMenuResp

	var menu GetMenuRespData
	var mItem menuItem

	var userInfo useInfo

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	ifOnline := checkUserIfOnline(req.UserName, req.Uuid)
	if !ifOnline {
		logs.Error("用户不在线")
		goto exit
	}

	userInfo, err = getUserInfo(req.UserName)
	if err != nil {
		logs.Error("getMenu:", err.Error())
		goto exit
	}

	menu.Title = "计划管理"
	menu.Index = "2"
	//menu.Class = "el-icon-s-data"
	//menu.SvgData.First = "M992.256 960 960 960 960 576.192C960 540.032 931.072 512 895.424 512l-126.784 0C732.352 512 704 540.736 704 576.192L704 960l-64 0L640 64.448C640 28.736 611.072 0 575.424 0L448.576 0C412.352 0 384 28.864 384 64.448L384 960 320 960 320 319.744C320 284.48 291.072 256 255.424 256L128.576 256C92.352 256 64 284.544 64 319.744L64 960 31.744 960C14.464 960 0 974.336 0 992 0 1009.152 14.208 1024 31.744 1024l960.448 0C1009.536 1024 1024 1009.664 1024 992 1024 974.848 1009.792 960 992.256 960z"
	menu.SvgData.First = "M955.3 77.1H798.1V59.3c0-16.6-13.4-30-30-30s-30 13.4-30 30v17.8H278.3V59.3c0-16.6-13.4-30-30-30s-30 13.4-30 30v17.8H69.2c-22.1 0-40 17.9-40 40v837.1c0 22.1 17.9 40 40 40h886.1c22.1 0 40-17.9 40-40V117.1c0-22.1-17.9-40-40-40z m-29.9 847.1H99.2V376.4h826.2v547.8z m0-607.8H99.2V137.1h119.1v17.8c0 16.6 13.4 30 30 30s30-13.4 30-30v-17.8h459.9v17.8c0 16.6 13.4 30 30 30s30-13.4 30-30v-17.8h127.2v179.3z"
	menu.SvgData.Second = "M470.4 551.3h321.4c18.2 0 33-14.8 33-33s-14.8-33-33-33H470.4c-18.2 0-33 14.8-33 33s14.8 33 33 33zM210.3 562.6l64.8 64.8 110.8-110.8c9.5-9.5 9.5-25 0-34.5s-25-9.5-34.5 0l-76.3 76.3-30.3-30.3c-9.5-9.5-25-9.5-34.5 0s-9.5 25 0 34.5zM470.4 785h321.4c18.2 0 33-14.8 33-33s-14.8-33-33-33H470.4c-18.2 0-33 14.8-33 33s14.8 33 33 33zM316.8 719.2h-67.9c-18.2 0-33 14.8-33 33s14.8 33 33 33h67.9c18.2 0 33-14.8 33-33s-14.8-33-33-33z"
	menu.Key = menu.Index

	mItem.Index = "/scb"
	mItem.Title = "采购计划"
	mItem.Key = mItem.Index
	menu.Items = append(menu.Items, mItem)
	resp.MenuData = append(resp.MenuData, menu)

	menu.Title = "审核"
	menu.Index = "4"
	//menu.Class = "el-icon-s-data"
	//menu.SvgData.First = "M992.256 960 960 960 960 576.192C960 540.032 931.072 512 895.424 512l-126.784 0C732.352 512 704 540.736 704 576.192L704 960l-64 0L640 64.448C640 28.736 611.072 0 575.424 0L448.576 0C412.352 0 384 28.864 384 64.448L384 960 320 960 320 319.744C320 284.48 291.072 256 255.424 256L128.576 256C92.352 256 64 284.544 64 319.744L64 960 31.744 960C14.464 960 0 974.336 0 992 0 1009.152 14.208 1024 31.744 1024l960.448 0C1009.536 1024 1024 1009.664 1024 992 1024 974.848 1009.792 960 992.256 960z"
	menu.SvgData.First = "M450.56 597.12L342.4 489.6l-44.8 44.8 147.84 148.48 342.4-273.92-39.68-49.92-297.6 238.08z"
	menu.SvgData.Second = "M512 32A480 480 0 1 0 992 512 480.64 480.64 0 0 0 512 32z m0 896A416 416 0 1 1 928 512 416.64 416.64 0 0 1 512 928z"
	menu.Key = menu.Index
	menu.Items = []menuItem{}

	mItem.Index = "/sp_1"
	mItem.Title = "合同录入审批"
	mItem.Key = mItem.Index
	menu.Items = append(menu.Items, mItem)

	mItem.Index = "/sp_2"
	mItem.Title = "付款申请审批"
	mItem.Key = mItem.Index
	menu.Items = append(menu.Items, mItem)

	resp.MenuData = append(resp.MenuData, menu)

	if userInfo.RoleId == 1 {
		menu.Title = "数据管理"
		menu.Index = "3"
		//menu.Class = "el-icon-user"
		menu.SvgData.First = "M64 192V896h896V192H64zM0 128h1024v832H0V128z"
		menu.SvgData.Second = "M64 384h896v64H64zM64 640h896v64H64zM128 256h192v64H128zM128 512h192v64H128zM128 768h192v64H128z"
		menu.Key = menu.Index
		menu.Items = []menuItem{}

		mItem.Index = "/base_data"
		mItem.Title = "物料数据库"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)

		mItem.Index = "/pf"
		mItem.Title = "导入物料审批"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)

		mItem.Index = "/search_code"
		mItem.Title = "根据编码匹配物料"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)

		/*mItem.Index = "/payment"
		mItem.Title = "付款维护"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)*/

		resp.MenuData = append(resp.MenuData, menu)
	}

	if userInfo.RoleId == 1 {
		menu.Title = "用户管理"
		menu.Index = "1"
		//menu.Class = "el-icon-user"
		menu.SvgData.First = "M955.456 765.12a41.792 41.792 0 0 0-34.368-32.64 8.256 8.256 0 0 1-6.08-3.904 8.256 8.256 0 0 1-0.384-7.104 41.856 41.856 0 0 0-11.136-45.696 165.76 165.76 0 0 0-60.096-34.56 41.728 41.728 0 0 0-45.056 13.12c-1.216 1.472-3.328 3.264-6.336 3.264s-5.12-1.728-6.336-3.264a41.6 41.6 0 0 0-45.056-13.184 166.4 166.4 0 0 0-60.224 34.624 41.728 41.728 0 0 0-11.136 45.632 8.064 8.064 0 0 1-0.384 7.104 8.256 8.256 0 0 1-6.08 3.904 41.728 41.728 0 0 0-34.304 32.64 166.72 166.72 0 0 0 0 68.928c3.584 16.96 17.28 29.952 34.432 32.64 1.92 0.32 4.544 1.216 6.08 3.904a8.256 8.256 0 0 1 0.384 7.104 41.6 41.6 0 0 0 11.136 45.696c17.344 15.616 37.568 27.2 60.096 34.56a41.728 41.728 0 0 0 45.056-13.056c1.216-1.472 3.328-3.264 6.336-3.264s5.12 1.728 6.336 3.264a41.728 41.728 0 0 0 45.056 13.12c22.528-7.296 42.688-18.88 59.968-34.432 12.8-11.52 17.216-29.696 11.136-45.76a8.192 8.192 0 0 1 0.384-7.168 8.256 8.256 0 0 1 6.08-3.904 41.728 41.728 0 0 0 34.496-32.64 166.144 166.144 0 0 0 0-68.928z m-40.832 60.288a49.92 49.92 0 0 0-35.904 24.256 49.92 49.92 0 0 0-3.264 42.752 123.584 123.584 0 0 1-44.992 25.792 49.92 49.92 0 0 0-38.528-18.432 49.664 49.664 0 0 0-38.528 18.432 125.44 125.44 0 0 1-45.056-25.856 49.728 49.728 0 0 0-39.04-66.944 123.712 123.712 0 0 1 0-51.776 49.92 49.92 0 0 0 35.648-24.256 49.92 49.92 0 0 0 3.328-42.624c12.928-11.648 28.224-20.416 45.12-25.92a49.92 49.92 0 0 0 38.528 18.432c15.68 0 29.44-7.296 38.592-18.432 16.896 5.504 32.128 14.272 45.056 25.856a49.728 49.728 0 0 0 39.04 66.944 122.624 122.624 0 0 1 0 51.776z"
		menu.SvgData.Second = "M791.936 736.96c-34.496 0-62.592 28.096-62.592 62.592s28.096 62.592 62.592 62.592 62.592-28.096 62.592-62.592-28.096-62.592-62.592-62.592z m0 83.456a20.864 20.864 0 1 1 0-41.728 20.864 20.864 0 0 1 0 41.728zM670.336 588.736c0.256 0.128 0.512 0.064 0.768 0.128l1.472 0.512 0.064-0.256a35.392 35.392 0 0 0 22.912-67.008l-0.384-0.064c-8.512-3.392-17.472-6.144-26.304-9.088a247.424 247.424 0 0 0 104.192-201.472 248.192 248.192 0 1 0-496.384 0c0 83.072 41.216 156.224 103.936 201.28-175.68 57.984-304.832 218.368-315.776 410.688 0 0.128 0.256 0.192 0.256 0.256a35.328 35.328 0 0 0 68.608 13.504c1.344-3.456 1.536-7.04 1.728-10.56l0.256-0.192a390.016 390.016 0 0 1 389.248-366.336c51.264 0 100.032 10.176 144.832 28.16 0.192 0.192 0.32 0.384 0.576 0.448zM347.648 311.424a177.28 177.28 0 1 1 354.56 0 177.28 177.28 0 0 1-354.56 0z"
		menu.Key = menu.Index
		menu.Items = []menuItem{}

		mItem.Index = "/user"
		mItem.Title = "用户信息"
		mItem.Key = mItem.Index
		menu.Items = append(menu.Items, mItem)

		resp.MenuData = append(resp.MenuData, menu)
	}

exit:
	jdata, _ := json.Marshal(resp)

	_, err = response.Write(jdata)
	if err != nil {
		logs.Error("getMenu:", err.Error())
	}

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("getMenu recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func checkFileExpired() {

	t := time.NewTicker(time.Minute * 3)

	for {
		select {
		case <-t.C:
			modelePath, err := ModulePath.GetModuleCurrentPath()
			if err != nil {
				logs.Error("GetModuleCurrentPath() failed err:", err.Error())
				return
			}

			fileInfoList, err := ioutil.ReadDir(modelePath + "/file")
			if err != nil {
				logs.Error("ioutil.ReadDir err:", err.Error())
			}

			for i := range fileInfoList {
				index := strings.Index(fileInfoList[i].Name(), ".")
				if index > 0 {
					filename := fileInfoList[i].Name()[:index]
					//filename := strings.TrimSuffix(fileInfoList[i].Name(), ".auf")
					logs.Info(filename) //打印当前文件或目录下的文件或目录名

					t, err := strconv.ParseInt(filename, 10, 64)
					if err == nil {
						t = t / 1e9

						if time.Now().Unix()-t > 60 {
							os.Remove(modelePath + "/file/" + fileInfoList[i].Name())
						}
					} else {
						//logs.Error("checkFileExpired err:", err.Error())
					}
				}

			}

		default:
			time.Sleep(time.Minute * 1)
		}
	}
}

// 登录
func getUuid() string {
	return uuid.NewV4().String()
}

func refreshUser(response http.ResponseWriter, request *http.Request) {
	//beginTime := time.Now().UnixNano()
	//logs.Info("refreshUser recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp CommonResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req RefreshUserReq
	json.Unmarshal(reqdata, &req)

	deesUserStatMaplck.RLock()
	if v, ok := deesUserStatMap[req.Username]; ok {
		deesUserStatMaplck.RUnlock()

		v.Lock()
		if v.Uuid == req.Uuid {

			if time.Now().Before(v.ExpireTime) {
				v.RefreshTime = time.Now()
				v.ExpireTime = time.Now().Add(ExpireTimeSpan)
			} else {
				resp.Ret = -1
			}

			//logs.Info(fmt.Sprintf("refreshTime:%v expiretime:%v", v.RefreshTime.Format("2006-01-02 15:04:05"), v.ExpireTime.Format("2006-01-02 15:04:05")))

			v.Unlock()
		} else {
			v.Unlock()
			resp.Ret = -1

			//fmt.Println("uuid:", v.Uuid)
			//fmt.Println("req.uuid", req.Uuid)
		}

	} else {
		deesUserStatMaplck.RUnlock()

		resp.Ret = -1
	}

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	//	endTime := time.Now().UnixNano()
	//logs.Info(fmt.Sprintf("refreshUser recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func LoginOut(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("LoginOut recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var resp CommonResp

	reqdata, _ := ioutil.ReadAll(request.Body)
	var req LoginOutReq
	json.Unmarshal(reqdata, &req)

	/*
		deesUserStatMaplck.Lock()
		if _, ok := deesUserStatMap[req.Username]; ok {
			delete(deesUserStatMap, req.Username)
		}
		deesUserStatMaplck.Unlock()
	*/
	resp.Ret = 0

	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("LoginOut recv req end, use time: %v ms", (endTime-beginTime)/1e6))

}

func Login(response http.ResponseWriter, request *http.Request) {
	beginTime := time.Now().UnixNano()
	logs.Info("Login recv req begin", time.Now().Format("2006-01-02 15:04:05"))

	var req LoginReq
	var resp LoginResp
	var err error
	var uuid string

	reqdata, _ := ioutil.ReadAll(request.Body)
	json.Unmarshal(reqdata, &req)

	userinfo, err := getUserInfo(req.Username)
	fmt.Println(userinfo)
	if err != nil {
		resp.Ret = -1
		logs.Error("login::getUserInfo err:", err.Error())
		goto exit
	}

	deesUserStatMaplck.RLock()
	if v, ok := deesUserStatMap[req.Username]; ok {
		deesUserStatMaplck.RUnlock()

		v.RLock()
		uuid = v.Uuid

		if time.Now().Before(v.ExpireTime) {
			refreshTime := v.RefreshTime
			v.RUnlock()

			if int64(time.Since(refreshTime).Seconds()) <= refreshSpan {
				resp.Ret = 1
				goto exit
			}

			//online user nojust refresh
			//...
		} else {
			v.RUnlock()
		}

		uuid = getUuid()

	} else {
		deesUserStatMaplck.RUnlock()

		uuid = getUuid()
	}

	if req.Password != userinfo.Password {
		resp.Ret = -1
		goto exit
	}

exit:

	if resp.Ret == 0 {

		resp.RoleId = userinfo.RoleId
		resp.DId = userinfo.DepartmentId

		//refresh user state
		var v DeesUserStat
		v.Username = req.Username
		v.RefreshTime = time.Now()
		v.ExpireTime = time.Now().Add(ExpireTimeSpan)
		v.Uuid = uuid
		v.UserRole = userinfo.RoleId

		resp.Uuid = uuid

		deesUserStatMaplck.Lock()
		deesUserStatMap[req.Username] = &v
		deesUserStatMaplck.Unlock()
	}

	resp.Url = "main.html"
	jdata, _ := json.Marshal(resp)
	fmt.Fprintf(response, string(jdata))

	endTime := time.Now().UnixNano()
	logs.Info(fmt.Sprintf("Login recv req end, use time: %v ms", (endTime-beginTime)/1e6))
}

// 跨域测试
func test(response http.ResponseWriter, request *http.Request) {
	fmt.Println("recv test req")

	response.Header().Set("Access-Control-Allow-Origin", "*")             //允许访问所有域
	response.Header().Add("Access-Control-Allow-Headers", "Content-Type") //header的类型
	response.Header().Set("content-type", "application/json")             //返回数据格式是json

	fmt.Fprintf(response, "3")

}
