Apply code review fixes
All checks were successful
Tests / test (push) Successful in 37s

This commit is contained in:
Tobias Kunze 2025-06-22 17:41:35 +02:00
parent adda59fe7f
commit 6a1f554854
3 changed files with 4 additions and 156 deletions

View file

@ -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:])
}

View file

@ -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])

View file

@ -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
)