Example #1
0
    def self_save_billing(self):
        cust = self.request.ctx.customer
        self.forbid_if(cust.campaign.company.enterprise_id != self.enterprise_id)
        bill = cust.billing
        if not bill:
            bill = Billing.create(cust, True)

        bill.set_cc_info(self.request.POST.get('bill_cc_num'), self.request.POST.get('bill_cc_cvv'))
        bill.cc_exp = self.request.POST.get('bill_cc_exp')
        bill.cc_token = self.request.POST.get('bill_cc_token')
        if 'bill_exp_month' in self.request.POST and 'bill_exp_year' in self.request.POST:
            bill.cc_exp = self.request.POST.get('bill_exp_month') + '/' + self.request.POST.get('bill_exp_year')

        bill.bind(self.request.POST, False, 'bill')
        bill.save()
        cust.save()
        self.db_flush()
        api = BaseBillingApi.create_api(cust.campaign.company.enterprise)
        if api.update_billing(cust, bill):
            Status.add(cust, cust, Status.find_event(self.enterprise_id, cust, 'NOTE'),
                       'Billing Updated at gateway')
            self.flash('Successfully saved billing information.')
            cust.invalidate_caches()
            return self.find_redirect()
        else:
            (_, last_note) = api.get_last_status()
            self.flash('Unable to save credit card information: %s' % last_note)
            log.error('CC CHANGE DECLINED %s %s %s' % (cust.customer_id, cust.email, last_note))
            self.raise_redirect(self.request.referrer)
Example #2
0
 def delete(self):
     customer_id = self.request.matchdict.get('customer_id')
     customer = Customer.load(customer_id)
     self.forbid_if(not customer or customer.campaign.company.enterprise_id != self.enterprise_id)
     customer.mod_dt = util.now()
     customer.delete_dt = util.now()
     Status.add(customer, customer, StatusEvent.find(self.enterprise_id, 'Customer', 'DELETED'), 'Customer Deleted')
     return 'True'
Example #3
0
 def remove(self):
     lis = Listing.load(self.request.matchdict.get('listing_id'))
     cust = self.request.ctx.customer
     self.forbid_if(not lis or not cust or lis.customer.customer_id != cust.customer_id or cust.campaign.company.enterprise_id != self.enterprise_id)
     lis.soft_delete()
     Status.add(cust, lis, Status.find_event(self.enterprise_id, lis, 'CLOSED'),
                'Listing Deleted: %s' % self.request.POST.get('title'))
     return 'True'
Example #4
0
 def send_to_customer(self, sender, customer, order=None, extra_message=None, subject=None):   #pylint: disable-msg=R0913
     output = self.render(customer, order, extra_message)
     subject = subject if subject else self.tokenize(self.subject, customer, order)
     mail = UserMail(sender)
     mail.send(customer.email, subject, output)
     Status.add(customer, self, Status.find_event(customer.campaign.company.enterprise_id, self, 'SENT'),
                'Sent %s (%s)' % (self.name, subject))
     return True
Example #5
0
 def save_status(self):
     product_id = self.request.POST['product_id']
     product = Product.load(product_id)
     self.forbid_if(not product or product.company.enterprise_id != self.enterprise_id)
     event = StatusEvent.load(self.request.POST['event_id'])
     self.forbid_if(not event or (not event.is_system and event.enterprise_id != self.enterprise_id))
     note = self.request.POST.get('note')
     Status.add(None, product, event, note, self.request.ctx.user)
     return HTTPFound('/crm/product/show_history/%s' % product_id)
Example #6
0
 def delete(self):
     product_id = self.request.matchdict.get('product_id')
     product = Product.load(product_id)
     self.forbid_if(not product or str(product.company.enterprise_id) != str(self.enterprise_id))
     product.mod_dt = util.now()
     product.delete_dt = util.now()
     Status.add(None, product, StatusEvent.find(self.enterprise_id, 'Product', 'DELETED'), 'Product Deleted')
     product.invalidate_caches()
     return 'True'
