Dev - A new way to create invoices from shipments

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

Dev - A new way to create invoices from shipments

Jacopo Cappellato
Hi all,

I'll need to implement a new way to create invoices from sales shipments.

If I'm not wrong, right now in OFBiz you can create invoices in two ways:

a) from an orderId: the createInvoiceForOrder service is used
b) from a shipmentId: the createInvoicesFromShipment service is used,
this service internally calls the createInvoiceForOrder service for each
of the orders associated to the shipment

The new way I'm going to implement is this:

c) from a set of shipment ids: I'd like to call a modified version of
the createInvoicesFromShipment service

The main difference between method c and b is that if an order is
shipped with two shipments and I pass the two shipment ids to the
service of point c, I'll get ONE invoice (instead of TWO with method b)
for the order containing all the items shipped in the two shipments.

I've modified the createInvoicesFromShipment service to accept as an
optional input parameter a List of shipmentIds: then all the
ItemIssuances associated to the shipments are selected (instead of only
the ItemIssuances associated to one shipment); then the logic is EXACTLY
the same.
I'm I'm testing it right now and it seems to work pretty well.

How to trigger this service?
I'd like to add a new shipment status to mark all the shipments that are
ready to be invoiced; then a new service can be run that:
1) selects all the shipments in this status and puts thir ids in a List
2) calls the modified version of the createInvoicesFromShipment passing
the List to it
3) updates the shipments' status to mark them as invoiced/completed


What do you think of this?

Jacopo

 
_______________________________________________
Dev mailing list
[hidden email]
http://lists.ofbiz.org/mailman/listinfo/dev
Reply | Threaded
Open this post in threaded view
|

Re: Dev - A new way to create invoices from shipments

cjhowe
While many small businesses do create one invoice from
multiple shipments, it is precisely because they do
not use an ERP application.  Providing a single
invoice for multiple shipments inside an ERP
application is a bad practice as time lapses between
the first shipment and an invoice being created.  This
lapse is prone to be overlooked and should be avoided
especially when you have the capabilities that an ERP
system provides.

--- Jacopo Cappellato <[hidden email]> wrote:

> Hi all,
>
> I'll need to implement a new way to create invoices
> from sales shipments.
>
> If I'm not wrong, right now in OFBiz you can create
> invoices in two ways:
>
> a) from an orderId: the createInvoiceForOrder
> service is used
> b) from a shipmentId: the createInvoicesFromShipment
> service is used,
> this service internally calls the
> createInvoiceForOrder service for each
> of the orders associated to the shipment
>
> The new way I'm going to implement is this:
>
> c) from a set of shipment ids: I'd like to call a
> modified version of
> the createInvoicesFromShipment service
>
> The main difference between method c and b is that
> if an order is
> shipped with two shipments and I pass the two
> shipment ids to the
> service of point c, I'll get ONE invoice (instead of
> TWO with method b)
> for the order containing all the items shipped in
> the two shipments.
>
> I've modified the createInvoicesFromShipment service
> to accept as an
> optional input parameter a List of shipmentIds: then
> all the
> ItemIssuances associated to the shipments are
> selected (instead of only
> the ItemIssuances associated to one shipment); then
> the logic is EXACTLY
> the same.
> I'm I'm testing it right now and it seems to work
> pretty well.
>
> How to trigger this service?
> I'd like to add a new shipment status to mark all
> the shipments that are
> ready to be invoiced; then a new service can be run
> that:
> 1) selects all the shipments in this status and puts
> thir ids in a List
> 2) calls the modified version of the
> createInvoicesFromShipment passing
> the List to it
> 3) updates the shipments' status to mark them as
> invoiced/completed
>
>
> What do you think of this?
>
> Jacopo
>
>  
> _______________________________________________
> Dev mailing list
> [hidden email]
> http://lists.ofbiz.org/mailman/listinfo/dev
>

 
_______________________________________________
Dev mailing list
[hidden email]
http://lists.ofbiz.org/mailman/listinfo/dev
Reply | Threaded
Open this post in threaded view
|

Re: Dev - A new way to create invoices from shipments

Daniel Goodwin
In reply to this post by Jacopo Cappellato
 From my experience, I have seen both
In defence of Jacopo ...
Take for example a large manufacturing company which
may distribute raw
materials (sand gravel etc) to building industry.
Where a large building firm may get 20+ loads a day
from manufacturing
firm, they dont want 20+ invoices and much prefer what
they refer to as
consolidated invoicing as Jacopo is suggesting where a
reference is made
on each line to delivery docket no (shipment ID in
ofbiz).
It also makes printing of invoices cheaper, (less
paper used) and easier
to manage for posting etc.

I dont think Jacopo is advocating its use, just
offering ofbiz users
(customers) the choice.

Daniel

Chris Howe wrote:
> While many small businesses do create one invoice
from
> multiple shipments, it is precisely because they do
> not use an ERP application.  Providing a single
> invoice for multiple shipments inside an ERP
> application is a bad practice as time lapses between
> the first shipment and an invoice being created.
This
> lapse is prone to be overlooked and should be
avoided
> especially when you have the capabilities that an
ERP

> system provides.
>
> --- Jacopo Cappellato <[hidden email]> wrote:
>
>  
>> Hi all,
>>
>> I'll need to implement a new way to create invoices
>> from sales shipments.
>>
>> If I'm not wrong, right now in OFBiz you can create
>> invoices in two ways:
>>
>> a) from an orderId: the createInvoiceForOrder
>> service is used
>> b) from a shipmentId: the
createInvoicesFromShipment

