Fosi Fossil Service
Small teams. Open source. Built on Fossil.

IaC / SwiftFlow

High-performance WMS with wave picking, smart routing, and real-time inventory visibility.

Public | Owner: IaC | Default branch: trunk | Last update: 2026-10-23 14:37

Artifact b08e1014dd30f913aa079ab3d01e8d2087456cb51d8f341dc57ec9c193a8aa00:


import gleam/dynamic/decode
import gleam/json
import gleam/result
import ql361api/client.{type Client}
import ql361api/json_codec
import ql361api/models.{type ApiError, type GoodsItem, type Page, GoodsItem, JsonError, Page}

pub const list_goods_method = "cc.erp.bll.bas.baseinfomanager.getlist"

pub const page_size = 100

pub fn fetch_goods_page(
  client client: Client,
  page page: Int,
  page_size page_size: Int,
  modified_from modified_from: String,
  modified_to modified_to: String,
) -> Result(Page(GoodsItem), ApiError) {
  let condition = [
    #("bastype", json.string("goods")),
    #("showtree", json.bool(False)),
    #("showline", json.bool(True)),
    #("showstop", json.bool(True)),
    #("showstopstatus", json.int(2)),
    #("keywords", json.string("")),
    #("pnode", json.string("00000")),
    #("root", json.string("00000")),
    #("level", json.int(0)),
    #("isusecoupon", json.int(-1)),
    #("isstandard", json.int(-1)),
    #("goodsclass", json.int(-1)),
    #("goodstype", json.int(-1)),
  ]

  let condition = case modified_from {
    "" -> condition
    from -> [
      #("modifytimebegin", json.string(from)),
      #("modifytimeend", json.string(modified_to)),
      ..condition
    ]
  }

  let payload =
    json.object([
      #(
        "reportparam",
        json.object([
          #("pagerow", json.int(page_size)),
          #("pagenumber", json.int(page)),
          #("parid", json.int(0)),
          #("displaytype", json.string("list")),
          #("orders", json.string("")),
        ]),
      ),
      #("conditionparam", json.object(condition)),
    ])
    |> json.to_string

  use raw_json <- result.try(
    client.post_rpc(client, list_goods_method, "erp", payload),
  )
  parse_goods_body(raw_json)
}

pub fn parse_goods_body(body: String) -> Result(Page(GoodsItem), ApiError) {
  let item_decoder = {
    use id <- decode.field("gid", json_codec.int())
    use code <- decode.optional_field("code", "", decode.string)
    use name <- decode.optional_field("fullname", "", decode.string)
    use barcode <- decode.optional_field("commonunitbarcode", "", decode.string)
    use unit <- decode.optional_field("ufullname", "", decode.string)
    use spec <- decode.optional_field("spec", "", decode.string)
    use shelf_life <- decode.optional_field("strshelflife", "", decode.string)
    use shelf_life_days <- decode.optional_field("shelflife", 0, json_codec.int())
    use position_code <- decode.optional_field("gpcode", "", decode.string)
    use flag <- decode.optional_field("flag", 0, json_codec.int())
    use is_parent <- decode.optional_field("isparent", 0, json_codec.int())
    use modified_at <- decode.optional_field("modifytime", "", decode.string)
    use created_at <- decode.optional_field("createtime", "", decode.string)
    decode.success(GoodsItem(
      id: id,
      code: code,
      name: name,
      barcode: barcode,
      unit: unit,
      spec: spec,
      shelf_life: shelf_life,
      shelf_life_days: shelf_life_days,
      position_code: position_code,
      disabled: flag != 0,
      is_category: is_parent != 0,
      modified_at: modified_at,
      created_at: created_at,
    ))
  }

  let data_decoder = {
    use items <- decode.field("datasource", decode.list(of: item_decoder))
    use total <- decode.optional_field("rowcount", 0, json_codec.int())
    decode.success(Page(items: items, total: total))
  }

  let wrapper_decoder = {
    use data <- decode.field("data", data_decoder)
    decode.success(data)
  }

  case json.parse(body, wrapper_decoder) {
    Ok(page) -> Ok(page)
    Error(_) -> Error(JsonError("商品列表响应无法解析"))
  }
}

Clone

You can clone this repository with the following command:

fossil clone https://fosi.dev/IaC/SwiftFlow

Contribute

The best way to contribute is through e-mail. See the project documentation for more details.