예제 #1
0
def close_order_delivery(permanence,
                         delivery,
                         all_producers,
                         producers_id=None):
    from repanier.apps import REPANIER_SETTINGS_CUSTOMERS_MUST_CONFIRM_ORDERS
    getcontext().rounding = ROUND_HALF_UP
    if REPANIER_SETTINGS_CUSTOMERS_MUST_CONFIRM_ORDERS:
        # Cancel unconfirmed purchases whichever the producer is
        customer_invoice_qs = CustomerInvoice.objects.filter(
            permanence_id=permanence.id,
            delivery=delivery,
            is_order_confirm_send=False,
            total_price_with_tax__gt=DECIMAL_ZERO,
        )
        for customer_invoice in customer_invoice_qs:
            customer_invoice.delete_if_unconfirmed(permanence)
    if all_producers:
        # 1 - Do not round to multiple producer_order_by_quantity
        # 2 - Do not add Transport
        for customer in Customer.objects.filter(
                is_active=True,
                may_order=True,
                customerinvoice__permanence_id=permanence.id,
                customerinvoice__delivery=delivery,
                customerinvoice__total_price_with_tax__gt=DECIMAL_ZERO,
                represent_this_buyinggroup=False).order_by('?'):
            # 3 - Add Deposit
            for offer_item in OfferItem.objects.filter(
                    permanence_id=permanence.id,
                    order_unit=PRODUCT_ORDER_UNIT_DEPOSIT).order_by('?'):
                create_or_update_one_purchase(
                    customer.id,
                    offer_item,
                    q_order=1,
                    permanence_date=permanence.permanence_date,
                    batch_job=True,
                    is_box_content=False)
                create_or_update_one_purchase(
                    customer.id,
                    offer_item,
                    q_order=0,
                    permanence_date=permanence.permanence_date,
                    batch_job=True,
                    is_box_content=False)

    delivery.set_status(PERMANENCE_CLOSED, all_producers, producers_id)
예제 #2
0
def import_invoice_sheet(worksheet, invoice_reference=EMPTY_STRING,
                         customer_2_id_dict=None,
                         producer=None
                         ):
    error = False
    error_msg = None
    header = get_header(worksheet)
    if header:
        now = timezone.now().date()
        lut_reverse_vat = dict(LUT_ALL_VAT_REVERSE)
        import_counter = 0
        row_num = 1
        sid = transaction.savepoint()
        try:

            permanence = Permanence.objects.create(
                permanence_date=now,
                short_name=invoice_reference,
                status=PERMANENCE_SEND,
                highest_status=PERMANENCE_SEND
            )
            permanence.producers.add(producer)
            row = get_row(worksheet, header, row_num)
            while row and not error:
                customer_name = row[_("Customer")]
                if customer_name:
                    if customer_name in customer_2_id_dict:
                        customer_id = customer_2_id_dict[customer_name]
                    else:
                        error = True
                        error_msg = _("Row %(row_num)d : No valid customer") % {'row_num': row_num + 1}
                        break
                    product_reference = row[_("Reference")] or EMPTY_STRING
                    unit = row[_("Unit")]
                    order_unit = get_reverse_invoice_unit(unit)
                    vat = row[_("VAT level")]
                    vat_level = lut_reverse_vat[vat]
                    product = Product.objects.filter(producer_id=producer.id, reference=product_reference).order_by(
                        '?').first()
                    if product is None:
                        product = Product.objects.create(
                            producer=producer,
                            reference=product_reference,
                        )
                    long_name = row[_("Product")]
                    # The producer unit price is the imported customer unit price
                    # If the group get a reduction, this one must be mentioned into the producer admin screen
                    # into the "price_list_multiplier" field
                    product.producer_unit_price = row[_("Customer unit price")]
                    product.unit_deposit = row[_("Deposit")]
                    product.order_unit = order_unit
                    product.vat_level = vat_level
                    product.wrapped = row[_("Wrapped")]
                    qty_and_price_display = product.get_qty_and_price_display(customer_price=False)
                    if long_name.endswith(qty_and_price_display):
                        long_name = long_name[:-len(qty_and_price_display)]
                    product.long_name = long_name[:100]
                    product.save()
                    offer_item = product.get_or_create_offer_item(permanence)
                    create_or_update_one_purchase(
                        customer_id=customer_id,
                        offer_item=offer_item,
                        status=PERMANENCE_SEND,
                        q_order=Decimal(row[_("Quantity")]),
                        batch_job=True, is_box_content=False,
                        comment=row[_("Comment")] or EMPTY_STRING
                    )
                    import_counter += 1

                row_num += 1
                row = get_row(worksheet, header, row_num)
            reorder_offer_items(permanence.id)
            reorder_purchases(permanence.id)

        except KeyError as e:
            # Missing field
            error = True
            error_msg = _("Row %(row_num)d : A required column is missing %(error_msg)s.") % {
                'row_num': row_num + 1, 'error_msg': str(e)}
        except Exception as e:
            error = True
            error_msg = _("Row %(row_num)d : %(error_msg)s.") % {'row_num': row_num + 1, 'error_msg': str(e)}
        if not error and import_counter == 0:
            error = True
            error_msg = "{}".format(_("Nothing to import."))
        if error:
            transaction.savepoint_rollback(sid)
        else:
            transaction.savepoint_commit(sid)
    return error, error_msg