>> service is used,
>> this service internally calls the
>> createInvoiceForOrder service for each
>> of the orders associated to the shipment
>>
>> The new way I'm going to implement is this:
>>
>> c) from a set of shipment ids: I'd like to call a
>> modified version of
>> the createInvoicesFromShipment service
>>
>> The main difference between method c and b is that
>> if an order is
>> shipped with two shipments and I pass the two
>> shipment ids to the
>> service of point c, I'll get ONE invoice (instead
of
>> TWO with method b)
>> for the order containing all the items shipped in
>> the two shipments.
>>
>> I've modified the createInvoicesFromShipment
service
>> to accept as an
>> optional input parameter a List of shipmentIds:
then

>> all the
>> ItemIssuances associated to the shipments are
>> selected (instead of only
>> the ItemIssuances associated to one shipment); then
>> the logic is EXACTLY
>> the same.
>> I'm I'm testing it right now and it seems to work
>> pretty well.
>>
>> How to trigger this service?
>> I'd like to add a new shipment status to mark all
>> the shipments that are
>> ready to be invoiced; then a new service can be run
>> that:
>> 1) selects all the shipments in this status and
puts

>> thir ids in a List
>> 2) calls the modified version of the
>> createInvoicesFromShipment passing
>> the List to it
>> 3) updates the shipments' status to mark them as
>> invoiced/completed
>>
>>
>> What do you think of this?
>>
>> Jacopo
>>
>>  
>> _______________________________________________
>> Dev mailing list
>> [hidden email]
>> http://lists.ofbiz.org/mailman/listinfo/dev
>>
>>    
>
>  
> _______________________________________________
> Dev mailing list
> [hidden email]
> http://lists.ofbiz.org/mailman/listinfo/dev
>
>  


               
___________________________________________________________
Yahoo! Photos – NEW, now offering a quality print service from just 8p a photo http://uk.photos.yahoo.com
 
_______________________________________________
Dev mailing list
[hidden email]
http://lists.ofbiz.org/mailman/listinfo/dev
Reply | Threaded
Open this post in threaded view
|

Re: Dev - A new way to create invoices from shipments

David E. Jones
In reply to this post by Jacopo Cappellato

Jacopo,

It might be more useful to look at this in term of how the user interface will work. I don't think an additional status is really necessary, though I could be wrong. You could use the picked status, or even just show a list of all shipments for an order with a checkbox by each and a submit button to "pack" those orders and thereby trigger the invoicing. Or just use the picked status and have a link that does a basic "pack all picked shipments for this order" thingy.

-David


Jacopo Cappellato wrote:

> Hi all,
>
> I'll need to implement a new way to create invoices from sales shipments.
>
> If I'm not wrong, right now in OFBiz you can create invoices in two ways:
>
> a) from an orderId: the createInvoiceForOrder service is used
> b) from a shipmentId: the createInvoicesFromShipment service is used,
> this service internally calls the createInvoiceForOrder service for each
> of the orders associated to the shipment
>
> The new way I'm going to implement is this:
>
> c) from a set of shipment ids: I'd like to call a modified version of
> the createInvoicesFromShipment service
>
> The main difference between method c and b is that if an order is
> shipped with two shipments and I pass the two shipment ids to the
> service of point c, I'll get ONE invoice (instead of TWO with method b)
> for the order containing all the items shipped in the two shipments.
>
> I've modified the createInvoicesFromShipment service to accept as an
> optional input parameter a List of shipmentIds: then all the
> ItemIssuances associated to the shipments are selected (instead of only
> the ItemIssuances associated to one shipment); then the logic is EXACTLY
> the same.
> I'm I'm testing it right now and it seems to work pretty well.
>
> How to trigger this service?
> I'd like to add a new shipment status to mark all the shipments that are
> ready to be invoiced; then a new service can be run that:
> 1) selects all the shipments in this status and puts thir ids in a List
> 2) calls the modified version of the createInvoicesFromShipment passing
> the List to it
> 3) updates the shipments' status to mark them as invoiced/completed
>
>
> What do you think of this?
>
> Jacopo
>
>  
> _______________________________________________
> Dev mailing list
> [hidden email]
> http://lists.ofbiz.org/mailman/listinfo/dev
 
_______________________________________________
Dev mailing list
[hidden email]
http://lists.ofbiz.org/mailman/listinfo/dev
Reply | Threaded
Open this post in threaded view
|

Re: Dev - A new way to create invoices from shipments

cjhowe
In reply to this post by Daniel Goodwin
Just throwing out this idea...

If you're consolidating invoices, then perhaps each
shipment should have it's own invoice...and then
invoices can have a parent invoice.  This way you're
actually consolidating invoices instead of
consolidating shipments.  In addition, this should be
an option for the product store.  ie Consolidate
invoice on/off

--- Daniel Goodwin <[hidden email]> wrote:

