I am working on a use case of "Purchase Order" wherein there will be multiple Products listed/ordered under one Purchase Order(PO) by a buyer.

1 PO : N Products

struct Product{
    bytes32 product_code;
    bytes32 product_name;
    uint quantity;
    uint unit_price;  

struct PurchaseOrder{
    bytes32 po_number;
    string po_creation_date;
    // next line is the question
    mapping( bytes32 => Product[]) products;  // or Products[] products

//mapping to store Purchase Orders
mapping(uint => PurchaseOrder) purchaseOrders;

uint po_number = 100;

function createPO(string memory po_creation_date,bytes32[] memory products) public returns(bool){

    require(msg.sender == buyerAddress);
    purchaseOrders[po_number].po_creation_date = po_creation_date;

    for (uint256 i = 0; i < products.length; i++) {
        bytes32[] memory arr=new bytes32[](products.length);
        arr[0]= products[i];
        //bytes32 product_code = arr[0].product_code;
        purchaseOrders[po_number].products[product_code].push(Product(arr)); // how do i need to proceed ??


parameter bytes32[] memory products comes from nodejs app and as a array of objects.

I must also be able to retrieve all the products under a PO for particular buyer.

Improve this code or if this code does not make sense and can be rewritten to achieve same, please feel free to do so or guide me.


  • There's no question here! Commented May 29, 2019 at 14:55
  • title says it all.. still, in createPO function i'm getting "products" as array of Objects. Now, how do i set it in products array available in PurchaseOrder struct also in turn set values from products into Product struct. 1 purchaseOrder holds multiple products/line item @goodvibration
    – Hem M
    Commented May 29, 2019 at 18:15

2 Answers 2


Improve this code or if this code does not make sense and can be rewritten to achieve same, please feel free to do so or guide me.


  1. This will not scale to larger Purchase Orders because it contains an O(n) loop. https://blog.b9lab.com/getting-loopy-with-solidity-1d51794622ad
  2. The data structure doesn't map to my idea of a PO which would be one-to-many Header to Line Items, and one-to-one Line Items to Products.
  3. A mapping alone is not iterable, so that means there would be no way to enumerate the Products in the Purchase Order - probably not acceptable.


  1. Create data structure with PO Header => LineItem (with qty, other attributes) => Product.
  2. Amortize the work with smaller O(1) steps, e.g. create header, append line item.
  3. Push the iteration of line items outside the contract. This way, a client can initiate many small operations, as needed, and never run out of gas.

If you want to offer an append-only process for adding Line-Items, a simple array will work. If you want CRUD operations before commitment, use Mapped Structs with Index and Delete: Are there well-solved and simple storage patterns for Solidity?

By "commitment" I mean finalized PO should not be altered but during the creating process you have multiple steps, so you'll probably want a "finalize" function to conclude the editing of the draft PO and carry on with the finalized document.

Hope it helps.

  • Thanks a lot for insight on issues and to be taken care of things. I didn't get this point clearly "PO Header => LineItem (with qty, other attributes) => Product" . can you provide an example as such ? @Rob Hitchens
    – Hem M
    Commented May 29, 2019 at 18:17
  • You seem to be saying a PO contains a set of Products. In practice, they tend to contain a set of line items, and each line item has a product, how many, and possibly other details. Like 2 hamburgers, 1 nachos and 3 beers is an order. LineItem{ qty:n, product: id}. The order has header info and n Line Items. Don't let me over-complicate it if the quantity is always 1 in your case. Commented May 29, 2019 at 23:22

It looks like this example may fit for you:

pragma solidity ^0.4.18;

contract StructArrayInit {
  event OnCreateRoom(address indexed _from, uint256 _value);
  struct Room {
    address[] players;       
    uint256 whosTurnId;
    uint256 roomState;
  Room[] public rooms;

  function createRoom() public {
      Room memory room = Room(new address[](0), 0, 0);

      OnCreateRoom(msg.sender, 0);
  function getRoomPlayers(uint i) public view returns (address[]){
      return rooms[i].players;

This example addresses the issue of not having a way to iterate through a map.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.