예제 #3
0
def import_invoice_sheet(worksheet, invoice_reference=EMPTY_STRING,
                         customer_2_id_dict=None,
                         producer=None
                         ):
    error = False
    error_msg = None
    header = get_header(worksheet)
    if header:
        now = timezone.now().date()
        lut_reverse_vat = dict(LUT_ALL_VAT_REVERSE)
        import_counter = 0
        row_num = 1
        sid = transaction.savepoint()
        try:

            permanence = Permanence.objects.create(
                permanence_date=now,
                short_name=invoice_reference,
                status=PERMANENCE_SEND,
                highest_status=PERMANENCE_SEND
            )
            permanence.producers.add(producer)
            row = get_row(worksheet, header, row_num)
            while row and not error:
                customer_name = row[_("Customer")]
                if customer_name:
                    if customer_name in customer_2_id_dict:
                        customer_id = customer_2_id_dict[customer_name]
                    else:
                        error = True
                        error_msg = _("Row %(row_num)d : No valid customer") % {'row_num': row_num + 1}
                        break
                    product_reference = row[_("Reference")] or EMPTY_STRING
                    unit = row[_("Unit")]
                    order_unit = get_reverse_invoice_unit(unit)
                    vat = row[_("VAT level")]
                    vat_level = lut_reverse_vat[vat]
                    product = Product.objects.filter(producer_id=producer.id, reference=product_reference).order_by(
                        '?').first()
                    if product is None:
                        product = Product.objects.create(
                            producer=producer,
                            reference=product_reference,
                        )
                    long_name = row[_("Product")]
                    # The producer unit price is the imported customer unit price
                    # If the group get a reduction, this one must be mentioned into the producer admin screen
                    # into the "price_list_multiplier" field
                    product.producer_unit_price = row[_("Customer unit price")]
                    product.unit_deposit = row[_("Deposit")]
                    product.order_unit = order_unit
                    product.vat_level = vat_level
                    product.wrapped = row[_("Wrapped")]
                    qty_and_price_display = product.get_qty_and_price_display(customer_price=False)
                    if long_name.endswith(qty_and_price_display):
                        long_name = long_name[:-len(qty_and_price_display)]
                    product.long_name = long_name[:100]
                    product.save()
                    offer_item = product.get_or_create_offer_item(permanence, reset_add_2_stock=True)
                    create_or_update_one_purchase(
                        customer_id=customer_id,
                        offer_item=offer_item,
                        status=PERMANENCE_SEND,
                        q_order=Decimal(row[_("Quantity")]),
                        batch_job=True, is_box_content=False,
                        comment=row[_("Comment")] or EMPTY_STRING
                    )
                    import_counter += 1

                row_num += 1
                row = get_row(worksheet, header, row_num)
            reorder_offer_items(permanence.id)
            reorder_purchases(permanence.id)

        except KeyError as e:
            # Missing field
            error = True
            error_msg = _("Row %(row_num)d : A required column is missing %(error_msg)s.") % {
                'row_num': row_num + 1, 'error_msg': str(e)}
        except Exception as e:
            error = True
            error_msg = _("Row %(row_num)d : %(error_msg)s.") % {'row_num': row_num + 1, 'error_msg': str(e)}
        if not error and import_counter == 0:
            error = True
            error_msg = "{}".format(_("Nothing to import."))
        if error:
            transaction.savepoint_rollback(sid)
        else:
            transaction.savepoint_commit(sid)
    return error, error_msg