Example #7
0
 def upload_asset(self):
     """ KB: [2011-03-23]: Take this file and hash its name up to put it in a sensible directory. """
     listing_id = self.request.matchdict.get('listing_id')
     listing_hash = self.request.matchdict.get('hash')
     lis = Listing.load(listing_id)
     self.forbid_if(not lis or lis.hash != listing_hash)
     ass = Asset.create_new(lis, self.enterprise_id, self.request)
     Status.add(lis.customer, lis, Status.find_event(self.enterprise_id, lis, 'ASSET_UPLOAD'), ass.name)
     return str(ass.id)
Example #8
0
 def _cancel_order_impl(self, order_id, reason, by_customer=False):
     codr = CustomerOrder.load(order_id)
     self.forbid_if(not codr)
     cust = codr.customer
     api = BaseBillingApi.create_api(cust.campaign.company.enterprise)
     if api.cancel_order(codr, cust.billing):
         Status.add(cust, cust, Status.find_event(self.enterprise_id, cust, 'NOTE'), 'Billing Cancelled at gateway')
     codr.cancel(reason, by_customer)
     cust.invalidate_caches()
Example #9
0
 def save_status(self):
     purchase_order_id = self.request.matchdict.get('purchase_order_id')
     purchase = PurchaseOrder.load(purchase_order_id)
     self.forbid_if(not purchase or purchase.company.enterprise_id != self.enterprise_id)
     event = StatusEvent.load(self.request.POST.get('event_id'))
     self.forbid_if(not event or not self.request.POST.get('event_id') or (not event.is_system and event.enterprise_id != self.enterprise_id))
     note = self.request.POST.get('note')
     Status.add(None, purchase, event, note, self.request.ctx.user)
     self.flash("Saved status")
     return HTTPFound('/crm/purchase/edit/%s' % purchase_order_id)
Example #10
0
 def delete_purchase_order_item(self):
     purchase_order_id = self.request.matchdict.get('purchase_order_id')
     order_item_id = self.request.matchdict.get('order_item_id')
     porder = PurchaseOrder.load(purchase_order_id)
     self.forbid_if(not porder)
     poi = PurchaseOrderItem.load(order_item_id)
     self.forbid_if(not poi or poi.purchase_order != porder)
     prod = poi.product
     poi.delete()
     Status.add(None, porder, Status.find_event(self.enterprise_id, porder, 'MODIFIED'),
                'Purchase Order %s. "%s" removed.' % ('MODIFIED', prod.name),
                self.request.ctx.user)
     poi.flush()
     return 'True'
Example #11
0
 def complete(self):
     purchase_order_id = self.request.matchdict.get('purchase_order_id')
     porder = PurchaseOrder.load(purchase_order_id)
     self.forbid_if(not porder or porder.company.enterprise_id != self.enterprise_id)
     porder.complete_dt = util.today()
     porder.save()
     for oitem in porder.order_items:
         if not oitem.complete_dt:
             oitem.complete_dt = util.today()
             oitem.save()
             InventoryJournal.create_new(oitem.product, 'Item Receipt', oitem.quantity)
     Status.add(None, porder, Status.find_event(self.enterprise_id, porder, 'COMPLETED'),
                'Purchase Order Completed', self.request.ctx.user) 
     return 'True'
Example #12
0
 def save(self):
     porder = PurchaseOrder.load(self.request.POST.get('purchase_order_id'))
     new = False
     if not porder:
         new = True
         porder = PurchaseOrder()
     porder.bind(self.request.POST)
     porder.save()
     porder.flush()
     Status.add(None, porder, Status.find_event(self.enterprise_id, porder, 'CREATED' if new else 'MODIFIED'),
                'Purchase Order %s' % ('CREATED' if new else 'MODIFIED'),
                self.request.ctx.user)
     self.db_flush()
     self.flash('Successfully saved PO %s.' % porder.purchase_order_id)
     return HTTPFound('/crm/purchase/edit/%s' % porder.purchase_order_id)
