Merge branch 'master' of github.com:webnotes/erpnext into wsgi
Conflicts: accounts/doctype/sales_invoice/sales_invoice.txt controllers/selling_controller.py patches/patch_list.py selling/doctype/lead/lead.py selling/doctype/opportunity/opportunity.py selling/doctype/quotation/quotation.py selling/doctype/quotation/quotation.txt selling/doctype/sales_order/sales_order.txt stock/doctype/purchase_receipt/purchase_receipt.py stock/doctype/serial_no/serial_no.py stock/doctype/stock_entry/stock_entry.py stock/doctype/stock_ledger_entry/stock_ledger_entry.py
This commit is contained in:
commit
7e9048570e
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-24 12:15:51",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-08-28 19:13:42",
|
||||
"modified": "2013-10-15 11:12:02",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -80,16 +80,6 @@
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "conversion_rate",
|
||||
"fieldtype": "Float",
|
||||
"label": "Conversion Rate",
|
||||
"oldfieldname": "conversion_rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "selling_price_list",
|
||||
|
@ -147,7 +147,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
debit_to: function() {
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-24 19:29:05",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-10-03 18:54:31",
|
||||
"modified": "2013-10-11 13:12:38",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -226,7 +226,6 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"default": "1.00",
|
||||
"description": "Rate at which Customer Currency is converted to customer's base currency",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "conversion_rate",
|
||||
|
@ -52,7 +52,7 @@ class AccountsController(TransactionBase):
|
||||
msgprint(_("Account for this ") + fieldname + _(" has been freezed. ") +
|
||||
self.doc.doctype + _(" can not be made."), raise_exception=1)
|
||||
|
||||
def set_price_list_currency(self, buying_or_selling):
|
||||
def set_price_list_currency(self, buying_or_selling, for_validate=False):
|
||||
if self.meta.get_field("currency"):
|
||||
company_currency = get_company_currency(self.doc.company)
|
||||
|
||||
@ -60,14 +60,13 @@ class AccountsController(TransactionBase):
|
||||
fieldname = "selling_price_list" if buying_or_selling.lower() == "selling" \
|
||||
else "buying_price_list"
|
||||
if self.meta.get_field(fieldname) and self.doc.fields.get(fieldname):
|
||||
if not self.doc.price_list_currency:
|
||||
self.doc.price_list_currency = webnotes.conn.get_value("Price List",
|
||||
self.doc.fields.get(fieldname), "currency")
|
||||
self.doc.price_list_currency = webnotes.conn.get_value("Price List",
|
||||
self.doc.fields.get(fieldname), "currency")
|
||||
|
||||
if self.doc.price_list_currency == company_currency:
|
||||
self.doc.plc_conversion_rate = 1.0
|
||||
|
||||
elif not self.doc.plc_conversion_rate:
|
||||
elif not self.doc.plc_conversion_rate or not for_validate:
|
||||
self.doc.plc_conversion_rate = self.get_exchange_rate(
|
||||
self.doc.price_list_currency, company_currency)
|
||||
|
||||
@ -77,7 +76,7 @@ class AccountsController(TransactionBase):
|
||||
self.doc.conversion_rate = self.doc.plc_conversion_rate
|
||||
elif self.doc.currency == company_currency:
|
||||
self.doc.conversion_rate = 1.0
|
||||
elif not self.doc.conversion_rate:
|
||||
elif not self.doc.conversion_rate or not for_validate:
|
||||
self.doc.conversion_rate = self.get_exchange_rate(self.doc.currency,
|
||||
company_currency)
|
||||
|
||||
|
@ -29,7 +29,7 @@ class BuyingController(StockController):
|
||||
super(BuyingController, self).set_missing_values(for_validate)
|
||||
|
||||
self.set_supplier_from_item_default()
|
||||
self.set_price_list_currency("Buying")
|
||||
self.set_price_list_currency("Buying", for_validate)
|
||||
|
||||
# set contact and address details for supplier, if they are not mentioned
|
||||
if self.doc.supplier and not (self.doc.contact_person and self.doc.supplier_address):
|
||||
|
@ -23,7 +23,7 @@ class SellingController(StockController):
|
||||
|
||||
# set contact and address details for customer, if they are not mentioned
|
||||
self.set_missing_lead_customer_details()
|
||||
self.set_price_list_and_item_details()
|
||||
self.set_price_list_and_item_details(for_validate)
|
||||
if self.doc.fields.get("__islocal"):
|
||||
self.set_taxes("other_charges", "charge")
|
||||
|
||||
@ -41,8 +41,8 @@ class SellingController(StockController):
|
||||
if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname):
|
||||
self.doc.fields[fieldname] = val
|
||||
|
||||
def set_price_list_and_item_details(self):
|
||||
self.set_price_list_currency("Selling")
|
||||
def set_price_list_and_item_details(self, for_validate=False):
|
||||
self.set_price_list_currency("Selling", for_validate)
|
||||
self.set_missing_item_details(get_item_details)
|
||||
|
||||
def get_other_charges(self):
|
||||
|
@ -13,33 +13,34 @@ You can make a Sales Invoice of type POS by checking on “Is POS”. When you c
|
||||
|
||||
- Update Stock: If this is checked, Stock Ledger Entries will be made when you “Submit” this Sales Invoice thereby eliminating the need for a separate Delivery Note.
|
||||
- In your Items table, update inventory information like Warehouse (saved as default), Serial Number, or Batch Number if applicable.
|
||||
- Update Payment Details like your Bank / Cash Account, paid amount etc.
|
||||
- Update Payment Details like your Bank / Cash Account, Paid amount etc.
|
||||
- If you are writing off certain amount. For example when you receive extra cash as a result of not having exact denomination of change, check on ‘Write off Outstanding Amount’ and set the Account.
|
||||
|
||||
Setup [POS Setting](docs.user.setup.pos_setting.html)
|
||||
|
||||
#### Enable POS View
|
||||
|
||||
Sales Invoice has 2 different interfaces, Invoice View and POS View. The current view used by most users is the Invoice View. This view is preferred by non-retailing companies.The POS view is used by retailing companies. For retailers it is very important to provide bill or sales invoice at the point of sale. Their customers cannot wait to receive the bill by post. The customers want an immediate bill for the payment which they make. In such cases, the POS View is preferred.
|
||||
- Every Sales & Purchase documents has 2 different interfaces, Invoice View and POS View. The current view used by most users is the Invoice View. This view is preferred by non-retailing companies.The POS view is used by retailing companies. For retailers it is very important to provide bill or sales invoice at the point of sale. Their customers cannot wait to receive the bill by post. The customers want an immediate bill for the payment which they make. In such cases, the POS View is preferred.
|
||||
|
||||
> Setup > Show/Hide Features
|
||||
|
||||
![POS View](img/pos-features-setup.png)
|
||||
|
||||
- Setup [POS Setting](docs.user.setup.pos_setting.html)
|
||||
|
||||
### Adding an Item
|
||||
|
||||
At the billing counter, the retailer needs to select Items which the consumer buys. In the POS interface you can select an Item by two methods. One, is by clicking on the Item image and the other, is through the Barcode.
|
||||
At the billing counter, the retailer needs to select Items which the consumer buys. In the POS interface you can select an Item by two methods. One, is by clicking on the Item image and the other, is through the Barcode / Serial No.
|
||||
|
||||
**Select Item** - To select a product click on the Item image and add it into the cart. A cart is an area that prepares a customer for checkout by allowing to edit product information, adjust taxes and add discounts.
|
||||
|
||||
**Barcode** - A Barcode is an optical machine-readable representation of data relating to the object to which it is attached. Enter Barcode in the barcode box and pause for a second. The Item will be automatically added to the cart.
|
||||
**Barcode / Serial No** - A Barcode / Serial No is an optical machine-readable representation of data relating to the object to which it is attached. Enter Barcode / Serial No in the box as shown in the image below and pause for a second, the item will be automatically added to the cart.
|
||||
|
||||
![POS](img/pos-add-item.png)
|
||||
|
||||
> Tip: To change the quantity of an Item, enter your desired quantity in the quantity box. These are mostly used if the same Item is purchased in bulk.
|
||||
|
||||
|
||||
If your product list is very long use the universal search field, to type the product name and select faster.
|
||||
If your product list is very long use the Search field, type the product name in Search box.
|
||||
|
||||
### Removing an Item
|
||||
|
||||
@ -48,7 +49,7 @@ There are two ways to remove an Item.
|
||||
- Select an Item by clicking on the row of that Item from Item cart. Then click on “Del” button. OR
|
||||
|
||||
|
||||
- Type 0 in the ‘select quantity’ field to delete the record.
|
||||
- Enter 0(zero) quantity of any item to delete that item.
|
||||
|
||||
To remove multiple Items together, select multiple rows & click on “Del” button.
|
||||
|
||||
@ -62,11 +63,11 @@ After all the Items and their quantities are added into the cart, you are ready
|
||||
|
||||
1. Click on “Make Payment” to get the Payment window.
|
||||
1. Select your “Mode of Payment”.
|
||||
1. Click on “Pay” button to Save the Sales Invoice.
|
||||
1. Click on “Pay” button to Save the document.
|
||||
|
||||
![POS Payment](img/pos-make-payment.png)
|
||||
|
||||
Submit the document to finalise the record. After the Invoice is submitted, you can either print an invoice or email it directly to the customer.
|
||||
Submit the document to finalise the record. After the document is submitted, you can either print or email it directly to the customer.
|
||||
|
||||
#### Accounting entries (GL Entry) for a Point of Sale:
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
"_label": "User Guide",
|
||||
"_toc": [
|
||||
"docs.user.intro",
|
||||
"docs.user.five_day_setup",
|
||||
"docs.user.implement",
|
||||
"docs.user.setup",
|
||||
"docs.user.selling",
|
||||
@ -17,7 +18,7 @@
|
||||
"docs.user.tools",
|
||||
"docs.user.customize",
|
||||
"docs.user.knowledge"
|
||||
],
|
||||
],
|
||||
"_no_toc": 1
|
||||
}
|
||||
---
|
||||
@ -29,6 +30,12 @@ Contents
|
||||
1. [Open Source](docs.user.intro.open_source.html)
|
||||
1. [Ways to get started](docs.user.intro.try.html)
|
||||
1. [Getting Help](docs.user.help.html)
|
||||
1. [Five-Day-Setup](docs.user.five_day_setup.html)
|
||||
1. [Day-1: Setup Customer,Item, and Supplier](docs.user.five_day_setup.day_1.html)
|
||||
1. [Day-2: Setup Chart of Accounts, Opening Accounts, and HR](docs.user.five_day_setup.day_2.html)
|
||||
1. [Day-3: Sales Cycle and Purchase Cycle](docs.user.five_day_setup.day_3.html)
|
||||
1. [Day-4: Manufacturing Cycle and Accounting Reports](docs.user.five_day_setup.day_4.html)
|
||||
1. [Day-5: Projects, Calendar, and Website](docs.user.five_day_setup.day_5.html)
|
||||
1. [Implementation](docs.user.implement.html)
|
||||
1. [Implementation Strategy](docs.user.implement.strategy.html)
|
||||
1. [Concepts](docs.user.implement.concepts.html)
|
||||
@ -154,4 +161,3 @@ Contents
|
||||
1. [DocType Definitions](docs.user.knowledge.doctype.html)
|
||||
1. [Attachment and CSV Files](docs.user.knowledge.attachment_csv.html)
|
||||
1. [Format using Markdown](docs.user.knowledge.markdown.html)
|
||||
|
||||
|
81
docs/user/five_day_setup/docs.user.five_day_setup.day_1.md
Normal file
81
docs/user/five_day_setup/docs.user.five_day_setup.day_1.md
Normal file
@ -0,0 +1,81 @@
|
||||
---
|
||||
{
|
||||
"_label": "Day-1: Setup Customer, Item, and Supplier"
|
||||
}
|
||||
---
|
||||
Login to your ERPNext account with the User ID and Password sent through the mail.
|
||||
|
||||
After logging into your account you will receive a pop-up form to fill. Please fill this form. Select the abbreviation you would wish to have for your company. The abbreviation selected here will be used in naming most of the business documents.
|
||||
|
||||
#### Form Part I
|
||||
|
||||
![1st Form](img/firstdaysetup-1.png)
|
||||
<br><br>
|
||||
#### Form Part II
|
||||
To understand about Company Financial Year or Fiscal Year visit [Fiscal Year](docs.user.knowledge.fiscal_year.html)
|
||||
|
||||
|
||||
![1st Form](img/firstdaysetup-2.png)
|
||||
|
||||
After filling this form, you will get a pop-up message for completing the set-up process. Click on the Setup button. The Setup page will appear.
|
||||
|
||||
<br>
|
||||
#### Setup Page - Customer
|
||||
|
||||
The Organisation details are updated in ERPNext, after filling the first form. Go directly to the Customer Icon.
|
||||
|
||||
![Customer](img/firstdaysetup-customer.png)
|
||||
<br>
|
||||
|
||||
|
||||
After clicking on Customer, a new form will appear.
|
||||
<br>
|
||||
|
||||
![Customer](img/firstdaysetup-customer-1.png)
|
||||
|
||||
To see how customer details are added, visit [Customer](docs.user.selling.customer.html). Create 5 new customer records in the system.
|
||||
|
||||
Now proceed to make an Item. To go to the main menu, click on erpnext icon which is on the left hand corner of the page. On the main menu page, click on Setup
|
||||
|
||||
![Main Menu](img/firstdaysetup-main-menu.png)
|
||||
|
||||
<br>
|
||||
|
||||
#### Setup Page - Item
|
||||
|
||||
On the setup page go to Item.
|
||||
|
||||
|
||||
![Item](img/firstdaysetup-item.png)
|
||||
|
||||
|
||||
Create a new Item. An Item is your company's product or a service.The term Item is applicable to your core products as well as your raw materials. It can be a product or service that you buy/sell from your customers/ suppliers.
|
||||
|
||||
Filling Item details is an important step in ERPNext. Do not postpone this step. After clicking on Item, make a new Item.
|
||||
|
||||
![Item](img/firstdaysetup-item-1.png)
|
||||
|
||||
To understand how to fill an Item in detail, visit [Item](docs.user.stock.item.html). Add 5 item records to ERPnext. After adding these records, go back to the Setup Page and add Suppliers.
|
||||
|
||||
<br>
|
||||
#### Setup Page - Suppliers
|
||||
On the Setup page go to Supplier.
|
||||
|
||||
![Supplier](img/firstdaysetup-supplier.png)
|
||||
<br>
|
||||
|
||||
Suppliers are companies or individuals who provide you with products or services. They are treated in exactly the same manner as Customers in ERPNext. Create a new Supplier record.
|
||||
|
||||
![Supplier](img/firstdaysetup-supplier-1.png)
|
||||
|
||||
|
||||
To understand how to fill Supplier details, visit [Supplier](docs.user.buying.supplier.html).
|
||||
|
||||
If you wish to import your list of customers and suppliers directly to ERPNext, you can do that via the Data Import Tool.
|
||||
|
||||
To upload Customers or suppliers in bulk, go to the Data Import Tool.
|
||||
|
||||
> Note: The data import format is case-sensitive. The file will not be processed if there are any spelling mistakes or deviations from the default values.
|
||||
|
||||
To understand how to import data, visit [Importing Data](docs.user.setup.data_import.html).
|
||||
|
54
docs/user/five_day_setup/docs.user.five_day_setup.day_2.md
Normal file
54
docs/user/five_day_setup/docs.user.five_day_setup.day_2.md
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
{
|
||||
"_label": "Day-2: Setup Chart of Accounts, Opening Accounts, and HR"
|
||||
}
|
||||
---
|
||||
|
||||
#### Setup Page - Accounts
|
||||
<br>
|
||||
Go to the Accounts icon and make ledgers under Chart of Accounts.
|
||||
|
||||
![Accounts](img/seconddaysetup-accounts.png)
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
Create acccounting ledgers.
|
||||
|
||||
![Tree](img/seconddaysetup-tree.png)
|
||||
|
||||
<br>
|
||||
|
||||
To begin Opening Entries, go to 'Opening Accounts and Stock' on the Setup Page.
|
||||
|
||||
![Ledger](img/seconddaysetup-accounts-jv.png)
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
To understand how to create opening entries in detail visit [Opening Entry](docs.user.setup.opening.html).
|
||||
|
||||
<br>
|
||||
|
||||
#### Opening Stock
|
||||
|
||||
You can upload your opening stock in the system using Stock Reconciliation. Stock Reconciliation will update your stock for any given Item.
|
||||
|
||||
![Stock Opening](img/seconddaysetup-stock-opening.png)
|
||||
<br>
|
||||
|
||||
|
||||
To understand Stock Opening in detail visit [Opening Stock](docs.user.accounts.opening_stock.html).
|
||||
|
||||
<br>
|
||||
|
||||
#### Setup Page - HR Setup
|
||||
|
||||
To setup HR, begin by creating individual employee records.
|
||||
|
||||
|
||||
![Employee](img/seconddaysetup-hr.png)
|
||||
|
||||
To fill the Employee Form, refer to [Employee](docs.user.hr.employee.html)
|
||||
|
||||
To complete the remaining HR-Setup, see [Human Resources](docs.user.hr.html)
|
139
docs/user/five_day_setup/docs.user.five_day_setup.day_3.md
Normal file
139
docs/user/five_day_setup/docs.user.five_day_setup.day_3.md
Normal file
@ -0,0 +1,139 @@
|
||||
---
|
||||
{
|
||||
"_label": "Day-3: Sales Cycle and Purchase Cycle"
|
||||
}
|
||||
---
|
||||
After completing the set-up and account opening process, it is advisable to complete a few cycles of sales, purchase, and manufacturing process.
|
||||
|
||||
|
||||
### Sales Cycle
|
||||
|
||||
Complete a standard Sales Cycle.
|
||||
> Lead > Opportunity > Quotation > Sales Order > Delivery Note > Sales Invoice > Payment (Journal Voucher)
|
||||
|
||||
<br>
|
||||
#### Lead
|
||||
|
||||
To begin the sales cycle, go to the Selling Icon. On the selling page, click on Lead.
|
||||
|
||||
![Lead](img/thirddaysetup-lead.png)
|
||||
|
||||
Fill the Lead form.
|
||||
|
||||
> To understand Lead in detail, visit [Lead](docs.user.selling.lead.html)
|
||||
|
||||
<br>
|
||||
#### Opportunity
|
||||
|
||||
After completing the Lead form, assume that, this same lead is getting converted into an Opportunity. Thus, to create an Opportunity from the existing lead, click on Create Opportunity, on the Lead page.
|
||||
|
||||
##### Step 1: Go to 'Lead List' Page and open the Lead that shows interested status.
|
||||
|
||||
![Opportunity](img/thirddaysetup-opportunity-1.png)
|
||||
|
||||
<br>
|
||||
|
||||
##### Step 2: Generate Opportunity from the selected Lead
|
||||
|
||||
![Opportunity](img/thirddaysetup-opportunity.png)
|
||||
|
||||
You can also generate an Opportunity directly from the Selling Page.
|
||||
|
||||
> To understand Opportunity in detail visit [Opportunity](docs.user.selling.opportunity.html).
|
||||
|
||||
<br>
|
||||
#### Quotation
|
||||
|
||||
Imagine that your Opportunity has shown interest and asked for a Quotation. To generate a Quotation from the same Opportunity, open the submitted Opportunity and click on Create Quotation.
|
||||
|
||||
![Quotation](img/thirddaysetup-quotation.png)
|
||||
|
||||
You can also generate a Quotation directly from the Selling Page.
|
||||
|
||||
> To understand Quotation in detail visit [Quotation](docs.user.selling.quotation.html)
|
||||
|
||||
<br>
|
||||
#### Sales Order
|
||||
|
||||
Imagine that the Quotation which you sent was accepted by the prospect. You are now reequired to send him a Sales Order. To make a sales order from this same Quotation, go to that Quotation page and click on Make Sales Order.
|
||||
|
||||
![Sales Order](img/thirddaysetup-sales-order.png)
|
||||
|
||||
You can also generate a Sales Order directly from the Selling Page.
|
||||
|
||||
> To understand Sales Order in detail visit [Sales Order](docs.user.selling.sales_order.html).
|
||||
|
||||
<br>
|
||||
#### Delivery Note
|
||||
|
||||
If your organisation has the practice of sending Delivery Note, this section will be helpful. To create a Delivery Note from the a Sales Order, go to that Sales Order and click on Make Delivery.
|
||||
|
||||
|
||||
![Delivery Note](img/thirddaysetup-delivery-note.png)
|
||||
|
||||
> To understand Delivery Note in detail, visit [Delivery Note](docs.user.stock.delivery_note.html)
|
||||
|
||||
<br>
|
||||
#### Sales Invoice
|
||||
|
||||
Save and Submit your Delivery Note to generate a Sales Invoice. You can also generate an Invoice from Sales Order.
|
||||
|
||||
![Sales Invoice](img/thirddaysetup-sales-invoice.png)
|
||||
|
||||
<br>
|
||||
|
||||
#### Payment (Journal Voucher)
|
||||
|
||||
|
||||
A Journal Voucher or a payment entry can be generated directly from the Sales Invoice.
|
||||
|
||||
![Payment Entry](img/thirddaysetup-payment-entry.png)
|
||||
|
||||
> To understand a Journal Voucher in detail, visit [Journal Voucher](docs.user.accounts.journal_voucher.html)
|
||||
|
||||
<br>
|
||||
|
||||
### Purchase Cycle
|
||||
|
||||
Complete a standard Purchase Cycle.
|
||||
> Material Request > Purchase Order > Purchase Receipt > Payment (Journal Voucher).
|
||||
|
||||
<br>
|
||||
#### Material Request
|
||||
|
||||
To create a Material Request, go to Stock/Buying and Click on Material Request.
|
||||
|
||||
![Material Request](img/thirddaysetup-material-request.png)
|
||||
|
||||
> To understand Material Request in detail, visit [Material Request](docs.user.buying.material_request.html)
|
||||
|
||||
<br>
|
||||
#### Purchase Order
|
||||
|
||||
To create a Purchase Order go to Buying and click on Purchase Order
|
||||
|
||||
![Purchase Order](img/thirddaysetup-purchase-order.png)
|
||||
|
||||
> To understand Purchase Order in detail, visit [Purchase Order](docs.user.buying.purchase_order.html)
|
||||
|
||||
<br>
|
||||
#### Purchase Receipt
|
||||
|
||||
To create a Purchase Receipt from an existing Purchase Order, open that purchase order and click on Make Purchase Receipt.
|
||||
|
||||
![Purchase Receipt](img/thirddaysetup-purchase-receipt.png)
|
||||
<br>
|
||||
|
||||
>To understand Purchase Receipt in detail, visit [Purchase Receipt](docs.user.stock.purchase_receipt.html)
|
||||
|
||||
<br>
|
||||
|
||||
#### Payment (Journal Voucher)
|
||||
|
||||
Payments made against Sales Invoices or Purchase Invoices can be made by clicking on “Make Payment Entry” button on “Submitted” invoices.
|
||||
|
||||
|
||||
![Payment Entry](img/thirddaysetup-payment-entry.png)
|
||||
<br>
|
||||
|
||||
> To understand Payment Entry in detail, visit [Payment Entry](docs.user.accounts.payments.html).
|
86
docs/user/five_day_setup/docs.user.five_day_setup.day_4.md
Normal file
86
docs/user/five_day_setup/docs.user.five_day_setup.day_4.md
Normal file
@ -0,0 +1,86 @@
|
||||
---
|
||||
{
|
||||
"_label": "Day-4: Manufacturing Cycle and Accounting Reports"
|
||||
}
|
||||
---
|
||||
|
||||
### Manufacturing Cycle
|
||||
|
||||
Complete a manufacturing cycle (if applicable).
|
||||
> BOM > Production Planning Tool > Production Order > Stock Entry (Material Issue) > Stock Entry (Sales Return)
|
||||
|
||||
<br>
|
||||
#### Bill of Materials
|
||||
|
||||
To go to Bill of Materials, Click on Manufacturing. On the Manufacturing page, click on Bill of Materials.
|
||||
|
||||
![Bill of Materials](img/fourthdaysetup-bom.png)
|
||||
|
||||
> To understand BOM in detail, visit [Bill of Materials](docs.user.mfg.bom.html)
|
||||
|
||||
<br>
|
||||
#### Production Planning Tool
|
||||
|
||||
To go to Production Planning Tool, click on the Manufacturing Icon. On the Manufacturing Page, click on Production Planning Tool to go to that page.
|
||||
|
||||
![Production Planning Page](img/fourthdaysetup-ppt.png)
|
||||
|
||||
> To understand Production Planning Tool in detail, visit [Production Planning](docs.user.mfg.planning.html)
|
||||
|
||||
<br>
|
||||
#### Production Order
|
||||
|
||||
To go to Production Order click on the Manufacturing Icon. On the Manufacturing Page, click on Production Order.
|
||||
|
||||
![Production Order](img/fourthdaysetup-po.png)
|
||||
|
||||
> To understand Production Order in detail, visit [Production Order](docs.user.mfg.production_order.html)
|
||||
|
||||
<br>
|
||||
#### Stock Entry
|
||||
|
||||
To go to Stock Entry, click on the Stock Icon and go to Stock Entry.
|
||||
|
||||
![Stock Entry](img/fourthdaysetup-stock.png)
|
||||
|
||||
> To understand Material Issue, visit [Material Issue](docs.user.stock.material_issue.html).
|
||||
|
||||
> To understand Sales Return, visit [Sales Return](docs.user.stock.sales_return.html).
|
||||
|
||||
<br>
|
||||
#### Delivery Note
|
||||
|
||||
To go to Delivery Note, click on Stock. On the Stock Page, click on Delivery Note.
|
||||
|
||||
![Delivery Note](img/fourthdaysetup-delivery-note.png)
|
||||
|
||||
> To understand Delivery Note in detail, visit [Delivery Note](docs.user.stock.delivery_note.html)
|
||||
|
||||
<br>
|
||||
#### Warehouse
|
||||
|
||||
To go to Warehouse, Click on Stock. On the Stock Page, go to Warehouse.
|
||||
|
||||
![Warehouse](img/fourthdaysetup-warehouse.png)
|
||||
|
||||
> To understand Warehouse in detail, visit [Warehouse](docs.user.stock.warehouse.html)
|
||||
|
||||
<br>
|
||||
#### Accounts
|
||||
|
||||
Make a few Journal Vouchers. Generate some Accounting Reports.
|
||||
|
||||
#### Journal Voucher
|
||||
|
||||
To go to a Journal Voucher, click on Accounts. On the Accounts page, click on Journal Voucher.
|
||||
|
||||
![Journal Voucher](img/fourthdaysetup-jv.png)
|
||||
|
||||
> To understand Journal Voucher in detail, visit [Journal Voucher](docs.user.accounts.journal_voucher.html)
|
||||
|
||||
<br>
|
||||
### Accounting Reports
|
||||
|
||||
Some of the major Accounting Reports are General Ledger, Trial Balance, Accounts Payable and Accounts Receivables, and Sales and Purchase Register.
|
||||
|
||||
> To be able to generate these accounts, visti [Accounting Reports](docs.user.accounts.report.html)
|
32
docs/user/five_day_setup/docs.user.five_day_setup.day_5.md
Normal file
32
docs/user/five_day_setup/docs.user.five_day_setup.day_5.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
{
|
||||
"_label": "Day-5: Projects, Calendar, and Website"
|
||||
}
|
||||
---
|
||||
|
||||
#### Projects
|
||||
|
||||
ERPNext helps you to manage your Projects by breaking them into Tasks and allocating them to different people.
|
||||
|
||||
<br>
|
||||
#### Tasks
|
||||
|
||||
Project is divided into Tasks and each Task is allocated to a resource. In ERPNext, you can also create and allocate a Task independently of a Project.
|
||||
|
||||
To create a Task, go to Project and click on Task.
|
||||
|
||||
![Tasks](img/fifthdaysetup-tasks.png)
|
||||
|
||||
> To understand Projects in detail, visit [Projects](docs.user.projects.html).
|
||||
|
||||
> To understand Task in detail, visit [Tasks](docs.user.projects.tasks.html)
|
||||
|
||||
<br>
|
||||
#### Calendar
|
||||
|
||||
> To understand Calendar in detail, visit [Calendar](docs.user.tools.calendar.html)
|
||||
|
||||
<br>
|
||||
#### Website
|
||||
|
||||
> To understand Website in detail, visit [Website](docs.user.website.html)
|
48
docs/user/five_day_setup/docs.user.five_day_setup.md
Normal file
48
docs/user/five_day_setup/docs.user.five_day_setup.md
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
{
|
||||
"_label": "Five-Day Setup",
|
||||
"_toc": [
|
||||
"docs.user.five_day_setup.day_1",
|
||||
"docs.user.five_day_setup.day_2",
|
||||
"docs.user.five_day_setup.day_3",
|
||||
"docs.user.five_day_setup.day_4",
|
||||
"docs.user.five_day_setup.day_5"
|
||||
|
||||
]
|
||||
}
|
||||
---
|
||||
Welcome to ERPNext. To be able to setup ERPNext account successfully, a five-day-setup process is recommended. Perform the 5-days-setup instructions and sail through the ERPNext implementation.
|
||||
|
||||
The setup help is divided into day-wise instructions for 5 consecutive days.
|
||||
|
||||
#### Day 1
|
||||
|
||||
- Company Setup
|
||||
- Customer Setup
|
||||
- Item Setup
|
||||
- Supplier Setup
|
||||
- Data Import Tool
|
||||
|
||||
#### Day 2
|
||||
|
||||
- Opening Accounts
|
||||
- Opening Stock
|
||||
- HR Setup
|
||||
|
||||
#### Day 3
|
||||
|
||||
- Sales Cycle
|
||||
- Purchase Cycle
|
||||
|
||||
|
||||
#### Day 4
|
||||
|
||||
- Manufacturing Cycle
|
||||
- Delivery Note and Warehouse
|
||||
- Accounts
|
||||
|
||||
#### Day 5
|
||||
|
||||
- Projects
|
||||
- Calendar
|
||||
- Website
|
@ -10,11 +10,12 @@ Before you start managing your Operations in EPRNext, you must first become fami
|
||||
### Test Phase
|
||||
|
||||
- Read the Manual
|
||||
- Follow the Five-Day-Setup Module or the instructions given below.
|
||||
- Create your first Customer, Supplier and Item. Add a few more so you get familiar with them.
|
||||
- Create Customer Groups, Item Groups, Warehouses, Supplier Groups, so that you can classify your Items.
|
||||
- Complete a standard sales cycle - Lead > Opportunity > Quotation > Sales Order > Delivery Note > Sales Invoice > Payment (Journal Voucher)
|
||||
- Complete a standard purchase cycle - Purchase Request > Purchase Order > Purchase Receipt > Payment (Journal Voucher).
|
||||
- Complete a manufacturing cycle (if applicable) - BOM > Production Planning Tool > Production Order > Stock Entry (issue) > Stock Entry (back-flush)
|
||||
- Complete a standard purchase cycle - Material Request > Purchase Order > Purchase Receipt > Payment (Journal Voucher).
|
||||
- Complete a manufacturing cycle (if applicable) - BOM > Production Planning Tool > Production Order > Material Issue > Sales Return
|
||||
|
||||
> Tip: Use the 30-day free trial at [erpnext.com](https://erpnext.com) to take your test drive.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
{
|
||||
"_label": "Attachement and CSV files"
|
||||
"_label": "Attachment and CSV files"
|
||||
}
|
||||
---
|
||||
|
||||
|
@ -45,6 +45,14 @@ ERPNext will help you set and manage budgets on your Cost Centers. This is usefu
|
||||
Budgets are also great for planning purposes. When you are making plans for the next financial year, you would typically target a revenue based on which you would set your expenses. Setting a budget will ensure that your expenses do not get out of hand, at any point, as per your plans.
|
||||
|
||||
You can define it in the Cost Center. If you have seasonal sales you can also define a budget distribution that the budget will follow.
|
||||
|
||||
> Accounts > Budget Distribution > New Budget Distribution
|
||||
|
||||
|
||||
![Budget Distribution](img/budgeting.png)
|
||||
|
||||
|
||||
|
||||

|
||||
#### Budget Actions
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
"docs.user.setup.email",
|
||||
"docs.user.setup.sms",
|
||||
"docs.user.setup.taxes",
|
||||
"docs.user.setup.price_lists",
|
||||
"docs.user.setup.price_list",
|
||||
"docs.user.setup.opening",
|
||||
"docs.user.setup.pos_setting",
|
||||
"docs.user.setup.third_party_backups"
|
||||
|
@ -7,7 +7,7 @@ A Price List is a place where different rate plans can be stored. It’s a name
|
||||
|
||||
An Item can have multiple prices based on customer, currency, region, shipping cost etc, which can be stored as different rate plans. In ERPNext, you are required to store all the lists seperately. Buying Price List is different from Selling Price List and thus is stored separately.
|
||||
|
||||
> Selling > Price List
|
||||
> Setup > Price List
|
||||
|
||||
|
||||
![Price-List](img/price-lists.png)
|
||||
@ -15,7 +15,14 @@ An Item can have multiple prices based on customer, currency, region, shipping c
|
||||
|
||||
> For multiple currencies, maintain multiple Price Lists.
|
||||
|
||||
<br>
|
||||
### Add Item in Price List
|
||||
|
||||
To add a new Item to the Price List, add the Item Code and its rate in the Item Prices table.
|
||||
> Setup > Item Price
|
||||
|
||||
You can also import Item Prices via [Data Import Tool](docs.user.setup.data_import.html)
|
||||
- Enter Price List and Item Code, Valid for Buying or Selling, Item Name & Item Description will be automatically fetched.
|
||||
- Enter Rate and save the document.
|
||||
|
||||
![Item-Price](img/item-price.png)
|
||||
|
||||
For bulk upload of Item Prices, use [Data Import Tool](docs.user.setup.data_import.html)
|
@ -6,7 +6,7 @@
|
||||
|
||||
ERPNext has a role-based permission system, which means that you can assign Roles to Users, and permissions on Roles.Each ERPNext user has a Profile. The Profile contains the user’s email and authentication and can be set from:
|
||||
|
||||
> Setup > Users and Permissions > Users
|
||||
> Setup > Profile
|
||||
|
||||
#### Step 1: Adding a new User
|
||||
|
||||
|
@ -15,7 +15,7 @@ ERPNext is optimized for itemized management of your sales and purchase. If you
|
||||
|
||||
- **Item Name:** Item name is the actual name of your product or service.
|
||||
- **Item Code:** Item Code is a short-form to denote your Item. If you have very few Items, it is advisable to keep the Item Name and the Item Code same. This helps new users to recognise and update Item details in all transactions. In case you have lot of Items with long names and the list runs in hundreds, it is advisable to code. To understand naming Item codes see [Item Codification](docs.user.setup.codification.html)
|
||||
- **Item Group:** Item Group is used to categorize an Item under various criterias like products, raw materials, services, sub-assemblies, consumables or all Item groups. Create your default Item Group list under Setup> Item Group and pre-select the option while filling your New Item details under Item Group.
|
||||
- **Item Group:** Item Group is used to categorize an Item under various criterias like products, raw materials, services, sub-assemblies, consumables or all Item groups. Create your default Item Group list under Setup> Item Group and pre-select the option while filling your New Item details under [Item Group](docs.user.stock.item_group.html)
|
||||
- **Default Unit of Measure:** This is the default measuring unit that you will use for your product. It could be in nos, kgs, meters, etc. You can store all the UOM’s that your product will require under Set Up> Master Data > UOM. These can be preselected while filling New Item by using % sign to get a pop up of the UOM list.
|
||||
- **Brand:** If you have more than one brand save them under Set Up> Master Data> Brand and pre-select them while filling a New Item.
|
||||
|
||||
@ -91,3 +91,59 @@ Inspection Criteria: If a Quality Inspection is prepared for this Item, then thi
|
||||
|
||||
|
||||
Visit [Manufacturing](docs.user.mfg.html) and [Website](docs.user.website.html) to understand these topics in detail.
|
||||
|
||||
### Listing Item on Website
|
||||
|
||||
To list your Item on the Website, fill the Item details and save the file. Once the file is saved, a plus (+) button will appear next to the Image icon. Click on the plus button and add your Item image. The html code will be generated automatically.
|
||||
|
||||
##### Step 1: Save Image
|
||||
|
||||
![Webimage](img/item-webimage.png)
|
||||
|
||||
<br>
|
||||
|
||||
##### Step 2: Check the 'Show in Website' box.
|
||||
|
||||
Under the Website section, please check the box that says 'show in Website'. Once the box is checked, the page will display other fields for entering information.
|
||||
|
||||
![Webimage](img/item-webimage-1.png)
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
##### Step 3: Enter Website Details
|
||||
|
||||
![Webimage](img/item-webimage-2.png)
|
||||
|
||||
|
||||
The page name will be generated automatically. Mention the Item-Group under which the Item will be displayed.
|
||||
|
||||
#### Item Groups
|
||||
|
||||
Mention the Item Group under this column. If you wish to list your Item under the broad category products, name your Item Group as Products. In case you have various varieties of Item and want to classify them under different names, make Item Groups with those names and check the box that says 'show in Website'. For Example, if you wish to create a category called 'Bags', create a Item Group named Bags.
|
||||
|
||||
|
||||
![Item Group](img/itemgroup-webimage-bags.png)
|
||||
|
||||
Once the Item Group is created go to the Website Settings page under Website. Enter the Label, Url, and Parent Label.
|
||||
|
||||
|
||||
![Item Group](img/itemgroup-website-settings.png)
|
||||
|
||||
<br>
|
||||
|
||||
#### Webpage labels
|
||||
|
||||
![Webpage](img/webpage-labels.png)
|
||||
|
||||
Add more Items under a particular Item Group.
|
||||
|
||||
To add more Items under a certain Label, mention the Item Group on the Item Page. The Items will be added automatically on the Webpage, under the Item Group Label. For Example, To add Item-Kiddies Bag and Butterfly Print Bag, check the 'Show in Website'box. The Items will be placed under the Label Bags on the Webpage.
|
||||
|
||||
![Item Group](img/itemgroup-websettings.png)
|
||||
|
||||
<br>
|
||||
|
||||
Item Group Display
|
||||
|
||||
![Item Group Display](img/webpage-itemgroup-display.png)
|
@ -15,6 +15,11 @@ To create a new blog, just create a new Blog from:
|
||||
![Blog](img/blog.png)
|
||||
|
||||
|
||||
You can format the blog using the same Markdown format
|
||||
You can format a blog using the Markdown format.You can also access your blog by going to the page “blog.html”.
|
||||
|
||||
|
||||
#### A sample blog-page.
|
||||
|
||||
|
||||
![Blog](img/blog-look.png)
|
||||
|
||||
You can access your blog by going to the page “blog.html”
|
||||
|
@ -29,11 +29,36 @@ To define the Top Bar Menus, Brand, Footers and Home Page, go to:
|
||||
|
||||
> Website > Website Settings
|
||||
|
||||
#### Step 1: Landing Page Details
|
||||
|
||||
![Website Setting](img/website-settings.png)
|
||||
|
||||
<br>
|
||||
|
||||
#### Step 2: Banner Details
|
||||
|
||||
![Website Setting](img/website-settings-1.png)
|
||||
|
||||
<br>
|
||||
|
||||
#### Step 3: Top Bar Labels
|
||||
|
||||
![Website Setting](img/website-settings-2.png)
|
||||
|
||||
> Note: Create seperate web pages which will be linked to the main web-icons like company, contact, products etc.
|
||||
|
||||
<br>
|
||||
#### Step 4: Footer Details
|
||||
|
||||
![Website Setting](img/website-settings-3.png)
|
||||
|
||||
A website can be generated once all the settings and style requirements are added.
|
||||
|
||||
A sample website generated by ERPNext would look like this.
|
||||
|
||||
![Website](img/website-settings-4.png)
|
||||
|
||||
<br>
|
||||
|
||||
#### Top Menu
|
||||
|
||||
|
@ -17,6 +17,9 @@ class DocType:
|
||||
self.doclist = doclist
|
||||
|
||||
def validate(self):
|
||||
if self.doc.docstatus == 0:
|
||||
self.doc.status = "Draft"
|
||||
|
||||
import utilities
|
||||
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
|
||||
"In Process", "Completed", "Cancelled"])
|
||||
@ -148,12 +151,6 @@ def get_item_details(item):
|
||||
@webnotes.whitelist()
|
||||
def make_stock_entry(production_order_id, purpose):
|
||||
production_order = webnotes.bean("Production Order", production_order_id)
|
||||
|
||||
# validate already existing
|
||||
ste = webnotes.conn.get_value("Stock Entry", {
|
||||
"production_order":production_order_id,
|
||||
"purpose": purpose
|
||||
}, "name")
|
||||
|
||||
stock_entry = webnotes.new_bean("Stock Entry")
|
||||
stock_entry.doc.purpose = purpose
|
||||
|
@ -0,0 +1,75 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import unittest
|
||||
import webnotes
|
||||
from stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
||||
from manufacturing.doctype.production_order.production_order import make_stock_entry
|
||||
|
||||
|
||||
class TestProductionOrder(unittest.TestCase):
|
||||
def test_planned_qty(self):
|
||||
set_perpetual_inventory(0)
|
||||
webnotes.conn.sql("delete from `tabStock Ledger Entry`")
|
||||
webnotes.conn.sql("""delete from `tabBin`""")
|
||||
webnotes.conn.sql("""delete from `tabGL Entry`""")
|
||||
|
||||
pro_bean = webnotes.bean(copy = test_records[0])
|
||||
pro_bean.insert()
|
||||
pro_bean.submit()
|
||||
|
||||
from stock.doctype.stock_entry.test_stock_entry import test_records as se_test_records
|
||||
mr1 = webnotes.bean(copy = se_test_records[0])
|
||||
mr1.insert()
|
||||
mr1.submit()
|
||||
|
||||
mr2 = webnotes.bean(copy = se_test_records[0])
|
||||
mr2.doclist[1].item_code = "_Test Item Home Desktop 100"
|
||||
mr2.insert()
|
||||
mr2.submit()
|
||||
|
||||
stock_entry = make_stock_entry(pro_bean.doc.name, "Manufacture/Repack")
|
||||
stock_entry = webnotes.bean(stock_entry)
|
||||
|
||||
stock_entry.doc.fg_completed_qty = 4
|
||||
stock_entry.run_method("get_items")
|
||||
stock_entry.submit()
|
||||
|
||||
self.assertEqual(webnotes.conn.get_value("Production Order", pro_bean.doc.name,
|
||||
"produced_qty"), 4)
|
||||
self.assertEqual(webnotes.conn.get_value("Bin", {"item_code": "_Test FG Item",
|
||||
"warehouse": "_Test Warehouse 1 - _TC"}, "planned_qty"), 6)
|
||||
|
||||
return pro_bean.doc.name
|
||||
|
||||
def test_over_production(self):
|
||||
from stock.doctype.stock_entry.stock_entry import StockOverProductionError
|
||||
pro_order = self.test_planned_qty()
|
||||
|
||||
stock_entry = make_stock_entry(pro_order, "Manufacture/Repack")
|
||||
stock_entry = webnotes.bean(stock_entry)
|
||||
|
||||
stock_entry.doc.fg_completed_qty = 15
|
||||
stock_entry.run_method("get_items")
|
||||
stock_entry.insert()
|
||||
|
||||
self.assertRaises(StockOverProductionError, stock_entry.submit)
|
||||
|
||||
|
||||
|
||||
test_records = [
|
||||
[
|
||||
{
|
||||
"bom_no": "BOM/_Test FG Item/001",
|
||||
"company": "_Test Company",
|
||||
"doctype": "Production Order",
|
||||
"production_item": "_Test FG Item",
|
||||
"qty": 10.0,
|
||||
"fg_warehouse": "_Test Warehouse 1 - _TC",
|
||||
"wip_warehouse": "_Test Warehouse - _TC",
|
||||
"stock_uom": "Nos"
|
||||
}
|
||||
]
|
||||
]
|
@ -3,16 +3,9 @@
|
||||
|
||||
def execute():
|
||||
import webnotes
|
||||
from webnotes.utils import flt
|
||||
bins = webnotes.conn.sql("select item_code, warehouse, name, ordered_qty from `tabBin`")
|
||||
for d in bins:
|
||||
ordered_qty = webnotes.conn.sql("""
|
||||
select sum(ifnull(po_item.qty, 0) - ifnull(po_item.received_qty, 0))
|
||||
from `tabPurchase Order Item` po_item, `tabPurchase Order` po
|
||||
where po_item.parent = po.name and po.docstatus = 1 and po.status != 'Stopped'
|
||||
and po_item.item_code = %s and po_item.warehouse = %s
|
||||
""", (d[0], d[1]))
|
||||
|
||||
if flt(d[3]) != flt(ordered_qty[0][0]):
|
||||
webnotes.conn.sql("""update `tabBin` set ordered_qty = %s where name = %s""",
|
||||
(ordered_qty and ordered_qty[0][0] or 0, d[2]))
|
||||
from utilities.repost_stock import get_ordered_qty, update_bin
|
||||
|
||||
for d in webnotes.conn.sql("select item_code, warehouse from tabBin"):
|
||||
update_bin(d[0], d[1], {
|
||||
"ordered_qty": get_ordered_qty(d[0], d[1])
|
||||
})
|
@ -4,54 +4,10 @@
|
||||
import webnotes
|
||||
def execute():
|
||||
webnotes.conn.auto_commit_on_many_writes = 1
|
||||
repost_reserved_qty()
|
||||
webnotes.conn.auto_commit_on_many_writes = 0
|
||||
from utilities.repost_stock import get_reserved_qty, update_bin
|
||||
|
||||
def repost_reserved_qty():
|
||||
from webnotes.utils import flt
|
||||
bins = webnotes.conn.sql("select item_code, warehouse, name, reserved_qty from `tabBin`")
|
||||
i = 0
|
||||
for d in bins:
|
||||
i += 1
|
||||
reserved_qty = webnotes.conn.sql("""
|
||||
select
|
||||
sum((dnpi_qty / so_item_qty) * (so_item_qty - so_item_delivered_qty))
|
||||
from
|
||||
(
|
||||
(select
|
||||
qty as dnpi_qty,
|
||||
(
|
||||
select qty from `tabSales Order Item`
|
||||
where name = dnpi.parent_detail_docname
|
||||
) as so_item_qty,
|
||||
(
|
||||
select ifnull(delivered_qty, 0) from `tabSales Order Item`
|
||||
where name = dnpi.parent_detail_docname
|
||||
) as so_item_delivered_qty,
|
||||
parent, name
|
||||
from
|
||||
(
|
||||
select qty, parent_detail_docname, parent, name
|
||||
from `tabDelivery Note Packing Item` dnpi_in
|
||||
where item_code = %s and warehouse = %s
|
||||
and parenttype="Sales Order"
|
||||
and item_code != parent_item
|
||||
and exists (select * from `tabSales Order` so
|
||||
where name = dnpi_in.parent and docstatus = 1 and status != 'Stopped')
|
||||
) dnpi)
|
||||
union
|
||||
(select qty as dnpi_qty, qty as so_item_qty,
|
||||
ifnull(delivered_qty, 0) as so_item_delivered_qty, parent, name
|
||||
from `tabSales Order Item` so_item
|
||||
where item_code = %s and reserved_warehouse = %s
|
||||
and exists(select * from `tabSales Order` so
|
||||
where so.name = so_item.parent and so.docstatus = 1
|
||||
and so.status != 'Stopped'))
|
||||
) tab
|
||||
where
|
||||
so_item_qty >= so_item_delivered_qty
|
||||
""", (d[0], d[1], d[0], d[1]))
|
||||
|
||||
if flt(d[3]) != flt(reserved_qty[0][0]):
|
||||
webnotes.conn.sql("""update `tabBin` set reserved_qty = %s where name = %s""",
|
||||
(reserved_qty and reserved_qty[0][0] or 0, d[2]))
|
||||
for d in webnotes.conn.sql("select item_code, warehouse from tabBin"):
|
||||
update_bin(d[0], d[1], {
|
||||
"reserved_qty": get_reserved_qty(d[0], d[1])
|
||||
})
|
||||
webnotes.conn.auto_commit_on_many_writes = 0
|
6
patches/october_2013/repost_ordered_qty.py
Normal file
6
patches/october_2013/repost_ordered_qty.py
Normal file
@ -0,0 +1,6 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
def execute():
|
||||
from patches.december_2012 import repost_ordered_qty
|
||||
repost_ordered_qty.execute()
|
11
patches/october_2013/repost_planned_qty.py
Normal file
11
patches/october_2013/repost_planned_qty.py
Normal file
@ -0,0 +1,11 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
def execute():
|
||||
import webnotes
|
||||
from utilities.repost_stock import get_planned_qty, update_bin
|
||||
|
||||
for d in webnotes.conn.sql("select item_code, warehouse from tabBin"):
|
||||
update_bin(d[0], d[1], {
|
||||
"planned_qty": get_planned_qty(d[0], d[1])
|
||||
})
|
@ -226,4 +226,6 @@ patch_list = [
|
||||
"execute:webnotes.delete_doc('DocType', 'Setup Control')",
|
||||
"patches.october_2013.p04_wsgi_migration",
|
||||
"patches.october_2013.p05_server_custom_script_to_file",
|
||||
"patches.october_2013.repost_ordered_qty",
|
||||
"patches.october_2013.repost_planned_qty",
|
||||
]
|
@ -28,9 +28,7 @@ erpnext.StockGridReport = wn.views.TreeGridReport.extend({
|
||||
var value_diff = (rate * add_qty);
|
||||
|
||||
if(add_qty)
|
||||
wh.fifo_stack.push([add_qty, sl.incoming_rate, sl.posting_date]);
|
||||
|
||||
if(sl.serial_no) value_diff = this.get_serialized_value_diff(sl);
|
||||
wh.fifo_stack.push([add_qty, sl.incoming_rate, sl.posting_date]);
|
||||
} else {
|
||||
// outgoing
|
||||
if(sl.serial_no) {
|
||||
@ -113,7 +111,8 @@ erpnext.StockGridReport = wn.views.TreeGridReport.extend({
|
||||
$.each(wn.report_dump.data["Stock Ledger Entry"], function(i, sle) {
|
||||
if(sle.qty > 0 && sle.serial_no) {
|
||||
$.each(sle.serial_no.trim().split("\n"), function(i, sr) {
|
||||
if(sr && sle.incoming_rate !== undefined) {
|
||||
if(sr && sle.incoming_rate !== undefined
|
||||
&& !serialized_buying_rates[sr.trim().toLowerCase()]) {
|
||||
serialized_buying_rates[sr.trim().toLowerCase()] = flt(sle.incoming_rate);
|
||||
}
|
||||
});
|
||||
|
@ -21,8 +21,6 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
company: wn.defaults.get_default("company"),
|
||||
fiscal_year: wn.defaults.get_default("fiscal_year"),
|
||||
is_subcontracted: "No",
|
||||
conversion_rate: 1.0,
|
||||
plc_conversion_rate: 1.0
|
||||
}, function(fieldname, value) {
|
||||
if(me.frm.fields_dict[fieldname] && !me.frm.doc[fieldname])
|
||||
me.frm.set_value(fieldname, value);
|
||||
@ -41,18 +39,19 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
},
|
||||
|
||||
onload_post_render: function() {
|
||||
if(this.frm.doc.__islocal && this.frm.doc.company && !this.frm.doc.customer) {
|
||||
var me = this;
|
||||
return this.frm.call({
|
||||
doc: this.frm.doc,
|
||||
method: "onload_post_render",
|
||||
freeze: true,
|
||||
callback: function(r) {
|
||||
// remove this call when using client side mapper
|
||||
me.set_default_values();
|
||||
me.set_dynamic_labels();
|
||||
}
|
||||
});
|
||||
if(this.frm.doc.__islocal && this.frm.doc.company &&
|
||||
!this.frm.doc.customer && !this.frm.doc.is_pos) {
|
||||
var me = this;
|
||||
return this.frm.call({
|
||||
doc: this.frm.doc,
|
||||
method: "onload_post_render",
|
||||
freeze: true,
|
||||
callback: function(r) {
|
||||
// remove this call when using client side mapper
|
||||
me.set_default_values();
|
||||
me.set_dynamic_labels();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@ -131,10 +130,18 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
|
||||
company: function() {
|
||||
if(this.frm.doc.company && this.frm.fields_dict.currency) {
|
||||
if(!this.frm.doc.currency) {
|
||||
this.frm.set_value("currency", this.get_company_currency());
|
||||
var company_currency = this.get_company_currency();
|
||||
if (!this.frm.doc.currency) {
|
||||
this.frm.set_value("currency", company_currency);
|
||||
}
|
||||
|
||||
if (this.frm.doc.currency == company_currency) {
|
||||
this.frm.set_value("conversion_rate", 1.0);
|
||||
}
|
||||
if (this.frm.doc.price_list_currency == company_currency) {
|
||||
this.frm.set_value('plc_conversion_rate', 1.0);
|
||||
}
|
||||
|
||||
this.frm.script_manager.trigger("currency");
|
||||
}
|
||||
},
|
||||
@ -146,15 +153,13 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
currency: function() {
|
||||
var me = this;
|
||||
this.set_dynamic_labels();
|
||||
|
||||
|
||||
var company_currency = this.get_company_currency();
|
||||
if(this.frm.doc.currency !== company_currency) {
|
||||
this.get_exchange_rate(this.frm.doc.currency, company_currency,
|
||||
function(exchange_rate) {
|
||||
if(exchange_rate) {
|
||||
me.frm.set_value("conversion_rate", exchange_rate);
|
||||
me.conversion_rate();
|
||||
}
|
||||
me.frm.set_value("conversion_rate", exchange_rate);
|
||||
me.conversion_rate();
|
||||
});
|
||||
} else {
|
||||
this.conversion_rate();
|
||||
@ -168,7 +173,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
this.frm.doc.plc_conversion_rate !== this.frm.doc.conversion_rate) {
|
||||
this.frm.set_value("plc_conversion_rate", this.frm.doc.conversion_rate);
|
||||
}
|
||||
|
||||
|
||||
this.calculate_taxes_and_totals();
|
||||
},
|
||||
|
||||
@ -233,29 +238,6 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
this.calculate_taxes_and_totals();
|
||||
},
|
||||
|
||||
// serial_no: function(doc, cdt, cdn) {
|
||||
// var me = this;
|
||||
// var item = wn.model.get_doc(cdt, cdn);
|
||||
// if (!item.item_code) {
|
||||
// wn.call({
|
||||
// method: 'accounts.doctype.sales_invoice.pos.get_item_from_serial_no',
|
||||
// args: {serial_no: this.serial_no.$input.val()},
|
||||
// callback: function(r) {
|
||||
// if (r.message) {
|
||||
// var item_code = r.message[0].item_code;
|
||||
// var child = wn.model.add_child(me.frm.doc, this.frm.doctype + " Item",
|
||||
// this.frm.cscript.fname);
|
||||
// child.item_code = item_code;
|
||||
// me.frm.cscript.item_code(me.frm.doc, child.doctype, child.name);
|
||||
// }
|
||||
// else
|
||||
// msgprint(wn._("Invalid Serial No."));
|
||||
// me.refresh();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// },
|
||||
|
||||
row_id: function(doc, cdt, cdn) {
|
||||
var tax = wn.model.get_doc(cdt, cdn);
|
||||
try {
|
||||
@ -486,12 +468,8 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
}
|
||||
|
||||
var company_currency = this.get_company_currency();
|
||||
var valid_conversion_rate = this.frm.doc.conversion_rate ?
|
||||
((this.frm.doc.currency == company_currency && this.frm.doc.conversion_rate == 1.0) ||
|
||||
(this.frm.doc.currency != company_currency && this.frm.doc.conversion_rate != 1.0)) :
|
||||
false;
|
||||
|
||||
if(!valid_conversion_rate) {
|
||||
if(!this.frm.doc.conversion_rate) {
|
||||
wn.throw(wn._("Please enter valid") + " " + wn._(conversion_rate_label) +
|
||||
" 1 " + this.frm.doc.currency + " = [?] " + company_currency);
|
||||
}
|
||||
|
@ -121,4 +121,4 @@ def make_opportunity(source_name, target_doclist=None):
|
||||
}
|
||||
}}, target_doclist)
|
||||
|
||||
return [d if isinstance(d, dict) else d.fields for d in doclist]
|
||||
return [d if isinstance(d, dict) else d.fields for d in doclist]
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-24 19:29:08",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-10-03 16:31:55",
|
||||
"modified": "2013-10-11 13:21:07",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -258,7 +258,6 @@
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"default": "1.00",
|
||||
"description": "Rate at which customer's currency is converted to company's base currency",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "conversion_rate",
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-06-18 12:39:59",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-10-02 14:24:37",
|
||||
"modified": "2013-10-11 13:18:47",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -273,7 +273,6 @@
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"default": "1.00",
|
||||
"description": "Rate at which customer's currency is converted to company's base currency",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "conversion_rate",
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-24 19:29:09",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-08-09 14:46:32",
|
||||
"modified": "2013-10-11 13:19:40",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -230,7 +230,7 @@
|
||||
"depends_on": "eval:doc.po_no",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "po_date",
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 1,
|
||||
"label": "Customer's Purchase Order Date",
|
||||
"no_copy": 0,
|
||||
@ -263,7 +263,6 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"default": "1.00",
|
||||
"description": "Rate at which customer's currency is converted to company's base currency",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "conversion_rate",
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-21 16:16:39",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-08-09 14:47:05",
|
||||
"modified": "2013-10-11 13:20:13",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -215,7 +215,6 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"default": "1.00",
|
||||
"description": "Rate at which supplier's currency is converted to company's base currency",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "conversion_rate",
|
||||
|
@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.utils import cint, getdate, nowdate, cstr, flt, add_days
|
||||
from webnotes.utils import cint, getdate, cstr, flt, add_days
|
||||
import datetime
|
||||
from webnotes import msgprint, _, ValidationError
|
||||
|
||||
@ -36,9 +36,8 @@ class DocType(StockController):
|
||||
self.validate_amc_status()
|
||||
self.validate_warehouse()
|
||||
self.validate_item()
|
||||
|
||||
self.on_stock_ledger_entry()
|
||||
|
||||
|
||||
def validate_amc_status(self):
|
||||
"""
|
||||
validate amc status
|
||||
@ -115,7 +114,7 @@ class DocType(StockController):
|
||||
and ifnull(is_cancelled, 'No')='No' order by name asc limit 1""",
|
||||
("%%%s%%" % (self.doc.name+"\n"), "%%%s%%" % ("\n"+self.doc.name), self.doc.name,
|
||||
self.doc.item_code), as_dict=1)
|
||||
|
||||
|
||||
if purchase_sle:
|
||||
self.doc.purchase_document_type = purchase_sle[0].voucher_type
|
||||
self.doc.purchase_document_no = purchase_sle[0].voucher_no
|
||||
@ -178,7 +177,7 @@ class DocType(StockController):
|
||||
webnotes.conn.sql("""update `tab%s` set serial_no = %s
|
||||
where name=%s""" % (dt[0], '%s', '%s'),
|
||||
('\n'.join(serial_nos), item[0]))
|
||||
|
||||
|
||||
def on_stock_ledger_entry(self):
|
||||
if self.via_stock_ledger and not self.doc.fields.get("__islocal"):
|
||||
self.set_status()
|
||||
|
@ -6,7 +6,7 @@ import webnotes
|
||||
import webnotes.defaults
|
||||
|
||||
from webnotes.utils import cstr, cint, flt, comma_or, nowdate
|
||||
from webnotes.model.doc import Document, addchild
|
||||
from webnotes.model.doc import addchild
|
||||
from webnotes.model.bean import getlist
|
||||
from webnotes.model.code import get_obj
|
||||
from webnotes import msgprint, _
|
||||
@ -20,6 +20,7 @@ class NotUpdateStockError(webnotes.ValidationError): pass
|
||||
class StockOverReturnError(webnotes.ValidationError): pass
|
||||
class IncorrectValuationRateError(webnotes.ValidationError): pass
|
||||
class DuplicateEntryForProductionOrderError(webnotes.ValidationError): pass
|
||||
class StockOverProductionError(webnotes.ValidationError): pass
|
||||
|
||||
from controllers.stock_controller import StockController
|
||||
|
||||
@ -54,13 +55,12 @@ class DocType(StockController):
|
||||
|
||||
from stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
|
||||
update_serial_nos_after_submit(self, "mtn_details")
|
||||
|
||||
self.update_production_order(1)
|
||||
self.update_production_order()
|
||||
self.make_gl_entries()
|
||||
|
||||
def on_cancel(self):
|
||||
self.update_stock_ledger()
|
||||
self.update_production_order(0)
|
||||
self.update_production_order()
|
||||
self.make_cancel_gl_entries()
|
||||
|
||||
def validate_fiscal_year(self):
|
||||
@ -325,37 +325,44 @@ class DocType(StockController):
|
||||
|
||||
self.make_sl_entries(sl_entries, self.doc.amended_from and 'Yes' or 'No')
|
||||
|
||||
def update_production_order(self, is_submit):
|
||||
def update_production_order(self):
|
||||
def _validate_production_order(pro_bean):
|
||||
if flt(pro_bean.doc.docstatus) != 1:
|
||||
webnotes.throw(_("Production Order must be submitted") + ": " +
|
||||
self.doc.production_order)
|
||||
|
||||
if pro_bean.doc.status == 'Stopped':
|
||||
msgprint(_("Transaction not allowed against stopped Production Order") + ": " +
|
||||
self.doc.production_order)
|
||||
|
||||
if self.doc.production_order:
|
||||
# first perform some validations
|
||||
# (they are here coz this fn is also called during on_cancel)
|
||||
pro_obj = get_obj("Production Order", self.doc.production_order)
|
||||
if flt(pro_obj.doc.docstatus) != 1:
|
||||
msgprint("""You cannot do any transaction against
|
||||
Production Order : %s, as it's not submitted"""
|
||||
% (pro_obj.doc.name), raise_exception=1)
|
||||
|
||||
if pro_obj.doc.status == 'Stopped':
|
||||
msgprint("""You cannot do any transaction against Production Order : %s,
|
||||
as it's status is 'Stopped'"""% (pro_obj.doc.name), raise_exception=1)
|
||||
|
||||
# update bin
|
||||
if self.doc.purpose == "Manufacture/Repack":
|
||||
from stock.utils import update_bin
|
||||
pro_obj.doc.produced_qty = flt(pro_obj.doc.produced_qty) + \
|
||||
(is_submit and 1 or -1 ) * flt(self.doc.fg_completed_qty)
|
||||
args = {
|
||||
"item_code": pro_obj.doc.production_item,
|
||||
"warehouse": pro_obj.doc.fg_warehouse,
|
||||
"posting_date": self.doc.posting_date,
|
||||
"planned_qty": (is_submit and -1 or 1 ) * flt(self.doc.fg_completed_qty)
|
||||
}
|
||||
update_bin(args)
|
||||
pro_bean = webnotes.bean("Production Order", self.doc.production_order)
|
||||
_validate_production_order(pro_bean)
|
||||
self.update_produced_qty(pro_bean)
|
||||
self.update_planned_qty(pro_bean)
|
||||
|
||||
# update production order status
|
||||
pro_obj.doc.status = (flt(pro_obj.doc.qty)==flt(pro_obj.doc.produced_qty)) \
|
||||
and 'Completed' or 'In Process'
|
||||
pro_obj.doc.save()
|
||||
def update_produced_qty(self, pro_bean):
|
||||
if self.doc.purpose == "Manufacture/Repack":
|
||||
produced_qty = flt(pro_bean.doc.produced_qty) + \
|
||||
(self.doc.docstatus==1 and 1 or -1 ) * flt(self.doc.fg_completed_qty)
|
||||
|
||||
if produced_qty > flt(pro_bean.doc.qty):
|
||||
webnotes.throw(_("Production Order") + ": " + self.doc.production_order + "\n" +
|
||||
_("Total Manufactured Qty can not be greater than Planned qty to manufacture")
|
||||
+ "(%s/%s)" % (produced_qty, flt(pro_bean.doc.qty)), StockOverProductionError)
|
||||
|
||||
status = 'Completed' if flt(produced_qty) >= flt(pro_bean.doc.qty) else 'In Process'
|
||||
webnotes.conn.sql("""update `tabProduction Order` set status=%s, produced_qty=%s
|
||||
where name=%s""", (status, produced_qty, self.doc.production_order))
|
||||
|
||||
def update_planned_qty(self, pro_bean):
|
||||
from stock.utils import update_bin
|
||||
update_bin({
|
||||
"item_code": pro_bean.doc.production_item,
|
||||
"warehouse": pro_bean.doc.fg_warehouse,
|
||||
"posting_date": self.doc.posting_date,
|
||||
"planned_qty": (self.doc.docstatus==1 and -1 or 1 ) * flt(self.doc.fg_completed_qty)
|
||||
})
|
||||
|
||||
def get_item_details(self, arg):
|
||||
arg = json.loads(arg)
|
||||
@ -414,7 +421,8 @@ class DocType(StockController):
|
||||
return ret
|
||||
|
||||
def get_items(self):
|
||||
self.doclist = self.doc.clear_table(self.doclist, 'mtn_details', 1)
|
||||
self.doclist = filter(lambda d: d.parentfield!="mtn_details", self.doclist)
|
||||
# self.doclist = self.doc.clear_table(self.doclist, 'mtn_details')
|
||||
|
||||
pro_obj = None
|
||||
if self.doc.production_order:
|
||||
@ -453,7 +461,7 @@ class DocType(StockController):
|
||||
"stock_uom": pro_obj.doc.stock_uom
|
||||
}
|
||||
}, bom_no=pro_obj.doc.bom_no)
|
||||
|
||||
|
||||
elif self.doc.purpose in ["Material Receipt", "Manufacture/Repack"]:
|
||||
if self.doc.purpose=="Material Receipt":
|
||||
self.doc.from_warehouse = ""
|
||||
@ -470,6 +478,7 @@ class DocType(StockController):
|
||||
}, bom_no=self.doc.bom_no)
|
||||
|
||||
self.get_stock_and_rate()
|
||||
|
||||
|
||||
def get_bom_raw_materials(self, qty):
|
||||
from manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import _, msgprint
|
||||
from webnotes.utils import cint, flt, getdate, cstr
|
||||
from webnotes import msgprint
|
||||
from webnotes.utils import flt, getdate
|
||||
from webnotes.model.controller import DocListController
|
||||
|
||||
class DocType(DocListController):
|
||||
|
@ -5,7 +5,6 @@ from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.utils import cint, flt, validate_email_add
|
||||
from webnotes.model.code import get_obj
|
||||
from webnotes import msgprint, _
|
||||
|
||||
|
||||
@ -91,103 +90,15 @@ class DocType:
|
||||
|
||||
webnotes.conn.delete_doc("Account", old_warehouse_account)
|
||||
|
||||
from utilities.repost_stock import repost
|
||||
for item_code in items:
|
||||
self.repost(item_code[0], self.doc.merge_with)
|
||||
repost(item_code[0], self.doc.merge_with)
|
||||
|
||||
webnotes.conn.auto_commit_on_many_writes = 0
|
||||
|
||||
msgprint("Warehouse %s merged into %s. Now you can delete warehouse: %s"
|
||||
% (self.doc.name, self.doc.merge_with, self.doc.name))
|
||||
|
||||
|
||||
def repost(self, item_code, warehouse=None):
|
||||
from stock.utils import get_bin
|
||||
self.repost_actual_qty(item_code, warehouse)
|
||||
|
||||
bin = get_bin(item_code, warehouse)
|
||||
self.repost_reserved_qty(bin)
|
||||
self.repost_indented_qty(bin)
|
||||
self.repost_ordered_qty(bin)
|
||||
self.repost_planned_qty(bin)
|
||||
bin.doc.projected_qty = flt(bin.doc.actual_qty) + flt(bin.doc.planned_qty) \
|
||||
+ flt(bin.doc.indented_qty) + flt(bin.doc.ordered_qty) - flt(bin.doc.reserved_qty)
|
||||
bin.doc.save()
|
||||
|
||||
|
||||
def repost_actual_qty(self, item_code, warehouse=None):
|
||||
from stock.stock_ledger import update_entries_after
|
||||
if not warehouse:
|
||||
warehouse = self.doc.name
|
||||
|
||||
update_entries_after({ "item_code": item_code, "warehouse": warehouse })
|
||||
|
||||
def repost_reserved_qty(self, bin):
|
||||
reserved_qty = webnotes.conn.sql("""
|
||||
select
|
||||
sum((dnpi_qty / so_item_qty) * (so_item_qty - so_item_delivered_qty))
|
||||
from
|
||||
(
|
||||
select
|
||||
qty as dnpi_qty,
|
||||
(
|
||||
select qty from `tabSales Order Item`
|
||||
where name = dnpi.parent_detail_docname
|
||||
) as so_item_qty,
|
||||
(
|
||||
select ifnull(delivered_qty, 0) from `tabSales Order Item`
|
||||
where name = dnpi.parent_detail_docname
|
||||
) as so_item_delivered_qty
|
||||
from
|
||||
(
|
||||
select qty, parent_detail_docname
|
||||
from `tabDelivery Note Packing Item` dnpi_in
|
||||
where item_code = %s and warehouse = %s
|
||||
and parenttype="Sales Order"
|
||||
and exists (select * from `tabSales Order` so
|
||||
where name = dnpi_in.parent and docstatus = 1 and status != 'Stopped')
|
||||
) dnpi
|
||||
) tab
|
||||
where
|
||||
so_item_qty >= so_item_delivered_qty
|
||||
""", (bin.doc.item_code, bin.doc.warehouse))
|
||||
|
||||
if flt(bin.doc.reserved_qty) != flt(reserved_qty[0][0]):
|
||||
webnotes.conn.set_value("Bin", bin.doc.name, "reserved_qty", flt(reserved_qty[0][0]))
|
||||
|
||||
|
||||
def repost_indented_qty(self, bin):
|
||||
indented_qty = webnotes.conn.sql("""select sum(pr_item.qty - pr_item.ordered_qty)
|
||||
from `tabMaterial Request Item` pr_item, `tabMaterial Request` pr
|
||||
where pr_item.item_code=%s and pr_item.warehouse=%s
|
||||
and pr_item.qty > pr_item.ordered_qty and pr_item.parent=pr.name
|
||||
and pr.status!='Stopped' and pr.docstatus=1"""
|
||||
, (bin.doc.item_code, bin.doc.warehouse))
|
||||
|
||||
if flt(bin.doc.indented_qty) != flt(indented_qty[0][0]):
|
||||
webnotes.conn.set_value("Bin", bin.doc.name, "indented_qty", flt(indented_qty[0][0]))
|
||||
|
||||
|
||||
def repost_ordered_qty(self, bin):
|
||||
ordered_qty = webnotes.conn.sql("""
|
||||
select sum((po_item.qty - po_item.received_qty)*po_item.conversion_factor)
|
||||
from `tabPurchase Order Item` po_item, `tabPurchase Order` po
|
||||
where po_item.item_code=%s and po_item.warehouse=%s
|
||||
and po_item.qty > po_item.received_qty and po_item.parent=po.name
|
||||
and po.status!='Stopped' and po.docstatus=1"""
|
||||
, (bin.doc.item_code, bin.doc.warehouse))
|
||||
|
||||
if flt(bin.doc.ordered_qty) != flt(ordered_qty[0][0]):
|
||||
webnotes.conn.set_value("Bin", bin.doc.name, "ordered_qty", flt(ordered_qty[0][0]))
|
||||
|
||||
def repost_planned_qty(self, bin):
|
||||
planned_qty = webnotes.conn.sql("""
|
||||
select sum(qty - produced_qty) from `tabProduction Order`
|
||||
where production_item = %s and fg_warehouse = %s and status != "Stopped"
|
||||
and docstatus=1""", (bin.doc.item_code, bin.doc.warehouse))
|
||||
|
||||
if flt(bin.doc.planned_qty) != flt(planned_qty[0][0]):
|
||||
webnotes.conn.set_value("Bin", bin.doc.name, "planned_qty", flt(planned_qty[0][0]))
|
||||
|
||||
def on_trash(self):
|
||||
# delete bin
|
||||
bins = webnotes.conn.sql("select * from `tabBin` where warehouse = %s", self.doc.name, as_dict=1)
|
||||
@ -209,4 +120,4 @@ class DocType:
|
||||
msgprint("""Warehosue can not be deleted as stock ledger entry
|
||||
exists for this warehouse.""", raise_exception=1)
|
||||
else:
|
||||
webnotes.conn.sql("delete from `tabStock Ledger Entry` where warehouse = %s", self.doc.name)
|
||||
webnotes.conn.sql("delete from `tabStock Ledger Entry` where warehouse = %s", self.doc.name)
|
||||
|
@ -209,7 +209,7 @@ def get_warehouse_list(doctype, txt, searchfield, start, page_len, filters):
|
||||
return wlist
|
||||
|
||||
def validate_warehouse_user(warehouse):
|
||||
if webnotes.session.user=="Administrator":
|
||||
if webnotes.session.user=="Administrator" or not warehouse:
|
||||
return
|
||||
warehouse_users = [p[0] for p in webnotes.conn.sql("""select user from `tabWarehouse User`
|
||||
where parent=%s""", warehouse)]
|
||||
@ -394,12 +394,3 @@ def notify_errors(exceptions_list):
|
||||
|
||||
from webnotes.profile import get_system_managers
|
||||
sendmail(get_system_managers(), subject=subject, msg=msg)
|
||||
|
||||
|
||||
def repost():
|
||||
"""
|
||||
Repost everything!
|
||||
"""
|
||||
from webnotes.model.code import get_obj
|
||||
for wh in webnotes.conn.sql("select name from tabWarehouse"):
|
||||
get_obj('Warehouse', wh[0]).repost_stock()
|
||||
|
119
utilities/repost_stock.py
Normal file
119
utilities/repost_stock.py
Normal file
@ -0,0 +1,119 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.utils import flt
|
||||
|
||||
|
||||
def repost():
|
||||
"""
|
||||
Repost everything!
|
||||
"""
|
||||
webnotes.conn.auto_commit_on_many_writes = 1
|
||||
|
||||
for d in webnotes.conn.sql("select item_code, warehouse from tabBin"):
|
||||
repost_stock(d[0], d[1])
|
||||
|
||||
webnotes.conn.auto_commit_on_many_writes = 0
|
||||
|
||||
def repost_stock(item_code, warehouse):
|
||||
repost_actual_qty(item_code, warehouse)
|
||||
|
||||
if item_code and warehouse:
|
||||
update_bin(item_code, warehouse, {
|
||||
"reserved_qty": get_reserved_qty(item_code, warehouse),
|
||||
"indented_qty": get_indented_qty(item_code, warehouse),
|
||||
"ordered_qty": get_ordered_qty(item_code, warehouse),
|
||||
"planned_qty": get_planned_qty(item_code, warehouse)
|
||||
})
|
||||
|
||||
def repost_actual_qty(item_code, warehouse):
|
||||
from stock.stock_ledger import update_entries_after
|
||||
update_entries_after({ "item_code": item_code, "warehouse": warehouse })
|
||||
|
||||
def get_reserved_qty(item_code, warehouse):
|
||||
reserved_qty = webnotes.conn.sql("""
|
||||
select
|
||||
sum((dnpi_qty / so_item_qty) * (so_item_qty - so_item_delivered_qty))
|
||||
from
|
||||
(
|
||||
(select
|
||||
qty as dnpi_qty,
|
||||
(
|
||||
select qty from `tabSales Order Item`
|
||||
where name = dnpi.parent_detail_docname
|
||||
) as so_item_qty,
|
||||
(
|
||||
select ifnull(delivered_qty, 0) from `tabSales Order Item`
|
||||
where name = dnpi.parent_detail_docname
|
||||
) as so_item_delivered_qty,
|
||||
parent, name
|
||||
from
|
||||
(
|
||||
select qty, parent_detail_docname, parent, name
|
||||
from `tabDelivery Note Packing Item` dnpi_in
|
||||
where item_code = %s and warehouse = %s
|
||||
and parenttype="Sales Order"
|
||||
and item_code != parent_item
|
||||
and exists (select * from `tabSales Order` so
|
||||
where name = dnpi_in.parent and docstatus = 1 and status != 'Stopped')
|
||||
) dnpi)
|
||||
union
|
||||
(select qty as dnpi_qty, qty as so_item_qty,
|
||||
ifnull(delivered_qty, 0) as so_item_delivered_qty, parent, name
|
||||
from `tabSales Order Item` so_item
|
||||
where item_code = %s and reserved_warehouse = %s
|
||||
and exists(select * from `tabSales Order` so
|
||||
where so.name = so_item.parent and so.docstatus = 1
|
||||
and so.status != 'Stopped'))
|
||||
) tab
|
||||
where
|
||||
so_item_qty >= so_item_delivered_qty
|
||||
""", (item_code, warehouse, item_code, warehouse))
|
||||
|
||||
return flt(reserved_qty[0][0]) if reserved_qty else 0
|
||||
|
||||
def get_indented_qty(item_code, warehouse):
|
||||
indented_qty = webnotes.conn.sql("""select sum(pr_item.qty - ifnull(pr_item.ordered_qty, 0))
|
||||
from `tabMaterial Request Item` pr_item, `tabMaterial Request` pr
|
||||
where pr_item.item_code=%s and pr_item.warehouse=%s
|
||||
and pr_item.qty > ifnull(pr_item.ordered_qty, 0) and pr_item.parent=pr.name
|
||||
and pr.status!='Stopped' and pr.docstatus=1""", (item_code, warehouse))
|
||||
|
||||
return flt(indented_qty[0][0]) if indented_qty else 0
|
||||
|
||||
def get_ordered_qty(item_code, warehouse):
|
||||
ordered_qty = webnotes.conn.sql("""
|
||||
select sum((po_item.qty - ifnull(po_item.received_qty, 0))*po_item.conversion_factor)
|
||||
from `tabPurchase Order Item` po_item, `tabPurchase Order` po
|
||||
where po_item.item_code=%s and po_item.warehouse=%s
|
||||
and po_item.qty > ifnull(po_item.received_qty, 0) and po_item.parent=po.name
|
||||
and po.status!='Stopped' and po.docstatus=1""", (item_code, warehouse))
|
||||
|
||||
return flt(ordered_qty[0][0]) if ordered_qty else 0
|
||||
|
||||
def get_planned_qty(item_code, warehouse):
|
||||
planned_qty = webnotes.conn.sql("""
|
||||
select sum(ifnull(qty, 0) - ifnull(produced_qty, 0)) from `tabProduction Order`
|
||||
where production_item = %s and fg_warehouse = %s and status != "Stopped"
|
||||
and docstatus=1 and ifnull(qty, 0) > ifnull(produced_qty, 0)""", (item_code, warehouse))
|
||||
|
||||
return flt(planned_qty[0][0]) if planned_qty else 0
|
||||
|
||||
|
||||
def update_bin(item_code, warehouse, qty_dict=None):
|
||||
from stock.utils import get_bin
|
||||
bin = get_bin(item_code, warehouse)
|
||||
mismatch = False
|
||||
for fld, val in qty_dict.items():
|
||||
if flt(bin.doc.fields.get(fld)) != flt(val):
|
||||
bin.doc.fields[fld] = flt(val)
|
||||
mismatch = True
|
||||
|
||||
if mismatch:
|
||||
bin.doc.projected_qty = flt(bin.doc.actual_qty) + flt(bin.doc.ordered_qty) + \
|
||||
flt(bin.doc.indented_qty) + flt(bin.doc.planned_qty) - flt(bin.doc.reserved_qty)
|
||||
|
||||
bin.doc.save()
|
@ -144,7 +144,6 @@ class TransactionBase(StatusUpdater):
|
||||
|
||||
def get_customer_address(self, args):
|
||||
args = load_json(args)
|
||||
webnotes.errprint(args)
|
||||
ret = {
|
||||
'customer_address' : args["address"],
|
||||
'address_display' : get_address_display(args["address"]),
|
||||
@ -432,14 +431,7 @@ def validate_conversion_rate(currency, conversion_rate, conversion_rate_label, c
|
||||
|
||||
company_currency = webnotes.conn.get_value("Company", company, "default_currency")
|
||||
|
||||
# parenthesis for 'OR' are necessary as we want it to evaluate as
|
||||
# mandatory valid condition and (1st optional valid condition
|
||||
# or 2nd optional valid condition)
|
||||
valid_conversion_rate = (conversion_rate and
|
||||
((currency == company_currency and conversion_rate == 1.00)
|
||||
or (currency != company_currency and conversion_rate != 1.00)))
|
||||
|
||||
if not valid_conversion_rate:
|
||||
if not conversion_rate:
|
||||
msgprint(_('Please enter valid ') + conversion_rate_label + (': ')
|
||||
+ ("1 %s = [?] %s" % (currency, company_currency)),
|
||||
raise_exception=True)
|
||||
|
Loading…
x
Reference in New Issue
Block a user