예제 #4
0
def close_order(permanence, all_producers, producers_id=None):
    getcontext().rounding = ROUND_HALF_UP
    today = timezone.now().date()

    if repanier.apps.REPANIER_SETTINGS_CUSTOMERS_MUST_CONFIRM_ORDERS:
        # 0 - Cancel unconfirmed purchases
        purchase_qs = Purchase.objects.filter(
            permanence_id=permanence.id,
            customer_invoice__is_order_confirm_send=False,
            is_box_content=False
        ).exclude(
            quantity_ordered=DECIMAL_ZERO
        ).order_by('customer_invoice')
        if not all_producers:
            purchase_qs = purchase_qs.filter(producer_id__in=producers_id)
        customer_invoice_id_save = -1
        for purchase in purchase_qs.select_related("customer", "offer_item"):
            if customer_invoice_id_save != purchase.customer_invoice_id:
                customer_invoice_id_save = purchase.customer_invoice_id
                # This order has been cancelled
                # filename = force_filename("%s - %s.xlsx" % (_("Canceled order"), permanence))
                filename = "{0}-{1}.xlsx".format(
                    slugify(_("Canceled order")),
                    slugify(permanence)
                )
                sender_email, sender_function, signature, cc_email_staff = get_signature(
                    is_reply_to_order_email=True)
                export_order_2_1_customer(
                    purchase.customer, filename, permanence, sender_email,
                    sender_function, signature,
                    cancel_order=True)
            update_or_create_purchase(
                customer=purchase.customer,
                offer_item_id=purchase.offer_item.id,
                value_id=DECIMAL_ZERO,
                batch_job=True
            )
    else:
        # 0 - Delete unused purchases
        purchase_qs = Purchase.objects.filter(
            permanence_id=permanence.id,
            quantity_ordered=0
        ).order_by('?')
        if not all_producers:
            purchase_qs = purchase_qs.filter(producer_id__in=producers_id)
        purchase_qs.delete()
    # 1 - Round to multiple producer_order_by_quantity
    offer_item_qs = OfferItem.objects.filter(
        permanence_id=permanence.id,
        is_active=True,
        order_unit__lt=PRODUCT_ORDER_UNIT_DEPOSIT,
        producer_order_by_quantity__gt=1,
        quantity_invoiced__gt=0
    ).order_by('?')
    if not all_producers:
        offer_item_qs = offer_item_qs.filter(producer_id__in=producers_id)
    for offer_item in offer_item_qs:
        # It's possible to round the ordered qty even If we do not manage stock
        if offer_item.manage_replenishment:
            needed = (offer_item.quantity_invoiced - offer_item.stock)
        else:
            needed = offer_item.quantity_invoiced
        if needed > DECIMAL_ZERO:
            offer_item.add_2_stock = offer_item.producer_order_by_quantity - (
            needed % offer_item.producer_order_by_quantity)
            offer_item.save()
    # 2 - Add Transport
    offer_item_qs = OfferItem.objects.filter(
        permanence_id=permanence.id,
        is_active=False,
        order_unit=PRODUCT_ORDER_UNIT_TRANSPORTATION
    ).order_by('?')
    if not all_producers:
        offer_item_qs = offer_item_qs.filter(producer_id__in=producers_id)
    for offer_item in offer_item_qs:
        buying_group = Customer.objects.filter(is_active=True, represent_this_buyinggroup=True).order_by('?').first()
        create_or_update_one_purchase(buying_group, offer_item, 1, None, True, is_box_content=False)
    membership_fee_product = Product.objects.filter(is_membership_fee=True, is_active=True).order_by('?').first()
    membership_fee_product.producer_unit_price = repanier.apps.REPANIER_SETTINGS_MEMBERSHIP_FEE
    # Update the prices
    membership_fee_product.save()
    membership_fee_offer_item = get_or_create_offer_item(
        permanence, membership_fee_product.id,
        membership_fee_product.producer_id
    )
    for customer in Customer.objects.filter(
            is_active=True,
            may_order=True,
            customerinvoice__permanence_id=permanence.id,
            customerinvoice__total_price_with_tax__gt=DECIMAL_ZERO,
            represent_this_buyinggroup=False
    ).order_by('?'):
        # 3 - Add Deposit
        offer_item_qs = OfferItem.objects.filter(
            permanence_id=permanence.id,
            order_unit=PRODUCT_ORDER_UNIT_DEPOSIT
        ).order_by('?')
        if not all_producers:
            offer_item_qs = offer_item_qs.filter(producer_id__in=producers_id)
        for offer_item in offer_item_qs:
            create_or_update_one_purchase(customer, offer_item, 1, None, True, is_box_content=False)
            create_or_update_one_purchase(customer, offer_item, 0, None, True, is_box_content=False)
        # 4 - Add Add Membership fee Subscription
        if repanier.apps.REPANIER_SETTINGS_MEMBERSHIP_FEE_DURATION > 0:
            # There is a membership fee
            if customer.membership_fee_valid_until < today:
                permanence.producers.add(membership_fee_offer_item.producer_id)
                create_or_update_one_purchase(customer, membership_fee_offer_item, 1, None, True, is_box_content=False)
                while customer.membership_fee_valid_until < today:
                    # Do not pay the membership fee if no order passed during a certain amount of time
                    customer.membership_fee_valid_until = add_months(
                        customer.membership_fee_valid_until,
                        repanier.apps.REPANIER_SETTINGS_MEMBERSHIP_FEE_DURATION
                    )
                customer.save(update_fields=['membership_fee_valid_until', ])

    # 5 - Add Common participation Subscription
    if all_producers:
        for offer_item in OfferItem.objects.filter(
                permanence_id=permanence.id, is_membership_fee=False,
                order_unit=PRODUCT_ORDER_UNIT_SUBSCRIPTION
        ).order_by('?'):
            for customer in Customer.objects.filter(
                    is_active=True, may_order=True,
                    represent_this_buyinggroup=False
            ).order_by('?'):
                permanence.producers.add(offer_item.producer_id)
                create_or_update_one_purchase(customer, offer_item, 1, None, True, is_box_content=False)
        # Disable subscription for next permanence
        Product.objects.filter(
            order_unit=PRODUCT_ORDER_UNIT_SUBSCRIPTION, is_into_offer=True, is_membership_fee=False
        ).order_by('?').update(is_into_offer=False)

        permanence.set_status(PERMANENCE_CLOSED, allow_downgrade=False)
        if not repanier.apps.REPANIER_SETTINGS_INVOICE and repanier.apps.REPANIER_SETTINGS_BANK_ACCOUNT is None:
            # No Invoice and no bank_account --> auto archive
            # Put send permanences to the done status, because they will "never" be invoiced
            for permanence in Permanence.objects.filter(status=PERMANENCE_SEND):
                permanence.set_status(PERMANENCE_ARCHIVED, update_payment_date=True)
    else:
        permanence.set_status(PERMANENCE_CLOSED, all_producers=all_producers, producers_id=producers_id)
    # 6 - Refresh the Purchase 'sum' for each customer
    recalculate_order_amount(
        permanence_id=permanence.id,
        all_producers=all_producers,
        producers_id=producers_id,
        send_to_producer=False,
    )
