Пример #1
0
class Customer_admin(MultiDBModelAdmin):
    model = Customer
    raw_id_fields = ("owner",)
    save_on_top = True
    fieldsets = (
        (None, {"fields": ("name", "description", "owner")}),
        (
            _("advanced"),
            {
                "fields": ["category", "subcategory"]
                + [a[0] for a in getAttributes(Location) if a[3]],
                "classes": ("collapse",),
            },
        ),
    )
    tabs = [
        {
            "name": "edit",
            "label": _("edit"),
            "view": "admin:input_customer_change",
            "permissions": "input.change_customer",
        },
        {
            "name": "messages",
            "label": _("messages"),
            "view": "admin:input_customer_comment",
        },
    ]
Пример #2
0
class Supplier_admin(MultiDBModelAdmin):
    model = Supplier
    raw_id_fields = ("available", "owner")
    save_on_top = True
    fieldsets = (
        (None, {"fields": ("name", "description")}),
        (
            _("advanced"),
            {
                "fields": ["category", "subcategory"]
                + [a[0] for a in getAttributes(Supplier) if a[3]],
                "classes": ("collapse",),
            },
        ),
    )
    tabs = [
        {
            "name": "edit",
            "label": _("edit"),
            "view": "admin:input_supplier_change",
            "permissions": "input.change_supplier",
        },
        {
            "name": "purchaseorders",
            "label": _("purchase orders"),
            "view": "input_purchaseorder_by_supplier",
        },
        {
            "name": "messages",
            "label": _("messages"),
            "view": "admin:input_supplier_comment",
        },
    ]
Пример #3
0
 def loadItems(self):
   print('Importing items...')
   cnt = 0
   starttime = time()
   attrs = [ f[0] for f in getAttributes(Item) ]
   if attrs:
     attrsql = ', %s' % ', '.join(attrs)
   else:
     attrsql = ''
   self.cursor.execute('''
     SELECT
       name, description, operation_id, owner_id,
       price, category, subcategory, source %s
     FROM item %s
     ''' % (attrsql, self.filter_where))
   for i in self.cursor.fetchall():
     cnt += 1
     try:
       x = frepple.item(name=i[0], description=i[1], category=i[5], subcategory=i[6], source=i[7])
       if i[2]:
         x.operation = frepple.operation(name=i[2])
       if i[3]:
         x.owner = frepple.item(name=i[3])
       if i[4]:
         x.price = i[4]
       idx = 8
       for a in attrs:
         setattr(x, a, i[idx])
         idx += 1
     except Exception as e:
       print("Error:", e)
   print('Loaded %d items in %.2f seconds' % (cnt, time() - starttime))
Пример #4
0
class Calendar_admin(MultiDBModelAdmin):
    model = Calendar
    save_on_top = True
    inlines = [CalendarBucket_inline]
    fieldsets = (
        (None, {"fields": ("name", "defaultvalue")}),
        (
            _("advanced"),
            {
                "fields": ["description", "category", "subcategory"]
                + [a[0] for a in getAttributes(Calendar) if a[3]],
                "classes": ("collapse",),
            },
        ),
    )
    tabs = [
        {
            "name": "edit",
            "label": _("edit"),
            "view": "admin:input_calendar_change",
            "permissions": "input.change_calendar",
        },
        {
            "name": "messages",
            "label": _("messages"),
            "view": "admin:input_calendar_comment",
        },
    ]
Пример #5
0
class ResourceSkill_admin(MultiDBModelAdmin):
    model = ResourceSkill
    raw_id_fields = ("resource", "skill")
    save_on_top = True
    fieldsets = (
        (None, {"fields": ("resource", "skill")}),
        (
            _("advanced"),
            {
                "fields": ["priority", "effective_start", "effective_end"]
                + [a[0] for a in getAttributes(ResourceSkill) if a[3]],
                "classes": ("collapse",),
            },
        ),
    )
    tabs = [
        {
            "name": "edit",
            "label": _("edit"),
            "view": "admin:input_resourceskill_change",
            "permissions": "input.change_resoureskill",
        },
        {
            "name": "messages",
            "label": _("messages"),
            "view": "admin:input_resourceskill_comment",
        },
    ]