Example #13
0
 def complete_item(self):
     purchase_order_id = self.request.matchdict.get('purchase_order_id')
     order_item_id = self.request.matchdict.get('order_item_id')
     porder = PurchaseOrder.load(purchase_order_id)
     self.forbid_if(not porder)
     poi = PurchaseOrderItem.load(order_item_id)
     self.forbid_if(not poi or poi.purchase_order != porder or poi.complete_dt)
     poi.complete_dt = util.today()
     poi.save()
     poi.flush()
     InventoryJournal.create_new(poi.product, 'Item Receipt', poi.quantity)
     Status.add(None, porder, Status.find_event(self.enterprise_id, porder, 'COMPLETED'),
                'Purchase Order Item "%s" Completed' % poi.product.name,
                self.request.ctx.user) 
     return 'True'
Example #14
0
 def show_history(self):
     product_id = self.request.matchdict['product_id']
     product = Product.load(product_id)
     self.forbid_if(not product or product.company.enterprise_id != self.enterprise_id)
     return {'product' : product,
             'events' : util.select_list(StatusEvent.find_all_applicable(self.enterprise_id, product), 'event_id', 'display_name'),
             'history' : Status.find(product)
             }
Example #15
0
 def save_purchase_order_item(self):
     purchase_order_id = self.request.matchdict.get('purchase_order_id')
     self.forbid_if(not 'product_id' in self.request.GET or not self.request.GET.get('product_id'))
     poi = PurchaseOrderItem.load(self.request.POST.get('order_item_id'))
     if not poi:
         poi = PurchaseOrderItem()
         poi.purchase_order_id = purchase_order_id
     poi.bind(self.request.POST)
     poi.product_id = self.request.GET.get('product_id')
     poi.note = self.request.POST.get('order_note')
     poi.save()
     poi.flush()
     porder = poi.purchase_order
     Status.add(None, porder, Status.find_event(self.enterprise_id, porder, 'MODIFIED'),
                'Purchase Order %s. "%s" added.' % ('MODIFIED', poi.product.name),
                self.request.ctx.user)
     self.db_flush()
     return '{"id": "%s"}' % poi.order_item_id
Example #16
0
 def show_history(self):
     customer_id = self.request.matchdict.get('customer_id')
     customer = Customer.load(customer_id)
     self.forbid_if(not customer or customer.campaign.company.enterprise_id != self.enterprise_id)
     return {
         'customer' : customer,
         'history' : Status.find_by_customer(customer, self.offset),
         'offset' : self.offset
         }
Example #17
0
 def show_history(self):
     purchase_order_id = self.request.matchdict.get('purchase_order_id')
     purchase = PurchaseOrder.load(purchase_order_id)
     self.forbid_if(not purchase or purchase.company.enterprise_id != self.enterprise_id)
     return {
         'history' : Status.find(purchase),
         'purchase' : purchase,
         'offset' : self.offset
         }
Example #18
0
 def show_status_dialog(self):
     customer_id = self.request.matchdict.get('customer_id')
     status_id = self.request.matchdict.get('status_id')
     customer = Customer.load(customer_id)
     self.forbid_if(not customer or customer.campaign.company.enterprise_id != self.enterprise_id)
     status = Status.load(status_id)
     self.forbid_if(not status or str(customer.customer_id) != str(customer_id))
     return {
         'customer' : customer,
         'status' : status
         }
Example #19
0
    def cancel(self, reason, by_customer=False):
        self.cancel_dt = datetime.datetime.date(datetime.datetime.now())
        for oitem in self.active_items:
            prod = oitem.product
            InventoryJournal.create_new(prod, "Cancelled Order", oitem.quantity, oitem)
            oitem.delete_dt = util.today()
            oitem.save()

        journals = Journal.find_all_by_order(self)
        for j in journals:
            j.delete_dt = util.today()
            j.save()

        msg = "Order Canceled" if not by_customer else "Order Cancelled by Customer"
        Status.add(
            self.customer,
            self,
            Status.find_event(self.customer.campaign.company.enterprise_id, self, "CREATED"),
            "%s : %s" % (msg, reason),
        )
        self.save()