예제 #5
0
def close_order_delivery(permanence, delivery, all_producers, producers_id=None):
    today = timezone.now().date()
    getcontext().rounding = ROUND_HALF_UP
    # 0 - Delete unused purchases
    # No need to select : customer_invoice__delivery = delivery
    Purchase.objects.filter(
        permanence_id=permanence.id,
        quantity_ordered=0
    ).order_by('?').delete()
    if repanier.apps.REPANIER_SETTINGS_CUSTOMERS_MUST_CONFIRM_ORDERS:
        purchase_qs = Purchase.objects.filter(
            permanence_id=permanence.id,
            customer_invoice__delivery=delivery,
            customer_invoice__is_order_confirm_send=False,
            is_box_content=False
        ).exclude(
            quantity_ordered=DECIMAL_ZERO
        ).order_by('customer_invoice')
        if not all_producers:
            # This may never be the but, but...
            purchase_qs = purchase_qs.filter(producer_id__in=producers_id)
        customer_invoice_id_save = -1
        for purchase in purchase_qs.select_related("customer", "offer_item"):
            if customer_invoice_id_save != purchase.customer_invoice_id:
                customer_invoice_id_save =purchase.customer_invoice_id
                # This order has been cancelled
                # filename = force_filename("%s - %s.xlsx" % (_("Canceled order"), permanence))
                filename = "{0}-{1}.xlsx".format(
                    slugify(_("Canceled order")),
                    slugify(permanence)
                )
                sender_email, sender_function, signature, cc_email_staff = get_signature(
                    is_reply_to_order_email=True)
                export_order_2_1_customer(
                    purchase.customer, filename, permanence, sender_email,
                    sender_function, signature,
                    cancel_order=True)
            update_or_create_purchase(
                customer=purchase.customer,
                offer_item_id=purchase.offer_item.id,
                value_id=DECIMAL_ZERO,
                batch_job=True
            )
    if all_producers:
        # 1 - Do not round to multiple producer_order_by_quantity
        # 2 - Do not add Transport
        membership_fee_product = Product.objects.filter(is_membership_fee=True, is_active=True).order_by('?').first()
        membership_fee_product.producer_unit_price = repanier.apps.REPANIER_SETTINGS_MEMBERSHIP_FEE
        # Update the prices
        membership_fee_product.save()
        membership_fee_offer_item = get_or_create_offer_item(permanence, membership_fee_product.id,
                                                             membership_fee_product.producer_id)
        for customer in Customer.objects.filter(
                is_active=True, may_order=True,
                customerinvoice__permanence_id=permanence.id,
                customerinvoice__delivery=delivery,
                customerinvoice__total_price_with_tax__gt=DECIMAL_ZERO,
                represent_this_buyinggroup=False
        ).order_by('?'):
            # 3 - Add Deposit
            for offer_item in OfferItem.objects.filter(permanence_id=permanence.id,  # is_active=False,
                                                       order_unit=PRODUCT_ORDER_UNIT_DEPOSIT).order_by('?'):
                permanence.producers.add(offer_item.producer_id)
                create_or_update_one_purchase(customer, offer_item, 1, None, True, is_box_content=False)
                create_or_update_one_purchase(customer, offer_item, 0, None, True, is_box_content=False)
            # 4 - Add Membership fee Subscription
            if repanier.apps.REPANIER_SETTINGS_MEMBERSHIP_FEE_DURATION > 0:
                # There is a membership fee
                if customer.membership_fee_valid_until < today:
                    permanence.producers.add(membership_fee_offer_item.producer_id)
                    create_or_update_one_purchase(customer, membership_fee_offer_item, 1, None, True,
                                                  is_box_content=False)
                    customer.membership_fee_valid_until = add_months(
                        customer.membership_fee_valid_until,
                        repanier.apps.REPANIER_SETTINGS_MEMBERSHIP_FEE_DURATION
                    )
                    customer.save(update_fields=['membership_fee_valid_until', ])
        # 5 - Add Common participation Subscription
        for offer_item in OfferItem.objects.filter(
                permanence_id=permanence.id, is_membership_fee=False,
                order_unit=PRODUCT_ORDER_UNIT_SUBSCRIPTION).order_by('?'):
            for customer in Customer.objects.filter(is_active=True, may_order=True,
                                                    represent_this_buyinggroup=False).order_by('?'):
                permanence.producers.add(offer_item.producer_id)
                create_or_update_one_purchase(customer, offer_item, 1, None, True, is_box_content=False)
    # 6 - Refresh the Purchase 'sum'
    recalculate_order_amount(
        permanence_id=permanence.id,
        all_producers=all_producers,
        producers_id=producers_id,
        send_to_producer=False
    )
    delivery.set_status(PERMANENCE_CLOSED, all_producers, producers_id)