>  From my experience, I have seen both
> In defence of Jacopo ...
> Take for example a large manufacturing company which
> may distribute raw
> materials (sand gravel etc) to building industry.
> Where a large building firm may get 20+ loads a day
> from manufacturing
> firm, they dont want 20+ invoices and much prefer
> what
> they refer to as
> consolidated invoicing as Jacopo is suggesting where
> a
> reference is made
> on each line to delivery docket no (shipment ID in
> ofbiz).
> It also makes printing of invoices cheaper, (less
> paper used) and easier
> to manage for posting etc.
>
> I dont think Jacopo is advocating its use, just
> offering ofbiz users
> (customers) the choice.
>
> Daniel
>
> Chris Howe wrote:
> > While many small businesses do create one invoice
> from
> > multiple shipments, it is precisely because they
> do
> > not use an ERP application.  Providing a single
> > invoice for multiple shipments inside an ERP
> > application is a bad practice as time lapses
> between
> > the first shipment and an invoice being created.
> This
> > lapse is prone to be overlooked and should be
> avoided
> > especially when you have the capabilities that an
> ERP
> > system provides.
> >
> > --- Jacopo Cappellato <[hidden email]> wrote:
> >
> >  
> >> Hi all,
> >>
> >> I'll need to implement a new way to create
> invoices
> >> from sales shipments.
> >>
> >> If I'm not wrong, right now in OFBiz you can
> create
> >> invoices in two ways:
> >>
> >> a) from an orderId: the createInvoiceForOrder
> >> service is used
> >> b) from a shipmentId: the
> createInvoicesFromShipment
> >> service is used,
> >> this service internally calls the
> >> createInvoiceForOrder service for each
> >> of the orders associated to the shipment
> >>
> >> The new way I'm going to implement is this:
> >>
> >> c) from a set of shipment ids: I'd like to call a
> >> modified version of
> >> the createInvoicesFromShipment service
> >>
> >> The main difference between method c and b is
> that
> >> if an order is
> >> shipped with two shipments and I pass the two
> >> shipment ids to the
> >> service of point c, I'll get ONE invoice (instead
> of
> >> TWO with method b)
> >> for the order containing all the items shipped in
> >> the two shipments.
> >>
> >> I've modified the createInvoicesFromShipment
> service
> >> to accept as an
> >> optional input parameter a List of shipmentIds:
> then
> >> all the
> >> ItemIssuances associated to the shipments are
> >> selected (instead of only
> >> the ItemIssuances associated to one shipment);
> then
> >> the logic is EXACTLY
> >> the same.
> >> I'm I'm testing it right now and it seems to work
> >> pretty well.
> >>
> >> How to trigger this service?
> >> I'd like to add a new shipment status to mark all
> >> the shipments that are
> >> ready to be invoiced; then a new service can be
> run
> >> that:
> >> 1) selects all the shipments in this status and
> puts
> >> thir ids in a List
> >> 2) calls the modified version of the
> >> createInvoicesFromShipment passing
> >> the List to it
> >> 3) updates the shipments' status to mark them as
> >> invoiced/completed
> >>
> >>
> >> What do you think of this?
> >>
> >> Jacopo
> >>
> >>  
> >> _______________________________________________
> >> Dev mailing list
> >> [hidden email]
> >> http://lists.ofbiz.org/mailman/listinfo/dev
> >>
> >>    
> >
> >  
> > _______________________________________________
> > Dev mailing list
> > [hidden email]
> > http://lists.ofbiz.org/mailman/listinfo/dev
> >
> >  
>
>
>
>
___________________________________________________________

>
> Yahoo! Photos – NEW, now offering a quality print
> service from just 8p a photo
> http://uk.photos.yahoo.com
>  
> _______________________________________________
> Dev mailing list
> [hidden email]
> http://lists.ofbiz.org/mailman/listinfo/dev
>

 
_______________________________________________
Dev mailing list
[hidden email]
http://lists.ofbiz.org/mailman/listinfo/dev
Reply | Threaded
Open this post in threaded view
|

Re: Dev - A new way to create invoices from shipments

Jacopo Cappellato
In reply to this post by David E. Jones
David,

yes, the additional status is not strictly necessary and I can use the
picked status.
In term of user interface/workflow, this is what I have in mind:

1) the user marks as 'picked' all the shipments that can be invoiced
2) from a (new?) screen in the facility application the user can see all
the picked shipments (maybe select some of them) and create invoices for
them

However, I don't think it's sufficient to move the shipments' status to
packed (and so trigger the existing invoice creation process for each
shipment) because I'd like to create one invoice per order and not one
invoice per shipment/order so I think I'll need to modify the
createInvoicesForShipment service (the new invoice will contain order
items issued to different shipments).

Hmmm... I think I've not well explained what I have in mind... maybe the
attached patch for the beginning of the createInvoicesForShipment
service (the only change needed) will help clarify things.

Thanks for your feedback,

Jacopo


David E. Jones wrote:
> Jacopo,
>
> It might be more useful to look at this in term of how the user interface will work. I don't think an additional status is really necessary, though I could be wrong. You could use the picked status, or even just show a list of all shipments for an order with a checkbox by each and a submit button to "pack" those orders and thereby trigger the invoicing. Or just use the picked status and have a link that does a basic "pack all picked shipments for this order" thingy.
>
> -David
>


@@ -633,6 +644,19 @@
             return ServiceUtil.returnError("Trouble getting Shipment entity");
         }
+        List shipmentIdList = new LinkedList();
+        if (shipmentIds != null) {
+            for (int i = 0; i < shipmentIds.size(); i++) {
+                String tmpShipmentId = (String)shipmentIds.get(i);
+                // TODO: verificare il tipo di shipment (devono essere tutte uguali)
+                shipmentIdList.add(new org.ofbiz.entity.condition.EntityExpr("shipmentId", org.ofbiz.entity.condition.EntityOperator.EQUALS, tmpShipmentId));
+            }
+        }
+        org.ofbiz.entity.condition.EntityConditionList shipmentIdCondList = null;
+        if (!shipmentIdList.isEmpty()){
+            shipmentIdCondList = new org.ofbiz.entity.condition.EntityConditionList(shipmentIdList, org.ofbiz.entity.condition.EntityOperator.OR);
+        }
+
         // check the status of the shipment
 
         // get the items of the shipment.  They can come from ItemIssuance if the shipment were from a sales order or ShipmentReceipt
@@ -642,7 +666,11 @@
             if ((shipment.getString("shipmentTypeId") != null) && (shipment.getString("shipmentTypeId").equals("PURCHASE_SHIPMENT"))) {
                 items = delegator.findByAnd("ShipmentReceipt", UtilMisc.toMap("shipmentId", shipmentId));
             } else {
-                items = delegator.findByAnd("ItemIssuance", UtilMisc.toMap("shipmentId", shipmentId));
+                if (shipmentIdCondList == null) {
+                    items = delegator.findByAnd("ItemIssuance", UtilMisc.toMap("shipmentId", shipmentId));
+                } else {
+                    items = delegator.findByCondition("ItemIssuance", shipmentIdCondList, null, null);
+                }
             }
         } catch (GenericEntityException e) {
             Debug.logError(e, "Problem getting issued items from Shipment [" + shipmentId + "]", module);
 
_______________________________________________
Dev mailing list
[hidden email]
http://lists.ofbiz.org/mailman/listinfo/dev
Reply | Threaded
Open this post in threaded view
|

Re: Dev - A new way to create invoices from shipments

Jacopo Cappellato
In reply to this post by cjhowe
Hi Chris,

I mostly agree with you, however the concept of a 'summary invoice'
(i.e. one invoice for order item issued to different shipments) is
present in many ERP systems.
And in Italy both small and big companies usually create invoices once
every month :-(

Thanks for your feedback,

Jacopo


Chris Howe wrote:

> While many small businesses do create one invoice from
> multiple shipments, it is precisely because they do
> not use an ERP application.  Providing a single
> invoice for multiple shipments inside an ERP
> application is a bad practice as time lapses between
> the first shipment and an invoice being created.  This
> lapse is prone to be overlooked and should be avoided
> especially when you have the capabilities that an ERP
> system provides.
>


 
_______________________________________________
Dev mailing list
[hidden email]
http://lists.ofbiz.org/mailman/listinfo/dev
Reply | Threaded
Open this post in threaded view
|

Re: Dev - A new way to create invoices from shipments

Si Chen-2
In reply to this post by Jacopo Cappellato
Jacopo,

So it seems that you are modifying the service to get ItemIssuance for all the shipmentId in Shipment, instead of looping through each shipmentId, getting its ItemIssuance, and then creating an invoice for it.

I think this is a good feature.  I think it would also be nice to make it configurable somehow?  Ideally I think since yours is a manual process, we can make it so that in the presence of an additional parameter, it would create a single invoice for all shipments.

Also, I think EntityOperator.IN might be a good alternative to all the EntityOperator.EQUALS

Si

Jacopo Cappellato wrote:
David,

yes, the additional status is not strictly necessary and I can use the picked status.
In term of user interface/workflow, this is what I have in mind:

1) the user marks as 'picked' all the shipments that can be invoiced
2) from a (new?) screen in the facility application the user can see all the picked shipments (maybe select some of them) and create invoices for them

However, I don't think it's sufficient to move the shipments' status to packed (and so trigger the existing invoice creation process for each shipment) because I'd like to create one invoice per order and not one invoice per shipment/order so I think I'll need to modify the createInvoicesForShipment service (the new invoice will contain order items issued to different shipments).

Hmmm... I think I've not well explained what I have in mind... maybe the attached patch for the beginning of the createInvoicesForShipment service (the only change needed) will help clarify things.

Thanks for your feedback,

Jacopo


David E. Jones wrote:
Jacopo,

It might be more useful to look at this in term of how the user interface will work. I don't think an additional status is really necessary, though I could be wrong. You could use the picked status, or even just show a list of all shipments for an order with a checkbox by each and a submit button to "pack" those orders and thereby trigger the invoicing. Or just use the picked status and have a link that does a basic "pack all picked shipments for this order" thingy.

-David