Example #20
0
 def augment_order(self, customer, product, campaign, user_created, quantity=0, incl_tax=True):
     enterprise_id = product.company.enterprise_id
     item = OrderItem()
     item.order = self
     item.product = product
     item.creator = user_created
     discount = product.get_discount_price(campaign)
     retail = product.get_price(campaign)
     item.unit_price = discount if discount else retail
     item.unit_cost = product.unit_cost
     item.unit_discount_price = discount if discount else 0.0
     item.unit_retail_price = retail
     item.quantity = quantity
     if campaign.tax_rate and incl_tax:
         item.tax = (item.unit_price * item.quantity) * campaign.tax_rate
     if quantity > 0:
         if product.track_inventory:
             InventoryJournal.create_new(product, "Sale", item.quantity, item)
     item.save()
     if product.can_have_children():
         item.flush()  # we need this to get the parent ID.
         children = product.get_children()
         if children and len(children) > 0:
             for kid in children:
                 child_item = OrderItem()
                 child_item.order = self
                 child_item.parent_id = item.order_item_id
                 child_item.product = kid.child
                 child_item.creator = user_created
                 child_item.unit_price = 0.0
                 child_item.unit_discount_price = 0.0
                 child_item.unit_cost = product.unit_cost
                 child_item.quantity = kid.child_quantity
                 if kid.child.track_inventory:
                     InventoryJournal.create_new(kid.child, "Sale", child_item.quantity, child_item)
     Status.add(customer, self, Status.find_event(enterprise_id, self, "MODIFIED"), "Order Modified ")
     self.save()
     self.flush()
     return item
Example #21
0
    def save(self):
        self.forbid_if('redir' not in self.request.POST)
        redir = self.request.POST.get('redir')
        cust = self.request.ctx.customer
        lis = Listing.load(self.request.POST.get('listing_id'))
        if not lis:
            lis = Listing()
            lis.customer = cust
            lis.company = self.request.ctx.campaign.company
            lis.site = self.request.ctx.site
            # l.ip = util.self.request_ip()
            # g = Geo()
            # gip = g.by_ip(l.ip)
            # if gip and gip['latitude'] and gip['longitude']:
            #     l.latitude = gip['latitude'] if 'latitude' in gip else None
            #     l.longitude = gip['longitude'] if 'longitude' in gip else None
            #     l.city = gip['city'] if 'city' in gip else None
            #     l.state = gip['region_name'] if 'region_name' in gip else None
            #     l.zip = gip['postal_code'] if 'postal_code' in gip else None
            #     l.country = gip['country_code'] if 'country_code' in gip else None
            #     l.dma = gip['dma_code'] if 'dma_code' in gip else None
        # this overrides the original lat/lng settings if they are coming from
        # the POST instead of the geo ip.
        lis.bind(self.request.POST, True)
        lis.save()
        self.db_flush()

        # for key in self.request.POST.keys():
        #     if key.startswith('asset_'):
        #         ass = Asset.load(key[6:])
        #         ass.fk_type = 'Listing'
        #         ass.fk_id = lis.listing_id
        #         ass.save()

        Status.add(cust, lis, Status.find_event(self.enterprise_id, lis, 'OPEN'),
                   'Listing Created: %s' % self.request.POST.get('title'))
        self.flash('Listing: "%s" saved' % lis.title)
        return HTTPFound('%s?listing_id=%s&post=1' % (redir, lis.listing_id))
