diff --git a/src/saleorder_storage.go b/src/saleorder_storage.go deleted file mode 100644 index 5d01a2f..0000000 --- a/src/saleorder_storage.go +++ /dev/null @@ -1,152 +0,0 @@ -package saleorder - -import ( - "fmt" - "strconv" - "strings" - - organizationv1 "github.com/appuio/control-api/apis/organization/v1" - odooclient "github.com/appuio/go-odoo" -) - -type Odoo16Credentials = odooclient.ClientConfig - -type Odoo16Options struct { - SaleOrderClientReferencePrefix string - SaleOrderInternalNote string - Odoo8CompatibilityMode bool -} - -const defaultSaleOrderState = "sale" - -type SaleOrderStorage interface { - CreateSaleOrder(organizationv1.Organization) (string, error) - GetSaleOrderName(organizationv1.Organization) (string, error) -} - -type Odoo16Client interface { - Read(string, []int64, *odooclient.Options, interface{}) error - CreateSaleOrder(*odooclient.SaleOrder) (int64, error) - FindResPartners(*odooclient.Criteria, *odooclient.Options) (*odooclient.ResPartners, error) -} - -type Odoo16SaleOrderStorage struct { - client Odoo16Client - options *Odoo16Options -} - -func NewOdoo16Storage(credentials *Odoo16Credentials, options *Odoo16Options) (SaleOrderStorage, error) { - client, err := odooclient.NewClient(credentials) - return &Odoo16SaleOrderStorage{ - client: client, - options: options, - }, err -} - -func NewOdoo16StorageFromClient(client Odoo16Client, options *Odoo16Options) SaleOrderStorage { - return &Odoo16SaleOrderStorage{ - client: client, - options: options, - } -} - -func (s *Odoo16SaleOrderStorage) CreateSaleOrder(org organizationv1.Organization) (string, error) { - beID, err := k8sIDToOdooID(org.Spec.BillingEntityRef) - if err != nil { - return "", err - } - - var beRecord odooclient.ResPartner - - fetchPartnerFieldOpts := odooclient.NewOptions().FetchFields( - "id", - "parent_id", - ) - - if s.options.Odoo8CompatibilityMode { - odoo8ID := fmt.Sprintf("__export__.res_partner_%d", beID) - - idMatchCriteria := odooclient.NewCriteria().Add("x_odoo_8_ID", "=", odoo8ID) - - r, err := s.client.FindResPartners(idMatchCriteria, fetchPartnerFieldOpts) - if err != nil { - return "", fmt.Errorf("fetching accounting contact by ID: %w", err) - } - - if len(*r) <= 0 { - return "", fmt.Errorf("no results when fetching accounting contact by ID") - } - resPartners := *r - - beRecord = resPartners[0] - } else { - beRecords := []odooclient.ResPartner{} - err = s.client.Read(odooclient.ResPartnerModel, []int64{int64(beID)}, fetchPartnerFieldOpts, &beRecords) - if err != nil { - return "", fmt.Errorf("fetching accounting contact by ID: %w", err) - } - - if len(beRecords) <= 0 { - return "", fmt.Errorf("no results when fetching accounting contact by ID") - } - - beRecord = beRecords[0] - } - - if beRecord.ParentId == nil { - return "", fmt.Errorf("accounting contact %d has no parent", beRecord.Id.Get()) - } - - var clientRef string - if org.Spec.DisplayName != "" { - clientRef = fmt.Sprintf("%s (%s)", s.options.SaleOrderClientReferencePrefix, org.Spec.DisplayName) - } else { - clientRef = fmt.Sprintf("%s (%s)", s.options.SaleOrderClientReferencePrefix, org.ObjectMeta.Name) - } - - newSaleOrder := odooclient.SaleOrder{ - PartnerInvoiceId: odooclient.NewMany2One(beRecord.Id.Get(), ""), - PartnerId: odooclient.NewMany2One(beRecord.ParentId.ID, ""), - State: odooclient.NewSelection(defaultSaleOrderState), - ClientOrderRef: odooclient.NewString(clientRef), - InternalNote: odooclient.NewString(s.options.SaleOrderInternalNote), - } - - soID, err := s.client.CreateSaleOrder(&newSaleOrder) - if err != nil { - return "", fmt.Errorf("creating new sale order: %w", err) - } - - return fmt.Sprint(soID), nil -} - -func (s *Odoo16SaleOrderStorage) GetSaleOrderName(org organizationv1.Organization) (string, error) { - fetchOrderFieldOpts := odooclient.NewOptions().FetchFields( - "id", - "name", - ) - id, err := strconv.Atoi(org.Status.SalesOrderID) - if err != nil { - return "", fmt.Errorf("error parsing saleOrderID %q from organization status: %w", org.Status.SalesOrderID, err) - } - soRecords := []odooclient.SaleOrder{} - err = s.client.Read(odooclient.SaleOrderModel, []int64{int64(id)}, fetchOrderFieldOpts, &soRecords) - if err != nil { - return "", fmt.Errorf("fetching sale order by ID: %w", err) - } - - if len(soRecords) <= 0 { - return "", fmt.Errorf("no results when fetching sale orders with ID %q", id) - } - - return soRecords[0].Name.Get(), nil - -} - -func k8sIDToOdooID(id string) (int, error) { - if !strings.HasPrefix(id, "be-") { - return 0, fmt.Errorf("invalid ID, missing prefix: %s", id) - } - - return strconv.Atoi(id[3:]) -} diff --git a/src/servala/core/models/organization.py b/src/servala/core/models/organization.py index 8625203..1662dfa 100644 --- a/src/servala/core/models/organization.py +++ b/src/servala/core/models/organization.py @@ -94,7 +94,7 @@ class Organization(ServalaModelMixin, models.Model): "partner_invoice_id": instance.billing_entity.odoo_invoice_id, "state": "sale", "client_order_ref": f"Servala (Organization: {instance.name})", - "note": "auto-generated by Servala Portal", + "internal_note": "auto-generated by Servala Portal", } sale_order_id = CLIENT.execute("sale.order", "create", [payload]) diff --git a/src/servala/core/models/service.py b/src/servala/core/models/service.py index e17bda2..6eb912e 100644 --- a/src/servala/core/models/service.py +++ b/src/servala/core/models/service.py @@ -222,8 +222,8 @@ class ControlPlane(ServalaModelMixin, models.Model): } annotations = { "servala.com/organization": organization.name, - "servala.com/billing": organization.origin.name, - "servala.com/origin": organization.billing_entity.name, + "servala.com/origin": organization.origin.name, + "servala.com/billing": organization.billing_entity.name, } for field in ("company_id", "invoice_id"): @@ -231,7 +231,7 @@ class ControlPlane(ServalaModelMixin, models.Model): labels[f"servala.com/erp_{field}"] = str(value) if organization.odoo_sale_order_id: - annotations["servala.com/sales_order"] = str( + labels["servala.com/erp_sale_order_id"] = str( organization.odoo_sale_order_id )