def test_subscription_cancellation_invoices_with_prorata_true(self): settings = frappe.get_single('Subscription Settings') to_prorate = settings.prorate settings.prorate = 1 settings.save() subscription = frappe.new_doc('Subscription') subscription.subscriber = '_Test Customer' subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1}) subscription.save() subscription.cancel_subscription() invoice = subscription.get_current_invoice() diff = flt( date_diff(nowdate(), subscription.current_invoice_start) + 1) plan_days = flt( date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1) prorate_factor = flt(diff / plan_days) self.assertEqual(flt(invoice.grand_total, 2), flt(prorate_factor * 900, 2)) settings.prorate = to_prorate settings.save() subscription.delete()
def harvest(self, flower, other_material=None, waste=None, additional_collection=None): if self.disabled: frappe.throw("Plant <strong>{}</strong> is not available for harvesting.") if self.destroy_scheduled: frappe.throw("Plant <strong>{}</strong> is currently scheduled for destruction and cannot be harvested.") items = [] frappe.flags.ignore_external_sync = True if other_material: item_group = frappe.get_doc("Item Group", {"external_id": 9}) items.append(self.collect_item(item_group, other_material)) if waste: item_group = frappe.get_doc("Item Group", {"external_id": 27}) items.append(self.collect_item(item_group, waste)) self.wet_weight = flt(self.wet_weight) + flt(flower) if not additional_collection: self.state = "Drying" # Reset harvest_scheduled status self.harvest_scheduled = 0 self.harvest_schedule_time = None self.harvest_collect = self.harvest_collect + 1 self.flags.ignore_validate_update_after_submit = True self.save() self.run_method("after_harvest", items=items, flower=flower, other_material=other_material, waste=waste, additional_collection=additional_collection) return {"items": items}
def test_subscription_cancellation_invoices_with_prorata_true(self): settings = frappe.get_single("Subscription Settings") to_prorate = settings.prorate settings.prorate = 1 settings.save() subscription = frappe.new_doc("Subscription") subscription.party_type = "Customer" subscription.party = "_Test Customer" subscription.append("plans", {"plan": "_Test Plan Name", "qty": 1}) subscription.save() subscription.cancel_subscription() invoice = subscription.get_current_invoice() diff = flt(date_diff(nowdate(), subscription.current_invoice_start) + 1) plan_days = flt( date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1 ) prorate_factor = flt(diff / plan_days) self.assertEqual(flt(invoice.grand_total, 2), flt(prorate_factor * 900, 2)) settings.prorate = to_prorate settings.save() subscription.delete()
def test_prepaid_subscriptions_with_prorate_true(self): settings = frappe.get_single('Subscription Settings') to_prorate = settings.prorate settings.prorate = 1 settings.save() subscription = frappe.new_doc('Subscription') subscription.party_type = 'Customer' subscription.party = '_Test Customer' subscription.generate_invoice_at_period_start = True subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1}) subscription.save() subscription.process() subscription.cancel_subscription() self.assertEqual(len(subscription.invoices), 1) current_inv = subscription.get_current_invoice() self.assertEqual(current_inv.status, "Unpaid") diff = flt(date_diff(nowdate(), subscription.current_invoice_start) + 1) plan_days = flt(date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1) prorate_factor = flt(diff / plan_days) self.assertEqual(flt(current_inv.grand_total, 2), flt(prorate_factor * 900, 2)) settings.prorate = to_prorate settings.save() subscription.delete()
def test_prepaid_subscriptions_with_prorate_true(self): settings = frappe.get_single("Subscription Settings") to_prorate = settings.prorate settings.prorate = 1 settings.save() subscription = frappe.new_doc("Subscription") subscription.party_type = "Customer" subscription.party = "_Test Customer" subscription.generate_invoice_at_period_start = True subscription.append("plans", {"plan": "_Test Plan Name", "qty": 1}) subscription.save() subscription.process() subscription.cancel_subscription() self.assertEqual(len(subscription.invoices), 1) current_inv = subscription.get_current_invoice() self.assertEqual(current_inv.status, "Unpaid") prorate_factor = 1 self.assertEqual(flt(current_inv.grand_total, 2), flt(prorate_factor * 900, 2)) settings.prorate = to_prorate settings.save() subscription.delete()
def make_weights_data(flower, other_material=None, waste=None): amount_map = { 6: flt(flower), 9: flt(other_material), 27: flt(waste), } weights = [ { "amount": amount_map[6], "invtype": 6, "uom": "g" } ] if other_material: weights.append({ "amount": amount_map[9], "invtype": 9, "uom": "g" }) if waste: weights.append({ "amount": amount_map[27], "invtype": 27, "uom": "g" }) return weights
def test_prepaid_subscriptions_with_prorate_true(self): settings = frappe.get_single('Subscription Settings') to_prorate = settings.prorate settings.prorate = 1 settings.save() subscription = frappe.new_doc('Subscription') subscription.customer = '_Test Customer' subscription.generate_invoice_at_period_start = True subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1}) subscription.save() subscription.cancel_subscription() self.assertEqual(len(subscription.invoices), 1) current_inv = subscription.get_current_invoice() self.assertEqual(current_inv.status, "Unpaid") diff = flt(date_diff(nowdate(), subscription.current_invoice_start) + 1) plan_days = flt(date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1) prorate_factor = flt(diff / plan_days) self.assertEqual(flt(current_inv.grand_total, 2), flt(prorate_factor * 900, 2)) settings.prorate = to_prorate settings.save() subscription.delete()
def get_prorata_factor(period_end, period_start, is_prepaid): if is_prepaid: prorate_factor = 1 else: diff = flt(date_diff(nowdate(), period_start) + 1) plan_days = flt(date_diff(period_end, period_start) + 1) prorate_factor = diff / plan_days return prorate_factor
def get_subscription_rates(self): total = 0 for plan in self.plans: if plan.status == "Active": plan.rate = self.get_plan_rate(plan, plan.qty) total += (flt(plan.qty) * flt(plan.rate)) if total != self.total: self.total = total
def get_prorata_factor(self): consumed = flt( date_diff(self.cancellation_date, self.current_invoice_start) + 1) plan_days = flt( date_diff(self.current_invoice_end, self.current_invoice_start) + 1) prorata_factor = consumed / plan_days return prorata_factor
def validate_einvoice(validations, einvoice, errors=[]): for fieldname, field_validation in validations.items(): value = einvoice.get(fieldname, None) if not value or value == "None": # remove keys with empty values einvoice.pop(fieldname, None) continue value_type = field_validation.get("type").lower() if value_type in ['object', 'array']: child_validations = field_validation.get('properties') if isinstance(value, list): for d in value: validate_einvoice(child_validations, d, errors) if not d: # remove empty dicts einvoice.pop(fieldname, None) else: validate_einvoice(child_validations, value, errors) if not value: # remove empty dicts einvoice.pop(fieldname, None) continue # convert to int or str if value_type == 'string': einvoice[fieldname] = str(value) elif value_type == 'number': is_integer = '.' not in str(field_validation.get('maximum')) precision = 3 if '.999' in str( field_validation.get('maximum')) else 2 einvoice[fieldname] = flt( value, precision) if not is_integer else cint(value) value = einvoice[fieldname] max_length = field_validation.get('maxLength') minimum = flt(field_validation.get('minimum')) maximum = flt(field_validation.get('maximum')) pattern_str = field_validation.get('pattern') pattern = re.compile(pattern_str or '') label = field_validation.get('description') or fieldname if value_type == 'string' and len(value) > max_length: errors.append( _('{} should not exceed {} characters').format( label, max_length)) if value_type == 'number' and (value > maximum or value < minimum): errors.append( _('{} {} should be between {} and {}').format( label, value, minimum, maximum)) if pattern_str and not pattern.match(value): errors.append(field_validation.get('validationMsg')) return errors
def add_primacasa_items(): from frappe.utils.csvutils import read_csv_content from frappe.core.doctype.data_import.importer import upload with open( "/home/frappe/frappe-bench/apps/erpnext/erpnext/primacasa_items.csv", "r") as infile: rows = read_csv_content(infile.read()) i = 0 for index, row in enumerate(rows): if index: print(index) item = frappe.new_doc('Item') item.company = 'Primacasa' item.item_name = row[1] item.description = row[2] item.item_group = row[3] item.sub_item_group = row[4] item.item_company = row[5] item.standard_rate = row[6] item.valuation_rate = row[6] item.stock_uom = row[7] item.is_stock_item = 1 item.item_code = row[11] if flt(row[8]) > 0 and flt(row[6]) > 0: item.opening_stock = row[8] if cint(row[12]) == 1: item.append('taxes', { 'tax_type': 'VAT 5% - P', 'tax_rate': 5 }) if row[10]: item.append( 'item_defaults', { 'company': 'Primacasa', 'default_warehouse': 'Stores - P', 'default_price_list': 'Standard Selling', 'default_supplier': row[10] }) item.append('supplier_items', { 'supplier': row[10], 'supplier_part_no': str(row[10][0:5]) }) item.save() i += 1 print('*************') print(i) print('*************')
def commit_single_currency_exchange_rate(cls, tcmb_data: dict): data_dict = dict(tcmb_data.get("items")[0]) exchange_rate_date = datetime.datetime.strptime( data_dict.pop(cls.tcmb_date_key), cls.tcmb_date_format).date() data_dict.pop(cls.tcmb_strip_key) for key in data_dict.keys(): for_selling = 0 for_buying = 0 key_list = str(key).split(cls.response_separator) from_currency = key_list[2] if key_list[3] == cls.selling_code: for_selling = 1 elif key_list[3] == cls.buying_code: for_buying = 1 # check if record exists by filters if frappe.db.exists({ "doctype": cls.doctype, "date": exchange_rate_date, "from_currency": from_currency, "to_currency": cls.to_currency, "for_buying": for_buying, "for_selling": for_selling }): frdoc_list = frappe.db.get_list(doctype=cls.doctype, filters={ "date": exchange_rate_date, "from_currency": from_currency, "to_currency": cls.to_currency, "for_buying": for_buying, "for_selling": for_selling }) frdoc = frappe.get_doc(cls.doctype, frdoc_list[0].get("name")) if frdoc.exchange_rate != flt(data_dict.get(key)): frdoc.exchange_rate = flt(data_dict.get(key)) return frappe.enqueue(frdoc.save, queue="short", timeout=None, event=None, is_async=False, job_name=None) else: newdoc = frappe.new_doc(cls.doctype) newdoc.date = exchange_rate_date newdoc.from_currency = from_currency newdoc.to_currency = cls.to_currency newdoc.for_buying = for_buying newdoc.for_selling = for_selling newdoc.exchange_rate = flt(data_dict.get(key)) return frappe.enqueue(newdoc.insert, queue="short", timeout=None, event=None, is_async=False, job_name=None)
def has_item_modified(self, item): qty = get_stock_balance(item.item_code, self.target_warehouse) if item.item_group == "Flower": origin_qty = self.flower elif item.item_group == "Other Plant Material": origin_qty = self.other_material else: origin_qty = self.waste return flt(origin_qty) != flt(qty)
def budget_check(from_cc=None, from_acc=None, amount=None, fiscal_year=None): #Get cost center & target details budget = get_cc_acc_budget(from_cc, from_acc, fiscal_year) if budget: for a in budget: if flt(amount) <= flt(a.budget_amount): return True else: return False else: frappe.throw("No budget booked under " + str(from_acc) + " at " + str(from_cc))
def create_reddem_points_entry(rule_details, sales_invoice_details, debit_to, credit_to, journal_voucher): debit_to, credit_to = credit_to, debit_to for entry in journal_voucher.entries: if entry.mode == "Redeem": conversion_factor = frappe.db.get_value('LPE Configuration', None, 'conversion_factor') create_point_transaction( 'Customer', sales_invoice_details.customer, entry.against_invoice, 'Redeem', cint(flt(entry.credit) / flt(conversion_factor))) create_jv(sales_invoice_details, sales_invoice_details.redeem_points, debit_to, credit_to)
def _create_product(stock_entry, data): derivative_type = frappe.get_value("Item Group", stock_entry.product_group, "external_id") request_data = {} if not derivative_type: frappe.throw("Invalid Inventory type on '{0}'".format( stock_entry.product_group)) request_data["data"] = data request_data["derivative_type"] = cint(derivative_type) request_data["derivative_quantity"] = flt(stock_entry.product_qty) request_data["derivative_quantity_uom"] = "g" request_data["waste"] = flt(stock_entry.product_waste) request_data["waste_uom"] = "g" product_usable = flt(stock_entry.product_usable) if product_usable: request_data["derivative_usable"] = product_usable if stock_entry.product_name: request_data["derivative_product"] = stock_entry.product_name response = {} try: response = call("inventory_convert", request_data) except BioTrackClientError as ex: frappe.throw(cstr(ex.message), title="BioTrack sync-up failed") derivatives = response.get("derivatives", []) for derivative in derivatives: item_type = derivative.get("barcode_type") barcode = derivative.get("barcode_id") if item_type == 27 and stock_entry.waste_item: frappe.db.set_value("Item", stock_entry.waste_item, { "bio_barcode": barcode, "disabled": 0 }, update_modified=False) elif item_type == derivative_type and stock_entry.product_item: frappe.db.set_value("Item", stock_entry.product_item, { "bio_barcode": barcode, "disabled": 0 }, update_modified=False)
def clone_item(item_code, qty, rate, default_warehouse): # todo data = biotrackthc_call( "inventory_split", data={"data": [{ "barcodeid": item_code, "remove_quantity": qty }]}) parent = frappe.get_doc("Item", item_code) barcode = data['barcode_id'][0] item = frappe.get_doc({ "doctype": "Item", "item_name": barcode, "item_code": barcode, "barcode": barcode, "parent_item": parent.name, "item_group": parent.item_group, "default_warehouse": default_warehouse, "strain": parent.strain, "stock_uom": parent.stock_uom, "is_stock_item": 1, "actual_qty": qty, }) item.insert() make_stock_entry(item_code=barcode, target=default_warehouse, qty=qty) # parent.append("sub_items", { # "item_code": item.item_code, # "qty": qty # }) remaining_qty = flt(parent.actual_qty) - flt(qty) stock_reco = frappe.new_doc("Stock Reconciliation") stock_reco.posting_date = frappe.flags.current_date stock_reco.append( "items", { "item_code": parent.item_code, "warehouse": default_warehouse, "qty": remaining_qty, "valuation_rate": rate or 1, }) stock_reco.submit() parent.actual_qty = remaining_qty parent.save() return item.as_dict()
def get_item_list(invoice): item_list = [] for d in invoice.items: einvoice_item_schema = read_json('einv_item_template') item = frappe._dict({}) item.update(d.as_dict()) item.sr_no = d.idx item.description = sanitize_for_json(d.item_name) item.qty = abs(item.qty) if flt(item.qty) != 0.0: item.unit_rate = abs(item.taxable_value / item.qty) else: item.unit_rate = abs(item.taxable_value) item.gross_amount = abs(item.taxable_value) item.taxable_value = abs(item.taxable_value) item.discount_amount = 0 item.batch_expiry_date = frappe.db.get_value('Batch', d.batch_no, 'expiry_date') if d.batch_no else None item.batch_expiry_date = format_date(item.batch_expiry_date, 'dd/mm/yyyy') if item.batch_expiry_date else None item.is_service_item = 'Y' if item.gst_hsn_code and item.gst_hsn_code[:2] == "99" else 'N' item.serial_no = "" item = update_item_taxes(invoice, item) item.total_value = abs( item.taxable_value + item.igst_amount + item.sgst_amount + item.cgst_amount + item.cess_amount + item.cess_nadv_amount + item.other_charges ) einv_item = einvoice_item_schema.format(item=item) item_list.append(einv_item) return ', '.join(item_list)
def get_leaves_without_pay(from_date, to_date, employee): total_lwp_days = 0.0 total_lwp_days = frappe.db.sql(""" select sum(total_leave_days) total_lwp_days from( select leave_type ,from_date,to_date, case when from_date BETWEEN %s and %s and to_date BETWEEN %s and %s then total_leave_days when from_date < %s and to_date > %s then DATEDIFF(to_date,%s)+1 when from_date > %s and to_date > %s then DATEDIFF(%s ,from_date) else total_leave_days end total_leave_days from `tabLeave Application` L where employee=%s and (select is_lwp from `tabLeave Type` where `name` = L.leave_type ) = 1 and ( from_date BETWEEN %s and %s or to_date BETWEEN %s and %s ) )T """, (from_date, to_date, from_date, to_date, from_date, from_date, from_date, from_date, to_date, to_date, employee, from_date, to_date, from_date, to_date), as_dict=1, debug=False) if total_lwp_days: total_lwp_days = flt(total_lwp_days[0]["total_lwp_days"]) return total_lwp_days
def santize_einvoice_fields(einvoice): int_fields = ["Pin","Distance","CrDay"] float_fields = ["Qty","FreeQty","UnitPrice","TotAmt","Discount","PreTaxVal","AssAmt","GstRt","IgstAmt","CgstAmt","SgstAmt","CesRt","CesAmt","CesNonAdvlAmt","StateCesRt","StateCesAmt","StateCesNonAdvlAmt","OthChrg","TotItemVal","AssVal","CgstVal","SgstVal","IgstVal","CesVal","StCesVal","Discount","OthChrg","RndOffAmt","TotInvVal","TotInvValFc","PaidAmt","PaymtDue","ExpDuty",] copy = einvoice.copy() for key, value in copy.items(): if isinstance(value, list): for idx, d in enumerate(value): santized_dict = santize_einvoice_fields(d) if santized_dict: einvoice[key][idx] = santized_dict else: einvoice[key].pop(idx) if not einvoice[key]: einvoice.pop(key, None) elif isinstance(value, dict): santized_dict = santize_einvoice_fields(value) if santized_dict: einvoice[key] = santized_dict else: einvoice.pop(key, None) elif not value or value == "None": einvoice.pop(key, None) elif key in float_fields: einvoice[key] = flt(value, 2) elif key in int_fields: einvoice[key] = cint(value) return einvoice
def make_weights_data(flower, other_material=None, waste=None): amount_map = { 6: flt(flower), 9: flt(other_material), 27: flt(waste), } weights = [{"amount": amount_map[6], "invtype": 6, "uom": "g"}] if other_material: weights.append({"amount": amount_map[9], "invtype": 9, "uom": "g"}) if waste: weights.append({"amount": amount_map[27], "invtype": 27, "uom": "g"}) return weights
def send_to_company(name): doc = frappe.get_doc("Delivery Note", name) if not doc.po_no: frappe.throw("Delivery Note must be dropship type") from_so = next(d.against_sales_order for d in doc.items if d.against_sales_order) if not from_so: frappe.throw("No linked Sales Order found") so = frappe.get_doc("Sales Order", from_so) # if not so.dropship_order or not so.po_no: # frappe.throw("Linked Sales Order {0} must be dropship type to use this feature".format(so.name)) po = frappe.get_doc("Purchase Order", doc.po_no) if po.per_received == so.per_delivered: frappe.throw( "Purchase Order {0} was already set to latest status".format( po.name)) # update % Received po.per_received = so.per_delivered if flt(so.per_delivered, 2) > 99.99: po.update_status("Delivered") po.update_delivered_qty_in_sales_order() po.flags.ignore_validate_update_after_submit = True po.save() frappe.db.commit() return po
def round_to_nearest_half(num): syllable = flt("0." + str(num).split('.')[1]) if syllable > 0.5: syllable = syllable - 0.5 num = num - syllable return num
def validate(self): if not self.card_number: self.create_card_number() if flt(self.amount) <= 0: frappe.throw("Amount Should be Positive number") if not self.balance: self.balance = self.amount self.is_expired_on_validate()
def test_subscription_cancellation_invoices(self): settings = frappe.get_single('Subscription Settings') to_prorate = settings.prorate settings.prorate = 1 settings.save() subscription = frappe.new_doc('Subscription') subscription.customer = '_Test Customer' subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1}) subscription.save() self.assertEqual(subscription.status, 'Active') subscription.cancel_subscription() # Invoice must have been generated self.assertEqual(len(subscription.invoices), 1) invoice = subscription.get_current_invoice() diff = flt(date_diff(nowdate(), subscription.current_invoice_start) + 1) plan_days = flt(date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1) prorate_factor = flt(diff/plan_days) self.assertEqual( flt( get_prorata_factor(subscription.current_invoice_end, subscription.current_invoice_start), 2), flt(prorate_factor, 2) ) self.assertEqual(flt(invoice.grand_total, 2), flt(prorate_factor * 900, 2)) self.assertEqual(subscription.status, 'Cancelled') subscription.delete() settings.prorate = to_prorate settings.save()
def test_subscription_cancellation_invoices(self): settings = frappe.get_single('Subscription Settings') to_prorate = settings.prorate settings.prorate = 1 settings.save() subscription = frappe.new_doc('Subscription') subscription.party_type = 'Customer' subscription.party = '_Test Customer' subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1}) subscription.save() self.assertEqual(subscription.status, 'Active') subscription.cancel_subscription() # Invoice must have been generated self.assertEqual(len(subscription.invoices), 1) invoice = subscription.get_current_invoice() diff = flt(date_diff(nowdate(), subscription.current_invoice_start) + 1) plan_days = flt(date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1) prorate_factor = flt(diff/plan_days) self.assertEqual( flt( get_prorata_factor(subscription.current_invoice_end, subscription.current_invoice_start), 2), flt(prorate_factor, 2) ) self.assertEqual(flt(invoice.grand_total, 2), flt(prorate_factor * 900, 2)) self.assertEqual(subscription.status, 'Cancelled') subscription.delete() settings.prorate = to_prorate settings.save()
def create_earned_points_entry(points_earned, rule_details, sales_invoice_details, debit_to, credit_to): create_point_transaction('Customer', sales_invoice_details.customer, sales_invoice_details.name, 'Earned', points_earned, rule_details) conversion_factor = frappe.db.get_value('LPE Configuration', None, 'conversion_factor') create_jv(sales_invoice_details, points_earned * flt(conversion_factor), debit_to, credit_to)
def tst_edit_allo(): from frappe.utils.csvutils import read_csv_content from frappe.core.doctype.data_import.importer import upload with open('/home/frappe/frappe-bench/apps/client/client/Book1.csv', "r") as infile: rows = read_csv_content(infile.read()) for index, row in enumerate(rows): emp = frappe.db.sql( "select work_days from `tabEmployee` where name='EMP00{0}'". format(row[0])) allocation = frappe.db.sql( "select name from `tabLeave Allocation` where employee='EMP00{0}' order by creation desc limit 1" .format(row[0])) doc = frappe.get_doc('Leave Allocation', allocation[0][0]) doc.new_leaves_allocated = flt( row[3]) - (doc.total_leaves_allocated - flt(emp[0][0])) doc.flags.ignore_validate = True doc.save(ignore_permissions=True) print 'Done'
def get_transferred_qty(production_order_id, item_list): """get the minumum qty that can be manufactured with the transferred item_list""" exploded_items = get_exploded_items_from_production_order( production_order_id) exploded_items_dict = { i['item_code']: i['stock_qty'] for i in exploded_items } item_list = json.loads(item_list) qty = [] for item in item_list: item_qty = (flt(item['qty'])) / flt( exploded_items_dict[item['item_code']]) if not item_qty.is_integer(): frappe.throw( _("item {0} has not valid qty, qty should be divisible by {1} " ).format(item.item_code, exploded_items_dict[item.item_code])) qty.append(item_qty) return min(qty)
def cure(self, flower, other_material=None, waste=None, additional_collection=None): if self.disabled: frappe.throw("Plant <strong>{}</strong> is not available for harvesting.") if self.destroy_scheduled: frappe.throw("Plant <strong>{}</strong> is currently scheduled for destruction and cannot be harvested.") self.dry_weight = flt(self.dry_weight) + flt(flower) if self.wet_weight and self.dry_weight > self.wet_weight: frappe.throw( "The provided dry weight <strong>{0}</strong> exceeds the previous wet weight <strong>{1}</strong>.". format(self.dry_weight, self.wet_weight), title="Error") items = [] frappe.flags.ignore_external_sync = True # collect Flower item_group = frappe.get_doc("Item Group", {"external_id": 6}) items.append(self.collect_item(item_group, flower)) if other_material: item_group = frappe.get_doc("Item Group", {"external_id": 9}) items.append(self.collect_item(item_group, other_material)) if waste: item_group = frappe.get_doc("Item Group", {"external_id": 27}) items.append(self.collect_item(item_group, waste)) # Remove from Cultivation if not additional_collection or self.dry_weight == self.wet_weight: self.disabled = 1 self.cure_collect = self.cure_collect + 1 self.flags.ignore_validate_update_after_submit = True self.save() # hook self.run_method("after_cure", items=items, flower=flower, other_material=other_material, waste=waste, additional_collection=additional_collection) return {"items": items}
def money_in_words(number, main_currency=None, fraction_currency=None): """ Returns string in words with currency and fraction currency. """ from frappe.utils import get_defaults _ = frappe._ try: # note: `flt` returns 0 for invalid input and we don't want that number = float(number) except ValueError: return "" number = flt(number) if number < 0: return "" d = get_defaults() if not main_currency: main_currency = d.get('currency', 'INR') if not fraction_currency: fraction_currency = frappe.db.get_value( "Currency", main_currency, "fraction", cache=True) or _("Cent") number_format = frappe.db.get_value("Currency", main_currency, "number_format", cache=True) or \ frappe.db.get_default("number_format") or "#,###.##" fraction_length = get_number_format_info(number_format)[2] n = "%.{0}f".format(fraction_length) % number numbers = n.split('.') main, fraction = numbers if len(numbers) > 1 else [n, '00'] if len(fraction) < fraction_length: zeros = '0' * (fraction_length - len(fraction)) fraction += zeros in_million = True if number_format == "#,##,###.##": in_million = False # 0.00 if main == '0' and fraction in ['00', '000']: out = "{0} {1}".format(main_currency, _('Zero')) # 0.XX elif main == '0': out = fraction + '/100' else: out = _(in_words(main, in_million).title()) if cint(fraction): out = out + ' ' + _('and') + ' ' + fraction + '/100' return out
def _create_product(stock_entry, data): derivative_type = frappe.get_value("Item Group", stock_entry.product_group, "external_id") request_data = {} if not derivative_type: frappe.throw("Invalid Inventory type on '{0}'".format(stock_entry.product_group)) request_data["data"] = data request_data["derivative_type"] = cint(derivative_type) request_data["derivative_quantity"] = flt(stock_entry.product_qty) request_data["derivative_quantity_uom"] = "g" request_data["waste"] = flt(stock_entry.product_waste) request_data["waste_uom"] = "g" product_usable = flt(stock_entry.product_usable) if product_usable: request_data["derivative_usable"] = product_usable if stock_entry.product_name: request_data["derivative_product"] = stock_entry.product_name response = {} try: response = call("inventory_convert", request_data) except BioTrackClientError as ex: frappe.throw(cstr(ex.message), title="BioTrack sync-up failed") derivatives = response.get("derivatives", []) for derivative in derivatives: item_type = derivative.get("barcode_type") barcode = derivative.get("barcode_id") if item_type == 27 and stock_entry.waste_item: frappe.db.set_value("Item", stock_entry.waste_item, {"bio_barcode": barcode, "disabled": 0}, update_modified=False) elif item_type == derivative_type and stock_entry.product_item: frappe.db.set_value("Item", stock_entry.product_item, {"bio_barcode": barcode, "disabled": 0}, update_modified=False)
def supplement(to_cc=None, to_acc=None, amount=None, fiscal_year=None): to_account = get_cc_acc_budget(to_cc, to_acc, fiscal_year) if to_account: #Add in the To Account and Cost Center to_budget_account = frappe.get_doc("Budget Account", to_account[0].name) supplement = flt(to_budget_account.supplementary_budget) + flt(amount) total = flt(to_budget_account.budget_amount) + flt(amount) to_budget_account.db_set("supplementary_budget", supplement) to_budget_account.db_set("budget_amount", total) #Add the reappropriation details for record supp_details = frappe.new_doc("Supplementary Details") supp_details.to_cc = to_cc supp_details.to_acc = to_acc supp_details.amount = amount supp_details.posted_date = nowdate() supp_details.submit() return "DONE" else: return "The budget head you specified doesn't exist. Please try again"
def test_subscription_cancellation_invoices_with_prorata_true(self): settings = frappe.get_single('Subscription Settings') to_prorate = settings.prorate settings.prorate = 1 settings.save() subscription = frappe.new_doc('Subscription') subscription.customer = '_Test Customer' subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1}) subscription.save() subscription.cancel_subscription() invoice = subscription.get_current_invoice() diff = flt(date_diff(nowdate(), subscription.current_invoice_start) + 1) plan_days = flt(date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1) prorate_factor = flt(diff / plan_days) self.assertEqual(flt(invoice.grand_total, 2), flt(prorate_factor * 900, 2)) settings.prorate = to_prorate settings.save() subscription.delete()
def test_limitation(self): set_user("*****@*****.**") doc = get_doc("Expense Claim", "GCL-EXP-02725") # Assuming this is a temporary file # check if the user has a limitation rule = frappe.db.sql( """select `currency_field`,`limit_value`,`period` ,`days`, `date_field`, `form` ,`user` from `tabLimit Restriction` where form='{}' and disable=0 and user='******'""" .format(doc.doctype, frappe.session.user), as_list=1) for row in rule: """ row[0] holds the currency field used in the doctype / form row[1] holds the limit value row[2] holds the restriction type row[3] holds the number of days restriction applies if the restriction type is per day row[4] holds the date field used in the doctype / form row[5] holds the doctype / form row[6] holds the user the limitation is on doctype / form """ if row[2] == "By Transaction": if flt(doc.get(row[0])) > flt(row[1]): frappe.throw( "Sorry, You can not create this document because over limit maximum " "allowed transaction is {} ".format(row[1])) else: qry = """select sum({}) from `tab{}` where docstatus=1 and ({} between DATE_SUB(CURDATE(),INTERVAL {} DAY) and CURDATE()) and owner='{}' """.format( row[0], row[5], row[4], row[3], row[6]) data = frappe.db.sql(qry, as_list=0) for transaction in data: if flt(transaction[0]) + flt(doc.get(row[0])) > flt( row[1]): frappe.throw( "Sorry, You can not create this document because over limit maximum allowed " "transaction is {} for last {} day".format( row[1], row[3]))
def add_advances(self, invoice, payment_entry): pe = frappe.db.get_value("Payment Entry", payment_entry, ["remarks", "unallocated_amount"], as_dict=True) invoice.append( "advances", { "doctype": "Sales Invoice Advance", "reference_type": "Payment Entry", "reference_name": payment_entry, "remarks": pe.get("remarks"), "advance_amount": flt(pe.get("unallocated_amount")), "allocated_amount": min(flt(invoice.outstanding_amount), flt(pe.get("unallocated_amount"))) }) return invoice
def make_sample(item, sample_size): if frappe.db.exists("Quality Inspection", {"item_code": item.item_code}): doc = frappe.get_doc("Quality Inspection", {"item_code": item.item_code}) else: doc = frappe.new_doc("Quality Inspection") doc.update({ "item_code": item.item_code, "item_name": item.item_name, "inspection_type": _("In Process"), "sample_size": flt(sample_size), "inspected_by": "Administrator", "barcode": item.sample_id }) return doc
def sync_item(data): barcode = str(data.get("id")) remaining_quantity = flt(data.get("remaining_quantity")) name = None item_values = get_item_values(barcode, ["name", "transaction_id"]) if item_values: name, transaction_id = item_values if not (frappe.flags.force_sync or False) and transaction_id == data.get("transactionid"): frappe.db.set_value("Item", name, "bio_last_sync", now(), update_modified=False) return False # inventory type item_group = find_item_group(data) warehouse = find_warehouse(data) current_remaining_quantity = 0 # product (Item) mapping if data.get("productname"): item_name = data.get("productname") else: item_name = " ".join(filter(None, [data.get("strain"), item_group.name])) if not name: item_code = barcode item = frappe.get_doc({ "doctype": "Item", "item_code": item_code, "item_name": item_name, "bio_barcode": barcode, "is_stock_item": 1, "stock_uom": "Gram", "item_group": item_group.name, "default_warehouse": warehouse.name, }) else: item = frappe.get_doc("Item", name) current_remaining_quantity = item.bio_remaining_quantity strain = "" if data.get("strain"): strain = find_strain(data.get("strain")) # Post task will do on biotrack_after_sync hook parent_ids = data.get("parentid") plant_ids = data.get("plantid") if not item.is_lot_item and (parent_ids or plant_ids): item.set("linking_data", json.dumps({"parent_ids": parent_ids, "plant_ids": plant_ids})) item.update({ "item_name": item_name, "bio_barcode": barcode, "strain": strain, "bio_remaining_quantity": remaining_quantity, "transaction_id": data.get("transactionid"), "bio_last_sync": now(), "disabled": 1 if remaining_quantity == 0 else 0, }) item.flags.ignore_links = True item.save() # adjust_stock if item.is_stock_item: if remaining_quantity > current_remaining_quantity: make_stock_entry(item_code=item.name, target=item.default_warehouse, qty=remaining_quantity - current_remaining_quantity) # Consider to not modified down item's balance because it's hard to figure out the correct warehouse and its balance to deduct # elif remaining_quantity < current_remaining_quantity: # posting_date, posting_time = nowdate(), nowtime() # balance = get_stock_balance_for(item.name, item.default_warehouse, posting_date, posting_time) # # if balance["qty"] >= remaining_quantity: # make_stock_entry(item_code=item.name, source=item.default_warehouse, # qty=current_remaining_quantity - remaining_quantity) # Disable Usable Marijuana item does not have product name if not data.get("productname") and item_group.external_id == 28: frappe.db.set_value("Item", item.name, "disabled", 1) log_invalid_item(item) frappe.db.commit() return True
def get_prorata_factor(period_end, period_start): diff = flt(date_diff(nowdate(), period_start) + 1) plan_days = flt(date_diff(period_end, period_start) + 1) prorate_factor = diff / plan_days return prorate_factor
def create_reddem_points_entry(rule_details, sales_invoice_details, debit_to, credit_to, journal_voucher): debit_to, credit_to = credit_to, debit_to for entry in journal_voucher.entries: if entry.mode == "Redeem": conversion_factor = frappe.db.get_value('LPE Configuration', None, 'conversion_factor') create_point_transaction('Customer', sales_invoice_details.customer, entry.against_invoice, 'Redeem', cint(flt(entry.credit) / flt(conversion_factor))) create_jv(sales_invoice_details, sales_invoice_details.redeem_points, debit_to, credit_to)