Example #22
0
    def contact(self):
        camp = self.request.ctx.campaign
        message = self.request.POST.get('message')
        email = self.request.POST.get('email')
        msg = "%s %s<br>(%s)<br><br>%s<br><br>%s" % (self.request.POST.get('fname'),
                                                     self.request.POST.get('lname'),
                                                     email,
                                                     self.request.POST.get('phone'),
                                                     message)
        if util.nvl(self.request.POST.get('save')):
            cust = Customer.find(email, camp)
            if not cust:
                cust = Customer()
                cust.campaign = camp
                cust.bind(self.request.POST)
                cust.phone = cust.phone[:20] if cust.phone else None # prevents people from putting in "904-716-7487 (mobile)" and it barfs
                cust.save()
            Status.add(cust, cust, Status.find_event(self.enterprise_id, cust, 'NOTE'),
                       'NOTE FROM CUSTOMER\n%s' % message)

        email_info = camp.get_email_info()
        mail = UserMail(camp)
        mail.send(email_info.email, 'SITE CONTACT FORM %s' % self.request.host, msg)
        return self.find_redirect()
Example #23
0
    def return_item(self):
        customer_id = self.request.matchdict.get('customer_id')
        order_id = self.request.matchdict.get('order_id')
        order_item_id = self.request.matchdict.get('order_item_id')
        customer = Customer.load(customer_id)
        self.forbid_if(not customer or customer.campaign.company.enterprise_id != self.enterprise_id)
        order = customer.get_order(order_id)
        self.forbid_if(not order)
        order_item = OrderItem.load(order_item_id)
        self.forbid_if(not order_item or str(order_item.order.order_id) != str(order.order_id))
        user = self.request.ctx.user
        return_type = self.request.POST.get('rt_refund_type')
        quantity_returned = float(self.request.POST.get('quantity_returned'))
        credit_amount = float(self.request.POST.get('credit_amount'))

        jrnl = Journal.create_new(credit_amount, customer, order, user, return_type)
        ret = ProductReturn.create_new(order_item.product, order_item.order, quantity_returned, credit_amount, jrnl, user)
        status_note = "'%s' returned.  $%.2f refunded by %s" % (order_item.product.name, credit_amount, return_type)
        Status.add(customer, order_item, Status.find_event(self.enterprise_id, order_item, 'RETURN'), status_note)

        order_item.quantity -= quantity_returned
        if order_item.quantity == 0:
            order_item.delete_dt = util.today()
        order_item.save()
        if order_item.product.track_inventory:
            InventoryJournal.create_new(order_item.product, 'Return', quantity_returned, order_item, None, None, ret)

        for attr_kid in order_item.children:
            Status.add(customer, attr_kid, Status.find_event(self.enterprise_id, attr_kid, 'RETURN'), status_note)
            attr_kid_prod = attr_kid.product
            if attr_kid_prod.track_inventory:
                InventoryJournal.create_new(attr_kid_prod, 'Return', quantity_returned, attr_kid)

        self.flash(status_note)
        if len(order.active_items) == 0:
            # KB: [2012-09-06]: Deleted the one thing out of this
            # order.  Kill the order
            status_note = 'Only item in order returned. Order cancelled.'
            self._cancel_order_impl(order_id, status_note, False)
            self.flash(status_note)
            ret = HTTPFound('/crm/customer/show_orders/%s' % customer_id)
        else:
            ret = HTTPFound('/crm/customer/edit_order_dialog/%s/%s' % (customer_id, order_id))
        customer.invalidate_caches()
        return ret
