This commit is contained in:
parent
adda59fe7f
commit
6a1f554854
3 changed files with 4 additions and 156 deletions
|
@ -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:])
|
|
||||||
}
|
|
|
@ -94,7 +94,7 @@ class Organization(ServalaModelMixin, models.Model):
|
||||||
"partner_invoice_id": instance.billing_entity.odoo_invoice_id,
|
"partner_invoice_id": instance.billing_entity.odoo_invoice_id,
|
||||||
"state": "sale",
|
"state": "sale",
|
||||||
"client_order_ref": f"Servala (Organization: {instance.name})",
|
"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])
|
sale_order_id = CLIENT.execute("sale.order", "create", [payload])
|
||||||
|
|
||||||
|
|
|
@ -222,8 +222,8 @@ class ControlPlane(ServalaModelMixin, models.Model):
|
||||||
}
|
}
|
||||||
annotations = {
|
annotations = {
|
||||||
"servala.com/organization": organization.name,
|
"servala.com/organization": organization.name,
|
||||||
"servala.com/billing": organization.origin.name,
|
"servala.com/origin": organization.origin.name,
|
||||||
"servala.com/origin": organization.billing_entity.name,
|
"servala.com/billing": organization.billing_entity.name,
|
||||||
}
|
}
|
||||||
|
|
||||||
for field in ("company_id", "invoice_id"):
|
for field in ("company_id", "invoice_id"):
|
||||||
|
@ -231,7 +231,7 @@ class ControlPlane(ServalaModelMixin, models.Model):
|
||||||
labels[f"servala.com/erp_{field}"] = str(value)
|
labels[f"servala.com/erp_{field}"] = str(value)
|
||||||
|
|
||||||
if organization.odoo_sale_order_id:
|
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
|
organization.odoo_sale_order_id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue