OMSĐơn hàng

Tạo đơn hàng

Tạo đơn hàng mới từ nội bộ hệ thống

Tạo đơn hàng an toàn với flow checkout của API /v1/customercarts

Nếu muốn tạo đơn hàng một cách an toàn, tự động áp dụng cơ chế khuyến mãi cho chi tiết, cho giỏ hàng...thì nên gọi api checkout của customercarts (/v1/customercarts/checkout). Đây là API được sử dụng bởi màn hình POS để tạo đơn hàng.

Tạo đơn hàng mới

Để gọi API này, bạn phải tính toán trước toàn bộ thông tin đơn hàng. Bao gồm: chi tiết đơn hàng, kết quả tính toán của khuyến mãi, giá bán...API này hiện được gọi nội bộ từ flow checkout của customercarts.

Endpoint

POST /v1/orders

Headers

TênBắt buộcMô tả
AuthorizationCó<JWT> của người dùng có quyền tạo đơn (order.add) tại cửa hàng store_id
Content-TypeCóapplication/json
Idempotency-KeyKhôngKhoá chống tạo trùng. Nếu không truyền, hệ thống tự sinh khoá từ nội dung payload: gửi lại cùng một payload trong vài giây sau khi tạo thành công sẽ bị từ chối với HTTP 409

Request Payload

JSON Object Payload:

{
  "company_id": 10311,
  "creator_id": 1,
  "customer_id": 101,
  "source": 1,
  "source_name": "",
  "external_id": "",
  "uuid": "3b733736-2278-42d1-8c2f-31d5cef7cd81",
  "store_id": 32,
  "pickup_store_id": 0,
  "billing_full_name": "Hoàng Văn Hải",
  "billing_phone": "0909876543",
  "billing_email": "",
  "billing_address": "15 Trần Phú",
  "billing_region_id": 88831,
  "billing_sub_region_id": 88810507,
  "billing_sub_sub_region_id": 88811332,
  "shipping_type": 3,
  "shipping_address_id": 0,
  "shipping_full_name": "Hoàng Văn Hải",
  "shipping_phone": "0909876543",
  "shipping_email": "",
  "shipping_address": "15 Trần Phú",
  "shipping_region_id": 88831,
  "shipping_sub_region_id": 88810507,
  "shipping_sub_sub_region_id": 88811332,
  "shipping_address_line_2": "",
  "shipping_instruction": "",
  "shipping_legacy_province_name": "",
  "shipping_legacy_district_name": "",
  "shipping_legacy_ward_name": "",
  "shipping_carrier_id": 23,
  "warehouse_id": 33,
  "payment_method": 11,
  "payment_status": 1,
  "note": "",
  "promotion_coupon": "",
  "tax_name": "",
  "tax_is_company": 0,
  "tax_code": "",
  "tax_address": "",
  "tax_email": "",
  "price_sell": 1963600,
  "price_shipping": 20000,
  "price_discount_order": 98180,
  "price_discount_shipping": 12000,
  "price_discount_coupon": 0,
  "price_discount": 110180,
  "price_final": 1873420,
  "ip_address": "203.0.113.10",
  "date_created": 0,
  "details": [
    {
      "row_identifier": "486_948_1000_0",
      "product_id": 486,
      "product_variant_id": 948,
      "uom_id": 1000,
      "uom_name": "Cái",
      "uom_factor": 1,
      "uom_quantity": 3,
      "uom_unit_price": 479200,
      "uom_unit_price_original": 599000,
      "selected_options": null,
      "type": 1,
      "sku": "2397540229784",
      "item_type": 1,
      "item_name": "PUMA - Áo khoác nam thể thao cổ trụ phối zip Fit Woven Half Zip Training 522129",
      "item_serial_number": "",
      "item_weight": 400,
      "customize_required": 0,
      "customize_description": "",
      "file_id_list": [],
      "bundle_identifier": "",
      "bundle_promotion_id": 0,
      "bundle_promotion_product_id": 0,
      "bundle_promotion_multiplier": 0,
      "bundle_index": 0,
      "bundle_allocation_rule": "",
      "bundle_discount_allocated": 0,
      "bundle_promotion_name": "",
      "bundle_promotion_type": 0
    }
  ],
  "promotionengine": {
    "order_promotion_decision": {
      "applied": [],
      "rejected": [],
      "eligible": []
    },
    "shipping_promotion_decision": {
      "applied": [],
      "rejected": [],
      "eligible": []
    },
    "coupon_promotion_decision": {
      "applied": [],
      "rejected": [],
      "eligible": []
    }
  },
  "price_policy_id": 1,
  "tag": "",
  "file_id_list": [],
  "weight": 2700,
  "quantity": 7
}

Các trường chính