예제 #6
0
def close_order(permanence, all_producers, producers_id=None):
    from repanier.apps import REPANIER_SETTINGS_CUSTOMERS_MUST_CONFIRM_ORDERS
    getcontext().rounding = ROUND_HALF_UP
    if REPANIER_SETTINGS_CUSTOMERS_MUST_CONFIRM_ORDERS:
        # Cancel unconfirmed purchases whichever the producer is
        customer_invoice_qs = CustomerInvoice.objects.filter(
            permanence_id=permanence.id,
            is_order_confirm_send=False,
            total_price_with_tax__gt=DECIMAL_ZERO,
        )
        for customer_invoice in customer_invoice_qs:
            customer_invoice.delete_if_unconfirmed(permanence)
    # 1 - Round to multiple producer_order_by_quantity
    offer_item_qs = OfferItem.objects.filter(
        permanence_id=permanence.id,
        is_active=True,
        order_unit__lt=PRODUCT_ORDER_UNIT_DEPOSIT,
        producer_order_by_quantity__gt=1,
        quantity_invoiced__gt=0).order_by('?')
    if not all_producers:
        offer_item_qs = offer_item_qs.filter(producer_id__in=producers_id)
    for offer_item in offer_item_qs:
        # It's possible to round the ordered qty even If we do not manage stock
        if offer_item.manage_replenishment:
            needed = (offer_item.quantity_invoiced - offer_item.stock)
        else:
            needed = offer_item.quantity_invoiced
        if needed > DECIMAL_ZERO:
            offer_item.add_2_stock = offer_item.producer_order_by_quantity - (
                needed % offer_item.producer_order_by_quantity)
            offer_item.save()
    # 2 - Add Transport
    offer_item_qs = OfferItem.objects.filter(
        permanence_id=permanence.id,
        is_active=False,
        order_unit=PRODUCT_ORDER_UNIT_TRANSPORTATION).order_by('?')
    if not all_producers:
        offer_item_qs = offer_item_qs.filter(producer_id__in=producers_id)
    for offer_item in offer_item_qs:
        buying_group = Customer.objects.filter(
            is_active=True,
            represent_this_buyinggroup=True).order_by('?').first()
        create_or_update_one_purchase(
            buying_group.id,
            offer_item,
            q_order=1,
            permanence_date=permanence.permanence_date,
            batch_job=True,
            is_box_content=False)
    for customer in Customer.objects.filter(
            is_active=True,
            may_order=True,
            customerinvoice__permanence_id=permanence.id,
            customerinvoice__total_price_with_tax__gt=DECIMAL_ZERO,
            represent_this_buyinggroup=False).order_by('?'):
        # 3 - Add Deposit
        offer_item_qs = OfferItem.objects.filter(
            permanence_id=permanence.id,
            order_unit=PRODUCT_ORDER_UNIT_DEPOSIT).order_by('?')
        if not all_producers:
            offer_item_qs = offer_item_qs.filter(producer_id__in=producers_id)
        for offer_item in offer_item_qs:
            create_or_update_one_purchase(
                customer.id,
                offer_item,
                q_order=1,
                permanence_date=permanence.permanence_date,
                batch_job=True,
                is_box_content=False)
            create_or_update_one_purchase(
                customer.id,
                offer_item,
                q_order=0,
                permanence_date=permanence.permanence_date,
                batch_job=True,
                is_box_content=False)

    if all_producers:
        permanence.set_status(PERMANENCE_CLOSED, allow_downgrade=False)
        if not repanier.apps.REPANIER_SETTINGS_INVOICE and repanier.apps.REPANIER_SETTINGS_BANK_ACCOUNT is None:
            # No Invoice and no bank_account --> auto archive
            # Put send permanences to the done status, because they will "never" be invoiced
            for permanence in Permanence.objects.filter(
                    status=PERMANENCE_SEND):
                permanence.set_status(PERMANENCE_ARCHIVED,
                                      update_payment_date=True)
    else:
        permanence.set_status(PERMANENCE_CLOSED,
                              all_producers=all_producers,
                              producers_id=producers_id)