Can't create multiple instances of Product()

#1 · open · 2 comments

View on GitHub ↗

twoblokeswithapostie

Hey jsok, I really love what you've done here and I have extended the API by adding a lot of other classes for other features which I'm hoping to add a merge request for, however, I'm stuck at one thing and I really don't know how to go about it. Say you have a loop of products and you wish to create an instance for each and push it to API. This doesn't work: p1 = Product() p2 = Product() Every time you make a change to p1 it makes a change to p2 or vice versa, even though their ids are different in memory. I guess it has something to do with **metaclass** = MetaResource inside the UnleashedResource and override on **new** inside MetaResource class, but for the life of me I can't work it out. Basically, I've created these 2 classes: ``` python from unleashed.resources import UnleashedResource from unleashed.resources import fields from unleashed.resources.customer import Customer from unleashed.resources.tax import Tax from unleashed.resources.sales_person import SalesPerson from unleashed.resources.sales_invoice_line_item import SalesInvoiceLineItem class SaleInvoice(UnleashedResource): __endpoint__ = "SaleInvoices" BCSubTotal = fields.FieldNullableDecimal() BCTaxTotal = fields.FieldNullableDecimal() BCTotal = fields.FieldNullableDecimal() Comments = fields.FieldString() CreatedBy = fields.FieldString() Currency = fields.FieldNullableDecimal() Customer = Customer() CustomerRef = fields.FieldString() DeliveryCity = fields.FieldString() DeliveryCountry = fields.FieldString() DeliveryMethod= fields.FieldString() DeliveryName = fields.FieldString() DeliveryPostCode = fields.FieldString() DeliveryRegion = fields.FieldString() DeliveryStreetAddress = fields.FieldString() DeliverySuburb = fields.FieldString() DiscountRate = fields.FieldNullableDecimal() ExchangeRate = fields.FieldNullableDecimal() Guid = fields.FieldGuid(required=True) LastModifiedOn = fields.FieldNullableDateTime() OrderDate = fields.FieldNullableDateTime() OrderNumber = fields.FieldString() OrderStatus = fields.FieldString() PaymentDueDate = fields.FieldNullableDateTime() QuoteExpiryDate = fields.FieldNullableDateTime() ReceivedDate = fields.FieldNullableDateTime() RequiredDate = fields.FieldNullableDateTime() SalesOrderGroup = fields.FieldString() SalesOrderLines = fields.FieldResourceList(SalesInvoiceLineItem()) SalesPerson = SalesPerson() SendAccountingJournalOnly = fields.FieldBoolean() SourceId = fields.FieldString() SubTotal = fields.FieldNullableDecimal() Tax = Tax() TaxRate = fields.FieldNullableDecimal() TaxTotal = fields.FieldNullableDecimal() Total = fields.FieldNullableDecimal() TotalVolume = fields.FieldNullableDecimal() TotalWeight = fields.FieldNullableDecimal() # Warehouse = Warehouse() ``` and ``` python from unleashed.resources import UnleashedResource from unleashed.resources import fields from unleashed.resources.sales_invoice_product import SalesInvoiceProduct class SalesInvoiceLineItem(UnleashedResource): Guid = fields.FieldGuid(required=True) LineNumber = fields.FieldInteger() Product = SalesInvoiceProduct() DueDate = None OrderQuantity = fields.FieldNullableDecimal() UnitPrice = fields.FieldNullableDecimal() DiscountRate = fields.FieldNullableDecimal() LineTotal = fields.FieldNullableDecimal() Volume = None Comments = None AverageLandedPriceAtTimeOfSale = 0 TaxRate = 0.1000 LineTax = fields.FieldNullableDecimal() XeroTaxCode = None BCUnitPrice = fields.FieldNullableDecimal() BCLineTotal = fields.FieldNullableDecimal() BCLineTax = fields.FieldNullableDecimal() LineTaxCode = fields.FieldNullableDecimal() XeroSalesAccount = fields.FieldString() LastModifiedOn = None ``` But then in this loop the list ends up with multiples of the same instance of SalesInvoiceLineItem(): ``` python for bc_product in bc_products: product = SalesInvoiceProduct() line = SalesInvoiceLineItem() product.ProductCode = bc_product.productCode product.ProductDescription = bc_product.productDescription line.LineNumber = line_number + 1 line.Product = product line.OrderQuantity = bc_product.units line.UnitPrice = float(bc_product.unitPrice) line.DiscountRate = None # Discount are not per product in BC line.LineTotal = float(bc_product.totalProductPrice) line.LineTax = 0.10 line.BCUnitPrice = float(bc_product.unitPrice) line.BCLineTotal = float(bc_product.totalProductPrice) line.BCLineTax = 0.10 line.LineTaxCode = None line.XeroSalesAccount = "" order_lines.append(line) ``` Is there a solution to this? Your help is much appreciated.

Comments

jsok

Hi Mario, Yeah this is very much an experimental approach using metaclasses which I'm still unsure are the best approach. The declarative style of the fields is pretty, but definitely introduces some complexity. I've got some subsequent patches (which don't yet support embedded/nested resources) which have simplified MetaResource and pushed some more logic into the concrete UnleashedResource class. I can't promise or give ETAs on landing it. I've got this bug as a regression test so make sure it's sane, so I won't forget about it. - Jonathan

twoblokeswithapostie

Hey Jonathan, I love the approach and it makes everything really easy. I'll be on the look out for the updates for sure. I did spend a whole day today trying to figure out the solution to this issue I posted and and I'll try a bit more before I give up. I'll post the solution here if I find one. Mario