Пример #6
0
 def loadItems(self):
   print('Importing items...')
   cnt = 0
   starttime = time()
   attrs = [ f[0] for f in getAttributes(Item) ]
   if attrs:
     attrsql = ', %s' % ', '.join(attrs)
   else:
     attrsql = ''
   self.cursor.execute('''
     SELECT
       name, description, owner_id,
       price, category, subcategory, source %s
     FROM item %s
     ''' % (attrsql, self.filter_where))
   for i in self.cursor.fetchall():
     cnt += 1
     try:
       x = frepple.item(name=i[0], description=i[1], category=i[4], subcategory=i[5], source=i[6])
       if i[2]:
         x.owner = frepple.item(name=i[2])
       if i[3]:
         x.price = i[3]
       idx = 7
       for a in attrs:
         setattr(x, a, i[idx])
         idx += 1
     except Exception as e:
       print("Error:", e)
   print('Loaded %d items in %.2f seconds' % (cnt, time() - starttime))
Пример #7
0
class Demand_admin(MultiDBModelAdmin):
    model = Demand
    raw_id_fields = ("customer", "item", "operation", "owner")
    fieldsets = (
        (
            None,
            {
                "fields": (
                    "name",
                    "item",
                    "location",
                    "customer",
                    "due",
                    "quantity",
                    "priority",
                    "status",
                )
            },
        ),
        (
            _("advanced"),
            {
                "fields": [
                    "description",
                    "category",
                    "subcategory",
                    "batch",
                    "operation",
                    "minshipment",
                    "maxlateness",
                ]
                + [a[0] for a in getAttributes(Demand) if a[3]],
                "classes": ("collapse",),
            },
        ),
    )
    save_on_top = True
    tabs = [
        {
            "name": "edit",
            "label": _("edit"),
            "view": "admin:input_demand_change",
            "permissions": "input.change_demand",
        },
        {"name": "supplypath", "label": _("supply path"), "view": "supplypath_demand"},
        {
            "name": "constraint",
            "label": _("why short or late?"),
            "view": "output_constraint_demand",
        },
        {"name": "plan", "label": _("plan"), "view": "output_demand_pegging"},
        {
            "name": "messages",
            "label": _("messages"),
            "view": "admin:input_demand_comment",
        },
    ]
Пример #8
0
class Item_admin(MultiDBModelAdmin):
    model = Item
    save_on_top = True
    raw_id_fields = ("owner", )
    search_fields = ("name", "description")
    fieldsets = (
        (None, {
            "fields": ("name", "description", "cost", "owner", "uom")
        }),
        (
            _("advanced"),
            {
                "fields":
                ["category", "subcategory", "type", "volume", "weight"] +
                [a[0] for a in getAttributes(Item) if a[3]],
                "classes": ("collapse", ),
            },
        ),
    )
    tabs = [
        {
            "name": "edit",
            "label": _("edit"),
            "view": "admin:input_item_change",
            "permissions": "input.change_item",
        },
        {
            "name": "supplypath",
            "label": _("supply path"),
            "view": "supplypath_item"
        },
        {
            "name": "whereused",
            "label": _("where used"),
            "view": "whereused_item"
        },
        {
            "name": "plan",
            "label": _("plan"),
            "view": "output_demand_plandetail"
        },
        {
            "name": "inventory",
            "label": _("inventory"),
            "view": "output_buffer_plandetail_by_item",
        },
        {
            "name": "inventorydetail",
            "label": _("inventory detail"),
            "view": "input_operationplanmaterial_plandetail_by_item",
        },
        {
            "name": "messages",
            "label": _("messages"),
            "view": "admin:input_item_comment",
        },
    ]
Пример #9
0
class Location_admin(MultiDBModelAdmin):
    model = Location
    raw_id_fields = ("available", "owner")
    save_on_top = True
    fieldsets = (
        (None, {
            "fields": ("name", "owner")
        }),
        (
            _("Advanced"),
            {
                "fields":
                ["description", "category", "subcategory", "available"] +
                [a[0] for a in getAttributes(Location) if a[3]],
                "classes": ("collapse", ),
            },
        ),
    )
    tabs = [
        {
            "name": "edit",
            "label": _("edit"),
            "view": "admin:input_location_change",
            "permissions": "input.change_location",
        },
        {
            "name": "inboundorders",
            "label": _("inbound distribution"),
            "view": "input_distributionorder_in_by_location",
        },
        {
            "name": "outboundorders",
            "label": _("outbound distribution"),
            "view": "input_distributionorder_out_by_location",
        },
        {
            "name": "manufacturingorders",
            "label": _("manufacturing orders"),
            "view": "input_manufacturingorder_by_location",
        },
        {
            "name": "purchaseorders",
            "label": _("purchase orders"),
            "view": "input_purchaseorder_by_location",
        },
        {
            "name": "messages",
            "label": _("messages"),
            "view": "admin:input_location_comment",
        },
    ]