TênKiểuBắt buộcMô tả
company_idintCóID công ty, phải trùng với công ty của phiên đăng nhập
creator_idintCóID người dùng tạo đơn (người dùng của phiên đăng nhập)
store_idintCóID cửa hàng tạo đơn; tài khoản phải có quyền order.add tại cửa hàng này
shipping_typeintCóLoại hình vận chuyển (xem constant SHIPPING_TYPE_*)
pickup_store_idintKhi shipping_type = 1ID cửa hàng khách đến lấy hàng
shipping_full_name, shipping_phone, shipping_address, shipping_region_idKhi shipping_type = 3Thông tin người nhận khi giao hàng tận nơi
detailsarrayCóDanh sách dòng sản phẩm (ít nhất 1 dòng). Mỗi dòng cần product_variant_id, uom_id, uom_quantity, uom_unit_price...
uuidstringKhôngUUID của đơn. Nếu bỏ trống hệ thống tự sinh. Không được trùng với đơn chưa hủy khác của công ty
customer_idintKhôngID khách hàng. Nếu bỏ trống nhưng có billing_phone, hệ thống tìm khách theo số điện thoại hoặc tự tạo khách mới
source, source_name, external_idKhôngNguồn đơn và mã đơn ở hệ thống bên ngoài (xem constant)
price_*intKhôngCác khoản tiền của đơn đã được tính sẵn phía client (price_sell, price_shipping, price_discount_*, price_discount, price_handling, price_tax, price_final, price_deposit)
promotion_id, promotion_coupon, promotions, coupons, promotionengineKhôngThông tin khuyến mãi / coupon đã áp dụng
payment_method, payment_statusintKhôngPhương thức và trạng thái thanh toán. Với COD (11) đơn mới luôn ở PAYMENT_STATUS_PENDING
fulfillment_status, shipping_statusintKhôngTrạng thái fulfillment / vận chuyển ban đầu
aff_click_tokenstringKhôngToken click affiliate (lấy khi khách mở link cộng tác viên). Có token thì hệ thống ghi nhận hoa hồng cho cộng tác viên của link
aff_codestringKhôngMã giới thiệu khách nhập khi đặt hàng (dùng khi không có aff_click_token). Mã phải đang bật và thuộc cộng tác viên đang hoạt động
redeem_pointsintKhôngSố điểm tích luỹ khách dùng
date_createdintKhôngThời gian tạo đơn (UNIX timestamp), mặc định là thời điểm gọi API

Workflow & Logic

  • Trạng thái đơn (status) do hệ thống xác định, không lấy từ payload:
    • shipping_type = 9 (SHIPPING_TYPE_INSTORE): đơn được đánh dấu đã giao và hoàn tất fulfillment; nếu payment_status = 9 (COMPLETED) thì status = STATUS_COMPLETE, ngược lại là STATUS_CONFIRMED_CUSTOMER.
    • shipping_type = 1 hoặc 3: đơn do nhân viên tạo (creator_id > 0) hoặc có external_id sẽ ở STATUS_CONFIRMED_CUSTOMER, còn lại là STATUS_NEW.
  • tax_invoice_type được gán tự động: TAX_INVOICE_TYPE_API nếu công ty đã cấu hình đầy đủ nhà cung cấp hóa đơn điện tử, ngược lại TAX_INVOICE_TYPE_MANUAL.
  • Nếu không thêm được dòng chi tiết nào, đơn vừa tạo sẽ bị hủy với cancel_reason = CANCEL_REASON_SYSTEM_ERROR và API trả lỗi 422.
  • Sau khi tạo thành công, các bước hậu xử lý (cập nhật khách hàng, điểm tích luỹ, coupon, webhook...) chạy bất đồng bộ.

Response Schema

HTTP 201 - JSON Object

Xem Order Object Schema

Error Codes

HTTPCodeMô tả
401error_jwt_is_requiredThiếu token xác thực
409error_idempotent_check_duplicate_foundYêu cầu trùng lặp (cùng Idempotency-Key hoặc cùng payload) vừa được xử lý
422error_company_id_requiredThiếu company_id
422error_company_id_notfoundcompany_id không thuộc phiên đăng nhập
422error_user_id_notfoundcreator_id không hợp lệ
422error_not_permissionKhông có quyền tạo đơn hàng tại cửa hàng này
422error_order_with_uuid_existed(<uuid>)UUID đã tồn tại trong hệ thống
422error_shipping_type_requiredLoại vận chuyển không hợp lệ
422error_pickup_store_requiredCửa hàng nhận hàng bắt buộc cho loại pickup
422error_pickup_store_not_existCửa hàng nhận hàng không tồn tại
422error_shift_not_existCa làm việc không tồn tại
422error_warehouse_invalidKho hàng không hợp lệ
422error_order_detail_not_foundKhông có chi tiết sản phẩm trong đơn hàng
422error_setting_fetch_errorLỗi lấy cấu hình công ty
422error_customer_id_not_foundKhách hàng không tồn tại
422error_create_customer_failedKhông tạo được khách hàng mới từ thông tin người đặt
422error_shipping_full_name_requiredTên người nhận bắt buộc cho giao hàng
422error_shipping_phone_requiredSố điện thoại người nhận bắt buộc cho giao hàng
422error_shipping_address_requiredĐịa chỉ giao hàng bắt buộc
422error_shipping_region_requiredVùng giao hàng bắt buộc
422error_shipping_region_id_not_existVùng giao hàng không tồn tại
422error_shipping_sub_region_id_not_existQuận/huyện giao hàng không tồn tại
422error_shipping_sub_sub_region_id_not_existPhường/xã giao hàng không tồn tại
422error_billing_region_id_not_existVùng thanh toán không tồn tại
422error_billing_sub_region_id_not_existQuận/huyện thanh toán không tồn tại
422error_billing_sub_sub_region_id_not_existPhường/xã thanh toán không tồn tại
422error_add_detail_order_invalid_variant_id_<product_variant_id>Biến thể sản phẩm không tồn tại hoặc không thuộc công ty
422error_add_detail_order_invalid_selection_<product_variant_id>Lựa chọn trong combo trỏ tới sản phẩm không thuộc công ty
422error_add_detail_order_sku_<product_variant_id>Không lưu được dòng chi tiết sản phẩm

On this page