Example #24
0
    def _apply_payment(self, customer_id, order_id, pmt_amount=None, pmt_method=None, pmt_note=None):  #pylint: disable-msg=R0913
        """ KB: [2011-03-09]: Check that everything is kosher
        Create a journal entry for the order for the amount and type specified in the UI
        Create a status noting the type and amount of the payment applied.
        """
        customer = Customer.load(customer_id)
        self.forbid_if(not customer or customer.campaign.company.enterprise_id != self.enterprise_id)
        order = customer.get_order(order_id)
        self.forbid_if(not order)
        user = self.request.ctx.user
        current_customer_balance = customer.get_current_balance()
        #prior_payments_applied = order.total_payments_applied()
        prior_total_due = order.total_payments_due()
        balance_amount_to_apply = float(self.request.POST.get('pmt_balance_amount_to_apply', 0.0))
        amt = float(util.nvl(pmt_amount, self.request.POST.get('pmt_amount')))
        method = util.nvl(pmt_method, self.request.POST.get('pmt_method'))
        note = util.nvl(pmt_note, self.request.POST.get('pmt_note'))

        self.forbid_if(round(amt + balance_amount_to_apply, 2) > round(prior_total_due, 2),
                       "amt + balance_amount_to_apply > prior_total_due")
        self.forbid_if(current_customer_balance > 0 and round(balance_amount_to_apply, 2) > round(current_customer_balance, 2),
                       "balance_amount_to_apply > current_customer_balance")

        pmt_type = 'PartialPayment'
        if amt == prior_total_due:
            pmt_type = 'FullPayment'

        Journal.create_new(amt, customer, order, user, pmt_type, method, note)
        status_note = '%s applied: $%s' % (pmt_type, util.money(amt))
        Status.add(customer, order, Status.find_event(self.enterprise_id, order, 'PAYMENT_APPLIED'), status_note)
        self.flash(status_note)
        if balance_amount_to_apply > 0:
            Journal.create_new(balance_amount_to_apply, customer, order, user, 'CreditDecrease')
            status_note = '%s applied: $%s' % ('CreditDecrease', util.money(balance_amount_to_apply))
            Status.add(customer, order, Status.find_event(self.enterprise_id, order, 'PAYMENT_APPLIED'), status_note)
            self.flash(status_note)
        customer.invalidate_caches()
        customer.flush()
        return 'True'
Example #25
0
 def save_status(self):
     customer_id = self.request.matchdict.get('customer_id')
     customer = Customer.load(customer_id)
     self.forbid_if(not customer or customer.campaign.company.enterprise_id != self.enterprise_id)
     event = StatusEvent.load(self.request.POST.get('event_id'))
     self.forbid_if(not event or not self.request.POST.get('event_id') or (not event.is_system and event.enterprise_id is not None and event.enterprise_id != self.enterprise_id))
     order = None
     note = self.request.POST.get('note')
     if self.request.POST.get('order_id'):
         order = CustomerOrder.load(self.request.POST.get('order_id'))
         self.forbid_if(not order or order.campaign.company.enterprise_id != self.enterprise_id)
         Status.add(customer, order, event, note, self.request.ctx.user)
         self.flash('Statused Order to %s' % event.display_name)
     elif self.request.POST.get('order_item_id'):
         order_item = OrderItem.load(self.request.POST.get('order_item_id'))
         self.forbid_if(not order_item or order_item.order.campaign.company.enterprise_id != self.enterprise_id)
         Status.add(customer, order_item, event, note, self.request.ctx.user)
         self.flash('Statused Item to %s' % event.display_name)
     else:
         Status.add(customer, customer, event, note, self.request.ctx.user)
         self.flash('Statused Customer to %s' % event.display_name)
     customer.invalidate_caches()
     return self.find_redirect()
