Allow to control Prefix and Purchase Order sequence.
---------------------------------------------------- Key: OFBIZ-2456 URL: https://issues.apache.org/jira/browse/OFBIZ-2456 Project: OFBiz Issue Type: New Feature Components: accounting Affects Versions: SVN trunk Reporter: Jacques Le Roux Fix For: SVN trunk For the moment the Data Model does not take into account the possibility to control Prefix and Purchase Order sequence. In PartyAcctgPreference, there are the couples of fields (invoiceSequenceEnumId, invoiceIdPrefix), (quoteSequenceEnumId, quoteIdPrefix) and (orderSequenceEnumId, orderIdPrefix). So we should either add a couple (purchInvoiceSequenceEnumId, purchinvoiceIdPrefix), which IMO is simpler and enough, or deprecate the couple (invoiceSequenceEnumId, invoiceIdPrefix) to (salesInvoiceSequenceEnumId, salesInvoiceIdPrefix) and add the couple above. Then the same User Interface than for Sales Order (configuration settings in Organization GL Settings) could be used but it would have to differentiate the 2 kinds of invoices. -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. |
[ https://issues.apache.org/jira/browse/OFBIZ-2456?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12710138#action_12710138 ] Karim Rahimpur commented on OFBIZ-2456: --------------------------------------- I really agree with you on the first option. Actually we were missing part of this in a current project, to be more specific: sales invoices use enforced sequence without prefix and thus purchase invoices using the same sequence numbering (also without prefix) is not workable. So I'll outline a solution to that in the hope it will help you or anyone who needs this. It's actually quite simple for invoices at least (I don't care much about purchase orders etc. at least in this case): _The idea: Distinguish between invoice numbers for sales and purchase invoices._ *1. Add attributes to PartyAcctgPreference in accounting/entitydef/entitymodel.xml* {code} <entity entity-name="PartyAcctgPreference" package-name="org.ofbiz.accounting.ledger" title="Party (organization) accounting preferences"> ... <field name="purchaseInvoiceSequenceEnumId" type="id-ne"/> <field name="purchaseInvoiceIdPrefix" type="very-short"/> <field name="lastPurchaseInvoiceNumber" type="numeric"/> <field name="lastPurchaseInvoiceRestartDate" type="date-time"/> <field name="usePurchaseInvoiceIdForReturns" type="indicator"/> ... <relation type="one" fk-name="ACTGPREF_PINVSQ" title="PurchaseInvoiceSequence" rel-entity-name="Enumeration"> <key-map field-name="purchaseInvoiceSequenceEnumId" rel-field-name="enumId"/> </relation> ... </entity> {code} *Provide the invoice type to getNextInvoiceId service/method* In accounting/servicedef/services_invoice.xml add the invoiceTypeId and the billed party (partyIdTo) as an optional input parameter: {code} <service name="getNextInvoiceId" engine="simple" location="org/ofbiz/accounting/invoice/InvoiceServices.xml" invoke="getNextInvoiceId"> <description>Get the Next Invoice ID According to Settings on the PartyAcctgPreference Entity for the given Party</description> <attribute name="partyId" type="String" mode="IN" optional="false"/> <attribute name="partyIdTo" type="String" mode="IN" optional="true"/> <attribute name="invoiceTypeId" type="String" mode="IN" optional="true"/> <attribute name="invoiceId" type="String" mode="OUT" optional="false"/> </service> {code} *In accounting/script/.../InvoiceServices.xml for the simple method createInvoice pass the additional parameters:* {code} <simple-method method-name="createInvoice" short-description="Create a new Invoice"> <now-timestamp field="nowTimestamp"/> <make-value value-field="newEntity" entity-name="Invoice"/> <set-nonpk-fields map="parameters" value-field="newEntity"/> <!-- call getNextInvoiceId service with the parameters.partyIdFrom when invoice Id is not suplied else use it from the input --> <if-empty field="parameters.invoiceId"> <set field="getNextInvoiceIdMap.partyId" from-field="parameters.partyIdFrom"/> <set field="getNextInvoiceIdMap.partyIdTo" from-field="parameters.partyId"/> <set field="getNextInvoiceIdMap.invoiceTypeId" from-field="parameters.invoiceTypeId"/> <call-service service-name="getNextInvoiceId" in-map-name="getNextInvoiceIdMap"> <result-to-field result-name="invoiceId" field="newEntity.invoiceId"/> </call-service> ... </simple-method> {code} *Adapt the getNextInvoiceId method* Just the same code as before but distinguishes between sales and purchase invoices to get the prefix and sequence number. {code} <simple-method method-name="getNextInvoiceId" short-description="Get Next invoiceId"> <!-- try to find PartyAcctgPreference for parameters.partyId, see if we need any special invoice number sequencing --> <entity-one entity-name="PartyAcctgPreference" value-field="partyAcctgPreference" auto-field-map="false"> <field-map field-name="partyId" from-field="parameters.partyId"/> </entity-one> <entity-one entity-name="InvoiceType" value-field="invoiceType"> <field-map field-name="invoiceTypeId" value="${parameters.invoiceTypeId}"/> </entity-one> </entity-one> <log level="info" message="In getNextInvoiceId partyId is [${parameters.partyId}], partyAcctgPreference: ${partyAcctgPreference}, invoiceType: ${invoiceType}"/> <if> <condition> <or> <if-empty field="invoiceType"/> <if-compare field="invoiceType.parentTypeId" operator="equals" value="SALES_INVOICE"/> </or> </condition> <then> <!-- get a sequence number for a sales invoice --> <if> <condition> <if-compare field="partyAcctgPreference.invoiceSequenceEnumId" operator="equals" value="INVSQ_ENF_SEQ"/> </condition> <then> <log level="info" message="In createInvoice sequence enum INVSQ_ENF_SEQ"/> <!-- this is sequential sequencing, we can't skip a number, also it must be a unique sequence per partyIdFrom --> <if-not-empty field="partyAcctgPreference.lastInvoiceNumber"> <calculate field="partyAcctgPreference.lastInvoiceNumber" type="Long"> <calcop operator="add" field="partyAcctgPreference.lastInvoiceNumber"/> <number value="1"/> </calculate> <else> <calculate field="partyAcctgPreference.lastInvoiceNumber" type="Long"><number value="1"/></calculate> </else> </if-not-empty> <store-value value-field="partyAcctgPreference"/> <set from-field="partyAcctgPreference.lastInvoiceNumber" field="invoiceIdTemp"/> </then> <else-if> <condition> <if-compare field="partyAcctgPreference.invoiceSequenceEnumId" operator="equals" value="INVSQ_RESTARTYR"/> </condition> <then> <log level="info" message="In createInvoice sequence enum INVSQ_RESTARTYR"/> <!-- this is sequential sequencing, we can't skip a number; except that it is restarted each fiscal year --> <now-timestamp field="nowTimestamp"/> <if-empty field="partyAcctgPreference.lastInvoiceRestartDate"> <!-- if no lastInvoiceRestartDate then it's easy, just start now with 1 --> <calculate field="partyAcctgPreference.lastInvoiceNumber" type="Long"><number value="1"/></calculate> <set from-field="nowTimestamp" field="partyAcctgPreference.lastInvoiceRestartDate"/> <else> <!-- first figure out if we need to reset the lastInvoiceNumber; is the lastInvoiceRestartDate after the fiscalYearStartMonth/Day for this year? --> <calculate field="zeroLong" type="Long"><number value="0"/></calculate> <call-class-method class-name="org.ofbiz.base.util.UtilDateTime" method-name="getYearStart" ret-field="curYearFiscalStartDate"> <field field="nowTimestamp" type="java.sql.Timestamp"/> <field field="partyAcctgPreference.fiscalYearStartDay" type="java.lang.Number"/> <field field="partyAcctgPreference.fiscalYearStartMonth" type="java.lang.Number"/> <field field="zeroLong" type="java.lang.Number"/> </call-class-method> <if> <condition> <and> <if-compare-field field="partyAcctgPreference.lastInvoiceRestartDate" to-field="curYearFiscalStartDate" operator="less" type="Timestamp"/> <if-compare-field field="nowTimestamp" to-field="curYearFiscalStartDate" operator="greater-equals" type="Timestamp"/> </and> </condition> <then> <!-- less than fiscal year start, we need to reset it --> <calculate field="partyAcctgPreference.lastInvoiceNumber" type="Long"><number value="1"/></calculate> <set from-field="nowTimestamp" field="partyAcctgPreference.lastInvoiceRestartDate"/> </then> <else> <!-- greater than or equal to fiscal year start or nowTimestamp hasn't yet hit the current year fiscal start date, we're okay, just increment --> <calculate field="partyAcctgPreference.lastInvoiceNumber" type="Long"> <calcop operator="add" field="partyAcctgPreference.lastInvoiceNumber"/> <number value="1"/> </calculate> </else> </if> </else> </if-empty> <store-value value-field="partyAcctgPreference"/> <!-- get the current year string for prefix, etc; simple 4 digit year date string (using system defaults) --> <set field="curYearString" value="${str:toString(date:year(partyAcctgPreference.lastInvoiceRestartDate, util:defaultTimeZone(), util:defaultLocale()))}"/> <set field="invoiceIdTemp" value="${curYearString}-${str:toString(partyAcctgPreference.lastInvoiceNumber)}"/> </then> </else-if> <else> <log level="info" message="In createInvoice sequence enum INVSQ_STANDARD"/> <!-- default to the default sequencing: INVSQ_STANDARD --> <set from-field="parameters.invoiceId" field="invoiceIdTemp"/> <if-empty field="invoiceIdTemp"> <sequenced-id sequence-name="Invoice" field="invoiceIdTemp"/> <else> <!-- check the provided ID --> <check-id field="invoiceIdTemp"/> <check-errors/> </else> </if-empty> </else> </if> <!-- use invoiceIdTemp along with the invoiceIdPrefix to create the real ID --> <set field="invoiceId" value="${partyAcctgPreference.invoiceIdPrefix}${str:toString(invoiceIdTemp)}"/> <field-to-result field="invoiceId" result-name="invoiceId"/> </then> <else> <!-- get a sequence number for a purchase invoice --> <if> <condition> <if-compare field="partyAcctgPreference.purchaseInvoiceSequenceEnumId" operator="equals" value="INVSQ_ENF_SEQ"/> </condition> <then> <log level="info" message="In createInvoice sequence enum INVSQ_ENF_SEQ"/> <!-- this is sequential sequencing, we can't skip a number, also it must be a unique sequence per partyIdFrom --> <if-not-empty field="partyAcctgPreference.lastPurchaseInvoiceNumber"> <calculate field="partyAcctgPreference.lastPurchaseInvoiceNumber" type="Long"> <calcop operator="add" field="partyAcctgPreference.lastPurchaseInvoiceNumber"/> <number value="1"/> </calculate> <else> <calculate field="partyAcctgPreference.lastPurchaseInvoiceNumber" type="Long"><number value="1"/></calculate> </else> </if-not-empty> <store-value value-field="partyAcctgPreference"/> <set from-field="partyAcctgPreference.lastPurchaseInvoiceNumber" field="invoiceIdTemp"/> </then> <else-if> <condition> <if-compare field="partyAcctgPreference.purchaseInvoiceSequenceEnumId" operator="equals" value="INVSQ_RESTARTYR"/> </condition> <then> <log level="info" message="In createInvoice sequence enum INVSQ_RESTARTYR"/> <!-- this is sequential sequencing, we can't skip a number; except that it is restarted each fiscal year --> <now-timestamp field="nowTimestamp"/> <if-empty field="partyAcctgPreference.lastPurchaseInvoiceRestartDate"> <!-- if no lastInvoiceRestartDate then it's easy, just start now with 1 --> <calculate field="partyAcctgPreference.lastPurchaseInvoiceNumber" type="Long"><number value="1"/></calculate> <set from-field="nowTimestamp" field="partyAcctgPreference.lastPurchaseInvoiceRestartDate"/> <else> <!-- first figure out if we need to reset the lastPurchaseInvoiceNumber; is the lastPurchaseInvoiceRestartDate after the fiscalYearStartMonth/Day for this year? --> <calculate field="zeroLong" type="Long"><number value="0"/></calculate> <call-class-method class-name="org.ofbiz.base.util.UtilDateTime" method-name="getYearStart" ret-field="curYearFiscalStartDate"> <field field="nowTimestamp" type="java.sql.Timestamp"/> <field field="partyAcctgPreference.fiscalYearStartDay" type="java.lang.Number"/> <field field="partyAcctgPreference.fiscalYearStartMonth" type="java.lang.Number"/> <field field="zeroLong" type="java.lang.Number"/> </call-class-method> <if> <condition> <and> <if-compare-field field="partyAcctgPreference.lastPurchaseInvoiceRestartDate" to-field="curYearFiscalStartDate" operator="less" type="Timestamp"/> <if-compare-field field="nowTimestamp" to-field="curYearFiscalStartDate" operator="greater-equals" type="Timestamp"/> </and> </condition> <then> <!-- less than fiscal year start, we need to reset it --> <calculate field="partyAcctgPreference.lastPurchaseInvoiceNumber" type="Long"><number value="1"/></calculate> <set from-field="nowTimestamp" field="partyAcctgPreference.lastPurchaseInvoiceRestartDate"/> </then> <else> <!-- greater than or equal to fiscal year start or nowTimestamp hasn't yet hit the current year fiscal start date, we're okay, just increment --> <calculate field="partyAcctgPreference.lastPurchaseInvoiceNumber" type="Long"> <calcop operator="add" field="partyAcctgPreference.lastPurchaseInvoiceNumber"/> <number value="1"/> </calculate> </else> </if> </else> </if-empty> <store-value value-field="partyAcctgPreference"/> <!-- get the current year string for prefix, etc; simple 4 digit year date string (using system defaults) --> <set field="curYearString" value="${str:toString(date:year(partyAcctgPreference.lastPurchaseInvoiceRestartDate, util:defaultTimeZone(), util:defaultLocale()))}"/> <set field="invoiceIdTemp" value="${curYearString}-${str:toString(partyAcctgPreference.lastPurchaseInvoiceNumber)}"/> </then> </else-if> <else> <log level="info" message="In createInvoice sequence enum INVSQ_STANDARD"/> <!-- default to the default sequencing: INVSQ_STANDARD --> <set from-field="parameters.invoiceId" field="invoiceIdTemp"/> <if-empty field="invoiceIdTemp"> <sequenced-id sequence-name="Invoice" field="invoiceIdTemp"/> <else> <!-- check the provided ID --> <check-id field="invoiceIdTemp"/> <check-errors/> </else> </if-empty> </else> </if> <!-- use invoiceIdTemp along with the invoiceIdPrefix to create the real ID --> <set field="invoiceId" value="${partyAcctgPreference.purchaseInvoiceIdPrefix}${str:toString(invoiceIdTemp)}"/> <field-to-result field="invoiceId" result-name="invoiceId"/> </else> </if> </simple-method> {code} Sorry for not providing a patch but the version we're working on is not in sync with the current revision, but I think there should not be much difference. Hope this helps. > Allow to control Prefix and Purchase Order sequence. > ---------------------------------------------------- > > Key: OFBIZ-2456 > URL: https://issues.apache.org/jira/browse/OFBIZ-2456 > Project: OFBiz > Issue Type: New Feature > Components: accounting > Affects Versions: SVN trunk > Reporter: Jacques Le Roux > Fix For: SVN trunk > > > For the moment the Data Model does not take into account the possibility to control Prefix and Purchase Order sequence. > In PartyAcctgPreference, there are the couples of fields (invoiceSequenceEnumId, invoiceIdPrefix), (quoteSequenceEnumId, quoteIdPrefix) and (orderSequenceEnumId, orderIdPrefix). So we should either add a couple (purchInvoiceSequenceEnumId, purchinvoiceIdPrefix), which IMO is simpler and enough, or deprecate the couple (invoiceSequenceEnumId, invoiceIdPrefix) to (salesInvoiceSequenceEnumId, salesInvoiceIdPrefix) and add the couple above. Then the same User Interface than for Sales Order (configuration settings in Organization GL Settings) could be used but it would have to differentiate the 2 kinds of invoices. -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. |
In reply to this post by Nicolas Malin (Jira)
[ https://issues.apache.org/jira/browse/OFBIZ-2456?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Jacques Le Roux reassigned OFBIZ-2456: -------------------------------------- Assignee: Jacques Le Roux > Allow to control Prefix and Purchase Order sequence. > ---------------------------------------------------- > > Key: OFBIZ-2456 > URL: https://issues.apache.org/jira/browse/OFBIZ-2456 > Project: OFBiz > Issue Type: New Feature > Components: accounting > Affects Versions: SVN trunk > Reporter: Jacques Le Roux > Assignee: Jacques Le Roux > Fix For: SVN trunk > > > For the moment the Data Model does not take into account the possibility to control Prefix and Purchase Order sequence. > In PartyAcctgPreference, there are the couples of fields (invoiceSequenceEnumId, invoiceIdPrefix), (quoteSequenceEnumId, quoteIdPrefix) and (orderSequenceEnumId, orderIdPrefix). So we should either add a couple (purchInvoiceSequenceEnumId, purchinvoiceIdPrefix), which IMO is simpler and enough, or deprecate the couple (invoiceSequenceEnumId, invoiceIdPrefix) to (salesInvoiceSequenceEnumId, salesInvoiceIdPrefix) and add the couple above. Then the same User Interface than for Sales Order (configuration settings in Organization GL Settings) could be used but it would have to differentiate the 2 kinds of invoices. -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. |
Free forum by Nabble | Edit this page |