Пример #10
0
class Buffer_admin(MultiDBModelAdmin):
    model = Buffer
    raw_id_fields = ("location", "item", "minimum_calendar")
    fieldsets = (
        (None, {"fields": ("item", "location", "onhand", "minimum")}),
        (
            _("advanced"),
            {
                "fields": [
                    "batch",
                    "description",
                    "category",
                    "subcategory",
                    "type",
                    "minimum_calendar",
                    "min_interval",
                ]
                + [a[0] for a in getAttributes(Buffer) if a[3]],
                "classes": ("collapse",),
            },
        ),
    )
    save_on_top = True
    tabs = [
        {
            "name": "edit",
            "label": _("edit"),
            "view": "create_or_edit_buffer",
            "permissions": "input.change_buffer",
        },
        {"name": "supplypath", "label": _("supply path"), "view": "supplypath_buffer"},
        {"name": "whereused", "label": _("where used"), "view": "whereused_buffer"},
        {"name": "plan", "label": _("plan"), "view": "output_buffer_plandetail"},
        {
            "name": "plandetail",
            "label": _("plan detail"),
            "view": "input_operationplanmaterial_plandetail_by_buffer",
        },
        {
            "name": "constraint",
            "label": _("constrained demand"),
            "view": "output_constraint_buffer",
        },
        {
            "name": "messages",
            "label": _("messages"),
            "view": "admin:input_buffer_comment",
        },
    ]
Пример #11
0
class PurchaseOrder_admin(MultiDBModelAdmin):
    model = PurchaseOrder
    raw_id_fields = ("item", "supplier")
    save_on_top = True
    fieldsets = (
        (
            None,
            {
                "fields": [
                    "reference",
                    "item",
                    "location",
                    "supplier",
                    "quantity",
                    "ordering_date",
                    "receipt_date",
                    "status",
                    "batch",
                ]
                + [a[0] for a in getAttributes(PurchaseOrder) if a[3]]
            },
        ),
    )
    exclude = (
        "type",
        "source",
        "criticality",
        "delay",
        "operation",
        "owner",
        "color",
        "origin",
        "destination",
        "demand",
        "name",
        "due",
        "startdate",
        "enddate",
    )
    tabs = [
        {
            "name": "edit",
            "label": _("edit"),
            "view": "admin:input_purchaseorder_change",
            "permissions": "input.change_purchaseorder",
        }
    ]
Пример #12
0
def getAttributeAPIFilterDefinition(cls):
    flt = {}
    for fld in getAttributes(cls):
        if fld[2] in (
                "number",
                "integer",
                "date",
                "datetime",
                "duration",
                "time",
        ):
            flt[fld[0]] = ["exact", "in", "gt", "gte", "lt", "lte"]
        elif fld[2] == "string":
            flt[fld[0]] = ["exact", "in", "contains"]
        elif fld[2] == "boolean":
            flt[fld[0]] = [
                "exact",
            ]
    return flt
Пример #13
0
class ItemDistribution_admin(MultiDBModelAdmin):
    model = ItemDistribution
    save_on_top = True
    raw_id_fields = ("item", "resource")
    fieldsets = (
        (None, {
            "fields": ("item", "location", "origin", "leadtime")
        }),
        (
            _("advanced"),
            {
                "fields": [
                    "sizeminimum",
                    "sizemultiple",
                    "sizemaximum",
                    "batchwindow",
                    "cost",
                    "priority",
                    "fence",
                    "effective_start",
                    "effective_end",
                    "resource",
                    "resource_qty",
                ] + [a[0] for a in getAttributes(ItemDistribution) if a[3]],
                "classes": ("collapse", ),
            },
        ),
    )
    tabs = [
        {
            "name": "edit",
            "label": _("edit"),
            "view": "admin:input_itemdistribution_change",
            "permissions": "input.change_itemdistribution",
        },
        {
            "name": "messages",
            "label": _("messages"),
            "view": "admin:input_itemdistribution_comment",
        },
    ]
