class Product(ProductBase): name = base.String('description1') code = base.String('number') ean13 = base.String('ean') list_price = base.Decimal('recommendedretailprice') cost_price = base.Decimal('unitprice') manufacturer = base.String('supplier') picture = base.URL('pictureurl') @property def valid(self): return True @property def description(self): descr = base.String('description2').parse(self) if descr is None: return self.name return descr @classmethod def search(cls, keywords, offset=0, limit=20, count=False): if limit is None: limit = 20 sp = SearchProducts(cls._ctx) products = sp.execute(keywords, offset, limit) if count: if len(products) < limit: return len(products) else: # HACK return 100 * limit return [p.code for p in products] @classmethod def read(cls, codes): if len(codes) == 0: return [] # If products dont exist, create invalid products. # All for all codes coming in, products have to be returned. itd = ItemDetails(cls._ctx) products = {} for product in itd.execute(codes): products[product.code] = product res = [] for code in codes: if code in products: res.append(products[code]) else: res.append(InvalidProduct(code)) return res
class Line(Model): product = base.Many2One(model=Product) quantity = base.Decimal('quantity') available_quantity = base.Decimal('availablequantity') @property def availability(self): if self.available_quantity >= self.quantity: return 'available' elif self.available_quantity > 0: return 'partially_available' else: return 'not_available'
class Line(VeloModelMixin, Model): quantity = base.Decimal('cbc:Quantity') unit_price = base.Decimal('cac:UnitPrice') product = base.Many2One('cac:Item', model=Product) availability = base.String('vco:Availability/vco:Code') available_quantity = base.Decimal('vco:Availability/vco:AvailableQuantity')
class Product(VeloModelMixin, ProductBase): _name_exp = re.compile(r'[\n\r]| ') _prefixes = ['cac:Item/'] # 'Works with ItemDetail and Item nodes.' valid = ~base.Bool('vco:ItemUnknown/cac:SellersItemIdentification/cac:ID', default=True) code = base.String( 'cac:SellersItemIdentification/cac:ID', 'vco:RequestReplacement/cac:SellersItemIdentification/cac:ID', 'vco:ItemUnknown/cac:SellersItemIdentification/cac:ID') replacement = base.String( 'vco:RequestReplacement/cac:ItemReplacement/cac:ID') description = base.String('cbc:Description', subst=(r' ', ' ')) list_price = base.Decimal('cac:RecommendedRetailPrice/cbc:PriceAmount') cost_price = base.Decimal('cac:BasePrice/cbc:PriceAmount') unit_code = base.Attribute('cac:BasePrice/cbc:BaseQuantity', attr='quantityUnitCode') manufacturer = base.String('cac:ManufacturersItemIdentification' '/cac:IssuerParty/cac:PartyName/cbc:Name') availability = base.String('vco:Availability/vco:Code') available_quantity = base.Decimal('vco:Availability/vco:AvailableQuantity') @property def name(self): if self.description is None: return None return self._name_exp.sub(' ', self.description[:100] + '...') @property def ean13(self): ean13 = self._data.xpath( 'cac:Item/cac:StandardItemIdentification' '/cac:ID[@identificationSchemeID="EAN/UCC-13"]', namespaces=NAMESPACES) return len(ean13) and ean13[0].text or None @property def sellers_item_identification(self): return SellersItemIdentification(ID(self.code)) @property def picture(self): urls = self._data.xpath( 'cac:Item/vcc:ItemInformation/vcc:InformationURL' '/vcc:Disposition[text()="picture"]/../vcc:URI', namespaces=NAMESPACES) url = len(urls) and urls[0].text or None if url is None: return None return buffer(urllib2.urlopen(url).read()) @classmethod def search(cls, keywords, offset=0, limit=20, count=False): cts = CreateTextSearch(cls._ctx) ctsresp = cts.execute(keywords) if count: return ctsresp.count if ctsresp.count == 0: return [] sr = SearchResult(cls._ctx) return sr.execute(ctsresp.tan, offset, limit) @classmethod def read(cls, codes): gidl = GetItemDetailsList(cls._ctx) return gidl.execute(codes)