@@ -633,6 +644,19 @@ return ServiceUtil.returnError("Trouble getting Shipment entity"); } + List shipmentIdList = new LinkedList(); + if (shipmentIds != null) { + for (int i = 0; i < shipmentIds.size(); i++) { + String tmpShipmentId = (String)shipmentIds.get(i); + // TODO: verificare il tipo di shipment (devono essere tutte uguali) + shipmentIdList.add(new org.ofbiz.entity.condition.EntityExpr("shipmentId", org.ofbiz.entity.condition.EntityOperator.EQUALS, tmpShipmentId)); + } + } + org.ofbiz.entity.condition.EntityConditionList shipmentIdCondList = null; + if (!shipmentIdList.isEmpty()){ + shipmentIdCondList = new org.ofbiz.entity.condition.EntityConditionList(shipmentIdList, org.ofbiz.entity.condition.EntityOperator.OR); + } + // check the status of the shipment // get the items of the shipment. They can come from ItemIssuance if the shipment were from a sales order or ShipmentReceipt @@ -642,7 +666,11 @@ if ((shipment.getString("shipmentTypeId") != null) && (shipment.getString("shipmentTypeId").equals("PURCHASE_SHIPMENT"))) { items = delegator.findByAnd("ShipmentReceipt", UtilMisc.toMap("shipmentId", shipmentId)); } else { - items = delegator.findByAnd("ItemIssuance", UtilMisc.toMap("shipmentId", shipmentId)); + if (shipmentIdCondList == null) { + items = delegator.findByAnd("ItemIssuance", UtilMisc.toMap("shipmentId", shipmentId)); + } else { + items = delegator.findByCondition("ItemIssuance", shipmentIdCondList, null, null); + } } } catch (GenericEntityException e) { Debug.logError(e, "Problem getting issued items from Shipment [" + shipmentId + "]", module);

_______________________________________________ Dev mailing list [hidden email] http://lists.ofbiz.org/mailman/listinfo/dev

 
_______________________________________________
Dev mailing list
[hidden email]
http://lists.ofbiz.org/mailman/listinfo/dev
Reply | Threaded
Open this post in threaded view
|

Re: Dev - A new way to create invoices from shipments

Jacopo Cappellato
What do you all think of the attached patch?

With this patch the "createInvoicesFromShipment" service, that takes as
input the shipmentId, creates a List and puts in it the shipmentId and
then calls the new "createInvoicesFromShipments" service, that takes as
input a list of shipments.
In this way the definition of the existing createInvoicesFromShipment
service is not changed, and there is a new service that can be used to
create summary invoices (and the two services shares the same code).

If you think that this design is good, I'll commit this patch and then
we could go on with the design of the user interface i.e. how to call
the new service.

Jacopo



Index: applications/accounting/servicedef/services_invoice.xml
===================================================================
--- applications/accounting/servicedef/services_invoice.xml (revision 7102)
+++ applications/accounting/servicedef/services_invoice.xml (working copy)
@@ -156,11 +156,25 @@
         location="org.ofbiz.accounting.invoice.InvoiceServices" invoke="createInvoicesFromShipment">
         <description>
             Create invoice(s) from a Shipment
+            All the order items associated with the shipment will be selected and
+            one invoice for each order in the shipment will be created.
             invoicesCreated = List of invoiceIds which were created by this service
         </description>
         <attribute name="shipmentId" type="String" mode="IN" optional="false"/>
         <attribute name="invoicesCreated" type="List" mode="OUT" optional="true"/>
     </service>
+    <service name="createInvoicesFromShipments" engine="java"
+        location="org.ofbiz.accounting.invoice.InvoiceServices" invoke="createInvoicesFromShipment">
+        <description>
+            Create invoice(s) from a shipment list.
+            All the order items associated with the shipments will be selected and
+            one invoice for each order will be created (each invoice could contain
+            items shipped in different shipments).
+            invoicesCreated = List of invoiceIds which were created by this service
+        </description>
+        <attribute name="shipmentIds" type="List" mode="IN" optional="false"/>
+        <attribute name="invoicesCreated" type="List" mode="OUT" optional="true"/>
+    </service>
     <service name="createInvoicesFromReturnShipment" engine="java"
         location="org.ofbiz.accounting.invoice.InvoiceServices" invoke="createInvoicesFromReturnShipment">
         <description>
Index: applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java
===================================================================
--- applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java (revision 7102)
+++ applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java (working copy)
@@ -41,6 +41,9 @@
 import org.ofbiz.entity.GenericDelegator;
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.condition.EntityCondition;
+import org.ofbiz.entity.condition.EntityOperator;
+import org.ofbiz.entity.condition.EntityExpr;
 import org.ofbiz.order.order.OrderReadHelper;
 import org.ofbiz.product.product.ProductWorker;
 import org.ofbiz.service.DispatchContext;
@@ -622,34 +625,67 @@
         GenericDelegator delegator = dctx.getDelegator();
         LocalDispatcher dispatcher = dctx.getDispatcher();
         String shipmentId = (String) context.get("shipmentId");
+        List invoicesCreated = new ArrayList();
+        
+        Map serviceContext = UtilMisc.toMap("shipmentIds", UtilMisc.toList(shipmentId), "userLogin", context.get("userLogin"));
+        try {
+            Map result = dispatcher.runSync("createInvoicesFromShipments", serviceContext);
+            invoicesCreated = (List)result.get("invoicesCreated");
+        } catch (GenericServiceException e) {
+            Debug.logError(e, "Trouble calling createInvoicesFromShipments service; invoice not created for shipment [" + shipmentId + "]", module);
+            return ServiceUtil.returnError("Trouble calling createInvoicesFromShipments service; invoice not created for shipment [" + shipmentId + "]");
+        }
+        Map response = ServiceUtil.returnSuccess();
+        response.put("invoicesCreated", invoicesCreated);
+        return response;
+    }
+    
+    public static Map createInvoicesFromShipments(DispatchContext dctx, Map context) {
+        GenericDelegator delegator = dctx.getDelegator();
+        LocalDispatcher dispatcher = dctx.getDispatcher();
+        List shipmentIds = (List) context.get("shipmentIds");
 
+        boolean salesShipmentFound = false;
+        boolean purchaseShipmentFound = false;
+        
         List invoicesCreated = new ArrayList();
 
-        GenericValue shipment = null;
-        try {
-            shipment = delegator.findByPrimaryKey("Shipment", UtilMisc.toMap("shipmentId", shipmentId));
-        } catch (GenericEntityException e) {
-            Debug.logError(e, "Trouble getting Shipment entity", module);
-            return ServiceUtil.returnError("Trouble getting Shipment entity");
+        List shipmentIdList = new LinkedList();
+        for (int i = 0; i < shipmentIds.size(); i++) {
+            String tmpShipmentId = (String)shipmentIds.get(i);
+            try {
+                GenericValue shipment = delegator.findByPrimaryKey("Shipment", UtilMisc.toMap("shipmentId", tmpShipmentId));
+                if ((shipment.getString("shipmentTypeId") != null) && (shipment.getString("shipmentTypeId").equals("PURCHASE_SHIPMENT"))) {
+                    purchaseShipmentFound = true;
+                } else {
+                    salesShipmentFound = true;
+                }
+                if (purchaseShipmentFound && salesShipmentFound) {
+                    return ServiceUtil.returnError("Shipments of different types found; shipment [" + tmpShipmentId + "] of type [" + shipment.getString("shipmentTypeId") + "] is of different type from the previous ones.");
+                }
+            } catch (GenericEntityException e) {
+                Debug.logError(e, "Trouble getting Shipment entity for shipment [" + tmpShipmentId + "]", module);
+                return ServiceUtil.returnError("Trouble getting Shipment entity for shipment [" + tmpShipmentId + "]");
+            }
         }
-
+        EntityCondition shipmentIdsCond = new EntityExpr("shipmentId", EntityOperator.IN, shipmentIds);
         // check the status of the shipment
 
         // get the items of the shipment.  They can come from ItemIssuance if the shipment were from a sales order or ShipmentReceipt
         // if it were a purchase order
         List items = null;
         try {
-            if ((shipment.getString("shipmentTypeId") != null) && (shipment.getString("shipmentTypeId").equals("PURCHASE_SHIPMENT"))) {
-                items = delegator.findByAnd("ShipmentReceipt", UtilMisc.toMap("shipmentId", shipmentId));
+            if (purchaseShipmentFound) {
+                items = delegator.findByCondition("ShipmentReceipt", shipmentIdsCond, null, null);
             } else {
-                items = delegator.findByAnd("ItemIssuance", UtilMisc.toMap("shipmentId", shipmentId));
+                items = delegator.findByCondition("ItemIssuance", shipmentIdsCond, null, null);
             }
         } catch (GenericEntityException e) {
-            Debug.logError(e, "Problem getting issued items from Shipment [" + shipmentId + "]", module);
-            return ServiceUtil.returnError("Problem getting issued items from Shipment [" + shipmentId + "]");
+            Debug.logError(e, "Problem getting issued items from shipments", module);
+            return ServiceUtil.returnError("Problem getting issued items from shipments");
         }
         if (items == null) {
-            Debug.logInfo("No items issued for shipment [" + shipmentId + "]", module);
+            Debug.logInfo("No items issued for shipments", module);
             return ServiceUtil.returnSuccess();
         }
 
 
_______________________________________________
Dev mailing list
[hidden email]
http://lists.ofbiz.org/mailman/listinfo/dev
Reply | Threaded
Open this post in threaded view
|

Re: Dev - A new way to create invoices from shipments

Si Chen-2
Jacopo,

It looks good.

Si


Jacopo Cappellato wrote:
What do you all think of the attached patch?

With this patch the "createInvoicesFromShipment" service, that takes as input the shipmentId, creates a List and puts in it the shipmentId and then calls the new "createInvoicesFromShipments" service, that takes as input a list of shipments.
In this way the definition of the existing createInvoicesFromShipment service is not changed, and there is a new service that can be used to create summary invoices (and the two services shares the same code).

If you think that this design is good, I'll commit this patch and then we could go on with the design of the user interface i.e. how to call the new service.

Jacopo



Index: applications/accounting/servicedef/services_invoice.xml =================================================================== --- applications/accounting/servicedef/services_invoice.xml (revision 7102) +++ applications/accounting/servicedef/services_invoice.xml (working copy) @@ -156,11 +156,25 @@ location="org.ofbiz.accounting.invoice.InvoiceServices" invoke="createInvoicesFromShipment"> <description> Create invoice(s) from a Shipment + All the order items associated with the shipment will be selected and + one invoice for each order in the shipment will be created. invoicesCreated = List of invoiceIds which were created by this service </description> <attribute name="shipmentId" type="String" mode="IN" optional="false"/> <attribute name="invoicesCreated" type="List" mode="OUT" optional="true"/> </service> + <service name="createInvoicesFromShipments" engine="java" + location="org.ofbiz.accounting.invoice.InvoiceServices" invoke="createInvoicesFromShipment"> + <description> + Create invoice(s) from a shipment list. + All the order items associated with the shipments will be selected and + one invoice for each order will be created (each invoice could contain + items shipped in different shipments). + invoicesCreated = List of invoiceIds which were created by this service + </description> + <attribute name="shipmentIds" type="List" mode="IN" optional="false"/> + <attribute name="invoicesCreated" type="List" mode="OUT" optional="true"/> + </service> <service name="createInvoicesFromReturnShipment" engine="java" location="org.ofbiz.accounting.invoice.InvoiceServices" invoke="createInvoicesFromReturnShipment"> <description> Index: applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java =================================================================== --- applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java (revision 7102) +++ applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java (working copy) @@ -41,6 +41,9 @@ import org.ofbiz.entity.GenericDelegator; import org.ofbiz.entity.GenericEntityException; import org.ofbiz.entity.GenericValue; +import org.ofbiz.entity.condition.EntityCondition; +import org.ofbiz.entity.condition.EntityOperator; +import org.ofbiz.entity.condition.EntityExpr; import org.ofbiz.order.order.OrderReadHelper; import org.ofbiz.product.product.ProductWorker; import org.ofbiz.service.DispatchContext; @@ -622,34 +625,67 @@ GenericDelegator delegator = dctx.getDelegator(); LocalDispatcher dispatcher = dctx.getDispatcher(); String shipmentId = (String) context.get("shipmentId"); + List invoicesCreated = new ArrayList(); + + Map serviceContext = UtilMisc.toMap("shipmentIds", UtilMisc.toList(shipmentId), "userLogin", context.get("userLogin")); + try { + Map result = dispatcher.runSync("createInvoicesFromShipments", serviceContext); + invoicesCreated = (List)result.get("invoicesCreated"); + } catch (GenericServiceException e) { + Debug.logError(e, "Trouble calling createInvoicesFromShipments service; invoice not created for shipment [" + shipmentId + "]", module); + return ServiceUtil.returnError("Trouble calling createInvoicesFromShipments service; invoice not created for shipment [" + shipmentId + "]"); + } + Map response = ServiceUtil.returnSuccess(); + response.put("invoicesCreated", invoicesCreated); + return response; + } + + public static Map createInvoicesFromShipments(DispatchContext dctx, Map context) { + GenericDelegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + List shipmentIds = (List) context.get("shipmentIds"); + boolean salesShipmentFound = false; + boolean purchaseShipmentFound = false; + List invoicesCreated = new ArrayList(); - GenericValue shipment = null; - try { - shipment = delegator.findByPrimaryKey("Shipment", UtilMisc.toMap("shipmentId", shipmentId)); - } catch (GenericEntityException e) { - Debug.logError(e, "Trouble getting Shipment entity", module); - return ServiceUtil.returnError("Trouble getting Shipment entity"); + List shipmentIdList = new LinkedList(); + for (int i = 0; i < shipmentIds.size(); i++) { + String tmpShipmentId = (String)shipmentIds.get(i); + try { + GenericValue shipment = delegator.findByPrimaryKey("Shipment", UtilMisc.toMap("shipmentId", tmpShipmentId)); + if ((shipment.getString("shipmentTypeId") != null) && (shipment.getString("shipmentTypeId").equals("PURCHASE_SHIPMENT"))) { + purchaseShipmentFound = true; + } else { + salesShipmentFound = true; + } + if (purchaseShipmentFound && salesShipmentFound) { + return ServiceUtil.returnError("Shipments of different types found; shipment [" + tmpShipmentId + "] of type [" + shipment.getString("shipmentTypeId") + "] is of different type from the previous ones."); + } + } catch (GenericEntityException e) { + Debug.logError(e, "Trouble getting Shipment entity for shipment [" + tmpShipmentId + "]", module); + return ServiceUtil.returnError("Trouble getting Shipment entity for shipment [" + tmpShipmentId + "]"); + } } - + EntityCondition shipmentIdsCond = new EntityExpr("shipmentId", EntityOperator.IN, shipmentIds); // check the status of the shipment // get the items of the shipment. They can come from ItemIssuance if the shipment were from a sales order or ShipmentReceipt // if it were a purchase order List items = null; try { - if ((shipment.getString("shipmentTypeId") != null) && (shipment.getString("shipmentTypeId").equals("PURCHASE_SHIPMENT"))) { - items = delegator.findByAnd("ShipmentReceipt", UtilMisc.toMap("shipmentId", shipmentId)); + if (purchaseShipmentFound) { + items = delegator.findByCondition("ShipmentReceipt", shipmentIdsCond, null, null); } else { - items = delegator.findByAnd("ItemIssuance", UtilMisc.toMap("shipmentId", shipmentId)); + items = delegator.findByCondition("ItemIssuance", shipmentIdsCond, null, null); } } catch (GenericEntityException e) { - Debug.logError(e, "Problem getting issued items from Shipment [" + shipmentId + "]", module); - return ServiceUtil.returnError("Problem getting issued items from Shipment [" + shipmentId + "]"); + Debug.logError(e, "Problem getting issued items from shipments", module); + return ServiceUtil.returnError("Problem getting issued items from shipments"); } if (items == null) { - Debug.logInfo("No items issued for shipment [" + shipmentId + "]", module); + Debug.logInfo("No items issued for shipments", module); return ServiceUtil.returnSuccess(); }

_______________________________________________ Dev mailing list [hidden email] http://lists.ofbiz.org/mailman/listinfo/dev

 
_______________________________________________
Dev mailing list
[hidden email]
http://lists.ofbiz.org/mailman/listinfo/dev
Reply | Threaded
Open this post in threaded view
|

Re: Dev - A new way to create invoices from shipments

Jim Yanda
In reply to this post by Jacopo Cappellato
Hi Jacopo,
Was this functionality ever implemented? How do I consolidated multiple shipments onto a single invoice?
Thanks.
Jim

Jacopo Cappellato wrote
Hi all,

I'll need to implement a new way to create invoices from sales shipments.

If I'm not wrong, right now in OFBiz you can create invoices in two ways:

a) from an orderId: the createInvoiceForOrder service is used
b) from a shipmentId: the createInvoicesFromShipment service is used,
this service internally calls the createInvoiceForOrder service for each
of the orders associated to the shipment

The new way I'm going to implement is this:

c) from a set of shipment ids: I'd like to call a modified version of
the createInvoicesFromShipment service

The main difference between method c and b is that if an order is
shipped with two shipments and I pass the two shipment ids to the
service of point c, I'll get ONE invoice (instead of TWO with method b)
for the order containing all the items shipped in the two shipments.

I've modified the createInvoicesFromShipment service to accept as an
optional input parameter a List of shipmentIds: then all the
ItemIssuances associated to the shipments are selected (instead of only
the ItemIssuances associated to one shipment); then the logic is EXACTLY
the same.
I'm I'm testing it right now and it seems to work pretty well.

How to trigger this service?
I'd like to add a new shipment status to mark all the shipments that are
ready to be invoiced; then a new service can be run that:
1) selects all the shipments in this status and puts thir ids in a List
2) calls the modified version of the createInvoicesFromShipment passing
the List to it
3) updates the shipments' status to mark them as invoiced/completed