Пример #14
0
class OperationResource_admin(MultiDBModelAdmin):
    model = OperationResource
    raw_id_fields = ("operation", "resource", "skill")
    save_on_top = True
    exclude = ("id", )
    fieldsets = (
        (None, {
            "fields": ("operation", "resource", "quantity")
        }),
        (
            _("Advanced"),
            {
                "fields": [
                    "skill",
                    "setup",
                    "quantity_fixed",
                    "effective_start",
                    "effective_end",
                    "name",
                    "priority",
                    "search",
                ] + [a[0] for a in getAttributes(OperationResource) if a[3]],
                "classes": ("collapse", ),
            },
        ),
    )
    tabs = [
        {
            "name": "edit",
            "label": _("edit"),
            "view": "admin:input_operationresource_change",
            "permissions": "input.change_operationresource",
        },
        {
            "name": "messages",
            "label": _("messages"),
            "view": "admin:input_operationresource_comment",
        },
    ]
Пример #15
0
class OperationMaterial_admin(MultiDBModelAdmin):
    model = OperationMaterial
    raw_id_fields = ("operation", "item")
    save_on_top = True
    exclude = ("id", )
    fieldsets = (
        (None, {
            "fields": ("operation", "item", "type", "quantity")
        }),
        (
            _("advanced"),
            {
                "fields": [
                    "quantity_fixed",
                    "transferbatch",
                    "offset",
                    "effective_start",
                    "effective_end",
                    "name",
                    "priority",
                    "search",
                ] + [a[0] for a in getAttributes(OperationMaterial) if a[3]],
                "classes": ("collapse", ),
            },
        ),
    )
    tabs = [
        {
            "name": "edit",
            "label": _("edit"),
            "view": "admin:input_operationmaterial_change",
            "permissions": "input.change_operationmaterial",
        },
        {
            "name": "messages",
            "label": _("messages"),
            "view": "admin:input_operationmaterial_comment",
        },
    ]
Пример #16
0
  def run(cls, database=DEFAULT_DB_ALIAS, **kwargs):
    import frepple

    if cls.filter:
      filter_and = "and %s " % cls.filter
      filter_where = "where %s " % cls.filter
    else:
      filter_and = ""
      filter_where = ""

    with connections[database].chunked_cursor() as cursor:
      cnt = 0
      starttime = time()
      attrs = [ f[0] for f in getAttributes(Item) ]
      if attrs:
        attrsql = ', %s' % ', '.join(attrs)
      else:
        attrsql = ''
      cursor.execute('''
        SELECT
          name, description, owner_id,
          cost, category, subcategory, source %s
        FROM item %s
        ''' % (attrsql, filter_where))
      for i in cursor:
        cnt += 1
        try:
          x = frepple.item(name=i[0], description=i[1], category=i[4], subcategory=i[5], source=i[6])
          if i[2]:
            x.owner = frepple.item(name=i[2])
          if i[3]:
            x.cost = i[3]
          idx = 7
          for a in attrs:
            setattr(x, a, i[idx])
            idx += 1
        except Exception as e:
          logger.error("**** %s ****" % e)
      logger.info('Loaded %d items in %.2f seconds' % (cnt, time() - starttime))
Пример #17
0
def getAttributeAPIFields(cls):
    return tuple(i[0] for i in getAttributes(cls))