Example #26
0
    def edit_order(self):   #pylint: disable-msg=R0915,R0912
        customer_id = self.request.matchdict.get('customer_id')
        order_id = self.request.matchdict.get('order_id')
        oids_to_delete = self.request.POST.getall('order_items_to_delete[]')
        customer = Customer.load(customer_id)
        self.forbid_if(not customer or customer.campaign.company.enterprise_id != self.enterprise_id)
        order = customer.get_order(order_id)
        self.forbid_if(not order)
        order.shipping_total = self.request.POST.get('shipping_total') if self.request.POST.get('shipping_total') else 0.0
        order.create_dt = self.request.POST.get('create_dt') if self.request.POST.get('create_dt') else order.create_dt
        order.save()

        total_payments_applied = order.total_payments_applied()

        for oid in oids_to_delete:
            oitem = OrderItem.load(oid)
            Status.add(customer, oitem, Status.find_event(self.enterprise_id, oitem, 'DELETED'), 'OrderItem deleted ')
            prod = oitem.product
            if prod.track_inventory:
                InventoryJournal.create_new(prod, 'Cancelled Item', oitem.quantity, oitem)
            for attr_kid in oitem.children:
                Status.add(customer, attr_kid, Status.find_event(self.enterprise_id, attr_kid, 'DELETED'), 'OrderItem deleted ')
                attr_kid_prod = attr_kid.product
                if attr_kid_prod.track_inventory:
                    InventoryJournal.create_new(attr_kid_prod, 'Cancelled Item', oitem.quantity, attr_kid)
                attr_kid.soft_delete()
            oitem.soft_delete()                

        # extract order_items[27][quantity] to set those properties.
        order_items = {}
        for key in self.request.POST.keys():
            if key.startswith('order_items'):
                match = re.search(r'^.*\[(.*)\]\[(.*)\]', key)
                if match:
                    order_item_id = match.group(1)
                    attr = match.group(2)
                    new_val = float(self.request.POST.get(key)) if attr != 'product_id' else self.request.POST.get(key)
                    # KB: [2011-03-07]: If the ID ends in '_', its not really an ID but a new item.
                    # product_id will only show up as non-null in the hash of a new product
                    if order_item_id[-1] == '_':
                        order_item_product = Product.load(self.request.POST.get('order_items[%s][product_id]' % order_item_id))
                        if not order_items.has_key(order_item_id):
                            order_items[order_item_id] = order.augment_order(customer,
                                                                             order_item_product,
                                                                             customer.campaign,
                                                                             self.request.ctx.user)
                        oitem = order_items[order_item_id]
                        assert oitem.product is not None
                        if 'quantity' == attr:
                            new_val = float(new_val)
                            if order_item_product.track_inventory:
                                InventoryJournal.create_new(order_item_product, 'Sale', new_val, oitem)
                        setattr(oitem, attr, new_val)
                        oitem.save()
                    else:
                        if not order_items.has_key(order_item_id):
                            order_items[order_item_id] = OrderItem.load(order_item_id)
                        oitem = order_items[order_item_id]
                        order_item_product = oitem.product

                        if util.money(getattr(oitem, attr)) != util.money(new_val):
                            Status.add(customer, oitem, Status.find_event(self.enterprise_id, oitem, 'MODIFIED'),
                                       'Order Item modified: (id=%s). %s : %s -> %s' % (oitem.order_item_id, attr, util.money(getattr(oitem, attr)), util.money(new_val)))
                        if 'quantity' == attr:
                            new_val = float(new_val)
                            if not total_payments_applied:
                                if order_item_product.track_inventory:
                                    InventoryJournal.cleanup(oitem, 'Sale')
                                    InventoryJournal.create_new(order_item_product, 'Sale', new_val, oitem)
                        setattr(oitem, attr, new_val)
                        oitem.save()
        Status.add(customer, order, Status.find_event(self.enterprise_id, order, 'MODIFIED'), 'Order modified')
        customer.invalidate_caches()
        self.flash("Saved Order")
        return 'True'