What do you think of this?

Jacopo

 
_______________________________________________
Dev mailing list
Dev@lists.ofbiz.org
http://lists.ofbiz.org/mailman/listinfo/dev
Reply | Threaded
Open this post in threaded view
|

Re: Dev - A new way to create invoices from shipments

Jacopo Cappellato-3
Hi Jim,

the service has been modified to support and generate one invoice for  
multiple order/shipments; this is true also for the Invoice PDF (if I  
am not wrong).
However right now there is no way to trigger the invoice generation  
using the existing ui.
If you want to test this feature you may try to invoke the  
createInvoicesFromShipment service from a bsh script (for example) and  
pass to it the list of shipmentIds you want to invoice.

Jacopo


On May 22, 2008, at 4:07 AM, Jim Yanda wrote:

>
> Hi Jacopo,
> Was this functionality ever implemented? How do I consolidated  
> multiple
> shipments onto a single invoice?
> Thanks.
> Jim
>
>
> Jacopo Cappellato wrote:
>>
>> Hi all,
>>
>> I'll need to implement a new way to create invoices from sales  
>> shipments.
>>
>> If I'm not wrong, right now in OFBiz you can create invoices in two  
>> ways:
>>
>> a) from an orderId: the createInvoiceForOrder service is used
>> b) from a shipmentId: the createInvoicesFromShipment service is used,
>> this service internally calls the createInvoiceForOrder service for  
>> each
>> of the orders associated to the shipment
>>
>> The new way I'm going to implement is this:
>>
>> c) from a set of shipment ids: I'd like to call a modified version of
>> the createInvoicesFromShipment service
>>
>> The main difference between method c and b is that if an order is
>> shipped with two shipments and I pass the two shipment ids to the
>> service of point c, I'll get ONE invoice (instead of TWO with  
>> method b)
>> for the order containing all the items shipped in the two shipments.
>>
>> I've modified the createInvoicesFromShipment service to accept as an
>> optional input parameter a List of shipmentIds: then all the
>> ItemIssuances associated to the shipments are selected (instead of  
>> only
>> the ItemIssuances associated to one shipment); then the logic is  
>> EXACTLY
>> the same.
>> I'm I'm testing it right now and it seems to work pretty well.
>>
>> How to trigger this service?
>> I'd like to add a new shipment status to mark all the shipments  
>> that are
>> ready to be invoiced; then a new service can be run that:
>> 1) selects all the shipments in this status and puts thir ids in a  
>> List
>> 2) calls the modified version of the createInvoicesFromShipment  
>> passing
>> the List to it
>> 3) updates the shipments' status to mark them as invoiced/completed
>>
>>
>> What do you think of this?
>>
>> Jacopo
>>
>>
>> _______________________________________________
>> Dev mailing list
>> [hidden email]
>> http://lists.ofbiz.org/mailman/listinfo/dev
>>
>>
>
> --
> View this message in context: http://www.nabble.com/Dev---A-new-way-to-create-invoices-from-shipments-tp3630362p17395979.html
> Sent from the OFBiz - Dev mailing list archive at Nabble.com.
>