Пример #18
0
    def run(cls, cluster=-1, database=DEFAULT_DB_ALIAS, **kwargs):
        cls.attrs = [
            x for x in getAttributes(OperationPlan) if x[0] != "forecast"
        ]

        # Export operationplans to a temporary table
        cursor = connections[database].cursor()
        sql = """
            create temporary table tmp_operationplan (
                name character varying(1000),
                type character varying(5) NOT NULL,
                status character varying(20),
                quantity numeric(20,8) NOT NULL,
                startdate timestamp with time zone,
                enddate timestamp with time zone,
                criticality numeric(20,8),
                delay numeric,
                plan jsonb,
                source character varying(300),
                lastmodified timestamp with time zone NOT NULL,
                operation_id character varying(300),
                owner_id character varying(300),
                item_id character varying(300),
                destination_id character varying(300),
                origin_id character varying(300),
                location_id character varying(300),
                supplier_id character varying(300),
                demand_id character varying(300),
                due timestamp with time zone,
                color numeric(20,8),
                reference character varying(300) NOT NULL,
                batch character varying(300),
                quantity_completed numeric(20,8)
            """
        for attr in cls.attrs:
            if attr[2] == "boolean":
                sql += ", %s boolean" % attr[0]
            elif attr[2] == "duration":
                sql += ", %s interval" % attr[0]
            elif attr[2] == "integer":
                sql += ", %s integer" % attr[0]
            elif attr[2] == "number":
                sql += ", %s numeric(15,6)" % attr[0]
            elif attr[2] == "string":
                sql += ", %s character varying(300)" % attr[0]
            elif attr[2] == "time":
                sql += ", %s time without time zone" % attr[0]
            elif attr[2] == "date":
                sql += ", %s date" % attr[0]
            elif attr[2] == "datetime":
                sql += ", %s timestamp with time zone" % attr[0]
            else:
                raise Exception("Unknown attribute type %s" % attr[2])
        sql += ")"
        cursor.execute(sql)

        cursor.copy_from(
            CopyFromGenerator(
                cls.getData(
                    cls.parent.timestamp,
                    cluster=cluster,
                    accepted_status=[
                        "confirmed", "approved", "completed", "closed"
                    ],
                )),
            table="tmp_operationplan",
            size=1024,
            sep="\v",
        )

        forecastfield0 = ""
        forecastfield1 = ""

        # Merge temp table into the actual table
        sql = ("""
            update operationplan
                set name=tmp.name, type=tmp.type, status=tmp.status,
                quantity=tmp.quantity, startdate=tmp.startdate, enddate=tmp.enddate,
                criticality=tmp.criticality, delay=tmp.delay * interval '1 second',
                plan=tmp.plan, source=tmp.source,
                lastmodified=tmp.lastmodified, operation_id=tmp.operation_id, owner_id=tmp.owner_id,
                item_id=tmp.item_id, destination_id=tmp.destination_id, origin_id=tmp.origin_id,
                location_id=tmp.location_id, supplier_id=tmp.supplier_id, demand_id=tmp.demand_id,
                due=tmp.due,%s color=tmp.color, batch=tmp.batch, quantity_completed=tmp.quantity_completed
            """ % forecastfield0)
        for a in cls.attrs:
            sql += ", %s=tmp.%s" % (a[0], a[0])
        sql += """
            from tmp_operationplan as tmp
            where operationplan.reference = tmp.reference
            """
        cursor.execute(sql)

        # Make sure any deleted confirmed MO from Plan Editor gets deleted in the database
        # Only MO can currently be deleted through Plan Editor
        cursor.execute("""
            delete from operationplan
            where status in ('confirmed','approved','completed','closed')
            and type = 'MO'
            and not exists (select 1 from tmp_operationplan where reference = operationplan.reference)
            """)

        cursor.execute("""
            insert into operationplan
              (name,type,status,quantity,startdate,enddate,
              criticality,delay,plan,source,lastmodified,
              operation_id,owner_id,
              item_id,destination_id,origin_id,
              location_id,supplier_id,
              demand_id,due,color,reference,batch,quantity_completed%s)
            select name,type,status,quantity,startdate,enddate,
              criticality,delay * interval '1 second',plan,source,lastmodified,
              operation_id,owner_id,
              item_id,destination_id,origin_id,
              location_id,supplier_id,
              demand_id,due,color,reference,batch,quantity_completed%s
            from tmp_operationplan
            where not exists (
              select 1
              from operationplan
              where operationplan.reference = tmp_operationplan.reference
              );
            """ % (forecastfield1, forecastfield1))

        # directly injecting proposed records in operationplan table
        cursor.copy_from(
            CopyFromGenerator(
                cls.getData(
                    cls.parent.timestamp,
                    cluster=cluster,
                    accepted_status=["proposed"],
                )),
            table="operationplan",
            size=1024,
            sep="\v",
            columns=[
                "name",
                "type",
                "status",
                "quantity",
                "startdate",
                "enddate",
                "criticality",
                "delay",
                "plan",
                "source",
                "lastmodified",
                "operation_id",
                "owner_id",
                "item_id",
                "destination_id",
                "origin_id",
                "location_id",
                "supplier_id",
                "demand_id",
                "due",
                "color",
                "reference",
                "batch",
                "quantity_completed",
            ] + [a[0] for a in cls.attrs],
        )

        # update demand table specific fields
        cursor.execute("""
            with cte as (
              select demand_id, sum(quantity) plannedquantity, max(enddate) deliverydate, max(enddate)-due as delay
              from operationplan
              where demand_id is not null and owner_id is null
              group by demand_id, due
            )
            update demand
              set delay = cte.delay,
              plannedquantity = cte.plannedquantity,
              deliverydate = cte.deliverydate
            from cte
            where cte.demand_id = demand.name
            """)
        cursor.execute("""
            update demand set
              delay = null,
              plannedquantity = null,
              deliverydate = null
            where (delay is not null or plannedquantity is not null or deliverydate is not null)
            and not exists(
              select 1 from operationplan where owner_id is null and operationplan.demand_id = demand.name
              )
            """)
        cursor.execute("""
            update demand
              set plannedquantity = 0
            where status in ('open','quote') and plannedquantity is null
            """)
