3

当我在 commercetools API 上从购物车创建订单时(记录在此: http: //dev.commercetools.com/http-api-projects-orders.html#create-order-from-cart),我必须设置orderNumber 手动。数字很​​重要,因为商务工具平台的内部 ID 是长 UUID,在履行和支付过程中不实用。

可靠地生成顺序递增且唯一的订单号的最佳方法是什么(在这种情况下没有外部系统生成它们,不必为这种情况引入一个会很好)?

4

3 回答 3

3

执行此操作的一个好方法是使用自定义对象来包含您的顺序订单号。在创建订单时,您可以尝试更新此自定义对象http://dev.commercetools.com/http-api-projects-custom-objects.html#create-or-update-a-customobject。如果更新成功,您可以使用该数字作为 orderNumber,如果失败,增加并重试。

回顾一下:当您要将购物车变成订单时,请从您的自定义对象中获取当前订单号。然后,尝试增加它。如果成功,则使用该编号作为订单的 orderNumber。

于 2017-12-14T14:41:50.177 回答
0

正如@svaj 所说,您可以使用自定义对象获取客户或订单的序列号。由于版本,自定义对象将充当锁,避免两个并发请求可能获得相同的数字。如果出现并发错误,您还可以使用递归重试。

这是 ES6 中的一个工作示例(同样适用于订单号)。您唯一需要设置的是序列的名称,它将成为自定义对象的容器和键(例如“ customerSequence ”)。

setCustomerNumber({ sequence, value, version }) {
  return customObjectsService
    .save({
      container: sequence,
      key: sequence,
      value,
      version,
    })
    .then(customObject => customObject.value);
},

getCustomerNumber(sequence) {
  return customObjectsService
    .find({ where: `key="${sequence}"` })
    .then(({ results }) => (results.length ? results[0] : { value: 0 }))
    .then(lastValue => {
      return this.setCustomerNumber({
        sequence,
        value: lastValue.value + 1,
        version: lastValue.version,
      }).catch(() => this.getCustomerNumber(sequence)); // We request a new one on error
    });
},

在这里你有前面代码的单元测试

describe('when getting the next customer number', () => {
  const sequence = 'customersSequence';

  describe('when existing previous customer number', () => {
    const oldCustomerNumber = 1;
    const newCustomerNumber = oldCustomerNumber + 1;
    const version = 1;

    beforeEach(() => {
      spyOn(customObjectsService, 'find').and.returnValue(
        Promise.resolve({
          results: [
            {
              value: oldCustomerNumber,
              version,
            },
          ],
          total: 1,
        }),
      );
      spyOn(customersService, 'setCustomerNumber').and.returnValue(
        Promise.resolve(newCustomerNumber),
      );
    });

    it('should get a customer number equals to <previous customer number> + 1', done => {
      customersService
        .getCustomerNumber(sequence)
        .then(customerNumber => {
          expect(customObjectsService.find).toHaveBeenCalledWith({
            where: `key="${sequence}"`,
          });
          expect(customersService.setCustomerNumber).toHaveBeenCalledWith({
            sequence,
            value: newCustomerNumber,
            version,
          });
          expect(customerNumber).toBe(newCustomerNumber);
        })
        .then(done, done.fail);
    });
  });

  describe('when NOT existing previous customer number', () => {
    const newCustomerNumber = 1;

    beforeEach(() => {
      spyOn(customObjectsService, 'find').and.returnValue(
        Promise.resolve({
          results: [],
          total: 0,
        }),
      );
      spyOn(customersService, 'setCustomerNumber').and.returnValue(
        Promise.resolve(newCustomerNumber),
      );
    });

    it('should get a customer number equals to 1', done => {
      customersService
        .getCustomerNumber(sequence)
        .then(customerNumber => {
          expect(customObjectsService.find).toHaveBeenCalledWith({
            where: `key="${sequence}"`,
          });
          expect(customersService.setCustomerNumber).toHaveBeenCalledWith({
            sequence,
            value: newCustomerNumber,
            version: undefined,
          });
          expect(customerNumber).toBe(newCustomerNumber);
        })
        .then(done, done.fail);
    });
  });
});
于 2017-12-14T21:51:44.753 回答
-1

如果您使用 Java 编写集成(使用 CommerceTools Java SDK),那么您可以使用 java.util.concurrent.atomic.AtomicLong。这是一个在 CommerceTools 中创建订单后将订单号设置为订单的示例。

首先像这样在你的类中定义一个静态变量

private static final AtomicLong sequence = new AtomicLong(System.currentTimeMillis() / 1000);

然后可以在这样的方法中使用它

public void setOrderNumber(Order order) throws ShoppingCartException {
    long orderNumber = sequence.incrementAndGet();

    // command to set order number
    SetOrderNumber action = SetOrderNumber.of(String.valueOf(orderNumber));
    OrderUpdateCommand command = OrderUpdateCommand.of(order, action);

    // execute the command
    try {
        // some code to get a Java SDK client
        BlockingSphereClient client = ...;
        this.order = client.executeBlocking(command);
    } catch (Exception e) {
        // log/throw exeception
    }
}
于 2018-08-04T02:41:51.667 回答