Reply | Threaded
Open this post in threaded view
|

Re: Dev - A new way to create invoices from shipments

Jim Yanda
Hi Jacopo,
What I really need is a way to combine invoice consolidation with "Quick Complete Drop Shipment".
I have sales orders that have multiple drop shipments. I'd like to "Quick Complete" all of them in one step and have that process generate a single consolidated invoice to the customer.
Can you give me a synopsis of how this would be done or do you know if someone has done it?
Thank you.
Jim

Jacopo Cappellato-3 wrote
Hi Jim,

the service has been modified to support and generate one invoice for  
multiple order/shipments; this is true also for the Invoice PDF (if I  
am not wrong).
However right now there is no way to trigger the invoice generation  
using the existing ui.
If you want to test this feature you may try to invoke the  
createInvoicesFromShipment service from a bsh script (for example) and  
pass to it the list of shipmentIds you want to invoice.

Jacopo


On May 22, 2008, at 4:07 AM, Jim Yanda wrote:

>
> Hi Jacopo,
> Was this functionality ever implemented? How do I consolidated  
> multiple
> shipments onto a single invoice?
> Thanks.
> Jim
>
>
> Jacopo Cappellato wrote:
>>
>> Hi all,
>>
>> I'll need to implement a new way to create invoices from sales  
>> shipments.
>>
>> If I'm not wrong, right now in OFBiz you can create invoices in two  
>> ways:
>>
>> a) from an orderId: the createInvoiceForOrder service is used
>> b) from a shipmentId: the createInvoicesFromShipment service is used,
>> this service internally calls the createInvoiceForOrder service for  
>> each
>> of the orders associated to the shipment
>>
>> The new way I'm going to implement is this:
>>
>> c) from a set of shipment ids: I'd like to call a modified version of
>> the createInvoicesFromShipment service
>>
>> The main difference between method c and b is that if an order is
>> shipped with two shipments and I pass the two shipment ids to the
>> service of point c, I'll get ONE invoice (instead of TWO with  
>> method b)
>> for the order containing all the items shipped in the two shipments.
>>
>> I've modified the createInvoicesFromShipment service to accept as an
>> optional input parameter a List of shipmentIds: then all the
>> ItemIssuances associated to the shipments are selected (instead of  
>> only
>> the ItemIssuances associated to one shipment); then the logic is  
>> EXACTLY
>> the same.
>> I'm I'm testing it right now and it seems to work pretty well.
>>
>> How to trigger this service?
>> I'd like to add a new shipment status to mark all the shipments  
>> that are
>> ready to be invoiced; then a new service can be run that:
>> 1) selects all the shipments in this status and puts thir ids in a  
>> List
>> 2) calls the modified version of the createInvoicesFromShipment  
>> passing
>> the List to it
>> 3) updates the shipments' status to mark them as invoiced/completed
>>
>>
>> What do you think of this?
>>
>> Jacopo
>>
>>
>> _______________________________________________
>> Dev mailing list
>> Dev@lists.ofbiz.org
>> http://lists.ofbiz.org/mailman/listinfo/dev
>>
>>
>
> --
> View this message in context: http://www.nabble.com/Dev---A-new-way-to-create-invoices-from-shipments-tp3630362p17395979.html
> Sent from the OFBiz - Dev mailing list archive at Nabble.com.
>