From d81e7de9114a29439142efba67f205653f562730 Mon Sep 17 00:00:00 2001 From: Andriy Oblivantsev Date: Thu, 6 Aug 2026 12:47:06 +0100 Subject: [PATCH] feat(crm): invoice update notes and PO fields Allow oo invoices update --description/--po so Notizen can be multiline refs without portal URLs; keep opportunity link support. --- cmd/oo/invoices.go | 17 ++++++++++++----- invoices.go | 18 ++++++++++++++---- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/cmd/oo/invoices.go b/cmd/oo/invoices.go index 5d55523..3a2ff61 100644 --- a/cmd/oo/invoices.go +++ b/cmd/oo/invoices.go @@ -160,21 +160,26 @@ Example: func invoiceUpdateCmd() *cobra.Command { var opportunityID int64 + var description, po string cmd := &cobra.Command{ Use: "update INVOICE_ID", - Short: "Update invoice (link to opportunity)", + Short: "Update invoice (opportunity link, notes, PO)", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - if opportunityID == 0 { - return fmt.Errorf("--opportunity is required") + if opportunityID == 0 && !cmd.Flags().Changed("description") && !cmd.Flags().Changed("po") { + return fmt.Errorf("set --opportunity and/or --description and/or --po") } c, err := newOO(cmd) if err != nil { return err } out, err := c.UpdateInvoice(cmd.Context(), args[0], onlyoffice.UpdateInvoiceParams{ - EntityID: opportunityID, - EntityType: 0, + EntityID: opportunityID, + EntityType: 0, + Description: description, + DescriptionSet: cmd.Flags().Changed("description"), + PurchaseOrder: po, + PurchaseOrderSet: cmd.Flags().Changed("po"), }) if err != nil { return err @@ -184,6 +189,8 @@ func invoiceUpdateCmd() *cobra.Command { }, } cmd.Flags().Int64Var(&opportunityID, "opportunity", 0, "CRM opportunity/deal id to link") + cmd.Flags().StringVar(&description, "description", "", "invoice notes (Notizen); use \\n for line breaks") + cmd.Flags().StringVar(&po, "po", "", "purchase order number") return cmd } diff --git a/invoices.go b/invoices.go index 4e06f35..f5c2fdd 100644 --- a/invoices.go +++ b/invoices.go @@ -115,11 +115,15 @@ func (c *Client) CreateInvoice(ctx context.Context, p CreateInvoiceParams) (map[ } // UpdateInvoiceParams are fields for PUT /api/2.0/crm/invoice/{id}. -// Loads the current invoice and merges non-zero entity / contact updates. +// Loads the current invoice and merges non-zero / set fields. type UpdateInvoiceParams struct { - EntityID int64 // link to opportunity; 0 = leave unchanged - EntityType int - ContactID int64 // 0 = leave unchanged + EntityID int64 // link to opportunity; 0 = leave unchanged + EntityType int + ContactID int64 // 0 = leave unchanged + Description string // invoice notes; empty + DescriptionSet=false keeps existing + DescriptionSet bool + PurchaseOrder string + PurchaseOrderSet bool } // UpdateInvoice PUTs a full invoice body (OnlyOffice requires complete payload). @@ -196,6 +200,12 @@ func (c *Client) UpdateInvoice(ctx context.Context, id string, p UpdateInvoicePa "status": statusID, "invoiceLines": lines, } + if p.DescriptionSet { + body["description"] = p.Description + } + if p.PurchaseOrderSet { + body["purchaseOrderNumber"] = p.PurchaseOrder + } if p.EntityID != 0 { body["entityId"] = p.EntityID body["entityType"] = p.EntityType