2026-06-14 11:33:31 +08:00
|
|
|
package model
|
|
|
|
|
|
2026-07-04 02:34:20 +00:00
|
|
|
import (
|
|
|
|
|
"database/sql/driver"
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"fmt"
|
|
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type ProductYarnRatio struct {
|
|
|
|
|
YarnName string `json:"yarn_name"`
|
|
|
|
|
YarnType string `json:"yarn_type"`
|
|
|
|
|
Ratio float64 `json:"ratio"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type JSONStringSlice []string
|
|
|
|
|
|
|
|
|
|
func (s *JSONStringSlice) Scan(src interface{}) error {
|
|
|
|
|
if src == nil {
|
|
|
|
|
*s = nil
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
var b []byte
|
|
|
|
|
switch v := src.(type) {
|
|
|
|
|
case []byte:
|
|
|
|
|
b = v
|
|
|
|
|
case string:
|
|
|
|
|
b = []byte(v)
|
|
|
|
|
default:
|
|
|
|
|
return fmt.Errorf("unsupported type: %T", src)
|
|
|
|
|
}
|
|
|
|
|
return json.Unmarshal(b, s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s JSONStringSlice) Value() (driver.Value, error) {
|
|
|
|
|
if s == nil {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
b, err := json.Marshal(s)
|
|
|
|
|
return string(b), err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type JSONYarnRatios []ProductYarnRatio
|
|
|
|
|
|
|
|
|
|
func (r *JSONYarnRatios) Scan(src interface{}) error {
|
|
|
|
|
if src == nil {
|
|
|
|
|
*r = nil
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
var b []byte
|
|
|
|
|
switch v := src.(type) {
|
|
|
|
|
case []byte:
|
|
|
|
|
b = v
|
|
|
|
|
case string:
|
|
|
|
|
b = []byte(v)
|
|
|
|
|
default:
|
|
|
|
|
return fmt.Errorf("unsupported type: %T", src)
|
|
|
|
|
}
|
|
|
|
|
return json.Unmarshal(b, r)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (r JSONYarnRatios) Value() (driver.Value, error) {
|
|
|
|
|
if r == nil {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
b, err := json.Marshal(r)
|
|
|
|
|
return string(b), err
|
|
|
|
|
}
|
2026-06-14 11:33:31 +08:00
|
|
|
|
|
|
|
|
type Product struct {
|
2026-07-04 02:34:20 +00:00
|
|
|
ID string `json:"id" db:"id"`
|
|
|
|
|
CompanyID string `json:"company_id" db:"company_id"`
|
|
|
|
|
ProductName string `json:"product_name" db:"product_name"`
|
|
|
|
|
FabricCode string `json:"fabric_code" db:"fabric_code"`
|
|
|
|
|
Color string `json:"color" db:"color"`
|
|
|
|
|
ColorCode string `json:"color_code" db:"color_code"`
|
|
|
|
|
Weight float64 `json:"weight" db:"weight"`
|
|
|
|
|
WarpWeight *float64 `json:"warp_weight,omitempty" db:"warp_weight"`
|
|
|
|
|
WeftWeight *float64 `json:"weft_weight,omitempty" db:"weft_weight"`
|
|
|
|
|
TotalWeight *float64 `json:"total_weight,omitempty" db:"total_weight"`
|
|
|
|
|
YarnUsagePerMeter float64 `json:"yarn_usage_per_meter" db:"yarn_usage_per_meter"`
|
|
|
|
|
ProductionPrice *float64 `json:"production_price,omitempty" db:"production_price"`
|
|
|
|
|
TotalStock float64 `json:"total_stock" db:"total_stock"`
|
|
|
|
|
RawFabricMeters float64 `json:"raw_fabric_meters" db:"raw_fabric_meters"`
|
|
|
|
|
RawFabricRolls int `json:"raw_fabric_rolls" db:"raw_fabric_rolls"`
|
|
|
|
|
ImageURL *string `json:"image_url,omitempty" db:"image_url"`
|
|
|
|
|
ProductType string `json:"product_type" db:"product_type"`
|
|
|
|
|
YarnTypes JSONStringSlice `json:"yarn_types,omitempty" db:"yarn_types"`
|
|
|
|
|
YarnRatios JSONYarnRatios `json:"yarn_ratios,omitempty" db:"yarn_ratios"`
|
|
|
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
|
|
|
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
2026-06-14 11:33:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ProductInventoryRecord struct {
|
|
|
|
|
ID string `json:"id" db:"id"`
|
|
|
|
|
ProductID string `json:"product_id" db:"product_id"`
|
|
|
|
|
BatchNo string `json:"batch_no" db:"batch_no"`
|
|
|
|
|
Rolls int `json:"rolls" db:"rolls"`
|
|
|
|
|
Meters float64 `json:"meters" db:"meters"`
|
|
|
|
|
Notes *string `json:"notes,omitempty" db:"notes"`
|
|
|
|
|
OperatorID *string `json:"operator_id,omitempty" db:"operator_id"`
|
|
|
|
|
CompanyID *string `json:"company_id,omitempty" db:"company_id"`
|
|
|
|
|
WarehouseID *string `json:"warehouse_id,omitempty" db:"warehouse_id"`
|
|
|
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ProductOutboundRecord struct {
|
|
|
|
|
ID string `json:"id" db:"id"`
|
|
|
|
|
ProductID string `json:"product_id" db:"product_id"`
|
|
|
|
|
BatchNo string `json:"batch_no" db:"batch_no"`
|
|
|
|
|
Rolls int `json:"rolls" db:"rolls"`
|
|
|
|
|
Meters float64 `json:"meters" db:"meters"`
|
|
|
|
|
OutboundType string `json:"outbound_type" db:"outbound_type"`
|
|
|
|
|
Notes *string `json:"notes,omitempty" db:"notes"`
|
|
|
|
|
OperatorID *string `json:"operator_id,omitempty" db:"operator_id"`
|
|
|
|
|
CompanyID *string `json:"company_id,omitempty" db:"company_id"`
|
|
|
|
|
RecipientCompanyID *string `json:"recipient_company_id,omitempty" db:"recipient_company_id"`
|
|
|
|
|
RecipientCompanyName *string `json:"recipient_company_name,omitempty" db:"recipient_company_name"`
|
|
|
|
|
SourceBatchID *string `json:"source_batch_id,omitempty" db:"source_batch_id"`
|
|
|
|
|
WashingPlanID *string `json:"washing_plan_id,omitempty" db:"washing_plan_id"`
|
|
|
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ProductPriceHistory struct {
|
|
|
|
|
ID string `json:"id" db:"id"`
|
|
|
|
|
ProductID string `json:"product_id" db:"product_id"`
|
|
|
|
|
OldPrice *float64 `json:"old_price,omitempty" db:"old_price"`
|
|
|
|
|
NewPrice float64 `json:"new_price" db:"new_price"`
|
|
|
|
|
Reason *string `json:"reason,omitempty" db:"reason"`
|
|
|
|
|
ChangedBy *string `json:"changed_by,omitempty" db:"changed_by"`
|
|
|
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
|
|
|
}
|