Пример #19
0
class Operation_admin(MultiDBModelAdmin):
    model = Operation
    raw_id_fields = ("item", "available", "owner")
    save_on_top = True
    fieldsets = (
        (
            None,
            {
                "fields": (
                    "name",
                    "type",
                    "item",
                    "location",
                    "duration",
                    "duration_per",
                    "owner",
                )
            },
        ),
        (
            _("advanced"),
            {
                "fields": [
                    "description",
                    "category",
                    "subcategory",
                    "fence",
                    "posttime",
                    "sizeminimum",
                    "sizemultiple",
                    "sizemaximum",
                    "cost",
                    "available",
                    "priority",
                    "search",
                    "effective_start",
                    "effective_end",
                ]
                + [a[0] for a in getAttributes(Operation) if a[3]],
                "classes": ("collapse",),
            },
        ),
    )
    tabs = [
        {
            "name": "edit",
            "label": _("edit"),
            "view": "admin:input_operation_change",
            "permissions": "input.change_operation",
        },
        {
            "name": "supplypath",
            "label": _("supply path"),
            "view": "supplypath_operation",
        },
        {"name": "whereused", "label": _("where used"), "view": "whereused_operation"},
        {"name": "plan", "label": _("plan"), "view": "output_operation_plandetail"},
        {
            "name": "plandetail",
            "label": _("manufacturing orders"),
            "view": "input_manufacturingorder_by_operation",
        },
        {
            "name": "constraint",
            "label": _("constrained demand"),
            "view": "output_constraint_operation",
        },
        {
            "name": "messages",
            "label": _("messages"),
            "view": "admin:input_operation_comment",
        },
    ]
Пример #20
0
def getAttributeAPIReadOnlyFields(cls):
    return tuple(i[0] for i in getAttributes(cls) if not i[3])
Пример #21
0
class Resource_admin(MultiDBModelAdmin):
    model = Resource
    raw_id_fields = (
        "maximum_calendar",
        "location",
        "setupmatrix",
        "owner",
        "available",
        "efficiency_calendar",
    )
    fieldsets = (
        (None, {"fields": ("name", "location", "type", "maximum")}),
        (
            _("advanced"),
            {
                "fields": [
                    "description",
                    "category",
                    "subcategory",
                    "constrained",
                    "owner",
                    "maximum_calendar",
                    "available",
                    "cost",
                    "maxearly",
                    "setupmatrix",
                    "efficiency",
                    "efficiency_calendar",
                ]
                + [a[0] for a in getAttributes(Resource) if a[3]],
                "classes": ("collapse",),
            },
        ),
    )
    save_on_top = True
    tabs = [
        {
            "name": "edit",
            "label": _("edit"),
            "view": "admin:input_resource_change",
            "permissions": "input.change_resource",
        },
        {
            "name": "supplypath",
            "label": _("supply path"),
            "view": "supplypath_resource",
        },
        {"name": "whereused", "label": _("where used"), "view": "whereused_resource"},
        {"name": "plan", "label": _("plan"), "view": "output_resource_plandetail"},
        {
            "name": "plandetail",
            "label": _("plan detail"),
            "view": "input_operationplanresource_plandetail",
        },
        {
            "name": "constraint",
            "label": _("constrained demand"),
            "view": "output_constraint_resource",
        },
        {
            "name": "messages",
            "label": _("messages"),
            "view": "admin:input_resource_comment",
        },
    ]