Example #27
0
    def create_new(cart, customer, enterprise_id, campaign, user_created, order_note=None, incl_tax=True):
        """ KB: [2010-09-09]: Given a cart full of products, create a new order and return it.
        if a given product is a parent, then create an kid order_item of zero cost and attach it to the parent.
        """
        cord = CustomerOrder()
        cord.creator = user_created
        cord.customer = customer
        cord.campaign = campaign
        cord.shipping_total = util.nvl(cart.shipping_total, 0.0)
        cord.shipping_note = cart.shipping_selection_name
        cord.handling_total = util.nvl(cart.handling_total, 0.0)
        cord.shipping_addr1 = cart.shipping_addr1
        cord.shipping_addr2 = cart.shipping_addr2
        cord.shipping_city = cart.shipping_city
        cord.shipping_state = cart.shipping_state
        cord.shipping_zip = cart.shipping_zip
        cord.shipping_country = cart.shipping_country
        cord.shipping_phone = cart.shipping_phone
        cart.calculate_cart_discount_for_order(cord)
        cord.note = order_note
        cord.save()
        cord.flush()
        for cart_item in cart.items:
            prd = Product.load(cart_item["product"].product_id)
            item = OrderItem()
            item.order = cord
            item.product = prd
            item.creator = user_created
            item.start_dt = cart_item["start_dt"]
            item.note = cart_item["note"]
            item.save()
            item.flush()

            attribute_order_items = []
            for attribute_product_id in cart_item["attributes"].keys():
                attribute_order_item = OrderItem()
                attribute_order_item.parent_id = item.order_item_id
                attribute_order_item.order = cord
                ao_prd = Product.load(attribute_product_id)
                attribute_order_item.product = ao_prd
                attribute_order_item.creator = user_created
                attribute_order_item.unit_cost = ao_prd.unit_cost
                attribute_order_item.unit_discount_price = ao_prd.get_discount_price(campaign)
                attribute_order_item.unit_retail_price = ao_prd.get_retail_price(campaign)
                attribute_order_item.quantity = cart_item["attributes"][attribute_product_id]["quantity"]
                attribute_order_item.save()
                attribute_order_items.append(attribute_order_item)

            # KB: [2013-02-24]: Discount is calculated by using the highest price of the discounts for the product and all of its selected attributes
            discount = max(
                [util.nvl(aois.unit_discount_price) for aois in attribute_order_items]
                + [prd.get_discount_price(campaign)]
            )
            # KB: [2013-02-24]: Retail is calculated by using the highest price of the retail prices for the product and all its selected attributes.
            retail = max(
                [util.nvl(aois.unit_retail_price, 0.0) for aois in attribute_order_items]
                + [cart_item["base_price"] if "base_price" in cart_item else prd.get_retail_price(campaign)]
            )

            item.quantity = float(cart_item["quantity"])
            item.unit_price = discount if discount else retail
            if campaign.tax_rate and incl_tax:
                item.tax = (item.unit_price * item.quantity) * campaign.tax_rate
            item.unit_cost = prd.unit_cost
            item.unit_discount_price = discount if discount else None
            item.unit_retail_price = retail
            item.save()
            if prd.track_inventory:
                InventoryJournal.create_new(prd, "Sale", int(item.quantity), item)
            if item.unit_discount_price is not None:
                discount = DiscountProduct.find_by_product(prd)
                Journal.create_new(
                    (item.unit_retail_price - item.unit_discount_price) * int(item.quantity),
                    customer,
                    cord,
                    None,
                    typ="AutomaticDiscount",
                    attachment=discount,
                )
            Status.add(
                customer,
                item,
                Status.find_event(enterprise_id, item, "CREATED"),
                "Item added to order %s @ $%s" % (prd.name, util.money(item.unit_price)),
            )
            if prd.can_have_children():
                item.flush()  # we need this to get the parent ID.
                children = prd.get_children()
                if children and len(children) > 0:
                    for kid in children:
                        child_item = OrderItem()
                        child_item.order = cord
                        child_item.parent_id = item.order_item_id
                        child_item.product = kid.child
                        child_item.creator = user_created
                        child_item.start_dt = cart_item["start_dt"]
                        child_item.unit_price = 0.0
                        child_item.unit_discount_price = None
                        child_item.unit_retail_price = 0.0
                        child_item.unit_cost = prd.unit_cost
                        child_item.quantity = kid.child_quantity
                        if kid.child.track_inventory:
                            InventoryJournal.create_new(kid.child, "Sale", child_item.quantity, child_item)
        Status.add(customer, cord, Status.find_event(enterprise_id, cord, "CREATED"), "Order created ")
        if cord.discount:
            discount_amount = None
            if cord.discount.percent_off:
                item_price = cord.total_item_price()
                discount_amount = item_price - (item_price * cord.discount.percent_off)
            elif cord.discount.shipping_percent_off:
                # (9.0 / (1.0-0.1)) = 10.00
                discount_amount = cart.shipping_discount_total
            if discount_amount and int(discount_amount) > 0:
                Journal.create_new(
                    discount_amount, customer, cord, None, typ="AutomaticDiscount", attachment=cord.discount
                )
        cord.save()
        cord.flush()
        return cord